extrudeToRegionMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  extrudeToRegionMesh
29 
30 Group
31  grpMeshGenerationUtilities
32 
33 Description
34  Extrude faceZones (internal or boundary faces) or faceSets (boundary faces
35  only) into a separate mesh (as a different region).
36 
37  - used to e.g. extrude baffles (extrude internal faces) or create
38  liquid film regions.
39  - if extruding internal faces:
40  - create baffles in original mesh with mappedWall patches
41  - if extruding boundary faces:
42  - convert boundary faces to mappedWall patches
43  - extrude edges of faceZone as a <zone>_sidePatch
44  - extrude edges inbetween different faceZones as a
45  (nonuniformTransform)cyclic <zoneA>_<zoneB>
46  - extrudes into master direction (i.e. away from the owner cell
47  if flipMap is false)
48 
49 \verbatim
50 
51 Internal face extrusion
52 -----------------------
53 
54  +-------------+
55  | |
56  | |
57  +---AAAAAAA---+
58  | |
59  | |
60  +-------------+
61 
62  AAA=faceZone to extrude.
63 
64 
65 For the case of no flipMap the extrusion starts at owner and extrudes
66 into the space of the neighbour:
67 
68  +CCCCCCC+
69  | | <= extruded mesh
70  +BBBBBBB+
71 
72  +-------------+
73  | |
74  | (neighbour) |
75  |___CCCCCCC___| <= original mesh (with 'baffles' added)
76  | BBBBBBB |
77  |(owner side) |
78  | |
79  +-------------+
80 
81  BBB=mapped between owner on original mesh and new extrusion.
82  (zero offset)
83  CCC=mapped between neighbour on original mesh and new extrusion
84  (offset due to the thickness of the extruded mesh)
85 
86 For the case of flipMap the extrusion is the other way around: from the
87 neighbour side into the owner side.
88 
89 
90 Boundary face extrusion
91 -----------------------
92 
93  +--AAAAAAA--+
94  | |
95  | |
96  +-----------+
97 
98  AAA=faceZone to extrude. E.g. slave side is owner side (no flipmap)
99 
100 becomes
101 
102  +CCCCCCC+
103  | | <= extruded mesh
104  +BBBBBBB+
105 
106  +--BBBBBBB--+
107  | | <= original mesh
108  | |
109  +-----------+
110 
111  BBB=mapped between original mesh and new extrusion
112  CCC=polypatch
113 
114 
115 Notes:
116  - when extruding cyclics with only one cell inbetween it does not
117  detect this as a cyclic since the face is the same face. It will
118  only work if the coupled edge extrudes a different face so if there
119  are more than 1 cell inbetween.
120 
121 \endverbatim
122 
123 \*---------------------------------------------------------------------------*/
124 
125 #include "argList.H"
126 #include "fvMesh.H"
127 #include "polyTopoChange.H"
128 #include "OFstream.H"
129 #include "meshTools.H"
130 #include "mappedWallPolyPatch.H"
131 #include "createShellMesh.H"
132 #include "syncTools.H"
133 #include "cyclicPolyPatch.H"
134 #include "wedgePolyPatch.H"
136 #include "extrudeModel.H"
137 #include "globalIndex.H"
138 #include "faceSet.H"
139 
140 #include "volFields.H"
141 #include "surfaceFields.H"
142 #include "pointFields.H"
143 //#include "ReadFields.H"
144 #include "fvMeshTools.H"
145 #include "OBJstream.H"
146 #include "PatchTools.H"
147 #include "processorMeshes.H"
148 
149 using namespace Foam;
150 
151 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
152 
153 label findPatchID(const UList<polyPatch*>& newPatches, const word& name)
154 {
155  forAll(newPatches, i)
156  {
157  if (newPatches[i]->name() == name)
158  {
159  return i;
160  }
161  }
162  return -1;
163 }
164 
165 
166 #ifdef FULLDEBUG
167 void printPatches(Ostream& os, const UList<polyPatch*>& newPatches)
168 {
169  for (const polyPatch* ppPtr : newPatches)
170  {
171  const polyPatch& pp = *ppPtr;
172  os << " name:" << pp.name() << " index:" << pp.index()
173  << " start:" << pp.start() << " size:" << pp.size()
174  << " type:" << pp.type() << nl;
175  }
176 }
177 #endif
178 
179 
180 template<class PatchType>
181 label addPatch
182 (
183  const polyBoundaryMesh& patches,
184  const word& patchName,
185  DynamicList<polyPatch*>& newPatches
186 )
187 {
188  label patchi = findPatchID(newPatches, patchName);
189 
190  if (patchi != -1)
191  {
192  if (isA<PatchType>(*newPatches[patchi]))
193  {
194  // Already there
195  return patchi;
196  }
197  else
198  {
200  << "Already have patch " << patchName
201  << " but of type " << newPatches[patchi]->type()
202  << exit(FatalError);
203  }
204  }
205 
206 
207  patchi = newPatches.size();
208 
209  label startFacei = 0;
210  if (patchi > 0)
211  {
212  const polyPatch& pp = *newPatches.last();
213  startFacei = pp.start()+pp.size();
214  }
215 
216  #ifdef FULLDEBUG
217  Pout<< "addPatch : starting newPatches:"
218  << " patch:" << patchi << " startFace:" << startFacei << nl;
219  printPatches(Pout, newPatches);
220  Pout<< "*** end of addPatch:" << endl;
221  #endif
222 
223  newPatches.append
224  (
226  (
227  PatchType::typeName,
228  patchName,
229  0, // size
230  startFacei, // nFaces
231  patchi,
232  patches
233  ).ptr()
234  );
235 
236  return patchi;
237 }
238 
239 
240 template<class PatchType>
241 label addPatch
242 (
243  const polyBoundaryMesh& patches,
244  const word& patchName,
245  const dictionary& dict,
246  DynamicList<polyPatch*>& newPatches
247 )
248 {
249  label patchi = findPatchID(newPatches, patchName);
250 
251  if (patchi != -1)
252  {
253  if (isA<PatchType>(*newPatches[patchi]))
254  {
255  // Already there
256  return patchi;
257  }
258  else
259  {
261  << "Already have patch " << patchName
262  << " but of type " << newPatches[patchi]->type()
263  << exit(FatalError);
264  }
265  }
266 
267 
268  patchi = newPatches.size();
269 
270  label startFacei = 0;
271  if (patchi > 0)
272  {
273  const polyPatch& pp = *newPatches.last();
274  startFacei = pp.start()+pp.size();
275  }
276 
277 
278  #ifdef FULLDEBUG
279  Pout<< "addPatch : starting newPatches:"
280  << " patch:" << patchi << " startFace:" << startFacei << nl;
281  printPatches(Pout, newPatches);
282  Pout<< "*** end of addPatch:" << endl;
283  #endif
284 
285 
286  dictionary patchDict(dict);
287  patchDict.set("type", PatchType::typeName);
288  patchDict.set("nFaces", 0);
289  patchDict.set("startFace", startFacei);
290 
291  newPatches.append
292  (
294  (
295  patchName,
296  patchDict,
297  patchi,
298  patches
299  ).ptr()
300  );
301 
302  return patchi;
303 }
304 
305 
306 // Remove zero-sized patches
307 void deleteEmptyPatches(fvMesh& mesh)
308 {
310 
311  wordList masterNames;
312  if (Pstream::master())
313  {
314  masterNames = patches.names();
315  }
316  Pstream::scatter(masterNames);
317 
318 
319  labelList oldToNew(patches.size(), -1);
320  label usedI = 0;
321  label notUsedI = patches.size();
322 
323  // Add all the non-empty, non-processor patches
324  forAll(masterNames, masterI)
325  {
326  label patchi = patches.findPatchID(masterNames[masterI]);
327 
328  if (patchi != -1)
329  {
330  if (isA<processorPolyPatch>(patches[patchi]))
331  {
332  // Similar named processor patch? Not 'possible'.
333  if (patches[patchi].empty())
334  {
335  Pout<< "Deleting processor patch " << patchi
336  << " name:" << patches[patchi].name()
337  << endl;
338  oldToNew[patchi] = --notUsedI;
339  }
340  else
341  {
342  oldToNew[patchi] = usedI++;
343  }
344  }
345  else
346  {
347  // Common patch.
348  if (returnReduce(patches[patchi].empty(), andOp<bool>()))
349  {
350  Pout<< "Deleting patch " << patchi
351  << " name:" << patches[patchi].name()
352  << endl;
353  oldToNew[patchi] = --notUsedI;
354  }
355  else
356  {
357  oldToNew[patchi] = usedI++;
358  }
359  }
360  }
361  }
362 
363  // Add remaining patches at the end
364  forAll(patches, patchi)
365  {
366  if (oldToNew[patchi] == -1)
367  {
368  // Unique to this processor. Note: could check that these are
369  // only processor patches.
370  if (patches[patchi].empty())
371  {
372  Pout<< "Deleting processor patch " << patchi
373  << " name:" << patches[patchi].name()
374  << endl;
375  oldToNew[patchi] = --notUsedI;
376  }
377  else
378  {
379  oldToNew[patchi] = usedI++;
380  }
381  }
382  }
383 
384  fvMeshTools::reorderPatches(mesh, oldToNew, usedI, true);
385 }
386 
387 
388 // Check zone either all internal or all external faces
389 void checkZoneInside
390 (
391  const polyMesh& mesh,
392  const wordList& zoneNames,
393  const labelList& zoneID,
394  const labelList& extrudeMeshFaces,
395  const boolList& isInternal
396 )
397 {
398  forAll(zoneNames, i)
399  {
400  if (isInternal[i])
401  {
402  Info<< "Zone " << zoneNames[i] << " has internal faces" << endl;
403  }
404  else
405  {
406  Info<< "Zone " << zoneNames[i] << " has boundary faces" << endl;
407  }
408  }
409 
410  forAll(extrudeMeshFaces, i)
411  {
412  label facei = extrudeMeshFaces[i];
413  label zoneI = zoneID[i];
414  if (isInternal[zoneI] != mesh.isInternalFace(facei))
415  {
417  << "Zone " << zoneNames[zoneI]
418  << " is not consistently all internal or all boundary faces."
419  << " Face " << facei << " at " << mesh.faceCentres()[facei]
420  << " is the first occurrence."
421  << exit(FatalError);
422  }
423  }
424 }
425 
426 
427 // Calculate global pp faces per pp edge.
428 labelListList globalEdgeFaces
429 (
430  const polyMesh& mesh,
431  const globalIndex& globalFaces,
432  const primitiveFacePatch& pp,
433  const labelList& ppMeshEdges
434 )
435 {
436  // From mesh edge to global pp face labels.
437  labelListList globalEdgeFaces(ppMeshEdges.size());
438 
439  const labelListList& edgeFaces = pp.edgeFaces();
440 
441  forAll(edgeFaces, edgeI)
442  {
443  // Store pp face and processor as unique tag.
444  globalEdgeFaces[edgeI] = globalFaces.toGlobal(edgeFaces[edgeI]);
445  }
446 
447  // Synchronise across coupled edges.
449  (
450  mesh,
451  ppMeshEdges,
452  globalEdgeFaces,
454  labelList() // null value
455  );
456 
457  return globalEdgeFaces;
458 }
459 
460 
461 // Find a patch face that is not extruded. Return -1 if not found.
462 label findUncoveredPatchFace
463 (
464  const fvMesh& mesh,
465  const labelUIndList& extrudeMeshFaces, // mesh faces that are extruded
466  const label meshEdgeI // mesh edge
467 )
468 {
469  // Make set of extruded faces.
470  labelHashSet extrudeFaceSet(extrudeMeshFaces.size());
471  extrudeFaceSet.insert(extrudeMeshFaces);
472 
473  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
474  const labelList& eFaces = mesh.edgeFaces()[meshEdgeI];
475  forAll(eFaces, i)
476  {
477  label facei = eFaces[i];
478  label patchi = pbm.whichPatch(facei);
479 
480  if
481  (
482  patchi != -1
483  && !pbm[patchi].coupled()
484  && !extrudeFaceSet.found(facei)
485  )
486  {
487  return facei;
488  }
489  }
490 
491  return -1;
492 }
493 
494 
495 // Same as findUncoveredPatchFace, except explicitly checks for cyclic faces
496 label findUncoveredCyclicPatchFace
497 (
498  const fvMesh& mesh,
499  const labelUIndList& extrudeMeshFaces, // mesh faces that are extruded
500  const label meshEdgeI // mesh edge
501 )
502 {
503  // Make set of extruded faces.
504  labelHashSet extrudeFaceSet(extrudeMeshFaces.size());
505  extrudeFaceSet.insert(extrudeMeshFaces);
506 
507  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
508  const labelList& eFaces = mesh.edgeFaces()[meshEdgeI];
509  forAll(eFaces, i)
510  {
511  label facei = eFaces[i];
512  label patchi = pbm.whichPatch(facei);
513 
514  if
515  (
516  patchi != -1
517  && isA<cyclicPolyPatch>(pbm[patchi])
518  && !extrudeFaceSet.found(facei)
519  )
520  {
521  return facei;
522  }
523  }
524 
525  return -1;
526 }
527 
528 
529 // Calculate per edge min and max zone
530 void calcEdgeMinMaxZone
531 (
532  const fvMesh& mesh,
533  const primitiveFacePatch& extrudePatch,
534  const labelList& extrudeMeshEdges,
535  const labelList& zoneID,
536  const mapDistribute& extrudeEdgeFacesMap,
537  const labelListList& extrudeEdgeGlobalFaces,
538 
539  labelList& minZoneID,
540  labelList& maxZoneID
541 )
542 {
543  // Get zoneIDs in extrudeEdgeGlobalFaces order
544  labelList mappedZoneID(zoneID);
545  extrudeEdgeFacesMap.distribute(mappedZoneID);
546 
547  // Get min and max zone per edge
548  minZoneID.setSize(extrudeEdgeGlobalFaces.size(), labelMax);
549  maxZoneID.setSize(extrudeEdgeGlobalFaces.size(), labelMin);
550 
551  forAll(extrudeEdgeGlobalFaces, edgeI)
552  {
553  const labelList& eFaces = extrudeEdgeGlobalFaces[edgeI];
554  if (eFaces.size())
555  {
556  forAll(eFaces, i)
557  {
558  label zoneI = mappedZoneID[eFaces[i]];
559  minZoneID[edgeI] = min(minZoneID[edgeI], zoneI);
560  maxZoneID[edgeI] = max(maxZoneID[edgeI], zoneI);
561  }
562  }
563  }
565  (
566  mesh,
567  extrudeMeshEdges,
568  minZoneID,
569  minEqOp<label>(),
570  labelMax // null value
571  );
573  (
574  mesh,
575  extrudeMeshEdges,
576  maxZoneID,
577  maxEqOp<label>(),
578  labelMin // null value
579  );
580 }
581 
582 
583 // Count the number of faces in patches that need to be created. Calculates:
584 // zoneSidePatch[zoneI] : the number of side faces to be created
585 // zoneZonePatch[zoneA,zoneB] : the number of faces inbetween zoneA and B
586 // Since this only counts we're not taking the processor patches into
587 // account.
588 void countExtrudePatches
589 (
590  const fvMesh& mesh,
591  const label nZones,
592  const primitiveFacePatch& extrudePatch,
593  const labelList& extrudeMeshFaces,
594  const labelList& extrudeMeshEdges,
595 
596  const labelListList& extrudeEdgeGlobalFaces,
597  const labelList& minZoneID,
598  const labelList& maxZoneID,
599 
600  labelList& zoneSidePatch,
601  labelList& zoneZonePatch
602 )
603 {
604  // Check on master edge for use of zones. Since we only want to know
605  // whether they are being used at all no need to accurately count on slave
606  // edge as well. Just add all together at the end of this routine so it
607  // gets detected at least.
608 
609  forAll(extrudePatch.edgeFaces(), edgeI)
610  {
611  const labelList& eFaces = extrudePatch.edgeFaces()[edgeI];
612 
613  if (eFaces.size() == 2)
614  {
615  // Internal edge - check if inbetween different zones.
616  if (minZoneID[edgeI] != maxZoneID[edgeI])
617  {
618  zoneZonePatch[minZoneID[edgeI]*nZones+maxZoneID[edgeI]]++;
619  }
620  }
621  else if
622  (
623  eFaces.size() == 1
624  && extrudeEdgeGlobalFaces[edgeI].size() == 2
625  )
626  {
627  // Coupled edge - check if inbetween different zones.
628  if (minZoneID[edgeI] != maxZoneID[edgeI])
629  {
630  const edge& e = extrudePatch.edges()[edgeI];
631  const pointField& pts = extrudePatch.localPoints();
633  << "Edge " << edgeI
634  << "at " << pts[e[0]] << pts[e[1]]
635  << " is a coupled edge and inbetween two different zones "
636  << minZoneID[edgeI] << " and " << maxZoneID[edgeI] << endl
637  << " This is currently not supported." << endl;
638 
639  zoneZonePatch[minZoneID[edgeI]*nZones+maxZoneID[edgeI]]++;
640  }
641  }
642  else
643  {
644  // One or more than two edge-faces.
645  // Check whether we are on a mesh edge with external patches. If
646  // so choose any uncovered one. If none found put face in
647  // undetermined zone 'side' patch
648 
649  label facei = findUncoveredPatchFace
650  (
651  mesh,
652  labelUIndList(extrudeMeshFaces, eFaces),
653  extrudeMeshEdges[edgeI]
654  );
655 
656  if (facei == -1)
657  {
658  zoneSidePatch[minZoneID[edgeI]]++;
659  }
660  }
661  }
662  // Synchronise decision. Actual numbers are not important, just make
663  // sure that they're > 0 on all processors.
665  Pstream::listCombineScatter(zoneSidePatch);
667  Pstream::listCombineScatter(zoneZonePatch);
668 }
669 
670 
671 void addCouplingPatches
672 (
673  const fvMesh& mesh,
674  const word& regionName,
675  const word& shellRegionName,
676  const wordList& zoneNames,
677  const wordList& zoneShadowNames,
678  const boolList& isInternal,
679  const labelList& zoneIDs,
680 
681  DynamicList<polyPatch*>& newPatches,
682  labelList& interRegionTopPatch,
683  labelList& interRegionBottomPatch
684 )
685 {
686  Pout<< "Adding coupling patches:" << nl << nl
687  << "patchID\tpatch\ttype" << nl
688  << "-------\t-----\t----"
689  << endl;
690 
691  interRegionTopPatch.setSize(zoneNames.size(), -1);
692  interRegionBottomPatch.setSize(zoneNames.size(), -1);
693 
694  label nOldPatches = newPatches.size();
695  forAll(zoneNames, zoneI)
696  {
697  word interName
698  (
699  regionName
700  +"_to_"
701  +shellRegionName
702  +'_'
703  +zoneNames[zoneI]
704  );
705 
706  if (isInternal[zoneI])
707  {
708  interRegionTopPatch[zoneI] = addPatch<mappedWallPolyPatch>
709  (
710  mesh.boundaryMesh(),
711  interName + "_top",
712  newPatches
713  );
714  Pout<< interRegionTopPatch[zoneI]
715  << '\t' << newPatches[interRegionTopPatch[zoneI]]->name()
716  << '\t' << newPatches[interRegionTopPatch[zoneI]]->type()
717  << nl;
718 
719  interRegionBottomPatch[zoneI] = addPatch<mappedWallPolyPatch>
720  (
721  mesh.boundaryMesh(),
722  interName + "_bottom",
723  newPatches
724  );
725  Pout<< interRegionBottomPatch[zoneI]
726  << '\t' << newPatches[interRegionBottomPatch[zoneI]]->name()
727  << '\t' << newPatches[interRegionBottomPatch[zoneI]]->type()
728  << nl;
729  }
730  else if (zoneShadowNames.size() == 0)
731  {
732  interRegionTopPatch[zoneI] = addPatch<polyPatch>
733  (
734  mesh.boundaryMesh(),
735  zoneNames[zoneI] + "_top",
736  newPatches
737  );
738  Pout<< interRegionTopPatch[zoneI]
739  << '\t' << newPatches[interRegionTopPatch[zoneI]]->name()
740  << '\t' << newPatches[interRegionTopPatch[zoneI]]->type()
741  << nl;
742 
743  interRegionBottomPatch[zoneI] = addPatch<mappedWallPolyPatch>
744  (
745  mesh.boundaryMesh(),
746  interName,
747  newPatches
748  );
749  Pout<< interRegionBottomPatch[zoneI]
750  << '\t' << newPatches[interRegionBottomPatch[zoneI]]->name()
751  << '\t' << newPatches[interRegionBottomPatch[zoneI]]->type()
752  << nl;
753  }
754  else //patch using shadow face zones.
755  {
756  interRegionTopPatch[zoneI] = addPatch<mappedWallPolyPatch>
757  (
758  mesh.boundaryMesh(),
759  zoneShadowNames[zoneI] + "_top",
760  newPatches
761  );
762  Pout<< interRegionTopPatch[zoneI]
763  << '\t' << newPatches[interRegionTopPatch[zoneI]]->name()
764  << '\t' << newPatches[interRegionTopPatch[zoneI]]->type()
765  << nl;
766 
767  interRegionBottomPatch[zoneI] = addPatch<mappedWallPolyPatch>
768  (
769  mesh.boundaryMesh(),
770  interName,
771  newPatches
772  );
773  Pout<< interRegionBottomPatch[zoneI]
774  << '\t' << newPatches[interRegionBottomPatch[zoneI]]->name()
775  << '\t' << newPatches[interRegionBottomPatch[zoneI]]->type()
776  << nl;
777  }
778  }
779  Pout<< "Added " << newPatches.size()-nOldPatches
780  << " inter-region patches." << nl
781  << endl;
782 }
783 
784 
785 // Sets sidePatch[edgeI] to interprocessor or cyclic patch. Adds any
786 // coupled patches if necessary.
787 void addCoupledPatches
788 (
789  const fvMesh& mesh,
790  const primitiveFacePatch& extrudePatch,
791  const labelList& extrudeMeshFaces,
792  const labelList& extrudeMeshEdges,
793  const mapDistribute& extrudeEdgeFacesMap,
794  const labelListList& extrudeEdgeGlobalFaces,
795 
796  labelList& sidePatchID,
797  DynamicList<polyPatch*>& newPatches
798 )
799 {
800  // Calculate opposite processor for coupled edges (only if shared by
801  // two procs). Note: could have saved original globalEdgeFaces structure.
802 
803  // Get procID in extrudeEdgeGlobalFaces order
804  labelList procID(extrudeEdgeGlobalFaces.size(), Pstream::myProcNo());
805  extrudeEdgeFacesMap.distribute(procID);
806 
807  labelList minProcID(extrudeEdgeGlobalFaces.size(), labelMax);
808  labelList maxProcID(extrudeEdgeGlobalFaces.size(), labelMin);
809 
810  forAll(extrudeEdgeGlobalFaces, edgeI)
811  {
812  const labelList& eFaces = extrudeEdgeGlobalFaces[edgeI];
813  if (eFaces.size())
814  {
815  forAll(eFaces, i)
816  {
817  label proci = procID[eFaces[i]];
818  minProcID[edgeI] = min(minProcID[edgeI], proci);
819  maxProcID[edgeI] = max(maxProcID[edgeI], proci);
820  }
821  }
822  }
824  (
825  mesh,
826  extrudeMeshEdges,
827  minProcID,
828  minEqOp<label>(),
829  labelMax // null value
830  );
832  (
833  mesh,
834  extrudeMeshEdges,
835  maxProcID,
836  maxEqOp<label>(),
837  labelMin // null value
838  );
839 
840  Pout<< "Adding processor or cyclic patches:" << nl << nl
841  << "patchID\tpatch" << nl
842  << "-------\t-----"
843  << endl;
844 
845  label nOldPatches = newPatches.size();
846 
847  sidePatchID.setSize(extrudePatch.edgeFaces().size(), -1);
848  forAll(extrudePatch.edgeFaces(), edgeI)
849  {
850  const labelList& eFaces = extrudePatch.edgeFaces()[edgeI];
851 
852  if
853  (
854  eFaces.size() == 1
855  && extrudeEdgeGlobalFaces[edgeI].size() == 2
856  )
857  {
858  // coupled boundary edge. Find matching patch.
859  label nbrProci = minProcID[edgeI];
860  if (nbrProci == Pstream::myProcNo())
861  {
862  nbrProci = maxProcID[edgeI];
863  }
864 
865 
866  if (nbrProci == Pstream::myProcNo())
867  {
868  // Cyclic patch since both procs the same. This cyclic should
869  // already exist in newPatches so no adding necessary.
870 
871  label facei = findUncoveredCyclicPatchFace
872  (
873  mesh,
874  labelUIndList(extrudeMeshFaces, eFaces),
875  extrudeMeshEdges[edgeI]
876  );
877 
878  if (facei != -1)
879  {
881 
882  label newPatchi = findPatchID
883  (
884  newPatches,
885  patches[patches.whichPatch(facei)].name()
886  );
887 
888  sidePatchID[edgeI] = newPatchi;
889  }
890  else
891  {
893  << "Unable to determine coupled patch addressing"
894  << abort(FatalError);
895  }
896  }
897  else
898  {
899  // Processor patch
900  word name
901  (
903  );
904 
905  sidePatchID[edgeI] = findPatchID(newPatches, name);
906 
907  if (sidePatchID[edgeI] == -1)
908  {
909  dictionary patchDict;
910  patchDict.add("myProcNo", Pstream::myProcNo());
911  patchDict.add("neighbProcNo", nbrProci);
912 
913  sidePatchID[edgeI] = addPatch<processorPolyPatch>
914  (
915  mesh.boundaryMesh(),
916  name,
917  patchDict,
918  newPatches
919  );
920 
921  Pout<< sidePatchID[edgeI] << '\t' << name
922  << nl;
923  }
924  }
925  }
926  }
927  Pout<< "Added " << newPatches.size()-nOldPatches
928  << " coupled patches." << nl
929  << endl;
930 }
931 
932 
933 void addZoneSidePatches
934 (
935  const fvMesh& mesh,
936  const wordList& zoneNames,
937  const word& oneDPolyPatchType,
938 
939  DynamicList<polyPatch*>& newPatches,
940  labelList& zoneSidePatch
941 )
942 {
943  Pout<< "Adding patches for sides on zones:" << nl << nl
944  << "patchID\tpatch" << nl
945  << "-------\t-----"
946  << endl;
947 
948  label nOldPatches = newPatches.size();
949 
950  forAll(zoneSidePatch, zoneI)
951  {
952  if (oneDPolyPatchType != word::null)
953  {
954  // Reuse single empty patch.
955  word patchName;
956  if (oneDPolyPatchType == "empty")
957  {
958  patchName = "oneDEmptyPatch";
959  zoneSidePatch[zoneI] = addPatch<emptyPolyPatch>
960  (
961  mesh.boundaryMesh(),
962  patchName,
963  newPatches
964  );
965  }
966  else if (oneDPolyPatchType == "wedge")
967  {
968  patchName = "oneDWedgePatch";
969  zoneSidePatch[zoneI] = addPatch<wedgePolyPatch>
970  (
971  mesh.boundaryMesh(),
972  patchName,
973  newPatches
974  );
975  }
976  else
977  {
979  << "Type " << oneDPolyPatchType << " does not exist "
980  << exit(FatalError);
981  }
982 
983  Pout<< zoneSidePatch[zoneI] << '\t' << patchName << nl;
984  }
985  else if (zoneSidePatch[zoneI] > 0)
986  {
987  word patchName = zoneNames[zoneI] + "_" + "side";
988 
989  zoneSidePatch[zoneI] = addPatch<polyPatch>
990  (
991  mesh.boundaryMesh(),
992  patchName,
993  newPatches
994  );
995 
996  Pout<< zoneSidePatch[zoneI] << '\t' << patchName << nl;
997  }
998  }
999  Pout<< "Added " << newPatches.size()-nOldPatches << " zone-side patches."
1000  << nl << endl;
1001 }
1002 
1003 
1004 void addInterZonePatches
1005 (
1006  const fvMesh& mesh,
1007  const wordList& zoneNames,
1008  const bool oneD,
1009 
1010  labelList& zoneZonePatch_min,
1011  labelList& zoneZonePatch_max,
1012  DynamicList<polyPatch*>& newPatches
1013 )
1014 {
1015  Pout<< "Adding inter-zone patches:" << nl << nl
1016  << "patchID\tpatch" << nl
1017  << "-------\t-----"
1018  << endl;
1019 
1020  dictionary transformDict;
1021  transformDict.add
1022  (
1023  "transform",
1025  );
1026 
1027  label nOldPatches = newPatches.size();
1028 
1029  if (!oneD)
1030  {
1031  forAll(zoneZonePatch_min, minZone)
1032  {
1033  for (label maxZone = minZone; maxZone < zoneNames.size(); maxZone++)
1034  {
1035  label index = minZone*zoneNames.size()+maxZone;
1036 
1037  if (zoneZonePatch_min[index] > 0)
1038  {
1039  word minToMax =
1040  zoneNames[minZone]
1041  + "_to_"
1042  + zoneNames[maxZone];
1043  word maxToMin =
1044  zoneNames[maxZone]
1045  + "_to_"
1046  + zoneNames[minZone];
1047 
1048  {
1049  transformDict.set("neighbourPatch", maxToMin);
1050  zoneZonePatch_min[index] =
1051  addPatch<nonuniformTransformCyclicPolyPatch>
1052  (
1053  mesh.boundaryMesh(),
1054  minToMax,
1055  transformDict,
1056  newPatches
1057  );
1058  Pout<< zoneZonePatch_min[index] << '\t' << minToMax
1059  << nl;
1060  }
1061  {
1062  transformDict.set("neighbourPatch", minToMax);
1063  zoneZonePatch_max[index] =
1064  addPatch<nonuniformTransformCyclicPolyPatch>
1065  (
1066  mesh.boundaryMesh(),
1067  maxToMin,
1068  transformDict,
1069  newPatches
1070  );
1071  Pout<< zoneZonePatch_max[index] << '\t' << maxToMin
1072  << nl;
1073  }
1074 
1075  }
1076  }
1077  }
1078  }
1079  Pout<< "Added " << newPatches.size()-nOldPatches << " inter-zone patches."
1080  << nl << endl;
1081 }
1082 
1083 
1084 tmp<pointField> calcOffset
1085 (
1086  const primitiveFacePatch& extrudePatch,
1087  const createShellMesh& extruder,
1088  const polyPatch& pp
1089 )
1090 {
1092 
1093  tmp<pointField> toffsets(new pointField(fc.size()));
1094  pointField& offsets = toffsets.ref();
1095 
1096  forAll(fc, i)
1097  {
1098  label meshFacei = pp.start()+i;
1099  label patchFacei = mag(extruder.faceToFaceMap()[meshFacei])-1;
1100  point patchFc = extrudePatch[patchFacei].centre
1101  (
1102  extrudePatch.points()
1103  );
1104  offsets[i] = patchFc - fc[i];
1105  }
1106  return toffsets;
1107 }
1108 
1109 
1110 void setCouplingInfo
1111 (
1112  fvMesh& mesh,
1113  const labelList& zoneToPatch,
1114  const word& sampleRegion,
1116  const List<pointField>& offsets
1117 )
1118 {
1120 
1121  List<polyPatch*> newPatches
1122  (
1123  patches.size(),
1124  static_cast<polyPatch*>(nullptr)
1125  );
1126 
1127  forAll(zoneToPatch, zoneI)
1128  {
1129  const label patchi = zoneToPatch[zoneI];
1130 
1131  if (patchi != -1)
1132  {
1133  const polyPatch& pp = patches[patchi];
1134 
1135  if (isA<mappedWallPolyPatch>(pp))
1136  {
1137  const boundBox bb(pp.points(), pp.meshPoints(), true);
1138  const vector avgOffset = gAverage(offsets[zoneI]);
1139  const scalar mergeSqrDist =
1140  gMax(magSqr(offsets[zoneI]-avgOffset));
1141 
1142  // Create with uniform offset initially
1143  auto mappedPtr = autoPtr<mappedWallPolyPatch>::New
1144  (
1145  pp.name(),
1146  pp.size(),
1147  pp.start(),
1148  patchi,
1149  sampleRegion, // sampleRegion
1150  mode, // sampleMode
1151  pp.name(), // samplePatch
1152 
1153  avgOffset, // uniform offset
1154  patches
1155  );
1156 
1157  Info<< "Adding on " << mesh.name() << " coupling patch "
1158  << pp.name() << " with ";
1159 
1160  // Verify uniformity of offset
1161  // (same check as blockMesh geom merge)
1162  if (mergeSqrDist < magSqr(10*SMALL*bb.span()))
1163  {
1164  Info<< "uniform offset " << avgOffset << endl;
1165  }
1166  else
1167  {
1168  Info<< "non-uniform offset" << endl;
1169 
1170  (*mappedPtr).setOffset(offsets[zoneI]);
1171  }
1172 
1173  newPatches[patchi] = mappedPtr.release();
1174  }
1175  }
1176  }
1177 
1178  forAll(newPatches, patchi)
1179  {
1180  if (!newPatches[patchi])
1181  {
1182  newPatches[patchi] = patches[patchi].clone(patches).ptr();
1183  //newPatches[patchi].index() = patchi;
1184  }
1185  }
1186 
1187 
1188  #ifdef FULLDEBUG
1189  Pout<< "*** setCouplingInfo addFvPAtches:" << nl;
1190  printPatches(Pout, newPatches);
1191  Pout<< "*** setCouplingInfo end of addFvPAtches:" << endl;
1192  #endif
1193 
1195  mesh.addFvPatches(newPatches, true);
1196 }
1197 
1198 
1199 // Extrude and write geometric properties
1200 void extrudeGeometricProperties
1201 (
1202  const polyMesh& mesh,
1203  const primitiveFacePatch& extrudePatch,
1204  const createShellMesh& extruder,
1205  const polyMesh& regionMesh,
1206  const extrudeModel& model
1207 )
1208 {
1209  const pointIOField patchFaceCentres
1210  (
1211  IOobject
1212  (
1213  "patchFaceCentres",
1214  mesh.pointsInstance(),
1215  mesh.meshSubDir,
1216  mesh,
1218  )
1219  );
1220 
1221  const pointIOField patchEdgeCentres
1222  (
1223  IOobject
1224  (
1225  "patchEdgeCentres",
1226  mesh.pointsInstance(),
1227  mesh.meshSubDir,
1228  mesh,
1230  )
1231  );
1232 
1233  //forAll(extrudePatch.edges(), edgeI)
1234  //{
1235  // const edge& e = extrudePatch.edges()[edgeI];
1236  // Pout<< "Edge:" << e.centre(extrudePatch.localPoints()) << nl
1237  // << "read:" << patchEdgeCentres[edgeI]
1238  // << endl;
1239  //}
1240 
1241 
1242  // Determine edge normals on original patch
1243  labelList patchEdges;
1244  labelList coupledEdges;
1245  bitSet sameEdgeOrientation;
1247  (
1248  extrudePatch,
1250  patchEdges,
1251  coupledEdges,
1252  sameEdgeOrientation
1253  );
1254 
1255  pointField patchEdgeNormals
1256  (
1258  (
1259  mesh,
1260  extrudePatch,
1261  patchEdges,
1262  coupledEdges
1263  )
1264  );
1265 
1266 
1267  pointIOField faceCentres
1268  (
1269  IOobject
1270  (
1271  "faceCentres",
1272  regionMesh.pointsInstance(),
1273  regionMesh.meshSubDir,
1274  regionMesh,
1277  false
1278  ),
1279  regionMesh.nFaces()
1280  );
1281 
1282 
1283  // Work out layers. Guaranteed in columns so no fancy parallel bits.
1284 
1285 
1286  forAll(extruder.faceToFaceMap(), facei)
1287  {
1288  if (extruder.faceToFaceMap()[facei] != 0)
1289  {
1290  // 'horizontal' face
1291  label patchFacei = mag(extruder.faceToFaceMap()[facei])-1;
1292 
1293  label celli = regionMesh.faceOwner()[facei];
1294  if (regionMesh.isInternalFace(facei))
1295  {
1296  celli = max(celli, regionMesh.faceNeighbour()[facei]);
1297  }
1298 
1299  // Calculate layer from cell numbering (see createShellMesh)
1300  label layerI = (celli % model.nLayers());
1301 
1302  if
1303  (
1304  !regionMesh.isInternalFace(facei)
1305  && extruder.faceToFaceMap()[facei] > 0
1306  )
1307  {
1308  // Top face
1309  layerI++;
1310  }
1311 
1312 
1313  // Recalculate based on extrusion model
1314  faceCentres[facei] = model
1315  (
1316  patchFaceCentres[patchFacei],
1317  extrudePatch.faceNormals()[patchFacei],
1318  layerI
1319  );
1320  }
1321  else
1322  {
1323  // 'vertical face
1324  label patchEdgeI = extruder.faceToEdgeMap()[facei];
1325  label layerI =
1326  (
1327  regionMesh.faceOwner()[facei]
1328  % model.nLayers()
1329  );
1330 
1331  // Extrude patch edge centre to this layer
1332  point pt0 = model
1333  (
1334  patchEdgeCentres[patchEdgeI],
1335  patchEdgeNormals[patchEdgeI],
1336  layerI
1337  );
1338  // Extrude patch edge centre to next layer
1339  point pt1 = model
1340  (
1341  patchEdgeCentres[patchEdgeI],
1342  patchEdgeNormals[patchEdgeI],
1343  layerI+1
1344  );
1345 
1346  // Interpolate
1347  faceCentres[facei] = 0.5*(pt0+pt1);
1348  }
1349  }
1350 
1351  pointIOField cellCentres
1352  (
1353  IOobject
1354  (
1355  "cellCentres",
1356  regionMesh.pointsInstance(),
1357  regionMesh.meshSubDir,
1358  regionMesh,
1361  false
1362  ),
1363  regionMesh.nCells()
1364  );
1365 
1366  forAll(extruder.cellToFaceMap(), celli)
1367  {
1368  label patchFacei = extruder.cellToFaceMap()[celli];
1369 
1370  // Calculate layer from cell numbering (see createShellMesh)
1371  label layerI = (celli % model.nLayers());
1372 
1373  // Recalculate based on extrusion model
1374  point pt0 = model
1375  (
1376  patchFaceCentres[patchFacei],
1377  extrudePatch.faceNormals()[patchFacei],
1378  layerI
1379  );
1380  point pt1 = model
1381  (
1382  patchFaceCentres[patchFacei],
1383  extrudePatch.faceNormals()[patchFacei],
1384  layerI+1
1385  );
1386 
1387  // Interpolate
1388  cellCentres[celli] = 0.5*(pt0+pt1);
1389  }
1390 
1391 
1392  // Bit of checking
1393  if (false)
1394  {
1395  OBJstream faceStr(regionMesh.time().path()/"faceCentres.obj");
1396  OBJstream cellStr(regionMesh.time().path()/"cellCentres.obj");
1397 
1398  forAll(faceCentres, facei)
1399  {
1400  Pout<< "Model :" << faceCentres[facei] << endl
1401  << "regionMesh:" << regionMesh.faceCentres()[facei] << endl;
1402  faceStr.write
1403  (
1404  linePointRef
1405  (
1406  faceCentres[facei],
1407  regionMesh.faceCentres()[facei]
1408  )
1409  );
1410  }
1411  forAll(cellCentres, celli)
1412  {
1413  Pout<< "Model :" << cellCentres[celli] << endl
1414  << "regionMesh:" << regionMesh.cellCentres()[celli] << endl;
1415  cellStr.write
1416  (
1417  linePointRef
1418  (
1419  cellCentres[celli],
1420  regionMesh.cellCentres()[celli]
1421  )
1422  );
1423  }
1424  }
1425 
1426 
1427 
1428  Info<< "Writing geometric properties for mesh " << regionMesh.name()
1429  << " to " << regionMesh.pointsInstance() << nl
1430  << endl;
1431 
1432  bool ok = faceCentres.write() && cellCentres.write();
1433 
1434  if (!ok)
1435  {
1437  << "Failed writing " << faceCentres.objectPath()
1438  << " and " << cellCentres.objectPath()
1439  << exit(FatalError);
1440  }
1441 }
1442 
1443 
1444 int main(int argc, char *argv[])
1445 {
1447  (
1448  "Create region mesh by extruding a faceZone or faceSet"
1449  );
1450 
1451  #include "addRegionOption.H"
1452  #include "addOverwriteOption.H"
1453 
1455  (
1456  "dict", "file", "Alternative extrudeToRegionMeshDict"
1457  );
1458 
1459  #include "setRootCase.H"
1460  #include "createTime.H"
1461  #include "createNamedMesh.H"
1462 
1463  if (mesh.boundaryMesh().checkParallelSync(true))
1464  {
1465  List<wordList> allNames(Pstream::nProcs());
1466  allNames[Pstream::myProcNo()] = mesh.boundaryMesh().names();
1467  Pstream::gatherList(allNames);
1468  Pstream::scatterList(allNames);
1469 
1471  << "Patches are not synchronised on all processors."
1472  << " Per processor patches " << allNames
1473  << exit(FatalError);
1474  }
1475 
1476 
1477  const word oldInstance = mesh.pointsInstance();
1478  const bool overwrite = args.found("overwrite");
1479 
1480  const word dictName("extrudeToRegionMeshDict");
1481 
1482  #include "setSystemMeshDictionaryIO.H"
1483 
1485 
1486  // Point generator
1488 
1489  // Region
1490  const word shellRegionName(dict.get<word>("region"));
1491 
1492  // Faces to extrude - either faceZones or faceSets (boundary faces only)
1493  wordList zoneNames;
1494  wordList zoneShadowNames;
1495 
1496  const bool hasZones = dict.found("faceZones");
1497  if (hasZones)
1498  {
1499  dict.readEntry("faceZones", zoneNames);
1500  dict.readIfPresent("faceZonesShadow", zoneShadowNames);
1501 
1502  // Check
1503  if (dict.found("faceSets"))
1504  {
1506  << "Please supply faces to extrude either through 'faceZones'"
1507  << " or 'faceSets' entry. Found both."
1508  << exit(FatalIOError);
1509  }
1510  }
1511  else
1512  {
1513  dict.readEntry("faceSets", zoneNames);
1514  dict.readIfPresent("faceSetsShadow", zoneShadowNames);
1515  }
1516 
1517 
1518  mappedPatchBase::sampleMode sampleMode =
1520 
1521  const bool oneD(dict.get<bool>("oneD"));
1522  bool oneDNonManifoldEdges(false);
1523  word oneDPatchType(emptyPolyPatch::typeName);
1524  if (oneD)
1525  {
1526  oneDNonManifoldEdges = dict.getOrDefault("nonManifold", false);
1527  oneDPatchType = dict.get<word>("oneDPolyPatchType");
1528  }
1529 
1530  const bool adaptMesh(dict.get<bool>("adaptMesh"));
1531 
1532  if (hasZones)
1533  {
1534  Info<< "Extruding zones " << zoneNames
1535  << " on mesh " << regionName
1536  << " into shell mesh " << shellRegionName
1537  << endl;
1538  }
1539  else
1540  {
1541  Info<< "Extruding faceSets " << zoneNames
1542  << " on mesh " << regionName
1543  << " into shell mesh " << shellRegionName
1544  << endl;
1545  }
1546 
1547  if (shellRegionName == regionName)
1548  {
1550  << "Cannot extrude into same region as mesh." << endl
1551  << "Mesh region : " << regionName << endl
1552  << "Shell region : " << shellRegionName
1553  << exit(FatalIOError);
1554  }
1555 
1556 
1557  if (oneD)
1558  {
1559  if (oneDNonManifoldEdges)
1560  {
1561  Info<< "Extruding as 1D columns with sides in patch type "
1562  << oneDPatchType
1563  << " and connected points (except on non-manifold areas)."
1564  << endl;
1565  }
1566  else
1567  {
1568  Info<< "Extruding as 1D columns with sides in patch type "
1569  << oneDPatchType
1570  << " and duplicated points (overlapping volumes)."
1571  << endl;
1572  }
1573  }
1574 
1575 
1576 
1577 
1579  //IOobjectList objects(mesh, runTime.timeName());
1580  //
1582  //
1583  //PtrList<volScalarField> vsFlds;
1584  //ReadFields(mesh, objects, vsFlds);
1585  //
1586  //PtrList<volVectorField> vvFlds;
1587  //ReadFields(mesh, objects, vvFlds);
1588  //
1589  //PtrList<volSphericalTensorField> vstFlds;
1590  //ReadFields(mesh, objects, vstFlds);
1591  //
1592  //PtrList<volSymmTensorField> vsymtFlds;
1593  //ReadFields(mesh, objects, vsymtFlds);
1594  //
1595  //PtrList<volTensorField> vtFlds;
1596  //ReadFields(mesh, objects, vtFlds);
1597  //
1599  //
1600  //PtrList<surfaceScalarField> ssFlds;
1601  //ReadFields(mesh, objects, ssFlds);
1602  //
1603  //PtrList<surfaceVectorField> svFlds;
1604  //ReadFields(mesh, objects, svFlds);
1605  //
1606  //PtrList<surfaceSphericalTensorField> sstFlds;
1607  //ReadFields(mesh, objects, sstFlds);
1608  //
1609  //PtrList<surfaceSymmTensorField> ssymtFlds;
1610  //ReadFields(mesh, objects, ssymtFlds);
1611  //
1612  //PtrList<surfaceTensorField> stFlds;
1613  //ReadFields(mesh, objects, stFlds);
1614  //
1616  //
1617  //PtrList<pointScalarField> psFlds;
1618  //ReadFields(pointMesh::New(mesh), objects, psFlds);
1619  //
1620  //PtrList<pointVectorField> pvFlds;
1621  //ReadFields(pointMesh::New(mesh), objects, pvFlds);
1622 
1623 
1624 
1625  // Create dummy fv* files
1626  fvMeshTools::createDummyFvMeshFiles(mesh, shellRegionName, true);
1627 
1628 
1629  word meshInstance;
1630  if (!overwrite)
1631  {
1632  ++runTime;
1633  meshInstance = runTime.timeName();
1634  }
1635  else
1636  {
1637  meshInstance = oldInstance;
1638  }
1639  Info<< "Writing meshes to " << meshInstance << nl << endl;
1640 
1641 
1643 
1644 
1645  // Extract faces to extrude
1646  // ~~~~~~~~~~~~~~~~~~~~~~~~
1647  // Note: zoneID are regions of extrusion. They are not mesh.faceZones
1648  // indices.
1649 
1650  // From extrude zone to mesh zone (or -1 if extruding faceSets)
1651  labelList meshZoneID;
1652  // Per extrude zone whether contains internal or external faces
1653  boolList isInternal(zoneNames.size(), false);
1654 
1655  labelList extrudeMeshFaces;
1656  faceList zoneFaces;
1657  labelList zoneID;
1658  boolList zoneFlipMap;
1659  // Shadow
1660  labelList zoneShadowIDs; // from extrude shadow zone to mesh zone
1661  labelList extrudeMeshShadowFaces;
1662  boolList zoneShadowFlipMap;
1663  labelList zoneShadowID;
1664 
1665  if (hasZones)
1666  {
1667  const faceZoneMesh& faceZones = mesh.faceZones();
1668 
1669  meshZoneID.setSize(zoneNames.size());
1670  forAll(zoneNames, i)
1671  {
1672  meshZoneID[i] = faceZones.findZoneID(zoneNames[i]);
1673  if (meshZoneID[i] == -1)
1674  {
1676  << "Cannot find zone " << zoneNames[i] << endl
1677  << "Valid zones are " << faceZones.names()
1678  << exit(FatalIOError);
1679  }
1680  }
1681  // Collect per face information
1682  label nExtrudeFaces = 0;
1683  forAll(meshZoneID, i)
1684  {
1685  nExtrudeFaces += faceZones[meshZoneID[i]].size();
1686  }
1687  extrudeMeshFaces.setSize(nExtrudeFaces);
1688  zoneFaces.setSize(nExtrudeFaces);
1689  zoneID.setSize(nExtrudeFaces);
1690  zoneFlipMap.setSize(nExtrudeFaces);
1691  nExtrudeFaces = 0;
1692  forAll(meshZoneID, i)
1693  {
1694  const faceZone& fz = faceZones[meshZoneID[i]];
1695  const primitiveFacePatch& fzp = fz();
1696  forAll(fz, j)
1697  {
1698  extrudeMeshFaces[nExtrudeFaces] = fz[j];
1699  zoneFaces[nExtrudeFaces] = fzp[j];
1700  zoneID[nExtrudeFaces] = i;
1701  zoneFlipMap[nExtrudeFaces] = fz.flipMap()[j];
1702  nExtrudeFaces++;
1703 
1704  if (mesh.isInternalFace(fz[j]))
1705  {
1706  isInternal[i] = true;
1707  }
1708  }
1709  }
1710 
1711  // Shadow zone
1712  // ~~~~~~~~~~~
1713 
1714  if (zoneShadowNames.size())
1715  {
1716  zoneShadowIDs.setSize(zoneShadowNames.size());
1717  forAll(zoneShadowNames, i)
1718  {
1719  zoneShadowIDs[i] = faceZones.findZoneID(zoneShadowNames[i]);
1720  if (zoneShadowIDs[i] == -1)
1721  {
1723  << "Cannot find zone " << zoneShadowNames[i] << endl
1724  << "Valid zones are " << faceZones.names()
1725  << exit(FatalIOError);
1726  }
1727  }
1728 
1729  label nShadowFaces = 0;
1730  forAll(zoneShadowIDs, i)
1731  {
1732  nShadowFaces += faceZones[zoneShadowIDs[i]].size();
1733  }
1734 
1735  extrudeMeshShadowFaces.setSize(nShadowFaces);
1736  zoneShadowFlipMap.setSize(nShadowFaces);
1737  zoneShadowID.setSize(nShadowFaces);
1738 
1739  nShadowFaces = 0;
1740  forAll(zoneShadowIDs, i)
1741  {
1742  const faceZone& fz = faceZones[zoneShadowIDs[i]];
1743  forAll(fz, j)
1744  {
1745  extrudeMeshShadowFaces[nShadowFaces] = fz[j];
1746  zoneShadowFlipMap[nShadowFaces] = fz.flipMap()[j];
1747  zoneShadowID[nShadowFaces] = i;
1748  nShadowFaces++;
1749  }
1750  }
1751  }
1752  }
1753  else
1754  {
1755  meshZoneID.setSize(zoneNames.size(), -1);
1756  // Load faceSets
1757  PtrList<faceSet> zones(zoneNames.size());
1758  forAll(zoneNames, i)
1759  {
1760  Info<< "Loading faceSet " << zoneNames[i] << endl;
1761  zones.set(i, new faceSet(mesh, zoneNames[i]));
1762  }
1763 
1764 
1765  // Collect per face information
1766  label nExtrudeFaces = 0;
1767  forAll(zones, i)
1768  {
1769  nExtrudeFaces += zones[i].size();
1770  }
1771  extrudeMeshFaces.setSize(nExtrudeFaces);
1772  zoneFaces.setSize(nExtrudeFaces);
1773  zoneID.setSize(nExtrudeFaces);
1774  zoneFlipMap.setSize(nExtrudeFaces);
1775 
1776  nExtrudeFaces = 0;
1777  forAll(zones, i)
1778  {
1779  const faceSet& fz = zones[i];
1780  for (const label facei : fz)
1781  {
1782  if (mesh.isInternalFace(facei))
1783  {
1785  << "faceSet " << fz.name()
1786  << "contains internal faces."
1787  << " This is not permitted."
1788  << exit(FatalIOError);
1789  }
1790  extrudeMeshFaces[nExtrudeFaces] = facei;
1791  zoneFaces[nExtrudeFaces] = mesh.faces()[facei];
1792  zoneID[nExtrudeFaces] = i;
1793  zoneFlipMap[nExtrudeFaces] = false;
1794  nExtrudeFaces++;
1795 
1796  if (mesh.isInternalFace(facei))
1797  {
1798  isInternal[i] = true;
1799  }
1800  }
1801  }
1802 
1803 
1804  // Shadow zone
1805  // ~~~~~~~~~~~
1806 
1807  PtrList<faceSet> shadowZones(zoneShadowNames.size());
1808  if (zoneShadowNames.size())
1809  {
1810  zoneShadowIDs.setSize(zoneShadowNames.size(), -1);
1811  forAll(zoneShadowNames, i)
1812  {
1813  shadowZones.set(i, new faceSet(mesh, zoneShadowNames[i]));
1814  }
1815 
1816  label nShadowFaces = 0;
1817  for (const faceSet& fz : shadowZones)
1818  {
1819  nShadowFaces += fz.size();
1820  }
1821 
1822  if (nExtrudeFaces != nShadowFaces)
1823  {
1825  << "Extruded faces " << nExtrudeFaces << endl
1826  << "is different from shadow faces. " << nShadowFaces
1827  << "This is not permitted " << endl
1828  << exit(FatalIOError);
1829  }
1830 
1831  extrudeMeshShadowFaces.setSize(nShadowFaces);
1832  zoneShadowFlipMap.setSize(nShadowFaces);
1833  zoneShadowID.setSize(nShadowFaces);
1834 
1835  nShadowFaces = 0;
1836  forAll(shadowZones, i)
1837  {
1838  const faceSet& fz = shadowZones[i];
1839  for (const label facei : fz)
1840  {
1841  if (mesh.isInternalFace(facei))
1842  {
1844  << "faceSet " << fz.name()
1845  << "contains internal faces."
1846  << " This is not permitted."
1847  << exit(FatalIOError);
1848  }
1849  extrudeMeshShadowFaces[nShadowFaces] = facei;
1850  zoneShadowFlipMap[nShadowFaces] = false;
1851  zoneShadowID[nShadowFaces] = i;
1852  nShadowFaces++;
1853  }
1854  }
1855  }
1856  }
1857  const primitiveFacePatch extrudePatch(std::move(zoneFaces), mesh.points());
1858 
1859 
1861  Pstream::listCombineScatter(isInternal);
1862 
1863  // Check zone either all internal or all external faces
1864  checkZoneInside(mesh, zoneNames, zoneID, extrudeMeshFaces, isInternal);
1865 
1866 
1867  const pointField& extrudePoints = extrudePatch.localPoints();
1868  const faceList& extrudeFaces = extrudePatch.localFaces();
1869  const labelListList& edgeFaces = extrudePatch.edgeFaces();
1870 
1871 
1872  Info<< "extrudePatch :"
1873  << " faces:" << extrudePatch.size()
1874  << " points:" << extrudePatch.nPoints()
1875  << " edges:" << extrudePatch.nEdges()
1876  << nl
1877  << endl;
1878 
1879 
1880  // Determine per-extrude-edge info
1881  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1882 
1883  // Corresponding mesh edges
1884  const labelList extrudeMeshEdges
1885  (
1886  extrudePatch.meshEdges
1887  (
1888  mesh.edges(),
1889  mesh.pointEdges()
1890  )
1891  );
1892 
1893  const globalIndex globalExtrudeFaces(extrudePatch.size());
1894 
1895  // Global pp faces per pp edge.
1896  labelListList extrudeEdgeGlobalFaces
1897  (
1898  globalEdgeFaces
1899  (
1900  mesh,
1901  globalExtrudeFaces,
1902  extrudePatch,
1903  extrudeMeshEdges
1904  )
1905  );
1906  List<Map<label>> compactMap;
1907  const mapDistribute extrudeEdgeFacesMap
1908  (
1909  globalExtrudeFaces,
1910  extrudeEdgeGlobalFaces,
1911  compactMap
1912  );
1913 
1914 
1915  // Determine min and max zone per edge
1916  labelList edgeMinZoneID;
1917  labelList edgeMaxZoneID;
1918  calcEdgeMinMaxZone
1919  (
1920  mesh,
1921  extrudePatch,
1922  extrudeMeshEdges,
1923  zoneID,
1924  extrudeEdgeFacesMap,
1925  extrudeEdgeGlobalFaces,
1926 
1927  edgeMinZoneID,
1928  edgeMaxZoneID
1929  );
1930 
1931 
1932 
1933 
1934  DynamicList<polyPatch*> regionPatches(patches.size());
1935  // Copy all non-local patches since these are used on boundary edges of
1936  // the extrusion
1937  forAll(patches, patchi)
1938  {
1939  if (!isA<processorPolyPatch>(patches[patchi]))
1940  {
1941  label newPatchi = regionPatches.size();
1942  regionPatches.append
1943  (
1944  patches[patchi].clone
1945  (
1946  patches,
1947  newPatchi,
1948  0, // size
1949  0 // start
1950  ).ptr()
1951  );
1952  }
1953  }
1954 
1955 
1956  // Add interface patches
1957  // ~~~~~~~~~~~~~~~~~~~~~
1958 
1959  // From zone to interface patch (region side)
1960  labelList interRegionTopPatch;
1961  labelList interRegionBottomPatch;
1962 
1963  addCouplingPatches
1964  (
1965  mesh,
1966  regionName,
1967  shellRegionName,
1968  zoneNames,
1969  zoneShadowNames,
1970  isInternal,
1971  meshZoneID,
1972 
1973  regionPatches,
1974  interRegionTopPatch,
1975  interRegionBottomPatch
1976  );
1977 
1978 
1979  // From zone to interface patch (mesh side)
1980  labelList interMeshTopPatch;
1981  labelList interMeshBottomPatch;
1982 
1983  if (adaptMesh)
1984  {
1985  // Add coupling patches to mesh
1986 
1987  // 1. Clone existing global patches
1988  DynamicList<polyPatch*> newPatches(patches.size());
1989  forAll(patches, patchi)
1990  {
1991  if (!isA<processorPolyPatch>(patches[patchi]))
1992  {
1993  autoPtr<polyPatch> clonedPatch(patches[patchi].clone(patches));
1994  clonedPatch->index() = newPatches.size();
1995  newPatches.append(clonedPatch.ptr());
1996  }
1997  }
1998 
1999  // 2. Add new patches
2000  addCouplingPatches
2001  (
2002  mesh,
2003  regionName,
2004  shellRegionName,
2005  zoneNames,
2006  zoneShadowNames,
2007  isInternal,
2008  meshZoneID,
2009 
2010  newPatches,
2011  interMeshTopPatch,
2012  interMeshBottomPatch
2013  );
2014 
2015  // 3. Clone processor patches
2016  forAll(patches, patchi)
2017  {
2018  if (isA<processorPolyPatch>(patches[patchi]))
2019  {
2020  autoPtr<polyPatch> clonedPatch(patches[patchi].clone(patches));
2021  clonedPatch->index() = newPatches.size();
2022  newPatches.append(clonedPatch.ptr());
2023  }
2024  }
2025 
2026 
2027  #ifdef FULLDEBUG
2028  Pout<< "*** adaptMesh : addFvPAtches:" << nl;
2029  printPatches(Pout, newPatches);
2030  Pout<< "*** end of adaptMesh : addFvPAtches:" << endl;
2031  #endif
2032 
2033 
2034  // Add to mesh
2035  mesh.clearOut();
2037  mesh.addFvPatches(newPatches, true);
2038 
2040  }
2041 
2042 
2043  // Patch per extruded face
2044  labelList extrudeTopPatchID(extrudePatch.size());
2045  labelList extrudeBottomPatchID(extrudePatch.size());
2046 
2047  forAll(zoneID, facei)
2048  {
2049  extrudeTopPatchID[facei] = interRegionTopPatch[zoneID[facei]];
2050  extrudeBottomPatchID[facei] = interRegionBottomPatch[zoneID[facei]];
2051  }
2052 
2053 
2054 
2055  // Count how many patches on special edges of extrudePatch are necessary
2056  // - zoneXXX_sides
2057  // - zoneXXX_zoneYYY
2058  labelList zoneSidePatch(zoneNames.size(), Zero);
2059  // Patch to use for minZone
2060  labelList zoneZonePatch_min(zoneNames.size()*zoneNames.size(), Zero);
2061  // Patch to use for maxZone
2062  labelList zoneZonePatch_max(zoneNames.size()*zoneNames.size(), Zero);
2063 
2064  countExtrudePatches
2065  (
2066  mesh,
2067  zoneNames.size(),
2068 
2069  extrudePatch, // patch
2070  extrudeMeshFaces, // mesh face per patch face
2071  extrudeMeshEdges, // mesh edge per patch edge
2072 
2073  extrudeEdgeGlobalFaces, // global indexing per patch edge
2074  edgeMinZoneID, // minZone per patch edge
2075  edgeMaxZoneID, // maxZone per patch edge
2076 
2077  zoneSidePatch, // per zone-side num edges that extrude into it
2078  zoneZonePatch_min // per zone-zone num edges that extrude into it
2079  );
2080 
2081  // Now we'll have:
2082  // zoneSidePatch[zoneA] : number of faces needed on the side of zoneA
2083  // zoneZonePatch_min[zoneA,zoneB] : number of faces needed inbetween A,B
2084 
2085 
2086  // Add the zone-side patches.
2087  addZoneSidePatches
2088  (
2089  mesh,
2090  zoneNames,
2091  (oneD ? oneDPatchType : word::null),
2092 
2093  regionPatches,
2094  zoneSidePatch
2095  );
2096 
2097 
2098  // Add the patches inbetween zones
2099  addInterZonePatches
2100  (
2101  mesh,
2102  zoneNames,
2103  oneD,
2104 
2105  zoneZonePatch_min,
2106  zoneZonePatch_max,
2107  regionPatches
2108  );
2109 
2110 
2111  // Sets sidePatchID[edgeI] to interprocessor patch. Adds any
2112  // interprocessor or cyclic patches if necessary.
2113  labelList sidePatchID;
2114  addCoupledPatches
2115  (
2116  mesh,
2117  extrudePatch,
2118  extrudeMeshFaces,
2119  extrudeMeshEdges,
2120  extrudeEdgeFacesMap,
2121  extrudeEdgeGlobalFaces,
2122 
2123  sidePatchID,
2124  regionPatches
2125  );
2126 
2127 
2128 // // Add all the newPatches to the mesh and fields
2129 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2130 // {
2131 // forAll(newPatches, patchi)
2132 // {
2133 // Pout<< "Adding patch " << patchi
2134 // << " name:" << newPatches[patchi]->name()
2135 // << endl;
2136 // }
2137 // //label nOldPatches = mesh.boundary().size();
2138 // mesh.clearOut();
2139 // mesh.removeFvBoundary();
2140 // mesh.addFvPatches(newPatches, true);
2141 // //// Add calculated fvPatchFields for the added patches
2142 // //for
2143 // //(
2144 // // label patchi = nOldPatches;
2145 // // patchi < mesh.boundary().size();
2146 // // patchi++
2147 // //)
2148 // //{
2149 // // Pout<< "ADDing calculated to patch " << patchi
2150 // // << endl;
2151 // // addCalculatedPatchFields(mesh);
2152 // //}
2153 // //Pout<< "** Added " << mesh.boundary().size()-nOldPatches
2154 // // << " patches." << endl;
2155 // }
2156 
2157 
2158  // Set patches to use for edges to be extruded into boundary faces
2159  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2160  // In order of edgeFaces: per edge, per originating face the
2161  // patch to use for the side face (from the extruded edge).
2162  // If empty size create an internal face.
2163  labelListList extrudeEdgePatches(extrudePatch.nEdges());
2164 
2165  // Is edge a non-manifold edge
2166  bitSet nonManifoldEdge(extrudePatch.nEdges());
2167 
2168  // Note: logic has to be same as in countExtrudePatches.
2169  forAll(edgeFaces, edgeI)
2170  {
2171  const labelList& eFaces = edgeFaces[edgeI];
2172 
2173  labelList& ePatches = extrudeEdgePatches[edgeI];
2174 
2175  if (oneD)
2176  {
2177  ePatches.setSize(eFaces.size());
2178  forAll(eFaces, i)
2179  {
2180  ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]];
2181  }
2182 
2183  if (oneDNonManifoldEdges)
2184  {
2185  //- Set nonManifoldEdge[edgeI] for non-manifold edges only
2186  // The other option is to have non-manifold edges everywhere
2187  // and generate space overlapping columns of cells.
2188  if (eFaces.size() != 2)
2189  {
2190  nonManifoldEdge.set(edgeI);
2191  }
2192  }
2193  else
2194  {
2195  nonManifoldEdge.set(edgeI);
2196  }
2197  }
2198  else if (eFaces.size() == 2)
2199  {
2200  label zone0 = zoneID[eFaces[0]];
2201  label zone1 = zoneID[eFaces[1]];
2202 
2203  if (zone0 != zone1) // || (cos(angle) > blabla))
2204  {
2205  label minZone = min(zone0,zone1);
2206  label maxZone = max(zone0,zone1);
2207  label index = minZone*zoneNames.size()+maxZone;
2208 
2209  ePatches.setSize(eFaces.size());
2210 
2211  if (zone0 == minZone)
2212  {
2213  ePatches[0] = zoneZonePatch_min[index];
2214  ePatches[1] = zoneZonePatch_max[index];
2215  }
2216  else
2217  {
2218  ePatches[0] = zoneZonePatch_max[index];
2219  ePatches[1] = zoneZonePatch_min[index];
2220  }
2221 
2222  nonManifoldEdge.set(edgeI);
2223  }
2224  }
2225  else if (sidePatchID[edgeI] != -1)
2226  {
2227  // Coupled extrusion
2228  ePatches.setSize(eFaces.size());
2229  forAll(eFaces, i)
2230  {
2231  ePatches[i] = sidePatchID[edgeI];
2232  }
2233  }
2234  else
2235  {
2236  label facei = findUncoveredPatchFace
2237  (
2238  mesh,
2239  labelUIndList(extrudeMeshFaces, eFaces),
2240  extrudeMeshEdges[edgeI]
2241  );
2242 
2243  if (facei != -1)
2244  {
2245  label newPatchi = findPatchID
2246  (
2247  regionPatches,
2248  patches[patches.whichPatch(facei)].name()
2249  );
2250  ePatches.setSize(eFaces.size(), newPatchi);
2251  }
2252  else
2253  {
2254  ePatches.setSize(eFaces.size());
2255  forAll(eFaces, i)
2256  {
2257  ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]];
2258  }
2259  }
2260  nonManifoldEdge.set(edgeI);
2261  }
2262  }
2263 
2264 
2265 
2266  // Assign point regions
2267  // ~~~~~~~~~~~~~~~~~~~~
2268 
2269  // Per face, per point the region number.
2270  faceList pointGlobalRegions;
2271  faceList pointLocalRegions;
2272  labelList localToGlobalRegion;
2273 
2275  (
2276  mesh.globalData(),
2277  extrudePatch,
2278  nonManifoldEdge,
2279  false, // keep cyclic separated regions apart
2280 
2281  pointGlobalRegions,
2282  pointLocalRegions,
2283  localToGlobalRegion
2284  );
2285 
2286  // Per local region an originating point
2287  labelList localRegionPoints(localToGlobalRegion.size());
2288  forAll(pointLocalRegions, facei)
2289  {
2290  const face& f = extrudePatch.localFaces()[facei];
2291  const face& pRegions = pointLocalRegions[facei];
2292  forAll(pRegions, fp)
2293  {
2294  localRegionPoints[pRegions[fp]] = f[fp];
2295  }
2296  }
2297 
2298  // Calculate region normals by reducing local region normals
2299  pointField localRegionNormals(localToGlobalRegion.size());
2300  {
2301  pointField localSum(localToGlobalRegion.size(), Zero);
2302 
2303  forAll(pointLocalRegions, facei)
2304  {
2305  const face& pRegions = pointLocalRegions[facei];
2306  forAll(pRegions, fp)
2307  {
2308  label localRegionI = pRegions[fp];
2309  localSum[localRegionI] += extrudePatch.faceNormals()[facei];
2310  }
2311  }
2312 
2313  Map<point> globalSum(2*localToGlobalRegion.size());
2314 
2315  forAll(localSum, localRegionI)
2316  {
2317  label globalRegionI = localToGlobalRegion[localRegionI];
2318  globalSum.insert(globalRegionI, localSum[localRegionI]);
2319  }
2320 
2321  // Reduce
2323  Pstream::mapCombineScatter(globalSum);
2324 
2325  forAll(localToGlobalRegion, localRegionI)
2326  {
2327  label globalRegionI = localToGlobalRegion[localRegionI];
2328  localRegionNormals[localRegionI] = globalSum[globalRegionI];
2329  }
2330  localRegionNormals /= mag(localRegionNormals);
2331  }
2332 
2333 
2334  // For debugging: dump hedgehog plot of normals
2335  if (false)
2336  {
2337  OFstream str(runTime.path()/"localRegionNormals.obj");
2338  label vertI = 0;
2339 
2340  scalar thickness = model().sumThickness(1);
2341 
2342  forAll(pointLocalRegions, facei)
2343  {
2344  const face& f = extrudeFaces[facei];
2345 
2346  forAll(f, fp)
2347  {
2348  label region = pointLocalRegions[facei][fp];
2349  const point& pt = extrudePoints[f[fp]];
2350 
2351  meshTools::writeOBJ(str, pt);
2352  vertI++;
2354  (
2355  str,
2356  pt+thickness*localRegionNormals[region]
2357  );
2358  vertI++;
2359  str << "l " << vertI-1 << ' ' << vertI << nl;
2360  }
2361  }
2362  }
2363 
2364 
2365  // Use model to create displacements of first layer
2366  vectorField firstDisp(localRegionNormals.size());
2367  forAll(firstDisp, regionI)
2368  {
2369  //const point& regionPt = regionCentres[regionI];
2370  const point& regionPt = extrudePatch.points()
2371  [
2372  extrudePatch.meshPoints()
2373  [
2374  localRegionPoints[regionI]
2375  ]
2376  ];
2377  const vector& n = localRegionNormals[regionI];
2378  firstDisp[regionI] = model()(regionPt, n, 1) - regionPt;
2379  }
2380 
2381 
2382  // Create a new mesh
2383  // ~~~~~~~~~~~~~~~~~
2384 
2385  createShellMesh extruder
2386  (
2387  extrudePatch,
2388  pointLocalRegions,
2389  localRegionPoints
2390  );
2391 
2392 
2393  autoPtr<mapPolyMesh> shellMap;
2394  fvMesh regionMesh
2395  (
2396  IOobject
2397  (
2398  shellRegionName,
2399  meshInstance,
2400  runTime,
2403  false
2404  ),
2405  Zero,
2406  false
2407  );
2408 
2409  // Add the new patches
2410  forAll(regionPatches, patchi)
2411  {
2412  polyPatch* ppPtr = regionPatches[patchi];
2413  regionPatches[patchi] = ppPtr->clone(regionMesh.boundaryMesh()).ptr();
2414  delete ppPtr;
2415  }
2416 
2417  #ifdef FULLDEBUG
2418  Pout<< "*** regionPatches : regionPatches:" << nl;
2419  printPatches(Pout, regionPatches);
2420  Pout<< "*** end of regionPatches : regionPatches:" << endl;
2421  #endif
2422 
2423 
2424  regionMesh.clearOut();
2425  regionMesh.removeFvBoundary();
2426  regionMesh.addFvPatches(regionPatches, true);
2427 
2428  {
2429  polyTopoChange meshMod(regionPatches.size());
2430 
2431  extruder.setRefinement
2432  (
2433  firstDisp, // first displacement
2434  model().expansionRatio(),
2435  model().nLayers(), // nLayers
2436  extrudeTopPatchID,
2437  extrudeBottomPatchID,
2438  extrudeEdgePatches,
2439  meshMod
2440  );
2441 
2442  // Enforce actual point positions according to extrudeModel (model)
2443  // (extruder.setRefinement only does fixed expansionRatio)
2444  // The regionPoints and nLayers are looped in the same way as in
2445  // createShellMesh
2446  DynamicList<point>& newPoints = const_cast<DynamicList<point>&>
2447  (
2448  meshMod.points()
2449  );
2450  label meshPointi = extrudePatch.localPoints().size();
2451  forAll(localRegionPoints, regionI)
2452  {
2453  label pointi = localRegionPoints[regionI];
2454  point pt = extrudePatch.localPoints()[pointi];
2455  const vector& n = localRegionNormals[regionI];
2456 
2457  for (label layerI = 1; layerI <= model().nLayers(); layerI++)
2458  {
2459  newPoints[meshPointi++] = model()(pt, n, layerI);
2460  }
2461  }
2462 
2463  shellMap = meshMod.changeMesh
2464  (
2465  regionMesh, // mesh to change
2466  false // inflate
2467  );
2468  }
2469 
2470  // Necessary?
2471  regionMesh.setInstance(meshInstance);
2472 
2473 
2474  // Update numbering on extruder.
2475  extruder.updateMesh(shellMap());
2476 
2477 
2478  // Calculate offsets from shell mesh back to original mesh
2479  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2480 
2481  List<pointField> topOffsets(zoneNames.size());
2482  List<pointField> bottomOffsets(zoneNames.size());
2483 
2484  forAll(regionMesh.boundaryMesh(), patchi)
2485  {
2486  const polyPatch& pp = regionMesh.boundaryMesh()[patchi];
2487 
2488  if (isA<mappedWallPolyPatch>(pp))
2489  {
2490  if (interRegionTopPatch.found(patchi))
2491  {
2492  label zoneI = interRegionTopPatch.find(patchi);
2493  topOffsets[zoneI] = calcOffset(extrudePatch, extruder, pp);
2494  }
2495  else if (interRegionBottomPatch.found(patchi))
2496  {
2497  label zoneI = interRegionBottomPatch.find(patchi);
2498  bottomOffsets[zoneI] = calcOffset(extrudePatch, extruder, pp);
2499  }
2500  }
2501  }
2502 
2503 
2504  // Change top and bottom boundary conditions on regionMesh
2505  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2506 
2507  {
2508  // Correct top patches for offset
2509  setCouplingInfo
2510  (
2511  regionMesh,
2512  interRegionTopPatch,
2513  regionName, // name of main mesh
2514  sampleMode, // sampleMode
2515  topOffsets
2516  );
2517 
2518  // Correct bottom patches for offset
2519  setCouplingInfo
2520  (
2521  regionMesh,
2522  interRegionBottomPatch,
2523  regionName,
2524  sampleMode, // sampleMode
2525  bottomOffsets
2526  );
2527 
2528  // Remove any unused patches
2529  deleteEmptyPatches(regionMesh);
2530  }
2531 
2532  // Change top and bottom boundary conditions on main mesh
2533  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2534 
2535  if (adaptMesh)
2536  {
2537  // Correct top patches for offset
2538  setCouplingInfo
2539  (
2540  mesh,
2541  interMeshTopPatch,
2542  shellRegionName, // name of shell mesh
2543  sampleMode, // sampleMode
2544  -topOffsets
2545  );
2546 
2547  // Correct bottom patches for offset
2548  setCouplingInfo
2549  (
2550  mesh,
2551  interMeshBottomPatch,
2552  shellRegionName,
2553  sampleMode,
2554  -bottomOffsets
2555  );
2556  }
2557 
2558 
2559 
2560  // Write addressing from region mesh back to originating patch
2561  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2562 
2563  labelIOList cellToPatchFaceAddressing
2564  (
2565  IOobject
2566  (
2567  "cellToPatchFaceAddressing",
2568  regionMesh.facesInstance(),
2569  regionMesh.meshSubDir,
2570  regionMesh,
2573  false
2574  ),
2575  extruder.cellToFaceMap()
2576  );
2577  cellToPatchFaceAddressing.note() = "cell to patch face addressing";
2578 
2579  labelIOList faceToPatchFaceAddressing
2580  (
2581  IOobject
2582  (
2583  "faceToPatchFaceAddressing",
2584  regionMesh.facesInstance(),
2585  regionMesh.meshSubDir,
2586  regionMesh,
2589  false
2590  ),
2591  extruder.faceToFaceMap()
2592  );
2593  faceToPatchFaceAddressing.note() =
2594  "front/back face + turning index to patch face addressing";
2595 
2596  labelIOList faceToPatchEdgeAddressing
2597  (
2598  IOobject
2599  (
2600  "faceToPatchEdgeAddressing",
2601  regionMesh.facesInstance(),
2602  regionMesh.meshSubDir,
2603  regionMesh,
2606  false
2607  ),
2608  extruder.faceToEdgeMap()
2609  );
2610  faceToPatchEdgeAddressing.note() =
2611  "side face to patch edge addressing";
2612 
2613  labelIOList pointToPatchPointAddressing
2614  (
2615  IOobject
2616  (
2617  "pointToPatchPointAddressing",
2618  regionMesh.facesInstance(),
2619  regionMesh.meshSubDir,
2620  regionMesh,
2623  false
2624  ),
2625  extruder.pointToPointMap()
2626  );
2627  pointToPatchPointAddressing.note() =
2628  "point to patch point addressing";
2629 
2630 
2631  Info<< "Writing mesh " << regionMesh.name()
2632  << " to " << regionMesh.facesInstance() << nl
2633  << endl;
2634 
2635  bool ok =
2636  regionMesh.write()
2637  && cellToPatchFaceAddressing.write()
2638  && faceToPatchFaceAddressing.write()
2639  && faceToPatchEdgeAddressing.write()
2640  && pointToPatchPointAddressing.write();
2641 
2642  if (!ok)
2643  {
2645  << "Failed writing mesh " << regionMesh.name()
2646  << " at location " << regionMesh.facesInstance()
2647  << exit(FatalError);
2648  }
2649  topoSet::removeFiles(regionMesh);
2650  processorMeshes::removeFiles(regionMesh);
2651 
2652 
2653  // See if we need to extrude coordinates as well
2654  {
2655  autoPtr<pointIOField> patchFaceCentresPtr;
2656 
2657  IOobject io
2658  (
2659  "patchFaceCentres",
2660  mesh.pointsInstance(),
2661  mesh.meshSubDir,
2662  mesh,
2664  );
2665  if (io.typeHeaderOk<pointIOField>(true))
2666  {
2667  // Read patchFaceCentres and patchEdgeCentres
2668  Info<< "Reading patch face,edge centres : "
2669  << io.name() << " and patchEdgeCentres" << endl;
2670 
2671  extrudeGeometricProperties
2672  (
2673  mesh,
2674  extrudePatch,
2675  extruder,
2676  regionMesh,
2677  model()
2678  );
2679  }
2680  }
2681 
2682 
2683 
2684 
2685  // Insert baffles into original mesh
2686  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2687 
2688  autoPtr<mapPolyMesh> addBafflesMap;
2689 
2690  if (adaptMesh)
2691  {
2692  polyTopoChange meshMod(mesh);
2693 
2694  // Modify faces to be in bottom (= always coupled) patch
2695  forAll(extrudeMeshFaces, zoneFacei)
2696  {
2697  label meshFacei = extrudeMeshFaces[zoneFacei];
2698  label zoneI = zoneID[zoneFacei];
2699  bool flip = zoneFlipMap[zoneFacei];
2700  const face& f = mesh.faces()[meshFacei];
2701 
2702  if (!flip)
2703  {
2704  meshMod.modifyFace
2705  (
2706  f, // modified face
2707  meshFacei, // label of face being modified
2708  mesh.faceOwner()[meshFacei],// owner
2709  -1, // neighbour
2710  false, // face flip
2711  interMeshBottomPatch[zoneI],// patch for face
2712  meshZoneID[zoneI], // zone for face
2713  flip // face flip in zone
2714  );
2715  }
2716  else if (mesh.isInternalFace(meshFacei))
2717  {
2718  meshMod.modifyFace
2719  (
2720  f.reverseFace(), // modified face
2721  meshFacei, // label of modified face
2722  mesh.faceNeighbour()[meshFacei],// owner
2723  -1, // neighbour
2724  true, // face flip
2725  interMeshBottomPatch[zoneI], // patch for face
2726  meshZoneID[zoneI], // zone for face
2727  !flip // face flip in zone
2728  );
2729  }
2730  }
2731 
2732  if (zoneShadowNames.size() > 0) //if there is a top faceZone specified
2733  {
2734  forAll(extrudeMeshFaces, zoneFacei)
2735  {
2736  label meshFacei = extrudeMeshShadowFaces[zoneFacei];
2737  label zoneI = zoneShadowID[zoneFacei];
2738  bool flip = zoneShadowFlipMap[zoneFacei];
2739  const face& f = mesh.faces()[meshFacei];
2740 
2741  if (!flip)
2742  {
2743  meshMod.modifyFace
2744  (
2745  f, // modified face
2746  meshFacei, // face being modified
2747  mesh.faceOwner()[meshFacei],// owner
2748  -1, // neighbour
2749  false, // face flip
2750  interMeshTopPatch[zoneI], // patch for face
2751  meshZoneID[zoneI], // zone for face
2752  flip // face flip in zone
2753  );
2754  }
2755  else if (mesh.isInternalFace(meshFacei))
2756  {
2757  meshMod.modifyFace
2758  (
2759  f.reverseFace(), // modified face
2760  meshFacei, // label modified face
2761  mesh.faceNeighbour()[meshFacei],// owner
2762  -1, // neighbour
2763  true, // face flip
2764  interMeshTopPatch[zoneI], // patch for face
2765  meshZoneID[zoneI], // zone for face
2766  !flip // face flip in zone
2767  );
2768  }
2769  }
2770  }
2771  else
2772  {
2773  // Add faces (using same points) to be in top patch
2774  forAll(extrudeMeshFaces, zoneFacei)
2775  {
2776  label meshFacei = extrudeMeshFaces[zoneFacei];
2777  label zoneI = zoneID[zoneFacei];
2778  bool flip = zoneFlipMap[zoneFacei];
2779  const face& f = mesh.faces()[meshFacei];
2780 
2781  if (!flip)
2782  {
2783  if (mesh.isInternalFace(meshFacei))
2784  {
2785  meshMod.addFace
2786  (
2787  f.reverseFace(), // modified face
2788  mesh.faceNeighbour()[meshFacei],// owner
2789  -1, // neighbour
2790  -1, // master point
2791  -1, // master edge
2792  meshFacei, // master face
2793  true, // flip flux
2794  interMeshTopPatch[zoneI], // patch for face
2795  -1, // zone for face
2796  false //face flip in zone
2797  );
2798  }
2799  }
2800  else
2801  {
2802  meshMod.addFace
2803  (
2804  f, // face
2805  mesh.faceOwner()[meshFacei], // owner
2806  -1, // neighbour
2807  -1, // master point
2808  -1, // master edge
2809  meshFacei, // master face
2810  false, // flip flux
2811  interMeshTopPatch[zoneI], // patch for face
2812  -1, // zone for face
2813  false // zone flip
2814  );
2815  }
2816  }
2817  }
2818 
2819  // Change the mesh. Change points directly (no inflation).
2820  addBafflesMap = meshMod.changeMesh(mesh, false);
2821 
2822  // Update fields
2823  mesh.updateMesh(addBafflesMap());
2824 
2825 
2826 //XXXXXX
2827 // Update maps! e.g. faceToPatchFaceAddressing
2828 //XXXXXX
2829 
2830  // Move mesh (since morphing might not do this)
2831  if (addBafflesMap().hasMotionPoints())
2832  {
2833  mesh.movePoints(addBafflesMap().preMotionPoints());
2834  }
2835 
2836  mesh.setInstance(meshInstance);
2837 
2838  // Remove any unused patches
2839  deleteEmptyPatches(mesh);
2840 
2841  Info<< "Writing mesh " << mesh.name()
2842  << " to " << mesh.facesInstance() << nl
2843  << endl;
2844 
2845  if (!mesh.write())
2846  {
2848  << "Failed writing mesh " << mesh.name()
2849  << " at location " << mesh.facesInstance()
2850  << exit(FatalError);
2851  }
2854  }
2855 
2856  Info << "End\n" << endl;
2857 
2858  return 0;
2859 }
2860 
2861 
2862 // ************************************************************************* //
Foam::Pstream::mapCombineGather
static void mapCombineGather(const List< commsStruct > &comms, Container &Values, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:545
Foam::PrimitivePatch::points
const Field< point_type > & points() const noexcept
Definition: PrimitivePatch.H:295
Foam::createShellMesh::faceToEdgeMap
const labelList & faceToEdgeMap() const
Definition: createShellMesh.H:143
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:191
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:63
volFields.H
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::syncTools::syncEdgeList
static void syncEdgeList(const polyMesh &mesh, List< T > &edgeValues, const CombineOp &cop, const T &nullValue, const TransformOp &top, const FlipOp &fop)
Definition: syncToolsTemplates.C:793
Foam::polyMesh::points
virtual const pointField & points() const
Definition: polyMesh.C:1062
Foam::createShellMesh::pointToPointMap
const labelList & pointToPointMap() const
Definition: createShellMesh.H:149
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:165
meshTools.H
Foam::extrudeModel::sumThickness
scalar sumThickness(const label layer) const
Definition: extrudeModel.C:64
Foam::IOobject::AUTO_WRITE
@ AUTO_WRITE
Definition: IOobject.H:190
mappedWallPolyPatch.H
Foam::PrimitivePatch::edgeFaces
const labelListList & edgeFaces() const
Definition: PrimitivePatch.C:255
Foam::labelMax
constexpr label labelMax
Definition: label.H:55
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
Foam::faceZone::flipMap
const boolList & flipMap() const noexcept
Definition: faceZone.H:268
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: foamVtkLagrangianWriter.H:57
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Definition: fvMesh.C:1034
Foam::fvMeshTools::createDummyFvMeshFiles
static void createDummyFvMeshFiles(const objectRegistry &parent, const word &regionName, const bool verbose=false)
Definition: fvMeshTools.C:753
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:88
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
Foam::OBJstream
OFstream that keeps track of vertices.
Definition: OBJstream.H:54
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:59
Foam::PrimitivePatch::edges
const edgeList & edges() const
Definition: PrimitivePatch.C:176
Foam::extrudeModel
Top level extrusion model class.
Definition: extrudeModel.H:72
cyclicPolyPatch.H
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:57
Foam::Zero
static constexpr const zero Zero
Definition: zero.H:131
PatchTools.H
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:51
Foam::dictionary::found
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryI.H:80
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:597
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Definition: meshTools.C:196
wedgePolyPatch.H
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Definition: gatherScatterList.C:209
addOverwriteOption.H
Foam::primitiveMesh::edgeFaces
const labelListList & edgeFaces() const
Definition: primitiveMeshEdgeFaces.C:27
globalIndex.H
Foam::PrimitivePatch::nEdges
label nEdges() const
Definition: PrimitivePatch.H:318
dictName
const word dictName("faMeshDefinition")
Foam::polyMesh::meshSubDir
static word meshSubDir
Definition: polyMesh.H:317
polyTopoChange.H
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:773
Foam::PrimitivePatch::meshEdges
labelList meshEdges(const edgeList &allEdges, const labelListList &cellEdges, const labelList &faceCells) const
Definition: PrimitivePatchMeshEdges.C:46
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:95
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:59
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::coupledPolyPatch::transformTypeNames
static const Enum< transformType > transformTypeNames
Definition: coupledPolyPatch.H:66
Foam::polyMesh::facesInstance
const fileName & facesInstance() const
Definition: polyMesh.C:845
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: lumpedPointController.H:65
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Definition: UPstream.H:453
Foam::faceSet
A list of face labels.
Definition: faceSet.H:47
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Definition: gatherScatter.C:144
Foam::orEqOp
Definition: ops.H:80
Foam::fvMesh::removeFvBoundary
void removeFvBoundary()
Definition: fvMesh.C:628
Foam::FatalIOError
IOerror FatalIOError
Foam::fvMesh::movePoints
virtual tmp< scalarField > movePoints(const pointField &)
Definition: fvMesh.C:858
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Definition: polyMesh.H:440
Foam::polyMesh::clearOut
void clearOut()
Definition: polyMeshClear.C:215
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
surfaceFields.H
Foam::surfaceFields.
Foam::createShellMesh::faceToFaceMap
const labelList & faceToFaceMap() const
Definition: createShellMesh.H:137
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:100
Foam::primitiveMesh::edges
const edgeList & edges() const
Definition: primitiveMeshEdges.C:498
Foam::dictionary::set
entry * set(entry *entryPtr)
Definition: dictionary.C:773
Foam::Pout
prefixOSstream Pout
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshEdges.C:509
Foam::Enum::get
EnumType get(const word &enumName) const
Definition: Enum.C:68
Foam::HashSet
A HashTable with keys but without contents that is similar to std::unordered_set.
Definition: HashSet.H:73
processorMeshes.H
syncTools.H
Foam::extrudeModel::nLayers
label nLayers() const
Definition: extrudeModel.C:52
setSystemMeshDictionaryIO.H
zoneIDs
const labelIOList & zoneIDs
Definition: correctPhi.H:59
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Definition: hashSets.C:26
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:73
Foam::polyBoundaryMesh::names
wordList names() const
Definition: polyBoundaryMesh.C:548
Foam::mappedPatchBase::sampleModeNames_
static const Enum< sampleMode > sampleModeNames_
Definition: mappedPatchBase.H:133
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::minEqOp
Definition: ops.H:75
OFstream.H
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::SubField
SubField is a Field obtained as a section of another Field, without its own allocation....
Definition: Field.H:60
Foam::mode
mode_t mode(const fileName &name, const bool followLink=true)
Definition: POSIX.C:692
Foam::createShellMesh::updateMesh
void updateMesh(const mapPolyMesh &)
Definition: createShellMesh.C:902
Foam::polyMesh::pointsInstance
const fileName & pointsInstance() const
Definition: polyMesh.C:839
n
label n
Definition: TABSMDCalcMethod2.H:31
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
createShellMesh.H
Foam::polyBoundaryMesh::checkParallelSync
bool checkParallelSync(const bool report=false) const
Definition: polyBoundaryMesh.C:965
Foam::primitiveMesh::nCells
label nCells() const noexcept
Definition: primitiveMeshI.H:89
Foam::Field
Generic templated field type.
Definition: Field.H:59
Foam::regIOobject::write
virtual bool write(const bool valid=true) const
Definition: regIOobjectWrite.C:125
Foam::coupledPolyPatch::NOORDERING
@ NOORDERING
Definition: coupledPolyPatch.H:63
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
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:64
Foam::List::setSize
void setSize(const label n)
Definition: List.H:218
extrudeModel.H
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Definition: DynamicListI.H:504
argList.H
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:159
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Definition: polyMesh.C:1100
faceSet.H
addRegionOption.H
Foam::fvMesh::updateMesh
virtual void updateMesh(const mapPolyMesh &mpm)
Definition: fvMesh.C:946
Foam::ZoneMesh< faceZone, polyMesh >
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:295
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Definition: polyMesh.H:482
Foam::extrudeModel::New
static autoPtr< extrudeModel > New(const dictionary &dict)
Definition: extrudeModelNew.C:27
Foam::andOp
Definition: ops.H:227
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Definition: polyBoundaryMesh.C:805
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:55
Foam::fvMeshTools::reorderPatches
static void reorderPatches(fvMesh &, const labelList &oldToNew, const label nPatches, const bool validBoundary)
Definition: fvMeshTools.C:322
Foam::polyBoundaryMesh::findPatchID
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Definition: polyBoundaryMesh.C:758
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Definition: hashSets.C:40
Foam::mapDistribute::distribute
void distribute(List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Definition: mapDistributeTemplates.C:147
Foam::PatchTools::matchEdges
static void matchEdges(const PrimitivePatch< FaceList1, PointField1 > &p1, const PrimitivePatch< FaceList2, PointField2 > &p2, labelList &p1EdgeLabels, labelList &p2EdgeLabels, bitSet &sameOrientation)
Definition: PatchToolsMatch.C:70
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::PrimitivePatch::nPoints
label nPoints() const
Definition: PrimitivePatch.H:312
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:119
Foam::fvMesh::addFvPatches
void addFvPatches(PtrList< polyPatch > &plist, const bool validBoundary=true)
Definition: fvMesh.C:598
Foam::PtrList::clone
PtrList< T > clone(Args &&... args) const
createNamedMesh.H
Required Variables.
Foam::polyPatch::New
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Definition: polyPatchNew.C:28
Foam::createShellMesh::setRefinement
void setRefinement(const pointField &firstLayerThickness, const scalar expansionRatio, const label nLayers, const labelList &topPatchID, const labelList &bottomPatchID, const labelListList &extrudeEdgePatches, polyTopoChange &meshMod)
Definition: createShellMesh.C:442
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::PrimitivePatch::localFaces
const List< face_type > & localFaces() const
Definition: PrimitivePatch.C:310
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
dictIO
IOobject dictIO
Definition: setConstantMeshDictionaryIO.H:1
Foam::createShellMesh::cellToFaceMap
const labelList & cellToFaceMap() const
Definition: createShellMesh.H:126
Foam::Ostream::write
virtual bool write(const token &tok)=0
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:81
fvMesh.H
Foam
Definition: atmBoundaryLayer.C:26
Foam::patchIdentifier::index
label index() const noexcept
Definition: patchIdentifier.H:143
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
Foam::ZoneMesh::findZoneID
label findZoneID(const word &zoneName) const
Definition: ZoneMesh.C:512
Foam::ListOps::uniqueEqOp
Definition: ListOps.H:701
Foam::polyPatch::start
label start() const
Definition: polyPatch.H:357
Foam::maxEqOp
Definition: ops.H:74
Foam::ZoneMesh::names
wordList names() const
Definition: ZoneMesh.C:298
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Foam::PrimitivePatch::localPoints
const Field< point_type > & localPoints() const
Definition: PrimitivePatch.C:352
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:49
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:284
Foam::IOobject::name
const word & name() const noexcept
Definition: IOobjectI.H:58
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:49
setRootCase.H
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:78
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const noexcept
Definition: primitiveMeshI.H:96
Foam::polyMesh::faces
virtual const faceList & faces() const
Definition: polyMesh.C:1087
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Definition: gatherScatterList.C:46
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Definition: UPstream.H:459
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::Time::path
fileName path() const
Definition: Time.H:354
Foam::Pstream::mapCombineScatter
static void mapCombineScatter(const List< commsStruct > &comms, Container &Values, const int tag, const label comm)
Definition: combineGatherScatter.C:660
Foam::polyPatch::faceCentres
const vectorField::subField faceCentres() const
Definition: polyPatch.C:314
fvMeshTools.H
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::createShellMesh::calcPointRegions
static void calcPointRegions(const globalMeshData &globalData, const primitiveFacePatch &patch, const bitSet &nonManifoldEdge, const bool syncNonCollocated, faceList &pointGlobalRegions, faceList &pointLocalRegions, labelList &localToGlobalRegion)
Definition: createShellMesh.C:150
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:58
Foam::processorPolyPatch::newName
static word newName(const label myProcNo, const label neighbProcNo)
Definition: processorPolyPatch.C:178
Foam::globalMeshData::coupledPatch
const indirectPrimitivePatch & coupledPatch() const
Definition: globalMeshData.C:2039
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:71
Foam::processorMeshes::removeFiles
static void removeFiles(const polyMesh &mesh)
Definition: processorMeshes.C:267
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:99
Foam::constant::electromagnetic::e
const dimensionedScalar e
Definition: createFields.H:11
Foam::IOList< label >
Foam::word::null
static const word null
Definition: word.H:78
createTime.H
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:59
Foam::line
A line primitive.
Definition: line.H:49
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
Definition: List.H:337
Foam::PrimitivePatch::faceNormals
const Field< point_type > & faceNormals() const
Definition: PrimitivePatch.C:438
Foam::createShellMesh
Creates mesh by extruding a patch.
Definition: createShellMesh.H:57
Foam::labelMin
constexpr label labelMin
Definition: label.H:54
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:57
Foam::polyPatch::clone
virtual autoPtr< polyPatch > clone(const labelList &faceCells) const
Definition: polyPatch.H:231
nonuniformTransformCyclicPolyPatch.H
Foam::name
word name(const expressions::valueTypeCode typeCode)
Definition: exprTraits.C:52
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:56
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Definition: dictionary.C:633
Foam::primitiveMesh::nFaces
label nFaces() const noexcept
Definition: primitiveMeshI.H:83
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Definition: error.H:494
Foam::patchIdentifier::name
const word & name() const noexcept
Definition: patchIdentifier.H:131
Foam::plusEqOp
Definition: ops.H:66
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:52
coupled
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Definition: polyMesh.C:1288
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Definition: combineGatherScatter.C:426
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Definition: PrimitivePatch.C:323
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:141
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Definition: argList.C:328
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:184
args
Foam::argList args(argc, argv)
Foam::PatchTools::edgeNormals
static tmp< pointField > edgeNormals(const polyMesh &, const PrimitivePatch< FaceList, PointField > &, const labelList &patchEdges, const labelList &coupledEdges)
Foam::topoSet::removeFiles
static void removeFiles(const polyMesh &)
Definition: topoSet.C:628
WarningInFunction
#define WarningInFunction
Definition: messageStream.H:353
Foam::mappedPatchBase::sampleMode
sampleMode
Definition: mappedPatchBase.H:115
pointFields.H
Foam::objectRegistry::time
const Time & time() const noexcept
Definition: objectRegistry.H:174
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:585
OBJstream.H
Foam::polyMesh::setInstance
void setInstance(const fileName &instance, const IOobject::writeOption wOpt=IOobject::AUTO_WRITE)
Definition: polyMeshIO.C:29
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Definition: polyMesh.C:1106
Foam::UPstream::nProcs
static label nProcs(const label communicator=worldComm)
Definition: UPstream.H:441
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:398
Foam::fvMesh::clearOut
void clearOut()
Definition: fvMesh.C:232
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
Definition: globalIndexI.H:233
Foam::argList::found
bool found(const word &optName) const
Definition: argListI.H:171
Foam::fvMesh::name
const word & name() const
Definition: fvMesh.H:296
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:75
Foam::IOobject::MUST_READ
@ MUST_READ
Definition: IOobject.H:181
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:54