/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2014 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 . \*---------------------------------------------------------------------------*/ #include "dynamicRefineFvMesh.H" #include "addToRunTimeSelectionTable.H" #include "surfaceInterpolate.H" #include "volFields.H" #include "polyTopoChange.H" #include "surfaceFields.H" #include "syncTools.H" #include "pointFields.H" #include "sigFpe.H" #include "cellSet.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(dynamicRefineFvMesh, 0); addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, IOobject); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // the PackedBoolList::count method would probably be faster // since we are only checking for 'true' anyhow Foam::label Foam::dynamicRefineFvMesh::count ( const PackedBoolList& l, const unsigned int val ) { label n = 0; forAll(l, i) { if (l.get(i) == val) { n++; } // debug also serves to get-around Clang compiler trying to optimsie // out this forAll loop under O3 optimisation if (debug) { Info<< "n=" << n << endl; } } return n; } void Foam::dynamicRefineFvMesh::calculateProtectedCells ( PackedBoolList& unrefineableCell ) const { if (protectedCell_.empty()) { unrefineableCell.clear(); return; } const labelList& cellLevel = meshCutter_.cellLevel(); unrefineableCell = protectedCell_; // Get neighbouring cell level labelList neiLevel(nFaces()-nInternalFaces()); for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++) { neiLevel[faceI-nInternalFaces()] = cellLevel[faceOwner()[faceI]]; } syncTools::swapBoundaryFaceList(*this, neiLevel); while (true) { // Pick up faces on border of protected cells boolList seedFace(nFaces(), false); forAll(faceNeighbour(), faceI) { label own = faceOwner()[faceI]; bool ownProtected = unrefineableCell.get(own); label nei = faceNeighbour()[faceI]; bool neiProtected = unrefineableCell.get(nei); if (ownProtected && (cellLevel[nei] > cellLevel[own])) { seedFace[faceI] = true; } else if (neiProtected && (cellLevel[own] > cellLevel[nei])) { seedFace[faceI] = true; } } for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++) { label own = faceOwner()[faceI]; bool ownProtected = unrefineableCell.get(own); if ( ownProtected && (neiLevel[faceI-nInternalFaces()] > cellLevel[own]) ) { seedFace[faceI] = true; } } syncTools::syncFaceList(*this, seedFace, orEqOp()); // Extend unrefineableCell bool hasExtended = false; for (label faceI = 0; faceI < nInternalFaces(); faceI++) { if (seedFace[faceI]) { label own = faceOwner()[faceI]; if (unrefineableCell.get(own) == 0) { unrefineableCell.set(own, 1); hasExtended = true; } label nei = faceNeighbour()[faceI]; if (unrefineableCell.get(nei) == 0) { unrefineableCell.set(nei, 1); hasExtended = true; } } } for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++) { if (seedFace[faceI]) { label own = faceOwner()[faceI]; if (unrefineableCell.get(own) == 0) { unrefineableCell.set(own, 1); hasExtended = true; } } } if (!returnReduce(hasExtended, orOp())) { break; } } } void Foam::dynamicRefineFvMesh::readDict() { dictionary refineDict ( IOdictionary ( IOobject ( "dynamicMeshDict", time().constant(), *this, IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE, false ) ).subDict(typeName + "Coeffs") ); List > fluxVelocities = List > ( refineDict.lookup("correctFluxes") ); // Rework into hashtable. correctFluxes_.resize(fluxVelocities.size()); forAll(fluxVelocities, i) { correctFluxes_.insert(fluxVelocities[i][0], fluxVelocities[i][1]); } dumpLevel_ = Switch(refineDict.lookup("dumpLevel")); } // Refines cells, maps fields and recalculates (an approximate) flux Foam::autoPtr Foam::dynamicRefineFvMesh::refine ( const labelList& cellsToRefine ) { // Mesh changing engine. polyTopoChange meshMod(*this); // Play refinement commands into mesh changer. meshCutter_.setRefinement(cellsToRefine, meshMod); // Create mesh (with inflation), return map from old to new mesh. //autoPtr map = meshMod.changeMesh(*this, true); autoPtr map = meshMod.changeMesh(*this, false); Info<< "Refined from " << returnReduce(map().nOldCells(), sumOp