diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.H b/src/OpenFOAM/dimensionSet/dimensionSet.H index 777099f8dd..05d4d67ca1 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSet.H +++ b/src/OpenFOAM/dimensionSet/dimensionSet.H @@ -227,15 +227,21 @@ public: // I/O - //- Read, assuming the '[' has already been read - Istream& readNoBegin(Istream& is); + //- Read without the square brackets + Istream& readNoBeginOrEnd(Istream& is); //- Read Istream& read(Istream& is); + //- Write without the square brackets + Ostream& writeNoBeginOrEnd(Ostream& os) const; + //- Write Ostream& write(Ostream& os) const; + //- Write info without the square brackets + Ostream& writeInfoNoBeginOrEnd(Ostream& os) const; + //- Return info proxy inline InfoProxy info() const { diff --git a/src/OpenFOAM/dimensionSet/dimensionSetIO.C b/src/OpenFOAM/dimensionSet/dimensionSetIO.C index ecba0c49a5..ed744b8147 100644 --- a/src/OpenFOAM/dimensionSet/dimensionSetIO.C +++ b/src/OpenFOAM/dimensionSet/dimensionSetIO.C @@ -30,7 +30,7 @@ License void Foam::dimensionSet::round(const scalar tol) { - for (int i=0; i < dimensionSet::nDimensions; ++i) + for (int i=0; i> nextToken; + is.putBack(nextToken); + + // If not a number, then these are named dimensions. Parse. if (!nextToken.isNumber()) { - // Named dimensions. Parse. - is.putBack(nextToken); - reset(symbols::parseNoBegin(is, dimless, dimensions())); + reset(symbols::parseNoBeginOrEnd(is, dimless, dimensions())); + + return is; + } + + // Otherwise these are numbered dimensions. Read directly... + + // Read first five dimensions + for (int i=0; i> exponents_[i]; + } + + // Peek at the next token + is >> nextToken; + is.putBack(nextToken); + + // If next token is another number then read the last two dimensions + // and then read another token for the end of the dimensionSet + if (nextToken.isNumber()) + { + is >> exponents_[dimensionSet::CURRENT]; + is >> exponents_[dimensionSet::LUMINOUS_INTENSITY]; } else { - // Numbered dimensions. Read directly. - - // 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 then read the 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) - { - FatalIOErrorInFunction(is) - << "expected a " << token::END_SQR << " in dimensionSet " - << endl << "in stream " << is.info() - << exit(FatalIOError); - } + exponents_[dimensionSet::CURRENT] = 0; + exponents_[dimensionSet::LUMINOUS_INTENSITY] = 0; } - // Check state of Istream - is.check("Istream& operator>>(Istream&, dimensionSet&)"); - return is; } @@ -122,7 +110,6 @@ Foam::Istream& Foam::dimensionSet::read(Istream& is) { // Read beginning of dimensionSet token startToken(is); - if (startToken != token::BEGIN_SQR) { FatalIOErrorInFunction(is) @@ -131,7 +118,42 @@ Foam::Istream& Foam::dimensionSet::read(Istream& is) << exit(FatalIOError); } - return readNoBegin(is); + readNoBeginOrEnd(is); + + // Read end of dimensionSet + token endToken(is); + if (endToken != token::END_SQR) + { + FatalIOErrorInFunction(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::writeNoBeginOrEnd(Ostream& os) const +{ + if (dimensionless()) + { + // Do nothing + } + else + { + for (int i=0; i dimensionSet::smallExponent) + { + if (!first) + { + os << token::SPACE; + } + + os << dimensionSet::dimensionTypeNames_ + [static_cast(i)]; + + if (exponents_[i] != 1) + { + os << '^' << exponents_[i]; + } + + first = false; + } + } + + return os; +} + + void Foam::writeEntry(Ostream& os, const dimensionSet& value) { os << value; @@ -185,30 +231,9 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const dimensionSet& dims) Foam::Ostream& Foam::operator<<(Ostream& os, const InfoProxy& ip) { - const dimensionSet& dims = ip.t_; - os << token::BEGIN_SQR; - for (int first=true, i=0; i dimensionSet::smallExponent) - { - if (!first) - { - os << token::SPACE; - } - - os << dimensionSet::dimensionTypeNames_ - [static_cast(i)]; - - if (dims.exponents_[i] != 1) - { - os << '^' << dims.exponents_[i]; - } - - first = false; - } - } + ip.t_.writeInfoNoBeginOrEnd(os); os << token::END_SQR; diff --git a/src/OpenFOAM/primitives/functions/Function1/Function1/Function1UnitConversions.C b/src/OpenFOAM/primitives/functions/Function1/Function1/Function1UnitConversions.C index d4dac7a034..90a52e5624 100644 --- a/src/OpenFOAM/primitives/functions/Function1/Function1/Function1UnitConversions.C +++ b/src/OpenFOAM/primitives/functions/Function1/Function1/Function1UnitConversions.C @@ -72,8 +72,8 @@ bool Foam::Function1s::unitConversions::readIfPresent ITstream& is = entryPtr->stream(); is.readBegin("unitConversions"); - x.readIfPresent(keyword, dict, is); - value.readIfPresent(keyword, dict, is); + x.read(keyword, dict, is); + value.read(keyword, dict, is); is.readEnd("unitConversions"); return true; diff --git a/src/OpenFOAM/symbols/symbols.C b/src/OpenFOAM/symbols/symbols.C index c2e01ba40d..71205402eb 100644 --- a/src/OpenFOAM/symbols/symbols.C +++ b/src/OpenFOAM/symbols/symbols.C @@ -90,6 +90,7 @@ Foam::token Foam::symbols::tokeniser::nextToken() if (size_ == 0) { token t(is_); + if (t.isWord()) { splitWord(t.wordToken()); @@ -175,16 +176,17 @@ bool Foam::symbols::tokeniser::valid(char c) !isspace(c) && c != '"' // string quote && c != '\'' // string quote - && c != '/' // div + && c != '/' // divide && c != ';' // end statement - && c != '{' // beg subdict - && c != '}' // end subdict - && c != '(' // beg expr - && c != ')' // end expr - && c != '[' // beg dim - && c != ']' // end dim + && c != '{' // begin sub-dictionary + && c != '}' // end sub-dictionary + && c != '(' // begin expression + && c != ')' // end expression + && c != '[' // begin dimensions/units + && c != ']' // end dimensions/units + && c != ':' // separate dimensions/units && c != '^' // power - && c != '*' // mult + && c != '*' // multiply ); } diff --git a/src/OpenFOAM/symbols/symbols.H b/src/OpenFOAM/symbols/symbols.H index c6cea6ee71..ad814a25c7 100644 --- a/src/OpenFOAM/symbols/symbols.H +++ b/src/OpenFOAM/symbols/symbols.H @@ -124,10 +124,11 @@ Type parseNoBegin const HashTable& table ); -//- Parse a dimension set or unit conversion, assuming that the '[' has already -// been read +//- Parse tokens into a dimension set or unit conversion, assuming that the '[' +// has already been read, and ending before the '[' or ':'. Note that this +// will leave the stream with a pushed back token. template -Type parseNoBegin +Type parseNoBeginOrEnd ( Istream& is, const Type& identity, diff --git a/src/OpenFOAM/symbols/symbolsTemplates.C b/src/OpenFOAM/symbols/symbolsTemplates.C index d84c991307..37b075c557 100644 --- a/src/OpenFOAM/symbols/symbolsTemplates.C +++ b/src/OpenFOAM/symbols/symbolsTemplates.C @@ -76,12 +76,19 @@ Type Foam::symbols::parseNoBegin tis.putBack(nextToken); return result; } + else if (nextToken.pToken() == token::COLON) + { + // End the units + tis.putBack(nextToken); + return result; + } else if (nextToken.pToken() == token::BEGIN_LIST) { // Parenthesis. Evaluate the sub-units and multiply. result.reset ( - result*parseNoBegin(nextPrior, tis, identity, table) + result + *parseNoBegin(nextPrior, tis, identity, table) ); // Check that the parentheses end @@ -108,7 +115,8 @@ Type Foam::symbols::parseNoBegin // This has priority. Evaluate the next units and multiply. result.reset ( - result*parseNoBegin(nextPrior, tis, identity, table) + result + *parseNoBegin(nextPrior, tis, identity, table) ); } else @@ -127,7 +135,8 @@ Type Foam::symbols::parseNoBegin { result.reset ( - result/parseNoBegin(nextPrior, tis, identity, table) + result + /parseNoBegin(nextPrior, tis, identity, table) ); } else @@ -177,6 +186,7 @@ Type Foam::symbols::parseNoBegin } nextToken = tis.nextToken(); + if (nextToken.error()) { break; @@ -195,7 +205,7 @@ Type Foam::symbols::parseNoBegin template -Type Foam::symbols::parseNoBegin +Type Foam::symbols::parseNoBeginOrEnd ( Istream& is, const Type& identity, @@ -204,7 +214,11 @@ Type Foam::symbols::parseNoBegin { symbols::tokeniser tis(is); - return parseNoBegin(0, tis, identity, table); + Type result = parseNoBegin(0, tis, identity, table); + + is.putBack(tis.nextToken()); + + return result; } diff --git a/src/OpenFOAM/unitConversion/unitConversion.H b/src/OpenFOAM/unitConversion/unitConversion.H index c5010fa7e5..9e0a240c4d 100644 --- a/src/OpenFOAM/unitConversion/unitConversion.H +++ b/src/OpenFOAM/unitConversion/unitConversion.H @@ -219,6 +219,12 @@ public: //- Update void read(const word& keyword, const dictionary&); + //- Update + void read(Istream& is); + + //- Update + void read(const word& keyword, const dictionary&, Istream& is); + //- Update if found in the dictionary bool readIfPresent(const word& keyword, const dictionary&); diff --git a/src/OpenFOAM/unitConversion/unitConversionIO.C b/src/OpenFOAM/unitConversion/unitConversionIO.C index a5f28eb790..84772d94b2 100644 --- a/src/OpenFOAM/unitConversion/unitConversionIO.C +++ b/src/OpenFOAM/unitConversion/unitConversionIO.C @@ -47,6 +47,23 @@ void Foam::unitConversion::read(const word& keyword, const dictionary& dict) if (!compare(*this, units, false)) { FatalIOErrorInFunction(dict) + << "The units " << units.info() << " of " << keyword + << " in dictionary " << dict.name() << " do not match " + << "the required units " << info() + << abort(FatalIOError); + } + + reset(units); +} + + +void Foam::unitConversion::read(Istream& is) +{ + const unitConversion units(is); + + if (!compare(*this, units, false)) + { + FatalIOErrorInFunction(is) << "The units " << units.info() << " provided do not match " << "the required units " << info() << abort(FatalIOError); @@ -56,6 +73,28 @@ void Foam::unitConversion::read(const word& keyword, const dictionary& dict) } +void Foam::unitConversion::read +( + const word& keyword, + const dictionary& dict, + Istream& is +) +{ + const unitConversion units(is); + + if (!compare(*this, units, false)) + { + FatalIOErrorInFunction(dict) + << "The units " << units.info() << " of " << keyword + << " in dictionary " << dict.name() << " do not match " + << "the required units " << info() + << abort(FatalIOError); + } + + reset(units); +} + + bool Foam::unitConversion::readIfPresent ( const word& keyword, @@ -71,7 +110,8 @@ bool Foam::unitConversion::readIfPresent if (!compare(*this, units, false)) { FatalIOErrorInFunction(dict) - << "The units " << units.info() << " provided do not match " + << "The units " << units.info() << " of " << keyword + << " in dictionary " << dict.name() << " do not match " << "the required units " << info() << abort(FatalIOError); } @@ -102,24 +142,24 @@ bool Foam::unitConversion::readIfPresent(Istream& is) if (nextToken != token::BEGIN_SQR) return false; - unitConversion u(is); + const unitConversion units(is); - if (!unitConversion::compare(u, *this, false)) + if (!unitConversion::compare(units, *this, false)) { FatalIOErrorInFunction(is) - << "The units " << u.info() << " provided do not match " + << "The units " << units.info() << " provided do not match " << "the required units " << info() << abort(FatalIOError); } - if (debug && (any() || !unitConversion::compare(u, *this, true))) + if (debug && (any() || !unitConversion::compare(units, *this, true))) { Info<< "Unit conversion at line " << is.lineNumber() << " of file " << is.name() - << " with factor " << u.multiplier_ << endl; + << " with factor " << units.multiplier_ << endl; } - reset(u); + reset(units); return true; } @@ -137,25 +177,25 @@ bool Foam::unitConversion::readIfPresent if (nextToken != token::BEGIN_SQR) return false; - unitConversion u(is); + const unitConversion units(is); - if (!unitConversion::compare(u, *this, false)) + if (!unitConversion::compare(units, *this, false)) { - FatalIOErrorInFunction(is) - << "The units " << u.info() << " of " << keyword + FatalIOErrorInFunction(dict) + << "The units " << units.info() << " of " << keyword << " in dictionary " << dict.name() << " do not match " << "the required units " << info() << abort(FatalIOError); } - if (debug && (any() || !unitConversion::compare(u, *this, true))) + if (debug && (any() || !unitConversion::compare(units, *this, true))) { Info<< "Unit conversion of " << keyword << " in dictionary " << dict.name() - << " with factor " << u.multiplier_ << endl; + << " with factor " << units.multiplier_ << endl; } - reset(u); + reset(units); return true; } @@ -165,95 +205,133 @@ bool Foam::unitConversion::readIfPresent Foam::Istream& Foam::operator>>(Istream& is, unitConversion& units) { - // Read beginning of unitConversion - token startToken(is); + token nextToken; - if (startToken != token::BEGIN_SQR) + // Read the next delimiting token. This must be the start bracket. + is >> nextToken; + if (nextToken != token::BEGIN_SQR) { FatalIOErrorInFunction(is) << "expected a " << token::BEGIN_SQR << " in unitConversion" - << endl << "in stream " << is.info() - << exit(FatalIOError); + << endl << "in stream " << is.info() << ", got a " + << nextToken << exit(FatalIOError); } // Peek at the next token - token nextToken(is); + is >> nextToken; is.putBack(nextToken); - if (!nextToken.isNumber()) + // If not a number or separator, then these are named units. Parse. + if (!nextToken.isNumber() && nextToken != token::COLON) { // Named units. Parse. - units.reset(symbols::parseNoBegin(is, unitless, Foam::units())); + units.reset(symbols::parseNoBeginOrEnd(is, unitless, Foam::units())); + + // Read the next delimiting token. This must be the end bracket. + is >> nextToken; + if (nextToken != token::END_SQR) + { + FatalIOErrorInFunction(is) + << "expected a " << token::END_SQR << " in unitConversion " + << endl << "in stream " << is.info() << ", got a " + << nextToken << exit(FatalIOError); + } + + // Check state of Istream + is.check("Istream& operator>>(Istream&, unitConversion&)"); + + return is; } - else + + // Otherwise these are numbered units. Read directly... + + // Read the dimensions + units.dimensions_.readNoBeginOrEnd(is); + + // Read the next delimiting token. If a separator, then there are + // dimensionless units and a multiplier to read. If it is an end bracket, + // then the dimensionless units are zero and the multiplier is one and the + // parsing is finished. Otherwise the parsing has failed. + is >> nextToken; + if (nextToken == token::COLON) { - // Read the dimensions - units.dimensions_.readNoBegin(is); + // Peek at the next token + is >> nextToken; + is.putBack(nextToken); // Read the dimensionless units if present, or set to zero - token nextToken; - if (!is.eof()) - { - is >> nextToken; - } - if (nextToken == token::BEGIN_SQR) + if (!nextToken.isNumber()) { for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { - is >> units.exponents_[i]; - } - - // Check end of dimensionless units - token endToken(is); - if (endToken != token::END_SQR) - { - FatalIOErrorInFunction(is) - << "expected a " << token::END_SQR - << " in unitConversion " << endl << "in stream " - << is.info() << exit(FatalIOError); - } - - // Read the multiplier if present, or set to unity - token nextToken; - if (!is.eof()) - { - is >> nextToken; - } - if (nextToken == token::BEGIN_SQR) - { - is >> units.multiplier_; - - // Check end of multiplier - token endToken(is); - if (endToken != token::END_SQR) - { - FatalIOErrorInFunction(is) - << "expected a " << token::END_SQR - << " in unitConversion " << endl << "in stream " - << is.info() << exit(FatalIOError); - } - } - else - { - units.multiplier_ = 1; - if (!nextToken.undefined()) - { - is.putBack(nextToken); - } + units.exponents_[i] = 0; } } else { for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { - units.exponents_[i] = 0; - } - units.multiplier_ = 1; - if (!nextToken.undefined()) - { - is.putBack(nextToken); + is >> units.exponents_[i]; } } + + // Read the next delimiting token. If a separator then there is a + // multiplier to read. If it is an end bracket then the multiplier is + // one and the parsing is finished. Otherwise the parsing has failed. + is >> nextToken; + if (nextToken == token::COLON) + { + // Peek at the next token + is >> nextToken; + is.putBack(nextToken); + + // Read the multiplier if present, or set to unity + if (!nextToken.isNumber()) + { + units.multiplier_ = 1; + } + else + { + is >> units.multiplier_; + } + + // Read the next delimiting token. This must be the end bracket. + is >> nextToken; + if (nextToken != token::END_SQR) + { + FatalIOErrorInFunction(is) + << "expected a " << token::END_SQR << " in unitConversion " + << endl << "in stream " << is.info() << ", got a " + << nextToken << exit(FatalIOError); + } + } + else if (nextToken == token::END_SQR) + { + units.multiplier_ = 1; + } + else + { + FatalIOErrorInFunction(is) + << "expected a " << token::END_SQR << " or a " << token::COLON + << " in unitConversion " << endl << "in stream " << is.info() + << ", got a " << nextToken << exit(FatalIOError); + } + } + else if (nextToken == token::END_SQR) + { + for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) + { + units.exponents_[i] = 0; + } + + units.multiplier_ = 1; + } + else + { + FatalIOErrorInFunction(is) + << "expected a " << token::END_SQR << " or a " << token::COLON + << " in unitConversion " << endl << "in stream " << is.info() + << ", got a " << nextToken << exit(FatalIOError); } // Check state of Istream @@ -265,8 +343,11 @@ Foam::Istream& Foam::operator>>(Istream& is, unitConversion& units) Foam::Ostream& Foam::operator<<(Ostream& os, const unitConversion& units) { + // Write the start + os << token::BEGIN_SQR; + // Write the dimensions - os << units.dimensions_; + units.dimensions_.writeNoBeginOrEnd(os); // Determine if any dimensionless units are non-zero bool nonZeroDimlessUnits = false; @@ -280,25 +361,36 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const unitConversion& units) // Determine if the multiplier is non-unity bool nonUnityMultiplier = units.multiplier_ != 1; - // Write the dimensionless units if any are non-zero or we have a - // multiplier to write out afterwards + // Write a separator if there is anything to follow if (nonZeroDimlessUnits || nonUnityMultiplier) { - os << token::BEGIN_SQR; + os << token::SPACE << token::COLON; + } + + // Write the dimensionless units if any are non-zero + if (nonZeroDimlessUnits) + { for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { - if (i) os << token::SPACE; - os << units.exponents_[i]; + os << token::SPACE << units.exponents_[i]; } - os << token::END_SQR; + } + + // Write a separator if there is anything to follow + if (nonUnityMultiplier) + { + os << token::SPACE << token::COLON; } // Write the multiplier if it is non-unity if (nonUnityMultiplier) { - os << token::BEGIN_SQR << units.multiplier_ << token::END_SQR; + os << token::SPACE << units.multiplier_; } + // Write the end + os << token::END_SQR; + // Check state of Ostream os.check("Ostream& operator<<(Ostream&, const unitConversion&)"); @@ -324,8 +416,11 @@ Foam::Ostream& Foam::operator<< return os << token::BEGIN_SQR << "" << token::END_SQR; } + // Write the start + os << token::BEGIN_SQR; + // Write the dimensions - os << units.dimensions_.info(); + units.dimensions_.writeInfoNoBeginOrEnd(os); // Determine if any dimensionless units are non-zero bool nonZeroDimlessUnits = false; @@ -339,43 +434,45 @@ Foam::Ostream& Foam::operator<< // Determine if the multiplier is non-unity bool nonUnityMultiplier = units.multiplier_ != 1; - // Write the dimensionless units if any are non-zero or we have a - // multiplier to write out afterwards + // Write a separator if there is anything to follow if (nonZeroDimlessUnits || nonUnityMultiplier) { - // Write the dimensionless units - os << token::BEGIN_SQR; + os << token::SPACE << token::COLON; + } - for (int first=true, i=0; i unitConversion::smallExponent) { - if (!first) - { - os << token::SPACE; - } - - os << unitConversion::dimlessUnitTypeNames_ + os << token::SPACE << unitConversion::dimlessUnitTypeNames_ [static_cast(i)]; if (units.exponents_[i] != 1) { os << '^' << units.exponents_[i]; } - - first = false; } } + } - os << token::END_SQR; + // Write a separator if there is anything to follow + if (nonUnityMultiplier) + { + os << token::SPACE << token::COLON; } // Write the multiplier if it is non-unity if (nonUnityMultiplier) { - os << token::BEGIN_SQR << units.multiplier_ << token::END_SQR; + os << token::SPACE << units.multiplier_; } + // Write the end + os << token::END_SQR; + // Check state of Ostream os.check("Ostream& operator<<(Ostream&, const InfoProxy&)");