/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 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 extrudeToRegionMesh Description Extrude faceZones (internal or boundary faces) or faceSets (boundary faces only) into a separate mesh (as a different region). - used to e.g. extrude baffles (extrude internal faces) or create liquid film regions. - if extruding internal faces: - create baffles in original mesh with mappedWall patches - if extruding boundary faces: - convert boundary faces to mappedWall patches - extrude edges of faceZone as a \_sidePatch - extrude edges inbetween different faceZones as a (nonuniformTransform)cyclic \_\ - extrudes into master direction (i.e. away from the owner cell if flipMap is false) \verbatim Internal face extrusion ----------------------- +-------------+ | | | | +---AAAAAAA---+ | | | | +-------------+ AAA=faceZone to extrude. For the case of no flipMap the extrusion starts at owner and extrudes into the space of the neighbour: +CCCCCCC+ | | <= extruded mesh +BBBBBBB+ +-------------+ | | | (neighbour) | |___CCCCCCC___| <= original mesh (with 'baffles' added) | BBBBBBB | |(owner side) | | | +-------------+ BBB=mapped between owner on original mesh and new extrusion. (zero offset) CCC=mapped between neighbour on original mesh and new extrusion (offset due to the thickness of the extruded mesh) For the case of flipMap the extrusion is the other way around: from the neighbour side into the owner side. Boundary face extrusion ----------------------- +--AAAAAAA--+ | | | | +-----------+ AAA=faceZone to extrude. E.g. slave side is owner side (no flipmap) becomes +CCCCCCC+ | | <= extruded mesh +BBBBBBB+ +--BBBBBBB--+ | | <= original mesh | | +-----------+ BBB=mapped between original mesh and new extrusion CCC=polypatch Notes: - when extruding cyclics with only one cell inbetween it does not detect this as a cyclic since the face is the same face. It will only work if the coupled edge extrudes a different face so if there are more than 1 cell inbetween. \endverbatim \*---------------------------------------------------------------------------*/ #include "argList.H" #include "fvMesh.H" #include "polyTopoChange.H" #include "OFstream.H" #include "meshTools.H" #include "mappedWallPolyPatch.H" #include "createShellMesh.H" #include "syncTools.H" #include "cyclicPolyPatch.H" #include "wedgePolyPatch.H" #include "nonuniformTransformCyclicPolyPatch.H" #include "extrudeModel.H" #include "globalIndex.H" #include "faceSet.H" #include "volFields.H" #include "surfaceFields.H" #include "pointFields.H" //#include "ReadFields.H" #include "fvMeshTools.H" #include "OBJstream.H" #include "PatchTools.H" using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // label findPatchID(const List& newPatches, const word& name) { forAll(newPatches, i) { if (newPatches[i]->name() == name) { return i; } } return -1; } template label addPatch ( const polyBoundaryMesh& patches, const word& patchName, DynamicList& newPatches ) { label patchi = findPatchID(newPatches, patchName); if (patchi != -1) { if (isA(*newPatches[patchi])) { // Already there return patchi; } else { FatalErrorInFunction << "Already have patch " << patchName << " but of type " << newPatches[patchi]->type() << exit(FatalError); } } patchi = newPatches.size(); label startFacei = 0; if (patchi > 0) { const polyPatch& pp = *newPatches.last(); startFacei = pp.start()+pp.size(); } newPatches.append ( polyPatch::New ( PatchType::typeName, patchName, 0, // size startFacei, // nFaces patchi, patches ).ptr() ); return patchi; } template label addPatch ( const polyBoundaryMesh& patches, const word& patchName, const dictionary& dict, DynamicList& newPatches ) { label patchi = findPatchID(newPatches, patchName); if (patchi != -1) { if (isA(*newPatches[patchi])) { // Already there return patchi; } else { FatalErrorInFunction << "Already have patch " << patchName << " but of type " << newPatches[patchi]->type() << exit(FatalError); } } patchi = newPatches.size(); label startFacei = 0; if (patchi > 0) { const polyPatch& pp = *newPatches.last(); startFacei = pp.start()+pp.size(); } dictionary patchDict(dict); patchDict.set("type", PatchType::typeName); patchDict.set("nFaces", 0); patchDict.set("startFace", startFacei); newPatches.append ( polyPatch::New ( patchName, patchDict, patchi, patches ).ptr() ); return patchi; } // Remove zero-sized patches void deleteEmptyPatches(fvMesh& mesh) { const polyBoundaryMesh& patches = mesh.boundaryMesh(); wordList masterNames; if (Pstream::master()) { masterNames = patches.names(); } Pstream::scatter(masterNames); labelList oldToNew(patches.size(), -1); label usedI = 0; label notUsedI = patches.size(); // Add all the non-empty, non-processor patches forAll(masterNames, masterI) { label patchi = patches.findPatchID(masterNames[masterI]); if (patchi != -1) { if (isA(patches[patchi])) { // Similar named processor patch? Not 'possible'. if (patches[patchi].size() == 0) { Pout<< "Deleting processor patch " << patchi << " name:" << patches[patchi].name() << endl; oldToNew[patchi] = --notUsedI; } else { oldToNew[patchi] = usedI++; } } else { // Common patch. if (returnReduce(patches[patchi].size(), sumOp