- 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
For example,
T
{
solver PBiCGStab;
preconditioner DILU;
tolerance 1e-6;
norm none;
}
STYLE: define defaultMaxIter, defaultTolerance directly in lduMatrix
- in situations where the simulation diverges, the ensight writing can
be incomplete. If the case file is updated prior to writing geometry
or fields, the generated case may refer to incomplete entries (which
make loading problematic).
NOTE: if multiple fields are sampled and written, this change cannot
entirely prevent case files addressing corrupt fields. For example,
1a. write U field, update case file with new times/fields
1b. write p field, update case file with new times/fields
2a. write U field, update case file with new times
2b. write p field, but fails
Since 2a already updates the case file with a new time-step entry
(for the U field), the case glob patterns will automatically include
the not-yet-written 'p' field. If this write fails with an
incomplete/corrupt field, the case file will still be addressing it!
- barycentric coordinates in interpolation (instead of x/y/z)
- ease U (velocity) requirement.
Needn't be named in the sampled fields.
- default tracking direction is 'forward'
In movePoints had some duplicated code but did not update the
lower level (polyPatch) areas. This caused scaling to be applied
multiple times (so only 1.0 would not be affected)
- the file removal cleanup, which makes reasonable sense for
redistribute mode, always forced the removal of the reconstructed
lagrangian fields (since all of the non-master fields are empty by
definition)!
Detect reconstruct mode (by using constructSize from the map) to
circumvent this logic.
phaseSystemModels function objects are relocated within
functionObjects in order to enable broader usage.
ENH: multiphaseInterHtcModel: new heatTransferCoeff function object model
COMP: createExternalCoupledPatchGeometry: add new dependencies
COMP: alphaContactAngle: avoid duplicate entries between multiphaseEuler and reactingEuler
TUT: damBreak4Phase: rename alphaContactAngle as multiphaseEuler::alphaContactAngle
thermoTools is a relocation of various existing tools:
- src/TurbulenceModels/compressible/turbulentFluidThermoModels/derivedFvPatchFields/
- src/semiPermeableBaffle/derivedFvPatchFields/
- src/thermophysicalModels/thermophysicalPropertiesFvPatchFields/liquidProperties/
ENH: Allwmake: reordering various compilation steps
Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
This is on
- incompressible/pimpleFoam/laminar/mixerVesselAMI2D/mixerVesselAMI2D-topologyChange
- redistributePar -reconstruct
where the fvMesh::updateMesh does an early trigger of
mesh.phi() calculation
Specific to the VOF-to-lagrangian FO is to generate particles
which potentially do not relate to the mesh. So here they
are preserved instead of trying to locate them on the
reconstructed mesh. Note: this has the same effect
of actually copying the file...
speciesSorption is a zeroGradient BC which absorbs mass given by a first
order time derivative, absoprtion rate and an equilibrium value
calculated based on internal species values next to the wall.
patchCellsSource is a source fvOption which applies to the corresponding
species and apply the source calculated on the speciesSorption BC.
A new abstract virtual class was created to group BC's which
don't introduce a source to the matrix (i.e zeroGradient) but calculate
a mass sink/source which should be introduced into the matrix. This
is done through the fvOption patchCellsSource.
- this allows the "relocation" of sampled surfaces. For example,
to reposition into a different coordinate system for importing
into CAD.
- incorporate output scaling for all surface writer types.
This was previously done on an adhoc basis for different writers,
but with now included in the base-level so that all writers
can automatically use scale + transform.
Example:
formatOptions
{
vtk
{
scale 1000; // m -> mm
transform
{
origin (0.05 0 0);
rotation axisAngle;
axis (0 0 1);
angle -45;
}
}
}
in RASModelVariables were doing this by checking whether the
corresponding pointer was allocated. In some cases, however, even if the
field does not exist, the pointer is not null, leading to the wrong
output. Made the correspding functions virtual and overwritten their
return values in the derived classes. Kept the initial implementation in
base to facilitate the clone function.
in cases with more than one primal or adjoint solvers
TUT: removed all occurances of useSolverNameForFields
from the optimisation tutorials since it is now set
automatically.
in the sensitivity patches, symmetry::evaluate() needs access to the
internalField which does exist, leading to wrong memory access.
Fixed by specifying a calculated type fvPatchField for all patches when
creating a boundaryField<Type>
Using a symmetry(Plane) as a sensitivity patch is quite rare and
borderline wrong, but this provides a fix nonetheless.
The multiplier of grad(dxdb) is a volTensorField which, by itself, is
memory consuming. The function computing it though was sloppy in terms
of memory management, constituting the peak memory consumption during an
adjoint optimisation. Initial changes to remedy the problem include the
deallocation of some of the volTensorFields included in the computation
of grad(dxdb) once unneeded, the utilisation of volSymmTensorFields
instead of volTensorFields where possible and avoiding allocating some
unnecessary intermediate fields.
Actions to further reduce memory consumption:
- For historical reasons, the code computes/stores the transpose of
grad(dxdb), which is then transposed when used in the computation of
the FI or the ESI sensitivity derivatives. This redundant
transposition can be avoid, saving the allocation of an additional
volTensorField, but the changes need to permeate a number of places in
the code that contribute to grad(dxdb) (e.g. ATC, adjoint turbulence
models, adjoint MRF, etc).
- Allocation of unnecessary pointers in the objective class should be
avoided.
- ATCstandard, ATCUaGradU:
the ATC is now added as a dimensioned field and not as an fvMatrix
to UaEqn. This get rid of many unnecessary allocations.
- ATCstandard:
gradU is cached within the class to avoid its re-computation in
every adjoint iteration of the steady state solver.
- Inlined a number of functions within the primal and adjoint solvers.
This probably has a negligible effect since they likely were inlined
by the compiler either way.
- The momentum diffusivity at the boundary, used by the adjoint boundary
conditions, was computed for the entire field and, then, only the
boundary field of each adjoint boundary condition was used. If many
outlet boundaries exist, the entire nuEff field would be computed as
many times as the number of boundaries, leading to an unnecessary
computational overhead.
- Outlet boundary conditions (both pressure and velocity) use the local
patch gradient to compute their fluxes. This patch gradient requires
the computation of the adjacent cell gradient, which is done on the
fly, on a per patch basis. To compute this patch adjacent gradient
however, the field under the grad sign is interpolated on the entire
mesh. If many outlets exist, this leads to a huge computational
overhead. Solved by caching the interpolated field to the database and
re-using it, in a way similar to the caching of gradient fields (see
fvc::grad).
WIP: functions returning references to primal and adjoint boundary
fields within boundaryAdjointContributions seem to have a non-negligible
overhead for cases with many patches. No easy work-around here since
these are virtual and cannot be inlined.
WIP: introduced the code structure for caching the contributions to
the adjoint boundary conditions that depend only on the primal fields
and reusing. The process needs to be completed and evaluated, to make
sure that the extra code complexity is justified by gains in
performance.
is now appended by the name of the adjoint solver, if more than one
exist. This was necessary for an accurate continuation since, before
these changes, only the ma field of the last solver was written. As a
result, when restarting the first adjoint solver was reading the ma
field of the last one. No changes are needed in fvSolution and fvSchemes
w.r.t. the previous code version.
as a step towards machine-accuracy continuation of the optimisation
loop.
Additionally, control points are now written under the time/uniform
folder, to be in-line with rest of the code structure for continuation.
As a side-effect, the controlPointsDefinition in
constant/dynamicMeshDict does not need to be changed to 'fromFile'
anymore in order to perform the continuation. The 'fromFile' option is
still valid if the user wants to supply the control points manually but,
as with all other controlPointsDefinitions, it will be disregarded if the
proper file exists under the time/uniform/volumetricBSplines folder.
Before the commit, the sensitivity classes were receiving references of
the (incompressible) primal and adjoint variables. However, if
additional physics was added (energy equation, multiphase, etc), the
infrastructure wasn't convenient for accommodating (new terms in the FI
and E-SI formulations, new terms in the sensitivity map, etc).
Now, the sensitivity classes receive a reference to an
incompressibleAdjointSolver and receive the terms for the FI and
sensitivity maps through there. The latter is still WIP.
Modified adjointSimple to incorporate these changes as well.
Each solver now writes its sensitivity derivatives to its dictionary,
enabling also a binary format. If present, the sensitivities are then
re-read from the dictionary, avoiding thus possible loss of information
due to re-computation.
As a side-effect, sensitivities are computed after the completion of
each adjoint solver, instead of being computed after all adjoint solvers
have been completed.
for incompressible flows. The typical convention of appending the primal
field name with 'a' to form the adjoint field is followed for the
adjoint turbulent kinetic energy (i.e. 'ka') but since this would produce
an ugly variable name for the adjoint to omega (i.e. omegaa), the latter
is abbreviated to 'wa'.
The work is based on
\verbatim
Kavvadias, I., Papoutsis-Kiachagias, E.,
Dimitrakopoulos, G., & Giannakoglou, K. (2014).
The continuous adjoint approach to the k–$omega$ SST turbulence model with
applications in shape optimization
Engineering Optimization, 47(11), 1523-1542.
https://doi.org/10.1080/0305215X.2014.979816
\endverbatim
with changes in the discretisation of
a number of differential operators and the formulation of the adjoint to
the wall functions employed by the primal model.
Regarding the latter, the code assumes (and differentiates) the default
behaviour of nutkWallFunction (i.e. nutWallFunction::blendingType::STEPWISE)
and omegaWallFunction (i.e. omegaWallFunction::blendingType::BINOMIAL2).
Due to the availability of a number of terms required for the
formulation of the wall function for ka, the latter is implemented
within adjointkOmegaSST itself, with contributions from objective functions
implemented within kaqRWallFunction. Wall functions for wa are
implemented within waWallFunction.
The initial implementation of the above-mentioned reference was
performed by Dr. Ioannis Kavvadias
the Jacobian of an objective function, defined at the boundary, wrt nut
and gradU. Also modified the current objectives that include such
contributions
- update the area-centres processor/processor information as part of
faMesh::init() after all of the global data and geometry data is
setup.
- improve flattenEdgeField helper to properly handle empty patches.
This change removes the false fails when testing edge-centre
redistribution (FULLDEBUG mode).
TUT: add filmPanel (rivulet) tutorial
- include constant/faMesh cleanup (cleanFaMesh) as part of standard
cleanCase
- simplify cleanPolyMesh function to now just warn about old
constant/polyMesh/blockMeshDict but not try to remove anything
- cleanup cellDist.vtu (decomposePar -dry-run) as well
ENH: foamRunTutorials - fallback to Allrun-parallel, Allrun-serial
TUT: call m4 with file argument instead of redirected stdin
TUT: adjust suffixes on decomposeParDict variants
- enables runtime selection of operand coefficients by 'coefficients' entry
- removes binning - now handled using the new 'binField' FO
Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
The new 'binField' function object calculates binned data,
where specified patches are divided into segments according to
various input bin characteristics, so that spatially-localised
information can be output for each segment.
Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
- simpler to write for sampled cutting planes etc.
For example,
slice
{
type cuttingPlane;
point (0 0 0);
normal (0 0 1);
interpolate true;
}
instead of
slice
{
type cuttingPlane;
planeType pointAndNormal;
pointAndNormalDict
{
point (0 0 0);
normal (0 0 1);
}
interpolate true;
}
STYLE: add noexcept to some plane methods
- Previous state of the condition was largely inoperative
due to bugs and lack of functionalities
- New state of the condition is more versatile, elegant, robust and faster
ENH: turbulentDigitalFilter: add new scalar-based synthetic turbulence condition
- Realistic temperature and/or concentration fluctuations
can be generated based on given input statistics
- can specify rotations that are not "axes" in a compact form:
transform
{
origin (0 0 0);
rotation none;
}
transform
{
origin (0 0 0);
rotation axisAngle;
axis (0 0 1);
angle 45;
}
An expanded dictionary form also remains possible:
transform
{
origin (0 0 0);
rotation
{
type axisAngle;
axis (0 0 1);
angle 45;
}
}
STYLE: verbose deprecation for "coordinateRotation" keyword
- the "coordinateRotation" keyword was replaced by the "rotation"
keyword (OpenFOAM-v1812 and later) but was handled silently.
Now elevated to non-silent.
STYLE: alias lookups "axesRotation", "EulerRotation", "STARCDRotation"
- these warn and report the equivalent short form, which aids in
upgrading. Previously had silent lookups.
- append single character
- make append() methods void: methods are never chained anyhow
- refactor digest comparison (code reduction)
COMP: add overflow handling for OSHA1stream
- add overflow() method to the SHA1 streambuf. Previously could rely
on xsputn for adding to sha1 content, but streams now check pptr()
first to test for the buffering range and thus overflow() is needed.
- can be more intuitive to specify for some cases:
rotation
{
type euler;
order rollPitchYaw;
angles (0 20 45);
}
- refactor starcd rotation to reuse Euler ZXY ordering
(code reduction)
ENH: add -rotate-x, -rotate-y, -rotate-z for transformPoints etc
- easier to specify for simple rotations
- aligns calling signatures with wordList, for possible future
replacement
- drop construct from const char** (can use initializer_list instead)
ENH: replace hashedWordList with plain wordList in triSurfaceLoader
- additional hashing optimisation (and overhead) is not worth it for
the comparatively small lists of surfaces used.
- catch extra punctuation tokens in chemical equations
- catch unknown species
- simplify generation of reaction string (output)
ENH: allow access of solid concentrations from sub-classes (#2441)
- ensightWrite, vtkWrite, fv::cellSetOption
ENH: additional topoSet "ignore" action
- this no-op can be used to skip an action step, instead of removing
the entire entry
- this allows more flexibility when defining the location or intensity
of sources.
For example,
{
type scalarSemiImplicitSource;
volumeMode specific;
selectionMode all;
sources
{
tracer0
{
explicit
{
type exprField;
functions<scalar>
{
square
{
type square;
scale 0.0025;
level 0.0025;
frequency 10;
}
}
expression
#{
(hypot(pos().x() + 0.025, pos().y()) < 0.01)
? fn:square(time())
: 0
#};
}
}
}
}
ENH: SemiImplicitSource: handle "sources" with explicit/implicit entries
- essentially the same as injectionRateSuSp with Su/Sp,
but potentially clearer in purpose.
ENH: add Function1 good() method to define if function can be evaluated
- for example, provides a programmatic means of avoiding the 'none'
function
- avoid any operations for zero sources
- explicit sources are applied to the entire mesh can be added directly,
without an intermediate DimensionedField
- update some legacy faMatrix/fvMatrix methods that used Istream
instead of dictionary or dimensionSet for their parameters.
Simplify handling of tmps.
- align faMatrix methods with the updated their fvMatrix counterparts
(eg, DimensionedField instead of GeometricField for sources)
- similar to the geometric decomposition constraint,
allows a compositing selection of cells based on topoSet sources
which also include various searchableSurface mechanisms.
This makes for potentially easier placement of sources without
resorting to defining a cellSet.
ENH: support zone group selection for fv::cellSetOption and fa::faceSetOption
- select motion for the entire mesh, or restrict to a subset
of points based on a specified cellSet or cellZone(s).
Can now combine cellSet and cellZone specifications
(uses an 'or' combination).
- move consistent use of keyType and wordRe to allow regex selection,
possibly using zone groups
STYLE: remove duplicate code in solidBodyMotionSolver
- shorter lookup names for more consistency
ENH: accept point1/point2 as alternative to p1/p2 for sources
- better alignment with searchable specification
- refactor so that cylinderAnnulus sources derive directly from
cylinder sources (which handle an annulus as well).
Accept radius or outerRadius as synonyms.
STYLE: noexcept on topoBitSet access methods
DOC: update description for geometricConstraint
- in various situations with mesh regions it is also useful to
filter out or remove the defaultRegion name (ie, "region0").
Can now do that conveniently from the polyMesh itself or as a static
function. Simply use this
const word& regionDir = polyMesh::regionName(regionName);
OR mesh.regionName()
instead of
const word& regionDir =
(
regionName != polyMesh::defaultRegion
? regionName
: word::null
);
Additionally, since the string '/' join operator filters out empty
strings, the following will work correctly:
(polyMesh::regionName(regionName)/polyMesh::meshSubDir)
(mesh.regionName()/polyMesh::meshSubDir)
Reports cloud information for particles passing through a specified cell
zone.
Example usage:
cloudFunctions
{
particleZoneInfo1
{
type particleZoneInfo;
cellZone leftFluid;
// Optional entries
//writer vtk;
}
}
Results are written to file:
- \<case\>/postProcessing/lagrangian/\<cloudName\>/\<functionName\>/\<time\>
\# cellZone : leftFluid
\# time : 1.0000000000e+00
\#
\# origID origProc (x y z) time0 age d0 d mass0 mass
Where
- origID : particle ID
- origProc : processor ID
- (x y z) : Cartesian co-ordinates
- time0 : time particle enters the cellZone
- age : time spent in the cellZone
- d0 : diameter on entry to the cellZone
- d : current diameter
- mass0 : mass on entry to the cellZone
- mass : current mass
If the optional \c writer entry is supplied, cloud data is written in the
specified format.
During the run, output statistics are reported after the cloud solution,
e.g.:
particleZoneInfo:
Cell zone = leftFluid
Contributions = 257
Here, 'Contributions' refers to the number of incremental particle-move
contributions recorded during this time step. At write times, the output
is extended, e.g.:
particleZoneInfo:
Cell zone = leftFluid
Contributions = 822
Number of particles = 199
Written data to "postProcessing/lagrangian/reactingCloud1/
TUT: filter: add an example for the particleZoneInfo function object
- Previously, the multiFieldValue function object was limited to operate on
lists of fieldValue function objects.
- Any function objects that generate results can now be used, e.g.
pressureAverage
{
type multiFieldValue;
libs (fieldFunctionObjects);
operation average;
functions
{
inlet
{
type surfaceFieldValue;
operation areaAverage;
regionType patch;
name inlet;
fields (p);
writeFields no;
writeToFile no;
log no;
resultFields (areaAverage(inlet,p));
}
outlet
{
type surfaceFieldValue;
operation areaAverage;
regionType patch;
name outlet;
fields (p);
writeFields no;
writeToFile no;
log no;
}
average
{
type valueAverage;
functionObject testSample1;
fields (average(p));
writeToFile no;
log no;
}
}
}
TUT: cavity: add an example for the multiFieldValue function object
- now have both compactData(),compactLocalData(), compactRemoteData()
depending on where the compaction information is actually known.
The compactData() performs a consistent union of local and remote
values, which eliminates the danger of mapping to non-existent
locations but does require a double communication to setup.
Typically needed for point maps (for example).
The compactLocalData() and compactRemoteData() work on the
assumption that the source or target values are sufficent for
creating unique compact maps.
Can be used, for example, when compacting cell maps since there is
no possibility of a source cell being represented on different
target processors (ie, each cell is unique and only occurs once).
The existing compact() is equivalent to compactRemoteData()
and is now simply a redirect.
- use bitSet for defining compaction, but the existing compact()
continues to use a boolList (for code compatibility).
BUG: compaction in non-parallel mode didn't compact anything.
STYLE: compact ascii output for procAddressing
- simplify procAddressing read/write
- avoid accessing points in faMeshReconstructor.
Can rely on the patch meshPoints (labelList), which does not need
access to a pointField
- report number of points on decomposed mesh.
Can be useful additional information.
Additional statistics for finite area decomposition
- provide bundled reconstructAllFields for various reconstructors
- remove reconstructPar checks for very old face addressing
(from foam2.0 - ie, older than OpenFOAM itself)
- bundle all reading into fieldsDistributor tools,
where it can be reused by various utilities as required.
- combine decomposition fields as respective fieldsCache
which eliminates most of the clutter from decomposePar
and similfies reuse in the future.
STYLE: remove old wordHashSet selection (deprecated in 2018)
BUG: incorrect face flip handling for faMeshReconstructor
- a latent bug which is not yet triggered since the faMesh faces are
currently only definable on boundary faces (which never flip)
Geometry calculation scheme that performs geometry updates only in regions
where the mesh has changed, identified by comparing current and old points.
Example usage in fvSchemes:
geometry
{
type solidBody;
// Optional entries
// If set to false, update the entire mesh
partialUpdate yes;
// Cache the motion addressing (changed points, faces, cells etc)
cacheMotion yes;
}
The most frequent changes have been as follows.
from:
tmp<scalarField> tuTau(new scalarField(patch().size(), Zero));
scalarField& uTau = tuTau.ref();
to:
auto tuTau = tmp<scalarField>::New(patch().size(), Zero);
auto& uTau = tuTau.ref();
- Other changes involved the addition of - wherever approapriate -:
const
noexcept
auto
Previously, a nutWallFunctionFvPatchScalarField ref should be
created in epsilon, k, and omega wall functions to fetch various
common wall-function coefficients necessary to carry out and complete
local operations inside these wall functions.
However, this arrangement required the use of a nut wall function,
even when unnecessary, when any of non-nut wall functions are being used.
Therefore, some users had been redundantly restrained and
obstructed with rather obscure casting-error messages.
Also, the wall-function coefficients Cmu, kappa and E have been obtained
from the specified nutWallFunction in order to ensure that each patch
possesses the same set of values for these coefficients.
Although the motivation sounds reasonable, it has also been putting redundant
restraints on users and disregarding the specifics of each wall-function.
For example, the variation of epsilon in near-wall regions is usually very
steep and non-monotonic specific - an expert user may therefore want to use
an epsilon-specific coefficient, and this was not allowed by the previous
arrangement.
This commit introduces a new class (i.e. wallFunctionCoefficients) comprising
all common wall-function coefficients and yPlus calculations.
Previously, a number of wall functions were not not writing
their boundary-condition entries in the defacto order
(i.e. from type to value) while writing a field. For example:
<patchName>
{
lowReCorrection 1;
blending stepwise;
n 2;
type epsilonWallFunction; <!-- expected to be the first entry
value uniform 1; <!-- expected to be the last entry
}
Also, various wall functions have been writing out entries that
have not been being used by the wall function. For example:
<patchName>
{
type nutUSpaldingWallFunction;
...
blending stepwise; <!-- no blending treatment in nutUSpaldingWF
...
}
Additionally, various derived wall functions (e.g. atmOmegaWallFunction)
have been failing to write some of the inherited entries even though
these entries have been being used in carrying out wall-function calculations.
Taken these into consideration, wall functions have been reworked to obtain
reliable and consistent way of writing their traits while writing out a field.
- writeLocalEntries uses writeIfDifferent if constructed with getOrDefault.
ENH: simple faMeshSubset (zero-sized meshes only)
ENH: additional access methods for faMesh, primitive geometry mode
- wrapped walking of boundary edgeLabels as list of list
(similar to edgeFaces).
- primitive finiteArea geometry mode with reduced communication:
primarily interesting for decomposition/redistribution (#2436)
ENH: extra vtk debug outputs for checkFaMesh
- report per-processor sizes in the mesh summary
- similar functionality as newMesh etc.
Relocated to finiteVolume since there are no dynamicMesh dependencies.
- use simpler procAddressing (with updated mapDistributeBase).
separated from redistributePar
- returns UPtrList view (read-only or read/write) of the objects
- shorter names for IOobject checks: hasHeaderClass(), isHeaderClass()
- remove unused IOobject::isHeaderClassName(const word&) method.
The typed versions are preferable/recommended, but can still check
directly if needed:
(io.headerClassName() == "foo")
- additional distribute/reverseDistribute with specified commsType.
Improves flexibility.
- distribute with nullValue
- support move construct mapDistribute from mapDistributeBase
- refactor handling of schedules (as whichSchedule method) to
simplify code.
- renumberMap helper for working with compact sub maps
and renumberVisit for handling walk-ordered compaction.
COMP: make mapDistributeBase data private
- accessor methods are available - direct access is unnecessary
- mapDistribute : inherit mapDistributeBase constructors
STYLE: use List<labelPair>::null() for schedule placeholders
- clearer that they are doing nothing
- for int64 compilations this disambiguates between '0' as int32 (size)
or as bool 'false' for local processor validity
Eg,
IOList list(io, 0); <- With label-size 64: is this bool or label?
IOList list(io, Zero); <- Size = 0 (int32/int64), not a bool
- for indirect lists we use element-wise output streaming and read
back as a regular list. This approach cannot however work with
non-blocking mode - the receive buffers will simply not be filled
before attempting to read from them.
For contiguous data, the lowest overhead solution is to locally
flatten the indirect list and use the regular gather routines
for non-blocking mode. For non-contiguous data, can continue to
use the element-wise output, but cannot use non-blocking for it.
STYLE: use non-blocking consistently as default for globalIndex gather(s)
- most of the front-facing code was already using non-blocking,
but there were a few low-level routines defaulting to scheduled
(but never relied upon in the code).
- previously filtered on the existence of area fields, but with
faMesh::TryNew this is not required anymore.
STYLE: enable -verbose for various parallel utilities (consistency)
- introduced UList<bool>::operator()(label) as part of bf0b3d8872
but with gcc-4.8.5 this participates in operator resolution even
for non-bool lists!!
Partial revert until this predicate handling is really required.
- use DynamicList instead of List in the cache, which reduces the
number of allocations occuring each time.
- since the cached times are stored in sorted order, first check if the
new time is greater than the last list entry. Can then simply append
without performing a binary search and can obviously also skip any
subsequent sorting.
STYLE: add noexcept to Instant methods, declare in header (like Tuple2)
- as part of #2358 the writing was changed to be lazy.
Which means that files are only created before they are actually
written, which helps avoid flooding the filesystem if sample-only
is required and also handles case such as "rho.*" where the sampled
fields are not known from the objectRegistry at startup.
- now create any new files using the startTime value, which means they
are easier to find but still retains the lazy construct.
Don't expect any file collisions with this, but there could be some
corner cases where the user has edited to remove fields (during
runtime) and then re-edits to add them back in. In this case the
file pointers would be closed but reopened later and overwriting
the old probed values. This could be considered a feature or a bug.
BUG: bad indexing for streamlines (fixes#2454)
- a cut-and-paste error
- only wrap compiler calls (not things like flex/bison)
- avoid single quoted '&&' (causes syntax errors)
STYLE: report WM_COMPILE_CONTROL value in top-level Allwmake
- relocate templating to factory method 'New'.
Adds provisions for more general re-use.
- expose processor topology in globalMesh as topology()
- wrap proc->patch lookup as processorTopology::procPatchLookup method
(failsafe). May consider using Map<label> for its storage in the
future.
- Uses a refPtr to reference external content.
Useful (for example) when writing data without copying.
Reading into external locations is not implemented
(no current requirement for that).
* IOFieldRef -> IOField
* IOListRef -> IOList
* IOmapDistributePolyMeshRef -> IOmapDistributePolyMesh
Eg,
labelList addressing = ...;
io.rename("cellProcAddressing");
IOListRef<label>(io, addressing).write();
Or,
primitivePatch patch = ...;
IOFieldRef<vector>(io, patch.localPoints()).write();
- the values from non-overlapping blocks were simply ignored,
which meant that ('111111111111' & '111111') would not mask out
the unset values at all.
- similar oddities in other operations (|=, ^= etc)
where the original implementation tried hard to avoid touching the
sizing at all, but now better resolved as follows:
- '|=' : Set may grow to accommodate new 'on' bits.
- '^=' : Set may grow to accommodate new 'on' bits.
- '-=' : Never changes the original set size.
- '&=' : Never changes the original set size.
Non-overlapping elements are considered 'off'.
These definitions are consistent with HashSet behaviour
and also ensures that (a & b) == (b & a)
ENH: improve short-circuiting within bitSet ops
- in a few places can optimise by checking for none() instead of
empty() and avoid unnecessary block operations.
ENH: added bitSet::resize_last() method
- as the name says: resizes to the last bit set.
A friendlier way of writing `resize(find_last()+1)`
- uniq() : creates an IndirectList with duplicated entries
filtered out
- subset() : creates an IndirectList with positions that satisfy
a condition predicate.
- subset_if() : creates an IndirectList with values that satisfy a
given predicate.
An indirect subset will be cheaper than creating a subset copy
of the original data, and also allows modification.
STYLE: combine UIndirectList.H into UIndirectList.H (reduce file clutter)
- the sorted() method fills a UPtrList with sorted entries. In some
places this can provide a more convenient means of traversing a
HashTable in consistent order, without the extra step of creating
a sortedToc(). The sorted() method with a UPtrList will also have
a lower overhead than creating any sortedToc() or toc() since it is
list of pointers and not full copies of the keys.
Instead of this:
HashTable<someType> table = ...;
for (const word& key : table.sortedToc())
{
Info<< key << " => " << table[key] << nl;
}
can write this:
for (const auto& iter : table.sorted())
{
Info<< iter.key() << " => " << iter.val() << nl;
}
STYLE:
- declare hash entry key 'const' since it is immutable
- local writeHeaderEntry helper was not marked as file-scope static.
- use do/while to simplify handling of padding spaces
ENH: IOobject - copy construct, resetting name and local component
- when copying with a new local component, this is simpler than
constructing from all of the components, which was previously the
only possibility for setting a new local component.
- commonly used, only depends on routines defined in UList
(don't need the rest of ListOps for it).
ENH: implement boolList::operator() const
- allows use as a predicate functor, as per bitSet and labelHashSet
GIT: combine SubList, UList into List directory (intertwined concepts)
STYLE: default initialize DynamicList instead of with size 0
- specifies the number of consecutive cells to assign to the same
randomly chosen processor. Can be used to have a less extremely
random distribution for testing possible breaking points.
Eg,
method random;
coeffs
{
agglom 4;
}
- Add finiteArea cellID (actually face ids) / faceLabel and procID
for foamToVTK with -write-ids. Useful when this type of information
is needed.
- Arbitrary number of outlets can be connected to a single inlet
- Each inlet can be connected to different and arbitrary
combination of outlets
- Each outlet-inlet connection has:
- Optional filtration fraction as a Function1 type
- Optional offset as a Function1 type (i.e. adding/substracting a substance)
- Optional time delay (from outlet to inlet) as a Function1 type
- Each inlet has an optional base inlet-field as a PatchFunction1 type
The blendingFactor function object overwrites the DEShybrid:Factor
field internally when blendedSchemeBase debug flag is active.
However, users are allowed to write out the original DEShybrid:Factor
field by executing the writeObjects function object before
any blendingFactor function object execution.
- direct construct and reset method for creating a zero-sized (dummy)
subMesh. Has no exposed faces and no parallel synchronization
required.
- core mapping (interpolate) functionality with direct handling
of subsetting in fvMeshSubset (src/finiteVolume).
Does not use dynamicMesh topology changes
- two-step subsetting as fvMeshSubsetter (src/dynamicMesh).
Does use dynamicMesh topology changes.
This is apparently only needed by the subsetMesh application itself.
DEFEATURE: remove deprecated setLargeCellSubset() method
- was deprecated JUL-2018, now removed (see issue #951)
- allows restricted evaluation to specific coupled patch types.
Code relocated/refactored from redistributePar.
STYLE: ensure use of waitRequests() also corresponds to nonBlocking
ENH: additional copy/move construct GeometricField from DimensionedField
STYLE: processorPointPatch owner()/neighbour() as per processorPolyPatch
STYLE: orientedType with bool cast operator and noexcept
- move construct from components. Construct with optional IO control
- separate init() method (as per polyMesh) to delay evaluation of
globalData and base geometry.
- faMesh removeFiles method
ENH: faBoundaryMeshEntries for reading faBoundary files without a mesh
ENH: adjust debug output for {fa,fae,fv,fvs}patchField::New
- add alternative constraint type selection for faePatchField.
- unify handling of "patchType" reading.
Make less noisy when reporting dictionary defaults.
- allows reuse by finiteArea, for example.
- simplify edge looping with face thisLabel/nextLabel method
ENH: additional storage checks for mesh weights (faMesh + fvMesh)
- allow finite-area field decomposition without edge weights.
STYLE: use tmp New in various places. Simpler updateGeom check
STYLE: remove spurious (no-op) processor boundary evaluations
- boundary fields for faceAreaCentres and edgeCentres had no-op
initEvaluate/evaluate pair on processor boundaries.
Now consistent with each other and with how finiteVolume is defined.
STYLE: add comments about which private methods trigger communication
- reduce the amount of communication when checking zones and patches
by performing the synchonization check on the gathered strings
(master only) and reduce or broadcast the result.
STYLE: simplify coupled() checks depending only on parRun
* lessEqOp -> lessEqualOp
* greaterEqOp -> greaterEqualOp
to avoid ambiguitity with other forms such as 'plusEqOp' where the
'Eq' implies an assigment. The name change also aligns better with
C++ <functional> names such as std::less_equal, std::greater_equal
ENH: simple labelRange predicates gt0/ge0/lt0/le0
- mirrors scalarRange tests.
Lower overhead than using labelMinMax::ge(0) etc since it does not
create an intermediate (is stateless) and can be used as a constexpr
- was in fvMotionSolver, but only requires PatchFunction1 capabilities
(from within meshTools).
GIT: relocate IOmapDistributePolyMesh (from dynamicMesh to OpenFOAM)
- adds handling of negative start times for masterUncollatedFileOperation
as well (#1112).
- handle failures *after* restoring non-parRun mode.
This ensures exit(FatalError) will exit MPI properly as well.
STYLE: replace "polyMesh" with polyMesh::meshSubDir
STYLE: adjust IOobject read/write enumerated values
- provision for possible bitwise handling
- additional Pstream::broadcasts() method to serialize/deserialize
multiple items.
- revoke the broadcast specialisations for std::string and List(s) and
use a generic broadcasting template. In most cases, the previous
specialisations would have required two broadcasts:
(1) for the size
(2) for the contiguous content.
Now favour reduced communication over potential local (intermediate)
storage that would have only benefited a few select cases.
ENH: refine PstreamBuffers access methods
- replace 'bool hasRecvData(label)' with 'label recvDataCount(label)'
to recover the number of unconsumed receive bytes from specified
processor. Can use 'labelList recvDataCounts()' to recover the
number of unconsumed receive bytes from all processor.
- additional peekRecvData() method (for transcribing contiguous data)
ENH: globalIndex whichProcID - check for isLocal first
- reasonable to assume that local items are searched for more
frequently, so do preliminary check for isLocal before performing
a more costly binary search of globalIndex offsets
ENH: masterUncollatedFileOperation - bundled scatter of status
Eg,
export WM_COMPILER=Clang130
export WM_COMPILE_CONTROL="version=13.0 +lld"
- also support the mold linker (+mold) for clang
STYLE: report as 'link' stage instead of 'ld' in short messages
- use vector::removeCollinear a few places
COMP: incorrect initialization order in edgeFaceCirculator
COMP: Silence boost bind deprecation warnings (before CGAL-5.2.1)
- for most field types this is a no-op, but for a field of floatVector
or doubleVector (eg, vector and solveVector) it will normalise each
element with divide-by-zero protection.
More reliable and efficient than dividing a field by the mag of itself
(even with VSMALL protection).
Applied to FieldField and GeometricField as well.
Eg,
fld.normalise();
vs.
fld /= mag(fld) + VSMALL;
ENH: support optional tolerance for vector::normalise
- for cases where tolerances larger than ROOTVSMALL are preferable.
Not currently available for the field method (a templating question).
ENH: vector::removeCollinear method
- when working with geometries it is frequently necessary to have a
normal vector without any collinear components. The removeCollinear
method provides for clearer, compacter code.
Eg,
vector edgeNorm = ...;
const vector edgeDirn = e.unitVec(points());
edgeNorm.removeCollinear(edgeDirn);
edgeNorm.normalise();
vs.
vector edgeNorm = ...;
const vector edgeDirn = e.unitVec(points());
edgeNorm -= edgeDirn*(edgeDirn & edgeNorm);
edgeNorm /= mag(edgeNorm);
- for obtaining set entries from a boolList
- BitOps::select to mirror bitSet constructor but returning a boolList
- BitOps::set/unset for boolList
ENH: construct bitSet from a labelRange
- useful, for example, when marking up patch slices
ENH: ListOps methods
- ListOps::count_if to mirror std::count_if but with list indexing.
- ListOps::find_if to mirror std::find_if but with list indexing.
ENH: UPtrList::test() method.
- includes bounds checks, which means it can be used in more places
(eg, even if the storage is empty).
Previous commit solved: "mixture rho to volume-based in rhoThermo."
This proved to work correctly for rho=constant EoS but not for
idealGas. Fixes#2304. The previous gitlab issue was #1812.
- `functions<scalar>` and `functions<vector>` were erroneously
documented in header as `lookup<scalar>` etc.
INT: handle fluent square brackets (fixes#2429)
- patch applied from openfoam.org
- support direct processing of CompactListList instead of requiring
a conversion to labelListList for bandCompression and renumbering
methods.
- manage FIFO with CircularBuffer instead of SLList (avoids
allocations in inner loops). Invert logic to use a bitSet of
unvisited cells, which improves looping as the matrix becomes more
sparse.
- fix missed weighting in bandCompression (same as #1376).
In polyTopoChange, handle removed cells immediately to simplify
the logic and align more closely with bandCompression.
STYLE: enclose bandCompression within meshTools namespace
ENH: PrimitivePatch pointFaces with DynamicList instead of SLList
- MPI_Gatherv requires contiguous data, but a byte-wise transfer can
quickly exceed the 'int' limits used for MPI sizes/offsets. Thus
gather label/scalar components when possible to increase the
effective size limit.
For non-contiguous types (or large contiguous data) now also
reverts to manual handling
ENH: handle contiguous data in GAMGAgglomeration gather values
- delegate to globalIndex::gatherValues static method (new)
- bundles frequently used 'gather/scatter' patterns more consistently.
- combineAllGather -> combineGather + broadcast
- listCombineAllGather -> listCombineGather + broadcast
- mapCombineAllGather -> mapCombineGather + broadcast
- allGatherList -> gatherList + scatterList
- reduce -> gather + broadcast (ie, allreduce)
- The allGatherList currently wraps gatherList/scatterList, but may be
replaced with a different algorithm in the future.
STYLE: PstreamCombineReduceOps.H is mostly unneeded now
STYLE: LduInterfaceFieldPtrsList as alias instead of a class
STYLE: define patch lists typedefs when defining the base patch
- eg, polyPatchList typedef within polyPatch.H
INT: relocate GeometricField::Boundary -> GeometricBoundaryField
- was internal to GeometricField but moving it outside simplifies
forward declarations etc. Code adapted from openfoam.org
Two problems:
- flipping inside snappyHexMesh is not done in a parallel
consistent way. So e.g. the octree-cached inside/outside information
has already been calculated. For now flipping of
distributedTriSurfaceMesh is disabled.
- octree-cached inside/outside information was using already
cached information and would only work for outwards pointing
volumes
- percent of cells is taken relative to selection size.
- percent of faces is taken relative to the number of boundary faces
that do not fix velocity themselves.
ENH: avoid correctBoundaryConditions() if values were not limited
- when writing surface formats (eg, vtk, ensight etc) the sampled
surfaces merge the faces/points originating from different
processors into a single surface (ie, patch gatherAndMerge).
Previous versions of mergePoints simply merged all points possible,
which proves to be rather slow for larger meshes. This has now been
modified to only consider boundary points, which reduces the number
of points to consider. As part of this change, the reference point
is now always equivalent to the min of the bounding box, which
reduces the number of search loops. The merged points retain their
original order.
- inplaceMergePoints version to simplify use and improve code
robustness and efficiency.
ENH: make PrimitivePatch::boundaryPoints() less costly
- if edge addressing does not already exist, it will now simply walk
the local face edges directly to define the boundary points.
This avoids a rather large overhead of the full faceFaces,
edgeFaces, faceEdges addressing.
This operation is now more important since it is used in the revised
patch gatherAndMerge.
ENH: topological merge for mesh-based surfaces in surfaceFieldValue
- lower memory overhead, simpler code and eliminates need for
ListListOps::combineOffset()
- optional handling of local faces/points for re-using in different
contexts
STYLE: labelUList instead of labelList for globalMesh mergePoints
STYLE: adjust verbose information from mergePoints
- also report the current new-point location
- also disables PointData if manifold cells are detected.
This is a partial workaround for volPointInterpolation problems
with handling manifold cells.
- additional verbosity option for conversions
- ignore old `-finite-area` option and always convert available
finiteArea mesh/fields unless `-no-finite-area` is specified (#2374)
ENH: simplify point offset handling for ensight output
- extend writing to include compact face/cell lists
- a try/catch approach is not really robust enough (or even possible)
since read failures likely do not occur on all ranks simultaneously.
This leads to situations where the master has thrown an exception
(and thus exiting the current routine) while other ranks are still
waiting to receive data and the program blocks completely.
Since this primarily affects data conversion routines such as
foamToEnsight etc, treat similarly to lagrangian: check for the
existence of essential files before proceeding or not. This is
wrapped into a TryNew factory method:
autoPtr<faMesh> faMeshPtr(faMesh::TryNew(mesh));
if (faMeshPtr) ...
- gather/scatter types of operations can avoid AllToAll communication
and use simple MPI gather (or scatter) to establish the receive sizes.
New methods: finishedGathers() / finishedScatters()
BUG: masterUncollatedFileOperation checking of file-size
- used Foam:fileSize check to decide on scheduled/nonBlocking but this
was being done on all ranks and subsequently broadcast.
Now avoid unnecessary filesystem access on non-master ranks.
- both schemes and solutions data are treated as MUST_READ_IF_MODIFIED
even if the requested readOption is nominally MUST_READ or
READ_IF_PRESENT, but now delay this change.
- do not need contruct or move assign from SortableList.
Rarely (never) used and can simply treat like a normal list
by applying shrink beforehand.
- make append() methods return void instead of returning self, which
makes it easier to derive from. Having them return self was a bit of
an original design mistake.
Chaining appends do not actually occur anywhere. Even if they were
to be used, would not want to rely on them (fear of slicing on any
derived classes).
BUG: IndirectList iterator comparison loses constness
- eliminate redundant size_ accounting
- drop extra 'Container' template parameter and replace functionality
with more flexible pack/unpack methods.
There is also a pack() method that handles indirect lists of lists
that can be used, for example, to pack a patch slice of faces.
Drop the 'operator()' method in favour of unpack to expose and properly
document the conversion. Should revisit the corresponding code in
some places for optimization potential.
- align some method names with globalIndex:
totalSize(), maxSize() etc
- less communication than gatherList/scatterList
ENH: refine send granularity in Pstream::exchange
STYLE: ensure PstreamBuffers and defaultCommsType agree
- simpler loops for lduSchedule
- can restrict calculation of D32 and other spray properties to a
subset of parcels. Uses a predicate selection mechanism similar to
vtkCloud etc.
ENH: code cleanup in scalar predicates
- pass by value not reference in predicates
- additional assign() method to refactor common code
- with the special setFormat "probes", all of the sampled sets are
treated more similarly to probes, with an ensemble output to raw
probed format.
This is of course less useful when the number of sampled points
becomes very large.
- can now specify sampled sets as dictionary entries instead of a list
entry.
can now use: sets { ... }
instead of: sets ( ... );
This is similar to sampled surfaces and makes it easier to
manage with dictionary manipulation tools.
TUT: update to use writeTime instead of outputTime
- in v2112 the functionObject results were only delivering values from
the last set listed (ie, overwritten).
Now that the values are properly scoped by the name of the set itself
Eg, `average(lines,p)` for the average for 'lines' set, existing
workflows will break.
It thus makes reasonble sense to also handle results without a
qualifier as ensemble values.
average(p) // Ensemble average of all listed sets
- the very old 'writer' class was fully stateless and always templated
on an particular output type.
This is now replaced with a 'coordSetWriter' with similar concepts
as previously introduced for surface writers (#1206).
- writers change from being a generic state-less set of routines to
more properly conforming to the normal notion of a writer.
- Parallel data is done *outside* of the writers, since they are used
in a wide variety of contexts and the caller is currently still in
a better position for deciding how to combine parallel data.
ENH: update sampleSets to sample on per-field basis (#2347)
- sample/write a field in a single step.
- support for 'sampleOnExecute' to obtain values at execution
intervals without writing.
- support 'sets' input as a dictionary entry (as well as a list),
which is similar to the changes for sampled-surface and permits use
of changeDictionary to modify content.
- globalIndex for gather to reduce parallel communication, less code
- qualify the sampleSet results (properties) with the name of the set.
The sample results were previously without a qualifier, which meant
that only the last property value was actually saved (previous ones
overwritten).
For example,
```
sample1
{
scalar
{
average(line,T) 349.96521;
min(line,T) 349.9544281;
max(line,T) 350;
average(cells,T) 349.9854619;
min(cells,T) 349.6589286;
max(cells,T) 350.4967271;
average(line,epsilon) 0.04947733869;
min(line,epsilon) 0.04449639927;
max(line,epsilon) 0.06452856475;
}
label
{
size(line,T) 79;
size(cells,T) 1720;
size(line,epsilon) 79;
}
}
```
ENH: update particleTracks application
- use globalIndex to manage original parcel addressing and
for gathering. Simplify code by introducing a helper class,
storing intermediate fields in hash tables instead of
separate lists.
ADDITIONAL NOTES:
- the regionSizeDistribution largely retains separate writers since
the utility of placing sum/dev/count for all fields into a single file
is questionable.
- the streamline writing remains a "soft" upgrade, which means that
scalar and vector fields are still collected a priori and not
on-the-fly. This is due to how the streamline infrastructure is
currently handled (should be upgraded in the future).
Automatic hole closure:
- introduces 'holeToFace' topoSet source
- used when detecting a 'leak-path'
- creates additional baffles to close the leak
Multi-stage layer addition:
- Can add layers in multiple passes
See issues: #2403, #2404
- for metis-like graphs there is no guarantee that a zero-sized graph
has an offsets list with size 1 or size 0, so always use
numCells = max(0, xadj.size()-1)
this was already done in most places, but missed in the
decomposeGeneral method
STYLE: use sumOp<label>() instead of plusOp<label>()
- the internal data are contiguous so can broadcast size and internals
directly without an intermediate stream.
ENH: split out broadcast time for profilingPstream information
STYLE: minor Pstream cleanup
- UPstream::commsType_ from protected to private, since it already has
inlined noexcept getters/setters that should be used.
- don't pass unused/unneed tag into low-level MPI reduction templates.
Document where tags are not needed
- had Pstream::broadcast instead of UPstream::broadcast in internals
- used Pstream::maxCommsSize (bytes) for the lower limit when sending.
This would have send more data on each iteration than expected based
on maxCommsSize and finish with a number of useless iterations.
Was generally not a serious bug since maxCommsSize (if used) was
likely still far away from the MPI limits and exchange() is primarily
harnessed by PstreamBuffers, which is sending character data
(ie, number of elements and number of bytes is identical).
- For v2112 and earlier: pre-assembled lists of particles
to be transferred and target patch on a per processor basis.
Apart from memory overhead of assembling the lists this adds
allocations/de-allocation when building linked-lists.
- Now stream particle transfer tuples directly into PstreamBuffers.
Use a local cache of UOPstream wrappers for the formatters
(since there are potentially many particles being shifted about).
On the receiving size, read out tuple-wise.
- Communication on transfers now restricted to the immediate
neighbours instead of using an all-to-all to exchange sizes.
Applied to Cloud::move and RecycleInteraction
- now largely encapsulated using PstreamBuffers methods,
which makes it simpler to centralize and maintain
- avoid building intermediate structures when sending data,
remove unused methods/data
TUT: parallel version of depthCharge2D
STYLE: minor update in ProcessorTopology
- PstreamBuffers nProcs() and allProcs() methods to recover the rank
information consistent with the communicator used for construction
- allowClearRecv() methods for more control over buffer reuse
For example,
pBufs.allowClearRecv(false);
forAll(particles, particlei)
{
pBufs.clear();
fill...
read via IPstream(..., pBufs);
}
This preserves the receive buffers memory allocation between calls.
- finishedNeighbourSends() method as compact wrapper for
finishedSends() when send/recv ranks are identically
(eg, neighbours)
- hasSendData()/hasRecvData() methods for PstreamBuffers.
Can be useful for some situations to skip reading entirely.
For example,
pBufs.finishedNeighbourSends(neighProcs);
if (!returnReduce(pBufs.hasRecvData(), orOp<bool>()))
{
// Nothing to do
continue;
}
...
On an individual basis:
for (const int proci : pBufs.allProcs())
{
if (pBufs.hasRecvData(proci))
{
...
}
}
Also conceivable to do the following instead (nonBlocking only):
if (!returnReduce(pBufs.hasSendData(), orOp<bool>()))
{
// Nothing to do
pBufs.clear();
continue;
}
pBufs.finishedNeighbourSends(neighProcs);
...
- a somewhat specialized use case, but can be useful when there are
many ranks with sparse communication but for which the access
pattern is established during inner loops.
PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
pBufs.allowClearRecv(false);
PtrList<OPstream> output(Pstream::nProcs());
while (condition)
{
// Rewind existing streams
forAll(output, proci)
{
auto* osptr = output.get(proci);
if (osptr)
{
(*osptr).rewind();
}
}
for (Particle& p : myCloud)
{
label toProci = ...;
// Get or create output stream
auto* osptr = output.get(toProci);
if (!osptr)
{
osptr = new OPstream(toProci, pBufs);
output.set(toProci, osptr);
}
// Append more data...
(*osptr) << p;
}
pBufs.finishedSends();
... reads
}
- split off a Pstream::genericBroadcast() which uses UOPBstream during
serialization and UOPBstream during de-serialization.
This function will not normally be used directly by callers, but
provides a base layer for higher-level broadcast calls.
- low-level UPstream broadcast of string content.
Since std::string has length and contiguous content, it is possible
to handle directly by the following:
1. broadcast size
2. resize
3. broadcast content when size != 0
Although this is a similar amount of communication as the generic
streaming version (min 1, max 2 broadcasts) it is more efficient
by avoiding serialization/de-serialization overhead.
- handle broadcast of List content distinctly.
Allows an optimized path for contiguous data, similar to how
std::string is handled (broadcast size, resize container, broadcast
content when size != 0), but can revert to genericBroadcast (streamed)
for non-contiguous data.
- make various scatter variants simple aliases for broadcast, since
that is what they are doing behind the scenes anyhow:
* scatter()
* combineScatter()
* listCombineScatter()
* mapCombineScatter()
Except scatterList() which remains somewhat different.
Beyond the additional (size == nProcs) check, the only difference to
using broadcast(List<T>&) or a regular scatter(List<T>&) is that
processor-local data is skipped. So leave this variant as-is.
STYLE: rename/prefix implementation code with 'Pstream'
- better association with its purpose and provides a unique name
- reduces later surprises and simplifies effort for the caller
- more flexible globalIndex scatter with auto-sized return field.
- Avoid communication for scattering into zero-sized fields.
- the data front for isoAdvection can be particularly sparse and at
higher processor counts there is an advantage to avoiding all-to-all
communication for the PstreamBuffers exchange
Based on code changes from T.Aoyagi(RIST), A.Azami(RIST)
- use MPI_Bcast intrinsic instead of manual tree to reduce the overall
number of messages.
Old behaviour can be re-enabled with
`#define Foam_Pstream_scatter_nobroadcast`
- The idea of broadcast streams is to replace multiple master to
subProcs communications with a single MPI_Bcast.
if (Pstream::master())
{
OPBstream toAll(Pstream::masterNo());
toAll << data;
}
else
{
IPBstream fromMaster(Pstream::masterNo());
fromMaster >> data;
}
// vs.
if (Pstream::master())
{
for (const int proci : Pstream::subProcs())
{
OPstream os(Pstream::commsTypes::scheduled, proci);
os << data;
}
}
else
{
IPstream is(Pstream::commsTypes::scheduled, Pstream::masterNo());
is >> data;
}
Can simply use UPstream::broadcast() directly for contiguous data
with known lengths.
Based on ideas from T.Aoyagi(RIST), A.Azami(RIST)
- native MPI min/max/sum reductions for float/double
irrespective of WM_PRECISION_OPTION
- native MPI min/max/sum reductions for (u)int32_t/(u)int64_t types,
irrespective of WM_LABEL_SIZE
- replace rarely used vector2D sum reduction with FixedList as a
indicator of its intent and also generalizes to different lengths.
OLD:
vector2D values; values.x() = ...; values.y() = ...;
reduce(values, sumOp<vector2D>());
NEW:
FixedList<scalar,2> values; values[0] = ...; values[1] = ...;
reduce(values, sumOp<scalar>());
- allow returnReduce() to use native reductions. Previous code (with
linear/tree selector) would have bypassed them inadvertently.
ENH: added support for MPI broadcast (for a memory span)
ENH: select communication schedule as a static method
- UPstream::whichCommunication(comm) to select linear/tree
communication instead of ternary or
if (Pstream::nProcs() < Pstream::nProcsSimpleSum) ...
STYLE: align nProcsSimpleSum static value with etc/controlDict override
- refactor as an MPI-independent base class.
Add bufferIPC{send,recv} private methods for construct/destruct.
Eliminates code duplication from two constructor forms and reduces
additional constructor definitions in dummy library.
- add PstreamBuffers access methods, refactor common finish sends
code, tweak member packing
ENH: resize_nocopy for processorLduInterface buffers
- content is immediately overwritten
STYLE: cull unneeded includes in processorFa*
- handled by processorLduInterface
- this can be used to apply a uniform field level to remove from
a sampled field. For example,
fieldLevel
{
"p.*" 1e5; // Absolute -> gauge [Pa]
T 273.15; // [K] -> [C]
U #eval{ 10/sqrt(3) }; // Uniform mag(U)=10
}
After the fieldLevel has been removed, any fieldScale is applied.
For example
fieldScale
{
"p.*" 0.01; // [Pa] -> [mbar]
}
The fieldLevel for vector and tensor fields may still need some
further refinement.
The runTimeControl function object can activate further function objects using
triggers. Previously the trigger index could only advance; this change set
allows users to set smaller values to enable function object recycling, e.g.
Repeat for N cycles:
1. average the pressure at a point in space
2. when the average stabilises, run for a further 100 iterations
3. set a new patch inlet velocity
- back to (1)
- Removes old default behaviour that only permitted an increase in the
trigger level. This type of 'ratcheting' mechanism (if required) is
now the responsibility of the derived function object.
- notably affects writing continuous data in binary. If generating a
compound token (eg, List<label>), need to add in the size prefix
otherwise it cannot actually be parsed properly as a List.
BUG: bad fallthrough for compound reading (FixedList)
- the branch was likely never reached, but would have attempted to
read twice due to a bad fall-through condition.
GIT: relocate globalIndex (is independent of mesh)
STYLE: include label/scalar Fwd in contiguous.H
STYLE: unneed commSchedule include in GeometricField
- as a side-effect of changes to probes, the file pointers are not
automatically creating when reading the dictionary but delayed
until prepare(WRITE_ACTION) is called.
This nuance was missed in thermoCoupleProbes.
- added in special handling for monitoring controlDict.
Since controlDict is an unwatchedIOdictionary (not IOdictionary) and
not registered either, the usual objectRegistry caching is not
available. Instead, access directly from Time.
Left the balance of the file handling largely intact (for handling
unregistered dictionaries) but could potentially revisit in the
future and attempt master-only file access if required. However,
most other IOdictionary types will be registered, otherwise the
READ_IF_MODIFIED mechanism would not really work properly.
- when used for example with wallShearStress, the stress field is
initially created as incompressible but later updated with the
correct compressible/incompressible dimensions.
If this field is sampled as a surface and stored on the registry
the dimensions should be reset() and not '=' assigned, since that
causes a dimension check which will obviously fail.
- add writer support for VERTICES
- updated use of globalIndex
ENH: add base vtk writer for points/verts/lines
STYLE: noexcept, explicit constructors etc
- when used with *any* alphaField and normalised (the usual case)
would largely give a 0-1 corresponding to the min/max of the first
component, but could also yield negative values.
- if the alpha field corresponds identically to colour field, it is
readily possible to combine as into RGBA sequences. However, if the
fields are different it potentially means referencing an opacity
field that has not yet been sampled. This impedes using the format
for a streaming sampler without additional overhead and/or rewriting
the alpha channel later.
- scene
- write with fileName, additional getMesh accessor
- addColourToMesh accepts an alpha field size 1 as a constant
alpha value
- sceneWriter wrapper
ENH: improve gltf handling of colour and alpha specification
- accept plain input directly.
Eg,
colour (1 0 1);
vs
colour uniform;
colourValue (1 0 1);
- use field magnitude for colouring of non-scalar fields.
Eg, having three different colour maps for a vector field simply
does not help much with visualisation.
- meshTools is the first layer in which coordSet is actually needed
STYLE: rename writer implementations in advance of upcoming changes (#2347)
- simplifies tracing of code changes (git blame)
- supports sampling/probing of values to obtain min/max/average/size
at execution intervals without writing any output or generating
output directories.
- 'verbose' option for additional output
- min, max, average and sample size results now stored in
functionObjectProperties similar to sampledSets, e.g. for field p
- min(p)
- max(p)
- average(p)
- size(p)
ENH: provide fieldTypes::surface names (as per fieldTypes::volume)
ENH: reduce number of files for surface fields
- combine face and point field declarations/definitions,
simplify typeName definitions
- used low-level MPI gather, but the wrapping routine contains an
additional safety check for is_contiguous which is not defined for
various std::pair<..> combination.
So std::pair<label,vector> (which is actually contiguous, but not
declared as is_contiguous) would falsely trip the check.
Avoid by simply gathering unbundled values instead.
- do not need STRINGIFY macros in ragel code
- remove wordPairHashTable.H and use equivalent wordPairHashes.H instead
STYLE: replace addDictOption with explicit option
- the usage text is otherwise misleading
GIT: combine Pair/Tuple2 directories
- unused in regular OpenFOAM code
- POSIX version uses deprecated gethostbyname()
- Windows version never worked
COMP: localize, noexcept on internal OSspecific methods
STYLE: support fileName::Type SYMLINK and LINK as synonyms
The logic was not maintaining consistent sets of constraints
on different processors. A single processor with a full
match (very easy with 0 local faces) would invalidate
adding the constraint.
- for contiguous data, added mpiGatherOp() to complement the
gatherOp() static method
- the gather ops (static methods) populate the globalIndex on the
master only (not needed on other procs) for reduced communication
- rename inplace gather methods to include 'inplace' in their name.
Regular gather methods return the gathered data directly, which
allows the following:
const scalarField mergedWeights(globalFaces().gather(wghtSum));
vs.
scalarField mergedWeights;
globalFaces().gather(wghtSum, mergedWeights());
or even:
scalarField mergedWeights;
List<scalarField> allWeights(Pstream::nProcs());
allWeights[Pstream::myProcNo()] = wghtSum;
Pstream::gatherList(allWeights);
if (Pstream::master())
{
mergedWeights =
ListListOps::combine<scalarField>
(
allWeights, accessOp<scalarField>()
);
}
- add parRun guards on various globalIndex gather methods
(simple copies or no-ops in serial) to simplify the effort for callers.
ENH: reduce code effort for clearing linked-lists
ENH: adjust linked-list method name
- complement linked-list append() method with prepend() method
instead of 'insert', which is not very descriptive
Assumes that gap is formed when both surfaces agree i.e.
it takes the minimum distance of the two. This means that
any wave only needs to be propagated according to the
originating surface.
- set() was silently deprecated in favour of reset() FEB-2018
since the original additional check for overwriting an existing
pointer was never used. The reset(...) name is more consistent
with unique_ptr, tmp etc.
Now emit deprecations for set().
- use direct test for autoPtr, tmp instead of valid() method.
More consistent with unique_ptr etc.
STYLE: eliminate redundant ptr() use on cloned quantities
- occurs with newer gcc on ubuntu impish (gcc-11.2.0), but may perhaps
actually be related to `-flto=auto` or to the destruction order of
the static variables (race condition?).
Leaving the compat table around for automatic cleanup does not
impact on other lookups (which are nullptr checked anyhow).
- partial revert for 13740de427 (#2158)
MS-MPI does not currently have a MPI_Comm_create_group(),
so keep using MPI_Comm_create() there.
Only affects multi-world simulations.
CONFIG: retain dummy version of libPstream.dll
- retain as libPstream.dll-dummy so that it is available for
manual replacement of the regular libPstream.dll (#2290)
Keep extra copy of libPstream.dll as libPstream.dll-msmpi
(for example) for manual replacement.
- this is now consistent with what the internal
"get(Vol|Surface|Point)Field" methods deliver
(ie, zero-gradient for volume, calculated otherwise).
Still some slight inconsistencies with what the internal
"new(Vol|Surface|Point)Field" methods deliver however.
There they are always "calculated"
Enables particles to interact with mesh faces (decsribed using faceZones).
faceInteraction1
{
type faceInteraction;
faceZones
(
(blockageFaces stick)
// (blockageFaces escape)
// (blockageFaces rebound) // not applicable for this test case (!)
);
dMin 0;
dMax 1;
}
The faceZones entry is a list of (faceZoneName interactionType), where
interaction type is either stick, escape or rebound.
The parcel initial velocity can now be set using the new `velocityType`
entry, taking one of the following options:
- fixedValue : (default) same as earlier versions, requires U0
- patchValue : velocity set to seed patch face value
- zeroGradient : velocity set to seed patch face adjacent cell value
Example usage:
model1
{
type patchInjection;
massTotal 1;
SOI 0;
parcelBasisType mass;
patch cylinder;
duration 10;
parcelsPerSecond 100;
velocityType patchValue;
//velocityType zeroGradient;
//U0 (-10 0 0);
flowRateProfile constant 1;
sizeDistribution
{
type normal;
normalDistribution
{
expectation 1e-3;
variance 1e-4;
minValue 1e-5;
maxValue 2e-3;
}
}
}
See the new $FOAM_TUTORIALS/lagrangian/kinematicParcelFoam/spinningDisk tutorial
The turbulentTemperatureCoupledBaffleMixed boundary condition
has been superseded by the turbulentTemperatureRadCoupledMixed condition
TUT: injectorPipe: remove an unused entry
TUT: waveMakerFlap: remove uncompressed entry
ENH: Copying alphatLiquid value to alphatVapour for boiling regimes.
When using correlations for boiling regimes the phases next to the
wall are not relevant to these. Therefore the alphat is copied
accordingly from the alphat for liquid.
Only in the sub-cooling RPI model the partition of heat flux
between vapour and liquid is considered.
Calculates propeller performance and wake field properties.
Controlled by executeControl:
- Propeller performance
- Thrust coefficient, Kt
- Torque coefficient, 10*Kq
- Advance coefficient, J
- Open water efficiency, etaO
- Written to postProcessing/<name>/<time>/propellerPerformance.dat
Controlled by writeControl:
- Wake field text file
- Wake: 1 - UzMean/URef
- Velocity in cylindrical coordinates at xyz locations
- Written to postProcessing/<name>/<time>/wake.dat
- Axial wake field text file
- 1 - Uz/URef at r/R and angle
- Written to postProcessing/<name>/<time>/axialWake.dat
- Velocity surface
- Written to postProcessing/<name>/surfaces/time>/disk.<fileType>
Usage
Example of function object specification:
\verbatim
propellerInfo1
{
type propellerInfo;
libs (forces);
writeControl writeTime;
patches ("propeller.*");
URef 5; // Function1 type; 'constant' form shown here
rho rhoInf; // incompressible
rhoInf 1.2;
// Optionally write propeller performance data
writePropellerPerformance yes;
// Propeller data:
// Radius
radius 0.1;
rotationMode specified; // specified | MRF
// rotationMode = specified:
origin (0 -0.1 0);
n 25.15;
axis (0 1 0);
// Optional reference direction for angle (alpha) = 0
alphaAxis (1 0 0);
//// rotationMode = mrf
//// MRF MRFZoneName;
//// (origin, n and axis retrieved from MRF model)
// Optionally write wake text files
// Note: controlled by writeControl
writeWakeFields yes;
// Sample plane (disk) properties
// Note: controlled by writeControl
sampleDisk
{
surfaceWriter vtk;
r1 0.05;
r2 0.2;
nTheta 36;
nRadial 10;
interpolationScheme cellPoint;
errorOnPointNotFound false;
}
}
\endverbatim
Where the entries comprise:
\table
Property | Description | Required | Deflt value
type | Type name: propellerInfo | yes |
log | Write to standard output | no | no
patches | Patches included in the forces calculation | yes |
p | Pressure field name | no | p
U | Velocity field name | no | U
rho | Density field name | no | rho
URef | Reference velocity | yes |
rotationMode | Rotation mode (see below) | yes |
origin | Sample disk centre | no* |
n | Revolutions per second | no* |
axis | Propeller axis | no* |
alphaAxis | Axis that defines alpha=0 dir | no |
MRF | Name of MRF zone | no* |
originOffset | Origin offset for MRF mode | no | (0 0 0)
writePropellerPerformance| Write propeller performance text file | yes |
writeWakeFields | Write wake field text files | yes |
surfaceWriter | Sample disk surface writer | no* |
r1 | Sample disk inner radius | no | 0
r2 | Sample disk outer radius | no* |
nTheta | Divisions in theta direction | no* |
nRadial | Divisions in radial direction | no* |
interpolationScheme | Sampling interpolation scheme | no* | cell
\endtable
Note
- URef is a scalar Function1 type, i.e. supports constant, table, lookup values
- rotationMode is used to set the origin, axis and revolutions per second
- if set to 'specified' all 3 entries are required
- note: origin is the sample disk origin
- if set to 'MRF' only the MRF entry is required
- to move the sample disk away from the MRF origin, use the originOffset
- if writePropellerPerformance is set to on|true:
- propellerPerformance text file will be written
- if writeWakeFields is set to on|true:
- wake and axialWake text files will be written
- if the surfaceWriter entry is set, the sample disk surface will be written
- extents set according to the r1 and r2 entries
- discretised according to the nTheta and nRadial entries
- provides a simple means of defining/modifying fields. For example,
```
<name1>
{
type exprField;
libs (fieldFunctionObjects);
field pTotal;
expression "p + 0.5*(rho*magSqr(U))";
dimensions [ Pa ];
}
```
It is is also possible to modify an existing field.
For example, to modify the previous one.
```
<name2>
{
type exprField;
libs (fieldFunctionObjects);
field pTotal;
action modify;
// Static pressure only in these regions
fieldMask
#{
(mag(pos()) < 0.05) && (pos().y() > 0)
|| cellZone(inlet)
#};
expression "p";
}
```
To use as a simple post-process calculator, simply avoid storing the
result and only generate on write:
```
<name2>
{
store false;
executionControl none;
writeControl writeTime;
...
}
```
- literal lookups only for expression strings
- code reduction for setExprFields.
- changed keyword "condition" to "fieldMask" (option -field-mask).
This is a better description of its purpose and avoids possible
naming ambiguities with functionObject triggers (for example)
if we apply similar syntax elsewhere.
BUG: erroneous check in volumeExpr::parseDriver::isResultType()
- not triggered since this method is not used anywhere
(may remove in future version)
Based on:
Cao, L., Sun, F., Chen, T., Tang, Y., & Liao, D. (2018).
Quantitative prediction of oxide inclusion defects inside
the casting and on the walls during cast-filling processes.
International Journal of Heat and Mass Transfer, 119, 614-623.
DOI:10.1016/j.ijheatmasstransfer.2017.11.127
Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
- this refines commit c233961d45, which added prefix scoping.
Default is now off (v2106 behaviour).
The 'useNamePrefix' keyword can be specified on a per function basis
or at the top-level of "functions".
```
functions
{
errors warn;
useNamePrefix true;
func1
{
type ...;
useNamePrefix false;
}
func2
{
type ...;
// Uses current default for useNamePrefix
}
}
```
- at the moment there is no significant difference since FieldBase is
essentially just a refCount anyhow, but changing the inheritance
ensures that reinterpret casting from SubField -> Field will
continue to work if FieldBase is changed in the future.
A Helmholtz-like filter is applied to the original field of sensitivity
derivatives. The corresponding PDE is solved on the sensitivity patches,
using the finite area infrastructure. A smoothing radius is needed,
which is computed based on the average 'length' of the boundary faces,
if not provided by the user explicitly.
If an faMesh is provided, it will be used; otherwise it will be created
on the fly based on either an faMeshDefinition dictionary in system or
one constructed internally based on the sensitivity patches.
Surface gradient scheme with under-/over-relaxed
full or limited explicit non-orthogonal correction.
A minimal example by using system/fvSchemes:
snGradSchemes
{
snGrad(<term>) relaxed;
}
and by using system/fvSolution:
relaxationFactors
{
fields
{
snGrad(<term>) <relaxation factor>;
}
}
A second-order gradient scheme using face-interpolation,
Gauss' theorem and iterative skew correction.
Minimal example by using system/fvSchemes:
gradSchemes
{
grad(<term>) iterativeGauss <interpolation scheme> <number of iters>;
}
- fix overly aggressive match in the API value
- allow `INTELMPI*` generic value, this can be used to specify something
like INTELMPI_custom and populate the corresponding wmake rule
manually
STYLE: mention FOAM_BUILDROOT in wmake -help-full output
STYLE: adjust openfoam shell session welcome information
- adjust internal variable names to reduce collision potential
- improve handling of openfoam -etc=...
Description
Writes point data in glTF v2 format
Two files are generated:
- filename.bin : a binary file containing all scene entities
- filename.gltf : a JSON file that ties fields to the binary data
The output can contain both geometry and fields, with additional support
for colours using a user-supplied colour map, and animation of particle
tracks.
Controls are provided via the optional formatOptions dictionary.
For non-particle track data:
\verbatim
formatOptions
{
// Apply colours flag (yes | no ) [optional]
colours yes;
// List of options per field
fieldInfo
{
p
{
// Colour map [optional]
colourMap <colourMap>;
// Colour map minimum and maximum limits [optional]
// Uses field min and max if not specified
min 0;
max 1;
// Alpha channel [optional] (uniform | field)
alpha uniform;
alphaValue 0.5;
//alpha field;
//alphaField T;
//normalise yes;
}
}
}
\verbatim
For particle tracks:
\verbatim
formatOptions
{
// Apply colours flag (yes | no) [optional]
colours yes;
// Animate tracks (yes | no) [optional]
animate yes;
// Animation properties [optional]
animationInfo
{
// Colour map [optional]
colourMap <colourMap>;
// Colour [optional] (uniform | field)
colour uniform;
colourValue (1 0 0); // RGB in range [0-1]
//colour field;
//colourField d;
// Colour map minimum and maximum limits [optional]
// Note: for colour = field option
// Uses field min and max if not specified
min 0;
max 1;
// Alpha channel [optional] (uniform | field)
alpha uniform;
alphaValue 0.5;
//alpha field;
//alphaField T;
//normalise yes;
}
}
\endverbatim
Note
When writing particle animations, the particle field and colour properties
correspond to initial particle state (first data point) and cannot be
animated (limitation of the file format).
For more information on the specification see
https://www.khronos.org/registry/glTF/
The utility will now add field data to all tracks (previous version only
created the geometry)
The new 'fields' entry can be used to output specific fields.
Example
cloud reactingCloud1;
sampleFrequency 1;
maxPositions 1000000;
fields (d U); // includes wildcard support
STYLE: minor typo fix
- specify any of these
./Allwmake -build-root=...
wmake -build-root=...
FOAM_BUILDROOT=... wmake
these specify an alternative root where build artifacts are to land.
Currently only used as an alternative for the 'build/' hierarchy
since the 'platforms/' target normally includes inputs as well.
Possible use:
```
(
export WM_MPLIB="%{foam_mplib}"
export FOAM_MPI="%{foam_mpi}"
export MPI_ARCH_PATH="%{mpi_prefix}"
export FOAM_BUILDROOT=/tmp/mpibuild
export FOAM_MPI_LIBBIN="$FOAM_BUILDROOT/platforms/$WM_OPTIONS/lib/$FOAM_MPI"
src/Pstream/Allwmake-mpi
)
```
- exposed by the new embedded function handling.
Requires local copies of dictionary content instead
(similar to coded BCs handling)
BUG: incorrect formatting for expression function output
ENH: simpler copyDict version taking wordList instead of wordRes
- corresponds to the most common use case at the moment
ENH: expression string writeEntry method
- write as verbatim for better readability
- this revises the changes made in 95cd8ee75c to replace the
SFINAE-type of handling of string hashes with direct definitions.
This places a bit more burden on the developer if creating hashable
classes derived from std::string or variants of Foam::string, but
improves reliability when linking.
STYLE: drop template key defaulting from HashSet
- this was never used and `HashSet<>` is much less transparent
than writing `HashSet<word>` or `wordHashSet`
- Generic thermophysical properties class for a liquid in which the
functions and coefficients for each property are run-time selected.
Code adapted from openfoam.org
- had lookups into the merge-point map instead of
determining/remapping the duplicate points directly.
The result was a jumble of face/point addressing.
STYLE: additional debug/verbosity comment for mergePoints
- marks if the value is considered to be independent of 'x'.
Propagate into PatchFunction1 instead ad hoc checks there.
- adjust method name in PatchFunction1 to 'whichDb()' to reflect
final changes in Function1 method names.
ENH: add a Function1 'none' placeholder function
- This is principally useful for interfaces that expect a Function1
but where it is not necessarily used by a particular submodel.
TUT: update Function1 creation to use objectRegistry
- allows an additional HashTable of pointers to reference external
content which not otherwise directly available via an
objectRegistry.
This could typically be used to provide a function-local "rho"
to the expression evaluation.
- for cell quantities, these evaluate on the faceCells associated with
that patch to produce a field of true/false values
- for face quantities, these simply correspond to the mesh faces
associated with that patch to produce a field of true/false values
- similar idea to swak timelines/lookuptables but combined together
and based on Function1 for more flexibility.
Specified as 'functions<scalar>' or 'functions<vector>'.
For example,
functions<scalar>
{
intakeType table ((0 0) (10 1.2));
p_inlet
{
type sine;
frequency 3000;
scale 50;
level 101325;
}
}
These can be referenced in the expressions as a nullary function or a
unary function.
Within the parser, the names are prefixed with "fn:" (function).
It is thus possible to define "fn:sin()" that is different than
the builtin "sin()" function.
* A nullary call uses time value
- Eg, fn:p_inlet()
* A unary call acts as a remapper function.
- Eg, fn:intakeType(6.25)
- previously simply reused the scan token, which works fine for
non-nested tokenizations but becomes too fragile with nesting.
Now changed to use tagged unions that can be copied about
and still retain some rudimentary knowledge of their types,
which can be manually triggered with a destroy() call.
- provide an 'identifier' non-terminal as an additional catch
to avoid potential leakage on parsing failure.
- adjust lemon rules and infrastructure:
- use %token to predefine standard tokens.
Will reduce some noise on the generated headers by retaining the
order on the initial token names.
- Define BIT_NOT, internal token rename NOT -> LNOT
- handle non-terminal vector values.
Support vector::x, vector::y and vector::z constants
- permit fieldExpr access to time().
Probably not usable or useful for an '#eval' expression,
but useful for a Function1.
- provisioning for hooks into function calls. Establishes token
names for next commit(s).
Returns a 0/1 value corresponding to function object trigger levels.
Usage:
\verbatim
<entryName> functionObjectTrigger;
<entryName>Coeffs
{
triggers (1 3 5);
defaultValue false; // Default when no triggers activated
}
\endverbatim
ENH: add reset() method for Constant Function1
ENH: allow forced change of trigger index
- the triggers are normally increase only,
but can now override this optionally
Description
Function1 wrapper that maps the input value prior to it being used by
another Function1.
Example usage for limiting a polynomial:
\verbatim
<entryName>
{
type inputValueMapper;
mode minMax;
min 0.4;
max 1.4;
value polynomial
(
(5 1)
(-2 2)
(-2 3)
(1 4)
);
}
\endverbatim
Here the return value will be:
- poly(0.4) for x <= 0.4;
- poly(1.4) for x >= 1.4; and
- poly(x) for 0.4 < x < 1.4.
Example usage for supplying a patch mass flux for a table lookup:
\verbatim
<entryName>
{
type inputValueMapper;
mode function;
function
{
type functionObjectValue;
functionObject surfaceFieldValue1;
functionObjectResult sum(outlet,phi);
}
value
{
type table;
file "<system>/fanCurve.txt";
}
}
\endverbatim
Where:
\table
Property | Description | Required
mode | Mapping mode (see below) | yes
function | Mapping Function1 | no*
min | Minimum input value | no*
max | Maximum input value | no*
value | Function of type Function1<Type> | yes
\endtable
Mapping modes include
- none : the input value is simply passed to the 'value' Function1
- function : the input value is passed through the 'function' Function1
before being passed to the 'value' Function1
- minMax : limits the input value to 'min' and 'max' values before being
passed to the 'value' Function1
Note
Replaces the LimitRange Function1 (v2106 and earlier)
Returns a value retrieved from a function object result.
Usage:
<entryName> functionObjectValue;
<entryName>Coeffs
{
functionObject <name>;
functionObjectResult <function object result field name>
}
Function1 can now be created with an object registry, e.g. time or mesh
database. This enables access to other stored objects, e.g. fields,
dictionaries etc. making Function1 much more flexible.
Note: will allow TimeFunction1 to be deprecated
- created new functionObjects::properties class derived from IOdictionary
- replaces raw state IOdictionary owned by functionObjectList
- state dictionary access/manipulators moved from stateFunctionObject
- stateFunctionObject now acts as a light wrapper around
functionObjecties::properties
- updated dependent code
- more closely reflect what the binaries report
- report the installation path
- change PS1 case/separator to roughly correspond to package names
STYLE: adjust README to mention upcoming v2112
- use `#word` to concatenate, expand content with the resulting string
being treated as a word token. Can be used in dictionary or
primitive context.
In dictionary context, it fills the gap for constructing dictionary
names on-the-fly. For example,
```
#word "some_prefix_solverInfo_${application}"
{
type solverInfo;
libs (utilityFunctionObjects);
...
}
```
The '#word' directive will automatically squeeze out non-word
characters. In the block content form, it will also strip out
comments. This means that this type of content should also work:
```
#word {
some_prefix_solverInfo
/* Appended with application name (if defined) */
${application:+_} // Use '_' separator
${application} // The application
}
{
type solverInfo;
libs (utilityFunctionObjects);
...
}
```
This is admittedly quite ugly, but illustrates its capabilities.
- use `#message` to report expanded string content to stderr.
For example,
```
T
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-10;
relTol 0;
#message "using solver: $solver"
}
```
Only reports on the master node.
- use FACE_DATA (was SURFACE_DATA) for similarity with polySurface
ENH: add expression value enumerations and traits
- simple enumeration of standard types (bool, label, scalar, vector)
that can be used as a value type-code for internal bookkeeping.
GIT: relocate pTraits into general traits/ directory
- releases ownership of the pointer. A no-op (and returns nullptr)
for references.
Naming consistent with unique_ptr and autoPtr.
DOC: adjust wording for memory-related classes
- add is_const() method for tmp, refPtr.
Drop (ununsed and confusing looking) isTmp method from refPtr
in favour of is_pointer() or movable() checks
ENH: noexcept for some pTraits methods, remove redundant 'inline'
- test for const first for tmp/refPtr (simpler logic)
- previously had codeAddSup used for both incompressible and
compressible source terms. However, it was not actually possible to
use it for compressible sources since any references to the 'rho'
parameter would cause a compilation error for the incompressible case.
Added 'codeAddSupRho' to distinguish the compressible case.
User must supply one or both of them on input.
- decomposePar: -no-fields to suppress decomposition of fields
- makeFaMesh: -no-decompose to suppress creation of *ProcAddressing
and fields, -no-fields to suppress decomposition of fields only
- switch from default topology merge to point merge if degenerate
blocks are detected. This should alleviate the problems noted in
#1862.
NB: this detection only works for blocks with duplicate vertex
indices, not ones with geometrically duplicate points.
ENH: add patch block/face summary in blockMesh generation
- add blockMesh -verbose option to override the static or dictionary
settings. The -verbose option can be used multiple times to increase
the verbosity.
ENH: extend hexCell handling with more cellShape-type methods
- allows better reuse in blockMesh.
Remove blockMesh-local hex edge definitions that shadowed the
hexCell values.
ENH: simplify some of the block-edge internals
- similar to -dry-run handling, can be interrogated from argList,
which makes it simpler to add into utilities.
- support multiple uses of -dry-run and -verbose to increase the
level. For example, could have
someApplication -verbose -verbose
and inside of the application:
if (args.verbose() > 2) ...
BUG: error with empty distributed roots specification (fixes#2196)
- previously used the size of distributed roots to transmit if the
case was running in distributed mode, but this behaves rather poorly
with bad input. Specifically, the following questionable setup:
distributed true;
roots ( /*none*/ );
Now transmit the ParRunControl distributed() value instead,
and also emit a gentle warning for the user:
WARNING: running distributed but did not specify roots!
COMP: implicit cast scope name to C++-string in IOobject::scopedName
- handles 'const char*' and allows a check for an empty scope name
COMP: avoid potential name conflict in local function (Istream)
- reportedly some resolution issues (unconfirmed) with Fujitsu clang
- added -dry-run, -write-vtk options.
Additional mesh information after creation.
- add parallel reductions and more information for checkFaMesh
ENH: minor cleanup of faPatch internals
- align pointLabels and pointEdges creation more closely with coding
patterns used in PrimitivePatch
- use fileHandler when loading "S0" field.
- previous handling did not correctly account for off-processor
connections (SEGFAULT).
- revised the point/area normal calculations to use the dual of the
faces. This simplifies the logic and reduces the depth of loops.
Point corrections from the neighbouring patches is handled
centrally by the new halo face information, which properly handles
on-processor or off-processor faces irrespective of any explicit
processor patches.
STYLE: local function and add comments for finiteArea area weighting
- following the original Tukovic code, the area-weighted normal
for a vector pair (defining a triangle) is weighted by
(1) area : larger weight for larger areas
(2) sin : lower weight for narrow angles (eg, shards)
(3) invDist squared : lower weights for distant points
Refactored to eliminate intermediate operations, some additional
divide-by-zero protection - similar to vector normalise()
- the finiteArea is typically restricteed to one or more patches on a
polyMesh but will have an external connectivity to other parts of
the polyMesh. For proper determination of the point normals (for
example), the neighbouring information is needed.
These outside 'halo' faces can be located on different processors,
but not correspond to an internal processor-processor interface.
Add a dedicated form of mapDistribute for swapping this type of
information. Since this is a collective operation, locate
corresponding methods directly on the faMesh level instead of
the faPatch level.
- the case of 'fan-like' processor was previously assumed to be
rare (see merge-request !490 and issue #2084).
However, Vaggelis Papoutsis noticed that even fairly normal geometries
can trigger problems.
- replaced the old patch/patch matching style with a more general
edge-based synchronisation and matching that appears to handle
the corner cases inherently. The internal communication overhead
is essentially unchanged, and the logic is simpler.
ENH: additional framework for managing patch connectivity
- the patch remapping in faFieldDecomposer calls weights
internalField() which can trigger parallel communication on the
complete mesh for some processors only (ie, blocks).
Force a priori creation of weights instead.
- ensure that the complete mesh (reconstruction helper)
is serial when adding patches.
- when creating a finite-area mesh in parallel, need to determine
the equivalent ProcAddressing for the faMesh.
In the faceProcAddressing the collected and sorted order was being
scattered directly back to the individual processors instead of only
the sections relevant to each particular processor.
This caused the observed jumbled order for reconstructed fields.
- this makes the lookup and use of tables slightly cleaner and
provides a hook for update (compat) messages
The singleton-style method returns the function pointer directly,
or nullptr on not-found.
NEW access method (mnemonic: 'ctor' prefix for constructors)
```
auto* ctorPtr = dictionaryConstructorTable(modelType);
if (!ctorPtr)
{
...
}
return autoPtr<myModel>(ctorPtr(dict, ...));
```
OLD method, which also still works, but without any compat handling:
```
auto ctorIter = dictionaryConstructorTablePtr_->cfind(modelType);
if (!ctorIter.found())
{
...
}
return autoPtr<myModel>(ctorIter()(dict, ...));
```
- a Pstream::master with a Pstream::parRun guard in case Pstream has
not yet been initialised, as will be the case for low-level messages
during startup.
- propagate relativeName handling into IOstreams
- better distinction between content and storage type
by appending 'Type' to the typedef.
old: 'Class::abcConstructorTable* tablePtr'
new: 'Class::abcConstructorTableType* tablePtr'
Was rarely used in any exposed code.
BREAKING: LESdelta::New with additional table
- parameter change to dictionaryConstructorTableType
(was dictionaryConstructorTable)
Example using mean turbulence fields (mean fields should be available e.g. from
a fieldAverage function object)
proudmanAcousticPower1
{
// Mandatory entries (unmodifiable)
type proudmanAcousticPower;
libs (fieldFunctionObjects);
...
// Turbulence field names (if not retrieved from the turb model)
k kMean;
epsilon epsilonMean;
omega none; // omegaMean
}
- was taking from the current head instead from specified commit-ish
ENH: add -debian=NUM convenience option to foamPackRelease
STYLE: relocate compile begin/end messages
COMP: suppress more clang warnings (needed for boost)
- provide a plain stream() method on messageStream to reduce reliance
on casting operators and slightly opaque operator()() calls etc
- support alternative stream for messageStream serial output.
This can be used to support local redirection of output.
For example,
refPtr<OFstream> logging; // or autoPtr, unique_ptr etc
// Later...
Info.stream(logging.get())
<< "Detailed output ..." << endl;
This will use the stdout semantics in the normal case, or allow
redirection to an output file if a target output stream is defined,
but still effectively use /dev/null on non-master processes.
This is mostly the same as this ternary
(logging ? *logging : Info())
except that the ternary could be incorrect on sub-processes,
requires more typing etc.
ENH: use case-relative names of dictionary, IOstream for FatalIOError
- normally yields more easily understandable information
- argList::envExecutable() static method.
This is identical to getEnv("FOAM_EXECUTABLE"), where the name of
the executable has typically been set from the argList construction.
Provides a singleton access to this value from locations that
do not have knowledge of the originating command args (argList).
This is a similar rationale as for the argList::envGlobalPath() static.
- additional argList::envRelativePath() static method.
- make -dry-run handling more central and easier to use by adding into
argList itself.
STYLE: drop handling of -srcDoc (v1706 option)
- replaced with -doc-source for 1712 and never used much anyhow
- for compilers such as gcc and clang, may have several different
variants installed on the computer. Use WM_COMPILER_CONTROL to
specify the preferred variant.
Eg,
WM_COMPILER=Gcc
WM_COMPILER_CONTROL="version=8"
will compile with "gcc-8" and "g++-8"
Good practice would be to tag output directory names with the
version too. Eg
WM_COMPILER=Clang110
WM_COMPILER_CONTROL="version=11.0"
STYLE: modify message for change of gcc -> clang (darwin)
- using the proximityRegions filter when there is no enclosing surface
to segregate domains causes a surface of zero-faces to be created.
In most cases, this means that a simpler proximityFaces filter would
have been more appropriate. To increase overall robustness, revert
to the simpler proximityFaces filter logic when the proximityRegions
would otherwise result in zero faces (globally seen).
- reuse single component buffer within an Ensight output method.
Use direct UPstream read/write to avoid Pstream char buffers
- replace blocking transfer with scheduled for Ensight cloud output
- UPstream::mpiGather (MPI_Gather) - used by Pstream::listGatherValues
- UPstream::mpiScatter (MPI_Scatter) - used by Pstream::listScatterValues
These are much simpler forms for gather/scatter of fixed-sized
contiguous types data types (eg, primitives, simple pairs etc).
In the gather form, creates a list of gathered values on the master
process. The subranks have a list size of zero.
Similarly, scatter will distribute a list of values to single values
on each process.
Instead of
labelList sendSizes(Pstream::nProcs());
sendSizes[Pstream::myProcNo()] = sendData.size();
Pstream::gatherList(sendSizes);
Can write
const labelList sendSizes
(
UPstream::listGatherValues<label>(sendData.size())
);
// Less code, lower overhead and list can be const.
For scattering an individual value only,
instead of
labelList someValues;
if (Pstream::master()) someValues = ...;
Pstream::gatherList(sendSizes);
const label localValue
(
someValues[Pstream::myProcNo()]
);
Can write
labelList someValues;
if (Pstream::master()) someValues = ...;
Pstream::gatherList(sendSizes);
const label localValue
(
UPstream::listScatterValues<label>(someValues)
);
Can of course also mix listGatherValues to assemble a list on master
and use Pstream::scatterList to distribute.
ENH: adjusted globalIndex gather methods
- added mpiGather() method [contiguous data only] using MPI_Gatherv
- respect localSize if gathering master data to ensure that a
request for 0 master elements is properly handled.
- Pstreams can be ascii/binary but are always currentVersion
- rename UIPstream externalBuf_ to 'recvBuf_' for similar naming as
PstreamBuffers and symmetry with UOPstream::sendBuf_
- specific enum size for commsType (for more compact structures in the
future). Default construct lists items.
BUG: possible incidental indexing in UIPstream::read(char*, std::streamsize)
- raw reading had been split into beginRawRead(), readRaw().
However, this could change the current input position (due to word
boundary alignment), even if the expected count is zero. Make a
no-op for count == 0. This mirrors UOPstream::write behaviour.
- construct or reset from a list of local sizes. It is generally
easier and safer to assemble sizes and let globalIndex determine the
corresponding offsets, when working with raw values.
- Can use reset() from sizes or fine-tune offsets with setLocalSize()
instead of using the potentially more fragile non-const access to
the offsets.
- add globalIndex const_iterator to iterate across the access ranges.
This is makes it simpler to use with the List slice() method to
access or operate on a sub-section of list.
For example,
scalarField allValues = ...;
globalIndex procAccess = ...;
for (const labelRange& range : procAccess)
{
someOutput(allValues.slice(range));
}
- the size of a List often requires adjustment prior to an operation,
but old values (if any) are not of interest and will be overwritten.
In these cases can use the _nocopy versions to avoid additional memory
overhead of the intermediate list and the copy/move overhead of
retaining the old values (that we will subsequently discard anyhow).
No equivalent for PtrList/UPtrList - this would be too fragile.
- add swap DynamicField with DynamicList
BUG: fixed Dynamic{Field,List} setCapacity corner case
- for the case when the newly requested capacity coincides with the
current addressable size, the resize of the underlying list would have
been bypassed - ie, the real capacity was not actually changed.
- remove (unused) PtrDynList setCapacity method as too fragile
- previously returned the range slice as a UList,
but this prevents convenient assignment.
Apply similar handling for Field/SubField
Allows the following
labelRange range(...);
fullList.slice(range) = identity(range.size());
and
fullList.slice(range) = UIndirectList<T>(other, addr);
ENH: create SubList from full FixedList (simplifies interface)
- allow default constructed SubList. Use shallowCopy to 'reset' later
- simply adds in the reinterpret_cast, which simplifies coding for
binary data movement.
Name complements the size_bytes() method for contiguous data
STYLE: container IO.C files into main headers for better visibility
STYLE: include CompactListList.H in polyTopoChange
- avoids future mismatches if the CompactListList template signature
changes
GIT: relocate CompactListList into CompactLists/ directory
- previously used an indirect patch to get the sampling locations,
but this doesn't take account of the face flips. Now use
the faceZone intrinsic for generating a properly flipped patch
and provide the sampling locations separately.
STYLE: adjust compatiblity header for surfaceMeshWriter
- it is now possible to include the selected mpi version in the
top-level bashrc or prefs.sh file. For example,
WM_MPLIB=OPENMPI-4.1.1 or WM_MPLIB=openmpi-4.1.1
after evaluation of the config.sh/mpi, this will define
WM_MPLIB=OPENMPI-4.1.1 and FOAM_MPI=openmpi-4.1.1
During the wmake, the mpi-rules will first load the MPI 'family'
rules (OPENMPI in this example) before trying to load
version-specific rules if they exist.
NOTE: the regular user-defined prefs system is unaffected by this
change. This means it is still possible to use a file such as
'prefs.openmpi' to define the preferred version instead or as well.
However, it does mean inconsistent naming can be specified.
For example, specify WM_MPLIB=OPENMPI-4.1.1 at the top-level but
actually have FOAM_MPI=openmpi-4.0.6 in the prefs.openmpi file.
This will make the value of WM_MPLIB misleading.
CONFIG: foamConfigurePaths support for sys-openmpi major version
CONFIG: cleanup any shadow env variables
- migrate to c++14 for most compilers *except* gcc.
There are still many systems in use with gcc-4.8.5, which does not
support c++14.
- initial rules for nvidia compilers (pgi is will soon be defunct).
Not fully tested...
CONFIG: provide fallback value for the user directory name
- in containers may have an unset USER env variable.
Default to 'user' to prevent ugly looking directory names.
- supports redistributePar -decompose -fileHandler collated
- supports redistributePar -reconstruct
- does not support redistributePar with collated in redistribution mode
- noticed by Robin Knowles with `decomposePar -fields -copyZero`
The internals for the Foam:cp method combine the behaviour of
a regular `cp` and `cp -R` combined.
When source and target are both directories, the old implementation
created a subdirectory for the contents.
This normally fine,
ok: cp "path1/0/" to "path2/1" -> "path2/1/2"
BUT: cp "path1/0/" to "path2/0" -> "path2/0/0" !!
Now add check for the basenames first.
If they are identical, we probably meant to copy directory contents
only, without the additional subdir layer.
BUG: decomposePar -fields -copyZero copies the wrong directory
- was using the current time name (usually latest) instead of copying
the 0 directory
ENH: accept 0.orig directories as a fallback to copy if the 0 directory
is missing
- use orte-info to determine prefix/libdir for openmpi.
This removes a run-time dependency on mpicc, which is actually
only needed for building with MPI (not running with MPI).
The corresponding openmpi devel package (deb/rpm) will not
necessarily be installed on a particular system.
- retain mpicc logic if the new logic using orte-info does not
deliver an answer. Final fallback to using 'orterun' to
infer prefix/libdir.
- Additional logic for intel and msmpi to make it easier to
locate these vendor packages within ThirdParty
(ie, under ThirdParty/opt/...)
CONFIG: improve robustness
- add check for absolute path when adding PATH/LD_LIBRARY_PATH etc.
- prefix more variables with '_foam*' to prevent accidental overwrite
of userspace shell variables when sourcing
- avoid deprecated autoPtr check
- bundle bool values in fvPatchField for compacter allocation
- change useImplicit to a set method taking an argument instead of
allowing direct access.
- top-level faceCells() on the boundary list simplifies the creation
of lduAddressing etc, can also be useful on its own
STYLE: replace isA/refCast combination with a single isA
- helps avoid the creation of small face cuts (near corners, edges)
that result in zero-size faces on output.
CONFIG: make default iso-surface topo regularisation less aggressive
- The full (diagcell) regularisation no longer includes cleaning of
non-manifold surfaces by removing open edges.
This can be selected by the 'clean' regularisation option instead.
ie, 'clean' = 'full' + erode open edges
ENH: additional debug modes for iso-surface topo
- with (debug & 8) dumps out a VTK file of the tets to be cut and the
calculated open edges.
- PstreamBuffers for parallel VTK output.
- avoids MPI overflows for larger meshes
- new vtk::lineWriter for writing edges
- vtk::fileWriter::writeUniform now also supports processor-specific
uniform values instead of assuming that they are identical everywhere.
- support simple mesh subsetting to vtu formats to enable debug output
for a subsection of an existing polyMesh
- rudimentary support for VTK from cellShapes is intended for handling
basic primitive cell shapes without a full blown polyMesh description.
For example,
// Create an empty polyMesh with points only
polyMesh debugMesh
(
io,
std::move(points),
faceList(), // faces
labelList(), // owner
labelList(), // neighbour
true // syncPar
);
// Establish the appropriate VTK sizing for the TET shapes
vtk::vtuCells vtuCells;
vtuCells.resetShapes(debugCutTets);
vtuCells.nPoints(debugMesh.nPoints());
NOTE
Since the vtk::internalMeshWriter only uses the polyMesh reference
for the points, it is also possible to create the vtuCells
description without a pointField (or from a different mesh
description) and write out the connectivity using the pointField
from a different mesh.
This intercepts all vector/tensor AMI interpolations and
does the interpolation in cylindrical coordinates.
Use (component) 'coupled' linear solver to enable this in
the linear solver sweeps.
- previously used the size of distributed roots to transmit if the
case was running in distributed mode, but this behaves rather poorly
with bad input. Specifically, the following questionable setup:
distributed true;
roots ( /*none*/ );
Now transmit the ParRunControl distributed() value instead,
and also emit a gentle warning for the user:
WARNING: running distributed but did not specify roots!
- use dictionary methods directly in LduMatrix::solver::readControls.
Deprecate the redundant LduMatrix::solver::readControl helper-function
- define solver log-level outside of the loop,
narrow log flag to int.
- reinstate API-compatible parameters for SolverPerformance
- allows reuse of an int64_t scotch library with label-size 32
and/or label-size 64.
COMP: prefer scotch/metis/kahip libraries with label-size qualifiers
- as noted in #2200, mpirun may insert mpi libraries higher in the
library loader which can cause masking of our ThirdParty libraries
of the same name. With scotch (for example), the operating system
may have an int32 version installed but we have an int64 version
compiled under ThirdParty. Runing in serial is fine, but in parallel
we resolve to the (incorrect) system version due to the adjustments
in mpirun.
- adjust the ThirdParty make scripts to also create corresponding
links (eg, 'ln -s libscotch.so libscotch-int64.so') and prefer
linkage with these qualified libraries.
Eg, -L$(SCOTCH_LIB_DIR) -lscotch$(SCOTCH_LIBNAME_SUFFIX)
this prevent accidental runtime linkage with the system versions.
STYLE: simplify scotch interface code by using local functions
- allows reuse similar to refPtr for wrapping different content.
- additional control for when contents are copied back,
instead of waiting for the adaptor to go out of scope.
Eg,
if (adaptor.active())
{
adaptor.commit();
adaptor.clear();
}
- static ConstPrecisionAdaptor::get method renamed to 'select' as a
better description of its purpose and avoid confusion with
non-static 'get' method.
Was previously only used within GAMGPreconditioner, but even there
it is better just to use the ConstPrecisionAdaptor directly.
For cases where the number of injectors exceeded the number of parcels to
inject, processing the injectors sequentially led to not all injector locations
being active and yielding non-physical spatial distributions.
Previous naming conventions for input variables in the
normal, multiNormal, RosinRammler, and massRosinRammler
distributions were heuristic and did not reflect
the de facto conventions being used in statistics.
BUG: distributionModel: disallow any distribution
where input min is equal to input max
ENH: distributionModel: ensure execution of check() at ctor level
Previously, for basic incompressible and compressible simulations,
the "force" function object has not been using the user-specified "UName"
for the "devRhoReff" computation (affecting the tangential component),
but using the "U" of the latest available step. In contrast,
the user-specified "pName" has always been being used correctly.
This has been causing issues for users when they wish to use a specific
"UMean" field in various force and forceCoeff function object computations.
Introduces a new optional keyword of label type 'log'
to linear-solver dictionaries to enable variable-specific
debug statements. For example, in fvOptions file:
solvers
{
p
{
solver GAMG;
...
log 2;
}
U
{
...
log 0;
}
}
The meanings of values of 'log' are:
log 0; <!-- no output
log 1; <!-- standard output
log 2; <!-- debug output
// values higher than 2 are expected to have no effect
This keyword does not directly affect the operations of various
DebugSwitches and backward compatibility has been ensured in exchange
of code cleanness. The related DebugSwitches are:
DebugSwitches
{
SolverPerformance 0;
GAMG 0;
PCG 0;
PBiCG 0;
smoothSolver 0;
}
- previously reported the WM_PROJECT_VERSION in the top banner
but this makes it overly sensitive to arbitrary user naming.
Change to the current API in the comment banner, include the
WM_PROJECT_VERSION as part of the reported "Build: ..."
string instead.
- previously had a patch-size check, which caused a zero-sized patch
to be "sticky" as uniform Zero regardless of what the original input
stated (eg, "constant 0.5")
This was caused by short-circuiting logic that circumvented reading
on zero-size patches.
- support non-uniform scaling, prescaling and cartesian coordinate
transformations.
Eg, stretch in one direction and then rotate
```
prescale (1.5 1 1);
transform
{
origin (0 0 0);
rotation
{
type axisAngle;
axis (0 0 1);
angle 45;
}
}
```
- support "transformed" versions of blockMesh vertices, topology.
With the additional of transformations etc, a simplistic application
of a single scale parameter is no longer sufficient.
new: blMesh.vertices(true);
old: blMesh.vertices() * blMesh.scaleFactor();
new: blMesh.topology(true);
old: N/A
- add individual edge access for blockDescriptor.
Saves copying and duplicate calculations.
- handle '(block face)' specification for curved faces,
which is ok for external block faces, but likely somewhat
questionable if used for internal block faces.
- Can specify
```
transform
{
origin (1 2 3);
rotation none;
}
```
instead of the longer form
```
transform
{
origin (1 2 3);
e1 (1 0 0);
e3 (0 0 1);
}
```
COMPAT: remove old (pre-1812) Euler and STARCD keywords
- use "angles", remove old compat name "rotation"
as clutter and possible confusion with "coordinate rotation"
STYLE: remove coordinate rotation move constructors
- an unnecessary holdover from older code.
- for v2106 restricted the input conversion of string types to disallow
treating verbatim strings as possible word input.
However, it was too strict in just allowing quoted strings
and should have also permitted '$'-sigil variables as well.
- ensure that errors for bad string -> word input conversion
are raised from within the '>>' read operator. These were
previously triggered during the stripping process, which
made error tracing more difficult.
The original thermoSurfaceFilm sub-models were divided between kinematicSurfaceFilm and thermoSurfaceFilm in order to use the surfaceFilm model in a kinematicCloud.
The film interaction models are now in a kinematicSurface class which can be used in a kinematic cloud adding constant thermal properties (p and T) for some sub-models, e.g. drySplashInteraction/wetSplashInteraction.
pRef and Tref were added to the kinematicSurfaceFilm as entry to the regionFilm when used with a kinematic cloud.
In the finite area surface film model Tref, pRef are stored in filmSubModelBase.
TUT: kinematicParcelFoam: new tutorial pitzDailySprinkles
ENH: Several additions to thinFilm models
1) Changing the faSolution entry nonOrthoCorr to nFilmCorr entry.
This entry specify the number of iterations on the film thickness
Eq which does not correct for laplacian non-orthogonality.
2) Changing laminar turbulent model for the skin friction exerted by
the flow to the film.
3) Adding optional relaxation factors for source terms coming from
the added mass of the lagragian particles into the film such as
rhoSp, pnSp and Usp. Similarly the film pressure (pf) can be
relaxed in the inner loops.
4) Adding optional entries to curvatureSepration injection model.
minimum (fThreshold) force and minimum curvature (minInvR1) for
separation were added to have more control on determining the
points of film separation
ENH: ThermoSurfaceFilm in lagragian to search for finiteArea film models
- new model framework: liquidFilm
- new film turbulence models: filmTurbulenceModel with friction models
- new velocity boundary condition: velocityFilmShell to handle/evolve regionFa film
- new function object: setTimeStep to control the simulation time-step based on regionFa Courant number
- add support for the absorption of Lagrangian particles into films
Issue first shows up on gcc-11 with these types of library symbols:
U Foam::tableReader<double>::dictionaryConstructorTablePtr_[abi:cxx11]
xx B Foam::tableReader<double>::dictionaryConstructorTablePtr_
Use concrete hasher functor for runtime selection tables, which
avoids any additional template resolutions (introduced with
95cd8ee75c). The library symbols now resolve _without_ an
additional abi:cxx11 tag.
- need to change requireUpdate_ at the beginning of calculateCache
otherwise it is not updated for "ALL" selection (causing unnecessary
repeated calculations). For other modes, it would have tripped
an error in FULLDEBUG.
- all flags before loaders. Avoids "uninitialized when used here"
warning while preserving the field ownership logic.
- relocate override of updateT basicThermo into constructor body
for clearer logic and initialization
STYLE: plain bool instead of Switch for dpdt flag
1) Adding subMesh capabilities to momentumError and div FOs.
- A subMesh is created from cellZones.
- The operators (div, etc) are only calculated in the subMesh.
2) Optionally, halo cells can be added to the cellZones.
3) New helper class to handle the subMesh creation and field mapping.
- add setter/getter methods for number of grow/shrink steps,
which allows reuse of the same object.
- remove the lower input hard-limit of 1 step, to allow definition of
a no-op filter.
- drop early exit from grow/shrink cycle (potential parallel issues).
- previously a function (unlike the csh version) but since bashrc and
setup have been split -> replace with inline definition
STYLE: formatting/wording for openfoam starters
TUT: simplify controlDict modification, add default substitution
ENH: accept '/' for end-of-options terminator (etc/openfoam)
- makes the application or service more apparent.
* eg. /usr/bin/openfoam / blockMesh
* vs. /usr/bin/openfoam -- blockMesh
Accept lone '-' as the end-of-options terminator, as per bash
- Adjust handling of openfoam '-c' option to flag that a command-string
will appear, but continue with option parsing.
Consistent with bash definition.
- in the 'auto' mode (now the default), it will use cleanCase and also
remove the 0/ directory if a 0.orig/ directory also exists.
This corresponds to a frequent idiom and can be used quite safely
for most cases.
ENH: add -serial / -parallel preference for foamRunTutorials
- adjust commented-out evaluation to avoid warnings.
With code like this
```
#if 0
nxin #eval{ round($nxin / 5) };
#endif
```
The handling of the "#if 0 / #endif" clause uses the plain ISstream
parser to tokenize. This means that the "round(" is parsed as a word
with a mismatched closing ')', whereas the "#eval" parser will slurp
everything in until the closing brace and send it off as a string
to the expression parser.
- Added new faceAreaWeightAMI2D AMIMethod:
- performs intersection using a new 2D triangle class;
- candidate face matches set using an AABBTree method (vs advancing front for
faceAreaWeightAMI).
- Use by setting the AMIMethod entry when specifying the AMI in the
constant/polyMesh/boundary file, e.g.
AMI
{
type cyclicACMI;
AMIMethod faceAreaWeightAMI2D; // new method
Cbb 0.1; // optional coefficient
nFaces 1000;
startFace 100000;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch AMI1;
nonOverlapPatch AMI1_non_overlap;
}
- The optional Cbb coeffcient controls the size of the bounding box used when
looking for candidate pairs; the value of 0.1 is the default and worked well
for a large range of test cases. For badly matched AMI patches this may need
to be increased.
- Deprecated the partialFaceAreaWeightAMI class - primarily used by ACMI:
- functionality now offered by the AMI variants.
- prghPermeableAlphaTotalPressure for p_rgh
- pressurePermeableAlphaInletOutletVelocity for U
- new helper class for pressure-related BCs: updateableSnGrad
Wrapper that clones the supplied object for each region.
Simplifies the setup of identical post-processing requirements for
multi-region cases.
Applies the supplied function to all regions by default.
Example of function object specification:
multiRegion
{
type multiRegion;
libs (utilityFunctionObjects);
...
function
{
// Actual object specification
type fieldMinMax;
libs (fieldFunctionObjects);
fields (<field1> .. <fieldN>);
}
// Optional entries
regions (region1 region2);
}
Where the entries comprise:
Property | Description | Reqd | Default
type | Type name: multiRegion | yes |
function | Function object sub-dictionary | yes |
regions | List of region names | no | all
Computes a selected operation between multiple \c fieldValue function
objects.
The operation is applied to all results of each \c fieldValue object.
Note
Each object must generate the same number and type of results.
Usage
Minimal example by using \c system/controlDict.functions:
multiFieldValue1
{
// Mandatory entries (unmodifiable)
type multiFieldValue;
libs (fieldFunctionObjects);
// Mandatory entries (runtime modifiable)
operation subtract;
// List of fieldValue function objects as dictionaries
functions
{
region1
{
...
}
region2
{
...
}
...
regionN
{
...
}
}
// Optional (inherited) entries
...
}
where the entries mean:
Property | Description | Type | Req'd | Dflt
type | Type name: multiFieldValue | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | -
operation | Operation type to apply to values | word | yes | -
functions | List of fieldValue function objects | dict | yes | -
\endtable
Options for the \c operation entry:
add | add
subtract | subtract
min | minimum
max | maximum
average | average
Deprecated fieldValueDelta
- The fieldValueDelta function object was originally written to compute the
difference between two fieldValue-type function objects. The multiFieldValue
object name better describes its purpose whilst being able to operate on an
arbitrary number of fieldValue-type objects.
Currently only applied to the fanFvPatchField, e.g.
plane
{
type fan;
patchType cyclic;
jump uniform 0;
value uniform 0;
uniformJump false;
// Optional under-relaxation
relax 0.2;
...
}
- combines region-based and proximity-based filtering
proxityRegions (post-filter):
Checks the distance of the resulting faces against the original
search surface. Filters based on the area-weighted distance
of each topologically connected region.
If the area-weighted distance of a region is greater than
\c absProximity, the entire region is rejected.
STYLE: 'proxityFaces' as newer synonym for 'proximity' filter
- snGrad, internalField, neighbourField.
Functional use as per swak: "... + internalField(T) ..."
ENH: additional volume/patch expressions
- deltaT()
STYLE: rename exprDriverWriter -> fvExprDriverWriter
- the original class name was a misnomer since it holds a reference
to fvExprDriver
BUG: expression faceToPoint/pointToFace definitions were flipped
ENH: refactor expression hierarchy and code style
- handle TimeState reference at the top-level for simpler derivations
- unified internal search parameters (cruft)
- support wordRes for selecting patch names
- ownerPolyPatch specification is now optional, which simplifies input
and also supports a faMesh spanning different patches but with a
single boundary condition.
Alternatively, can specify more granularity if required.
```
polyMeshPatches ( "top.*" );
boundary
{
inlet1
{
type patch;
ownerPolyPatch top1; // <- specific to this portion
neighbourPolyPatch inlet;
}
inlet2
{
type patch;
ownerPolyPatch top2; // <- specific to this portion
neighbourPolyPatch inlet;
}
outlet
{
type patch;
neighbourPolyPatch outflow;
}
bound
{
type symmetry;
neighbourPolyPatch bound;
}
}
```
- additional -serial/-parallel option:
prefer Allrun-serial or Allrun-parallel if available
- optional -output=DIR to preserve output
ENH: report missing tutorials/ directory in RunFunctions
- add to wmakeFunctions to ensure it works even without 'make' being
installed. Exit immediately after -show-api for consistency with
-version.
foamEtcFile:
- drop warnings for some old (pre-v1812) defunct options
and simply flag as unknown options.
- handle -version, --version as equivalent to -show-api
Prior to the commit, initial residual fields were registered by
the `setResidualField()` function of a linear solver with a field name
prefixed by `residual:`. However, `solverInfo` FO could only access to
the initial residual fields prefixed by `initialResidual:`.
Due to this discrepancy, using `solverInfo` FO with `writeResidualFields=true`
option was resulting in empty residual fields to be output.
- ENH: turbulentDFSEMInlet: add normalisation factors for
input Reynolds stresses, mean velocity and integral-length
scales as entries `Uref` and `Lref`.
- ENH: turbulentDFSEMInlet: add scaling factor entries, `scale`
and `m`, to enable users to tune C1 normalisation coefficient,
if need be.
- BUG: turbulentDFSEM: (fixes#1004#1744#2089)
- see #2090 for theoretical issues related to the DFSEM method.
three macros:
- makeParcelCloudFunctionObjects for kinematic parcels
- makeThermoParcelCloudFunctionObjects for thermo parcels
- makeReactingParcelCloudFunctionObjects for reacting parcels
code style and quality improvements
renamed recon::centre to interfaceCentre.{groupName}
ranmed recon::normal to interfaceNormal.{groupName}
centre and normal field are not written by default
- makes it easier to use for local or alternative storage.
Eg,
```
tmp<volScalarField> tfld;
tfld.cref(obj.cfindObject<volScalarField>("name"));
if (!tfld)
{
tfld = volScalarField::New("name", ...);
}
```
- in some cases, additional dictionary inputs are useful for extending
the input parameters or functionality of dynamic coded conditions.
Typically this can be used to provide a simple set of dictionary
inputs that are used to drive specific code, but allows changing the
inputs without causing a recompilation.
Accessed with this type of code:
```
const dictionary& dict = this->codeContext();
```
boundary conditions and function objects:
* specify an additional codeContext dictionary entry:
```
codeContext
{
...
}
```
PatchFunction1:
* The code context dictionary is simply the dictionary used to specify
the PatchFunction1 coefficients.
To replicated persistant data, use local member static data.
Eg,
```
code
#{
// Persistent (Member) Data
static autoPtr<Function1<scalar>> baseVel;
static autoPtr<Function1<vector>> baseDir;
...
#}
```
fvOptions:
* currently not applicable
- meshTools include/library for many (most) coded items
- add PatchFunction1 include for coded BCs to provide ready access
to Function1 and PatchFunction1
- resizes to current fieldNames_ size and assigns everything to
false to avoid any "stickiness" if the field ordering changes
between reads.
ENH: additional debugging faOption/fvOption (#2110)
- aids tracing which sources are being used/ignored
- update code style
STYLE: rename CodedSource -> CodedFvSource
- avoid future name clashes with CodedFaSource
- with the changes in vtkCellArray, the legacy files now have
OFFSET, CONNECTIVITY information.
- support reading of both versions.
- continue to generate legacy format 2.0, since this is what
many programs still expect
- consider the neighbour polyPatch addressing on the connecting edge,
even when the neighbouring processor does not have a corresponding
section of the finiteArea mesh.
These "dangling" edges now propagate their real connectivity across.
- A bare-bones reconstructor for finiteArea meshes when processor
meshes are available (in parallel) but an equivalent serial faMesh
is needed for reconstruction or decomposition.
In these situations, a serial version of the faMesh is needed,
but preferably without reconstructing the entire volume mesh.
It uses the finiteVolume faceProcAddressing in addition to
the geometric information available from the underlying polyMesh.
The resulting equivalent faMesh can be used for basic operations,
but caution should be exercised before attempting large operations.
- adjust surfactantFoam/planeTransport tutorial to have partial
coverage of the plate by the finiteArea mesh.
Depending on the decomposition, the outflow boundary may coincide
with a processor patch (good for testing purposes).
- additional Allrun-parallel versions for targetted future behaviour
- improved separation of patch creation that is also parallel-aware,
which now allows creation in parallel
- memory-safe use of PtrList for adding patches, with a more generalized
faPatchData helper
- use uindirectPrimitivePatch instead of indirectPrimitivePatch
for internal patch handling.
- align boundary methods with polyMesh equivalents
- system/faMeshDefinition instead of constant/faMesh/faMeshDefinition
as per blockMesh convention. Easier to manage definitions, easier
for cleanup.
- drop inheritence from GeoMesh.
- depending on how the finiteArea is split up across processors,
it is possible that some processors have failed to register
fields in their object registry.
Now ensure that the field names are synchronized in parallel before
attempting a write. Replace locally missing fields with a dummy
zero-sized field.
- refine definition of patch boundary faces to distinguish between
boundaryFaces() and uniqBoundaryFaces().
* boundaryFaces() for edge to face lookup on boundary edges.
* uniqBoundaryFaces() for accessing quantities such as face areas
or eroding an outer layer
ENH: LabelledItem container, replaces unused 'Keyed' container
- method names in alignment with objectHit, pointIndexHit etc.
Top-level name aligns with labelledTri.
- provide '-clean' option for removing old files
- handle out of order '-decomposeParDict' as per RunFunctions
- implicit no-prompt '-yes' with the shortcuts (eg, -log, -xterm)
and set -local if not already defined
- accept <return> to select defaults
This is a partial fix for #2103. If there are no points
extruded for a stand-alone mesh (so not adding to mesh)
it should still include the original patch points. Not
doing so would generate illegal faces (also copiedPatchPoints
would not get set).
- can now drop older Test-decomposePar for exploration purposes
and simply use -dry-run with the -domains and -method options.
- write VTK file instead of volScalarField in combination
with -dry-run and -cellDist.
Avoids adding any OpenFOAM fields and is usually faster to load.
Also easier to rename than a volScalarField would be when exploring
multiple decompositions.
* removed internal upper limit on word/string length for parsed input.
- Although it has not caused many problems, no reason to retain
these limits.
- simplify some of the internal logic for reading string-like items.
- localize parsers for better separation from the header
- expose new function seekCommentEnd_Cstyle(), as useful
handler of C-style comments
* exclude imbalanced closing ')' from word/variable
- previously included this into the word/variable, but makes more
sense to leave on the parser for the following token.
Prevents content like 'vector (10 20 $zmax);' from being parsed
as '$zmax)' instead of as '$zmax' followed by a ')'.
No conceivable reason that the former would actually be desirable,
but can still be obtained with brace notation: Eg, '${zmax)}'
* consistent handling of ${{ ... }} expressions
- within a dictionary content, the following construct was
incorrectly processed:
value ${{2*sqrt(0.5)}};
Complains about no dictionary/env variable "{2*sqrt(0.5)}"
Now trap expressions directly and assign their own token type
while reading. Later expansion can then be properly passed to
the exprDriver (evalEntry) instead of incorrectly trying
variable expansion.
Does not alter the use of expressions embedded within other
expansions. Eg, "file${{10*2}}"
* improve #eval { ... } brace slurping
- the initial implementation of this was rudimentary and simply
grabbed everything until the next '}'. Now continue to grab
content until braces are properly balanced
Eg, the content: value #eval{${radius}*2};
would have previously terminated prematurely with "${radius" for
the expression!
NOTE:
both the ${{ expr }} parsed input and the #eval { ... } input
discard C/C++ comments during reading to reduce intermediate
overhead for content that will be discarded before evaluation
anyhow.
* tighten recognition of verbatim strings and expressions.
- parser was previously sloppy and would have accepted content such
as "# { ..." (for example) as an verbatim string introducer.
Now only accept parse if there are no intermediate characters
discarded.
- minor simplification of #if/#endif handling
ENH: improve input robustness with negative-prefixed expansions (#2095)
- especially in blockMeshDict it is useful to negate an value directly.
Eg,
```
xmax 100;
xmin -$xmax;
```
However, this fails since the dictionary expansion is a two-step
process of tokenization followed by expansion. After the expansion
the given input would now be the following:
```
xmax 100;
xmin - 100;
```
and retrieving a scalar value for 'xmin' fails.
Counteract this by being more generous on tokenized input when
attempting to retrieve a label or scalar value.
If a '-' is found where a number is expected, use it to negate the
subsequent value.
The previous solution was to invoke an 'eval':
```
xmax 100;
xmin #eval{-$xmax};
```
which adds additional clutter.
- intended for the following type of use:
auto oldHandler = fileHandler(fileOperation::NewUncollated());
... do something that only works with uncollated
// Restore previous (if any)
if (oldHandler)
{
fileHandler(std::move(oldHandler));
}
ENH: make fileOperation distributed(bool) mutable
- use is "static-like" and akin to Pstream::parRun(bool),
thus allow toggling of the switch without a const_cast
- return internalEdges() and boundaryEdges() sub lists directly
- calculate and return boundaryFaces() to identify faces attached to
boundary edges.
- minor code cleanup, and add PrimitivePatchBase class for
non-templated code.
STYLE: mark unused parameter in globalMeshData mergePoints
- this constructor was added for similarity with std::vector,
but continues to cause various annoyances.
The main problem is that the templated parameter tends to grab
anything that is not a perfect match for other constructors.
Typically seen with two integers (in 64-bit mode), but various other
cases as well.
If required, the ListOps::create() function provides a lengthier
alternative but one that can also incorporate transformations.
Eg,
pointField pts = ....;
List<scalar> mags
(
List<scalar>::create
(
pts.begin(),
pts.end(),
[](const vector& v){ return magSqr(v); }
);
- additional rcEdge(), rcEdges() methods for reverse order walk
- accept generic edge() method as alternative to faceEdge() for
single edge retrieval.
- edge() method with points -> returns the vector
- reduce the number of operations in edgeDirection methods
DEFEATURE: remove longestEdge global function
- deprecated and replaced by face::longestEdge() method (2017-04)
Historically the "geometry" for static meshes was placed under
directly in the EnSight case directory.
Eg,
ensight/ensight.case
ensight/geometry
ensight/data/000001
ensight/data/000002 ...
This generally works ok, but relocating it to a constant data directory
Eg
ensight/ensight.case
ensight/data/constant/geometry
ensight/data/000001
ensight/data/000002 ...
Improves handling and avoids potential collisions when adding in
additional mesh regions
- reduces code, simplifies creation of new, specialized polyData
writers.
- new templated vtk::GenericPatchWriter, which adds support for
writing both uindirectPrimitivePatch + indirectPrimitivePatch types.
- handle geometric fields separately from regular fields with
* vtk:GenericPatchGeoFieldsWriter
* vtk:indirectPatchGeoFieldsWriter
* vtk:uindirectPatchGeoFieldsWriter
- can be used for block-like meshes that are not aligned with the global
coordinate directions. Alternatively, for general testing purposes.
Example,
method simple;
coeffs
{
n ( 2 2 2 );
transform
{
origin (-0.15 0.15 0);
e1 (1 1 0);
e3 (0 0 1);
}
}
Step 1.
include "addAllRegionOptions.H"
Adds the -allRegions, -regions and -region options to argList.
Step 2.
include "getAllRegionOptions.H"
Processes the options with -allRegions selecting everything
from the regionProperties.
OR use -regions to specify multiple regions (from
regionProperties), and can also contain regular expressions
OR use the -region option
Specifying a single -regions NAME (not a regular expresssion)
is the same as -region NAME and doesn't use regionProperties
Creates a `wordList regionNames`
Step 3.
Do something with the region names.
Either directly, or quite commonly with the following
include "createNamedMeshes.H"
Creates a `PtrList<fvMesh> meshes`
STYLE: add description to some central include files
- make regionName an optional constructor parameter, which eliminates
a separate set of constructors and construction tables. Adjust
internals to treat a missing/empty regionName as a no-op.
- pass in fallback dictionary content via new IOdictionary constructor
with a pointer
ENH: further relax check for matching number of processor dirs
- if the "numberOfSubdomains" entry is missing (or even zero)
ignore checks of processor dirs as meaningless.
- additional debug information
- improve support for dictionary specification of constant, polynomial
and table entries. These previously only worked properly for
primitiveEntry, which causes confusion.
- extend table Function1 to include TableFile functionality.
Simplifies switching and modifying content.
- additional default construct
- add explicit zero-size constructor for ITstream.
For tagged dispatching, without ambiguity
- elminate mandatory name for parsing versions.
This makes it easier to use ITstream, IStringStream, UListStream
interchangeable.
- some code used copy construct from dictionary::null instead.
The result is the same but suggests that something else may be intended.
Only need dictionary::null for const-ref usage.
- allows use of surface names starting with a digit
(by quoting the name).
User is responsible for not generating bad names for output files.
Eg "bad.**.name", since these will be difficult to handle from the
shell
- largely as per patch from Jong-Gwan (Jason) Do
NB: the intel-one setup adds in paths for intelmpi.
Its mpicc version does not harmonize with the OpenFOAM
system openmpi setup (using mpicc --showme:link).
Needs adjustment, or use intelmpi instead.
- update name mappings for newer gcc, clang versions
Checking for the sum of species mass fraction in multiComponentMixture.
It can't be zero at the internal field or patches. A fatal error is thrown.
A warning was added if the mixture sum is different from one. In a
re-start the mass fraction can be slightly unbounded and new
normalization is required.
- The keyType is primarily used within dictionary reading, whereas
wordRe and wordRes are used for selectors in code.
Unifying on wordRe and wordRes reduces the number matching options.
- additional dummy template parameter to assist with supporting
derived classes. Currently just used for string types, but can be
extended.
- provide hash specialization for various integer types.
Removes the need for any forwarding.
- change default hasher for HashSet/HashTable from 'string::hash'
to `Hash<Key>`. This avoids questionable hashing calls and/or
avoids compiler resolution problems.
For example,
HashSet<label>::hasher and labelHashSet::hasher now both properly
map to Hash<label> whereas previously HashSet<label> would have
persistently mapped to string::hash, which was incorrect.
- standardize internal hashing functors.
Functor name is 'hasher', as per STL set/map and the OpenFOAM
HashSet/HashTable definitions.
Older code had a local templated name, which added unnecessary
clutter and the template parameter was always defaulted.
For example,
Old: `FixedList<label, 3>::Hash<>()`
New: `FixedList<label, 3>::hasher()`
Unchanged: `labelHashSet::hasher()`
Existing `Hash<>` functor namings are still supported,
but deprecated.
- define hasher and Hash specialization for bitSet and PackedList
- add symmetric hasher for 'face'.
Starts with lowest vertex value and walks in the direction
of the next lowest value. This ensures that the hash code is
independent of face orientation and face rotation.
NB:
- some of keys for multiphase handling (eg, phasePairKey)
still use yet another function naming: `hash` and `symmHash`.
This will be targeted for alignment in the future.
- wrap command-line retrieval of fileName with an implicit validate.
Instead of this:
fileName input(args[1]);
fileName other(args["someopt"]);
Now use this:
auto input = args.get<fileName>(1);
auto other = args.get<fileName>("someopt");
which adds a fileName::validate on the inputs
Because of how it is implemented, it will automatically also apply
to argList getOrDefault<fileName>, readIfPresent<fileName> etc.
- adjust fileName::validate and clean to handle backslash conversion.
This makes it easier to ensure that path names arising from MS-Windows
are consistently handled internally.
- dictionarySearch: now check for initial '/' directly instead of
relying on fileName isAbsolute(), which now does more things
BREAKING: remove fileName::clean() const method
- relying on const/non-const to control the behaviour (inplace change
or return a copy) is too fragile and the const version was
almost never used.
Replace:
fileName sanitized = constPath.clean();
With:
fileName sanitized(constPath);
sanitized.clean());
STYLE: test empty() instead of comparing with fileName::null
- simplify compile/uncompile, reading, assignment
- implicit construct wordRe from keyType (was explicit) to simplify
future API changes.
- make Foam::isspace consistent with std::isspace (C-locale)
by including vertical tab and form feed
ENH: improve #ifeq float/label comparisons
- originally had tests for regex meta characters strewn across
regExp classes as well as wordRe, keyType, string.
And had special-purpose quotemeta static function within string
that relied on special naming convention for testing the meta
characters.
The regex meta character testing/handling now relegated entirely
to the regExp class(es).
Relocate quotemeta to stringOps, with a predicate.
- avoid code duplication. Reuse some regExpCxx methods in regExpPosix
It was only looking for faces that were used in both
endpoints but not actually checking whether they were indeed
an edge (== consecutive vertex) in all faces. So if one
face had an additional crossing edge and another didn't it
would find more edgeFaces than the proper
'primitiveMesh::edgeFaces()' routine.
This occasionally happened inside snappyHexMesh
(e.g. motorBike tutorial)
When extruding an edge to a patch face make sure to extrude
all the patch faces connected to that edge and cell. This
will handle cyclicACMI (has duplicate patches - AMI and non-overlap)
fvMesh::readUpdate calls polyMesh::readUpdate which updates
the ACMI (including mesh areas etc). So we should not call
polyMesh::clearOut again inside fvMesh::readUpdate to avoid
having to re-do all the ACMI.
For example,
```
entry #eval 10 { vector(rand(), 0, 0) };
```
ENH: be more generous and ignore trailing ';' in expressions
STYLE: adjust parse token name for tensor::I
- previously had a very old (likely irrelevant) setting for solaris
systems only.
- support site-specific customization.
Eg, using etc/config.{csh,sh}/prefs.fjmpi
- remove erroneous shell redirects present in cshell files
- less important for VTK (may help in future though) but preserve
the face point 0 when flipping faces to ensure that the result
is the same as having called face::reverseFace()
- overCompressibleInterDyMFoam: Overset solver for two compressible,
non-isothermal, immiscible fluids using a VOF (i.e. volume of fluid)
phase-fraction based interface capturing approach.
- overInterPhaseChangeDyMFoam: Overset solver for two incompressible,
isothermal, immiscible fluids with phase-change (e.g. cavitation) using
VoF (i.e. volume of fluid) phase-fraction based interface capturing approach.
- adds new tutorials:
- multiphase/overCompressibleInterDyMFoam/compressibleTwoSimpleRotors
- multiphase/overInterPhaseChangeDyMFoam/twoSimpleRotors
Signed-off-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
- useful when used in a batch process to trap the exit signal,
e.g. stop the run when the velocity magnitude exceeds a given
threshold:
runTimeControl
{
type runTimeControl;
libs ("libutilityFunctionObjects.so");
nWriteStep 1;
// Optional end 'action'
satisfiedAction abort; // end; // setTrigger
conditions
{
maxU
{
type minMax;
functionObject MinMax;
fields ("max(mag(U))");
value 1e6;
mode maximum;
}
}
}
- if the system/decomposeParDict is missing, skip check for matching
number of processor dirs. This can make job dispatch easier.
Does not apply if -decomposeParDict was explicitly specified.
STYLE: adjust naming of host/slaves in argList
- ensure that the processor directory cache is consistently available
by providing appropriate synthesized names. If the expected files
really do not exist, it will still fail at a later point (but not in
the caching).
This addresses cases that have been manually distributed
(different content on different nodes, but the same root path),
while still maintaining the readDir on master only for massively
parallel cases (#1946). It also addresses regular cases with
gaps in the processor directories.
- new '-ascii' option to write in ASCII format instead of the
controlDict setting. This can be useful when generating fields that
should be parsed with other tools, or for visual inspection.
- correct mismatch of option names and lookups
- can use either command-line option "-load-fields" or dictionary
entry "readFields" to specify field names to be preloaded.
Essentially the same functionality as with a readFields function
object but with a lot less typing.
- tutorial examples provided by Ryan Danks <ryan.danks@rwdi.com>
illustrate using setExpr* utilities to calculate a quantity
as a post-processing step.
- simplifies local toggling.
- centralize fileModification static variables into IOobject.
They were previously scattered between IOobject and regIOobject
to operate with overset
1) Adding zoneMotion to rigidBodyMotion
2) Introducing PID to prescribedRotation restraint
3) Making drivenLinearMotion read total displacement
4) When drivenLinearMotion is used sixDof and rigid-body solvers
write total displacement
- currently add to mesh zones to provide a table of contents
of the zone names that allows downstream consumers quick access to
the information without needing to parse the entire file.
- support selective enable/disable of the file banner.
ENH: improve code isolation for decomposedBlockData
- use readBlockEntry/writeBlockEntry to encapsulate the IO handling,
which ensures more consistency
- new decomposedBlockData::readHeader for chaining into the
block header information.
- remove unused constructors for decomposedBlockData
ENH: minor cleanup of collated fileOperations
- improves interface and data consistency.
Older signatures are still active (via the Foam_IOstream_extras
define).
- refine internals for IOstreamOption streamFormat, versionNumber
ENH: improve data alignment for IOstream and IOobject
- fit sizeof label/scalar into unsigned char
STYLE: remove dead code
- read/write lists of character data in binary only.
This is the only means of preserving data.
If character data are written as an ASCII list, there is no means of
determining if spaces or newlines are content or separators.
- handle binary/contiguous first as being the most obvious, followed
by increasing complexity of ascii.
Structure reading and writing routines similarly by introducing a
readList method to compliment the writeList method.
- override casename, procesorCase flags to guarantee reconstructed
case to be written to the undecomposed directory
- alternative is to construct a Zero mesh on the undecomposed
runTime and add all other bits to that but that has not been
pursued
- patch point ordering was affected by the EnSight face sorting
(tri, quad, nsided). This did not affect other point fields,
since they use the internal field values.
- for use when the is_contiguous check has already been done outside
the loop. Naming as per std::span.
STYLE: use data/cdata instead of begin
ENH: replace random_shuffle with shuffle, fix OSX int64 ambiguity
- direct check of punctuation.
For example,
while (!tok.isPunctuation(token::BEGIN_LIST)) ..
instead of
while (!(tok.isPunctuation() && tok.pToken() == token::BEGIN_LIST)) ..
Using direct comparison (tok != token::BEGIN_LIST) can be fragile
when comparing int values:
int c = readChar(is);
while (tok != c) .. // Danger, uses LABEL comparison!
- direct check of word.
For example,
if (tok.isWord("uniform")) ..
instead of
if (tok.isWord() && tok.wordToken() == "uniform") ..
- make token lineNumber() a setter method
ENH: adjust internal compound method empty() -> moved()
- support named compound tokens
STYLE: setter method for stream indentation
- pointPatches may or may not have a "value" type.
Use the patch value field where possible and the internal field
otherwise. Previously always used the internal field.
- the raw surface writer simply outputs x/y/z and field values.
This additional flag allows recovery of some geometric information.
- optional user-specified output precision
Example,
```
formatOptions
{
raw
{
normal yes;
precision 10;
}
}
```
- centralises existing functions (erfInv, incGamma*, invIncGamma*).
Provides a location for additional functions in the future.
- adjusted existing models to use these functions
(e.g. distributionModels::normal)
- eliminates a potentially invalid code branch.
Since it essentially had the same internals as std::swap anyhow,
make that more evident.
ENH: use std::swap for basic types
- makes it clearer that they do not rely on any special semantics
- since the wrapped cmake calls generally use the regular build
locations, add in MPI information to properly handle changes
in that as well. This makes it easier to build for multiple MPI
instances.
- ensure surface writing is time-step and nFields aware.
This avoids overwriting (ignoring) previous output fields.
- allow sampled surfaces to be used for weight fields as well.
Not sure why this restriction was still there.
- remove old compatibility reading of orientedFields.
Last used in v1612, now removed.
- only use face sampling. For surfaceFieldValue we can only do
something meaningful with face values.
ENH: modify interface methods for surfaceWriter
- replace direct modification of values with setter methods.
Eg,
old: writer.isPointData() = true;
new: writer.isPointData(true);
This makes it possible to add internal hooks to catch state changes.
ENH: allow post-construction change to sampledSurface interpolation
- rename interpolate() method to isPointData() for consistency with
other classes and to indicate that it is a query.
- additional isPointData(bool) setter method to change the expected
representation type after construction
- remove 'interpolate' restriction on isoSurfacePoint which was
previously flagged as an error but within sampledSurfaces can use
sampleScheme cellPoint and obtain representative samples.
Relax this restriction since this particular iso-surface algorithm
is slated for removal in the foreseeable future.
1) Small modification to the tracking logic for detA zero.
2) Adding small vector displacement to locate function to avoid error where
particle is inserted at the cell centre.
- setup writer outside the data loop to ensure that the number of
output fields is correct (VTK format).
- ignore 'interpolate' on sampled surfaces to ensure proper
face sampling, never allow point sampling
BUG: incorrect debug-switch for sampledIsoSurface
- get: uses access operation to get values for each list item
Example,
PtrListOps::get(mesh.boundaryMesh(), nameOp<polyPatch>());
- names: the name() of each list item filtered for matches
- firstMatching: index of first item with a matching name()
- findMatching: indices of items with a matching match name()
Example,
PtrListOps::findMatching(mesh.boundaryMesh(), wordRes( ... ));
STYLE: deprecate transitional getNameOp, getTypeOp
- use nameOp, typeOp (word.H) instead
If the 'writeFields' option is set in surfaceFieldValue, e.g.
surface1
{
type surfaceFieldValue;
libs (fieldFunctionObjects);
operation none;
fields (p);
regionType patch;
name walls;
// Create a surface in VTK format
writeFields yes;
surfaceFormat vtk;
}
... the surface can now be used in runTimePostProcessing, e.g.:
surfaces
{
surfaceFieldValueOutput
{
type functionObjectSurface;
representation surface;
liveObject no;
field p;
colourBy field;
range (0 120000);
functionObject surface1;
}
}
Note: setting 'liveObject' to 'no' to suppress warnings due to the surface
not being retrieved from the object registry (default = 'yes') - this surface
can [currently] only be read from disk.
- modification/continuation of 8d63073b08 and 5c1ec7ecb8 (#595).
Although this protected function is only used internally, the name
`size(label)` is too easily confused with `resize(label)` and
`setSize(label)`. The longer method name eliminates some ambiguity.
Name consistent with PtrListDetail.
- leave size(label) method (for possible compatibility),
but mark as deprecated
- improve sizing consistency for (Istream >> DynamicList)
STYLE: more consistent use of resize vs setSize in DynamicList
- more consistency between DynamicList and DynamicField.
There were some inconsistencies in how construct with a size was
interpreted.
STYLE: more consistent declaration/use of Swap
- this was previously suppressed for ASCII format as being 'clutter',
but without it there is no context for interpreting the type of data
contained in ASCII files: potentially leading to integer overflows
when reading in ParaView etc.
dynamicRefineFvMesh optionally can map fluxes derived from velocities
fields specified in dynamicMeshDict. The surface interpolation was
using old weights. This fix clear the old weights before mapping
the fluxes
The polyMesh construct-from-components will now ignore
the readOpt for the supplied primitives as before.
This again re-allows READ_IF_PRESENT for fv* in
combination with supplied primitives.
This makes the initialisation order of dynamicMesh consistent
with plain ones using the virtual mechanism. It does not
solve the cyclicACMI construction order yet.
2020-12-21 14:54:59 +00:00
20517 changed files with 690177 additions and 3150246 deletions
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.