extrudeMesh.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-2023 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  extrudeMesh
26 
27 Description
28  Extrude mesh from existing patch (by default outwards facing normals;
29  optional flips faces) or from patch read from file.
30 
31  Note: Merges close points so be careful.
32 
33  Type of extrusion prescribed by run-time selectable model.
34 
35 \*---------------------------------------------------------------------------*/
36 
37 #include "argList.H"
38 #include "Time.H"
39 #include "polyTopoChange.H"
40 #include "polyTopoChanger.H"
41 #include "edgeCollapser.H"
42 #include "perfectInterface.H"
43 #include "addPatchCellLayer.H"
44 #include "fvMesh.H"
45 #include "MeshedSurfaces.H"
46 #include "globalIndex.H"
47 #include "cellSet.H"
48 #include "systemDict.H"
49 
50 #include "extrudedMesh.H"
51 #include "extrudeModel.H"
52 
53 #include "wedge.H"
54 #include "wedgePolyPatch.H"
55 #include "planeExtrusion.H"
56 #include "emptyPolyPatch.H"
57 #include "processorPolyPatch.H"
58 
59 using namespace Foam;
60 
61 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
62 
63 enum ExtrudeMode
64 {
65  MESH,
66  PATCH,
67  SURFACE
68 };
69 
70 namespace Foam
71 {
72  template<>
73  const char* NamedEnum<ExtrudeMode, 3>::names[] =
74  {
75  "mesh",
76  "patch",
77  "surface"
78  };
79 }
80 
81 static const NamedEnum<ExtrudeMode, 3> ExtrudeModeNames;
82 
83 
84 void createDummyFvMeshFiles(const polyMesh& mesh, const word& regionName)
85 {
86  // Create dummy system/fv*
87  {
89  (
90  "fvSchemes",
91  mesh.time().system(),
92  regionName,
93  mesh,
96  false
97  );
98 
99  Info<< "Testing:" << io.objectPath() << endl;
100 
101  if (!io.headerOk())
102  {
103  Info<< "Writing dummy " << regionName/io.name() << endl;
104  dictionary dummyDict;
105  dictionary divDict;
106  dummyDict.add("divSchemes", divDict);
107  dictionary gradDict;
108  dummyDict.add("gradSchemes", gradDict);
109  dictionary laplDict;
110  dummyDict.add("laplacianSchemes", laplDict);
111 
112  IOdictionary(io, dummyDict).regIOobject::write();
113  }
114  }
115  {
117  (
118  "fvSolution",
119  mesh.time().system(),
120  regionName,
121  mesh,
124  false
125  );
126 
127  if (!io.headerOk())
128  {
129  Info<< "Writing dummy " << regionName/io.name() << endl;
130  dictionary dummyDict;
131  IOdictionary(io, dummyDict).regIOobject::write();
132  }
133  }
134 }
135 
136 
137 label findPatchID(const polyBoundaryMesh& patches, const word& name)
138 {
139  const label patchID = patches.findPatchID(name);
140 
141  if (patchID == -1)
142  {
144  << "Cannot find patch " << name
145  << " in the source mesh.\n"
146  << "Valid patch names are " << patches.names()
147  << exit(FatalError);
148  }
149  return patchID;
150 }
151 
152 
153 labelList patchFaces(const polyBoundaryMesh& patches, const wordList& names)
154 {
155  label n = 0;
156 
157  forAll(names, i)
158  {
159  const polyPatch& pp = patches[findPatchID(patches, names[i])];
160 
161  n += pp.size();
162  }
163  labelList faceLabels(n);
164  n = 0;
165  forAll(names, i)
166  {
167  const polyPatch& pp = patches[findPatchID(patches, names[i])];
168 
169  forAll(pp, j)
170  {
171  faceLabels[n++] = pp.start()+j;
172  }
173  }
174 
175  return faceLabels;
176 }
177 
178 
179 void updateFaceLabels(const polyTopoChangeMap& map, labelList& faceLabels)
180 {
181  const labelList& reverseMap = map.reverseFaceMap();
182 
183  labelList newFaceLabels(faceLabels.size());
184  label newI = 0;
185 
186  forAll(faceLabels, i)
187  {
188  label oldFacei = faceLabels[i];
189 
190  if (reverseMap[oldFacei] >= 0)
191  {
192  newFaceLabels[newI++] = reverseMap[oldFacei];
193  }
194  }
195  newFaceLabels.setSize(newI);
196  faceLabels.transfer(newFaceLabels);
197 }
198 
199 
200 void updateCellSet(const polyTopoChangeMap& map, labelHashSet& cellLabels)
201 {
202  const labelList& reverseMap = map.reverseCellMap();
203 
204  labelHashSet newCellLabels(2*cellLabels.size());
205 
206  forAll(cellLabels, i)
207  {
208  label oldCelli = cellLabels[i];
209 
210  if (reverseMap[oldCelli] >= 0)
211  {
212  newCellLabels.insert(reverseMap[oldCelli]);
213  }
214  }
215  cellLabels.transfer(newCellLabels);
216 }
217 
218 
219 template<class PatchType>
220 void changeFrontBackPatches
221 (
222  polyMesh& mesh,
223  const word& frontPatchName,
224  const word& backPatchName
225 )
226 {
227  const polyBoundaryMesh& patches = mesh.boundaryMesh();
228 
229  label frontPatchi = findPatchID(patches, frontPatchName);
230  label backPatchi = findPatchID(patches, backPatchName);
231 
232  DynamicList<polyPatch*> newPatches(patches.size());
233 
235  {
236  const polyPatch& pp(patches[patchi]);
237 
238  if (patchi == frontPatchi || patchi == backPatchi)
239  {
240  newPatches.append
241  (
242  new PatchType
243  (
244  pp.name(),
245  pp.size(),
246  pp.start(),
247  pp.index(),
248  mesh.boundaryMesh(),
249  PatchType::typeName
250  )
251  );
252  }
253  else
254  {
255  newPatches.append(pp.clone(mesh.boundaryMesh()).ptr());
256  }
257  }
258 
259  // Edit patches
260  mesh.removeBoundary();
261  mesh.addPatches(newPatches, true);
262 }
263 
264 
265 int main(int argc, char *argv[])
266 {
267  #include "addRegionOption.H"
268  #include "addDictOption.H"
269 
270  #include "setRootCase.H"
271  #include "createTimeExtruded.H"
272 
273  // Get optional regionName
275  word regionDir;
276  if (args.optionReadIfPresent("region", regionName))
277  {
278  regionDir = regionName;
279  Info<< "Create mesh " << regionName << " for time = "
280  << runTimeExtruded.name() << nl << endl;
281  }
282  else
283  {
285  Info<< "Create mesh for time = "
286  << runTimeExtruded.name() << nl << endl;
287  }
288 
289  const dictionary dict(systemDict("extrudeMeshDict", args, runTimeExtruded));
290 
291  // Point generator
293 
294  // Whether to flip normals
295  const Switch flipNormals(dict.lookup("flipNormals"));
296 
297  // What to extrude
298  const ExtrudeMode mode = ExtrudeModeNames.read
299  (
300  dict.lookup("constructFrom")
301  );
302 
303  // Any merging of small edges
304  const scalar mergeTol(dict.lookupOrDefault<scalar>("mergeTol", 1e-4));
305 
306  Info<< "Extruding from " << ExtrudeModeNames[mode]
307  << " using model " << model().type() << endl;
308  if (flipNormals)
309  {
310  Info<< "Flipping normals before extruding" << endl;
311  }
312  if (mergeTol > 0)
313  {
314  Info<< "Collapsing edges < " << mergeTol << " of bounding box" << endl;
315  }
316  else
317  {
318  Info<< "Not collapsing any edges after extrusion" << endl;
319  }
320  Info<< endl;
321 
322 
323  // Generated mesh (one of either)
324  autoPtr<fvMesh> meshFromMesh;
325  autoPtr<polyMesh> meshFromSurface;
326 
327  // Faces on front and back for stitching (in case of mergeFaces)
328  word frontPatchName;
329  labelList frontPatchFaces;
330  word backPatchName;
331  labelList backPatchFaces;
332 
333  // Optional added cells (get written to cellSet)
334  labelHashSet addedCellsSet;
335 
336  if (mode == PATCH || mode == MESH)
337  {
338  if (flipNormals && mode == MESH)
339  {
341  << "Flipping normals not supported for extrusions from mesh."
342  << exit(FatalError);
343  }
344 
345  fileName sourceCasePath(dict.lookup("sourceCase"));
346  sourceCasePath.expand();
347  fileName sourceRootDir = sourceCasePath.path();
348  fileName sourceCaseDir = sourceCasePath.name();
349  if (Pstream::parRun())
350  {
351  sourceCaseDir =
352  sourceCaseDir
353  /"processor" + Foam::name(Pstream::myProcNo());
354  }
355  wordList sourcePatches;
356  dict.lookup("sourcePatches") >> sourcePatches;
357 
358  if (sourcePatches.size() == 1)
359  {
360  frontPatchName = sourcePatches[0];
361  }
362 
363  Info<< "Extruding patches " << sourcePatches
364  << " on mesh " << sourceCasePath << nl
365  << endl;
366 
367  Time runTime
368  (
370  sourceRootDir,
371  sourceCaseDir
372  );
373 
374  #include "createMeshNoChangers.H"
375 
376  const polyBoundaryMesh& patches = mesh.boundaryMesh();
377 
378 
379  // Extrusion engine. Either adding to existing mesh or
380  // creating separate mesh.
381  addPatchCellLayer layerExtrude(mesh, (mode == MESH));
382 
383  const labelList meshFaces(patchFaces(patches, sourcePatches));
384 
385  if (mode == PATCH && flipNormals)
386  {
387  // Cheat. Flip patch faces in mesh. This invalidates the
388  // mesh (open cells) but does produce the correct extrusion.
389  polyTopoChange meshMod(mesh);
390  forAll(meshFaces, i)
391  {
392  label meshFacei = meshFaces[i];
393 
394  label patchi = patches.whichPatch(meshFacei);
395  label own = mesh.faceOwner()[meshFacei];
396  label nei = -1;
397  if (patchi == -1)
398  {
399  nei = mesh.faceNeighbour()[meshFacei];
400  }
401 
402  label zoneI = mesh.faceZones().whichZone(meshFacei);
403  bool zoneFlip = false;
404  if (zoneI != -1)
405  {
406  label index = mesh.faceZones()[zoneI].whichFace(meshFacei);
407  zoneFlip = mesh.faceZones()[zoneI].flipMap()[index];
408  }
409 
410  meshMod.modifyFace
411  (
412  mesh.faces()[meshFacei].reverseFace(), // modified face
413  meshFacei, // label of face
414  own, // owner
415  nei, // neighbour
416  true, // face flip
417  patchi, // patch for face
418  zoneI, // zone for face
419  zoneFlip // face flip in zone
420  );
421  }
422 
423  // Change the mesh. No inflation.
424  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh, false);
425 
426  // Update fields
427  mesh.topoChange(map);
428 
429  // Move mesh (since morphing does not do this)
430  if (map().hasMotionPoints())
431  {
432  mesh.setPoints(map().preMotionPoints());
433  }
434  }
435 
436 
437 
438  indirectPrimitivePatch extrudePatch
439  (
441  (
442  mesh.faces(),
443  meshFaces
444  ),
445  mesh.points()
446  );
447 
448  // Determine extrudePatch normal
449  pointField extrudePatchPointNormals
450  (
451  PatchTools::pointNormals(mesh, extrudePatch)
452  );
453 
454 
455  // Precalculate mesh edges for pp.edges.
456  const labelList meshEdges
457  (
458  extrudePatch.meshEdges
459  (
460  mesh.edges(),
461  mesh.pointEdges()
462  )
463  );
464 
465  // Global face indices engine
466  const globalIndex globalFaces(mesh.nFaces());
467 
468  // Determine extrudePatch.edgeFaces in global numbering (so across
469  // coupled patches)
470  labelListList edgeGlobalFaces
471  (
473  (
474  mesh,
475  globalFaces,
476  extrudePatch
477  )
478  );
479 
480 
481  // Determine what patches boundary edges need to get extruded into.
482  // This might actually cause edge-connected processors to become
483  // face-connected so might need to introduce new processor boundaries.
484  // Calculates:
485  // - per pp.edge the patch to extrude into
486  // - any additional processor boundaries (patchToNbrProc = map from
487  // new patchID to neighbour processor)
488  // - number of new patches (nPatches)
489 
490  labelList sidePatchID;
491  label nPatches;
492  Map<label> nbrProcToPatch;
493  Map<label> patchToNbrProc;
495  (
496  mesh,
497  globalFaces,
498  edgeGlobalFaces,
499  extrudePatch,
500 
501  sidePatchID,
502  nPatches,
503  nbrProcToPatch,
504  patchToNbrProc
505  );
506 
507 
508  // Add any patches.
509 
510  label nAdded = nPatches - mesh.boundaryMesh().size();
511  reduce(nAdded, sumOp<label>());
512 
513  Info<< "Adding overall " << nAdded << " processor patches." << endl;
514 
515  if (nAdded > 0)
516  {
517  DynamicList<polyPatch*> newPatches(nPatches);
518  forAll(mesh.boundaryMesh(), patchi)
519  {
520  newPatches.append
521  (
522  mesh.boundaryMesh()[patchi].clone
523  (
524  mesh.boundaryMesh()
525  ).ptr()
526  );
527  }
528  for
529  (
530  label patchi = mesh.boundaryMesh().size();
531  patchi < nPatches;
532  patchi++
533  )
534  {
535  label nbrProci = patchToNbrProc[patchi];
536 
537  Pout<< "Adding patch " << patchi
538  << " between " << Pstream::myProcNo()
539  << " and " << nbrProci
540  << endl;
541 
542  newPatches.append
543  (
545  (
546  0, // size
547  mesh.nFaces(), // start
548  patchi, // index
549  mesh.boundaryMesh(),// polyBoundaryMesh
550  Pstream::myProcNo(),// myProcNo
551  nbrProci // neighbProcNo
552  )
553  );
554  }
555 
556  // Add patches. Do no parallel updates.
557  mesh.removeFvBoundary();
558  mesh.addFvPatches(newPatches, true);
559  }
560 
561 
562 
563  // Only used for addPatchCellLayer into new mesh
564  labelList exposedPatchID;
565  if (mode == PATCH)
566  {
567  dict.lookup("exposedPatchName") >> backPatchName;
568  exposedPatchID.setSize
569  (
570  extrudePatch.size(),
571  findPatchID(patches, backPatchName)
572  );
573  }
574 
575  // Determine points and extrusion
576  pointField layer0Points(extrudePatch.nPoints());
577  pointField displacement(extrudePatch.nPoints());
578  forAll(displacement, pointi)
579  {
580  const vector& patchNormal = extrudePatchPointNormals[pointi];
581 
582  // layer0 point
583  layer0Points[pointi] = model()
584  (
585  extrudePatch.localPoints()[pointi],
586  patchNormal,
587  0
588  );
589  // layerN point
590  point extrudePt = model()
591  (
592  extrudePatch.localPoints()[pointi],
593  patchNormal,
594  model().nLayers()
595  );
596  displacement[pointi] = extrudePt - layer0Points[pointi];
597  }
598 
599 
600  // Check if wedge (has layer0 different from original patch points)
601  // If so move the mesh to starting position.
602  if (gMax(mag(layer0Points-extrudePatch.localPoints())) > small)
603  {
604  Info<< "Moving mesh to layer0 points since differ from original"
605  << " points - this can happen for wedge extrusions." << nl
606  << endl;
607 
608  pointField newPoints(mesh.points());
609  forAll(extrudePatch.meshPoints(), i)
610  {
611  newPoints[extrudePatch.meshPoints()[i]] = layer0Points[i];
612  }
613  mesh.setPoints(newPoints);
614  }
615 
616 
617  // Layers per face
618  labelList nFaceLayers(extrudePatch.size(), model().nLayers());
619 
620  // Layers per point
621  labelList nPointLayers(extrudePatch.nPoints(), model().nLayers());
622 
623  // Displacement for first layer
624  vectorField firstLayerDisp(displacement*model().sumThickness(1));
625 
626  // Expansion ratio not used.
627  scalarField ratio(extrudePatch.nPoints(), 1.0);
628 
629  // Topo change container. Either copy an existing mesh or start
630  // with empty storage (number of patches only needed for checking)
632  (
633  (
634  mode == MESH
635  ? new polyTopoChange(mesh)
636  : new polyTopoChange(patches.size())
637  )
638  );
639 
640  layerExtrude.setRefinement
641  (
642  globalFaces,
643  edgeGlobalFaces,
644 
645  ratio, // expansion ratio
646  extrudePatch, // patch faces to extrude
647  sidePatchID, // if boundary edge: patch to use
648  exposedPatchID, // if new mesh: patches for exposed faces
649  nFaceLayers,
650  nPointLayers,
651  firstLayerDisp,
652  meshMod()
653  );
654 
655  // Reset points according to extrusion model
656  forAll(layerExtrude.addedPoints(), pointi)
657  {
658  const labelList& pPoints = layerExtrude.addedPoints()[pointi];
659  forAll(pPoints, pPointi)
660  {
661  label meshPointi = pPoints[pPointi];
662 
663  point modelPt
664  (
665  model()
666  (
667  extrudePatch.localPoints()[pointi],
668  extrudePatchPointNormals[pointi],
669  pPointi+1 // layer
670  )
671  );
672 
673  const_cast<DynamicList<point>&>
674  (
675  meshMod().points()
676  )[meshPointi] = modelPt;
677  }
678  }
679 
680  // Store faces on front and exposed patch (if mode=patch there are
681  // only added faces so cannot used map to old faces)
682  const labelListList& layerFaces = layerExtrude.layerFaces();
683  backPatchFaces.setSize(layerFaces.size());
684  frontPatchFaces.setSize(layerFaces.size());
685  forAll(backPatchFaces, patchFacei)
686  {
687  backPatchFaces[patchFacei] = layerFaces[patchFacei].first();
688  frontPatchFaces[patchFacei] = layerFaces[patchFacei].last();
689  }
690 
691 
692  // Create dummy fvSchemes, fvSolution
693  createDummyFvMeshFiles(mesh, regionDir);
694 
695  // Create actual mesh from polyTopoChange container
696  autoPtr<polyTopoChangeMap> map = meshMod().makeMesh
697  (
698  meshFromMesh,
699  IOobject
700  (
701  regionName,
702  runTimeExtruded.constant(),
703  runTimeExtruded,
706  false
707  ),
708  mesh
709  );
710 
711  layerExtrude.topoChange
712  (
713  map(),
714  identityMap(extrudePatch.size()),
715  identityMap(extrudePatch.nPoints())
716  );
717 
718  // Calculate face labels for front and back.
719  frontPatchFaces = renumber
720  (
721  map().reverseFaceMap(),
722  frontPatchFaces
723  );
724  backPatchFaces = renumber
725  (
726  map().reverseFaceMap(),
727  backPatchFaces
728  );
729 
730  // Store added cells
731  if (mode == MESH)
732  {
733  const labelListList addedCells
734  (
735  layerExtrude.addedCells
736  (
737  meshFromMesh,
738  layerExtrude.layerFaces()
739  )
740  );
741  forAll(addedCells, facei)
742  {
743  const labelList& aCells = addedCells[facei];
744  forAll(aCells, i)
745  {
746  addedCellsSet.insert(aCells[i]);
747  }
748  }
749  }
750  }
751  else
752  {
753  // Read from surface
754  fileName surfName(dict.lookup("surface"));
755  surfName.expand();
756 
757  Info<< "Extruding surfaceMesh read from file " << surfName << nl
758  << endl;
759 
760  MeshedSurface<face> fMesh(surfName);
761 
762  if (flipNormals)
763  {
764  Info<< "Flipping faces." << nl << endl;
765  faceList& faces = const_cast<faceList&>(fMesh.faces());
766  forAll(faces, i)
767  {
768  faces[i] = fMesh[i].reverseFace();
769  }
770  }
771 
772  Info<< "Extruding surface with :" << nl
773  << " points : " << fMesh.points().size() << nl
774  << " faces : " << fMesh.size() << nl
775  << " normals[0] : " << fMesh.faceNormals()[0]
776  << nl
777  << endl;
778 
779  meshFromSurface.reset
780  (
781  new extrudedMesh
782  (
783  IOobject
784  (
786  runTimeExtruded.constant(),
787  runTimeExtruded
788  ),
789  fMesh,
790  model()
791  )
792  );
793 
794 
795  // Get the faces on front and back
796  frontPatchName = "originalPatch";
797  frontPatchFaces = patchFaces
798  (
799  meshFromSurface().boundaryMesh(),
800  wordList(1, frontPatchName)
801  );
802  backPatchName = "otherSide";
803  backPatchFaces = patchFaces
804  (
805  meshFromSurface().boundaryMesh(),
806  wordList(1, backPatchName)
807  );
808  }
809 
810 
811  polyMesh& mesh =
812  (
813  meshFromMesh.valid()
814  ? meshFromMesh()
815  : meshFromSurface()
816  );
817 
818 
819  const boundBox& bb = mesh.bounds();
820  const vector span = bb.span();
821  const scalar mergeDim = mergeTol * bb.minDim();
822 
823  Info<< "Mesh bounding box : " << bb << nl
824  << " with span : " << span << nl
825  << "Merge distance : " << mergeDim << nl
826  << endl;
827 
828 
829  // Collapse edges
830  // ~~~~~~~~~~~~~~
831 
832  if (mergeDim > 0)
833  {
834  Pout<< "Collapsing edges < " << mergeDim << " ..." << nl << endl;
835 
836  // Edge collapsing engine
837  edgeCollapser collapser(mesh);
838 
839  const edgeList& edges = mesh.edges();
840  const pointField& points = mesh.points();
841 
843  Map<point> collapsePointToLocation(mesh.nPoints());
844 
845  forAll(edges, edgeI)
846  {
847  const edge& e = edges[edgeI];
848 
849  scalar d = e.mag(points);
850 
851  if (d < mergeDim)
852  {
853  Pout<< "Merging edge " << e << " since length " << d
854  << " << " << mergeDim << nl;
855 
856  collapseEdge[edgeI] = true;
857  collapsePointToLocation.set(e[1], points[e[0]]);
858  }
859  }
860 
861  List<pointEdgeCollapse> allPointInfo;
862  const globalIndex globalPoints(mesh.nPoints());
863  labelList pointPriority(mesh.nPoints(), 0);
864 
865  collapser.consistentCollapse
866  (
867  globalPoints,
868  pointPriority,
869  collapsePointToLocation,
870  collapseEdge,
871  allPointInfo
872  );
873 
874  // Topo change container
875  polyTopoChange meshMod(mesh);
876 
877  // Put all modifications into meshMod
878  bool anyChange = collapser.setRefinement(allPointInfo, meshMod);
879  reduce(anyChange, orOp<bool>());
880 
881  if (anyChange)
882  {
883  // Construct new mesh from polyTopoChange.
884  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh, false);
885 
886  // Update fields
887  mesh.topoChange(map);
888 
889  // Update stored data
890  updateFaceLabels(map(), frontPatchFaces);
891  updateFaceLabels(map(), backPatchFaces);
892  updateCellSet(map(), addedCellsSet);
893 
894  // Move mesh (if inflation used)
895  if (map().hasMotionPoints())
896  {
897  mesh.setPoints(map().preMotionPoints());
898  }
899  }
900  }
901 
902 
903  // Change the front and back patch types as required
904  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
905 
906  word frontBackType(word::null);
907 
908  if (isType<extrudeModels::wedge>(model()))
909  {
910  changeFrontBackPatches<wedgePolyPatch>
911  (
912  mesh,
913  frontPatchName,
914  backPatchName
915  );
916  }
917  else if (isType<extrudeModels::plane>(model()))
918  {
919  changeFrontBackPatches<emptyPolyPatch>
920  (
921  mesh,
922  frontPatchName,
923  backPatchName
924  );
925  }
926 
927 
928  // Merging front and back patch faces
929  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
930 
931  Switch mergeFaces(dict.lookup("mergeFaces"));
932  if (mergeFaces)
933  {
934  if (mode == MESH)
935  {
937  << "Cannot stitch front and back of extrusion since"
938  << " in 'mesh' mode (extrusion appended to mesh)."
939  << exit(FatalError);
940  }
941 
942  Info<< "Assuming full 360 degree axisymmetric case;"
943  << " stitching faces on patches "
944  << frontPatchName << " and "
945  << backPatchName << " together ..." << nl << endl;
946 
947  if (frontPatchFaces.size() != backPatchFaces.size())
948  {
950  << "Differing number of faces on front ("
951  << frontPatchFaces.size() << ") and back ("
952  << backPatchFaces.size() << ")"
953  << exit(FatalError);
954  }
955 
956 
957 
958  polyTopoChanger stitcher(mesh);
959  stitcher.setSize(1);
960 
961  const word cutZoneName("originalCutFaceZone");
962 
963  List<faceZone*> fz
964  (
965  1,
966  new faceZone
967  (
968  cutZoneName,
969  frontPatchFaces,
970  boolList(frontPatchFaces.size(), false),
971  0,
972  mesh.faceZones()
973  )
974  );
975 
976  mesh.addZones(List<pointZone*>(0), fz, List<cellZone*>(0));
977 
978  // Add the perfect interface mesh modifier
979  perfectInterface perfectStitcher
980  (
981  "couple",
982  0,
983  stitcher,
984  cutZoneName,
985  word::null, // dummy patch name
986  word::null // dummy patch name
987  );
988 
989  // Topo change container
990  polyTopoChange meshMod(mesh);
991 
992  perfectStitcher.setRefinement
993  (
995  (
997  (
998  mesh.faces(),
999  frontPatchFaces
1000  ),
1001  mesh.points()
1002  ),
1004  (
1006  (
1007  mesh.faces(),
1008  backPatchFaces
1009  ),
1010  mesh.points()
1011  ),
1012  meshMod
1013  );
1014 
1015  // Construct new mesh from polyTopoChange.
1016  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh, false);
1017 
1018  // Update fields
1019  mesh.topoChange(map);
1020 
1021  // Update local data
1022  updateCellSet(map(), addedCellsSet);
1023 
1024  // Move mesh (if inflation used)
1025  if (map().hasMotionPoints())
1026  {
1027  mesh.setPoints(map().preMotionPoints());
1028  }
1029  }
1030 
1031  mesh.setInstance(runTimeExtruded.constant());
1032  Info<< "Writing mesh to " << mesh.relativeObjectPath() << nl << endl;
1033 
1034  if (!mesh.write())
1035  {
1037  << exit(FatalError);
1038  }
1039 
1040  // Need writing cellSet
1041  label nAdded = returnReduce(addedCellsSet.size(), sumOp<label>());
1042  if (nAdded > 0)
1043  {
1044  cellSet addedCells(mesh, "addedCells", addedCellsSet);
1045  Info<< "Writing added cells to cellSet " << addedCells.name()
1046  << nl << endl;
1047  if (!addedCells.write())
1048  {
1050  << addedCells.name()
1051  << exit(FatalError);
1052  }
1053  }
1054 
1055  Info<< "End\n" << endl;
1056 
1057  return 0;
1058 }
1059 
1060 
1061 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:111
void transfer(HashTable< T, Key, Hash > &)
Transfer the contents of the argument table into this table.
Definition: HashTable.C:513
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:57
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
fileName relativeObjectPath() const
Return complete relativePath + object name.
Definition: IOobject.H:420
autoPtr< IOobject > clone() const
Clone.
Definition: IOobject.H:283
A List with indirect addressing.
Definition: IndirectList.H:105
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: MeshZones.C:221
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:54
Enum read(Istream &) const
Read a word from Istream and return the corresponding.
Definition: NamedEnum.C:61
A bit-packed bool list.
static tmp< pointField > pointNormals(const polyMesh &, const PrimitivePatch< FaceList, PointField > &)
Return parallel consistent point normals for patches using mesh points.
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
static const word & system()
Return system name.
Definition: TimePaths.H:112
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
static word controlDictName
The default control dictionary name (normally "controlDict")
Definition: Time.H:204
T & first()
Return the first element of the list.
Definition: UListI.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:128
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
Adds layers of cells to outside of polyPatch. Can optionally create stand-alone extruded mesh (addToM...
static void calcSidePatch(const polyMesh &, const globalIndex &globalFaces, const labelListList &globalEdgeFaces, const indirectPrimitivePatch &pp, labelList &sidePatchID, label &nPatches, Map< label > &nbrProcToPatch, Map< label > &patchToNbrProc)
Boundary edges get extruded into boundary faces. Determine patch.
static labelListList globalEdgeFaces(const polyMesh &, const globalIndex &globalFaces, const indirectPrimitivePatch &pp)
Per patch edge the pp faces (in global indices) using it. Uses.
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:204
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
void reset(T *=nullptr)
If object pointer already set, delete object and set to given.
Definition: autoPtrI.H:114
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
scalar minDim() const
Smallest length/height/width dimension.
Definition: boundBoxI.H:102
vector span() const
The bounding box span (from minimum to maximum)
Definition: boundBoxI.H:84
A collection of cell labels.
Definition: cellSet.H:51
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:860
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1169
Does polyTopoChanges to remove edges. Can remove faces due to edge collapse but can not remove cells ...
Definition: edgeCollapser.H:67
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
static autoPtr< extrudeModel > New(const dictionary &)
Select null constructed.
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:68
A class for handling file names.
Definition: fileName.H:82
word name() const
Return file name (part beyond last /)
Definition: fileName.C:195
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:265
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
Calculates points shared by more than two processor patches or cyclic patches.
Definition: globalPoints.H:101
const Time & time() const
Return time.
label index() const
Return the index of this patch in the boundaryMesh.
const word & name() const
Return name.
Hack of attachDetach to couple patches when they perfectly align. Does not decouple....
Foam::polyBoundaryMesh.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:268
const meshFaceZones & faceZones() const
Return face zones.
Definition: polyMesh.H:447
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1373
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1386
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:405
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1392
void addPatches(const List< polyPatch * > &, const bool validBoundary=true)
Add boundary patches.
Definition: polyMesh.C:1138
void addZones(const List< pointZone * > &pz, const List< faceZone * > &fz, const List< cellZone * > &cz)
Add mesh zones.
Definition: polyMesh.C:1182
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1360
void removeBoundary()
Remove boundary patches.
Definition: polyMeshClear.C:36
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:78
const boundBox & bounds() const
Return mesh bounding box.
Definition: polyMesh.H:411
virtual void setPoints(const pointField &)
Reset the points.
Definition: polyMesh.C:1448
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:280
virtual autoPtr< polyPatch > clone(const polyBoundaryMesh &bm) const
Construct and return a clone, resetting the boundary mesh.
Definition: polyPatch.H:215
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
const labelList & reverseCellMap() const
Reverse cell map.
const labelList & reverseFaceMap() const
Reverse face map.
Direct mesh changes based on v1.3 polyTopoChange syntax.
List of mesh modifiers defining the mesh dynamics.
label nEdges() const
label nPoints() const
const labelListList & pointEdges() const
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
label nFaces() const
Neighbour processor patch.
virtual bool write(const bool write=true) const
Write using setting from DB.
Templated form of IOobject providing type information for file reading and header type checking.
Definition: IOobject.H:531
A class for handling words, derived from string.
Definition: word.H:62
static const word null
An empty word.
Definition: word.H:77
label collapseEdge(triSurface &surf, const scalar minLen)
Keep collapsing all edges < minLen.
Foam::word regionName
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
int main(int argc, char *argv[])
Definition: financialFoam.C:44
label patchi
const pointField & points
const fvPatchList & patches
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< word > wordList
A List of words.
Definition: fileName.H:54
const doubleScalar e
Definition: doubleScalar.H:105
mode_t mode(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file mode.
Definition: POSIX.C:461
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
IOdictionary systemDict(const word &dictName, const argList &args, const objectRegistry &ob, const word &regionName=polyMesh::defaultRegion)
Definition: systemDict.C:92
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
messageStream Info
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< scalar > mag(const dimensioned< Type > &)
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
error FatalError
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
static const char nl
Definition: Ostream.H:260
Type gMax(const FieldField< Field, Type > &f)
label nPatches
Definition: readKivaGrid.H:396
dictionary dict
Foam::argList args(argc, argv)