autoLayerDriver.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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25  All to do with adding cell layers
26 
27 \*----------------------------------------------------------------------------*/
28 
29 #include "autoLayerDriver.H"
30 #include "fvMesh.H"
31 #include "Time.H"
32 #include "meshRefinement.H"
33 #include "removePoints.H"
34 #include "pointFields.H"
35 #include "motionSmoother.H"
36 #include "unitConversion.H"
37 #include "pointSet.H"
38 #include "faceSet.H"
39 #include "cellSet.H"
40 #include "polyTopoChange.H"
41 #include "mapPolyMesh.H"
42 #include "addPatchCellLayer.H"
43 #include "mapDistributePolyMesh.H"
44 #include "OBJstream.H"
45 #include "layerParameters.H"
46 #include "combineFaces.H"
47 #include "IOmanip.H"
48 #include "globalIndex.H"
49 #include "DynamicField.H"
50 #include "PatchTools.H"
51 #include "slipPointPatchFields.H"
57 #include "localPointRegion.H"
59 #include "scalarIOField.H"
60 
61 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
62 
63 namespace Foam
64 {
65 
66 defineTypeNameAndDebug(autoLayerDriver, 0);
67 
68 } // End namespace Foam
69 
70 
71 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
72 
73 // For debugging: Dump displacement to .obj files
75 (
76  const fileName& prefix,
77  const indirectPrimitivePatch& pp,
78  const vectorField& patchDisp,
79  const List<extrudeMode>& extrudeStatus
80 )
81 {
82  OBJstream dispStr(prefix + "_disp.obj");
83  Info<< "Writing all displacements to " << dispStr.name() << endl;
84 
85  forAll(patchDisp, patchPointI)
86  {
87  const point& pt = pp.localPoints()[patchPointI];
88  dispStr.write(linePointRef(pt, pt + patchDisp[patchPointI]));
89  }
90 
91 
92  OBJstream illStr(prefix + "_illegal.obj");
93  Info<< "Writing invalid displacements to " << illStr.name() << endl;
94 
95  forAll(patchDisp, patchPointI)
96  {
97  if (extrudeStatus[patchPointI] != EXTRUDE)
98  {
99  const point& pt = pp.localPoints()[patchPointI];
100  illStr.write(linePointRef(pt, pt + patchDisp[patchPointI]));
101  }
102  }
103 }
104 
105 
107 (
108  const indirectPrimitivePatch& pp,
109  const scalarField& pointFld
110 )
111 {
112  tmp<scalarField> tfaceFld(new scalarField(pp.size(), 0.0));
113  scalarField& faceFld = tfaceFld();
114 
115  forAll(pp.localFaces(), faceI)
116  {
117  const face& f = pp.localFaces()[faceI];
118  if (f.size())
119  {
120  forAll(f, fp)
121  {
122  faceFld[faceI] += pointFld[f[fp]];
123  }
124  faceFld[faceI] /= f.size();
125  }
126  }
127  return tfaceFld;
128 }
129 
130 
131 // Check that primitivePatch is not multiply connected. Collect non-manifold
132 // points in pointSet.
134 (
135  const indirectPrimitivePatch& fp,
136  pointSet& nonManifoldPoints
137 )
138 {
139  // Check for non-manifold points (surface pinched at point)
140  fp.checkPointManifold(false, &nonManifoldPoints);
141 
142  // Check for edge-faces (surface pinched at edge)
143  const labelListList& edgeFaces = fp.edgeFaces();
144 
145  forAll(edgeFaces, edgeI)
146  {
147  const labelList& eFaces = edgeFaces[edgeI];
148 
149  if (eFaces.size() > 2)
150  {
151  const edge& e = fp.edges()[edgeI];
152 
153  nonManifoldPoints.insert(fp.meshPoints()[e[0]]);
154  nonManifoldPoints.insert(fp.meshPoints()[e[1]]);
155  }
156  }
157 }
158 
159 
161 {
162  const fvMesh& mesh = meshRefiner_.mesh();
163 
164  Info<< nl << "Checking mesh manifoldness ..." << endl;
165 
166  // Get all outside faces
167  labelList outsideFaces(mesh.nFaces() - mesh.nInternalFaces());
168 
169  for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
170  {
171  outsideFaces[faceI - mesh.nInternalFaces()] = faceI;
172  }
173 
174  pointSet nonManifoldPoints
175  (
176  mesh,
177  "nonManifoldPoints",
178  mesh.nPoints() / 100
179  );
180 
181  // Build primitivePatch out of faces and check it for problems.
183  (
185  (
186  IndirectList<face>(mesh.faces(), outsideFaces),
187  mesh.points()
188  ),
189  nonManifoldPoints
190  );
191 
192  label nNonManif = returnReduce(nonManifoldPoints.size(), sumOp<label>());
193 
194  if (nNonManif > 0)
195  {
196  Info<< "Outside of mesh is multiply connected across edges or"
197  << " points." << nl
198  << "This is not a fatal error but might cause some unexpected"
199  << " behaviour." << nl
200  //<< "Writing " << nNonManif
201  //<< " points where this happens to pointSet "
202  //<< nonManifoldPoints.name()
203  << endl;
204 
205  //nonManifoldPoints.instance() = meshRefiner_.timeName();
206  //nonManifoldPoints.write();
207  }
208  Info<< endl;
209 }
210 
211 
212 
213 // Unset extrusion on point. Returns true if anything unset.
215 (
216  const label patchPointI,
217  pointField& patchDisp,
218  labelList& patchNLayers,
219  List<extrudeMode>& extrudeStatus
220 )
221 {
222  if (extrudeStatus[patchPointI] == EXTRUDE)
223  {
224  extrudeStatus[patchPointI] = NOEXTRUDE;
225  patchNLayers[patchPointI] = 0;
226  patchDisp[patchPointI] = vector::zero;
227  return true;
228  }
229  else if (extrudeStatus[patchPointI] == EXTRUDEREMOVE)
230  {
231  extrudeStatus[patchPointI] = NOEXTRUDE;
232  patchNLayers[patchPointI] = 0;
233  patchDisp[patchPointI] = vector::zero;
234  return true;
235  }
236  else
237  {
238  return false;
239  }
240 }
241 
242 
243 // Unset extrusion on face. Returns true if anything unset.
245 (
246  const face& localFace,
247  pointField& patchDisp,
248  labelList& patchNLayers,
249  List<extrudeMode>& extrudeStatus
250 )
251 {
252  bool unextruded = false;
253 
254  forAll(localFace, fp)
255  {
256  if
257  (
258  unmarkExtrusion
259  (
260  localFace[fp],
261  patchDisp,
262  patchNLayers,
263  extrudeStatus
264  )
265  )
266  {
267  unextruded = true;
268  }
269  }
270  return unextruded;
271 }
272 
273 
274 // No extrusion at non-manifold points.
276 (
277  const indirectPrimitivePatch& pp,
278  const labelList& meshEdges,
279  const labelListList& edgeGlobalFaces,
280  pointField& patchDisp,
281  labelList& patchNLayers,
282  List<extrudeMode>& extrudeStatus
283 ) const
284 {
285  const fvMesh& mesh = meshRefiner_.mesh();
286 
287  Info<< nl << "Handling non-manifold points ..." << endl;
288 
289  // Detect non-manifold points
290  Info<< nl << "Checking patch manifoldness ..." << endl;
291 
292  pointSet nonManifoldPoints(mesh, "nonManifoldPoints", pp.nPoints());
293 
294  // 1. Local check
295  checkManifold(pp, nonManifoldPoints);
296 
297  // 2. Remote check for boundary edges on coupled boundaries
298  forAll(edgeGlobalFaces, edgeI)
299  {
300  if
301  (
302  pp.edgeFaces()[edgeI].size() == 1
303  && edgeGlobalFaces[edgeI].size() > 2
304  )
305  {
306  // So boundary edges that are connected to more than 2 processors
307  // i.e. a non-manifold edge which is exactly on a processor
308  // boundary.
309  const edge& e = pp.edges()[edgeI];
310  nonManifoldPoints.insert(pp.meshPoints()[e[0]]);
311  nonManifoldPoints.insert(pp.meshPoints()[e[1]]);
312  }
313  }
314 
315  // 3. Remote check for end of layer across coupled boundaries
316  {
317  PackedBoolList isCoupledEdge(mesh.nEdges());
318 
319  const labelList& cpEdges = mesh.globalData().coupledPatchMeshEdges();
320  forAll(cpEdges, i)
321  {
322  isCoupledEdge[cpEdges[i]] = true;
323  }
325  (
326  mesh,
327  isCoupledEdge,
329  0
330  );
331 
332  forAll(edgeGlobalFaces, edgeI)
333  {
334  label meshEdgeI = meshEdges[edgeI];
335 
336  if
337  (
338  pp.edgeFaces()[edgeI].size() == 1
339  && edgeGlobalFaces[edgeI].size() == 1
340  && isCoupledEdge[meshEdgeI]
341  )
342  {
343  // Edge of patch but no continuation across processor.
344  const edge& e = pp.edges()[edgeI];
345  //Pout<< "** Stopping extrusion on edge "
346  // << pp.localPoints()[e[0]]
347  // << pp.localPoints()[e[1]] << endl;
348  nonManifoldPoints.insert(pp.meshPoints()[e[0]]);
349  nonManifoldPoints.insert(pp.meshPoints()[e[1]]);
350  }
351  }
352  }
353 
354 
355 
356  label nNonManif = returnReduce(nonManifoldPoints.size(), sumOp<label>());
357 
358  Info<< "Outside of local patch is multiply connected across edges or"
359  << " points at " << nNonManif << " points." << endl;
360 
361  if (nNonManif > 0)
362  {
363  const labelList& meshPoints = pp.meshPoints();
364 
365  forAll(meshPoints, patchPointI)
366  {
367  if (nonManifoldPoints.found(meshPoints[patchPointI]))
368  {
369  unmarkExtrusion
370  (
371  patchPointI,
372  patchDisp,
373  patchNLayers,
374  extrudeStatus
375  );
376  }
377  }
378  }
379 
380  Info<< "Set displacement to zero for all " << nNonManif
381  << " non-manifold points" << endl;
382 }
383 
384 
385 // Parallel feature edge detection. Assumes non-manifold edges already handled.
387 (
388  const indirectPrimitivePatch& pp,
389  const labelList& meshEdges,
390  const scalar minCos,
391  pointField& patchDisp,
392  labelList& patchNLayers,
393  List<extrudeMode>& extrudeStatus
394 ) const
395 {
396  const fvMesh& mesh = meshRefiner_.mesh();
397 
398  Info<< nl << "Handling feature edges ..." << endl;
399 
400  if (minCos < 1-SMALL)
401  {
402  // Normal component of normals of connected faces.
403  vectorField edgeNormal(mesh.nEdges(), point::max);
404 
405  const labelListList& edgeFaces = pp.edgeFaces();
406 
407  forAll(edgeFaces, edgeI)
408  {
409  const labelList& eFaces = pp.edgeFaces()[edgeI];
410 
411  label meshEdgeI = meshEdges[edgeI];
412 
413  forAll(eFaces, i)
414  {
415  nomalsCombine()
416  (
417  edgeNormal[meshEdgeI],
418  pp.faceNormals()[eFaces[i]]
419  );
420  }
421  }
422 
424  (
425  mesh,
426  edgeNormal,
427  nomalsCombine(),
428  point::max // null value
429  );
430 
431  autoPtr<OBJstream> str;
432  if (debug&meshRefinement::MESH)
433  {
434  str.reset
435  (
436  new OBJstream
437  (
438  mesh.time().path()
439  / "featureEdges_"
440  + meshRefiner_.timeName()
441  + ".obj"
442  )
443  );
444  Info<< "Writing feature edges to " << str().name() << endl;
445  }
446 
447  label nFeats = 0;
448 
449  // Now on coupled edges the edgeNormal will have been truncated and
450  // only be still be the old value where two faces have the same normal
451  forAll(edgeFaces, edgeI)
452  {
453  const labelList& eFaces = pp.edgeFaces()[edgeI];
454 
455  label meshEdgeI = meshEdges[edgeI];
456 
457  const vector& n = edgeNormal[meshEdgeI];
458 
459  if (n != point::max)
460  {
461  scalar cos = n & pp.faceNormals()[eFaces[0]];
462 
463  if (cos < minCos)
464  {
465  const edge& e = pp.edges()[edgeI];
466 
467  unmarkExtrusion
468  (
469  e[0],
470  patchDisp,
471  patchNLayers,
472  extrudeStatus
473  );
474  unmarkExtrusion
475  (
476  e[1],
477  patchDisp,
478  patchNLayers,
479  extrudeStatus
480  );
481 
482  nFeats++;
483 
484  if (str.valid())
485  {
486  const point& p0 = pp.localPoints()[e[0]];
487  const point& p1 = pp.localPoints()[e[1]];
488  str().write(linePointRef(p0, p1));
489  }
490  }
491  }
492  }
493 
494  Info<< "Set displacement to zero for points on "
495  << returnReduce(nFeats, sumOp<label>())
496  << " feature edges" << endl;
497  }
498 }
499 
500 
501 // No extrusion on cells with warped faces. Calculates the thickness of the
502 // layer and compares it to the space the warped face takes up. Disables
503 // extrusion if layer thickness is more than faceRatio of the thickness of
504 // the face.
506 (
507  const indirectPrimitivePatch& pp,
508  const scalar faceRatio,
509  const scalar edge0Len,
510  const labelList& cellLevel,
511  pointField& patchDisp,
512  labelList& patchNLayers,
513  List<extrudeMode>& extrudeStatus
514 ) const
515 {
516  const fvMesh& mesh = meshRefiner_.mesh();
517 
518  Info<< nl << "Handling cells with warped patch faces ..." << nl;
519 
520  const pointField& points = mesh.points();
521 
522  label nWarpedFaces = 0;
523 
524  forAll(pp, i)
525  {
526  const face& f = pp[i];
527 
528  if (f.size() > 3)
529  {
530  label faceI = pp.addressing()[i];
531 
532  label ownLevel = cellLevel[mesh.faceOwner()[faceI]];
533  scalar edgeLen = edge0Len/(1<<ownLevel);
534 
535  // Normal distance to face centre plane
536  const point& fc = mesh.faceCentres()[faceI];
537  const vector& fn = pp.faceNormals()[i];
538 
539  scalarField vProj(f.size());
540 
541  forAll(f, fp)
542  {
543  vector n = points[f[fp]] - fc;
544  vProj[fp] = (n & fn);
545  }
546 
547  // Get normal 'span' of face
548  scalar minVal = min(vProj);
549  scalar maxVal = max(vProj);
550 
551  if ((maxVal - minVal) > faceRatio * edgeLen)
552  {
553  if
554  (
555  unmarkExtrusion
556  (
557  pp.localFaces()[i],
558  patchDisp,
559  patchNLayers,
560  extrudeStatus
561  )
562  )
563  {
564  nWarpedFaces++;
565  }
566  }
567  }
568  }
569 
570  Info<< "Set displacement to zero on "
571  << returnReduce(nWarpedFaces, sumOp<label>())
572  << " warped faces since layer would be > " << faceRatio
573  << " of the size of the bounding box." << endl;
574 }
575 
576 
579 //void Foam::autoLayerDriver::handleMultiplePatchFaces
580 //(
581 // const indirectPrimitivePatch& pp,
582 // pointField& patchDisp,
583 // labelList& patchNLayers,
584 // List<extrudeMode>& extrudeStatus
585 //) const
586 //{
587 // const fvMesh& mesh = meshRefiner_.mesh();
588 //
589 // Info<< nl << "Handling cells with multiple patch faces ..." << nl;
590 //
591 // const labelListList& pointFaces = pp.pointFaces();
592 //
593 // // Cells that should not get an extrusion layer
594 // cellSet multiPatchCells(mesh, "multiPatchCells", pp.size());
595 //
596 // // Detect points that use multiple faces on same cell.
597 // forAll(pointFaces, patchPointI)
598 // {
599 // const labelList& pFaces = pointFaces[patchPointI];
600 //
601 // labelHashSet pointCells(pFaces.size());
602 //
603 // forAll(pFaces, i)
604 // {
605 // label cellI = mesh.faceOwner()[pp.addressing()[pFaces[i]]];
606 //
607 // if (!pointCells.insert(cellI))
608 // {
609 // // Second or more occurrence of cell so cell has two or more
610 // // pp faces connected to this point.
611 // multiPatchCells.insert(cellI);
612 // }
613 // }
614 // }
615 //
616 // label nMultiPatchCells = returnReduce
617 // (
618 // multiPatchCells.size(),
619 // sumOp<label>()
620 // );
621 //
622 // Info<< "Detected " << nMultiPatchCells
623 // << " cells with multiple (connected) patch faces." << endl;
624 //
625 // label nChanged = 0;
626 //
627 // if (nMultiPatchCells > 0)
628 // {
629 // multiPatchCells.instance() = meshRefiner_.timeName();
630 // Info<< "Writing " << nMultiPatchCells
631 // << " cells with multiple (connected) patch faces to cellSet "
632 // << multiPatchCells.objectPath() << endl;
633 // multiPatchCells.write();
634 //
635 //
636 // // Go through all points and remove extrusion on any cell in
637 // // multiPatchCells
638 // // (has to be done in separate loop since having one point on
639 // // multipatches has to reset extrusion on all points of cell)
640 //
641 // forAll(pointFaces, patchPointI)
642 // {
643 // if (extrudeStatus[patchPointI] != NOEXTRUDE)
644 // {
645 // const labelList& pFaces = pointFaces[patchPointI];
646 //
647 // forAll(pFaces, i)
648 // {
649 // label cellI =
650 // mesh.faceOwner()[pp.addressing()[pFaces[i]]];
651 //
652 // if (multiPatchCells.found(cellI))
653 // {
654 // if
655 // (
656 // unmarkExtrusion
657 // (
658 // patchPointI,
659 // patchDisp,
660 // patchNLayers,
661 // extrudeStatus
662 // )
663 // )
664 // {
665 // nChanged++;
666 // }
667 // }
668 // }
669 // }
670 // }
671 //
672 // reduce(nChanged, sumOp<label>());
673 // }
674 //
675 // Info<< "Prevented extrusion on " << nChanged
676 // << " points due to multiple patch faces." << nl << endl;
677 //}
678 
679 
681 (
682  const labelList& patchToNLayers,
683  const labelList& patchIDs,
684  const indirectPrimitivePatch& pp,
685  pointField& patchDisp,
686  labelList& patchNLayers,
687  List<extrudeMode>& extrudeStatus,
688  label& nAddedCells
689 ) const
690 {
691  const fvMesh& mesh = meshRefiner_.mesh();
692 
693  Info<< nl << "Handling points with inconsistent layer specification ..."
694  << endl;
695 
696  // Get for every point (really only necessary on patch external points)
697  // the max and min of any patch faces using it.
698  labelList maxLayers(patchNLayers.size(), labelMin);
699  labelList minLayers(patchNLayers.size(), labelMax);
700 
701  forAll(patchIDs, i)
702  {
703  label patchI = patchIDs[i];
704 
705  const labelList& meshPoints = mesh.boundaryMesh()[patchI].meshPoints();
706 
707  label wantedLayers = patchToNLayers[patchI];
708 
709  forAll(meshPoints, patchPointI)
710  {
711  label ppPointI = pp.meshPointMap()[meshPoints[patchPointI]];
712 
713  maxLayers[ppPointI] = max(wantedLayers, maxLayers[ppPointI]);
714  minLayers[ppPointI] = min(wantedLayers, minLayers[ppPointI]);
715  }
716  }
717 
719  (
720  mesh,
721  pp.meshPoints(),
722  maxLayers,
723  maxEqOp<label>(),
724  labelMin // null value
725  );
727  (
728  mesh,
729  pp.meshPoints(),
730  minLayers,
731  minEqOp<label>(),
732  labelMax // null value
733  );
734 
735  // Unmark any point with different min and max
736  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
737 
738  //label nConflicts = 0;
739 
740  forAll(maxLayers, i)
741  {
742  if (maxLayers[i] == labelMin || minLayers[i] == labelMax)
743  {
745  << "Patchpoint:" << i << " coord:" << pp.localPoints()[i]
746  << " maxLayers:" << maxLayers
747  << " minLayers:" << minLayers
748  << abort(FatalError);
749  }
750  else if (maxLayers[i] == minLayers[i])
751  {
752  // Ok setting.
753  patchNLayers[i] = maxLayers[i];
754  }
755  else
756  {
757  // Inconsistent num layers between patch faces using point
758  //if
759  //(
760  // unmarkExtrusion
761  // (
762  // i,
763  // patchDisp,
764  // patchNLayers,
765  // extrudeStatus
766  // )
767  //)
768  //{
769  // nConflicts++;
770  //}
771  patchNLayers[i] = maxLayers[i];
772  }
773  }
774 
775 
776  // Calculate number of cells to create
777  nAddedCells = 0;
778  forAll(pp.localFaces(), faceI)
779  {
780  const face& f = pp.localFaces()[faceI];
781 
782  // Get max of extrusion per point
783  label nCells = 0;
784  forAll(f, fp)
785  {
786  nCells = max(nCells, patchNLayers[f[fp]]);
787  }
788 
789  nAddedCells += nCells;
790  }
791  reduce(nAddedCells, sumOp<label>());
792 
793  //reduce(nConflicts, sumOp<label>());
794  //
795  //Info<< "Set displacement to zero for " << nConflicts
796  // << " points due to points being on multiple regions"
797  // << " with inconsistent nLayers specification." << endl;
798 }
799 
800 
801 // Construct pointVectorField with correct boundary conditions for adding
802 // layers
805 (
806  const pointMesh& pMesh,
807  const labelList& numLayers
808 )
809 {
810  // Construct displacement field.
811  const pointBoundaryMesh& pointPatches = pMesh.boundary();
812 
813  wordList patchFieldTypes
814  (
815  pointPatches.size(),
816  slipPointPatchVectorField::typeName
817  );
818  wordList actualPatchTypes(patchFieldTypes.size());
819  forAll(pointPatches, patchI)
820  {
821  actualPatchTypes[patchI] = pointPatches[patchI].type();
822  }
823 
824  forAll(numLayers, patchI)
825  {
826  // 0 layers: do not allow slip so fixedValue 0
827  // >0 layers: fixedValue which gets adapted
828  if (numLayers[patchI] == 0)
829  {
830  patchFieldTypes[patchI] =
831  zeroFixedValuePointPatchVectorField::typeName;
832  }
833  else if (numLayers[patchI] > 0)
834  {
835  patchFieldTypes[patchI] = fixedValuePointPatchVectorField::typeName;
836  }
837  }
838 
839  forAll(pointPatches, patchI)
840  {
841  if (isA<processorPointPatch>(pointPatches[patchI]))
842  {
843  patchFieldTypes[patchI] = calculatedPointPatchVectorField::typeName;
844  }
845  else if (isA<cyclicPointPatch>(pointPatches[patchI]))
846  {
847  patchFieldTypes[patchI] = cyclicSlipPointPatchVectorField::typeName;
848  }
849  }
850 
851 
852  const polyMesh& mesh = pMesh();
853 
854  // Note: time().timeName() instead of meshRefinement::timeName() since
855  // postprocessable field.
857  (
858  new pointVectorField
859  (
860  IOobject
861  (
862  "pointDisplacement",
863  mesh.time().timeName(),
864  mesh,
867  ),
868  pMesh,
869  dimensionedVector("displacement", dimLength, vector::zero),
870  patchFieldTypes,
871  actualPatchTypes
872  )
873  );
874  return tfld;
875 }
876 
877 
879 (
880  const indirectPrimitivePatch& pp,
881  pointField& patchDisp,
882  labelList& patchNLayers,
883  List<extrudeMode>& extrudeStatus
884 ) const
885 {
886  Info<< nl << "Growing non-extrusion points by one layer ..." << endl;
887 
888  List<extrudeMode> grownExtrudeStatus(extrudeStatus);
889 
890  const faceList& localFaces = pp.localFaces();
891 
892  label nGrown = 0;
893 
894  forAll(localFaces, faceI)
895  {
896  const face& f = localFaces[faceI];
897 
898  bool hasSqueeze = false;
899  forAll(f, fp)
900  {
901  if (extrudeStatus[f[fp]] == NOEXTRUDE)
902  {
903  hasSqueeze = true;
904  break;
905  }
906  }
907 
908  if (hasSqueeze)
909  {
910  // Squeeze all points of face
911  forAll(f, fp)
912  {
913  if
914  (
915  extrudeStatus[f[fp]] == EXTRUDE
916  && grownExtrudeStatus[f[fp]] != NOEXTRUDE
917  )
918  {
919  grownExtrudeStatus[f[fp]] = NOEXTRUDE;
920  nGrown++;
921  }
922  }
923  }
924  }
925 
926  extrudeStatus.transfer(grownExtrudeStatus);
927 
928 
929  // Synchronise since might get called multiple times.
930  // Use the fact that NOEXTRUDE is the minimum value.
931  {
932  labelList status(extrudeStatus.size());
933  forAll(status, i)
934  {
935  status[i] = extrudeStatus[i];
936  }
938  (
939  meshRefiner_.mesh(),
940  pp.meshPoints(),
941  status,
942  minEqOp<label>(),
943  labelMax // null value
944  );
945  forAll(status, i)
946  {
947  extrudeStatus[i] = extrudeMode(status[i]);
948  }
949  }
950 
951 
952  forAll(extrudeStatus, patchPointI)
953  {
954  if (extrudeStatus[patchPointI] == NOEXTRUDE)
955  {
956  patchDisp[patchPointI] = vector::zero;
957  patchNLayers[patchPointI] = 0;
958  }
959  }
960 
961  reduce(nGrown, sumOp<label>());
962 
963  Info<< "Set displacement to zero for an additional " << nGrown
964  << " points." << endl;
965 }
966 
967 
969 (
970  const globalIndex& globalFaces,
971  const labelListList& edgeGlobalFaces,
972  const indirectPrimitivePatch& pp,
973 
974  labelList& edgePatchID,
975  labelList& edgeZoneID,
976  boolList& edgeFlip,
977  labelList& inflateFaceID
978 )
979 {
980  // Sometimes edges-to-be-extruded are on more than 2 processors.
981  // Work out which 2 hold the faces to be extruded and thus which procpatch
982  // the edge-face should be in. As an additional complication this might
983  // mean that 2 procesors that were only edge-connected now suddenly need
984  // to become face-connected i.e. have a processor patch between them.
985 
986  fvMesh& mesh = meshRefiner_.mesh();
987 
988  // Determine edgePatchID. Any additional processor boundary gets added to
989  // patchToNbrProc,nbrProcToPatch and nPatches gets set to the new number
990  // of patches.
991  label nPatches;
992  Map<label> nbrProcToPatch;
993  Map<label> patchToNbrProc;
995  (
996  true, // zoneFromAnyFace
997 
998  mesh,
999  globalFaces,
1000  edgeGlobalFaces,
1001  pp,
1002 
1003  edgePatchID,
1004  nPatches,
1005  nbrProcToPatch,
1006  patchToNbrProc,
1007  edgeZoneID,
1008  edgeFlip,
1009  inflateFaceID
1010  );
1011 
1012  label nOldPatches = mesh.boundaryMesh().size();
1013  label nAdded = returnReduce(nPatches-nOldPatches, sumOp<label>());
1014  Info<< nl << "Adding in total " << nAdded/2 << " inter-processor patches to"
1015  << " handle extrusion of non-manifold processor boundaries."
1016  << endl;
1017 
1018  if (nAdded > 0)
1019  {
1020  // We might not add patches in same order as in patchToNbrProc
1021  // so prepare to renumber edgePatchID
1022  Map<label> wantedToAddedPatch;
1023 
1024  for (label patchI = nOldPatches; patchI < nPatches; patchI++)
1025  {
1026  label nbrProcI = patchToNbrProc[patchI];
1027  word name =
1028  "procBoundary"
1030  + "to"
1031  + Foam::name(nbrProcI);
1032 
1033  dictionary patchDict;
1034  patchDict.add("type", processorPolyPatch::typeName);
1035  patchDict.add("myProcNo", Pstream::myProcNo());
1036  patchDict.add("neighbProcNo", nbrProcI);
1037  patchDict.add("nFaces", 0);
1038  patchDict.add("startFace", mesh.nFaces());
1039 
1040  //Pout<< "Adding patch " << patchI
1041  // << " name:" << name
1042  // << " between " << Pstream::myProcNo()
1043  // << " and " << nbrProcI << endl;
1044 
1045  label procPatchI = meshRefiner_.appendPatch
1046  (
1047  mesh,
1048  mesh.boundaryMesh().size(), // new patch index
1049  name,
1050  patchDict
1051  );
1052  wantedToAddedPatch.insert(patchI, procPatchI);
1053  }
1054 
1055  // Renumber edgePatchID
1056  forAll(edgePatchID, i)
1057  {
1058  label patchI = edgePatchID[i];
1059  Map<label>::const_iterator fnd = wantedToAddedPatch.find(patchI);
1060  if (fnd != wantedToAddedPatch.end())
1061  {
1062  edgePatchID[i] = fnd();
1063  }
1064  }
1065 
1066  mesh.clearOut();
1067  const_cast<polyBoundaryMesh&>(mesh.boundaryMesh()).updateMesh();
1068  }
1069 }
1070 
1071 
1074  const indirectPrimitivePatch& pp,
1075  const labelList& patchIDs,
1076  const layerParameters& layerParams,
1077  const labelList& cellLevel,
1078  const labelList& patchNLayers,
1079  const scalar edge0Len,
1080 
1081  scalarField& thickness,
1082  scalarField& minThickness,
1083  scalarField& expansionRatio
1084 ) const
1085 {
1086  const fvMesh& mesh = meshRefiner_.mesh();
1088 
1089 
1090  // Rework patch-wise layer parameters into minimum per point
1091  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1092  // Note: only layer parameters consistent with layer specification
1093  // method (see layerParameters) will be correct.
1094  scalarField firstLayerThickness(pp.nPoints(), GREAT);
1095  scalarField finalLayerThickness(pp.nPoints(), GREAT);
1096  scalarField totalThickness(pp.nPoints(), GREAT);
1097  scalarField expRatio(pp.nPoints(), GREAT);
1098 
1099  minThickness.setSize(pp.nPoints());
1100  minThickness = GREAT;
1101 
1102  forAll(patchIDs, i)
1103  {
1104  label patchI = patchIDs[i];
1105 
1106  const labelList& meshPoints = patches[patchI].meshPoints();
1107 
1108  forAll(meshPoints, patchPointI)
1109  {
1110  label ppPointI = pp.meshPointMap()[meshPoints[patchPointI]];
1111 
1112  firstLayerThickness[ppPointI] = min
1113  (
1114  firstLayerThickness[ppPointI],
1115  layerParams.firstLayerThickness()[patchI]
1116  );
1117  finalLayerThickness[ppPointI] = min
1118  (
1119  finalLayerThickness[ppPointI],
1120  layerParams.finalLayerThickness()[patchI]
1121  );
1122  totalThickness[ppPointI] = min
1123  (
1124  totalThickness[ppPointI],
1125  layerParams.thickness()[patchI]
1126  );
1127  expRatio[ppPointI] = min
1128  (
1129  expRatio[ppPointI],
1130  layerParams.expansionRatio()[patchI]
1131  );
1132  minThickness[ppPointI] = min
1133  (
1134  minThickness[ppPointI],
1135  layerParams.minThickness()[patchI]
1136  );
1137  }
1138  }
1139 
1141  (
1142  mesh,
1143  pp.meshPoints(),
1144  firstLayerThickness,
1145  minEqOp<scalar>(),
1146  GREAT // null value
1147  );
1149  (
1150  mesh,
1151  pp.meshPoints(),
1152  finalLayerThickness,
1153  minEqOp<scalar>(),
1154  GREAT // null value
1155  );
1157  (
1158  mesh,
1159  pp.meshPoints(),
1160  totalThickness,
1161  minEqOp<scalar>(),
1162  GREAT // null value
1163  );
1165  (
1166  mesh,
1167  pp.meshPoints(),
1168  expRatio,
1169  minEqOp<scalar>(),
1170  GREAT // null value
1171  );
1173  (
1174  mesh,
1175  pp.meshPoints(),
1176  minThickness,
1177  minEqOp<scalar>(),
1178  GREAT // null value
1179  );
1180 
1181 
1182  // Now the thicknesses are set according to the minimum of connected
1183  // patches.
1184 
1185 
1186  // Rework relative thickness into absolute
1187  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1188  // by multiplying with the internal cell size.
1189 
1190  if (layerParams.relativeSizes())
1191  {
1192  if
1193  (
1194  min(layerParams.minThickness()) < 0
1195  || max(layerParams.minThickness()) > 2
1196  )
1197  {
1199  << "Thickness should be factor of local undistorted cell size."
1200  << " Valid values are [0..2]." << nl
1201  << " minThickness:" << layerParams.minThickness()
1202  << exit(FatalError);
1203  }
1204 
1205 
1206  // Determine per point the max cell level of connected cells
1207  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1208 
1209  labelList maxPointLevel(pp.nPoints(), labelMin);
1210 
1211  forAll(pp, i)
1212  {
1213  label ownLevel = cellLevel[mesh.faceOwner()[pp.addressing()[i]]];
1214 
1215  const face& f = pp.localFaces()[i];
1216 
1217  forAll(f, fp)
1218  {
1219  maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel);
1220  }
1221  }
1222 
1224  (
1225  mesh,
1226  pp.meshPoints(),
1227  maxPointLevel,
1228  maxEqOp<label>(),
1229  labelMin // null value
1230  );
1231 
1232 
1233  forAll(maxPointLevel, pointI)
1234  {
1235  // Find undistorted edge size for this level.
1236  scalar edgeLen = edge0Len/(1<<maxPointLevel[pointI]);
1237  firstLayerThickness[pointI] *= edgeLen;
1238  finalLayerThickness[pointI] *= edgeLen;
1239  totalThickness[pointI] *= edgeLen;
1240  minThickness[pointI] *= edgeLen;
1241  }
1242  }
1243 
1244 
1245 
1246  // Rework thickness parameters into overall thickness
1247  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1248 
1249  forAll(firstLayerThickness, pointI)
1250  {
1251  thickness[pointI] = layerParams.layerThickness
1252  (
1253  patchNLayers[pointI],
1254  firstLayerThickness[pointI],
1255  finalLayerThickness[pointI],
1256  totalThickness[pointI],
1257  expRatio[pointI]
1258  );
1259 
1260  expansionRatio[pointI] = layerParams.layerExpansionRatio
1261  (
1262  patchNLayers[pointI],
1263  firstLayerThickness[pointI],
1264  finalLayerThickness[pointI],
1265  totalThickness[pointI],
1266  expRatio[pointI]
1267  );
1268  }
1269 
1270  //Info<< "calculateLayerThickness : min:" << gMin(thickness)
1271  // << " max:" << gMax(thickness) << endl;
1272 
1273  // Print a bit
1274  {
1276 
1277  int oldPrecision = Info().precision();
1278 
1279  // Find maximum length of a patch name, for a nicer output
1280  label maxPatchNameLen = 0;
1281  forAll(patchIDs, i)
1282  {
1283  label patchI = patchIDs[i];
1284  word patchName = patches[patchI].name();
1285  maxPatchNameLen = max(maxPatchNameLen, label(patchName.size()));
1286  }
1287 
1288  Info<< nl
1289  << setf(ios_base::left) << setw(maxPatchNameLen) << "patch"
1290  << setw(0) << " faces layers avg thickness[m]" << nl
1291  << setf(ios_base::left) << setw(maxPatchNameLen) << " "
1292  << setw(0) << " near-wall overall" << nl
1293  << setf(ios_base::left) << setw(maxPatchNameLen) << "-----"
1294  << setw(0) << " ----- ------ --------- -------" << endl;
1295 
1296 
1297  const PackedBoolList isMasterPoint(syncTools::getMasterPoints(mesh));
1298 
1299  forAll(patchIDs, i)
1300  {
1301  label patchI = patchIDs[i];
1302 
1303  const labelList& meshPoints = patches[patchI].meshPoints();
1304 
1305  scalar sumThickness = 0;
1306  scalar sumNearWallThickness = 0;
1307  label nMasterPoints = 0;
1308 
1309  forAll(meshPoints, patchPointI)
1310  {
1311  label meshPointI = meshPoints[patchPointI];
1312  if (isMasterPoint[meshPointI])
1313  {
1314  label ppPointI = pp.meshPointMap()[meshPointI];
1315 
1316  sumThickness += thickness[ppPointI];
1317  sumNearWallThickness += layerParams.firstLayerThickness
1318  (
1319  patchNLayers[ppPointI],
1320  firstLayerThickness[ppPointI],
1321  finalLayerThickness[ppPointI],
1322  thickness[ppPointI],
1323  expansionRatio[ppPointI]
1324  );
1325  nMasterPoints++;
1326  }
1327  }
1328 
1329  label totNPoints = returnReduce(nMasterPoints, sumOp<label>());
1330 
1331  // For empty patches, totNPoints is 0.
1332  scalar avgThickness = 0;
1333  scalar avgNearWallThickness = 0;
1334 
1335  if (totNPoints > 0)
1336  {
1337  avgThickness =
1338  returnReduce(sumThickness, sumOp<scalar>())
1339  / totNPoints;
1340  avgNearWallThickness =
1341  returnReduce(sumNearWallThickness, sumOp<scalar>())
1342  / totNPoints;
1343  }
1344 
1345  Info<< setf(ios_base::left) << setw(maxPatchNameLen)
1346  << patches[patchI].name() << setprecision(3)
1347  << " " << setw(8)
1348  << returnReduce(patches[patchI].size(), sumOp<scalar>())
1349  << " " << setw(6) << layerParams.numLayers()[patchI]
1350  << " " << setw(8) << avgNearWallThickness
1351  << " " << setw(8) << avgThickness
1352  << endl;
1353  }
1354  Info<< setprecision(oldPrecision) << endl;
1355  }
1356 }
1357 
1358 
1359 // Synchronize displacement among coupled patches.
1362  const indirectPrimitivePatch& pp,
1363  const scalarField& minThickness,
1364  pointField& patchDisp,
1365  labelList& patchNLayers,
1366  List<extrudeMode>& extrudeStatus
1367 ) const
1368 {
1369  const fvMesh& mesh = meshRefiner_.mesh();
1370  const labelList& meshPoints = pp.meshPoints();
1371 
1372  label nChangedTotal = 0;
1373 
1374  while (true)
1375  {
1376  label nChanged = 0;
1377 
1378  // Sync displacement (by taking min)
1380  (
1381  mesh,
1382  meshPoints,
1383  patchDisp,
1385  point::rootMax // null value
1386  );
1387 
1388  // Unmark if displacement too small
1389  forAll(patchDisp, i)
1390  {
1391  if (mag(patchDisp[i]) < minThickness[i])
1392  {
1393  if
1394  (
1395  unmarkExtrusion
1396  (
1397  i,
1398  patchDisp,
1399  patchNLayers,
1400  extrudeStatus
1401  )
1402  )
1403  {
1404  nChanged++;
1405  }
1406  }
1407  }
1408 
1409  labelList syncPatchNLayers(patchNLayers);
1410 
1412  (
1413  mesh,
1414  meshPoints,
1415  syncPatchNLayers,
1416  minEqOp<label>(),
1417  labelMax // null value
1418  );
1419 
1420  // Reset if differs
1421  // 1. take max
1422  forAll(syncPatchNLayers, i)
1423  {
1424  if (syncPatchNLayers[i] != patchNLayers[i])
1425  {
1426  if
1427  (
1428  unmarkExtrusion
1429  (
1430  i,
1431  patchDisp,
1432  patchNLayers,
1433  extrudeStatus
1434  )
1435  )
1436  {
1437  nChanged++;
1438  }
1439  }
1440  }
1441 
1443  (
1444  mesh,
1445  meshPoints,
1446  syncPatchNLayers,
1447  maxEqOp<label>(),
1448  labelMin // null value
1449  );
1450 
1451  // Reset if differs
1452  // 2. take min
1453  forAll(syncPatchNLayers, i)
1454  {
1455  if (syncPatchNLayers[i] != patchNLayers[i])
1456  {
1457  if
1458  (
1459  unmarkExtrusion
1460  (
1461  i,
1462  patchDisp,
1463  patchNLayers,
1464  extrudeStatus
1465  )
1466  )
1467  {
1468  nChanged++;
1469  }
1470  }
1471  }
1472  nChangedTotal += nChanged;
1473 
1474  if (!returnReduce(nChanged, sumOp<label>()))
1475  {
1476  break;
1477  }
1478  }
1479 
1480  //Info<< "Prevented extrusion on "
1481  // << returnReduce(nChangedTotal, sumOp<label>())
1482  // << " coupled patch points during syncPatchDisplacement." << endl;
1483 }
1484 
1485 
1486 // Calculate displacement vector for all patch points. Uses pointNormal.
1487 // Checks that displaced patch point would be visible from all centres
1488 // of the faces using it.
1489 // extrudeStatus is both input and output and gives the status of each
1490 // patch point.
1493  const indirectPrimitivePatch& pp,
1494  const scalarField& thickness,
1495  const scalarField& minThickness,
1496  pointField& patchDisp,
1497  labelList& patchNLayers,
1498  List<extrudeMode>& extrudeStatus
1499 ) const
1500 {
1501  Info<< nl << "Determining displacement for added points"
1502  << " according to pointNormal ..." << endl;
1503 
1504  const fvMesh& mesh = meshRefiner_.mesh();
1505  const vectorField& faceNormals = pp.faceNormals();
1506  const labelListList& pointFaces = pp.pointFaces();
1507  const pointField& localPoints = pp.localPoints();
1508 
1509  // Determine pointNormal
1510  // ~~~~~~~~~~~~~~~~~~~~~
1511 
1512  pointField pointNormals(PatchTools::pointNormals(mesh, pp));
1513 
1514 
1515  // Determine local length scale on patch
1516  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1517 
1518  // Start off from same thickness everywhere (except where no extrusion)
1519  patchDisp = thickness*pointNormals;
1520 
1521 
1522  label nNoVisNormal = 0;
1523  label nExtrudeRemove = 0;
1524 
1525 
1526  // Check if no extrude possible.
1527  forAll(pointNormals, patchPointI)
1528  {
1529  label meshPointI = pp.meshPoints()[patchPointI];
1530 
1531  if (extrudeStatus[patchPointI] == NOEXTRUDE)
1532  {
1533  // Do not use unmarkExtrusion; forcibly set to zero extrusion.
1534  patchNLayers[patchPointI] = 0;
1535  patchDisp[patchPointI] = vector::zero;
1536  }
1537  else
1538  {
1539  // Get normal
1540  const vector& n = pointNormals[patchPointI];
1541 
1542  if (!meshTools::visNormal(n, faceNormals, pointFaces[patchPointI]))
1543  {
1544  if (debug&meshRefinement::ATTRACTION)
1545  {
1546  Pout<< "No valid normal for point " << meshPointI
1547  << ' ' << pp.points()[meshPointI]
1548  << "; setting displacement to "
1549  << patchDisp[patchPointI]
1550  << endl;
1551  }
1552 
1553  extrudeStatus[patchPointI] = EXTRUDEREMOVE;
1554  nNoVisNormal++;
1555  }
1556  }
1557  }
1558 
1559  // At illegal points make displacement average of new neighbour positions
1560  forAll(extrudeStatus, patchPointI)
1561  {
1562  if (extrudeStatus[patchPointI] == EXTRUDEREMOVE)
1563  {
1564  point avg(vector::zero);
1565  label nPoints = 0;
1566 
1567  const labelList& pEdges = pp.pointEdges()[patchPointI];
1568 
1569  forAll(pEdges, i)
1570  {
1571  label edgeI = pEdges[i];
1572 
1573  label otherPointI = pp.edges()[edgeI].otherVertex(patchPointI);
1574 
1575  if (extrudeStatus[otherPointI] != NOEXTRUDE)
1576  {
1577  avg += localPoints[otherPointI] + patchDisp[otherPointI];
1578  nPoints++;
1579  }
1580  }
1581 
1582  if (nPoints > 0)
1583  {
1584  if (debug&meshRefinement::ATTRACTION)
1585  {
1586  Pout<< "Displacement at illegal point "
1587  << localPoints[patchPointI]
1588  << " set to "
1589  << (avg / nPoints - localPoints[patchPointI])
1590  << endl;
1591  }
1592 
1593  patchDisp[patchPointI] =
1594  avg / nPoints
1595  - localPoints[patchPointI];
1596 
1597  nExtrudeRemove++;
1598  }
1599  else
1600  {
1601  // All surrounding points are not extruded. Leave patchDisp
1602  // intact.
1603  }
1604  }
1605  }
1606 
1607  Info<< "Detected " << returnReduce(nNoVisNormal, sumOp<label>())
1608  << " points with point normal pointing through faces." << nl
1609  << "Reset displacement at "
1610  << returnReduce(nExtrudeRemove, sumOp<label>())
1611  << " points to average of surrounding points." << endl;
1612 
1613  // Make sure displacement is equal on both sides of coupled patches.
1614  syncPatchDisplacement
1615  (
1616  pp,
1617  minThickness,
1618  patchDisp,
1619  patchNLayers,
1620  extrudeStatus
1621  );
1622 
1623  Info<< endl;
1624 }
1625 
1626 
1629  const labelListList& globalEdgeFaces,
1630  const label myGlobalFaceI,
1631  const label nbrGlobFaceI,
1632  const label edgeI
1633 ) const
1634 {
1635  const labelList& eFaces = globalEdgeFaces[edgeI];
1636  if (eFaces.size() == 2)
1637  {
1638  return edge(myGlobalFaceI, nbrGlobFaceI) == edge(eFaces[0], eFaces[1]);
1639  }
1640  else
1641  {
1642  return false;
1643  }
1644 }
1645 
1646 
1649  const indirectPrimitivePatch& pp,
1650  const labelListList& globalEdgeFaces,
1651  const label faceI,
1652  const label edgeI,
1653  const label myGlobFaceI,
1654  const label nbrGlobFaceI,
1655  DynamicList<label>& vertices
1656 ) const
1657 {
1658  const labelList& fEdges = pp.faceEdges()[faceI];
1659  label fp = findIndex(fEdges, edgeI);
1660 
1661  if (fp == -1)
1662  {
1664  << "problem." << abort(FatalError);
1665  }
1666 
1667  // Search back
1668  label startFp = fp;
1669 
1670  forAll(fEdges, i)
1671  {
1672  label prevFp = fEdges.rcIndex(startFp);
1673  if
1674  (
1675  !sameEdgeNeighbour
1676  (
1677  globalEdgeFaces,
1678  myGlobFaceI,
1679  nbrGlobFaceI,
1680  fEdges[prevFp]
1681  )
1682  )
1683  {
1684  break;
1685  }
1686  startFp = prevFp;
1687  }
1688 
1689  label endFp = fp;
1690  forAll(fEdges, i)
1691  {
1692  label nextFp = fEdges.fcIndex(endFp);
1693  if
1694  (
1695  !sameEdgeNeighbour
1696  (
1697  globalEdgeFaces,
1698  myGlobFaceI,
1699  nbrGlobFaceI,
1700  fEdges[nextFp]
1701  )
1702  )
1703  {
1704  break;
1705  }
1706  endFp = nextFp;
1707  }
1708 
1709  const face& f = pp.localFaces()[faceI];
1710  vertices.clear();
1711  fp = startFp;
1712  while (fp != endFp)
1713  {
1714  vertices.append(f[fp]);
1715  fp = f.fcIndex(fp);
1716  }
1717  vertices.append(f[fp]);
1718  fp = f.fcIndex(fp);
1719  vertices.append(f[fp]);
1720 }
1721 
1722 
1723 // Truncates displacement
1724 // - for all patchFaces in the faceset displacement gets set to zero
1725 // - all displacement < minThickness gets set to zero
1728  const globalIndex& globalFaces,
1729  const labelListList& edgeGlobalFaces,
1730  const indirectPrimitivePatch& pp,
1731  const scalarField& minThickness,
1732  const faceSet& illegalPatchFaces,
1733  pointField& patchDisp,
1734  labelList& patchNLayers,
1735  List<extrudeMode>& extrudeStatus
1736 ) const
1737 {
1738  const fvMesh& mesh = meshRefiner_.mesh();
1739 
1740  label nChanged = 0;
1741 
1742  const Map<label>& meshPointMap = pp.meshPointMap();
1743 
1744  forAllConstIter(faceSet, illegalPatchFaces, iter)
1745  {
1746  label faceI = iter.key();
1747 
1748  if (mesh.isInternalFace(faceI))
1749  {
1751  << "Faceset " << illegalPatchFaces.name()
1752  << " contains internal face " << faceI << nl
1753  << "It should only contain patch faces" << abort(FatalError);
1754  }
1755 
1756  const face& f = mesh.faces()[faceI];
1757 
1758 
1759  forAll(f, fp)
1760  {
1761  if (meshPointMap.found(f[fp]))
1762  {
1763  label patchPointI = meshPointMap[f[fp]];
1764 
1765  if (extrudeStatus[patchPointI] != NOEXTRUDE)
1766  {
1767  unmarkExtrusion
1768  (
1769  patchPointI,
1770  patchDisp,
1771  patchNLayers,
1772  extrudeStatus
1773  );
1774  nChanged++;
1775  }
1776  }
1777  }
1778  }
1779 
1780  forAll(patchDisp, patchPointI)
1781  {
1782  if (mag(patchDisp[patchPointI]) < minThickness[patchPointI])
1783  {
1784  if
1785  (
1786  unmarkExtrusion
1787  (
1788  patchPointI,
1789  patchDisp,
1790  patchNLayers,
1791  extrudeStatus
1792  )
1793  )
1794  {
1795  nChanged++;
1796  }
1797  }
1798  else if (extrudeStatus[patchPointI] == NOEXTRUDE)
1799  {
1800  // Make sure displacement is 0. Should already be so but ...
1801  patchDisp[patchPointI] = vector::zero;
1802  patchNLayers[patchPointI] = 0;
1803  }
1804  }
1805 
1806 
1807  const faceList& localFaces = pp.localFaces();
1808 
1809  while (true)
1810  {
1811  syncPatchDisplacement
1812  (
1813  pp,
1814  minThickness,
1815  patchDisp,
1816  patchNLayers,
1817  extrudeStatus
1818  );
1819 
1820 
1821  // Pinch
1822  // ~~~~~
1823 
1824  // Make sure that a face doesn't have two non-consecutive areas
1825  // not extruded (e.g. quad where vertex 0 and 2 are not extruded
1826  // but 1 and 3 are) since this gives topological errors.
1827 
1828  label nPinched = 0;
1829 
1830  forAll(localFaces, i)
1831  {
1832  const face& localF = localFaces[i];
1833 
1834  // Count number of transitions from unsnapped to snapped.
1835  label nTrans = 0;
1836 
1837  extrudeMode prevMode = extrudeStatus[localF.prevLabel(0)];
1838 
1839  forAll(localF, fp)
1840  {
1841  extrudeMode fpMode = extrudeStatus[localF[fp]];
1842 
1843  if (prevMode == NOEXTRUDE && fpMode != NOEXTRUDE)
1844  {
1845  nTrans++;
1846  }
1847  prevMode = fpMode;
1848  }
1849 
1850  if (nTrans > 1)
1851  {
1852  // Multiple pinches. Reset whole face as unextruded.
1853  if
1854  (
1855  unmarkExtrusion
1856  (
1857  localF,
1858  patchDisp,
1859  patchNLayers,
1860  extrudeStatus
1861  )
1862  )
1863  {
1864  nPinched++;
1865  nChanged++;
1866  }
1867  }
1868  }
1869 
1870  reduce(nPinched, sumOp<label>());
1871 
1872  Info<< "truncateDisplacement : Unextruded " << nPinched
1873  << " faces due to non-consecutive vertices being extruded." << endl;
1874 
1875 
1876  // Butterfly
1877  // ~~~~~~~~~
1878 
1879  // Make sure that a string of edges becomes a single face so
1880  // not a butterfly. Occassionally an 'edge' will have a single dangling
1881  // vertex due to face combining. These get extruded as a single face
1882  // (with a dangling vertex) so make sure this extrusion forms a single
1883  // shape.
1884  // - continuous i.e. no butterfly:
1885  // + +
1886  // |\ /|
1887  // | \ / |
1888  // +--+--+
1889  // - extrudes from all but the endpoints i.e. no partial
1890  // extrude
1891  // +
1892  // /|
1893  // / |
1894  // +--+--+
1895  // The common error topology is a pinch somewhere in the middle
1896  label nButterFly = 0;
1897  {
1898  DynamicList<label> stringedVerts;
1899  forAll(pp.edges(), edgeI)
1900  {
1901  const labelList& globFaces = edgeGlobalFaces[edgeI];
1902 
1903  if (globFaces.size() == 2)
1904  {
1905  label myFaceI = pp.edgeFaces()[edgeI][0];
1906  label myGlobalFaceI = globalFaces.toGlobal
1907  (
1908  pp.addressing()[myFaceI]
1909  );
1910  label nbrGlobalFaceI =
1911  (
1912  globFaces[0] != myGlobalFaceI
1913  ? globFaces[0]
1914  : globFaces[1]
1915  );
1916  getVertexString
1917  (
1918  pp,
1919  edgeGlobalFaces,
1920  myFaceI,
1921  edgeI,
1922  myGlobalFaceI,
1923  nbrGlobalFaceI,
1924  stringedVerts
1925  );
1926 
1927  if
1928  (
1929  extrudeStatus[stringedVerts[0]] != NOEXTRUDE
1930  || extrudeStatus[stringedVerts.last()] != NOEXTRUDE
1931  )
1932  {
1933  // Any pinch in the middle
1934  bool pinch = false;
1935  for (label i = 1; i < stringedVerts.size()-1; i++)
1936  {
1937  if
1938  (
1939  extrudeStatus[stringedVerts[i]] == NOEXTRUDE
1940  )
1941  {
1942  pinch = true;
1943  break;
1944  }
1945  }
1946  if (pinch)
1947  {
1948  forAll(stringedVerts, i)
1949  {
1950  if
1951  (
1952  unmarkExtrusion
1953  (
1954  stringedVerts[i],
1955  patchDisp,
1956  patchNLayers,
1957  extrudeStatus
1958  )
1959  )
1960  {
1961  nButterFly++;
1962  nChanged++;
1963  }
1964  }
1965  }
1966  }
1967  }
1968  }
1969  }
1970 
1971  reduce(nButterFly, sumOp<label>());
1972 
1973  Info<< "truncateDisplacement : Unextruded " << nButterFly
1974  << " faces due to stringed edges with inconsistent extrusion."
1975  << endl;
1976 
1977 
1978 
1979  // Consistent number of layers
1980  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1981 
1982  // Make sure that a face has consistent number of layers for all
1983  // its vertices.
1984 
1985  label nDiffering = 0;
1986 
1987  //forAll(localFaces, i)
1988  //{
1989  // const face& localF = localFaces[i];
1990  //
1991  // label numLayers = -1;
1992  //
1993  // forAll(localF, fp)
1994  // {
1995  // if (patchNLayers[localF[fp]] > 0)
1996  // {
1997  // if (numLayers == -1)
1998  // {
1999  // numLayers = patchNLayers[localF[fp]];
2000  // }
2001  // else if (numLayers != patchNLayers[localF[fp]])
2002  // {
2003  // // Differing number of layers
2004  // if
2005  // (
2006  // unmarkExtrusion
2007  // (
2008  // localF,
2009  // patchDisp,
2010  // patchNLayers,
2011  // extrudeStatus
2012  // )
2013  // )
2014  // {
2015  // nDiffering++;
2016  // nChanged++;
2017  // }
2018  // break;
2019  // }
2020  // }
2021  // }
2022  //}
2023  //
2024  //reduce(nDiffering, sumOp<label>());
2025  //
2026  //Info<< "truncateDisplacement : Unextruded " << nDiffering
2027  // << " faces due to having differing number of layers." << endl;
2028 
2029  if (nPinched+nButterFly+nDiffering == 0)
2030  {
2031  break;
2032  }
2033  }
2034 
2035  return nChanged;
2036 }
2037 
2038 
2039 // Setup layer information (at points and faces) to modify mesh topology in
2040 // regions where layer mesh terminates.
2043  const indirectPrimitivePatch& pp,
2044  const labelList& patchNLayers,
2045  const List<extrudeMode>& extrudeStatus,
2046  const label nBufferCellsNoExtrude,
2047  labelList& nPatchPointLayers,
2048  labelList& nPatchFaceLayers
2049 ) const
2050 {
2051  Info<< nl << "Setting up information for layer truncation ..." << endl;
2052 
2053  const fvMesh& mesh = meshRefiner_.mesh();
2054 
2055  if (nBufferCellsNoExtrude < 0)
2056  {
2057  Info<< nl << "Performing no layer truncation."
2058  << " nBufferCellsNoExtrude set to less than 0 ..." << endl;
2059 
2060  // Face layers if any point gets extruded
2061  forAll(pp.localFaces(), patchFaceI)
2062  {
2063  const face& f = pp.localFaces()[patchFaceI];
2064 
2065  forAll(f, fp)
2066  {
2067  if (patchNLayers[f[fp]] > 0)
2068  {
2069  nPatchFaceLayers[patchFaceI] = patchNLayers[f[fp]];
2070  break;
2071  }
2072  }
2073  }
2074  nPatchPointLayers = patchNLayers;
2075 
2076  // Set any unset patch face layers
2077  forAll(nPatchFaceLayers, patchFaceI)
2078  {
2079  if (nPatchFaceLayers[patchFaceI] == -1)
2080  {
2081  nPatchFaceLayers[patchFaceI] = 0;
2082  }
2083  }
2084  }
2085  else
2086  {
2087  // Determine max point layers per face.
2088  labelList maxLevel(pp.size(), 0);
2089 
2090  forAll(pp.localFaces(), patchFaceI)
2091  {
2092  const face& f = pp.localFaces()[patchFaceI];
2093 
2094  // find patch faces where layer terminates (i.e contains extrude
2095  // and noextrude points).
2096 
2097  bool noExtrude = false;
2098  label mLevel = 0;
2099 
2100  forAll(f, fp)
2101  {
2102  if (extrudeStatus[f[fp]] == NOEXTRUDE)
2103  {
2104  noExtrude = true;
2105  }
2106  mLevel = max(mLevel, patchNLayers[f[fp]]);
2107  }
2108 
2109  if (mLevel > 0)
2110  {
2111  // So one of the points is extruded. Check if all are extruded
2112  // or is a mix.
2113 
2114  if (noExtrude)
2115  {
2116  nPatchFaceLayers[patchFaceI] = 1;
2117  maxLevel[patchFaceI] = mLevel;
2118  }
2119  else
2120  {
2121  maxLevel[patchFaceI] = mLevel;
2122  }
2123  }
2124  }
2125 
2126  // We have the seed faces (faces with nPatchFaceLayers != maxLevel)
2127  // Now do a meshwave across the patch where we pick up neighbours
2128  // of seed faces.
2129  // Note: quite inefficient. Could probably be coded better.
2130 
2131  const labelListList& pointFaces = pp.pointFaces();
2132 
2133  label nLevels = gMax(patchNLayers);
2134 
2135  // flag neighbouring patch faces with number of layers to grow
2136  for (label ilevel = 1; ilevel < nLevels; ilevel++)
2137  {
2138  label nBuffer;
2139 
2140  if (ilevel == 1)
2141  {
2142  nBuffer = nBufferCellsNoExtrude - 1;
2143  }
2144  else
2145  {
2146  nBuffer = nBufferCellsNoExtrude;
2147  }
2148 
2149  for (label ibuffer = 0; ibuffer < nBuffer + 1; ibuffer++)
2150  {
2151  labelList tempCounter(nPatchFaceLayers);
2152 
2153  boolList foundNeighbour(pp.nPoints(), false);
2154 
2155  forAll(pp.meshPoints(), patchPointI)
2156  {
2157  forAll(pointFaces[patchPointI], pointFaceI)
2158  {
2159  label faceI = pointFaces[patchPointI][pointFaceI];
2160 
2161  if
2162  (
2163  nPatchFaceLayers[faceI] != -1
2164  && maxLevel[faceI] > 0
2165  )
2166  {
2167  foundNeighbour[patchPointI] = true;
2168  break;
2169  }
2170  }
2171  }
2172 
2174  (
2175  mesh,
2176  pp.meshPoints(),
2177  foundNeighbour,
2178  orEqOp<bool>(),
2179  false // null value
2180  );
2181 
2182  forAll(pp.meshPoints(), patchPointI)
2183  {
2184  if (foundNeighbour[patchPointI])
2185  {
2186  forAll(pointFaces[patchPointI], pointFaceI)
2187  {
2188  label faceI = pointFaces[patchPointI][pointFaceI];
2189  if
2190  (
2191  nPatchFaceLayers[faceI] == -1
2192  && maxLevel[faceI] > 0
2193  && ilevel < maxLevel[faceI]
2194  )
2195  {
2196  tempCounter[faceI] = ilevel;
2197  }
2198  }
2199  }
2200  }
2201  nPatchFaceLayers = tempCounter;
2202  }
2203  }
2204 
2205  forAll(pp.localFaces(), patchFaceI)
2206  {
2207  if (nPatchFaceLayers[patchFaceI] == -1)
2208  {
2209  nPatchFaceLayers[patchFaceI] = maxLevel[patchFaceI];
2210  }
2211  }
2212 
2213  forAll(pp.meshPoints(), patchPointI)
2214  {
2215  if (extrudeStatus[patchPointI] != NOEXTRUDE)
2216  {
2217  forAll(pointFaces[patchPointI], pointFaceI)
2218  {
2219  label face = pointFaces[patchPointI][pointFaceI];
2220  nPatchPointLayers[patchPointI] = max
2221  (
2222  nPatchPointLayers[patchPointI],
2223  nPatchFaceLayers[face]
2224  );
2225  }
2226  }
2227  else
2228  {
2229  nPatchPointLayers[patchPointI] = 0;
2230  }
2231  }
2233  (
2234  mesh,
2235  pp.meshPoints(),
2236  nPatchPointLayers,
2237  maxEqOp<label>(),
2238  label(0) // null value
2239  );
2240  }
2241 }
2242 
2243 
2244 // Does any of the cells use a face from faces?
2247  const polyMesh& mesh,
2248  const labelList& cellLabels,
2249  const labelHashSet& faces
2250 )
2251 {
2252  forAll(cellLabels, i)
2253  {
2254  const cell& cFaces = mesh.cells()[cellLabels[i]];
2255 
2256  forAll(cFaces, cFaceI)
2257  {
2258  if (faces.found(cFaces[cFaceI]))
2259  {
2260  return true;
2261  }
2262  }
2263  }
2264  return false;
2265 }
2266 
2267 
2268 // Checks the newly added cells and locally unmarks points so they
2269 // will not get extruded next time round. Returns global number of unmarked
2270 // points (0 if all was fine)
2273  const addPatchCellLayer& addLayer,
2274  const dictionary& meshQualityDict,
2275  const bool additionalReporting,
2276  const List<labelPair>& baffles,
2277  const indirectPrimitivePatch& pp,
2278  const fvMesh& newMesh,
2279 
2280  pointField& patchDisp,
2281  labelList& patchNLayers,
2282  List<extrudeMode>& extrudeStatus
2283 )
2284 {
2285  // Check the resulting mesh for errors
2286  Info<< nl << "Checking mesh with layer ..." << endl;
2287  faceSet wrongFaces(newMesh, "wrongFaces", newMesh.nFaces()/1000);
2289  (
2290  false,
2291  newMesh,
2292  meshQualityDict,
2293  identity(newMesh.nFaces()),
2294  baffles,
2295  wrongFaces
2296  );
2297  Info<< "Detected " << returnReduce(wrongFaces.size(), sumOp<label>())
2298  << " illegal faces"
2299  << " (concave, zero area or negative cell pyramid volume)"
2300  << endl;
2301 
2302  // Undo local extrusion if
2303  // - any of the added cells in error
2304 
2305  label nChanged = 0;
2306 
2307  // Get all cells in the layer.
2308  labelListList addedCells
2309  (
2311  (
2312  newMesh,
2313  addLayer.layerFaces()
2314  )
2315  );
2316 
2317  // Check if any of the faces in error uses any face of an added cell
2318  // - if additionalReporting print the few remaining areas for ease of
2319  // finding out where the problems are.
2320 
2321  const label nReportMax = 10;
2322  DynamicField<point> disabledFaceCentres(nReportMax);
2323 
2324  forAll(addedCells, oldPatchFaceI)
2325  {
2326  // Get the cells (in newMesh labels) per old patch face (in mesh
2327  // labels)
2328  const labelList& fCells = addedCells[oldPatchFaceI];
2329 
2330  if (cellsUseFace(newMesh, fCells, wrongFaces))
2331  {
2332  // Unmark points on old mesh
2333  if
2334  (
2335  unmarkExtrusion
2336  (
2337  pp.localFaces()[oldPatchFaceI],
2338  patchDisp,
2339  patchNLayers,
2340  extrudeStatus
2341  )
2342  )
2343  {
2344  if (additionalReporting && (nChanged < nReportMax))
2345  {
2346  disabledFaceCentres.append
2347  (
2348  pp.faceCentres()[oldPatchFaceI]
2349  );
2350  }
2351 
2352  nChanged++;
2353  }
2354  }
2355  }
2356 
2357 
2358  label nChangedTotal = returnReduce(nChanged, sumOp<label>());
2359 
2360  if (additionalReporting)
2361  {
2362  // Limit the number of points to be printed so that
2363  // not too many points are reported when running in parallel
2364  // Not accurate, i.e. not always nReportMax points are written,
2365  // but this estimation avoid some communication here.
2366  // The important thing, however, is that when only a few faces
2367  // are disabled, their coordinates are printed, and this should be
2368  // the case
2369  label nReportLocal = nChanged;
2370  if (nChangedTotal > nReportMax)
2371  {
2372  nReportLocal = min
2373  (
2374  max(nChangedTotal / Pstream::nProcs(), 1),
2375  min
2376  (
2377  nChanged,
2378  max(nReportMax / Pstream::nProcs(), 1)
2379  )
2380  );
2381  }
2382 
2383  if (nReportLocal)
2384  {
2385  Pout<< "Checked mesh with layers. Disabled extrusion at " << endl;
2386  for (label i=0; i < nReportLocal; i++)
2387  {
2388  Pout<< " " << disabledFaceCentres[i] << endl;
2389  }
2390  }
2391 
2392  label nReportTotal = returnReduce(nReportLocal, sumOp<label>());
2393 
2394  if (nReportTotal < nChangedTotal)
2395  {
2396  Info<< "Suppressed disabled extrusion message for other "
2397  << nChangedTotal - nReportTotal << " faces." << endl;
2398  }
2399  }
2400 
2401  return nChangedTotal;
2402 }
2403 
2404 
2405 //- Count global number of extruded faces
2408  const indirectPrimitivePatch& pp,
2409  const List<extrudeMode>& extrudeStatus
2410 )
2411 {
2412  // Count number of extruded patch faces
2413  label nExtruded = 0;
2414  {
2415  const faceList& localFaces = pp.localFaces();
2416 
2417  forAll(localFaces, i)
2418  {
2419  const face& localFace = localFaces[i];
2420 
2421  forAll(localFace, fp)
2422  {
2423  if (extrudeStatus[localFace[fp]] != NOEXTRUDE)
2424  {
2425  nExtruded++;
2426  break;
2427  }
2428  }
2429  }
2430  }
2431 
2432  return returnReduce(nExtruded, sumOp<label>());
2433 }
2434 
2435 
2438  const polyMesh& mesh,
2439  const labelList& newToOldFaces,
2440  const List<labelPair>& baffles
2441 )
2442 {
2443  // The problem is that the baffle faces are now inside the
2444  // mesh (addPatchCellLayer modifies original boundary faces and
2445  // adds new ones. So 2 pass:
2446  // - find the boundary face for all faces originating from baffle
2447  // - use the boundary face for the new baffles
2448 
2449  Map<label> baffleSet(4*baffles.size());
2450  forAll(baffles, baffleI)
2451  {
2452  baffleSet.insert(baffles[baffleI][0], baffleI);
2453  baffleSet.insert(baffles[baffleI][1], baffleI);
2454  }
2455 
2456 
2457  List<labelPair> newBaffles(baffles.size(), labelPair(-1, -1));
2458  for
2459  (
2460  label faceI = mesh.nInternalFaces();
2461  faceI < mesh.nFaces();
2462  faceI++
2463  )
2464  {
2465  label oldFaceI = newToOldFaces[faceI];
2466 
2467  Map<label>::const_iterator faceFnd = baffleSet.find(oldFaceI);
2468  if (faceFnd != baffleSet.end())
2469  {
2470  label baffleI = faceFnd();
2471  labelPair& p = newBaffles[baffleI];
2472  if (p[0] == -1)
2473  {
2474  p[0] = faceI;
2475  }
2476  else if (p[1] == -1)
2477  {
2478  p[1] = faceI;
2479  }
2480  else
2481  {
2483  << "Problem:" << faceI << " at:"
2484  << mesh.faceCentres()[faceI]
2485  << " is on same baffle as " << p[0]
2486  << " at:" << mesh.faceCentres()[p[0]]
2487  << " and " << p[1]
2488  << " at:" << mesh.faceCentres()[p[1]]
2489  << exit(FatalError);
2490  }
2491  }
2492  }
2493  return newBaffles;
2494 }
2495 
2496 
2497 // Collect layer faces and layer cells into mesh fields for ease of handling
2500  const polyMesh& mesh,
2501  const addPatchCellLayer& addLayer,
2502  const scalarField& oldRealThickness,
2503 
2504  labelList& cellNLayers,
2505  scalarField& faceRealThickness
2506 )
2507 {
2508  cellNLayers.setSize(mesh.nCells());
2509  cellNLayers = 0;
2510  faceRealThickness.setSize(mesh.nFaces());
2511  faceRealThickness = 0;
2512 
2513  // Mark all faces in the layer
2514  const labelListList& layerFaces = addLayer.layerFaces();
2515 
2516  // Mark all cells in the layer.
2517  labelListList addedCells(addPatchCellLayer::addedCells(mesh, layerFaces));
2518 
2519  forAll(addedCells, oldPatchFaceI)
2520  {
2521  const labelList& added = addedCells[oldPatchFaceI];
2522 
2523  const labelList& layer = layerFaces[oldPatchFaceI];
2524 
2525  if (layer.size())
2526  {
2527  // Leave out original internal face
2528  forAll(added, i)
2529  {
2530  cellNLayers[added[i]] = layer.size()-1;
2531  }
2532  }
2533  }
2534 
2535  forAll(layerFaces, oldPatchFaceI)
2536  {
2537  const labelList& layer = layerFaces[oldPatchFaceI];
2538  const scalar realThickness = oldRealThickness[oldPatchFaceI];
2539 
2540  if (layer.size())
2541  {
2542  // Layer contains both original boundary face and new boundary
2543  // face so is nLayers+1. Leave out old internal face.
2544  for (label i = 1; i < layer.size(); i++)
2545  {
2546  faceRealThickness[layer[i]] = realThickness;
2547  }
2548  }
2549  }
2550 }
2551 
2552 
2555  const fvMesh& mesh,
2556  const labelList& patchIDs,
2557  const labelList& cellNLayers,
2558  const scalarField& faceWantedThickness,
2559  const scalarField& faceRealThickness
2560 ) const
2561 {
2562  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2563 
2564  int oldPrecision = Info().precision();
2565 
2566  // Find maximum length of a patch name, for a nicer output
2567  label maxPatchNameLen = 0;
2568  forAll(patchIDs, i)
2569  {
2570  label patchI = patchIDs[i];
2571  word patchName = pbm[patchI].name();
2572  maxPatchNameLen = max(maxPatchNameLen, label(patchName.size()));
2573  }
2574 
2575  Info<< nl
2576  << setf(ios_base::left) << setw(maxPatchNameLen) << "patch"
2577  << setw(0) << " faces layers overall thickness" << nl
2578  << setf(ios_base::left) << setw(maxPatchNameLen) << " "
2579  << setw(0) << " [m] [%]" << nl
2580  << setf(ios_base::left) << setw(maxPatchNameLen) << "-----"
2581  << setw(0) << " ----- ------ --- ---" << endl;
2582 
2583 
2584  forAll(patchIDs, i)
2585  {
2586  label patchI = patchIDs[i];
2587  const polyPatch& pp = pbm[patchI];
2588 
2589  label sumSize = pp.size();
2590 
2591  // Number of layers
2592  const labelList& faceCells = pp.faceCells();
2593  label sumNLayers = 0;
2594  forAll(faceCells, i)
2595  {
2596  sumNLayers += cellNLayers[faceCells[i]];
2597  }
2598 
2599  // Thickness
2600  scalarField::subField patchWanted = pbm[patchI].patchSlice
2601  (
2602  faceWantedThickness
2603  );
2604  scalarField::subField patchReal = pbm[patchI].patchSlice
2605  (
2606  faceRealThickness
2607  );
2608 
2609  scalar sumRealThickness = sum(patchReal);
2610  scalar sumFraction = 0;
2611  forAll(patchReal, i)
2612  {
2613  if (patchWanted[i] > VSMALL)
2614  {
2615  sumFraction += (patchReal[i]/patchWanted[i]);
2616  }
2617  }
2618 
2619 
2620  reduce(sumSize, sumOp<label>());
2621  reduce(sumNLayers, sumOp<label>());
2622  reduce(sumRealThickness, sumOp<scalar>());
2623  reduce(sumFraction, sumOp<scalar>());
2624 
2625 
2626  scalar avgLayers = 0;
2627  scalar avgReal = 0;
2628  scalar avgFraction = 0;
2629  if (sumSize > 0)
2630  {
2631  avgLayers = scalar(sumNLayers)/sumSize;
2632  avgReal = sumRealThickness/sumSize;
2633  avgFraction = sumFraction/sumSize;
2634  }
2635 
2636  Info<< setf(ios_base::left) << setw(maxPatchNameLen)
2637  << pbm[patchI].name() << setprecision(3)
2638  << " " << setw(8) << sumSize
2639  << " " << setw(8) << avgLayers
2640  << " " << setw(8) << avgReal
2641  << " " << setw(8) << 100*avgFraction
2642  << endl;
2643  }
2644  Info<< setprecision(oldPrecision) << endl;
2645 }
2646 
2647 
2650  const fvMesh& mesh,
2651  const labelList& cellNLayers,
2652  const scalarField& faceRealThickness
2653 ) const
2654 {
2655  bool allOk = true;
2656  {
2657  label nAdded = 0;
2658  forAll(cellNLayers, cellI)
2659  {
2660  if (cellNLayers[cellI] > 0)
2661  {
2662  nAdded++;
2663  }
2664  }
2665  cellSet addedCellSet(mesh, "addedCells", nAdded);
2666  forAll(cellNLayers, cellI)
2667  {
2668  if (cellNLayers[cellI] > 0)
2669  {
2670  addedCellSet.insert(cellI);
2671  }
2672  }
2673  addedCellSet.instance() = meshRefiner_.timeName();
2674  Info<< "Writing "
2675  << returnReduce(addedCellSet.size(), sumOp<label>())
2676  << " added cells to cellSet "
2677  << addedCellSet.name() << endl;
2678  bool ok = addedCellSet.write();
2679  allOk = allOk && ok;
2680  }
2681  {
2682  label nAdded = 0;
2683  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
2684  {
2685  if (faceRealThickness[faceI] > 0)
2686  {
2687  nAdded++;
2688  }
2689  }
2690 
2691  faceSet layerFacesSet(mesh, "layerFaces", nAdded);
2692  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
2693  {
2694  if (faceRealThickness[faceI] > 0)
2695  {
2696  layerFacesSet.insert(faceI);
2697  }
2698  }
2699  layerFacesSet.instance() = meshRefiner_.timeName();
2700  Info<< "Writing "
2701  << returnReduce(layerFacesSet.size(), sumOp<label>())
2702  << " faces inside added layer to faceSet "
2703  << layerFacesSet.name() << endl;
2704  bool ok = layerFacesSet.write();
2705  allOk = allOk && ok;
2706  }
2707  return allOk;
2708 }
2709 
2710 
2713  const fvMesh& mesh,
2714  const labelList& patchIDs,
2715  const labelList& cellNLayers,
2716  const scalarField& faceWantedThickness,
2717  const scalarField& faceRealThickness
2718 ) const
2719 {
2720  bool allOk = true;
2721 
2723  {
2724  bool ok = writeLayerSets(mesh, cellNLayers, faceRealThickness);
2725  allOk = allOk && ok;
2726  }
2727 
2729  {
2730  Info<< nl << "Writing fields with layer information:" << incrIndent
2731  << endl;
2732  {
2734  (
2735  IOobject
2736  (
2737  "nSurfaceLayers",
2738  mesh.time().timeName(),
2739  mesh,
2742  false
2743  ),
2744  mesh,
2745  dimensionedScalar("zero", dimless, 0),
2746  fixedValueFvPatchScalarField::typeName
2747  );
2748  forAll(fld, cellI)
2749  {
2750  fld[cellI] = cellNLayers[cellI];
2751  }
2752  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2753  forAll(patchIDs, i)
2754  {
2755  label patchI = patchIDs[i];
2756  const polyPatch& pp = pbm[patchI];
2757  const labelList& faceCells = pp.faceCells();
2758  scalarField pfld(faceCells.size());
2759  forAll(faceCells, i)
2760  {
2761  pfld[i] = cellNLayers[faceCells[i]];
2762  }
2763  fld.boundaryField()[patchI] == pfld;
2764  }
2765  Info<< indent << fld.name() << " : actual number of layers"
2766  << endl;
2767  bool ok = fld.write();
2768  allOk = allOk && ok;
2769  }
2770  {
2772  (
2773  IOobject
2774  (
2775  "thickness",
2776  mesh.time().timeName(),
2777  mesh,
2780  false
2781  ),
2782  mesh,
2783  dimensionedScalar("zero", dimless, 0),
2784  fixedValueFvPatchScalarField::typeName
2785  );
2786  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2787  forAll(patchIDs, i)
2788  {
2789  label patchI = patchIDs[i];
2790  fld.boundaryField()[patchI] == pbm[patchI].patchSlice
2791  (
2792  faceRealThickness
2793  );
2794  }
2795  Info<< indent << fld.name() << " : overall layer thickness"
2796  << endl;
2797  bool ok = fld.write();
2798  allOk = allOk && ok;
2799  }
2800  {
2802  (
2803  IOobject
2804  (
2805  "thicknessFraction",
2806  mesh.time().timeName(),
2807  mesh,
2810  false
2811  ),
2812  mesh,
2813  dimensionedScalar("zero", dimless, 0),
2814  fixedValueFvPatchScalarField::typeName
2815  );
2816  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2817  forAll(patchIDs, i)
2818  {
2819  label patchI = patchIDs[i];
2820 
2821  scalarField::subField patchWanted = pbm[patchI].patchSlice
2822  (
2823  faceWantedThickness
2824  );
2825  scalarField::subField patchReal = pbm[patchI].patchSlice
2826  (
2827  faceRealThickness
2828  );
2829 
2830  // Convert patchReal to relavtive thickness
2831  scalarField pfld(patchReal.size(), 0.0);
2832  forAll(patchReal, i)
2833  {
2834  if (patchWanted[i] > VSMALL)
2835  {
2836  pfld[i] = patchReal[i]/patchWanted[i];
2837  }
2838  }
2839 
2840  fld.boundaryField()[patchI] == pfld;
2841  }
2842  Info<< indent << fld.name()
2843  << " : overall layer thickness (fraction"
2844  << " of desired thickness)" << endl;
2845  bool ok = fld.write();
2846  allOk = allOk && ok;
2847  }
2848  Info<< decrIndent<< endl;
2849  }
2850 
2851  return allOk;
2852 }
2853 
2854 
2855 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
2856 
2859  meshRefinement& meshRefiner,
2860  const labelList& globalToMasterPatch,
2861  const labelList& globalToSlavePatch
2862 )
2863 :
2864  meshRefiner_(meshRefiner),
2865  globalToMasterPatch_(globalToMasterPatch),
2866  globalToSlavePatch_(globalToSlavePatch)
2867 {}
2868 
2869 
2870 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2871 
2874  const layerParameters& layerParams,
2875  const dictionary& motionDict
2876 )
2877 {
2878  // Clip to 30 degrees. Not helpful!
2879  //scalar planarAngle = min(30.0, layerParams.featureAngle());
2880  scalar planarAngle = layerParams.mergePatchFacesAngle();
2881  scalar minCos = Foam::cos(degToRad(planarAngle));
2882 
2883  scalar concaveCos = Foam::cos(degToRad(layerParams.concaveAngle()));
2884 
2885  Info<< nl
2886  << "Merging all faces of a cell" << nl
2887  << "---------------------------" << nl
2888  << " - which are on the same patch" << nl
2889  << " - which make an angle < " << planarAngle
2890  << " degrees"
2891  << " (cos:" << minCos << ')' << nl
2892  << " - as long as the resulting face doesn't become concave"
2893  << " by more than "
2894  << layerParams.concaveAngle() << " degrees" << nl
2895  << " (0=straight, 180=fully concave)" << nl
2896  << endl;
2897 
2898  const fvMesh& mesh = meshRefiner_.mesh();
2899 
2901 
2902  labelList duplicateFace(mesh.nFaces(), -1);
2903  forAll(couples, i)
2904  {
2905  const labelPair& cpl = couples[i];
2906  duplicateFace[cpl[0]] = cpl[1];
2907  duplicateFace[cpl[1]] = cpl[0];
2908  }
2909 
2910  label nChanged = meshRefiner_.mergePatchFacesUndo
2911  (
2912  minCos,
2913  concaveCos,
2914  meshRefiner_.meshedPatches(),
2915  motionDict,
2916  duplicateFace
2917  );
2918 
2919  nChanged += meshRefiner_.mergeEdgesUndo(minCos, motionDict);
2920 }
2921 
2922 
2925  const layerParameters& layerParams,
2926  const dictionary& motionDict,
2927  const labelList& patchIDs,
2928  const label nAllowableErrors,
2929  decompositionMethod& decomposer,
2930  fvMeshDistribute& distributor
2931 )
2932 {
2933  fvMesh& mesh = meshRefiner_.mesh();
2934 
2935 
2936  // faceZones of type internal or baffle (for merging points across)
2937  labelList internalOrBaffleFaceZones;
2938  {
2940  fzTypes[0] = surfaceZonesInfo::INTERNAL;
2941  fzTypes[1] = surfaceZonesInfo::BAFFLE;
2942  internalOrBaffleFaceZones = meshRefiner_.getZones(fzTypes);
2943  }
2944 
2945  // faceZones of type internal (for checking mesh quality across and
2946  // merging baffles)
2947  const labelList internalFaceZones
2948  (
2949  meshRefiner_.getZones
2950  (
2952  (
2953  1,
2955  )
2956  )
2957  );
2958 
2959  // Create baffles (pairs of faces that share the same points)
2960  // Baffles stored as owner and neighbour face that have been created.
2961  List<labelPair> baffles;
2962  {
2963  labelList originatingFaceZone;
2964  meshRefiner_.createZoneBaffles
2965  (
2966  identity(mesh.faceZones().size()),
2967  baffles,
2968  originatingFaceZone
2969  );
2970 
2972  {
2973  const_cast<Time&>(mesh.time())++;
2974  Info<< "Writing baffled mesh to time "
2975  << meshRefiner_.timeName() << endl;
2976  meshRefiner_.write
2977  (
2980  (
2983  ),
2984  mesh.time().path()/meshRefiner_.timeName()
2985  );
2986  }
2987  }
2988 
2989 
2990  // Duplicate points on faceZones of type boundary. Should normally already
2991  // be done by snapping phase
2992  {
2993  autoPtr<mapPolyMesh> map = meshRefiner_.dupNonManifoldBoundaryPoints();
2994  if (map.valid())
2995  {
2996  const labelList& reverseFaceMap = map().reverseFaceMap();
2997  forAll(baffles, i)
2998  {
2999  label f0 = reverseFaceMap[baffles[i].first()];
3000  label f1 = reverseFaceMap[baffles[i].second()];
3001  baffles[i] = labelPair(f0, f1);
3002  }
3003  }
3004  }
3005 
3006 
3007 
3008  // Now we have all patches determine the number of layer per patch
3009  // This will be layerParams.numLayers() except for faceZones where one
3010  // side does get layers and the other not in which case we want to
3011  // suppress movement by explicitly setting numLayers 0
3012  labelList numLayers(layerParams.numLayers());
3013  {
3014  labelHashSet layerIDs(patchIDs);
3015  forAll(mesh.faceZones(), zoneI)
3016  {
3017  label mpI, spI;
3019  bool hasInfo = meshRefiner_.getFaceZoneInfo
3020  (
3021  mesh.faceZones()[zoneI].name(),
3022  mpI,
3023  spI,
3024  fzType
3025  );
3026  if (hasInfo)
3027  {
3028  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
3029  if (layerIDs.found(mpI) && !layerIDs.found(spI))
3030  {
3031  // Only layers on master side. Fix points on slave side
3032  Info<< "On faceZone " << mesh.faceZones()[zoneI].name()
3033  << " adding layers to master patch " << pbm[mpI].name()
3034  << " only. Freezing points on slave patch "
3035  << pbm[spI].name() << endl;
3036  numLayers[spI] = 0;
3037  }
3038  else if (!layerIDs.found(mpI) && layerIDs.found(spI))
3039  {
3040  // Only layers on slave side. Fix points on master side
3041  Info<< "On faceZone " << mesh.faceZones()[zoneI].name()
3042  << " adding layers to slave patch " << pbm[spI].name()
3043  << " only. Freezing points on master patch "
3044  << pbm[mpI].name() << endl;
3045  numLayers[mpI] = 0;
3046  }
3047  }
3048  }
3049  }
3050 
3051 
3052 
3053  // Duplicate points on faceZones that layers are added to
3054  labelList pointToDuplicate;
3055 
3056  {
3057  // Check outside of baffles for non-manifoldness
3058  PackedBoolList duplicatePoint(mesh.nPoints());
3059  {
3060  // Do full analysis to see if we need to extrude points
3061  // so have to duplicate them
3063  (
3065  (
3066  mesh,
3067  patchIDs
3068  )
3069  );
3070 
3071  // Displacement for all pp.localPoints. Set to large value to
3072  // avoid truncation in syncPatchDisplacement because of
3073  // minThickness.
3074  vectorField patchDisp(pp().nPoints(), vector(GREAT, GREAT, GREAT));
3075  labelList patchNLayers(pp().nPoints(), 0);
3076  label nIdealTotAddedCells = 0;
3077  List<extrudeMode> extrudeStatus(pp().nPoints(), EXTRUDE);
3078  // Get number of layers per point from number of layers per patch
3079  setNumLayers
3080  (
3081  numLayers, // per patch the num layers
3082  patchIDs, // patches that are being moved
3083  pp, // indirectpatch for all faces moving
3084 
3085  patchDisp,
3086  patchNLayers,
3087  extrudeStatus,
3088  nIdealTotAddedCells
3089  );
3090  // Make sure displacement is equal on both sides of coupled patches.
3091  // Note that we explicitly disable the minThickness truncation
3092  // of the patchDisp here.
3093  syncPatchDisplacement
3094  (
3095  pp,
3096  scalarField(patchDisp.size(), 0.0), //minThickness,
3097  patchDisp,
3098  patchNLayers,
3099  extrudeStatus
3100  );
3101 
3102  forAll(extrudeStatus, patchPointI)
3103  {
3104  if (extrudeStatus[patchPointI] != NOEXTRUDE)
3105  {
3106  duplicatePoint[pp().meshPoints()[patchPointI]] = 1;
3107  }
3108  }
3109  }
3110 
3111 
3112  // Duplicate points only if all points agree
3114  (
3115  mesh,
3116  duplicatePoint,
3117  andEqOp<unsigned int>(), // combine op
3118  0u // null value
3119  );
3120  label n = duplicatePoint.count();
3121  labelList candidatePoints(n);
3122  n = 0;
3123  forAll(duplicatePoint, pointI)
3124  {
3125  if (duplicatePoint[pointI])
3126  {
3127  candidatePoints[n++] = pointI;
3128  }
3129  }
3130 
3131  // Not duplicate points on either side of baffles that don't get any
3132  // layers
3133  labelPairList nonDupBaffles;
3134 
3135  {
3136  // faceZones that are not being duplicated
3137  DynamicList<label> nonDupZones(mesh.faceZones().size());
3138 
3139  labelHashSet layerIDs(patchIDs);
3140  forAll(mesh.faceZones(), zoneI)
3141  {
3142  label mpI, spI;
3144  bool hasInfo = meshRefiner_.getFaceZoneInfo
3145  (
3146  mesh.faceZones()[zoneI].name(),
3147  mpI,
3148  spI,
3149  fzType
3150  );
3151  if (hasInfo && !layerIDs.found(mpI) && !layerIDs.found(spI))
3152  {
3153  nonDupZones.append(zoneI);
3154  }
3155  }
3156  nonDupBaffles = meshRefinement::subsetBaffles
3157  (
3158  mesh,
3159  nonDupZones,
3161  );
3162  }
3163 
3164 
3165  const localPointRegion regionSide(mesh, nonDupBaffles, candidatePoints);
3166 
3167  autoPtr<mapPolyMesh> map = meshRefiner_.dupNonManifoldPoints
3168  (
3169  regionSide
3170  );
3171 
3172  if (map.valid())
3173  {
3174  // Store point duplication
3175  pointToDuplicate.setSize(mesh.nPoints(), -1);
3176 
3177  const labelList& pointMap = map().pointMap();
3178  const labelList& reversePointMap = map().reversePointMap();
3179 
3180  forAll(pointMap, pointI)
3181  {
3182  label oldPointI = pointMap[pointI];
3183  label newMasterPointI = reversePointMap[oldPointI];
3184 
3185  if (newMasterPointI != pointI)
3186  {
3187  // Found slave. Mark both master and slave
3188  pointToDuplicate[pointI] = newMasterPointI;
3189  pointToDuplicate[newMasterPointI] = newMasterPointI;
3190  }
3191  }
3192 
3193  // Update baffle numbering
3194  {
3195  const labelList& reverseFaceMap = map().reverseFaceMap();
3196  forAll(baffles, i)
3197  {
3198  label f0 = reverseFaceMap[baffles[i].first()];
3199  label f1 = reverseFaceMap[baffles[i].second()];
3200  baffles[i] = labelPair(f0, f1);
3201  }
3202  }
3203 
3204 
3206  {
3207  const_cast<Time&>(mesh.time())++;
3208  Info<< "Writing point-duplicate mesh to time "
3209  << meshRefiner_.timeName() << endl;
3210 
3211  meshRefiner_.write
3212  (
3215  (
3218  ),
3219  mesh.time().path()/meshRefiner_.timeName()
3220  );
3221 
3222  OBJstream str
3223  (
3224  mesh.time().path()
3225  / "duplicatePoints_"
3226  + meshRefiner_.timeName()
3227  + ".obj"
3228  );
3229  Info<< "Writing point-duplicates to " << str.name() << endl;
3230  const pointField& p = mesh.points();
3231  forAll(pointMap, pointI)
3232  {
3233  label newMasterI = reversePointMap[pointMap[pointI]];
3234 
3235  if (newMasterI != pointI)
3236  {
3237  str.write(linePointRef(p[pointI], p[newMasterI]));
3238  }
3239  }
3240  }
3241  }
3242  }
3243 
3244 
3245  // Add layers to patches
3246  // ~~~~~~~~~~~~~~~~~~~~~
3247 
3248  // Now we have
3249  // - mesh with optional baffles and duplicated points for faceZones
3250  // where layers are to be added
3251  // - pointToDuplicate : correspondence for duplicated points
3252  // - baffles : list of pairs of faces
3253 
3254 
3256  (
3258  (
3259  mesh,
3260  patchIDs
3261  )
3262  );
3263 
3264 
3265  // Global face indices engine
3266  const globalIndex globalFaces(mesh.nFaces());
3267 
3268  // Determine extrudePatch.edgeFaces in global numbering (so across
3269  // coupled patches). This is used only to string up edges between coupled
3270  // faces (all edges between same (global)face indices get extruded).
3271  labelListList edgeGlobalFaces
3272  (
3274  (
3275  mesh,
3276  globalFaces,
3277  pp
3278  )
3279  );
3280 
3281  // Determine patches for extruded boundary edges. Calculates if any
3282  // additional processor patches need to be constructed.
3283 
3284  labelList edgePatchID;
3285  labelList edgeZoneID;
3286  boolList edgeFlip;
3287  labelList inflateFaceID;
3288  determineSidePatches
3289  (
3290  globalFaces,
3291  edgeGlobalFaces,
3292  pp,
3293 
3294  edgePatchID,
3295  edgeZoneID,
3296  edgeFlip,
3297  inflateFaceID
3298  );
3299 
3300 
3301  // Point-wise extrusion data
3302  // ~~~~~~~~~~~~~~~~~~~~~~~~~
3303 
3304  // Displacement for all pp.localPoints. Set to large value so does
3305  // not trigger the minThickness truncation (see syncPatchDisplacement below)
3306  vectorField patchDisp(pp().nPoints(), vector(GREAT, GREAT, GREAT));
3307 
3308  // Number of layers for all pp.localPoints. Note: only valid if
3309  // extrudeStatus = EXTRUDE.
3310  labelList patchNLayers(pp().nPoints(), 0);
3311 
3312  // Ideal number of cells added
3313  label nIdealTotAddedCells = 0;
3314 
3315  // Whether to add edge for all pp.localPoints.
3316  List<extrudeMode> extrudeStatus(pp().nPoints(), EXTRUDE);
3317 
3318 
3319  {
3320  // Get number of layers per point from number of layers per patch
3321  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3322 
3323  setNumLayers
3324  (
3325  numLayers, // per patch the num layers
3326  patchIDs, // patches that are being moved
3327  pp, // indirectpatch for all faces moving
3328 
3329  patchDisp,
3330  patchNLayers,
3331  extrudeStatus,
3332  nIdealTotAddedCells
3333  );
3334 
3335  // Precalculate mesh edge labels for patch edges
3336  labelList meshEdges(pp().meshEdges(mesh.edges(), mesh.pointEdges()));
3337 
3338  // Disable extrusion on non-manifold points
3339  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3340 
3341  handleNonManifolds
3342  (
3343  pp,
3344  meshEdges,
3345  edgeGlobalFaces,
3346 
3347  patchDisp,
3348  patchNLayers,
3349  extrudeStatus
3350  );
3351 
3352  // Disable extrusion on feature angles
3353  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3354 
3355  handleFeatureAngle
3356  (
3357  pp,
3358  meshEdges,
3359  degToRad(layerParams.featureAngle()),
3360 
3361  patchDisp,
3362  patchNLayers,
3363  extrudeStatus
3364  );
3365 
3366  // Disable extrusion on warped faces
3367  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3368  // It is hard to calculate some length scale if not in relative
3369  // mode so disable this check.
3370  if (layerParams.relativeSizes())
3371  {
3372  // Undistorted edge length
3373  const scalar edge0Len =
3374  meshRefiner_.meshCutter().level0EdgeLength();
3375  const labelList& cellLevel = meshRefiner_.meshCutter().cellLevel();
3376 
3377  handleWarpedFaces
3378  (
3379  pp,
3380  layerParams.maxFaceThicknessRatio(),
3381  edge0Len,
3382  cellLevel,
3383 
3384  patchDisp,
3385  patchNLayers,
3386  extrudeStatus
3387  );
3388  }
3389 
3392  //
3393  //handleMultiplePatchFaces
3394  //(
3395  // pp,
3396  //
3397  // patchDisp,
3398  // patchNLayers,
3399  // extrudeStatus
3400  //);
3401 
3402 
3403  // Grow out region of non-extrusion
3404  for (label i = 0; i < layerParams.nGrow(); i++)
3405  {
3406  growNoExtrusion
3407  (
3408  pp,
3409  patchDisp,
3410  patchNLayers,
3411  extrudeStatus
3412  );
3413  }
3414  }
3415 
3416 
3417  // Undistorted edge length
3418  const scalar edge0Len = meshRefiner_.meshCutter().level0EdgeLength();
3419  const labelList& cellLevel = meshRefiner_.meshCutter().cellLevel();
3420 
3421  // Determine (wanted) point-wise overall layer thickness and expansion
3422  // ratio
3423  scalarField thickness(pp().nPoints());
3424  scalarIOField minThickness
3425  (
3426  IOobject
3427  (
3428  "minThickness",
3429  meshRefiner_.timeName(),
3430  mesh,
3432  ),
3433  pp().nPoints()
3434  );
3435  scalarField expansionRatio(pp().nPoints());
3436  calculateLayerThickness
3437  (
3438  pp,
3439  patchIDs,
3440  layerParams,
3441  cellLevel,
3442  patchNLayers,
3443  edge0Len,
3444 
3445  thickness,
3446  minThickness,
3447  expansionRatio
3448  );
3449 
3450 
3451 
3452  // Current set of topology changes. (changing mesh clears out
3453  // polyTopoChange)
3454  polyTopoChange savedMeshMod(mesh.boundaryMesh().size());
3455  // Per cell 0 or number of layers in the cell column it is part of
3456  labelList cellNLayers;
3457  // Per face actual overall layer thickness
3458  scalarField faceRealThickness;
3459  // Per face wanted overall layer thickness
3460  scalarField faceWantedThickness(mesh.nFaces(), 0.0);
3461  {
3462  UIndirectList<scalar>(faceWantedThickness, pp().addressing()) =
3463  avgPointData(pp, thickness);
3464  }
3465 
3466 
3467  {
3468  // Overall displacement field
3469  pointVectorField displacement
3470  (
3471  makeLayerDisplacementField
3472  (
3474  numLayers
3475  )
3476  );
3477 
3478  // Allocate run-time selectable mesh mover
3479  autoPtr<externalDisplacementMeshMover> medialAxisMoverPtr;
3480  {
3481  // Set up controls for meshMover
3482  dictionary combinedDict(layerParams.dict());
3483  // Add mesh quality constraints
3484  combinedDict.merge(motionDict);
3485  // Where to get minThickness from
3486  combinedDict.add("minThicknessName", minThickness.name());
3487 
3488  const List<labelPair> internalBaffles
3489  (
3491  (
3492  mesh,
3493  internalFaceZones,
3495  )
3496  );
3497 
3498  // Take over patchDisp as boundary conditions on displacement
3499  // pointVectorField
3500  medialAxisMoverPtr = externalDisplacementMeshMover::New
3501  (
3502  layerParams.meshShrinker(),
3503  combinedDict,
3504  internalBaffles,
3505  displacement
3506  );
3507  }
3508 
3509 
3510  // Saved old points
3511  const pointField oldPoints(mesh.points());
3512 
3513  for
3514  (
3515  label iteration = 0;
3516  iteration < layerParams.nLayerIter();
3517  iteration++
3518  )
3519  {
3520  Info<< nl
3521  << "Layer addition iteration " << iteration << nl
3522  << "--------------------------" << endl;
3523 
3524 
3525  // Unset the extrusion at the pp.
3526  const dictionary& meshQualityDict =
3527  (
3528  iteration < layerParams.nRelaxedIter()
3529  ? motionDict
3530  : motionDict.subDict("relaxed")
3531  );
3532 
3533  if (iteration >= layerParams.nRelaxedIter())
3534  {
3535  Info<< "Switched to relaxed meshQuality constraints." << endl;
3536  }
3537 
3538 
3539 
3540  // Make sure displacement is equal on both sides of coupled patches.
3541  // Note that this also does the patchDisp < minThickness truncation
3542  // so for the first pass make sure the patchDisp is larger than
3543  // that.
3544  syncPatchDisplacement
3545  (
3546  pp,
3547  minThickness,
3548  patchDisp,
3549  patchNLayers,
3550  extrudeStatus
3551  );
3552 
3553  // Displacement acc. to pointnormals
3554  getPatchDisplacement
3555  (
3556  pp,
3557  thickness,
3558  minThickness,
3559  patchDisp,
3560  patchNLayers,
3561  extrudeStatus
3562  );
3563 
3564  // Shrink mesh by displacement value first.
3565  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3566 
3567  {
3568  const pointField oldPatchPos(pp().localPoints());
3569 
3570  // We have patchDisp which is the outwards pointing
3571  // extrusion distance. Convert into an inwards pointing
3572  // shrink distance
3573  patchDisp = -patchDisp;
3574 
3575  // Take over patchDisp into pointDisplacement field and
3576  // adjust both for multi-patch constraints
3578  (
3579  patchIDs,
3580  pp,
3581  patchDisp,
3582  displacement
3583  );
3584 
3585 
3586  // Move mesh
3587  // ~~~~~~~~~
3588 
3589  // Set up controls for meshMover
3590  dictionary combinedDict(layerParams.dict());
3591  // Add standard quality constraints
3592  combinedDict.merge(motionDict);
3593  // Add relaxed constraints (overrides standard ones)
3594  combinedDict.merge(meshQualityDict);
3595  // Where to get minThickness from
3596  combinedDict.add("minThicknessName", minThickness.name());
3597 
3598  labelList checkFaces(identity(mesh.nFaces()));
3599  medialAxisMoverPtr().move
3600  (
3601  combinedDict,
3602  nAllowableErrors,
3603  checkFaces
3604  );
3605 
3606  pp().movePoints(mesh.points());
3607 
3608  // Update patchDisp (since not all might have been honoured)
3609  patchDisp = oldPatchPos - pp().localPoints();
3610  }
3611 
3612  // Truncate displacements that are too small (this will do internal
3613  // ones, coupled ones have already been truncated by
3614  // syncPatchDisplacement)
3615  faceSet dummySet(mesh, "wrongPatchFaces", 0);
3616  truncateDisplacement
3617  (
3618  globalFaces,
3619  edgeGlobalFaces,
3620  pp,
3621  minThickness,
3622  dummySet,
3623  patchDisp,
3624  patchNLayers,
3625  extrudeStatus
3626  );
3627 
3628 
3629  // Dump to .obj file for debugging.
3631  {
3632  dumpDisplacement
3633  (
3634  mesh.time().path()/"layer_" + meshRefiner_.timeName(),
3635  pp(),
3636  patchDisp,
3637  extrudeStatus
3638  );
3639 
3640  const_cast<Time&>(mesh.time())++;
3641  Info<< "Writing shrunk mesh to time "
3642  << meshRefiner_.timeName() << endl;
3643 
3644  // See comment in autoSnapDriver why we should not remove
3645  // meshPhi using mesh.clearOut().
3646 
3647  meshRefiner_.write
3648  (
3651  (
3654  ),
3655  mesh.time().path()/meshRefiner_.timeName()
3656  );
3657  }
3658 
3659 
3660  // Mesh topo change engine. Insert current mesh.
3661  polyTopoChange meshMod(mesh);
3662 
3663  // Grow layer of cells on to patch. Handles zero sized displacement.
3664  addPatchCellLayer addLayer(mesh);
3665 
3666  // Determine per point/per face number of layers to extrude. Also
3667  // handles the slow termination of layers when going switching
3668  // layers
3669 
3670  labelList nPatchPointLayers(pp().nPoints(), -1);
3671  labelList nPatchFaceLayers(pp().size(), -1);
3672  setupLayerInfoTruncation
3673  (
3674  pp,
3675  patchNLayers,
3676  extrudeStatus,
3677  layerParams.nBufferCellsNoExtrude(),
3678  nPatchPointLayers,
3679  nPatchFaceLayers
3680  );
3681 
3682  // Calculate displacement for final layer for addPatchLayer.
3683  // (layer of cells next to the original mesh)
3684  vectorField finalDisp(patchNLayers.size(), vector::zero);
3685 
3686  forAll(nPatchPointLayers, i)
3687  {
3688  scalar ratio = layerParams.finalLayerThicknessRatio
3689  (
3690  nPatchPointLayers[i],
3691  expansionRatio[i]
3692  );
3693  finalDisp[i] = ratio*patchDisp[i];
3694  }
3695 
3696 
3697  const scalarField invExpansionRatio(1.0/expansionRatio);
3698 
3699  // Add topo regardless of whether extrudeStatus is extruderemove.
3700  // Not add layer if patchDisp is zero.
3701  addLayer.setRefinement
3702  (
3703  globalFaces,
3704  edgeGlobalFaces,
3705 
3706  invExpansionRatio,
3707  pp(),
3708 
3709  edgePatchID, // boundary patch for extruded boundary edges
3710  edgeZoneID, // zone for extruded edges
3711  edgeFlip,
3712  inflateFaceID,
3713 
3714 
3715  labelList(0), // exposed patchIDs, not used for adding layers
3716  nPatchFaceLayers, // layers per face
3717  nPatchPointLayers, // layers per point
3718  finalDisp, // thickness of layer nearest internal mesh
3719  meshMod
3720  );
3721 
3722  if (debug)
3723  {
3724  const_cast<Time&>(mesh.time())++;
3725  }
3726 
3727  // Store mesh changes for if mesh is correct.
3728  savedMeshMod = meshMod;
3729 
3730 
3731  // With the stored topo changes we create a new mesh so we can
3732  // undo if neccesary.
3733 
3734  autoPtr<fvMesh> newMeshPtr;
3735  autoPtr<mapPolyMesh> map = meshMod.makeMesh
3736  (
3737  newMeshPtr,
3738  IOobject
3739  (
3740  //mesh.name()+"_layer",
3741  mesh.name(),
3742  static_cast<polyMesh&>(mesh).instance(),
3743  mesh.time(), // register with runTime
3745  static_cast<polyMesh&>(mesh).writeOpt()
3746  ), // io params from original mesh but new name
3747  mesh, // original mesh
3748  true // parallel sync
3749  );
3750  fvMesh& newMesh = newMeshPtr();
3751 
3752  //?neccesary? Update fields
3753  newMesh.updateMesh(map);
3754 
3755  newMesh.setInstance(meshRefiner_.timeName());
3756 
3757  // Update numbering on addLayer:
3758  // - cell/point labels to be newMesh.
3759  // - patchFaces to remain in oldMesh order.
3760  addLayer.updateMesh
3761  (
3762  map,
3763  identity(pp().size()),
3764  identity(pp().nPoints())
3765  );
3766 
3767  // Collect layer faces and cells for outside loop.
3768  getLayerCellsFaces
3769  (
3770  newMesh,
3771  addLayer,
3772  avgPointData(pp, mag(patchDisp))(), // current thickness
3773 
3774  cellNLayers,
3775  faceRealThickness
3776  );
3777 
3778 
3779  // Count number of added cells
3780  label nAddedCells = 0;
3781  forAll(cellNLayers, cellI)
3782  {
3783  if (cellNLayers[cellI] > 0)
3784  {
3785  nAddedCells++;
3786  }
3787  }
3788 
3789 
3790  if (debug&meshRefinement::MESH)
3791  {
3792  Info<< "Writing layer mesh to time " << meshRefiner_.timeName()
3793  << endl;
3794  newMesh.write();
3795  writeLayerSets(newMesh, cellNLayers, faceRealThickness);
3796 
3797  // Reset the instance of the original mesh so next iteration
3798  // it dumps a complete mesh. This is just so that the inbetween
3799  // newMesh does not upset e.g. paraFoam cycling through the
3800  // times.
3801  mesh.setInstance(meshRefiner_.timeName());
3802  }
3803 
3804 
3805  //- Get baffles in newMesh numbering. Note that we cannot detect
3806  // baffles here since the points are duplicated
3807  List<labelPair> internalBaffles;
3808  {
3809  // From old mesh face to corresponding newMesh boundary face
3810  labelList meshToNewMesh(mesh.nFaces(), -1);
3811  for
3812  (
3813  label faceI = newMesh.nInternalFaces();
3814  faceI < newMesh.nFaces();
3815  faceI++
3816  )
3817  {
3818  label newMeshFaceI = map().faceMap()[faceI];
3819  if (newMeshFaceI != -1)
3820  {
3821  meshToNewMesh[newMeshFaceI] = faceI;
3822  }
3823  }
3824 
3825  List<labelPair> newMeshBaffles(baffles.size());
3826  label newI = 0;
3827  forAll(baffles, i)
3828  {
3829  const labelPair& p = baffles[i];
3830  labelPair newMeshBaffle
3831  (
3832  meshToNewMesh[p[0]],
3833  meshToNewMesh[p[1]]
3834  );
3835  if (newMeshBaffle[0] != -1 && newMeshBaffle[1] != -1)
3836  {
3837  newMeshBaffles[newI++] = newMeshBaffle;
3838  }
3839  }
3840  newMeshBaffles.setSize(newI);
3841 
3842  internalBaffles = meshRefinement::subsetBaffles
3843  (
3844  newMesh,
3845  internalFaceZones,
3846  newMeshBaffles
3847  );
3848 
3849  Info<< "Detected "
3850  << returnReduce(internalBaffles.size(), sumOp<label>())
3851  << " baffles across faceZones of type internal" << nl
3852  << endl;
3853  }
3854 
3855  label nTotChanged = checkAndUnmark
3856  (
3857  addLayer,
3858  meshQualityDict,
3859  layerParams.additionalReporting(),
3860  internalBaffles,
3861  pp(),
3862  newMesh,
3863 
3864  patchDisp,
3865  patchNLayers,
3866  extrudeStatus
3867  );
3868 
3869  label nTotExtruded = countExtrusion(pp, extrudeStatus);
3870  label nTotFaces = returnReduce(pp().size(), sumOp<label>());
3871  label nTotAddedCells = returnReduce(nAddedCells, sumOp<label>());
3872 
3873  Info<< "Extruding " << nTotExtruded
3874  << " out of " << nTotFaces
3875  << " faces (" << 100.0*nTotExtruded/nTotFaces << "%)."
3876  << " Removed extrusion at " << nTotChanged << " faces."
3877  << endl
3878  << "Added " << nTotAddedCells << " out of "
3879  << nIdealTotAddedCells
3880  << " cells (" << 100.0*nTotAddedCells/nIdealTotAddedCells
3881  << "%)." << endl;
3882 
3883  if (nTotChanged == 0)
3884  {
3885  break;
3886  }
3887 
3888  // Reset mesh points and start again
3889  mesh.movePoints(oldPoints);
3890  pp().movePoints(mesh.points());
3891  medialAxisMoverPtr().movePoints(mesh.points());
3892 
3893  // Grow out region of non-extrusion
3894  for (label i = 0; i < layerParams.nGrow(); i++)
3895  {
3896  growNoExtrusion
3897  (
3898  pp,
3899  patchDisp,
3900  patchNLayers,
3901  extrudeStatus
3902  );
3903  }
3904 
3905  Info<< endl;
3906  }
3907  }
3908 
3909 
3910  // At this point we have a (shrunk) mesh and a set of topology changes
3911  // which will make a valid mesh with layer. Apply these changes to the
3912  // current mesh.
3913 
3914  {
3915  // Apply the stored topo changes to the current mesh.
3916  autoPtr<mapPolyMesh> map = savedMeshMod.changeMesh(mesh, false);
3917 
3918  // Hack to remove meshPhi - mapped incorrectly. TBD.
3919  mesh.clearOut();
3920 
3921  // Update fields
3922  mesh.updateMesh(map);
3923 
3924  // Move mesh (since morphing does not do this)
3925  if (map().hasMotionPoints())
3926  {
3927  mesh.movePoints(map().preMotionPoints());
3928  }
3929  else
3930  {
3931  // Delete mesh volumes.
3932  mesh.clearOut();
3933  }
3934 
3935  // Reset the instance for if in overwrite mode
3936  mesh.setInstance(meshRefiner_.timeName());
3937 
3938  meshRefiner_.updateMesh(map, labelList(0));
3939 
3940  // Update numbering of faceWantedThickness
3942  (
3943  map().faceMap(),
3944  scalar(0),
3945  faceWantedThickness
3946  );
3947 
3948  // Print data now that we still have patches for the zones
3949  //if (meshRefinement::outputLevel() & meshRefinement::OUTPUTLAYERINFO)
3950  printLayerData
3951  (
3952  mesh,
3953  patchIDs,
3954  cellNLayers,
3955  faceWantedThickness,
3956  faceRealThickness
3957  );
3958 
3959 
3960  // Dump for debugging
3962  {
3963  const_cast<Time&>(mesh.time())++;
3964  Info<< "Writing mesh with layers but disconnected to time "
3965  << meshRefiner_.timeName() << endl;
3966  meshRefiner_.write
3967  (
3970  (
3973  ),
3974  mesh.time().path()/meshRefiner_.timeName()
3975  );
3976  }
3977 
3978 
3979 
3980  // Update numbering of baffles
3981  {
3982  // From old mesh face to corresponding newMesh boundary face.
3983  // (we cannot just use faceMap or reverseFaceMap here since
3984  // multiple faces originate from the old face)
3985  labelList oldMeshToNewMesh(map().nOldFaces(), -1);
3986  for
3987  (
3988  label faceI = mesh.nInternalFaces();
3989  faceI < mesh.nFaces();
3990  faceI++
3991  )
3992  {
3993  label oldFaceI = map().faceMap()[faceI];
3994 
3995  if (oldFaceI != -1)
3996  {
3997  oldMeshToNewMesh[oldFaceI] = faceI;
3998  }
3999  }
4000 
4001  label newI = 0;
4002  forAll(baffles, i)
4003  {
4004  const labelPair& p = baffles[i];
4005 
4006  labelPair newB(oldMeshToNewMesh[p[0]], oldMeshToNewMesh[p[1]]);
4007  if (newB[0] != -1 && newB[1] != -1)
4008  {
4009  baffles[newI++] = newB;
4010  }
4011  }
4012  baffles.setSize(newI);
4013  }
4014 
4015 
4016 
4017  // Update numbering of pointToDuplicate
4018  if (returnReduce(pointToDuplicate.size(), sumOp<label>()))
4019  {
4020  // The problem is that pointToDuplicate is valid for the old
4021  // boundary points which are now internal. We need to find the
4022  // corresponding new boundary point.
4023 
4024 
4025  List<labelPair> mergePointBaffles
4026  (
4028  (
4029  mesh,
4030  internalOrBaffleFaceZones,
4031  baffles
4032  )
4033  );
4034  Info<< "Detected "
4035  << returnReduce(mergePointBaffles.size(), sumOp<label>())
4036  << " baffles to merge points across" << nl << endl;
4037 
4038 
4039  label nPointPairs = 0;
4040  forAll(pointToDuplicate, oldPointI)
4041  {
4042  label otherOldPointI = pointToDuplicate[oldPointI];
4043  if (otherOldPointI != -1)
4044  {
4045  nPointPairs++;
4046  }
4047  }
4048 
4049  const labelList& pointMap = map().pointMap();
4050 
4051  // 1. Construct map from old (possibly) internal point to
4052  // new boundary point
4053  Map<label> oldPointToBoundaryPoint(2*nPointPairs);
4054 
4055  forAll(mergePointBaffles, i)
4056  {
4057  const labelPair& baffle = mergePointBaffles[i];
4058  forAll(baffle, j)
4059  {
4060  const face& f = mesh.faces()[baffle[j]];
4061  forAll(f, fp)
4062  {
4063  label pointI = f[fp];
4064  label oldPointI = pointMap[pointI];
4065  if (pointToDuplicate[oldPointI] != -1)
4066  {
4067  oldPointToBoundaryPoint.insert(oldPointI, pointI);
4068  }
4069  }
4070  }
4071  }
4072 
4073 
4074  // 2. Pick up old internal point
4075 
4076  labelList oldPointToDuplicate(pointToDuplicate.xfer());
4077  pointToDuplicate.setSize(mesh.nPoints(), -1);
4078 
4079  forAll(mergePointBaffles, i)
4080  {
4081  const labelPair& baffle = mergePointBaffles[i];
4082  forAll(baffle, j)
4083  {
4084  const face& f = mesh.faces()[baffle[j]];
4085  forAll(f, fp)
4086  {
4087  label pointI = f[fp];
4088  label oldPointI = pointMap[pointI];
4089  label oldDupI = oldPointToDuplicate[oldPointI];
4090  if (oldDupI != -1)
4091  {
4092  label newPointI = oldPointToBoundaryPoint[oldDupI];
4093  pointToDuplicate[pointI] = newPointI;
4094  }
4095  }
4096  }
4097  }
4098 
4099 
4100  // Check
4101  forAll(pointToDuplicate, pointI)
4102  {
4103  label dupI = pointToDuplicate[pointI];
4104  if (dupI != -1)
4105  {
4106  const point& pt = mesh.points()[pointI];
4107  const point& dupPt = mesh.points()[dupI];
4108  if (mag(pt-dupPt) > meshRefiner_.mergeDistance())
4109  {
4111  << "Trying to merge points "
4112  << pointI << " at:" << pt
4113  << "and " << dupI << " at:" << dupPt
4114  << " distance " << mag(pt-dupPt)
4115  << endl;
4116  }
4117  }
4118  }
4119  }
4120  }
4121 
4122  // Count duplicate points
4123  label nPointPairs = 0;
4124  forAll(pointToDuplicate, pointI)
4125  {
4126  label otherPointI = pointToDuplicate[pointI];
4127  if (otherPointI != -1)
4128  {
4129  nPointPairs++;
4130  }
4131  }
4132  reduce(nPointPairs, sumOp<label>());
4133  if (nPointPairs > 0)
4134  {
4135  // Merge any duplicated points
4136  Info<< "Merging " << nPointPairs << " duplicated points ..." << endl;
4137 
4139  {
4140  OBJstream str
4141  (
4142  mesh.time().path()
4143  / "mergePoints_"
4144  + meshRefiner_.timeName()
4145  + ".obj"
4146  );
4147  Info<< "Points to be merged to " << str.name() << endl;
4148  forAll(pointToDuplicate, pointI)
4149  {
4150  label otherPointI = pointToDuplicate[pointI];
4151  if (otherPointI != -1)
4152  {
4153  const point& pt = mesh.points()[pointI];
4154  const point& otherPt = mesh.points()[otherPointI];
4155  str.write(linePointRef(pt, otherPt));
4156  }
4157  }
4158  }
4159 
4160 
4161  autoPtr<mapPolyMesh> map = meshRefiner_.mergePoints(pointToDuplicate);
4162  if (map.valid())
4163  {
4164  inplaceReorder(map().reverseCellMap(), cellNLayers);
4165 
4166  const labelList& reverseFaceMap = map().reverseFaceMap();
4167  inplaceReorder(reverseFaceMap, faceWantedThickness);
4168  inplaceReorder(reverseFaceMap, faceRealThickness);
4169 
4170  Info<< "Merged points in = "
4171  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
4172  }
4173  }
4174 
4175  if (mesh.faceZones().size() > 0)
4176  {
4177  // Merge any baffles
4178  Info<< "Converting baffles back into zoned faces ..."
4179  << endl;
4180 
4181  autoPtr<mapPolyMesh> map = meshRefiner_.mergeZoneBaffles
4182  (
4183  true, // internal zones
4184  false // baffle zones
4185  );
4186  if (map.valid())
4187  {
4188  inplaceReorder(map().reverseCellMap(), cellNLayers);
4189 
4190  const labelList& faceMap = map().faceMap();
4191 
4192  // Make sure to keep the max since on two patches only one has
4193  // layers.
4194  scalarField newFaceRealThickness(mesh.nFaces(), 0.0);
4195  scalarField newFaceWantedThickness(mesh.nFaces(), 0.0);
4196  forAll(newFaceRealThickness, faceI)
4197  {
4198  label oldFaceI = faceMap[faceI];
4199  if (oldFaceI >= 0)
4200  {
4201  scalar& realThick = newFaceRealThickness[faceI];
4202  realThick = max(realThick, faceRealThickness[oldFaceI]);
4203  scalar& wanted = newFaceWantedThickness[faceI];
4204  wanted = max(wanted, faceWantedThickness[oldFaceI]);
4205  }
4206  }
4207  faceRealThickness.transfer(newFaceRealThickness);
4208  faceWantedThickness.transfer(newFaceWantedThickness);
4209  }
4210 
4211  Info<< "Converted baffles in = "
4212  << meshRefiner_.mesh().time().cpuTimeIncrement()
4213  << " s\n" << nl << endl;
4214  }
4215 
4216  // Do final balancing
4217  // ~~~~~~~~~~~~~~~~~~
4218 
4219  if (Pstream::parRun())
4220  {
4221  Info<< nl
4222  << "Doing final balancing" << nl
4223  << "---------------------" << nl
4224  << endl;
4225 
4226  if (debug)
4227  {
4228  const_cast<Time&>(mesh.time())++;
4229  }
4230 
4231  // Balance. No restriction on face zones and baffles.
4232  autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
4233  (
4234  false,
4235  false,
4236  scalarField(mesh.nCells(), 1.0),
4237  decomposer,
4238  distributor
4239  );
4240 
4241  // Re-distribute flag of layer faces and cells
4242  map().distributeCellData(cellNLayers);
4243  map().distributeFaceData(faceWantedThickness);
4244  map().distributeFaceData(faceRealThickness);
4245  }
4246 
4247 
4248  // Write mesh data
4249  // ~~~~~~~~~~~~~~~
4250 
4251  writeLayerData
4252  (
4253  mesh,
4254  patchIDs,
4255  cellNLayers,
4256  faceWantedThickness,
4257  faceRealThickness
4258  );
4259 }
4260 
4261 
4264  const dictionary& shrinkDict,
4265  const dictionary& motionDict,
4266  const layerParameters& layerParams,
4267  const bool mergePatchFaces,
4268  const bool preBalance,
4269  decompositionMethod& decomposer,
4270  fvMeshDistribute& distributor
4271 )
4272 {
4273  const fvMesh& mesh = meshRefiner_.mesh();
4274 
4275  Info<< nl
4276  << "Shrinking and layer addition phase" << nl
4277  << "----------------------------------" << nl
4278  << endl;
4279 
4280 
4281  Info<< "Using mesh parameters " << motionDict << nl << endl;
4282 
4283  // Merge coplanar boundary faces
4284  if (mergePatchFaces)
4285  {
4286  mergePatchFacesUndo(layerParams, motionDict);
4287  }
4288 
4289 
4290  // Per patch the number of layers (-1 or 0 if no layer)
4291  const labelList& numLayers = layerParams.numLayers();
4292 
4293  // Patches that need to get a layer
4294  DynamicList<label> patchIDs(numLayers.size());
4295  label nFacesWithLayers = 0;
4296  forAll(numLayers, patchI)
4297  {
4298  if (numLayers[patchI] > 0)
4299  {
4300  const polyPatch& pp = mesh.boundaryMesh()[patchI];
4301 
4302  if (!pp.coupled())
4303  {
4304  patchIDs.append(patchI);
4305  nFacesWithLayers += mesh.boundaryMesh()[patchI].size();
4306  }
4307  else
4308  {
4310  << "Ignoring layers on coupled patch " << pp.name()
4311  << endl;
4312  }
4313  }
4314  }
4315 
4316  // Add contributions from faceZones that get layers
4317  const faceZoneMesh& fZones = mesh.faceZones();
4318  forAll(fZones, zoneI)
4319  {
4320  label mpI, spI;
4322  meshRefiner_.getFaceZoneInfo(fZones[zoneI].name(), mpI, spI, fzType);
4323 
4324  if (numLayers[mpI] > 0)
4325  {
4326  nFacesWithLayers += fZones[zoneI].size();
4327  }
4328  if (numLayers[spI] > 0)
4329  {
4330  nFacesWithLayers += fZones[zoneI].size();
4331  }
4332  }
4333 
4334 
4335  patchIDs.shrink();
4336 
4337  if (returnReduce(nFacesWithLayers, sumOp<label>()) == 0)
4338  {
4339  Info<< nl << "No layers to generate ..." << endl;
4340  }
4341  else
4342  {
4343  // Check that outside of mesh is not multiply connected.
4344  checkMeshManifold();
4345 
4346  // Check initial mesh
4347  Info<< "Checking initial mesh ..." << endl;
4348  labelHashSet wrongFaces(mesh.nFaces()/100);
4349  motionSmoother::checkMesh(false, mesh, motionDict, wrongFaces);
4350  const label nInitErrors = returnReduce
4351  (
4352  wrongFaces.size(),
4353  sumOp<label>()
4354  );
4355 
4356  Info<< "Detected " << nInitErrors << " illegal faces"
4357  << " (concave, zero area or negative cell pyramid volume)"
4358  << endl;
4359 
4360 
4361  // Balance
4362  if (Pstream::parRun() && preBalance)
4363  {
4364  Info<< nl
4365  << "Doing initial balancing" << nl
4366  << "-----------------------" << nl
4367  << endl;
4368 
4369  scalarField cellWeights(mesh.nCells(), 1);
4370  forAll(numLayers, patchI)
4371  {
4372  if (numLayers[patchI] > 0)
4373  {
4374  const polyPatch& pp = mesh.boundaryMesh()[patchI];
4375  forAll(pp.faceCells(), i)
4376  {
4377  cellWeights[pp.faceCells()[i]] += numLayers[patchI];
4378  }
4379  }
4380  }
4381 
4382  // Add contributions from faceZones that get layers
4383  const faceZoneMesh& fZones = mesh.faceZones();
4384  forAll(fZones, zoneI)
4385  {
4386  const faceZone& fZone = fZones[zoneI];
4387  const word& fzName = fZone.name();
4388 
4389  label mpI, spI;
4391  meshRefiner_.getFaceZoneInfo(fzName, mpI, spI, fzType);
4392 
4393  if (numLayers[mpI] > 0)
4394  {
4395  // Get the owner side for unflipped faces, neighbour side
4396  // for flipped ones
4397  const labelList& cellIDs = fZone.slaveCells();
4398  forAll(cellIDs, i)
4399  {
4400  cellWeights[cellIDs[i]] += numLayers[mpI];
4401  }
4402  }
4403  if (numLayers[spI] > 0)
4404  {
4405  const labelList& cellIDs = fZone.masterCells();
4406  forAll(cellIDs, i)
4407  {
4408  cellWeights[cellIDs[i]] += numLayers[mpI];
4409  }
4410  }
4411  }
4412 
4413 
4414 
4415  // Balance mesh (and meshRefinement). Restrict faceZones to
4416  // be on internal faces only since they will be converted into
4417  // baffles.
4418  autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
4419  (
4420  true, // keepZoneFaces
4421  false,
4422  cellWeights,
4423  decomposer,
4424  distributor
4425  );
4426  }
4427 
4428 
4429  // Do all topo changes
4430  addLayers
4431  (
4432  layerParams,
4433  motionDict,
4434  patchIDs,
4435  nInitErrors,
4436  decomposer,
4437  distributor
4438  );
4439  }
4440 }
4441 
4442 
4443 // ************************************************************************* //
Foam::layerParameters::nGrow
label nGrow() const
If points get not extruded do nGrow layers of connected faces.
Definition: layerParameters.H:264
Foam::setf
Smanip< ios_base::fmtflags > setf(const ios_base::fmtflags flags)
Definition: IOmanip.H:164
addPatchCellLayer.H
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:48
Foam::IOobject
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
Foam::autoLayerDriver::mergePatchFacesUndo
void mergePatchFacesUndo(const layerParameters &layerParams, const dictionary &motionDict)
Merge patch faces on same cell.
Definition: autoLayerDriver.C:2873
Foam::PackedBoolList
A bit-packed bool list.
Definition: PackedBoolList.H:63
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatchTemplate.C:352
Foam::layerParameters::layerExpansionRatio
scalar layerExpansionRatio(const label n, const scalar totalOverFirst) const
Calculate expansion ratio from overall size v.s. thickness of.
Definition: layerParameters.C:41
Foam::autoLayerDriver::doLayers
void doLayers(const dictionary &shrinkDict, const dictionary &motionDict, const layerParameters &layerParams, const bool mergePatchFaces, const bool preBalance, decompositionMethod &decomposer, fvMeshDistribute &distributor)
Add layers according to the dictionary settings.
Definition: autoLayerDriver.C:4263
Foam::localPointRegion
Takes mesh with 'baffles' (= boundary faces sharing points). Determines for selected points on bounda...
Definition: localPointRegion.H:67
Foam::pointMesh::boundary
const pointBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: pointMesh.H:106
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
Foam::autoLayerDriver::getLayerCellsFaces
static void getLayerCellsFaces(const polyMesh &, const addPatchCellLayer &, const scalarField &oldRealThickness, labelList &cellStatus, scalarField &faceRealThickness)
Collect layer faces and layer cells into bools.
Definition: autoLayerDriver.C:2499
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
Foam::autoLayerDriver::determineSidePatches
void determineSidePatches(const globalIndex &globalFaces, const labelListList &edgeGlobalFaces, const indirectPrimitivePatch &pp, labelList &edgePatchID, labelList &edgeZoneID, boolList &edgeFlip, labelList &inflateFaceID)
See what zones and patches edges should be extruded into.
Definition: autoLayerDriver.C:969
Foam::autoLayerDriver::sameEdgeNeighbour
bool sameEdgeNeighbour(const labelListList &globalEdgeFaces, const label myGlobalFaceI, const label nbrGlobFaceI, const label edgeI) const
For truncateDisplacement: find strings of edges.
Definition: autoLayerDriver.C:1628
Foam::meshRefinement::WRITEMESH
@ WRITEMESH
Definition: meshRefinement.H:132
Foam::surfaceZonesInfo::faceZoneType
faceZoneType
What to do with faceZone faces.
Definition: surfaceZonesInfo.H:73
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:90
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatchTemplate.H:282
Foam::PrimitivePatch::edgeFaces
const labelListList & edgeFaces() const
Return edge-face addressing.
Definition: PrimitivePatchTemplate.C:292
Foam::autoLayerDriver::growNoExtrusion
void growNoExtrusion(const indirectPrimitivePatch &pp, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
Grow no-extrusion layer.
Definition: autoLayerDriver.C:879
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: IOField.H:50
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::OBJstream
OFstream which keeps track of vertices.
Definition: OBJstream.H:53
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
Foam::PrimitivePatch::edges
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Definition: PrimitivePatchTemplate.C:212
cyclicSlipPointPatchFields.H
Foam::IOobject::AUTO_WRITE
@ AUTO_WRITE
Definition: IOobject.H:117
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
nPatches
label nPatches
Definition: readKivaGrid.H:402
Foam::cpuTime::cpuTimeIncrement
double cpuTimeIncrement() const
Return CPU time (in seconds) since last call to cpuTimeIncrement()
Definition: cpuTime.C:74
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::layerParameters::dict
const dictionary & dict() const
Definition: layerParameters.H:162
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:118
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::autoLayerDriver::checkMeshManifold
void checkMeshManifold() const
Check that mesh outside is not multiply connected.
Definition: autoLayerDriver.C:160
Foam::addPatchCellLayer::globalEdgeFaces
static labelListList globalEdgeFaces(const polyMesh &, const globalIndex &globalFaces, const indirectPrimitivePatch &pp)
Per patch edge the pp faces (in global indices) using it. Uses.
Definition: addPatchCellLayer.C:618
Foam::polyTopoChange::changeMesh
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
Definition: polyTopoChange.C:3039
Foam::DynamicList< label >
calculatedPointPatchFields.H
Foam::List::xfer
Xfer< List< T > > xfer()
Transfer contents to the Xfer container.
Definition: ListI.H:90
Foam::OBJstream::write
virtual Ostream & write(const char)
Write character.
Definition: OBJstream.C:82
Foam::layerParameters::maxFaceThicknessRatio
scalar maxFaceThicknessRatio() const
Stop layer growth on highly warped cells.
Definition: layerParameters.H:270
Foam::PrimitivePatch::localPoints
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatchTemplate.C:432
mapPolyMesh.H
globalIndex.H
Foam::labelMax
static const label labelMax
Definition: label.H:62
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:387
Foam::meshRefinement::writeLevel
static writeType writeLevel()
Get/set write level.
Definition: meshRefinement.C:3065
Foam::Vector< scalar >::max
static const Vector max
Definition: Vector.H:82
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:322
polyTopoChange.H
motionSmoother.H
combineFaces.H
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
zeroFixedValuePointPatchFields.H
localPointRegion.H
Foam::meshRefinement::ATTRACTION
@ ATTRACTION
Definition: meshRefinement.H:106
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:136
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:97
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::layerParameters::nRelaxedIter
label nRelaxedIter() const
Number of iterations after which relaxed motion rules.
Definition: layerParameters.H:238
Foam::maxEqOp
Definition: ops.H:77
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::autoLayerDriver::truncateDisplacement
label truncateDisplacement(const globalIndex &globalFaces, const labelListList &edgeGlobalFaces, const indirectPrimitivePatch &pp, const scalarField &minThickness, const faceSet &illegalPatchFaces, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
Truncates displacement.
Definition: autoLayerDriver.C:1727
Foam::autoLayerDriver::unmarkExtrusion
static bool unmarkExtrusion(const label patchPointI, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus)
Unset extrusion on point. Returns true if anything unset.
Definition: autoLayerDriver.C:215
Foam::Map< label >
unitConversion.H
Unit conversion functions.
Foam::regIOobject::write
virtual bool write() const
Write using setting from DB.
Definition: regIOobjectWrite.C:126
Foam::autoLayerDriver::extrudeMode
extrudeMode
Extrusion controls.
Definition: autoLayerDriver.H:63
Foam::faceSet
A list of face labels.
Definition: faceSet.H:48
Foam::autoLayerDriver::addLayers
void addLayers(const layerParameters &layerParams, const dictionary &motionDict, const labelList &patchIDs, const label nAllowableErrors, decompositionMethod &decomposer, fvMeshDistribute &distributor)
Add cell layers.
Definition: autoLayerDriver.C:2924
Foam::fvMesh::movePoints
virtual tmp< scalarField > movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: fvMesh.C:726
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
scalarIOField.H
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:353
Foam::PrimitivePatch::faceEdges
const labelListList & faceEdges() const
Return face-edge addressing.
Definition: PrimitivePatchTemplate.C:312
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshPointEdges.C:96
Foam::IOobject::instance
const fileName & instance() const
Definition: IOobject.H:350
Foam::IOobject::writeOpt
writeOption writeOpt() const
Definition: IOobject.H:327
Foam::HashSet< label, Hash< label > >
Foam::meshRefinement::mesh
const fvMesh & mesh() const
Reference to mesh.
Definition: meshRefinement.H:817
Foam::primitiveMesh::nEdges
label nEdges() const
Definition: primitiveMeshI.H:41
Foam::incrIndent
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:228
Foam::autoLayerDriver::setupLayerInfoTruncation
void setupLayerInfoTruncation(const indirectPrimitivePatch &pp, const labelList &patchNLayers, const List< extrudeMode > &extrudeStatus, const label nBufferCellsNoExtrude, labelList &nPatchPointLayers, labelList &nPatchFaceLayers) const
Setup layer information (at points and faces) to.
Definition: autoLayerDriver.C:2042
Foam::autoLayerDriver::calculateLayerThickness
void calculateLayerThickness(const indirectPrimitivePatch &pp, const labelList &patchIDs, const layerParameters &layerParams, const labelList &cellLevel, const labelList &patchNLayers, const scalar edge0Len, scalarField &thickness, scalarField &minThickness, scalarField &expansionRatio) const
Calculate pointwise wanted and minimum thickness.
Definition: autoLayerDriver.C:1073
Foam::help::mergePatchFaces
faceList mergePatchFaces(const List< DynList< label > > &pfcs, const pointField &polyPoints)
Definition: helperFunctionsGeometryQueriesI.H:232
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::meshRefinement::updateList
static void updateList(const labelList &newToOld, const T &nullValue, List< T > &elems)
Helper: reorder list according to map.
Definition: meshRefinementTemplates.C:35
Foam::MeshObject< polyMesh, UpdateableMeshObject, pointMesh >::New
static const pointMesh & New(const polyMesh &mesh)
Definition: MeshObject.C:44
Foam::layerParameters::nLayerIter
label nLayerIter() const
Number of overall layer addition iterations.
Definition: layerParameters.H:231
Foam::autoLayerDriver::syncPatchDisplacement
void syncPatchDisplacement(const indirectPrimitivePatch &pp, const scalarField &minThickness, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
Synchronize displacement among coupled patches.
Definition: autoLayerDriver.C:1361
Foam::meshRefinement::subsetBaffles
static List< labelPair > subsetBaffles(const polyMesh &mesh, const labelList &zoneIDs, const List< labelPair > &baffles)
Subset baffles according to zones.
Definition: meshRefinementBaffles.C:739
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
Foam::DynamicField
Dynamically sized Field.
Definition: DynamicField.H:49
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::SubField
Pre-declare related SubField type.
Definition: Field.H:61
Foam::primitiveMesh::nCells
label nCells() const
Definition: primitiveMeshI.H:64
Foam::autoLayerDriver::avgPointData
static tmp< scalarField > avgPointData(const indirectPrimitivePatch &, const scalarField &pointFld)
Average point wise data to face wise.
Definition: autoLayerDriver.C:107
Foam::fvMesh::write
virtual bool write() const
Write mesh using IO settings from time.
Definition: fvMesh.C:873
Foam::autoLayerDriver::getPatchDisplacement
void getPatchDisplacement(const indirectPrimitivePatch &pp, const scalarField &thickness, const scalarField &minThickness, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
Get nearest point on surface to snap to.
Definition: autoLayerDriver.C:1492
Foam::autoLayerDriver::dumpDisplacement
static void dumpDisplacement(const fileName &, const indirectPrimitivePatch &, const vectorField &, const List< extrudeMode > &)
For debugging: Dump displacement to .obj files.
Definition: autoLayerDriver.C:75
mapDistributePolyMesh.H
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::layerParameters::minThickness
const scalarField & minThickness() const
Minimum overall thickness of cell layer. If for any reason layer.
Definition: layerParameters.H:222
Foam::autoLayerDriver::writeLayerSets
bool writeLayerSets(const fvMesh &mesh, const labelList &cellNLayers, const scalarField &faceRealThickness) const
Write cellSet,faceSet for layers.
Definition: autoLayerDriver.C:2649
Foam::regionSide
Determines the 'side' for every face and connected to a singly-connected (through edges) region of fa...
Definition: regionSide.H:61
Foam::primitiveMesh::nPoints
label nPoints() const
Definition: primitiveMeshI.H:35
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
removePoints.H
Foam::labelMin
static const label labelMin
Definition: label.H:61
Foam::layerParameters::nBufferCellsNoExtrude
label nBufferCellsNoExtrude() const
Create buffer region for new layer terminations.
Definition: layerParameters.H:276
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:102
Foam::autoLayerDriver::writeLayerData
bool writeLayerData(const fvMesh &mesh, const labelList &patchIDs, const labelList &cellNLayers, const scalarField &faceWantedThickness, const scalarField &faceRealThickness) const
Write volFields,cellSet,faceSet for layers depending.
Definition: autoLayerDriver.C:2712
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
externalDisplacementMeshMover.H
Foam::meshRefinement::LAYERINFO
@ LAYERINFO
Definition: meshRefinement.H:107
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::autoLayerDriver::getVertexString
void getVertexString(const indirectPrimitivePatch &pp, const labelListList &globalEdgeFaces, const label faceI, const label edgeI, const label myGlobFaceI, const label nbrGlobFaceI, DynamicList< label > &vertices) const
For truncateDisplacement: find strings of edges.
Definition: autoLayerDriver.C:1648
Foam::Ostream::write
virtual Ostream & write(const token &)=0
Write next token to stream.
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:111
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::autoLayerDriver::countExtrusion
static label countExtrusion(const indirectPrimitivePatch &pp, const List< extrudeMode > &extrudeStatus)
Count global number of extruded faces.
Definition: autoLayerDriver.C:2407
Foam::minEqOp
Definition: ops.H:78
Foam::externalDisplacementMeshMover::New
static autoPtr< externalDisplacementMeshMover > New(const word &type, const dictionary &dict, const List< labelPair > &baffles, pointVectorField &pointDisplacement)
Return a reference to the selected meshMover model.
Definition: externalDisplacementMeshMover.C:135
Foam::polyTopoChange::makeMesh
autoPtr< mapPolyMesh > makeMesh(autoPtr< fvMesh > &newMesh, const IOobject &io, const polyMesh &mesh, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Create new mesh with old mesh patches.
Definition: polyTopoChange.C:3305
Foam::globalMeshData::coupledPatchMeshEdges
const labelList & coupledPatchMeshEdges() const
Return map from coupledPatch edges to mesh edges.
Definition: globalMeshData.C:2107
Foam::PrimitivePatch::pointEdges
const labelListList & pointEdges() const
Return point-edge addressing.
Definition: PrimitivePatchTemplate.C:332
Foam::DynamicList::clear
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:242
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1017
faceSet.H
Foam::DynamicField::append
DynamicField< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::layerParameters::mergePatchFacesAngle
scalar mergePatchFacesAngle() const
Definition: layerParameters.H:251
Foam::IndirectList
A List with indirect addressing.
Definition: IndirectList.H:102
Foam::fvMesh::updateMesh
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
Definition: fvMesh.C:802
Foam::faceZone::slaveCells
const labelList & slaveCells() const
Return labels of slave cells.
Definition: faceZone.C:342
Foam::ZoneMesh< faceZone, polyMesh >
f1
scalar f1
Definition: createFields.H:28
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::dictionary::merge
bool merge(const dictionary &)
Merge entries from the given dictionary.
Definition: dictionary.C:1005
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobject.H:273
Foam::PackedList::count
unsigned int count() const
Count number of bits set, O(log(n))
Definition: PackedList.C:55
slipPointPatchFields.H
Foam::DynamicList::shrink
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
Foam::autoLayerDriver::checkAndUnmark
static label checkAndUnmark(const addPatchCellLayer &addLayer, const dictionary &motionDict, const bool additionalReporting, const List< labelPair > &baffles, const indirectPrimitivePatch &pp, const fvMesh &, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus)
Checks the newly added cells and locally unmarks points.
Definition: autoLayerDriver.C:2272
Foam::autoLayerDriver::getBafflesOnAddedMesh
static List< labelPair > getBafflesOnAddedMesh(const polyMesh &mesh, const labelList &newToOldFaces, const List< labelPair > &baffles)
After adding to mesh get the new baffles.
Definition: autoLayerDriver.C:2437
Foam::layerParameters
Simple container to keep together layer specific information.
Definition: layerParameters.H:55
Foam::orEqOp
Definition: ops.H:82
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
Foam::PrimitivePatch::nPoints
label nPoints() const
Return number of points supporting patch faces.
Definition: PrimitivePatchTemplate.H:293
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const
Definition: primitiveMeshI.H:52
Foam::meshRefinement::makePatch
static autoPtr< indirectPrimitivePatch > makePatch(const polyMesh &, const labelList &)
Create patch from set of patches.
Definition: meshRefinement.C:1644
Foam::addPatchCellLayer
Adds layers of cells to outside of polyPatch. Can optionally create stand-alone extruded mesh (addToM...
Definition: addPatchCellLayer.H:125
Foam::layerParameters::numLayers
const labelList & numLayers() const
How many layers to add.
Definition: layerParameters.H:175
Foam::autoLayerDriver::handleWarpedFaces
void handleWarpedFaces(const indirectPrimitivePatch &pp, const scalar faceRatio, const scalar edge0Len, const labelList &cellLevel, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
No extrusion on warped faces.
Definition: autoLayerDriver.C:506
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
fld
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< ' ';}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< ' ';}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< ' ';}gmvFile<< nl;forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
meshRefinement.H
Foam::autoLayerDriver::autoLayerDriver
autoLayerDriver(const autoLayerDriver &)
Disallow default bitwise copy construct.
Foam::dimensioned
Generic dimensioned Type class.
Definition: dimensionedScalarFwd.H:41
Foam::decompositionMethod
Abstract base class for decomposition.
Definition: decompositionMethod.H:48
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::pointMesh
Mesh representing a set of points created from polyMesh.
Definition: pointMesh.H:48
Foam::layerParameters::layerThickness
scalar layerThickness(const label nLayers, const scalar firstLayerThickess, const scalar finalLayerThickess, const scalar totalThickness, const scalar expansionRatio) const
Determine overall thickness. Uses two of the four parameters.
Definition: layerParameters.C:380
Foam::decrIndent
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:235
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::polyPatch::faceCells
const labelUList & faceCells() const
Return face-cell addressing.
Definition: polyPatch.C:340
Foam::zone::name
const word & name() const
Return name.
Definition: zone.H:150
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:48
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
Foam::indent
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:221
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Foam::addPatchCellLayer::updateMesh
void updateMesh(const mapPolyMesh &, const labelList &faceMap, const labelList &pointMap)
Update any locally stored mesh information. Gets additional.
Definition: addPatchCellLayer.C:1972
Foam::autoLayerDriver::meshRefiner_
meshRefinement & meshRefiner_
Mesh+surface.
Definition: autoLayerDriver.H:100
fixedValuePointPatchFields.H
Foam::layerParameters::additionalReporting
const Switch & additionalReporting() const
Definition: layerParameters.H:281
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::pointBoundaryMesh
Foam::pointBoundaryMesh.
Definition: pointBoundaryMesh.H:52
Foam::addPatchCellLayer::layerFaces
const labelListList & layerFaces() const
Layer faces per patch face. See above.
Definition: addPatchCellLayer.H:312
Foam::meshRefinement::WRITELAYERFIELDS
@ WRITELAYERFIELDS
Definition: meshRefinement.H:135
Foam::polyMesh::setInstance
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:32
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::surfaceZonesInfo::BAFFLE
@ BAFFLE
Definition: surfaceZonesInfo.H:76
Foam::setprecision
Omanip< int > setprecision(const int i)
Definition: IOmanip.H:205
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::autoPtr
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
Foam::autoLayerDriver::handleNonManifolds
void handleNonManifolds(const indirectPrimitivePatch &pp, const labelList &meshEdges, const labelListList &edgeGlobalFaces, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
No extrusion at non-manifold points.
Definition: autoLayerDriver.C:276
Foam::layerParameters::finalLayerThicknessRatio
scalar finalLayerThicknessRatio(const label nLayers, const scalar expansionRatio) const
Determine ratio of final layer thickness to.
Definition: layerParameters.C:550
Foam::autoLayerDriver::makeLayerDisplacementField
static tmp< pointVectorField > makeLayerDisplacementField(const pointMesh &pMesh, const labelList &numLayers)
Helper function to make a pointVectorField with correct.
Definition: autoLayerDriver.C:805
Foam::face::prevLabel
label prevLabel(const label i) const
Previous vertex on face.
Definition: faceI.H:124
Foam::faceZone::masterCells
const labelList & masterCells() const
Return labels of master cells (cells next to the master face.
Definition: faceZone.C:331
Foam::linePointRef
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
DynamicField.H
Foam::syncTools::syncEdgeList
static void syncEdgeList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh edges.
Definition: syncToolsTemplates.C:1141
Foam::primitiveMesh::nFaces
label nFaces() const
Definition: primitiveMeshI.H:58
Foam::layerParameters::featureAngle
scalar featureAngle() const
Definition: layerParameters.H:246
Foam::autoLayerDriver::cellsUseFace
static bool cellsUseFace(const polyMesh &mesh, const labelList &cellLabels, const labelHashSet &faces)
Does any of the cells use a face from faces?
Definition: autoLayerDriver.C:2246
Foam::sumOp
Definition: ops.H:162
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:281
Foam::pointSet
A set of point labels.
Definition: pointSet.H:48
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::PrimitivePatch::faceNormals
const Field< PointType > & faceNormals() const
Return face normals for patch.
Definition: PrimitivePatchTemplate.C:520
f
labelList f(nPoints)
Foam::motionSmootherAlgo::checkMesh
static bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, labelHashSet &wrongFaces)
Check mesh with mesh settings in dict. Collects incorrect faces.
Definition: motionSmootherAlgoCheck.C:415
layerParameters.H
Foam::PatchTools::pointNormals
static tmp< pointField > pointNormals(const polyMesh &, const PrimitivePatch< Face, FaceList, PointField, PointType > &)
Return parallel consistent point normals for patches using mesh points.
Foam::Vector< scalar >
Foam::meshRefinement::writeType
writeType
Definition: meshRefinement.H:130
Foam::Time::timeName
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:741
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::addPatchCellLayer::calcExtrudeInfo
static void calcExtrudeInfo(const bool zoneFromAnyFace, const polyMesh &, const globalIndex &globalFaces, const labelListList &globalEdgeFaces, const indirectPrimitivePatch &pp, labelList &edgePatchID, label &nPatches, Map< label > &nbrProcToPatch, Map< label > &patchToNbrProc, labelList &edgeZoneID, boolList &edgeFlip, labelList &inflateFaceID)
Determine extrude information per patch edge:
Definition: addPatchCellLayer.C:663
scalarField
volScalarField scalarField(fieldObject, mesh)
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:70
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:130
fixedValueFvPatchFields.H
Foam::PrimitivePatch::faceCentres
const Field< PointType > & faceCentres() const
Return face centres for patch.
Definition: PrimitivePatchTemplate.C:500
Foam::meshRefinement
Helper class which maintains intersections of (changing) mesh with (static) surfaces.
Definition: meshRefinement.H:82
Foam::autoPtr::valid
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set).
Definition: autoPtrI.H:83
Foam::motionSmootherAlgo::setDisplacement
static void setDisplacement(const labelList &patchIDs, const indirectPrimitivePatch &pp, pointField &patchDisp, pointVectorField &displacement)
Set displacement field from displacement on patch points.
Definition: motionSmootherAlgo.C:492
Foam::Vector< scalar >::rootMax
static const Vector rootMax
Definition: Vector.H:84
Foam::layerParameters::firstLayerThickness
const scalarField & firstLayerThickness() const
Wanted thickness of the layer nearest to the wall.
Definition: layerParameters.H:205
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::PtrList::size
label size() const
Return the number of elements in the PtrList.
Definition: PtrListI.H:32
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
Foam::layerParameters::expansionRatio
const scalarField & expansionRatio() const
Definition: layerParameters.H:188
Foam::syncTools::getMasterPoints
static PackedBoolList getMasterPoints(const polyMesh &)
Get per point whether it is uncoupled or a master of a.
Definition: syncTools.C:65
Foam::layerParameters::thickness
const scalarField & thickness() const
Wanted overall thickness of all layers.
Definition: layerParameters.H:213
Foam::autoLayerDriver::checkManifold
static void checkManifold(const indirectPrimitivePatch &, pointSet &nonManifoldPoints)
Check that primitivePatch is not multiply connected.
Definition: autoLayerDriver.C:134
Foam::autoPtr::reset
void reset(T *=0)
If object pointer already set, delete object and set to given.
Definition: autoPtrI.H:114
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:243
Foam::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatchTemplate.C:372
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:106
Foam::autoLayerDriver::printLayerData
void printLayerData(const fvMesh &mesh, const labelList &patchIDs, const labelList &cellNLayers, const scalarField &faceWantedThickness, const scalarField &faceRealThickness) const
Print layer coverage table.
Definition: autoLayerDriver.C:2554
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::minMagSqrEqOp
Definition: ops.H:79
Foam::OFstream::name
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:118
cellSet.H
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::layerParameters::relativeSizes
bool relativeSizes() const
Are size parameters relative to inner cell size or.
Definition: layerParameters.H:182
Foam::autoLayerDriver::handleFeatureAngle
void handleFeatureAngle(const indirectPrimitivePatch &pp, const labelList &meshEdges, const scalar minCos, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus) const
No extrusion on feature edges. Assumes non-manifold.
Definition: autoLayerDriver.C:387
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1143
Foam::PrimitivePatch::meshPointMap
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
Definition: PrimitivePatchTemplate.C:412
autoLayerDriver.H
Foam::autoLayerDriver::nomalsCombine
Combine operator class to combine normal with other normal.
Definition: autoLayerDriver.H:76
Foam::layerParameters::finalLayerThickness
const scalarField & finalLayerThickness() const
Wanted thickness of the layer furthest away.
Definition: layerParameters.H:197
Foam::meshTools::visNormal
bool visNormal(const vector &n, const vectorField &faceNormals, const labelList &faceLabels)
Check if n is in same direction as normals of all faceLabels.
Definition: meshTools.C:33
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatchTemplate.C:392
Foam::dictionary::subDict
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:631
Foam::GeometricField
Generic GeometricField class.
Definition: surfaceFieldsFwd.H:52
Foam::meshRefinement::WRITELAYERSETS
@ WRITELAYERSETS
Definition: meshRefinement.H:134
Foam::layerParameters::meshShrinker
const word & meshShrinker() const
Type of mesh shrinker.
Definition: layerParameters.H:287
Foam::PrimitivePatch::checkPointManifold
bool checkPointManifold(const bool report=false, labelHashSet *setPtr=NULL) const
Checks primitivePatch for faces sharing point but not edge.
Definition: PrimitivePatchCheck.C:247
Foam::autoLayerDriver::setNumLayers
void setNumLayers(const labelList &patchToNLayers, const labelList &patchIDs, const indirectPrimitivePatch &pp, pointField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus, label &nIdealAddedCells) const
Determine the number of layers per point from the number of.
Definition: autoLayerDriver.C:681
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::patchIdentifier::name
const word & name() const
Return name.
Definition: patchIdentifier.H:109
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::fvMeshDistribute
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
Definition: fvMeshDistribute.H:70
Foam::labelPair
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
pointFields.H
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:562
OBJstream.H
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::meshRefinement::MESH
@ MESH
Definition: meshRefinement.H:102
Foam::syncTools::syncPointList
static void syncPointList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
Definition: syncToolsTemplates.C:984
Foam::localPointRegion::findDuplicateFacePairs
static labelPairList findDuplicateFacePairs(const polyMesh &)
Helper routine to find all baffles (two boundary faces.
Definition: localPointRegion.C:620
Foam::dictionary::add
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:729
Foam::fvMesh::clearOut
void clearOut()
Clear all geometry and addressing.
Definition: fvMesh.C:231
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global.
Definition: globalIndexI.H:82
Foam::layerParameters::concaveAngle
scalar concaveAngle() const
Definition: layerParameters.H:256
Foam::fvMesh::name
const word & name() const
Return reference to name.
Definition: fvMesh.H:257
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88
Foam::andEqOp
Definition: ops.H:81
Foam::degToRad
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
Definition: unitConversion.H:45
Foam::addPatchCellLayer::setRefinement
void setRefinement(const globalIndex &globalFaces, const labelListList &globalEdgeFaces, const scalarField &expansionRatio, const indirectPrimitivePatch &pp, const labelList &sidePatchID, const labelList &sideZoneID, const boolList &sideFlip, const labelList &inflateFaceID, const labelList &exposedPatchID, const labelList &nFaceLayers, const labelList &nPointLayers, const vectorField &firstLayerDisp, polyTopoChange &meshMod)
Play commands into polyTopoChange to create layers on top.
Definition: addPatchCellLayer.C:1008
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256
Foam::addPatchCellLayer::addedCells
labelListList addedCells() const
Added cells given current mesh & layerfaces.
Definition: addPatchCellLayer.C:610
pointSet.H
Foam::meshRefinement::debugType
debugType
Definition: meshRefinement.H:100
Foam::surfaceZonesInfo::INTERNAL
@ INTERNAL
Definition: surfaceZonesInfo.H:75