/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2015-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . Application splitMeshRegions Group grpMeshManipulationUtilities Description Splits mesh into multiple regions. Each region is defined as a domain whose cells can all be reached by cell-face-cell walking without crossing - boundary faces - additional faces from faceset (-blockedFaces faceSet). - any face between differing cellZones (-cellZones) Output is: - volScalarField with regions as different scalars (-detectOnly) or - mesh with multiple regions and mapped patches. These patches either cover the whole interface between two region (default) or only part according to faceZones (-useFaceZones) or - 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. - cellZonesFileOnly behaves like -cellZonesOnly but reads the cellZones from the specified file. This allows one to explicitly specify the region distribution and still have multiple cellZones per region. - prefixRegion prefixes all normal patches with region name (interface (patches already have region name prefix) - Should work in parallel. cellZones can differ on either side of processor boundaries in which case 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 region that covers more than 50% of the zone. It has to be a subset so cannot have any cells in any other zone. - If explicitly a single region has been selected (-largestOnly or -insidePoint) its region name will be either - name of a cellZone it matches to or - "largestOnly" respectively "insidePoint" or - polyMesh::defaultRegion if additionally -overwrite (so it will overwrite the input mesh!) - writes maps like decomposePar back to original mesh: - pointRegionAddressing : for every point in this region the point in the original mesh - cellRegionAddressing : ,, cell ,, cell ,, - faceRegionAddressing : ,, face ,, face in the original mesh + 'turning index'. For a face in the same orientation this is the original facelabel+1, for a turned face this is -facelabel-1 - boundaryRegionAddressing : for every patch in this region the patch in the original mesh (or -1 if added patch) \*---------------------------------------------------------------------------*/ #include "SortableList.H" #include "argList.H" #include "regionSplit.H" #include "fvMeshSubset.H" #include "IOobjectList.H" #include "volFields.H" #include "faceSet.H" #include "cellSet.H" #include "polyTopoChange.H" #include "removeCells.H" #include "edgeHashes.H" #include "syncTools.H" #include "ReadFields.H" #include "mappedWallPolyPatch.H" #include "fvMeshTools.H" #include "zeroGradientFvPatchFields.H" #include "processorMeshes.H" using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Prepend prefix to selected patches. void renamePatches ( fvMesh& mesh, const word& prefix, const labelList& patchesToRename ) { polyBoundaryMesh& polyPatches = const_cast(mesh.boundaryMesh()); forAll(patchesToRename, i) { label patchi = patchesToRename[i]; polyPatch& pp = polyPatches[patchi]; if (isA(pp)) { WarningInFunction << "Encountered coupled patch " << pp.name() << ". Will only rename the patch itself," << " not any referred patches." << " This might have to be done by hand." << endl; } pp.name() = prefix + '_' + pp.name(); } // Recalculate any demand driven data (e.g. group to name lookup) polyPatches.updateMesh(); } template void subsetVolFields ( const fvMesh& mesh, const fvMesh& subMesh, const labelList& cellMap, const labelList& faceMap, const labelHashSet& addedPatches ) { const labelList patchMap(identity(mesh.boundaryMesh().size())); HashTable fields ( mesh.objectRegistry::lookupClass() ); forAllConstIters(fields, iter) { const GeoField& fld = *iter.val(); Info<< "Mapping field " << fld.name() << endl; tmp tSubFld ( fvMeshSubset::interpolate ( fld, subMesh, patchMap, cellMap, faceMap ) ); // Hack: set value to 0 for introduced patches (since don't // get initialised. forAll(tSubFld().boundaryField(), patchi) { if (addedPatches.found(patchi)) { tSubFld.ref().boundaryFieldRef()[patchi] == typename GeoField::value_type(Zero); } } // Store on subMesh GeoField* subFld = tSubFld.ptr(); subFld->rename(fld.name()); subFld->writeOpt(IOobject::AUTO_WRITE); subFld->store(); } } template void subsetSurfaceFields ( const fvMesh& mesh, const fvMesh& subMesh, const labelList& cellMap, const labelList& faceMap, const labelHashSet& addedPatches ) { const labelList patchMap(identity(mesh.boundaryMesh().size())); HashTable fields ( mesh.objectRegistry::lookupClass() ); forAllConstIters(fields, iter) { const GeoField& fld = *iter.val(); Info<< "Mapping field " << fld.name() << endl; tmp tSubFld ( fvMeshSubset::interpolate ( fld, subMesh, patchMap, cellMap, faceMap ) ); // Hack: set value to 0 for introduced patches (since don't // get initialised. forAll(tSubFld().boundaryField(), patchi) { if (addedPatches.found(patchi)) { tSubFld.ref().boundaryFieldRef()[patchi] == typename GeoField::value_type(Zero); } } // Store on subMesh GeoField* subFld = tSubFld.ptr(); subFld->rename(fld.name()); subFld->writeOpt(IOobject::AUTO_WRITE); subFld->store(); } } // Select all cells not in the region labelList getNonRegionCells(const labelList& cellRegion, const label regionI) { DynamicList