Various minor changes to tutorial scripts. In particular, ensuring that
they all change to the containing directory so that batches of tutorials
can be run easily from the root of the installation.
The majority of input parameters now support automatic unit conversion.
Units are specified within square brackets, either before or after the
value. Primitive parameters (e.g., scalars, vectors, tensors, ...),
dimensioned types, fields, Function1-s and Function2-s all support unit
conversion in this way.
Unit conversion occurs on input only. OpenFOAM writes out all fields and
parameters in standard units. It is recommended to use '.orig' files in
the 0 directory to preserve user-readable input if those files are being
modified by pre-processing applications (e.g., setFields).
For example, to specify a volumetric flow rate inlet boundary in litres
per second [l/s], rather than metres-cubed per second [m^3/s], in 0/U:
boundaryField
{
inlet
{
type flowRateInletVelocity;
volumetricFlowRate 0.1 [l/s];
value $internalField;
}
...
}
Or, to specify the pressure field in bar, in 0/p:
internalField uniform 1 [bar];
Or, to convert the parameters of an Arrhenius reaction rate from a
cm-mol-kcal unit system, in constant/chemistryProperties:
reactions
{
methaneReaction
{
type irreversibleArrhenius;
reaction "CH4^0.2 + 2O2^1.3 = CO2 + 2H2O";
A 6.7e12 [(mol/cm^3)^-0.5/s];
beta 0;
Ea 48.4 [kcal/mol];
}
}
Or, to define a time-varying outlet pressure using a CSV file in which
the pressure column is in mega-pascals [MPa], in 0/p:
boundaryField
{
outlet
{
type uniformFixedValue;
value
{
type table;
format csv;
nHeaderLine 1;
units ([s] [MPa]); // <-- new units entry
columns (0 1);
mergeSeparators no;
file "data/pressure.csv";
outOfBounds clamp;
interpolationScheme linear;
}
}
...
}
(Note also that a new 'columns' entry replaces the old 'refColumn' and
'componentColumns'. This is is considered to be more intuitive, and has
a consistent syntax with the new 'units' entry. 'columns' and
'componentColumns' have been retained for backwards compatibility and
will continue to work for the time being.)
Unit definitions can be added in the global or case controlDict files.
See UnitConversions in $WM_PROJECT_DIR/etc/controlDict for examples.
Currently available units include:
Standard: kg m s K kmol A Cd
Derived: Hz N Pa J W g um mm cm km l ml us ms min hr mol
rpm bar atm kPa MPa cal kcal cSt cP % rad rot deg
A user-time unit is also provided if user-time is in operation. This
allows it to be specified locally whether a parameter relates to
real-time or to user-time. For example, to define a mass source that
ramps up from a given engine-time (in crank-angle-degrees [CAD]) over a
duration in real-time, in constant/fvModels:
massSource1
{
type massSource;
points ((1 2 3));
massFlowRate
{
type scale;
scale linearRamp;
start 20 [CAD];
duration 50 [ms];
value 0.1 [g/s];
}
}
Specified units will be checked against the parameter's dimensions where
possible, and an error generated if they are not consistent. For the
dimensions to be available for this check, the code requires
modification, and work propagating this change across OpenFOAM is
ongoing. Unit conversions are still possible without these changes, but
the validity of such conversions will not be checked.
Units are no longer permitted in 'dimensions' entries in field files.
These 'dimensions' entries can now, instead, take the names of
dimensions. The names of the available dimensions are:
Standard: mass length time temperature
moles current luminousIntensity
Derived: area volume rate velocity momentum acceleration density
force energy power pressure kinematicPressure
compressibility gasConstant specificHeatCapacity
kinematicViscosity dynamicViscosity thermalConductivity
volumetricFlux massFlux
So, for example, a 0/epsilon file might specify the dimensions as
follows:
dimensions [energy/mass/time];
And a 0/alphat file might have:
dimensions [thermalConductivity/specificHeatCapacity];
*** Development Notes ***
A unit conversion can construct trivially from a dimension set,
resulting in a "standard" unit with a conversion factor of one. This
means the functions which perform unit conversion on read can be
provided dimension sets or unit conversion objects interchangeably.
A basic `dict.lookup<vector>("Umean")` call will do unit conversion, but
it does not know the parameter's dimensions, so it cannot check the
validity of the supplied units. A corresponding lookup function has been
added in which the dimensions or units can be provided; in this case the
corresponding call would be `dict.lookup<vector>("Umean", dimVelocity)`.
This function enables additional checking and should be used wherever
possible.
Function1-s and Function2-s have had their constructors and selectors
changed so that dimensions/units must be specified by calling code. In
the case of Function1, two unit arguments must be given; one for the
x-axis and one for the value-axis. For Function2-s, three must be
provided.
In some cases, it is desirable (or at least established practice), that
a given non-standard unit be used in the absence of specific
user-defined units. Commonly this includes reading angles in degrees
(rather than radians) and reading times in user-time (rather than
real-time). The primitive lookup functions and Function1 and Function2
selectors both support specifying a non-standard default unit. For
example, `theta_ = dict.lookup<scalar>("theta", unitDegrees)` will read
an angle in degrees by default. If this is done within a model which
also supports writing then the write call must be modified accordingly
so that the data is also written out in degrees. Overloads of writeEntry
have been created for this purpose. In this case, the angle theta should
be written out with `writeEntry(os, "theta", unitDegrees, theta_)`.
Function1-s and Function2-s behave similarly, but with greater numbers
of dimensions/units arguments as before.
The non-standard user-time unit can be accessed by a `userUnits()`
method that has been added to Time. Use of this user-time unit in the
construction of Function1-s should prevent the need for explicit
user-time conversion in boundary conditions and sub-models and similar.
Some models might contain non-typed stream-based lookups of the form
`dict.lookup("p0") >> p0_` (e.g., in a re-read method), or
`Umean_(dict.lookup("Umean"))` (e.g., in an initialiser list). These
calls cannot facilitate unit conversion and are therefore discouraged.
They should be replaced with
`p0_ = dict.lookup<scalar>("p0", dimPressure)` and
`Umean_(dict.lookup<vector>("Umean", dimVelocity))` and similar whenever
they are found.
The 'featureAngle' control defines the included angle between faces
above which layer extrusion is prevented. Its use within snappyHexMesh
was incorrect in that the cosine was not being taken before being
compared to dot products of face normals. This has now been corrected.
Existing 'featureAngle' settings may need changing to recover equivalent
behaviour. Any angle previously set to 58 degrees or above previously
resulted in no reduction of layer coverage. A large angle between 90 and
180 degrees is likely to be an appropriate replacement for cases such as
this. Angles previously set to 57 degrees and below can be equivalently
replaced by a value of (180/pi)*arccos(<angle>*(pi/180)).
Note that changing the feature angle also affects the slip feature
angle. The slip feature angle is taken to be half the feature angle if a
'slipFeatureAngle' is not specified.
This boundary condition provides a cyclic condition for p_rgh. It applies
corrections to the value and gradient on both sides of the cyclic to
account for the non-cylicity of the gravitational force.
This condition is only needed when the cyclic patches have a transformation
and a normal component in the direction of gravity. If the cyclic patches
are orthogonal to the direction gravity, then a normal cyclic boundary
condition can be used instead.
Care must be taken when using this boundary condition that the simulation
is actually cyclic. The following constraints apply:
- Both cyclic patches must be oriented in the same way with respect to
gravity. In practice this means that applicability is limited to cyclics
with translational transformations.
- The model cannot have any dependence on the absolute value of the
pressure field. The absolute value of the pressure, in reality, varies
between each repetition of the geometry; it is not actually formally
cyclic. Only the gradient of the pressure field can be truly cyclic. This
model is therefore only valid if the absolute value of the pressure is
arbitrary, and only the gradient has an effect on the solution. This is
the case for incompressible multiphase solutions or incompressible
Boussinesq-like models of density variation. It is not true if (for
example) a compressible thermodynamic model is being used.
Specification is as follows. A "patchType" entry must be provided to
indicate that this condition overrides the underlying cyclic constraint,
and a "rhoInf" entry is needed (by the owner patch only) to specify the
density of the far-field environment. For example:
cyclicA
{
type prghCyclicPressure;
patchType cyclic;
rhoInf 1; // [kg/m^3]
}
cyclicB
{
type prghCyclicPressure;
patchType cyclic;
}
A tutorial, incompressibleVoF/trayedPipe, has been added to demonstrate
usage of this boundary condition.
to calculate and write the forces and moments on moving rigid bodies with
specified or calculated centre of rotation using Foam::RBD::rigidBodyMotion
respectively. The current moving centre of rotation is used in the evaluation
of the moments but does not affect the evaluation of the forces.
Class
Foam::functionObjects::movingForces
Description
Calculates the forces and moments by integrating the pressure and
skin-friction forces over a given list of patches of a moving object.
The centre of rotation (CofR) of the moving object is specified as a
Foam::Function1<vector> of time.
Member function movingForces::write() calculates the forces/moments and
writes the forces/moments into the file \<timeDir\>/movingForces.dat and bin
data (if selected) to the file \<timeDir\>/movingForces_bin.dat
Example of function object specification:
\verbatim
movingForces1
{
type movingForces;
libs ("libforces.so");
log yes;
patches (walls);
CofR
{
type sine;
amplitude (0 0.025 0);
frequency 1;
start 0;
level (0 0 0);
}
}
\endverbatim
Usage
\table
Property | Description | Required | Default value
type | Type name: movingForces | yes |
log | Write force data to standard output | no | no
patches | Patches included in the forces calculation | yes |
p | Pressure field name | no | p
U | Velocity field name | no | U
rho | Density field name (see below) | no | rho
phase | Phase name for phase-fraction | no |
CofR | Centre of rotation Foam::Function1<vector> | yes |
directForceDensity | Force density supplied directly (see below)|no|no
fD | Name of force density field (see below) | no | fD
\endtable
Bin data is optional, but if the dictionary is present, the entries must
be defined according o
\table
nBin | number of data bins | yes |
direction | direction along which bins are defined | yes |
cumulative | bin data accumulated with increasing distance | yes |
\endtable
Note
- For incompressible cases, set \c rho to \c rhoInf and provide
a \c rhoInf value corresponding to the free-stream constant density.
- If the \c phase name is specified the corresponding phase-fraction field
\c alpha.<phase> is used to filter the surface force field
before integration.
- If the force density is supplied directly, set the \c directForceDensity
flag to 'yes', and supply the force density field using the \c
fDName entry
See also
Foam::functionObject
Foam::functionObjects::forcesBase
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::logFiles
Foam::functionObjects::timeControl
Foam::Function1
SourceFiles
movingForces.C
Class
Foam::functionObjects::rigidBodyForces
Description
Calculates the forces and moments by integrating the pressure and
skin-friction forces over a given list of patches of a moving rigid body.
The centre of rotation (CofR) of the moving rigid object is obtained
directly from the corresponding Foam::RBD::rigidBodyMotion of the
specified body.
Member function rigidBodyForces::write() calculates the forces/moments and
writes the forces/moments into the file \<timeDir\>/rigidBodyForces.dat
and bin data (if selected) to the file \<timeDir\>/rigidBodyForces_bin.dat
Example of function object specification:
\verbatim
rigidBodyForces1
{
type rigidBodyForces;
libs ("librigidBodyForces.so");
body (hull);
patches (walls);
log yes;
}
\endverbatim
Usage
\table
Property | Description | Required | Default value
type | Type name: rigidBodyForces | yes |
log | Write force data to standard output | no | no
body | Name of the rigid body | yes |
patches | Patches included in the forces calculation | yes |
p | Pressure field name | no | p
U | Velocity field name | no | U
rho | Density field name (see below) | no | rho
phase | Phase name for phase-fraction | no |
directForceDensity | Force density supplied directly (see below)|no|no
fD | Name of force density field (see below) | no | fD
\endtable
Bin data is optional, but if the dictionary is present, the entries must
be defined according o
\table
nBin | number of data bins | yes |
direction | direction along which bins are defined | yes |
cumulative | bin data accumulated with increasing distance | yes |
\endtable
Note
- For incompressible cases, set \c rho to \c rhoInf and provide
a \c rhoInf value corresponding to the free-stream constant density.
- If the \c phase name is specified the corresponding phase-fraction field
\c alpha.<phase> is used to filter the surface force field
before integration.
- If the force density is supplied directly, set the \c directForceDensity
flag to 'yes', and supply the force density field using the \c
fDName entry
See also
Foam::functionObject
Foam::functionObjects::forcesBase
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::logFiles
Foam::functionObjects::timeControl
Foam::RBD::rigidBodyMotion
SourceFiles
rigidBodyForces.C
This function now looks up an alphaPhi field by default and exits with
an error if the field cannot be found. In order to solve for alphaPhi a
new 'solveAlphaPhi' switch has to be set.
The documentation has been updated to reflect the fact that the VoF
solvers now store all the alphaPhi fluxes necessary for a in-phase
equation to be constructed.
The phaseScalarTransport function has been added to the damBreakLaminar
tutorial.
This lets calling code determine the difference between a polyMesh
topology change and a re-stitch. This prevents unnecessary
post-processing output in a few cases when using NCC; most notably the
generation of cellProc fields by reconstructPar.
A number of fixes have been made in order to make non-conformal cyclic
patches compatible with run-time distribution.
A tutorial case, incompressibleVoF/rotatingCube, has been added which
demonstrates simultaneous usage of motion, non-conformal couplings,
adaptive refinement and load-balancing.
The fact that these names create sources in their associated transport
equations is clear in context, so the name does not need to contain
'Source'.
Having 'Source' in the name is a historic convention that dates back to
when fvModels and fvConstraints were combined in a single fvOptions
interface. In this interface, disambiguation between sources and
constraints was necessary.
The full set of name changes is as follows:
accelerationSource -> acceleration
actuationDiskSource -> actuationDisk
effectivenessHeatExchangerSource -> effectivenessHeatExchanger
explicitPorositySource -> porosityForce
radialActuationDiskSource -> radialActuationDisk
rotorDiskSource -> rotorDisk
sixDoFAccelerationSource -> sixDoFAcceleration
solidEquilibriumEnergySource -> solidThermalEquilibrium
solidificationMeltingSource -> solidificationMelting
volumeFractionSource -> volumeBlockage
interRegionExplicitPorositySource -> interRegionPorosityForce
VoFSolidificationMeltingSource -> VoFSolidificationMelting
The old names are still available for backwards compatibility.
When an fvModel source introduces fluid into a simulation it should also
create a corresponding source term for all properties transported into
the domain by that injection. The source is, effectively, an alternative
form of inlet boundary, on which all transported properties need an
inlet value specified.
These values are now specified in the property field files. The
following is an example of a 0/U file in which the velocity of fluid
introduced by a fvModel source called "injection1" is set to a fixed
value of (-1 0 0):
dimensions [0 1 -1 0 0 0 0];
internalField uniform (0 0 0);
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
wall
{
type noSlip;
}
atmosphere
{
type pressureInletOutletVelocity;
value $internalField;
}
}
// *** NEW ***
sources
{
injection1
{
type uniformFixedValue;
uniformValue (-1 0 0);
}
}
And the following entry in the 0/k file specifies the turbulent kinetic
energy introduced as a fraction of the mean flow kinetic energy:
sources
{
injection1
{
type turbulentIntensityKineticEnergy;
intensity 0.05;
}
}
The specification is directly analogous to boundary conditions. The
conditions are run-time selectable and can be concisely implemented.
They can access each other and be inter-dependent (e.g., the above,
where turbulent kinetic energy depends on velocity). The syntax keeps
field data localised and makes the source model (e.g., massSource,
volumeSource, ...) specification independent from what other models and
fields are present in the simulation. The 'fieldValues' entry previously
required by source models is now no longer required.
If source values need specifying and no source condition has been
supplied in the relevant field file then an error will be generated.
This error is similar to that generated for missing boundary conditions.
This replaces the behaviour where sources such as these would introduce
a value of zero, either silently or with a warning. This is now
considered unacceptable. Zero might be a tolerable default for certain
fields (U, k), but is wholly inappropriate for others (T, epsilon, rho).
This change additionally makes it possible to inject fluid into a
multicomponent solver with a specified temperature. Previously, it was
not possible to do this as there was no means of evaluating the energy
of fluid with the injected composition.
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.
Description
This fvModel applies forcing to the liquid phase-fraction field and all
components of the vector field to relax the fields towards those
calculated from the current wave distribution.
The force coefficient \f$\lambda\f$ should be set based on the desired level
of forcing and the residence time the waves through the forcing zone. For
example, if waves moving at 2 [m/s] are travelling through a forcing zone 8
[m] in length, then the residence time is 4 [s]. If it is deemed necessary
to force for 5 time-scales, then \f$\lambda\f$ should be set to equal 5/(4
[s]) = 1.2 [1/s]. If more aggressive forcing is required adjacent to the
boundaries, which is often the case if wave boundary conditions are
specified at outflow boundaries, the optional \f$\lambdaBoundary\f$
coefficient can be specified higher than the value of \f$\lambda\f$.
Alternatively the forcing force coefficient \f$\lambdaCoeff\f$ can be
specified in which case \f$\lambda\f$ is evaluated by multiplying the
maximum wave speed by \f$\lambdaCoeff\f$ and dividing by the forcing region
length. \f$\lambdaBoundary\f$ is similarly evaluated from
\f$\lambdaBoundaryCoeff\f$ if specified.
Usage
Example usage:
\verbatim
waveForcing1
{
type waveForcing;
libs ("libwaves.so");
liquidPhase water;
// Define the line along which to apply the graduation
origin (600 0 0);
direction (-1 0 0);
// // Or, define multiple lines
// origins ((600 0 0) (600 -300 0) (600 300 0));
// directions ((-1 0 0) (0 1 0) (0 -1 0));
scale
{
type halfCosineRamp;
start 0;
duration 300;
}
lambdaCoeff 2; // Forcing coefficient
// lambdaBoundaryCoeff 10; // Optional boundary forcing coefficient
// Useful when wave BCs are specified at outlets
// Write the forcing fields: forcing:scale, forcing:forceCoeff
writeForceFields true;
}
\endverbatim
e.g.
waveForcing1
{
type waveForcing;
libs ("libwaves.so");
liquidPhase water;
// Define the line along which to apply the graduation
origin (600 0 0);
direction (-1 0 0);
// // Or, define multiple lines
// origins ((600 0 0) (600 -300 0) (600 300 0));
// directions ((-1 0 0) (0 1 0) (0 -1 0));
scale
{
type halfCosineRamp;
start 0;
duration 300;
}
lambda 0.5; // Forcing coefficient
// lambdaBoundary 2; // Optional boundary forcing coefficient
// Useful when wave BCs are specified
// without mean flow
// Write the forcing fields: forcing:scale, forcing:forceCoeff
writeForceFields true;
}
will write the fields forcing:scale and forcing:forceCoeff at the start of the
run to visualise and check correctness.
Simplifications have been made where possible, as permitted by the new
$<type>var syntax. Duplication has been reduced in similar blockMesh
files (e.g., sloshingTank cases). Settings that cannot practically be
changed have been hard-coded (e.g., angle in the mixerVessel2D
blockMeshDict). The rotor2D blockMeshDict has been centralised and
extended to work with an arbitrary number of rotor blades.
If the libs entry is not provided and the name of the library containing the
functionObject, fvModel or fvConstraint corresponds to the type specified the
corresponding library is automatically loaded, e.g. to apply the
VoFTurbulenceDamping fvModel to an incompressibleVoF simulation the following
will load the libVoFTurbulenceDamping.so library automatically and instantiate
the fvModel:
turbulenceDamping
{
type VoFTurbulenceDamping;
delta 1e-4;
}
which allows lambda to set higher in the cells adjacent to the boundary which is
particularly useful when solving for waves in a domain with no mean-flow and
wave BCs to avoid numerical stability problems where the specified wave flow
reverses into the domain. The alternative is to use symmetry rather than wave
BCs on the side patches which is stable without using lambdaBoundary but there
is modest distortion of the wave profile adjacent to the side patches which does
not propagate into the domain due to the wave forcing.