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
- 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
- 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).
- 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)
- 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!
- 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
- 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.
- 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
- 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.
- 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.
- 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.
- 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.
- 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", ...);
}
```
- 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.
- 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.
- 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.
- 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)