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  label patchi = zoneToPatch[zoneI];
1130 
1131  if (patchi != -1)
1132  {
1133  const polyPatch& pp = patches[patchi];
1134 
1135  if (isA<mappedWallPolyPatch>(pp))
1136  {
1137  newPatches[patchi] = new mappedWallPolyPatch
1138  (
1139  pp.name(),
1140  pp.size(),
1141  pp.start(),
1142  patchi,
1143  sampleRegion, // sampleRegion
1144  mode, // sampleMode
1145  pp.name(), // samplePatch
1146  offsets[zoneI], // offset
1147  patches
1148  );
1149  }
1150  }
1151  }
1152 
1153  forAll(newPatches, patchi)
1154  {
1155  if (!newPatches[patchi])
1156  {
1157  newPatches[patchi] = patches[patchi].clone(patches).ptr();
1158  //newPatches[patchi].index() = patchi;
1159  }
1160  }
1161 
1162 
1163  #ifdef FULLDEBUG
1164  Pout<< "*** setCouplingInfo addFvPAtches:" << nl;
1165  printPatches(Pout, newPatches);
1166  Pout<< "*** setCouplingInfo end of addFvPAtches:" << endl;
1167  #endif
1168 
1170  mesh.addFvPatches(newPatches, true);
1171 }
1172 
1173 
1174 // Extrude and write geometric properties
1175 void extrudeGeometricProperties
1176 (
1177  const polyMesh& mesh,
1178  const primitiveFacePatch& extrudePatch,
1179  const createShellMesh& extruder,
1180  const polyMesh& regionMesh,
1181  const extrudeModel& model
1182 )
1183 {
1184  const pointIOField patchFaceCentres
1185  (
1186  IOobject
1187  (
1188  "patchFaceCentres",
1189  mesh.pointsInstance(),
1190  mesh.meshSubDir,
1191  mesh,
1193  )
1194  );
1195 
1196  const pointIOField patchEdgeCentres
1197  (
1198  IOobject
1199  (
1200  "patchEdgeCentres",
1201  mesh.pointsInstance(),
1202  mesh.meshSubDir,
1203  mesh,
1205  )
1206  );
1207 
1208  //forAll(extrudePatch.edges(), edgeI)
1209  //{
1210  // const edge& e = extrudePatch.edges()[edgeI];
1211  // Pout<< "Edge:" << e.centre(extrudePatch.localPoints()) << nl
1212  // << "read:" << patchEdgeCentres[edgeI]
1213  // << endl;
1214  //}
1215 
1216 
1217  // Determine edge normals on original patch
1218  labelList patchEdges;
1219  labelList coupledEdges;
1220  bitSet sameEdgeOrientation;
1222  (
1223  extrudePatch,
1225  patchEdges,
1226  coupledEdges,
1227  sameEdgeOrientation
1228  );
1229 
1230  pointField patchEdgeNormals
1231  (
1233  (
1234  mesh,
1235  extrudePatch,
1236  patchEdges,
1237  coupledEdges
1238  )
1239  );
1240 
1241 
1242  pointIOField faceCentres
1243  (
1244  IOobject
1245  (
1246  "faceCentres",
1247  regionMesh.pointsInstance(),
1248  regionMesh.meshSubDir,
1249  regionMesh,
1252  false
1253  ),
1254  regionMesh.nFaces()
1255  );
1256 
1257 
1258  // Work out layers. Guaranteed in columns so no fancy parallel bits.
1259 
1260 
1261  forAll(extruder.faceToFaceMap(), facei)
1262  {
1263  if (extruder.faceToFaceMap()[facei] != 0)
1264  {
1265  // 'horizontal' face
1266  label patchFacei = mag(extruder.faceToFaceMap()[facei])-1;
1267 
1268  label celli = regionMesh.faceOwner()[facei];
1269  if (regionMesh.isInternalFace(facei))
1270  {
1271  celli = max(celli, regionMesh.faceNeighbour()[facei]);
1272  }
1273 
1274  // Calculate layer from cell numbering (see createShellMesh)
1275  label layerI = (celli % model.nLayers());
1276 
1277  if
1278  (
1279  !regionMesh.isInternalFace(facei)
1280  && extruder.faceToFaceMap()[facei] > 0
1281  )
1282  {
1283  // Top face
1284  layerI++;
1285  }
1286 
1287 
1288  // Recalculate based on extrusion model
1289  faceCentres[facei] = model
1290  (
1291  patchFaceCentres[patchFacei],
1292  extrudePatch.faceNormals()[patchFacei],
1293  layerI
1294  );
1295  }
1296  else
1297  {
1298  // 'vertical face
1299  label patchEdgeI = extruder.faceToEdgeMap()[facei];
1300  label layerI =
1301  (
1302  regionMesh.faceOwner()[facei]
1303  % model.nLayers()
1304  );
1305 
1306  // Extrude patch edge centre to this layer
1307  point pt0 = model
1308  (
1309  patchEdgeCentres[patchEdgeI],
1310  patchEdgeNormals[patchEdgeI],
1311  layerI
1312  );
1313  // Extrude patch edge centre to next layer
1314  point pt1 = model
1315  (
1316  patchEdgeCentres[patchEdgeI],
1317  patchEdgeNormals[patchEdgeI],
1318  layerI+1
1319  );
1320 
1321  // Interpolate
1322  faceCentres[facei] = 0.5*(pt0+pt1);
1323  }
1324  }
1325 
1326  pointIOField cellCentres
1327  (
1328  IOobject
1329  (
1330  "cellCentres",
1331  regionMesh.pointsInstance(),
1332  regionMesh.meshSubDir,
1333  regionMesh,
1336  false
1337  ),
1338  regionMesh.nCells()
1339  );
1340 
1341  forAll(extruder.cellToFaceMap(), celli)
1342  {
1343  label patchFacei = extruder.cellToFaceMap()[celli];
1344 
1345  // Calculate layer from cell numbering (see createShellMesh)
1346  label layerI = (celli % model.nLayers());
1347 
1348  // Recalculate based on extrusion model
1349  point pt0 = model
1350  (
1351  patchFaceCentres[patchFacei],
1352  extrudePatch.faceNormals()[patchFacei],
1353  layerI
1354  );
1355  point pt1 = model
1356  (
1357  patchFaceCentres[patchFacei],
1358  extrudePatch.faceNormals()[patchFacei],
1359  layerI+1
1360  );
1361 
1362  // Interpolate
1363  cellCentres[celli] = 0.5*(pt0+pt1);
1364  }
1365 
1366 
1367  // Bit of checking
1368  if (false)
1369  {
1370  OBJstream faceStr(regionMesh.time().path()/"faceCentres.obj");
1371  OBJstream cellStr(regionMesh.time().path()/"cellCentres.obj");
1372 
1373  forAll(faceCentres, facei)
1374  {
1375  Pout<< "Model :" << faceCentres[facei] << endl
1376  << "regionMesh:" << regionMesh.faceCentres()[facei] << endl;
1377  faceStr.write
1378  (
1379  linePointRef
1380  (
1381  faceCentres[facei],
1382  regionMesh.faceCentres()[facei]
1383  )
1384  );
1385  }
1386  forAll(cellCentres, celli)
1387  {
1388  Pout<< "Model :" << cellCentres[celli] << endl
1389  << "regionMesh:" << regionMesh.cellCentres()[celli] << endl;
1390  cellStr.write
1391  (
1392  linePointRef
1393  (
1394  cellCentres[celli],
1395  regionMesh.cellCentres()[celli]
1396  )
1397  );
1398  }
1399  }
1400 
1401 
1402 
1403  Info<< "Writing geometric properties for mesh " << regionMesh.name()
1404  << " to " << regionMesh.pointsInstance() << nl
1405  << endl;
1406 
1407  bool ok = faceCentres.write() && cellCentres.write();
1408 
1409  if (!ok)
1410  {
1412  << "Failed writing " << faceCentres.objectPath()
1413  << " and " << cellCentres.objectPath()
1414  << exit(FatalError);
1415  }
1416 }
1417 
1418 
1419 int main(int argc, char *argv[])
1420 {
1422  (
1423  "Create region mesh by extruding a faceZone or faceSet"
1424  );
1425 
1426  #include "addRegionOption.H"
1427  #include "addOverwriteOption.H"
1428 
1430  (
1431  "dict", "file", "Alternative extrudeToRegionMeshDict"
1432  );
1433 
1434  #include "setRootCase.H"
1435  #include "createTime.H"
1436  #include "createNamedMesh.H"
1437 
1438  if (mesh.boundaryMesh().checkParallelSync(true))
1439  {
1440  List<wordList> allNames(Pstream::nProcs());
1441  allNames[Pstream::myProcNo()] = mesh.boundaryMesh().names();
1442  Pstream::gatherList(allNames);
1443  Pstream::scatterList(allNames);
1444 
1446  << "Patches are not synchronised on all processors."
1447  << " Per processor patches " << allNames
1448  << exit(FatalError);
1449  }
1450 
1451 
1452  const word oldInstance = mesh.pointsInstance();
1453  const bool overwrite = args.found("overwrite");
1454 
1455  const word dictName("extrudeToRegionMeshDict");
1456 
1457  #include "setSystemMeshDictionaryIO.H"
1458 
1460 
1461  // Point generator
1463 
1464  // Region
1465  const word shellRegionName(dict.get<word>("region"));
1466 
1467  // Faces to extrude - either faceZones or faceSets (boundary faces only)
1468  wordList zoneNames;
1469  wordList zoneShadowNames;
1470 
1471  const bool hasZones = dict.found("faceZones");
1472  if (hasZones)
1473  {
1474  dict.readEntry("faceZones", zoneNames);
1475  dict.readIfPresent("faceZonesShadow", zoneShadowNames);
1476 
1477  // Check
1478  if (dict.found("faceSets"))
1479  {
1481  << "Please supply faces to extrude either through 'faceZones'"
1482  << " or 'faceSets' entry. Found both."
1483  << exit(FatalIOError);
1484  }
1485  }
1486  else
1487  {
1488  dict.readEntry("faceSets", zoneNames);
1489  dict.readIfPresent("faceSetsShadow", zoneShadowNames);
1490  }
1491 
1492 
1493  mappedPatchBase::sampleMode sampleMode =
1495 
1496  const bool oneD(dict.get<bool>("oneD"));
1497  bool oneDNonManifoldEdges(false);
1498  word oneDPatchType(emptyPolyPatch::typeName);
1499  if (oneD)
1500  {
1501  oneDNonManifoldEdges = dict.getOrDefault("nonManifold", false);
1502  oneDPatchType = dict.get<word>("oneDPolyPatchType");
1503  }
1504 
1505  const bool adaptMesh(dict.get<bool>("adaptMesh"));
1506 
1507  if (hasZones)
1508  {
1509  Info<< "Extruding zones " << zoneNames
1510  << " on mesh " << regionName
1511  << " into shell mesh " << shellRegionName
1512  << endl;
1513  }
1514  else
1515  {
1516  Info<< "Extruding faceSets " << zoneNames
1517  << " on mesh " << regionName
1518  << " into shell mesh " << shellRegionName
1519  << endl;
1520  }
1521 
1522  if (shellRegionName == regionName)
1523  {
1525  << "Cannot extrude into same region as mesh." << endl
1526  << "Mesh region : " << regionName << endl
1527  << "Shell region : " << shellRegionName
1528  << exit(FatalIOError);
1529  }
1530 
1531 
1532  if (oneD)
1533  {
1534  if (oneDNonManifoldEdges)
1535  {
1536  Info<< "Extruding as 1D columns with sides in patch type "
1537  << oneDPatchType
1538  << " and connected points (except on non-manifold areas)."
1539  << endl;
1540  }
1541  else
1542  {
1543  Info<< "Extruding as 1D columns with sides in patch type "
1544  << oneDPatchType
1545  << " and duplicated points (overlapping volumes)."
1546  << endl;
1547  }
1548  }
1549 
1550 
1551 
1552 
1554  //IOobjectList objects(mesh, runTime.timeName());
1555  //
1557  //
1558  //PtrList<volScalarField> vsFlds;
1559  //ReadFields(mesh, objects, vsFlds);
1560  //
1561  //PtrList<volVectorField> vvFlds;
1562  //ReadFields(mesh, objects, vvFlds);
1563  //
1564  //PtrList<volSphericalTensorField> vstFlds;
1565  //ReadFields(mesh, objects, vstFlds);
1566  //
1567  //PtrList<volSymmTensorField> vsymtFlds;
1568  //ReadFields(mesh, objects, vsymtFlds);
1569  //
1570  //PtrList<volTensorField> vtFlds;
1571  //ReadFields(mesh, objects, vtFlds);
1572  //
1574  //
1575  //PtrList<surfaceScalarField> ssFlds;
1576  //ReadFields(mesh, objects, ssFlds);
1577  //
1578  //PtrList<surfaceVectorField> svFlds;
1579  //ReadFields(mesh, objects, svFlds);
1580  //
1581  //PtrList<surfaceSphericalTensorField> sstFlds;
1582  //ReadFields(mesh, objects, sstFlds);
1583  //
1584  //PtrList<surfaceSymmTensorField> ssymtFlds;
1585  //ReadFields(mesh, objects, ssymtFlds);
1586  //
1587  //PtrList<surfaceTensorField> stFlds;
1588  //ReadFields(mesh, objects, stFlds);
1589  //
1591  //
1592  //PtrList<pointScalarField> psFlds;
1593  //ReadFields(pointMesh::New(mesh), objects, psFlds);
1594  //
1595  //PtrList<pointVectorField> pvFlds;
1596  //ReadFields(pointMesh::New(mesh), objects, pvFlds);
1597 
1598 
1599 
1600  // Create dummy fv* files
1601  fvMeshTools::createDummyFvMeshFiles(mesh, shellRegionName, true);
1602 
1603 
1604  word meshInstance;
1605  if (!overwrite)
1606  {
1607  ++runTime;
1608  meshInstance = runTime.timeName();
1609  }
1610  else
1611  {
1612  meshInstance = oldInstance;
1613  }
1614  Info<< "Writing meshes to " << meshInstance << nl << endl;
1615 
1616 
1618 
1619 
1620  // Extract faces to extrude
1621  // ~~~~~~~~~~~~~~~~~~~~~~~~
1622  // Note: zoneID are regions of extrusion. They are not mesh.faceZones
1623  // indices.
1624 
1625  // From extrude zone to mesh zone (or -1 if extruding faceSets)
1626  labelList meshZoneID;
1627  // Per extrude zone whether contains internal or external faces
1628  boolList isInternal(zoneNames.size(), false);
1629 
1630  labelList extrudeMeshFaces;
1631  faceList zoneFaces;
1632  labelList zoneID;
1633  boolList zoneFlipMap;
1634  // Shadow
1635  labelList zoneShadowIDs; // from extrude shadow zone to mesh zone
1636  labelList extrudeMeshShadowFaces;
1637  boolList zoneShadowFlipMap;
1638  labelList zoneShadowID;
1639 
1640  if (hasZones)
1641  {
1642  const faceZoneMesh& faceZones = mesh.faceZones();
1643 
1644  meshZoneID.setSize(zoneNames.size());
1645  forAll(zoneNames, i)
1646  {
1647  meshZoneID[i] = faceZones.findZoneID(zoneNames[i]);
1648  if (meshZoneID[i] == -1)
1649  {
1651  << "Cannot find zone " << zoneNames[i] << endl
1652  << "Valid zones are " << faceZones.names()
1653  << exit(FatalIOError);
1654  }
1655  }
1656  // Collect per face information
1657  label nExtrudeFaces = 0;
1658  forAll(meshZoneID, i)
1659  {
1660  nExtrudeFaces += faceZones[meshZoneID[i]].size();
1661  }
1662  extrudeMeshFaces.setSize(nExtrudeFaces);
1663  zoneFaces.setSize(nExtrudeFaces);
1664  zoneID.setSize(nExtrudeFaces);
1665  zoneFlipMap.setSize(nExtrudeFaces);
1666  nExtrudeFaces = 0;
1667  forAll(meshZoneID, i)
1668  {
1669  const faceZone& fz = faceZones[meshZoneID[i]];
1670  const primitiveFacePatch& fzp = fz();
1671  forAll(fz, j)
1672  {
1673  extrudeMeshFaces[nExtrudeFaces] = fz[j];
1674  zoneFaces[nExtrudeFaces] = fzp[j];
1675  zoneID[nExtrudeFaces] = i;
1676  zoneFlipMap[nExtrudeFaces] = fz.flipMap()[j];
1677  nExtrudeFaces++;
1678 
1679  if (mesh.isInternalFace(fz[j]))
1680  {
1681  isInternal[i] = true;
1682  }
1683  }
1684  }
1685 
1686  // Shadow zone
1687  // ~~~~~~~~~~~
1688 
1689  if (zoneShadowNames.size())
1690  {
1691  zoneShadowIDs.setSize(zoneShadowNames.size());
1692  forAll(zoneShadowNames, i)
1693  {
1694  zoneShadowIDs[i] = faceZones.findZoneID(zoneShadowNames[i]);
1695  if (zoneShadowIDs[i] == -1)
1696  {
1698  << "Cannot find zone " << zoneShadowNames[i] << endl
1699  << "Valid zones are " << faceZones.names()
1700  << exit(FatalIOError);
1701  }
1702  }
1703 
1704  label nShadowFaces = 0;
1705  forAll(zoneShadowIDs, i)
1706  {
1707  nShadowFaces += faceZones[zoneShadowIDs[i]].size();
1708  }
1709 
1710  extrudeMeshShadowFaces.setSize(nShadowFaces);
1711  zoneShadowFlipMap.setSize(nShadowFaces);
1712  zoneShadowID.setSize(nShadowFaces);
1713 
1714  nShadowFaces = 0;
1715  forAll(zoneShadowIDs, i)
1716  {
1717  const faceZone& fz = faceZones[zoneShadowIDs[i]];
1718  forAll(fz, j)
1719  {
1720  extrudeMeshShadowFaces[nShadowFaces] = fz[j];
1721  zoneShadowFlipMap[nShadowFaces] = fz.flipMap()[j];
1722  zoneShadowID[nShadowFaces] = i;
1723  nShadowFaces++;
1724  }
1725  }
1726  }
1727  }
1728  else
1729  {
1730  meshZoneID.setSize(zoneNames.size(), -1);
1731  // Load faceSets
1732  PtrList<faceSet> zones(zoneNames.size());
1733  forAll(zoneNames, i)
1734  {
1735  Info<< "Loading faceSet " << zoneNames[i] << endl;
1736  zones.set(i, new faceSet(mesh, zoneNames[i]));
1737  }
1738 
1739 
1740  // Collect per face information
1741  label nExtrudeFaces = 0;
1742  forAll(zones, i)
1743  {
1744  nExtrudeFaces += zones[i].size();
1745  }
1746  extrudeMeshFaces.setSize(nExtrudeFaces);
1747  zoneFaces.setSize(nExtrudeFaces);
1748  zoneID.setSize(nExtrudeFaces);
1749  zoneFlipMap.setSize(nExtrudeFaces);
1750 
1751  nExtrudeFaces = 0;
1752  forAll(zones, i)
1753  {
1754  const faceSet& fz = zones[i];
1755  for (const label facei : fz)
1756  {
1757  if (mesh.isInternalFace(facei))
1758  {
1760  << "faceSet " << fz.name()
1761  << "contains internal faces."
1762  << " This is not permitted."
1763  << exit(FatalIOError);
1764  }
1765  extrudeMeshFaces[nExtrudeFaces] = facei;
1766  zoneFaces[nExtrudeFaces] = mesh.faces()[facei];
1767  zoneID[nExtrudeFaces] = i;
1768  zoneFlipMap[nExtrudeFaces] = false;
1769  nExtrudeFaces++;
1770 
1771  if (mesh.isInternalFace(facei))
1772  {
1773  isInternal[i] = true;
1774  }
1775  }
1776  }
1777 
1778 
1779  // Shadow zone
1780  // ~~~~~~~~~~~
1781 
1782  PtrList<faceSet> shadowZones(zoneShadowNames.size());
1783  if (zoneShadowNames.size())
1784  {
1785  zoneShadowIDs.setSize(zoneShadowNames.size(), -1);
1786  forAll(zoneShadowNames, i)
1787  {
1788  shadowZones.set(i, new faceSet(mesh, zoneShadowNames[i]));
1789  }
1790 
1791  label nShadowFaces = 0;
1792  for (const faceSet& fz : shadowZones)
1793  {
1794  nShadowFaces += fz.size();
1795  }
1796 
1797  if (nExtrudeFaces != nShadowFaces)
1798  {
1800  << "Extruded faces " << nExtrudeFaces << endl
1801  << "is different from shadow faces. " << nShadowFaces
1802  << "This is not permitted " << endl
1803  << exit(FatalIOError);
1804  }
1805 
1806  extrudeMeshShadowFaces.setSize(nShadowFaces);
1807  zoneShadowFlipMap.setSize(nShadowFaces);
1808  zoneShadowID.setSize(nShadowFaces);
1809 
1810  nShadowFaces = 0;
1811  forAll(shadowZones, i)
1812  {
1813  const faceSet& fz = shadowZones[i];
1814  for (const label facei : fz)
1815  {
1816  if (mesh.isInternalFace(facei))
1817  {
1819  << "faceSet " << fz.name()
1820  << "contains internal faces."
1821  << " This is not permitted."
1822  << exit(FatalIOError);
1823  }
1824  extrudeMeshShadowFaces[nShadowFaces] = facei;
1825  zoneShadowFlipMap[nShadowFaces] = false;
1826  zoneShadowID[nShadowFaces] = i;
1827  nShadowFaces++;
1828  }
1829  }
1830  }
1831  }
1832  const primitiveFacePatch extrudePatch(std::move(zoneFaces), mesh.points());
1833 
1834 
1836  Pstream::listCombineScatter(isInternal);
1837 
1838  // Check zone either all internal or all external faces
1839  checkZoneInside(mesh, zoneNames, zoneID, extrudeMeshFaces, isInternal);
1840 
1841 
1842  const pointField& extrudePoints = extrudePatch.localPoints();
1843  const faceList& extrudeFaces = extrudePatch.localFaces();
1844  const labelListList& edgeFaces = extrudePatch.edgeFaces();
1845 
1846 
1847  Info<< "extrudePatch :"
1848  << " faces:" << extrudePatch.size()
1849  << " points:" << extrudePatch.nPoints()
1850  << " edges:" << extrudePatch.nEdges()
1851  << nl
1852  << endl;
1853 
1854 
1855  // Determine per-extrude-edge info
1856  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1857 
1858  // Corresponding mesh edges
1859  const labelList extrudeMeshEdges
1860  (
1861  extrudePatch.meshEdges
1862  (
1863  mesh.edges(),
1864  mesh.pointEdges()
1865  )
1866  );
1867 
1868  const globalIndex globalExtrudeFaces(extrudePatch.size());
1869 
1870  // Global pp faces per pp edge.
1871  labelListList extrudeEdgeGlobalFaces
1872  (
1873  globalEdgeFaces
1874  (
1875  mesh,
1876  globalExtrudeFaces,
1877  extrudePatch,
1878  extrudeMeshEdges
1879  )
1880  );
1881  List<Map<label>> compactMap;
1882  const mapDistribute extrudeEdgeFacesMap
1883  (
1884  globalExtrudeFaces,
1885  extrudeEdgeGlobalFaces,
1886  compactMap
1887  );
1888 
1889 
1890  // Determine min and max zone per edge
1891  labelList edgeMinZoneID;
1892  labelList edgeMaxZoneID;
1893  calcEdgeMinMaxZone
1894  (
1895  mesh,
1896  extrudePatch,
1897  extrudeMeshEdges,
1898  zoneID,
1899  extrudeEdgeFacesMap,
1900  extrudeEdgeGlobalFaces,
1901 
1902  edgeMinZoneID,
1903  edgeMaxZoneID
1904  );
1905 
1906 
1907 
1908 
1909  DynamicList<polyPatch*> regionPatches(patches.size());
1910  // Copy all non-local patches since these are used on boundary edges of
1911  // the extrusion
1912  forAll(patches, patchi)
1913  {
1914  if (!isA<processorPolyPatch>(patches[patchi]))
1915  {
1916  label newPatchi = regionPatches.size();
1917  regionPatches.append
1918  (
1919  patches[patchi].clone
1920  (
1921  patches,
1922  newPatchi,
1923  0, // size
1924  0 // start
1925  ).ptr()
1926  );
1927  }
1928  }
1929 
1930 
1931  // Add interface patches
1932  // ~~~~~~~~~~~~~~~~~~~~~
1933 
1934  // From zone to interface patch (region side)
1935  labelList interRegionTopPatch;
1936  labelList interRegionBottomPatch;
1937 
1938  addCouplingPatches
1939  (
1940  mesh,
1941  regionName,
1942  shellRegionName,
1943  zoneNames,
1944  zoneShadowNames,
1945  isInternal,
1946  meshZoneID,
1947 
1948  regionPatches,
1949  interRegionTopPatch,
1950  interRegionBottomPatch
1951  );
1952 
1953 
1954  // From zone to interface patch (mesh side)
1955  labelList interMeshTopPatch;
1956  labelList interMeshBottomPatch;
1957 
1958  if (adaptMesh)
1959  {
1960  // Add coupling patches to mesh
1961 
1962  // 1. Clone existing global patches
1963  DynamicList<polyPatch*> newPatches(patches.size());
1964  forAll(patches, patchi)
1965  {
1966  if (!isA<processorPolyPatch>(patches[patchi]))
1967  {
1968  autoPtr<polyPatch> clonedPatch(patches[patchi].clone(patches));
1969  clonedPatch->index() = newPatches.size();
1970  newPatches.append(clonedPatch.ptr());
1971  }
1972  }
1973 
1974  // 2. Add new patches
1975  addCouplingPatches
1976  (
1977  mesh,
1978  regionName,
1979  shellRegionName,
1980  zoneNames,
1981  zoneShadowNames,
1982  isInternal,
1983  meshZoneID,
1984 
1985  newPatches,
1986  interMeshTopPatch,
1987  interMeshBottomPatch
1988  );
1989 
1990  // 3. Clone processor patches
1991  forAll(patches, patchi)
1992  {
1993  if (isA<processorPolyPatch>(patches[patchi]))
1994  {
1995  autoPtr<polyPatch> clonedPatch(patches[patchi].clone(patches));
1996  clonedPatch->index() = newPatches.size();
1997  newPatches.append(clonedPatch.ptr());
1998  }
1999  }
2000 
2001 
2002  #ifdef FULLDEBUG
2003  Pout<< "*** adaptMesh : addFvPAtches:" << nl;
2004  printPatches(Pout, newPatches);
2005  Pout<< "*** end of adaptMesh : addFvPAtches:" << endl;
2006  #endif
2007 
2008 
2009  // Add to mesh
2010  mesh.clearOut();
2012  mesh.addFvPatches(newPatches, true);
2013 
2015  }
2016 
2017 
2018  // Patch per extruded face
2019  labelList extrudeTopPatchID(extrudePatch.size());
2020  labelList extrudeBottomPatchID(extrudePatch.size());
2021 
2022  forAll(zoneID, facei)
2023  {
2024  extrudeTopPatchID[facei] = interRegionTopPatch[zoneID[facei]];
2025  extrudeBottomPatchID[facei] = interRegionBottomPatch[zoneID[facei]];
2026  }
2027 
2028 
2029 
2030  // Count how many patches on special edges of extrudePatch are necessary
2031  // - zoneXXX_sides
2032  // - zoneXXX_zoneYYY
2033  labelList zoneSidePatch(zoneNames.size(), Zero);
2034  // Patch to use for minZone
2035  labelList zoneZonePatch_min(zoneNames.size()*zoneNames.size(), Zero);
2036  // Patch to use for maxZone
2037  labelList zoneZonePatch_max(zoneNames.size()*zoneNames.size(), Zero);
2038 
2039  countExtrudePatches
2040  (
2041  mesh,
2042  zoneNames.size(),
2043 
2044  extrudePatch, // patch
2045  extrudeMeshFaces, // mesh face per patch face
2046  extrudeMeshEdges, // mesh edge per patch edge
2047 
2048  extrudeEdgeGlobalFaces, // global indexing per patch edge
2049  edgeMinZoneID, // minZone per patch edge
2050  edgeMaxZoneID, // maxZone per patch edge
2051 
2052  zoneSidePatch, // per zone-side num edges that extrude into it
2053  zoneZonePatch_min // per zone-zone num edges that extrude into it
2054  );
2055 
2056  // Now we'll have:
2057  // zoneSidePatch[zoneA] : number of faces needed on the side of zoneA
2058  // zoneZonePatch_min[zoneA,zoneB] : number of faces needed inbetween A,B
2059 
2060 
2061  // Add the zone-side patches.
2062  addZoneSidePatches
2063  (
2064  mesh,
2065  zoneNames,
2066  (oneD ? oneDPatchType : word::null),
2067 
2068  regionPatches,
2069  zoneSidePatch
2070  );
2071 
2072 
2073  // Add the patches inbetween zones
2074  addInterZonePatches
2075  (
2076  mesh,
2077  zoneNames,
2078  oneD,
2079 
2080  zoneZonePatch_min,
2081  zoneZonePatch_max,
2082  regionPatches
2083  );
2084 
2085 
2086  // Sets sidePatchID[edgeI] to interprocessor patch. Adds any
2087  // interprocessor or cyclic patches if necessary.
2088  labelList sidePatchID;
2089  addCoupledPatches
2090  (
2091  mesh,
2092  extrudePatch,
2093  extrudeMeshFaces,
2094  extrudeMeshEdges,
2095  extrudeEdgeFacesMap,
2096  extrudeEdgeGlobalFaces,
2097 
2098  sidePatchID,
2099  regionPatches
2100  );
2101 
2102 
2103 // // Add all the newPatches to the mesh and fields
2104 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2105 // {
2106 // forAll(newPatches, patchi)
2107 // {
2108 // Pout<< "Adding patch " << patchi
2109 // << " name:" << newPatches[patchi]->name()
2110 // << endl;
2111 // }
2112 // //label nOldPatches = mesh.boundary().size();
2113 // mesh.clearOut();
2114 // mesh.removeFvBoundary();
2115 // mesh.addFvPatches(newPatches, true);
2116 // //// Add calculated fvPatchFields for the added patches
2117 // //for
2118 // //(
2119 // // label patchi = nOldPatches;
2120 // // patchi < mesh.boundary().size();
2121 // // patchi++
2122 // //)
2123 // //{
2124 // // Pout<< "ADDing calculated to patch " << patchi
2125 // // << endl;
2126 // // addCalculatedPatchFields(mesh);
2127 // //}
2128 // //Pout<< "** Added " << mesh.boundary().size()-nOldPatches
2129 // // << " patches." << endl;
2130 // }
2131 
2132 
2133  // Set patches to use for edges to be extruded into boundary faces
2134  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2135  // In order of edgeFaces: per edge, per originating face the
2136  // patch to use for the side face (from the extruded edge).
2137  // If empty size create an internal face.
2138  labelListList extrudeEdgePatches(extrudePatch.nEdges());
2139 
2140  // Is edge a non-manifold edge
2141  bitSet nonManifoldEdge(extrudePatch.nEdges());
2142 
2143  // Note: logic has to be same as in countExtrudePatches.
2144  forAll(edgeFaces, edgeI)
2145  {
2146  const labelList& eFaces = edgeFaces[edgeI];
2147 
2148  labelList& ePatches = extrudeEdgePatches[edgeI];
2149 
2150  if (oneD)
2151  {
2152  ePatches.setSize(eFaces.size());
2153  forAll(eFaces, i)
2154  {
2155  ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]];
2156  }
2157 
2158  if (oneDNonManifoldEdges)
2159  {
2160  //- Set nonManifoldEdge[edgeI] for non-manifold edges only
2161  // The other option is to have non-manifold edges everywhere
2162  // and generate space overlapping columns of cells.
2163  if (eFaces.size() != 2)
2164  {
2165  nonManifoldEdge.set(edgeI);
2166  }
2167  }
2168  else
2169  {
2170  nonManifoldEdge.set(edgeI);
2171  }
2172  }
2173  else if (eFaces.size() == 2)
2174  {
2175  label zone0 = zoneID[eFaces[0]];
2176  label zone1 = zoneID[eFaces[1]];
2177 
2178  if (zone0 != zone1) // || (cos(angle) > blabla))
2179  {
2180  label minZone = min(zone0,zone1);
2181  label maxZone = max(zone0,zone1);
2182  label index = minZone*zoneNames.size()+maxZone;
2183 
2184  ePatches.setSize(eFaces.size());
2185 
2186  if (zone0 == minZone)
2187  {
2188  ePatches[0] = zoneZonePatch_min[index];
2189  ePatches[1] = zoneZonePatch_max[index];
2190  }
2191  else
2192  {
2193  ePatches[0] = zoneZonePatch_max[index];
2194  ePatches[1] = zoneZonePatch_min[index];
2195  }
2196 
2197  nonManifoldEdge.set(edgeI);
2198  }
2199  }
2200  else if (sidePatchID[edgeI] != -1)
2201  {
2202  // Coupled extrusion
2203  ePatches.setSize(eFaces.size());
2204  forAll(eFaces, i)
2205  {
2206  ePatches[i] = sidePatchID[edgeI];
2207  }
2208  }
2209  else
2210  {
2211  label facei = findUncoveredPatchFace
2212  (
2213  mesh,
2214  labelUIndList(extrudeMeshFaces, eFaces),
2215  extrudeMeshEdges[edgeI]
2216  );
2217 
2218  if (facei != -1)
2219  {
2220  label newPatchi = findPatchID
2221  (
2222  regionPatches,
2223  patches[patches.whichPatch(facei)].name()
2224  );
2225  ePatches.setSize(eFaces.size(), newPatchi);
2226  }
2227  else
2228  {
2229  ePatches.setSize(eFaces.size());
2230  forAll(eFaces, i)
2231  {
2232  ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]];
2233  }
2234  }
2235  nonManifoldEdge.set(edgeI);
2236  }
2237  }
2238 
2239 
2240 
2241  // Assign point regions
2242  // ~~~~~~~~~~~~~~~~~~~~
2243 
2244  // Per face, per point the region number.
2245  faceList pointGlobalRegions;
2246  faceList pointLocalRegions;
2247  labelList localToGlobalRegion;
2248 
2250  (
2251  mesh.globalData(),
2252  extrudePatch,
2253  nonManifoldEdge,
2254  false, // keep cyclic separated regions apart
2255 
2256  pointGlobalRegions,
2257  pointLocalRegions,
2258  localToGlobalRegion
2259  );
2260 
2261  // Per local region an originating point
2262  labelList localRegionPoints(localToGlobalRegion.size());
2263  forAll(pointLocalRegions, facei)
2264  {
2265  const face& f = extrudePatch.localFaces()[facei];
2266  const face& pRegions = pointLocalRegions[facei];
2267  forAll(pRegions, fp)
2268  {
2269  localRegionPoints[pRegions[fp]] = f[fp];
2270  }
2271  }
2272 
2273  // Calculate region normals by reducing local region normals
2274  pointField localRegionNormals(localToGlobalRegion.size());
2275  {
2276  pointField localSum(localToGlobalRegion.size(), Zero);
2277 
2278  forAll(pointLocalRegions, facei)
2279  {
2280  const face& pRegions = pointLocalRegions[facei];
2281  forAll(pRegions, fp)
2282  {
2283  label localRegionI = pRegions[fp];
2284  localSum[localRegionI] += extrudePatch.faceNormals()[facei];
2285  }
2286  }
2287 
2288  Map<point> globalSum(2*localToGlobalRegion.size());
2289 
2290  forAll(localSum, localRegionI)
2291  {
2292  label globalRegionI = localToGlobalRegion[localRegionI];
2293  globalSum.insert(globalRegionI, localSum[localRegionI]);
2294  }
2295 
2296  // Reduce
2298  Pstream::mapCombineScatter(globalSum);
2299 
2300  forAll(localToGlobalRegion, localRegionI)
2301  {
2302  label globalRegionI = localToGlobalRegion[localRegionI];
2303  localRegionNormals[localRegionI] = globalSum[globalRegionI];
2304  }
2305  localRegionNormals /= mag(localRegionNormals);
2306  }
2307 
2308 
2309  // For debugging: dump hedgehog plot of normals
2310  if (false)
2311  {
2312  OFstream str(runTime.path()/"localRegionNormals.obj");
2313  label vertI = 0;
2314 
2315  scalar thickness = model().sumThickness(1);
2316 
2317  forAll(pointLocalRegions, facei)
2318  {
2319  const face& f = extrudeFaces[facei];
2320 
2321  forAll(f, fp)
2322  {
2323  label region = pointLocalRegions[facei][fp];
2324  const point& pt = extrudePoints[f[fp]];
2325 
2326  meshTools::writeOBJ(str, pt);
2327  vertI++;
2329  (
2330  str,
2331  pt+thickness*localRegionNormals[region]
2332  );
2333  vertI++;
2334  str << "l " << vertI-1 << ' ' << vertI << nl;
2335  }
2336  }
2337  }
2338 
2339 
2340  // Use model to create displacements of first layer
2341  vectorField firstDisp(localRegionNormals.size());
2342  forAll(firstDisp, regionI)
2343  {
2344  //const point& regionPt = regionCentres[regionI];
2345  const point& regionPt = extrudePatch.points()
2346  [
2347  extrudePatch.meshPoints()
2348  [
2349  localRegionPoints[regionI]
2350  ]
2351  ];
2352  const vector& n = localRegionNormals[regionI];
2353  firstDisp[regionI] = model()(regionPt, n, 1) - regionPt;
2354  }
2355 
2356 
2357  // Create a new mesh
2358  // ~~~~~~~~~~~~~~~~~
2359 
2360  createShellMesh extruder
2361  (
2362  extrudePatch,
2363  pointLocalRegions,
2364  localRegionPoints
2365  );
2366 
2367 
2368  autoPtr<mapPolyMesh> shellMap;
2369  fvMesh regionMesh
2370  (
2371  IOobject
2372  (
2373  shellRegionName,
2374  meshInstance,
2375  runTime,
2378  false
2379  ),
2380  Zero,
2381  false
2382  );
2383 
2384  // Add the new patches
2385  forAll(regionPatches, patchi)
2386  {
2387  polyPatch* ppPtr = regionPatches[patchi];
2388  regionPatches[patchi] = ppPtr->clone(regionMesh.boundaryMesh()).ptr();
2389  delete ppPtr;
2390  }
2391 
2392  #ifdef FULLDEBUG
2393  Pout<< "*** regionPatches : regionPatches:" << nl;
2394  printPatches(Pout, regionPatches);
2395  Pout<< "*** end of regionPatches : regionPatches:" << endl;
2396  #endif
2397 
2398 
2399  regionMesh.clearOut();
2400  regionMesh.removeFvBoundary();
2401  regionMesh.addFvPatches(regionPatches, true);
2402 
2403  {
2404  polyTopoChange meshMod(regionPatches.size());
2405 
2406  extruder.setRefinement
2407  (
2408  firstDisp, // first displacement
2409  model().expansionRatio(),
2410  model().nLayers(), // nLayers
2411  extrudeTopPatchID,
2412  extrudeBottomPatchID,
2413  extrudeEdgePatches,
2414  meshMod
2415  );
2416 
2417  // Enforce actual point positions according to extrudeModel (model)
2418  // (extruder.setRefinement only does fixed expansionRatio)
2419  // The regionPoints and nLayers are looped in the same way as in
2420  // createShellMesh
2421  DynamicList<point>& newPoints = const_cast<DynamicList<point>&>
2422  (
2423  meshMod.points()
2424  );
2425  label meshPointi = extrudePatch.localPoints().size();
2426  forAll(localRegionPoints, regionI)
2427  {
2428  label pointi = localRegionPoints[regionI];
2429  point pt = extrudePatch.localPoints()[pointi];
2430  const vector& n = localRegionNormals[regionI];
2431 
2432  for (label layerI = 1; layerI <= model().nLayers(); layerI++)
2433  {
2434  newPoints[meshPointi++] = model()(pt, n, layerI);
2435  }
2436  }
2437 
2438  shellMap = meshMod.changeMesh
2439  (
2440  regionMesh, // mesh to change
2441  false // inflate
2442  );
2443  }
2444 
2445  // Necessary?
2446  regionMesh.setInstance(meshInstance);
2447 
2448 
2449  // Update numbering on extruder.
2450  extruder.updateMesh(shellMap());
2451 
2452 
2453  // Calculate offsets from shell mesh back to original mesh
2454  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2455 
2456  List<pointField> topOffsets(zoneNames.size());
2457  List<pointField> bottomOffsets(zoneNames.size());
2458 
2459  forAll(regionMesh.boundaryMesh(), patchi)
2460  {
2461  const polyPatch& pp = regionMesh.boundaryMesh()[patchi];
2462 
2463  if (isA<mappedWallPolyPatch>(pp))
2464  {
2465  if (interRegionTopPatch.found(patchi))
2466  {
2467  label zoneI = interRegionTopPatch.find(patchi);
2468  topOffsets[zoneI] = calcOffset(extrudePatch, extruder, pp);
2469  }
2470  else if (interRegionBottomPatch.found(patchi))
2471  {
2472  label zoneI = interRegionBottomPatch.find(patchi);
2473  bottomOffsets[zoneI] = calcOffset(extrudePatch, extruder, pp);
2474  }
2475  }
2476  }
2477 
2478 
2479  // Change top and bottom boundary conditions on regionMesh
2480  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2481 
2482  {
2483  // Correct top patches for offset
2484  setCouplingInfo
2485  (
2486  regionMesh,
2487  interRegionTopPatch,
2488  regionName, // name of main mesh
2489  sampleMode, // sampleMode
2490  topOffsets
2491  );
2492 
2493  // Correct bottom patches for offset
2494  setCouplingInfo
2495  (
2496  regionMesh,
2497  interRegionBottomPatch,
2498  regionName,
2499  sampleMode, // sampleMode
2500  bottomOffsets
2501  );
2502 
2503  // Remove any unused patches
2504  deleteEmptyPatches(regionMesh);
2505  }
2506 
2507  // Change top and bottom boundary conditions on main mesh
2508  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2509 
2510  if (adaptMesh)
2511  {
2512  // Correct top patches for offset
2513  setCouplingInfo
2514  (
2515  mesh,
2516  interMeshTopPatch,
2517  shellRegionName, // name of shell mesh
2518  sampleMode, // sampleMode
2519  -topOffsets
2520  );
2521 
2522  // Correct bottom patches for offset
2523  setCouplingInfo
2524  (
2525  mesh,
2526  interMeshBottomPatch,
2527  shellRegionName,
2528  sampleMode,
2529  -bottomOffsets
2530  );
2531  }
2532 
2533 
2534 
2535  // Write addressing from region mesh back to originating patch
2536  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2537 
2538  labelIOList cellToPatchFaceAddressing
2539  (
2540  IOobject
2541  (
2542  "cellToPatchFaceAddressing",
2543  regionMesh.facesInstance(),
2544  regionMesh.meshSubDir,
2545  regionMesh,
2548  false
2549  ),
2550  extruder.cellToFaceMap()
2551  );
2552  cellToPatchFaceAddressing.note() = "cell to patch face addressing";
2553 
2554  labelIOList faceToPatchFaceAddressing
2555  (
2556  IOobject
2557  (
2558  "faceToPatchFaceAddressing",
2559  regionMesh.facesInstance(),
2560  regionMesh.meshSubDir,
2561  regionMesh,
2564  false
2565  ),
2566  extruder.faceToFaceMap()
2567  );
2568  faceToPatchFaceAddressing.note() =
2569  "front/back face + turning index to patch face addressing";
2570 
2571  labelIOList faceToPatchEdgeAddressing
2572  (
2573  IOobject
2574  (
2575  "faceToPatchEdgeAddressing",
2576  regionMesh.facesInstance(),
2577  regionMesh.meshSubDir,
2578  regionMesh,
2581  false
2582  ),
2583  extruder.faceToEdgeMap()
2584  );
2585  faceToPatchEdgeAddressing.note() =
2586  "side face to patch edge addressing";
2587 
2588  labelIOList pointToPatchPointAddressing
2589  (
2590  IOobject
2591  (
2592  "pointToPatchPointAddressing",
2593  regionMesh.facesInstance(),
2594  regionMesh.meshSubDir,
2595  regionMesh,
2598  false
2599  ),
2600  extruder.pointToPointMap()
2601  );
2602  pointToPatchPointAddressing.note() =
2603  "point to patch point addressing";
2604 
2605 
2606  Info<< "Writing mesh " << regionMesh.name()
2607  << " to " << regionMesh.facesInstance() << nl
2608  << endl;
2609 
2610  bool ok =
2611  regionMesh.write()
2612  && cellToPatchFaceAddressing.write()
2613  && faceToPatchFaceAddressing.write()
2614  && faceToPatchEdgeAddressing.write()
2615  && pointToPatchPointAddressing.write();
2616 
2617  if (!ok)
2618  {
2620  << "Failed writing mesh " << regionMesh.name()
2621  << " at location " << regionMesh.facesInstance()
2622  << exit(FatalError);
2623  }
2624  topoSet::removeFiles(regionMesh);
2625  processorMeshes::removeFiles(regionMesh);
2626 
2627 
2628  // See if we need to extrude coordinates as well
2629  {
2630  autoPtr<pointIOField> patchFaceCentresPtr;
2631 
2632  IOobject io
2633  (
2634  "patchFaceCentres",
2635  mesh.pointsInstance(),
2636  mesh.meshSubDir,
2637  mesh,
2639  );
2640  if (io.typeHeaderOk<pointIOField>(true))
2641  {
2642  // Read patchFaceCentres and patchEdgeCentres
2643  Info<< "Reading patch face,edge centres : "
2644  << io.name() << " and patchEdgeCentres" << endl;
2645 
2646  extrudeGeometricProperties
2647  (
2648  mesh,
2649  extrudePatch,
2650  extruder,
2651  regionMesh,
2652  model()
2653  );
2654  }
2655  }
2656 
2657 
2658 
2659 
2660  // Insert baffles into original mesh
2661  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2662 
2663  autoPtr<mapPolyMesh> addBafflesMap;
2664 
2665  if (adaptMesh)
2666  {
2667  polyTopoChange meshMod(mesh);
2668 
2669  // Modify faces to be in bottom (= always coupled) patch
2670  forAll(extrudeMeshFaces, zoneFacei)
2671  {
2672  label meshFacei = extrudeMeshFaces[zoneFacei];
2673  label zoneI = zoneID[zoneFacei];
2674  bool flip = zoneFlipMap[zoneFacei];
2675  const face& f = mesh.faces()[meshFacei];
2676 
2677  if (!flip)
2678  {
2679  meshMod.modifyFace
2680  (
2681  f, // modified face
2682  meshFacei, // label of face being modified
2683  mesh.faceOwner()[meshFacei],// owner
2684  -1, // neighbour
2685  false, // face flip
2686  interMeshBottomPatch[zoneI],// patch for face
2687  meshZoneID[zoneI], // zone for face
2688  flip // face flip in zone
2689  );
2690  }
2691  else if (mesh.isInternalFace(meshFacei))
2692  {
2693  meshMod.modifyFace
2694  (
2695  f.reverseFace(), // modified face
2696  meshFacei, // label of modified face
2697  mesh.faceNeighbour()[meshFacei],// owner
2698  -1, // neighbour
2699  true, // face flip
2700  interMeshBottomPatch[zoneI], // patch for face
2701  meshZoneID[zoneI], // zone for face
2702  !flip // face flip in zone
2703  );
2704  }
2705  }
2706 
2707  if (zoneShadowNames.size() > 0) //if there is a top faceZone specified
2708  {
2709  forAll(extrudeMeshFaces, zoneFacei)
2710  {
2711  label meshFacei = extrudeMeshShadowFaces[zoneFacei];
2712  label zoneI = zoneShadowID[zoneFacei];
2713  bool flip = zoneShadowFlipMap[zoneFacei];
2714  const face& f = mesh.faces()[meshFacei];
2715 
2716  if (!flip)
2717  {
2718  meshMod.modifyFace
2719  (
2720  f, // modified face
2721  meshFacei, // face being modified
2722  mesh.faceOwner()[meshFacei],// owner
2723  -1, // neighbour
2724  false, // face flip
2725  interMeshTopPatch[zoneI], // patch for face
2726  meshZoneID[zoneI], // zone for face
2727  flip // face flip in zone
2728  );
2729  }
2730  else if (mesh.isInternalFace(meshFacei))
2731  {
2732  meshMod.modifyFace
2733  (
2734  f.reverseFace(), // modified face
2735  meshFacei, // label modified face
2736  mesh.faceNeighbour()[meshFacei],// owner
2737  -1, // neighbour
2738  true, // face flip
2739  interMeshTopPatch[zoneI], // patch for face
2740  meshZoneID[zoneI], // zone for face
2741  !flip // face flip in zone
2742  );
2743  }
2744  }
2745  }
2746  else
2747  {
2748  // Add faces (using same points) to be in top patch
2749  forAll(extrudeMeshFaces, zoneFacei)
2750  {
2751  label meshFacei = extrudeMeshFaces[zoneFacei];
2752  label zoneI = zoneID[zoneFacei];
2753  bool flip = zoneFlipMap[zoneFacei];
2754  const face& f = mesh.faces()[meshFacei];
2755 
2756  if (!flip)
2757  {
2758  if (mesh.isInternalFace(meshFacei))
2759  {
2760  meshMod.addFace
2761  (
2762  f.reverseFace(), // modified face
2763  mesh.faceNeighbour()[meshFacei],// owner
2764  -1, // neighbour
2765  -1, // master point
2766  -1, // master edge
2767  meshFacei, // master face
2768  true, // flip flux
2769  interMeshTopPatch[zoneI], // patch for face
2770  -1, // zone for face
2771  false //face flip in zone
2772  );
2773  }
2774  }
2775  else
2776  {
2777  meshMod.addFace
2778  (
2779  f, // face
2780  mesh.faceOwner()[meshFacei], // owner
2781  -1, // neighbour
2782  -1, // master point
2783  -1, // master edge
2784  meshFacei, // master face
2785  false, // flip flux
2786  interMeshTopPatch[zoneI], // patch for face
2787  -1, // zone for face
2788  false // zone flip
2789  );
2790  }
2791  }
2792  }
2793 
2794  // Change the mesh. Change points directly (no inflation).
2795  addBafflesMap = meshMod.changeMesh(mesh, false);
2796 
2797  // Update fields
2798  mesh.updateMesh(addBafflesMap());
2799 
2800 
2801 //XXXXXX
2802 // Update maps! e.g. faceToPatchFaceAddressing
2803 //XXXXXX
2804 
2805  // Move mesh (since morphing might not do this)
2806  if (addBafflesMap().hasMotionPoints())
2807  {
2808  mesh.movePoints(addBafflesMap().preMotionPoints());
2809  }
2810 
2811  mesh.setInstance(meshInstance);
2812 
2813  // Remove any unused patches
2814  deleteEmptyPatches(mesh);
2815 
2816  Info<< "Writing mesh " << mesh.name()
2817  << " to " << mesh.facesInstance() << nl
2818  << endl;
2819 
2820  if (!mesh.write())
2821  {
2823  << "Failed writing mesh " << mesh.name()
2824  << " at location " << mesh.facesInstance()
2825  << exit(FatalError);
2826  }
2829  }
2830 
2831  Info << "End\n" << endl;
2832 
2833  return 0;
2834 }
2835 
2836 
2837 // ************************************************************************* //
Foam::Pstream::mapCombineGather
static void mapCombineGather(const List< commsStruct > &comms, Container &Values, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:551
Foam::createShellMesh::faceToEdgeMap
const labelList & faceToEdgeMap() const
From region side-face to patch edge. -1 for non-edge faces.
Definition: createShellMesh.H:147
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
volFields.H
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:54
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1038
Foam::createShellMesh::pointToPointMap
const labelList & pointToPointMap() const
From region point to patch point.
Definition: createShellMesh.H:153
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
meshTools.H
Foam::extrudeModel::sumThickness
scalar sumThickness(const label layer) const
Helper: calculate cumulative relative thickness for layer.
Definition: extrudeModel.C:71
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:129
mappedWallPolyPatch.H
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobjectI.H:70
Foam::PrimitivePatch::edgeFaces
const labelListList & edgeFaces() const
Return edge-face addressing.
Definition: PrimitivePatch.C:242
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: foamVtkLagrangianWriter.H:61
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:895
Foam::fvMeshTools::createDummyFvMeshFiles
static void createDummyFvMeshFiles(const objectRegistry &parent, const word &regionName, const bool verbose=false)
Create additional fv* files.
Definition: fvMeshTools.C:674
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::OBJstream
OFstream that keeps track of vertices.
Definition: OBJstream.H:58
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::PrimitivePatch::edges
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Definition: PrimitivePatch.C:190
Foam::extrudeModel
Top level extrusion model class.
Definition: extrudeModel.H:76
cyclicPolyPatch.H
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero (0)
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:55
Foam::dictionary::found
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionary.C:364
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
wedgePolyPatch.H
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:215
addOverwriteOption.H
Foam::primitiveMesh::edgeFaces
const labelListList & edgeFaces() const
Definition: primitiveMeshEdgeFaces.C:33
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
globalIndex.H
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:427
Foam::PrimitivePatch::nEdges
label nEdges() const
Return number of edges in patch.
Definition: PrimitivePatch.H:322
Foam::objectRegistry::time
const Time & time() const
Return time.
Definition: objectRegistry.H:186
Foam::polyMesh::meshSubDir
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:315
polyTopoChange.H
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:785
Foam::PrimitivePatch::meshEdges
labelList meshEdges(const edgeList &allEdges, const labelListList &cellEdges, const labelList &faceCells) const
Definition: PrimitivePatchMeshEdges.C:37
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:99
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:413
dictName
const word dictName("blockMeshDict")
Foam::coupledPolyPatch::transformTypeNames
static const Enum< transformType > transformTypeNames
Definition: coupledPolyPatch.H:69
Foam::polyMesh::facesInstance
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:821
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: lumpedPointController.H:69
Foam::faceSet
A list of face labels.
Definition: faceSet.H:51
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::orEqOp
Definition: ops.H:86
Foam::fvMesh::removeFvBoundary
void removeFvBoundary()
Remove boundary patches. Warning: fvPatchFields hold ref to.
Definition: fvMesh.C:506
Foam::FatalIOError
IOerror FatalIOError
Foam::fvMesh::movePoints
virtual tmp< scalarField > movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: fvMesh.C:727
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::polyMesh::clearOut
void clearOut()
Clear all geometry and addressing unnecessary for CFD.
Definition: polyMeshClear.C:222
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
surfaceFields.H
Foam::surfaceFields.
Foam::createShellMesh::faceToFaceMap
const labelList & faceToFaceMap() const
From region face to patch face. Contains turning index:
Definition: createShellMesh.H:141
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:505
Foam::dictionary::set
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:847
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshEdges.C:516
Foam::Enum::get
EnumType get(const word &enumName) const
The enumeration corresponding to the given name.
Definition: Enum.C:86
Foam::HashSet< label, Hash< label > >
processorMeshes.H
syncTools.H
Foam::extrudeModel::nLayers
label nLayers() const
Return the number of layers.
Definition: extrudeModel.C:59
setSystemMeshDictionaryIO.H
zoneIDs
const labelIOList & zoneIDs
Definition: correctPhi.H:59
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::polyBoundaryMesh::names
wordList names() const
Return a list of patch names.
Definition: polyBoundaryMesh.C:593
Foam::mappedPatchBase::sampleModeNames_
static const Enum< sampleMode > sampleModeNames_
Definition: mappedPatchBase.H:131
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::minEqOp
Definition: ops.H:81
OFstream.H
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:477
Foam::SubField
SubField is a Field obtained as a section of another Field.
Definition: Field.H:64
Foam::mode
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: MSwindows.C:564
Foam::createShellMesh::updateMesh
void updateMesh(const mapPolyMesh &)
Update any locally stored mesh information.
Definition: createShellMesh.C:909
Foam::polyMesh::pointsInstance
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:815
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
Check whether all procs have all patches and in same order. Return.
Definition: polyBoundaryMesh.C:950
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::Field< vector >
Foam::regIOobject::write
virtual bool write(const bool valid=true) const
Write using setting from DB.
Definition: regIOobjectWrite.C:165
Foam::coupledPolyPatch::NOORDERING
Definition: coupledPolyPatch.H:66
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:65
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:67
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
extrudeModel.H
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
argList.H
Foam::syncTools::syncEdgeList
static void syncEdgeList(const polyMesh &mesh, List< T > &edgeValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh edges.
Definition: syncToolsTemplates.C:826
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1076
faceSet.H
addRegionOption.H
Foam::fvMesh::updateMesh
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
Definition: fvMesh.C:807
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:314
Foam::extrudeModel::New
static autoPtr< extrudeModel > New(const dictionary &dict)
Select null constructed.
Definition: extrudeModelNew.C:34
Foam::andOp
Definition: ops.H:233
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
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:62
Foam::fvMeshTools::reorderPatches
static void reorderPatches(fvMesh &, const labelList &oldToNew, const label nPatches, const bool validBoundary)
Reorder and remove trailing patches. If validBoundary call is parallel.
Definition: fvMeshTools.C:329
Foam::polyBoundaryMesh::findPatchID
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
Definition: polyBoundaryMesh.C:766
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::mapDistribute::distribute
void distribute(List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Distribute data using default commsType.
Definition: mapDistributeTemplates.C:152
Foam::PatchTools::matchEdges
static void matchEdges(const PrimitivePatch< FaceList1, PointField1 > &p1, const PrimitivePatch< FaceList2, PointField2 > &p2, labelList &p1EdgeLabels, labelList &p2EdgeLabels, bitSet &sameOrientation)
Find corresponding edges on patches sharing the same points.
Definition: PatchToolsMatch.C:76
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::PrimitivePatch::nPoints
label nPoints() const
Return number of points supporting patch faces.
Definition: PrimitivePatch.H:316
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:121
Foam::fvMesh::addFvPatches
void addFvPatches(PtrList< polyPatch > &plist, const bool validBoundary=true)
Add boundary patches. Constructor helper.
Definition: fvMesh.C:476
Foam::PtrList::clone
PtrList< T > clone(Args &&... args) const
Make a copy by cloning each of the list elements.
createNamedMesh.H
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)
Return a pointer to a new patch created on freestore from.
Definition: polyPatchNew.C:35
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)
Play commands into polyTopoChange to create layer mesh.
Definition: createShellMesh.C:449
Foam::PrimitivePatch::points
const Field< point_type > & points() const
Return reference to global points.
Definition: PrimitivePatch.H:305
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::PrimitivePatch::localFaces
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatch.C:297
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
dictIO
IOobject dictIO
Definition: setConstantMeshDictionaryIO.H:1
Foam::createShellMesh::cellToFaceMap
const labelList & cellToFaceMap() const
From region cell to patch face. Consecutively added so.
Definition: createShellMesh.H:130
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::ZoneMesh::findZoneID
label findZoneID(const word &zoneName) const
Find zone index given a name, return -1 if not found.
Definition: ZoneMesh.C:484
Foam::ListOps::uniqueEqOp
List helper to append y unique elements onto the end of x.
Definition: ListOps.H:577
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
Foam::maxEqOp
Definition: ops.H:80
Foam::mappedWallPolyPatch
Determines a mapping between patch face centres and mesh cell or face centres and processors they're ...
Definition: mappedWallPolyPatch.H:59
Foam::ZoneMesh::names
wordList names() const
A list of the zone names.
Definition: ZoneMesh.C:340
Foam::polyPatch::clone
virtual autoPtr< polyPatch > clone(const polyBoundaryMesh &bm) const
Construct and return a clone, resetting the boundary mesh.
Definition: polyPatch.H:232
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::PrimitivePatch::localPoints
const Field< point_type > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatch.C:339
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:87
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:445
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:439
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:290
Foam::IOobject::note
const string & note() const
Return the optional note.
Definition: IOobjectI.H:100
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
setRootCase.H
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:175
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1063
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:52
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:358
Foam::Pstream::mapCombineScatter
static void mapCombineScatter(const List< commsStruct > &comms, Container &Values, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:666
Foam::polyPatch::faceCentres
const vectorField::subField faceCentres() const
Return face centres.
Definition: polyPatch.C:313
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)
Helper: calculate point regions. The point region is the.
Definition: createShellMesh.C:157
Foam::List< word >
Foam::processorPolyPatch::newName
static word newName(const label myProcNo, const label neighbProcNo)
Return the name of a processorPolyPatch.
Definition: processorPolyPatch.C:186
Foam::globalMeshData::coupledPatch
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
Definition: globalMeshData.C:2066
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:102
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:144
Foam::processorMeshes::removeFiles
static void removeFiles(const polyMesh &mesh)
Helper: remove all procAddressing files from mesh instance.
Definition: processorMeshes.C:274
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:103
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::IOList< label >
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:181
Foam::word::null
static const word null
An empty word.
Definition: word.H:77
createTime.H
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::line
A line primitive.
Definition: line.H:59
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:325
Foam::PrimitivePatch::faceNormals
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
Definition: PrimitivePatch.C:425
Foam::createShellMesh
Creates mesh by extruding a patch.
Definition: createShellMesh.H:61
Foam::labelMin
constexpr label labelMin
Definition: label.H:60
nonuniformTransformCyclicPolyPatch.H
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:109
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:708
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:392
Foam::plusEqOp
Definition: ops.H:72
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1234
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatch.C:310
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:336
Foam::IOobject::NO_READ
Definition: IOobject.H:123
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)
Return parallel consistent edge normals for patches using mesh points.
Foam::faceZone::flipMap
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:271
Foam::topoSet::removeFiles
static void removeFiles(const polyMesh &)
Helper: remove all sets files from mesh instance.
Definition: topoSet.C:638
Foam::patchIdentifier::name
const word & name() const
The patch name.
Definition: patchIdentifier.H:134
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::patchIdentifier::index
label index() const
The index of this patch in the boundaryMesh.
Definition: patchIdentifier.H:158
Foam::mappedPatchBase::sampleMode
sampleMode
Mesh items to sample.
Definition: mappedPatchBase.H:113
pointFields.H
OBJstream.H
Foam::polyMesh::setInstance
void setInstance(const fileName &instance, const IOobject::writeOption wOpt=IOobject::AUTO_WRITE)
Set the instance for mesh files.
Definition: polyMeshIO.C:36
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:417
Foam::fvMesh::clearOut
void clearOut()
Clear all geometry and addressing.
Definition: fvMesh.C:227
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:164
Foam::argList::found
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:157
Foam::fvMesh::name
const word & name() const
Return reference to name.
Definition: fvMesh.H:268
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:85
Foam::IOobject::MUST_READ
Definition: IOobject.H:120
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:58