From 5120c51ba19f24e35192a4e6b4350c731ad66141 Mon Sep 17 00:00:00 2001 From: Mattijs Janssens Date: Mon, 17 May 2021 10:53:40 +0000 Subject: [PATCH] ENH: splitMeshRegions: combine cellZones. See #2046 --- .../splitMeshRegions/splitMeshRegions.C | 452 ++++++++++++------ 1 file changed, 306 insertions(+), 146 deletions(-) diff --git a/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C b/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C index 194b29809f..cdab0733b1 100644 --- a/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C +++ b/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C @@ -49,6 +49,14 @@ Description - mesh with cells put into cellZones (-makeCellZones) Note: + + - multiple cellZones can be combined into a single cellZone (cluster) + for further analysis using the 'combineZones' option: + -combineZones '((zoneA "zoneB.*")(none otherZone)) + This can be combined with e.g. 'cellZones' or 'cellZonesOnly'. The + corresponding region name will be the names of the cellZones combined e.g. + zoneA_zoneB0_zoneB1 + - cellZonesOnly does not do a walk and uses the cellZones only. Use this if you don't mind having disconnected domains in a single region. This option requires all cells to be in one (and one only) cellZone. @@ -62,9 +70,8 @@ Description - Should work in parallel. cellZones can differ on either side of processor boundaries in which case - the faces get moved from processor patch to directMapped patch. Not - the faces get moved from processor patch to mapped patch. Not - very well tested. + the faces get moved from processor patch to mapped patch. Not very well + tested. - If a cell zone gets split into more than one region it can detect the largest matching region (-sloppyCellZones). This will accept any @@ -1136,53 +1143,127 @@ label findCorrespondingRegion } -// Get zone per cell -// - non-unique zoning -// - coupled zones -void getZoneID +void getClusterID ( const polyMesh& mesh, const cellZoneMesh& cellZones, - labelList& zoneID, - labelList& neiZoneID + const wordList& clusterNames, + const labelListList& clusterToZones, + labelList& clusterID, + labelList& neiClusterID ) { // Existing zoneID - zoneID.setSize(mesh.nCells()); - zoneID = -1; + clusterID.setSize(mesh.nCells()); + clusterID = -1; - forAll(cellZones, zoneI) + forAll(clusterToZones, clusterI) { - const cellZone& cz = cellZones[zoneI]; - - forAll(cz, i) + for (const label zoneI : clusterToZones[clusterI]) { - label celli = cz[i]; - if (zoneID[celli] == -1) + const cellZone& cz = cellZones[zoneI]; + + forAll(cz, i) { - zoneID[celli] = zoneI; - } - else - { - FatalErrorInFunction - << "Cell " << celli << " with cell centre " - << mesh.cellCentres()[celli] - << " is multiple zones. This is not allowed." << endl - << "It is in zone " << cellZones[zoneID[celli]].name() - << " and in zone " << cellZones[zoneI].name() - << exit(FatalError); + label celli = cz[i]; + if (clusterID[celli] == -1) + { + clusterID[celli] = clusterI; + } + else + { + FatalErrorInFunction + << "Cell " << celli << " with cell centre " + << mesh.cellCentres()[celli] + << " is multiple zones. This is not allowed." << endl + << "It is in zone " << clusterNames[clusterID[celli]] + << " and in zone " << clusterNames[clusterI] + << exit(FatalError); + } } } } // Neighbour zoneID. - neiZoneID.setSize(mesh.nBoundaryFaces()); + syncTools::swapBoundaryCellList(mesh, clusterID, neiClusterID); +} - forAll(neiZoneID, i) + +word makeRegionName +( + const cellZoneMesh& czs, + const label regioni, + const labelList& zoneIDs +) +{ + // Synthesise region name. Equals the zone name if cluster consist of only + // one zone + + if (zoneIDs.empty()) { - neiZoneID[i] = zoneID[mesh.faceOwner()[i+mesh.nInternalFaces()]]; + return word("domain") + Foam::name(regioni); + } + else + { + // Synthesize name from appended cellZone names + word regionName(czs[zoneIDs[0]].name()); + for (label i = 1; i < zoneIDs.size(); i++) + { + regionName += "_" + czs[zoneIDs[i]].name(); + } + return regionName; + } +} + + +void makeClusters +( + const List& zoneClusters, + const cellZoneMesh& cellZones, + wordList& clusterNames, + labelListList& clusterToZones, + labelList& zoneToCluster +) +{ + // Check if there are clustering for zones. If none every zone goes into + // its own cluster. + + clusterNames.clear(); + clusterToZones.clear(); + zoneToCluster.setSize(cellZones.size()); + zoneToCluster = -1; + + if (zoneClusters.size()) + { + forAll(zoneClusters, clusteri) + { + const labelList zoneIDs(cellZones.indices(zoneClusters[clusteri])); + UIndirectList