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 bool Foam::dimensionSet::dimensionless() const
{ {
for (const scalar& val : exponents_) for (const scalar val : exponents_)
{ {
// ie, mag(val) > smallExponent // ie, mag(val) > smallExponent
if ((val > smallExponent) || (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_; return exponents_;
} }
Foam::FixedList<Foam::scalar,7>& Foam::dimensionSet::values() Foam::FixedList<Foam::scalar,7>&
Foam::dimensionSet::values() noexcept
{ {
return exponents_; return exponents_;
} }

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,21 +26,37 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "dictionary.H"
#include "dimensionSet.H" #include "dimensionSet.H"
#include "IOstreams.H"
#include "dimensionedScalar.H" #include "dimensionedScalar.H"
#include "IOstreams.H"
#include <limits> #include <limits>
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * 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); this->readEntry(entryName, dict, mandatory);
ITstream& is = e.stream(); }
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) Foam::label Foam::dimensionSet::tokeniser::priority(const token& t)
{ {
if (!t.isPunctuation()) if (t.isPunctuation())
{ {
return 0; if
} (
else if t.pToken() == token::MULTIPLY
( || t.pToken() == token::DIVIDE
t.pToken() == token::MULTIPLY )
|| t.pToken() == token::DIVIDE {
) return 2;
{ }
return 2; else if (t.pToken() == '^')
} {
else if (t.pToken() == '^') return 3;
{ }
return 3;
}
else
{
return 0;
} }
// 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) void Foam::dimensionSet::round(const scalar tol)
{ {
scalar integralPart; scalar integralPart;
@ -260,7 +276,7 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
const HashTable<dimensionedScalar>& readSet const HashTable<dimensionedScalar>& readSet
) const ) const
{ {
dimensionedScalar ds("", dimless, 1.0); dimensionedScalar ds("", dimless, 1);
// Get initial token // Get initial token
token nextToken(tis.nextToken()); token nextToken(tis.nextToken());
@ -359,12 +375,12 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
{ {
if (nextPrior > lastPrior) 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 // Round to nearest integer if close to it
ds.dimensions().round(10*smallExponent); ds.dimensions().round(10*smallExponent);
ds.value() = Foam::pow(ds.value(), exp.value()); ds.value() = Foam::pow(ds.value(), expon.value());
} }
else 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 Foam::Istream& Foam::dimensionSet::read
( (
Istream& is, Istream& is,
@ -533,7 +581,7 @@ Foam::Istream& Foam::dimensionSet::read
// Parse unit // Parse unit
dimensionSet symbolSet(dimless); dimensionSet symbolSet; // dimless
const auto index = symbolPow.find('^'); const auto index = symbolPow.find('^');
if (index != std::string::npos) if (index != std::string::npos)
@ -542,7 +590,7 @@ Foam::Istream& Foam::dimensionSet::read
const scalar exponent = readScalar(symbolPow.substr(index+1)); const scalar exponent = readScalar(symbolPow.substr(index+1));
dimensionedScalar s; dimensionedScalar s;
s.read(readSet.lookup(symbol), readSet); s.read(readSet.lookup(symbol, keyType::LITERAL), readSet);
symbolSet.reset(pow(s.dimensions(), exponent)); symbolSet.reset(pow(s.dimensions(), exponent));
@ -553,7 +601,7 @@ Foam::Istream& Foam::dimensionSet::read
else else
{ {
dimensionedScalar s; dimensionedScalar s;
s.read(readSet.lookup(symbolPow), readSet); s.read(readSet.lookup(symbolPow, keyType::LITERAL), readSet);
symbolSet.reset(s.dimensions()); symbolSet.reset(s.dimensions());
multiplier *= s.value(); 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 dimMass(1, 0, 0, 0, 0, 0, 0);
const dimensionSet dimLength(0, 1, 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 #ifndef dimensionSets_H
#define dimensionSets_H #define dimensionSets_H
@ -85,7 +84,7 @@ extern const dimensionSet dimDynamicViscosity;
//- Construction of unit sets //- Construction of unit sets
class dimensionSets class dimensionSets
{ {
// Private data // Private Data
//- Set of dimensions //- Set of dimensions
PtrList<dimensionedScalar> units_; PtrList<dimensionedScalar> units_;
@ -111,16 +110,17 @@ public:
const wordList& unitNames const wordList& unitNames
); );
// Member Functions // Member Functions
//- Return the units //- Return the units
const PtrList<dimensionedScalar>& units() const const PtrList<dimensionedScalar>& units() const noexcept
{ {
return units_; return units_;
} }
//- Is there a valid inverse of the selected unit //- Is there a valid inverse of the selected unit
bool valid() const bool valid() const noexcept
{ {
return valid_; return valid_;
} }

View File

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

View File

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

View File

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