120 using namespace Foam;
134 forAll(patchesToRename, i)
136 label patchi = patchesToRename[i];
139 if (isA<coupledPolyPatch>(pp))
142 <<
"Encountered coupled patch " << pp.
name()
143 <<
". Will only rename the patch itself,"
144 <<
" not any referred patches."
145 <<
" This might have to be done by hand."
149 pp.
name() = prefix +
'_' + pp.
name();
156 template<
class GeoField>
170 mesh.objectRegistry::lookupClass<GeoField>()
174 const GeoField&
fld = *iter.val();
192 forAll(tSubFld().boundaryField(), patchi)
194 if (addedPatches.found(patchi))
196 tSubFld.ref().boundaryFieldRef()[patchi] ==
197 typename GeoField::value_type(
Zero);
202 GeoField* subFld = tSubFld.ptr();
203 subFld->rename(
fld.name());
210 template<
class GeoField>
211 void subsetSurfaceFields
224 mesh.objectRegistry::lookupClass<GeoField>()
228 const GeoField&
fld = *iter.val();
246 forAll(tSubFld().boundaryField(), patchi)
248 if (addedPatches.found(patchi))
250 tSubFld.ref().boundaryFieldRef()[patchi] ==
251 typename GeoField::value_type(
Zero);
256 GeoField* subFld = tSubFld.ptr();
257 subFld->rename(
fld.name());
269 if (cellRegion[celli] != regionI)
271 nonRegionCells.append(celli);
274 return nonRegionCells.shrink();
282 const label ownRegion,
283 const label neiRegion,
289 min(ownRegion, neiRegion),
290 max(ownRegion, neiRegion)
298 auto zoneIter = iter().find(
zoneID);
299 if (zoneIter.found())
314 zoneToSize.insert(
zoneID, 1);
322 void getInterfaceSizes
325 const bool useFaceZones,
348 if (ownRegion != neiRegion)
370 coupledRegion[i] = cellRegion[celli];
378 label neiRegion = coupledRegion[i];
380 if (ownRegion != neiRegion)
409 auto masterIter = regionsToSize.
find(slaveIter.key());
411 if (masterIter.found())
418 const label
zoneID = iter.key();
419 const label slaveSize = iter.val();
421 auto zoneIter = masterInfo.find(
zoneID);
422 if (zoneIter.found())
424 *zoneIter += slaveSize;
428 masterInfo.insert(
zoneID, slaveSize);
434 regionsToSize.
insert(slaveIter.key(), slaveInfo);
448 toMaster << regionsToSize;
461 label nInterfaces = 0;
465 nInterfaces += info.size();
468 interfaces.
setSize(nInterfaces);
469 interfaceNames.
setSize(nInterfaces);
470 interfaceSizes.
setSize(nInterfaces);
476 const edge&
e = iter.key();
484 interfaces[nInterfaces] = iter.key();
485 label
zoneID = infoIter.key();
490 name0 +
"_to_" + name1,
491 name1 +
"_to_" + name0
499 zoneName +
"_" + name0 +
"_to_" + name1,
500 zoneName +
"_" + name1 +
"_to_" + name0
503 interfaceSizes[nInterfaces] = infoIter();
505 if (regionsToInterface.found(
e))
507 regionsToInterface[
e].insert(
zoneID, nInterfaces);
512 zoneAndInterface.insert(
zoneID, nInterfaces);
513 regionsToInterface.insert(
e, zoneAndInterface);
535 if (ownRegion != neiRegion)
545 min(ownRegion, neiRegion),
546 max(ownRegion, neiRegion)
556 label neiRegion = coupledRegion[i];
558 if (ownRegion != neiRegion)
568 min(ownRegion, neiRegion),
569 max(ownRegion, neiRegion)
602 coupledRegion[i] = cellRegion[celli];
614 labelList cellsToRemove(getNonRegionCells(cellRegion, regionI));
619 labelList exposedFaces = cellRemover.getExposedFaces(cellsToRemove);
621 labelList exposedPatchIDs(exposedFaces.size());
624 label facei = exposedFaces[i];
625 label interfacei = faceToInterface[facei];
628 label neiRegion = -1;
643 label otherRegion = -1;
645 if (ownRegion == regionI && neiRegion != regionI)
647 otherRegion = neiRegion;
649 else if (ownRegion != regionI && neiRegion == regionI)
651 otherRegion = ownRegion;
656 <<
"Exposed face:" << facei
658 <<
" has owner region " << ownRegion
659 <<
" and neighbour region " << neiRegion
660 <<
" when handling region:" << regionI
665 if (regionI < otherRegion)
667 exposedPatchIDs[i] = interfacePatches[interfacei];
671 exposedPatchIDs[i] = interfacePatches[interfacei]+1;
676 cellRemover.setRefinement
702 void createAndWriteRegion
707 const bool prefixRegion,
711 const word& newMeshInstance
714 Info<<
"Creating mesh for region " << regionI
732 forAll(interfacePatches, interfacei)
734 addedPatches.
insert(interfacePatches[interfacei]);
735 addedPatches.
insert(interfacePatches[interfacei]+1);
742 newMesh().updateMesh(map());
745 subsetVolFields<volScalarField>
753 subsetVolFields<volVectorField>
761 subsetVolFields<volSphericalTensorField>
769 subsetVolFields<volSymmTensorField>
777 subsetVolFields<volTensorField>
786 subsetSurfaceFields<surfaceScalarField>
794 subsetSurfaceFields<surfaceVectorField>
802 subsetSurfaceFields<surfaceSphericalTensorField>
810 subsetSurfaceFields<surfaceSymmTensorField>
818 subsetSurfaceFields<surfaceTensorField>
835 labelList oldToNew(newPatches.size(), -1);
839 Info<<
"Deleting empty patches" <<
endl;
842 forAll(newPatches, patchi)
844 const polyPatch& pp = newPatches[patchi];
846 if (!isA<processorPolyPatch>(pp))
850 oldToNew[patchi] = newI;
851 if (!addedPatches.found(patchi))
853 sharedPatches.
append(newI);
861 forAll(newPatches, patchi)
863 const polyPatch& pp = newPatches[patchi];
865 if (isA<processorPolyPatch>(pp) && pp.size())
867 oldToNew[patchi] = newI++;
871 const label nNewPatches = newI;
876 if (oldToNew[patchi] == -1)
878 oldToNew[patchi] = newI++;
888 Info<<
"Prefixing patches with region name" <<
endl;
890 renamePatches(newMesh(),
regionNames[regionI], sharedPatches);
896 newMesh().setInstance(newMeshInstance);
902 Info<<
"Writing addressing to base mesh" <<
endl;
908 "pointRegionAddressing",
909 newMesh().facesInstance(),
910 newMesh().meshSubDir,
918 Info<<
"Writing map " << pointProcAddressing.name()
919 <<
" from region" << regionI
920 <<
" points back to base mesh." <<
endl;
921 pointProcAddressing.
write();
927 "faceRegionAddressing",
928 newMesh().facesInstance(),
929 newMesh().meshSubDir,
941 label oldFacei = map().faceMap()[facei];
945 map().cellMap()[newMesh().faceOwner()[facei]]
957 <<
" from region" << regionI
958 <<
" faces back to base mesh." <<
endl;
965 "cellRegionAddressing",
966 newMesh().facesInstance(),
967 newMesh().meshSubDir,
975 Info<<
"Writing map " <<cellProcAddressing.name()
976 <<
" from region" << regionI
977 <<
" cells back to base mesh." <<
endl;
978 cellProcAddressing.
write();
984 "boundaryRegionAddressing",
985 newMesh().facesInstance(),
986 newMesh().meshSubDir,
996 if (!addedPatches.found(i))
998 label newI = oldToNew[i];
999 if (newI >= 0 && newI < nNewPatches)
1001 boundaryProcAddressing[oldToNew[i]] = i;
1005 Info<<
"Writing map " << boundaryProcAddressing.name()
1006 <<
" from region" << regionI
1007 <<
" boundary back to base mesh." <<
endl;
1008 boundaryProcAddressing.
write();
1026 labelList interfacePatches(interfaces.size());
1028 forAll(interfaces, interI)
1030 const edge&
e = interfaces[interI];
1083 <<
" " << interfacePatches[interI]
1086 <<
" " << interfacePatches[interI]+1
1090 return interfacePatches;
1095 label findCorrespondingRegion
1099 const label nCellRegions,
1101 const label minOverlapSize
1107 forAll(cellRegion, celli)
1109 if (existingZoneID[celli] == zoneI)
1111 cellsInZone[cellRegion[celli]]++;
1119 label regionI =
findMax(cellsInZone);
1122 if (cellsInZone[regionI] < minOverlapSize)
1130 forAll(cellRegion, celli)
1132 if (cellRegion[celli] == regionI && existingZoneID[celli] != zoneI)
1162 forAll(clusterToZones, clusterI)
1164 for (
const label zoneI : clusterToZones[clusterI])
1166 const cellZone& cz = cellZones[zoneI];
1170 label celli = cz[i];
1171 if (clusterID[celli] == -1)
1173 clusterID[celli] = clusterI;
1178 <<
"Cell " << celli <<
" with cell centre "
1180 <<
" is multiple zones. This is not allowed." <<
endl
1181 <<
"It is in zone " << clusterNames[clusterID[celli]]
1182 <<
" and in zone " << clusterNames[clusterI]
1197 const label regioni,
1214 for (label i = 1; i <
zoneIDs.size(); i++)
1236 clusterNames.
clear();
1237 clusterToZones.
clear();
1238 zoneToCluster.
setSize(cellZones.size());
1241 if (zoneClusters.size())
1243 forAll(zoneClusters, clusteri)
1249 zoneClusterNames[clusteri].size()
1250 ? zoneClusterNames[clusteri]
1262 forAll(zoneToCluster, zonei)
1264 if (zoneToCluster[zonei] == -1)
1266 clusterNames.
append(cellZones[zonei].
name());
1268 zoneToCluster[zonei] = clusterToZones.size();
1274 for (
const auto&
cellZone : cellZones)
1276 const label nClusters = clusterToZones.size();
1287 const bool sloppyCellZones,
1294 const label nCellRegions,
1304 regionToZones.
setSize(nCellRegions);
1308 zoneToRegion.
setSize(cellZones.size(), -1);
1313 forAll(clusterToZones, clusterI)
1315 for (
const label zoneI : clusterToZones[clusterI])
1317 clusterSizes[clusterI] += cellZones[zoneI].size();
1322 if (sloppyCellZones)
1324 Info<<
"Trying to match regions to existing cell zones;"
1325 <<
" region can be subset of cell zone." <<
nl <<
endl;
1327 forAll(clusterToZones, clusterI)
1329 label regionI = findCorrespondingRegion
1335 label(0.5*clusterSizes[clusterI])
1340 Info<<
"Sloppily matched region " << regionI
1342 <<
" to cluster " << clusterI
1343 <<
" size " << clusterSizes[clusterI]
1348 clusterToZones[clusterI]
1350 regionToZones[regionI] = clusterToZones[clusterI];
1357 Info<<
"Trying to match regions to existing cell zones." <<
nl <<
endl;
1359 forAll(clusterToZones, clusterI)
1361 label regionI = findCorrespondingRegion
1367 clusterSizes[clusterI]
1375 clusterToZones[clusterI]
1377 regionToZones[regionI] = clusterToZones[clusterI];
1391 regionToZones[regionI]
1415 cellToRegion.write();
1417 Info<<
"Writing region per cell file (for manual decomposition) to "
1418 << cellToRegion.objectPath() <<
nl <<
endl;
1435 zeroGradientFvPatchScalarField::typeName
1437 forAll(cellRegion, celli)
1439 cellToRegion[celli] = cellRegion[celli];
1441 cellToRegion.write();
1443 Info<<
"Writing region per cell as volScalarField to "
1444 << cellToRegion.objectPath() <<
nl <<
endl;
1451 int main(
int argc,
char *argv[])
1455 "Split mesh into multiple regions (detected by walking across faces)"
1462 "Additionally split cellZones off into separate regions"
1467 "Use cellZones only to split mesh into regions; do not use walking"
1471 "cellZonesFileOnly",
1473 "Like -cellZonesOnly, but use specified file"
1479 "Combine zones in follow-on analysis"
1485 "Combine zones in follow-on analysis"
1491 "Specify additional region boundaries that walking does not cross"
1496 "Place cells into cellZones instead of splitting mesh"
1501 "Only write largest region"
1507 "Only write region containing point"
1517 "Try to match heuristically regions to existing cell zones"
1522 "Use faceZones to patch inter-region faces instead of single patch"
1527 "Prefix region name to all patches, not just coupling patches"
1538 word blockedFacesName;
1541 Info<<
"Reading blocked internal faces from faceSet "
1542 << blockedFacesName <<
nl <<
endl;
1545 const bool makeCellZones =
args.
found(
"makeCellZones");
1546 const bool largestOnly =
args.
found(
"largestOnly");
1547 const bool insidePoint =
args.
found(
"insidePoint");
1548 const bool useCellZones =
args.
found(
"cellZones");
1549 const bool useCellZonesOnly =
args.
found(
"cellZonesOnly");
1550 const bool useCellZonesFile =
args.
found(
"cellZonesFileOnly");
1551 const bool combineZones =
args.
found(
"combineZones");
1552 const bool addZones =
args.
found(
"addZones");
1553 const bool overwrite =
args.
found(
"overwrite");
1554 const bool detectOnly =
args.
found(
"detectOnly");
1555 const bool sloppyCellZones =
args.
found(
"sloppyCellZones");
1556 const bool useFaceZones =
args.
found(
"useFaceZones");
1557 const bool prefixRegion =
args.
found(
"prefixRegion");
1562 (useCellZonesOnly || useCellZonesFile)
1563 && (useCellZones || blockedFacesName.size())
1567 <<
"You cannot specify both -cellZonesOnly or -cellZonesFileOnly"
1568 <<
" (which specify complete split)"
1569 <<
" in combination with -blockedFaces or -cellZones"
1570 <<
" (which imply a split based on topology)"
1577 Info<<
"Using current faceZones to divide inter-region interfaces"
1578 <<
" into multiple patches."
1583 Info<<
"Creating single patch per inter-region interface."
1589 if (insidePoint && largestOnly)
1592 <<
"You cannot specify both -largestOnly"
1593 <<
" (keep region with most cells)"
1594 <<
" and -insidePoint (keep region containing point)"
1609 <<
"Cannot specify both combineZones and addZones"
1613 zoneClusterNames.
setSize(zoneClusters.size());
1618 zoneClusterNames.
setSize(zoneClusters.size());
1619 forAll(zoneClusters, clusteri)
1623 wordRes& wrs = zoneClusters[clusteri];
1625 zoneClusterNames[clusteri] = wrs[0];
1627 for (label i = 1; i < wrs.size(); i++)
1648 label nCellRegions = 0;
1649 if (useCellZonesOnly)
1651 Info<<
"Using current cellZones to split mesh into regions."
1652 <<
" This requires all"
1653 <<
" cells to be in one and only one cellZone." <<
nl <<
endl;
1684 label unzonedCelli = clusterID.find(-1);
1685 if (unzonedCelli != -1)
1688 <<
"For the cellZonesOnly option all cells "
1689 <<
"have to be in a cellZone." <<
endl
1690 <<
"Cell " << unzonedCelli
1692 <<
" is not in a cellZone. There might be more unzoned cells."
1695 cellRegion = clusterID;
1696 nCellRegions =
gMax(cellRegion)+1;
1697 zoneToRegion = zoneToCluster;
1698 regionToZones = clusterToZones;
1701 else if (useCellZonesFile)
1703 const word zoneFile(
args[
"cellZonesFileOnly"]);
1704 Info<<
"Reading split from cellZones file " << zoneFile <<
endl
1705 <<
"This requires all"
1706 <<
" cells to be in one and only one cellZone." <<
nl <<
endl;
1752 label unzonedCelli = clusterID.find(-1);
1753 if (unzonedCelli != -1)
1756 <<
"For the cellZonesFileOnly option all cells "
1757 <<
"have to be in a cellZone." <<
endl
1758 <<
"Cell " << unzonedCelli
1760 <<
" is not in a cellZone. There might be more unzoned cells."
1763 cellRegion = clusterID;
1764 nCellRegions =
gMax(cellRegion)+1;
1765 zoneToRegion = zoneToCluster;
1766 regionToZones = clusterToZones;
1778 if (blockedFacesName.size())
1783 <<
" blocked faces from set " << blockedFacesName <<
nl <<
endl;
1787 for (
const label facei : blockedFaceSet)
1789 blockedFace[facei] =
true;
1833 if (ownCluster != neiCluster)
1835 blockedFace[facei] =
true;
1844 label neiCluster = neiClusterID[i];
1846 if (ownCluster != neiCluster)
1848 blockedFace[facei] =
true;
1855 nCellRegions = regions.nRegions();
1880 if (largestOnly || insidePoint)
1882 forAll(regionToZones, regionI)
1884 if (regionToZones[regionI].empty())
1890 else if (insidePoint)
1894 else if (largestOnly)
1903 Info<<
endl <<
"Number of regions:" << nCellRegions <<
nl <<
endl;
1907 writeCellToRegion(
mesh, cellRegion);
1916 forAll(cellRegion, celli)
1918 regionSizes[cellRegion[celli]]++;
1920 forAll(regionSizes, regionI)
1925 Info<<
"Region\tCells" <<
nl
1926 <<
"------\t-----" <<
endl;
1928 forAll(regionSizes, regionI)
1930 Info<< regionI <<
"\t\t" << regionSizes[regionI] <<
nl;
1937 Info<<
"Region\tZone\tName" <<
nl
1938 <<
"------\t----\t----" <<
endl;
1939 forAll(regionToZones, regionI)
1980 Info<<
"Sizes of interfaces between regions:" <<
nl <<
nl
1981 <<
"Interface\tRegion\tRegion\tFaces" <<
nl
1982 <<
"---------\t------\t------\t-----" <<
endl;
1984 forAll(interfaces, interI)
1986 const edge&
e = interfaces[interI];
1989 <<
"\t\t\t" <<
e[0] <<
"\t\t" <<
e[1]
1990 <<
"\t\t" << interfaceSizes[interI] <<
nl;
2049 if (nCellRegions == 1)
2051 Info<<
"Only one region. Doing nothing." <<
endl;
2053 else if (makeCellZones)
2055 Info<<
"Putting cells into cellZones instead of splitting mesh."
2060 for (label regionI = 0; regionI < nCellRegions; regionI++)
2062 const labelList& zones = regionToZones[regionI];
2064 if (zones.size() == 1 && zones[0] != -1)
2067 const label zoneI = zones[0];
2068 Info<<
" Region " << regionI <<
" : corresponds to existing"
2091 std::move(regionCells),
2102 Info<<
" Region " << regionI <<
" : created new cellZone "
2127 Info<<
"Writing cellSets corresponding to cellZones." <<
nl <<
endl;
2173 Info<<
nl <<
"Found point " << insidePoint <<
" in cell " << celli
2178 regionI = cellRegion[celli];
2184 <<
"Subsetting region " << regionI
2185 <<
" containing point " << insidePoint <<
endl;
2190 <<
"Point " << insidePoint
2191 <<
" is not inside the mesh." <<
nl
2192 <<
"Bounding box of the mesh:" <<
mesh.
bounds()
2196 createAndWriteRegion
2208 else if (largestOnly)
2210 label regionI =
findMax(regionSizes);
2213 <<
"Subsetting region " << regionI
2214 <<
" of size " << regionSizes[regionI]
2217 createAndWriteRegion
2232 for (label regionI = 0; regionI < nCellRegions; regionI++)
2235 <<
"Region " << regionI <<
nl
2236 <<
"-------- " <<
endl;
2238 createAndWriteRegion