- introduce wallHeatFluxModel base class for extensible heat flux models
- add 'wall' model implementing original wallHeatFlux function object
- add 'gauge' model for heat-flux gauge measurements with custom temperature
The gauge model enables simulation of heat-flux gauges at specified locations
with configurable temperature, absorptivity, and emissivity properties.
- add support for convective and radiative heat flux calculations in gauge model
- makes fileHandler calling resemble Time more closely
ENH: provide natural_sort less/greater functions
- more succinct than (compare < 0) or (compare > 0).
The corresponding wrappers for UList renamed as list_less, etc
but they were only used in unit tests
ENH: handle (-allRegions | -all-regions, ..) directly when retrieving args
- makes handling independent of aliasing order
STYLE: include <string_view> when including <string>
- the standard does not guarantee which headers (if any) actually
include string_view
Ideally wish to delay construction of the finite-area mesh until
updateCoeffs(), when it is actually needed.
This helps avoid difficult to trace errors and avoids inadvertent
parallel communication during construction from a dictionary.
However, lazy evaluation fails at the later stage while attempting
to load the corresponding initial fields, since the timeIndex has
already advanced.
Use the newly introduced regionModels::allowFaModels() switch
to locally enable or disable lazy evaluation as needed.
This allows selective disabling (eg, in post-processing utilities)
where loading the volume field should not activate the associated
regionFaModel and loading a finite-area mesh too (which may not
exist or be defined at that point).
- less typing than before and avoids relying on bash-specific behaviour
(fixes#3448)
ENH: add -region support for cleanFaMesh and cleanPolyMesh
CONFIG: add bash completion help for -area-region
ENH: general improvements for regionProperties
- robustness and failsafe for foamListRegions, regionProperties
- additional global model switches for regionModels
- further hide implementation (cxx ending)
STYLE: better distinction between code/templates for fileFormats/conversion
- for ensight and vtk, a large part of the code is header only.
Make this easier to identify
- add provisional support for selecting MPI_Gatherv
when merging fields in the surface writers.
Uses the 'gatherv' keyword [experimental]
BUG: gatherv/scatterv wrappers used the incorrect data type
- incorrectly checked against UPstream_basic_dataType trait instead of
UPstream_dataType, which resulted in a count mismatch for
user-defined types (eg, vector, tensor,...).
This was not visibly active bug, since previous internal uses of
gatherv were restricted to primitive types.
COMP: make UPstream dataType traits size(...) constexpr
- allows static asserts and/or compile-time selection
of code based on size(1)
- for a non-default mesh region, corresponding files:
system/finite-area/faOptions.<name>
system/finite-area/<name>/faSchemes, etc
if the entries within the faOptions dictionary happen to contain an
"area" entry and it conflicts with what is expected, it will be
rejected when creating the list of options, which helps avoid
unexpected behaviour and simplifies overall handling.
- unlike fvMesh and polyMesh, the faMesh mesh region name is passed
separately into constructors and functions. Thus need the same for
faMeshTools and faMeshSubset.
- ensure that an empty area name is treated like
polyMesh::defaultRegion.
The faMeshRegistry or other registries cannot have an empty name!
- extend the getAllRegionOptions and getAllFaRegionOptions handling
to use the supplied string literals as fallback values.
If regionProperties is missing (or empty) and the -regions/-area-regions
option is supplied with literal names, these will be used directly
instead of being used to filter the regionProperties.
STYLE: support both -all-regions and -allRegions
- in some shell models, only the mechanical properties (rho,E,nu) are
meaningful or just the basic thermal properties
(rho,Cp,kappa,emissivity).
Add a distinction when reading the dictionary entries
if those properties are mandatory and the thermo properties
(eg, molWt, Cp, etc) are optional or not.
This simplifies user input for thermal and vibration shell models.
- activeRequest() checks if given request is still active/pending
- finishedRequest() will now always call MPI_Test when running in
parallel instead of using a fast-path for skipping a null request.
This allows MPI a chance to progress operations even if that
particular request is not active.
- sameProcs() is a convenience wrapper for the following:
* check if indices resolve to the same underlying procs
* check the communicator procs against a list of procs
* to compare two lists of procs.
For example, check if the communicator corresponds to a
host-local communication:
if (UPstream::sameProcs(UPstream::commLocalNode(), myComm)) ...
STYLE: UPstream::Request gets an 'active()' method
- more MPI idiomatic than 'good'
- to avoid the many overload warnings on that platform,
may wish to use
FOAM_EXTRA_CXXFLAGS="-Wno-overloaded-virtual"
GIT: remove some old compilation stub files
- adjust the if/else-if/else-if cascade to have 'if constexpr (..)'
first and the *entire* alternate branch within the following 'else'.
This lets the compiler know that it can safely discarded the other
parts.
This change introduces a large amount of indentation change,
so use `--ignore-space-change` when inspecting.
COMP: reintroduce UList<T>() initialization in List [silence gcc]
COMP: use std::min() instead of direct check [silence gcc]
- gcc complains about possible strict-overflow for this:
```
if (count > len)
{
count = len; // The count truncated by the new length
}
```
Using `count = std::min(count, len);` avoids these (spurious)
warnings without adding a "diagnostic ignored" pragma
STYLE: pass std::pair<int,int> by copy [cheaper]
STYLE: make isdigit() and isspace() tests constexpr
- constexpr and C-locale only vs. the std counterparts
- extend time searching mechanisms to support searching in the case
global path: times(), findClosestTime(), findInstancePath()
- extend IOobject path() and objectPath() methods with
IOobjectOption::Layout variants
The changes are needed for addressing a global file structure
in parallel (#3431)
- add '<=' and '>=' operators that include rounding.
This means that typical code like the following would not have
considered any rounding:
instantList times = ...;
scalar val = ..;
// No rounding!
if (times[i].value() <= val) { ... }
// NEW: with rounding
if (times[i] <= val) { ... }
// old equivalent:
if (times[i].value() <= val || times[i].equal(val)) { ... }
ENH: provide a default stopInstance for fileOperation::findInstance
- makes it more consistent with Time::findInstance and more convenient
to use
STYLE: minor code style changes to TimePaths etc
- enables partial overwriting of content
- make default construct zero-sized, add reserve_exact() method
- improve sizing behaviour of OCharStream.
Since char buffers will approach the INT_MAX size more quickly than
other content, adapt the following strategy:
| Capacity range | Strategy |
|--------------------|------------------------------|
| 0 < N <= 0.25) | fast growth (2) |
| 0.25 < N <= 0.5) | slower growth (1.5) |
| 0.5 < N <= 0.75) | very slow growth (1.25) |
| 0.75 < N | already large - use max |
- improves usability of List as a general dynamic container as member
data without inheritance. Provide the same method for DynamicList
to enable more efficient use.
- additional string_view support for charList: useful when being used
as a character buffer
STYLE: improve allocation handling in List
- consolidate routines. Only assign size after allocation to ensure
that states are always consistent.
- make memory streams header-only (simpler)
- add sub-views and direct seek for span streams
New IOobject convenience methods
- IOobject::instanceValue() : return the IOobject instance as a scalar
value (or 0). Effectively the same as instant(io.instance()).value()
but with far less typing.
- IOobject::fileModificationChecking_masterOnly() : combines checks for
time-stamp and inotify variants
STYLE: minor adjustments for Enum
- can now create an empty entry and add/overwrite with tokens afterwards,
or copy/move construct from a list of tokens.
ENH: provided named token setter methods (disambiguates bool/char/label)
COMP: use 'if constexpr' for FlatOutput
DOC: more description for Field
- num_blocks(), test_set() as per boost
- broadcast(), reduceAnd(), reduceOr() to simplify parallel operations
- matrix-like output for PackedList::writeList()
BUG: Pstream::broadcastList() missing resize on sub-ranks
- latent bug since it was unused in any OpenFOAM code
- the snGradTransformDiag() is used in this type of code:
```
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type
return tmp<Field<Type>>::New(this->size(), pTraits<Type>::one);
}
else
{
return pTraits<Type>::one - snGradTransformDiag();
}
```
This implies that a rotational-invariant form should return 0
and not 1 like the pow(..., 0) does.
This is a backstop for any code that may inadvertently hit it,
but also allows the possibility of having integer indicator fields
without upsetting the compiler.
STYLE: doTransform() logic now uses is_rotational_vectorspace
- a special case of fixedValue with a value of zero:
* non-assignable
* no mapping needed
* value internal coeffs are zero
* value boundary coeffs are zero
- align some of the internal handling with each other and with
CompactListList
ENH: add readContentsSize to IOList, IOField etc.
- sometimes just need to know how many elements are stored on disk
without actually caring about the content. In those cases, can
frequently just get that information from the first label token
without needing to read anything else.
- the logic has been revised to allow list copying with nullptr entries.
These previously would have thrown an error.
- remove PtrList trimTrailingNull() method.
It was unused and would result in inconsistent addressing sizes.
FIX: inconsistent sizing used for DynamicList/PtrDynList clearStorage()
- older code did not reset addressable size prior to clearStorage()
or transfer(). Only a latent bug until memory pools are used.
- can be used in most places where checkType=false is used
ENH: add non-const get() method to HashPtrTable
- allows checking and modification (symmetric with PtrList methods)
STYLE: improve annotations in fileOperations headers
- previously handled stdin redirection as part of the run command but
(as Alexey Matveichev noted) this meant the command would actually
require an `eval` for this to work. Instead redirect before executing
the run command.
- can always use 'echo -e' (bash builtin) in mpirunDebug
CONFIG: add removal of mpirun.files/ to CleanFunctions
- leave mpirun.log/ files untouched, since they may still be useful
for later diagnosis
- provides some additional safety and precludes any recursive searching
ENH: support local directory handling in regionProperties
- allows alternative locations. Eg, for finite-area (#3419)
- since direct streaming of particles is only ever used internally and
never for disk I/O (which is collated by property), mixed precision
will never occur when constructing a particle from a stream.
Due to padding issues, the previous code would have been faulty anyhow.
Thus remove that code and replace with a simple sanity check.
- appears to hit single precision overflow with clang-15 in
face::center(), cellModel::center() and blockMesh createPoints().
The blockMesh might be particularly sensitive, since the points are
frequently defined in millimeters (scaled later), which results
in large intermediate summations.
Similar to primitiveMesh checks, use double precision for these
calculations.
ENH: support vector += and -= from compatible types
- eg, doubleVector += floatVector is now supported.
This streamlines some coding for mixed precision.
- To avoid lots of boilerplate, do not yet attempt to support general
operations such as `operator+(doubleVector, floatVector)`
until they become necessary.
- since pointConstraint is a tuple of (label, vector) not simply use
readRawLabel, readRawScalar since the tuple will also include
trailing padding and/or padding between its members
FIX: remove flawed handling of non-native precision for directionInfo
- packing of (label, vector) makes handling of non-native content
non-trivial (#3412). Content is only streamed, not written to disk,
so replace with a fatalCheck.
- local templates and 'if constexpr' to simplify logic and reduce
reliance on pre-processor defines.
FIX: readScalarOrDefault used scalarToken() not number() token
- will rarely (or never) be triggered, but was inconsistent
- as seen in #3201, using count() based on the ostringstream tellp
is not reliable since it is not updated with reset or copying.
STYLE: minor changes to string/char/span streams
- update docs to only mention string_view
- use auto return, without extra trailing 'decltype'
ENH: add IOstream size check helper methods
* checkNativeSizes() : test only
* fatalCheckNativeSizes() : an assert with FatalIOError
- find patch by name and return pointer to it. Similar to cfindZone()
ENH: robuster PatchFunction1 handling for uniformFixedValuePointPatchField
COMP: use 'if constexpr' with is_contiguous check
STYLE: consistent patch slicing parameters
- slice UList values, not List values
- base DimensionedField on DynamicField instead of Field to allow
convenient resizing
- initial infrastructure for unified GeometricField handling with
the boundaryEvaluate() method
Co-authored-by: <Mark.Olesen@keysight.com>
- regular or forced assignment from `zero` does not need dimension
checking:
Old: U = dimensionedVector(U.dimensions(), Zero);
New: U = Zero;
this eliminates a fair bit of clutter and simplifies new coding
without losing general dimension checking capabilities.
- reserve() did not set the addressable size to the current capacity
before resizing, which meant that the delete[] would not have the
true allocated size. Only affects memory-pool usage (#3381), which
is not yet integrated
ENH: remove unused DynamicList '*_unsafe()' methods
- can result in a mismatch between allocated and addressed sizes,
which becomes important for memory-pool usage.
Triggers function object to execute on the first time step.
Example usage:
minMax1
{
type fieldMinMax;
libs (fieldFunctionObjects);
writeControl onStart;
fields (".*");
}
Ref: EP2608
Correcting bug introduced when trying to keep the old communicator.
We do not need local communicator if all ranks of comm have
some faces. Not all ranks of the already local communicator.
- previous handling of forced inclusion of the master would taint the
logic about single vs multiple ranks.
- be fussier about avoing creation of a local communicator when not
needed.
STYLE: rename internal switch from localComm_ to useLocalComm_
- less confusing (it is a switch, not the communicator itself)
- setting the warnComm is useful for diagnosing multi-world issues but
triggers many false warnings when used in combination with AMI local
communicators.
COMP: unresolved pTraits<long int> for reductions on i586 systems
- now always just use int64_t instead of off_t and time_t
for master reductions.
Note that this is not the only place where the off_t definition
causes compilation issues (cf. fileOperation::broadcastCopy)
- in many cases the local communicator has the same communication
pattern for several timesteps so it can be reused instead of being
recreated. Avoids repeated MPI_Comm_free()/MPI_Comm_group() calls
- STYLE: eliminate bitSet intermediate when determining the sub-ranks
Calculates thrust, drag, torque and lift/drag/pressure coefficients
of single or multiple blades (eg, propeller, turbine blades)
This function object differs from the propellerInfo and forces
function objects in that all forces are calculated within the local
cylindrical coordinate system, which yields thrust and drag values
within the expected reference frame.
The output comprises:
- coefficients per radial bin
- area-weighted total coefficients
- integrated forces and torque
For convenient post-processing, the results are also written in a VTK
(.vtp) output format. All surface results are registered internally,
which makes them available for other function objects.
- originally only listed in functionObjectList, now also list the same
information under namespace functionObjects so it is more likely to
be found. Document the behaviour as a table to make it more
immediately visible than the text form.
- the indices(const wordRes& allow, const wordRes& deny) methods
were not defined consistently with the wordRes::filter handling.
wordRes::filter - allow/deny both empty:
= no filtering (ie, accept everything)
indices(allow,deny) - allow/deny both empty:
= return identity list (NEW behaviour)
= return empty list (OLD behaviour)
Consider the old behaviour a minor bug since the limited number of
callers had their own checks that avoided the poor behaviour.
Example of the inconsistent behaviour:
pbm.indices(wordRes(), wordRes({"non-existent"}))
--> identity list (old, new behaviour)
pbm.indices(wordRes(), wordRes())
--> identity list (new behaviour)
--> empty list (old behaviour)
- tests for list equality with different but compatible data types.
Eg, when comparing lists of int32 and int64 values.
STYLE: pass UList instead of List references into ListOps functors
- avoids intermediate allocation and re-assignment to self (#3374)
BUG: checkMesh (application) with questionable memory handling (#3374)
- move the contents of the new points instead of attempting to transfer
the entire list
COMP: replace mapDistribute specializations with if constexpr handling
- simplify future maintenance
- in messageStream::masterStream(int), it forwarded to stream()
without the communicator, which meant it would incorrectly check
UPstream::master(worldComm) and possibly not produce any output (or
block).
ENH: align MPI_Probe non-blocking handling with header description
- the header states that the commsType is non-blocking or not,
but the implementation actually checked for 'buffered' or not.
STYLE: fix some spacing and some documentation
- use functionObject writeInterval not timeInterval.
No change in behaviour since the missing writeInterval is treated
as '1' anyhow when using 'timeStep' for the writeControl
- consistent use of 'adjustable' vs 'adjustableRunTime'
- prefer '#eval{ vector(...) }' to calling '#eval' multiple times
ENH: improvements for GeometricBoundaryField evaluation
- early termination from evaluate_if() and evaluateCoupled().
- evaluateCoupled() now forwards to evaluate_if() and receives
additional handling for a 'void' parameter type.
BREAKING: extra template parameter for overset correctBoundaryCondition
- the true/false flag as a template parameter instead of as an
argument to use 'if constexpr' code
- encapsulates (foundObject && lookupPatchField) together,
similar to cfindObject
STYLE: remove unnecessary dummy parameters from lookupPatchField
- these were a workaround for a very old gcc bug and are no longer
needed. However, retain the (unneeded) second template parameter to
continue with not breaking existing old code - it has no overhead.
Signature:
void patchInternalField(UList<Type>& pfld) const;
// OLD: void patchInternalField(Field<Type>& pfld) const;
This change is necessary to allow collection into slices of a
larger list.
ENH: add {fa,fv}PatchField::patchNeighbourField(UList<Type>&)
- a retrieval version similar to patchInternalField(...)
STYLE: adjust AMI patch field private method names
- rename private method
patchNeighbourField(...) -> getNeighbourField(...)
to avoid access clashes with public methods
- remove undefined method neighbourSideField()
- the number of false positives has reduced, but in a few remaining
cases, the compiler cannot possibly "know" that the pointer stored
on the registry will outlive the scope of the method (for example)
gcc-13: suppressing these spurious warnings needs to be done at each
caller, which is simply not worth it, since later compiler versions
provide a cleaner solution.
gcc-14: the [[gnu::no_dangling]] attribute on the declaration
lets the compiler know the intent.
- additional FOAM_REAL_GNUC macro (defined in stdFoam.H) to define
the "real" gcc version and ignoring other compilers masquerading
as gcc.
COMP: rename MeshObject code to {cxx,txx}
- avoids issues on case-insensitive filesystems (#3316)
- the output parameter was previously a field and resized according to
the patch size. Now the output parameter must be pre-sized prior to
calling, which makes it possible to collect the patch internal
fields into slices of a larger list.
Signatures:
void patchInternalField
(
const UList<Type>& internalData,
UList<Type>& pfld // OLD: Field<Type>& pfld
) const;
void patchInternalField
(
const UList<Type>& internalData,
const labelUList& addressing,
UList<Type>& pfld // OLD: Field<Type>& pfld
) const;
This low-level change is not expected to affect any user code,
which would normally use a higher-level interface such as from
fvPatchField etc.
- can be used to pre-allocate space for internal+boundary field for
flat addressing (issue #3364).
For example:
DynamicField<Type> fld
(
std::pair<label,label>
(
GeoMesh::size(mesh),
GeoMesh::size(mesh)
+ (extra ? GeoMesh::boundary_size(mesh) : label(0))
)
);
ENH: base changes for GeometricField flags
- FieldBase 'localBoundaryConsistency_' and 'localBoundaryTolerance_'
for central handling of local boundary consistency checks.
- FieldBase 'unifiedGeometricField' for future extensions to GeometricField
- include "contiguous.H" in ListPolicy, which makes it available
whenever UList.H has been included
ENH: return plain List instead of shrinking the DynamicList
- constCast() convenience methods.
This simplies coding in places, especially in solvers
- inline some methods within headers, for better overview/maintenance
- only set DimensionedField default value on construct if not read
- storeOldTimes() does not require const_cast
- makes fvPatch consistent with faPatch etc and can simplify coding
ENH: handle sizing within extrapolateInternal() patch field methods
- reduces reliance on any sub-components
ENH: extend polyBoundaryMesh patch selectors
- indices_if() method with a predicate, or with a patch-type
behaves similarly to findPatchIDs(), but returns a sorted
labelList instead of a labelHashSet
- nFaces_if() method with a predicate return the number of boundary
faces for patches matching the given predicate.
The solverPerformanceDict gets larger due to the addition of a SolverPerformance
data per field at every outer iteration within the same main iteration/time
step.
However, the subsequent functionalities seem to use only the first and last
element of this dictionary per field; therefore, storing the interim values
was revealed to be redundant.
The change removes the interim values by transforming the `List` container
into the `Pair` container, and modifying the relevant algorithms.
- this can be used as an alternative to the (-world) multi-world
option. For example, for calling OpenFOAM applications with MUI
(https://github.com/MxUI/MUI)
- can use -mpi-no-comm-dup to suppress the initial communicator
duplication (to avoid potential deadlock with coupled processes).
This is partly related to comments in merge-request !735
ENH: simplify parsing/removal of local -world option
- can extract the world name in a single pass and also makes the
parsing robuster.
ENH: support regular MPI_Comm_split()
- the two-step method of Allgather + Comm_create_group may not be
expected by other applications (issue #3127) and that can lead to
deadlock, so also add in code for the regular MPI_Comm_split.
Does not support re-sorting keys!
FIX: faulty logic for splitting communicators
- only affected more recent develop branch
- useful to have std::reduce(), std::transform_reduce() available in
more places, so treat like <algorithm> and include in "stdFoam.H"
STYLE: add 'stricter' detection markers for cast of SubList to List etc.
STYLE: remove 'const' qualifier from Foam:one/Foam::zero (in Field)
- previously had special resizing treatment for the corner case when
the addressable size and the new capacity are identical. However,
that particular approach (to minimize copying) meant that the exact
deallocation size would likely be incorrect.
Having the correct deallocation size becomes more important with
alternative allocators.
Introduce resize_copy() protected function to limit the number
of elements copied during the resize.
ENH: provide DynamicList/DynamicField constructor with sizing
- allows fine-grained creation of a DynamicList/DynamicField with a
given size/capacity without an initial value.
COMP: typo in code for DynamicList::push_back() with IndirectList
- for reciprocal values, gMinMax() first and then calculate the
reciprocal, which avoids creating temporaries
STYLE: prefer MinMax to separate min/max accounting
COMP: namespace qualify min/max for deltaT, CourantNo, etc (#3348)
- these already existed for a single value, but now handle the full
field. This is more memory-friendly.
fld.clamp_min(lower); OLD: fld = max(fld, lower);
fld.clamp_max(upper); OLD: fld = min(fld, upper);
- central way to calculate reverse sizes for dynamic containers.
For example;
reserve_size<16, 2>(len, cap); // min-size=16, ratio=2
reserve_size<16, 3, 2>(len, cap); // min-size=16, ratio=1.5
replaces this type of code that was used in several places:
max(SizeMin, max(len, label(2*capacity_)));
The caller will have already checked (len < cap) before deciding
to make this call.
ENH: updates for DynamicList/DynamicField handling
- add reserve_exact() method, which is like reserve() but without any
extra sizing heuristics
- add DynamicField 'reuse' constructors, consistent with Field constructors
- sync allocated size before list destruction.
This may help when using aligned allocation strategies.
Using 'return List<T>(std::move(dynList))' for transfer of content
(with implicit shrinking) into a plain List, and leave copy elision
to do the rest. The implicit transfer (move construct List from
DynamicList) will normally invoke resize (new/delete and moving
elements).
With 'return dynList.shrink()', it will first invoke an internal
resize (new/delete and moving elements), followed by a copy
construct as a plain list.
STYLE: avoid implicit cast to 'const List&' in constructors
- provides an additional hook when linking OSspecific
CONFIG: apply quiet flag to wmkdepend
- suppresses "could not open FileName" warnings in quiet mode
FIX: reinstate selection of strict/non-strict deprecation
- accidentally removed in cf2b305b4f.
- extend with a _STRICTER version as well.
- provide separate float/double UList interfaces, which improves
flexibility (eg, with SPDP)
- sigFpe::fillNan_if() interface, for filling in when using alternative
memory allocators
- previous code used derived string iterators, but these would
be largely ignored anyhow since the underlying std::sub_match
str() method would just yields a std::string anyhow.
The SubStrings::str(size_t) method wasn't used in any code, so now
just use std::string iterators only.
This change simplfies overall handling, since it removes an unneeded
template dependency.
- /usr/bin/{gcc,g++} normally just symlinks to clang/clang++
and may have unknown default flags.
For a gcc toolchain, it would be better to use a homebrew
installation.
For these cases, the compiler will need to be specified with
version=.. in WM_COMPILE_CONTROL.
For example, with "version=14", to select gcc-14, g++-14 from the
homebrew installation.
- needs a slight hack for locating the FlexLexer.h header.
Added into src/OSspecific/POSIX similar to how it is handled
in src/OSspecific/MSwindows
CONFIG: add simple config/detection support for libumpire (Linux)
- new options to set components specified by homebrew.
Sets version as system, path from brew --prefix
-adios-brew, -adios2-brew, -boost-brew, -cgal-brew,
-fftw-brew, -kahip-brew, -metis-brew, -scotch-brew,
-gmp-brew, -mpfr-brew
-with-homebrew
Shortcut for selecting all the above (except gmp, mpfr)
* additional special treatment for GMP and MPFR.
If using non-system locations and not part of the ThirdParty
compiler, they can additionally be set in the CGAL config file:
-gmp-brew, -gmp-path
-mpfr-brew, -mpfr-path
- easier to create type-specific looping in templated code
STYLE: pass 'direction' and 'label' by value instead of reference
COMP: qualify Foam::min() in dense matrix classes
- compiler versions are now sufficient that only the C++ regex
interface is now being used. Can remove the old POSIX code
accordingly.
This change also removes any dependency on the SubStrings class to
manage the matching results.
ENH: remove OpenFOAM dependencies from MacOS addr2line utility
- The register keyword has been removed from c++17 but old flex
versions (version < 2.6.0) produce code including it, leading to
compilation errors when using clang (despite disabling the diagnostic).
gcc compiles but issues warnings.
- use '#define register' as empty as a workaround
STYLE: mark Pstream::scatterList() as deprecated
- this entry point is not directly used anywhere, only the
scatterList_algorithm backend is actually used.
The scatterList() routine is misnomer since it actually works like a
broadcast that skips overwriting the local rank, but only if used in
combination with the gatherList() manual implementation that uses
the same walk pattern.
- can be used to simplify some logic. For example,
if
(
(tok.read(is) && tok.isWord("FoamFile"))
&& (tok.read(is) && tok.isPunctuation(token::BEGIN_BLOCK))
)
...
vs
if
(
(is.good() && (is >> tok) && tok.isWord("FoamFile")) ...
&& (is.good() && (is >> tok) && tok.isPunctuation(token::BEGIN_BLOCK))
) ...
- compiler cannot decide between std::string and std::string_view
when creating from 'const char*' without also supplying the size,
so also supply a 'const char*' constructor.
ENH: additional string_view handling for ITstream and SubStrings
- the 'move' treatment performs a shallow copy but does not alter
the passed parameter. Identical semantics as per std::span.
ENH: constexpr for basic HashTable constructors
STYLE: 'Foam::zero' instead of 'const Foam::zero' for containers
- this is simply a compiler dispatch flag, so the additional 'const'
qualifier is unnecessary
- should ideally avoid SLList in most cases, since it is allocation
intensive and most places can easily use DynamicList or
CircularBuffer instead.
STYLE: use push_uniq instead of deprecated appendUniq method
- mark with a 'normal' deprecation instead of 'strict' deprecation
- the '-no-core' to limit coredumps to zero size
- the '-quick' option, which changes valgrind --leak-check from "full"
to "summary", and implies -no-core as well.
- enforce tcp libfabrics provider under valgrind since valgrind
does not otherwie work nicely with RMA
- fails with MPI_ARG_ERR.
Do not assume that any vendors actually support in-place handling
for MPI_Reduce(), regardless of what their documentation may claim.
- includes intrinsic MPI types, but no component aggregates since we
barely wish to use gatherv/scatterv (slow!) in the first place
and it makes no sense to recalculate the list of counts for
component aggregates which we will never use.
- for known data types (and component aggregates),
and intrisic reduction operation can now use
UPstream::mpiReduce(), UPstream::mpiAllReduce().
This change permits more operations to use MPI calls directly.
eg,
reduce(vec, sumOp<vector>);
now calls mpiAllReduce(..., op_sum) instead of point-to-point,
followed by a broadcast.
Similarly, when called as a simple reduction (not all-reduce)
Pstream::gather(vec, sumOp<vector>);
now calls mpiReduce(..., op_sum) instead of point-to-point
- extend use of MPI calls to list-wise reductions as well
- extend sumReduce() to bundle/unbundle vector-space types,
which lowers overall communication.
Before:
1) send/recv + binary op through a communication tree
2) broadcast
3) all-reduce of the count
Now:
1) pack into a local bundle
2) all-reduce
3) unpack the bundle
- support send/recv of basic types (int32, float, double, ...) in
addition to common OpenFOAM vectorspace types (floatVector,
doubleVector, ...)
This permits sending NUM items of the given types instead of sending
NUM sizeof() bytes.
For a vector (as double): 1 item instead of 24 items (3*8 bytes).
For a tensor (as double): 1 item instead of 72 items (9*8 bytes).
- simplify and rationalize some of the broadcast methods for more code
reuse.
The bottom level UPstream::broadcast is now always to/from "root=0".
This was previously passed as a default parameter, but never used
anything other than '0' in the code. Fixing it as '0' makes it
consistent with the 'top-down' logical for node-based broadcast.
- now distinguish between basic MPI types and user-defined types.
The new front-facing trait UPstream_basic_dataType unwinds components
and other types, but only for MPI fundamental types
(including any aliases)
- additional helper to combine a test for binary operator validity and
basic data type validity, which better expresses intent:
template<class BinaryOp, class T>
UPstream_data_opType;
- relax bit-wise operators to also accept signed integrals
and 'void' generic
- remove unused/unusable broadcast stream constructors/methods
- provide OPBstream::sends() and IPBstream::recvs() methods,
refactored from Pstream::broadcasts. These will always use
serializations, even for contiguous content.
- additional methods to support special handling of zero-sized lists.
For example,
if (UPstream::master(comm))
{
if (list.empty()) OPBstream::send(Foam::zero, comm);
else OPBstream::send(list, comm);
}
else
{
IPBstream is(comm);
if (is.remaining()) { is >> list; }
else { list.clear(); }
}
This avoids serialization of an empty list and the resulting double
broadcast (size + content), using instead a single broadcast (size).
STYLE: more consistency in communicator types (int vs label)
- returns the (start/size) range of the commLocalNode ranks in terms
of the (const) world communicator processors. This allows mapping
back into lists defined in terms of the world ranks.
- similar to what std::copy_n and std::fill_n would do, except with
templated loops. This allows compile-time transcribing with loop
unrolling. For example,
vector vec1 = ..., vec2 = ...;
FixedList<scalar, 6> values;
VectorSpaceOps<3>::copy_n(vec1.begin(), values.begin());
VectorSpaceOps<3>::copy_n(vec2.begin(), values.begin(3))
// do something with all of these values
STYLE: make start index of VectorSpaceOps optional
ENH: add clamped begin(int) versions to FixedList as per UList
The front-end traits:
- UPstream_dataType trait:
This wrapper is unwinds the type to check against base/alias, but also
checks if it is a component aggregate of a supported UPstream data type.
This will be that main entry point for usage.
- UPstream_opType trait:
Provides a mapping of OpenFOAM ops to their MPI equivalent.
The \c opcode_id is the corresponding internal representation.
The lower-level traits (not normally used within coding)
- UPstream_base_dataType trait:
Tests true/false if the specified data type has an internal MPI equivalent.
The \c datatype_id is the corresponding internal enumeration.
Even if this tests as false, it will always return \c type_byte as the
fallback for general contiguous data
- UPstream_alias_dataType trait:
Provides mapping for <int/long/long long,...> to the fundamental 32/64
integrals, since <int/long/long long,...> may not otherwise directly map
on all systems.
NOTE: can use the updates Test-machine-sizes test application to
determine if all data types and aliases are properly defined on
different systems
- this will allow send/recv/broadcast of various data types directly
without reinterpreting as bytes. No performance benefit, but makes
programming more flexible. In addition to the normal MPI types, also
provide some convenient groupings such as double[3], double[9] etc.
- the additional user-defined data types are created on the start of
MPI and removed before shutdown
- previously there were two places that used nProcsSimpleSum for
defining the communication pattern. However, this meant in practice
that filling of linearCommunication_ and treeCommunication_ themselves
where globally controlled.
Now retain the state within commsStructList and use linear/tree
when populating.
- deprecated and replaced (JAN-2023) with a version that uses
UPstream::Request to track the request. This avoids placing a
request on the global list and then having difficulty isolating it
later (or having it cleared out by someone else).
ENH: UPstream::addRequest() now ignores null requests
- avoids placing useless requests on the global list
- replace with plusOp for reductions. The old use didn't necessarily work
well with compiler resolution in all cases.
Simplify to use plusOp (and removed the old version).
[Does not affect very much code...]
COMP: incorrect include ordering for GeometricFieldFunctions
- header was included after the template code
REGRESSION: combineAllGather mapped to incorrect method (81fa7d08ee)
STYLE: use UPstream::commWarn(...) setter method
- eliminates nearly identical code between 'gather' and 'combineGather'
* Normal gather updates by assigning the result of the binary operation.
* Combine gather updates by using a binary operator that modifies
its first parameter in-place
By-product of this refactoring are these new variants:
listGather(), listGatherReduce()
mapGather(), mapGatherReduce()
that mirror the previously existing ones
listCombineGather(), listCombineReduce()
mapCombineGather(), mapCombineReduce()
except that they use the 'regular' binary operator
- the general OpenFOAM way of collecting data often looks like this:
List<scalar> allValues(numProcs);
allValues[myProc] = localValue;
Pstream::gatherList(allValues);
// Now possible like this
List<scalar> allValues(numProcs);
allValues[myProc] = localValue;
UPstream::mpiGather(nullptr, allValues.data_bytes(), sizeof(scalar));
- adjusted Pstream::gatherList accordingly.
Split out the manual implementations, give them new names
(..._tree_algorithm) and make them private.
STYLE: rename UPstream::gather -> UPstream::mpiGatherv
- easier to identify and establishes the connection to the MPI call
- additional startup guard for inter-node/local-node queries (UPstream)
- impose linear communication tree for inter-node/local-node
communicators. Was previously defaulted to a basic tree, but more
consistent to have flat addressing for these types of connections.
- demand-driven UPstream::interNode_offsets() for walking
inter-node ranges instead of creating it manually in various places.
- (style): List<int> instead of labelList for internal commsStruct
since the communication structures are tied to MPI sizes
and not to the OpenFOAM label sizes
- reduce the number of intermediate buffer allocations within
gatherList, scatterList.
- replace gatherValues() with listGatherValues(), which returns the
gathered values instead of passing by argument. This makes it less
fragile and more convenient. Naming as per
Pstream::listGatherValues(), but still retaining the original
parameter order.
- rename inplace 'gather' variant as 'gatherInplace' for clarity.
- changed signature of lowest-level globalIndex::gather routines from
List<Type> to UList<Type> for the output and removed any resizing.
This means that the caller is responsible for ensuring that the
receiving field is adequately sized (on master). This change allows
potential reuse of 'work' arrays etc.
The only code change for using this low-level gather was in
GAMGAgglomeration.
- split/duplicate functionality
- rework inter-node/intra-node handling to allow selection of
splitting based on 'shared' or hostname (default).
- always creates node communicators at startup:
* commInterNode() - between nodes
* commLocalNode() - within a node
- world-comm is now always a duplicate of MPI_COMM_WORLD to provide
better separation from other processes.
NB:
the inter-node comm is a slight exception to other communicators
in that we always retain its list of (global) ranks, even if the
local process is not in that communicator.
This can help when constructing topology-aware patterns.
FIX: non-participating ranks still had knowledge of their potential siblings
- after create by group, the procIDs_ of non-participating ranks
should be empty (except for the inter-node exception)
- using the List containers, and not their low-level data_bytes(),
size_bytes() methods is more convenient and allows future
adjustments to be centralized
ENH: trivial intptr_t wrapper for MPI_Win
STYLE: minor adjustments to mpirunDebug
- 'if constexpr (...)'
* instead of std::enable_if
* terminate template recursion
* compile-time elimination of code
- use C++14 '_t', '_v' versions,
eg, std::is_integral_v<T> instead of std::is_integral<T>::value
- std::begin, std::end, std::void_t instead of prev stdFoam versions
- provide is_contiguous_v<..> as short form of is_contiguous<..>::value
with the additional benefit of removing any cv qualifiers.
ENH: include is_rotational_vectorspace trait
- tests for vector-space and nComponents > 1 (ie, not sphericalTensor)
ENH: improve robustness of pTraits_.. tests by removing cv qualifiers
- as per std::array and FixedList
STYLE: rename Scalar.[CH] -> scalarImpl.[CH] (these are internal files)
- added inclusion guards to protect against bad use
- poor naming (eg, 'exponential.[CH]') within the same set of library
files means that the lnInclude/ contents are inconsistent or partly
meaningless (related to #2520 and !542).
Remedied by adding model-type qualifiers to the file names.
- remove unneeded -Wno-old-style flags with boost/cgal elements
- add nvc equivalent to gcc/clang -Wno-invalid-offsetof
- avoid warnings about set-but-unused variable and change of scoping
STYLE: remove wmake 'CGAL' rule
- was a transitional forward to 'cgal' rule since DEC-2020
Description:
The plicRDF interface reconstruction scheme calculates a reconstructed distance
function (RDF) in all interface cells and their point neighbours.
In point neighbours to interface cells, the RDF is calculated as a weighted
average of the distances to all adjacent interface cell centres with the weight
being the inverse distance to the cell centre.
By using the zoneDistribute class written by Henning Scheufler, the required
stencil data is communicated efficiently for stencil cells living on different
sides of one or more processor patches.
Some of the data required for the RDF reconstruction are cell centre and
interface centre positions. When a stencil extends across a cyclic patch these
positions have so far not been properly transformed in OpenFOAM. This issue is
fixed by the current contribution.
The fix is done by modifying the zoneDistribute class to hold the required
information about zone cells adjacent to cyclic patches. Positions are then
communicated with a new getPosition function which replaces getValue for
position data in the reconstructedDistanceFunction and plicRDF classes.
The implementation does not change the behaviour for cells not on
a cyclic patch and should have insignificant effect on efficiency for these.
The implementation can probably be optimised in terms of efficiency for zone
cells on cyclic patches, but we note that there are generally only very few of
these (interface cells and their point neighbours on cyclic patches) and so
the potential for speedup is expected to be limited.
Current limitations:
- In parallel, the user must constrain the decomposition to preserve cyclic
patches on the same processor, for the implementation to work properly.
- See an example here: tutorials/discInConstantFlowCyclicBCs/system/decomposeParDict
- In the case of parallel rotational cyclics that are split by the decomposition
the current bugfix does not work and therefore throws an error. This is ongoing
work and should be reported and fixed by a future patch.
For further details, please see the modified files and the comments therein:
- $FOAM_SRC/finiteVolume/fvMesh/zoneDistribute/zoneDistribute.H
- $FOAM_SRC/finiteVolume/fvMesh/zoneDistribute/zoneDistribute.C
- $FOAM_SRC/finiteVolume/fvMesh/zoneDistribute/zoneDistributeI.H
- $FOAM_SRC/transportModels/geometricVoF/reconstructedDistanceFunction/reconstructedDistanceFunction.C
- $FOAM_SRC/src/transportModels/geometricVoF/reconstructionSchemes/plicSchemes/plicRDF/plicRDF.C
Co-authored-by: David Müller <> KIT
Co-authored-by: Konstantinos Missios <> Roskilde University
Co-authored-by: Johan Roenby <> Roskilde University and STROMNING
Reverting 267bd1af36 since makes it hard
to run cell-based algorithm on symmetric matrix.
- might become a problem if all discretisation
becomes lowerCSR based and lower() is never
constructed ...
- normally mingw will export *all* symbols, but since the ADF library
explicitly uses __declspec(dllexport) itself we must do the same
otherwise none of our library symbols are exported and linking fails.
- update some code style for conversion/ccm
Accumulates function object result values and renders into a graph in SVG format
Minimal example by using system/controlDict.functions to plot the residuals from
the solverInfo function Object:
residualGraph
{
type graphFunctionObject;
libs (utilityFunctionObjects);
writeControl writeTime;
logScaleX no;
logScaleY yes;
xlabel "Iteration";
ylabel "log10(Initial residual)";
functions
{
line1
{
object solverInfo1;
entry Ux_initial;
}
line2
{
object solverInfo1;
entry Uy_initial;
}
line3
{
object solverInfo1;
entry Uz_initial;
}
line4
{
object solverInfo1;
entry p_initial;
}
}
}
Activated using the [optional] 'shielding' keyword having the options:
- standard: [default] same as v2406 and earlier
- ZDES2020: new option based on the reference:
Deck, S., Renard, N. (2020).
Towards an enhanced protection of attached boundary layers in hybrid
RANS/LES methods.
Journal of Computational Physics, 400, 108970.
DOI:10.1016/j.jcp.2019.108970
Contribution from Marian Fuchs at UpstreamCFD GmbH
Integrated by Andrew Heather OpenCFD Ltd.
Multi-faceZone based blending differencing scheme.
Schemes are set in dictonary format according to:
divSchemes
{
.
.
div(phi,U) Gauss zoneBlended
{
default defaultScheme;
faceZone1 scheme1;
faceZone2 scheme2;
...
faceZoneN schemeN;
}
.
.
}
The default entry specifies the background scheme; additional schemes
can be set per faceZone, e.g. scheme1 is applied to facZone1,
scheme2 is applied to facZone2 etc.
- The edgeInterpolation::makeCorrectionVectors() disables the non-orthogonality
correction if the calculated non-orthogonality coefficient is below 0.1.
However, this activation routine only considers internal edges, and excludes
any processor edges, resulting in inconsistent parallel calculations. This
routine is removed.
- Fatal errors are replaced with zero-valued fields for non-orthogonality-
and skewness-correction routines.
- 1_Inlet_2_Outlet/porosityBased/R_10x-init/reEval: showcases the
initialization of the design variables using topoSet and setFields
- 3DBox/losses-mass-uniformity-SQP-extraVars: showcases the use of the
so-called 'extra variables' in the QP problem which relax it,
allowing its solution even if there is no feasible one
in topology optimisation, through a volScalarfield named alpha.
The order of precedence is (top to bottom):
- values read from time/uniform/topOVars (used also for continuation)
- values read from 0/alpha (can be easily set with topoSet + setFields)
- uniform zero
to Function1, to be able to change their value at runtime. Useful when
constraints are not feasible at the beginning of the optimisation
(frequent in topology optimisation) and we want to leave some room to
the optimiser to not focus heavily on them at the beginning, but respect
them during the last optimisation cycles.
Has a big impact, especially in MMA, when dealing with volume
constraints in topology optimisation.
When using the (optional) convergence criteria for the optimisation
loop, adherence to them is checked in the postUpdate phase of the update
of the design variables. If a line search is used, this means that the
flow equations have been solved anew using the new design variables and
the objective reduction check makes sense. If, however, no line search
is used, the objective reduction check happens immediately after the
update of the design variables and before re-solving the flow equations,
giving a reduction in the objective function and terminating the
optimisation loop prematurely.
Solved by calling the convergence check directly after the solution of
the flow equations, in case of a fixedStepUpdate
Was triggering update of cell-cell stencil (=meshObject) without
corresponding rebuilding of lduAddressing (= oversetFvMeshBase storage).
- added clearOut to oversetFvMesh(Base)
- added call to clearOut when rebuilding stencil
- PLOAD2 is a reasonable default and PLOAD4 output
(currently misused for vectors/tensors) is the exception.
- simplify the specification by using optional PLOAD4, PLOAD2 wordRes
lists to act as allow/deny selectors. In the regular case won't need
to specify anything or perhaps only the PLOAD4 list.
ENH: atomic creation of Nastran files
FIX: inconsistent Nastran surface output format
- use FREE format by default. Previously had an odd mix of SHORT
format when created without options and LONG format (as default)
when created with format options.
- the old logic relied on the presence/absence of a comma to decide
whether to parse as fixed or free format. This logic is faulty when
handling the final (trailing) entry and will generally lead to the
last field being truncated when read in.
Now the caller decides on fixed vs free.
FIX: inconsistent Nastran surface output format
- use FREE format by default. Previously had an odd mix of SHORT
format when created without options and LONG format (as default)
when created with format options.
Creates view factors for the view factor radiation model.
User-selectable models:
- raySearchEngine: model to generate rays, i.e. face-to-face connections
- viewFactorModel: model to compute the view factors
For visualisation, use:
- Write the view factors as a volume field
writeViewFactors yes;
- Write the rays using OBJ format:
writeRays yes; // default = no
Participating patches must be in the \c vewFactorWall group, i.e. using the
\c inGroups entry of the "\<case\>/polyMesh/boundary" file.
\verbatim
myPatch
{
type wall;
inGroups 2(wall viewFactorWall);
...
}
\endverbatim
Reads:
- <constant>/viewFactorsDict : main controls
- <constant>/finalAgglom : agglomeration addressing (from faceAgglomerate)
Generates:
- <constant>/F : view factors (matrix)
- <constant>/mapDist : map used for parallel running
- <constant>/globalFaceFaces : face addressing
- can be useful for various orientation-related geometry or mesh
manipulations during pre-/post-processing:
* combine with linearDirection to achieve better extrusion results.
* orientation of transformations, blockMesh, result projections, ...
STYLE: minor code modernizations
Co-authored-by: Mark Olesen <>
- 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.
Based on the reference
Tomiyama, A., Kataoka, I., Zun, I., Sakaguchi, T. (1998)
Drag coefficients of single bubbles under normal and micro gravity
conditions
JSME International Journal, 41(2), 472-479.
Example usage
subModels
{
particleForces
{
tomiyamaDrag
{
sigma 0.07;
contamination pure; // pure | slight | full
}
}
}
Determines radiation heat flux between patches when using the viewFactor
radiation model.
Example usage
viewFactorHeatFlux1
{
// Mandatory entries (unmodifiable)
type viewFactorHeatFlux;
libs (utilityFunctionObjects);
// Optional entries (runtime modifiable)
qr qr;
}
STYLE: polyPatch cached areaFraction as std::unique_ptr
- more consistent with other demand-driven data.
Getter now returns tmp field instead of const reference.
- 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.
- evaluate()
the communication type is exposed as a parameter to allow for more
tuning, but default parameter remains defaultCommsType so there is
no change in behaviour for existing code
- evaluate_if()
supports a general selection predicate
- evaluateSelected()
now does initEvaluate() for all patches, waits and then calls
evaluate(). This avoids potential deadlocks when multiple patches
are inter-communicating.
ENH: align DimensionedField reading with GeometricField treatment
- use localIOdictionary to obtain the dictionary contents
ENH: update GeometricField code
- change GeometricField writeData() as primary output method
(not operator<<) for better clarity of purpose
- use unique_ptr for GeometricField demand-driven data
- 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.
BUG: streamFunction used uninitialized values for symmetry patches
- related to 8a8b5db977 changes (#3144)
ENH: improve robustness of surface field flattening
- vtk::surfaceFieldWriter
- 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();
}
- ensures more accurate values for message sizes than using
MPI Get_count(), which trucates at INT_MAX
- add more/better error messages when trying to receive messages
that exceed INT_MAX or the char buffer lengths
- "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
- robuster and more reliable determination of inserted objects
(previous code could produce false positives).
Now also determine the number of inserted objects within the
constructor (instead of simply storing a bool). This allows reuse
in the address calculations to reduce overheads there.
BUG: dodgy short-circuit logic for insertedObjectLabels()
- as a quick short-circuit it previously created as demand-driven
pointer with a zero elements. However, this meant that if this code
was called first (before any other addressing), subsequent calls to
the addressing would fail.
BUG: bad logic and lookup for faAreaMapper (#3147)
- was using labelHashSet but returning a bool and set using the
addressing using the unfiltered objects!
This is a latent bug since interpolated/inserted faces not
currently supported anyhow.
ENH: use std::unique_ptr for demand-driven data
- manual revert for 44d0fbd594.
Unless required for post-processing the "value" entry should not
written if it is not mandatory for reading.
This is especially crucial with an 'empty' patch field where the
field (size 0) has a different size from the patch.
- the changes made align fvsPatchField behaviour with fvPatchField
- 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
- previously automatically skipped the first communicator (which was
assumed to be MPI_COMM_WORLD), but now simply rely on the
internal pendingMPIFree_ to track which communicators have actually
been allocated.
- 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)
);
- replace point-to-point transmission of the argList args/options with
a broadcast. This is sufficient for most cases (without distributed
roots).
For "normal" cases (non-distributed roots) this will replace the
nProcs-1 messages with a single broadcast.
- for cases with distributed roots, distinguish between a single,
identical root and different roots. An identical root can also be
subsequently handled with a broadcast. Different roots will still
require individual point-to-point communication.
For cases with distributed roots, it will add the overhead of an
additional broadcast.
- adds consistency with regular point-to-point parallel streams.
ENH: add ITstream::tokens() methods
- useful, for example, to disambiguate constructing tokenList from
a ITstream.
ITstream& is = otherDict.lookup("original");
tokenList deepCopy(is); // Error: from Istream or tokenList??
tokenList deepCopy(is.tokens()); // OK: from tokenList
- 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
STYLE: update code style for phi modification (engine motion)
ENH: pass isMeshUpdate param in fvMesh/polyMesh clearOut() methods
- top-level use of isMeshUpdate parameter to clearOut and
clearAddressing was being inadvertently filtered out
- after the modification of d578d48a4f, the parent was now actually
searched. However, should be returning "constant" and not trigger a
FatalError if the file/directory is not found.
- findStrings, findMatchingStrings now mostly covered by matching
intrinsics in wordRe and wordRes.
Add static wordRes match() and matching() variants
COMP: remove stringListOps include from objectRegistry.H
- was already noted for removal (NOV-2018)
- NewIFstream would read complete remote file to decide if
was collated.
- This limits files to 31bit size
- Instead now have master-only opening of file.
- Still has problem with refinement history/cellLevel etc.
- 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
- leave 'readContents' method name for exposed (public) methods.
Generally not a problem, but can confuse the compiler when various
public/private versions are available with the same number of
parameters.
STYLE: adjust meshObject debug statements
- the type/name for field caching were saved as word, but ensight has
things like "tensor symm" etc, which do not parse very well as
'word'. Now save as 'string' type.
Backwards compatibility is OK since a word token will also be
readable as string etc.
- makes string reading consistent with fileName reading.
Related to #3133 to also allow compatibility when reading existing
dictionaries written with unquoted string contents.
- used defunct "processors/" directory naming, and includes are now
addressed by the file-handler anyhow.
ENH: support 'tutorials/Alltest -init'
- for copying/creating test directory without running
- in renumberMesh replace calculation of a subMesh connectivity
with calculation of the full mesh connectivity followed by subsetting
of the full adjacency matrix. This should reduce the overall number of
operations. (MR !669)
- added solidBodyMotionFunctions to topoSet which allows things like
moving cellSet selection for fvOptions etc.
COMP: relocate solidBodyMotionFunctions to meshTools
Co-authored-by: Kutalmis Bercin <>
- 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
- particularly useful in these combinations:
1.
OCharStream buf;
// populate
ISpanStream is(buf.view());
// parse
2.
// read from file
ifile.getLine(str);
ISpanStream is(str);
// parse
These avoid making a copy of the character content, compared to
versions with stringstream:
OStringStream buf;
IStringStream is(buf.str());
- a few places still used listCombineReduce instead of
newer constructs (eg allGatherList) with fewer MPI calls.
- align triangulation handling of turbulentDFSEMInlet and
patchInjectionBase with meshTools/triangulatedPatch
(will ease future code refactoring)
- 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
- surfaceWriter TryNew() factory methods for more failure tolerant
handling
- reduce communication for sampledSurfaces.
Track non-empty surfaces as bool, only updated on change
(expire/update).
- use Pstream::listScatterValues() instead of the old hand-rolled
method.
Reduces code and since it is mostly used with primitives it
will use MPI_Scatter directly (see #3087)
COMP: fix some inconsistent masterOp return types
- 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
- related to issue #3095. Some type of geometry is required when
loading "measured" ensight data.
ENH: emit a fallback geometry-box for foamToEnsight
- eg, with "foamToEnsight -no-internal -no-boundary" and lagrangian
- process the contents of the cloud object registry, which enables
output support for calculated values such as Reynolds, Weber numbers
etc.
ENH: select any/all clouds by default instead of defaultCloud
- adds robustness
- 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
- range(proci) instead of localStart(proci), localSize(proci) combination.
* does the same thing, can be used directly with various other
routines for slicing etc.
Eg,
Foam::identity(globalNumbering.range(myProci))
- globalIndex::calcOffset() instead of constructing a globalIndex and
taking the localStart(). Avoids intermediate resizing and storing of
an offsets table (which is then discarded) as well as the subsequent
lookup into that table
- creates an IOobject at the current time instance (timeName) with
NO_READ/NO_WRITE/NO_REGISTER characteristics.
This generalises and replaces the Cloud fieldIOobject() to simplify
some common use.
// Shorter version (new):
volScalarField fld
(
mesh.newIOobject(name),
...
);
// Longer version:
volScalarField fld
(
IOobject
(
name,
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
IOobject::NO_REGISTER
),
...
);
- can be useful when using memory-based streams for buffering,
in which case the name() can be used to specify the filesystem
location instead of the default stream names ("input", "output").
- shape optimisation: SQP failed due to wrong divScheme for the adjoint
equations
- shape optimisation: tutorials designed to show the impact of different flow
conditions were actually using the same U
- topology optimisation: tutorials designed to show the impact of the
flow rate distribution were actually using the same target
fractions
- topology optimisation: updated old fvSolution syntax
- shape optimisation: SQP failed due to wrong divScheme for the adjoint
equations
- shape optimisation: tutorials designed to show the impact of different flow
conditions were actually using the same U
- topology optimisation: tutorials designed to show the impact of the
flow rate distribution were actually using the same target
fractions
- topology optimisation: updated old fvSolution syntax
- had max(std::streamsize, label) but this does not resolve properly
on OSX, so write out in long form instead.
The similar logic in DynamicList is okay since there it compares
max(label, label) instead
In steadyOptimisation mode, each time-step corresponds to an
optimisation cycle and is sub-cycled, to allow for iterating the flow
and adjoint equations. This sub-cycling does not allow the execution of
function objects. This was circumvented in 8947735b1d, by explicitly
calling the execution of the function objects in the simple solver
of adjointOptimisationFoam.
However, each sub-cycled iteration is a writeTime, if the current
optimisation cycle corresponds to a writeTime. This means that function
objects with a
writeControl write;
will be executed in each iteration of the flow equations, within this
specific optimisation cycle, leading to a lot of disc space and file
clutter, if the function object outputs fields (e.g. yPlus).
8947735b1d is partially rolled back, by protecting the call to the
execution of the function objects with a bool that defaults to false.
- adjointOptimisation : missing link to fileFormats
- snappyHexMesh : add fvMotionSolvers link (#3058)
STYLE: remove remnant -DFULLDEBUG hints
- now more easily covered with wmake -debug ...
- the fileHandler changes included setting cacheLevel(0) to avoid
blocking with redistributePar. However, this meant if clouds
were not uniformly present on all ranks the fileHandler would follow
different code paths and lead to blocking.
Now switch to distributed mode for the lagrangian operations within
redistributePar based on the cacheLevel information.
FIX: avoid triggering a false processor check in argList
- when redistributing to few ranks
The solution of the QP subproblem can become quite expensive, especially
for cases with many design variables (e.g. topology optimisation).
A (potentially dense) matrix with the size of the design variables is
solved using a matrix-free CG solver. The convergence speed greatly
depends on the used preconditioner. This commit adds
preconditioner-vector products based on the L-BFGS inverse Hessian and,
more importantly, a preconditioner computed using the Sherman-Morrison
formula. The latter is applicable here since the LHS of the QP problem
is computed as the sum of rank-2 L-BFGS updates, a sum of rank-1 updates
(as many as the flow-related constraints) and a diagonal matrix
depending on the bound constraints.
Additionally, the QP subproblem could have no feasible points. To relax
this, constraints can be applied gradually through the
targetConstraintReduction enty (typical value of 0.1 for topology
optimisation).
Most cases now rely on the nullSpace update method, instead of MMA,
since it has proven more reliable.
Also, added some constrained optimisation cases, including constraints
on the flow rate partition and total pressure losses as well as cases
targeting uniformity as the objective function.
Added a 3D topology optimisation case which also includes constraints.
of the STL written by topology optimisation.
BUG: when determining which mesh faces are cut by iso-surface faces,
only append the latter if it contains more than two points
by a small amount, if all of them lay on the lower or upper bounds at
the beginning of the optimisation, to avoid singular matrices when
computing the update of the design variables.
and the Jacobian of the objective function wrt the turbulence variables
is called (rare/unorthodox case).
Additionally, objectivePowerDissipation dissipation can now be used in
topology optimisation, adding the necessary blockage dependency to it.
- Building the iso-surface spliting fluid and solid parts in topology
optimisation has been re-worked to obtain an iso-surface with unique
point numbering
- The mechanism behind marchingCells for dynamicTopODesignVariables has
been slightly reworked
The derivatives of the objective and constraint functions can optionally
be normalised in each optimisation cycle, so that MMA does not put an
excesive stress on the constraints, which can negatively affect the
course of the optimisation
A 1-Inlet-2-Outlet geometry is showcased for laminar and turbulent
flows, set-up with different variants of porosity-based and
level-set-based topology optimisation
Both porosity-based and level-set-based topO frameworks are included
through the topO and levelSet designVariables, respectively.
Both frameworks work by manipulating an underlying field of design
variables, defined in all cells of the computational domain. That field
is then regularised through a Helmholtz-like filter, before being
processed in a different way from the two topO frameworks (the
porosity-based topO sharpens/projects it while the level-set-based topO
computes signed distances around its zero iso-surface). The result of
this processing is then fed into functions that define source terms to
be added to the mean flow and turbulence model equations, to block
off/solidify parts of the mesh that are counterproductive with respect
to the objective function. These source terms are added through
fvOptions.
Since the designed walls are only simulated through source terms, the
outcome of topO should be re-analyzed on a body-fitted grid, to quantify
the actual gain in the objective function. Both topO frameworks output
the designed wall in STL format which can be used, for instance with
snappyHexMesh, to construct such a body fitted grid.
This provides a list of faces (can be internal ones) to act as
additional seeds for the wave algorithm. The default argument provides
an empty list, so the behaviour of patchWave should not change.
Useful in topology optimisation, for propagating the active design
variables from the seed faces to the interior, with a given number of
cells at a time.
- advectionDiffusion is frequently used within optimisation loops since
it is differentiable. In shape optimisation, the re-computation of
mesh distances is performed at the very beginning of a new
optimisation cycle, due to inheriting from MeshObject. If the mesh
quality is poor enough, the advectionDiffusion PDE might diverge and
crash the run, before the problematic mesh is written to files for
inspection. The default behaviour now is to check the mesh before
solving the advectionDiffusion PDE and write the mesh points if some
mesh check fails.
- fvOptions can now be included in advectionDiffusion (necessary for
topology optimisation of turbulent flows for models that include the
distance field)
- Minor changes in the numerical treatment of the diffusion term, to
enhance stability
Parts of the adjoint optimisation library were re-designed to generalise
the way sensitivity derivatives (SDs) are computed and to allow easier
extension to primal problems other than the ones governed by
incompressible flows. In specific:
- the adjoint solver now holds virtual functions returning the part of
SDs that depends only on the primal and the adjoint fields.
- a new class named designVariables was introduced which, apart from
defining the design variables of the optimisation problem and
providing hooks for updating them in an optimisation loop, provides
the part of the SDs that affects directly the flow residuals (e.g.
geometric variations in shape optimisation, derivatives of source
terms in topology optimisation, etc). The final assembly of the SDs
happens here, with the updated sensitivity class acting as an
intermediate.
With the new structure, when the primal problem changes (for instance,
passive scalars are included), the same design variables and sensitivity
classes can be re-used for all physics, with additional contributions to
the SDs being limited (and contained) to the new adjoint solver to be
implemented. The old code structure would require new SD classes for
each additional primal problem.
As a side-effect, setting up a case has arguably become a bit easier and
more intuitive.
Additional changes include:
---------------------------
- Changes in the formulation and computation of shape sensitivity derivatives
using the E-SI approach. The latter is now derived directly from the
FI approach, with proper discretization for the terms and boundary
conditions that emerge from applying the Gauss divergence theorem used
to transition from FI to E-SI. When E-SI and FI are based on the same
Laplace grid displacement model, they are now numerically equivalent
(the previous formulation proved the theoretical equivalence of the
two approaches but numerical results could differ, depending on the
case).
- Sensitivity maps at faces are now computed based (and are deriving
from) sensitivity maps at points, with a constistent point-to-face
interpolation (requires the differentiation of volPointInterpolation).
- The objective class now allocates only the member pointers that
correspond to the non-zero derivatives of the objective w.r.t. the
flow and geometric quantities, leading to a reduced memory footprint.
Additionally, contributions from volume-based objectives to the
adjoint equations have been re-worked, removing the need for
objectiveManager to be virtual.
- In constrained optimisation, an adjoint solver needs to be present for
each constraint function. For geometric constraints though, no adjoint
equations need to solved. This is now accounted for through the null
adjoint solver and the geometric objectives which do not allocate
adjoint fields for this kind of constraints, reducing memory
requirements and file clutter.
- Refactoring of the updateMethod to collaborate with the new
designVariables. Additionally, all updateMethods can now read and
write restart data in binary, facilitating exact continuation.
Furthermore, code shared by various quasi-Newton methods (BFGS, DBFGS,
LBFGS, SR1) has been organised in the namesake class. Over and above,
an SQP variant capable of tackling inequality constraints has been
added (ISQP, with I indicating that the QP problem in the presence of
inequality constraints is solved through an interior point method).
Inequality constraints can be one-sided (constraint < upper-value)
or double-sided (lower-value < constraint < upper-value).
- Bounds can now be defined for the design variables.
For volumetricBSplines in specific, these can be computed as the
mid-points of the control points and their neighbouring ones. This
usually leads to better-defined optimisation problems and reduces the
chances of an invalid mesh during optimisation.
- Convergence criteria can now be defined for the optimisation loop
which will stop if the relative objective function reduction over
the last objective value is lower than a given threshold and
constraints are satisfied within a give tolerance. If no criteria are
defined, the optimisation will run for the max. given number of cycles
provided in controlDict.
- Added a new grid displacement method based on the p-Laplacian
equation, which seems to outperform other PDE-based approaches.
TUT: updated the shape optimisation tutorials and added a new one
showcasing the use of double-sided constraints, ISQP, applying
no-overlapping constraints to volumetric B-Splines control points
and defining convergence criteria for the optimisation loop.
- enhance POSIX compliance
- apply distinct colours and dash type for each line
- standardize the frame size to 1200x627
- dynamically replace the title with <function-object-name>/<file-name>
- address underscore character issues
- introduce legend components for tensors
- resolve a bug caused by parentheses in tensor files
BUG: particleTrackProperties: correct the typo (fixes#3050)
- 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
- better code style and seems to avoid triggering a gcc warning about
possibly uninitialized values
COMP: JSONformatter writeEntry missing a return value
STYLE: accept 'json' for checkMesh write format
- consistent with caseInfo functionObject
- for clang-based compilers the default linker may be lld or simply ld.
Support '+link-ld' to explicitly select use of the ld linker.
- consolidate linker rules into single files
STYLE: adjust SPDX Identifier
redistributePar -decompose switches communicator when
reading on master. However other processors still get
constructed with the worldComm. >v2306 AMI stores the communicator
from construction time there was a mismatch
- regression introduced by commit 0ff86ee2
(only affects recent develop).
- now split off first/final iterations into a separate
"controls" dictionary (instead of lumping them into "solver") to
make them persistent between iterations.
- updating the header information (by copying) was closing the stream,
removing all watches and doing a checkOut/checkIn, which could lead to
dangling references.
Now just close the stream and simply copy the IOobject header
information directly.
STYLE: mark regIOobject assignment operator as possibly deprecated
- will revisit to revise or remove in the future
- the faMesh/fvMesh copy constructors were using the readOption from
the base-mesh schemes/solution instead of copying their contents.
This would not really affect fvMesh (since it has its own IOobject
for the constructor), but did affect faMesh. However, the problem
only shows up with collated + redistribute, since that is where
the ranks can be doing uncoordinated IO.
Only consider as a bug for recent develop since previous versions
had other problems with collated+redistribute with finite-area
anyhow.
- 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.
- give precedence to ~openmp (-no-openmp) over +openmp (-openmp)
in the general rules and in the Makefile. This makes it robuster
when specifying +openmp in general, but ~openmp for specific build
components.
- disable openmp for OSspecific and Pstream components.
Neither should contain any openmp code anyhow.
Additionally, since OSspecific is generally built as a static
object, it can become problematic (eg, with AMD ROCm) if the
compiler generates information that openmp is required but then uses
static linkage.
- the fields for finite-area are currently stored directly on the
polyMesh registry, but for future relocation to a sub-registry
provide a uniform accessor.
ENH: use thisDb() for faMatrix access and extrapolatedCalculated
- 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
- static version of polyMesh::meshDir(), which takes a region name
polyMesh::meshDir(regionName)
vs
polyMesh::regionName(regionName)/polyMesh::meshSubDir
STYLE: use polyMesh::regionName(..) instead of comparing to defaultRegion
STYLE: use getOrDefault when retrieving various -region options
FIX: polyMesh::dbDir() now checks registry name, not full path (#3033)
Generates sample positions from points specified in a file as Abaqus mesh
points.
Example usage:
sets
{
cone25 // user-specified set name
{
type abaqusMesh;
file "abaqusMesh.inp";
// Optional entries
// Scale, e.g. mm to m
scale 0.001;
// Search distance when the sample point is not located in a cell
maxDist 0.25;
...
}
}
Write coordSet(s) as Abaqus point fields
Example usage
T
{
type sets;
setFormat abaqus;
fields (T);
sets
{
...
}
}
\endverbatim
Optional format options
\verbatim
formatOptions
{
abaqus
{
format ascii;
// Optional entries
// Custom header: $ entries are substituions
header
(
"** OpenFOAM abaqus output"
"** Project $FOAM_CASE"
"** File $FILE_NAME"
"** $FIELD_NAME Time t=$TIME"
);
// Write geometry in addition to field data
writeGeometry yes;
// Null value when sample value is not found
// Default is scalar::min
nullValue 0;
// Insert additional time sub-directory in the output path
// - yes : postProcessing/<fo-name>/<time>/<file>
// - no : postProcessing/<fo-name>/<file>
useTimeDir no;
// Available when 'useTimeDir' is 'no' to disambiguate file names
// Time base for output file names:
// - 'time' : <base>.inp_<field>.<time>
// - 'iteration' : <base>.inp_<field>.<iteration>
timeBase iteration;
// Optional start counters when using timeBase iteration
writeIndex
(
T 1
);
...
}
}
Example:
formatOptions
{
<writer>
{
// Apply offsets to field values
fieldLevel
{
T 273.15; // Convert from K to C by subtracting 273.15
}
// Note: scale applied after application of field level
fieldScale
{
p 0.001; // Convert pressure from Pa to kPa by scaling by 0.001
}
}
}
Added -writeChecks <format> option
- writes computed mesh metrics to file in using <format>
- currently supported formats are OpenFOAM dictionary and JSON
Collects and writes case information to file in OpenFOAM dictionary or JSON
format. Data includes:
- meta: case name, path, regions, parallel etc.
- dictionaries: entries retrieved from dictionaries - registered or from file
- per region: mesh metrics, boundary and boundary field types
- function object results
Example of function object specification:
caseInfo
{
type caseInfo;
libs (utilityFunctionObjects);
// Warn when entries are not found
lookupMode warn; // none | warn | error;
// Write format
writeFormat json; // dictionary | json;
dictionaries
{
USolver // User-specified names
{
// Look up using registered name
name "fvSolution";
// Optionally limit to specific entries
include
(
"solvers/U/solver"
);
}
fvSchemes
{
name "fvSchemes";
// include all entries by default
}
timeScheme
{
name "fvSchemes";
include
(
"/ddtSchemes/default"
);
}
turbulence
{
name "turbulenceProperties";
// include all entries by default
}
controlDict
{
// Look up using file path
path "<case>/system/controlDict";
include
(
"application"
"deltaT"
"startTime"
"endTime"
);
}
}
functionObjects (minMax1);
}
Quality metrics, e.g. non-orthogonality, skewness etc are calculated/reported
in polyMeshCheck functions. These results are now added to the meshState/mesh
dictionary to enable external access.
ENH: added 'mesh' dictionary to meshState to hold mesh properties
- solver information now stored in a 'solver' dictionary (was solverPerformance)
- {first|final}Iteration entry now stored in solver dict instead of top level
- mesh data (new) stored in 'mesh' dictionary
- code is compiled dynamically on the master node.
In the normal (non-distributed) case, simply poll the NFS
to see when it appears on the sub-procs.
For a case with distributed roots, first broadcast it (via MPI)
to the IO master nodes and then poll afterwards.
- on startup, detect and create missing processorXXX/ subdirectories
on distributed filesystems
- when reading, detect all clouds on all processors and uses this when
reading fields. Similarly, when writing it uses writeOnProc to skip
clouds that are empty on any particular processor.
Co-authored-by: Mark Olesen <>
- was previously limited to 'char' whereas gatherv/scatterv
already supported various integer and float types
STYLE: rebundle allToAll declarations with macros
ENH: provide a version of allToAllConsensus returning the Map
- simplifies use and avoids ambiguities in the send/recv parameters
- the Map version will now also transmit zero value data if they exist
in the Map. Unlike the List version, zero values are not necessary to
signal connectivity with a Map.
COMP: forwarding template parameters for NBX routines
ENH: consolidate PstreamBuffers size exchange options
- had a variety of nearly identical backends for all-to-all,
gather/scatter. Now combined internally with a dispatch enumeration
which provides better control over which size exchange algorithm
is used.
DEFEATURE: remove experimental full-NBX PstreamBuffers variant
- no advantages seen compared to the hybrid NBX/PEX approach.
Removal reduces some code cruft.
DEFEATURE: remove experimental "double non-blocking" NBX version
- the idea was to avoid blocking receives for very large data transfers,
but that is usually better accomplished with a hybrid NBX/PEX approach
like PstreamBuffers allows
- 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.
- report location with previous good offset and the new count that
would cause overflow. Simpler to report and the (very long) list
of input sizes is not particularly useful for diagnostics either.
ENH: add globalIndex comparison operators
- for outputting lists of globalIndex
- 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.
- the default returns -1 (ie, not found/available). This is overridden
by processorCyclicPolyPatch to actually perform a search
COMP: explicitly define polyMesh::writeObject in the header
- currently no special treatment, but allows future adjustments
without affecting the header.
- extends the enumeration (NO_REGISTER, REGISTER, LEGACY_REGISTER).
Can be used to tweak registration preference where required and
potentially (TDB) to define a different default value in the future
- CompactListList::size() corresponds to the number of sub-lists
whereas globalIndex::size() corresponds to the totalSize().
This difference can lead to potential coding errors when switching
between pure addressing (eg globalIndex) and addressing with content
(eg, CompactListList).
Within the source tree, there are no longer any occurances of
globalIndex::size() but it is nonetheless unsafe to change its
meaning now. Instead provide a commonly named length() method that
corresponds to the natural length: ie, the number of offsets minus 1
(with guards).
- add CompactListList::writeMatrix for writing the compact contents
in an unpacked form (eg, for debugging) without actually needing to
unpack into storage.
- provide globalIndex::whichProcID() two-parameter version
with myProcNo as the first argument.
Symmetric with isLocal etc, useful when using a communicator
that is not worldComm.
- avoids clutter of argList::envGlobalPath() ...
ENH: allow temporary overwriting of output writeFormat
- allows switching for particular output routines
COMP: explicitly use TimePaths methods with Time
- this simplifies any overloading done at a later stage
- remnant was left in the NBX implementation for Map<Type>.
Still not entirely certain which vendors/versions handle message
probe/recv properly, but using the "regular" probe and recv is OK
since everything is without threaded race conditions.
STYLE: adjust file extension of UPstreamWrapping templates
- avoids it being exposed via lnInclude
- this makes it easier to split creation into a two-stage process
as required
- extend handling for polyBoundaryMeshEntries, faBoundaryMeshEntries
with more functionality. Ensure that these are never registered.
ENH: addition writeEntry methods for polyBoundaryMesh
- simplifies streaming and collating into other files
ENH: polyMesh rereading - update owner/neighbour header information
- this avoids accidentally reading the "cells" file if the mesh has
been created with NO_READ and then updated
STYLE: less vertical space when outputting empty PtrList
- combined most of the unweighted and weighted decomposition routines
such that an empty weight field is treated as uniform weighting.
This allows default parameters and cuts down on the number of
decompose methods.
- for topology-driven decomposition, it is now possible to pass in the
owner/neighbour connectivity as a CompactListList directly instead
of first creating a labelListList (which was internally repacked into
a CompactListList in many cases).
However, multiLevelDecomp still uses unpacking (to avoid a larger
reworking of code).
- support direct creation of some methods (eg, random, scotch etc)
without a dictionary
- fix incorrect neighbour face weighting (fixes#3019)
ENH: relocate calcCellCells from decompositionMethod to globalMeshData
- makes it more universally available
- usually only need big/little defines (which are now in the Fwd)
and rarely need byte-swapping.
Provide endian.H compatibility include, but foamEndianFwd.H or
foamEndian.H to avoid potential name clashes.
- The pTraits_cmptType returns the data type of 'cmptType' (for
arithmetic and VectorSpace types) or is simply a pass-through.
This can be combined with the pTraits_nComponents for casting.
For example,
function
(
reinterpret_cast<pTraits_cmptType<Type>::type*>(buf.data()),
(buf.size()/pTraits_nComponents<Type>::value)
);
ENH: extend Foam::identityOp so support array indexing (pass-through)
- single() method : simply tests if the globalIndex has nProcs == 1,
which is typically from a gatherNone invocation.
For example,
globalIndex gi;
if (...) gi.reset(localSize);
else gi.reset(globalIndex::gatherNone{}, localSize);
// later...
const label begin = (gi.single() ? 0 : gi.localStart());
const label count = (gi.single() ? gi.totalSize() : gi.localSize());
- add front() and back() methods to return the begin/end ranges,
and begin_value(), end_value() - as per labelRange.
- make more methods noexcept
- calcOffset(), calcRange() helper functions to determine
the processor-local of a numbering range without the overhead of
creating a list of offsets.
For example,
label myOffset = globalIndex::calcOffset(mesh.nCells());
labelRange mySlice = globalIndex::calcRange(mesh.nCells());
- add globalIndex localEnd() as per CompactListList method
STYLE: align looping constructs in CompactListList with List
- make more methods noexcept
- becoming more frequently used and there is no ambiguity in calling
parameters either - identity(label) vs identity(labelUList&).
Provide both int32 and int64 versions.
- it seems that both sides of the ternary are evaluated despite
the divide-by-zero protection. Use volatile to force the compiler
to use in-order evaluation.
- attempt to minimize rounding in the cached time values
since these are also used to re-populate the case files
STYLE: remove ancient handling of "meshes" entry
- was superseded by "geometry" entry in OpenFOAM-1912 and later.
Now remove the transitional shim, which was in place for
restart migration from 1906.
CONFIG: downgrade non-uniform time from error to warning
- can be a spurious error when the deltaT is very small
CONFIG: support keywords 'minFreq', 'maxFreq'
- these are the updated naming for 'fl' and 'fu' (still supported)
- new format option keywords: timeFormat, timePrecision
CONFIG: default ensight output is now consistently BINARY
- this removes some uncertainty with the ensightWrite functionObject
which was previously dependent on the simulation writeFormat
and makes its behaviour consistent with foamToEnsight
Note: binary Ensight output is consistent with the
defaults for VTP output (inline binary)
ENH: minor adjustment of ensight writing methods
- retain group information when copying zones
- support construct empty (add details later)
- improve consistency for zone and boundaryMesh construction
- support front/back/both selection for faceZoneToCell
STYLE: prefer faceZone patch() method instead of operator()
STYLE: use std::unique_ptr instead of manual pointer management
- for zones and core patch types.
Easier data management, allows default destructors (for example)
- use add_tokens() instead of the old multi-parameter
append(.., bool) method which was misleading since it added tokens
at the current tokenIndex, not at the end.
- stringify ITstream contents with CharStream instead of StringStream.
Allows string_view for copying out the content.
ENH: set namedDictionary dictionary name from Istream
- provides context for error messages etc (#2990)
- now mark methods with strict deprecation, to make it easier to find
their use but without adding extra compilation noise for others
ENH: minor update for Enum methods and iterator
- add warnOnly (failsafe) option for readEntry and getOrDefault
- add good() method to Enum iterator (simliar to HashTable)
- replace unused/fragile Enum find() methods with iterator return
that can be used more generally
- explicit use of UPstream::worldComm in globalIndex methods
for more clarity
- adjust method declaration ordering:
de-emphasize the processor-local convenience methods
- consistent use of leading tag dispatch,
remove unused enum-based dispatch tag
- add begin()/cbegin() with offset (as per List containers)
BUG: missing use of communicator in globalIndex gatherNonLocal
- does not affect any existing code (which all use worldComm anyhow)
- support std::string_view (c++17) or span view (older c++) of stream
buffer contents. This simplifies formatting + reparsing.
Example,
OCharStream os;
os << ...;
ISpanStream is(os.view());
is >> ...;
- additional release() method for ICharStream, OCharStream
that returns the contents as a DynamicList<char> and resets the stream.
- provide a str() method for API compatibility with older
std::ostringstream etc.
- change write(const string&) to write(const std::string&).
This allows output of std::string without an intermediate copy.
- additional writeQuoted method to handle range of char data:
writeQuoted(const char* str, std::streamsize len, bool)
This helps with supporting string_view and span<char>
- add operator<< for stdFoam::span<char> and std::string_view (c++17)
- avoid duplicate code in OBJstream
STYLE: add override keyword for IO stream methods
- default construct is now identical to HashTable(Foam::zero).
It performs no allocation and is also noexcept.
The previously used default capacity (128) was a holdover from
much older versions where set/insert did not properly handle
insertion into a table with zero capacity (number of buckets).
- earlier deletion of unpopulated HashTable on resizing:
If the table is already clear (ie, has no entries),
can immediately remove the old internal table before reallocating
the newly sized table, which may avoid a needless memory spike.
- reserve() method:
Naming and general behaviour as per std::unordered_map.
It behaves similarly to the resize() method but is supplied the
number of elements instead of the capacity, which can be a more
natural way of specifying the storage requirements.
Additionally, reserve() will only increase the table capacity for
behaviour similar to DynamicList and std::vector, std::string etc.
Old:
labelHashSet set;
set.resize(2*nElems);
Now:
labelHashSet set;
set.reserve(nElems);
- remove unused HashTable(Istream&, label) constructor
STYLE: static_cast of (nullptr) and std::fill_n for filling table
- changes the addressed list size without affecting list allocation.
Can be useful for the following type of coding pattern:
- pre-allocate a List with some max content length
- populate with some content (likely not the entire pre-allocated size)
- truncate the list to the length of valid content
- process the List
- discard the List
Since the List is being discarded, using resize_unsafe() instead of
resize() avoids an additional allocation with the new size and
copying/moving of the elements.
This programming pattern can also be used when the List is being
returned from a subroutine, and carrying about a bit of unused memory
is less important than avoiding reallocation + copy/move.
If used improperly, it can obviously result in addressing into
unmanaged memory regions (ie, 'unsafe').
- shrink_to_fit()
corresponds to std::vector naming.
For DynamicList it is a *binding* request.
- shrink_unsafe()
simply adjusts the capacity() to match the
current size() without forcing a re-allocation.
Useful when collapsing to a non-dynamic list to avoid reallocation
and copying contents. The memory cleanup will still occur properly
at a later stage.
- DynamicList::swap(List&)
simple recovery of content into a non-dynamic List that also
ensures that the capacity is correctly updated.
STYLE: promote List::capacity() to public visibility (like std::vector)
STYLE: remove unused expandStorage() method
- simply a wrapper for resize(capacity())
- when running with "errors warn;" it will reset the warnings counter
(if any) when it returns to a good state.
This re-enables un-suppressed warnings for the next cycle.
Also reset the warnings counter on end().
ENH: add short-circuit in HashTable::erase(key)
- skip and return false if the table is empty or the key is not found.
This makes for faster no-op behaviour.
- for workflows with appearing/disappearing patches (for example)
can specify that empty surfaces should be ignored or warned about
instead of raising a FatalError.
Note that this handling is additional to the regular top-level
"errors" specification. So specifying 'strict' will only actually
result in a FatalError if the "errors" does not trap errors.
- "ignore" : any empty surfaces are simply ignored and no
file output (besides the header).
- "warn" : empty surfaces are warned about a few times (10)
and the file output contains a NaN entry
- "strict" : corresponds to the default behaviour.
Throws a FatalError if the surface is empty.
This error may still be caught by the top-level "errors" handling.
- support UList shallowCopy with pointer/size
(eg, for slicing into or from span)
ENH: add SubList::reset() functionality
- allows modification of a SubList after construction.
Previously a SubList had an immutable location after construction
and there was no way to shift or change its location.
BUG: missed special handling for DynamicList<char>::readList (fixes#2974)
- equivalent to List<char>::readList, in which the stream is
temporarily toggled from ASCII to BINARY when reading in a List of
char data.
This specialization was missed when DynamicList<T>::readList() was
fully implemented.
- defines values for EMPTY, UNIFORM, NONUNIFORM and MIXED
that allow bitwise OR reduction and provide an algorithm
for calculating uniformity
ENH: consolidate more efficient uniformity checks in PackedList
ENH: improve linebreak handling when outputting small matrices
- use ignore instead of seekg/tellg to swallow input (robuster)
- check for bad gcount() values
- wrap Foam::fileSize() compressed/uncompressed handling into IFstream.
- improve handling of compressed files in masterUncollatedFileOperation.
Previously read into a string via stream iterators.
Now read chunk-wise into a List of char for fewer reallocations.
- soft renames (ie, old names still available via typedefs) for more
reasonable names and more coverage with std stream variants.
The old names could be a bit cryptic.
For example, uiliststream (== an unallocated/external list storage),
which is written as std::ispanstream for C++23.
Could similarly argue that IListStream is better named as
ICharStream, since it is an input stream of characters and the
internal storage mechanism (List or something else) is mostly
irrelevant.
Extending the coverage to include all std stream variants, and
simply rewrap them for OpenFOAM IOstream types. This simplifies the
inheritance patterns and allows reuse of icharstream/ocharstream as
a drop-in replace for istringstream/ostringstream in other wrappers.
Classes:
* icharstream / ICharStream [old: none / IListStream]
* ocharstream / OCharStream [old: none / OListStream]
* ispanstream / ISpanStream [old: uiliststream / UIListStream]
* ospanstream / OSpanStream [old: none / UOListStream]
Possible new uses : read file contents into a buffer, broadcast
buffer contents to other ranks and then transfer into an icharstream
to be read from. This avoid the multiple intermediate copies that
would be associated when using an istringstream.
- Use size doubling instead of block-wise incremental for ocharstream
(OCharStream). This corresponds to the sizing behaviour as per
std::stringstream (according to gcc-11 includes)
STYLE: drop Foam_IOstream_extras constructors for memory streams
- transitional/legacy constructors but not used in any code
- nonBlocking: receive before send
- nonBlocking: wait for receive requests, process and then wait for
other requests. Can be extended to use polling...
- the 'fake' send (to self) now send copies into recv buffers instead
of send buffers.
This provides a clear separation of send and receive fields
- avoid unnecessary reallocations with PtrList of send/recv buffers
- remove outer looping for accessAndFlip and pass target field
as parameter for inner looping instead
ENH: refine mapDistribute send/recv requests handling
- separate send/recv requests for finer control
- receive does not need access to PtrList of sendBuffers, since the
send-to-self now uses the recvBuffers
- totalSize() returns retrieve the linear (total) size
(naming as per globalIndex)
- operator[] retrieves the referenced value (linear indexing)
- labels() returns a flattened labelList (as per labelRange itself)
- broadcasts list contiguous content as a two-step process:
1. broadcast the size, and resize for receiver list
2. broadcast contiguous contents (if non-empty)
This avoids serialization/de-serialization memory overhead but at
the expense of an additional broadcast call.
The trade-off of the extra broadcast of the size will be less
important than avoiding a memory peak for large contiguous mesh data.
REVERT: unstable MPI_Mprobe/MPI_Mrecv on intelmpi + PMI-2 (#2796)
- partial revert of commit c6f528588b, for NBX implementation.
Not yet flagged as causing errors here, but eliminated for
consistency.
- simplifies use with other allocators (eg, memory pools).
Can also be used with other containers.
vectorField fld = ...;
sigFpe::fillNan(fld.data_bytes(), fld.size_bytes());
COMP: inline sigFpe::ignore helper class
- now unused (may be removed in the future), but can avoid compiling
code for it
COMP: missing sigStopAtWriteNow() definition for MSwindows
- simplifies internal handling (like a fileName) and allows the
dictionary name to be used with unambiguous addressing.
The previous dot (.) separator is ambiguous (ie, as dictionary
separator or as part of a keyword).
ENH: foamDictionary report -add/-set to stderr
- selected with '+strict' in WM_COMPILE_CONTROL or 'wmake -strict', it
enables the FOAM_DEPRECATED_STRICT() macro, which can be used to
mark methods that are implicitly deprecated, but are not yet marked
as full deprecated (eg, API modification is too recent, generates
too many warnings). Can be considered a developer option.
- since the Apple SIP (System Integrity Protection) clears environment
variables such as DYLD_LIBRARY_PATH, a number of workarounds have
been used to provide shadow values. However, for a more robust
installation using -rpath at compilation time appears to be the
better solution.
In addition to the usual -rpath specification with absolute file
paths, MacOS supports (@loader_path, @executable_path) as well.
Now default to link with rpath information for MacOS, which can be
disabled by adding `~rpath` in WM_COMPILE_CONTROL
Explicit library paths handled:
- FOAM_FOAM_EXT_LIBBIN, FOAM_EXT_LIBBIN/FOAM_MPI
The executable rpaths are handled assuming a structure of
install-path/bin
install-path/lib/$(FOAM_MPI)
install-path/lib
Absolute compile-time paths for FOAM_USER_LIBBIN, FOAM_SITE_LIBBIN
and FOAM_LIBBIN are not handled since these are either too fragile
(FOAM_USER_LIBBIN and FOAM_SITE_LIBBIN values) or covered via
@loader_path anyhow (FOAM_LIBBIN).
Since the value of FOAM_MPI is a compile-time value, this rpath
treatment makes the installation less suitable for runtime changes
to the MPI vendor/version.
Note: no rpath added for c-only compilations since there are
currently no c-only libraries or executables with dynamic loading
- eliminate ClassName in favour of simple debug
- include Apple-specific FPE handling after local definition
to allow for more redefinitions
COMP: remove stray <csignal> includes
- naming like std::map::try_emplace(), it behaves like emplace_set()
if there is no element at the given location otherwise a no-op
ENH: reuse existing HashPtrTable 'slot' when setting pointers
- avoids extra HashTable operations
- the construction of compound tokens is now split into two stages:
- default construct
- read contents
This permits a larger variety of handling.
- the new token::readCompoundToken(..) method allows for simpler
more failsafe invocations.
- forward resize(), read() methods for compound tokens to support
separate read and population.
Top-level refCompoundToken() method for modify access.
ENH: split off a private readCompoundToken() method within ISstream
- this allows overloading and alternative tokenisation handling for
derived classes
- simplifies iteration of ITstream using nRemainingTokens() and skip()
methods or directly as a list of tokens.
The currentToken() method returns const or non-const access to
the token at the current tokenIndex.
The peekToken(label) method provides failsafe read access to tokens
at given locations.
ENH: add primitiveEntry construct with moving a single token
Increase usage of std algoritms within the OpenFOAM List classes. Remove reliance on linked-list during reading
See merge request Development/openfoam!620
- drop unnecessary Foam::Swap specializations when MoveConstructible
and MoveAssignable already apply. The explicit redirect to swap
member functions was needed before proper move semantics where
added.
Removed specializations: autoPtr, refPtr, tmp, UList.
Retained specialization: DynamicList, FixedList.
Special handling for DynamicList is only to accommodate dissimilar
sizing template parameters (which probably doesn't occur in
practice).
Special handling for FixedList to apply element-wise swapping.
- use std::swap for primitives. No need to mask with Foam::Swap wrapper
- fully implement DynamicList::readList() instead of simply
redirecting to List::readList(). This also benefits DynamicField.
Leverage DynamicList reading to simplify and improve CircularBuffer
reading.
- bracket lists are now read chunk-wise instead of using a
singly-linked list. For integral and vector-space types
(eg, scalar, vector, etc) this avoids intermediate allocations
for each element.
ENH: add CircularBuffer emplace_front/emplace_back
STYLE: isolate to-be-deprecated construct/assign forms
- still have construct/assign FixedList from a C-array.
This is not really needed, can use std::initializer_list
- still have construct/assign List from SLList.
Prefer to avoid these in the future.
DEFEATURE: remove construct/assign FixedList from SLList
- never used
DEFEATURE: remove move construct/assign List from SLList
- now unused. Retain copy construct/assign from SLList for transition
purposes.
- test for existing globalData() or perhaps use DIY globalIndex instead
STYLE: check for non-ASCII instead of BINARY with compression
- allows for other non-ASCII formats
- is_vectorspace :
test existence and non-zero value of the Type 'rank' static variable
- pTraits_rank :
value of 'rank' static variable (if it exists), 0 otherwise
- pTraits_nComponents :
value of 'nComponents' static variable (if it exists), 1 otherwise
- pTraits_has_zero :
test for pTraits<T>::zero member, which probably means that it also
has one, min, max members as well
Note that these traits are usable with any classes. For example,
- is_vectorspace<std::string>::value ==> false
- pTraits_nComponents<std::string>::value ==> 1
- pTraits<std::string>::nComponents ==> fails to compile
Thus also allows testing pTraits_rank<...>::value with items
for which pTraits<...>::rank fails to compile.
Eg, cyclicAMIPolyPatch::interpolate called by FaceCellWave with a
wallPoint.
pTraits<wallPoint>::rank ==> fails to compile
is_vectorspace<wallPoint>::value ==> false
GIT: relocate ListLoopM.H to src/OpenFOAM/fields/Fields (future isolation)
- in most cases a parallel-consistent order is required.
Even when the order is not important, it will generally require
fewer allocations to create a UPtrList of entries instead of a
HashTable or even a wordList.
- prefer csorted() method for const access since it ensures that the
return values are also const pointers (for example) even if
the object itself can be accessed as a non-const.
- the csorted() method already existed for HashTable and
objectRegistry, but now added to IOobjectList for method name
consistency (even although the IOobjectList only has a const-access
version)
ENH: objectRegistry with templated strict lookup
- for lookupClass and csorted/sorted. Allows isType restriction as a
compile-time specification.
* resize_null() methods for PtrList variants
- for cases where an existing PtrList needs a specific size and
but not retain any existing entries.
Eg,
ptrs.resize_null(100);
vs. ptrs.free(); ptr.resize(100);
or ptr.resize(100); ptrs.free();
* remove stored pointer before emplacing PtrList elements
- may reduce memory peaks
* STYLE: static_cast of (nullptr) instead of reinterpret_cast of (0)
* COMP: implement emplace_set() for PtrDynList
- previously missing, which meant it would have leaked through to the
underlying PtrList definition
* emplace methods for autoPtr, refPtr, tmp
- applies reset() with forwarding arguments.
For example,
tmp<GeoField> tfld = ...;
later...
tfld.emplace(io, mesh);
vs.
tfld.reset(new GeoField(io, mesh));
or
tfld.reset(tmp<GeoField>::New(io, mesh));
The emplace() obviously has reduced typing, but also allows the
existing stored pointer to be deleted *before* creating its
replacement (reduces memory peaks).
- this simplifies polling receives and allows separation from
the sends
ENH: add UPstream::removeRequests(pos, len)
- cancel/free of outstanding requests and remove segment from the
internal list of outstanding requests
- removed gatherv control.
The globalIndex information is cached on the merged surface
and thus not triggered often.
- strip out debug mergeField method which was a precursor to
what is now within surfaceWriter itself.
- add 'merge' true/false handling to allow testing without
parallel merging (implies no writing)
- continue to support spherical by default (for compatibility)
but add the 'spherical' switch to disable that and use a cubic
distribution instead.
STYLE: reduce number of inline files
Co-authored-by: Mark Olesen <>
- can be used, for example, to track global states:
// Encode as 0:empty, 1:uniform, 2:nonuniform, 3:mixed
PackedList<2> uniformity(fields.size());
forAll(fields, i)
{
uniformity.set(i, fields[i].whichUniformity());
}
reduce
(
uniformity.data(),
uniformity.size_data(),
bitOrOp<unsigned>()
);
- can reduce communication by only sending non-zero data (especially
when using NBX for size exchanges), but proper synchronisation with
multiply-connected processor/processor patches (eg, processorCyclic)
may still require speculative sends.
Can now setup for PstreamBuffers 'registered' sends to avoid
ad hoc bookkeeping within the caller.
- simplifies code by avoiding code duplication:
* parLagrangianDistributor
* meshToMesh (processorLOD and AABBTree methods)
BUG: inconsistent mapping when using processorLOD boxes (fixes#2932)
- internally the processorLODs createMap() method used a 'localFirst'
layout whereas a 'linear' order is what is actually expected for the
meshToMesh mapping. This will cause of incorrect behaviour
if using processorLOD instead of AABBTree.
A dormant bug since processorLOD is not currently selectable.
- when constructing from a sendMap, can now also specify a linear
receive layout instead of a localFirst layout
This will make it easier to reduce some code (#2932)
- add missing interface for simple distribute of List/DynamicList
with a specified commsType. Was previously restricted to
defaultCommsType only.
ENH: mapDistribute distribute/reverseDistribute with specified commsType
STYLE: prefer UPstream vs Pstream within mapDistribute
- replaces previous (similar) union but leverages the type tag for
handling logic
STYLE: remove unneeded refCount from exprResult
COMP: operator!= as member operator (exprResultDelayed, exprResultStored)
- the operator!= as a free function failed to resolve after removing
the refCount inheritance
- primarily for handling expression results,
but can also be used as a universal value holder.
Has some characteristics suitable for type-less IO:
eg, is_integral(), nComponents()
ENH: add is_pointer() check for expression scanToken
- handle existence/non-existence of a FoamFile header automatically
- support an upper limit when getting the number of blocks and
use that for a hasBlock(...) method, which will stop reading sooner.
- Time is normally constructed with READ_MODIFIED for its controlDict
and objectRegistry, but for certain applications (eg, redistributePar)
it can be useful to construct without file monitoring and specifying
MUST_READ instead.
Example,
Info<< "Create time\n" << Foam::endl;
Time runTime
(
Time::controlDictName,
args,
false, // Disallow functionObjects
true, // Allow controlDict "libs"
IOobjectOption::MUST_READ // Instead of READ_MODIFIED
);
- update TimeState access methods
- use writeTime() instead of old method name outputTime()
- use deltaTValue() instead of deltaT().value()
to avoids pointless construct of intermediate
- no change in behaviour except to emit a warning when called with the
a non-reading readOption
STYLE: remove redundant size check
- size checking is already done by Field::assign() within the
DimensionedField::readField
- commit fb69a54bc3 accidentally changed the constructMap compact
order from linear ordering to local elements first order. Seems to
interact poorly with other bookkeeping so doing a partial revert,
but still replacing the old allGatherList with exchangeSizes.
Note:
the processorLOD method does actually use a constructMap with local
elements first ordering, so some inconsistency may still exist
there
Corrects turbulence viscosity field (e.g. nut) within a specified
region by applying a maximum limit, set according to a coefficient
multiplied by the laminar viscosity:
\nu_{t,max} = c \nu
Corrections applied to:
nut | Turbulence vicosity [m2/s2]
Usage
Minimal example by using \c constant/fvOptions:
\verbatim
limitTurbulenceViscosity1
{
// Mandatory entries (unmodifiable)
type limitTurbulenceViscosity;
// Optional entries (runtime modifiable)
nut nut;
c 1e5;
// Mandatory/Optional (inherited) entries
...
}
The optional areaNormalisationMode entry determines how the area normalisation
is performed. Options are:
- `project`: tri face area dotted with patch face normal; same as v2212 (default)
- `mag`: tri face area magnitude (v2206 and earlier)
Example usage:
AMI1
{
type cyclicAMI;
...
areaNormalisationMode mag;
//areaNormalisationMode project;
}
- the special MacOS dlopen handling (commit f584ec97d0)
did not fully solve the problem with SIP clearing.
Eg, sourcing the RunFunctions (for runParallel) triggers SIP and
clears DYLD_LIBRARY_PATH. With the cleared path it finds the dummy
libraries: the dummy Pstream::init() fails.
- for simulations where the yPlus is needed for other purposes or
just for obtaining information on the patches it can be useful
to disable field writing and save disk space.
The 'writeFields' flag (as per some other function objects)
has been added control writing the yPlus volume field.
If unspecified, the default value is 'true' so that the yPlus
function object continues to work as before.
However, this default may change to 'false' in the future to align
with other function objects.
ENH: wallShearStress: support disable of field writing
- similar to yPlus, the write() method combines writing information
and writing the fields. The 'writeFields' flag allows some
separation of that logic.
- replace Map with a List or DynamicList to reduce the number of
operations and allocations within the loops.
Use polyBoundaryMesh::nProcessorPatches() for initial capacity
to avoid reallocations.
- returns the number of processorPolyPatch patches (finiteVolume)
or else the number of processorFaPatch patches (finiteArea).
These can be useful when sizing lists etc.
- the changes introduced in f215ad15d1 aim to reduce unnecessary
point-to-point communication. However, if there are also
processorCyclic boundaries involved, there are multiple connections
between any two processors, so simply skipping empty sends will cause
synchronization problems.
Eg,
On the send side:
patch0to1_a is zero (doesn't send) and patch0to1_b does send
(to the same processor).
On the receive side:
patch1to0_a receives the data intended for patch1to0_b !
Remedy
======
Simply stream all of send data into PstreamBuffers
(regardless if empty or non-empty) but track the sends
as a bit operation: empty (0) or non-empty (1)
Reset the buffer slots that were only sent empty data.
This adds an additional local overhead but avoids communication
as much as possible.
- files might have been set during token reading so only on
known on master processor.
Broadcast names to all processors (even alhough they are only
checked on master) so that the watched states remain synchronised
- freeCommmunicatorComponents needs an additional bounds check.
When MPI is initialized outside of OpenFOAM, there are no
UPstream communicator equivalents
- for boundary conditions such as uniformFixed, uniformMixed etc the
optional 'value' entry (optional) is used for the initial values and
restarts. Otherwise the various Function1 or PatchFunction1 entries
are evaluated and used determine the boundary condition values.
In most cases this is OK, but in some case such coded or expression
entries with references to other fields it can be problematic since
they may reference fields (eg, phi) that have not yet been created.
For these cases the 'value' entry will be needed: documentation
updated accordingly.
STYLE: eliminate some unneeded/unused declaration headers
- provides a more succinct way of writing
{fa,fv}PatchField<Type>::patchInternalField(*this)
as well as a consistent naming that can be used for patches derived
from valuePointPatchField
ENH: readGradientEntry helper method for fixedGradient conditions
- simplifies coding and logic.
- support different read construct modes for fixedGradient
- individual processor Time databases are purely for internal logistics
and should not be introducing any new library symbols: these will
already have been loaded in the outer loop.
- MPI_THREAD_MULTIPLE is usually undesirable for performance reasons,
but in some cases may be necessary if a linked library expects it.
Provide a '-mpi-threads' option to explicitly request it.
ENH: consolidate some looping logic within argList
- can be broadly categorised as 'unthreaded'
or 'collated' (threading requirement depends on buffering)
without other opaque inheritances.
CONFIG: add hostUncollated to bash completion prompt
- The Apple SIP (System Integrity Protection) clears environment
variables, which affects the behaviour of dynamic library loading
(the DYLD_LIBRARY_PATH env variable).
OpenFOAM shadows this variable as FOAM_LD_LIBRARY_PATH, which has
been used to restore DYLD_LIBRARY_PATH (eg, in RunFunctions script).
However, this solution is not quite complete, as it
(a) requires sourcing of RunFunctions file,
(b) additional errors appear depending on a user workflow.
This changeset alleviates the problem by also iterating through
paths stored in the shadow variable when loading dynamic libraries
(if the DYLD_LIBRARY_PATH is empty).
- with C++11, static constexpr variables apparently also require
definition in a translation unit and not just as inlined quantities.
Mostly not an issue, however gcc with -O0 does not do the inlining
and thus actually requires them to be defined in a translation unit
as well.
These variables were provided for symmetry with worldComm, but only
used in low-level internal code. Changing to inlined functions
solves the linkage issue and also aligns with the commWorld()
function naming.
Mnemonics:
MPI_COMM_SELF => UPstream::commSelf()
overall MPI_COMM_WORLD => UPstream::commGlobal(), sometimes commWorld()
local COMM_WORLD => UPstream::commWorld()
- useful when speculative receives have been initiated but are no
longer required.
Combines MPI_Cancel() + MPI_Request_free() for consistent resource
management. Currently no feedback provided if the request was
satisfied by a completed send/recv or by cancellation (can be added
later if required).
- primarily relevant for finite-area meshes, in which case they can be
considered to be an additional, detailed diagnositic that is
normally not needed (clutters the file system).
Writing can be enabled with the `-write-edges` option.
- enable 'faceZones' support.
- enable 'writeFile' support to better control file output.
- rename 'PatchPostProcessing' as 'ParticlePostProcessing' for better clarity.
- fix#1808
- enable 'faceZone' support.
- introduce 'cloudFunctionObjectTools' to simplify collection of particle info
on patches or face zones.
- enable 'writeFile' support to better control file output.
- rename 'PatchParticleHistogram' as 'ParticleHistogram' for better clarity.
- extend the loadOrCreateMesh functionality to work in conjunction
with file handlers. This allows selective loading of the mesh parts
without the ugly workaround of writing zero-sized meshes to disk and
then reading them back.
Co-authored-by: Mark Olesen <>
- fatten the interface to continue allowing write control with a bool
or with a dedicated file handler. This may slim down in the future.
Co-authored-by: mattijs <mattijs>
- use local function for the decision making, whether worldComm or a
dedicated communicator is needed (and which sibling ranks are
involved)
Co-authored-by: mattijs <mattijs>
- accept plain lists (space or comma separated) as well as the
traditional OpenFOAM lists. This simplifies argument handling
with job scripts.
For example,
simpleFoam -ioRanks 0,4,8 ...
vs
simpleFoam -ioRanks '(0 4 8)' ...
It is also possible to select the IO ranks on a per-host basis:
simpleFoam -ioRanks host ...
- expose rank/subrank handling as static fileOperation methods
- previously checked on destruction, but it is robuster to check for a
locally defined communicator during construction
- add InfoProxy output for fileOperation
ENH: add fileOperation::storeComm()
- transfers management of the communicator from external to internal.
Use with caution
- for special cases it can simplify sharing of processor communication
patterns, but no visible change for most code.
- make fileHandler communicator modifiable (mutable), for special
cases. The changes from 9711b7f1b9 now make this safer to do.
Continue to support legacy global function using an autoPtr:
autoPtr<fileOperation> Foam::fileHandler(autoPtr<fileOperation>&&);
However, new code using refPtr uses the following static method since
swapping out file handlers is an infrequent operation that should
also stand out a bit more.
fileOperation::fileHandler(...);
- consolidate file synchronization checks in dynamicCode
STYLE: report missing library on master only (not every rank)
- avoid flooding the output with messages
Co-authored-by: mattijs <mattijs>
- avoid explicit isFile() check in favour of a lazy-read.
With redistributePar + fileHandler, for example, it is possible that
the master processor finds file but not the subprocs
ENH: lazy reading of tetBasePtIs
- delay reading until needed
Co-authored-by: Mark Olesen <>
- added UPstream::allGatherValues() with a direct call to MPI_Allgather.
This enables possible benefit from a variety of internal algorithms
and simplifies the caller
Old:
labelList nPerProc
(
UPstream::listGatherValues<label>(patch_.size(), myComm)
);
Pstream::broadcast(nPerProc, myComm);
New:
const labelList nPerProc
(
UPstream::allGatherValues<label>(patch_.size(), myComm)
);
- Pstream::allGatherList uses MPI_Allgather for contiguous values
instead of the hand-rolled tree walking involved with
gatherList/scatterList.
-
- simplified the calling parameters for mpiGather/mpiScatter.
Since send/recv data types are identical, the send/recv count
is also always identical. Eliminates the possibility of any
discrepancies.
Since this is a low-level call, it does not affect much code.
Currently just Foam::profilingPstream and a UPstream internal.
BUG: call to MPI_Allgather had hard-coded MPI_BYTE (not the data type)
- a latent bug since it is currently only passed char data anyhow
UPstream::allocateCommunicator
- with contiguous sub-procs. Simpler, more compact handling, ranks
are guaranteed to be monotonic
UPstream::commWorld(label)
- ignore placeholder values, prevents accidental negative values
- make communicator non-optional for UPstream::broadcast(), which
means it has three mandatory parameters and thus always fully
disambiguated from Pstream::broadcast().
ENH: relax size checking on gatherList/scatterList
- only fatal if the List size is less than nProcs.
Can silent ignore any trailing elements: they will be untouched.
- calling the mixed BC dictionary construct with NO_READ leaves the
fields properly sized, but not initialised.
ENH: add mixed BC constructor zero initialise
- sometimes the last commit is not enough information about
the tested state (especially with extensive rebasing).
Also provide the short context of some previous commits.
- this refinement of commit 81807646ca makes these methods
consistent with other objects/containers.
The 'unsigned char' access is still available via cdata()
- extend toc/sortedToc wrappers to bitSet and labelHashSet to allow
use of BitOps::toc(...) in templated code
- size_data() method to return the number of addressed integer blocks
similar to size_bytes() does, but for int instead of char.
- use typeHeaderOk<regIOobject>(false) for some generic file existence
checks. Often had something like labelIOField as a placeholder, but
that may be construed to have a particular something.
- ensures that read failures can be properly detected
COMP: include refPtr.H instead of autoPtr.H in IOobject.H
- ensures inclusion of autoPtr/refPtr/tmp/stdFoam
ENH: add IOobject::resetHeader() method
- when re-using an IOobject for repeated read operations it enforces
resetting of headerClassName, scalar/label sizes etc prior to
reading. Permits convenient resetting of the name too (optional).
Example,
IOobject rio("none", ..., IOobject::LAZY_READ);
rio.resetHeader("U")
if (returnReduceOr(rio.typeHeaderOk<volVectorField>(false)))
...
io.resetHeader("p")
if (returnReduceOr(rio.typeHeaderOk<volScalarField>(false)))
...
- coupled patches are treated distinctly and independently of
internalFacesOnly, it makes little sense to report them with a
warning about turning off boundary faces (which would not work
anyhow).
STYLE: update code style for createBaffles
- permitting a cast to a non-const pointer adds uncertainty of
ownership.
- adjust PtrDynList transfer. Remove the unused 'PtrDynList::remove()'
method, which is better handled with pop().
- initialise with Switch::INVALID and then test if good() to
trigger the initial update.
This avoids some overhead, but primarily avoids ambiguity with
implicit casting to a 'bool' that autoPtr<bool> has.
- Allows clearing or freeing pointers without touching the underlying
list size. Was previously only for PtrDynList, but now available on
UPtrList, PtrList as well.
- add transfer() method to PtrDynList to avoid potential slicing.
- provide uniformMixed conditions for finite-area and finite-volume.
These are intended to replace the exprMixed condition but allow
the full range of different PatchFunction1 and Function1 types.
- add uniformFixedGradient to finite-area for completeness.
Note:
- still some possible difficulties with the order of evaluation.
- eg, using an expression within the 'U' field that depends
of the surface 'phi' field before that is constructed.
In this case, the 'value' entry is really needed.
- multiply-connected edges can arise at the centre of a "star"
connection or because the patch faces are actually baffles.
- In the serial case these internal edges are also rather dubious in
terms of modelling. However, when they are split across multiple
processors there can only be a single processor-to-processor
connectivity.
We don't necessary have enough information to know how things should
be connected, so connect pair-wise as the first remedial solution
- Any extra dangle edges are relegated to an 'ignore' faPatch
to tag as needing different handling.
- this is a placeholder boundary BC for using with bad or illegal
edges. It is currently functionally identical to zero-gradient.
Naming and definition still subject to change.
- this complements the whichPatch(meshFacei) method [binary search]
and the list of patchID() by adding internal range checks.
eg,
Before
~~~~~~
if (facei >= mesh.nInternalFaces() && facei < mesh.nFaces())
{
patchi = pbm.patchID()[facei - mesh.nInternalFaces()];
...
}
After
~~~~~
patchi = pbm.patchID(facei);
if (patchi >= 0)
{
...
}
- functionality introduced by openfoam.org to support selective
caching of temporary fields. The purpose is two-fold: to enable
diagnostics and to allow more places to use unregistered fields by
default.
For example to cache the grad(k) field in
cacheTemporaryObjects
(
grad(k)
);
If the name of a field which in never constructed is added to the
cacheTemporaryObjects list a waning message is generated which
includes a useful list of ALL the temporary fields constructed
during the time step
Multiple regions are also supported by specifying individual region
names in a cacheTemporaryObjects dictionary.
cacheTemporaryObjects
{
porous
(
porosityBlockage:UNbr
);
}
functions
{
writePorousObjects
{
type writeObjects;
libs (utilityFunctionObjects);
region porous;
writeControl writeTime;
writeOption anyWrite;
objects (porosityBlockage:UNbr);
}
}
- for interface polling previously required that both send and recv
requests were completed before evaluating (values or matrix update).
However, only the recv needs to be complete, which helps disentangle
the inter-rank waiting.
NB: this change is possible following (1f5cf3958b) that replaced
UPstream::resetRequests() call in favour of UPstream::waitRequests()
- UPstream exit with a non-zero return code is raised by things like
exit(FatalError) which means there is no reason to believe that
any/all of the buffered sends, requests etc have completed.
Thus avoid detaching buffers, freeing communicators etc in this
situation. This makes exit(1) behave much more like abort(), but
without any stack trace. Should presumably help with avoiding
deadlocks on exit.
ENH: support transfer from a wrapped MPI request to global list
- allows coding with a list UPstream::Request and subsequently either
retain that list or transfer into the global list.
- can use traits to distinguish label vs scalar types and
setComponents to properly index into single or multi-component
types without needing template specialisations for the task.
This avoids the need for a concrete translation unit and the
reported problem of multiply-defined specialisations when the header
is included in different places.
- the default (uninitialised) value for edge connections of -1
could be confused with a tagged finiteArea patch, which used
(-patchid-1) encoding. This would lead to messages about erroneous
processor-processor addressing, but is in fact an mismatched edge
connection.
Now tag the finiteArea patch as (-patchid-2) to avoid this ambiguity
and correctly generate an "Undefined connection:" message instead.
Properly flush the VTP writers before raising a FatalError
to ensure that they are not prematurely truncated.
Open Point:
The base problem of "Undefined connection:" is largely related to
multiply-connected face edges (ie, from the underlying volume mesh).
Not easily remedied in the finiteArea generation.
TUT: basic finiteArea setup on motorBike
- have read(nullptr, count) and readRaw(nullptr, count) act like a
forward seek instead of failing.
This lets it be used to advance through a file without needing to
allocate (and discard) storage space etc.
- construct from components, or use word::null to ensure
consistent avoid naming between IOobject vs dimensioned type.
- support construct with parameter ordering as per DimensionedField
ENH: instantiate a uniformDimensionedLabelField
- eg, for registering standalone integer counters
- directory discovery originally designed for a sub-dir location
(eg, etc/openfoam) but failed if called from within the sub-dir
itself.
Now simply assume it is located in the project directory or the etc/
sub-dir, so that it can also be relocated into the project directory
in the future (pending changes to RPM and debian packaging)
- for querying all outstanding requests:
if (UPstream::finishedRequests(startRequest)) ...
if (UPstream::finishedRequests(startRequest, -1)) ...
- for querying slice of outstanding requests:
if (UPstream::finishedRequests(startRequest, 10)) ...
- simplifies communication structuring with intra-host communication.
Can be used for IO only, or for specialised communication.
Demand-driven construction. Gathers the SHA1 of host names when
determining the connectivity. Internally uses an MPI_Gather of the
digests and a MPI_Bcast of the unique host indices.
NOTE:
does not use MPI_Comm_splt or MPI_Comm_splt_type since these
return MPI_COMM_NULL on non-participating process which does not
easily fit into the OpenFOAM framework.
Additionally, if using the caching version of
UPstream::commInterHost() and UPstream::commIntraHost()
the topology is determined simultaneously
(ie, equivalent or potentially lower communication).
- make sizing of commsStruct List demand-driven as well
for more robustness, fewer unneeded allocations.
- fix potential latent bug with allBelow/allNotBelow for proc 0
(linear communication).
ENH: remove unused/unusable UPstream::communicator optional parameter
- had constructor option to avoid constructing the MPI backend,
but this is not useful and inconsistent with what the reset or
destructor expect.
STYLE: local use of UPstream::communicator
- automatically frees communicator when it leaves scope
- these are primarily when encountering sparse (eg, inter-host)
communicators. Additional UPstream convenience methods:
is_rank(comm)
=> True if process corresponds to a rank in the communicators.
Can be a master rank or a sub-rank.
is_parallel(comm)
=> True if parallel algorithm or exchange is used on the process.
same as
(parRun() && (nProcs(comm) > 1) && is_rank(comm))
- for robustness with small edges (which can occur with snappy meshes),
the Le() and magLe() are limited to SMALL (commit a0f1e98d24).
Now use factor sqrt(1/3) in the components to maintain magnitude of 1.
ENH: add fvMesh::unitSf() and faMesh::unitLe() methods
- simple wrappers around Sf()/magSf() and Le()/magLe() but with
the potential for additional/alternative corrections.
STYLE: thisDb() in faMesh code to simplify future changes in storage
ENH: do not register finite-area geometric fields
- consistent with finite-volume treatment
- replace the "one-size-fits-all" approach of tensor field inv()
with individual 'failsafe' inverts.
The inv() field function historically just checked the first entry
to detect 2D cases and adjusted/readjusted *all* tensors accordingly
(to avoid singularity tensors and/or noisy inversions).
This seems to have worked reasonably well with 3D volume meshes, but
breaks down for 2D area meshes, which can be axis-aligned
differently on different sections of the mesh.
- with (nPollProcInterfaces < 0) it does the following:
- loop, waiting for some requests to finish
- for each out-of-date interface, check if its associated
requests have now finished (ie, the ready() check).
- if ready() -> call updateInterfaceMatrix()
In contrast to (nPollProcInterfaces > 0) which loops a specified
number of times with several calls to MPI_Test each time, the
(nPollProcInterfaces < 0) variant relies on internal MPI looping
within MPI_Waitsome to progress communication.
The actual dispatch still remains non-deterministic (ie, waiting for
some requests to finish does not mean that any particular interface
is eligible for update, or in any particular order). However, using
Waitsome places the tight looping into the MPI layer, which results
in few calls and eliminates behaviour dependent on the value of
nPollProcInterfaces.
TUT: add polling to windAroundBuildings case (for testing purposes)
- fewer calls, potentially more consistent
ENH: update sendRequest state after recvRequest wait
- previously had this type of code:
// Treat send as finished when recv is done
UPstream::waitRequest(recvRequest_);
recvRequest_ = -1;
sendRequest_ = -1;
Now refined as follows:
// Require receive data. Update the send request state.
UPstream::waitRequest(recvRequest_);
recvRequest_ = -1;
if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
Can potentially investigate with requiring both,
but this may be over-contrained.
Example,
// Require receive data, but also wait for sends too
UPstream::waitRequestPair(recvRequest_, sendRequest_);
- checks requests from completion, returning true when some requests
have completed and false when there are no active requests.
This allows it to be used in a polling loop to progress MPI
and then respond when as requests become satisfied.
When using as part of a dispatch loop, waitSomeRequests() is
probably more efficient than calling waitAnyRequest() and can help
avoid biasing which client requests are serviced.
Takes an optional return parameter, to retrieve the indices,
but more importantly to avoid inner-loop reallocations.
Example,
DynamicList<int> indices;
while (UPstream::waitSomeRequests(startRequest, &indices))
{
// Dispatch something ....
}
// Reset list of outstanding requests with 'Waitall' for safety
UPstream::waitRequests(startRequest);
---
If only dealing with single items and an index is required for
dispatching, it can be better to use a list of UPstream::Request
instead.
Example,
List<UPstream::Request> requests = ...;
label index = -1;
while ((index = UPstream::waitAnyRequest(requests)) >= 0)
{
// Do something at index
}
ENH: pair-wise wrappers for MPI_Test or MPI_Wait
- for send/recv pairs of requests, can bundle both together and use a
single MPI_Testsome and MPI_Waitall instead of two individual
calls.
- previously had an additional stack for freedRequests_,
which were used to 'remember' locations into the list of
outstandingRequests_ that were handled by 'waitRequest()'.
This was principally done for sanity checks on shutdown,
but we now just test for any outstanding requests that
are *not* MPI_REQUEST_NULL instead (much simpler).
The framework with freedRequests_ also had a provision to 'recycle'
them by popping from that stack, but this is rather fragile since it
would only triggered by some collectives
(MPI_Iallreduce, MPI_Ialltoall, MPI_Igather, MPI_Iscatter)
with no guarantee that these will all be properly removed again.
There was also no pruning of extraneous indices.
ENH: consolidate internal reset/push of requests
- replace duplicate code with inline functions
reset_request(), push_request()
ENH: null out trailing requests
- extra safety (paranoia) for the UPstream::Request versions
of finishedRequests(), waitAnyRequest()
CONFIG: document nPollProcInterfaces in etc/controlDict
- still experimental, but at least make the keyword known
- mechanism has been unused for at least a decade or more
(or was never used). Message tags are assigned on an ad hoc basis
locally when collision avoidance is necessary.
- not currently used, but it is possible that communicator allocation
modifies the list of sub-ranks. Ensure that the correct size is used
when (re)initialising the linear/tree structures.
STYLE: adjust MPI test applications
- remove some clutter and unneeded grouping.
Some ideas for host-only communicators
- allow reporting even when profiling is suspended
- consolidate reporting into profilingPstream itself
(avoids code scatter).
Example of possible advanced use for timing only one section of
code:
====
// Profile local operations
profilingPstream::enable();
... do something
// Don't profile elsewhere
profilingPstream::suspend();
====
- separate broadcast times from reduce/gather/scatter time
- separate wait times from all-to-all time
- support invocation counts, split off requests time/count
from others to avoid flooding the counts
- support 'detail' switch to increase the output information.
Format may change in the future
- attributes such as assignable(), coupled() etc
- common patchField types: calculatedType(), zeroGradientType() etc.
This simplifies reference to these types without actually needing a
typed patchField version.
ENH: add some basic patchField types to fieldTypes namespace
- allows more general use of the names
ENH: set extrapolated/calculated from patchInternalField directly
- avoids intermediate tmp
- with the current handling of small edges (finite-area), the LSQ
vectors can result in singular/2D tensors. However, the regular
2D handling in field inv() only detects based on the first element.
Provide a 'failsafe' inv() method for symmTensor and tensor that
follows a similar logic for avoiding zero determinates, but it is
applied on a per element basis, instead of deciding based on the
first field element.
The symmTensor::inv(bool) and tensor::inv(bool) methods have a
fairly modest additional overhead.
- unroll the field inv() function to avoid creating an intermediate
field. Reduce the number of operations when adjusting/re-adjusting
the diagonal.
- for cases where a 3D tensor is being used to represent 2D content,
the determinant is zero. Can use inv2D(excludeDirection) to compensate
and invert as if it were only 2D.
ENH: consistent definitions for magSqr of symmTensors, diagSqr() norm
COMP: return scalar not component type for magSqr
- had inconsistent definitions with SymmTensor returning the component
type and Tensor returning scalar. Only evident with complex.
- when only a partial stacktrace is desirable.
ENH: add stack trace decorators
- the 0-th frame is always printStack(), so skip that and emit
some headers/footers instead. Eg,
[stack trace]
=============
#1 Foam::SymmTensor<double> Foam::inv<double>(...)
#2 Foam::inv(Foam::UList<Foam::SymmTensor<double>> const&) ...
...
=============
- data_bytes(), size_bytes() methods to support broadcasting or
gather/scatter content. Additional construct from raw bytes
to support transmitting content.
- missed consistency in a few places.
- return nullptr (with automatic conversion to tmp) on failures
instead of tmp<....>(nullptr), for cleaner coding.
INT: add support for an 'immovable' tmp pointer
- this idea is from openfoam.org, to allow creation of a tmp that is
protected from having its memory reclaimed in field operations
ENH: tmp NewImmovable factory method, forwards as immovable/movable
- no-op implementations, but makes the call to
GeometricBoundaryField::evaluate() less dependent on PatchField type
- add updated()/manipulatedMatrix() methods to faePatchField,
fvsPatchField etc. These are mostly no-ops, but provide name
compatible with fvPatchField etc.
- similar to UPstream::parRun(), the setter returns the previous value.
The accessors are prefixed with 'comm':
Eg, commGlobal(), commWarn(), commWorld(), commSelf().
This distinguishes them from any existing variables (eg, worldComm)
and arguably more similar to MPI_COMM_WORLD etc...
If demand-driven communicators are added in the future, the function
call syntax can help encapsulate that.
Previously:
const label oldWarnComm = UPstream::warnComm;
const label oldWorldComm = UPstream::worldComm;
UPstream::warnComm = myComm;
UPstream::worldComm = myComm;
...
UPstream::warnComm = oldWarnComm;
UPstream::worldComm = oldWorldComm;
Now:
const label oldWarnComm = UPstream::commWarn(myComm);
const label oldWorldComm = UPstream::commWorld(myComm);
...
UPstream::commWarn(oldWarnComm);
UPstream::commWorld(oldWorldComm);
STYLE: check (warnComm >= 0) instead of (warnComm != -1)
- constructing with valueRequired as a bool is still supported,
but now also support more refined requirements
(eg, NO_READ, MUST_READ, LAZY_READ)
- continue with LAZY_READ for finite-area fields
- interpret as '-decomposeParDict xyz' for simpler scripting:
A empty value ("") as well as "none" or "false" values are ignored.
Eg,
unset decompDict
if some_condition; then decompDict=decomposeParDict-12; fi
runParallel -decompose-dict=$decompDict ...
ENH: more generous when scanning decomposeParDict for numberOfSubdomains
- assume file is in system/ directory if not otherwise found
- useful when regular contents are to be read via an IOobject and
returned.
Eg, dictionary propsDict(IOdictionary::readContents(dictIO));
vs. dictionary propsDict(static_cast<dictionary&&>(IOdictionary(dictIO)));
Commonly these would have simply been constructed directly as the
IO container:
eg, IOdictionary propsDict(dictIO);
However, that style may not ensure proper move semantics for return
types.
Now,
=====
labelList decomp(labelIOList::readContents(io));
... something
return decomp;
=====
Previously,
=====
labelIOList decomp(io);
// Hope for the best...
return decomp;
// Or be explicit and ensure elision occurs...
return labelList(std::move(static_cast<labelList&>(decomp)));
=====
Note:
labelList list(labelIOList(io));
looks like a good idea, but generally fails to compile
- the iterator/const_iterator now skip any nullptr entries,
which enables the following code to work even if the PtrList
contains nullptr:
for (const auto& intf : interfaces)
{
// Do something
...
}
- this is a change in behaviour compared to OpenFOAM-v2212 and earlier,
but is non-breaking:
* Lists without null entries will traverse exactly as before.
* Lists with null entries will now traverse correctly without
provoking a FatalError.
- allows unambiguous of count() for other classes.
Naming as per std::shared_ptr.
STYLE: qualify use_count() and unique() methods with the refCount base
- clearer/consistent meaning
- the null output adapter was previously used for the HashTables API
when HashSet actually stored key/value. Now that the node only
contains the key, having suppressed output is redundant, as is the
zero::null class (reduces clutter)
STYLE: replace one::minus dispatch in extendedEdgeMesh
GIT: remove Foam::nil typedef (deprecated since May-2017)
ENH: add pTraits and IO for std::int8_t
STYLE: cull some implicitly available includes
- pTraits.H is included by label/scalar etc
- zero.H is included by UList
STYLE: cull redundant forward declarations for Istream/Ostream
- in earlier versions: used 'fixed' notation
to force floating point numbers to be printed with at least
some decimal digits. However, in the meantime we are more
flexible with handling float/int input so remove this constraint.
- use ITstream::toString, which makes the string expansion of ${var}
and the expression expansion of $[var] consistent.
- other systems (eg, ARM64 linux with clang) do not have a separate
mpfr library configured so also check for mpfr (gmp is assumed to be
the same) and return corresponding cgal flavour (eg, header-no-mpfr)
Note:
in some borderline cases (eg, PDRFoam) the multiplication order
and rounding imposed by the lerp function may affect the
results slightly.
eg, (valueFraction_ * this->patch().deltaCoeffs()*refValue_)
vs. (valueFraction_ * (this->patch().deltaCoeffs()*refValue_))
- defined for lerp between two fields,
either with a constant or a field of interpolation factors.
* plain Field, DimensionedField, FieldField, GeometricFields
- using a field to lerp between two constants is not currently
supported
- clearer, more consistent parameter naming, which helps when
maintaining different field function types (eg, DimensionedFields,
GeometricFields)
- provide reuseTmpGeometricField::New taking a reference (not a tmp),
with forwarding. This helps centralise naming and acquisition etc
- split binary function macros into transform/interface
for easier support of different transform loops.
- initial field macros for looping over ternaries
- newer naming allows for less confusing code.
Eg,
max(lower) -> clamp_min(lower)
min(upper) -> clamp_max(upper)
- prefer combined method, for few operations.
Eg,
max(lower) + min(upper) -> clamp_range(lower, upper)
The updated naming also helps avoid some obvious coding errors.
Eg,
Re.min(1200.0);
Re.max(18800.0);
instead of
Re.clamp_range(1200.0, 18800.0);
- can also use implicit conversion of zero_one to MinMax<Type> for
this type of code:
lambda_.clamp_range(zero_one{});
- this is slightly longer to write (but consistent with clamp_min
etc). The main reason is that this allows easier use of the clamp()
free function.
STYLE: skip checks for bad/invalid clamping ranges
- ranges are either already validated before calling, the caller logic
has already made the branching decision.
- run-time warning about deprecated features. For example,
DeprecatedInFunction(2212)
<< "Prefer using xyz boundary condition. "
<< "This boundary condition will be removed in the future." << endl;
CONFIG: mark exprFixedValue as deprecated
- same functionality is possible with uniformFixedValue and an
expression PatchFunction1, which can also be easily changed to any
other PatchFunction1
- was using UPstream::procIDs(), which returns the sub-ranks with
respect to the parent communicator. This is normally just an
identity list (single-world) but with multi-world the indexing
is incorrect. Use UPstream::allProcs() instead.
- was only used in Pstream::combineReduce(...) with a full list,
which should have been avoided in most cases anyhow.
Much more efficient to simply gather the sizes directly
- adjust nullptr checks to discourage flip-flop when confronted with
multiple null values.
Old: (a && b) ? (*a < *b) : bool(a);
New: (a && b) ? (*a < *b) : !b;
comparing (non-null < null) and (null < non-null) behaves
identically, but comparing (null < null) now tests as true
(ie, already sorted) whereas before it would have been false
(ie, needs a swap)
- add UPtrList trimTrailingNull(), which reduces the effective
(addressable) list size to ignore any trailing null pointers, but
without reallocation. This is particularly useful when creating a
UPtrList list view. For example,
UPtrList<some_iterator> validValues(container.size());
...Loop to add valid entries, by some criteria...
// Shorten list to hide null entries
validValues.trimTrailingNull();
This list view now only needs a single allocation, whereas using
a resize (as was previously necessary) could invoke a second
allocation, as well as recopying.
- in most cases can simply construct mapDistribute with the sendMap
and have it take care of communication and addressing for the
corresponding constructMap.
This removes code duplication, which in some cases was also using
much less efficient mechanisms (eg, combineReduce on list of
lists, or an allGatherList on the send sizes etc) and also
reduces the number of places where Pstream::exchange/exchangeSizes
is being called.
ENH: reduce communication in turbulentDFSEMInlet
- was doing an allGatherList to populate a mapDistribute.
Now simply use PstreamBuffers mechanisms directly.
- dynamic sparse data exchange using Map to hold data and sizes.
Still uses the personalised exchange paradigm, but with non-blocking
consensus exchange to obtain the sizes and regular point-to-point
for the data exchange itself. This avoids an all-to-all but still
keeps the point-to-point for overlapping communication, data
chunking etc.
- to service both List and Map exchanges with limited message sizes
(termed 'data chunking' here) add a PstreamDetail for walking and
dispatching. Like other Detail components, the API is subject
to (possibly breaking) changes in the future at any time.
The regular exchangeBuf detail has this type of signature:
PstreamDetail::exchangeBuf
(
const UList<std::pair<int, stdFoam::span<const Type>>>& sends,
const UList<std::pair<int, stdFoam::span<Type>>>& recvs,
...
)
Where [rank, span] is the tuple pack.
The basic idea is to pre-process the send/receive buffers and
marshall them into a flat list of [rank, span] tuples.
The originating buffers could be any type of container (List or Map)
which is then marshalled into this given sequence that can be
processed in source-agnostic fashion.
If data chunking is required (when UPstream::maxCommsSize > 0)
it is possible to make a cheap copy of the rank/address information
and then walk different slices or views.
ENH: replace private static methods with PstreamDetail functions
- simpler to update locally.
- since List is being used to manage the storage content for
DynamicList, it needs to free old memory for zero-sized lists first.
Consider this case (slightly exaggerated):
line 0: DynamicList<label> list;
line 1: list.reserve(100000);
line 2: list.reserve(200000);
After line 0:
- list has size=0, capacity=0 and data=nullptr
After line 1:
- list has size=0, capacity=1e+5 and data != nullptr
After line 2:
- list has size=0, capacity=2e+5 and data != nullptr
---
The internal resizing associated with line 1 corresponds to what the
List resize would naturally do. Namely allocate new storage, copy/move
any overlapping elements (in this case none) before freeing the old
storage and replacing with new storage.
Applying the same resizing logic for line 2 means, however, that the
old memory (1e5) and new memory (2e5) are temporarily both
accessible - leading to an unnecessary memory peak.
Now: if there is no overlap, just remove old memory first.
- basic functionality similar to std::span (C++20).
Holds pointer and size: for lightweight handling of address ranges.
- implements cdata_bytes() and data_bytes() methods for similarity
with UList. For span, however, both container accesses are const
but the data_bytes() method is only available when the
underlying pointer is non-const.
No specializations of std::as_bytes() or std::as_writeable_bytes()
as free functions, since std::byte etc are not available anyhow.
- name and functionality similar to std::unordered_map (C++17).
Formalizes what had been previously been implemented in IOobjectList
but now manages without pointer deletion/creation.
- use persistent PstreamBuffers between iterations, restrict size
information exchange to the processor neighbours (which is what the
algorithm is handling there anyhow).
- attempted reduction in bookkeeping (commit: 068ab8ccc7) meant that
the worldComm didn't have a group from which sub-communicators could
be spun off.
- do not force reset of PstreamBuffers positions
STYLE: UPstream::globalComm instead of '0'
- functionality provided as 'found(key)' in OpenFOAM naming, since
there was no stl equivalent at the time. Now support contains(),
which is the equivalent for C++20 maps/sets.
STYLE: general contains() method for containers
STYLE: treat Enum and Switch similarly as hash-like objects
- waits for completion of any of the listed requests and returns the
corresponding index into the list.
This allows, for example, dispatching of data when the receive is
completed.
- make nProcs() independent of internal storage mechanism.
- reset receive positions with finished sends
- use size of received buffers to manage validity instead of
an separate additional gather operation.
- clearing the receive 'slots' is preferrable to clearing out the map
itself since this can potentially preserve allocated space (eg
DynamicList entries) between calls.
BUG: remove stray MPI barrier in exchange code
- permits distinction between communicators/groups that were
user-created (eg, MPI_Comm_create) versus those queried from MPI.
Previously simply relied on non-null values, but that is too fragile
ENH: support List<Request> version of UPstream::finishedRequests
- allows more independent algorithms
ENH: added UPstream::probeMessage(...). Blocking or non-blocking
- allows the possibility of using demand-driven internal buffers
and/or different storage mechanisms.
Changes:
* old: sendBuf_[proci] -> accessSendBuffer(proci)
* old: recvBuf_[proci] -> accessRecvBuffer(proci)
* old: recvBufPos_[proci] -> accessRecvPosition(proci)
only affects internals of UIPstreamBase and UOPstreamBase
BUG: reduceOr in PstreamBuffers uses world communicator
- should respect the value of the communicator defined within
PstreamBuffers
- previously built the entire adjacency table (full communication!)
but this is only strictly needed when using 'scheduled' as the
default communication mode. For blocking/nonBlocking modes this
information is not necessary at that point.
The processorTopology::New now generally creates a smaller amount of
data at startup: the processor->patch mapping and the patchSchedule.
If the default communication mode is 'scheduled', the behaviour is
almost identical to previously.
- Use Map<label> for the processor->patch mapping for a smaller memory
footprint on large (ie, sparsely connected) cases. It also
simplifies coding and allows recovery of the list of procNeighbours
on demand.
- Setup the processor initEvaluate/evaluate states with fewer loops
over the patches.
========
BREAKING: procNeighbours() method changed definition
- this was previously the entire adjacency table, but is now only the
processor-local neighbours. Now use procAdjacency() to create or
recover the entire adjacency table.
The only known use is within Cloud<ParticleType>::move and there it
was only used to obtain processor-local information.
Old:
const labelList& neighbourProcs =
mesh.globalData().topology().procNeighbours()[Pstream::myProcNo()];
New:
const labelList& neighbourProcs =
mesh.globalData().topology().procNeighbours();
// If needed, the old definition (with communication!)
const labelListList& connectivity =
mesh.globalData().topology().procAdjacency();
In the 'standard' and 'UaGradU' options for the ATC term of the adjoint
equations, there is an option to add 'aritificial dissipation', by
adding and subtracting a multiple of the adjoint convection term with
different discretizations. The implicit part was not multiplied with the
ATClimiter whereas the explicit one was, leading to mismatched
contributions in the areas affected by the ATClimiter, which could
affect the sensitivity derivatives.
- field blocking/exclusion added in commit d9ab5d54ef,
but was incorrectly doing a lookup for "blockField" for ensight
although "excludeFields" was documented (and expected).
Now corrected to use "excludeFields"
transformation support in-place modifies the data (e.g. to
add a transform). This might cause the neighbour side patch
to pick up owner side information.
- wish to deprecate and remove exprFixedValue in the future since the
same functionality is possible using patch expressions with a
uniformFixedValue condition.
- skip loading of fields with -no-internal, -no-boundary
- suppress reporting fields with -no-internal, -no-boundary
- cache loaded volume field for reuse with point interpolation.
Trade off some memory overhead against reading twice.
NOTE: this issue will not be evident with foamToEnsight since there
it only handles cell data *or* point data (not both), so a field is
only ever loaded/processed once.
- This simplifies definition of 'lazier' (READ_IF_PRESENT)
construction or assignment.
For construction:
- For MUST_READ and key not found: FatalIOError.
- For LAZY_READ and key not found: initialise field with Zero.
- For NO_READ and key not found: simply size the field.
For assignment:
- If len == 0 : a no-op and return True.
- For NO_READ : a no-op and return False.
- For MUST_READ and key not found : FatalIOError
- encompasses isReadOptional or isReadRequired check
STYLE: allow LAZY_READ as a shorter synonym for READ_IF_PRESENT
- add helper for downgrading MUST_READ... to LAZY_READ
- with geometryOrder=1, edge normal calculation is done directly from
the faces, whereas geometryOrder=2 they are calculated based on the
point normals of each end.
In both cases, the geometry calculation uses processor communication
(with corresponding waitRequests etc).
Since the final correction and the halo face normals also need
collective communication, these routines must be triggered on all
processors or they will block. Thus also include edgeAreaNormals()
triggering in addition to pointAreaNormals() triggering.
- handle lower geometryOrder values directly within edgeAreaNormals()
and reuse the results within Le().
- direct nonBlocking recv/send of edge normals instead using the
intermediate processorLduInterface buffers
- symmetrical evaluation for processor patches, eliminates
scalar/vector multiply followed by projection.
STYLE: use evaluateCoupled instead of local versions
- vector, tensor versions are defined component-wise
to avoid intermediates.
The base version uses the form "(1-t)*a + t*b" without any bounds
checking (ie, will also extrapolate).
- proper component-wise clamping for MinMax clamp().
- construct clampOp from components
- propagate clamp() method from GeometricField to FieldField and Field
- clamp_min() and clamp_max() for one-sided clamping,
as explicit alternative to min/max free functions which can
be less intuitive and often involve additional field copies.
- top-level checks to skip applying invalid min/max ranges
and bypass the internal checks of MinMax::clamp() etc.
GIT: primitives/compat with compatibility includes
GIT: primitives/traits with pTraits, contiguous, zero, one etc.
COMP: relocate base equal(a,b) definition from scalar.H -> label.H
- make more universally available
STYLE: replace occasional use of notEqual(a,b) with !equal(a,b)
- avoids implicit promotion of label to scalar for no-op,
or alternatively promotion of symmTensor to tensor for no-op
(ie, ambiguous).
- fix incorrect transform(.., symmTensor, ...) declarations.
COMP: update include for CGAL-5.5 (#2665)
old: Robust_circumcenter_filtered_traits_3
new: Robust_weighted_circumcenter_filtered_traits_3
COMP: adjust CGAL rule for OSX (#2664)
- since CGAL is now header-only, the previous OSX-specific rules have
become redundant
STYLE: rename some internal buffers with the data types
low-level : byteSendBuf_, byteRecvBuf_
field level: sendBuf_, recvBuf_
solve level: scalarSendBuf_, scalarRecvBuf_
- with alternative faceCell addressing, use the three-parameter
version only. This avoids potential future ambiguity with the
two-parameter version (eg, with a label type)
ENH: add faPatchField patchInternalField() for symmetry with fvPatchField
ENH: direct reference to mesh thisDb instead of inferring
ENH: pointMesh::boundaryMesh() method (eg, similar to fvMesh)
- UPstream::Request wrapping class provides an opaque wrapper for
vendor MPI_Request values, independent of global lists.
ENH: support for MPI barrier (blocking or non-blocking)
ENH: support for MPI sync-send variants
STYLE: deprecate waitRequests() without a position parameter
- in many cases this can indicate a problem in the program logic since
normally the startOfRequests should be tracked locally.
- reduces clutter. In some cases the Fwd typedefs were also incorrect
STYLE: combine Scalar specialisations into corresponding PatchFields.C
- reduces clutter, simplifies future adjustments
- simplifies code, consistent with other matrix transfer functions.
Use a setter method.
STYLE: AMIInterpolation::upToDate(bool) setter method
ENH: add guards to avoid float-compressed transfer of integral types
STYLE: drop unused debug member from abstract interface classes
- now simply a no-op for out-of-range values (instead of an error),
which simplifies the calling code.
Previously
==========
if (request_ >= 0 && request_ < UPstream::nRequests())
{
UPstream::waitRequest(request_);
}
Updated
=======
UPstream::waitRequest(request_);
- when 'recycling' freed request indices, ensure they are actually
within the currently addressable range
- MPI finalization now checks outstanding requests against
MPI_REQUEST_NULL to verify that they have been waited or tested on.
Previously simply checked against freed request indices
ENH: consistent initialisation of send/receive bookkeeping
- old logic (v2206 and earlier) always disabled writing on non-master,
but other parts of the code were more recently updated to use lazy
evaluation of surface data (with parallel communication)
- now retain full write/no-write logic identically on all ranks. Take
care of master/non-master at the final output stage.
It has been observed that the finite-area framework is prone to numerical
issues when zero-valued edge lenghts, edge/face normals and face areas exist.
To improve exception handling at identified code sections to gracefully
overcome math errors, the problematic entities are lower-bounded by SMALL.
Specified using the optional 'omega' entry (Function1 type), e.g. for a constant
value:
omega 12.56;
Note that the swirl contribution is applied in addition to the velocity set by
the 'flowType' option. For example, for the 'constantVelocity' option, parcels
are initially set the velocity according to the UMag and direction/cone angle;
the swirl velocity is then added.
- similar to surface writing formats, also support optional
dictionary of reading options. The main beneficiary of this is the
ensight surface reader:
readOptions
{
ensight
{
masterOnly true;
}
}
This will restrict reading to the master rank. Surfaces and values
read will be broadcast to the other ranks, with the intention of
reducing load on the filesystem.
ENH: add writing of Dimensioned fields for areaWrite functionObject
- can be useful for examining finite-area source terms
- flowRate: volume flow-rate through given patches
- flowRatePartition: distribution of the inlet flow-rate to certain
outlet patches, with given percentages
- uniformityPatch: uniformity of the velocity field at given (outlet) patches,
expressed as (half) the variance of the velocity field
- uniformityCellZone: same as uniformityPatch, but defined over
cellZones
- powerDissipation: the fluid power dissipation taking place within
given cellZones. In the absence of viscous stress at the "inlets" and
"outlets" of the cellZones, this corresponds to the volume flow-rate
weighted total pressure losses through the cellZones
ENH: updated nutSqr so it can be used with adjointkOmegaSST too
to help allocate pointers related to contributions to the adjoint
turbulence model PDEs, populate them and check the validity of the
cellZones provided for cellZone-based objectives
This pack adds a new entry 'parcelTypes' which can specify the list of
parcel type IDs interacting with a surface film. If the entry
is omitted, all particle types are considered.
```
surfaceFilmModel kinematicSurfaceFilm;
kinematicSurfaceFilmCoeffs
{
interactionType absorb;
// Optional list of participating parcel IDs
parcelTypes (10);
}
```
To set the parcel type by injector, 'injectorID' entry can be used
when specifying the injector models, e.g.
```
injectionModels
{
model1
{
type <injectionModelType>;
// Optional injector ID
// - if ommitted, parcels use '-1'
injectorID 10;
...
}
}
```
- 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
- comprises a few different elements:
FilterField (currently packaged in PatchFunction1Types namespace)
~~~~~~~~~~~
The FilterField helper class provides a multi-sweep median filter
for a Field of data associated with a geometric point cloud.
The points can be freestanding or the faceCentres (or points)
of a meshedSurface, for example.
Using an initial specified search radius, the nearest point
neighbours are gathered and addressing/weights are built for them.
This currently uses an area-weighted, linear RBF interpolator
with provision for quadratic RBF interpolator etc.
After the weights and addressing are established,
the evaluate() method can be called to apply a median filter
to data fields, with a specified number of sweeps.
boundaryDataSurfaceReader
~~~~~~~~~~~~~~~~~~~~~~~~~
- a surfaceReader (similar to ensightSurfaceReader) when a general
point data reader is needed.
MappedFile
~~~~~~~~~~
- has been extended to support alternative surface reading formats.
This allows, for example, sampled ensight data to be reused for
mapping. Cavaet: multi-patch entries may still needs some work.
- additional multi-sweep median filtering of the input data.
This can be used to remove higher spatial frequencies when
sampling onto a coarse mesh.
smoothSurfaceData
~~~~~~~~~~~~~~~~~
- standalone application for testing of filter radii/sweeps
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
Grid independency studies and grid adaptation for implicit LES/DES are
nontrivial and intractable due to the inherent coupling between spatial
resolution and subgrid-scale modelling.
To enable assessments for LES/DES resolution, a function object of
single-mesh resolution index with three submodels is introduced.
- replaced PstreamBuffers mechanism with globalIndex for both gather
and scatter operations. Use scheduled communication by default, but
is selectable.
- reduced communication with ensemble averaging and no-write
- pattern as per surfaceFieldValue::setFaceZoneFaces()
1. define faceId, facePatchId assuming an internal face
2. if actually a boundary face:
- get facePatchId
- ignore if emptyPolyPatch or coupledPolyPatch (neighbour side)
- get patch relative faceId
This currently seems to be the least amount of code clutter.
ENH: recover some memory my shrinking lists in fluxSummary
BUG: potentially trailing rubbish in the heatExchangerModel lists
- the final resize to length actually used was missing.
Does not affect any released versions
- 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.
- if the volume faceProcAddressing is missing, it is not readily
possible to determine equivalent area procAddressing.
Instead of throwing an error, be more fault-tolerant by having it
create with READ_IF_PRESENT and then detect and warn
if there are problems.
- 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.
- for repeated tests (eg, during bisection) can be used to preserve
the existing directory as tutorialsTest.bak01,
tutorialsTest.bak02, ... (max of 10).
- preserve the commit information as tutorialsTest/commit-info
to help document the current or backup test results.
- 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
- functionality similar to that provided by foamToEnsight, foamToVTK
which allows blocking out patches (eg, outer walls, inlet/outlet)
that are not particularly interesting to visualize
- since ensight format is always float and also always written
component-wise, perform the double -> float narrowing when
extracting the components. This reduces the amount of data
transferred between processors.
ENH: avoid vtk/ensight parallel communication of empty messages
- since ensight writes by element type (eg, tet, hex, polyhedral) the
individual written field sections will tend to be relatively sparse.
Skip zero-size messages, which should help reduce some of the
synchronization bottlenecks.
ENH: use 'data chunking' when writing ensight files in parallel
- since ensight fields are written on a per-element basis, the
corresponding segment can become rather sparsely distributed. With
'data chunking', we attempt to get as many send/recv messages in
before flushing the buffer for writing. This should make the
sequential send/recv less affected by the IO time.
ENH: allow use of an external buffer when writing ensight components
STYLE: remove last vestiges of autoPtr<ensightFile> for output routines
- 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.
- eg, for partially incomplete systems (without libz devel header)
ENH: clearer binding of dummy Pstream in OpenFOAM/Make/options
- link of dummy stub Pstream now contingent on linking libOpenFOAM as
well. This makes the purpose slightly clearer
ENH: cleaner option naming/handling in wmake script
- allow special purpose -no-openfoam option.
Eg, compiling test programs without OpenFOAM and Pstream libraries
but using the rest of the wmake system.
ENH: add +openmp support into WM_COMPILE_CONTROL (#2633)
- this adds compile/link flags for openmp.
For single-use, can also use 'wmake -openmp'.
If both +openmp and ~openmp are specified in WM_COMPILE_CONTROL
the ~openmp will have priority.
This is actually done indirectly since ~openmp will set empty
COMP_OPENMP, LINK_OPENMP internal variables, which the +openmp then
adds to the c++FLAGS and linkexe targets (ie, won't actually add
anything).
ENH: add +ccache or ccache=... support into WM_COMPILE_CONTROL (#2633)
- with the first version (+ccache), simply use ccache from the path
without any extra options.
- with the second version (ccache=...), can be more specific about
what is called.
Using "+ccache" is identical to "ccache=ccache", but the later could
be used in other ways. For example,
ccache=/strange/install/path/ccache
ccache=</path/my-tooling --option>
Have the choice of unquoted, single or double quoted or '< >' quoted
STYLE: relocate FOAM_EXTRA_LDFLAGS in general makefile
- removes clutter for different linkers (eg, gold, mold, ldd)
making it easier to extend for other linkers.
STYLE: protect makefile checks with 'strip' function
- consistent with sumOp
ENH: globalIndex with gatherNonLocal tag, and use leading dispatch tags
- useful for gather/write where the master data can be written
separately. Leading vs trailing dispatch tags for more similarity to
other C++ conventions.
- new submodels:
- 'equalBinWidth': groups data into bins of equal widths (previous behaviour)
- 'unequalBinWidth': groups data into bins of unequal widths
- output files per time-step are replaced with a single output file
- silently deprecates the input entries: 'setFormat' and 'formatOptions'
The improvements include:
- Allowing overset patches to be displaced outside background domain.
- The approach does not support overlapping of multiple inset meshes
on top of background domain.
- Allowing fringe faces to walk away from hole cells in background domain.
- The approach was not extensibly tested with overlapping patches.
- Improving mass conservation.
- Various experimental entries are removed: massFluxInterpolation, ddtCorr.
- New entries:
- oversetAdjustPhi: adds a flux correction outside the pressure equation.
- massCorrection: adds an implicit correction.
- replaced ad hoc handling of formatOptions with coordSetWriter and
surfaceWriter helpers.
Accompanying this change, it is now possible to specify "default"
settings to be inherited, format-specific settings and have a
similar layering with surface-specific overrides.
- snappyHexMesh now conforms to setFormats
Eg,
formatOptions
{
default
{
verbose true;
format binary;
}
vtk
{
precision 10;
}
}
surfaces
{
surf1
{
...
formatOptions
{
ensight
{
scale 1000;
}
}
}
}
- for later reuse with fields (for example)
ENH: use 'scheduled' for surfaceWriter field merging (#2402)
- in tests with merging fields (surfaceWriter), 'scheduled' was
generally faster than 'nonBlocking' for scalars, minorly faster for
vectors.
Thus make 'scheduled' the default for the surfaceWriter but with a
user-option to adjust as required. Previously simply relied on
whichever default globalIndex had (currently nonBlocking).
Reuse globalIndex information from mergedSurf instead of
globalIndex::gatherOp to avoid an extra MPI call to gather sizes
each time.
These changes will not be noticable unless surface sampling is done
very frequently (eg, every iteration) and with large core counts.
- support globalIndex for points/faces as an output parameter,
which allows reuse in subsequent field merge operations.
- make pointMergeMap an optional parameter. This information is not
always required. Eg, if only using gatherAndMerge to combine faces
but without any point fields.
ENH: make globalIndex() noexcept, add globalIndex::clear() method
- end_value() corresponds to the infrequently used after() method, but
with naming that corresponds better to iterator naming conventions.
Eg,
List<Type> list = ...;
labelRange range = ...;
std::transform
(
(list.data() + range.begin_value()),
(list.data() + range.end_value()),
outIter,
op
);
- promote min()/max() methods from labelRange to IntRange base class
STYLE: change timeSelector from "is-a" to "has-a" scalarRanges.
- resets min/max to be identical to the specified value,
which can be more convenient (and slightly more efficient) than doing
a full reset followed by add()
- additional MinMax intersects() query, which works like overlaps()
but with exclusive checks at the ends
- provide MinMax::operator&=() to replace (unused) intersect() method
ENH: single/double value reset method for boundBox
- boundBox::operator&=() to replace (rarely used) intersect() method.
Deprecate boundBox::intersect() to avoid confusion with various
intersects() method
COMP: provide triangleFwd.H
- background: for some application it can be useful to have fully
sorted points. i.e., sorted by x, followed by y, followed by z.
The default VectorSpace 'operator<' compares *all*
components. This is seen by the following comparisons
1. a = (-2.2 -3.3 -4.4)
b = (-1.1 -2.2 3.3)
(a < b) : True
Each 'a' component is less than each 'b' component
2. a = (-2.2 -3.3 -4.4)
b = (-2.2 3.3 4.4)
(a < b) : False
The a.x() is not less than b.x()
The static definitions 'less_xyz', 'less_yzx', 'less_zxy'
instead use comparison of the next components as tie breakers
(like a lexicographic sort).
- same type of definition that Pair and Tuple2 use.
a = (-2.2 -3.3 -4.4)
b = (-2.2 3.3 4.4)
vector::less_xyz(a, b) : True
The a.x() == b.x(), but a.y() < b.y()
They can be used directly as comparators:
pointField points = ...;
std::sort(points.begin(), points.end(), vector::less_zxy);
ENH: make VectorSpace named access methods noexcept.
Since the addressing range is restricted to enumerated offsets
(eg, X/Y/Z) into storage, always remains in-range.
Possible to make constexpr with future C++ versions.
STYLE: VectorSpace 'operator>' defined using 'operator<'
- standard rewriting rule
- useful when a characteristic per-face search dimension is required.
With PrimitivePatch we are certain to have consistent evaluations
of the face centre.
STYLE: tag PrimitivePatch compatibility headers as such
STYLE: combine templated/non-templated headers (reduced clutter)
STYLE: use hitPoint(const point&) combined setter
- same as setHit() + setPoint(const point&)
ENH: expose and use labelOctBits::pack method for addressing
- the old List_FOR_ALL macro only remained in use in relatively few
places. Replace with the expanded equivalent and move the looping
parameter out of the macro and give an explicit name (eg, loopLen)
which simplifies the addition of any loop pragmas in the various
TFOR_ALL... macros (for example).
- in places where direct reading from the std::stream is used,
this method can be used to ensure that the OpenFOAM Sstream state
is properly updated from the std::stream.
ENH: restrict stream renaming to ISstream
- non-const access was previously declared at the top-level (IOstream)
but that not only added in potentially odd setting of the static
fileName, but also meant that the OFstream name() could potentially
be altered after opening a file and thus be inconsistent with the
underlying file that had been opened.
Now restrict name modification to ISstream (and ITstream
counterpart). Does not affect any existing valid code.
STYLE: non-default OFstream destructor (for future file staging)
- construct boundBox from Pair<point> of min/max limits,
make sortable
- additional bounding box intersections (linePointRef), add noexcept
- templated access for boundBox hex-corners
(used to avoid temporary point field).
Eg, unrolled plane/bound-box intersection with early exit
- bounding box grow() to expand box by absolute amounts
Eg,
bb.grow(ROOTVSMALL); // Or: bb.grow(point::uniform(ROOTVSMALL));
vs
bb.min() -= point::uniform(ROOTVSMALL);
bb.max() += point::uniform(ROOTVSMALL);
- treeBoundBox bounding box extend with two or three parameters.
The three parameter version includes grow(...) for reduced writing.
Eg,
bb = bb.extend(rndGen, 1e-4, ROOTVSMALL);
vs
bb = bb.extend(rndGen, 1e-4);
bb.min() -= point::uniform(ROOTVSMALL);
bb.max() += point::uniform(ROOTVSMALL);
This also permits use as const variables or parameter passing.
Eg,
const treeBoundBox bb
(
treeBoundBox(some_points).extend(rndGen, 1e-4, ROOTVSMALL)
);
- box method on meshShapes (cell,edge,face,triangle,...)
returns a Pair<point>.
Can be used directly without dependency on boundBox,
but the limits can also passed through to boundBox.
- Direct box calculation for cell, which walks the cell-faces and
mesh-faces. Direct calculation for face (#2609)
- with geometryOrder=1, calculate the edge normals from the adjacent
faces (area-weighted, inverse distance squared) and also
use that for the Le() calculation.
Includes the contributions from processor edge neighbours, so it
should be consistent on both sides.
This new method (consider as 'beta') contrasts with the current
standard method that first calculates area-weighted point normals
and uses the average of them for the edge normal.
Enable for testing either with a controlDict OptimisationSwitch entry
"fa:geometryOrder", or on the command-line:
solverName -opt-switch=fa:geometryOrder=1
- the Le vector is calculated from (edgeVec ^ edgeNorm)
and should be oriented in direction (faceCentre -> edgeCentre).
If, however, the edgeNorm value is bad for any reason, the
cross-product falls apart and Le vector is calculated as a zero
vector!
For these cases, revert to using (faceCentre -> edgeCentre)
as a better approximation than a zero vector.
In the future, will very likely switch calculating the edge normals
directly from the attached faces, instead of from the attached
points as is currently done, which should improve robustness.
ENH: expose fa:geometryOrder as a registered OptimisationSwitch
ENN: reuse polyMesh data (eg, faceCentres) if possible in faMesh
STYLE: add code lambdas and static functions to isolate logic
ENH: extend rmDir to handle removal of empty directories only
- recursively remove directories that only contain other directories
but no other contents. Treats dead links as non-content.
- stem(), replace_name(), replace_ext(), remove_ext() etc
- string::contains() method - similar to C++23 method
Eg,
if (keyword.contains('/')) ...
vs
if (keyword.find('/') != std::string::npos) ...
- construct based on db and mesh information from an existing field
- check movable() instead of isTmp() when reusing fields
STYLE: isolate check for reuse GeometricField into Detail namespace
- code remnant from separate lookup + construct of coordinateSystem
(7b2bcfda0b).
Apply consistent use of coordinateSystem::NewIfPresent to avoid
these types of coding mishaps
- in continuation of #2565 (rotationCentre for surface output formats)
it is helpful to also support READ_IF_PRESENT behaviour for the
'origin' keyword.
This can be safely used wherever the coordinate system definition
is embedded within a sub-dictionary scope.
Eg,
dict1
{
coordinateSystem
{
origin (0 0 0); // now optional here
rotation ...;
}
}
but remains mandatory if constructed without a sub-dict:
dict2
{
origin (0 0 0); // still mandatory
e1 (1 0 0);
e3 (0 0 1);
}
With this change, the "transform" sub-dictionary can written
more naturally:
formatOptions
{
vtk
{
scale 1000; // m -> mm
transform
{
rotationCentre (1 0 0);
rotation axisAngle;
axis (0 0 1);
angle -45;
}
}
}
ENH: simplify handling of "coordinateSystem" dictionary lookups
- coordinateSystems::NewIfPresent method for optional entries:
coordSysPtr_ = coordinateSystem::NewIfPresent(mesh, dict);
Instead of
if (dict.found(coordinateSystem::typeName, keyType::LITERAL))
{
coordSysPtr_ =
coordinateSystem::New
(
mesh_,
dict,
coordinateSystem::typeName
);
}
else
{
coordSysPtr_.reset();
}
ENH: more consistent handling of priorities for binModels, forces (#2598)
- if the dictionaries are overspecified, give a 'coordinateSystem'
entry a higher prioriy than the 'CofR' shortcuts.
Was previously slightly inconsistent between the different models.
- previously had 'mandatory' (bool) for advanced control of reading
dictionary entries but its meaning was unclear in the calling code
without extra code comments.
Now use IOobjectOption::readOption instead, which allows further
options (ie, NO_READ) and is more transparent as to its purpose in
the code than a true/false bool flag was.
This is a minor breaking change (infrequent, advanced usage only)
- minor code cleanup in dictionary lookup methods
- with IOstreamOption there are no cases where we need to construct
top-level streams (eg, IFstream, OFstream) with additional information
about the internal IOstream 'version' (eg, version: 2.0).
Makes it more convenient to open files with a specified
format/compression combination - no clutter of specifying the
version
- avoids redundant dictionary searching
STYLE: remove dictionary lookupOrDefaultCompat wrapper
- deprecated and replaced by getOrDefaultCompat (2019-05).
The function is usually specific to internal keyword upgrading
(version compatibility) and unlikely to exist in any user code.
- read construct from dictionary.
Calling syntax similar to dimensionedType, dimensionedSet,...
Replaces the older getEntry(), getOptional() static methods
- support readIfPresent
- in expressions BCs in particular, there is various logic handling
for if value/refValue/refGradient etc are found or not.
Handle the lookups as findEntry and branch to use Field assign
or other handling, depending on its existence.
STYLE: use wordList instead of wordRes for copy/filter dictionary
- noexcept on some Time methods
ENH: pass through is_oriented() method for clearer coding
- use logical and/or/xor instead of bitwise versions (clearer intent)
Header information now includes, e.g.
f [Hz] vs P(f) [Pa]
Lower frequency: 2.500000e+01
Upper frequency: 5.000000e+03
Window model: Hanning
Window number: 2
Window samples: 512
Window overlap %: 5.000000e+01
dBRef : 2.000000e-05
Area average: false
Area sum : 6.475194e-04
Number of faces: 473
Note: output files now have .dat extension
- for example,
defaultFieldValues
(
areaScalarFieldValue h 0.00014
);
regions
(
clipPlaneToFace
{
point (0 0 0);
normal (1 0 0);
fieldValues
(
areaScalarFieldValue h 0.00015
);
}
);
ENH: additional clipPlaneTo{Cell,Face,Point} topo sets
- less cumbersome than defining a semi-infinite bounding box
- remedy by performing the attach() action sequentially (as per
stitchMesh changes). This ensures that the current point addressing
is always used and avoids references to the already-merged points
(which is what causes the failure).
ENH: improve handling of empty patch removal
- only remove empty *merged* patches, but leave any other empty
patches untouched since they may intentional placeholders for other
parts of a workflow.
- remove any empty point/face zones created for patch merging
- commonly used calculations
ENH: add faPatch::patchRawSlice method
- slices using the nEdges() instead of the virtual size(),
which provides similar functionality as finite-volume has with
its distinction between polyPatch vs fvPatch patchSlice
- use patchInternal for obtaining faPatch, fvPatch information
- similar to boundaryFieldRef(), primitiveFieldRef() for providing
write access. Complimentary naming to internalField(). Identical to
ref() but more explicitly named, and less likely to be confused with
a tmp::ref(), for example.
- prefer .primitiveFieldRef() over .ref().field()
- mark some access methods noexcept
- these were previously constructing from an fvPatch (for simpler
integration with regionFaModel) but this unnecessarily restricts
the finiteArea to a single volume patch.
- adjusted derived faOptions to support multiple patches
- list of faces() was using mesh-faces, not area-faces
ENH: provision for patch and faceSet selection in fa::faceSetOption
- adjust most of the faOptions to respect subset of faces
ENH: support Function1 for externalHeatFluxSource
BUG: incorrect handling of fixedPower (externalHeatFluxSource)
- used local areas instead of global total area
- old constructor interface allowed arbitrary strings to specify the
method enumeration. If actually used at runtime, they could/would
raise a FatalError (unknown enumeration).
Define a simpler default constructor instead.
- whichPolyPatches() = the polyPatches related to the areaMesh.
This helps when pre-calculating (and caching) any patch-specific
content.
- whichPatchFaces() = the poly-patch/patch-face for each of the faceLabels.
This allows more convenient lookups and, since the list is cached on
the area mesh, reduces the number of calls to whichPatch() etc.
- whichFace() = the area-face corresponding to the given mesh-face
ENH: more flexible/consistent volume->area mapper functions
- whichPatchFace() returns the (patchi, patchFacei) tuple,
whichPatch() simply wraps whichPatchFace()
- groupNames() : similar to zones
ENH: simplify calls to faPatch/fvPatch patchField, lookupPatchField
- make second (ununsed) template parameter optional.
Was previously needed for old compilers (2008 and earlier).
- simplifies construction/inheritance
ENH: add {fa,fv}PatchField::zeroGradientType() static
- can be used to avoid literal "zeroGradient" in places
STYLE: adjust naming of pointPatch runtime selection table
- simply use 'patch' as per fa/fv fields
STYLE: add zero-size guard to patch constraintType(const word&)
For example, instead of
if (dict.found("value"))
{
fvScalarField::operator=
(
Field<scalar>("value", dict, p.size())
);
}
can use more precise specifications, and also eliminate searching
the dictionary multiple times:
const auto* eptr = dict.findEntry("value", keyType::LITERAL);
//or: dict.findCompat("value", {{"oldName" ... }}, keyType::LITERAL);
if (eptr)
{
fvScalarField::assign(*eptr, p.size());
}
STYLE: combine declaration of FieldBase into Field.H
- include -no-libs option by default, similar to '-lib',
which makes it available to all solvers/utilities.
Add argList allowLibs() method to query it.
- relocate with/no functionObjects logic from Time to argList
itself as argList allowFunctionObjects()
- add libs/functionObjects override handling to decomposePar etc
ENH: report the stream relativeName for IOerrors (see c9333a5ac8)
- clearer coding intent. Mark operator() as 'deprecated'
- add bounds checking to get(label) and set(label) methods.
This gives failsafe behaviour for get() that is symmetric with
HashPtrTable, autoPtr etc and aligns the set(label) methods
for UPtrList, PtrList and PtrDynList.
- use top-level PtrList::clone() instead of cloning individual elements
ENH: support HashPtrTable set with refPtr/tmp (flexibility)
- define returnReduce *after* defining all specializations for reduce
so that the compiler does not take the generic templated reduce.
ENH: add UPstream::reduceAnd, UPstream::reduceOr
- direct wrapper of MPI_LAND, MPI_LOR intrinsics
ENH: provide special purpose returnReduce for logical operations
- returnReduceAnd(bool), returnReduceOr(bool) as a inline wrappers
for returnReduce with andOp<bool>(), orOp<bool>() operators,
respectively.
These forms are more succinct and force casting of the parameter
into a bool. Using MPI bool operations allows vendor/hardware MPI
optimisations.
* Test for existence on any rank:
1. if (returnReduceOr(list.size()) { ... }
1b. if (returnReduceOr(!list.empty()) { ... }
2. if (returnReduce(bool(list.size(), orOp<bool>())) { ... }
3. if (returnReduce(list.size(), sumOp<label>()) != 0) { ... }
3b. if (returnReduce(list.size(), sumOp<label>()) > 0) { ... }
* Test for non-existence on all ranks:
1. if (returnReduceAnd(list.empty()) { ... }
1b. if (!returnReduceOr(list.size()) { ... }
2. if (returnReduce(list.empty(), andOp<bool>())) { ... }
3. if (returnReduce(list.size(), sumOp<label>()) == 0) { ... }
Notes:
Form 1. succinct
Form 2. may require explicit bool() for correct dispatch
Form 3. more expensive sumOp<label> just for testing size!
There are also some places using maxOp<label> instead of sumOp<label>
- simplifies coding
* finishedRequest(), waitRequest(), waitRequests() with parRun guards
* nRequests() is noexcept
- more consistent use of UPstream::defaultCommsType in branching
- uses '-g -DFULLDEBUG' (like Debug), but with -O3 (like Opt).
This adds in debug symbols and FULLDEBUG code segments (good for
code development) but retains -O3 optimizations and code paths and
avoids the much slower -O0 associated with 'Debug'.
- add in central wmake/General/common/{c,c++}XXX tuning,
which helps reduce the number of nearly identical files
ENH: add support for wmake -debug-Og
- previously threw FatalError, which downgrades to a Warning only when
loading the functionObject. Now throw a FatalIOError so that missing
control files are treated as a critical error.
- this is especially evident in -reconstruct mode when
the fields have several processor boundaries.
Testing for an existing patch edge mapping must use the `test`
method (with range-checking) instead of the more common `set`
method since the source field will likely have many more boundaries
than physical edge mappings.
- rename effectivenessHeatExchangerSource -> heatExchangerSource
- introduce submodels:
- effectivenessTable (previous behaviour)
- referenceTemperature
- the referenceTemperature submodel uses a reference temperature
which is either a scalar or calculated from a 2D interpolation
table in order to calculate the heat exchange.
- the cpp command is used to process Make/{files,options}, but builtin
defines such as `linux` will cause problems (macro replacement) if
these is present in the Make/{files,options}.
Solve by undefining -Ulinux, -Uunix macros, which will leave directory
names such as "/usr/lib/x86_64-linux-gnu/..." intact.
Directories with _linux, __linux__ content (for example), could
still pose future issues.
- as an alternative output transform (supplementary to the regular
coordinate system specification - issue #2505) it is now possible to
specify the rotation centre directly.
Example:
formatOptions
{
vtk
{
scale 1000; // m -> mm
transform
{
origin (0 0 0);
rotationCentre (1 0 0);
rotation axisAngle;
axis (0 0 1);
angle -45;
}
}
}
This behaves like the transformPoints and surfaceTransformPoints
'-centre' option (formerly '-origin') in that it removes the
specified amount from the point locations, applies the rotation and
finally adds the specified amount back to the newly rotated point
locations.
The results of specifying a `rotationCentre` and a non-zero
coordinate system `origin` may not be intuitively evident.
- introduce a FOAM_LD_LIBRARY_PATH variable to shadow
DYLD_LIBRARY_PATH on MacOS.
The DYLD_LIBRARY_PATH and LD_LIBRARY_PATH cannot be modified via sub
shells etc when SIP is active. This helps circumvent these
restrictions, which is obviously a hack, but seems to be required.
COMP: disable -ftrapping-math in geompack for MacOS
- the output write scaling should be applied *after* undoing the
effects of the specified rotation centre. Fixes#2566
ENH: update option names for transformPoints and surfaceTransformPoints
- prefer '-auto-centre' and '-centre', but also accept the previous
options '-auto-origin' and '-origin' as aliases.
Changing to '-centre' avoids possible confusion with
coordinate system origin().
When a finite-area case could not find an entry for "lnGradSchemes"
in the "faSchemes" file, the "corrected" scheme has been picked up
by default. Therefore, any changes in "snGradSchemes" entry will not
be read by finite-area models.
- consistent with defining IO of int32_t/int64_t and with recent
changes to ensightFile. Using the primitives directly instead of
typedefs to them makes the code somewhat less opaque.
- parse out symbols and use abi::__cxa_demangle for more readable
names in safePrintStack.
- shorten prefixed /path/openfoam/platforms/lib/... to start
with "platforms/lib/..." to avoid unreadably long lines.
- improved file-scope localization of helper functions.
STYLE: use std::ios_base::basefield instead of dec|oct|hex for masking
- align timeVaryingMappedFixedValuePointPatchField keywords with
MappedFile
STYLE: minor cleanup of pointToPointPlanarInterpolation
BUG: incorrect keyword for timeVaryingMappedFixedValuePointPatchField
- lookup should be "fieldTable" (not "fieldTableName") for consistency
with the output and other BCs. (Bug introduced by a623ab42a3)
- some central (core) bits under fileFormats,
- general surface reading relocated from sampling to surfMesh since it
does not use any sampling-specific components and will permit
re-use in meshTools (for example)
- remove old mask, subDir methods from ensightFile which were
previously relocated to ensightCase
- improve handling of 'undef' values when generating and reading,
respect Ensight component ordering when reading.
STYLE: qualify format/version/compression with IOstreamOption not IOstream
STYLE: reduce number of lookups when scanning {fa,fv}Solution
STYLE: call IOobject::writeEndDivider as static
- Ensight places restrictions both on variable names and on file
names. When generating the variable to file name correspondence for
use in the Ensight case file, previously used the less stringent
variable name for both sides of the variable table.
This would lead to situations where the (valid) variable name
referred to the wrong file name. Now apply the file-name restriction
consistently when creating the variable table. This is especially
necessary since the stem of the filename additionally has
specific characters (eg, ":<>[]") that can be problematic for the
shell or file-system.
ENH: avoid repeated '_' in qualified ensight names.
- when replacing undesirable characters (eg, ":<>[]") with '_', avoid
duplicates.
Eg, "PaSR<psiReactionThermo>:Qdot" becomes
"PaSR_psiReactionThermo_Qdot" instead of
"PaSR_psiReactionThermo__Qdot"
ENH: additional ensightCase::padded static method
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.