- simplify procAddressing read/write
- avoid accessing points in faMeshReconstructor.
Can rely on the patch meshPoints (labelList), which does not need
access to a pointField
- report number of points on decomposed mesh.
Can be useful additional information.
Additional statistics for finite area decomposition
- provide bundled reconstructAllFields for various reconstructors
- remove reconstructPar checks for very old face addressing
(from foam2.0 - ie, older than OpenFOAM itself)
- bundle all reading into fieldsDistributor tools,
where it can be reused by various utilities as required.
- combine decomposition fields as respective fieldsCache
which eliminates most of the clutter from decomposePar
and similfies reuse in the future.
STYLE: remove old wordHashSet selection (deprecated in 2018)
BUG: incorrect face flip handling for faMeshReconstructor
- a latent bug which is not yet triggered since the faMesh faces are
currently only definable on boundary faces (which never flip)
- similar functionality as newMesh etc.
Relocated to finiteVolume since there are no dynamicMesh dependencies.
- use simpler procAddressing (with updated mapDistributeBase).
separated from redistributePar
- previously filtered on the existence of area fields, but with
faMesh::TryNew this is not required anymore.
STYLE: enable -verbose for various parallel utilities (consistency)
- direct construct and reset method for creating a zero-sized (dummy)
subMesh. Has no exposed faces and no parallel synchronization
required.
- core mapping (interpolate) functionality with direct handling
of subsetting in fvMeshSubset (src/finiteVolume).
Does not use dynamicMesh topology changes
- two-step subsetting as fvMeshSubsetter (src/dynamicMesh).
Does use dynamicMesh topology changes.
This is apparently only needed by the subsetMesh application itself.
DEFEATURE: remove deprecated setLargeCellSubset() method
- was deprecated JUL-2018, now removed (see issue #951)
- allows restricted evaluation to specific coupled patch types.
Code relocated/refactored from redistributePar.
STYLE: ensure use of waitRequests() also corresponds to nonBlocking
ENH: additional copy/move construct GeometricField from DimensionedField
STYLE: processorPointPatch owner()/neighbour() as per processorPolyPatch
STYLE: orientedType with bool cast operator and noexcept
- additional Pstream::broadcasts() method to serialize/deserialize
multiple items.
- revoke the broadcast specialisations for std::string and List(s) and
use a generic broadcasting template. In most cases, the previous
specialisations would have required two broadcasts:
(1) for the size
(2) for the contiguous content.
Now favour reduced communication over potential local (intermediate)
storage that would have only benefited a few select cases.
ENH: refine PstreamBuffers access methods
- replace 'bool hasRecvData(label)' with 'label recvDataCount(label)'
to recover the number of unconsumed receive bytes from specified
processor. Can use 'labelList recvDataCounts()' to recover the
number of unconsumed receive bytes from all processor.
- additional peekRecvData() method (for transcribing contiguous data)
ENH: globalIndex whichProcID - check for isLocal first
- reasonable to assume that local items are searched for more
frequently, so do preliminary check for isLocal before performing
a more costly binary search of globalIndex offsets
ENH: masterUncollatedFileOperation - bundled scatter of status
- bundles frequently used 'gather/scatter' patterns more consistently.
- combineAllGather -> combineGather + broadcast
- listCombineAllGather -> listCombineGather + broadcast
- mapCombineAllGather -> mapCombineGather + broadcast
- allGatherList -> gatherList + scatterList
- reduce -> gather + broadcast (ie, allreduce)
- The allGatherList currently wraps gatherList/scatterList, but may be
replaced with a different algorithm in the future.
STYLE: PstreamCombineReduceOps.H is mostly unneeded now
STYLE: LduInterfaceFieldPtrsList as alias instead of a class
STYLE: define patch lists typedefs when defining the base patch
- eg, polyPatchList typedef within polyPatch.H
INT: relocate GeometricField::Boundary -> GeometricBoundaryField
- was internal to GeometricField but moving it outside simplifies
forward declarations etc. Code adapted from openfoam.org
- less communication than gatherList/scatterList
ENH: refine send granularity in Pstream::exchange
STYLE: ensure PstreamBuffers and defaultCommsType agree
- simpler loops for lduSchedule
- PstreamBuffers nProcs() and allProcs() methods to recover the rank
information consistent with the communicator used for construction
- allowClearRecv() methods for more control over buffer reuse
For example,
pBufs.allowClearRecv(false);
forAll(particles, particlei)
{
pBufs.clear();
fill...
read via IPstream(..., pBufs);
}
This preserves the receive buffers memory allocation between calls.
- finishedNeighbourSends() method as compact wrapper for
finishedSends() when send/recv ranks are identically
(eg, neighbours)
- hasSendData()/hasRecvData() methods for PstreamBuffers.
Can be useful for some situations to skip reading entirely.
For example,
pBufs.finishedNeighbourSends(neighProcs);
if (!returnReduce(pBufs.hasRecvData(), orOp<bool>()))
{
// Nothing to do
continue;
}
...
On an individual basis:
for (const int proci : pBufs.allProcs())
{
if (pBufs.hasRecvData(proci))
{
...
}
}
Also conceivable to do the following instead (nonBlocking only):
if (!returnReduce(pBufs.hasSendData(), orOp<bool>()))
{
// Nothing to do
pBufs.clear();
continue;
}
pBufs.finishedNeighbourSends(neighProcs);
...
- unused in regular OpenFOAM code
- POSIX version uses deprecated gethostbyname()
- Windows version never worked
COMP: localize, noexcept on internal OSspecific methods
STYLE: support fileName::Type SYMLINK and LINK as synonyms
- set() was silently deprecated in favour of reset() FEB-2018
since the original additional check for overwriting an existing
pointer was never used. The reset(...) name is more consistent
with unique_ptr, tmp etc.
Now emit deprecations for set().
- use direct test for autoPtr, tmp instead of valid() method.
More consistent with unique_ptr etc.
STYLE: eliminate redundant ptr() use on cloned quantities
- argList::envExecutable() static method.
This is identical to getEnv("FOAM_EXECUTABLE"), where the name of
the executable has typically been set from the argList construction.
Provides a singleton access to this value from locations that
do not have knowledge of the originating command args (argList).
This is a similar rationale as for the argList::envGlobalPath() static.
- additional argList::envRelativePath() static method.
- make -dry-run handling more central and easier to use by adding into
argList itself.
STYLE: drop handling of -srcDoc (v1706 option)
- replaced with -doc-source for 1712 and never used much anyhow
- supports redistributePar -decompose -fileHandler collated
- supports redistributePar -reconstruct
- does not support redistributePar with collated in redistribution mode
- noticed by Robin Knowles with `decomposePar -fields -copyZero`
The internals for the Foam:cp method combine the behaviour of
a regular `cp` and `cp -R` combined.
When source and target are both directories, the old implementation
created a subdirectory for the contents.
This normally fine,
ok: cp "path1/0/" to "path2/1" -> "path2/1/2"
BUT: cp "path1/0/" to "path2/0" -> "path2/0/0" !!
Now add check for the basenames first.
If they are identical, we probably meant to copy directory contents
only, without the additional subdir layer.
BUG: decomposePar -fields -copyZero copies the wrong directory
- was using the current time name (usually latest) instead of copying
the 0 directory
ENH: accept 0.orig directories as a fallback to copy if the 0 directory
is missing
- intended for the following type of use:
auto oldHandler = fileHandler(fileOperation::NewUncollated());
... do something that only works with uncollated
// Restore previous (if any)
if (oldHandler)
{
fileHandler(std::move(oldHandler));
}
ENH: make fileOperation distributed(bool) mutable
- use is "static-like" and akin to Pstream::parRun(bool),
thus allow toggling of the switch without a const_cast
Step 1.
include "addAllRegionOptions.H"
Adds the -allRegions, -regions and -region options to argList.
Step 2.
include "getAllRegionOptions.H"
Processes the options with -allRegions selecting everything
from the regionProperties.
OR use -regions to specify multiple regions (from
regionProperties), and can also contain regular expressions
OR use the -region option
Specifying a single -regions NAME (not a regular expresssion)
is the same as -region NAME and doesn't use regionProperties
Creates a `wordList regionNames`
Step 3.
Do something with the region names.
Either directly, or quite commonly with the following
include "createNamedMeshes.H"
Creates a `PtrList<fvMesh> meshes`
STYLE: add description to some central include files
- simplifies local toggling.
- centralize fileModification static variables into IOobject.
They were previously scattered between IOobject and regIOobject
- override casename, procesorCase flags to guarantee reconstructed
case to be written to the undecomposed directory
- alternative is to construct a Zero mesh on the undecomposed
runTime and add all other bits to that but that has not been
pursued
In reconstruct mode redistributePar will have
- master read undecomposed mesh
- slaves construct dummy mesh (0 faces/points etc.)
but correct patches and zones
so all processors have two valid meshes. This was
all handled inside fvMeshTools::newMesh and this
was behaving differently.
This adds a 'geometry' scheme section to the system/fvSchemes:
geometry
{
type highAspectRatio;
}
These 'fvGeometryMethod's are used to calculate
- deltaCoeffs
- nonOrthoCoeffs
etc and can even modify the basic face/cellCentres calculation.
- returns a range of `int` values that can be iterated across.
For example,
for (const int proci : Pstream::subProcs()) { ... }
instead of
for
(
int proci = Pstream::firstSlave();
proci <= Pstream::lastSlave();
++proci
)
{
...
}
- returns a range of `int` values that can be iterated across.
For example,
for (const int proci : Pstream::allProcs()) { ... }
instead of
for (label proci = 0; proci < Pstream::nProcs(); ++proci) { ... }
- with '&&' conditions, often better to check for non-null autoPtr
first (it is cheap)
- check as bool instead of valid() method for cleaner code, especially
when the wrapped item itself has a valid/empty or good.
Also when handling multiple checks.
Now
if (ptr && ptr->valid())
if (ptr1 || ptr2)
instead
if (ptr.valid() && ptr->valid())
if (ptr1.valid() || ptr2.valid())
- Favour use of argList methods that are more similar to dictionary
method names with the aim of reducing the cognitive load.
* Silently deprecate two-parameter get() method in favour of the
more familiar getOrDefault.
* Silently deprecate opt() method in favour of get()
These may be verbosely deprecated in future versions.
- when windows portable executables (.exe or .dll) files are loaded,
their dependent libraries not fully loaded. For OpenFOAM this means
that the static constructors which are responsible for populating
run-time selection tables are not triggered, and most of the run-time
selectable models will simply not be available.
Possible Solution
=================
Avoid this problem by defining an additional library symbol such as
the following:
extern "C" void libName_Load() {}
in the respective library, and tag this symbol as 'unresolved' for
the linker so that it will attempt to resolve it at run-time by
loading the known libraries until it finds it. The link line would
resemble the following:
-L/some/path -llibName -ulibName_Load
Pros:
- Allows precise control of forced library loading
Cons:
- Moderately verbose adjustment of some source files (even with macro
wrapping for the declaration).
- Adjustment of numerous Make/options files and somewhat ad hoc
in nature.
- Requires additional care when implementing future libraries and/or
applications.
- This is the solution taken by the symscape patches (Richard Smith)
Possible Solution
=================
Avoid this problem by simply force loading all linked libraries.
This is done by "scraping" the information out of the respective
Make/options file (after pre-processing) and using that to define
the library list that will be passed to Foam::dlOpen() at run-time.
Pros:
- One-time (very) minimal adjustment of the sources and wmake toolchain
- Automatically applies to future applications
Cons:
- Possibly larger memory footprint of application (since all dependent
libraries are loaded).
- Possible impact on startup time (while loading libraries)
- More sensitive to build failures. Since the options files are
read and modified based on the existence of the dependent
libraries as a preprocessor step, if the libraries are initially
unavailable for the first attempt at building the application,
the dependencies will be inaccurate for later (successful) builds.
- This is solution taken by the bluecape patches (Bruno Santos)
Adopted Solution
================
The approach taken by Bruno was adopted in a modified form since
this appears to be the most easily maintained.
Additional Notes
================
It is always possible to solve this problem by defining a corresponding
'libs (...)' entry in the case system/controlDict, which forces a dlOpen
of the listed libraries. This is obviously less than ideal for large-scale
changes, but can work to resolve an individual problem.
The peldd utility (https://github.com/gsauthof/pe-util), which is
also packaged as part of MXE could provide yet another alternative.
Like ldd it can be used to determine the library dependencies of
binaries or libraries. This information could be used to define an
additional load layer for Windows.
- Eg, with surface writers now in surfMesh, there are fewer libraries
depending on conversion and sampling.
COMP: regularize linkage ordering and avoid some implicit linkage (#1238)
- can now safely use labelList::null() instead of emptyLabelList for
return values. No special treatment required for lists.
Possible replacements:
if (notNull(list) && list.size()) -> if (list.size())
if (isNull(list) || list.empty()) -> if (list.empty())
The receiver may still wish to handle differently to distinguish
between a null list and an empty list, but no additional special
protection is required when obtaining sizes, traversing, outputting
etc.
- makes the intent clearer and avoids the need for additional
constructor casting. Eg,
labelList(10, Zero) vs. labelList(10, 0)
scalarField(10, Zero) vs. scalarField(10, scalar(0))
vectorField(10, Zero) vs. vectorField(10, vector::zero)
- nBoundaryFaces() is often used and is identical to
(nFaces() - nInternalFaces()).
- forward the mesh nInternalFaces() and nBoundaryFaces() to
polyBoundaryMesh as nFaces() and start() respectively,
for use when operating on a polyBoundaryMesh.
STYLE:
- use identity() function with starting offset when creating boundary maps.
labelList map
(
identity(mesh.nBoundaryFaces(), mesh.nInternalFaces())
);
vs.
labelList map(mesh.nBoundaryFaces());
forAll(map, i)
{
map[i] = mesh.nInternalFaces() + i;
}
- With argList::noFunctionObjects() we use the logic added in
4b93333292 (issue #352)
By removing the '-noFunctionObjects' option, we automatically
suppress the creation of function-objects via Time (with argList
as a parameter).
There is generally no need in these cases for an additional
runTime.functionObjects().off() statement
Use the argList::noFunctionObjects() for more direct configuration
and reduce unnecessary clutter in the -help information.
In previous versions, the -noFunctionObjects would have been redundant
anyhow, so we can also just ignore it now instead.
General:
* -roots, -hostRoots, -fileHandler
Specific:
* -to <coordinateSystem> -from <coordinateSystem>
- Display -help-compat when compatibility or ignored options are available
STYLE: capitalization of options text
- simplifies usage.
Support syncPar check on names() to detect inconsistencies.
- simplify readFields, ReadFields and other routines by using these
new methods.
- what was previously termed 'setLargeCellSubset()' is now simply
'setCellSubset()' and supports memory efficient interfaces.
The new parameter ordering avoids ambiguities caused by default
parameters.
Old parameter order:
setLargeCellSubset
(
const labelList& region,
const label currentRegion,
const label patchID = -1,
const bool syncCouples = true
);
New parameter order:
setCellSubset
(
const label regioni,
const labelUList& regions,
const label patchID = -1,
const bool syncCouples = true
);
And without ambiguity:
setCellSubset
(
const labelUList& selectedCells,
const label patchID = -1,
const bool syncCouples = true
);
- support bitSet directly for specifying the selectedCells for
memory efficiency and ease of use.
- Additional constructors to perform setCellSubset() immediately,
which simplifies coding.
For example,
meshParts.set
(
zonei,
new fvMeshSubset(mesh, selectedCells)
);
Or even
return autoPtr<fvMeshSubset>::New(mesh, selectedCells);
- relocate some standard functionality to TimePaths to allow a lighter
means of managing time directories without using the entire Time
mechanism.
- optional enableLibs for Time construction (default is on)
and a corresponding argList::noLibs() and "-no-libs" option
STYLE:
- mark Time::outputTime() as deprecated MAY-2016
- use pre-increment for runTime, although there is no difference in
behaviour or performance.
This class is largely a pre-C++11 holdover. It is now possible to
simply use move construct/assignment directly.
In a few rare cases (eg, polyMesh::resetPrimitives) it has been
replaced by an autoPtr.
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 ListAppendEqOp and ListUniqueEqOp to ListOps::appendEqOp
and ListOps::UniqueEqOp, respectively for better code isolation and
documentation of purpose.
- relocated setValues to ListOps::setValue() with many more
alternative selectors possible
- relocated createWithValues to ListOps::createWithValue
for better code isolation. The default initialization value is itself
now a default parameter, which allow for less typing.
Negative indices in the locations to set are now silently ignored,
which makes it possible to use an oldToNew mapping that includes
negative indices.
- additional ListOps::createWithValue taking a single position to set,
available both in copy assign and move assign versions.
Since a negative index is ignored, it is possible to combine with
the output of List::find() etc.
STYLE: changes for PackedList
- code simplication in the PackedList iterators, including dropping
the unused operator() on iterators, which is not available in plain
list versions either.
- improved sizing for PackedBoolList creation from a labelUList.
ENH: additional List constructors, for handling single element list.
- can assist in reducing constructor ambiguity, but can also helps
memory optimization when creating a single element list.
For example,
labelListList labels(one(), identity(mesh.nFaces()));
- 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
- constructor for empty cell/face/point Zones, with contents to be
transferred in later.
- ZoneMesh::operator(const word&) to return existing zone or a new empty one.
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;