/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- 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 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 inbetween 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: - 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. - useCellZonesOnly 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. - 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 directMapped patch. Not 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 "EdgeMap.H" #include "syncTools.H" #include "ReadFields.H" #include "mappedWallPolyPatch.H" #include "fvMeshTools.H" #include "zeroGradientFvPatchFields.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() ); forAllConstIter(typename HashTable, fields, iter) { const GeoField& fld = *iter(); 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().boundaryField()[patchI] == pTraits::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& faceMap, const labelHashSet& addedPatches ) { const labelList patchMap(identity(mesh.boundaryMesh().size())); HashTable fields ( mesh.objectRegistry::lookupClass() ); forAllConstIter(typename HashTable, fields, iter) { const GeoField& fld = *iter(); Info<< "Mapping field " << fld.name() << endl; tmp tSubFld ( fvMeshSubset::interpolate ( fld, subMesh, patchMap, faceMap ) ); // Hack: set value to 0 for introduced patches (since don't // get initialised. forAll(tSubFld().boundaryField(), patchI) { if (addedPatches.found(patchI)) { tSubFld().boundaryField()[patchI] == pTraits::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