1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Mesh and field preparation utility for PDR type simulations.
29 - cellSet giving blockedCells
30 - faceSets giving blockedFaces and the patch they should go into
32 NOTE: To avoid exposing wrong fields values faceSets should include
33 faces contained in the blockedCells cellset.
35 - coupledFaces reads coupledFacesSet to introduces mixe-coupled baffles
37 Subsets out the blocked cells and splits the blockedFaces and updates
40 The face splitting is done by duplicating the faces. No duplication of
41 points for now (so checkMesh will show a lot of 'duplicate face' messages)
43 \*---------------------------------------------------------------------------*/
45 #include "fvMeshSubset.H"
48 #include "IOobjectList.H"
49 #include "volFields.H"
50 #include "mapPolyMesh.H"
53 #include "syncTools.H"
54 #include "polyTopoChange.H"
55 #include "polyModifyFace.H"
56 #include "polyAddFace.H"
57 #include "regionSplit.H"
59 #include "cyclicFvPatch.H"
63 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
67 polyTopoChange& meshMod,
71 const bool flipFaceFlux,
72 const label newPatchI,
76 PackedBoolList& modifiedFace
79 if (!modifiedFace[faceI])
81 // First usage of face. Modify.
87 faceI, // label of face
90 flipFaceFlux, // face flip
91 newPatchI, // patch for face
92 false, // remove from zone
93 zoneID, // zone for face
94 zoneFlip // face flip in zone
97 modifiedFace[faceI] = 1;
101 // Second or more usage of face. Add.
111 faceI, // master face
112 flipFaceFlux, // face flip
113 newPatchI, // patch for face
114 zoneID, // zone for face
115 zoneFlip // face flip in zone
125 const fvMeshSubset& subsetter,
126 const IOobjectList& objectsList,
128 const Type& exposedValue,
129 const word GeomVolType,
130 PtrList<GeometricField<Type, fvPatchField, volMesh> >& subFields
133 const fvMesh& baseMesh = subsetter.baseMesh();
137 forAllConstIter(IOobjectList , objectsList, iter)
139 if (iter()->headerClassName() == GeomVolType)
141 const word fieldName = iter()->name();
143 Info<< "Subsetting field " << fieldName << endl;
145 GeometricField<Type, fvPatchField, volMesh> volField
151 subFields.set(i, subsetter.interpolate(volField));
153 // Explicitly set exposed faces (in patchI) to exposedValue.
156 fvPatchField<Type>& fld =
157 subFields[i++].boundaryField()[patchI];
159 label newStart = fld.patch().patch().start();
161 label oldPatchI = subsetter.patchMap()[patchI];
165 // New patch. Reset whole value.
170 // Reset those faces that originate from different patch
171 // or internal faces.
172 label oldSize = volField.boundaryField()[oldPatchI].size();
173 label oldStart = volField.boundaryField()
176 ].patch().patch().start();
180 label oldFaceI = subsetter.faceMap()[newStart+j];
182 if(oldFaceI < oldStart || oldFaceI >= oldStart+oldSize)
184 fld[j] = exposedValue;
195 void subsetSurfaceFields
197 const fvMeshSubset& subsetter,
198 const IOobjectList& objectsList,
200 const Type& exposedValue,
201 const word GeomSurfType,
202 PtrList<GeometricField<Type, fvsPatchField, surfaceMesh> >& subFields
205 const fvMesh& baseMesh = subsetter.baseMesh();
209 forAllConstIter(IOobjectList , objectsList, iter)
211 if (iter()->headerClassName() == GeomSurfType)
213 const word& fieldName = iter.key();
215 Info<< "Subsetting field " << fieldName << endl;
217 GeometricField<Type, fvsPatchField, surfaceMesh> volField
223 subFields.set(i, subsetter.interpolate(volField));
226 // Explicitly set exposed faces (in patchI) to exposedValue.
229 fvsPatchField<Type>& fld =
230 subFields[i++].boundaryField()[patchI];
232 label newStart = fld.patch().patch().start();
234 label oldPatchI = subsetter.patchMap()[patchI];
238 // New patch. Reset whole value.
243 // Reset those faces that originate from different patch
244 // or internal faces.
245 label oldSize = volField.boundaryField()[oldPatchI].size();
246 label oldStart = volField.boundaryField()
249 ].patch().patch().start();
253 label oldFaceI = subsetter.faceMap()[newStart+j];
255 if(oldFaceI < oldStart || oldFaceI >= oldStart+oldSize)
257 fld[j] = exposedValue;
267 // Faces introduced into zero-sized patches don't get a value at all.
268 // This is hack to set them to an initial value.
269 template<class GeoField>
270 void initCreatedPatches
273 const mapPolyMesh& map,
274 const typename GeoField::value_type initValue
277 HashTable<const GeoField*> fields
279 mesh.objectRegistry::lookupClass<GeoField>()
284 typename HashTable<const GeoField*>::
285 iterator fieldIter = fields.begin();
286 fieldIter != fields.end();
290 GeoField& field = const_cast<GeoField&>(*fieldIter());
292 forAll(field.boundaryField(), patchi)
294 if (map.oldPatchSizes()[patchi] == 0)
297 field.boundaryField()[patchi] = initValue;
299 if (field.boundaryField()[patchi].fixesValue())
301 field.boundaryField()[patchi] == initValue;
309 void createCoupledBaffles
312 const labelList& coupledWantedPatch,
313 polyTopoChange& meshMod,
314 PackedBoolList& modifiedFace
317 const faceZoneMesh& faceZones = mesh.faceZones();
319 forAll(coupledWantedPatch, faceI)
321 if (coupledWantedPatch[faceI] != -1)
323 const face& f = mesh.faces()[faceI];
324 label zoneID = faceZones.whichZone(faceI);
325 bool zoneFlip = false;
329 const faceZone& fZone = faceZones[zoneID];
330 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
333 // Use owner side of face
338 faceI, // label of face
339 mesh.faceOwner()[faceI], // owner
341 coupledWantedPatch[faceI], // patch for face
342 zoneID, // zone for face
343 zoneFlip, // face flip in zone
344 modifiedFace // modify or add status
347 if (mesh.isInternalFace(faceI))
349 label zoneID = faceZones.whichZone(faceI);
350 bool zoneFlip = false;
354 const faceZone& fZone = faceZones[zoneID];
355 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
357 // Use neighbour side of face
361 f.reverseFace(), // modified face
362 faceI, // label of face
363 mesh.faceNeighbour()[faceI],// owner
365 coupledWantedPatch[faceI], // patch for face
366 zoneID, // zone for face
367 zoneFlip, // face flip in zone
368 modifiedFace // modify or add status
376 void createCyclicCoupledBaffles
379 const labelList& cyclicMasterPatch,
380 const labelList& cyclicSlavePatch,
381 polyTopoChange& meshMod,
382 PackedBoolList& modifiedFace
385 const faceZoneMesh& faceZones = mesh.faceZones();
387 forAll(cyclicMasterPatch, faceI)
389 if (cyclicMasterPatch[faceI] != -1)
391 const face& f = mesh.faces()[faceI];
393 label zoneID = faceZones.whichZone(faceI);
394 bool zoneFlip = false;
398 const faceZone& fZone = faceZones[zoneID];
399 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
405 f.reverseFace(), // modified face
406 faceI, // label of face
407 mesh.faceNeighbour()[faceI], // owner
409 cyclicMasterPatch[faceI], // patch for face
410 zoneID, // zone for face
411 zoneFlip, // face flip in zone
412 modifiedFace // modify or add
417 forAll(cyclicSlavePatch, faceI)
419 if (cyclicSlavePatch[faceI] != -1)
421 const face& f = mesh.faces()[faceI];
422 if (mesh.isInternalFace(faceI))
424 label zoneID = faceZones.whichZone(faceI);
425 bool zoneFlip = false;
429 const faceZone& fZone = faceZones[zoneID];
430 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
432 // Use owner side of face
437 faceI, // label of face
438 mesh.faceOwner()[faceI], // owner
440 cyclicSlavePatch[faceI], // patch for face
441 zoneID, // zone for face
442 zoneFlip, // face flip in zone
443 modifiedFace // modify or add status
454 const labelList& wantedPatch,
455 polyTopoChange& meshMod
458 const faceZoneMesh& faceZones = mesh.faceZones();
459 Info << "faceZone:createBaffle " << faceZones << endl;
460 forAll(wantedPatch, faceI)
462 if (wantedPatch[faceI] != -1)
464 const face& f = mesh.faces()[faceI];
466 label zoneID = faceZones.whichZone(faceI);
467 bool zoneFlip = false;
471 const faceZone& fZone = faceZones[zoneID];
472 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
480 faceI, // label of face
481 mesh.faceOwner()[faceI], // owner
484 wantedPatch[faceI], // patch for face
485 false, // remove from zone
486 zoneID, // zone for face
487 zoneFlip // face flip in zone
491 if (mesh.isInternalFace(faceI))
493 label zoneID = faceZones.whichZone(faceI);
494 bool zoneFlip = false;
498 const faceZone& fZone = faceZones[zoneID];
499 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
506 f.reverseFace(), // modified face
507 mesh.faceNeighbour()[faceI],// owner
511 faceI, // masterFaceID,
513 wantedPatch[faceI], // patch for face
514 zoneID, // zone for face
515 zoneFlip // face flip in zone
524 // Wrapper around find patch. Also makes sure same patch in parallel.
525 label findPatch(const polyBoundaryMesh& patches, const word& patchName)
527 label patchI = patches.findPatchID(patchName);
531 FatalErrorIn("findPatch(const polyBoundaryMesh&, const word&)")
532 << "Illegal patch " << patchName
533 << nl << "Valid patches are " << patches.names()
537 // Check same patch for all procs
539 label newPatch = patchI;
540 reduce(newPatch, minOp<label>());
542 if (newPatch != patchI)
544 FatalErrorIn("findPatch(const polyBoundaryMesh&, const word&)")
545 << "Patch " << patchName
546 << " should have the same patch index on all processors." << nl
547 << "On my processor it has index " << patchI
548 << " ; on some other processor it has index " << newPatch
558 int main(int argc, char *argv[])
560 #include "addOverwriteOption.H"
561 #include "setRootCase.H"
562 #include "createTime.H"
563 runTime.functionObjects().off();
564 #include "createMesh.H"
566 // Read control dictionary
567 // ~~~~~~~~~~~~~~~~~~~~~~~
576 IOobject::MUST_READ_IF_MODIFIED,
581 // Per faceSet the patch to put the baffles into
582 const List<Pair<word> > setsAndPatches(dict.lookup("blockedFaces"));
584 // Per faceSet the patch to put the coupled baffles into
585 DynamicList<FixedList<word, 3> > coupledAndPatches(10);
586 const dictionary& functionDicts = dict.subDict("coupledFaces");
587 forAllConstIter(dictionary, functionDicts, iter)
590 if (!iter().isDict())
594 const word& key = iter().keyword();
596 const dictionary& dict = iter().dict();
597 const word cyclicName = dict.lookup("cyclicMasterPatchName");
598 const word wallName = dict.lookup("wallPatchName");
599 FixedList<word, 3> nameAndType;
600 nameAndType[0] = key;
601 nameAndType[1] = wallName;
602 nameAndType[2] = cyclicName;
603 coupledAndPatches.append(nameAndType);
606 forAll(setsAndPatches, setI)
608 Info<< "Faces in faceSet " << setsAndPatches[setI][0]
609 << " become baffles in patch " << setsAndPatches[setI][1]
613 forAll(coupledAndPatches, setI)
615 Info<< "Faces in faceSet " << coupledAndPatches[setI][0]
616 << " become coupled baffles in patch " << coupledAndPatches[setI][1]
620 // All exposed faces that are not explicitly marked to be put into a patch
621 const word defaultPatch(dict.lookup("defaultPatch"));
623 Info<< "Faces that get exposed become boundary faces in patch "
624 << defaultPatch << endl;
626 const word blockedSetName(dict.lookup("blockedCells"));
628 Info<< "Reading blocked cells from cellSet " << blockedSetName
631 const bool overwrite = args.optionFound("overwrite");
634 // Read faceSets, lookup patches
635 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
637 // Check that face sets don't have coincident faces
638 labelList wantedPatch(mesh.nFaces(), -1);
639 forAll(setsAndPatches, setI)
641 faceSet fSet(mesh, setsAndPatches[setI][0]);
643 label patchI = findPatch
646 setsAndPatches[setI][1]
649 forAllConstIter(faceSet, fSet, iter)
651 if (wantedPatch[iter.key()] != -1)
653 FatalErrorIn(args.executable())
654 << "Face " << iter.key()
655 << " is in faceSet " << setsAndPatches[setI][0]
656 << " destined for patch " << setsAndPatches[setI][1]
657 << " but also in patch " << wantedPatch[iter.key()]
660 wantedPatch[iter.key()] = patchI;
664 // Per face the patch for coupled baffle or -1.
665 labelList coupledWantedPatch(mesh.nFaces(), -1);
666 labelList cyclicWantedPatch_half0(mesh.nFaces(), -1);
667 labelList cyclicWantedPatch_half1(mesh.nFaces(), -1);
669 forAll(coupledAndPatches, setI)
671 const polyBoundaryMesh& patches = mesh.boundaryMesh();
672 const label cyclicId =
673 findPatch(patches, coupledAndPatches[setI][2]);
675 const label cyclicSlaveId = findPatch
678 refCast<const cyclicFvPatch>
680 mesh.boundary()[cyclicId]
681 ).neighbFvPatch().name()
684 faceSet fSet(mesh, coupledAndPatches[setI][0]);
685 label patchI = findPatch(patches, coupledAndPatches[setI][1]);
687 forAllConstIter(faceSet, fSet, iter)
689 if (coupledWantedPatch[iter.key()] != -1)
691 FatalErrorIn(args.executable())
692 << "Face " << iter.key()
693 << " is in faceSet " << coupledAndPatches[setI][0]
694 << " destined for patch " << coupledAndPatches[setI][1]
695 << " but also in patch " << coupledWantedPatch[iter.key()]
698 coupledWantedPatch[iter.key()] = patchI;
699 cyclicWantedPatch_half0[iter.key()] = cyclicId;
700 cyclicWantedPatch_half1[iter.key()] = cyclicSlaveId;
704 // Exposed faces patch
705 label defaultPatchI = findPatch(mesh.boundaryMesh(), defaultPatch);
709 // Removing blockedCells (like subsetMesh)
710 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
713 // Create mesh subsetting engine
714 fvMeshSubset subsetter(mesh);
718 cellSet blockedCells(mesh, blockedSetName);
721 blockedCells.invert(mesh.nCells());
723 // Create subsetted mesh.
724 subsetter.setLargeCellSubset(blockedCells, defaultPatchI, true);
728 // Subset wantedPatch. Note that might also include boundary faces
729 // that have been exposed by subsetting.
730 wantedPatch = IndirectList<label>(wantedPatch, subsetter.faceMap())();
732 coupledWantedPatch = IndirectList<label>
738 cyclicWantedPatch_half0 = IndirectList<label>
740 cyclicWantedPatch_half0,
744 cyclicWantedPatch_half1 = IndirectList<label>
746 cyclicWantedPatch_half1,
750 // Read all fields in time and constant folders
751 IOobjectList objects(mesh, runTime.timeName());
752 IOobjectList timeObjects(IOobjectList(mesh, mesh.facesInstance()));
753 forAllConstIter(IOobjectList, timeObjects, iter)
757 iter()->headerClassName() == volScalarField::typeName
758 || iter()->headerClassName() == volVectorField::typeName
759 || iter()->headerClassName() == volSphericalTensorField::typeName
760 || iter()->headerClassName() == volTensorField::typeName
761 || iter()->headerClassName() == volSymmTensorField::typeName
762 || iter()->headerClassName() == surfaceScalarField::typeName
763 || iter()->headerClassName() == surfaceVectorField::typeName
764 || iter()->headerClassName()
765 == surfaceSphericalTensorField::typeName
766 || iter()->headerClassName() == surfaceSymmTensorField::typeName
767 || iter()->headerClassName() == surfaceTensorField::typeName
770 objects.add(*iter());
774 // Read vol fields and subset.
776 wordList scalarNames(objects.names(volScalarField::typeName));
777 PtrList<volScalarField> scalarFlds(scalarNames.size());
783 pTraits<scalar>::zero,
784 volScalarField::typeName,
788 wordList vectorNames(objects.names(volVectorField::typeName));
789 PtrList<volVectorField> vectorFlds(vectorNames.size());
795 pTraits<vector>::zero,
796 volVectorField::typeName,
800 wordList sphericalTensorNames
802 objects.names(volSphericalTensorField::typeName)
804 PtrList<volSphericalTensorField> sphericalTensorFlds
806 sphericalTensorNames.size()
813 pTraits<sphericalTensor>::zero,
814 volSphericalTensorField::typeName,
818 wordList symmTensorNames(objects.names(volSymmTensorField::typeName));
819 PtrList<volSymmTensorField> symmTensorFlds(symmTensorNames.size());
825 pTraits<symmTensor>::zero,
826 volSymmTensorField::typeName,
830 wordList tensorNames(objects.names(volTensorField::typeName));
831 PtrList<volTensorField> tensorFlds(tensorNames.size());
837 pTraits<tensor>::zero,
838 volTensorField::typeName,
842 // Read surface fields and subset.
844 wordList surfScalarNames(objects.names(surfaceScalarField::typeName));
845 PtrList<surfaceScalarField> surfScalarFlds(surfScalarNames.size());
851 pTraits<scalar>::zero,
852 surfaceScalarField::typeName,
856 wordList surfVectorNames(objects.names(surfaceVectorField::typeName));
857 PtrList<surfaceVectorField> surfVectorFlds(surfVectorNames.size());
863 pTraits<vector>::zero,
864 surfaceVectorField::typeName,
868 wordList surfSphericalTensorNames
870 objects.names(surfaceSphericalTensorField::typeName)
872 PtrList<surfaceSphericalTensorField> surfSphericalTensorFlds
874 surfSphericalTensorNames.size()
881 pTraits<sphericalTensor>::zero,
882 surfaceSphericalTensorField::typeName,
883 surfSphericalTensorFlds
886 wordList surfSymmTensorNames
888 objects.names(surfaceSymmTensorField::typeName)
891 PtrList<surfaceSymmTensorField> surfSymmTensorFlds
893 surfSymmTensorNames.size()
901 pTraits<symmTensor>::zero,
902 surfaceSymmTensorField::typeName,
906 wordList surfTensorNames(objects.names(surfaceTensorField::typeName));
907 PtrList<surfaceTensorField> surfTensorFlds(surfTensorNames.size());
913 pTraits<tensor>::zero,
914 surfaceTensorField::typeName,
923 Info<< "Writing mesh without blockedCells to time " << runTime.value()
926 // Subsetting adds 'subset' prefix. Rename field to be like original.
927 forAll(scalarFlds, i)
929 scalarFlds[i].rename(scalarNames[i]);
930 scalarFlds[i].writeOpt() = IOobject::AUTO_WRITE;
932 forAll(vectorFlds, i)
934 vectorFlds[i].rename(vectorNames[i]);
935 vectorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
937 forAll(sphericalTensorFlds, i)
939 sphericalTensorFlds[i].rename(sphericalTensorNames[i]);
940 sphericalTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
942 forAll(symmTensorFlds, i)
944 symmTensorFlds[i].rename(symmTensorNames[i]);
945 symmTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
947 forAll(tensorFlds, i)
949 tensorFlds[i].rename(tensorNames[i]);
950 tensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
954 forAll(surfScalarFlds, i)
956 surfScalarFlds[i].rename(surfScalarNames[i]);
957 surfScalarFlds[i].writeOpt() = IOobject::AUTO_WRITE;
959 forAll(surfVectorFlds, i)
961 surfVectorFlds[i].rename(surfVectorNames[i]);
962 surfVectorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
964 forAll(surfSphericalTensorFlds, i)
966 surfSphericalTensorFlds[i].rename(surfSphericalTensorNames[i]);
967 surfSphericalTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
969 forAll(surfSymmTensorFlds, i)
971 surfSymmTensorFlds[i].rename(surfSymmTensorNames[i]);
972 surfSymmTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
974 forAll(surfTensorNames, i)
976 surfTensorFlds[i].rename(surfTensorNames[i]);
977 surfTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
980 subsetter.subMesh().write();
984 // Splitting blockedFaces
985 // ~~~~~~~~~~~~~~~~~~~~~~
988 // Synchronize wantedPatch across coupled patches.
989 syncTools::syncFaceList
996 // Synchronize coupledWantedPatch across coupled patches.
997 syncTools::syncFaceList
1004 // Synchronize cyclicWantedPatch across coupled patches.
1005 syncTools::syncFaceList
1007 subsetter.subMesh(),
1008 cyclicWantedPatch_half0,
1012 // Synchronize cyclicWantedPatch across coupled patches.
1013 syncTools::syncFaceList
1015 subsetter.subMesh(),
1016 cyclicWantedPatch_half1,
1020 // Topochange container
1021 polyTopoChange meshMod(subsetter.subMesh());
1024 // Whether first use of face (modify) or consecutive (add)
1025 PackedBoolList modifiedFace(mesh.nFaces());
1027 // Create coupled wall-side baffles
1028 createCoupledBaffles
1030 subsetter.subMesh(),
1036 // Create coupled master/slave cyclic baffles
1037 createCyclicCoupledBaffles
1039 subsetter.subMesh(),
1040 cyclicWantedPatch_half0,
1041 cyclicWantedPatch_half1,
1046 // Create wall baffles
1049 subsetter.subMesh(),
1059 // Change the mesh. Change points directly (no inflation).
1060 autoPtr<mapPolyMesh> map = meshMod.changeMesh(subsetter.subMesh(), false);
1063 subsetter.subMesh().updateMesh(map);
1065 // Fix faces that get mapped to zero-sized patches (these don't get any
1067 initCreatedPatches<volScalarField>
1069 subsetter.subMesh(),
1073 initCreatedPatches<volVectorField>
1075 subsetter.subMesh(),
1079 initCreatedPatches<volSphericalTensorField>
1081 subsetter.subMesh(),
1083 sphericalTensor::zero
1085 initCreatedPatches<volSymmTensorField>
1087 subsetter.subMesh(),
1091 initCreatedPatches<volTensorField>
1093 subsetter.subMesh(),
1098 initCreatedPatches<surfaceScalarField>
1100 subsetter.subMesh(),
1104 initCreatedPatches<surfaceVectorField>
1106 subsetter.subMesh(),
1110 initCreatedPatches<surfaceSphericalTensorField>
1112 subsetter.subMesh(),
1114 sphericalTensor::zero
1116 initCreatedPatches<surfaceSymmTensorField>
1118 subsetter.subMesh(),
1122 initCreatedPatches<surfaceTensorField>
1124 subsetter.subMesh(),
1130 // Move mesh (since morphing might not do this)
1131 if (map().hasMotionPoints())
1133 subsetter.subMesh().movePoints(map().preMotionPoints());
1136 Info<< "Writing mesh with split blockedFaces to time " << runTime.value()
1139 subsetter.subMesh().write();
1143 // Removing inaccessible regions
1144 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1147 // Determine connected regions. regionSplit is the labelList with the
1149 regionSplit cellRegion(subsetter.subMesh());
1151 if (cellRegion.nRegions() > 1)
1153 WarningIn(args.executable())
1154 << "Removing blocked faces and cells created "
1155 << cellRegion.nRegions()
1156 << " regions that are not connected via a face." << nl
1157 << " This is not supported in solvers." << nl
1158 << " Use" << nl << nl
1159 << " splitMeshRegions <root> <case> -largestOnly" << nl << nl
1160 << " to extract a single region of the mesh." << nl
1161 << " This mesh will be written to a new timedirectory"
1162 << " so might have to be moved back to constant/" << nl
1165 word startFrom(runTime.controlDict().lookup("startFrom"));
1167 if (startFrom != "latestTime")
1169 WarningIn(args.executable())
1170 << "To run splitMeshRegions please set your"
1171 << " startFrom entry to latestTime" << endl;
1175 Info << nl << "End" << endl;
1181 // ************************************************************************* //