mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Mapping injected faces through interpolation
This commit is contained in:
47
README.txt
Normal file
47
README.txt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Notes from merging Integration-TUD-addOns and plus.
|
||||||
|
|
||||||
|
0)
|
||||||
|
- Changed
|
||||||
|
dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
|
||||||
|
to created internal faces out-of-nothing.
|
||||||
|
- Added the mapNewInternalFaces to dynamicRefineFvMesh
|
||||||
|
- unset FOAM_SETNAN, FOAM_SIGFPE and run
|
||||||
|
|
||||||
|
testCases/testAMRandLoadBalancing/damBreakWithObstacle
|
||||||
|
|
||||||
|
- However when writing V0 we noticed a nan in the V0 field.
|
||||||
|
(this doesn't get written anymore but it might indicate a bug)
|
||||||
|
|
||||||
|
|
||||||
|
1) Tried moving additional mapping of surface fields to
|
||||||
|
|
||||||
|
virtual dynamicRefineFvMesh::mapFields(const mapPolyMesh&);
|
||||||
|
|
||||||
|
so it would get called from the fvMesh::updateMesh. However
|
||||||
|
this mapping (explicitly) gets done using unadapted addressing
|
||||||
|
and it causes the cell addressing to be wrong:
|
||||||
|
|
||||||
|
|
||||||
|
[1] --> FOAM FATAL ERROR:
|
||||||
|
[1] index 826015320 out of range 0 ... 71079
|
||||||
|
[1]
|
||||||
|
[1] From function void Foam::UList<T>::checkIndex(Foam::label) const [with T = Foam::cell; Foam::label = int]
|
||||||
|
[1] in file /home/preston2/mattijs/OpenFOAM/work/OpenFOAM-plus.integration-TUD/src/OpenFOAM/lnInclude/UListI.H at line 106.
|
||||||
|
|
||||||
|
|
||||||
|
From dynamicRefineFvMesh::mapNewInternalFaces : (I think)
|
||||||
|
|
||||||
|
cell faceOwner = this->cells()[owner[facei]];
|
||||||
|
|
||||||
|
So this adaptation should be done in a separate pass
|
||||||
|
|
||||||
|
|
||||||
|
2) Mapping new internal faces:
|
||||||
|
- currently done by averaging the values of 'properly' mapped
|
||||||
|
faces from owner and neighbour.
|
||||||
|
- this would not work if a cell gets split into 3x3x3
|
||||||
|
- instead this should be done by some geometric interpolation
|
||||||
|
from point values?
|
||||||
|
- have selection mechanism instead or use oriented flag on surfaceFields
|
||||||
|
|
||||||
|
3) Current averaging is valid only for internal faces & only scalar/vector
|
||||||
@ -5,6 +5,7 @@ dynamicMotionSolverFvMesh/dynamicMotionSolverFvMesh.C
|
|||||||
dynamicMultiMotionSolverFvMesh/dynamicMultiMotionSolverFvMesh.C
|
dynamicMultiMotionSolverFvMesh/dynamicMultiMotionSolverFvMesh.C
|
||||||
dynamicInkJetFvMesh/dynamicInkJetFvMesh.C
|
dynamicInkJetFvMesh/dynamicInkJetFvMesh.C
|
||||||
dynamicRefineFvMesh/dynamicRefineFvMesh.C
|
dynamicRefineFvMesh/dynamicRefineFvMesh.C
|
||||||
|
dynamicRefineBalancedFvMesh/dynamicRefineBalancedFvMesh.C
|
||||||
dynamicMotionSolverListFvMesh/dynamicMotionSolverListFvMesh.C
|
dynamicMotionSolverListFvMesh/dynamicMotionSolverListFvMesh.C
|
||||||
|
|
||||||
simplifiedDynamicFvMesh/simplifiedDynamicFvMeshes.C
|
simplifiedDynamicFvMesh/simplifiedDynamicFvMeshes.C
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
|
-g -DFULLDEBUG -O0 -g \
|
||||||
|
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
|
||||||
-I$(LIB_SRC)/surfMesh/lnInclude \
|
-I$(LIB_SRC)/surfMesh/lnInclude \
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude
|
-I$(LIB_SRC)/finiteVolume/lnInclude
|
||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
|
-ldecompositionMethods \
|
||||||
-lmeshTools \
|
-lmeshTools \
|
||||||
-ldynamicMesh \
|
-ldynamicMesh \
|
||||||
-lfiniteVolume
|
-lfiniteVolume
|
||||||
|
|||||||
29
src/dynamicFvMesh/dynamicRefineBalancedFvMesh/balanceParDict
Normal file
29
src/dynamicFvMesh/dynamicRefineBalancedFvMesh/balanceParDict
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*--------------------------------*- C++ -*----------------------------------*\
|
||||||
|
| ========= | |
|
||||||
|
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||||
|
| \\ / O peration | Version: 2.1.1 |
|
||||||
|
| \\ / A nd | Web: www.OpenFOAM.org |
|
||||||
|
| \\/ M anipulation | |
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
FoamFile
|
||||||
|
{
|
||||||
|
version 2.0;
|
||||||
|
format ascii;
|
||||||
|
class dictionary;
|
||||||
|
location "system";
|
||||||
|
object balanceParDict;
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
numberOfSubdomains 2;
|
||||||
|
|
||||||
|
method ptscotch;
|
||||||
|
|
||||||
|
constraints
|
||||||
|
{
|
||||||
|
refinementHistory
|
||||||
|
{
|
||||||
|
type refinementHistory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ************************************************************************* //
|
||||||
125
src/dynamicFvMesh/dynamicRefineBalancedFvMesh/dynamicMeshDict
Normal file
125
src/dynamicFvMesh/dynamicRefineBalancedFvMesh/dynamicMeshDict
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*--------------------------------*- C++ -*----------------------------------*\
|
||||||
|
| ========= | |
|
||||||
|
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||||
|
| \\ / O peration | Version: dev |
|
||||||
|
| \\ / A nd | Web: www.OpenFOAM.org |
|
||||||
|
| \\/ M anipulation | |
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
FoamFile
|
||||||
|
{
|
||||||
|
version 2.0;
|
||||||
|
format ascii;
|
||||||
|
class dictionary;
|
||||||
|
location "constant";
|
||||||
|
object dynamicMeshDict;
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
dynamicFvMesh dynamicRefineBalancedFvMesh;
|
||||||
|
|
||||||
|
refinementControls
|
||||||
|
{
|
||||||
|
enableRefinementControl true;
|
||||||
|
|
||||||
|
fields // must be scalarFields
|
||||||
|
(
|
||||||
|
//alpha (min max refineLevel)
|
||||||
|
alpha (0.01 0.99 2) // refine cells where alpha in [0.01:0.99] with maximal 2 refinement layers
|
||||||
|
);
|
||||||
|
|
||||||
|
interface // must be a scalarField (only one dictionary!)
|
||||||
|
(
|
||||||
|
alpha // refine interface (found based on snGrad of alpha > 0.1)
|
||||||
|
{
|
||||||
|
innerRefLayers 2; // describes how many cell layers inside phase alpha are to be refined
|
||||||
|
outerRefLayers 5; // describes how many cell layers outside phase alpha are to be refined
|
||||||
|
|
||||||
|
// optional settings:
|
||||||
|
maxRefineLevel 4; // max refinement layers; Default: maxRefinement from dynamicRefineFvMeshCoeffs is used
|
||||||
|
// to get slower than 2:1 refinement; add #nAddLayers between each refinement level at the interface
|
||||||
|
nAddLayers 1; //Default: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
gradients // must be scalars
|
||||||
|
(
|
||||||
|
// arguments as in 'fields'
|
||||||
|
// min/max values are based on mag(fvc::grad(volScalarField)) * cellVolume
|
||||||
|
T (0.01 10 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
curls // must be vectors
|
||||||
|
(
|
||||||
|
// arguments as in 'fields'
|
||||||
|
// min/max values are based on mag(fvc::curl(volVectorField))
|
||||||
|
U (0.5 1 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
regions
|
||||||
|
(
|
||||||
|
boxToCell
|
||||||
|
{
|
||||||
|
minLevel 1;
|
||||||
|
|
||||||
|
box (-1 0.001 0.002)(1 0.005 0.003);
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamicRefineFvMeshCoeffs
|
||||||
|
{
|
||||||
|
// Extra entries for balancing
|
||||||
|
enableBalancing true;
|
||||||
|
allowableImbalance 0.15;
|
||||||
|
|
||||||
|
// How often to refine
|
||||||
|
refineInterval 10;
|
||||||
|
|
||||||
|
// Field to be refinement on (set it to 'internalRefinementField' to use the
|
||||||
|
// refinementControls dictionary entries above)
|
||||||
|
field internalRefinementField;
|
||||||
|
|
||||||
|
// Refine field inbetween lower..upper
|
||||||
|
lowerRefineLevel 0.5; // do not change
|
||||||
|
upperRefineLevel 3.5; // maxRefinement+0.5
|
||||||
|
|
||||||
|
// If value < unrefineLevel unrefine
|
||||||
|
unrefineLevel -0.5; // do not change
|
||||||
|
|
||||||
|
// Have slower than 2:1 refinement
|
||||||
|
nBufferLayers 4;
|
||||||
|
|
||||||
|
// Refine cells only up to maxRefinement levels
|
||||||
|
maxRefinement 3;
|
||||||
|
|
||||||
|
// Stop refinement if maxCells reached
|
||||||
|
maxCells 200000;
|
||||||
|
|
||||||
|
// Flux field and corresponding velocity field. Fluxes on changed
|
||||||
|
// faces get recalculated by interpolating the velocity. Use 'none'
|
||||||
|
// on surfaceScalarFields that do not need to be reinterpolated.
|
||||||
|
correctFluxes
|
||||||
|
(
|
||||||
|
(phi Urel)
|
||||||
|
(phiAbs U)
|
||||||
|
(phiAbs_0 U_0)
|
||||||
|
(nHatf none)
|
||||||
|
(rho*phi none)
|
||||||
|
(ghf none)
|
||||||
|
);
|
||||||
|
|
||||||
|
// List of non-flux surface<Type>Fields to be mapped
|
||||||
|
// only for new internal faces (AMR refine)
|
||||||
|
mapSurfaceFields
|
||||||
|
(
|
||||||
|
Uf
|
||||||
|
Uf_0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Write the refinement level as a volScalarField
|
||||||
|
dumpLevel true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,843 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2014 Tyler Voskuilen
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is a derivative work 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "dynamicRefineBalancedFvMesh.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "surfaceInterpolate.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "polyTopoChange.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
#include "syncTools.H"
|
||||||
|
#include "pointFields.H"
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "volPointInterpolation.H"
|
||||||
|
#include "pointMesh.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(dynamicRefineBalancedFvMesh, 0);
|
||||||
|
addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineBalancedFvMesh, IOobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
Foam::label Foam::dynamicRefineBalancedFvMesh::topParentID(label p)
|
||||||
|
{
|
||||||
|
label nextP = meshCutter().history().splitCells()[p].parent_;
|
||||||
|
if( nextP < 0 )
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return topParentID(nextP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Foam::List<Foam::scalar> Foam::dynamicRefineBalancedFvMesh::readRefinementPoints()
|
||||||
|
{
|
||||||
|
dictionary refineDict
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dynamicMeshDict",
|
||||||
|
time().constant(),
|
||||||
|
*this,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
).subDict("dynamicRefineFvMeshCoeffs")
|
||||||
|
);
|
||||||
|
|
||||||
|
List<scalar> refData(4, scalar(0));
|
||||||
|
|
||||||
|
refData[0] = readScalar(refineDict.lookup("unrefineLevel"));
|
||||||
|
refData[1] = readScalar(refineDict.lookup("lowerRefineLevel"));
|
||||||
|
refData[2] = readScalar(refineDict.lookup("refineInterval"));
|
||||||
|
refData[3] = readScalar(refineDict.lookup("maxRefinement"));
|
||||||
|
|
||||||
|
return refData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Foam::dynamicRefineBalancedFvMesh::updateRefinementField()
|
||||||
|
{
|
||||||
|
Info<< "Calculating internal refinement field" << endl;
|
||||||
|
|
||||||
|
volScalarField& intRefFld = *internalRefinementFieldPtr_;
|
||||||
|
volScalarField& targetFld = *targetLevelPtr_;
|
||||||
|
volScalarField& currFld = *isLevelPtr_;
|
||||||
|
|
||||||
|
// Set the internal refinement field to zero to start with
|
||||||
|
intRefFld = dimensionedScalar("zero",dimless,0.0);
|
||||||
|
|
||||||
|
// Get the cell level field from dynamicRefineFvMesh
|
||||||
|
const labelList& cellLevel = meshCutter().cellLevel();
|
||||||
|
|
||||||
|
// Read the points at which refinement and unrefinement occur from the
|
||||||
|
// dynamicMeshDict entries
|
||||||
|
List<scalar> refinePoints = readRefinementPoints();
|
||||||
|
|
||||||
|
// init list for refine/unrefine field (-1=unrefine, 1=refine, 0=do nothing)
|
||||||
|
labelList markRefineCells (this->nCells(), 0);
|
||||||
|
|
||||||
|
// init list for target refinement level per cell
|
||||||
|
labelList targetLevel (this->nCells(), 0);
|
||||||
|
|
||||||
|
// First fields
|
||||||
|
List<word> fieldNames = fields_.toc();
|
||||||
|
Field<scalar> refFld(nCells(),0.0);
|
||||||
|
|
||||||
|
forAll(fieldNames, i)
|
||||||
|
{
|
||||||
|
word fldName = fieldNames[i];
|
||||||
|
scalar minValue = fields_[fldName][0];
|
||||||
|
scalar maxValue = fields_[fldName][1];
|
||||||
|
label refineLevel = static_cast<label>(fields_[fldName][2]);
|
||||||
|
|
||||||
|
const volScalarField& fld = this->lookupObject<volScalarField>(fldName);
|
||||||
|
|
||||||
|
// Limit the value of refFld based on its max level
|
||||||
|
forAll(fld, cellI)
|
||||||
|
{
|
||||||
|
if ((fld[cellI] >= minValue) && (fld[cellI] <= maxValue))
|
||||||
|
{
|
||||||
|
// increase targetLevel up to refineLevel
|
||||||
|
// BUT: do not decrease if cell already marked for higher refinement level by previous criterion
|
||||||
|
targetLevel[cellI] = max(targetLevel[cellI], refineLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then gradients
|
||||||
|
List<word> gradFieldNames = gradFields_.toc();
|
||||||
|
|
||||||
|
Field<scalar> cubeRtV = Foam::pow(this->V(),1.0/3.0);
|
||||||
|
|
||||||
|
forAll(gradFieldNames, i)
|
||||||
|
{
|
||||||
|
word fldName = gradFieldNames[i];
|
||||||
|
scalar minValue = gradFields_[fldName][0];
|
||||||
|
scalar maxValue = gradFields_[fldName][1];
|
||||||
|
label refineLevel = static_cast<label>(gradFields_[fldName][2]);
|
||||||
|
|
||||||
|
const volScalarField& fld = this->lookupObject<volScalarField>(fldName);
|
||||||
|
|
||||||
|
refFld = mag(fvc::grad(fld)) * cubeRtV;
|
||||||
|
|
||||||
|
// Limit the value of refFld based on its max level
|
||||||
|
forAll(refFld, cellI)
|
||||||
|
{
|
||||||
|
if ((refFld[cellI] >= minValue) && (refFld[cellI] <= maxValue))
|
||||||
|
{
|
||||||
|
targetLevel[cellI] = max(targetLevel[cellI], refineLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then curls
|
||||||
|
List<word> curlFieldNames = curlFields_.toc();
|
||||||
|
|
||||||
|
|
||||||
|
forAll(curlFieldNames, i)
|
||||||
|
{
|
||||||
|
word fldName = curlFieldNames[i];
|
||||||
|
scalar minValue = curlFields_[fldName][0];
|
||||||
|
scalar maxValue = curlFields_[fldName][1];
|
||||||
|
label refineLevel = static_cast<label>(curlFields_[fldName][2]);
|
||||||
|
|
||||||
|
const volVectorField& fld = this->lookupObject<volVectorField>(fldName);
|
||||||
|
|
||||||
|
refFld = mag(fvc::curl(fld));
|
||||||
|
|
||||||
|
// Limit the value of refFld based on its max level
|
||||||
|
forAll(refFld, cellI)
|
||||||
|
{
|
||||||
|
if ((refFld[cellI] >= minValue) && (refFld[cellI] <= maxValue))
|
||||||
|
{
|
||||||
|
targetLevel[cellI] = max(targetLevel[cellI], refineLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At the interface, assumed to be always the maximum refinement level
|
||||||
|
List<word> interfaceRefineField = interface_.toc();
|
||||||
|
forAll(interfaceRefineField, i)
|
||||||
|
{
|
||||||
|
word fldName = interfaceRefineField[i];
|
||||||
|
// read region of maximum refinement levels inside and outside of interface indicator field
|
||||||
|
// (does not need to be alpha, can also be a concentration field)
|
||||||
|
|
||||||
|
scalar innerRefLayers = readScalar(interface_[fldName].lookup("innerRefLayers"));
|
||||||
|
scalar outerRefLayers = readScalar(interface_[fldName].lookup("outerRefLayers"));
|
||||||
|
|
||||||
|
scalar nAddLayers(0);
|
||||||
|
if (interface_[fldName].found("nAddLayers"))
|
||||||
|
{
|
||||||
|
nAddLayers = readScalar(interface_[fldName].lookup("nAddLayers"));
|
||||||
|
}
|
||||||
|
|
||||||
|
label refineLevel = refinePoints[3];
|
||||||
|
|
||||||
|
if (interface_[fldName].found("maxRefineLevel"))
|
||||||
|
{
|
||||||
|
refineLevel = readScalar(interface_[fldName].lookup("maxRefineLevel"));
|
||||||
|
|
||||||
|
// to avoid user input mistakes, limit the value with the maximum allowed
|
||||||
|
refineLevel = min(refinePoints[3], refineLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
const volScalarField& fld = this->lookupObject<volScalarField>(fldName);
|
||||||
|
|
||||||
|
volScalarField isInterface(intRefFld * 0.0);
|
||||||
|
isInterface = dimensionedScalar("isInterface",dimless,0.0);
|
||||||
|
|
||||||
|
surfaceScalarField deltaAlpha = mag(fvc::snGrad(fld) / this->deltaCoeffs());
|
||||||
|
|
||||||
|
const labelUList& owner = this->owner();
|
||||||
|
const labelUList& neighbour = this->neighbour();
|
||||||
|
|
||||||
|
forAll(deltaAlpha, faceI)
|
||||||
|
{
|
||||||
|
//TODO: add a min max value of the specified field to be marked for refinement
|
||||||
|
// NOW: hard-coded method snGradAlpha: checks mag(alpha_N - alpha_P) > 0.1 ? 1:0
|
||||||
|
if (deltaAlpha[faceI] > 0.1) // currently a fixed prescribed value; should be read from díctionary
|
||||||
|
{
|
||||||
|
label own = owner[faceI];
|
||||||
|
label nei = neighbour[faceI];
|
||||||
|
|
||||||
|
// set isInterface field to one
|
||||||
|
isInterface[own] = 1.0;
|
||||||
|
isInterface[nei] = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumed fld=0.5*(fldMax+fldMin) defines the interface
|
||||||
|
dimensionedScalar fldInterfaceValue(0.5*(max(fld)+min(fld)));
|
||||||
|
|
||||||
|
//-DD: old implementation based on face interpolation
|
||||||
|
// which results in slower transport in diagonal direction
|
||||||
|
// add inner refinement layers
|
||||||
|
//for(label i=0; i < innerRefLayers; i++)
|
||||||
|
//{
|
||||||
|
// isInterface += neg(- fvc::average(fvc::interpolate(isInterface)) * pos(fld - fldInterfaceValue));
|
||||||
|
// isInterface = neg(- isInterface);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// add outer refinement layers
|
||||||
|
//for(label i=0; i < outerRefLayers; i++)
|
||||||
|
//{
|
||||||
|
// isInterface += neg(- fvc::average(fvc::interpolate(isInterface)) * pos(fldInterfaceValue - fld));
|
||||||
|
// isInterface = neg(- isInterface);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//forAll(isInterface, cellI)
|
||||||
|
//{
|
||||||
|
// if (isInterface[cellI] > 0.5)
|
||||||
|
// {
|
||||||
|
// targetLevel[cellI] = max(targetLevel[cellI], refineLevel);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//-DD: new version using volPointInterpolation (direction independent buffer layer)
|
||||||
|
const volPointInterpolation& pInterp = volPointInterpolation::New(*this);
|
||||||
|
const fvMesh& mesh = fld.mesh();
|
||||||
|
|
||||||
|
// add inner refinement layers
|
||||||
|
for(label i=0; i < innerRefLayers; i++)
|
||||||
|
{
|
||||||
|
volScalarField markInner(isInterface*pos(fld - fldInterfaceValue));
|
||||||
|
pointScalarField markLayerP(pInterp.interpolate(markInner));
|
||||||
|
|
||||||
|
forAll(mesh.C(), cellI)
|
||||||
|
{
|
||||||
|
scalar sum = 0.;
|
||||||
|
label nPoints = 0;
|
||||||
|
|
||||||
|
forAll(mesh.cellPoints()[cellI], pointI)
|
||||||
|
{
|
||||||
|
sum += markLayerP[mesh.cellPoints()[cellI][pointI]];
|
||||||
|
nPoints++;
|
||||||
|
}
|
||||||
|
if (nPoints > 0)
|
||||||
|
{
|
||||||
|
sum /= nPoints;
|
||||||
|
}
|
||||||
|
isInterface[cellI] += sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isInterface = pos(isInterface - SMALL);
|
||||||
|
|
||||||
|
// add outer refinement layers
|
||||||
|
for(label i=0; i < outerRefLayers; i++)
|
||||||
|
{
|
||||||
|
volScalarField markOuter(isInterface*pos(fldInterfaceValue - fld));
|
||||||
|
pointScalarField markLayerP(pInterp.interpolate(markOuter));
|
||||||
|
|
||||||
|
forAll(mesh.C(), cellI)
|
||||||
|
{
|
||||||
|
scalar sum = 0.;
|
||||||
|
label nPoints = 0;
|
||||||
|
|
||||||
|
forAll(mesh.cellPoints()[cellI], pointI)
|
||||||
|
{
|
||||||
|
sum += markLayerP[mesh.cellPoints()[cellI][pointI]];
|
||||||
|
nPoints++;
|
||||||
|
}
|
||||||
|
if (nPoints > 0)
|
||||||
|
{
|
||||||
|
sum /= nPoints;
|
||||||
|
}
|
||||||
|
isInterface[cellI] += sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isInterface = pos(isInterface - SMALL);
|
||||||
|
|
||||||
|
forAll(isInterface, cellI)
|
||||||
|
{
|
||||||
|
if (isInterface[cellI] > 0.5)
|
||||||
|
{
|
||||||
|
targetLevel[cellI] = max(targetLevel[cellI], refineLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-DD: old implementation based on face interpolation
|
||||||
|
// which results in slower transport in diagonal direction
|
||||||
|
// expand additional layers if specified:
|
||||||
|
if (nAddLayers > 0)
|
||||||
|
{
|
||||||
|
// loop over additional layers
|
||||||
|
for(label i=1; i < refineLevel; i++)
|
||||||
|
{
|
||||||
|
// #nAddLayers cells per additional level
|
||||||
|
for(label j=0; j < nAddLayers; j++)
|
||||||
|
{
|
||||||
|
isInterface += neg(- fvc::average(fvc::interpolate(isInterface)));
|
||||||
|
isInterface = neg(- isInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(isInterface, cellI)
|
||||||
|
{
|
||||||
|
if (isInterface[cellI] == 1.0)
|
||||||
|
{
|
||||||
|
targetLevel[cellI] = max(targetLevel[cellI], (refineLevel - i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The set refinement physical regions (force the mesh to stay refined
|
||||||
|
// near key features)
|
||||||
|
forAll(refinedRegions_, regionI)
|
||||||
|
{
|
||||||
|
const entry& region = refinedRegions_[regionI];
|
||||||
|
|
||||||
|
autoPtr<topoSetSource> source =
|
||||||
|
topoSetSource::New(region.keyword(), *this, region.dict());
|
||||||
|
|
||||||
|
cellSet selectedCellSet
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
"cellSet",
|
||||||
|
nCells()/10+1 //estimate
|
||||||
|
);
|
||||||
|
|
||||||
|
source->applyToSet
|
||||||
|
(
|
||||||
|
topoSetSource::NEW,
|
||||||
|
selectedCellSet
|
||||||
|
);
|
||||||
|
|
||||||
|
const labelList cells = selectedCellSet.toc();
|
||||||
|
|
||||||
|
label minLevel = readLabel(region.dict().lookup("minLevel"));
|
||||||
|
|
||||||
|
forAll(cells, i)
|
||||||
|
{
|
||||||
|
const label& cellI = cells[i];
|
||||||
|
|
||||||
|
targetLevel[cellI] = max(targetLevel[cellI], minLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-DD: add buffer layer based on targetLevel field to prevent 2-to-1 refinement
|
||||||
|
|
||||||
|
volScalarField blockedLevel = targetFld * 0.;
|
||||||
|
|
||||||
|
for (label currLayer=refinePoints[3]; currLayer>=1; currLayer--)
|
||||||
|
{
|
||||||
|
forAll (targetLevel, cellI)
|
||||||
|
{
|
||||||
|
if (targetLevel[cellI] >= currLayer)
|
||||||
|
{
|
||||||
|
blockedLevel[cellI] = targetLevel[cellI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (label i=0; i<nBufferLayers_; i++)
|
||||||
|
{
|
||||||
|
blockedLevel = max(blockedLevel, pos(fvc::average(fvc::interpolate(blockedLevel)) - SMALL)*(currLayer-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
labelList blockLev(blockedLevel.internalField().size(), 0);
|
||||||
|
forAll (blockLev, cellI)
|
||||||
|
{
|
||||||
|
blockLev[cellI] = blockedLevel[cellI];
|
||||||
|
}
|
||||||
|
targetLevel = max(targetLevel, blockLev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark cells to be refined/unrefined based on above criteria:
|
||||||
|
// simply check, if targetLevel lower or higher cellLevel
|
||||||
|
forAll (intRefFld.internalField(), cellI)
|
||||||
|
{
|
||||||
|
intRefFld.primitiveFieldRef()[cellI] = targetLevel[cellI] - cellLevel[cellI];
|
||||||
|
targetFld.primitiveFieldRef()[cellI] = targetLevel[cellI];
|
||||||
|
currFld.primitiveFieldRef()[cellI] = cellLevel[cellI];
|
||||||
|
}
|
||||||
|
|
||||||
|
intRefFld.correctBoundaryConditions();
|
||||||
|
|
||||||
|
Info<<"Min,max refinement field = " << Foam::min(intRefFld).value() << ", "
|
||||||
|
<< Foam::max(intRefFld).value() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Foam::dynamicRefineBalancedFvMesh::readRefinementDict()
|
||||||
|
{
|
||||||
|
dictionary dynamicMeshDict
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dynamicMeshDict",
|
||||||
|
time().constant(),
|
||||||
|
*this,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const dictionary refineDict
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dynamicMeshDict",
|
||||||
|
time().constant(),
|
||||||
|
*this,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
).subDict("dynamicRefineFvMeshCoeffs")
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
wordList surfFlds;
|
||||||
|
if (refineDict.readIfPresent("mapSurfaceFields", surfFlds))
|
||||||
|
{
|
||||||
|
// Rework into hashtable.
|
||||||
|
mapSurfaceFields_.resize(surfFlds.size());
|
||||||
|
forAll(surfFlds, i)
|
||||||
|
{
|
||||||
|
mapSurfaceFields_.insert(surfFlds[i], surfFlds[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nBufferLayers_ = readLabel(refineDict.lookup("nBufferLayers"));
|
||||||
|
|
||||||
|
if( dynamicMeshDict.isDict("refinementControls") )
|
||||||
|
{
|
||||||
|
dictionary refineControlDict =
|
||||||
|
dynamicMeshDict.subDict("refinementControls");
|
||||||
|
|
||||||
|
enableRefinementControl_ =
|
||||||
|
Switch(refineControlDict.lookup("enableRefinementControl"));
|
||||||
|
|
||||||
|
if( enableRefinementControl_ )
|
||||||
|
{
|
||||||
|
// Overwrite field name entry in dynamicRefineFvMeshCoeffs?
|
||||||
|
// For now you just have to be smart and enter
|
||||||
|
// 'internalRefinementField' for the field name manually
|
||||||
|
|
||||||
|
// Read HashTable of field-refinement scalars
|
||||||
|
if( refineControlDict.found("fields") )
|
||||||
|
{
|
||||||
|
fields_ = HashTable< List<scalar> >
|
||||||
|
(
|
||||||
|
refineControlDict.lookup("fields")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read HashTable of gradient-refinement scalars
|
||||||
|
if( refineControlDict.found("gradients") )
|
||||||
|
{
|
||||||
|
gradFields_ = HashTable< List<scalar> >
|
||||||
|
(
|
||||||
|
refineControlDict.lookup("gradients")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read HashTable of curl-refinement vectors
|
||||||
|
if( refineControlDict.found("curls") )
|
||||||
|
{
|
||||||
|
curlFields_ = HashTable< List<scalar> >
|
||||||
|
(
|
||||||
|
refineControlDict.lookup("curls")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read interface refinement data
|
||||||
|
if( refineControlDict.found("interface") )
|
||||||
|
{
|
||||||
|
interface_ = HashTable< dictionary >
|
||||||
|
(
|
||||||
|
refineControlDict.lookup("interface")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read refinement regions
|
||||||
|
if( refineControlDict.found("regions") )
|
||||||
|
{
|
||||||
|
refinedRegions_ = PtrList<entry>
|
||||||
|
(
|
||||||
|
refineControlDict.lookup("regions")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::dynamicRefineBalancedFvMesh::dynamicRefineBalancedFvMesh
|
||||||
|
(
|
||||||
|
const IOobject& io
|
||||||
|
)
|
||||||
|
:
|
||||||
|
dynamicRefineFvMesh(io),
|
||||||
|
internalRefinementFieldPtr_(NULL),
|
||||||
|
targetLevelPtr_(NULL),
|
||||||
|
isLevelPtr_(NULL),
|
||||||
|
fields_(),
|
||||||
|
gradFields_(),
|
||||||
|
curlFields_(),
|
||||||
|
interface_(),
|
||||||
|
refinedRegions_(),
|
||||||
|
enableRefinementControl_(false),
|
||||||
|
nBufferLayers_(0),
|
||||||
|
rebalance_(false)
|
||||||
|
{
|
||||||
|
readRefinementDict();
|
||||||
|
|
||||||
|
if( enableRefinementControl_ )
|
||||||
|
{
|
||||||
|
internalRefinementFieldPtr_ = new volScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"internalRefinementField",
|
||||||
|
time().timeName(),
|
||||||
|
*this,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
*this,
|
||||||
|
dimensionedScalar("zero", dimless, 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
targetLevelPtr_ = new volScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"targetLevel",
|
||||||
|
time().timeName(),
|
||||||
|
*this,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
*this,
|
||||||
|
dimensionedScalar("zero", dimless, 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
isLevelPtr_ = new volScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"isLevel",
|
||||||
|
time().timeName(),
|
||||||
|
*this,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
*this,
|
||||||
|
dimensionedScalar("zero", dimless, 0.0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::dynamicRefineBalancedFvMesh::~dynamicRefineBalancedFvMesh()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::dynamicRefineBalancedFvMesh::mapFields(const mapPolyMesh& mpm)
|
||||||
|
{
|
||||||
|
DebugVar(mpm.nOldCells());
|
||||||
|
dynamicRefineFvMesh::mapFields(mpm);
|
||||||
|
|
||||||
|
// Correct surface fields on introduced internal faces. These get
|
||||||
|
// created out-of-nothing so get an interpolated value.
|
||||||
|
mapNewInternalFaces<scalar>(mpm.faceMap());
|
||||||
|
mapNewInternalFaces<vector>(mpm.faceMap());
|
||||||
|
mapNewInternalFaces<sphericalTensor>(mpm.faceMap());
|
||||||
|
mapNewInternalFaces<symmTensor>(mpm.faceMap());
|
||||||
|
mapNewInternalFaces<tensor>(mpm.faceMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::dynamicRefineBalancedFvMesh::update()
|
||||||
|
{
|
||||||
|
//Part 0 - Update internally calculated refinement field
|
||||||
|
readRefinementDict();
|
||||||
|
|
||||||
|
List<scalar> refinePoints = readRefinementPoints();
|
||||||
|
label refineInterval = refinePoints[2];
|
||||||
|
|
||||||
|
if( enableRefinementControl_ && time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0 )
|
||||||
|
{
|
||||||
|
updateRefinementField();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Part 1 - Call normal update from dynamicRefineFvMesh
|
||||||
|
bool hasChanged = dynamicRefineFvMesh::update();
|
||||||
|
|
||||||
|
if( Pstream::parRun() && hasChanged)
|
||||||
|
{
|
||||||
|
//Correct values on all coupled patches
|
||||||
|
correctBoundaries<scalar>();
|
||||||
|
correctBoundaries<vector>();
|
||||||
|
correctBoundaries<sphericalTensor>();
|
||||||
|
correctBoundaries<symmTensor>();
|
||||||
|
correctBoundaries<tensor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
dictionary decomposeParDict
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"decomposeParDict",
|
||||||
|
time().system(),
|
||||||
|
*this,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
rebalance_ = false;
|
||||||
|
|
||||||
|
// Part 2 - Load Balancing
|
||||||
|
{
|
||||||
|
dictionary refineDict
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dynamicMeshDict",
|
||||||
|
time().constant(),
|
||||||
|
*this,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
).subDict("dynamicRefineFvMeshCoeffs")
|
||||||
|
);
|
||||||
|
|
||||||
|
Switch enableBalancing = refineDict.lookup("enableBalancing");
|
||||||
|
|
||||||
|
if ( Pstream::parRun() && hasChanged )
|
||||||
|
{
|
||||||
|
const scalar allowableImbalance =
|
||||||
|
readScalar(refineDict.lookup("allowableImbalance"));
|
||||||
|
|
||||||
|
//First determine current level of imbalance - do this for all
|
||||||
|
// parallel runs with a changing mesh, even if balancing is disabled
|
||||||
|
label nGlobalCells = globalData().nTotalCells();
|
||||||
|
scalar idealNCells = scalar(nGlobalCells)/scalar(Pstream::nProcs());
|
||||||
|
scalar localImbalance = mag(scalar(nCells()) - idealNCells);
|
||||||
|
Foam::reduce(localImbalance, maxOp<scalar>());
|
||||||
|
scalar maxImbalance = localImbalance/idealNCells;
|
||||||
|
|
||||||
|
Info<<"Maximum imbalance = " << 100*maxImbalance << " %" << endl;
|
||||||
|
|
||||||
|
//If imbalanced, construct weighted coarse graph (level 0) with node
|
||||||
|
// weights equal to their number of subcells. This partitioning works
|
||||||
|
// as long as the number of level 0 cells is several times greater than
|
||||||
|
// the number of processors.
|
||||||
|
if( maxImbalance > allowableImbalance && enableBalancing)
|
||||||
|
{
|
||||||
|
Info << "\n**Solver hold for redistribution at time = " << time().timeName() << " s" << endl;
|
||||||
|
|
||||||
|
rebalance_ = true;
|
||||||
|
|
||||||
|
const labelIOList& cellLevel = meshCutter().cellLevel();
|
||||||
|
Map<label> coarseIDmap(100);
|
||||||
|
labelList uniqueIndex(nCells(),0);
|
||||||
|
|
||||||
|
label nCoarse = 0;
|
||||||
|
|
||||||
|
forAll(cells(), cellI)
|
||||||
|
{
|
||||||
|
if( cellLevel[cellI] > 0 )
|
||||||
|
{
|
||||||
|
uniqueIndex[cellI] = nCells() + topParentID
|
||||||
|
(
|
||||||
|
meshCutter().history().parentIndex(cellI)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uniqueIndex[cellI] = cellI;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( coarseIDmap.insert(uniqueIndex[cellI], nCoarse) )
|
||||||
|
{
|
||||||
|
++nCoarse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to local sequential indexing and calculate coarse
|
||||||
|
// points and weights
|
||||||
|
labelList localIndex(nCells(),0);
|
||||||
|
pointField coarsePoints(nCoarse,vector::zero);
|
||||||
|
scalarField coarseWeights(nCoarse,0.0);
|
||||||
|
|
||||||
|
forAll(uniqueIndex, cellI)
|
||||||
|
{
|
||||||
|
localIndex[cellI] = coarseIDmap[uniqueIndex[cellI]];
|
||||||
|
|
||||||
|
// If 2D refinement (quadtree) is ever implemented, this '3'
|
||||||
|
// should be set in general as the number of refinement
|
||||||
|
// dimensions.
|
||||||
|
label w = (1 << (3*cellLevel[cellI]));
|
||||||
|
|
||||||
|
coarseWeights[localIndex[cellI]] += 1.0;
|
||||||
|
coarsePoints[localIndex[cellI]] += C()[cellI]/w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up decomposer - a separate dictionary is used here so
|
||||||
|
// you can use a simple partitioning for decomposePar and
|
||||||
|
// ptscotch for the rebalancing (or any chosen algorithms)
|
||||||
|
autoPtr<decompositionMethod> decomposer
|
||||||
|
(
|
||||||
|
decompositionMethod::New
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"balanceParDict",
|
||||||
|
time().system(),
|
||||||
|
*this,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
labelList finalDecomp = decomposer().decompose
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
localIndex,
|
||||||
|
coarsePoints,
|
||||||
|
coarseWeights
|
||||||
|
);
|
||||||
|
|
||||||
|
scalar tolDim = globalMeshData::matchTol_ * bounds().mag();
|
||||||
|
|
||||||
|
Info<< "Distributing the mesh ..." << endl;
|
||||||
|
fvMeshDistribute distributor(*this, tolDim);
|
||||||
|
|
||||||
|
Info<< "Mapping the fields ..." << endl;
|
||||||
|
autoPtr<mapDistributePolyMesh> map =
|
||||||
|
distributor.distribute(finalDecomp);
|
||||||
|
|
||||||
|
Info<< "Distribute the map ..." << endl;
|
||||||
|
meshCutter_.distribute(map);
|
||||||
|
|
||||||
|
|
||||||
|
Info << "Successfully distributed mesh" << endl;
|
||||||
|
|
||||||
|
scalarList procLoadNew (Pstream::nProcs(), 0.0);
|
||||||
|
procLoadNew[Pstream::myProcNo()] = this->nCells();
|
||||||
|
|
||||||
|
reduce(procLoadNew, sumOp<List<scalar> >());
|
||||||
|
|
||||||
|
scalar overallLoadNew = sum(procLoadNew);
|
||||||
|
scalar averageLoadNew = overallLoadNew/double(Pstream::nProcs());
|
||||||
|
|
||||||
|
Info << "New distribution: " << procLoadNew << endl;
|
||||||
|
Info << "Max deviation: " << max(Foam::mag(procLoadNew-averageLoadNew)/averageLoadNew)*100.0 << " %" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Pstream::parRun() && rebalance_)
|
||||||
|
{
|
||||||
|
//Correct values on all coupled patches
|
||||||
|
correctBoundaries<scalar>();
|
||||||
|
correctBoundaries<vector>();
|
||||||
|
correctBoundaries<sphericalTensor>();
|
||||||
|
correctBoundaries<symmTensor>();
|
||||||
|
correctBoundaries<tensor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,206 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2014 Tyler Voskuilen
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is a derivative work 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::dynamicRefineBalancedFvMesh
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
dynamicRefineBalancedFvMesh.C
|
||||||
|
dynamicRefineBalancedFvMeshTemplates.C
|
||||||
|
|
||||||
|
Authors
|
||||||
|
T.G. Voskuilen ( https://github.com/tgvoskuilen/meshBalancing )
|
||||||
|
Daniel Deising <deising@mma.tu-darmstadt.de>
|
||||||
|
Daniel Rettenmaier <rettenmaier@gsc.tu-darmstadt.de>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Description
|
||||||
|
A fvMesh with built-in multi-criterion refinement
|
||||||
|
and run-time load balancing.
|
||||||
|
|
||||||
|
You may refer to this software as :
|
||||||
|
//- full bibliographic data to be provided
|
||||||
|
|
||||||
|
This code has been developed by :
|
||||||
|
Daniel Rettenmaier (main developer).
|
||||||
|
|
||||||
|
Method Development and Intellectual Property :
|
||||||
|
T.G. Voskuilen (Purdue University)
|
||||||
|
Timothée Pourpoint <timothee@purdue.edu> (Purdue University
|
||||||
|
Daniel Rettenmaier <rettenmaier@gsc.tu-darmstadt.de>
|
||||||
|
Daniel Deising <deising@mma.tu-darmstadt.de>
|
||||||
|
Holger Marschall <marschall@csi.tu-darmstadt.de>
|
||||||
|
Dieter Bothe <bothe@csi.tu-darmstadt.de>
|
||||||
|
Cameron Tropea <ctropea@sla.tu-darmstadt.de>
|
||||||
|
|
||||||
|
School of Aeronautics and Astronautics
|
||||||
|
Purdue University
|
||||||
|
Mathematical Modeling and Analysis
|
||||||
|
Institute for Fluid Mechanics and Aerodynamics
|
||||||
|
Center of Smart Interfaces
|
||||||
|
Technische Universitaet Darmstadt
|
||||||
|
|
||||||
|
If you use this software for your scientific work or your publications,
|
||||||
|
please don't forget to acknowledge explicitly the use of it.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef dynamicRefineBalancedFvMesh_H
|
||||||
|
#define dynamicRefineBalancedFvMesh_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "dynamicFvMesh.H"
|
||||||
|
#include "dynamicRefineFvMesh.H"
|
||||||
|
#include "hexRef8.H"
|
||||||
|
#include "PackedBoolList.H"
|
||||||
|
#include "Switch.H"
|
||||||
|
#include "decompositionMethod.H"
|
||||||
|
#include "fvMeshDistribute.H"
|
||||||
|
#include "mapDistributePolyMesh.H"
|
||||||
|
#include "HashTable.H"
|
||||||
|
#include "topoSetSource.H"
|
||||||
|
#include "cellSet.H"
|
||||||
|
#include "PtrDictionary.H"
|
||||||
|
#include "dictionaryEntry.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class dynamicRefineBalancedFvMesh Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class dynamicRefineBalancedFvMesh
|
||||||
|
:
|
||||||
|
public dynamicRefineFvMesh
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//- (non-flux)SurfaceFields to map
|
||||||
|
HashTable<word> mapSurfaceFields_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
volScalarField* internalRefinementFieldPtr_;
|
||||||
|
volScalarField* targetLevelPtr_;
|
||||||
|
volScalarField* isLevelPtr_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
HashTable< List<scalar> > fields_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
HashTable< List<scalar> > gradFields_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
HashTable< List<scalar> > curlFields_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
HashTable< dictionary > interface_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
PtrList<entry> refinedRegions_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
Switch enableRefinementControl_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
void updateRefinementField();
|
||||||
|
|
||||||
|
//-
|
||||||
|
void readRefinementDict();
|
||||||
|
|
||||||
|
//-
|
||||||
|
List<scalar> readRefinementPoints();
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
dynamicRefineBalancedFvMesh(const dynamicRefineBalancedFvMesh&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const dynamicRefineBalancedFvMesh&);
|
||||||
|
|
||||||
|
//-
|
||||||
|
label topParentID(label p);
|
||||||
|
|
||||||
|
//-
|
||||||
|
label nBufferLayers_;
|
||||||
|
|
||||||
|
//-
|
||||||
|
bool rebalance_;
|
||||||
|
|
||||||
|
//- Map non-flux surface<Type>Fields for new internal faces
|
||||||
|
// (from cell splitting)
|
||||||
|
template <class T>
|
||||||
|
void mapNewInternalFaces(const labelList& faceMap);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("dynamicRefineBalancedFvMesh");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from IOobject
|
||||||
|
explicit dynamicRefineBalancedFvMesh(const IOobject& io);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~dynamicRefineBalancedFvMesh();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Update the mesh for both mesh motion and topology change
|
||||||
|
virtual bool update();
|
||||||
|
|
||||||
|
//- Map all fields in time using given map
|
||||||
|
virtual void mapFields(const mapPolyMesh& mpm);
|
||||||
|
|
||||||
|
//- Template to update all volField boundaries
|
||||||
|
template<class Type> void correctBoundaries();
|
||||||
|
|
||||||
|
//-
|
||||||
|
bool rebalance()
|
||||||
|
{
|
||||||
|
return rebalance_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "dynamicRefineBalancedFvMeshTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,217 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2014 Tyler Voskuilen
|
||||||
|
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "volMesh.H"
|
||||||
|
#include "fvPatchField.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Foam::dynamicRefineBalancedFvMesh::mapNewInternalFaces
|
||||||
|
(
|
||||||
|
const labelList& faceMap
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef GeometricField<T, fvsPatchField, surfaceMesh> GeoField;
|
||||||
|
HashTable<GeoField*> sFlds(this->objectRegistry::lookupClass<GeoField>());
|
||||||
|
|
||||||
|
const labelUList& owner = this->faceOwner();
|
||||||
|
const labelUList& neighbour = this->faceNeighbour();
|
||||||
|
const dimensionedScalar deltaN = 1e-8 / pow(average(this->V()), 1.0 / 3.0);
|
||||||
|
|
||||||
|
forAllIter(typename HashTable<GeoField*>, sFlds, iter)
|
||||||
|
{
|
||||||
|
GeoField& sFld = *iter();
|
||||||
|
if (mapSurfaceFields_.found(iter.key()))
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
InfoInFunction << iter.key()<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create flat version of field
|
||||||
|
Field<T> tsFld(this->nFaces(), pTraits<T>::zero);
|
||||||
|
{
|
||||||
|
forAll(sFld.internalField(), iFace)
|
||||||
|
{
|
||||||
|
tsFld[iFace] = sFld.internalField()[iFace];
|
||||||
|
}
|
||||||
|
forAll(sFld.boundaryField(), iPatch)
|
||||||
|
{
|
||||||
|
const fvsPatchField<T>& pfld = sFld.boundaryField()[iPatch];
|
||||||
|
|
||||||
|
label start = pfld.patch().start();
|
||||||
|
forAll(pfld, faceI)
|
||||||
|
{
|
||||||
|
tsFld[faceI+start] = pfld[faceI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Loop over all faces
|
||||||
|
for (label facei = 0; facei < nInternalFaces(); facei++)
|
||||||
|
{
|
||||||
|
label oldFacei = faceMap[facei];
|
||||||
|
|
||||||
|
//- map surface field on newly generated faces
|
||||||
|
if (oldFacei == -1)
|
||||||
|
{
|
||||||
|
//- find owner and neighbour cell
|
||||||
|
const cell& ownFaces = this->cells()[owner[facei]];
|
||||||
|
const cell& neiFaces = this->cells()[neighbour[facei]];
|
||||||
|
|
||||||
|
//- loop over all owner/neighbour cell faces
|
||||||
|
//- and find already mapped ones (master-faces):
|
||||||
|
T tmpValue = pTraits<T>::zero;
|
||||||
|
scalar magFld = 0;
|
||||||
|
label counter = 0;
|
||||||
|
|
||||||
|
//- simple averaging of all neighbour master-faces
|
||||||
|
forAll(ownFaces, iFace)
|
||||||
|
{
|
||||||
|
if (faceMap[ownFaces[iFace]] != -1)
|
||||||
|
{
|
||||||
|
tmpValue += tsFld[ownFaces[iFace]];
|
||||||
|
magFld += mag(tsFld[ownFaces[iFace]]);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(neiFaces, iFace)
|
||||||
|
{
|
||||||
|
if (faceMap[neiFaces[iFace]] != -1)
|
||||||
|
{
|
||||||
|
tmpValue = tmpValue + tsFld[neiFaces[iFace]];
|
||||||
|
magFld += mag(tsFld[neiFaces[iFace]]);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(counter > 0)
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
GeometricField<T, fvsPatchField, surfaceMesh>::typeName
|
||||||
|
== "surfaceScalarField"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tmpValue /= counter;
|
||||||
|
}
|
||||||
|
else if
|
||||||
|
(
|
||||||
|
GeometricField<T, fvsPatchField, surfaceMesh>::typeName
|
||||||
|
== "surfaceVectorField"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
magFld /= counter;
|
||||||
|
tmpValue *= magFld/(mag(tmpValue)+deltaN.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "mapping implementation only valid for"
|
||||||
|
<< " scalar and vector fields! \n Field "
|
||||||
|
<< sFld.name() << " is of type: "
|
||||||
|
<< GeometricField<T, fvsPatchField, surfaceMesh>::typeName
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sFld[facei] = tmpValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::dynamicRefineBalancedFvMesh::correctBoundaries()
|
||||||
|
{
|
||||||
|
typedef GeometricField<Type, fvPatchField, volMesh> GeoField;
|
||||||
|
|
||||||
|
HashTable<GeoField*> flds(this->objectRegistry::lookupClass<GeoField>());
|
||||||
|
|
||||||
|
forAllIter(typename HashTable<GeoField*>, flds, iter)
|
||||||
|
{
|
||||||
|
GeoField& fld = *iter();
|
||||||
|
|
||||||
|
//mimic "evaluate" but only for coupled patches (processor or cyclic)
|
||||||
|
// and only for blocking or nonBlocking comms (no scheduled comms)
|
||||||
|
if
|
||||||
|
(
|
||||||
|
Pstream::defaultCommsType == Pstream::commsTypes::blocking
|
||||||
|
|| Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label nReq = Pstream::nRequests();
|
||||||
|
|
||||||
|
forAll(fld.boundaryField(), patchi)
|
||||||
|
{
|
||||||
|
if(fld.boundaryField()[patchi].coupled())
|
||||||
|
{
|
||||||
|
fld.boundaryFieldRef()[patchi].initEvaluate
|
||||||
|
(
|
||||||
|
Pstream::defaultCommsType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block for any outstanding requests
|
||||||
|
if
|
||||||
|
(
|
||||||
|
Pstream::parRun()
|
||||||
|
&& Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Pstream::waitRequests(nReq);
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(fld.boundaryField(), patchi)
|
||||||
|
{
|
||||||
|
if(fld.boundaryField()[patchi].coupled())
|
||||||
|
{
|
||||||
|
fld.boundaryFieldRef()[patchi].evaluate
|
||||||
|
(
|
||||||
|
Pstream::defaultCommsType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Scheduled patch updates not supported
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"dynamicRefineBalancedFvMeshTemplates::correctBoundaries"
|
||||||
|
) << "Unsuported communications type "
|
||||||
|
<< Pstream::commsTypeNames[Pstream::defaultCommsType]
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -46,7 +46,7 @@ namespace Foam
|
|||||||
|
|
||||||
Foam::label Foam::dynamicRefineFvMesh::count
|
Foam::label Foam::dynamicRefineFvMesh::count
|
||||||
(
|
(
|
||||||
const bitSet& l,
|
const PackedBoolList& l,
|
||||||
const unsigned int val
|
const unsigned int val
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -58,9 +58,9 @@ Foam::label Foam::dynamicRefineFvMesh::count
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug also serves to get-around Clang compiler trying to optimise
|
// debug also serves to get-around Clang compiler trying to optimsie
|
||||||
// out this forAll loop under O3 optimisation
|
// out this forAll loop under O3 optimisation
|
||||||
if (debug)
|
if (debug & 128)
|
||||||
{
|
{
|
||||||
Info<< "n=" << n << endl;
|
Info<< "n=" << n << endl;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ Foam::label Foam::dynamicRefineFvMesh::count
|
|||||||
|
|
||||||
void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
||||||
(
|
(
|
||||||
bitSet& unrefineableCell
|
PackedBoolList& unrefineableCell
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
if (protectedCell_.empty())
|
if (protectedCell_.empty())
|
||||||
@ -86,7 +86,7 @@ void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
|||||||
unrefineableCell = protectedCell_;
|
unrefineableCell = protectedCell_;
|
||||||
|
|
||||||
// Get neighbouring cell level
|
// Get neighbouring cell level
|
||||||
labelList neiLevel(nBoundaryFaces());
|
labelList neiLevel(nFaces()-nInternalFaces());
|
||||||
|
|
||||||
for (label facei = nInternalFaces(); facei < nFaces(); facei++)
|
for (label facei = nInternalFaces(); facei < nFaces(); facei++)
|
||||||
{
|
{
|
||||||
@ -103,10 +103,9 @@ void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
|||||||
forAll(faceNeighbour(), facei)
|
forAll(faceNeighbour(), facei)
|
||||||
{
|
{
|
||||||
label own = faceOwner()[facei];
|
label own = faceOwner()[facei];
|
||||||
|
bool ownProtected = unrefineableCell.get(own);
|
||||||
label nei = faceNeighbour()[facei];
|
label nei = faceNeighbour()[facei];
|
||||||
|
bool neiProtected = unrefineableCell.get(nei);
|
||||||
bool ownProtected = unrefineableCell.test(own);
|
|
||||||
bool neiProtected = unrefineableCell.test(nei);
|
|
||||||
|
|
||||||
if (ownProtected && (cellLevel[nei] > cellLevel[own]))
|
if (ownProtected && (cellLevel[nei] > cellLevel[own]))
|
||||||
{
|
{
|
||||||
@ -120,7 +119,7 @@ void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
|||||||
for (label facei = nInternalFaces(); facei < nFaces(); facei++)
|
for (label facei = nInternalFaces(); facei < nFaces(); facei++)
|
||||||
{
|
{
|
||||||
label own = faceOwner()[facei];
|
label own = faceOwner()[facei];
|
||||||
bool ownProtected = unrefineableCell.test(own);
|
bool ownProtected = unrefineableCell.get(own);
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
ownProtected
|
ownProtected
|
||||||
@ -142,14 +141,16 @@ void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
|||||||
if (seedFace[facei])
|
if (seedFace[facei])
|
||||||
{
|
{
|
||||||
label own = faceOwner()[facei];
|
label own = faceOwner()[facei];
|
||||||
if (unrefineableCell.set(own))
|
if (unrefineableCell.get(own) == 0)
|
||||||
{
|
{
|
||||||
|
unrefineableCell.set(own, 1);
|
||||||
hasExtended = true;
|
hasExtended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
label nei = faceNeighbour()[facei];
|
label nei = faceNeighbour()[facei];
|
||||||
if (unrefineableCell.set(nei))
|
if (unrefineableCell.get(nei) == 0)
|
||||||
{
|
{
|
||||||
|
unrefineableCell.set(nei, 1);
|
||||||
hasExtended = true;
|
hasExtended = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,8 +160,9 @@ void Foam::dynamicRefineFvMesh::calculateProtectedCells
|
|||||||
if (seedFace[facei])
|
if (seedFace[facei])
|
||||||
{
|
{
|
||||||
label own = faceOwner()[facei];
|
label own = faceOwner()[facei];
|
||||||
if (unrefineableCell.set(own))
|
if (unrefineableCell.get(own) == 0)
|
||||||
{
|
{
|
||||||
|
unrefineableCell.set(own, 1);
|
||||||
hasExtended = true;
|
hasExtended = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,63 +207,27 @@ void Foam::dynamicRefineFvMesh::readDict()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Refines cells, maps fields and recalculates (an approximate) flux
|
void Foam::dynamicRefineFvMesh::mapFields(const mapPolyMesh& mpm)
|
||||||
Foam::autoPtr<Foam::mapPolyMesh>
|
|
||||||
Foam::dynamicRefineFvMesh::refine
|
|
||||||
(
|
|
||||||
const labelList& cellsToRefine
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Mesh changing engine.
|
dynamicFvMesh::mapFields(mpm);
|
||||||
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<mapPolyMesh> mapPtr = meshMod.changeMesh(*this, false);
|
|
||||||
mapPolyMesh& map = *mapPtr;
|
|
||||||
|
|
||||||
Info<< "Refined from "
|
|
||||||
<< returnReduce(map.nOldCells(), sumOp<label>())
|
|
||||||
<< " to " << globalData().nTotalCells() << " cells." << endl;
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
// Check map.
|
|
||||||
for (label facei = 0; facei < nInternalFaces(); facei++)
|
|
||||||
{
|
|
||||||
label oldFacei = map.faceMap()[facei];
|
|
||||||
|
|
||||||
if (oldFacei >= nInternalFaces())
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< "New internal face:" << facei
|
|
||||||
<< " fc:" << faceCentres()[facei]
|
|
||||||
<< " originates from boundary oldFace:" << oldFacei
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // Remove the stored tet base points
|
|
||||||
// tetBasePtIsPtr_.clear();
|
|
||||||
// // Remove the cell tree
|
|
||||||
// cellTreePtr_.clear();
|
|
||||||
|
|
||||||
// Update fields
|
|
||||||
updateMesh(map);
|
|
||||||
|
|
||||||
// Correct the flux for modified/added faces. All the faces which only
|
// Correct the flux for modified/added faces. All the faces which only
|
||||||
// have been renumbered will already have been handled by the mapping.
|
// have been renumbered will already have been handled by the mapping.
|
||||||
{
|
{
|
||||||
const labelList& faceMap = map.faceMap();
|
const labelList& faceMap = mpm.faceMap();
|
||||||
const labelList& reverseFaceMap = map.reverseFaceMap();
|
const labelList& reverseFaceMap = mpm.reverseFaceMap();
|
||||||
|
|
||||||
// Storage for any master faces. These will be the original faces
|
// Storage for any master faces. These will be the original faces
|
||||||
// on the coarse cell that get split into four (or rather the
|
// on the coarse cell that get split into four (or rather the
|
||||||
// master face gets modified and three faces get added from the master)
|
// master face gets modified and three faces get added from the master)
|
||||||
labelHashSet masterFaces(4*cellsToRefine.size());
|
// Estimate number of faces created
|
||||||
|
labelHashSet masterFaces
|
||||||
|
(
|
||||||
|
max
|
||||||
|
(
|
||||||
|
mag(nFaces()-mpm.nOldFaces())/4,
|
||||||
|
nFaces()/100
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
forAll(faceMap, facei)
|
forAll(faceMap, facei)
|
||||||
{
|
{
|
||||||
@ -393,8 +359,10 @@ Foam::dynamicRefineFvMesh::refine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update master faces
|
// Update master faces
|
||||||
for (const label facei : masterFaces)
|
forAllConstIter(labelHashSet, masterFaces, iter)
|
||||||
{
|
{
|
||||||
|
label facei = iter.key();
|
||||||
|
|
||||||
if (isInternalFace(facei))
|
if (isInternalFace(facei))
|
||||||
{
|
{
|
||||||
phi[facei] = phiU[facei];
|
phi[facei] = phiU[facei];
|
||||||
@ -415,6 +383,86 @@ Foam::dynamicRefineFvMesh::refine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Correct the flux for injected faces - these are the faces which have
|
||||||
|
// no correspondence to the old mesh (i.e. added without a masterFace, edge
|
||||||
|
// or point). An example is the internal faces from hexRef8.
|
||||||
|
{
|
||||||
|
const labelList& faceMap = mpm.faceMap();
|
||||||
|
|
||||||
|
mapNewInternalFaces<scalar>(this->Sf(), this->magSf(), faceMap);
|
||||||
|
mapNewInternalFaces<vector>(this->Sf(), this->magSf(), faceMap);
|
||||||
|
|
||||||
|
// No oriented fields of more complex type
|
||||||
|
mapNewInternalFaces<sphericalTensor>(faceMap);
|
||||||
|
mapNewInternalFaces<symmTensor>(faceMap);
|
||||||
|
mapNewInternalFaces<tensor>(faceMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Refines cells, maps fields and recalculates (an approximate) flux
|
||||||
|
Foam::autoPtr<Foam::mapPolyMesh>
|
||||||
|
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<mapPolyMesh> map = meshMod.changeMesh(*this, true);
|
||||||
|
autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
|
||||||
|
|
||||||
|
Info<< "Refined from "
|
||||||
|
<< returnReduce(map().nOldCells(), sumOp<label>())
|
||||||
|
<< " to " << globalData().nTotalCells() << " cells." << endl;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
// Check map.
|
||||||
|
for (label facei = 0; facei < nInternalFaces(); facei++)
|
||||||
|
{
|
||||||
|
label oldFacei = map().faceMap()[facei];
|
||||||
|
|
||||||
|
if (oldFacei >= nInternalFaces())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "New internal face:" << facei
|
||||||
|
<< " fc:" << faceCentres()[facei]
|
||||||
|
<< " originates from boundary oldFace:" << oldFacei
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Remove the stored tet base points
|
||||||
|
// tetBasePtIsPtr_.clear();
|
||||||
|
// // Remove the cell tree
|
||||||
|
// cellTreePtr_.clear();
|
||||||
|
|
||||||
|
// Update fields
|
||||||
|
updateMesh(map);
|
||||||
|
|
||||||
|
|
||||||
|
// Move mesh
|
||||||
|
/*
|
||||||
|
pointField newPoints;
|
||||||
|
if (map().hasMotionPoints())
|
||||||
|
{
|
||||||
|
newPoints = map().preMotionPoints();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newPoints = points();
|
||||||
|
}
|
||||||
|
movePoints(newPoints);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Update numbering of cells/vertices.
|
// Update numbering of cells/vertices.
|
||||||
meshCutter_.updateMesh(map);
|
meshCutter_.updateMesh(map);
|
||||||
@ -422,12 +470,12 @@ Foam::dynamicRefineFvMesh::refine
|
|||||||
// Update numbering of protectedCell_
|
// Update numbering of protectedCell_
|
||||||
if (protectedCell_.size())
|
if (protectedCell_.size())
|
||||||
{
|
{
|
||||||
bitSet newProtectedCell(nCells());
|
PackedBoolList newProtectedCell(nCells());
|
||||||
|
|
||||||
forAll(newProtectedCell, celli)
|
forAll(newProtectedCell, celli)
|
||||||
{
|
{
|
||||||
const label oldCelli = map.cellMap()[celli];
|
label oldCelli = map().cellMap()[celli];
|
||||||
newProtectedCell.set(celli, protectedCell_.test(oldCelli));
|
newProtectedCell.set(celli, protectedCell_.get(oldCelli));
|
||||||
}
|
}
|
||||||
protectedCell_.transfer(newProtectedCell);
|
protectedCell_.transfer(newProtectedCell);
|
||||||
}
|
}
|
||||||
@ -435,7 +483,7 @@ Foam::dynamicRefineFvMesh::refine
|
|||||||
// Debug: Check refinement levels (across faces only)
|
// Debug: Check refinement levels (across faces only)
|
||||||
meshCutter_.checkRefinementLevels(-1, labelList(0));
|
meshCutter_.checkRefinementLevels(-1, labelList(0));
|
||||||
|
|
||||||
return mapPtr;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -482,21 +530,36 @@ Foam::dynamicRefineFvMesh::unrefine
|
|||||||
|
|
||||||
|
|
||||||
// Change mesh and generate map.
|
// Change mesh and generate map.
|
||||||
autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(*this, false);
|
//autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
|
||||||
mapPolyMesh& map = *mapPtr;
|
autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
|
||||||
|
|
||||||
Info<< "Unrefined from "
|
Info<< "Unrefined from "
|
||||||
<< returnReduce(map.nOldCells(), sumOp<label>())
|
<< returnReduce(map().nOldCells(), sumOp<label>())
|
||||||
<< " to " << globalData().nTotalCells() << " cells."
|
<< " to " << globalData().nTotalCells() << " cells."
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
// Update fields
|
// Update fields
|
||||||
updateMesh(map);
|
updateMesh(map);
|
||||||
|
|
||||||
|
|
||||||
|
// Move mesh
|
||||||
|
/*
|
||||||
|
pointField newPoints;
|
||||||
|
if (map().hasMotionPoints())
|
||||||
|
{
|
||||||
|
newPoints = map().preMotionPoints();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newPoints = points();
|
||||||
|
}
|
||||||
|
movePoints(newPoints);
|
||||||
|
*/
|
||||||
|
|
||||||
// Correct the flux for modified faces.
|
// Correct the flux for modified faces.
|
||||||
{
|
{
|
||||||
const labelList& reversePointMap = map.reversePointMap();
|
const labelList& reversePointMap = map().reversePointMap();
|
||||||
const labelList& reverseFaceMap = map.reverseFaceMap();
|
const labelList& reverseFaceMap = map().reverseFaceMap();
|
||||||
|
|
||||||
HashTable<surfaceScalarField*> fluxes
|
HashTable<surfaceScalarField*> fluxes
|
||||||
(
|
(
|
||||||
@ -585,14 +648,14 @@ Foam::dynamicRefineFvMesh::unrefine
|
|||||||
// Update numbering of protectedCell_
|
// Update numbering of protectedCell_
|
||||||
if (protectedCell_.size())
|
if (protectedCell_.size())
|
||||||
{
|
{
|
||||||
bitSet newProtectedCell(nCells());
|
PackedBoolList newProtectedCell(nCells());
|
||||||
|
|
||||||
forAll(newProtectedCell, celli)
|
forAll(newProtectedCell, celli)
|
||||||
{
|
{
|
||||||
label oldCelli = map.cellMap()[celli];
|
label oldCelli = map().cellMap()[celli];
|
||||||
if (oldCelli >= 0)
|
if (oldCelli >= 0)
|
||||||
{
|
{
|
||||||
newProtectedCell.set(celli, protectedCell_.test(oldCelli));
|
newProtectedCell.set(celli, protectedCell_.get(oldCelli));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protectedCell_.transfer(newProtectedCell);
|
protectedCell_.transfer(newProtectedCell);
|
||||||
@ -601,7 +664,7 @@ Foam::dynamicRefineFvMesh::unrefine
|
|||||||
// Debug: Check refinement levels (across faces only)
|
// Debug: Check refinement levels (across faces only)
|
||||||
meshCutter_.checkRefinementLevels(-1, labelList(0));
|
meshCutter_.checkRefinementLevels(-1, labelList(0));
|
||||||
|
|
||||||
return mapPtr;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -688,7 +751,7 @@ void Foam::dynamicRefineFvMesh::selectRefineCandidates
|
|||||||
const scalar lowerRefineLevel,
|
const scalar lowerRefineLevel,
|
||||||
const scalar upperRefineLevel,
|
const scalar upperRefineLevel,
|
||||||
const scalarField& vFld,
|
const scalarField& vFld,
|
||||||
bitSet& candidateCell
|
PackedBoolList& candidateCell
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
|
// Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
|
||||||
@ -711,7 +774,7 @@ void Foam::dynamicRefineFvMesh::selectRefineCandidates
|
|||||||
{
|
{
|
||||||
if (cellError[celli] > 0)
|
if (cellError[celli] > 0)
|
||||||
{
|
{
|
||||||
candidateCell.set(celli);
|
candidateCell.set(celli, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -721,7 +784,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
|
|||||||
(
|
(
|
||||||
const label maxCells,
|
const label maxCells,
|
||||||
const label maxRefinement,
|
const label maxRefinement,
|
||||||
const bitSet& candidateCell
|
const PackedBoolList& candidateCell
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Every refined cell causes 7 extra cells
|
// Every refined cell causes 7 extra cells
|
||||||
@ -731,7 +794,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
|
|||||||
|
|
||||||
// Mark cells that cannot be refined since they would trigger refinement
|
// Mark cells that cannot be refined since they would trigger refinement
|
||||||
// of protected cells (since 2:1 cascade)
|
// of protected cells (since 2:1 cascade)
|
||||||
bitSet unrefineableCell;
|
PackedBoolList unrefineableCell;
|
||||||
calculateProtectedCells(unrefineableCell);
|
calculateProtectedCells(unrefineableCell);
|
||||||
|
|
||||||
// Count current selection
|
// Count current selection
|
||||||
@ -748,8 +811,11 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
|
|||||||
if
|
if
|
||||||
(
|
(
|
||||||
cellLevel[celli] < maxRefinement
|
cellLevel[celli] < maxRefinement
|
||||||
&& candidateCell.test(celli)
|
&& candidateCell.get(celli)
|
||||||
&& !unrefineableCell.test(celli)
|
&& (
|
||||||
|
unrefineableCell.empty()
|
||||||
|
|| !unrefineableCell.get(celli)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
candidates.append(celli);
|
candidates.append(celli);
|
||||||
@ -766,8 +832,11 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
|
|||||||
if
|
if
|
||||||
(
|
(
|
||||||
cellLevel[celli] == level
|
cellLevel[celli] == level
|
||||||
&& candidateCell.test(celli)
|
&& candidateCell.get(celli)
|
||||||
&& !unrefineableCell.test(celli)
|
&& (
|
||||||
|
unrefineableCell.empty()
|
||||||
|
|| !unrefineableCell.get(celli)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
candidates.append(celli);
|
candidates.append(celli);
|
||||||
@ -802,7 +871,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
|
|||||||
Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
|
Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
|
||||||
(
|
(
|
||||||
const scalar unrefineLevel,
|
const scalar unrefineLevel,
|
||||||
const bitSet& markedCell,
|
const PackedBoolList& markedCell,
|
||||||
const scalarField& pFld
|
const scalarField& pFld
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -815,7 +884,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
|
|||||||
// If we have any protected cells make sure they also are not being
|
// If we have any protected cells make sure they also are not being
|
||||||
// unrefined
|
// unrefined
|
||||||
|
|
||||||
bitSet protectedPoint(nPoints());
|
PackedBoolList protectedPoint(nPoints());
|
||||||
|
|
||||||
if (protectedCell_.size())
|
if (protectedCell_.size())
|
||||||
{
|
{
|
||||||
@ -828,9 +897,9 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
|
|||||||
{
|
{
|
||||||
label cellI = pCells[pCellI];
|
label cellI = pCells[pCellI];
|
||||||
|
|
||||||
if (protectedCell_.test(cellI))
|
if (protectedCell_[cellI])
|
||||||
{
|
{
|
||||||
protectedPoint.set(pointI);
|
protectedPoint[pointI] = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -870,7 +939,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
|
|||||||
|
|
||||||
forAll(pCells, pCelli)
|
forAll(pCells, pCelli)
|
||||||
{
|
{
|
||||||
if (markedCell.test(pCells[pCelli]))
|
if (markedCell.get(pCells[pCelli]))
|
||||||
{
|
{
|
||||||
hasMarked = true;
|
hasMarked = true;
|
||||||
break;
|
break;
|
||||||
@ -907,7 +976,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
|
|||||||
|
|
||||||
void Foam::dynamicRefineFvMesh::extendMarkedCells
|
void Foam::dynamicRefineFvMesh::extendMarkedCells
|
||||||
(
|
(
|
||||||
bitSet& markedCell
|
PackedBoolList& markedCell
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Mark faces using any marked cell
|
// Mark faces using any marked cell
|
||||||
@ -915,7 +984,7 @@ void Foam::dynamicRefineFvMesh::extendMarkedCells
|
|||||||
|
|
||||||
forAll(markedCell, celli)
|
forAll(markedCell, celli)
|
||||||
{
|
{
|
||||||
if (markedCell.test(celli))
|
if (markedCell.get(celli))
|
||||||
{
|
{
|
||||||
const cell& cFaces = cells()[celli];
|
const cell& cFaces = cells()[celli];
|
||||||
|
|
||||||
@ -933,15 +1002,15 @@ void Foam::dynamicRefineFvMesh::extendMarkedCells
|
|||||||
{
|
{
|
||||||
if (markedFace[facei])
|
if (markedFace[facei])
|
||||||
{
|
{
|
||||||
markedCell.set(faceOwner()[facei]);
|
markedCell.set(faceOwner()[facei], 1);
|
||||||
markedCell.set(faceNeighbour()[facei]);
|
markedCell.set(faceNeighbour()[facei], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (label facei = nInternalFaces(); facei < nFaces(); facei++)
|
for (label facei = nInternalFaces(); facei < nFaces(); facei++)
|
||||||
{
|
{
|
||||||
if (markedFace[facei])
|
if (markedFace[facei])
|
||||||
{
|
{
|
||||||
markedCell.set(faceOwner()[facei]);
|
markedCell.set(faceOwner()[facei], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -949,7 +1018,7 @@ void Foam::dynamicRefineFvMesh::extendMarkedCells
|
|||||||
|
|
||||||
void Foam::dynamicRefineFvMesh::checkEightAnchorPoints
|
void Foam::dynamicRefineFvMesh::checkEightAnchorPoints
|
||||||
(
|
(
|
||||||
bitSet& protectedCell,
|
PackedBoolList& protectedCell,
|
||||||
label& nProtected
|
label& nProtected
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -971,7 +1040,7 @@ void Foam::dynamicRefineFvMesh::checkEightAnchorPoints
|
|||||||
// Check if cell has already 8 anchor points -> protect cell
|
// Check if cell has already 8 anchor points -> protect cell
|
||||||
if (nAnchorPoints[celli] == 8)
|
if (nAnchorPoints[celli] == 8)
|
||||||
{
|
{
|
||||||
if (protectedCell.set(celli))
|
if (protectedCell.set(celli, true))
|
||||||
{
|
{
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
@ -988,9 +1057,9 @@ void Foam::dynamicRefineFvMesh::checkEightAnchorPoints
|
|||||||
|
|
||||||
forAll(protectedCell, celli)
|
forAll(protectedCell, celli)
|
||||||
{
|
{
|
||||||
if (!protectedCell.test(celli) && nAnchorPoints[celli] != 8)
|
if (!protectedCell[celli] && nAnchorPoints[celli] != 8)
|
||||||
{
|
{
|
||||||
protectedCell.set(celli);
|
protectedCell.set(celli, true);
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1005,7 +1074,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
meshCutter_(*this),
|
meshCutter_(*this),
|
||||||
dumpLevel_(false),
|
dumpLevel_(false),
|
||||||
nRefinementIterations_(0),
|
nRefinementIterations_(0),
|
||||||
protectedCell_(nCells(), false)
|
protectedCell_(nCells(), 0)
|
||||||
{
|
{
|
||||||
// Read static part of dictionary
|
// Read static part of dictionary
|
||||||
readDict();
|
readDict();
|
||||||
@ -1034,7 +1103,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
{
|
{
|
||||||
label celli = pCells[i];
|
label celli = pCells[i];
|
||||||
|
|
||||||
if (!protectedCell_.test(celli))
|
if (!protectedCell_.get(celli))
|
||||||
{
|
{
|
||||||
if (pointLevel[pointi] <= cellLevel[celli])
|
if (pointLevel[pointi] <= cellLevel[celli])
|
||||||
{
|
{
|
||||||
@ -1042,7 +1111,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
|
|
||||||
if (nAnchors[celli] > 8)
|
if (nAnchors[celli] > 8)
|
||||||
{
|
{
|
||||||
protectedCell_.set(celli);
|
protectedCell_.set(celli, 1);
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1105,9 +1174,9 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
{
|
{
|
||||||
if (protectedFace[facei])
|
if (protectedFace[facei])
|
||||||
{
|
{
|
||||||
protectedCell_.set(faceOwner()[facei]);
|
protectedCell_.set(faceOwner()[facei], 1);
|
||||||
nProtected++;
|
nProtected++;
|
||||||
protectedCell_.set(faceNeighbour()[facei]);
|
protectedCell_.set(faceNeighbour()[facei], 1);
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1115,7 +1184,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
{
|
{
|
||||||
if (protectedFace[facei])
|
if (protectedFace[facei])
|
||||||
{
|
{
|
||||||
protectedCell_.set(faceOwner()[facei]);
|
protectedCell_.set(faceOwner()[facei], 1);
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1127,7 +1196,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
|
|
||||||
if (cFaces.size() < 6)
|
if (cFaces.size() < 6)
|
||||||
{
|
{
|
||||||
if (protectedCell_.set(celli))
|
if (protectedCell_.set(celli, 1))
|
||||||
{
|
{
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
@ -1138,7 +1207,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
{
|
{
|
||||||
if (faces()[cFaces[cFacei]].size() < 4)
|
if (faces()[cFaces[cFacei]].size() < 4)
|
||||||
{
|
{
|
||||||
if (protectedCell_.set(celli))
|
if (protectedCell_.set(celli, 1))
|
||||||
{
|
{
|
||||||
nProtected++;
|
nProtected++;
|
||||||
}
|
}
|
||||||
@ -1158,6 +1227,7 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
cellSet protectedCells(*this, "protectedCells", nProtected);
|
cellSet protectedCells(*this, "protectedCells", nProtected);
|
||||||
forAll(protectedCell_, celli)
|
forAll(protectedCell_, celli)
|
||||||
{
|
{
|
||||||
@ -1188,9 +1258,9 @@ Foam::dynamicRefineFvMesh::~dynamicRefineFvMesh()
|
|||||||
|
|
||||||
bool Foam::dynamicRefineFvMesh::update()
|
bool Foam::dynamicRefineFvMesh::update()
|
||||||
{
|
{
|
||||||
// Re-read dictionary. Usually small so takes trivial amount of time
|
// Re-read dictionary. Choosen since usually -small so trivial amount
|
||||||
// compared to actual refinement. Also very useful to be able to modify
|
// of time compared to actual refinement. Also very useful to be able
|
||||||
// on-the-fly.
|
// to modify on-the-fly.
|
||||||
dictionary refineDict
|
dictionary refineDict
|
||||||
(
|
(
|
||||||
IOdictionary
|
IOdictionary
|
||||||
@ -1264,18 +1334,16 @@ bool Foam::dynamicRefineFvMesh::update()
|
|||||||
refineDict.get<scalar>("lowerRefineLevel");
|
refineDict.get<scalar>("lowerRefineLevel");
|
||||||
const scalar upperRefineLevel =
|
const scalar upperRefineLevel =
|
||||||
refineDict.get<scalar>("upperRefineLevel");
|
refineDict.get<scalar>("upperRefineLevel");
|
||||||
|
|
||||||
const scalar unrefineLevel = refineDict.lookupOrDefault<scalar>
|
const scalar unrefineLevel = refineDict.lookupOrDefault<scalar>
|
||||||
(
|
(
|
||||||
"unrefineLevel",
|
"unrefineLevel",
|
||||||
GREAT
|
GREAT
|
||||||
);
|
);
|
||||||
|
|
||||||
const label nBufferLayers =
|
const label nBufferLayers =
|
||||||
refineDict.get<label>("nBufferLayers");
|
refineDict.get<label>("nBufferLayers");
|
||||||
|
|
||||||
// Cells marked for refinement or otherwise protected from unrefinement.
|
// Cells marked for refinement or otherwise protected from unrefinement.
|
||||||
bitSet refineCell(nCells());
|
PackedBoolList refineCell(nCells());
|
||||||
|
|
||||||
// Determine candidates for refinement (looking at field only)
|
// Determine candidates for refinement (looking at field only)
|
||||||
selectRefineCandidates
|
selectRefineCandidates
|
||||||
@ -1316,7 +1384,7 @@ bool Foam::dynamicRefineFvMesh::update()
|
|||||||
const labelList& cellMap = map().cellMap();
|
const labelList& cellMap = map().cellMap();
|
||||||
const labelList& reverseCellMap = map().reverseCellMap();
|
const labelList& reverseCellMap = map().reverseCellMap();
|
||||||
|
|
||||||
bitSet newRefineCell(cellMap.size());
|
PackedBoolList newRefineCell(cellMap.size());
|
||||||
|
|
||||||
forAll(cellMap, celli)
|
forAll(cellMap, celli)
|
||||||
{
|
{
|
||||||
@ -1324,15 +1392,15 @@ bool Foam::dynamicRefineFvMesh::update()
|
|||||||
|
|
||||||
if (oldCelli < 0)
|
if (oldCelli < 0)
|
||||||
{
|
{
|
||||||
newRefineCell.set(celli);
|
newRefineCell.set(celli, 1);
|
||||||
}
|
}
|
||||||
else if (reverseCellMap[oldCelli] != celli)
|
else if (reverseCellMap[oldCelli] != celli)
|
||||||
{
|
{
|
||||||
newRefineCell.set(celli);
|
newRefineCell.set(celli, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newRefineCell.set(celli, refineCell.test(oldCelli));
|
newRefineCell.set(celli, refineCell.get(oldCelli));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refineCell.transfer(newRefineCell);
|
refineCell.transfer(newRefineCell);
|
||||||
@ -1380,7 +1448,7 @@ bool Foam::dynamicRefineFvMesh::update()
|
|||||||
|
|
||||||
if ((nRefinementIterations_ % 10) == 0)
|
if ((nRefinementIterations_ % 10) == 0)
|
||||||
{
|
{
|
||||||
// Compact refinement history occasionally (how often?).
|
// Compact refinement history occassionally (how often?).
|
||||||
// Unrefinement causes holes in the refinementHistory.
|
// Unrefinement causes holes in the refinementHistory.
|
||||||
const_cast<refinementHistory&>(meshCutter().history()).compact();
|
const_cast<refinementHistory&>(meshCutter().history()).compact();
|
||||||
}
|
}
|
||||||
@ -1403,8 +1471,7 @@ bool Foam::dynamicRefineFvMesh::writeObject
|
|||||||
(
|
(
|
||||||
IOstream::streamFormat fmt,
|
IOstream::streamFormat fmt,
|
||||||
IOstream::versionNumber ver,
|
IOstream::versionNumber ver,
|
||||||
IOstream::compressionType cmp,
|
IOstream::compressionType cmp
|
||||||
const bool valid
|
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Force refinement data to go to the current time directory.
|
// Force refinement data to go to the current time directory.
|
||||||
@ -1412,8 +1479,8 @@ bool Foam::dynamicRefineFvMesh::writeObject
|
|||||||
|
|
||||||
bool writeOk =
|
bool writeOk =
|
||||||
(
|
(
|
||||||
dynamicFvMesh::writeObject(fmt, ver, cmp, valid)
|
dynamicFvMesh::writeObject(fmt, ver, cmp)
|
||||||
&& meshCutter_.write(valid)
|
&& meshCutter_.write()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (dumpLevel_)
|
if (dumpLevel_)
|
||||||
@ -1430,7 +1497,7 @@ bool Foam::dynamicRefineFvMesh::writeObject
|
|||||||
false
|
false
|
||||||
),
|
),
|
||||||
*this,
|
*this,
|
||||||
dimensionedScalar(dimless, Zero)
|
dimensionedScalar("level", dimless, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
const labelList& cellLevel = meshCutter_.cellLevel();
|
const labelList& cellLevel = meshCutter_.cellLevel();
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -56,6 +56,7 @@ Description
|
|||||||
(rho*phi none) //none)
|
(rho*phi none) //none)
|
||||||
(ghf none) //NaN) //none)
|
(ghf none) //NaN) //none)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Write the refinement level as a volScalarField
|
// Write the refinement level as a volScalarField
|
||||||
dumpLevel true;
|
dumpLevel true;
|
||||||
|
|
||||||
@ -117,10 +118,10 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
//- Refine cells. Update mesh and fields.
|
//- Refine cells. Update mesh and fields.
|
||||||
autoPtr<mapPolyMesh> refine(const labelList&);
|
virtual autoPtr<mapPolyMesh> refine(const labelList&);
|
||||||
|
|
||||||
//- Unrefine cells. Gets passed in centre points of cells to combine.
|
//- Unrefine cells. Gets passed in centre points of cells to combine.
|
||||||
autoPtr<mapPolyMesh> unrefine(const labelList&);
|
virtual autoPtr<mapPolyMesh> unrefine(const labelList&);
|
||||||
|
|
||||||
|
|
||||||
// Selection of cells to un/refine
|
// Selection of cells to un/refine
|
||||||
@ -185,6 +186,32 @@ protected:
|
|||||||
label& nProtected
|
label& nProtected
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Map single non-flux surface<Type>Field
|
||||||
|
// for new internal faces (e.g. AMR refine). This currently
|
||||||
|
// interpolates values from surrounding faces (faces on
|
||||||
|
// neighbouring cells) that do have a value.
|
||||||
|
template <class T>
|
||||||
|
void mapNewInternalFaces
|
||||||
|
(
|
||||||
|
const labelList& faceMap,
|
||||||
|
GeometricField<T, fvsPatchField, surfaceMesh>&
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Correct surface fields for new faces
|
||||||
|
template <class T>
|
||||||
|
void mapNewInternalFaces(const labelList& faceMap);
|
||||||
|
|
||||||
|
//- Correct surface fields for new faces. Converts any oriented
|
||||||
|
// fields into non-oriented (i.e. phi -> Uf) before mapping
|
||||||
|
template <class T>
|
||||||
|
void mapNewInternalFaces
|
||||||
|
(
|
||||||
|
const surfaceVectorField& Sf,
|
||||||
|
const surfaceScalarField& magSf,
|
||||||
|
const labelList& faceMap
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
@ -232,6 +259,9 @@ public:
|
|||||||
//- Update the mesh for both mesh motion and topology change
|
//- Update the mesh for both mesh motion and topology change
|
||||||
virtual bool update();
|
virtual bool update();
|
||||||
|
|
||||||
|
//- Map all fields in time using given map.
|
||||||
|
virtual void mapFields(const mapPolyMesh& mpm);
|
||||||
|
|
||||||
|
|
||||||
// Writing
|
// Writing
|
||||||
|
|
||||||
@ -243,16 +273,20 @@ public:
|
|||||||
IOstream::compressionType cmp,
|
IOstream::compressionType cmp,
|
||||||
const bool valid
|
const bool valid
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "dynamicRefineFvMeshTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -0,0 +1,196 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Foam::dynamicRefineFvMesh::mapNewInternalFaces
|
||||||
|
(
|
||||||
|
const labelList& faceMap,
|
||||||
|
GeometricField<T, fvsPatchField, surfaceMesh>& sFld
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef GeometricField<T, fvsPatchField, surfaceMesh> GeoField;
|
||||||
|
|
||||||
|
//- Make flat field for ease of looping
|
||||||
|
Field<T> tsFld(this->nFaces(), pTraits<T>::zero);
|
||||||
|
SubField<T>(tsFld, this->nInternalFaces()) = sFld.internalField();
|
||||||
|
|
||||||
|
const typename GeoField::Boundary& bFld = sFld.boundaryField();
|
||||||
|
forAll(bFld, patchi)
|
||||||
|
{
|
||||||
|
label facei = this->boundaryMesh()[patchi].start();
|
||||||
|
for (const T& val : bFld[patchi])
|
||||||
|
{
|
||||||
|
tsFld[facei++] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const labelUList& owner = this->faceOwner();
|
||||||
|
const labelUList& neighbour = this->faceNeighbour();
|
||||||
|
const cellList& cells = this->cells();
|
||||||
|
|
||||||
|
for (label facei = 0; facei < nInternalFaces(); facei++)
|
||||||
|
{
|
||||||
|
label oldFacei = faceMap[facei];
|
||||||
|
|
||||||
|
// Map surface field on newly generated faces by obtaining the
|
||||||
|
// hull of the outside faces
|
||||||
|
if (oldFacei == -1)
|
||||||
|
{
|
||||||
|
// Loop over all owner/neighbour cell faces
|
||||||
|
// and find already mapped ones (master-faces):
|
||||||
|
T tmpValue = pTraits<T>::zero;
|
||||||
|
label counter = 0;
|
||||||
|
|
||||||
|
const cell& ownFaces = cells[owner[facei]];
|
||||||
|
for (auto ownFacei : ownFaces)
|
||||||
|
{
|
||||||
|
if (faceMap[ownFacei] != -1)
|
||||||
|
{
|
||||||
|
tmpValue += tsFld[ownFacei];
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cell& neiFaces = cells[neighbour[facei]];
|
||||||
|
for (auto neiFacei : neiFaces)
|
||||||
|
{
|
||||||
|
if (faceMap[neiFacei] != -1)
|
||||||
|
{
|
||||||
|
tmpValue += tsFld[neiFacei];
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counter > 0)
|
||||||
|
{
|
||||||
|
sFld[facei] = tmpValue/counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Foam::dynamicRefineFvMesh::mapNewInternalFaces
|
||||||
|
(
|
||||||
|
const labelList& faceMap
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef GeometricField<T, fvsPatchField, surfaceMesh> GeoField;
|
||||||
|
HashTable<GeoField*> sFlds(this->objectRegistry::lookupClass<GeoField>());
|
||||||
|
|
||||||
|
forAllIter(typename HashTable<GeoField*>, sFlds, iter)
|
||||||
|
{
|
||||||
|
//if (mapSurfaceFields_.found(iter.key()))
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "dynamicRefineFvMesh::mapNewInternalFaces():"
|
||||||
|
<< " Mapping new internal faces by interpolation on "
|
||||||
|
<< iter.key()<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeoField& sFld = *iter();
|
||||||
|
|
||||||
|
if (sFld.oriented()())
|
||||||
|
{
|
||||||
|
WarningInFunction << "Ignoring mapping oriented field "
|
||||||
|
<< sFld.name() << " since of type " << sFld.type()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapNewInternalFaces(faceMap, sFld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Foam::dynamicRefineFvMesh::mapNewInternalFaces
|
||||||
|
(
|
||||||
|
const surfaceVectorField& Sf,
|
||||||
|
const surfaceScalarField& magSf,
|
||||||
|
const labelList& faceMap
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef GeometricField<T, fvsPatchField, surfaceMesh> GeoField;
|
||||||
|
HashTable<GeoField*> sFlds(this->objectRegistry::lookupClass<GeoField>());
|
||||||
|
|
||||||
|
forAllIter(typename HashTable<GeoField*>, sFlds, iter)
|
||||||
|
{
|
||||||
|
//if (mapSurfaceFields_.found(iter.key()))
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "dynamicRefineFvMesh::mapNewInternalFaces():"
|
||||||
|
<< " Mapping new internal faces by interpolation on "
|
||||||
|
<< iter.key()<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeoField& sFld = *iter();
|
||||||
|
|
||||||
|
if (sFld.oriented()())
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "dynamicRefineFvMesh::mapNewInternalFaces(): "
|
||||||
|
<< "Converting oriented field " << iter.key()
|
||||||
|
<< " to intensive field and mapping" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume any oriented field is face area weighted (i.e. a flux)
|
||||||
|
// Convert to intensive (& oriented) before mapping. Untested.
|
||||||
|
|
||||||
|
typedef GeometricField
|
||||||
|
<
|
||||||
|
typename outerProduct<vector, T>::type,
|
||||||
|
fvsPatchField,
|
||||||
|
surfaceMesh
|
||||||
|
> NormalGeoField;
|
||||||
|
|
||||||
|
// Convert to intensive and non oriented
|
||||||
|
NormalGeoField fFld(sFld*Sf/Foam::sqr(magSf));
|
||||||
|
|
||||||
|
// Interpolate
|
||||||
|
mapNewInternalFaces(faceMap, fFld);
|
||||||
|
|
||||||
|
// Convert back to extensive and oriented
|
||||||
|
sFld = (fFld & Sf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapNewInternalFaces(faceMap, sFld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -210,7 +210,7 @@ Foam::label Foam::hexRef8::addInternalFace
|
|||||||
nei, // neighbour
|
nei, // neighbour
|
||||||
-1, // master point
|
-1, // master point
|
||||||
-1, // master edge
|
-1, // master edge
|
||||||
meshFacei, // master face for addition
|
-1, // master face for addition
|
||||||
false, // flux flip
|
false, // flux flip
|
||||||
-1, // patch for face
|
-1, // patch for face
|
||||||
-1, // zone for face
|
-1, // zone for face
|
||||||
|
|||||||
@ -571,6 +571,13 @@ const Foam::lduAddressing& Foam::fvMesh::lduAddr() const
|
|||||||
{
|
{
|
||||||
if (!lduPtr_)
|
if (!lduPtr_)
|
||||||
{
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
InfoInFunction
|
||||||
|
<< " calculating fvMeshLduAddressing from nFaces:"
|
||||||
|
<< nFaces() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
lduPtr_ = new fvMeshLduAddressing(*this);
|
lduPtr_ = new fvMeshLduAddressing(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,6 +828,9 @@ void Foam::fvMesh::updateMesh(const mapPolyMesh& mpm)
|
|||||||
// Update polyMesh. This needs to keep volume existent!
|
// Update polyMesh. This needs to keep volume existent!
|
||||||
polyMesh::updateMesh(mpm);
|
polyMesh::updateMesh(mpm);
|
||||||
|
|
||||||
|
// Our slice of the addressing is no longer valid
|
||||||
|
deleteDemandDrivenData(lduPtr_);
|
||||||
|
|
||||||
if (VPtr_)
|
if (VPtr_)
|
||||||
{
|
{
|
||||||
// Grab old time volumes if the time has been incremented
|
// Grab old time volumes if the time has been incremented
|
||||||
|
|||||||
@ -49,6 +49,7 @@ correctFluxes
|
|||||||
(rhoPhi none)
|
(rhoPhi none)
|
||||||
(alphaPhi0.water none)
|
(alphaPhi0.water none)
|
||||||
(ghf none)
|
(ghf none)
|
||||||
|
(alphaPhiUn none)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Write the refinement level as a volScalarField
|
// Write the refinement level as a volScalarField
|
||||||
|
|||||||
Reference in New Issue
Block a user