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-2024 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 or from patch read from file.
29 
30  Type of extrusion prescribed by run-time selectable model.
31 
32 \*---------------------------------------------------------------------------*/
33 
34 #include "argList.H"
35 #include "Time.H"
36 #include "polyTopoChange.H"
37 #include "edgeCollapser.H"
38 #include "perfectInterface.H"
39 #include "addPatchCellLayer.H"
40 #include "fvMesh.H"
41 #include "MeshedSurfaces.H"
42 #include "globalIndex.H"
43 #include "cellSet.H"
44 #include "systemDict.H"
45 
46 #include "extrudedMesh.H"
47 #include "extrudeModel.H"
48 
49 #include "wedge.H"
50 #include "wedgePolyPatch.H"
51 #include "planeExtrusion.H"
52 #include "emptyPolyPatch.H"
53 #include "processorPolyPatch.H"
54 
55 using namespace Foam;
56 
57 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
58 
59 enum ExtrudeMode
60 {
61  MESH,
62  PATCH,
63  SURFACE
64 };
65 
66 namespace Foam
67 {
68  template<>
69  const char* NamedEnum<ExtrudeMode, 3>::names[] =
70  {
71  "mesh",
72  "patch",
73  "surface"
74  };
75 }
76 
77 static const NamedEnum<ExtrudeMode, 3> ExtrudeModeNames;
78 
79 
81 {
82  const label patchID = patches.findIndex(name);
83 
84  if (patchID == -1)
85  {
87  << "Cannot find patch " << name
88  << " in the source mesh.\n"
89  << "Valid patch names are " << patches.names()
90  << exit(FatalError);
91  }
92  return patchID;
93 }
94 
95 
96 labelList findPatchZones(polyMesh& mesh, const wordList& zoneNames)
97 {
98  labelList patchZones(zoneNames.size());
99 
100  // Add optional cellZone generation for the extrusion layer
101  forAll(zoneNames, i)
102  {
103  const label cellZonei = mesh.cellZones().findIndex(zoneNames[i]);
104  if (cellZonei >= 0)
105  {
106  patchZones[i] = cellZonei;
107  }
108  else
109  {
110  label nZones = mesh.cellZones().size();
111  mesh.cellZones().setSize(nZones + 1);
112  mesh.cellZones().set
113  (
114  nZones,
115  new cellZone
116  (
117  zoneNames[i],
118  labelList(),
119  mesh.cellZones()
120  )
121  );
122  patchZones[i] = nZones;
123  }
124  }
125 
126  return patchZones;
127 }
128 
129 
130 labelList findPatchFaces
131 (
132  polyMesh& mesh,
133  const polyBoundaryMesh& patches,
134  const wordList& patchNames,
135  const labelList& patchZones,
136  labelList& faceCellZones
137 )
138 {
139  // Count of the number of faces in the named patches
140  label n = 0;
141 
142  forAll(patchNames, i)
143  {
145  }
146 
147  labelList faceLabels(n);
148  faceCellZones.setSize(n);
149  n = 0;
150 
151  forAll(patchNames, i)
152  {
153  const polyPatch& pp = patches[findIndex(patches, patchNames[i])];
154 
155  forAll(pp, j)
156  {
157  faceLabels[n] = pp.start()+j;
158  faceCellZones[n] = patchZones[i];
159  n++;
160  }
161  }
162 
163  return faceLabels;
164 }
165 
166 
167 labelList findPatchFaces
168 (
169  const polyBoundaryMesh& patches,
170  const word& name
171 )
172 {
173  const polyPatch& pp = patches[findIndex(patches, name)];
174  labelList faceLabels(pp.size());
175 
176  forAll(pp, i)
177  {
178  faceLabels[i] = pp.start() + i;
179  }
180 
181  return faceLabels;
182 }
183 
184 
185 void updateFaceLabels(const polyTopoChangeMap& map, labelList& faceLabels)
186 {
187  const labelList& reverseMap = map.reverseFaceMap();
188 
189  labelList newFaceLabels(faceLabels.size());
190  label newI = 0;
191 
192  forAll(faceLabels, i)
193  {
194  label oldFacei = faceLabels[i];
195 
196  if (reverseMap[oldFacei] >= 0)
197  {
198  newFaceLabels[newI++] = reverseMap[oldFacei];
199  }
200  }
201  newFaceLabels.setSize(newI);
202  faceLabels.transfer(newFaceLabels);
203 }
204 
205 
206 void updateCellSet(const polyTopoChangeMap& map, labelHashSet& cellLabels)
207 {
208  const labelList& reverseMap = map.reverseCellMap();
209 
210  labelHashSet newCellLabels(2*cellLabels.size());
211 
212  forAll(cellLabels, i)
213  {
214  label oldCelli = cellLabels[i];
215 
216  if (reverseMap[oldCelli] >= 0)
217  {
218  newCellLabels.insert(reverseMap[oldCelli]);
219  }
220  }
221  cellLabels.transfer(newCellLabels);
222 }
223 
224 
225 template<class PatchType>
226 void changeFrontBackPatches
227 (
228  polyMesh& mesh,
229  const word& frontPatchName,
230  const word& backPatchName
231 )
232 {
233  const polyBoundaryMesh& patches = mesh.boundaryMesh();
234 
235  label frontPatchi = findIndex(patches, frontPatchName);
236  label backPatchi = findIndex(patches, backPatchName);
237 
238  DynamicList<polyPatch*> newPatches(patches.size());
239 
241  {
242  const polyPatch& pp(patches[patchi]);
243 
244  if (patchi == frontPatchi || patchi == backPatchi)
245  {
246  newPatches.append
247  (
248  new PatchType
249  (
250  pp.name(),
251  pp.size(),
252  pp.start(),
253  pp.index(),
254  mesh.boundaryMesh(),
255  PatchType::typeName
256  )
257  );
258  }
259  else
260  {
261  newPatches.append(pp.clone(mesh.boundaryMesh()).ptr());
262  }
263  }
264 
265  // Edit patches
266  mesh.removeBoundary();
267  mesh.addPatches(newPatches, true);
268 }
269 
270 
271 int main(int argc, char *argv[])
272 {
273  #include "addRegionOption.H"
274  #include "addDictOption.H"
275 
276  #include "setRootCase.H"
277  #include "createTimeExtruded.H"
278 
279  const dictionary dict(systemDict("extrudeMeshDict", args, runTimeExtruded));
280 
281  // Point generator
283 
284  // Whether to flip normals
285  const Switch flipNormals(dict.lookup("flipNormals"));
286 
287  // What to extrude
288  const ExtrudeMode mode = ExtrudeModeNames.read
289  (
290  dict.lookup("constructFrom")
291  );
292 
293  // Any merging of small edges
294  const scalar mergeTol(dict.lookupOrDefault<scalar>("mergeTol", 1e-4));
295 
296  Info<< "Extruding from " << ExtrudeModeNames[mode]
297  << " using model " << model().type() << endl;
298  if (flipNormals)
299  {
300  Info<< "Flipping normals before extruding" << endl;
301  }
302  if (mergeTol > 0)
303  {
304  Info<< "Collapsing edges < " << mergeTol << " of bounding box" << endl;
305  }
306  else
307  {
308  Info<< "Not collapsing any edges after extrusion" << endl;
309  }
310  Info<< endl;
311 
312 
313  // Generated mesh (one of either)
314  autoPtr<fvMesh> meshFromMesh;
315  autoPtr<polyMesh> meshFromSurface;
316 
317  // Faces on front and back for stitching (in case of mergeFaces)
318  word frontPatchName;
319  labelList frontPatchFaces;
320  word backPatchName;
321  labelList backPatchFaces;
322 
323  // Optional added cells (get written to cellSet)
324  labelHashSet addedCellsSet;
325 
326  if (mode == PATCH || mode == MESH)
327  {
328  if (flipNormals && mode == MESH)
329  {
331  << "Flipping normals not supported for extrusions from mesh."
332  << exit(FatalError);
333  }
334 
335  fileName sourceCasePath(dict.lookup("sourceCase"));
336  sourceCasePath.expand();
337  fileName sourceRootDir = sourceCasePath.path();
338  fileName sourceCaseDir = sourceCasePath.name();
339  if (Pstream::parRun())
340  {
341  sourceCaseDir =
342  sourceCaseDir
343  /"processor" + Foam::name(Pstream::myProcNo());
344  }
345  wordList sourcePatches(dict.lookup("sourcePatches"));
346 
347  if (sourcePatches.size() == 1)
348  {
349  frontPatchName = sourcePatches[0];
350  }
351 
352  wordList zoneNames(dict.lookupOrDefault("zoneNames", wordList::null()));
353  if (zoneNames.size() == 1)
354  {
355  if (zoneNames[0] == "patchNames")
356  {
357  zoneNames = sourcePatches;
358  }
359  else
360  {
361  zoneNames = wordList(sourcePatches.size(), zoneNames[0]);
362  }
363  }
364  else if (zoneNames.size() && zoneNames.size() != sourcePatches.size())
365  {
367  << "Number of zoneNames "
368  "does not equal the number of sourcePatches"
369  << exit(FatalError);
370  }
371 
372  Info<< "Extruding patches " << sourcePatches
373  << " on mesh " << sourceCasePath << nl
374  << endl;
375 
376  Time runTime
377  (
379  sourceRootDir,
380  sourceCaseDir
381  );
382 
384 
385  const polyBoundaryMesh& patches = mesh.boundaryMesh();
386 
387  const labelList patchZones
388  (
389  zoneNames.size()
390  ? findPatchZones(mesh, zoneNames)
391  : labelList(sourcePatches.size(), -1)
392  );
393 
394  labelList faceCellZones;
395  const labelList patchFaces
396  (
397  findPatchFaces
398  (
399  mesh,
400  patches,
401  sourcePatches,
402  patchZones,
403  faceCellZones
404  )
405  );
406 
407  // Extrusion engine. Either adding to existing mesh or
408  // creating separate mesh.
409  addPatchCellLayer layerExtrude(mesh, (mode == MESH));
410 
411  if (mode == PATCH && flipNormals)
412  {
413  // Cheat. Flip patch faces in mesh. This invalidates the
414  // mesh (open cells) but does produce the correct extrusion.
415  polyTopoChange meshMod(mesh);
416  forAll(patchFaces, i)
417  {
418  label patchFacei = patchFaces[i];
419 
420  label patchi = patches.whichPatch(patchFacei);
421  label own = mesh.faceOwner()[patchFacei];
422  label nei = -1;
423  if (patchi == -1)
424  {
425  nei = mesh.faceNeighbour()[patchFacei];
426  }
427 
428  meshMod.modifyFace
429  (
430  mesh.faces()[patchFacei].reverseFace(), // modified face
431  patchFacei, // label of face
432  own, // owner
433  nei, // neighbour
434  true, // face flip
435  patchi // patch for face
436  );
437  }
438 
439  // Change the mesh. without keeping old points.
440  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh);
441 
442  // Update fields
443  mesh.topoChange(map);
444  }
445 
446 
447  indirectPrimitivePatch extrudePatch
448  (
450  (
451  mesh.faces(),
452  patchFaces
453  ),
454  mesh.points()
455  );
456 
457  // Determine extrudePatch normal
458  pointField extrudePatchPointNormals
459  (
460  PatchTools::pointNormals(mesh, extrudePatch)
461  );
462 
463 
464  // Precalculate mesh edges for pp.edges.
465  const labelList meshEdges
466  (
467  extrudePatch.meshEdges
468  (
469  mesh.edges(),
470  mesh.pointEdges()
471  )
472  );
473 
474  // Global face indices engine
475  const globalIndex globalFaces(mesh.nFaces());
476 
477  // Determine extrudePatch.edgeFaces in global numbering (so across
478  // coupled patches)
479  labelListList edgeGlobalFaces
480  (
482  (
483  mesh,
484  globalFaces,
485  extrudePatch
486  )
487  );
488 
489 
490  // Determine what patches boundary edges need to get extruded into.
491  // This might actually cause edge-connected processors to become
492  // face-connected so might need to introduce new processor boundaries.
493  // Calculates:
494  // - per pp.edge the patch to extrude into
495  // - any additional processor boundaries (patchToNbrProc = map from
496  // new patchID to neighbour processor)
497  // - number of new patches (nPatches)
498 
499  labelList sidePatchID;
500  label nPatches;
501  Map<label> nbrProcToPatch;
502  Map<label> patchToNbrProc;
504  (
505  mesh,
506  globalFaces,
507  edgeGlobalFaces,
508  extrudePatch,
509 
510  sidePatchID,
511  nPatches,
512  nbrProcToPatch,
513  patchToNbrProc
514  );
515 
516 
517  // Add any patches
518 
519  label nAdded = nPatches - mesh.boundaryMesh().size();
520  reduce(nAdded, sumOp<label>());
521 
522  Info<< "Adding overall " << nAdded << " processor patches." << endl;
523 
524  if (nAdded > 0)
525  {
526  DynamicList<polyPatch*> newPatches(nPatches);
527  forAll(mesh.boundaryMesh(), patchi)
528  {
529  newPatches.append
530  (
531  mesh.boundaryMesh()[patchi].clone
532  (
533  mesh.boundaryMesh()
534  ).ptr()
535  );
536  }
537  for
538  (
539  label patchi = mesh.boundaryMesh().size();
540  patchi < nPatches;
541  patchi++
542  )
543  {
544  label nbrProci = patchToNbrProc[patchi];
545 
546  Pout<< "Adding patch " << patchi
547  << " between " << Pstream::myProcNo()
548  << " and " << nbrProci
549  << endl;
550 
551  newPatches.append
552  (
554  (
555  0, // size
556  mesh.nFaces(), // start
557  patchi, // index
558  mesh.boundaryMesh(),// polyBoundaryMesh
559  Pstream::myProcNo(),// myProcNo
560  nbrProci // neighbProcNo
561  )
562  );
563  }
564 
565  // Add patches. Do no parallel updates.
566  mesh.removeFvBoundary();
567  mesh.addFvPatches(newPatches, true);
568  }
569 
570 
571 
572  // Only used for addPatchCellLayer into new mesh
573  labelList exposedPatchID;
574  if (mode == PATCH)
575  {
576  dict.lookup("exposedPatchName") >> backPatchName;
577  exposedPatchID.setSize
578  (
579  extrudePatch.size(),
580  findIndex(patches, backPatchName)
581  );
582  }
583 
584  // Determine points and extrusion
585  pointField layer0Points(extrudePatch.nPoints());
586  pointField displacement(extrudePatch.nPoints());
587  forAll(displacement, pointi)
588  {
589  const vector& patchNormal = extrudePatchPointNormals[pointi];
590 
591  // layer0 point
592  layer0Points[pointi] = model()
593  (
594  extrudePatch.localPoints()[pointi],
595  patchNormal,
596  0
597  );
598  // layerN point
599  point extrudePt = model()
600  (
601  extrudePatch.localPoints()[pointi],
602  patchNormal,
603  model().nLayers()
604  );
605  displacement[pointi] = extrudePt - layer0Points[pointi];
606  }
607 
608 
609  // Check if wedge (has layer0 different from original patch points)
610  // If so move the mesh to starting position.
611  if (gMax(mag(layer0Points-extrudePatch.localPoints())) > small)
612  {
613  Info<< "Moving mesh to layer0 points since differ from original"
614  << " points - this can happen for wedge extrusions." << nl
615  << endl;
616 
617  pointField newPoints(mesh.points());
618  forAll(extrudePatch.meshPoints(), i)
619  {
620  newPoints[extrudePatch.meshPoints()[i]] = layer0Points[i];
621  }
622  mesh.setPoints(newPoints);
623  }
624 
625 
626  // Layers per face
627  labelList nFaceLayers(extrudePatch.size(), model().nLayers());
628 
629  // Layers per point
630  labelList nPointLayers(extrudePatch.nPoints(), model().nLayers());
631 
632  // Displacement for first layer
633  vectorField firstLayerDisp(displacement*model().sumThickness(1));
634 
635  // Expansion ratio not used.
636  scalarField ratio(extrudePatch.nPoints(), 1.0);
637 
638  // Topo change container. Either copy an existing mesh or start
639  // with empty storage (number of patches only needed for checking)
641  (
642  (
643  mode == MESH
644  ? new polyTopoChange(mesh)
645  : new polyTopoChange(patches.size())
646  )
647  );
648 
649  layerExtrude.setRefinement
650  (
651  globalFaces,
652  edgeGlobalFaces,
653 
654  ratio, // expansion ratio
655  extrudePatch, // patch faces to extrude
656  sidePatchID, // if boundary edge: patch to use
657  exposedPatchID, // if new mesh: patches for exposed faces
658  nFaceLayers,
659  nPointLayers,
660  firstLayerDisp,
661  faceCellZones,
662  meshMod()
663  );
664 
665  // Reset points according to extrusion model
666  forAll(layerExtrude.addedPoints(), pointi)
667  {
668  const labelList& pPoints = layerExtrude.addedPoints()[pointi];
669  forAll(pPoints, pPointi)
670  {
671  label meshPointi = pPoints[pPointi];
672 
673  point modelPt
674  (
675  model()
676  (
677  extrudePatch.localPoints()[pointi],
678  extrudePatchPointNormals[pointi],
679  pPointi+1 // layer
680  )
681  );
682 
683  const_cast<DynamicList<point>&>
684  (
685  meshMod().points()
686  )[meshPointi] = modelPt;
687  }
688  }
689 
690  // Store faces on front and exposed patch (if mode=patch there are
691  // only added faces so cannot used map to old faces)
692  const labelListList& layerFaces = layerExtrude.layerFaces();
693  backPatchFaces.setSize(layerFaces.size());
694  frontPatchFaces.setSize(layerFaces.size());
695  forAll(backPatchFaces, patchFacei)
696  {
697  backPatchFaces[patchFacei] = layerFaces[patchFacei].first();
698  frontPatchFaces[patchFacei] = layerFaces[patchFacei].last();
699  }
700 
701 
702  // Create actual mesh from polyTopoChange container
703  autoPtr<polyTopoChangeMap> map = meshMod().makeMesh
704  (
705  meshFromMesh,
706  IOobject
707  (
708  regionName,
709  runTimeExtruded.constant(),
710  runTimeExtruded,
713  false
714  ),
715  mesh
716  );
717 
718  layerExtrude.updateZones(meshFromMesh());
719 
720  meshFromMesh().topoChange(map);
721 
722  layerExtrude.topoChange
723  (
724  map(),
725  identityMap(extrudePatch.size()),
726  identityMap(extrudePatch.nPoints())
727  );
728 
729  // Calculate face labels for front and back.
730  frontPatchFaces = renumber
731  (
732  map().reverseFaceMap(),
733  frontPatchFaces
734  );
735  backPatchFaces = renumber
736  (
737  map().reverseFaceMap(),
738  backPatchFaces
739  );
740 
741  // Store added cells
742  if (mode == MESH)
743  {
744  const labelListList addedCells
745  (
746  layerExtrude.addedCells
747  (
748  meshFromMesh,
749  layerExtrude.layerFaces()
750  )
751  );
752  forAll(addedCells, facei)
753  {
754  const labelList& aCells = addedCells[facei];
755  forAll(aCells, i)
756  {
757  addedCellsSet.insert(aCells[i]);
758  }
759  }
760  }
761  }
762  else
763  {
764  // Read from surface
765  fileName surfName(dict.lookup("surface"));
766  surfName.expand();
767 
768  Info<< "Extruding surfaceMesh read from file " << surfName << nl
769  << endl;
770 
771  MeshedSurface<face> fMesh(surfName);
772 
773  if (flipNormals)
774  {
775  Info<< "Flipping faces." << nl << endl;
776  faceList& faces = const_cast<faceList&>(fMesh.faces());
777  forAll(faces, i)
778  {
779  faces[i] = fMesh[i].reverseFace();
780  }
781  }
782 
783  Info<< "Extruding surface with :" << nl
784  << " points : " << fMesh.points().size() << nl
785  << " faces : " << fMesh.size() << nl
786  << " normals[0] : " << fMesh.faceNormals()[0]
787  << nl
788  << endl;
789 
790  meshFromSurface.reset
791  (
792  new extrudedMesh
793  (
794  IOobject
795  (
797  runTimeExtruded.constant(),
798  runTimeExtruded
799  ),
800  fMesh,
801  model()
802  )
803  );
804 
805 
806  // Get the faces on front and back
807  frontPatchName = "originalPatch";
808  frontPatchFaces = findPatchFaces
809  (
810  meshFromSurface().boundaryMesh(),
811  frontPatchName
812  );
813  backPatchName = "otherSide";
814  backPatchFaces = findPatchFaces
815  (
816  meshFromSurface().boundaryMesh(),
817  backPatchName
818  );
819  }
820 
821 
822  polyMesh& mesh =
823  (
824  meshFromMesh.valid()
825  ? meshFromMesh()
826  : meshFromSurface()
827  );
828 
829 
830  const boundBox& bb = mesh.bounds();
831  const vector span = bb.span();
832  const scalar mergeDim = mergeTol * bb.minDim();
833 
834  Info<< "Mesh bounding box : " << bb << nl
835  << " with span : " << span << nl
836  << "Merge distance : " << mergeDim << nl
837  << endl;
838 
839 
840  // Collapse edges
841  // ~~~~~~~~~~~~~~
842 
843  if (mergeDim > 0)
844  {
845  Pout<< "Collapsing edges < " << mergeDim << " ..." << nl << endl;
846 
847  // Edge collapsing engine
848  edgeCollapser collapser(mesh);
849 
850  const edgeList& edges = mesh.edges();
851  const pointField& points = mesh.points();
852 
854  Map<point> collapsePointToLocation(mesh.nPoints());
855 
856  forAll(edges, edgeI)
857  {
858  const edge& e = edges[edgeI];
859 
860  scalar d = e.mag(points);
861 
862  if (d < mergeDim)
863  {
864  Pout<< "Merging edge " << e << " since length " << d
865  << " << " << mergeDim << nl;
866 
867  collapseEdge[edgeI] = true;
868  collapsePointToLocation.set(e[1], points[e[0]]);
869  }
870  }
871 
872  List<pointEdgeCollapse> allPointInfo;
873  const globalIndex globalPoints(mesh.nPoints());
874  labelList pointPriority(mesh.nPoints(), 0);
875 
876  collapser.consistentCollapse
877  (
878  globalPoints,
879  pointPriority,
880  collapsePointToLocation,
881  collapseEdge,
882  allPointInfo
883  );
884 
885  // Topo change container
886  polyTopoChange meshMod(mesh);
887 
888  // Put all modifications into meshMod
889  bool anyChange = collapser.setRefinement(allPointInfo, meshMod);
890  reduce(anyChange, orOp<bool>());
891 
892  if (anyChange)
893  {
894  // Construct new mesh from polyTopoChange.
895  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh);
896 
897  // Update fields
898  mesh.topoChange(map);
899 
900  // Update stored data
901  updateFaceLabels(map(), frontPatchFaces);
902  updateFaceLabels(map(), backPatchFaces);
903  updateCellSet(map(), addedCellsSet);
904  }
905  }
906 
907 
908  // Change the front and back patch types as required
909  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
910 
911  word frontBackType(word::null);
912 
913  if (isType<extrudeModels::wedge>(model()))
914  {
915  changeFrontBackPatches<wedgePolyPatch>
916  (
917  mesh,
918  frontPatchName,
919  backPatchName
920  );
921  }
922  else if (isType<extrudeModels::plane>(model()))
923  {
924  changeFrontBackPatches<emptyPolyPatch>
925  (
926  mesh,
927  frontPatchName,
928  backPatchName
929  );
930  }
931 
932 
933  // Merging front and back patch faces
934  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
935 
936  Switch mergeFaces(dict.lookup("mergeFaces"));
937  if (mergeFaces)
938  {
939  if (mode == MESH)
940  {
942  << "Cannot stitch front and back of extrusion since"
943  << " in 'mesh' mode (extrusion appended to mesh)."
944  << exit(FatalError);
945  }
946 
947  Info<< "Assuming full 360 degree axisymmetric case;"
948  << " stitching faces on patches "
949  << frontPatchName << " and "
950  << backPatchName << " together ..." << nl << endl;
951 
952  if (frontPatchFaces.size() != backPatchFaces.size())
953  {
955  << "Differing number of faces on front ("
956  << frontPatchFaces.size() << ") and back ("
957  << backPatchFaces.size() << ")"
958  << exit(FatalError);
959  }
960 
961  // Add the perfect interface mesh modifier
962  perfectInterface perfectStitcher
963  (
964  "couple",
965  mesh,
966  word::null, // dummy patch name
967  word::null // dummy patch name
968  );
969 
970  // Topo change container
971  polyTopoChange meshMod(mesh);
972 
973  perfectStitcher.setRefinement
974  (
976  (
978  (
979  mesh.faces(),
980  frontPatchFaces
981  ),
982  mesh.points()
983  ),
985  (
987  (
988  mesh.faces(),
989  backPatchFaces
990  ),
991  mesh.points()
992  ),
993  meshMod
994  );
995 
996  // Construct new mesh from polyTopoChange.
997  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh);
998 
999  // Update fields
1000  mesh.topoChange(map);
1001 
1002  // Update local data
1003  updateCellSet(map(), addedCellsSet);
1004  }
1005 
1006  mesh.setInstance(runTimeExtruded.constant());
1007  Info<< "Writing mesh to " << mesh.relativeObjectPath() << nl << endl;
1008 
1009  if (!mesh.write())
1010  {
1012  << exit(FatalError);
1013  }
1014 
1015  // Need writing cellSet
1016  label nAdded = returnReduce(addedCellsSet.size(), sumOp<label>());
1017  if (nAdded > 0)
1018  {
1019  cellSet addedCells(mesh, "addedCells", addedCellsSet);
1020  Info<< "Writing added cells to cellSet " << addedCells.name()
1021  << nl << endl;
1022  if (!addedCells.write())
1023  {
1025  << addedCells.name()
1026  << exit(FatalError);
1027  }
1028  }
1029 
1030  Info<< "End\n" << endl;
1031 
1032  return 0;
1033 }
1034 
1035 
1036 // ************************************************************************* //
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:109
void transfer(HashTable< T, Key, Hash > &)
Transfer the contents of the argument table into this table.
Definition: HashTable.C:587
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
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
static const List< word > & null()
Return a null List.
Definition: ListI.H:118
void setSize(const label)
Reset size of List.
Definition: List.C:281
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.
autoPtr< T > set(const label, const word &key, T *)
Set element to pointer provided and return old element.
label findIndex(const word &key) const
Return the index of the given the key or -1 if not found.
void setSize(const label)
Reset size of PtrList. If extending the PtrList, new entries are.
Definition: PtrList.C:131
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
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:208
T & first()
Return the first element of the list.
Definition: UListI.H:114
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
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.
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:108
vector span() const
The bounding box span (from minimum to maximum)
Definition: boundBoxI.H:90
A collection of cell labels.
Definition: cellSet.H:51
A subset of mesh cells.
Definition: cellZone.H:58
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T, if not found return the given default.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:710
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 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
label index() const
Return the index of this patch in the boundaryMesh.
const word & name() const
Return name.
Calculates zone number for every face of patch.
Definition: patchZones.H:56
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
const cellZoneList & cellZones() const
Return cell zones.
Definition: polyMesh.H:452
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:267
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1326
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1339
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:404
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1345
void addPatches(const List< polyPatch * > &, const bool validBoundary=true)
Add boundary patches.
Definition: polyMesh.C:1084
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1313
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:410
virtual void setPoints(const pointField &)
Reset the points.
Definition: polyMesh.C:1401
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.
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.
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.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
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:106
mode_t mode(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file mode.
Definition: POSIX.C:461
List< label > labelList
A List of labels.
Definition: labelList.H:56
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:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
const word & regionName(const solver &region)
Definition: solver.H:209
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
messageStream Info
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
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
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:266
Type gMax(const FieldField< Field, Type > &f)
wordList patchNames(nPatches)
label nPatches
Definition: readKivaGrid.H:396
dictionary dict
Foam::argList args(argc, argv)