diff --git a/etc/controlDict b/etc/controlDict index c4cf09edb2..d5c1fdb755 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -981,15 +981,29 @@ DimensionSets Cd Cd [ 0 0 0 0 0 0 1 ] 1.0; // Derived units - Pa Pa [ kg^1 m^-2 ] 1.0; + Hz Hz [ s^-1 ] 1.0; + N N [ kg m s^-2 ] 1.0; + Pa Pa [ N m^-2 ] 1.0; + J J [ N m ] 1.0; + W W [ J s^-1 ] 1.0; - // Scaled units - mm mm [ kg^1 m^-2 ] 1e-3; + // Some non-symbolic ones + area area [m^2] 1.0; + volume volume [m^3] 1.0; + density density [ kg m^-3 ] 1.0; + acceleration acceleration [ m s^-2 ] 1.0; + kinematicPressure kinematicPressure [ Pa density^-1 ] 1.0; + // Scaled units. Only allowed in dymensionedType (dimensionedScalar, + // dimensionedVector etc.) and UniformDimensionedField, not + // in DimensionedField or GeometricField + cm cm [ m ] 1e-2; + mm mm [ m ] 1e-3; + km km [ m ] 1e3; // Set of units used for printing. Can be any basic or derived // but not scaled (only supported for dimensionedScalar, etc) - writeUnits (kg m s K mol A Cd); + //writeUnits (kg m s K mol A Cd); } } diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.C b/src/OpenFOAM/dimensionSet/dimensionSet.C index 1b900f52d5..c0da41236e 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSet.C +++ b/src/OpenFOAM/dimensionSet/dimensionSet.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -105,83 +105,6 @@ void Foam::dimensionSet::reset(const dimensionSet& ds) } -Foam::string Foam::dimensionSet::asText() const -{ - OStringStream buf; - - bool Dimensionless = true; - - for (int Dimension=0; Dimension < dimensionSet::nDimensions-1; ++Dimension) - { - const scalar& expt = exponents_[Dimension]; - - if (expt < smallExponent && expt > -smallExponent) - { - continue; - } - - if (Dimensionless) - { - Dimensionless = false; - } - else - { - buf << ' '; - } - - // note: currently only handle SI - switch (Dimension) - { - case MASS: - buf << "kg"; - break; - - case LENGTH: - buf << "m"; - break; - - case TIME: - buf << "s"; - break; - - case TEMPERATURE: - buf << "K"; - break; - - case MOLES: - buf << "mol"; - break; - - case CURRENT: - buf << "A"; - break; - - case LUMINOUS_INTENSITY: - buf << "Cd"; - break; - - default: - buf << "??"; // this shouldn't be - flag as being weird - break; - } - - if (expt != 1) - { - buf << '^' << expt; - } - } - - if (Dimensionless) - { - return "none"; - } - else - { - return buf.str(); - } -} - - // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // Foam::scalar Foam::dimensionSet::operator[](const dimensionType type) const @@ -196,6 +119,18 @@ Foam::scalar& Foam::dimensionSet::operator[](const dimensionType type) } +Foam::scalar Foam::dimensionSet::operator[](const label type) const +{ + return exponents_[type]; +} + + +Foam::scalar& Foam::dimensionSet::operator[](const label type) +{ + return exponents_[type]; +} + + bool Foam::dimensionSet::operator==(const dimensionSet& ds) const { for (int Dimension=0; Dimension < nDimensions; ++Dimension) diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.H b/src/OpenFOAM/dimensionSet/dimensionSet.H index 5bdb41c332..ca4c3ed2d1 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSet.H +++ b/src/OpenFOAM/dimensionSet/dimensionSet.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -40,10 +40,12 @@ SourceFiles #ifndef dimensionSet_H #define dimensionSet_H -#include "scalar.H" #include "bool.H" #include "dimensionedScalarFwd.H" #include "className.H" +#include "scalarField.H" +#include "PtrList.H" +#include "HashTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -53,6 +55,7 @@ namespace Foam // Forward declaration of friend functions and operators class dimensionSet; +class dimensionSets; // Friend functions @@ -140,6 +143,64 @@ public: private: + // Private classes + + class tokeniser + { + // Private data + + Istream& is_; + + List tokens_; + + label start_; + + label size_; + + // Private Member Functions + + void push(const token&); + + token pop(); + + void unpop(const token&); + + public: + + // Constructors + + tokeniser(Istream&); + + // Member Functions + + Istream& stream() + { + return is_; + } + + bool hasToken() const; + + token nextToken(); + + void putBack(const token&); + + void splitWord(const word&); + + static bool valid(char c); + + static label priority(const token& t); + + }; + + + dimensionedScalar parse + ( + const label lastPrior, + tokeniser& tis, + const HashTable& + ) const; + + // private data // dimensionSet stored as an array of dimension exponents @@ -189,14 +250,56 @@ public: void reset(const dimensionSet&); - //- Return a text representation for added readability - string asText() const; + + // I/O + + //- Read using provided units. Used only in initial parsing + Istream& read + ( + Istream& is, + scalar& multiplier, + const dictionary& + ); + + //- Read using provided units + Istream& read + ( + Istream& is, + scalar& multiplier, + const HashTable& + ); + + //- Read using system units + Istream& read + ( + Istream& is, + scalar& multiplier + ); + + //- Write using provided units + Ostream& write + ( + Ostream& os, + scalar& multiplier, + const dimensionSets& + ) const; + + //- Write using system units + Ostream& write + ( + Ostream& os, + scalar& multiplier + ) const; // Member operators scalar operator[](const dimensionType) const; scalar& operator[](const dimensionType); + + scalar operator[](const label) const; + scalar& operator[](const label); + bool operator==(const dimensionSet&) const; bool operator!=(const dimensionSet&) const; diff --git a/src/OpenFOAM/dimensionSet/dimensionSetIO.C b/src/OpenFOAM/dimensionSet/dimensionSetIO.C index d27e9f1b99..0281005ce2 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSetIO.C +++ b/src/OpenFOAM/dimensionSet/dimensionSetIO.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -25,6 +25,7 @@ License #include "dimensionSet.H" #include "IOstreams.H" +#include "dimensionedScalar.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -34,46 +35,670 @@ Foam::dimensionSet::dimensionSet(Istream& is) } -// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // +Foam::dimensionSet::tokeniser::tokeniser(Istream& is) +: + is_(is), + tokens_(100), + start_(0), + size_(0) +{} -Foam::Istream& Foam::operator>>(Istream& is, dimensionSet& dset) + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::dimensionSet::tokeniser::push(const token& t) { - // Read begining of dimensionSet - if (token(is) != token::BEGIN_SQR) + label end = (start_+size_)%tokens_.size(); + tokens_[end] = t; + if (size_ == tokens_.size()) { - Info<< "expected a " << token::BEGIN_SQR << " in dimensionSet" - << endl << "in stream " << is.info() << endl; + start_ = tokens_.fcIndex(start_); + } + else + { + size_++; + } +} + + +Foam::token Foam::dimensionSet::tokeniser::pop() +{ + token t = tokens_[start_]; + start_ = tokens_.fcIndex(start_); + --size_; + return t; +} + + +void Foam::dimensionSet::tokeniser::unpop(const token& t) +{ + ++size_; + start_ = tokens_.rcIndex(start_); + tokens_[start_] = t; +} + + +bool Foam::dimensionSet::tokeniser::hasToken() const +{ + return size_ || is_.good(); +} + + +bool Foam::dimensionSet::tokeniser::valid(char c) +{ + return + ( + !isspace(c) + && c != '"' // string quote + && c != '\'' // string quote + && c != '/' // div + && c != ';' // end statement + && c != '{' // beg subdict + && c != '}' // end subdict + && c != '(' // beg expr + && c != ')' // end expr + && c != '[' // beg dim + && c != ']' // end dim + && c != '^' // power + && c != '*' // mult + ); +} + + +Foam::label Foam::dimensionSet::tokeniser::priority(const token& t) +{ + 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; + } +} + + +void Foam::dimensionSet::tokeniser::splitWord(const word& w) +{ + size_t start = 0; + for (size_t i=0; i start) + { + word subWord = w(start, i-start); + if (isdigit(subWord[0]) || subWord[0] == token::SUBTRACT) + { + push(token(readLabel(IStringStream(subWord)()))); + } + else + { + push(token(subWord)); + } + } + if (w[i] != token::SPACE) + { + if (isdigit(w[i])) + { + push(token(readLabel(IStringStream(w[i])()))); + } + else + { + push(token::punctuationToken(w[i])); + } + } + start = i+1; + } + } + if (start < w.size()) + { + word subWord = w(start, w.size()-start); + if (isdigit(subWord[0]) || subWord[0] == token::SUBTRACT) + { + push(token(readLabel(IStringStream(subWord)()))); + } + else + { + push(token(subWord)); + } + } +} + + +Foam::token Foam::dimensionSet::tokeniser::nextToken() +{ + if (size_ == 0) + { + token t(is_); + if (t.isWord()) + { + splitWord(t.wordToken()); + return pop(); + } + else + { + return t; + } + } + else + { + return pop(); + } +} + + +void Foam::dimensionSet::tokeniser::putBack(const token& t) +{ + if (size_ == 0) + { + push(t); + } + else + { + unpop(t); + } +} + + +Foam::dimensionedScalar Foam::dimensionSet::parse +( + const label lastPrior, + tokeniser& tis, + const HashTable& readSet +) const +{ + dimensionedScalar ds("", dimless, 1.0); + + // Get initial token + token nextToken(tis.nextToken()); + + // Store type of last token read. Used to detect two consecutive + // symbols and assume multiplication + bool haveReadSymbol = false; + + + while (true) + { + if (nextToken.isWord()) + { + const word& unitName = nextToken.wordToken(); + const dimensionedScalar& unitDim = readSet[unitName]; + ds.dimensions() *= unitDim.dimensions(); + ds.value() *= unitDim.value(); + haveReadSymbol = true; + } + else if (nextToken.isNumber()) + { + // no dimensions, just value + ds.value() *= nextToken.number(); + haveReadSymbol = true; + } + else if (nextToken.isPunctuation()) + { + label nextPrior = tokeniser::priority(nextToken); + + if (nextToken.pToken() == token::BEGIN_SQR) + { + // No idea when this will happen + tis.putBack(nextToken); + return ds; + } + else if (nextToken.pToken() == token::END_SQR) + { + tis.putBack(nextToken); + return ds; + } + else if (nextToken.pToken() == token::BEGIN_LIST) + { + dimensionedScalar sub(parse(nextPrior, tis, readSet)); + + token t = tis.nextToken(); + if (!t.isPunctuation() || t.pToken() != token::END_LIST) + { + FatalIOErrorIn + ( + "dimensionSet::parse" + "(const label, tokeniser&" + ", const HashTable&)", + tis.stream() + ) << "Illegal token " << t << exit(FatalIOError); + } + + ds.dimensions() *= sub.dimensions(); + ds.value() *= sub.value(); + + haveReadSymbol = true; + } + else if (nextToken.pToken() == token::END_LIST) + { + tis.putBack(nextToken); + return ds; + } + else if (nextToken.pToken() == token::MULTIPLY) + { + if (nextPrior > lastPrior) + { + dimensionedScalar sub(parse(nextPrior, tis, readSet)); + + ds.dimensions() *= sub.dimensions(); + ds.value() *= sub.value(); + } + else + { + // Restore token + tis.putBack(nextToken); + return ds; + } + haveReadSymbol = false; + } + else if (nextToken.pToken() == token::DIVIDE) + { + if (nextPrior > lastPrior) + { + dimensionedScalar sub(parse(nextPrior, tis, readSet)); + + ds.dimensions() /= sub.dimensions(); + ds.value() /= sub.value(); + } + else + { + tis.putBack(nextToken); + return ds; + } + haveReadSymbol = false; + } + else if (nextToken.pToken() == '^') + { + if (nextPrior > lastPrior) + { + dimensionedScalar exp(parse(nextPrior, tis, readSet)); + + ds.dimensions().reset(pow(ds.dimensions(), exp.value())); + ds.value() = Foam::pow(ds.value(), exp.value()); + } + else + { + tis.putBack(nextToken); + return ds; + } + haveReadSymbol = false; + } + else + { + FatalIOErrorIn + ( + "dimensionSet::parse" + "(const label, tokeniser&" + ", const HashTable&)", + tis.stream() + ) << "Illegal token " << nextToken << exit(FatalIOError); + } + } + else + { + FatalIOErrorIn + ( + "dimensionSet::parse" + "(const label, tokeniser&" + ", const HashTable&)", + tis.stream() + ) << "Illegal token " << nextToken << exit(FatalIOError); + } + + + if (!tis.hasToken()) + { + break; + } + + nextToken = tis.nextToken(); + if (nextToken.error()) + { + break; + } + + if (haveReadSymbol && (nextToken.isWord() || nextToken.isNumber())) + { + // Two consecutive symbols. Assume multiplication + tis.putBack(nextToken); + nextToken = token(token::MULTIPLY); + } } - // Read first five dimensions - for (int Dimension=0; Dimension& readSet +) +{ + multiplier = 1.0; + + // Read begining of dimensionSet + token startToken(is); + + if (startToken != token::BEGIN_SQR) { - is >> dset.exponents_[Dimension]; + FatalIOErrorIn + ( + "dimensionSet::read" + "(Istream&, scalar&, const HashTable&)", + is + ) << "expected a " << token::BEGIN_SQR << " in dimensionSet" + << endl << "in stream " << is.info() + << exit(FatalIOError); } // Read next token token nextToken(is); - // If next token is another number - // read last two dimensions - // and then read another token for the end of the dimensionSet - if (nextToken.isNumber()) + if (!nextToken.isNumber()) { - dset.exponents_[dimensionSet::CURRENT] = nextToken.number(); - is >> dset.exponents_[dimensionSet::LUMINOUS_INTENSITY]; - is >> nextToken; + is.putBack(nextToken); + + tokeniser tis(is); + + dimensionedScalar ds(parse(0, tis, readSet)); + + multiplier = ds.value(); + for (int i=0; i < dimensionSet::nDimensions; ++i) + { + exponents_[i] += ds.dimensions()[i]; + } } else { - dset.exponents_[dimensionSet::CURRENT] = 0; - dset.exponents_[dimensionSet::LUMINOUS_INTENSITY] = 0; + // Read first five dimensions + exponents_[dimensionSet::MASS] = nextToken.number(); + for (int Dimension=1; Dimension> exponents_[Dimension]; + } + + // Read next token + token nextToken(is); + + // If next token is another number + // read last two dimensions + // and then read another token for the end of the dimensionSet + if (nextToken.isNumber()) + { + exponents_[dimensionSet::CURRENT] = nextToken.number(); + is >> nextToken; + exponents_[dimensionSet::LUMINOUS_INTENSITY] = nextToken.number(); + is >> nextToken; + } + else + { + exponents_[dimensionSet::CURRENT] = 0; + exponents_[dimensionSet::LUMINOUS_INTENSITY] = 0; + } + + // Check end of dimensionSet + if (nextToken != token::END_SQR) + { + FatalIOErrorIn + ( + "dimensionSet::read" + "(Istream&, scalar&, const HashTable&)", + is + ) << "expected a " << token::END_SQR << " in dimensionSet " + << endl << "in stream " << is.info() + << exit(FatalIOError); + } + } + // Check state of Istream + is.check("Istream& operator>>(Istream&, dimensionSet&)"); + + return is; +} + + +Foam::Istream& Foam::dimensionSet::read +( + Istream& is, + scalar& multiplier +) +{ + return read(is, multiplier, unitSet()); +} + + +Foam::Istream& Foam::dimensionSet::read +( + Istream& is, + scalar& multiplier, + const dictionary& readSet +) +{ + multiplier = 1.0; + + // Read begining of dimensionSet + token startToken(is); + + if (startToken != token::BEGIN_SQR) + { + FatalIOErrorIn + ( + "dimensionSet::read" + "(Istream&, scalar&, const dictionary&)", + is + ) << "expected a " << token::BEGIN_SQR << " in dimensionSet" + << endl << "in stream " << is.info() + << exit(FatalIOError); } - // Check end of dimensionSet - if (nextToken != token::END_SQR) + // Read next token + token nextToken(is); + + if (nextToken.isWord()) { - Info<< "expected a " << token::END_SQR << " in dimensionSet" - << endl << "in stream " << is.info() << endl; + bool continueParsing = true; + do + { + word symbolPow = nextToken.wordToken(); + if (symbolPow[symbolPow.size()-1] == token::END_SQR) + { + symbolPow = symbolPow(0, symbolPow.size()-1); + continueParsing = false; + } + + + // Parse unit + dimensionSet symbolSet(dimless); + + size_t index = symbolPow.find('^'); + if (index != string::npos) + { + word symbol = symbolPow(0, index); + word exp = symbolPow(index+1, symbolPow.size()-index+1); + scalar exponent = readScalar(IStringStream(exp)()); + + dimensionedScalar s; + s.read(readSet[symbol], readSet); + + symbolSet.reset(pow(s.dimensions(), exponent)); + multiplier *= Foam::pow(s.value(), exponent); + } + else + { + dimensionedScalar s; + s.read(readSet[symbolPow], readSet); + + symbolSet.reset(s.dimensions()); + multiplier *= s.value(); + } + + // Add dimensions without checking + for (int i=0; i < dimensionSet::nDimensions; ++i) + { + exponents_[i] += symbolSet[i]; + } + + if (continueParsing) + { + nextToken = token(is); + + if (!nextToken.isWord() || nextToken == token::END_SQR) + { + continueParsing = false; + } + } + } + while (continueParsing); + } + else + { + // Read first five dimensions + exponents_[dimensionSet::MASS] = nextToken.number(); + for (int Dimension=1; Dimension> exponents_[Dimension]; + } + + // Read next token + token nextToken(is); + + // If next token is another number + // read last two dimensions + // and then read another token for the end of the dimensionSet + if (nextToken.isNumber()) + { + exponents_[dimensionSet::CURRENT] = nextToken.number(); + is >> nextToken; + exponents_[dimensionSet::LUMINOUS_INTENSITY] = nextToken.number(); + is >> nextToken; + } + else + { + exponents_[dimensionSet::CURRENT] = 0; + exponents_[dimensionSet::LUMINOUS_INTENSITY] = 0; + } + + // Check end of dimensionSet + if (nextToken != token::END_SQR) + { + FatalIOErrorIn + ( + "dimensionSet::read" + "(Istream&, scalar&, const dictionary&)", + is + ) << "expected a " << token::END_SQR << " in dimensionSet " + << endl << "in stream " << is.info() + << exit(FatalIOError); + } + } + + // Check state of Istream + is.check("Istream& operator>>(Istream&, dimensionSet&)"); + + return is; +} + + +Foam::Ostream& Foam::dimensionSet::write +( + Ostream& os, + scalar& multiplier, + const dimensionSets& writeUnits +) const +{ + multiplier = 1.0; + + os << token::BEGIN_SQR; + + if (writeUnits.valid()) + { + scalarField exponents(dimensionSet::nDimensions); + for (int d=0; d smallExponent) + { + const dimensionedScalar& ds = writeUnits.units()[i]; + + if (hasPrinted) + { + os << token::SPACE; + } + hasPrinted = true; + os << ds.name(); + if (mag(exponents[i]-1) > smallExponent) + { + os << '^' << exponents[i]; + + multiplier *= Foam::pow(ds.value(), exponents[i]); + } + else + { + multiplier *= ds.value(); + } + } + } + } + else + { + for (int d=0; d>(Istream& is, dimensionSet& dset) +{ + scalar multiplier; + dset.read(is, multiplier); + + if (mag(multiplier-1.0) > dimensionSet::smallExponent) + { + FatalIOErrorIn("Foam::operator>>(Istream&, dimensionSet&)", is) + << "Cannot use scaled units in dimensionSet" + << exit(FatalIOError); } // Check state of Istream @@ -85,13 +710,8 @@ Foam::Istream& Foam::operator>>(Istream& is, dimensionSet& dset) Foam::Ostream& Foam::operator<<(Ostream& os, const dimensionSet& dset) { - os << token::BEGIN_SQR; - - for (int Dimension=0; Dimension > unitSetPtr_; +autoPtr writeUnitSetPtr_; + + +const HashTable& unitSet() +{ + if (!unitSetPtr_.valid()) + { + const dictionary& dict = dimensionSystems(); + + if (!dict.found("unitSet")) + { + FatalIOErrorIn("unitSet()", dict) + << "Cannot find unitSet in dictionary " << dict.name() + << exit(FatalIOError); + } + + const word unitSetCoeffs(word(dict.lookup("unitSet")) + "Coeffs"); + + if (!dict.found(unitSetCoeffs)) + { + FatalIOErrorIn("unitSet()", dict) + << "Cannot find " << unitSetCoeffs << " in dictionary " + << dict.name() << exit(FatalIOError); + } + + const dictionary& unitDict = dict.subDict(unitSetCoeffs); + + unitSetPtr_.reset + ( + new HashTable(unitDict.size()) + ); + + forAllConstIter(dictionary, unitDict, iter) + { + if (iter().keyword() != "writeUnits") + { + dimensionedScalar dt; + dt.read(iter().stream(), unitDict); + bool ok = unitSetPtr_->insert(iter().keyword(), dt); + if (!ok) + { + FatalIOErrorIn("unitSet()", dict) + << "Duplicate unit " << iter().keyword() + << " in DimensionSets dictionary" + << exit(FatalIOError); + } + } + } + + wordList writeUnitNames + ( + unitDict.lookupOrDefault + ( + "writeUnits", + wordList(0) + ) + ); + + writeUnitSetPtr_.reset + ( + new dimensionSets + ( + unitSetPtr_(), + writeUnitNames + ) + ); + + if (writeUnitNames.size() != 0 && writeUnitNames.size() != 7) + { + FatalIOErrorIn("unitSet()", dict) + << "Cannot find entry \"writeUnits\" in " << unitDict.name() + << " or it is not a wordList of size 7" + << exit(FatalIOError); + } + } + return unitSetPtr_(); +} + + +const dimensionSets& writeUnitSet() +{ + if (!writeUnitSetPtr_.valid()) + { + (void)unitSet(); + } + return writeUnitSetPtr_(); +} + + +const dimensionSet dimless(0, 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 dimTime(0, 0, 1, 0, 0, 0, 0); +const dimensionSet dimTemperature(0, 0, 0, 1, 0, 0, 0); +const dimensionSet dimMoles(0, 0, 0, 0, 1, 0, 0); +const dimensionSet dimCurrent(0, 0, 0, 0, 0, 1, 0); +const dimensionSet dimLuminousIntensity(0, 0, 0, 0, 0, 0, 1); + +const dimensionSet dimArea(sqr(dimLength)); +const dimensionSet dimVolume(pow3(dimLength)); +const dimensionSet dimVol(dimVolume); + +const dimensionSet dimVelocity(dimLength/dimTime); +const dimensionSet dimAcceleration(dimVelocity/dimTime); + +const dimensionSet dimDensity(dimMass/dimVolume); +const dimensionSet dimForce(dimMass*dimAcceleration); +const dimensionSet dimEnergy(dimForce*dimLength); +const dimensionSet dimPower(dimEnergy/dimTime); + +const dimensionSet dimPressure(dimForce/dimArea); +const dimensionSet dimGasConstant(dimEnergy/dimMass/dimTemperature); +const dimensionSet dimSpecificHeatCapacity(dimGasConstant); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::dimensionSets::dimensionSets +( + const HashTable& units, + const wordList& unitNames +) +: + units_(unitNames.size()), + conversion_(unitNames.size()), + conversionPivots_(unitNames.size()), + valid_(false) +{ + forAll(unitNames, i) + { + units_.set + ( + i, + new dimensionedScalar + ( + units[unitNames[i]] + ) + ); + } + + if (unitNames.size() == 7) + { + valid_ = true; + + // Determine conversion from basic units to write units + for (label rowI = 0; rowI < conversion_.n(); rowI++) + { + scalar* row = conversion_[rowI]; + + for (label columnI = 0; columnI < conversion_.m(); columnI++) + { + const dimensionedScalar& dSet = units_[columnI]; + row[columnI] = dSet.dimensions()[rowI]; + } + } + conversionPivots_.setSize(conversion_.n()); + LUDecompose(conversion_, conversionPivots_); + + //- possibly some optimisation here to detect identity matri + //if + //( + // conversionPivots_ == identity(conversionPivots_.size()) + // && conversion_ == I) + //) + //{ + // identity_ = true; + //} + } +} + + +void Foam::dimensionSets::coefficients(scalarField& exponents) const +{ + LUBacksubstitute(conversion_, conversionPivots_, exponents); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam // ************************************************************************* // diff --git a/src/OpenFOAM/dimensionSet/dimensionSets.H b/src/OpenFOAM/dimensionSet/dimensionSets.H index 7d8dba56ef..bcd6a5edae 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSets.H +++ b/src/OpenFOAM/dimensionSet/dimensionSets.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -36,6 +36,10 @@ SourceFiles #ifndef dimensionSets_H #define dimensionSets_H +#include "scalarMatrices.H" +#include "dimensionedScalarFwd.H" +#include "PtrList.H" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -69,6 +73,65 @@ extern const dimensionSet dimGasConstant; extern const dimensionSet dimSpecificHeatCapacity; + +class dimensionSets +{ + // Private data + + //- Set of dimensions + PtrList units_; + + //- LU decomposition of dimensions + scalarSquareMatrix conversion_; + + //- See above + labelList conversionPivots_; + + //- Is LU decomposition valid + bool valid_; + +public: + + // Constructors + + //- Construct from all units and set of units to use for inversion + // (writing) + dimensionSets + ( + const HashTable&, + const wordList& unitNames + ); + + // Member functions + + //- Return the units + const PtrList& units() const + { + return units_; + } + + //- Is there a valid inverse of the selected unit + bool valid() const + { + return valid_; + } + + //- (if valid) obtain set of coefficients of unitNames + void coefficients(scalarField&) const; + +}; + + +//- Top level dictionary +dictionary& dimensionSystems(); + +//- Set of all dimensions +const HashTable& unitSet(); + +//- Set of units +const dimensionSets& writeUnitSet(); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C index 4e96c3012a..73fea9fdd2 100644 --- a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C +++ b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.C @@ -97,10 +97,10 @@ dimensioned::dimensioned Istream& is ) : - name_(is), - dimensions_(is), - value_(pTraits(is)) -{} + dimensions_(dimless) +{ + read(is); +} template @@ -111,9 +111,13 @@ dimensioned::dimensioned ) : name_(name), - dimensions_(is), - value_(pTraits(is)) -{} + dimensions_(dimless) +{ + scalar multiplier; + dimensions_.read(is, multiplier); + is >> value_; + value_ *= multiplier; +} template @@ -141,24 +145,29 @@ dimensioned::dimensioned } // If the dimensions are provided compare with the argument + scalar multiplier = 1.0; + if (nextToken == token::BEGIN_SQR) { - dimensionSet dims(is); + dimensionSet dims(dimless); + dims.read(is, multiplier); if (dims != dimensions_) { - FatalErrorIn + FatalIOErrorIn ( "dimensioned::dimensioned" - "(const word&, const dimensionSet&, Istream&)" + "(const word&, const dimensionSet&, Istream&)", + is ) << "The dimensions " << dims << " provided do not match the required dimensions " << dimensions_ - << abort(FatalError); + << abort(FatalIOError); } } is >> value_; + value_ *= multiplier; } @@ -247,6 +256,83 @@ bool dimensioned::readIfPresent(const dictionary& dict) } +template +Foam::Istream& dimensioned::read(Istream& is, const dictionary& readSet) +{ + // Read name + is >> name_; + + // Read dimensionSet + multiplier + scalar mult; + dimensions_.read(is, mult, readSet); + + // Read value + is >> value_; + value_ *= mult; + + // Check state of Istream + is.check + ( + "Istream& dimensioned::read(Istream& is, const dictionary&)" + ); + + return is; +} + + +template +Foam::Istream& dimensioned::read +( + Istream& is, + const HashTable& readSet +) +{ + // Read name + is >> name_; + + // Read dimensionSet + multiplier + scalar mult; + dimensions_.read(is, mult, readSet); + + // Read value + is >> value_; + value_ *= mult; + + // Check state of Istream + is.check + ( + "Istream& dimensioned::read" + "(Istream& is, const HashTable&)" + ); + + return is; +} + + +template +Foam::Istream& dimensioned::read(Istream& is) +{ + // Read name + is >> name_; + + // Read dimensionSet + multiplier + scalar mult; + dimensions_.read(is, mult); + + // Read value + is >> value_; + value_ *= mult; + + // Check state of Istream + is.check + ( + "Istream& dimensioned::read(Istream& is)" + ); + + return is; +} + + // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template @@ -414,13 +500,15 @@ Istream& operator>>(Istream& is, dimensioned& dt) } // If the dimensions are provided reset the dimensions to those read + scalar multiplier = 1.0; if (nextToken == token::BEGIN_SQR) { - is >> dt.dimensions_; + dt.dimensions_.read(is, multiplier); } // Read the value is >> dt.value_; + dt.value_ *= multiplier; // Check state of Istream is.check("Istream& operator>>(Istream&, dimensioned&)"); @@ -432,10 +520,17 @@ Istream& operator>>(Istream& is, dimensioned& dt) template Ostream& operator<<(Ostream& os, const dimensioned& dt) { - // do a stream write op for a dimensions()et - os << dt.name() << token::SPACE - << dt.dimensions() << token::SPACE - << dt.value(); + // Write the name + os << dt.name() << token::SPACE; + + // Write the dimensions + scalar mult; + dt.dimensions().write(os, mult); + + os << token::SPACE; + + // Write the value + os << dt.value()/mult; // Check state of Ostream os.check("Ostream& operator<<(Ostream&, const dimensioned&)"); diff --git a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H index 3cb8e0222a..8f5108df0b 100644 --- a/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H +++ b/src/OpenFOAM/dimensionedTypes/dimensionedType/dimensionedType.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -163,6 +163,17 @@ public: bool readIfPresent(const dictionary&); + // I/O + + //- Read using provided units. Only used during startup. + Istream& read(Istream& is, const dictionary&); + + //- Read using provided units + Istream& read(Istream& is, const HashTable&); + + //- Read using system units + Istream& read(Istream& is); + // Member operators //- Return a component as a dimensioned diff --git a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C index 2879e28f10..1fd8eac973 100644 --- a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C +++ b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C @@ -48,8 +48,10 @@ Foam::UniformDimensionedField::UniformDimensionedField ) { dictionary dict(readStream(typeName)); - this->dimensions().reset(dict.lookup("dimensions")); + scalar multiplier; + this->dimensions().read(dict.lookup("dimensions"), multiplier); dict.lookup("value") >> this->value(); + this->value() *= multiplier; } } @@ -75,8 +77,10 @@ Foam::UniformDimensionedField::UniformDimensionedField dimensioned(regIOobject::name(), dimless, pTraits::zero) { dictionary dict(readStream(typeName)); - this->dimensions().reset(dict.lookup("dimensions")); + scalar multiplier; + this->dimensions().read(dict.lookup("dimensions"), multiplier); dict.lookup("value") >> this->value(); + this->value() *= multiplier; } @@ -92,9 +96,11 @@ Foam::UniformDimensionedField::~UniformDimensionedField() template bool Foam::UniformDimensionedField::writeData(Ostream& os) const { - os.writeKeyword("dimensions") << this->dimensions() << token::END_STATEMENT + scalar multiplier; + os.writeKeyword("dimensions"); + this->dimensions().write(os, multiplier) << token::END_STATEMENT << nl; - os.writeKeyword("value") << this->value() << token::END_STATEMENT + os.writeKeyword("value") << this->value()/multiplier << token::END_STATEMENT << nl << nl; return (os.good()); diff --git a/src/thermophysicalModels/radiationModels/radiationModel/radiationModel/radiationModel.C b/src/thermophysicalModels/radiationModels/radiationModel/radiationModel/radiationModel.C index 4ef719498f..6a20fbcf5c 100644 --- a/src/thermophysicalModels/radiationModels/radiationModel/radiationModel/radiationModel.C +++ b/src/thermophysicalModels/radiationModels/radiationModel/radiationModel/radiationModel.C @@ -113,7 +113,7 @@ bool Foam::radiation::radiationModel::read() lookup("radiation") >> radiation_; coeffs_ = subDict(type() + "Coeffs"); - lookupOrDefault