ENH: Adding subMesh option to momentumError and div FOs

1) Adding subMesh capabilities to momentumError and div FOs.
	- A subMesh is created from cellZones.
	- The operators (div, etc) are only calculated in the subMesh.

2) Optionally, halo cells can be added to the cellZones.

3) New helper class to handle the subMesh creation and field mapping.
This commit is contained in:
sergio
2021-06-22 08:46:28 -07:00
committed by Mattijs Janssens
parent 6595429f53
commit 6101272133
25 changed files with 914 additions and 111 deletions

View File

@ -4,6 +4,7 @@ EXE_INC = \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/lagrangian/distributionModels/lnInclude \
@ -27,6 +28,7 @@ LIB_LIBS = \
-lfileFormats \
-lsurfMesh \
-lmeshTools \
-ldynamicMesh \
-lsampling \
-llagrangian \
-ldistributionModels \

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,12 +47,26 @@ namespace functionObjects
bool Foam::functionObjects::div::calc()
{
bool processed = false;
return
(
calcDiv<surfaceScalarField>()
|| calcDiv<volVectorField>()
);
}
processed = processed || calcDiv<surfaceScalarField>();
processed = processed || calcDiv<volVectorField>();
return processed;
bool Foam::functionObjects::div::write()
{
if (zoneSubSetPtr_)
{
return
(
writeField<scalar>()
|| writeField<vector>()
);
}
return writeObject(resultName_);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -53,15 +53,15 @@ Usage
// Mandatory (inherited) entry (runtime modifiable)
field \<field\>;
// Optional (inherited) entries
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Req'd | Dflt
type | Type name: add | word | yes | -
Property | Description | Type | Reqd | Deflt
type | Type name: div | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | -
field | Name of the operand field | word | yes | -
\endtable
@ -69,6 +69,7 @@ Usage
The inherited entries are elaborated in:
- \link functionObject.H \endlink
- \link fieldExpression.H \endlink
- \link zoneSubSet.H \endlink
Minimal example by using the \c postProcess utility:
\verbatim
@ -76,8 +77,10 @@ Usage
\endverbatim
Note
To execute \c div function object on an input \<field\>, a numerical scheme
- To execute \c div function object on an input \<field\>, a numerical scheme
should be defined for \c div(\<field\>) in \c system/fvSchemes.divSchemes.
- Optionally the user can specify \c cellZones to create a sub-mesh for the
\c div calculation.
See also
- Foam::functionObject
@ -121,6 +124,10 @@ class div
//- Calculate the divergence field and return true if successful
virtual bool calc();
//- Helper function for writing submesh fields
template<class Type>
bool writeField();
public:
@ -147,6 +154,12 @@ public:
//- Destructor
virtual ~div() = default;
// Member Functions
//- Write the result field
virtual bool write();
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,15 +33,50 @@ License
template<class FieldType>
bool Foam::functionObjects::div::calcDiv()
{
if (foundObject<FieldType>(fieldName_, false))
const auto* fieldptr = cfindObject<FieldType>(fieldName_);
if (!fieldptr)
{
return store
return false;
}
if (zoneSubSetPtr_)
{
const fvMeshSubset& subsetter = zoneSubSetPtr_->subsetter();
return storeInDb
(
resultName_,
fvc::div(lookupObject<FieldType>(fieldName_))
fvc::div(subsetter.interpolate(*fieldptr, false)),
subsetter.subMesh().thisDb()
);
}
return store
(
resultName_,
fvc::div(*fieldptr)
);
}
template<class Type>
bool Foam::functionObjects::div::writeField()
{
typedef GeometricField<Type, fvPatchField, volMesh> volFieldType;
const fvMesh& subMesh = zoneSubSetPtr_->subsetter().subMesh();
const auto* fieldptr = subMesh.findObject<volFieldType>(resultName_);
if (fieldptr)
{
tmp<volFieldType> tfield = zoneSubSetPtr_->mapToZone<Type>(*fieldptr);
tfield().write();
return true;
}
return false;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -90,16 +90,28 @@ Foam::functionObjects::fieldExpression::fieldExpression
bool Foam::functionObjects::fieldExpression::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict);
if (fieldName_.empty() || dict.found("field"))
if (fvMeshFunctionObject::read(dict))
{
dict.readEntry("field", fieldName_);
if (fieldName_.empty() || dict.found("field"))
{
dict.readEntry("field", fieldName_);
}
dict.readIfPresent("result", resultName_);
if (dict.found("cellZones"))
{
zoneSubSetPtr_.reset(new Detail::zoneSubSet(mesh_, dict));
}
else
{
zoneSubSetPtr_.reset(nullptr);
}
return true;
}
dict.readIfPresent("result", resultName_);
return true;
return false;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,22 +37,26 @@ Description
Usage
Minimal example by using \c system/controlDict.functions:
\verbatim
<userDefinedSubDictName1>
<functionObject>
{
// Mandatory and other optional entries
// Mandatory and optional entries
...
// Optional (inherited) entries (runtime modifiable)
// Inherited entries
field <field>;
result <fieldResult>;
cellZones ( <cellZone1> <cellZone2> ... <cellZoneN> );
nLayers <label>;
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Req'd | Dflt
field | Name of the operand field | word | yes | -
result | Name of the output field | word | no | \<FO\>(\<field\>)
Property | Description | Type | Reqd | Deflt
field | Name of the operand field | word | yes | -
result | Name of the output field | word | no | \<FO\>(\<field\>)
cellZones | Names of cellZones | wordRes | no | -
nLayers | Number of cell layers around cellZones | label | no | 0
\endtable
See also
@ -71,6 +75,7 @@ SourceFiles
#include "fvMeshFunctionObject.H"
#include "volFieldsFwd.H"
#include "zoneSubSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -89,7 +94,7 @@ class fieldExpression
{
protected:
// Protected Member Data
// Protected Data
//- Name of field to process
word fieldName_;
@ -97,6 +102,9 @@ protected:
//- Name of result field
word resultName_;
//- Sub-set mesh
autoPtr<Detail::zoneSubSet> zoneSubSetPtr_;
// Protected Member Functions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -54,6 +54,9 @@ Foam::functionObjects::momentumError::divDevRhoReff()
typedef compressible::turbulenceModel cmpTurbModel;
typedef incompressible::turbulenceModel icoTurbModel;
const auto& U = lookupObject<volVectorField>(UName_);
tmp<volVectorField> tU(U);
{
auto* turb = findObject<cmpTurbModel>
(
@ -62,19 +65,31 @@ Foam::functionObjects::momentumError::divDevRhoReff()
if (turb)
{
tmp<volScalarField> trho = turb->rho();
tmp<volScalarField> tnuEff = turb->nuEff();
if (zoneSubSetPtr_)
{
const fvMeshSubset& subsetter = zoneSubSetPtr_->subsetter();
tU = subsetter.interpolate(U, false);
trho = subsetter.interpolate(turb->rho(), false);
tnuEff = subsetter.interpolate(turb->nuEff()(), false);
}
return tmp<volVectorField>::New
(
"divDevRhoReff",
- fvc::div
- fvc::div
(
(turb->rho()*turb->nuEff())
*dev2(T(fvc::grad(turb->U()))),
"div(((rho*nuEff)*dev2(T(grad(U)))))"
(trho()*tnuEff())
*dev2(T(fvc::grad(tU()))),
"div(((rho*nuEff)*dev2(T(grad(U)))))"
)
- fvc::laplacian
- fvc::laplacian
(
turb->rho()*turb->nuEff(),
turb->U(),
trho()*tnuEff(),
tU(),
"laplacian(nuEff,U)"
)
);
@ -89,18 +104,25 @@ Foam::functionObjects::momentumError::divDevRhoReff()
if (turb)
{
tmp<volScalarField> tnuEff = turb->nuEff();
if (zoneSubSetPtr_)
{
const fvMeshSubset& subsetter = zoneSubSetPtr_->subsetter();
tU = subsetter.interpolate(U, false);
tnuEff = subsetter.interpolate(turb->nuEff()(), false);
}
return tmp<volVectorField>::New
(
"divDevReff",
- fvc::div
"divDevRhoReff",
- fvc::div
(
(turb->nuEff())*dev2(T(fvc::grad(turb->U()))),
"div((nuEff*dev2(T(grad(U)))))"
)
- fvc::laplacian
(
turb->nuEff(), turb->U(), "laplacian(nuEff,U)"
tnuEff()*dev2(T(fvc::grad(tU()))),
"div(((nuEff)*dev2(T(grad(U)))))"
)
- fvc::laplacian(tnuEff(), tU(), "laplacian(nuEff,U)")
);
}
}
@ -125,69 +147,139 @@ Foam::functionObjects::momentumError::momentumError
{
read(dict);
const surfaceScalarField& phi =
lookupObject<surfaceScalarField>(phiName_);
const auto& phi =lookupObject<surfaceScalarField>(phiName_);
volVectorField* momentPtr
const dimensionSet momDims
(
new volVectorField
phi.dimensions()*dimVelocity/dimVolume
);
volVectorField* momentPtr = nullptr;
word momName(scopedName("momentError"));
if (zoneSubSetPtr_)
{
const fvMesh& subMesh = zoneSubSetPtr_->subsetter().subMesh();
// momentErrorMap
momentPtr = new volVectorField
(
IOobject
(
"momentError",
time_.timeName(),
mesh_,
scopedName("momentErrorMap"),
subMesh.time().timeName(),
subMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
subMesh,
dimensionedVector(momDims)
);
subMesh.objectRegistry::store(momentPtr);
momName = scopedName("momentErrorZone");
}
momentPtr = new volVectorField
(
IOobject
(
momName,
time_.timeName(),
mesh_,
dimensionedVector(phi.dimensions()*dimVelocity/dimVolume, Zero)
)
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
dimensionedVector(momDims)
);
mesh_.objectRegistry::store(momentPtr);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::momentumError::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict);
Info<< type() << " " << name() << ":" << nl;
// Optional field name entries
if (dict.readIfPresent<word>("p", pName_))
if (fvMeshFunctionObject::read(dict))
{
Info<< " p: " << pName_ << endl;
}
if (dict.readIfPresent<word>("U", UName_))
{
Info<< " U: " << UName_ << endl;
Info<< type() << ' ' << name() << ':' << nl;
// Optional field name entries
if (dict.readIfPresent<word>("p", pName_))
{
Info<< " p: " << pName_ << endl;
}
if (dict.readIfPresent<word>("U", UName_))
{
Info<< " U: " << UName_ << endl;
}
if (dict.readIfPresent<word>("phi", phiName_))
{
Info<< " phi: " << phiName_ << endl;
}
if (dict.found("cellZones"))
{
zoneSubSetPtr_.reset(new Detail::zoneSubSet(mesh_, dict));
}
else
{
zoneSubSetPtr_.reset(nullptr);
}
return true;
}
if (dict.readIfPresent<word>("phi", phiName_))
{
Info<< " phi: " << phiName_ << endl;
}
return true;
return false;
}
void Foam::functionObjects::momentumError::calcMomentError()
{
const auto& p = lookupObject<volScalarField>(pName_);
const auto& U = lookupObject<volVectorField>(UName_);
const auto& phi = lookupObject<surfaceScalarField>(phiName_);
volVectorField& momentErr =
lookupObjectRef<volVectorField>("momentError");
if (zoneSubSetPtr_)
{
const fvMeshSubset& subsetter = zoneSubSetPtr_->subsetter();
const volScalarField& p = lookupObject<volScalarField>(pName_);
const volVectorField& U = lookupObject<volVectorField>(UName_);
const surfaceScalarField& phi =
lookupObject<surfaceScalarField>(phiName_);
fvMesh& subMesh = zoneSubSetPtr_->subsetter().subMesh();
momentErr = divDevRhoReff() + fvc::div(phi, U) + fvc::grad(p);
subMesh.fvSchemes::readOpt() = mesh_.fvSchemes::readOpt();
subMesh.fvSchemes::read();
auto& momentErrMap =
subMesh.lookupObjectRef<volVectorField>
(
scopedName("momentErrorMap")
);
tmp<volScalarField> tp = subsetter.interpolate(p, false);
tmp<volVectorField> tU = subsetter.interpolate(U, false);
tmp<surfaceScalarField> tphi = subsetter.interpolate(phi, false);
momentErrMap =
(
divDevRhoReff()
+ fvc::div(tphi, tU, "div(phi,U)")
+ fvc::grad(tp, "grad(p)")
);
}
else
{
auto& momentErr =
lookupObjectRef<volVectorField>(scopedName("momentError"));
momentErr = fvc::div(phi, U) + fvc::grad(p) + divDevRhoReff();
}
}
@ -201,10 +293,35 @@ bool Foam::functionObjects::momentumError::execute()
bool Foam::functionObjects::momentumError::write()
{
const volVectorField& momentErr =
lookupObjectRef<volVectorField>("momentError");
Log << " functionObjects::" << type() << " " << name();
momentErr.write();
if (!zoneSubSetPtr_)
{
Log << " writing field: " << scopedName("momentError") << endl;
const auto& momentErr =
lookupObjectRef<volVectorField>(scopedName("momentError"));
momentErr.write();
}
else
{
Log << " writing field: " << scopedName("momentErrorMap") << endl;
const fvMeshSubset& subsetter = zoneSubSetPtr_->subsetter();
const fvMesh& subMesh = subsetter.subMesh();
const auto& momentErrMap =
subMesh.lookupObject<volVectorField>
(
scopedName("momentErrorMap")
);
tmp<volVectorField> mapMomErr =
zoneSubSetPtr_->mapToZone<vector>(momentErrMap);
mapMomErr().write();
}
return true;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -54,14 +54,14 @@ Usage
U <UName>;
phi <phiName>;
// Optional (inherited) entries
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Req'd | Dflt
Property | Description | Type | Reqd | Deflt
type | Type name: momentumError | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | -
p | Name of pressure field | word | no | p
@ -71,9 +71,14 @@ Usage
The inherited entries are elaborated in:
- \link functionObject.H \endlink
- \link zoneSubSet.H \endlink
Usage by the \c postProcess utility is not available.
Note
- Optionally the user can specify \c cellZones to create a sub-mesh for the
\c momentumError calculation.
See also
- Foam::functionObject
- Foam::functionObjects::fvMeshFunctionObject
@ -89,6 +94,7 @@ SourceFiles
#include "fvMeshFunctionObject.H"
#include "volFieldsFwd.H"
#include "zoneSubSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -120,10 +126,13 @@ protected:
//- Name of flux field
word phiName_;
//- Sub-set mesh
autoPtr<Detail::zoneSubSet> zoneSubSetPtr_;
// Protected Member Functions
//- Return the effective viscous stress (laminar + turbulent).
//- Return the effective viscous stress (laminar + turbulent).
tmp<volVectorField> divDevRhoReff();

View File

@ -0,0 +1,3 @@
zoneSubSet/zoneSubSet.C
LIB = $(FOAM_LIBBIN)/libfunctionObjectsTools

View File

@ -0,0 +1,13 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
LIB_LIBS = \
-lfiniteVolume \
-lfileFormats \
-lsurfMesh \
-lmeshTools \
-ldynamicMesh