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