Program Listing for File wallModelFvPatchScalarField.C
↰ Return to documentation for file (wallModels/wallModelFvPatchScalarField.C
)
/*---------------------------------------------------------------------------* \
License
This file is part of libWallModelledLES.
libWallModelledLES 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.
libWallModelledLES 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 libWallModelledLES.
If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "wallModelFvPatchScalarField.H"
#include "turbulenceModel.H"
#include "meshSearch.H"
#include "wallFvPatch.H"
#include "codeRules.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#if !defined(DOXYGEN_SHOULD_SKIP_THIS)
namespace Foam
{
defineTypeNameAndDebug(wallModelFvPatchScalarField, 0);
}
#endif
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::wallModelFvPatchScalarField::checkType()
{
if (!isA<wallFvPatch>(patch()))
{
FatalErrorIn("wallModelFvPatchScalarField::checkType()")
<< "Invalid wall model specification" << nl
<< " Patch type for patch " << patch().name()
<< " must be wall" << nl
<< " Current patch type is " << patch().type() << nl << nl
<< abort(FatalError);
}
}
void Foam::wallModelFvPatchScalarField::writeLocalEntries(Ostream& os) const
{
os.writeKeyword("averagingTime")
<< averagingTime_ << token::END_STATEMENT << nl;
os.writeKeyword("copyToPatchInternalField")
<< copyToPatchInternalField_ << token::END_STATEMENT << nl;
os.writeKeyword("silent")
<< silent_ << token::END_STATEMENT << nl;
}
void Foam::wallModelFvPatchScalarField::createFields() const
{
if (debug)
{
Info<< "wallModelFvPatchScalarField creating fields" << nl;
}
// Name of the h field, default to hSampler
word hName = "hSampler";
// Check if hSampler exists
IOobject hHeader
(
"hSampler",
db().time().timeName(),
db(),
IOobject::NO_READ
);
bool foundhSampler = hHeader.typeHeaderOk<volScalarField>();
db().checkOut("hSampler");
if (debug)
{
Info<< "wallModelFvPatchScalarField: Found hSampler? " << foundhSampler
<< nl;
}
if (!foundhSampler)
{
Warning
<< "The hSampler field is not found, will try to find h. "
<< "Please note that h will not work with compressible solvers. "
<< "It is recommended to use hSampler in new cases." << nl;
IOobject hHeader
(
"h",
db().time().timeName(),
db(),
IOobject::NO_READ
);
if (hHeader.typeHeaderOk<volScalarField>())
{
hName = "h";
if (debug)
{
Info<< "wallModelFvPatchScalarField: Found field h" << nl;
}
}
db().checkOut("h");
}
if (!db().found(hName))
{
db().store
(
new volScalarField
(
IOobject
(
hName,
db().time().timeName(),
db(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
patch().boundaryMesh().mesh()
)
);
}
const volScalarField & h = db().lookupObject<volScalarField>(hName);
// Create and register wallShearStress field, if not there already.
if (!db().found("wallShearStress"))
{
db().store
(
new volVectorField
(
IOobject
(
"wallShearStress",
db().time().timeName(),
db(),
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
patch().boundaryMesh().mesh(),
dimensionedVector
(
"wallShearStress",
sqr(dimVelocity),
vector(0, 0, 0)
),
h.boundaryField().types()
)
);
}
// Field with uTau as predicted by the wall model.
if ((!db().found("uTauPredicted")))
{
db().store
(
new volScalarField
(
IOobject
(
"uTauPredicted",
db().time().timeName(),
db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
patch().boundaryMesh().mesh(),
dimensionedScalar("uTauPredicted", dimVelocity, 0.0),
h.boundaryField().types()
)
);
}
// wall-normal gradient field
if (!db().foundObject<volVectorField>("wallGradU"))
{
db().store
(
new volVectorField
(
IOobject
(
"wallGradU",
db().time().timeName(),
db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
patch().boundaryMesh().mesh(),
dimensionedVector
(
"wallGradU",
dimVelocity/dimLength,
pTraits<vector>::zero
),
h.boundaryField().types()
)
);
}
if (debug)
{
Info<< "wallModelFvPatchScalarField finished creating fields" << nl;
}
}
Foam::tmp<Foam::volScalarField> Foam::wallModelFvPatchScalarField::nu() const
{
const turbulenceModel& turbModel =
db().lookupObject<turbulenceModel>
(
turbulenceModel::propertiesName
);
return turbModel.nu();
}
Foam::tmp<Foam::scalarField> Foam::wallModelFvPatchScalarField::nu
(
const label patchi
) const
{
const turbulenceModel& turbModel =
db().lookupObject<turbulenceModel>
(
turbulenceModel::propertiesName
);
return turbModel.nu(patchi);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::wallModelFvPatchScalarField::wallModelFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF
)
:
fixedValueFvPatchScalarField(p, iF),
consumedTime_(0),
copyToPatchInternalField_(false),
silent_(false),
averagingTime_(0)
{
if (debug)
{
Info<< "Constructing wallModelFvPatchScalarField (w1) "
<< "from fvPatch and DimensionedField for patch " << patch().name()
<< nl;
}
checkType();
createFields();
}
Foam::wallModelFvPatchScalarField::wallModelFvPatchScalarField
(
const wallModelFvPatchScalarField& orig,
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
fixedValueFvPatchScalarField(orig, p, iF, mapper),
consumedTime_(0),
copyToPatchInternalField_(orig.copyToPatchInternalField_),
silent_(orig.silent_),
averagingTime_(orig.averagingTime_)
{
if (debug)
{
Info<< "Constructing wallModelFvPatchScalarField (w2) "
<< "from copy, fvPatch, DimensionedField, and fvPatchFieldMapper"
<< " for patch " << patch().name() << nl;
}
checkType();
}
Foam::wallModelFvPatchScalarField::wallModelFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const dictionary& dict
)
:
fixedValueFvPatchScalarField(p, iF, dict),
consumedTime_(0),
copyToPatchInternalField_
(
dict.lookupOrDefault<bool>("copyToPatchInternalField", false)
),
silent_(dict.lookupOrDefault<bool>("silent", false)),
averagingTime_(dict.lookupOrDefault<scalar>("averagingTime", 0))
{
if (debug)
{
Info<< "Constructing wallModelFvPatchScalarField (w3) "
<< "from fvPatch, DimensionedField, and dictionary for patch "
<< patch().name() << nl;
}
checkType();
createFields();
}
#ifdef FOAM_FVPATCHFIELD_NO_COPY
#else
Foam::wallModelFvPatchScalarField::wallModelFvPatchScalarField
(
const wallModelFvPatchScalarField& orig
)
:
fixedValueFvPatchScalarField(orig),
consumedTime_(orig.consumedTime_),
copyToPatchInternalField_(orig.copyToPatchInternalField_),
silent_(orig.silent_),
averagingTime_(orig.averagingTime_)
{
if (debug)
{
Info<< "Constructing wallModelFvPatchScalarField (w4)"
<< "using the copy constructor" << nl;
}
checkType();
}
#endif
Foam::wallModelFvPatchScalarField::wallModelFvPatchScalarField
(
const wallModelFvPatchScalarField& orig,
const DimensionedField<scalar, volMesh>& iF
)
:
fixedValueFvPatchScalarField(orig, iF),
consumedTime_(orig.consumedTime_),
copyToPatchInternalField_(orig.copyToPatchInternalField_),
silent_(orig.silent_),
averagingTime_(orig.averagingTime_)
{
if (debug)
{
Info<< "Constructing wallModelFvPatchScalarField (w5) "
<< "from copy and DimensionedField for patch " << patch().name()
<< nl;
}
checkType();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::wallModelFvPatchScalarField::updateCoeffs()
{
if (updated())
{
return;
}
scalar startCPUTime = db().time().elapsedClockTime();
label pI = patch().index();
// Compute uTau
volVectorField & wss =
const_cast<volVectorField &>
(
db().lookupObject<volVectorField>("wallShearStress")
);
const volVectorField & wallGradUField =
db().lookupObject<volVectorField>("wallGradU");
const vectorField & wallGradU = wallGradUField.boundaryField()[pI];
tmp<scalarField> tnuw = this->nu(pI);
const scalarField& nuw = tnuw();
// Compute nut and assign
scalarField nut(calcNut());
operator==(nut);
// Assign to the near-wall cells
if (copyToPatchInternalField())
{
volScalarField & nutField =
const_cast<volScalarField &>
(
db().lookupObject<volScalarField>("nut")
);
const labelUList fC = patch().faceCells();
forAll (nut, i)
{
nutField[fC[i]] = nut[i];
}
}
#ifdef FOAM_NEW_GEOMFIELD_RULES
wss.boundaryFieldRef()[pI]
#else
wss.boundaryField()[pI]
#endif
==
(nut + nuw)*wallGradU;
consumedTime_ += (db().time().elapsedClockTime() - startCPUTime);
// Take the max consumed time across all procs
reduce(consumedTime_, maxOp<scalar>());
if (!silent_)
{
Info<< "Wall modelling time consumption = " << consumedTime_
<< "s " << 100*consumedTime_/(db().time().elapsedClockTime() + SMALL)
<< "% of total " << nl;
}
}
void Foam::wallModelFvPatchScalarField::write(Ostream& os) const
{
fvPatchField<scalar>::write(os);
writeLocalEntries(os);
#ifdef FOAM_NEW_WRITEENTRY
writeEntry(os, "value", *this);
#else
writeEntry("value", os);
#endif
}