When an OpenFOAM simulation runs in parallel, the data for decomposed fields and
mesh(es) has historically been stored in multiple files within separate
directories for each processor. Processor directories are named 'processorN',
where N is the processor number.
This commit introduces an alternative "collated" file format where the data for
each decomposed field (and mesh) is collated into a single file, which is
written and read on the master processor. The files are stored in a single
directory named 'processors'.
The new format produces significantly fewer files - one per field, instead of N
per field. For large parallel cases, this avoids the restriction on the number
of open files imposed by the operating system limits.
The file writing can be threaded allowing the simulation to continue running
while the data is being written to file. NFS (Network File System) is not
needed when using the the collated format and additionally, there is an option
to run without NFS with the original uncollated approach, known as
"masterUncollated".
The controls for the file handling are in the OptimisationSwitches of
etc/controlDict:
OptimisationSwitches
{
...
//- Parallel IO file handler
// uncollated (default), collated or masterUncollated
fileHandler uncollated;
//- collated: thread buffer size for queued file writes.
// If set to 0 or not sufficient for the file size threading is not used.
// Default: 2e9
maxThreadFileBufferSize 2e9;
//- masterUncollated: non-blocking buffer size.
// If the file exceeds this buffer size scheduled transfer is used.
// Default: 2e9
maxMasterFileBufferSize 2e9;
}
When using the collated file handling, memory is allocated for the data in the
thread. maxThreadFileBufferSize sets the maximum size of memory in bytes that
is allocated. If the data exceeds this size, the write does not use threading.
When using the masterUncollated file handling, non-blocking MPI communication
requires a sufficiently large memory buffer on the master node.
maxMasterFileBufferSize sets the maximum size in bytes of the buffer. If the
data exceeds this size, the system uses scheduled communication.
The installation defaults for the fileHandler choice, maxThreadFileBufferSize
and maxMasterFileBufferSize (set in etc/controlDict) can be over-ridden within
the case controlDict file, like other parameters. Additionally the fileHandler
can be set by:
- the "-fileHandler" command line argument;
- a FOAM_FILEHANDLER environment variable.
A foamFormatConvert utility allows users to convert files between the collated
and uncollated formats, e.g.
mpirun -np 2 foamFormatConvert -parallel -fileHandler uncollated
An example case demonstrating the file handling methods is provided in:
$FOAM_TUTORIALS/IO/fileHandling
The work was undertaken by Mattijs Janssens, in collaboration with Henry Weller.
"pos" now returns 1 if the argument is greater than 0, otherwise it returns 0.
This is consistent with the common mathematical definition of the "pos" function:
https://en.wikipedia.org/wiki/Sign_(mathematics)
However the previous implementation in which 1 was also returned for a 0
argument is useful in many situations so the "pos0" has been added which returns
1 if the argument is greater or equal to 0. Additionally the "neg0" has been
added which returns 1 if if the argument is less than or equal to 0.
except turbulence and lagrangian which will also be updated shortly.
For example in the nonNewtonianIcoFoam offsetCylinder tutorial the viscosity
model coefficients may be specified in the corresponding "<type>Coeffs"
sub-dictionary:
transportModel CrossPowerLaw;
CrossPowerLawCoeffs
{
nu0 [0 2 -1 0 0 0 0] 0.01;
nuInf [0 2 -1 0 0 0 0] 10;
m [0 0 1 0 0 0 0] 0.4;
n [0 0 0 0 0 0 0] 3;
}
BirdCarreauCoeffs
{
nu0 [0 2 -1 0 0 0 0] 1e-06;
nuInf [0 2 -1 0 0 0 0] 1e-06;
k [0 0 1 0 0 0 0] 0;
n [0 0 0 0 0 0 0] 1;
}
which allows a quick change between models, or using the simpler
transportModel CrossPowerLaw;
nu0 [0 2 -1 0 0 0 0] 0.01;
nuInf [0 2 -1 0 0 0 0] 10;
m [0 0 1 0 0 0 0] 0.4;
n [0 0 0 0 0 0 0] 3;
if quick switching between models is not required.
To support this more convenient parameter specification the inconsistent
specification of seedSampleSet in the streamLine and wallBoundedStreamLine
functionObjects had to be corrected from
// Seeding method.
seedSampleSet uniform; //cloud; //triSurfaceMeshPointSet;
uniformCoeffs
{
type uniform;
axis x; //distance;
// Note: tracks slightly offset so as not to be on a face
start (-1.001 -0.05 0.0011);
end (-1.001 -0.05 1.0011);
nPoints 20;
}
to the simpler
// Seeding method.
seedSampleSet
{
type uniform;
axis x; //distance;
// Note: tracks slightly offset so as not to be on a face
start (-1.001 -0.05 0.0011);
end (-1.001 -0.05 1.0011);
nPoints 20;
}
which also support the "<type>Coeffs" form
// Seeding method.
seedSampleSet
{
type uniform;
uniformCoeffs
{
axis x; //distance;
// Note: tracks slightly offset so as not to be on a face
start (-1.001 -0.05 0.0011);
end (-1.001 -0.05 1.0011);
nPoints 20;
}
}
Avoids slight phase-fraction unboundedness at entertainment BCs and improved
robustness.
Additionally the phase-fractions in the multi-phase (rather than two-phase)
solvers are adjusted to avoid the slow growth of inconsistency ("drift") caused
by solving for all of the phase-fractions rather than deriving one from the
others.
Added the interfacial pressure-work terms according to:
Ishii, M., Hibiki, T.,
Thermo-fluid dynamics of two-phase flow,
ISBN-10: 0-387-28321-8, 2006
While this is the most common approach to handling the interfacial
pressure-work it introduces numerical stability issues in regions of low
phase-fraction and rapid flow deformation. To alleviate this problem an
optional limiter may be applied to the pressure-work term in either of
the energy forms. This may specified in the
"thermophysicalProperties.<phase>" file, e.g.
pressureWorkAlphaLimit 1e-3;
which sets the pressure work term to 0 for phase-fractions below 1e-3.
For particularly unstable cases a limit of 1e-2 may be necessary.
Previously the inlet flow of phase 1 (the phase solved for) is corrected
to match the inlet specification for that phase. However, if the second
phase is also constrained at inlets the inlet flux must also be
corrected to match the inlet specification.
Renamed the original 'laminar' model to 'Stokes' to indicate it is a
linear stress model supporting both Newtonian and non-Newtonian
viscosity.
This general framework will support linear, non-linear, visco-elastic
etc. laminar transport models.
For backward compatibility the 'Stokes' laminar stress model can be
selected either the original 'laminar' 'simulationType'
specification in turbulenceProperties:
simulationType laminar;
or using the new more general 'laminarModel' specification:
simulationType laminar;
laminar
{
laminarModel Stokes;
}
which allows other laminar stress models to be selected.
to have the prefix 'write' rather than 'output'
So outputTime() -> writeTime()
but 'outputTime()' is still supported for backward-compatibility.
Also removed the redundant secondary-writing functionality from Time
which has been superseded by the 'writeRegisteredObject' functionObject.
These new names are more consistent and logical because:
primitiveField():
primitiveFieldRef():
Provides low-level access to the Field<Type> (primitive field)
without dimension or mesh-consistency checking. This should only be
used in the low-level functions where dimensional consistency is
ensured by careful programming and computational efficiency is
paramount.
internalField():
internalFieldRef():
Provides access to the DimensionedField<Type, GeoMesh> of values on
the internal mesh-type for which the GeometricField is defined and
supports dimension and checking and mesh-consistency checking.
Non-const access to the internal field now obtained from a specifically
named access function consistent with the new names for non-canst access
to the boundary field boundaryFieldRef() and dimensioned internal field
dimensionedInternalFieldRef().
See also commit a4e2afa4b3
When the GeometricBoundaryField template class was originally written it
was a separate class in the Foam namespace rather than a sub-class of
GeometricField as it is now. Without loss of clarity and simplifying
code which access the boundary field of GeometricFields it is better
that GeometricBoundaryField be renamed Boundary for consistency with the
new naming convention for the type of the dimensioned internal field:
Internal, see commit a25a449c9e
This is a very simple text substitution change which can be applied to
any code which compiles with the OpenFOAM-dev libraries.
Given that the type of the dimensioned internal field is encapsulated in
the GeometricField class the name need not include "Field"; the type
name is "Internal" so
volScalarField::DimensionedInternalField -> volScalarField::Internal
In addition to the ".dimensionedInternalField()" access function the
simpler "()" de-reference operator is also provided to greatly simplify
FV equation source term expressions which need not evaluate boundary
conditions. To demonstrate this kEpsilon.C has been updated to use
dimensioned internal field expressions in the k and epsilon equation
source terms.
Resolves bug-report http://www.openfoam.org/mantisbt/view.php?id=1938
Because C++ does not support overloading based on the return-type there
is a problem defining both const and non-const member functions which
are resolved based on the const-ness of the object for which they are
called rather than the intent of the programmer declared via the
const-ness of the returned type. The issue for the "boundaryField()"
member function is that the non-const version increments the
event-counter and checks the state of the stored old-time fields in case
the returned value is altered whereas the const version has no
side-effects and simply returns the reference. If the the non-const
function is called within the patch-loop the event-counter may overflow.
To resolve this it in necessary to avoid calling the non-const form of
"boundaryField()" if the results is not altered and cache the reference
outside the patch-loop when mutation of the patch fields is needed.
The most straight forward way of resolving this problem is to name the
const and non-const forms of the member functions differently e.g. the
non-const form could be named:
mutableBoundaryField()
mutBoundaryField()
nonConstBoundaryField()
boundaryFieldRef()
Given that in C++ a reference is non-const unless specified as const:
"T&" vs "const T&" the logical convention would be
boundaryFieldRef()
boundaryFieldConstRef()
and given that the const form which is more commonly used is it could
simply be named "boundaryField()" then the logical convention is
GeometricBoundaryField& boundaryFieldRef();
inline const GeometricBoundaryField& boundaryField() const;
This is also consistent with the new "tmp" class for which non-const
access to the stored object is obtained using the ".ref()" member function.
This new convention for non-const access to the components of
GeometricField will be applied to "dimensionedInternalField()" and "internalField()" in the
future, i.e. "dimensionedInternalFieldRef()" and "internalFieldRef()".
e.g. (fvc::interpolate(HbyA) & mesh.Sf()) -> fvc::flux(HbyA)
This removes the need to create an intermediate face-vector field when
computing fluxes which is more efficient, reduces the peak storage and
improved cache coherency in addition to providing a simpler and cleaner
API.
The deprecated non-const tmp functionality is now on the compiler switch
NON_CONST_TMP which can be enabled by adding -DNON_CONST_TMP to EXE_INC
in the Make/options file. However, it is recommended to upgrade all
code to the new safer tmp by using the '.ref()' member function rather
than the non-const '()' dereference operator when non-const access to
the temporary object is required.
Please report any problems on Mantis.
Henry G. Weller
CFD Direct.
in case of tmp misuse.
Simplified tmp reuse pattern in field algebra to use tmp copy and
assignment rather than the complex delayed call to 'ptr()'.
Removed support for unused non-const 'REF' storage of non-tmp objects due to C++
limitation in constructor overloading: if both tmp(T&) and tmp(const T&)
constructors are provided resolution is ambiguous.
The turbulence libraries have been upgraded and '-DCONST_TMP' option
specified in the 'options' file to switch to the new 'tmp' behavior.
To be used instead of zeroGradientFvPatchField for temporary fields for
which zero-gradient extrapolation is use to evaluate the boundary field
but avoiding fields derived from temporary field using field algebra
inheriting the zeroGradient boundary condition by the reuse of the
temporary field storage.
zeroGradientFvPatchField should not be used as the default patch field
for any temporary fields and should be avoided for non-temporary fields
except where it is clearly appropriate;
extrapolatedCalculatedFvPatchField and calculatedFvPatchField are
generally more suitable defaults depending on the manner in which the
boundary values are specified or evaluated.
The entire OpenFOAM-dev code-base has been updated following the above
recommendations.
Henry G. Weller
CFD Direct
The boundary conditions of HbyA are now constrained by the new "constrainHbyA"
function which applies the velocity boundary values for patches for which the
velocity cannot be modified by assignment and pressure extrapolation is
not specified via the new
"fixedFluxExtrapolatedPressureFvPatchScalarField".
The new function "constrainPressure" sets the pressure gradient
appropriately for "fixedFluxPressureFvPatchScalarField" and
"fixedFluxExtrapolatedPressureFvPatchScalarField" boundary conditions to
ensure the evaluated flux corresponds to the known velocity values at
the boundary.
The "fixedFluxPressureFvPatchScalarField" boundary condition operates
exactly as before, ensuring the correct flux at fixed-flux boundaries by
compensating for the body forces (gravity in particular) with the
pressure gradient.
The new "fixedFluxExtrapolatedPressureFvPatchScalarField" boundary
condition may be used for cases with or without body-forces to set the
pressure gradient to compensate not only for the body-force but also the
extrapolated "HbyA" which provides a second-order boundary condition for
pressure. This is useful for a range a problems including impinging
flow, extrapolated inlet conditions with body-forces or for highly
viscous flows, pressure-induced separation etc. To test this boundary
condition at walls in the motorBike tutorial case set
lowerWall
{
type fixedFluxExtrapolatedPressure;
}
motorBikeGroup
{
type fixedFluxExtrapolatedPressure;
}
Currently the new extrapolated pressure boundary condition is supported
for all incompressible and sub-sonic compressible solvers except those
providing implicit and tensorial porosity support. The approach will be
extended to cover these solvers and options in the future.
Note: the extrapolated pressure boundary condition is experimental and
requires further testing to assess the range of applicability,
stability, accuracy etc.
Henry G. Weller
CFD Direct Ltd.