fv::zeroDimensionalMassSource: Support use of multiple sources

The computation of the current and total accumulated mass is now shared
across all zeroDimensionalMassSource models. So, multiple models can be
used simultaneously.
This commit is contained in:
Will Bainbridge
2023-03-24 15:00:26 +00:00
parent d7e3306761
commit 6233f98806
2 changed files with 190 additions and 58 deletions

View File

@ -39,49 +39,143 @@ namespace fv
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::fv::zeroDimensionalMassSource::readCoeffs()
Foam::tmp<Foam::volScalarField>
Foam::fv::zeroDimensionalMassSource::calcM0D() const
{
const basicThermo& thermo =
mesh().lookupObject<basicThermo>
tmp<volScalarField> tm =
volScalarField::New
(
IOobject::groupName(physicalProperties::typeName, phaseName_)
typedName("m0D"),
mesh(),
dimensionedScalar(dimMass, 0)
);
rho0Ptr_.reset
(
new volScalarField::Internal
(
IOobject
(
typedName("rho0"),
mesh().time().timeName(),
mesh(),
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
thermo.rho()().internalField()
)
);
HashTable<const basicThermo*> thermos(mesh().lookupClass<basicThermo>());
forAllConstIter(HashTable<const basicThermo*>, thermos, thermoIter)
{
const basicThermo& thermo = *thermoIter();
tmp<volScalarField> tRho = thermo.rho();
const volScalarField& rho = tRho();
const word phaseName = thermo.phaseName();
if (thermo.phaseName() != word::null)
{
const volScalarField alpha =
mesh().lookupObject<volScalarField>
(
IOobject::groupName("alpha", phaseName_)
);
tm.ref().ref() += alpha()*rho()*mesh().V();
}
else
{
tm.ref().ref() += rho()*mesh().V();
}
}
return tm;
}
Foam::scalar Foam::fv::zeroDimensionalMassSource::massFlowRate() const
Foam::volScalarField& Foam::fv::zeroDimensionalMassSource::initM0D() const
{
const scalar t = mesh().time().userTimeValue();
const scalar t0 = mesh().time().beginTime().value();
if (!mesh().foundObject<volScalarField>(typedName("m0D")))
{
volScalarField* mPtr =
new volScalarField
(
calcM0D()
);
const scalar mDot = massFlowRate_->value(t);
const scalar sumMDot = massFlowRate_->integral(t0, t);
mPtr->store();
}
const basicThermo& thermo =
mesh().lookupObject<basicThermo>
return mesh().lookupObjectRef<volScalarField>(typedName("m0D"));
}
const Foam::volScalarField& Foam::fv::zeroDimensionalMassSource::m() const
{
// If not registered, then read or create the mass field
if (!mesh().foundObject<volScalarField>(typedName("m")))
{
typeIOobject<volScalarField> mIo
(
IOobject::groupName(physicalProperties::typeName, phaseName_)
typedName("m"),
mesh().time().timeName(),
mesh(),
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
);
return mDot*thermo.rho()()[0]/(rho0Ptr_()[0] + sumMDot/mesh().V()[0]);
volScalarField* mPtr =
new volScalarField
(
mIo,
mesh(),
dimensionedScalar(dimMass, 0)
);
mPtr->store();
if (!mIo.headerOk())
{
*mPtr = m0D_;
}
volScalarField* factorPtr =
new volScalarField
(
IOobject
(
typedName("factor"),
mesh().time().timeName(),
mesh(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
*mPtr/m0D_
);
factorPtr->store();
}
volScalarField& m =
mesh().lookupObjectRef<volScalarField>(typedName("m"));
volScalarField& factor =
mesh().lookupObjectRef<volScalarField>(typedName("factor"));
// Update the mass if changes are available
if (mesh().foundObject<volScalarField>(typedName("deltaM")))
{
volScalarField& deltaM =
mesh().lookupObjectRef<volScalarField>(typedName("deltaM"));
m = m.oldTime() + deltaM;
factor = m/m0D_;
deltaM.checkOut();
}
return m;
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::scalar Foam::fv::zeroDimensionalMassSource::massFlowRate() const
{
const scalar mDot = massFlowRate_->value(mesh().time().userTimeValue());
return mDot*m0D_[0]/m()[0];
}
@ -96,7 +190,7 @@ Foam::fv::zeroDimensionalMassSource::zeroDimensionalMassSource
)
:
massSource(name, modelType, mesh, dict, true),
rho0Ptr_()
m0D_(initM0D())
{
if (mesh.nGeometricD() != 0)
{
@ -105,25 +199,41 @@ Foam::fv::zeroDimensionalMassSource::zeroDimensionalMassSource
<< mesh.nGeometricD() << "-dimensional mesh"
<< exit(FatalIOError);
}
readCoeffs();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fv::zeroDimensionalMassSource::read(const dictionary& dict)
void Foam::fv::zeroDimensionalMassSource::correct()
{
if (fvModel::read(dict))
// Correct the zero-dimensional mass
m0D_ = calcM0D();
// Create the mass change
if (!mesh().foundObject<volScalarField>(typedName("deltaM")))
{
massSource::readCoeffs();
readCoeffs();
return true;
}
else
{
return false;
volScalarField* dMPtr =
new volScalarField
(
IOobject
(
typedName("deltaM"),
mesh().time().timeName(),
mesh()
),
mesh(),
dimensionedScalar(dimMass, 0)
);
dMPtr->store();
}
volScalarField& deltaM =
mesh().lookupObjectRef<volScalarField>(typedName("deltaM"));
const scalar mDot = massFlowRate_->value(mesh().time().userTimeValue());
deltaM += mesh().time().deltaT()*dimensionedScalar(dimMass/dimTime, mDot);
}

View File

@ -30,6 +30,19 @@ Description
for the mass that exits the domain due to expansion in space, so that the
model correctly applies a total mass flow rate.
This model will write out additional fields, zeroDimensionalMassSource:m
and zeroDimensionalMassSource:factor. The zeroDimensionalMassSource:m field
is the total accumulated mass; the sum of the starting mass, plus all mass
added by models of this type. This may differ from the actual current mass
(= rho*V) within the zero-dimensional cell if pressure or density
constraints are being used. The zeroDimensionalMassSource:factor field is
the ratio between the current mass or volume and the total accumulated mass
or volume.
If the mass flow rate is positive then user-supplied fixed property values
are introduced to the field equations. If the mass flow rate is negative
then properties are removed at their current value.
Usage
Example usage:
\verbatim
@ -49,10 +62,10 @@ Usage
}
\endverbatim
Values should be provided for all solved for fields. Warnings will be
issued if values are not provided for fields for which transport equations
are solved. Warnings will also be issued if values are provided for fields
which are not solved for.
If the mass flow rate is positive then values should be provided for all
solved for fields. Warnings will be issued if values are not provided for
fields for which transport equations are solved. Warnings will also be
issued if values are provided for fields which are not solved for.
SourceFiles
zeroDimensionalMassSource.C
@ -79,19 +92,30 @@ class zeroDimensionalMassSource
:
public massSource
{
private:
// Private Data
//- Reference to the zero-dimensional mass
volScalarField& m0D_;
// Private Member Functions
//- Calculate and return the zero-dimensional mass
tmp<volScalarField> calcM0D() const;
//- Initialise and return a reference to the zero-dimensional mass
volScalarField& initM0D() const;
//- Get a reference to the mass
const volScalarField& m() const;
protected:
// Protected Data
//- Cached initial density field
autoPtr<volScalarField::Internal> rho0Ptr_;
// Protected Member Functions
//- Non-virtual read
void readCoeffs();
//- Return the mass flow rate
virtual scalar massFlowRate() const;
@ -116,10 +140,8 @@ public:
// Member Functions
// IO
//- Read source dictionary
virtual bool read(const dictionary& dict);
//- Update the model
virtual void correct();
};