- the API-versioned calls (eg, tecini142, teczne142, tecpoly142, tecend142),
the limited availability of the SDK and lack of adequate testing make
proper maintenance very difficult.
- when constructing dimensioned fields that are to be zero-initialized,
it is preferrable to use a form such as
dimensionedScalar(dims, Zero)
dimensionedVector(dims, Zero)
rather than
dimensionedScalar("0", dims, 0)
dimensionedVector("zero", dims, vector::zero)
This reduces clutter and also avoids any suggestion that the name of
the dimensioned quantity has any influence on the field's name.
An even shorter version is possible. Eg,
dimensionedScalar(dims)
but reduces the clarity of meaning.
- NB: UniformDimensionedField is an exception to these style changes
since it does use the name of the dimensioned type (instead of the
regIOobject).
Improve alignment of its behaviour with std::unique_ptr
- element_type typedef
- release() method - identical to ptr() method
- get() method to get the pointer without checking and without releasing it.
- operator*() for dereferencing
Method name changes
- renamed rawPtr() to get()
- renamed rawRef() to ref(), removed unused const version.
Removed methods/operators
- assignment from a raw pointer was deleted (was rarely used).
Can be convenient, but uncontrolled and potentially unsafe.
Do allow assignment from a literal nullptr though, since this
can never leak (and also corresponds to the unique_ptr API).
Additional methods
- clone() method: forwards to the clone() method of the underlying
data object with argument forwarding.
- reset(autoPtr&&) as an alternative to operator=(autoPtr&&)
STYLE: avoid implicit conversion from autoPtr to object type in many places
- existing implementation has the following:
operator const T&() const { return operator*(); }
which means that the following code works:
autoPtr<mapPolyMesh> map = ...;
updateMesh(*map); // OK: explicit dereferencing
updateMesh(map()); // OK: explicit dereferencing
updateMesh(map); // OK: implicit dereferencing
for clarity it may preferable to avoid the implicit dereferencing
- prefer operator* to operator() when deferenced a return value
so it is clearer that a pointer is involve and not a function call
etc Eg, return *meshPtr_; vs. return meshPtr_();
- relocated HashSetPlusEqOp and HashTablePlusEqOp to
HashSetOps::plusEqOp and HashTableOps::plusEqOp, respectively
- additional functions for converting between a labelHashSet
and a PackedBoolList or List<bool>:
From lists selections to labelHashSet indices:
HashSetOps::used(const PackedBoolList&);
HashSetOps::used(const UList<bool>&);
From labelHashSet to list forms:
PackedBoolList bitset(const labelHashSet&);
List<bool> bools(const labelHashSet&);
- this currently just strips off the leading parent directory name
"/this/path/and/subdirs/name"
relative("/this/path") -> "and/subdirs/name"
relative("/this") -> "path/and/subdirs/name"
- problems when the cloud was not available on all processors.
- NB: ensight measured data only allows a single cloud, but
foamToEnsight writes all clouds.
- use succincter method names that more closely resemble dictionary
and HashTable method names. This improves method name consistency
between classes and also requires less typing effort:
args.found(optName) vs. args.optionFound(optName)
args.readIfPresent(..) vs. args.optionReadIfPresent(..)
...
args.opt<scalar>(optName) vs. args.optionRead<scalar>(optName)
args.read<scalar>(index) vs. args.argRead<scalar>(index)
- the older method names forms have been retained for code compatibility,
but are now deprecated
old "positions" file form
The change to barycentric-based tracking changed the contents of the
cloud "positions" file to a new format comprising the barycentric
co-ordinates and other cell position-based info. This broke
backwards compatibility, providing no option to restart old cases
(v1706 and earlier), and caused difficulties for dependent code, e.g.
for post-processing utilities that could only infer the contents only
after reading.
The barycentric position info is now written to a file called
"coordinates" with provision to restart old cases for which only the
"positions" file is available. Related utilities, e.g. for parallel
running and data conversion have been updated to be able to support both
file types.
To write the "positions" file by default, use set the following option
in the InfoSwitches section of the controlDict:
writeLagrangianPositions 1;
Original commit message:
------------------------
Parallel IO: New collated file format
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.
- erroneous double logic for subset meshes.
The underlying vtk::vtuCells uses a cellMap to map into a global
field, which also allows handling of decomposed polyhedral cells.
If a mesh subset is involved (eg, cellSet, cellZone), then the
set/zone cellMap can be used to ensure that the original number is
properly adjusted. For foamToVTK, the meshSubsetHelper already
does the subsetting and is used when loading fields.
Does not affect ParaView reader module since there we work on the
full field and do the subsetting manually (using the cellMap).
- with the xml append format it is possible to write raw binary
(instead of base64), but the writer becomes more complicated.
Either needs two passes to create, or need to allocate a block
of space for the header information (like VTK itself does) and
write later.
* internalWriter
* patchWriter
* surfaceMeshWriter
* lagrangianWriter
Also these special purpose ones:
* foamVtkWriteSurfFields
- this shifts responsibility away from caller to the individual writers
for knowing which file formats are supported and which file ending is
appropriate. When the writer receives the output format request,
it can elect to downgrade or otherwise adjust it to what it can
actually manage (eg, legacy vs xml vs xml-append).
But currently still just with legacy format backends.
- Use on/off vs longer compressed/uncompressed.
For consistency, replaced yes/no with on/off.
- Avoid the combination of binary/compressed,
which is disallowed and provokes a warning anyhow
- ensure that the string-related classes have consistently similar
matching methods. Use operator()(const std::string) as an entry
point for the match() method, which makes it easier to use for
filters and predicates. In some cases this will also permit using
a HashSet as a match predicate.
regExp
====
- the set method now returns a bool to signal that the requested
pattern was compiled.
wordRe
====
- have separate constructors with the compilation option (was previously
a default parameter). This leaves the single parameter constructor
explicit, but the two parameter version is now non-explicit, which
makes it easier to use when building lists.
- renamed compile-option from REGEX (to REGEXP) for consistency with
with the <regex.h>, <regex> header names etc.
wordRes
====
- renamed from wordReListMatcher -> wordRes. For reduced typing and
since it behaves as an entity only slightly related to its underlying
list nature.
- Provide old name as typedef and include for code transition.
- pass through some list methods into wordRes
hashedWordList
====
- hashedWordList[const word& name] now returns a -1 if the name is is
not found in the list of indices. That has been a pending change
ever since hashedWordList was generalized out of speciesTable
(Oct-2010).
- add operator()(const word& name) for easy use as a predicate
STYLE: adjust parameter names in stringListOps
- reflect if the parameter is being used as a primary matcher, or the
matcher will be derived from the parameter.
For example,
(const char* re), which first creates a regExp
versus (const regExp& matcher) which is used directly.
- in specific cases it can be useful to suppress searching the instances.
For example, if one only wishes to check if a "points" is available at
the given time instance, without searching backwards through all
times.
- There will be triangles rendered inside the mesh (when
surface-rendering), because one of the cell's triangles is defined
as a quadrangle in VTK_WEDGE.
- Therefore, this VTK_WEDGE representation is only used when
decomposing the mesh, otherwise the correct representation is done
by VTK_POLYHEDRON.
- Furthermore, using VTK_PYRAMID gave worse result, because it renders
2 triangles inside the mesh for the collapsed quadrangle, likely due
to mismatch with the adjacent cell's face.
- Using VTK_HEXAHEDRON was not tested in this iteration, given that it
should give even worse results, when compared to using VTK_PYRAMID.
Patch contributed by Bruno Santos
Resolves bug-report http://bugs.openfoam.org/view.php?id=2099
- manifest in some parallel operations.
STYLE: update foamToEnsight, foamToEnsightParts to use C++ initializer_list
- avoid warning message when removing a non-existent directory (ensight output).
- Use ensightCase for case writing.
Rebase ensightPartCells/ensightPartFaces on
ensightCells/ensightFaces routines.
- Greatly reduces code duplication potential source of errors.
- eliminate ensightAsciiStream, ensightBinaryStream, ensightStream in
favour of using ensightFile and ensightGeoFile classes throughout.
- encapsulate mesh-parts sorting with the ensightCells, ensightFaces
class.
- handle of patches/faceZones entirely within ensightMesh for a lighter
interaction with field output. Both faceZones and point fields need
more testing to see if they behave properly for all cases.
- move some output functionality into its own namespace
'ensightOutput', move into a library.
- use the ensightCase class to open new ensight output streams
in the proper sub-directory locations.
- Place common code under OSspecific.
By including "endian.H", either one of WM_BIG_ENDIAN or WM_LITTLE_ENDIAN
will be defined.
Provides inline 32-bit and 64-bit byte swap routines that can be
used/re-used elsewhere.
The inplace memory swaps currently used by the VTK output are left for
the moment pending further cleanup of that code.
- Less looping when detecting lagrangian clouds and their fields.
- Avoid using Time::setTime() and IOobjectList in tight loops.
They both kill performance immensely.
ENH: provide a -noLagrangian option to foamToEnsight and foamToEnsightParts
for even more control.
- The new field needs initialization with a dimensioned<Type> not just
the dimensionSet.
- The new field was also incorrectly being registered, which could
cause issues later.
Old code:
Found 10990 time steps
Search for moving mesh ... no moving mesh detected.
Startup in 329.09 s
Updated:
Found 10990 time steps
Search for moving mesh ... no moving mesh detected.
Startup in 1.6 s
- Cause was checking "polyMesh/points" via an IOobject.
Short-circuit with a check for a polyMesh/ directory first.
Limit the check to the master-node as well to further reduce
load on the file-system.
------------------------------
ENH: improve per-step conversion times for foamToEnsight.
Old code:
Converting 11001 time steps
Time [0] = 0 Wrote in 1.53 s
Time [1] = 1 Wrote in 1.52 s
...
Time [100] = 100 Elapsed time 205.35 s
Updated:
Converting 11001 time steps
Time [0] = 0 Wrote in 1.4 s
Time [1] = 1 Wrote in 0.07 s
...
Time [100] = 100 Elapsed time 42.4 s
- Speedup by hashing test results from the first conversion step
instead of checking each time.
Check data on all nodes to avoid problems with incomplete writes.
------------------------------
BUG: moving mesh detection failed for foamToEnsightParts
- adjusted to agree with updated foamToEnsight
------------------------------
Note:
- foamToEnsightParts (serial) still has about twice the throughput of
foamToEnsight.
- Default is a width of 8 characters, but this can be extended up to 31
characters via the '-width' command-line option.
- Now use a similar structure as foamToEnsightParts for the masking.
This reduces the clutter within the directory, makes it easier to
selectively delete some time steps (using shell commands).
- Added in a "time" information data in each sub-directory to
make it possible to reconstruct the case file with an external
script.
- Conversion of cloud data should now also work in parallel
(may need more testing).
- Support binary output for cloud data.
- Better avoidance of illegal ensight variable names.
But still partially incomplete (due to patch fields).
==================================================
Example of NEW file structure:
EnSight/verticalChannel.case # case name
EnSight/geometry # for non-moving geometry
EnSight/data/ # time-varying data
EnSight/data/00000000/
EnSight/data/00000001/
...
Fields are stored by name within the data/********/ directories:
EnSight/data/00000001/time # human-readable time info
EnSight/data/00000001/U
EnSight/data/00000001/p
...
EnSight/data/00000001/geometry # for moving geometry
Clouds are stored at the next sub-directory level:
EnSight/data/00000001/lagrangian/<cloudName>/positions
EnSight/data/00000001/lagrangian/<cloudName>/U
...
==================================================
The old structure was significantly more cluttered:
EnSight/verticalChannel.case
EnSight/verticalChannel.0000.mesh
EnSight/verticalChannel.0001.p
EnSight/verticalChannel.0001.<cloudName>
EnSight/verticalChannel.0001.<cloudName>.U
==================================================
The normal library system() command uses 'fork', which causes
problems on IB+OPENMPI.
STYLE: add Foam:: qualifier to system calls to make them easier to spot.
Replaced the 'postProcess' argument to the 'write' and 'execute'
functions with the single static member 'postProcess' in the
functionObject base-class.
Generally fields and objects are selected using the 'field[s]' and
'object[s]' keywords but this was not consistent between all
functionObject, fvOptions etc. and now fixed by applying the following
renaming:
fieldName -> field
fieldNames -> fields
objectName -> object
objectNames -> objects
the equivalent functionality is provided by the writeRegisteredObject
functionObject in a MUCH simpler, easier and extensible manner.
functionObject: Removed the now redundant 'timeSet' function.
This changes simplifies the specification of functionObjects in
controlDict and is consistent with the 'libs' option in controlDict to
load special solver libraries.
Support for the old 'functionObjectLibs' name is supported for backward compatibility.
- Avoids the need for the 'OutputFilterFunctionObject' wrapper
- Time-control for execution and writing is now provided by the
'timeControlFunctionObject' which instantiates the processing
'functionObject' and controls its operation.
- Alternative time-control functionObjects can now be written and
selected at run-time without the need to compile wrapped version of
EVERY existing functionObject which would have been required in the
old structure.
- The separation of 'execute' and 'write' functions is now formalized in the
'functionObject' base-class and all derived classes implement the
two functions.
- Unnecessary implementations of functions with appropriate defaults
in the 'functionObject' base-class have been removed reducing
clutter and simplifying implementation of new functionObjects.
- The 'coded' 'functionObject' has also been updated, simplified and tested.
- Further simplification is now possible by creating some general
intermediate classes derived from 'functionObject'.
splitMeshRegions: handle flipping of faces for surface fields
subsetMesh: subset dimensionedFields
decomposePar: use run-time selection of decomposition constraints. Used to
keep cells on particular processors. See the decomposeParDict in
$FOAM_UTILITIES/parallel/decomposePar:
- preserveBaffles: keep baffle faces on same processor
- preserveFaceZones: keep faceZones owner and neighbour on same processor
- preservePatches: keep owner and neighbour on same processor. Note: not
suitable for cyclicAMI since these are not coupled on the patch level
- singleProcessorFaceSets: keep complete faceSet on a single processor
- refinementHistory: keep cells originating from a single cell on the
same processor.
decomposePar: clean up decomposition of refinement data from snappyHexMesh
reconstructPar: reconstruct refinement data (refineHexMesh, snappyHexMesh)
reconstructParMesh: reconstruct refinement data (refineHexMesh, snappyHexMesh)
redistributePar:
- corrected mapping surfaceFields
- adding processor patches in order consistent with decomposePar
argList: check that slaves are running same version as master
fvMeshSubset: move to dynamicMesh library
fvMeshDistribute:
- support for mapping dimensionedFields
- corrected mapping of surfaceFields
parallel routines: allow parallel running on single processor
Field: support for
- distributed mapping
- mapping with flipping
mapDistribute: support for flipping
AMIInterpolation: avoid constructing localPoints
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.
for consistency with the time controls in controlDict and to avoid
unnecessary confusion. All code and tutorials have been updated.
The old names 'outputControl' and 'outputInterval' are but supported for
backward compatibility but deprecated.
Description
This functionObject writes objects registered to the database in VTK format
using the foamToVTK library.
Currently only the writing of the cell-values of volFields is supported but
support for other field types, patch fields, Lagrangian data etc. will be
added.
Example of function object specification:
\verbatim
writeVTK1
{
type writeVTK;
functionObjectLibs ("libIOFunctionObjects.so");
...
objectNames (obj1 obj2);
}
\endverbatim
\heading Function object usage
\table
Property | Description | Required | Default value
type | type name: writeVTK | yes |
objectNames | objects to write | yes |
\endtable
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 22f4ad32b1
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.
- most notably the '%' which is used as a separator in places
caused problems.
EHN: only use valid ensight file/variable names for writers
- fixed: foamToEnsightParts, ensightSurfaceWriter
- pending: foamToEnsight
BUG: no geometry written for foamToEnsightParts with moving mesh (fixes#142)
- an incorrect path was causing the issue
Moved file path handling to regIOobject and made it type specific so
now every object can have its own rules. Examples:
- faceZones are now processor local (and don't search up anymore)
- timeStampMaster is now no longer hardcoded inside IOdictionary
(e.g. uniformDimensionedFields support it as well)
- the distributedTriSurfaceMesh is properly processor-local; no need
for fileModificationChecking manipulation.
- checkMesh has option to write faceSets or (outside of) cellSets as
sampledSurface format. It automatically reconstructs the set on the master
and writes it to the postProcessing folder (as any sampledSurface). E.g.
mpirun -np 6 checkMesh -allTopology -allGeometry -writeSets vtk -parallel
- fixed order writing of symmTensor in Ensight writers
- redistributePar to have almost (complete) functionality of decomposePar+reconstructPar
- low-level distributed Field mapping
- support for mapping surfaceFields (including flipping faces)
- support for decomposing/reconstructing refinement data