DimensionedFunction1: Permit setting argument-dimensions of inline functions

Both argument and value dimensions can be set for inline-constructable
function1-s. For example, this inline table function:

    massFlowRate table [CAD] [g/s]
    (
        (0 0.46)
        (0.17 1.9)
        (0.31 4.8)
    );

Is equivalent to this dictionary specification:

    massFlowRate
    {
        type    table;
        xDimensions [CAD];
        dimensions [g/s];
        values
        (
             (0 0.46)
             (0.17 1.9)
             (0.31 4.8)
        );
    }

In the inline form, the argument/x-dimensions come first, and the value
dimensions second. If there only one dimension set provided, then this
is assumed to be the value dimensions.
This commit is contained in:
Will Bainbridge
2023-08-09 11:46:04 +01:00
parent 9a7b9e9229
commit b790a69507
2 changed files with 109 additions and 65 deletions

View File

@ -203,11 +203,12 @@ DimensionSets
// Scaled units. Supported in dimensionedType and
// UniformDimensionedField. Not supported in DimensionedField or
// GeometricField.
cm [m] 1e-2;
g [kg] 1e-3;
mm [m] 1e-3;
cm [m] 1e-2;
km [m] 1e3;
ms [s] 1e-3;
us [s] 1e-6;
ms [s] 1e-3;
}
USCSCoeffs

View File

@ -25,6 +25,94 @@ License
#include "DimensionedFunction1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
inline dimensionedScalar readUnits(Istream& is)
{
scalar multiplier;
dimensionSet d(dimless);
d.read(is, multiplier);
return dimensionedScalar(d, multiplier);
}
inline void setUnits
(
Istream& is,
const word& prefix,
const dimensionedScalar& from,
dimensionedScalar& to
)
{
to.name() =
prefix + (prefix.empty() ? 'u' : 'U') + "nits";
if (from.dimensions() != to.dimensions())
{
FatalIOErrorInFunction(is)
<< "The " << prefix << (prefix.empty() ? "" : "-")
<< "dimensions " << from.dimensions()
<< " provided do not match the required "
<< "dimensions " << to.dimensions()
<< exit(FatalIOError);
}
to.value() = from.value();
}
inline void readAndSetUnits
(
Istream& is,
const word& prefix,
dimensionedScalar& units
)
{
setUnits(is, prefix, readUnits(is), units);
}
inline void lookupUnitsIfPresent
(
const dictionary& dict,
const word& prefix,
dimensionedScalar& units
)
{
const word unitsKey =
prefix + (prefix.empty() ? 'u' : 'U') + "nits";
const word dimsKey =
prefix + (prefix.empty() ? 'd' : 'D') + "imensions";
const bool haveUnits = dict.found(unitsKey);
const bool haveDims = dict.found(dimsKey);
if (haveUnits && haveDims)
{
FatalIOErrorInFunction(dict)
<< "Both " << unitsKey << " and " << dimsKey
<< " are specified. Only one is permitted."
<< exit(FatalError);
}
if (haveUnits)
{
units = dimensionedScalar(unitsKey, units.dimensions(), dict);
}
if (haveDims)
{
readAndSetUnits(dict.lookup(dimsKey), prefix, units);
}
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
@ -34,65 +122,6 @@ void Foam::Function1s::Dimensioned<Type>::read
const dictionary& dict
)
{
// Read units from the given stream
auto readUnits = []
(
Istream& is,
const word& prefix,
dimensionedScalar& units
)
{
units.name() =
prefix + (prefix.empty() ? 'u' : 'U') + "nits";
dimensionSet d(dimless);
d.read(is, units.value());
if (d != units.dimensions())
{
FatalIOErrorInFunction(is)
<< "The " << prefix << (prefix.empty() ? "" : "-")
<< "dimensions " << d << " provided do not match the required "
<< "dimensions " << units.dimensions()
<< exit(FatalIOError);
}
};
// Read units if present in the given dictionary
auto lookupUnitsIfPresent = [&readUnits]
(
const dictionary& dict,
const word& prefix,
dimensionedScalar& units
)
{
const word unitsKey =
prefix + (prefix.empty() ? 'u' : 'U') + "nits";
const word dimsKey =
prefix + (prefix.empty() ? 'd' : 'D') + "imensions";
const bool haveUnits = dict.found(unitsKey);
const bool haveDims = dict.found(dimsKey);
if (haveUnits && haveDims)
{
FatalIOErrorInFunction(dict)
<< "Both " << unitsKey << " and " << dimsKey
<< " are specified. Only one is permitted."
<< exit(FatalError);
}
if (haveUnits)
{
units = dimensionedScalar(unitsKey, units.dimensions(), dict);
}
if (haveDims)
{
readUnits(dict.lookup(dimsKey), prefix, units);
}
};
// If the function is a dictionary (preferred) then read straightforwardly
if (dict.isDict(name))
{
@ -121,16 +150,30 @@ void Foam::Function1s::Dimensioned<Type>::read
// construct the function from the stream
if (!firstToken.isWord() || !is.eof())
{
// Peek at the next token
PtrList<dimensionedScalar> units;
// Peek at the next token and read the units, if provided
token nextToken(is);
is.putBack(nextToken);
// Read dimensions if they are provided
if (nextToken == token::BEGIN_SQR)
{
readUnits(is, "", units_);
units.append(new dimensionedScalar(readUnits(is)));
// And again ...
token nextToken(is);
is.putBack(nextToken);
if (nextToken == token::BEGIN_SQR)
{
units.append(new dimensionedScalar(readUnits(is)));
}
}
// Set the units. If there is just one, then just take this to be the
// value units. If two, then the first is the argument units and the
// second is the value units.
if (units.size() == 2) setUnits(is, "x", units.first(), xUnits_);
if (units.size() >= 1) setUnits(is, "", units.last(), units_);
// Construct from a stream
value_.reset(Function1<Type>::New(name, Function1Type, is).ptr());