PDRMesh.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  PDRMesh
29 
30 Group
31  grpMeshAdvancedUtilities
32 
33 Description
34  Mesh and field preparation utility for PDR type simulations.
35 
36  Reads
37  - cellSet giving blockedCells
38  - faceSets giving blockedFaces and the patch they should go into
39 
40  NOTE: To avoid exposing wrong fields values faceSets should include
41  faces contained in the blockedCells cellset.
42 
43  - coupledFaces reads coupledFacesSet to introduces mixed-coupled
44  duplicate baffles
45 
46  Subsets out the blocked cells and splits the blockedFaces and updates
47  fields.
48 
49  The face splitting is done by duplicating the faces. No duplication of
50  points for now (so checkMesh will show a lot of 'duplicate face' messages)
51 
52 \*---------------------------------------------------------------------------*/
53 
54 #include "fvMeshSubset.H"
55 #include "argList.H"
56 #include "cellSet.H"
57 #include "BitOps.H"
58 #include "IOobjectList.H"
59 #include "volFields.H"
60 #include "mapPolyMesh.H"
61 #include "faceSet.H"
62 #include "cellSet.H"
63 #include "pointSet.H"
64 #include "syncTools.H"
65 #include "ReadFields.H"
66 #include "polyTopoChange.H"
67 #include "polyModifyFace.H"
68 #include "polyAddFace.H"
69 #include "regionSplit.H"
70 #include "Tuple2.H"
71 #include "cyclicFvPatch.H"
72 
73 using namespace Foam;
74 
75 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
76 
77 void modifyOrAddFace
78 (
79  polyTopoChange& meshMod,
80  const face& f,
81  const label facei,
82  const label own,
83  const bool flipFaceFlux,
84  const label newPatchi,
85  const label zoneID,
86  const bool zoneFlip,
87 
88  bitSet& modifiedFace
89 )
90 {
91  if (modifiedFace.set(facei))
92  {
93  // First usage of face. Modify.
94  meshMod.setAction
95  (
97  (
98  f, // modified face
99  facei, // label of face
100  own, // owner
101  -1, // neighbour
102  flipFaceFlux, // face flip
103  newPatchi, // patch for face
104  false, // remove from zone
105  zoneID, // zone for face
106  zoneFlip // face flip in zone
107  )
108  );
109  }
110  else
111  {
112  // Second or more usage of face. Add.
113  meshMod.setAction
114  (
116  (
117  f, // modified face
118  own, // owner
119  -1, // neighbour
120  -1, // master point
121  -1, // master edge
122  facei, // master face
123  flipFaceFlux, // face flip
124  newPatchi, // patch for face
125  zoneID, // zone for face
126  zoneFlip // face flip in zone
127  )
128  );
129  }
130 }
131 
132 
133 template<class Type>
134 void subsetVolFields
135 (
136  const fvMeshSubset& subsetter,
137  const IOobjectList& objects,
138  const label patchi,
139  const Type& exposedValue,
141 )
142 {
144 
145  const fvMesh& baseMesh = subsetter.baseMesh();
146 
147  label nFields = 0;
148 
149  for (const word& fieldName : objects.sortedNames<GeoField>())
150  {
151  const IOobject* ioptr = objects.findObject(fieldName);
152 
153  if (!nFields)
154  {
155  Info<< "Subsetting " << GeoField::typeName << nl;
156  }
157  Info<< " " << fieldName << endl;
158 
159  GeoField origField(*ioptr, baseMesh);
160 
161  subFields.set(nFields, subsetter.interpolate(origField));
162 
163  // Explicitly set exposed faces (in patchi) to exposedValue.
164  if (patchi >= 0)
165  {
167  subFields[nFields].boundaryFieldRef()[patchi];
168 
169  const label newStart = fld.patch().patch().start();
170  const label oldPatchi = subsetter.patchMap()[patchi];
171 
172  if (oldPatchi == -1)
173  {
174  // New patch. Reset whole value.
175  fld = exposedValue;
176  }
177  else
178  {
179  // Reset faces that originate from different patch
180  // or internal faces.
181 
182  const fvPatchField<Type>& origPfld =
183  origField.boundaryField()[oldPatchi];
184 
185  const label oldSize = origPfld.size();
186  const label oldStart = origPfld.patch().patch().start();
187 
188  forAll(fld, j)
189  {
190  const label oldFacei = subsetter.faceMap()[newStart+j];
191 
192  if (oldFacei < oldStart || oldFacei >= oldStart+oldSize)
193  {
194  fld[j] = exposedValue;
195  }
196  }
197  }
198 
199  ++nFields;
200  }
201  }
202 }
203 
204 
205 template<class Type>
206 void subsetSurfaceFields
207 (
208  const fvMeshSubset& subsetter,
209  const IOobjectList& objects,
210  const label patchi,
211  const Type& exposedValue,
213 )
214 {
216 
217  const fvMesh& baseMesh = subsetter.baseMesh();
218 
219  label nFields = 0;
220 
221  for (const word& fieldName : objects.sortedNames<GeoField>())
222  {
223  const IOobject* ioptr = objects.findObject(fieldName);
224 
225  if (!nFields)
226  {
227  Info<< "Subsetting " << GeoField::typeName << nl;
228  }
229  Info<< " " << fieldName << endl;
230 
231  GeoField origField(*ioptr, baseMesh);
232 
233  subFields.set(nFields, subsetter.interpolate(origField));
234 
235  // Explicitly set exposed faces (in patchi) to exposedValue.
236  if (patchi >= 0)
237  {
239  subFields[nFields].boundaryFieldRef()[patchi];
240 
241  const label newStart = fld.patch().patch().start();
242  const label oldPatchi = subsetter.patchMap()[patchi];
243 
244  if (oldPatchi == -1)
245  {
246  // New patch. Reset whole value.
247  fld = exposedValue;
248  }
249  else
250  {
251  // Reset faces that originate from different patch
252  // or internal faces.
253 
254  const fvsPatchField<Type>& origPfld =
255  origField.boundaryField()[oldPatchi];
256 
257  const label oldSize = origPfld.size();
258  const label oldStart = origPfld.patch().patch().start();
259 
260  forAll(fld, j)
261  {
262  const label oldFacei = subsetter.faceMap()[newStart+j];
263 
264  if (oldFacei < oldStart || oldFacei >= oldStart+oldSize)
265  {
266  fld[j] = exposedValue;
267  }
268  }
269  }
270  }
271 
272  ++nFields;
273  }
274 }
275 
276 
277 // Faces introduced into zero-sized patches don't get a value at all.
278 // This is hack to set them to an initial value.
279 template<class GeoField>
280 void initCreatedPatches
281 (
282  const fvMesh& mesh,
283  const mapPolyMesh& map,
284  const typename GeoField::value_type initValue
285 )
286 {
288  (
289  mesh.objectRegistry::lookupClass<GeoField>()
290  );
291 
292  forAllIters(fields, fieldIter)
293  {
294  GeoField& field = const_cast<GeoField&>(*fieldIter());
295 
296  auto& fieldBf = field.boundaryFieldRef();
297 
298  forAll(fieldBf, patchi)
299  {
300  if (map.oldPatchSizes()[patchi] == 0)
301  {
302  // Not mapped.
303  fieldBf[patchi] = initValue;
304 
305  if (fieldBf[patchi].fixesValue())
306  {
307  fieldBf[patchi] == initValue;
308  }
309  }
310  }
311  }
312 }
313 
314 
315 template<class TopoSet>
316 void subsetTopoSets
317 (
318  const fvMesh& mesh,
319  const IOobjectList& objects,
320  const labelList& map,
321  const fvMesh& subMesh,
322  PtrList<TopoSet>& subSets
323 )
324 {
325  // Read original sets
326  PtrList<TopoSet> sets;
327  ReadFields<TopoSet>(objects, sets);
328 
329  subSets.resize(sets.size());
330  forAll(sets, seti)
331  {
332  TopoSet& set = sets[seti];
333 
334  Info<< "Subsetting " << set.type() << " " << set.name() << endl;
335 
336  // Map the data
337  bitSet isSet(set.maxSize(mesh));
338  for (const label id : set)
339  {
340  isSet.set(id);
341  }
342 
343  label nSet = 0;
344  for (const label id : map)
345  {
346  if (isSet.test(id))
347  {
348  ++nSet;
349  }
350  }
351 
352  subSets.set
353  (
354  seti,
355  new TopoSet(subMesh, set.name(), nSet, IOobject::AUTO_WRITE)
356  );
357  TopoSet& subSet = subSets[seti];
358 
359  forAll(map, i)
360  {
361  if (isSet.test(map[i]))
362  {
363  subSet.insert(i);
364  }
365  }
366  }
367 }
368 
369 
370 void createCoupledBaffles
371 (
372  fvMesh& mesh,
373  const labelList& coupledWantedPatch,
374  polyTopoChange& meshMod,
375  bitSet& modifiedFace
376 )
377 {
378  const faceZoneMesh& faceZones = mesh.faceZones();
379 
380  forAll(coupledWantedPatch, facei)
381  {
382  if (coupledWantedPatch[facei] != -1)
383  {
384  const face& f = mesh.faces()[facei];
385  label zoneID = faceZones.whichZone(facei);
386  bool zoneFlip = false;
387 
388  if (zoneID >= 0)
389  {
390  const faceZone& fZone = faceZones[zoneID];
391  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
392  }
393 
394  // Use owner side of face
395  modifyOrAddFace
396  (
397  meshMod,
398  f, // modified face
399  facei, // label of face
400  mesh.faceOwner()[facei], // owner
401  false, // face flip
402  coupledWantedPatch[facei], // patch for face
403  zoneID, // zone for face
404  zoneFlip, // face flip in zone
405  modifiedFace // modify or add status
406  );
407 
408  if (mesh.isInternalFace(facei))
409  {
410  label zoneID = faceZones.whichZone(facei);
411  bool zoneFlip = false;
412 
413  if (zoneID >= 0)
414  {
415  const faceZone& fZone = faceZones[zoneID];
416  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
417  }
418  // Use neighbour side of face
419  modifyOrAddFace
420  (
421  meshMod,
422  f.reverseFace(), // modified face
423  facei, // label of face
424  mesh.faceNeighbour()[facei],// owner
425  false, // face flip
426  coupledWantedPatch[facei], // patch for face
427  zoneID, // zone for face
428  zoneFlip, // face flip in zone
429  modifiedFace // modify or add status
430  );
431  }
432  }
433  }
434 }
435 
436 
437 void createCyclicCoupledBaffles
438 (
439  fvMesh& mesh,
440  const labelList& cyclicMasterPatch,
441  const labelList& cyclicSlavePatch,
442  polyTopoChange& meshMod,
443  bitSet& modifiedFace
444 )
445 {
446  const faceZoneMesh& faceZones = mesh.faceZones();
447 
448  forAll(cyclicMasterPatch, facei)
449  {
450  if (cyclicMasterPatch[facei] != -1)
451  {
452  const face& f = mesh.faces()[facei];
453 
454  label zoneID = faceZones.whichZone(facei);
455  bool zoneFlip = false;
456 
457  if (zoneID >= 0)
458  {
459  const faceZone& fZone = faceZones[zoneID];
460  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
461  }
462 
463  modifyOrAddFace
464  (
465  meshMod,
466  f.reverseFace(), // modified face
467  facei, // label of face
468  mesh.faceNeighbour()[facei], // owner
469  false, // face flip
470  cyclicMasterPatch[facei], // patch for face
471  zoneID, // zone for face
472  zoneFlip, // face flip in zone
473  modifiedFace // modify or add
474  );
475  }
476  }
477 
478  forAll(cyclicSlavePatch, facei)
479  {
480  if (cyclicSlavePatch[facei] != -1)
481  {
482  const face& f = mesh.faces()[facei];
483  if (mesh.isInternalFace(facei))
484  {
485  label zoneID = faceZones.whichZone(facei);
486  bool zoneFlip = false;
487 
488  if (zoneID >= 0)
489  {
490  const faceZone& fZone = faceZones[zoneID];
491  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
492  }
493  // Use owner side of face
494  modifyOrAddFace
495  (
496  meshMod,
497  f, // modified face
498  facei, // label of face
499  mesh.faceOwner()[facei], // owner
500  false, // face flip
501  cyclicSlavePatch[facei], // patch for face
502  zoneID, // zone for face
503  zoneFlip, // face flip in zone
504  modifiedFace // modify or add status
505  );
506  }
507  }
508  }
509 }
510 
511 
512 void createBaffles
513 (
514  fvMesh& mesh,
515  const labelList& wantedPatch,
516  polyTopoChange& meshMod
517 )
518 {
519  const faceZoneMesh& faceZones = mesh.faceZones();
520  Info << "faceZone:createBaffle " << faceZones << endl;
521  forAll(wantedPatch, facei)
522  {
523  if (wantedPatch[facei] != -1)
524  {
525  const face& f = mesh.faces()[facei];
526 
527  label zoneID = faceZones.whichZone(facei);
528  bool zoneFlip = false;
529 
530  if (zoneID >= 0)
531  {
532  const faceZone& fZone = faceZones[zoneID];
533  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
534  }
535 
536  meshMod.setAction
537  (
539  (
540  f, // modified face
541  facei, // label of face
542  mesh.faceOwner()[facei], // owner
543  -1, // neighbour
544  false, // face flip
545  wantedPatch[facei], // patch for face
546  false, // remove from zone
547  zoneID, // zone for face
548  zoneFlip // face flip in zone
549  )
550  );
551 
552  if (mesh.isInternalFace(facei))
553  {
554  label zoneID = faceZones.whichZone(facei);
555  bool zoneFlip = false;
556 
557  if (zoneID >= 0)
558  {
559  const faceZone& fZone = faceZones[zoneID];
560  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
561  }
562 
563  meshMod.setAction
564  (
566  (
567  f.reverseFace(), // modified face
568  mesh.faceNeighbour()[facei],// owner
569  -1, // neighbour
570  -1, // masterPointID
571  -1, // masterEdgeID
572  facei, // masterFaceID,
573  false, // face flip
574  wantedPatch[facei], // patch for face
575  zoneID, // zone for face
576  zoneFlip // face flip in zone
577  )
578  );
579  }
580  }
581  }
582 }
583 
584 
585 // Wrapper around find patch. Also makes sure same patch in parallel.
586 label findPatch(const polyBoundaryMesh& patches, const word& patchName)
587 {
588  const label patchi = patches.findPatchID(patchName);
589 
590  if (patchi == -1)
591  {
593  << "Illegal patch " << patchName
594  << nl << "Valid patches are " << patches.names()
595  << exit(FatalError);
596  }
597 
598  // Check same patch for all procs
599  {
600  const label newPatchi = returnReduce(patchi, minOp<label>());
601 
602  if (newPatchi != patchi)
603  {
605  << "Patch " << patchName
606  << " should have the same patch index on all processors." << nl
607  << "On my processor it has index " << patchi
608  << " ; on some other processor it has index " << newPatchi
609  << exit(FatalError);
610  }
611  }
612  return patchi;
613 }
614 
615 
616 
617 int main(int argc, char *argv[])
618 {
620  (
621  "Mesh and field preparation utility for PDR type simulations."
622  );
623  #include "addOverwriteOption.H"
624 
625  argList::noFunctionObjects(); // Never use function objects
626 
627  #include "setRootCase.H"
628  #include "createTime.H"
629  #include "createNamedMesh.H"
630 
631  // Read control dictionary
632  // ~~~~~~~~~~~~~~~~~~~~~~~
633 
635  (
636  IOobject
637  (
638  "PDRMeshDict",
639  runTime.system(),
640  mesh,
643  )
644  );
645 
646  // Per faceSet the patch to put the baffles into
647  const List<Pair<word>> setsAndPatches(dict.lookup("blockedFaces"));
648 
649  // Per faceSet the patch to put the coupled baffles into
650  DynamicList<FixedList<word, 3>> coupledAndPatches(10);
651 
652  const dictionary& functionDicts = dict.subDict("coupledFaces");
653 
654  for (const entry& dEntry : functionDicts)
655  {
656  if (!dEntry.isDict()) // Safety
657  {
658  continue;
659  }
660 
661  const word& key = dEntry.keyword();
662  const dictionary& dict = dEntry.dict();
663 
664  const word cyclicName = dict.get<word>("cyclicMasterPatch");
665  const word wallName = dict.get<word>("wallPatch");
666  FixedList<word, 3> nameAndType;
667  nameAndType[0] = key;
668  nameAndType[1] = wallName;
669  nameAndType[2] = cyclicName;
670  coupledAndPatches.append(nameAndType);
671  }
672 
673  forAll(setsAndPatches, setI)
674  {
675  Info<< "Faces in faceSet " << setsAndPatches[setI][0]
676  << " become baffles in patch " << setsAndPatches[setI][1]
677  << endl;
678  }
679 
680  forAll(coupledAndPatches, setI)
681  {
682  Info<< "Faces in faceSet " << coupledAndPatches[setI][0]
683  << " become coupled baffles in patch " << coupledAndPatches[setI][1]
684  << endl;
685  }
686 
687  // All exposed faces that are not explicitly marked to be put into a patch
688  const word defaultPatch(dict.get<word>("defaultPatch"));
689 
690  Info<< "Faces that get exposed become boundary faces in patch "
691  << defaultPatch << endl;
692 
693  const word blockedSetName(dict.get<word>("blockedCells"));
694 
695  Info<< "Reading blocked cells from cellSet " << blockedSetName
696  << endl;
697 
698  const bool overwrite = args.found("overwrite");
699 
700 
701  // Read faceSets, lookup patches
702  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
703 
704  // Check that face sets don't have coincident faces
705  labelList wantedPatch(mesh.nFaces(), -1);
706  forAll(setsAndPatches, setI)
707  {
708  faceSet fSet(mesh, setsAndPatches[setI][0]);
709 
710  label patchi = findPatch
711  (
712  mesh.boundaryMesh(),
713  setsAndPatches[setI][1]
714  );
715 
716  for (const label facei : fSet)
717  {
718  if (wantedPatch[facei] != -1)
719  {
721  << "Face " << facei
722  << " is in faceSet " << setsAndPatches[setI][0]
723  << " destined for patch " << setsAndPatches[setI][1]
724  << " but also in patch " << wantedPatch[facei]
725  << exit(FatalError);
726  }
727  wantedPatch[facei] = patchi;
728  }
729  }
730 
731  // Per face the patch for coupled baffle or -1.
732  labelList coupledWantedPatch(mesh.nFaces(), -1);
733  labelList cyclicWantedPatch_half0(mesh.nFaces(), -1);
734  labelList cyclicWantedPatch_half1(mesh.nFaces(), -1);
735 
736  forAll(coupledAndPatches, setI)
737  {
739  const label cyclicId =
740  findPatch(patches, coupledAndPatches[setI][2]);
741 
742  const label cyclicSlaveId = findPatch
743  (
744  patches,
745  refCast<const cyclicFvPatch>
746  (
747  mesh.boundary()[cyclicId]
748  ).neighbFvPatch().name()
749  );
750 
751  faceSet fSet(mesh, coupledAndPatches[setI][0]);
752  label patchi = findPatch(patches, coupledAndPatches[setI][1]);
753 
754  for (const label facei : fSet)
755  {
756  if (coupledWantedPatch[facei] != -1)
757  {
759  << "Face " << facei
760  << " is in faceSet " << coupledAndPatches[setI][0]
761  << " destined for patch " << coupledAndPatches[setI][1]
762  << " but also in patch " << coupledWantedPatch[facei]
763  << exit(FatalError);
764  }
765 
766  coupledWantedPatch[facei] = patchi;
767  cyclicWantedPatch_half0[facei] = cyclicId;
768  cyclicWantedPatch_half1[facei] = cyclicSlaveId;
769  }
770  }
771 
772  // Exposed faces patch
773  label defaultPatchi = findPatch(mesh.boundaryMesh(), defaultPatch);
774 
775 
776  //
777  // Removing blockedCells (like subsetMesh)
778  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
779  //
780 
781  // Mesh subsetting engine
782  fvMeshSubset subsetter
783  (
784  mesh,
786  (
787  mesh.nCells(),
788  cellSet(mesh, blockedSetName), // Blocked cells as labelHashSet
789  false // on=false: invert logic => retain the unblocked cells
790  ),
791  defaultPatchi,
792  true
793  );
794 
795 
796  // Subset wantedPatch. Note that might also include boundary faces
797  // that have been exposed by subsetting.
798  wantedPatch = IndirectList<label>(wantedPatch, subsetter.faceMap())();
799 
800  coupledWantedPatch = IndirectList<label>
801  (
802  coupledWantedPatch,
803  subsetter.faceMap()
804  )();
805 
806  cyclicWantedPatch_half0 = IndirectList<label>
807  (
808  cyclicWantedPatch_half0,
809  subsetter.faceMap()
810  )();
811 
812  cyclicWantedPatch_half1 = IndirectList<label>
813  (
814  cyclicWantedPatch_half1,
815  subsetter.faceMap()
816  )();
817 
818  // Read all fields in time and constant directories
819  IOobjectList objects(mesh, runTime.timeName());
820  {
821  IOobjectList timeObjects(mesh, mesh.facesInstance());
822 
823  // Transfer specific types
824  forAllIters(timeObjects, iter)
825  {
826  autoPtr<IOobject> objPtr(timeObjects.remove(iter));
827  const auto& obj = *objPtr;
828 
829  if
830  (
831  obj.isHeaderClass<volScalarField>()
832  || obj.isHeaderClass<volVectorField>()
833  || obj.isHeaderClass<volSphericalTensorField>()
834  || obj.isHeaderClass<volTensorField>()
835  || obj.isHeaderClass<volSymmTensorField>()
836  || obj.isHeaderClass<surfaceScalarField>()
837  || obj.isHeaderClass<surfaceVectorField>()
838  || obj.isHeaderClass<surfaceSphericalTensorField>()
839  || obj.isHeaderClass<surfaceSymmTensorField>()
840  || obj.isHeaderClass<surfaceTensorField>()
841  )
842  {
843  objects.add(objPtr);
844  }
845  }
846  }
847  // Read vol fields and subset.
848 
849  wordList scalarNames(objects.sortedNames<volScalarField>());
850  PtrList<volScalarField> scalarFlds(scalarNames.size());
851  subsetVolFields
852  (
853  subsetter,
854  objects,
855  defaultPatchi,
856  scalar(Zero),
857  scalarFlds
858  );
859 
860  wordList vectorNames(objects.sortedNames<volVectorField>());
861  PtrList<volVectorField> vectorFlds(vectorNames.size());
862  subsetVolFields
863  (
864  subsetter,
865  objects,
866  defaultPatchi,
867  vector(Zero),
868  vectorFlds
869  );
870 
871  wordList sphTensorNames
872  (
873  objects.sortedNames<volSphericalTensorField>()
874  );
876  (
877  sphTensorNames.size()
878  );
879  subsetVolFields
880  (
881  subsetter,
882  objects,
883  defaultPatchi,
885  sphTensorFlds
886  );
887 
888  wordList symmTensorNames(objects.sortedNames<volSymmTensorField>());
889  PtrList<volSymmTensorField> symmTensorFlds(symmTensorNames.size());
890  subsetVolFields
891  (
892  subsetter,
893  objects,
894  defaultPatchi,
895  symmTensor(Zero),
896  symmTensorFlds
897  );
898 
899  wordList tensorNames(objects.sortedNames<volTensorField>());
900  PtrList<volTensorField> tensorFlds(tensorNames.size());
901  subsetVolFields
902  (
903  subsetter,
904  objects,
905  defaultPatchi,
906  tensor(Zero),
907  tensorFlds
908  );
909 
910  // Read surface fields and subset.
911 
912  wordList surfScalarNames(objects.sortedNames<surfaceScalarField>());
913  PtrList<surfaceScalarField> surfScalarFlds(surfScalarNames.size());
914  subsetSurfaceFields
915  (
916  subsetter,
917  objects,
918  defaultPatchi,
919  scalar(Zero),
920  surfScalarFlds
921  );
922 
923  wordList surfVectorNames(objects.sortedNames<surfaceVectorField>());
924  PtrList<surfaceVectorField> surfVectorFlds(surfVectorNames.size());
925  subsetSurfaceFields
926  (
927  subsetter,
928  objects,
929  defaultPatchi,
930  vector(Zero),
931  surfVectorFlds
932  );
933 
934  wordList surfSphTensorNames
935  (
936  objects.sortedNames<surfaceSphericalTensorField>()
937  );
938  PtrList<surfaceSphericalTensorField> surfSphericalTensorFlds
939  (
940  surfSphTensorNames.size()
941  );
942  subsetSurfaceFields
943  (
944  subsetter,
945  objects,
946  defaultPatchi,
948  surfSphericalTensorFlds
949  );
950 
951  wordList surfSymmTensorNames
952  (
953  objects.sortedNames<surfaceSymmTensorField>()
954  );
955 
956  PtrList<surfaceSymmTensorField> surfSymmTensorFlds
957  (
958  surfSymmTensorNames.size()
959  );
960 
961  subsetSurfaceFields
962  (
963  subsetter,
964  objects,
965  defaultPatchi,
966  symmTensor(Zero),
967  surfSymmTensorFlds
968  );
969 
970  wordList surfTensorNames(objects.sortedNames<surfaceTensorField>());
971  PtrList<surfaceTensorField> surfTensorFlds(surfTensorNames.size());
972  subsetSurfaceFields
973  (
974  subsetter,
975  objects,
976  defaultPatchi,
977  tensor(Zero),
978  surfTensorFlds
979  );
980 
981 
982  // Set handling
983  PtrList<cellSet> cellSets;
984  PtrList<faceSet> faceSets;
985  PtrList<pointSet> pointSets;
986  {
987  IOobjectList objects(mesh, mesh.facesInstance(), "polyMesh/sets");
988  subsetTopoSets
989  (
990  mesh,
991  objects,
992  subsetter.cellMap(),
993  subsetter.subMesh(),
994  cellSets
995  );
996  subsetTopoSets
997  (
998  mesh,
999  objects,
1000  subsetter.faceMap(),
1001  subsetter.subMesh(),
1002  faceSets
1003  );
1004  subsetTopoSets
1005  (
1006  mesh,
1007  objects,
1008  subsetter.pointMap(),
1009  subsetter.subMesh(),
1010  pointSets
1011  );
1012  }
1013 
1014 
1015  if (!overwrite)
1016  {
1017  ++runTime;
1018  }
1019 
1020  Info<< "Writing mesh without blockedCells to time " << runTime.value()
1021  << endl;
1022 
1023  // Subsetting adds 'subset' prefix. Rename field to be like original.
1024  forAll(scalarFlds, i)
1025  {
1026  scalarFlds[i].rename(scalarNames[i]);
1027  scalarFlds[i].writeOpt(IOobject::AUTO_WRITE);
1028  }
1029  forAll(vectorFlds, i)
1030  {
1031  vectorFlds[i].rename(vectorNames[i]);
1032  vectorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1033  }
1034  forAll(sphTensorFlds, i)
1035  {
1036  sphTensorFlds[i].rename(sphTensorNames[i]);
1037  sphTensorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1038  }
1039  forAll(symmTensorFlds, i)
1040  {
1041  symmTensorFlds[i].rename(symmTensorNames[i]);
1042  symmTensorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1043  }
1044  forAll(tensorFlds, i)
1045  {
1046  tensorFlds[i].rename(tensorNames[i]);
1047  tensorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1048  }
1049 
1050  // Surface ones.
1051  forAll(surfScalarFlds, i)
1052  {
1053  surfScalarFlds[i].rename(surfScalarNames[i]);
1054  surfScalarFlds[i].writeOpt(IOobject::AUTO_WRITE);
1055  }
1056  forAll(surfVectorFlds, i)
1057  {
1058  surfVectorFlds[i].rename(surfVectorNames[i]);
1059  surfVectorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1060  }
1061  forAll(surfSphericalTensorFlds, i)
1062  {
1063  surfSphericalTensorFlds[i].rename(surfSphTensorNames[i]);
1064  surfSphericalTensorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1065  }
1066  forAll(surfSymmTensorFlds, i)
1067  {
1068  surfSymmTensorFlds[i].rename(surfSymmTensorNames[i]);
1069  surfSymmTensorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1070  }
1071  forAll(surfTensorNames, i)
1072  {
1073  surfTensorFlds[i].rename(surfTensorNames[i]);
1074  surfTensorFlds[i].writeOpt(IOobject::AUTO_WRITE);
1075  }
1076 
1077  subsetter.subMesh().write();
1078 
1079 
1080  //
1081  // Splitting blockedFaces
1082  // ~~~~~~~~~~~~~~~~~~~~~~
1083  //
1084 
1085  // Synchronize wantedPatch across coupled patches.
1087  (
1088  subsetter.subMesh(),
1089  wantedPatch,
1090  maxEqOp<label>()
1091  );
1092 
1093  // Synchronize coupledWantedPatch across coupled patches.
1095  (
1096  subsetter.subMesh(),
1097  coupledWantedPatch,
1098  maxEqOp<label>()
1099  );
1100 
1101  // Synchronize cyclicWantedPatch across coupled patches.
1103  (
1104  subsetter.subMesh(),
1105  cyclicWantedPatch_half0,
1106  maxEqOp<label>()
1107  );
1108 
1109  // Synchronize cyclicWantedPatch across coupled patches.
1111  (
1112  subsetter.subMesh(),
1113  cyclicWantedPatch_half1,
1114  maxEqOp<label>()
1115  );
1116 
1117  // Topochange container
1118  polyTopoChange meshMod(subsetter.subMesh());
1119 
1120 
1121  // Whether first use of face (modify) or consecutive (add)
1122  bitSet modifiedFace(mesh.nFaces());
1123 
1124  // Create coupled wall-side baffles
1125  createCoupledBaffles
1126  (
1127  subsetter.subMesh(),
1128  coupledWantedPatch,
1129  meshMod,
1130  modifiedFace
1131  );
1132 
1133  // Create coupled master/slave cyclic baffles
1134  createCyclicCoupledBaffles
1135  (
1136  subsetter.subMesh(),
1137  cyclicWantedPatch_half0,
1138  cyclicWantedPatch_half1,
1139  meshMod,
1140  modifiedFace
1141  );
1142 
1143  // Create wall baffles
1144  createBaffles
1145  (
1146  subsetter.subMesh(),
1147  wantedPatch,
1148  meshMod
1149  );
1150 
1151  if (!overwrite)
1152  {
1153  ++runTime;
1154  }
1155 
1156  // Change the mesh. Change points directly (no inflation).
1157  autoPtr<mapPolyMesh> mapPtr =
1158  meshMod.changeMesh(subsetter.subMesh(), false);
1159  mapPolyMesh& map = *mapPtr;
1160 
1161  // Update fields
1162  subsetter.subMesh().updateMesh(map);
1163 
1164  // Fix faces that get mapped to zero-sized patches (these don't get any
1165  // value)
1166  initCreatedPatches<volScalarField>
1167  (
1168  subsetter.subMesh(),
1169  map,
1170  Zero
1171  );
1172  initCreatedPatches<volVectorField>
1173  (
1174  subsetter.subMesh(),
1175  map,
1176  Zero
1177  );
1178  initCreatedPatches<volSphericalTensorField>
1179  (
1180  subsetter.subMesh(),
1181  map,
1182  Zero
1183  );
1184  initCreatedPatches<volSymmTensorField>
1185  (
1186  subsetter.subMesh(),
1187  map,
1188  Zero
1189  );
1190  initCreatedPatches<volTensorField>
1191  (
1192  subsetter.subMesh(),
1193  map,
1194  Zero
1195  );
1196 
1197  initCreatedPatches<surfaceScalarField>
1198  (
1199  subsetter.subMesh(),
1200  map,
1201  Zero
1202  );
1203  initCreatedPatches<surfaceVectorField>
1204  (
1205  subsetter.subMesh(),
1206  map,
1207  Zero
1208  );
1209  initCreatedPatches<surfaceSphericalTensorField>
1210  (
1211  subsetter.subMesh(),
1212  map,
1213  Zero
1214  );
1215  initCreatedPatches<surfaceSymmTensorField>
1216  (
1217  subsetter.subMesh(),
1218  map,
1219  Zero
1220  );
1221  initCreatedPatches<surfaceTensorField>
1222  (
1223  subsetter.subMesh(),
1224  map,
1225  Zero
1226  );
1227 
1228  // Update numbering of topoSets
1229  topoSet::updateMesh(subsetter.subMesh().facesInstance(), map, cellSets);
1230  topoSet::updateMesh(subsetter.subMesh().facesInstance(), map, faceSets);
1231  topoSet::updateMesh(subsetter.subMesh().facesInstance(), map, pointSets);
1232 
1233 
1234  // Move mesh (since morphing might not do this)
1235  if (map.hasMotionPoints())
1236  {
1237  subsetter.subMesh().movePoints(map.preMotionPoints());
1238  }
1239 
1240  Info<< "Writing mesh with split blockedFaces to time " << runTime.value()
1241  << endl;
1242 
1243  subsetter.subMesh().write();
1244 
1245 
1246  //
1247  // Removing inaccessible regions
1248  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1249  //
1250 
1251  // Determine connected regions. regionSplit is the labelList with the
1252  // region per cell.
1253  regionSplit cellRegion(subsetter.subMesh());
1254 
1255  if (cellRegion.nRegions() > 1)
1256  {
1258  << "Removing blocked faces and cells created "
1259  << cellRegion.nRegions()
1260  << " regions that are not connected via a face." << nl
1261  << " This is not supported in solvers." << nl
1262  << " Use" << nl << nl
1263  << " splitMeshRegions <root> <case> -largestOnly" << nl << nl
1264  << " to extract a single region of the mesh." << nl
1265  << " This mesh will be written to a new timedirectory"
1266  << " so might have to be moved back to constant/" << nl
1267  << endl;
1268 
1269  const word startFrom(runTime.controlDict().get<word>("startFrom"));
1270 
1271  if (startFrom != "latestTime")
1272  {
1274  << "To run splitMeshRegions please set your"
1275  << " startFrom entry to latestTime" << endl;
1276  }
1277  }
1278 
1279  Info<< "\nEnd\n" << endl;
1280 
1281  return 0;
1282 }
1283 
1284 
1285 // ************************************************************************* //
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:584
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:136
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return an entry data stream. FatalIOError if not found, or not a stream. ...
Definition: dictionary.C:379
const Type & value() const noexcept
Return const reference to value.
static tmp< DimensionedField< Type, volMesh > > interpolate(const DimensionedField< Type, volMesh > &, const fvMesh &sMesh, const labelUList &cellMap)
Map volume internal (dimensioned) field.
dictionary dict
static void noFunctionObjects(bool addWithOption=false)
Remove &#39;-noFunctionObjects&#39; option and ignore any occurrences.
Definition: argList.C:514
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:453
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
rDeltaTY field()
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:583
A list of face labels.
Definition: faceSet.H:47
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable, so the various sorted methods should be used if traversing in parallel.
Definition: IOobjectList.H:55
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Class describing modification of a face.
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:853
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:101
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
const fvPatch & patch() const noexcept
Return the patch.
Definition: fvPatchField.H:199
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1110
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:150
virtual bool write(const bool valid=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1072
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
wordList sortedNames() const
The sorted names of the IOobjects.
Definition: IOobjectList.C:301
engineTime & runTime
Tensor< scalar > tensor
Definition: symmTensor.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
virtual void movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: fvMesh.C:888
Required Variables.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:432
const fvPatch & patch() const noexcept
Return the patch.
Generic GeometricField class.
Definition: areaFieldsFwd.H:50
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:365
Field reading functions for post-processing utilities.
const fvMesh & baseMesh() const noexcept
Original mesh.
Definition: fvMeshSubsetI.H:23
Ignore writing from objectRegistry::writeObject()
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
label nFaces() const noexcept
Number of mesh faces.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:453
bool hasMotionPoints() const
Has valid preMotionPoints?
Definition: mapPolyMesh.H:764
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:157
A face addition data class. A face can be inflated either from a point or from another face and can e...
Definition: polyAddFace.H:47
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
const labelList & faceMap() const
Return face map.
Definition: fvMeshSubsetI.H:65
multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:97
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
const labelList & oldPatchSizes() const
Return list of the old patch sizes.
Definition: mapPolyMesh.H:773
const fvMesh & subMesh() const
Return reference to subset mesh.
Definition: fvMeshSubsetI.H:41
const labelList & patchMap() const
Return patch map.
Definition: fvMeshSubsetI.H:92
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
Definition: fvMesh.C:964
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition: symmTensor.H:55
A class for handling words, derived from Foam::string.
Definition: word.H:63
Reading required, file watched for runTime modification.
wordList names() const
Return a list of patch names.
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:99
const word & system() const noexcept
Return system name.
Definition: TimePathsI.H:95
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1104
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:328
const labelList & pointMap() const
Return point map.
Definition: fvMeshSubsetI.H:57
const IOobject * findObject(const word &objName) const
Return const pointer to the object found by name.
Definition: IOobjectList.C:211
const labelList & cellMap() const
Return cell map.
Definition: fvMeshSubsetI.H:84
Vector< scalar > vector
Definition: vector.H:57
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1091
A HashTable similar to std::unordered_map.
Definition: HashTable.H:102
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:163
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:760
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:646
labelList f(nPoints)
Holds a reference to the original mesh (the baseMesh) and optionally to a subset of that mesh (the su...
Definition: fvMeshSubset.H:75
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:95
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:276
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
#define WarningInFunction
Report a warning using Foam::Warning.
label nCells() const noexcept
Number of mesh cells.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
A collection of cell labels.
Definition: cellSet.H:47
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:79
Direct mesh changes based on v1.3 polyTopoChange syntax.
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:441
const polyBoundaryMesh & patches
Automatically write from objectRegistry::writeObject()
const dictionary & controlDict() const
Return read access to the controlDict dictionary.
Definition: Time.H:457
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:325
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars, i.e. SphericalTensor<scalar>.
bitSet create(const label n, const labelHashSet &locations, const bool on=true)
Create a bitSet with length n with the specified on locations.
Definition: BitOps.C:204
const polyPatch & patch() const noexcept
Return the polyPatch.
Definition: fvPatch.H:200
Foam::argList args(argc, argv)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
virtual void updateMesh(const mapPolyMesh &morphMap)
Update any stored data for new labels. Not implemented.
Definition: topoSet.C:612
A List with indirect addressing.
Definition: IndirectList.H:60
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
const pointField & preMotionPoints() const
Pre-motion point positions.
Definition: mapPolyMesh.H:756
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:705
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157