- make fileHandler deletion mechanism more
transparent by providing a nullptr signature. A nullptr parameter
is already being used in the argList destructor for shutdown, but that
relied on an implicit conversion to autoPtr to trigger things.
- improved handling of file handler replacement.
Previously had a very basic check on old vs new handlers using their
type() values (string comparison!!), which would unfortunately
prevent proper swapping of the contents.
Check the actual pointers instead.
As part of the change, treat any empty autoPtr as no-op instead of as
deletion (which is handled explicitly as nullptr instead).
In addition to making the internal logic simpler, it means that the
current file handler always changes to a valid state without
inadvertently removing everything and falling back to creating a new
default handler (again).
This handling of no-ops also simplifies call code. For example,
<code>
autoPtr<fileHandler> oldHandler;
autoPtr<fileHandler> writeHandler;
word handlerName;
if (arg.readIfPresent("writeHandler", handlerName))
{
writeHandler = fileOperation::New(handlerName);
}
oldHandler = fileHandler(std::move(writeHandler));
... do something
writeHandler = fileHandler(std::move(oldHandler));
</code>
If the "writeHandler" is not specified, each call is a no-op.
If it is specified, the handlers are swapped out each time.
- the management of the fileHandler communicators is now encapsulated
privately (managedComm_) with the final layer being responsible for
cleaning up after itself. This makes delegation/inheritance clearer
and avoids the risk of freeing an MPI communicator twice.
STYLE: uniformFile static check relocated to fileOperation layer
- UPstream::globalComm constant always refers to MPI_COMM_WORLD but
UPstream::worldComm could be MPI_COMM_WORLD (single world)
or a dedicated local communicator (for multi-world).
- provide a Pstream wrapped version of MPI_COMM_SELF,
references as UPstream::selfComm
- UPstream::isUserComm(label)
test for additional user-defined communicators
- recover the target of symbolic links.
This is needed when re-creating a file tree on another rank.
ENH: handle checkGzip, followLink flags in fileHander filePath()
- previously just relied on the backend defaults, now pass through
- separate init(...) for common constructor init steps
- was previously populated with "IOobject" (the typeName) but then
cannot easily detect if the object was actually read.
Also clear the headerClassName on a failed read
BUG: parallel inconsistency in regIOobject::readHeaderOk
- headerOk() checked with master, but possible parallel operations
within it
Changes / Improvements
- more consistent subsetting, interface
* Extend the use of subset and non-subset collections with uniform
internal getters to ensure that the subset/non-subset versions
are robustly handled.
* operator[](label) and objectIndex(label) for standardized access
to the underlying item, or the original index, regardless of
subsetting or not.
* centres() and centre(label) for representative point cloud
information.
* nDim() returns the object dimensionality (0: point, 1: line, etc)
these can be used to determine how 'fat' each shape may be
and whether bounds(labelList) may contribute any useful information.
* bounds(labelList) to return the full bound box required for
specific items. Eg, the overall bounds for various 3D cells.
- easier construction of non-caching versions. The bounding boxes are
rarely cached, so simpler constructors without the caching bool
are provided.
- expose findNearest (bound sphere) method to allow general use
since this does not actually need a tree.
- static helpers
The boxes() static methods can be used by callers that need to build
their own treeBoundBoxList of common shapes (edge, face, cell)
that are also available as treeData types.
The bounds() static methods can be used by callers to determine the
overall bound-box size prior to constructing an indexedOctree
without writing ad hoc code inplace.
Not implemented for treeDataPrimitivePatch since similiar
functionality is available directly from the PrimitivePatch::box()
method with less typing.
========
BREAKING: cellLabels(), faceLabels(), edgeLabel() access methods
- it was always unsafe to use the treeData xxxLabels() methods without
subsetting elements. However, since the various classes
(treeDataCell, treeDataEdge, etc) automatically provided
an identity lookup, this problem was not apparent.
Use objectIndex(label) to safely de-reference to the original index
and operator[](index) to de-reference to the original object.
- more memory efficient within loops
- octree/boundBox overlaps().
Like findBox(), findSphere() but early exit if any shapes overlap.
ENH: additional query for nLeafs()
- don't need separate scratch arrays (avoids possible reallocations
when split is imbalanced)
ENH: upgrade dynamicIndexedOctree to use DynamicList directly
- with C++11 move semantics don't need lists of autoPtr
for efficient transfers
- use default initialize boundBox instead of invertedBox
- reset() instead of assigning from invertedBox
- extend (three parameter version) and grow method
- inflate(Random) instead of extend + re-assigning
- null() static method
* as const reference to the invertedBox with the appropriate casting.
- boundBox inflate(random)
* refactored from treeBoundBox::extend, but allows in-place modification
- boundBox::hexFaces() instead of boundBox::faces
* rarely used, but avoids confusion with treeBoundBox::faces
and reuses hexCell face definitions without code duplication
- boundBox::hexCorners() for corner points corresponding to a hexCell.
Can also be accessed from a treeBoundBox without ambiguity with
points(), which could be hex corners (boundBox) or octant corners
(treeBoundBox)
- boundBox::add with pairs of points
* convenient (for example) when adding edges or a 'box' that has
been extracted from a primitive mesh shape.
- declare boundBox nPoints(), nFaces(), nEdges() as per hexCell
ENH: return invertedBox instead of FatalError for empty trees
- similar to #2612
ENH: cellShape(HEX, ...) + boundBox hexCorners for block meshes
STYLE: cellModel::ref(...) instead of de-reference cellModel::ptr(...)
- the boundBox for a given cell, using the cheapest calculation:
- cellPoints if already available, since this will involve the
fewest number of min/max comparisions.
- otherwise walk the cell faces: via the cell box() method
to avoid creating demand-driven cellPoints etc.
ENH: use direct access to pointHit as point(), use dist(), distSqr()
- if the pointHit has already been checked for hit(), can/should
simply use point() noexcept access subsequently to avoid redundant
checks. Using vector distSqr() methods provides a minor optimization
(no itermediate temporary), but can also make for clearer code.
ENH: copy construct pointIndexHit with different index
- symmetric with constructing from a pointHit with an index
STYLE: prefer pointHit point() instead of rawPoint()
ENH: use DynamicList instead of List + size for point wave
- consistent with previous updates for the other algorithms
STYLE: unique_ptr instead of raw pointer in wave algorithms
- provides fast compile-time indexing for FixedList
(invalid indices trigger a compiler error).
This enables noexcept access, which can propagate into various
other uses (eg, triFace, triPoints, ...)
ENH: add triangle edge vectors
- traditionally used first(), last() methods,
but front(), back() are well-known from std::vector etc
which makes the access more familiar.
- support push_back() method for containers that already had append().
This increases name familiar and can help when porting between
different C++ code bases.
- support pop_back() method for List containers.
This is similar to std::vector
- ie, front(), back(), push_front(), push_back(), pop_front()
ENH: add CircularBuffer flattening operator() and list() method
- useful if assigning content to a List etc
BUG: CircularBuffer find() did not return logical index
- in makeFaMesh, the serial fields are now only read on the master
process and broadcast to the other ranks. The read+distribute is
almost identical to that used in redistributePar, except that in
this case entire fields are sent and not a zero-sized subset.
- improved internal faMesh checking for files so that the TryNew
method works with distributed roots.
- accept IOobjectOption::registerOption with (MUST_READ, NO_WRITE)
being implicit. Direct handling of IOobjectOption itself, for
consistency with IOobject.
The disabling of object registration is currently the only case
where IOobjectList doesn't use default construction parameters,
but it was previously a bit awkward to specify.
- had an off-by-one in the accounting for some corner caes,
partly because the logic was a bit convoluted
ENH: improved string wrapping (#2625)
- reworked logic (like a state machine) to handle backtracking
with fallback of splitting near punctuation characters.
Still doesn't compete with nroff or TeX, but does avoid long lines
and many funny splits. With this change the help for mapFieldsPar
now like this:
=====
Specify the mapping method
(direct|mapNearest|cellVolumeWeight|
correctedCellVolumeWeight)
=====
Since the list of options is very long without any spaces, it takes
'|' as the best split point, which definitely reads better
- with ATOMIC, an intermediary file is created - eg, (fileAbc~tmp~)
where all of the output is written to. When the stream goes out of
scope, this intermediary file is moved/renamed to the actually
output name - eg, (fileAbc~tmp~) -> (fileAbc).
This adds some safety if the simulation crashes while writing the
file, since it will the partial (corrupt) file will be left
behind as (fileAbc~tmp~) and not as (fileAbc), which means it will
will be treated as a backup file and not loaded again on restart.
ENH: provided enumeration for APPEND/NON_APPEND
- clearer than using bool (with comments).
Since append mode is primarily only used by masterOFstream etc
this change is unlikely to affect user coding.
ENH: use file atomic for ensight file creation
- avoids corrupt (truncated) files being referenced by the ensight
case file if the simulation crashes while writing the ensight file.