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