/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "unitConversion.H" #include "dictionary.H" #include "symbols.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::unitConversion::unitConversion(Istream& is) : dimensions_(dimless), multiplier_(NaN) { is >> *this; } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::unitConversion::read(const word& keyword, const dictionary& dict) { const unitConversion units(dict.lookup(keyword)); 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); } reset(units); } 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, const dictionary& dict ) { const entry* entryPtr = dict.lookupEntryPtr(keyword, false, true); if (entryPtr) { const unitConversion units(entryPtr->stream()); 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); return true; } else { if (dictionary::writeOptionalEntries) { IOInfoInFunction(dict) << "Optional entry '" << keyword << "' is not present," << " the default value '" << info() << "' will be used." << endl; } return false; } } bool Foam::unitConversion::readIfPresent(Istream& is) { token nextToken(is); is.putBack(nextToken); if (nextToken != token::BEGIN_SQR) return false; const unitConversion units(is); if (!unitConversion::compare(units, *this, false)) { FatalIOErrorInFunction(is) << "The units " << units.info() << " provided do not match " << "the required units " << info() << abort(FatalIOError); } if (debug && (any() || !unitConversion::compare(units, *this, true))) { Info<< "Unit conversion at line " << is.lineNumber() << " of file " << is.name() << " with factor " << units.multiplier_ << endl; } reset(units); return true; } bool Foam::unitConversion::readIfPresent ( const word& keyword, const dictionary& dict, Istream& is ) { token nextToken(is); is.putBack(nextToken); if (nextToken != token::BEGIN_SQR) return false; const unitConversion units(is); if (!unitConversion::compare(units, *this, false)) { 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(units, *this, true))) { Info<< "Unit conversion of " << keyword << " in dictionary " << dict.name() << " with factor " << units.multiplier_ << endl; } reset(units); return true; } // * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * // Foam::Istream& Foam::operator>>(Istream& is, unitConversion& units) { token nextToken; // 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() << ", got a " << nextToken << exit(FatalIOError); } // Peek at the next token is >> nextToken; is.putBack(nextToken); // If not a number or separator, then these are named units. Parse. if (!nextToken.isNumber() && nextToken != token::COLON) { // Named units. Parse. 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; } // 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) { // Peek at the next token is >> nextToken; is.putBack(nextToken); // Read the dimensionless units if present, or set to zero if (!nextToken.isNumber()) { for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { units.exponents_[i] = 0; } } else { for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { 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 is.check("Istream& operator>>(Istream&, unitConversion&)"); return is; } Foam::Ostream& Foam::operator<<(Ostream& os, const unitConversion& units) { // Write the start os << token::BEGIN_SQR; // Write the dimensions units.dimensions_.writeNoBeginOrEnd(os); // Determine if any dimensionless units are non-zero bool nonZeroDimlessUnits = false; for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { nonZeroDimlessUnits = nonZeroDimlessUnits || mag(units.exponents_[i]) > unitConversion::smallExponent; } // Determine if the multiplier is non-unity bool nonUnityMultiplier = units.multiplier_ != 1; // Write a separator if there is anything to follow if (nonZeroDimlessUnits || nonUnityMultiplier) { os << token::SPACE << token::COLON; } // Write the dimensionless units if any are non-zero if (nonZeroDimlessUnits) { for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { os << token::SPACE << units.exponents_[i]; } } // 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::SPACE << units.multiplier_; } // Write the end os << token::END_SQR; // Check state of Ostream os.check("Ostream& operator<<(Ostream&, const unitConversion&)"); return os; } Foam::Ostream& Foam::operator<< ( Ostream& os, const InfoProxy& ip ) { const unitConversion& units = ip.t_; // Filter out special cases if (units.any()) { return os << token::BEGIN_SQR << "" << token::END_SQR; } if (units.none()) { return os << token::BEGIN_SQR << "" << token::END_SQR; } // Write the start os << token::BEGIN_SQR; // Write the dimensions units.dimensions_.writeInfoNoBeginOrEnd(os); // Determine if any dimensionless units are non-zero bool nonZeroDimlessUnits = false; for (int i = 0; i < unitConversion::nDimlessUnits; ++ i) { nonZeroDimlessUnits = nonZeroDimlessUnits || mag(units.exponents_[i]) > unitConversion::smallExponent; } // Determine if the multiplier is non-unity bool nonUnityMultiplier = units.multiplier_ != 1; // Write a separator if there is anything to follow if (nonZeroDimlessUnits || nonUnityMultiplier) { os << token::SPACE << token::COLON; } // Write the dimensionless units if any are non-zero if (nonZeroDimlessUnits) { for (int i=0; i unitConversion::smallExponent) { os << token::SPACE << unitConversion::dimlessUnitTypeNames_ [static_cast(i)]; if (units.exponents_[i] != 1) { os << '^' << units.exponents_[i]; } } } } // 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::SPACE << units.multiplier_; } // Write the end os << token::END_SQR; // Check state of Ostream os.check("Ostream& operator<<(Ostream&, const InfoProxy&)"); return os; } // ************************************************************************* //