fvModels: Added volumeSource model

This fvModel applies a volume source to the continuity equation and to
all field equations. It can be applied to incompressible solvers, such
as incompressibleFluid and incompressibleVoF. For compressible solvers,
use the massSource model instead.

If the volumetric flow rate is positive then user-supplied fixed
property values are introduced to the field equations. If the volumetric
flow rate is negative then properties are removed at their current
value.

Example usage:

    volumeSource
    {
        type            volumeSource;

        select          cellSet;
        cellSet         volumeSource;

        volumetricFlowRate 1e-4;

        fieldValues
        {
            U               (10 0 0);
            k               0.375;
            epsilon         14.855;
        }
    }

If the volumetric 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.
This commit is contained in:
Will Bainbridge
2023-09-26 15:47:43 +01:00
parent a5ea0b41f1
commit 9181a699f2
13 changed files with 781 additions and 34 deletions

View File

@ -190,22 +190,7 @@ Foam::tmp<Foam::fvMatrix<Type>> Foam::fvModel::source
const VolField<Type>& field
) const
{
volScalarField one
(
IOobject
(
"one",
this->mesh_.time().name(),
this->mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
this->mesh_,
dimensionedScalar(dimless, 1.0)
);
return this->source(alpha, one, field);
return this->source(alpha, field);
}

View File

@ -174,22 +174,7 @@ Foam::tmp<Foam::fvMatrix<Type>> Foam::fvModels::source
const VolField<Type>& field
) const
{
volScalarField one
(
IOobject
(
"one",
this->mesh().time().name(),
this->mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
this->mesh(),
dimensionedScalar(dimless, 1.0)
);
return this->source(alpha, one, field);
return this->source(alpha, field);
}

View File

@ -26,7 +26,9 @@ Class
Description
This fvModel applies a mass source to the continuity equation and to all
field equations.
field equations. It can be applied to compressible solvers, such as fluid,
isothermalFluid, compressibleVoF and multiphaseEuler. For incompressible
solvers, use the volumeSource model instead.
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
@ -62,6 +64,9 @@ Usage
SourceFiles
massSource.C
See also
Foam::fv::volumeSource
\*---------------------------------------------------------------------------*/
#ifndef massSource_H

View File

@ -57,6 +57,21 @@ void Foam::fv::phaseLimitStabilisation::readCoeffs()
}
template<class Type>
void Foam::fv::phaseLimitStabilisation::addSupType
(
const volScalarField& alpha,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const
{
const uniformDimensionedScalarField& rate =
mesh().lookupObjectRef<uniformDimensionedScalarField>(rateName_);
eqn -= fvm::Sp(max(residualAlpha_ - alpha, scalar(0))*rate, eqn.psi());
}
template<class Type>
void Foam::fv::phaseLimitStabilisation::addSupType
(
@ -100,6 +115,13 @@ Foam::wordList Foam::fv::phaseLimitStabilisation::addSupFields() const
}
FOR_ALL_FIELD_TYPES
(
IMPLEMENT_FV_MODEL_ADD_RHO_FIELD_SUP,
fv::phaseLimitStabilisation
)
FOR_ALL_FIELD_TYPES
(
IMPLEMENT_FV_MODEL_ADD_ALPHA_RHO_FIELD_SUP,

View File

@ -92,6 +92,15 @@ class phaseLimitStabilisation
//- Non-virtual read
void readCoeffs();
//- Add source terms to an incompressible phase equation
template<class Type>
void addSupType
(
const volScalarField& alpha,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const;
//- Add source terms to a phase equation
template<class Type>
void addSupType
@ -140,6 +149,9 @@ public:
// Sources
//- Add a source term to an incompressible phase equation
FOR_ALL_FIELD_TYPES(DEFINE_FV_MODEL_ADD_RHO_FIELD_SUP)
//- Add a source term to a phase equation
FOR_ALL_FIELD_TYPES(DEFINE_FV_MODEL_ADD_ALPHA_RHO_FIELD_SUP)

View File

@ -0,0 +1,369 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "volumeSource.H"
#include "fvMatrices.H"
#include "basicThermo.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace fv
{
defineTypeNameAndDebug(volumeSource, 0);
addToRunTimeSelectionTable(fvModel, volumeSource, dictionary);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::fv::volumeSource::readCoeffs()
{
phaseName_ = coeffs().lookupOrDefault<word>("phase", word::null);
alphaName_ =
phaseName_ == word::null
? word::null
: coeffs().lookupOrDefault<word>
(
"alpha",
IOobject::groupName("alpha", phaseName_)
);
readSet();
readFieldValues();
volumetricFlowRate_.reset
(
Function1<scalar>::New("volumetricFlowRate", coeffs()).ptr()
);
}
Foam::scalar Foam::fv::volumeSource::volumetricFlowRate() const
{
return volumetricFlowRate_->value(mesh().time().userTimeValue());
}
template<class Type>
void Foam::fv::volumeSource::addSupType(fvMatrix<Type>& eqn) const
{
FatalErrorInFunction
<< "Continuity sources for non-scalar types are not supported"
<< exit(FatalError);
}
void Foam::fv::volumeSource::addSupType(fvMatrix<scalar>& eqn) const
{
const labelUList cells = set_.cells();
const scalar volumetricFlowRate = this->volumetricFlowRate();
// Continuity equation. Add the volumetric flow rate.
forAll(cells, i)
{
eqn.source()[cells[i]] -=
mesh().V()[cells[i]]/set_.V()*volumetricFlowRate;
}
}
template<class Type>
void Foam::fv::volumeSource::addSupType
(
const dimensionedScalar& oneOrRho,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const
{
const labelUList cells = set_.cells();
const scalar flowRate = this->volumetricFlowRate()*oneOrRho.value();
// Property equation. If the source is positive, introduce the value
// specified by the user. If negative, then sink the current internal value
// using an implicit term.
if (flowRate > 0)
{
const Type value =
fieldValues_[field.name()]->template value<Type>
(
mesh().time().userTimeValue()
);
forAll(cells, i)
{
eqn.source()[cells[i]] -=
mesh().V()[cells[i]]/set_.V()*flowRate*value;
}
}
else
{
forAll(cells, i)
{
eqn.diag()[cells[i]] +=
mesh().V()[cells[i]]/set_.V()*flowRate;
}
}
}
template<class Type>
void Foam::fv::volumeSource::addSupType
(
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const
{
// Property equation
addSupType(dimensionedScalar(dimless, scalar(1)), field, eqn);
}
void Foam::fv::volumeSource::addSupType
(
const volScalarField& field,
fvMatrix<scalar>& eqn
) const
{
// Multiphase continuity equation. Same source as single-phase case.
if (field.name() == alphaName_)
{
addSupType(eqn);
return;
}
// Property equation
addSupType<scalar>(field, eqn);
}
template<class Type>
void Foam::fv::volumeSource::addSupType
(
const volScalarField& rho,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const
{
// Multiphase property equation (e.g., turbulence equation if running
// two-phase transport modelling in the incompressibleVoF solver)
if (rho.name() == alphaName_)
{
addSupType(dimensionedScalar(dimless, scalar(1)), field, eqn);
return;
}
// Mixture property equation (e.g., the momentum equation in the
// incompressibleVoF solver)...
// We need to know the density of the phase of which this is a source in
// order to create the relevant term. There is no solver-agnostic
// interface, at present, that lets us do this. So, read the density from
// the physical properties file. This is clunky, but it should work in all
// circumstances. This is what the clouds fvModel does,
const dimensionedScalar rhoi
(
"rho",
dimDensity,
mesh().lookupObject<IOdictionary>
(
IOobject::groupName
(
physicalProperties::typeName,
phaseName_
)
)
);
addSupType(rhoi, field, eqn);
}
template<class Type>
void Foam::fv::volumeSource::addSupType
(
const volScalarField& alpha,
const volScalarField& rho,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const
{
FatalErrorInFunction
<< "Cannot add a volume source for field " << field.name()
<< " because this field's equation is not in volume-conservative form"
<< exit(FatalError);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::fv::volumeSource::readSet()
{
set_.read(coeffs());
}
void Foam::fv::volumeSource::readFieldValues()
{
fieldValues_.clear();
const dictionary& fieldCoeffs = coeffs().subDict("fieldValues");
forAllConstIter(dictionary, fieldCoeffs, iter)
{
fieldValues_.set
(
iter().keyword(),
new unknownTypeFunction1(iter().keyword(), fieldCoeffs)
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fv::volumeSource::volumeSource
(
const word& name,
const word& modelType,
const fvMesh& mesh,
const dictionary& dict
)
:
fvModel(name, modelType, mesh, dict),
phaseName_(),
set_(fvCellSet(mesh)),
fieldValues_(),
volumetricFlowRate_()
{
readCoeffs();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fv::volumeSource::addsSupToField(const word& fieldName) const
{
const bool isMixture = IOobject::group(fieldName) == word::null;
const bool isThisPhase = IOobject::group(fieldName) == phaseName_;
if
(
(isMixture || isThisPhase)
&& volumetricFlowRate() > 0
&& !(fieldName == alphaName_)
&& !fieldValues_.found(fieldName)
)
{
WarningInFunction
<< "No value supplied for field " << fieldName << " in "
<< type() << " fvModel " << name() << endl;
return false;
}
return isMixture || isThisPhase;
}
Foam::wordList Foam::fv::volumeSource::addSupFields() const
{
return fieldValues_.toc();
}
FOR_ALL_FIELD_TYPES
(
IMPLEMENT_FV_MODEL_ADD_SUP,
fv::volumeSource
)
FOR_ALL_FIELD_TYPES
(
IMPLEMENT_FV_MODEL_ADD_FIELD_SUP,
fv::volumeSource
)
FOR_ALL_FIELD_TYPES
(
IMPLEMENT_FV_MODEL_ADD_RHO_FIELD_SUP,
fv::volumeSource
)
FOR_ALL_FIELD_TYPES
(
IMPLEMENT_FV_MODEL_ADD_ALPHA_RHO_FIELD_SUP,
fv::volumeSource
)
bool Foam::fv::volumeSource::movePoints()
{
set_.movePoints();
return true;
}
void Foam::fv::volumeSource::topoChange(const polyTopoChangeMap& map)
{
set_.topoChange(map);
}
void Foam::fv::volumeSource::mapMesh(const polyMeshMap& map)
{
set_.mapMesh(map);
}
void Foam::fv::volumeSource::distribute(const polyDistributionMap& map)
{
set_.distribute(map);
}
bool Foam::fv::volumeSource::read(const dictionary& dict)
{
if (fvModel::read(dict))
{
readCoeffs();
return true;
}
else
{
return false;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,273 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::fv::volumeSource
Description
This fvModel applies a volume source to the continuity equation and to all
field equations. It can be applied to incompressible solvers, such as
incompressibleFluid and incompressibleVoF. For compressible solvers, use
the massSource model instead.
If the volumetric flow rate is positive then user-supplied fixed property
values are introduced to the field equations. If the volumetric flow rate
is negative then properties are removed at their current value.
Usage
Example usage:
\verbatim
volumeSource
{
type volumeSource;
select cellSet;
cellSet volumeSource;
volumetricFlowRate 1e-4;
fieldValues
{
U (10 0 0);
k 0.375;
epsilon 14.855;
}
}
\endverbatim
If the volumetric 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
volumeSource.C
See also
Foam::fv::massSource
\*---------------------------------------------------------------------------*/
#ifndef volumeSource_H
#define volumeSource_H
#include "fvModel.H"
#include "fvCellSet.H"
#include "HashPtrTable.H"
#include "unknownTypeFunction1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fv
{
/*---------------------------------------------------------------------------*\
Class volumeSource Declaration
\*---------------------------------------------------------------------------*/
class volumeSource
:
public fvModel
{
private:
// Private Data
//- Name of the phase
word phaseName_;
//- Name of the volume fraction field
word alphaName_;
//- The set of cells the fvConstraint applies to
fvCellSet set_;
//- Field values
HashPtrTable<unknownTypeFunction1> fieldValues_;
//- Volumetric flow rate
autoPtr<Function1<scalar>> volumetricFlowRate_;
// Private Member Functions
//- Non-virtual read
void readCoeffs();
//- Return the volumetric flow rate
scalar volumetricFlowRate() const;
// Sources
//- Add a source term to an equation
template<class Type>
void addSupType(fvMatrix<Type>& eqn) const;
//- Add a source term to a scalar equation
void addSupType(fvMatrix<scalar>& eqn) const;
//- Add a source term to an equation
template<class Type>
void addSupType
(
const dimensionedScalar& oneOrRho,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const;
//- Add a source term to an equation
template<class Type>
void addSupType
(
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const;
//- Add a source term to a scalar equation
void addSupType
(
const volScalarField& field,
fvMatrix<scalar>& eqn
) const;
//- Add a source term to a compressible equation
template<class Type>
void addSupType
(
const volScalarField& rho,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const;
//- Add a source term to a phase equation
template<class Type>
void addSupType
(
const volScalarField& alpha,
const volScalarField& rho,
const VolField<Type>& field,
fvMatrix<Type>& eqn
) const;
protected:
// Protected Member Functions
//- Read the set
void readSet();
//- Read the field values
void readFieldValues();
public:
//- Runtime type information
TypeName("volumeSource");
// Constructors
//- Construct from explicit source name and mesh
volumeSource
(
const word& name,
const word& modelType,
const fvMesh& mesh,
const dictionary& dict
);
//- Disallow default bitwise copy construction
volumeSource(const volumeSource&) = delete;
// Member Functions
// Checks
//- Return true if the fvModel adds a source term to the given
// field's transport equation
virtual bool addsSupToField(const word& fieldName) const;
//- Return the list of fields for which the fvModel adds source term
// to the transport equation
virtual wordList addSupFields() const;
// Sources
//- Add a source term to an equation
FOR_ALL_FIELD_TYPES(DEFINE_FV_MODEL_ADD_SUP)
//- Add a source term to an equation
FOR_ALL_FIELD_TYPES(DEFINE_FV_MODEL_ADD_FIELD_SUP)
//- Add a source term to a compressible equation
FOR_ALL_FIELD_TYPES(DEFINE_FV_MODEL_ADD_RHO_FIELD_SUP)
//- Add a source term to a phase equation
FOR_ALL_FIELD_TYPES(DEFINE_FV_MODEL_ADD_ALPHA_RHO_FIELD_SUP)
// Mesh changes
//- Update for mesh motion
virtual bool movePoints();
//- Update topology using the given map
virtual void topoChange(const polyTopoChangeMap&);
//- Update from another mesh using the given map
virtual void mapMesh(const polyMeshMap&);
//- Redistribute or update using the given distribution map
virtual void distribute(const polyDistributionMap&);
// IO
//- Read source dictionary
virtual bool read(const dictionary& dict);
// Member Operators
//- Disallow default bitwise assignment
void operator=(const volumeSource&) = delete;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fv
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -20,4 +20,19 @@ volumeFraction
volumePhase volume;
}
volumeSource
{
type volumeSource;
cellZone volumeSource;
volumetricFlowRate 0.00064;
fieldValues
{
U (0 0 0);
tracer 1;
}
}
// ************************************************************************* //

View File

@ -31,6 +31,11 @@ vertices
(0 -56 -1) (256 -56 -1)
(0 -88 1) (256 -88 1)
(0 -56 1) (256 -56 1)
(0 -124 -1) (16 -124 -1) (256 -124 -1)
(0 -92 -1) (16 -92 -1) (256 -92 -1)
(0 -124 1) (16 -124 1) (256 -124 1)
(0 -92 1) (16 -92 1) (256 -92 1)
);
blocks
@ -44,6 +49,9 @@ blocks
hex (12 13 19 18 24 25 31 30) (64 32 1) simpleGrading (1 1 1)
hex (32 33 35 34 36 37 39 38) (256 32 1) simpleGrading (1 1 1)
hex (40 41 44 43 46 47 50 49) volumeSource (16 32 1) simpleGrading (1 1 1)
hex (41 42 45 44 47 48 51 50) (240 32 1) simpleGrading (1 1 1)
);
defaultPatch
@ -76,6 +84,8 @@ boundary
(13 19 31 25)
(33 35 39 37)
(42 45 51 48)
);
}
walls
@ -99,6 +109,12 @@ boundary
(32 33 37 36)
(34 35 39 38)
(40 43 49 46)
(40 41 47 46)
(41 42 48 47)
(43 44 50 49)
(44 45 51 50)
);
}
);

View File

@ -42,7 +42,7 @@ codeWrite
mesh().time().constant(),
mesh()
),
0.5*pos(y - (-0.088))*pos((-0.056) - y)*f
0.5*pos(y - (-0.124))*pos((-0.056) - y)*f
).write();
#};

View File

@ -0,0 +1,11 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Source tutorial clean functions
. $WM_PROJECT_DIR/bin/tools/CleanFunctions
cleanVoFCase && rm -rf 0 system
find constant -type f -not -name fvModels.injection -delete
#------------------------------------------------------------------------------

View File

@ -0,0 +1,18 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions
# Copy the source case and add the volume source model
isTest "$@" && path=.. || path=$FOAM_TUTORIALS/incompressibleVoF
cp -rn $path/damBreak/0 $path/damBreak/constant $path/damBreak/system .
runApplication foamDictionary constant/fvModels \
-entry injection -dict -merge constant/fvModels.injection
# Run
runApplication blockMesh
runApplication setFields
runApplication $(getApplication)
#------------------------------------------------------------------------------

View File

@ -0,0 +1,36 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
\*---------------------------------------------------------------------------*/
FoamFile
{
format ascii;
class dictionary;
location "constant";
object fvModels.injection;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
injection
{
type volumeSource;
points ((0.438 0.438 0.0073));
volumetricFlowRate 0.0003;
phase water;
fieldValues
{
U (-1 0 0);
k 0.1;
epsilon 0.1;
}
}
//************************************************************************* //