diff --git a/src/fvOptions/Make/files b/src/fvOptions/Make/files
index 40d4bd74cf..370b50aa37 100644
--- a/src/fvOptions/Make/files
+++ b/src/fvOptions/Make/files
@@ -37,6 +37,7 @@ $(derivedSources)/phaseLimitStabilization/phaseLimitStabilization.C
$(derivedSources)/accelerationSource/accelerationSource.C
$(derivedSources)/volumeFractionSource/volumeFractionSource.C
$(derivedSources)/solidEquilibriumEnergySource/solidEquilibriumEnergySource.C
+$(derivedSources)/massSource/massSource.C
interRegion = sources/interRegion
$(interRegion)/interRegionHeatTransfer/interRegionHeatTransferModel/interRegionHeatTransferModel.C
diff --git a/src/fvOptions/sources/derived/massSource/massSource.C b/src/fvOptions/sources/derived/massSource/massSource.C
new file mode 100644
index 0000000000..41d4851ea2
--- /dev/null
+++ b/src/fvOptions/sources/derived/massSource/massSource.C
@@ -0,0 +1,445 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2021 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 .
+
+\*---------------------------------------------------------------------------*/
+
+#include "massSource.H"
+#include "fvMatrices.H"
+#include "basicThermo.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fv
+{
+ defineTypeNameAndDebug(massSource, 0);
+ addToRunTimeSelectionTable(option, massSource, dictionary);
+}
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+void Foam::fv::massSource::readCoeffs()
+{
+ phaseName_ = coeffs_.lookupOrDefault("phase", word::null);
+
+ rhoName_ =
+ coeffs_.lookupOrDefault
+ (
+ "rho",
+ IOobject::groupName("rho", phaseName_)
+ );
+
+ if
+ (
+ mesh_.foundObject
+ (
+ IOobject::groupName(basicThermo::dictName, phaseName_)
+ )
+ )
+ {
+ const basicThermo& thermo =
+ mesh_.lookupObject
+ (
+ IOobject::groupName(basicThermo::dictName, phaseName_)
+ );
+ heName_ = thermo.he().name();
+ TName_ = thermo.T().name();
+ }
+
+ fieldValues_.clear();
+ const dictionary& fieldCoeffs = coeffs_.subDict("fieldValues");
+ forAllConstIter(dictionary, fieldCoeffs, iter)
+ {
+ fieldValues_.set(iter().keyword(), nullptr);
+ }
+ readFieldValuesType();
+ readFieldValuesType();
+ readFieldValuesType();
+ readFieldValuesType();
+ readFieldValuesType();
+
+ massFlowRate_.reset(Function1::New("massFlowRate", coeffs_).ptr());
+}
+
+
+template
+void Foam::fv::massSource::readFieldValuesType()
+{
+ const dictionary& fieldCoeffs = coeffs_.subDict("fieldValues");
+
+ forAllConstIter(dictionary, fieldCoeffs, iter)
+ {
+ const word& fieldName = iter().keyword();
+
+ if (mesh_.foundObject>(fieldName))
+ {
+ fieldValues_.set
+ (
+ fieldName,
+ objectFunction1::New
+ (
+ fieldName,
+ fieldCoeffs,
+ fieldName,
+ mesh_
+ ).ptr()
+ );
+ }
+ }
+}
+
+
+void Foam::fv::massSource::addRhoSup
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ const scalar t = mesh_.time().value();
+ const scalar massFlowRate = massFlowRate_->value(t);
+
+ forAll(cells(), i)
+ {
+ eqn.source()[cells()[i]] -= mesh_.V()[cells()[i]]/V()*massFlowRate;
+ }
+}
+
+
+void Foam::fv::massSource::addHeSupT
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ if (fieldValues_.found(heName_))
+ {
+ WarningInFunction
+ << "Source " << name() << " defined for both field " << heName_
+ << " and " << TName_ << ". Only one of these should be present."
+ << endl;
+ }
+
+ const scalar t = mesh_.time().value();
+ const scalar massFlowRate = massFlowRate_->value(t);
+ const scalar T = fieldValues_[TName_]->value(t);
+ const basicThermo& thermo =
+ mesh_.lookupObject
+ (
+ IOobject::groupName(basicThermo::dictName, phaseName_)
+ );
+ const scalarField hs(thermo.hs(scalarField(cells().size(), T), cells()));
+
+ forAll(cells(), i)
+ {
+ eqn.source()[cells()[i]] -=
+ mesh_.V()[cells()[i]]/V()*massFlowRate*hs[i];
+ }
+}
+
+
+template
+void Foam::fv::massSource::addSupType
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ const scalar t = mesh_.time().value();
+ const scalar massFlowRate = massFlowRate_->value(t);
+ const Type value = fieldValues_[fieldName]->value(t);
+
+ forAll(cells(), i)
+ {
+ eqn.source()[cells()[i]] -=
+ mesh_.V()[cells()[i]]/V()*massFlowRate*value;
+ }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::fv::massSource::massSource
+(
+ const word& name,
+ const word& modelType,
+ const dictionary& dict,
+ const fvMesh& mesh
+)
+:
+ cellSetOption(name, modelType, dict, mesh),
+ phaseName_(),
+ rhoName_(),
+ heName_(),
+ TName_(),
+ massFlowRate_(),
+ fieldValues_()
+{
+ readCoeffs();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+bool Foam::fv::massSource::addsToField(const word& fieldName) const
+{
+ const bool isThisPhase = IOobject::group(fieldName) == phaseName_;
+
+ if
+ (
+ isThisPhase
+ && !(fieldName == rhoName_)
+ && !(fieldName == heName_ && fieldValues_.found(TName_))
+ && !fieldValues_.found(fieldName)
+ )
+ {
+ WarningInFunction
+ << "No value supplied for field " << fieldName << " in "
+ << type() << " fvOption " << name() << endl;
+
+ return false;
+ }
+
+ return isThisPhase;
+}
+
+
+Foam::wordList Foam::fv::massSource::addedToFields() const
+{
+ wordList fieldNames = fieldValues_.toc();
+
+ if (fieldValues_.found(TName_))
+ {
+ fieldNames[findIndex(fieldNames, TName_)] = heName_;
+ }
+
+ return fieldNames;
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ if (fieldName == rhoName_)
+ {
+ addRhoSup(eqn, fieldName);
+ }
+ else if (fieldName == heName_ && fieldValues_.found(TName_))
+ {
+ addHeSupT(eqn, fieldName);
+ }
+ else
+ {
+ addSupType(eqn, fieldName);
+ }
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSupType(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSupType(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSupType(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSupType(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ if (fieldName == heName_ && fieldValues_.found(TName_))
+ {
+ addHeSupT(eqn, fieldName);
+ }
+ else
+ {
+ addSup(eqn, fieldName);
+ }
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ if (fieldName == heName_ && fieldValues_.found(TName_))
+ {
+ addHeSupT(eqn, fieldName);
+ }
+ else
+ {
+ addSup(eqn, fieldName);
+ }
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+
+void Foam::fv::massSource::addSup
+(
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+) const
+{
+ addSup(eqn, fieldName);
+}
+
+
+bool Foam::fv::massSource::read(const dictionary& dict)
+{
+ if (cellSetOption::read(dict))
+ {
+ readCoeffs();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvOptions/sources/derived/massSource/massSource.H b/src/fvOptions/sources/derived/massSource/massSource.H
new file mode 100644
index 0000000000..977c9a07b9
--- /dev/null
+++ b/src/fvOptions/sources/derived/massSource/massSource.H
@@ -0,0 +1,300 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2021 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 .
+
+Class
+ Foam::fv::massSource
+
+Description
+ This fvOption applies a mass source to the continuity equation and to all
+ field equations.
+
+Usage
+ Example usage:
+ \verbatim
+ massSource
+ {
+ type massSource;
+
+ selectionMode cellSet;
+ cellSet massSource;
+
+ massFlowRate 1e-4;
+
+ fieldValues
+ {
+ U (10 0 0);
+ e 10;
+ k 0.375;
+ epsilon 14.855;
+ }
+ }
+ \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.
+
+SourceFiles
+ massSource.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef massSource_H
+#define massSource_H
+
+#include "cellSetOption.H"
+#include "HashPtrTable.H"
+#include "objectFunction1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fv
+{
+
+/*---------------------------------------------------------------------------*\
+ Class massSource Declaration
+\*---------------------------------------------------------------------------*/
+
+class massSource
+:
+ public cellSetOption
+{
+ // Private Data
+
+ //- Name of the phase
+ word phaseName_;
+
+ //- Name of the density field
+ word rhoName_;
+
+ //- Name of the energy field
+ word heName_;
+
+ //- Name of the temperature field
+ word TName_;
+
+ //- Mass source
+ autoPtr> massFlowRate_;
+
+ //- Field values
+ HashPtrTable fieldValues_;
+
+
+ // Private Member Functions
+
+ //- Non-virtual read
+ void readCoeffs();
+
+ //- Read field values for a given primitive type
+ template
+ void readFieldValuesType();
+
+ //- Add the mass source term to the continuity equation
+ void addRhoSup(fvMatrix& eqn, const word& fieldName) const;
+
+ //- Add the mass source term to the energy equation, given a value of
+ // temperature
+ void addHeSupT(fvMatrix& eqn, const word& fieldName) const;
+
+ //- Add the mass source term to an equation
+ template
+ void addSupType(fvMatrix& eqn, const word& fieldName) const;
+
+
+public:
+
+ //- Runtime type information
+ TypeName("massSource");
+
+
+ // Constructors
+
+ //- Construct from explicit source name and mesh
+ massSource
+ (
+ const word& sourceName,
+ const word& modelType,
+ const dictionary& dict,
+ const fvMesh& mesh
+ );
+
+ //- Disallow default bitwise copy construction
+ massSource(const massSource&) = delete;
+
+
+ // Member Functions
+
+ // Access
+
+ //- Return the name of the density field
+ const word& rhoName() const
+ {
+ return rhoName_;
+ }
+
+
+ // Checks
+
+ //- Return true if the option adds a source term to the given
+ // field's transport equation
+ virtual bool addsToField(const word& fieldName) const;
+
+ //- Return the list of fields for which the option adds source term
+ // to the transport equation
+ virtual wordList addedToFields() const;
+
+
+ // Evaluate
+
+ virtual void addSup
+ (
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+ virtual void addSup
+ (
+ const volScalarField& alpha,
+ const volScalarField& rho,
+ fvMatrix& eqn,
+ const word& fieldName
+ ) const;
+
+
+ // IO
+
+ //- Read source dictionary
+ virtual bool read(const dictionary& dict);
+
+
+ // Member Operators
+
+ //- Disallow default bitwise assignment
+ void operator=(const massSource&) = delete;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fv
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/tutorials/multiphase/multiphaseEulerFoam/laminar/bed/constant/fvOptions b/tutorials/multiphase/multiphaseEulerFoam/laminar/bed/constant/fvOptions
index e5f8536c42..0e31d185cd 100644
--- a/tutorials/multiphase/multiphaseEulerFoam/laminar/bed/constant/fvOptions
+++ b/tutorials/multiphase/multiphaseEulerFoam/laminar/bed/constant/fvOptions
@@ -19,26 +19,21 @@ options
{
massSource
{
- type semiImplicitSource;
-
- timeStart 0;
- duration 1e6;
+ type massSource;
selectionMode points;
- points
- (
- (0.075 0.925 0.05)
- );
+ points ((0.075 0.925 0.05));
volumeMode absolute;
- sources
+ massFlowRate 1;
+
+ phase water;
+ rho thermo:rho.water;
+
+ fieldValues
{
- thermo:rho.water
- {
- explicit 1; // kg/s
- implicit 0;
- }
+ U.water (0 0 0);
}
}
}
diff --git a/tutorials/multiphase/multiphaseEulerFoam/laminar/injection/constant/fvOptions b/tutorials/multiphase/multiphaseEulerFoam/laminar/injection/constant/fvOptions
index e2f5395324..dba627bc0e 100644
--- a/tutorials/multiphase/multiphaseEulerFoam/laminar/injection/constant/fvOptions
+++ b/tutorials/multiphase/multiphaseEulerFoam/laminar/injection/constant/fvOptions
@@ -19,7 +19,7 @@ options
{
massSource
{
- type semiImplicitSource;
+ type massSource;
timeStart 0.1;
duration 5;
@@ -32,25 +32,22 @@ options
volumeMode absolute;
- sources
+ phase air;
+ rho thermo:rho.air;
+
+ massFlowRate
{
- thermo:rho.air
- {
- explicit 1e-3; // kg/s
- implicit 0;
- }
+ type scale;
+ scale squarePulse;
+ start 0.1;
+ duration 5;
+ value 1e-3;
+ }
- U.air
- {
- explicit (0 -1e-2 0); // kg*m/s^2
- implicit 0;
- }
-
- e.air
- {
- explicit 500; // kg*m^2/s^3
- implicit 0;
- }
+ fieldValues
+ {
+ U.air (0 -10 0);
+ T.air 300;
}
}
}
diff --git a/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/constant/fvOptions b/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/constant/fvOptions
index 9a560f1778..e21e5c99cd 100644
--- a/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/constant/fvOptions
+++ b/tutorials/multiphase/multiphaseEulerFoam/laminar/steamInjection/constant/fvOptions
@@ -19,7 +19,7 @@ options
{
massSource
{
- type semiImplicitSource;
+ type massSource;
timeStart 1;
duration 500;
@@ -32,25 +32,22 @@ options
volumeMode absolute;
- sources
+ phase steam;
+ rho thermo:rho.steam;
+
+ massFlowRate
{
- thermo:rho.steam
- {
- explicit 1.0e-3; // kg/s
- implicit 0;
- }
+ type scale;
+ scale squarePulse;
+ start 1;
+ duration 1e6;
+ value 1e-3;
+ }
- U.steam
- {
- explicit (0 1e-1 0); // kg*m/s^2
- implicit 0;
- }
-
- h.steam
- {
- explicit 3700; // kg*m^2/s^3
- implicit 0;
- }
+ fieldValues
+ {
+ U.steam (0 10 0);
+ h.steam 3700000;
}
}