All Classes Namespaces Files Functions Variables Typedefs Friends Macros Groups
extendedFaceStencilCalculateWeights.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019 OpenCFD Ltd.
10  Copyright (C) 2016-2019 ISP RAS (www.ispras.ru) UniCFD Group (www.unicfd.ru)
11 -------------------------------------------------------------------------------
12 License
13  This file is part of QGDsolver library, based on OpenFOAM+.
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22  You should have received a copy of the GNU General Public License
23  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 Group
25  grpleastSquares
26 Class
27  Foam::fvsc::leastSquares::extendedFaceStencilCalculateWeights
28 Description
29  Base methods for calculating weights
30 \*---------------------------------------------------------------------------*/
31 
32 
33 
34 #include "leastSquaresBase.H"
35 #include "polyMesh.H"
36 #include "fvMesh.H"
37 #include "word.H"
38 #include "IOstream.H"
39 #include "Ostream.H"
40 #include <HashTable.H>
41 
42 //- Compute weights for least squares scheme for gradient calculation.
44 {
45  //Pout << "Start calculateWeights()" << endl;
46 
47  const faceList& faces = cMesh_.faces();
48  GdfAll_.resize(faces.size());
49  wf2All_.resize(faces.size());
50  label cellDim = 3;
51 
52  //create list of underdetermined cells:
53  //cellSet udCells(mesh_, "udCells", mesh_.nCells()/100);
54  //mesh_.checkCellDeterminant(true, &udCells);
55  label nDegFaces = 0;
56  scalar minDet = GREAT;
57  scalar detG = 0.0;
58 
59  //for internal faces
60  forAll(faces, facei)
61  {
62  if (cMesh_.isInternalFace(facei))
63  {
64  List<vector> df(neighbourCells_[facei].size());
65  scalarList wf2(neighbourCells_[facei].size());
66  symmTensor G(0);
67 
68  vector Cf = cMesh_.faceCentres()[facei];
69 
70  forAll(neighbourCells_[facei], i)
71  {
72  df[i] = cMesh_.cellCentres()[neighbourCells_[facei][i]] - Cf;
73  wf2[i] = 1/magSqr(df[i]);
74  symmTensor addToG(0);
75  addToG = sqr(df[i]);
76  addToG = addToG * wf2[i];
77  G += addToG;
78  }
79 
80  symmTensor G0(0);
81  cellDim = 3;
82 
83  //correct G tensor for zero directions
84  {
85  if (mag(G.xx()) < SMALL)
86  {
87  G0.xx() = 1;
88  cellDim--;
89  }
90  if (mag(G.yy()) < SMALL)
91  {
92  G0.yy() = 1;
93  cellDim--;
94  }
95  if (mag(G.zz()) < SMALL)
96  {
97  G0.zz() = 1;
98  cellDim--;
99  }
100 
101  if (cellDim != cMesh_.nGeometricD())
102  {
103  WarningInFunction
104  << "face " << facei << " with center "
105  << cMesh_.faceCentres()[facei] << nl
106  << " connected to cells with dimensions " << cellDim
107  << " less then geometric " << cMesh_.nGeometricD()
108  << nl << endl;
109  Pout << "Degenerate face: " << facei << endl;
110  }
111  }
112 
113  /*
114  if(mesh_.nGeometricD()==1)
115  {
116  symmTensor G01(1, 0, 0, 1, 0, 1);
117  symmTensor G02(sqr((Vector<label>::one + mesh_.geometricD())/2));
118  G0 = G01 - G02;
119  }
120  else
121  {
122  if(mesh_.nGeometricD()==2)
123  {
124  G0 = sqr((Vector<label>::one - mesh_.geometricD())/2);
125  }
126  };
127  */
128 
129  G = G + G0;
130  detG = det(G);
131  if (detG < minDet)
132  {
133  minDet = detG;
134  }
135 
136  if (detG < 1)
137  {
138  nDegFaces++;
139  internalDegFaces_.append(facei);
140  }
141  else
142  {
143  G = inv(G);
144  G = G - G0;
145  }
146 
147  forAll(df, i)
148  {
149  df[i] = G&df[i];
150  }
151 
152  GdfAll_[facei] = df;
153  wf2All_[facei] = wf2;
154  }
155  }
156 
157  if (nDegFaces > 0)
158  {
159  Pout << "Min determinant : " << minDet << endl;
160  Pout << "Total # of deg. faces: " << nDegFaces << endl;
161  }
162 
163  //Info << "End for not parallel" << endl;
164 
165  if (Pstream::parRun())
166  {
167  List3<vector> ownCellCenters(nProcPatches_);
168  List3<vector> neiCellCenters(nProcPatches_);
169  List3<vector> corCellCenters(nProcPatches_);
170  //List<label> nOwnCells(nProcPatches_, 0);
171 
172  label cellId = -1;
173  label nCorCells = -1;
174 
175  //Step 1. Set cell centers at my patches
176  //Cell centers are stored only per processor patch
177  forAll(ownCellCenters, iProcPatch)
178  {
179  ownCellCenters[iProcPatch].resize(myProcPatchCells_[iProcPatch].size());
180  neiCellCenters[iProcPatch].resize(myProcPatchCells_[iProcPatch].size());
181  corCellCenters[iProcPatch].resize(myProcPatchCells_[iProcPatch].size());
182  forAll(ownCellCenters[iProcPatch], iFace)
183  {
184  ownCellCenters[iProcPatch][iFace].resize
185  (
186  myProcPatchCells_[iProcPatch][iFace].size()
187  );
188 
189  nCorCells = corEnd_[iProcPatch][iFace] - corStart_[iProcPatch][iFace] + 1;
190 
191  //Pout << "corEnd = " << corEnd_[iProcPatch][iFace] << " nCorCell = " << nCorCells << endl;
192  corCellCenters[iProcPatch][iFace].resize
193  (
194  nCorCells
195  );
196 
197  forAll(ownCellCenters[iProcPatch][iFace], iCell)
198  {
199  cellId = myProcPatchCells_[iProcPatch][iFace][iCell];
200  ownCellCenters[iProcPatch][iFace][iCell] = cMesh_.C()[cellId];
201  }
202  //nOwnCells[iProcPatch] += ownCellCenters[iProcPatch][iFace].size();
203  }
204  }
205 
206  // Step 2. Loop over all neighboring processors and send/receive cell centers
207  {
208  PstreamBuffers pBuffers(Pstream::commsTypes::nonBlocking);
209 
210  forAll(neigProcs_, iProcPair)
211  {
212  if (procPairs_[iProcPair] > -1) //send cell centers for patch-neighbouring processes
213  {
214  label procId = neigProcs_[iProcPair];
215  UOPstream oProcStr(procId, pBuffers);
216  oProcStr << ownCellCenters[iProcPair];
217  }
218  }
219 
220  pBuffers.finishedSends();
221 
222  forAll(neigProcs_, iProcPair)
223  {
224  if (procPairs_[iProcPair] > -1) //recieve cell centers for patch-neighbouring processes
225  {
226  label procId = neigProcs_[iProcPair];
227  UIPstream iProcStr(procId, pBuffers);
228  iProcStr >> neiCellCenters[iProcPair];
229  }
230  }
231 
232  //Pout << "neiCellCenters = " << neiCellCenters << endl;
233  }
234 
235  // Step 3. Loop over all corner neigbouring processors and send/receive cell centers
236  {
237  PstreamBuffers pBuffers(Pstream::commsTypes::nonBlocking);
238 
239  // Send
240  forAll(neigProcs_, iProcPair)
241  {
242  if (procPairs_[iProcPair] < 0)
243  {
244  label procId = neigProcs_[iProcPair];
245  UOPstream oProcStr(procId, pBuffers);
246  label id = corProcIds_[procId];
247 
248  List<vector> locCc (corCellIds_[id].size());
249 
250  forAll(locCc, iCell)
251  {
252  label cellId = corCellIds_[id][iCell];
253  locCc[iCell] = cMesh_.C()[cellId];
254  }
255  oProcStr << locCc;
256  //Pout << "Sending " << locCc << " to " << procId << endl;
257  }
258  }
259 
260  // Recieve
261  pBuffers.finishedSends();
262  label iCorProc = 0;
263  forAll(neigProcs_, iProcPair)
264  {
265  if (procPairs_[iProcPair] < 0)
266  {
267  label procId = neigProcs_[iProcPair];
268  UIPstream iProcStr(procId, pBuffers);
269 
270  List<vector> corCc (iProcStr);
271 
272  //Pout << "Received from " << procId << " cell centers " << corCc << endl;
273 
274  const List<Triple<label> > & addr = corAddr_[iCorProc];
275  label patchNo = -1;
276  label faceNo = -1;
277  label cellNo = -1;
278 
279  forAll(corCc, iCell)
280  {
281  patchNo = addr[iCell][0];
282  faceNo = addr[iCell][1];
283  cellNo = addr[iCell][2];
284 
285  corCellCenters[patchNo][faceNo][cellNo] = corCc[iCell];
286  }
287 
288  iCorProc++;
289  }
290  }
291 
292  //Pout << "corCellCenters = " << corCellCenters << endl;
293  }
294 
295 
296  // Step 4. Calculate weights
297  //Pout << "neiCellCenters = " << neiCellCenters << endl;
298  //Pout << "corCellCenters = " << corCellCenters << endl;
300  forAll(myProcPatchCells_,iProcPatch)
301  {
302  if (procPairs_[iProcPatch] > -1)
303  {
304  const label iProcPatchId = procPairs_[iProcPatch];
305  const fvPatch& fvp = cMesh_.boundary()[iProcPatchId];
306 
307  label nFaceCells = 0;
308 
309  forAll(ownCellCenters[iProcPatch], facei)
310  {
311  nFaceCells = corEnd_[iProcPatch][facei] + 1;
312 
313  List<vector> df (nFaceCells, vector::zero);
314  List<scalar> wf2(nFaceCells, 0.0);
315 
316  symmTensor G(0);
317 
318  forAll(ownCellCenters[iProcPatch][facei], i)
319  {
320  df[i] = ownCellCenters[iProcPatch][facei][i] - fvp.Cf()[facei];
321  wf2[i] = 1/magSqr(df[i]);
322  symmTensor addToG(0);
323  addToG = sqr(df[i]);
324  addToG = addToG * wf2[i];
325  G += addToG;
326  }
327 
328  label k = neiStart_[iProcPatch][facei];
329  forAll(neiCellCenters[iProcPatch][facei], i)
330  {
331  df[k] = neiCellCenters[iProcPatch][facei][i] - fvp.Cf()[facei];
332  wf2[k] = 1/magSqr(df[k]);
333  symmTensor addToG(0);
334  addToG = sqr(df[k]);
335  addToG = addToG * wf2[k];
336  G += addToG;
337  k++;
338  }
339 
340  label l = corStart_[iProcPatch][facei];
341  forAll(corCellCenters[iProcPatch][facei], i)
342  {
343  df[l] = corCellCenters[iProcPatch][facei][i] - fvp.Cf()[facei];
344  wf2[l] = 1/magSqr(df[l]);
345  symmTensor addToG(0);
346  addToG = sqr(df[l]);
347  addToG = addToG * wf2[l];
348  G += addToG;
349  l++;
350  }
351 
352  symmTensor G0(0);
353  cellDim = 3;
354  /*
355  if(mesh_.nGeometricD()==1)
356  {
357  symmTensor G01(1, 0, 0, 1, 0, 1);
358  symmTensor G02(sqr((Vector<label>::one + mesh_.geometricD())/2));
359  G0 = G01 - G02;
360  }
361  else
362  {
363  if(mesh_.nGeometricD()==2)
364  {
365  G0 = sqr((Vector<label>::one - mesh_.geometricD())/2);
366  }
367  };
368  */
369 
370  //correct G tensor for zero directions
371  {
372  if (mag(G.xx()) < SMALL)
373  {
374  G0.xx() = 1;
375  cellDim--;
376  }
377  if (mag(G.yy()) < SMALL)
378  {
379  G0.yy() = 1;
380  cellDim--;
381  }
382  if (mag(G.zz()) < SMALL)
383  {
384  G0.zz() = 1;
385  cellDim--;
386  }
387  }
388 
389  if (cellDim != cMesh_.nGeometricD())
390  {
391  WarningInFunction
392  << "face " << facei << " with center "
393  << fvp.Cf()[facei] << nl
394  << " connected to cells with dimensions " << cellDim
395  << " less then geometric " << cMesh_.nGeometricD()
396  << nl << endl;
397  }
398 
399  G = G + G0;
400 
401  detG = det(G);
402  if (detG < 1)
403  {
404  procDegFaces_[iProcPatch].append(facei);
405  }
406  else
407  {
408  G = inv(G);
409  G = G - G0;
410  }
411 
412  forAll(df, i)
413  {
414  df[i] = G&df[i];
415  }
416 
417  procGdf_[iProcPatch][facei] = df;
418  procWf2_[iProcPatch][facei] = wf2;
419  }
420  }
421  }
422  }
423 
424  //Pout << "End calculateWeights()" << endl;
425 };
426 
List< DynamicList< label > > procDegFaces_
void calculateWeights()
Compute weights for least squares scheme for gradient calculation.
labelHashTable< label > corProcIds_
List< face > faceList
List2< Triple< label > > corAddr_
forAll(Y, i)
Definition: QGDYEqn.H:36
DynamicList< label > internalDegFaces_