ENH: support optional dimensionSet reading

This commit is contained in:
Mark Olesen 2021-12-08 10:20:07 +01:00
parent 8c98906780
commit efb187e3f7
8 changed files with 159 additions and 67 deletions

View File

@ -113,7 +113,7 @@ Foam::dimensionSet::dimensionSet(const dimensionSet& ds)
bool Foam::dimensionSet::dimensionless() const
{
for (const scalar& val : exponents_)
for (const scalar val : exponents_)
{
// ie, mag(val) > smallExponent
if ((val > smallExponent) || (val < -smallExponent))
@ -126,13 +126,15 @@ bool Foam::dimensionSet::dimensionless() const
}
const Foam::FixedList<Foam::scalar,7>& Foam::dimensionSet::values() const
const Foam::FixedList<Foam::scalar,7>&
Foam::dimensionSet::values() const noexcept
{
return exponents_;
}
Foam::FixedList<Foam::scalar,7>& Foam::dimensionSet::values()
Foam::FixedList<Foam::scalar,7>&
Foam::dimensionSet::values() noexcept
{
return exponents_;
}

View File

@ -28,10 +28,21 @@ Class
Foam::dimensionSet
Description
Dimension set for the base types.
Dimension set for the base types, which can be used to implement
rigorous dimension checking for algebraic manipulation.
This type may be used to implement rigorous dimension checking
for algebraic manipulation.
The dimensions are specified in the following order
(SI units for reference only):
\table
Property | SI Description | SI unit
MASS | kilogram | \c kg
LENGTH | metre | \c m
TIME | second | \c s
TEMPERATURE | Kelvin | \c K
MOLES | mole | \c mol
CURRENT | Ampere | \c A
LUMINOUS_INTENSITY | Candela | \c cd
\endtable
SourceFiles
dimensionSet.C
@ -55,7 +66,7 @@ namespace Foam
{
// Forward Declarations
class dictionary;
class dimensionSet;
class dimensionSets;
@ -79,13 +90,13 @@ public:
//- Enumeration for the dimension exponents
enum dimensionType
{
MASS, //!< kilogram kg
LENGTH, //!< metre m
TIME, //!< second s
TEMPERATURE, //!< Kelvin K
MOLES, //!< mole mol
CURRENT, //!< Ampere A
LUMINOUS_INTENSITY //!< Candela Cd
MASS, //!< kilogram \c kg
LENGTH, //!< metre \c m
TIME, //!< second \c s
TEMPERATURE, //!< Kelvin \c K
MOLES, //!< mole \c mol
CURRENT, //!< Ampere \c A
LUMINOUS_INTENSITY //!< Candela \c cd
};
@ -130,7 +141,7 @@ private:
// Constructors
tokeniser(Istream& is);
explicit tokeniser(Istream& is);
// Member Functions
@ -154,8 +165,8 @@ private:
};
//- Reset exponents to nearest integer if close to it. Used to
// handle reading with insufficient precision.
//- Reset exponents to nearest integer if close to it.
// Handles reading with insufficient precision.
void round(const scalar tol);
dimensionedScalar parse
@ -165,6 +176,7 @@ private:
const HashTable<dimensionedScalar>&
) const;
public:
// Declare name of the class and its debug switch
@ -212,8 +224,22 @@ public:
//- Copy construct
dimensionSet(const dimensionSet& ds);
//- Construct from dictionary entry - usually "dimensions".
dimensionSet(const dictionary& dict, const word& entryName);
//- Construct from dictionary entry (usually "dimensions")
// Dimensionless if non-mandatory and not found.
dimensionSet
(
const word& entryName, //!< Lookup key. LITERAL (not REGEX)
const dictionary& dict,
const bool mandatory = true
);
//- Construct from dictionary entry (usually "dimensions")
dimensionSet
(
const dictionary& dict,
const word& entryName, //!< Lookup key. LITERAL (not REGEX)
const bool mandatory = true
);
//- Construct and return a clone
autoPtr<dimensionSet> clone() const
@ -230,13 +256,13 @@ public:
//- Return true if it is dimensionless
bool dimensionless() const;
//- Return const access to the exponents as a list
const FixedList<scalar,7>& values() const;
//- Const access to the exponents as a list
const FixedList<scalar,7>& values() const noexcept;
//- Return non-const access to the exponents as a list
FixedList<scalar,7>& values();
//- Non-const access to the exponents as a list
FixedList<scalar,7>& values() noexcept;
//- Reset exponents to be dimensionless
//- Clear exponents - resets to be dimensionless
void clear();
//- Copy assign the exponents from the dimensionSet
@ -245,6 +271,18 @@ public:
// IO
//- Update the dimensions from dictionary entry.
//- FatalIOError if it is found and the number of tokens is incorrect,
//- or it is mandatory and not found.
//
// \return true if the entry was found.
bool readEntry
(
const word& entryName, //!< Lookup key. LITERAL (not REGEX)
const dictionary& dict, //!< The dictionary
const bool mandatory = true //!< The entry is mandatory
);
//- Read using provided units. Used only in initial parsing
Istream& read
(
@ -303,6 +341,7 @@ public:
bool operator/=(const dimensionSet&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// IOstream Operators

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,21 +26,37 @@ License
\*---------------------------------------------------------------------------*/
#include "dictionary.H"
#include "dimensionSet.H"
#include "IOstreams.H"
#include "dimensionedScalar.H"
#include "IOstreams.H"
#include <limits>
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dimensionSet::dimensionSet(const dictionary& dict, const word& entryName)
Foam::dimensionSet::dimensionSet
(
const word& entryName,
const dictionary& dict,
const bool mandatory
)
:
exponents_(Zero)
{
const entry& e = dict.lookupEntry(entryName, keyType::LITERAL);
ITstream& is = e.stream();
this->readEntry(entryName, dict, mandatory);
}
is >> *this;
e.checkITstream(is);
Foam::dimensionSet::dimensionSet
(
const dictionary& dict,
const word& entryName,
const bool mandatory
)
:
exponents_(Zero)
{
this->readEntry(entryName, dict, mandatory);
}
@ -122,26 +138,24 @@ bool Foam::dimensionSet::tokeniser::valid(char c)
Foam::label Foam::dimensionSet::tokeniser::priority(const token& t)
{
if (!t.isPunctuation())
if (t.isPunctuation())
{
return 0;
}
else if
(
t.pToken() == token::MULTIPLY
|| t.pToken() == token::DIVIDE
)
{
return 2;
}
else if (t.pToken() == '^')
{
return 3;
}
else
{
return 0;
if
(
t.pToken() == token::MULTIPLY
|| t.pToken() == token::DIVIDE
)
{
return 2;
}
else if (t.pToken() == '^')
{
return 3;
}
}
// Default priority
return 0;
}
@ -230,6 +244,8 @@ void Foam::dimensionSet::tokeniser::putBack(const token& t)
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::dimensionSet::round(const scalar tol)
{
scalar integralPart;
@ -260,7 +276,7 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
const HashTable<dimensionedScalar>& readSet
) const
{
dimensionedScalar ds("", dimless, 1.0);
dimensionedScalar ds("", dimless, 1);
// Get initial token
token nextToken(tis.nextToken());
@ -359,12 +375,12 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
{
if (nextPrior > lastPrior)
{
dimensionedScalar exp(parse(nextPrior, tis, readSet));
dimensionedScalar expon(parse(nextPrior, tis, readSet));
ds.dimensions().reset(pow(ds.dimensions(), exp.value()));
ds.dimensions().reset(pow(ds.dimensions(), expon.value()));
// Round to nearest integer if close to it
ds.dimensions().round(10*smallExponent);
ds.value() = Foam::pow(ds.value(), exp.value());
ds.value() = Foam::pow(ds.value(), expon.value());
}
else
{
@ -409,6 +425,38 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
}
bool Foam::dimensionSet::readEntry
(
const word& entryName,
const dictionary& dict,
const bool mandatory
)
{
const entry* eptr = dict.findEntry(entryName, keyType::LITERAL);
if (eptr)
{
const entry& e = *eptr;
ITstream& is = e.stream();
is >> *this;
e.checkITstream(is);
return true;
}
else if (mandatory)
{
FatalIOErrorInFunction(dict)
<< "Entry '" << entryName << "' not found in dictionary "
<< dict.relativeName() << nl
<< exit(FatalIOError);
}
return false;
}
Foam::Istream& Foam::dimensionSet::read
(
Istream& is,
@ -533,7 +581,7 @@ Foam::Istream& Foam::dimensionSet::read
// Parse unit
dimensionSet symbolSet(dimless);
dimensionSet symbolSet; // dimless
const auto index = symbolPow.find('^');
if (index != std::string::npos)
@ -542,7 +590,7 @@ Foam::Istream& Foam::dimensionSet::read
const scalar exponent = readScalar(symbolPow.substr(index+1));
dimensionedScalar s;
s.read(readSet.lookup(symbol), readSet);
s.read(readSet.lookup(symbol, keyType::LITERAL), readSet);
symbolSet.reset(pow(s.dimensions(), exponent));
@ -553,7 +601,7 @@ Foam::Istream& Foam::dimensionSet::read
else
{
dimensionedScalar s;
s.read(readSet.lookup(symbolPow), readSet);
s.read(readSet.lookup(symbolPow, keyType::LITERAL), readSet);
symbolSet.reset(s.dimensions());
multiplier *= s.value();

View File

@ -186,7 +186,7 @@ const dimensionSets& writeUnitSet()
}
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0);
const dimensionSet dimless;
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0);
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0);

View File

@ -34,7 +34,6 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef dimensionSets_H
#define dimensionSets_H
@ -85,7 +84,7 @@ extern const dimensionSet dimDynamicViscosity;
//- Construction of unit sets
class dimensionSets
{
// Private data
// Private Data
//- Set of dimensions
PtrList<dimensionedScalar> units_;
@ -111,16 +110,17 @@ public:
const wordList& unitNames
);
// Member Functions
//- Return the units
const PtrList<dimensionedScalar>& units() const
const PtrList<dimensionedScalar>& units() const noexcept
{
return units_;
}
//- Is there a valid inverse of the selected unit
bool valid() const
bool valid() const noexcept
{
return valid_;
}

View File

@ -39,8 +39,7 @@ namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
class dimensioned;
template<class Type> class dimensioned;
typedef dimensioned<scalar> dimensionedScalar;

View File

@ -38,7 +38,7 @@ void Foam::DimensionedField<Type, GeoMesh>::readField
const word& fieldDictEntry
)
{
dimensions_.reset(dimensionSet(fieldDict, "dimensions"));
dimensions_.readEntry("dimensions", fieldDict);
// Note: oriented state may have already been set on construction
// - if so - do not reset by re-reading

View File

@ -85,8 +85,12 @@ template<class Type>
bool Foam::UniformDimensionedField<Type>::readData(Istream& is)
{
dictionary dict(is);
scalar multiplier;
this->dimensions().read(dict.lookup("dimensions"), multiplier);
scalar multiplier(1);
this->dimensions().read
(
dict.lookup("dimensions", keyType::LITERAL),
multiplier
);
dict.readEntry("value", this->value());
this->value() *= multiplier;
@ -98,7 +102,7 @@ bool Foam::UniformDimensionedField<Type>::readData(Istream& is)
template<class Type>
bool Foam::UniformDimensionedField<Type>::writeData(Ostream& os) const
{
scalar multiplier;
scalar multiplier(1);
os.writeKeyword("dimensions");
this->dimensions().write(os, multiplier) << token::END_STATEMENT << nl;
os.writeEntry("value", this->value()/multiplier) << nl;