Population balance size-group fraction 'f<index>.<phase>' fields are now
read from an 'fDefault.<phase>' field if they are not provided
explicitly. This is the same process as is applied to species fractions
or fvDOM rays. The sum-of-fs field 'f.<phase>' is no longer required.
The value of a fraction field and its boundary conditions must now be
specified in the corresponding field file. Value entries are no longer
given in the size group dictionaries in the constant/phaseProperties
file, and an error message will be generated if a value entry is found.
The fraction fields are now numbered programatically, rather than being
named. So, the size-group dictionaries do not require a name any more.
All of the above is also true for any 'kappa<index>.<phase>' fields that
are constructed and solved for as part of a fractal shape model.
The following is an example of a specification of a population balance
with two phases in it:
populationBalances (bubbles);
air1
{
type pureIsothermalPhaseModel;
diameterModel velocityGroup;
velocityGroupCoeffs
{
populationBalance bubbles;
shapeModel spherical;
sizeGroups
(
{ dSph 1e-3; } // Size-group #0: Fraction field f0.air1
{ dSph 2e-3; } // ...
{ dSph 3e-3; }
{ dSph 4e-3; }
{ dSph 5e-3; }
);
}
residualAlpha 1e-6;
}
air2
{
type pureIsothermalPhaseModel;
diameterModel velocityGroup;
velocityGroupCoeffs
{
populationBalance bubbles;
shapeModel spherical;
sizeGroups
(
{ dSph 6e-3; } // Size-group #5: Fraction field f5.air2
{ dSph 7e-3; } // ...
{ dSph 8e-3; }
{ dSph 9e-3; }
{ dSph 10e-3; }
{ dSph 11e-3; }
{ dSph 12e-3; }
);
}
residualAlpha 1e-6;
}
Previously a fraction field was constructed automatically using the
boundary condition types from the sum-of-fs field, and the value of both
the internal and boundary field was then overridden by the value setting
provided for the size-group. This procedure doesn't generalise to
boundary conditions other than basic types that store no additional
data, like zeroGradient and fixedValue. More complex boundary conditions
such as inletOutlet and uniformFixedValue are incompatible with this
approach.
This is arguably less convenient than the previous specification, where
the sizes and fractions appeared together in a table-like list in the
sizeGroups entry. In the event that a substantial proportion of the
size-groups have a non-zero initial fraction, writing out all the field
files manually is extremely tedious. To mitigate this somewhat, a
packaged function has been added to initialise the fields given a file
containing a size distribution (see the pipeBend tutorial for an example
of its usage). This function has the same limitations as the previous
code in that it requires all boundary conditions to be default
constructable.
Ultimately, the "correct" fix for the issue of how to set the boundary
conditions conveniently is to create customised inlet-outlet boundary
conditions that determine their field's position within the population
balance and evaluate a distribution to determine the appropriate inlet
value. This work is pending funding.
The old fluid-specific rhoThermo has been split into a non-fluid
specific part which is still called rhoThermo, and a fluid-specific part
called rhoFluidThermo. The rhoThermo interface has been added to the
solidThermo model. This permits models and solvers that access the
density to operate on both solid and fluid thermophysical models.
// List of vectors example
listU ((1.1 2.1 1.1) (2.1 3.2 4.1) (4.3 5.3 0));
magU1 #calc "mag($<List<vector>>listU[1])";
// Field of vectors and scalars example
magUs #calc "mag($<Field<vector>>listU)";
magSqrU1 #calc "sqr($<Field<scalar>>magUs[1])";
If the code string is delimited by '#{...#}' multiple lines and multiple code
statements can be used to generate the entry using 'os << ...;'. This is
equivalent to #codeStream but with a more compact syntax, e.g.
maxAngle 30;
nAngles 7;
Us #calc
const vector U($<vector>testCalc2!U);
const int nAngles = $nAngles;
const scalar angleStep = ($<scalar>maxAngle)/(nAngles - 1);
List<vector> Us(nAngles);
for(int i=0; i<nAngles; i++)
{
const scalar angle = degToRad(i*angleStep);
Us[i] = transform(Ry(angle), U);
}
os << Us;
Note the 'os << Us;' statement which writes the data to the dictionary entry in
the same manner as #codeStream, this provides flexibility on how the data is
created and written.
This allows #FOAM_CASE for example to be used in #calc variable lookup, e.g. in
test/dictionary/testCalc:
// assuming the testCalc2 file is local
magU #calc "mag($<vector>testCalc2!U)";
// finding the testCalc2 file using $FOAM_CASE
k #calc "1.5*magSqr(0.05*$<vector>{${FOAM_CASE}/testCalc2!U})";
These additions mean that the volume-weighted average or volume integral
of a field can be conveniently post-processed. This can be done
interactively using foamPostProcess:
foamPostProcess -func "volAverage(U)"
foamPostProcess -func "volIntegrate(rho)"
Or at run-time by adding to the functions sub-section of the
controlDict:
#includeFunc volAverage(U)
#includeFunc volIntegrate(rho)
If a negative mass flow rate is specified, the mass source fvModel will
now remove mass by adding implicit sources to the transport equations.
Properties are thereby removed at their current value. This is stable,
and is analogous to a zero-gradient outlet boundary condition.
The keyword 'select' is now used to specify the cell, face or point set
selection method consistently across all classes requiring this functionality.
'select' replaces the inconsistently named 'regionType' and 'selectionMode'
keywords used previously but backwards-compatibility is provided for user
convenience. All configuration files and tutorials have been updated.
Examples of 'select' from the tutorial cases:
functionObjects:
cellZoneAverage
{
type volFieldValue;
libs ("libfieldFunctionObjects.so");
writeControl writeTime;
writeInterval 1;
fields (p);
select cellZone;
cellZone injection;
operation volAverage;
writeFields false;
}
#includeFunc populationBalanceSizeDistribution
(
name=numberDensity,
populationBalance=aggregates,
select=cellZone,
cellZone=outlet,
functionType=numberDensity,
coordinateType=projectedAreaDiameter,
allCoordinates=yes,
normalise=yes,
logTransform=yes
)
fvModel:
cylinderHeat
{
type heatSource;
select all;
q 5e7;
}
fvConstraint:
momentumForce
{
type meanVelocityForce;
select all;
Ubar (0.1335 0 0);
}
This is a more intuitive keyword than "funcName" or "entryName". A
function object's name and corresponding output directory can now be
renamed as follows:
#includeFunc patchAverage
(
name=cylinderT, // <-- was funcName=... or entryName=...
region=fluid,
patch=fluid_to_solid,
field=T
)
Some packaged functions previously relied on a "name" argument that
related to an aspect of the function; e.g., the name of the faceZone
used by the faceZoneFlowRate function. These have been disambiguated.
This has also made them consistent with the preferred input syntax of
the underlying function objects.
Examples of the changed #includeFunc entries are shown below:
#includeFunc faceZoneAverage
(
faceZone=f0, // <-- was name=f0
U
)
#includeFunc faceZoneFlowRate
(
faceZone=f0 // <-- was name=f0
)
#includeFunc populationBalanceSizeDistribution
(
populationBalance=bubbles,
regionType=cellZone,
cellZone=injection, // <-- was name=injection
functionType=volumeDensity,
coordinateType=diameter,
normalise=yes
)
#includeFunc triSurfaceAverage
(
triSurface=mid.obj, // <-- was name=mid.obj
p
)
#includeFunc triSurfaceVolumetricFlowRate
(
triSurface=mid.obj // <-- was name=mid.obj
)
#includeFunc uniform
(
fieldType=volScalarField,
fieldName=alpha, // <-- was name=alpha
dimensions=[0 0 0 0 0 0 0],
value=0.2
)
so that the same option with a rational name is also available for #includeModel
and #includeConstraint. Support for funcName is maintained for
backwards-compatibility.
The timeName() function simply returns the dimensionedScalar::name() which holds
the user-time name of the current time and now that timeName() is no longer
virtual the dimensionedScalar::name() can be called directly. The timeName()
function implementation is maintained for backward-compatibility.
The multiphaseEuler module now uses saturation models from the
centralised thermophysical properties library.
The control of these models is slightly different than for the previous
multiphaseEuler-specific saturation models. Where previously a
"saturationPressure" or "saturationTemperature" sub-dictionary was
employed, now "pSat" and "Tsat" entries are used which can be specified
flexibly in a similar manner to function1-s. See the previous commit for
details.
executed with foamRun for single region simulations of foamMultiRun for
multi-region simulations. Replaces multiphaseEulerFoam and all the
corresponding tutorials have been updated and moved to
tutorials/modules/multiphaseEuler.
Class
Foam::solvers::multiphaseEuler
Description
Solver module for a system of any number of compressible fluid phases with a
common pressure, but otherwise separate properties. The type of phase model
is run time selectable and can optionally represent multiple species and
in-phase reactions. The phase system is also run time selectable and can
optionally represent different types of momentum, heat and mass transfer.
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Optional fvModels and fvConstraints are provided to enhance the simulation
in many ways including adding various sources, Lagrangian
particles, surface film etc. and constraining or limiting the solution.
SourceFiles
multiphaseEuler.C
See also
Foam::solvers::compressibleVoF
Foam::solvers::fluidSolver
Foam::solvers::incompressibleFluid
The thermodynamic density field is now named "rho" by default and only renamed
"thermo:rho" by solvers that create and maintain a separate continuity density
field which is named "rho". This change significantly simplifies and
standardises the specification of schemes and boundary conditions requiring
density as it is now always named "rho" or "rho.<phase>" unless under some very
unusual circumstances the thermodynamic rather than continuity density is
required for a solver maintaining both.
The advantage of this change is particularly noticeable for multiphase
simulations in which each phase has its own density now named "rho.<phase>"
rather than "thermo:rho.<phase>" as separate phase continuity density fields are
not required so for multiphaseEulerFoam the scheme specification:
"div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1;
is now written:
"div\(alphaRhoPhi.*,\(p\|rho.*\)\)" Gauss limitedLinear 1;
This is a packaged function object that conveniently computes averages
of fields on tri-surfaces. It can be executed on the command line as
follows:
foamPostProcess -func "triSurfaceAverage(name=mid.obj, p)"
This will compute the average of the field "p" on a surface file in
"constant/geometry/mid.obj".
The calculation could also be done at run-time by adding the following
entry to the functions section of the system/controlDict
#includeFunc triSurfaceAverage(name=mid.obj, p)
in which different solver modules can be selected in each region to for complex
conjugate heat-transfer and other combined physics problems such as FSI
(fluid-structure interaction).
For single-region simulations the solver module is selected, instantiated and
executed in the PIMPLE loop in the new foamRun application.
For multi-region simulations the set of solver modules, one for each region, are
selected, instantiated and executed in the multi-region PIMPLE loop of new the
foamMultiRun application.
This provides a very general, flexible and extensible framework for complex
coupled problems by creating more solver modules, either by converting existing
solver applications or creating new ones.
The current set of solver modules provided are:
isothermalFluid
Solver module for steady or transient turbulent flow of compressible
isothermal fluids with optional mesh motion and mesh topology changes.
Created from the rhoSimpleFoam, rhoPimpleFoam and buoyantFoam solvers but
without the energy equation, hence isothermal. The buoyant pressure
formulation corresponding to the buoyantFoam solver is selected
automatically by the presence of the p_rgh pressure field in the start-time
directory.
fluid
Solver module for steady or transient turbulent flow of compressible fluids
with heat-transfer for HVAC and similar applications, with optional
mesh motion and mesh topology changes.
Derived from the isothermalFluid solver module with the addition of the
energy equation from the rhoSimpleFoam, rhoPimpleFoam and buoyantFoam
solvers, thus providing the equivalent functionality of these three solvers.
multicomponentFluid
Solver module for steady or transient turbulent flow of compressible
reacting fluids with optional mesh motion and mesh topology changes.
Derived from the isothermalFluid solver module with the addition of
multicomponent thermophysical properties energy and specie mass-fraction
equations from the reactingFoam solver, thus providing the equivalent
functionality in reactingFoam and buoyantReactingFoam. Chemical reactions
and/or combustion modelling may be optionally selected to simulate reacting
systems including fires, explosions etc.
solid
Solver module for turbulent flow of compressible fluids for conjugate heat
transfer, HVAC and similar applications, with optional mesh motion and mesh
topology changes.
The solid solver module may be selected in solid regions of a CHT case, with
either the fluid or multicomponentFluid solver module in the fluid regions
and executed with foamMultiRun to provide functionality equivalent
chtMultiRegionFoam but in a flexible and extensible framework for future
extension to more complex coupled problems.
All the usual fvModels, fvConstraints, functionObjects etc. are available with
these solver modules to support simulations including body-forces, local sources,
Lagrangian clouds, liquid films etc. etc.
Converting compressibleInterFoam and multiphaseEulerFoam into solver modules
would provide a significant enhancement to the CHT capability and incompressible
solvers like pimpleFoam run in conjunction with solidDisplacementFoam in
foamMultiRun would be useful for a range of FSI problems. Many other
combinations of existing solvers converted into solver modules could prove
useful for a very wide range of complex combined physics simulations.
All tutorials from the rhoSimpleFoam, rhoPimpleFoam, buoyantFoam, reactingFoam,
buoyantReactingFoam and chtMultiRegionFoam solver applications replaced by
solver modules have been updated and moved into the tutorials/modules directory:
modules
├── CHT
│ ├── coolingCylinder2D
│ ├── coolingSphere
│ ├── heatedDuct
│ ├── heatExchanger
│ ├── reverseBurner
│ └── shellAndTubeHeatExchanger
├── fluid
│ ├── aerofoilNACA0012
│ ├── aerofoilNACA0012Steady
│ ├── angledDuct
│ ├── angledDuctExplicitFixedCoeff
│ ├── angledDuctLTS
│ ├── annularThermalMixer
│ ├── BernardCells
│ ├── blockedChannel
│ ├── buoyantCavity
│ ├── cavity
│ ├── circuitBoardCooling
│ ├── decompressionTank
│ ├── externalCoupledCavity
│ ├── forwardStep
│ ├── helmholtzResonance
│ ├── hotRadiationRoom
│ ├── hotRadiationRoomFvDOM
│ ├── hotRoom
│ ├── hotRoomBoussinesq
│ ├── hotRoomBoussinesqSteady
│ ├── hotRoomComfort
│ ├── iglooWithFridges
│ ├── mixerVessel2DMRF
│ ├── nacaAirfoil
│ ├── pitzDaily
│ ├── prism
│ ├── shockTube
│ ├── squareBend
│ ├── squareBendLiq
│ └── squareBendLiqSteady
└── multicomponentFluid
├── aachenBomb
├── counterFlowFlame2D
├── counterFlowFlame2D_GRI
├── counterFlowFlame2D_GRI_TDAC
├── counterFlowFlame2DLTS
├── counterFlowFlame2DLTS_GRI_TDAC
├── cylinder
├── DLR_A_LTS
├── filter
├── hotBoxes
├── membrane
├── parcelInBox
├── rivuletPanel
├── SandiaD_LTS
├── simplifiedSiwek
├── smallPoolFire2D
├── smallPoolFire3D
├── splashPanel
├── verticalChannel
├── verticalChannelLTS
└── verticalChannelSteady
Also redirection scripts are provided for the replaced solvers which call
foamRun -solver <solver module name> or foamMultiRun in the case of
chtMultiRegionFoam for backward-compatibility.
Documentation for foamRun and foamMultiRun:
Application
foamRun
Description
Loads and executes an OpenFOAM solver module either specified by the
optional \c solver entry in the \c controlDict or as a command-line
argument.
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Usage
\b foamRun [OPTION]
- \par -solver <name>
Solver name
- \par -libs '(\"lib1.so\" ... \"libN.so\")'
Specify the additional libraries loaded
Example usage:
- To run a \c rhoPimpleFoam case by specifying the solver on the
command line:
\verbatim
foamRun -solver fluid
\endverbatim
- To update and run a \c rhoPimpleFoam case add the following entries to
the controlDict:
\verbatim
application foamRun;
solver fluid;
\endverbatim
then execute \c foamRun
Application
foamMultiRun
Description
Loads and executes an OpenFOAM solver modules for each region of a
multiregion simulation e.g. for conjugate heat transfer.
The region solvers are specified in the \c regionSolvers dictionary entry in
\c controlDict, containing a list of pairs of region and solver names,
e.g. for a two region case with one fluid region named
liquid and one solid region named tubeWall:
\verbatim
regionSolvers
{
liquid fluid;
tubeWall solid;
}
\endverbatim
The \c regionSolvers entry is a dictionary to support name substitutions to
simplify the specification of a single solver type for a set of
regions, e.g.
\verbatim
fluidSolver fluid;
solidSolver solid;
regionSolvers
{
tube1 $fluidSolver;
tubeWall1 solid;
tube2 $fluidSolver;
tubeWall2 solid;
tube3 $fluidSolver;
tubeWall3 solid;
}
\endverbatim
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Usage
\b foamMultiRun [OPTION]
- \par -libs '(\"lib1.so\" ... \"libN.so\")'
Specify the additional libraries loaded
Example usage:
- To update and run a \c chtMultiRegion case add the following entries to
the controlDict:
\verbatim
application foamMultiRun;
regionSolvers
{
fluid fluid;
solid solid;
}
\endverbatim
then execute \c foamMultiRun
Full backward-compatibility is provided which support for both multiComponentMixture and
multiComponentPhaseModel provided but all tutorials have been updated.
The reconstructPar utility now reconstructs the mesh if and when it is
necessary to do so. The reconstructParMesh utility is therefore no
longer necessary and has been removed.
It was necessary/advantagous to consolidate these utilities into one
because in the case of mesh changes it becomes increasingly less clear
which of the separate utilities is responsible for reconstructing data
that is neither clearly physical field nor mesh topology; e.g., moving
points, sets, refinement data, and so on.
The population balance model considers dilatation originating from density
change and mass transfer via source terms describing nucleation as well as
"drift" of the size distribution to smaller or larger sizes. Numerically, the
treatment does not necessarily equal the total dilatation, hence a correction is
introduced to ensure boundedness of the size group fractions.
Patch contributed by Institute of Fluid Dynamics,
Helmholtz-Zentrum Dresden - Rossendorf (HZDR)
and VTT Technical Research Centre of Finland Ltd.
This is a simple function that provides a convenient way for a user to
call fvc::reconstruct for the purposes of post-processing flux fields;
e.g., to construct a cell velocity from a face flux.
It can be used to generate output during a run by adding the following
settings to a case's controlDict:
functions
{
#includeFunc reconstruct(phi)
}
Or it can be executed as a postProcessing step by calling:
postProcess -func "reconstruct(phi)"
The defaultPatch type currently defaults to empty which is appropriate for 1D
and 2D cases but not when creating the initial blockMesh for snappyHexMesh as
the presence of empty patches triggers the inappropriate application of 2D point
constraint corrections following snapping and morphing. To avoid this hidden
problem a warning is now generated from blockMesh when the defaultPatch is not
explicitly set for cases which generate a default patch, i.e. for which the
boundary is not entirely defined. e.g.
.
.
.
Creating block mesh topology
--> FOAM FATAL IO ERROR:
The 'defaultPatch' type must be specified for the 'defaultFaces' patch, e.g. for snappyHexMesh
defaultPatch
{
name default; // optional
type patch;
}
or for 2D meshes
defaultPatch
{
name frontAndBack; // optional
type empty;
}
.
.
.
All the tutorials have been update to include the defaultPatch specification as
appropriate.
Solver for steady or transient buoyant, turbulent flow of compressible fluids
for ventilation and heat-transfer, with optional mesh motion and mesh topology
changes. Created by merging buoyantSimpleFoam and buoyantPimpleFoam to provide
a more general solver and simplify maintenance.
Updated tutorials for the changes to the blending system. Cases using
"none" blending have been updated to use "continuous" or "segregated" as
appropriate.
The bed tutorial has been extended to include a proper switch to a bed
drag model (AttouFerschneider) when the solid phase displaces the
fluids. This change made the trickleBed case a subset of the bed case,
so the trickleBed has been removed.
These changes are not required for the cases to run with the new
phaseInterface system. The syntax prior to this commit will be read in
the new phaseInterface system's backwards compatibility mode.
This model will generate an error if the diameter is requested. This
will happen if another sub model is included that depends on the
diameter of the continuous phase. It therefore provides a check that the
sub-modelling combination is valid.
Patch contributed by Institute of Fluid Dynamics,
Helmholtz-Zentrum Dresden - Rossendorf (HZDR)
Following the addition of the new moments functionObject, all related
functionality was removed from sizeDistribution.
In its revised version, sizeDistribution allows for different kinds of
weighted region averaging in case of field-dependent representative
particle properties.
A packaged function has also been added to allow for command line solver
post-processing.
For example, the following function object specification returns the
volume-based number density function:
numberDensity
{
type sizeDistribution;
libs ("libmultiphaseEulerFoamFunctionObjects.so");
writeControl writeTime;
populationBalance bubbles;
functionType numberDensity;
coordinateType volume;
setFormat raw;
}
The same can be achieved using a packaged function:
#includeFunc sizeDistribution
(
populationBalance=bubbles,
functionType=numberDensity,
coordinateType=volume,
funcName=numberDensity
)
Or on the command line:
multiphaseEulerFoam -postProcess -func "
sizeDistribution
(
populationBalance=bubbles,
functionType=numberDensity,
coordinateType=volume,
funcName=numberDensity
)"
Patch contributed by Institute of Fluid Dynamics,
Helmholtz-Zentrum Dresden - Rossendorf (HZDR)
This function calculates integral (integer moments) or mean properties
(mean, variance, standard deviation) of a size distribution computed with
multiphaseEulerFoam. It has to be run with multiphaseEulerFoam, either
at run-time or with -postProcess. It will not work with the postProcess
utility.
The following function object specification for example returns the first
moment of the volume-based number density function which is equivalent to
the phase fraction of the particulate phase:
moments
{
type moments;
libs ("libmultiphaseEulerFoamFunctionObjects.so");
executeControl timeStep;
writeControl writeTime;
populationBalance bubbles;
momentType integerMoment;
coordinateType volume;
order 1;
}
The same can be achieved using a packaged function:
#includeFunc moments
(
populationBalance=bubbles,
momentType=integerMoment,
coordinateType=volume,
order=1,
funcName=moments
)
Or on the command line:
multiphaseEulerFoam -postProcess -func "
moments
(
populationBalance=bubbles,
momentType=integerMoment,
coordinateType=volume,
order=1,
funcName=moments
)"
Patch contributed by Institute of Fluid Dynamics,
Helmholtz-Zentrum Dresden - Rossendorf (HZDR)