- exprValueFieldTag is an extended version of exprValue,
with additional Field/List uniformity handling
- the exprValueFieldTag reduce() method provides a more efficient
method than using a regular combine operator. Since fields are
usually non-uniform, will mostly only need the bitwise reduce and
not a more expensive gather/combine.
ENH: output of exprValue (scalar type) now includes '.'
- prevents scalar/label ambiguity for values like '100.0', which would
otherwise be written as '100' and thus interpreted as a label value
when re-reading.
- the ensightReadFile init() now automatically sets up binary/ascii
(for geometry files) and checks for the transient "BEGIN TIME STEP"
marker. If found, will also populate the file offsets for each of
the timesteps. If no corresponding footer is found (which would be
very inefficient), it simply pretends that there is only a single
time step instead of performing a costly file scan.
- parsing of the ensight case file now also supports the use of
filename numbers:
as an alternative to
filename start number:
filename increment:
- improved parsing robustness of "time values:" entry.
Can now also have contents on the same line as the introducer.
ENH: base-level adjustments for writing transient single-file
- beginGeometry() is now separated out from file creation.
- in append mode, ensightFile and ensightGeoFile will attempt to
parse existing time-step information.
- previous support for file appending (largely unused) always
specified opening with the std::ios_base::app flag.
Now differentiate between append behaviours:
APPEND_APP
~~~~~~~~~~
Corresponds to std::ios_base::app behaviour:
- Existing files will be preserved and a seek-to-end is performed at
every write. With this mode seeks/repositioning within the file
will effectively be ignored on output.
APPEND_ATE
~~~~~~~~~~
Largely approximates std::ios_base::ate behaviour:
- Existing files will be preserved and a seek-to-end is performed
immediately after opening, but not subsequently. Can use seekp()
to overwrite parts of a file.
- boundary entries with writeEntry(const word&, ...) instead of
writeEntry(const keyType&, ...) to match with most other
writeEntry() signatures. Also, this content will not be used
to supply regex matched sub-dictionaries.
STYLE: more consistent patch initEvaluate()/evaluate() coding
- delay construction of message buffer
- OStringStream count() method to test if anything has been streamed
STYLE: explicit use of std::ios_base in IOstreams
- document the return information of set flag methods
- can be used with this type of code:
ITstream* streamPtr = dict.findStream(name);
if (streamPtr)
{
auto& is = *streamPtr;
...
}
versus:
const entry* eptr = dict.findEntry(name);
if (eptr && eptr->isStream())
{
auto& is = eptr->stream();
...
}
ENH: add findStream(), streamPtr(), isStream() to dictionary search
- symmetric with findDict(), dictPtr(), isDict() methods
STYLE: use findDict() instead of found() + subDict() pairing
COMP: define is_globalIOobject trait at top of IOobject header
- more visibility, permits reuse for specializations etc.
- the maxCommsSize variable is used to 'chunk' large data transfers
(eg, with PstreamBuffers) into a multi-pass send/recv sequence.
The send/recv windows for chunk-wise transfers:
iter data window
---- -----------
0 [0, 1*chunk]
1 [1*chunk, 2*chunk]
2 [2*chunk, 3*chunk]
...
Since we mostly send/recv in bytes, the current internal limit
for MPI counts (INT_MAX) can be hit rather quickly.
The chunking limit should thus also be INT_MAX, but since it is
rather tedious to specify such large numbers, can instead use
maxCommsSize = -1
to specify (INT_MAX-1) as the limit.
The default value of maxCommsSize = 0 (ie, no chunking).
Note
~~~~
In previous versions, the number of chunks was determined by the
sender sizes. This required an additional MPI_Allreduce to establish
an overall consistent number of chunks to walk. This additional
overhead each time meant that maxCommsSize was rarely actually
enabled.
We can, however, instead rely on the send/recv buffers having been
consistently sized and simply walk through the local send/recvs until
no further chunks need to be exchanged. As an additional enhancement,
the message tags are connected to chunking iteration, which allows
the setup of all send/recvs without an intermediate Allwait.
ENH: extend UPstream::probeMessage to use int64 instead of int for sizes
- the timeSelector is often used to select single or multiple times
(eg, for post-processing). However, there are a few applications
where only a *single* time should be selected and set.
These are now covered by this type of use:
timeSelector::addOptions_singleTime(); // Single-time options
...
// Allow override of time from specified time options, or no-op
timeSelector::setTimeIfPresent(runTime, args);
In some cases, if can be desirable to force starting from the
initial Time=0 when no time options have been specified:
// Set time from specified time options, or force start from Time=0
timeSelector::setTimeIfPresent(runTime, args, true);
These changes make a number of includes redundant:
* addTimeOptions.H
* checkConstantOption.H
* checkTimeOption.H
* checkTimeOptions.H
* checkTimeOptionsNoConstant.H
ENH: add time handling to setFields, setAlphaField (#3143)
Co-authored-by: Johan Roenby <>
STYLE: replace instant("constant") with instant(0, "constant")
- avoids relying on atof parse behaviour returning zero
- for example,
string buffer = ...;
SubStrings<string> split;
{
auto colon = buffer.find(':');
if (colon != std::string::npos)
{
split = stringOps::splitSpace(buffer, colon+1);
}
}
Not really possible with a substr() since that would create a new
temporary which then disappears. Similarly awkward to split and
then scan for the ':' to decide how many to discard.
ENH: add pop_front() and pop_back() methods to SubStrings
- the content is trivial enough (a pair of iterators) and the total
number of elements is usually reasonable short so that removal of
elements is inexpensive
For example,
string buffer = ...;
auto split = stringOps::splitSpace(buffer);
if (!split.empty() && split[0].str() == "face")
{
split.pop_front();
}
- "buffered" corresponds to MPI_Bsend (buffered send),
whereas the old name "blocking" is misleading since the
regular MPI_Send also blocks until completion
(ie, buffer can be reused).
ENH: IPstream::read() returns std::streamsize instead of label (#3152)
- previously returned a 'label' but std::streamsize is consistent with
the input parameter and will help with later adjustments.
- use <label> instead of <int> for internal accounting of the message
size, for consistency with the underyling List<char> buffers used.
- improve handling for corner case of IPstream receive with
non-blocking, although this combination is not used anywhere
- return autoPtr<token::compound> instead of the derived type,
otherwise cannot easily construct a token from it
ENH: additional typed version of refCompoundToken()
- symmetric with typed version of transferCompoundToken()
and isCompound()
- add ITstream::findCompound<Type>() method.
Useful for searching within token streams
- UPstream::Communicator is similar to UPstream::Request to
wrap/unwrap MPI_Comm. Provides a 'lookup' method to transcribe
the internal OpenFOAM communicator tracking to the opaque wrapped
version.
- provide an 'openfoam_mpi.H' interfacing file, which includes
the <mpi.h> as well as casting routines.
Example (caution: ugly!)
MPI_Comm myComm =
PstreamUtils::Cast::to_mpi
(
UPstream::Communicator::lookup(UPstream::worldComm)
);
- The internal storage location of finite-area changes from being
piggybacked on the polyMesh registry to a having its own dedicated
registry:
* allows a clearer separation of field types without name clashes.
* prerequisite for supporting multiple finite-area regions (future)
Old Locations:
```
0/Us
constant/faMesh
system/faMeshDefinition
system/faSchemes
system/faSolution
```
New Locations:
```
0/finite-area/Us
constant/finite-area/faMesh
system/finite-area/faMeshDefinition (or system/faMeshDefinition)
system/finite-area/faSchemes
system/finite-area/faSolution
```
NOTES:
The new locations represent a hard change (breaking change) that
is normally to be avoided, but seamless compatibility handling
within the code was found to be unworkable.
The `foamUpgradeFiniteArea` script provides assistance with migration.
As a convenience, the system/faMeshDefinition location continues
to be supported (may be deprecated in the future).
- Delete() will perform a 'checkOut()' which does the following:
* remove the object from the registry
* delete the pointer (if owned by the registry)
- Release() does the following:
* transfer ownership of the pointer (if owned by the registry)
- Store() does the following:
* transfer ownership of the pointer to the registry
ENH: use UPtrList of sorted objects for MeshObject updates
- few allocations and lower overhead than using a HashTable,
ensures the same walk order over the objects (in parallel)
STYLE: adjust meshObject debug statements
- previously would always return "constant" as the instance for
an optional dir/file that wasn't found.
However, this meant retesting to screen out false positives.
Now support an additional parameter
'bool constant_fallback = ...'
to return "constant" or an empty word.
The method signature changes slightly with a new optional bool
parameter:
//! Return \c "constant" instead of \c "" if the search failed
const bool constant_fallback = true
ENH: code consolidation for findInstancePath
- relocate from Time to TimePaths and provide an additional static
version that is reused in fileOperations
BUG: distributedTriSurfaceMesh:::findLocalInstance broken (#3135)
- was not checking the parent at all.
COMP: remove unused findInstancePath(const fileName&, ..) method
- provide no_topology() characteristic to avoid triggering potentially
expensive mesh connectivity calculations when they are not required.
- remove/deprecate unused pointField references from the renumber
methods. These appear to have crept in from outer similarities
with decompositionMethod, but have no meaning for renumbering.
- remove/deprecate various unused aggregation renumberings since these
have been previously replaced by pre-calling calcCellCells, or
using bandCompression directly.
- make regionFaceOrder for block-wise renumbering optional and
treat as experimental (ie, default is now disabled).
The original idea was to sort the intra-region and inter-region faces
separately. However, this will mostly lead to non-upper triangular
ordering between regions, which checkMesh and others don't really like.
ENH: add timing information for various renumberMesh stages
ENH: add reset of clockTime and cpuTime increment
- simplifies section-wise timings
ENH: add globalIndex::null() and fieldTypes::processorType conveniences
- provides more central management of these characteristics
- renumberMesh now has -dry-run, -write-maps, -no-fields,
-renumber-method, -renumber-coeffs options.
* Use -dry-run with -write-maps to visualize the before/after
effects of renumbering (creates a VTK file).
* -no-fields to renumber the mesh only.
This is useful and faster when the input fields are uniform
and the -overwrite option is specified.
* -renumber-method allows a quick means of specifying a different
default renumber method (instead of Cuthill-McKee).
The -renumber-coeffs option allows passing of dictionary content
for the method.
Examples,
// Different ways to specify reverse Cuthill-McKee
* -renumber-method RCM
* -renumber-coeffs 'reverse true;'
* -renumber-method CuthillMcKee
* -renumber-coeffs 'reverse true;'
* -renumber-coeffs 'method CuthillMcKee; reverse true;'
// Other (without dictionary coefficients)
* renumberMesh -renumber-method random
// Other (with dictionary coefficients)
renumberMesh \
-renumber-method spring \
-renumber-coeffs 'maxCo 0.1; maxIter 1000; freezeFraction 0.99;'
// Other (with additional libraries)
renumberMesh -renumber-method zoltan -lib zoltanRenumber
COMP: build zoltan renumbering to MPI-specific location
- zoltan and Sloan renumbering are now longer automatically linked to
the renumberMesh utility but must be separately loaded by a
command-line option or through a dictionary "libs" entry.
ENH: add output cellID for decomposePar -dry-run -cellDist
ENH: eliminate unnecessary duplicate communicator
- in globalMeshData previously had a comm_dup hack to avoid clashes
with deltaCoeffs calculations. However, this was largely due to a
manual implementation of reduce() that used point-to-point
communication. This has since been updated to use an MPI_Allreduce
and now an MPI_Allgather, neither of which need this hack.
- this was previously a UList instead of SubList,
but SubList supports better assignment of values
ENH: add invertOneToManyCompact
- returns a CompactListList<label> instead of labelListList, which
allows for reuse as partitioning table etc and/or slightly reduced
memory overhead
- add convenience forms for common combinations
- avoid allocation for 1:1 identity agglomerations
- support subsetting forms (avoids an intermediate fvMeshSubset)
that also return the cellMap
- refactored to eliminate code duplication between weighted and
unweighted forms
- construct Map/HashTable from key/value lists.
- invertToMap() : like invert() but returns a Map<label>,
which is useful for sparse numbering
- inplaceRenumber() : taking a Map<label> for the mapper
ENH: construct/reset CStringList for list of C-strings
- can use UList signature since the routines do not resize the list
or attempt to broadcast it: useful for SubList handling.
ENH: add IPstream/OPstream send/recv static methods
- the old Pstream::scatter routines (which were largely a misnomer)
have been superseded by various broadcast routines, but were left in
the code with #ifndef/#ifdef Foam_Pstream_scatter_nobroadcast
guards. Now noisily deprecate them, and remove the old manual tree
communication in favour of MPI broadcast and/or
serialize/de-serialize with wrapped Pstream::broadcast
- consolidate various gather methods to include the communication
structure directly. No functional change, but reduces the number of
methods.
ENH: add parallel guard to UPstream::whichCommunication() method
- returns List::null() as the schedule for non-parallel instead
of an inappropriate linear or tree schedule
ENH: Pstream::listGatherValues, Pstream::listScatterValues
- like the existing UPstream versions but supporting non-contiguous
- adjointOptimisation : missing link to fileFormats
- snappyHexMesh : add fvMotionSolvers link (#3058)
STYLE: remove remnant -DFULLDEBUG hints
- now more easily covered with wmake -debug ...
- on large memory systems (eg, 6TB) the process information
exceeds an 'int' range, so adjust parsing of the /proc/..
to use int64
ENH: update/modernize OSspecific system information
ENH: minor update of profiling code
- std::string, noexcept, lazier evaluations
STYLE: use direct call of memInfo
- use Foam::zero as a dispatch tag
FIX: return moleculeCloud::constProps() List by reference not copy
STYLE: range-for when iterating cloud parcels
STYLE: more consistent typedefs / declarations for Clouds
- simplifies handling.
* enables unprotecting to avoid accidentally cloning.
* removes the need for dedicated constructor or factory forms.
* simplfies DimensionedField and GeometricField New factory methods
- update objectRegistry management method (internal use)
old: bool cacheTemporaryObject(...)
new: bool is_cacheTemporaryObject(...)
to clarify that it is a query, not a request for caching etc.
- replace typeGlobal() global function with is_globalIOobject
traits for more consistent and easier overriding.
- relocate typeFilePath() global function as a member of IOobject
for consistency with typeHeaderOk.
BUG: faSchemes, fvSchemes not marked as global file types
- caused issues with collated
- provide a globalIndex::calcOffsets() taking an indirect list, which
enables convenient offsets calculation from a variety of inputs.
- new CompactListList unpack variant: copy_unpack()
The copy_unpack() works somewhat like std::copy() in that it writes
the generated sublists to iterator positions, which makes this
type of code possible:
CompactListList<label> compact = ...;
DynamicList<face> extracted;
compact.copy_unpack<face>
(
std::back_inserter(extracted),
labelRange(4, 10)
);
-and-
const label nOldFaces = allFaces.size();
allFaces.resize(allFaces + nNewFaces);
auto iter = allFaces.begin(nOldFaces);
iter = compact.copy_unpack<face>(iter, /* selection 1 */);
...
iter = compact.copy_unpack<face>(iter, /* selection 2 */);
ENH: globalIndex resize()
- can be used to shrink or grow the offsets table.
Any extension of the offsets table corresponds to 'slots'
with 0 local size.
- allows construction of string tokens holding character content.
For example, data that has been serialized and buffered and that
now needs to be written or sent to another process.