extrudeToRegionMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 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 in between 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 in between 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 in between.
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 in between 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 in between 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 in between 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 in between 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  // Allow arbitrary matching for nonuniformTransformCyclicPolyPatch
1087  transformDict.add("matchTolerance", 1e6);
1088 
1089  label nOldPatches = newPatches.size();
1090 
1091  if (!oneD)
1092  {
1093  forAll(zoneZonePatch_min, minZone)
1094  {
1095  for (label maxZone = minZone; maxZone < zoneNames.size(); maxZone++)
1096  {
1097  label index = minZone*zoneNames.size()+maxZone;
1098 
1099  if (zoneZonePatch_min[index] > 0)
1100  {
1101  word minToMax =
1102  zoneNames[minZone]
1103  + "_to_"
1104  + zoneNames[maxZone];
1105  word maxToMin =
1106  zoneNames[maxZone]
1107  + "_to_"
1108  + zoneNames[minZone];
1109 
1110  {
1111  transformDict.set("neighbourPatch", maxToMin);
1112  zoneZonePatch_min[index] =
1113  addPatch<nonuniformTransformCyclicPolyPatch>
1114  (
1115  mesh.boundaryMesh(),
1116  minToMax,
1117  transformDict,
1118  newPatches
1119  );
1120  Pout<< zoneZonePatch_min[index] << '\t' << minToMax
1121  << nl;
1122  }
1123  {
1124  transformDict.set("neighbourPatch", minToMax);
1125  zoneZonePatch_max[index] =
1126  addPatch<nonuniformTransformCyclicPolyPatch>
1127  (
1128  mesh.boundaryMesh(),
1129  maxToMin,
1130  transformDict,
1131  newPatches
1132  );
1133  Pout<< zoneZonePatch_max[index] << '\t' << maxToMin
1134  << nl;
1135  }
1136 
1137  }
1138  }
1139  }
1140  }
1141  Pout<< "Added " << newPatches.size()-nOldPatches << " inter-zone patches."
1142  << nl << endl;
1143 }
1144 
1145 
1146 tmp<pointField> calcOffset
1147 (
1148  const primitiveFacePatch& extrudePatch,
1149  const createShellMesh& extruder,
1150  const polyPatch& pp
1151 )
1152 {
1154 
1155  tmp<pointField> toffsets(new pointField(fc.size()));
1156  pointField& offsets = toffsets.ref();
1157 
1158  forAll(fc, i)
1159  {
1160  label meshFacei = pp.start()+i;
1161  label patchFacei = mag(extruder.faceToFaceMap()[meshFacei])-1;
1162  point patchFc = extrudePatch[patchFacei].centre
1163  (
1164  extrudePatch.points()
1165  );
1166  offsets[i] = patchFc - fc[i];
1167  }
1168  return toffsets;
1169 }
1170 
1171 
1172 void setCouplingInfo
1173 (
1174  fvMesh& mesh,
1175  const labelList& zoneToPatch,
1176  const word& sampleRegion,
1178  const List<pointField>& offsets
1179 )
1180 {
1181  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1182 
1183  List<polyPatch*> newPatches
1184  (
1185  patches.size(),
1186  static_cast<polyPatch*>(nullptr)
1187  );
1188 
1189  forAll(zoneToPatch, zoneI)
1190  {
1191  label patchi = zoneToPatch[zoneI];
1192 
1193  if (patchi != -1)
1194  {
1195  const polyPatch& pp = patches[patchi];
1196 
1197  if (isA<mappedWallPolyPatch>(pp))
1198  {
1199  newPatches[patchi] = new mappedWallPolyPatch
1200  (
1201  pp.name(),
1202  pp.size(),
1203  pp.start(),
1204  patchi,
1205  sampleRegion, // sampleRegion
1206  mode, // sampleMode
1207  pp.name(), // samplePatch
1208  offsets[zoneI], // offset
1209  patches
1210  );
1211  }
1212  }
1213  }
1214 
1215  forAll(newPatches, patchi)
1216  {
1217  if (!newPatches[patchi])
1218  {
1219  newPatches[patchi] = patches[patchi].clone(patches).ptr();
1220  }
1221  }
1222 
1223  mesh.removeFvBoundary();
1224  mesh.addFvPatches(newPatches, true);
1225 }
1226 
1227 
1228 // Extrude and write geometric properties
1229 void extrudeGeometricProperties
1230 (
1231  const polyMesh& mesh,
1232  const primitiveFacePatch& extrudePatch,
1233  const createShellMesh& extruder,
1234  const polyMesh& regionMesh,
1235  const extrudeModel& model
1236 )
1237 {
1238  const pointIOField patchFaceCentres
1239  (
1240  IOobject
1241  (
1242  "patchFaceCentres",
1243  mesh.pointsInstance(),
1244  mesh.meshSubDir,
1245  mesh,
1247  )
1248  );
1249 
1250  const pointIOField patchEdgeCentres
1251  (
1252  IOobject
1253  (
1254  "patchEdgeCentres",
1255  mesh.pointsInstance(),
1256  mesh.meshSubDir,
1257  mesh,
1259  )
1260  );
1261 
1262  // forAll(extrudePatch.edges(), edgeI)
1263  //{
1264  // const edge& e = extrudePatch.edges()[edgeI];
1265  // Pout<< "Edge:" << e.centre(extrudePatch.localPoints()) << nl
1266  // << "read:" << patchEdgeCentres[edgeI]
1267  // << endl;
1268  //}
1269 
1270 
1271  // Determine edge normals on original patch
1272  labelList patchEdges;
1273  labelList coupledEdges;
1274  PackedBoolList sameEdgeOrientation;
1276  (
1277  extrudePatch,
1278  mesh.globalData().coupledPatch(),
1279  patchEdges,
1280  coupledEdges,
1281  sameEdgeOrientation
1282  );
1283 
1284  pointField patchEdgeNormals
1285  (
1287  (
1288  mesh,
1289  extrudePatch,
1290  patchEdges,
1291  coupledEdges
1292  )
1293  );
1294 
1295 
1296  pointIOField faceCentres
1297  (
1298  IOobject
1299  (
1300  "faceCentres",
1301  regionMesh.pointsInstance(),
1302  regionMesh.meshSubDir,
1303  regionMesh,
1306  false
1307  ),
1308  regionMesh.nFaces()
1309  );
1310 
1311 
1312  // Work out layers. Guaranteed in columns so no fancy parallel bits.
1313 
1314 
1315  forAll(extruder.faceToFaceMap(), facei)
1316  {
1317  if (extruder.faceToFaceMap()[facei] != 0)
1318  {
1319  // 'horizontal' face
1320  label patchFacei = mag(extruder.faceToFaceMap()[facei])-1;
1321 
1322  label celli = regionMesh.faceOwner()[facei];
1323  if (regionMesh.isInternalFace(facei))
1324  {
1325  celli = max(celli, regionMesh.faceNeighbour()[facei]);
1326  }
1327 
1328  // Calculate layer from cell numbering (see createShellMesh)
1329  label layerI = (celli % model.nLayers());
1330 
1331  if
1332  (
1333  !regionMesh.isInternalFace(facei)
1334  && extruder.faceToFaceMap()[facei] > 0
1335  )
1336  {
1337  // Top face
1338  layerI++;
1339  }
1340 
1341 
1342  // Recalculate based on extrusion model
1343  faceCentres[facei] = model
1344  (
1345  patchFaceCentres[patchFacei],
1346  extrudePatch.faceNormals()[patchFacei],
1347  layerI
1348  );
1349  }
1350  else
1351  {
1352  // 'vertical face
1353  label patchEdgeI = extruder.faceToEdgeMap()[facei];
1354  label layerI =
1355  (
1356  regionMesh.faceOwner()[facei]
1357  % model.nLayers()
1358  );
1359 
1360  // Extrude patch edge centre to this layer
1361  point pt0 = model
1362  (
1363  patchEdgeCentres[patchEdgeI],
1364  patchEdgeNormals[patchEdgeI],
1365  layerI
1366  );
1367  // Extrude patch edge centre to next layer
1368  point pt1 = model
1369  (
1370  patchEdgeCentres[patchEdgeI],
1371  patchEdgeNormals[patchEdgeI],
1372  layerI+1
1373  );
1374 
1375  // Interpolate
1376  faceCentres[facei] = 0.5*(pt0+pt1);
1377  }
1378  }
1379 
1380  pointIOField cellCentres
1381  (
1382  IOobject
1383  (
1384  "cellCentres",
1385  regionMesh.pointsInstance(),
1386  regionMesh.meshSubDir,
1387  regionMesh,
1390  false
1391  ),
1392  regionMesh.nCells()
1393  );
1394 
1395  forAll(extruder.cellToFaceMap(), celli)
1396  {
1397  label patchFacei = extruder.cellToFaceMap()[celli];
1398 
1399  // Calculate layer from cell numbering (see createShellMesh)
1400  label layerI = (celli % model.nLayers());
1401 
1402  // Recalculate based on extrusion model
1403  point pt0 = model
1404  (
1405  patchFaceCentres[patchFacei],
1406  extrudePatch.faceNormals()[patchFacei],
1407  layerI
1408  );
1409  point pt1 = model
1410  (
1411  patchFaceCentres[patchFacei],
1412  extrudePatch.faceNormals()[patchFacei],
1413  layerI+1
1414  );
1415 
1416  // Interpolate
1417  cellCentres[celli] = 0.5*(pt0+pt1);
1418  }
1419 
1420 
1421  // Bit of checking
1422  if (false)
1423  {
1424  OBJstream faceStr(regionMesh.time().path()/"faceCentres.obj");
1425  OBJstream cellStr(regionMesh.time().path()/"cellCentres.obj");
1426 
1427  forAll(faceCentres, facei)
1428  {
1429  Pout<< "Model :" << faceCentres[facei] << endl
1430  << "regionMesh:" << regionMesh.faceCentres()[facei] << endl;
1431  faceStr.write
1432  (
1433  linePointRef
1434  (
1435  faceCentres[facei],
1436  regionMesh.faceCentres()[facei]
1437  )
1438  );
1439  }
1440  forAll(cellCentres, celli)
1441  {
1442  Pout<< "Model :" << cellCentres[celli] << endl
1443  << "regionMesh:" << regionMesh.cellCentres()[celli] << endl;
1444  cellStr.write
1445  (
1446  linePointRef
1447  (
1448  cellCentres[celli],
1449  regionMesh.cellCentres()[celli]
1450  )
1451  );
1452  }
1453  }
1454 
1455 
1456 
1457  Info<< "Writing geometric properties for mesh " << regionMesh.name()
1458  << " to " << regionMesh.pointsInstance() << nl
1459  << endl;
1460 
1461  bool ok = faceCentres.write() && cellCentres.write();
1462 
1463  if (!ok)
1464  {
1466  << "Failed writing " << faceCentres.objectPath()
1467  << " and " << cellCentres.objectPath()
1468  << exit(FatalError);
1469  }
1470 }
1471 
1472 
1473 
1474 
1475 int main(int argc, char *argv[])
1476 {
1477  argList::addNote("Create region mesh by extruding a faceZone or faceSet");
1478 
1479  #include "addRegionOption.H"
1480  #include "addOverwriteOption.H"
1481  #include "addDictOption.H"
1482  #include "setRootCase.H"
1483  #include "createTime.H"
1484  #include "createNamedMesh.H"
1485 
1486  if (mesh.boundaryMesh().checkParallelSync(true))
1487  {
1488  List<wordList> allNames(Pstream::nProcs());
1489  allNames[Pstream::myProcNo()] = mesh.boundaryMesh().names();
1490  Pstream::gatherList(allNames);
1491  Pstream::scatterList(allNames);
1492 
1494  << "Patches are not synchronised on all processors."
1495  << " Per processor patches " << allNames
1496  << exit(FatalError);
1497  }
1498 
1499 
1500  const word oldInstance = mesh.pointsInstance();
1501  bool overwrite = args.optionFound("overwrite");
1502 
1503 
1504  const word dictName("extrudeToRegionMeshDict");
1505 
1506  #include "setSystemMeshDictionaryIO.H"
1507 
1509 
1510 
1511  // Point generator
1513 
1514 
1515  // Region
1516  const word shellRegionName(dict.lookup("region"));
1517 
1518  // Faces to extrude - either faceZones or faceSets (boundary faces only)
1519  wordList zoneNames;
1520  wordList zoneShadowNames;
1521 
1522  bool hasZones = dict.found("faceZones");
1523  if (hasZones)
1524  {
1525  dict.lookup("faceZones") >> zoneNames;
1526  dict.readIfPresent("faceZonesShadow", zoneShadowNames);
1527 
1528  // Check
1529  if (dict.found("faceSets"))
1530  {
1531  FatalIOErrorIn(args.executable().c_str(), dict)
1532  << "Please supply faces to extrude either through 'faceZones'"
1533  << " or 'faceSets' entry. Found both."
1534  << exit(FatalIOError);
1535  }
1536  }
1537  else
1538  {
1539  dict.lookup("faceSets") >> zoneNames;
1540  dict.readIfPresent("faceSetsShadow", zoneShadowNames);
1541  }
1542 
1543 
1544  mappedPatchBase::sampleMode sampleMode =
1545  mappedPatchBase::sampleModeNames_[dict.lookup("sampleMode")];
1546 
1547  const Switch oneD(dict.lookup("oneD"));
1548  Switch oneDNonManifoldEdges(false);
1549  word oneDPatchType(emptyPolyPatch::typeName);
1550  if (oneD)
1551  {
1552  oneDNonManifoldEdges = dict.lookupOrDefault("nonManifold", false);
1553  dict.lookup("oneDPolyPatchType") >> oneDPatchType;
1554  }
1555 
1556  const Switch adaptMesh(dict.lookup("adaptMesh"));
1557 
1558  if (hasZones)
1559  {
1560  Info<< "Extruding zones " << zoneNames
1561  << " on mesh " << regionName
1562  << " into shell mesh " << shellRegionName
1563  << endl;
1564  }
1565  else
1566  {
1567  Info<< "Extruding faceSets " << zoneNames
1568  << " on mesh " << regionName
1569  << " into shell mesh " << shellRegionName
1570  << endl;
1571  }
1572 
1573  if (shellRegionName == regionName)
1574  {
1575  FatalIOErrorIn(args.executable().c_str(), dict)
1576  << "Cannot extrude into same region as mesh." << endl
1577  << "Mesh region : " << regionName << endl
1578  << "Shell region : " << shellRegionName
1579  << exit(FatalIOError);
1580  }
1581 
1582 
1583  if (oneD)
1584  {
1585  if (oneDNonManifoldEdges)
1586  {
1587  Info<< "Extruding as 1D columns with sides in patch type "
1588  << oneDPatchType
1589  << " and connected points (except on non-manifold areas)."
1590  << endl;
1591  }
1592  else
1593  {
1594  Info<< "Extruding as 1D columns with sides in patch type "
1595  << oneDPatchType
1596  << " and duplicated points (overlapping volumes)."
1597  << endl;
1598  }
1599  }
1600 
1601 
1602 
1603 
1605  // IOobjectList objects(mesh, runTime.timeName());
1606  //
1608  //
1609  // PtrList<volScalarField> vsFlds;
1610  // ReadFields(mesh, objects, vsFlds);
1611  //
1612  // PtrList<volVectorField> vvFlds;
1613  // ReadFields(mesh, objects, vvFlds);
1614  //
1615  // PtrList<volSphericalTensorField> vstFlds;
1616  // ReadFields(mesh, objects, vstFlds);
1617  //
1618  // PtrList<volSymmTensorField> vsymtFlds;
1619  // ReadFields(mesh, objects, vsymtFlds);
1620  //
1621  // PtrList<volTensorField> vtFlds;
1622  // ReadFields(mesh, objects, vtFlds);
1623  //
1625  //
1626  // PtrList<surfaceScalarField> ssFlds;
1627  // ReadFields(mesh, objects, ssFlds);
1628  //
1629  // PtrList<surfaceVectorField> svFlds;
1630  // ReadFields(mesh, objects, svFlds);
1631  //
1632  // PtrList<surfaceSphericalTensorField> sstFlds;
1633  // ReadFields(mesh, objects, sstFlds);
1634  //
1635  // PtrList<surfaceSymmTensorField> ssymtFlds;
1636  // ReadFields(mesh, objects, ssymtFlds);
1637  //
1638  // PtrList<surfaceTensorField> stFlds;
1639  // ReadFields(mesh, objects, stFlds);
1640  //
1642  //
1643  // PtrList<pointScalarField> psFlds;
1644  // ReadFields(pointMesh::New(mesh), objects, psFlds);
1645  //
1646  // PtrList<pointVectorField> pvFlds;
1647  // ReadFields(pointMesh::New(mesh), objects, pvFlds);
1648 
1649 
1650 
1651  // Create dummy fv* files
1652  createDummyFvMeshFiles(mesh, shellRegionName);
1653 
1654 
1655  word meshInstance;
1656  if (!overwrite)
1657  {
1658  runTime++;
1659  meshInstance = runTime.timeName();
1660  }
1661  else
1662  {
1663  meshInstance = oldInstance;
1664  }
1665  Info<< "Writing meshes to " << meshInstance << nl << endl;
1666 
1667 
1668  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1669 
1670 
1671  // Extract faces to extrude
1672  // ~~~~~~~~~~~~~~~~~~~~~~~~
1673  // Note: zoneID are regions of extrusion. They are not mesh.faceZones
1674  // indices.
1675 
1676  // From extrude zone to mesh zone (or -1 if extruding faceSets)
1677  labelList meshZoneID;
1678  // Per extrude zone whether contains internal or external faces
1679  boolList isInternal(zoneNames.size(), false);
1680 
1681  labelList extrudeMeshFaces;
1682  faceList zoneFaces;
1683  labelList zoneID;
1684  boolList zoneFlipMap;
1685  // Shadow
1686  labelList zoneShadowIDs; // from extrude shadow zone to mesh zone
1687  labelList extrudeMeshShadowFaces;
1688  boolList zoneShadowFlipMap;
1689  labelList zoneShadowID;
1690 
1691  if (hasZones)
1692  {
1693  const faceZoneMesh& faceZones = mesh.faceZones();
1694 
1695  meshZoneID.setSize(zoneNames.size());
1696  forAll(zoneNames, i)
1697  {
1698  meshZoneID[i] = faceZones.findZoneID(zoneNames[i]);
1699  if (meshZoneID[i] == -1)
1700  {
1701  FatalIOErrorIn(args.executable().c_str(), dict)
1702  << "Cannot find zone " << zoneNames[i] << endl
1703  << "Valid zones are " << faceZones.names()
1704  << exit(FatalIOError);
1705  }
1706  }
1707  // Collect per face information
1708  label nExtrudeFaces = 0;
1709  forAll(meshZoneID, i)
1710  {
1711  nExtrudeFaces += faceZones[meshZoneID[i]].size();
1712  }
1713  extrudeMeshFaces.setSize(nExtrudeFaces);
1714  zoneFaces.setSize(nExtrudeFaces);
1715  zoneID.setSize(nExtrudeFaces);
1716  zoneFlipMap.setSize(nExtrudeFaces);
1717  nExtrudeFaces = 0;
1718  forAll(meshZoneID, i)
1719  {
1720  const faceZone& fz = faceZones[meshZoneID[i]];
1721  const primitiveFacePatch& fzp = fz();
1722  forAll(fz, j)
1723  {
1724  extrudeMeshFaces[nExtrudeFaces] = fz[j];
1725  zoneFaces[nExtrudeFaces] = fzp[j];
1726  zoneID[nExtrudeFaces] = i;
1727  zoneFlipMap[nExtrudeFaces] = fz.flipMap()[j];
1728  nExtrudeFaces++;
1729 
1730  if (mesh.isInternalFace(fz[j]))
1731  {
1732  isInternal[i] = true;
1733  }
1734  }
1735  }
1736 
1737  // Shadow zone
1738  // ~~~~~~~~~~~
1739 
1740  if (zoneShadowNames.size())
1741  {
1742  zoneShadowIDs.setSize(zoneShadowNames.size());
1743  forAll(zoneShadowNames, i)
1744  {
1745  zoneShadowIDs[i] = faceZones.findZoneID(zoneShadowNames[i]);
1746  if (zoneShadowIDs[i] == -1)
1747  {
1748  FatalIOErrorIn(args.executable().c_str(), dict)
1749  << "Cannot find zone " << zoneShadowNames[i] << endl
1750  << "Valid zones are " << faceZones.names()
1751  << exit(FatalIOError);
1752  }
1753  }
1754 
1755  label nShadowFaces = 0;
1756  forAll(zoneShadowIDs, i)
1757  {
1758  nShadowFaces += faceZones[zoneShadowIDs[i]].size();
1759  }
1760 
1761  extrudeMeshShadowFaces.setSize(nShadowFaces);
1762  zoneShadowFlipMap.setSize(nShadowFaces);
1763  zoneShadowID.setSize(nShadowFaces);
1764 
1765  nShadowFaces = 0;
1766  forAll(zoneShadowIDs, i)
1767  {
1768  const faceZone& fz = faceZones[zoneShadowIDs[i]];
1769  forAll(fz, j)
1770  {
1771  extrudeMeshShadowFaces[nShadowFaces] = fz[j];
1772  zoneShadowFlipMap[nShadowFaces] = fz.flipMap()[j];
1773  zoneShadowID[nShadowFaces] = i;
1774  nShadowFaces++;
1775  }
1776  }
1777  }
1778  }
1779  else
1780  {
1781  meshZoneID.setSize(zoneNames.size(), -1);
1782  // Load faceSets
1783  PtrList<faceSet> zones(zoneNames.size());
1784  forAll(zoneNames, i)
1785  {
1786  Info<< "Loading faceSet " << zoneNames[i] << endl;
1787  zones.set(i, new faceSet(mesh, zoneNames[i]));
1788  }
1789 
1790 
1791  // Collect per face information
1792  label nExtrudeFaces = 0;
1793  forAll(zones, i)
1794  {
1795  nExtrudeFaces += zones[i].size();
1796  }
1797  extrudeMeshFaces.setSize(nExtrudeFaces);
1798  zoneFaces.setSize(nExtrudeFaces);
1799  zoneID.setSize(nExtrudeFaces);
1800  zoneFlipMap.setSize(nExtrudeFaces);
1801 
1802  nExtrudeFaces = 0;
1803  forAll(zones, i)
1804  {
1805  const faceSet& fz = zones[i];
1806  forAllConstIter(faceSet, fz, iter)
1807  {
1808  label facei = iter.key();
1809  if (mesh.isInternalFace(facei))
1810  {
1811  FatalIOErrorIn(args.executable().c_str(), dict)
1812  << "faceSet " << fz.name()
1813  << "contains internal faces."
1814  << " This is not permitted."
1815  << exit(FatalIOError);
1816  }
1817  extrudeMeshFaces[nExtrudeFaces] = facei;
1818  zoneFaces[nExtrudeFaces] = mesh.faces()[facei];
1819  zoneID[nExtrudeFaces] = i;
1820  zoneFlipMap[nExtrudeFaces] = false;
1821  nExtrudeFaces++;
1822 
1823  if (mesh.isInternalFace(facei))
1824  {
1825  isInternal[i] = true;
1826  }
1827  }
1828  }
1829 
1830 
1831  // Shadow zone
1832  // ~~~~~~~~~~~
1833 
1834  PtrList<faceSet> shadowZones(zoneShadowNames.size());
1835  if (zoneShadowNames.size())
1836  {
1837  zoneShadowIDs.setSize(zoneShadowNames.size(), -1);
1838  forAll(zoneShadowNames, i)
1839  {
1840  shadowZones.set(i, new faceSet(mesh, zoneShadowNames[i]));
1841  }
1842 
1843  label nShadowFaces = 0;
1844  forAll(shadowZones, i)
1845  {
1846  nShadowFaces += shadowZones[i].size();
1847  }
1848 
1849  if (nExtrudeFaces != nShadowFaces)
1850  {
1851  FatalIOErrorIn(args.executable().c_str(), dict)
1852  << "Extruded faces " << nExtrudeFaces << endl
1853  << "is different from shadow faces. " << nShadowFaces
1854  << "This is not permitted " << endl
1855  << exit(FatalIOError);
1856  }
1857 
1858  extrudeMeshShadowFaces.setSize(nShadowFaces);
1859  zoneShadowFlipMap.setSize(nShadowFaces);
1860  zoneShadowID.setSize(nShadowFaces);
1861 
1862  nShadowFaces = 0;
1863  forAll(shadowZones, i)
1864  {
1865  const faceSet& fz = shadowZones[i];
1866  forAllConstIter(faceSet, fz, iter)
1867  {
1868  label facei = iter.key();
1869  if (mesh.isInternalFace(facei))
1870  {
1871  FatalIOErrorIn(args.executable().c_str(), dict)
1872  << "faceSet " << fz.name()
1873  << "contains internal faces."
1874  << " This is not permitted."
1875  << exit(FatalIOError);
1876  }
1877  extrudeMeshShadowFaces[nShadowFaces] = facei;
1878  zoneShadowFlipMap[nShadowFaces] = false;
1879  zoneShadowID[nShadowFaces] = i;
1880  nShadowFaces++;
1881  }
1882  }
1883  }
1884  }
1885  const primitiveFacePatch extrudePatch(zoneFaces.xfer(), mesh.points());
1886 
1887 
1889  Pstream::listCombineScatter(isInternal);
1890 
1891  // Check zone either all internal or all external faces
1892  checkZoneInside(mesh, zoneNames, zoneID, extrudeMeshFaces, isInternal);
1893 
1894 
1895 
1896  const pointField& extrudePoints = extrudePatch.localPoints();
1897  const faceList& extrudeFaces = extrudePatch.localFaces();
1898  const labelListList& edgeFaces = extrudePatch.edgeFaces();
1899 
1900 
1901  Info<< "extrudePatch :"
1902  << " faces:" << extrudePatch.size()
1903  << " points:" << extrudePatch.nPoints()
1904  << " edges:" << extrudePatch.nEdges()
1905  << nl
1906  << endl;
1907 
1908 
1909  // Determine per-extrude-edge info
1910  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1911 
1912  // Corresponding mesh edges
1913  const labelList extrudeMeshEdges
1914  (
1915  extrudePatch.meshEdges
1916  (
1917  mesh.edges(),
1918  mesh.pointEdges()
1919  )
1920  );
1921 
1922  const globalIndex globalExtrudeFaces(extrudePatch.size());
1923 
1924  // Global pp faces per pp edge.
1925  labelListList extrudeEdgeGlobalFaces
1926  (
1927  globalEdgeFaces
1928  (
1929  mesh,
1930  globalExtrudeFaces,
1931  extrudePatch,
1932  extrudeMeshEdges
1933  )
1934  );
1935  List<Map<label>> compactMap;
1936  const mapDistribute extrudeEdgeFacesMap
1937  (
1938  globalExtrudeFaces,
1939  extrudeEdgeGlobalFaces,
1940  compactMap
1941  );
1942 
1943 
1944  // Determine min and max zone per edge
1945  labelList edgeMinZoneID;
1946  labelList edgeMaxZoneID;
1947  calcEdgeMinMaxZone
1948  (
1949  mesh,
1950  extrudePatch,
1951  extrudeMeshEdges,
1952  zoneID,
1953  extrudeEdgeFacesMap,
1954  extrudeEdgeGlobalFaces,
1955 
1956  edgeMinZoneID,
1957  edgeMaxZoneID
1958  );
1959 
1960 
1961 
1962 
1963  DynamicList<polyPatch*> regionPatches(patches.size());
1964  // Copy all non-local patches since these are used on boundary edges of
1965  // the extrusion
1966  forAll(patches, patchi)
1967  {
1968  if (!isA<processorPolyPatch>(patches[patchi]))
1969  {
1970  label newPatchi = regionPatches.size();
1971  regionPatches.append
1972  (
1973  patches[patchi].clone
1974  (
1975  patches,
1976  newPatchi,
1977  0, // size
1978  0 // start
1979  ).ptr()
1980  );
1981  }
1982  }
1983 
1984 
1985  // Add interface patches
1986  // ~~~~~~~~~~~~~~~~~~~~~
1987 
1988  // From zone to interface patch (region side)
1989  labelList interRegionTopPatch;
1990  labelList interRegionBottomPatch;
1991 
1992  addCouplingPatches
1993  (
1994  mesh,
1995  regionName,
1996  shellRegionName,
1997  zoneNames,
1998  zoneShadowNames,
1999  isInternal,
2000  meshZoneID,
2001 
2002  regionPatches,
2003  interRegionTopPatch,
2004  interRegionBottomPatch
2005  );
2006 
2007 
2008  // From zone to interface patch (mesh side)
2009  labelList interMeshTopPatch;
2010  labelList interMeshBottomPatch;
2011 
2012  if (adaptMesh)
2013  {
2014  // Add coupling patches to mesh
2015 
2016  // Clone existing patches
2017  DynamicList<polyPatch*> newPatches(patches.size());
2018  forAll(patches, patchi)
2019  {
2020  newPatches.append(patches[patchi].clone(patches).ptr());
2021  }
2022 
2023  // Add new patches
2024  addCouplingPatches
2025  (
2026  mesh,
2027  regionName,
2028  shellRegionName,
2029  zoneNames,
2030  zoneShadowNames,
2031  isInternal,
2032  meshZoneID,
2033 
2034  newPatches,
2035  interMeshTopPatch,
2036  interMeshBottomPatch
2037  );
2038 
2039  // Add to mesh
2040  mesh.clearOut();
2041  mesh.removeFvBoundary();
2042  mesh.addFvPatches(newPatches, true);
2043 
2045  }
2046 
2047 
2048  // Patch per extruded face
2049  labelList extrudeTopPatchID(extrudePatch.size());
2050  labelList extrudeBottomPatchID(extrudePatch.size());
2051 
2052  forAll(zoneID, facei)
2053  {
2054  extrudeTopPatchID[facei] = interRegionTopPatch[zoneID[facei]];
2055  extrudeBottomPatchID[facei] = interRegionBottomPatch[zoneID[facei]];
2056  }
2057 
2058 
2059 
2060  // Count how many patches on special edges of extrudePatch are necessary
2061  // - zoneXXX_sides
2062  // - zoneXXX_zoneYYY
2063  labelList zoneSidePatch(zoneNames.size(), 0);
2064  // Patch to use for minZone
2065  labelList zoneZonePatch_min(zoneNames.size()*zoneNames.size(), 0);
2066  // Patch to use for maxZone
2067  labelList zoneZonePatch_max(zoneNames.size()*zoneNames.size(), 0);
2068 
2069  countExtrudePatches
2070  (
2071  mesh,
2072  zoneNames.size(),
2073 
2074  extrudePatch, // patch
2075  extrudeMeshFaces, // mesh face per patch face
2076  extrudeMeshEdges, // mesh edge per patch edge
2077 
2078  extrudeEdgeGlobalFaces, // global indexing per patch edge
2079  edgeMinZoneID, // minZone per patch edge
2080  edgeMaxZoneID, // maxZone per patch edge
2081 
2082  zoneSidePatch, // per zone-side num edges that extrude into it
2083  zoneZonePatch_min // per zone-zone num edges that extrude into it
2084  );
2085 
2086  // Now we'll have:
2087  // zoneSidePatch[zoneA] : number of faces needed on the side of zoneA
2088  // zoneZonePatch_min[zoneA,zoneB] : number of faces needed in between A,B
2089 
2090 
2091  // Add the zone-side patches.
2092  addZoneSidePatches
2093  (
2094  mesh,
2095  zoneNames,
2096  (oneD ? oneDPatchType : word::null),
2097 
2098  regionPatches,
2099  zoneSidePatch
2100  );
2101 
2102 
2103  // Add the patches in between zones
2104  addInterZonePatches
2105  (
2106  mesh,
2107  zoneNames,
2108  oneD,
2109 
2110  zoneZonePatch_min,
2111  zoneZonePatch_max,
2112  regionPatches
2113  );
2114 
2115 
2116  // Sets sidePatchID[edgeI] to interprocessor patch. Adds any
2117  // interprocessor or cyclic patches if necessary.
2118  labelList sidePatchID;
2119  addCoupledPatches
2120  (
2121  mesh,
2122  extrudePatch,
2123  extrudeMeshFaces,
2124  extrudeMeshEdges,
2125  extrudeEdgeFacesMap,
2126  extrudeEdgeGlobalFaces,
2127 
2128  sidePatchID,
2129  regionPatches
2130  );
2131 
2132 
2133 // // Add all the newPatches to the mesh and fields
2134 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2135 // {
2136 // forAll(newPatches, patchi)
2137 // {
2138 // Pout<< "Adding patch " << patchi
2139 // << " name:" << newPatches[patchi]->name()
2140 // << endl;
2141 // }
2142 // // label nOldPatches = mesh.boundary().size();
2143 // mesh.clearOut();
2144 // mesh.removeFvBoundary();
2145 // mesh.addFvPatches(newPatches, true);
2146 // //// Add calculated fvPatchFields for the added patches
2147 // // for
2148 // //(
2149 // // label patchi = nOldPatches;
2150 // // patchi < mesh.boundary().size();
2151 // // patchi++
2152 // //)
2153 // //{
2154 // // Pout<< "ADDing calculated to patch " << patchi
2155 // // << endl;
2156 // // addCalculatedPatchFields(mesh);
2157 // //}
2158 // // Pout<< "** Added " << mesh.boundary().size()-nOldPatches
2159 // // << " patches." << endl;
2160 // }
2161 
2162 
2163  // Set patches to use for edges to be extruded into boundary faces
2164  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2165  // In order of edgeFaces: per edge, per originating face the
2166  // patch to use for the side face (from the extruded edge).
2167  // If empty size create an internal face.
2168  labelListList extrudeEdgePatches(extrudePatch.nEdges());
2169 
2170  // Is edge a non-manifold edge
2171  PackedBoolList nonManifoldEdge(extrudePatch.nEdges());
2172 
2173  // Note: logic has to be same as in countExtrudePatches.
2174  forAll(edgeFaces, edgeI)
2175  {
2176  const labelList& eFaces = edgeFaces[edgeI];
2177 
2178  labelList& ePatches = extrudeEdgePatches[edgeI];
2179 
2180  if (oneD)
2181  {
2182  ePatches.setSize(eFaces.size());
2183  forAll(eFaces, i)
2184  {
2185  ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]];
2186  }
2187 
2188  if (oneDNonManifoldEdges)
2189  {
2190  //- Set nonManifoldEdge[edgeI] for non-manifold edges only
2191  // The other option is to have non-manifold edges everywhere
2192  // and generate space overlapping columns of cells.
2193  if (eFaces.size() != 2)
2194  {
2195  nonManifoldEdge[edgeI] = 1;
2196  }
2197  }
2198  else
2199  {
2200  nonManifoldEdge[edgeI] = 1;
2201  }
2202  }
2203  else if (eFaces.size() == 2)
2204  {
2205  label zone0 = zoneID[eFaces[0]];
2206  label zone1 = zoneID[eFaces[1]];
2207 
2208  if (zone0 != zone1) // || (cos(angle) > blabla))
2209  {
2210  label minZone = min(zone0,zone1);
2211  label maxZone = max(zone0,zone1);
2212  label index = minZone*zoneNames.size()+maxZone;
2213 
2214  ePatches.setSize(eFaces.size());
2215 
2216  if (zone0 == minZone)
2217  {
2218  ePatches[0] = zoneZonePatch_min[index];
2219  ePatches[1] = zoneZonePatch_max[index];
2220  }
2221  else
2222  {
2223  ePatches[0] = zoneZonePatch_max[index];
2224  ePatches[1] = zoneZonePatch_min[index];
2225  }
2226 
2227  nonManifoldEdge[edgeI] = 1;
2228  }
2229  }
2230  else if (sidePatchID[edgeI] != -1)
2231  {
2232  // Coupled extrusion
2233  ePatches.setSize(eFaces.size());
2234  forAll(eFaces, i)
2235  {
2236  ePatches[i] = sidePatchID[edgeI];
2237  }
2238  }
2239  else
2240  {
2241  label facei = findUncoveredPatchFace
2242  (
2243  mesh,
2244  UIndirectList<label>(extrudeMeshFaces, eFaces),
2245  extrudeMeshEdges[edgeI]
2246  );
2247 
2248  if (facei != -1)
2249  {
2250  label newPatchi = findPatchID
2251  (
2252  regionPatches,
2253  patches[patches.whichPatch(facei)].name()
2254  );
2255  ePatches.setSize(eFaces.size(), newPatchi);
2256  }
2257  else
2258  {
2259  ePatches.setSize(eFaces.size());
2260  forAll(eFaces, i)
2261  {
2262  ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]];
2263  }
2264  }
2265  nonManifoldEdge[edgeI] = 1;
2266  }
2267  }
2268 
2269 
2270 
2271  // Assign point regions
2272  // ~~~~~~~~~~~~~~~~~~~~
2273 
2274  // Per face, per point the region number.
2275  faceList pointGlobalRegions;
2276  faceList pointLocalRegions;
2277  labelList localToGlobalRegion;
2278 
2280  (
2281  mesh.globalData(),
2282  extrudePatch,
2283  nonManifoldEdge,
2284  false, // keep cyclic separated regions apart
2285 
2286  pointGlobalRegions,
2287  pointLocalRegions,
2288  localToGlobalRegion
2289  );
2290 
2291  // Per local region an originating point
2292  labelList localRegionPoints(localToGlobalRegion.size());
2293  forAll(pointLocalRegions, facei)
2294  {
2295  const face& f = extrudePatch.localFaces()[facei];
2296  const face& pRegions = pointLocalRegions[facei];
2297  forAll(pRegions, fp)
2298  {
2299  localRegionPoints[pRegions[fp]] = f[fp];
2300  }
2301  }
2302 
2303  // Calculate region normals by reducing local region normals
2304  pointField localRegionNormals(localToGlobalRegion.size());
2305  {
2306  pointField localSum(localToGlobalRegion.size(), Zero);
2307 
2308  forAll(pointLocalRegions, facei)
2309  {
2310  const face& pRegions = pointLocalRegions[facei];
2311  forAll(pRegions, fp)
2312  {
2313  label localRegionI = pRegions[fp];
2314  localSum[localRegionI] += extrudePatch.faceNormals()[facei];
2315  }
2316  }
2317 
2318  Map<point> globalSum(2*localToGlobalRegion.size());
2319 
2320  forAll(localSum, localRegionI)
2321  {
2322  label globalRegionI = localToGlobalRegion[localRegionI];
2323  globalSum.insert(globalRegionI, localSum[localRegionI]);
2324  }
2325 
2326  // Reduce
2328  Pstream::mapCombineScatter(globalSum);
2329 
2330  forAll(localToGlobalRegion, localRegionI)
2331  {
2332  label globalRegionI = localToGlobalRegion[localRegionI];
2333  localRegionNormals[localRegionI] = globalSum[globalRegionI];
2334  }
2335  localRegionNormals /= mag(localRegionNormals);
2336  }
2337 
2338 
2339  // For debugging: dump hedgehog plot of normals
2340  if (false)
2341  {
2342  OFstream str(runTime.path()/"localRegionNormals.obj");
2343  label vertI = 0;
2344 
2345  scalar thickness = model().sumThickness(1);
2346 
2347  forAll(pointLocalRegions, facei)
2348  {
2349  const face& f = extrudeFaces[facei];
2350 
2351  forAll(f, fp)
2352  {
2353  label region = pointLocalRegions[facei][fp];
2354  const point& pt = extrudePoints[f[fp]];
2355 
2356  meshTools::writeOBJ(str, pt);
2357  vertI++;
2359  (
2360  str,
2361  pt+thickness*localRegionNormals[region]
2362  );
2363  vertI++;
2364  str << "l " << vertI-1 << ' ' << vertI << nl;
2365  }
2366  }
2367  }
2368 
2369 
2370  // Use model to create displacements of first layer
2371  vectorField firstDisp(localRegionNormals.size());
2372  forAll(firstDisp, regionI)
2373  {
2374  // const point& regionPt = regionCentres[regionI];
2375  const point& regionPt = extrudePatch.points()
2376  [
2377  extrudePatch.meshPoints()
2378  [
2379  localRegionPoints[regionI]
2380  ]
2381  ];
2382  const vector& n = localRegionNormals[regionI];
2383  firstDisp[regionI] = model()(regionPt, n, 1) - regionPt;
2384  }
2385 
2386 
2387  // Create a new mesh
2388  // ~~~~~~~~~~~~~~~~~
2389 
2390  createShellMesh extruder
2391  (
2392  extrudePatch,
2393  pointLocalRegions,
2394  localRegionPoints
2395  );
2396 
2397 
2398  autoPtr<mapPolyMesh> shellMap;
2399  fvMesh regionMesh
2400  (
2401  IOobject
2402  (
2403  shellRegionName,
2404  meshInstance,
2405  runTime,
2406  IOobject::NO_READ,
2408  false
2409  ),
2410  xferCopy(pointField()),
2411  xferCopy(faceList()),
2412  xferCopy(labelList()),
2413  xferCopy(labelList()),
2414  false
2415  );
2416 
2417  // Add the new patches
2418  forAll(regionPatches, patchi)
2419  {
2420  polyPatch* ppPtr = regionPatches[patchi];
2421  regionPatches[patchi] = ppPtr->clone(regionMesh.boundaryMesh()).ptr();
2422  delete ppPtr;
2423  }
2424  regionMesh.clearOut();
2425  regionMesh.removeFvBoundary();
2426  regionMesh.addFvPatches(regionPatches, true);
2427 
2428  {
2429  polyTopoChange meshMod(regionPatches.size());
2430 
2431  extruder.setRefinement
2432  (
2433  firstDisp, // first displacement
2434  model().expansionRatio(),
2435  model().nLayers(), // nLayers
2436  extrudeTopPatchID,
2437  extrudeBottomPatchID,
2438  extrudeEdgePatches,
2439  meshMod
2440  );
2441 
2442  // Enforce actual point posititions according to extrudeModel (model)
2443  // (extruder.setRefinement only does fixed expansionRatio)
2444  // The regionPoints and nLayers are looped in the same way as in
2445  // createShellMesh
2446  DynamicList<point>& newPoints = const_cast<DynamicList<point>&>
2447  (
2448  meshMod.points()
2449  );
2450  label meshPointi = extrudePatch.localPoints().size();
2451  forAll(localRegionPoints, regionI)
2452  {
2453  label pointi = localRegionPoints[regionI];
2454  point pt = extrudePatch.localPoints()[pointi];
2455  const vector& n = localRegionNormals[regionI];
2456 
2457  for (label layerI = 1; layerI <= model().nLayers(); layerI++)
2458  {
2459  newPoints[meshPointi++] = model()(pt, n, layerI);
2460  }
2461  }
2462 
2463  shellMap = meshMod.changeMesh
2464  (
2465  regionMesh, // mesh to change
2466  false // inflate
2467  );
2468  }
2469 
2470  // Necessary?
2471  regionMesh.setInstance(meshInstance);
2472 
2473 
2474  // Update numbering on extruder.
2475  extruder.updateMesh(shellMap);
2476 
2477 
2478  // Calculate offsets from shell mesh back to original mesh
2479  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2480 
2481  List<pointField> topOffsets(zoneNames.size());
2482  List<pointField> bottomOffsets(zoneNames.size());
2483 
2484  forAll(regionMesh.boundaryMesh(), patchi)
2485  {
2486  const polyPatch& pp = regionMesh.boundaryMesh()[patchi];
2487 
2488  if (isA<mappedWallPolyPatch>(pp))
2489  {
2490  if (findIndex(interRegionTopPatch, patchi) != -1)
2491  {
2492  label zoneI = findIndex(interRegionTopPatch, patchi);
2493  topOffsets[zoneI] = calcOffset(extrudePatch, extruder, pp);
2494  }
2495  else if (findIndex(interRegionBottomPatch, patchi) != -1)
2496  {
2497  label zoneI = findIndex(interRegionBottomPatch, patchi);
2498  bottomOffsets[zoneI] = calcOffset(extrudePatch, extruder, pp);
2499  }
2500  }
2501  }
2502 
2503 
2504  // Change top and bottom boundary conditions on regionMesh
2505  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2506 
2507  {
2508  // Correct top patches for offset
2509  setCouplingInfo
2510  (
2511  regionMesh,
2512  interRegionTopPatch,
2513  regionName, // name of main mesh
2514  sampleMode, // sampleMode
2515  topOffsets
2516  );
2517 
2518  // Correct bottom patches for offset
2519  setCouplingInfo
2520  (
2521  regionMesh,
2522  interRegionBottomPatch,
2523  regionName,
2524  sampleMode, // sampleMode
2525  bottomOffsets
2526  );
2527 
2528  // Remove any unused patches
2529  deleteEmptyPatches(regionMesh);
2530  }
2531 
2532  // Change top and bottom boundary conditions on main mesh
2533  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2534 
2535  if (adaptMesh)
2536  {
2537  // Correct top patches for offset
2538  setCouplingInfo
2539  (
2540  mesh,
2541  interMeshTopPatch,
2542  shellRegionName, // name of shell mesh
2543  sampleMode, // sampleMode
2544  -topOffsets
2545  );
2546 
2547  // Correct bottom patches for offset
2548  setCouplingInfo
2549  (
2550  mesh,
2551  interMeshBottomPatch,
2552  shellRegionName,
2553  sampleMode,
2554  -bottomOffsets
2555  );
2556  }
2557 
2558 
2559 
2560  // Write addressing from region mesh back to originating patch
2561  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2562 
2563  labelIOList cellToPatchFaceAddressing
2564  (
2565  IOobject
2566  (
2567  "cellToPatchFaceAddressing",
2568  regionMesh.facesInstance(),
2569  regionMesh.meshSubDir,
2570  regionMesh,
2573  false
2574  ),
2575  extruder.cellToFaceMap()
2576  );
2577  cellToPatchFaceAddressing.note() = "cell to patch face addressing";
2578 
2579  labelIOList faceToPatchFaceAddressing
2580  (
2581  IOobject
2582  (
2583  "faceToPatchFaceAddressing",
2584  regionMesh.facesInstance(),
2585  regionMesh.meshSubDir,
2586  regionMesh,
2589  false
2590  ),
2591  extruder.faceToFaceMap()
2592  );
2593  faceToPatchFaceAddressing.note() =
2594  "front/back face + turning index to patch face addressing";
2595 
2596  labelIOList faceToPatchEdgeAddressing
2597  (
2598  IOobject
2599  (
2600  "faceToPatchEdgeAddressing",
2601  regionMesh.facesInstance(),
2602  regionMesh.meshSubDir,
2603  regionMesh,
2606  false
2607  ),
2608  extruder.faceToEdgeMap()
2609  );
2610  faceToPatchEdgeAddressing.note() =
2611  "side face to patch edge addressing";
2612 
2613  labelIOList pointToPatchPointAddressing
2614  (
2615  IOobject
2616  (
2617  "pointToPatchPointAddressing",
2618  regionMesh.facesInstance(),
2619  regionMesh.meshSubDir,
2620  regionMesh,
2623  false
2624  ),
2625  extruder.pointToPointMap()
2626  );
2627  pointToPatchPointAddressing.note() =
2628  "point to patch point addressing";
2629 
2630 
2631  Info<< "Writing mesh " << regionMesh.name()
2632  << " to " << regionMesh.facesInstance() << nl
2633  << endl;
2634 
2635  bool ok =
2636  regionMesh.write()
2637  && cellToPatchFaceAddressing.write()
2638  && faceToPatchFaceAddressing.write()
2639  && faceToPatchEdgeAddressing.write()
2640  && pointToPatchPointAddressing.write();
2641 
2642  if (!ok)
2643  {
2645  << "Failed writing mesh " << regionMesh.name()
2646  << " at location " << regionMesh.facesInstance()
2647  << exit(FatalError);
2648  }
2649 
2650 
2651  // See if we need to extrude coordinates as well
2652  {
2653  autoPtr<pointIOField> patchFaceCentresPtr;
2654 
2655  IOobject io
2656  (
2657  "patchFaceCentres",
2658  mesh.pointsInstance(),
2659  mesh.meshSubDir,
2660  mesh,
2662  );
2663  if (io.typeHeaderOk<pointIOField>(true))
2664  {
2665  // Read patchFaceCentres and patchEdgeCentres
2666  Info<< "Reading patch face,edge centres : "
2667  << io.name() << " and patchEdgeCentres" << endl;
2668 
2669  extrudeGeometricProperties
2670  (
2671  mesh,
2672  extrudePatch,
2673  extruder,
2674  regionMesh,
2675  model()
2676  );
2677  }
2678  }
2679 
2680 
2681 
2682 
2683  // Insert baffles into original mesh
2684  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2685 
2686  autoPtr<mapPolyMesh> addBafflesMap;
2687 
2688  if (adaptMesh)
2689  {
2690  polyTopoChange meshMod(mesh);
2691 
2692  // Modify faces to be in bottom (= always coupled) patch
2693  forAll(extrudeMeshFaces, zoneFacei)
2694  {
2695  label meshFacei = extrudeMeshFaces[zoneFacei];
2696  label zoneI = zoneID[zoneFacei];
2697  bool flip = zoneFlipMap[zoneFacei];
2698  const face& f = mesh.faces()[meshFacei];
2699 
2700  if (!flip)
2701  {
2702  meshMod.modifyFace
2703  (
2704  f, // modified face
2705  meshFacei, // label of face being modified
2706  mesh.faceOwner()[meshFacei],// owner
2707  -1, // neighbour
2708  false, // face flip
2709  interMeshBottomPatch[zoneI],// patch for face
2710  meshZoneID[zoneI], // zone for face
2711  flip // face flip in zone
2712  );
2713  }
2714  else if (mesh.isInternalFace(meshFacei))
2715  {
2716  meshMod.modifyFace
2717  (
2718  f.reverseFace(), // modified face
2719  meshFacei, // label of modified face
2720  mesh.faceNeighbour()[meshFacei],// owner
2721  -1, // neighbour
2722  true, // face flip
2723  interMeshBottomPatch[zoneI], // patch for face
2724  meshZoneID[zoneI], // zone for face
2725  !flip // face flip in zone
2726  );
2727  }
2728  }
2729 
2730  if (zoneShadowNames.size() > 0) // if there is a top faceZone specified
2731  {
2732  forAll(extrudeMeshFaces, zoneFacei)
2733  {
2734  label meshFacei = extrudeMeshShadowFaces[zoneFacei];
2735  label zoneI = zoneShadowID[zoneFacei];
2736  bool flip = zoneShadowFlipMap[zoneFacei];
2737  const face& f = mesh.faces()[meshFacei];
2738 
2739  if (!flip)
2740  {
2741  meshMod.modifyFace
2742  (
2743  f, // modified face
2744  meshFacei, // face being modified
2745  mesh.faceOwner()[meshFacei],// owner
2746  -1, // neighbour
2747  false, // face flip
2748  interMeshTopPatch[zoneI], // patch for face
2749  meshZoneID[zoneI], // zone for face
2750  flip // face flip in zone
2751  );
2752  }
2753  else if (mesh.isInternalFace(meshFacei))
2754  {
2755  meshMod.modifyFace
2756  (
2757  f.reverseFace(), // modified face
2758  meshFacei, // label modified face
2759  mesh.faceNeighbour()[meshFacei],// owner
2760  -1, // neighbour
2761  true, // face flip
2762  interMeshTopPatch[zoneI], // patch for face
2763  meshZoneID[zoneI], // zone for face
2764  !flip // face flip in zone
2765  );
2766  }
2767  }
2768  }
2769  else
2770  {
2771  // Add faces (using same points) to be in top patch
2772  forAll(extrudeMeshFaces, zoneFacei)
2773  {
2774  label meshFacei = extrudeMeshFaces[zoneFacei];
2775  label zoneI = zoneID[zoneFacei];
2776  bool flip = zoneFlipMap[zoneFacei];
2777  const face& f = mesh.faces()[meshFacei];
2778 
2779  if (!flip)
2780  {
2781  if (mesh.isInternalFace(meshFacei))
2782  {
2783  meshMod.addFace
2784  (
2785  f.reverseFace(), // modified face
2786  mesh.faceNeighbour()[meshFacei],// owner
2787  -1, // neighbour
2788  -1, // master point
2789  -1, // master edge
2790  meshFacei, // master face
2791  true, // flip flux
2792  interMeshTopPatch[zoneI], // patch for face
2793  -1, // zone for face
2794  false // face flip in zone
2795  );
2796  }
2797  }
2798  else
2799  {
2800  meshMod.addFace
2801  (
2802  f, // face
2803  mesh.faceOwner()[meshFacei], // owner
2804  -1, // neighbour
2805  -1, // master point
2806  -1, // master edge
2807  meshFacei, // master face
2808  false, // flip flux
2809  interMeshTopPatch[zoneI], // patch for face
2810  -1, // zone for face
2811  false // zone flip
2812  );
2813  }
2814  }
2815  }
2816 
2817  // Change the mesh. Change points directly (no inflation).
2818  addBafflesMap = meshMod.changeMesh(mesh, false);
2819 
2820  // Update fields
2821  mesh.updateMesh(addBafflesMap);
2822 
2823 
2824 //XXXXXX
2825 // Update maps! e.g. faceToPatchFaceAddressing
2826 //XXXXXX
2827 
2828  // Move mesh (since morphing might not do this)
2829  if (addBafflesMap().hasMotionPoints())
2830  {
2831  mesh.movePoints(addBafflesMap().preMotionPoints());
2832  }
2833 
2834  mesh.setInstance(meshInstance);
2835 
2836  // Remove any unused patches
2837  deleteEmptyPatches(mesh);
2838 
2839  Info<< "Writing mesh " << mesh.name()
2840  << " to " << mesh.facesInstance() << nl
2841  << endl;
2842 
2843  if (!mesh.write())
2844  {
2846  << "Failed writing mesh " << mesh.name()
2847  << " at location " << mesh.facesInstance()
2848  << exit(FatalError);
2849  }
2850  }
2851 
2852  Info << "End\n" << endl;
2853 
2854  return 0;
2855 }
2856 
2857 
2858 // ************************************************************************* //
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:270
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:1072
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:266
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:297
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:1047
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:427
List< face > faceList
Definition: faceListFwd.H:43
label nCells() const
engineTime & runTime
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:256
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:421
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
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:626
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:1003
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:315
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:619
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:459
label nLayers() const
Definition: extrudeModel.C:59
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1041
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:1174
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:97
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:1028
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:265
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 occurrence 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:409
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:151
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