- start/end values were underrepresented due to rounding.
Now extend the range to include -0.5 and +0.5 beyond the usual
range to ensure the same number density.
- improves backward compatibility and more naming consistency.
Retain setMany(iter1, iter2) to avoid ambiguity with the
PackedList::set(index, value) method.
- disallow insert() of raw pointers, since a failed insertion
(ie, entry already existed) results in an unmanaged pointer.
Either insert using an autoPtr, or set() with raw pointers or autoPtr.
- IOobjectList::add() now takes an autoPtr instead of an object reference
- IOobjectList::remove() now returns an autoPtr instead of a raw pointer
- controlled by the the 'printExecutionFormat' InfoSwitch in
etc/controlDict
// Style for "ExecutionTime = " output
// - 0 = seconds (with trailing 's')
// - 1 = day-hh:mm:ss
ExecutionTime = 112135.2 s ClockTime = 113017 s
ExecutionTime = 1-07:08:55.20 ClockTime = 1-07:23:37
- Callable via the new Time::printExecutionTime() method,
which also helps to reduce clutter in the applications.
Eg,
runTime.printExecutionTime(Info);
vs
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
--
ENH: return elapsedClockTime() and clockTimeIncrement as double
- previously returned as time_t, which is less portable.
For example, with some HashTable or Map container of models
{ model0 => 1, model1 => 4, model2 => 5, model3 => 12, model4 => 15, }
specify the remapping
Map<label> mapper({{1, 3}, {2, 6}, {3, 12}, {5, 8}});
inplaceMapValue(mapper, models) then yields
{ model0 => 3, model1 => 4, model2 => 8, model3 => 12, model4 => 15, }
--
ENH: extend bitSet::count() to optionally count unset bits instead.
--
ENH: BitOps compatibility methods for boolList.
- These ease coding that uses a boolList instead of bitSet and use
short-circuit logic when possible.
Eg, when 'bitset' and 'bools' contain the same information
bitset.count() <-> BitOps::count(bools)
bitset.all() <-> BitOps::all(bools)
bitset.any() <-> BitOps::any(bools)
bitset.none() <-> BitOps::none(bools)
These methods can then be used directly in parameters or in logic.
Eg,
returnReduce(bitset.any(), orOp<bool>());
returnReduce(BitOps::any(bools), orOp<bool>());
if (BitOps::any(bools)) ...
- flags the following type of problems:
* mismatches:
keyword mismatch ( set of { brackets ) in the } entry;
* underflow (too many closing brackets:
keyword too many ( set of ) brackets ) in ) entry;
- a missing semi-colon
dict
{
keyword entry with missing semi-colon
}
will be flagged as 'underflow', since it parses through the '}' but
did not open with it.
Max monitoring depth is 60 levels of nesting, to avoid incurring any
memory allocation.
- In addition to the traditional Flex-based parser, added a Ragel-based
parser and a handwritten one.
Some representative timings for reading 5874387 points (1958129 tris):
Flex Ragel Manual
5.2s 4.8s 6.7s total reading time
3.8s 3.4s 5.3s without point merging
- the expansions were previously required as slash to follow, but
now either are possible.
"<case>", "<case>/" both yield the same as "$FOAM_CASE" and
will not have a trailing slash in the result. The expansion of
"$FOAM_CASE/" will however have a trailing slash.
- adjust additional files using these expansions
Support the following expansions when they occur at the start of a
string:
Short-form Equivalent
========= ===========
<etc>/ ~OpenFOAM/ (as per foamEtcFile)
<case>/ $FOAM_CASE/
<constant>/ $FOAM_CASE/constant/
<system>/ $FOAM_CASE/system/
These can be used in fileName expansions to improve clarity and reduce
some typing
"<constant>/reactions" vs "$FOAM_CASE/constant/reactions"
- this removes an OS-specific dependency (eg, drand48_r is not POSIX)
and allows easier use of other random number generators.
The Rand48 generator has identical behaviour and period as the
lrand48() library routine, but holds its own seed and state
(which makes it re-entrant) and can be combined with other
random distributions.
However, when using the modified form to obtain scalar values
they will not be identical to what drand48() yields.
This is because drand48() uses the raw 48-bit values to directly
set the mantissa of an IEEE double where as the newer distribution
normalizes based on the 32-bit value.
STYLE: simplify code in Random::shuffle and use Swap
- when constructing dimensioned fields that are to be zero-initialized,
it is preferrable to use a form such as
dimensionedScalar(dims, Zero)
dimensionedVector(dims, Zero)
rather than
dimensionedScalar("0", dims, 0)
dimensionedVector("zero", dims, vector::zero)
This reduces clutter and also avoids any suggestion that the name of
the dimensioned quantity has any influence on the field's name.
An even shorter version is possible. Eg,
dimensionedScalar(dims)
but reduces the clarity of meaning.
- NB: UniformDimensionedField is an exception to these style changes
since it does use the name of the dimensioned type (instead of the
regIOobject).
- improve internal handling to permit deriving resizable containers
(eg, PtrDynList).
- include '->' iterator dereferencing
- Only append/set non-const autoPtr references. This doesn't break
existing code, but makes the intention more transparent.
- also ensure fewer side-effects from inplaceReorder
- provide ListOps::reorder especially for PackedList and PackedBoolList
since they behave differently from regular lists.
- eliminate iterators from PackedList since they were unused, had
lower performance than direct access and added unneeded complexity.
- eliminate auto-vivify for the PackedList '[] operator.
The set() method provides any required auto-vivification and
removing this ability from the '[]' operator allows for a lower
when accessing the values. Replaced the previous cascade of iterators
with simpler reference class.
PackedBoolList:
- (temporarily) eliminate logic and addition operators since
these contained partially unclear semantics.
- the new test() method tests the value of a single bit position and
returns a bool without any ambiguity caused by the return type
(like the get() method), nor the const/non-const access (like
operator[] has). The name corresponds to what std::bitset uses.
- more consistent use of PackedBoolList test(), set(), unset() methods
for fewer operation and clearer code. Eg,
if (list.test(index)) ... | if (list[index]) ...
if (!list.test(index)) ... | if (list[index] == 0u) ...
list.set(index); | list[index] = 1u;
list.unset(index); | list[index] = 0u;
- deleted the operator=(const labelUList&) and replaced with a setMany()
method for more clarity about the intended operation and to avoid any
potential inadvertent behaviour.
- clockValue class for managing the clock values only, with a null
constructor that does not query the system clock (can defer to later).
Can also be used directly for +/- operations.
- refactor clockTime, cpuTime, clock to reduce storage.
- The bitSet class replaces the old PackedBoolList class.
The redesign provides better block-wise access and reduced method
calls. This helps both in cases where the bitSet may be relatively
sparse, and in cases where advantage of contiguous operations can be
made. This makes it easier to work with a bitSet as top-level object.
In addition to the previously available count() method to determine
if a bitSet is being used, now have simpler queries:
- all() - true if all bits in the addressable range are empty
- any() - true if any bits are set at all.
- none() - true if no bits are set.
These are faster than count() and allow early termination.
The new test() method tests the value of a single bit position and
returns a bool without any ambiguity caused by the return type
(like the get() method), nor the const/non-const access (like
operator[] has). The name corresponds to what std::bitset uses.
The new find_first(), find_last(), find_next() methods provide a faster
means of searching for bits that are set.
This can be especially useful when using a bitSet to control an
conditional:
OLD (with macro):
forAll(selected, celli)
{
if (selected[celli])
{
sumVol += mesh_.cellVolumes()[celli];
}
}
NEW (with const_iterator):
for (const label celli : selected)
{
sumVol += mesh_.cellVolumes()[celli];
}
or manually
for
(
label celli = selected.find_first();
celli != -1;
celli = selected.find_next()
)
{
sumVol += mesh_.cellVolumes()[celli];
}
- When marking up contiguous parts of a bitset, an interval can be
represented more efficiently as a labelRange of start/size.
For example,
OLD:
if (isA<processorPolyPatch>(pp))
{
forAll(pp, i)
{
ignoreFaces.set(i);
}
}
NEW:
if (isA<processorPolyPatch>(pp))
{
ignoreFaces.set(pp.range());
}
This class is largely a pre-C++11 holdover. It is now possible to
simply use move construct/assignment directly.
In a few rare cases (eg, polyMesh::resetPrimitives) it has been
replaced by an autoPtr.
Improve alignment of its behaviour with std::shared_ptr
- element_type typedef
- swap, reset methods
* additional reference access methods:
cref()
returns a const reference, synonymous with operator().
This provides a more verbose alternative to using the '()' operator
when that is desired.
Mnemonic: a const form of 'ref()'
constCast()
returns a non-const reference, regardless if the underlying object
itself is a managed pointer or a const object.
This is similar to ref(), but more permissive.
Mnemonic: const_cast<>
Using the constCast() method greatly reduces the amount of typing
and reading. And since the data type is already defined via the tmp
template parameter, the type deduction is automatically known.
Previously,
const tmp<volScalarField>& tfld;
const_cast<volScalarField&>(tfld()).rename("name");
volScalarField& fld = const_cast<volScalarField&>(tfld());
Now,
tfld.constCast().rename("name");
auto& fld = tfld.constCast();
--
BUG: attempts to move tmp value that may still be shared.
- old code simply checked isTmp() to decide if the contents could be
transfered. However, this means that the content of a shared tmp
would be removed, leaving other instances without content.
* movable() method checks that for a non-null temporary that is
unique (not shared).
Improve alignment of its behaviour with std::unique_ptr
- element_type typedef
- release() method - identical to ptr() method
- get() method to get the pointer without checking and without releasing it.
- operator*() for dereferencing
Method name changes
- renamed rawPtr() to get()
- renamed rawRef() to ref(), removed unused const version.
Removed methods/operators
- assignment from a raw pointer was deleted (was rarely used).
Can be convenient, but uncontrolled and potentially unsafe.
Do allow assignment from a literal nullptr though, since this
can never leak (and also corresponds to the unique_ptr API).
Additional methods
- clone() method: forwards to the clone() method of the underlying
data object with argument forwarding.
- reset(autoPtr&&) as an alternative to operator=(autoPtr&&)
STYLE: avoid implicit conversion from autoPtr to object type in many places
- existing implementation has the following:
operator const T&() const { return operator*(); }
which means that the following code works:
autoPtr<mapPolyMesh> map = ...;
updateMesh(*map); // OK: explicit dereferencing
updateMesh(map()); // OK: explicit dereferencing
updateMesh(map); // OK: implicit dereferencing
for clarity it may preferable to avoid the implicit dereferencing
- prefer operator* to operator() when deferenced a return value
so it is clearer that a pointer is involve and not a function call
etc Eg, return *meshPtr_; vs. return meshPtr_();
- relocated HashSetPlusEqOp and HashTablePlusEqOp to
HashSetOps::plusEqOp and HashTableOps::plusEqOp, respectively
- additional functions for converting between a labelHashSet
and a PackedBoolList or List<bool>:
From lists selections to labelHashSet indices:
HashSetOps::used(const PackedBoolList&);
HashSetOps::used(const UList<bool>&);
From labelHashSet to list forms:
PackedBoolList bitset(const labelHashSet&);
List<bool> bools(const labelHashSet&);
- relocated ListAppendEqOp and ListUniqueEqOp to ListOps::appendEqOp
and ListOps::UniqueEqOp, respectively for better code isolation and
documentation of purpose.
- relocated setValues to ListOps::setValue() with many more
alternative selectors possible
- relocated createWithValues to ListOps::createWithValue
for better code isolation. The default initialization value is itself
now a default parameter, which allow for less typing.
Negative indices in the locations to set are now silently ignored,
which makes it possible to use an oldToNew mapping that includes
negative indices.
- additional ListOps::createWithValue taking a single position to set,
available both in copy assign and move assign versions.
Since a negative index is ignored, it is possible to combine with
the output of List::find() etc.
STYLE: changes for PackedList
- code simplication in the PackedList iterators, including dropping
the unused operator() on iterators, which is not available in plain
list versions either.
- improved sizing for PackedBoolList creation from a labelUList.
ENH: additional List constructors, for handling single element list.
- can assist in reducing constructor ambiguity, but can also helps
memory optimization when creating a single element list.
For example,
labelListList labels(one(), identity(mesh.nFaces()));
- This class is largely a pre-C++11 holdover, prior to having movable
references.
- align internals with autoPtr instead of always unconditionally
allocating memory. The valid() method can be used to check for a null
pointer.
- Consolidate into a single file, in anticipation of future removal.
- rvalue() is a (transitional) means of converting Xfer content to a
reference for move construct, move assign semantics.
- valid() method for consistency with autoPtr and tmp classes
- simplify structure, removed unused constuctors.
- transfer from base objects via '=' assignment removed as being too
non-transparent
- add New factory method with perfect forwarding.
- the transfer method was previously a copy
- use std::reverse_iterator adaptors in FixedList
This greatly reduces the amount of code and now avoids the array-bounds
warning for FixedList::rend()
- use pointer arithmetic instead of dereferencing the internal array
- without these will use the normal move construct + move assign.
This is similarly efficient, but avoids the inadvertently having the
incorrect Swap being used for derived classes.
STYLE: remove unused xfer methods for HashTable, HashSet
- unneeded since move construct and move assignment are possible
- can stop producing content when the target number of entries has
been reached.
- change return type to labelList instead an Xfer container.
This allows return-value-optimization and avoids a surrounding
allocation. This potentially breaks existing code.
- make PackedList and PackedBoolList moveable. Drop xfer wrappers.