diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 3ef3831e163c6b199ffa5bbe3a8f8c3c2a802edb..4b71bd073e4c1dcc5b80af8861f9ac5a5c5a56c5 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -145,6 +145,12 @@ $(expr)/exprEntry/expressionEntryBool.C $(expr)/exprEntry/expressionEntryDimensioned.C $(expr)/exprEntry/expressionEntryStrings.C $(expr)/exprEntry/expressionEntryVectors.C +$(expr)/exprResult/exprResult.C +$(expr)/exprResult/exprResultGlobals.C +$(expr)/exprResult/exprResultDelayed.C +$(expr)/exprResult/exprResultStack.C +$(expr)/exprResult/exprResultStored.C +$(expr)/exprResult/exprResultStoredStack.C $(expr)/exprString/exprString.C $(expr)/exprTools/exprTools.C diff --git a/src/OpenFOAM/expressions/exprResult/exprResult.C b/src/OpenFOAM/expressions/exprResult/exprResult.C new file mode 100644 index 0000000000000000000000000000000000000000..6cf76e2d108b7ebd1aed5ecb924de4e828df5b2f --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResult.C @@ -0,0 +1,735 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprResult.H" +#include "vector.H" +#include "tensor.H" +#include "symmTensor.H" +#include "sphericalTensor.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + defineTypeNameAndDebug(exprResult,0); + + defineRunTimeSelectionTable(exprResult, dictionary); + defineRunTimeSelectionTable(exprResult, empty); + + addToRunTimeSelectionTable(exprResult, exprResult, dictionary); + addToRunTimeSelectionTable(exprResult, exprResult, empty); + +} // End namespace expressions +} // End namespace Foam + + +const Foam::expressions::exprResult Foam::expressions::exprResult::null; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprResult::singleValue::singleValue() +{ + std::memset(static_cast<void*>(this), '\0', sizeof(*this)); +} + + +Foam::expressions::exprResult::singleValue::singleValue +( + const singleValue& val +) +{ + std::memcpy(static_cast<void*>(this), &val, sizeof(*this)); +} + + +void Foam::expressions::exprResult::singleValue::operator= +( + const singleValue& val +) +{ + if (this != &val) + { + // Self-assignment is a no-op + std::memcpy(static_cast<void*>(this), &val, sizeof(*this)); + } +} + + +Foam::expressions::exprResult::exprResult() +: + refCount(), + valType_(), + isUniform_(false), + isPointVal_(false), + noReset_(false), + needsReset_(false), + size_(0), + single_(), + fieldPtr_(nullptr), + objectPtr_(nullptr) +{ + clear(); +} + + +Foam::expressions::exprResult::exprResult(const exprResult& rhs) +: + exprResult() +{ + this->operator=(rhs); +} + + +Foam::expressions::exprResult::exprResult(exprResult&& rhs) +: + exprResult() +{ + this->operator=(std::move(rhs)); +} + + +Foam::expressions::exprResult::exprResult +( + const dictionary& dict, + bool uniform, + bool needsValue +) +: + refCount(), + valType_(dict.getOrDefault<word>("valueType", "")), + isUniform_(dict.getOrDefault("isSingleValue", uniform)), + isPointVal_(dict.getOrDefault("isPointValue", false)), + noReset_(dict.getOrDefault("noReset", false)), + needsReset_(false), + size_(0), + single_(), + fieldPtr_(nullptr), + objectPtr_(nullptr) +{ + DebugInFunction << nl; + + if (dict.found("value")) + { + const label len = + ( + isUniform_ + ? dict.getOrDefault<label>("fieldSize", 1) + : dict.get<label>("fieldSize") + ); + + if (isUniform_) + { + const bool created = + ( + createUniformChecked<bool>("value", dict, len) + || createUniformChecked<scalar>("value", dict, len) + || createUniformChecked<vector>("value", dict, len) + || createUniformChecked<tensor>("value", dict, len) + || createUniformChecked<symmTensor>("value", dict, len) + || createUniformChecked<sphericalTensor>("value", dict, len) + ); + + if (!created) + { + if (valType_.empty()) + { + // For the error message only + valType_ = "None"; + } + + FatalErrorInFunction + << "Don't know how to read data type " + << valType_ + << " as a single value" << nl + << exit(FatalError); + } + } + else + { + const bool created = + ( + createNonUniformChecked<bool>("value", dict, len) + || createNonUniformChecked<scalar>("value", dict, len) + || createNonUniformChecked<vector>("value", dict, len) + || createNonUniformChecked<tensor>("value", dict, len) + || createNonUniformChecked<symmTensor>("value", dict, len) + || createNonUniformChecked<sphericalTensor>("value", dict, len) + ); + + if (!created) + { + if (valType_.empty()) + { + // For the error message only + valType_ = "None"; + } + + FatalErrorInFunction + << "Don't know how to read data type " << valType_ << nl + << exit(FatalError); + } + } + } + else if (needsValue) + { + FatalIOErrorInFunction(dict) + << "No entry 'value' defined in " << dict.name() << nl + << exit(FatalIOError); + } +} + + +Foam::autoPtr<Foam::expressions::exprResult> +Foam::expressions::exprResult::New +( + const dictionary& dict +) +{ + const word resultType + ( + dict.getOrDefault<word>("resultType", "exprResult") + ); + + if (dict.getOrDefault("unsetValue", false)) + { + auto cstrIter = emptyConstructorTablePtr_->cfind(resultType); + + if (!cstrIter.found()) + { + FatalErrorInLookup + ( + "resultType", + resultType, + *emptyConstructorTablePtr_ + ) << exit(FatalError); + } + + DebugInfo + << "Creating unset result of type " << resultType << nl; + + return autoPtr<exprResult>(cstrIter()()); + } + + + auto cstrIter = dictionaryConstructorTablePtr_->cfind(resultType); + + if (!cstrIter.found()) + { + FatalErrorInLookup + ( + "resultType", + resultType, + *dictionaryConstructorTablePtr_ + ) << exit(FatalError); + } + + DebugInfo + << "Creating result of type " << resultType << nl; + + return autoPtr<exprResult>(cstrIter()(dict)); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::expressions::exprResult::~exprResult() +{ + DebugInFunction << nl; + + uglyDelete(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::expressions::exprResult::resetImpl() +{ + clear(); +} + + +bool Foam::expressions::exprResult::reset(bool force) +{ + if (force || !noReset_ || needsReset_) + { + this->resetImpl(); + return true; + } + + return false; +} + + +void Foam::expressions::exprResult::clear() +{ + uglyDelete(); + valType_.clear(); + objectPtr_.reset(); + size_ = 0; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::expressions::exprResult::uglyDelete() +{ + if (fieldPtr_) + { + const bool ok = + ( + deleteChecked<scalar>() + || deleteChecked<vector>() + || deleteChecked<tensor>() + || deleteChecked<symmTensor>() + || deleteChecked<sphericalTensor>() + || deleteChecked<bool>() + ); + + if (!ok) + { + FatalErrorInFunction + << "Unknown type " << valType_ + << " probable memory loss" << nl + << exit(FatalError); + } + + fieldPtr_ = nullptr; + size_ = 0; + } +} + + +Foam::expressions::exprResult +Foam::expressions::exprResult::getUniform +( + const label size, + const bool noWarn, + const bool parRun +) const +{ + if (fieldPtr_ == nullptr) + { + FatalErrorInFunction + << "Not set. Cannot construct uniform value" << nl + << exit(FatalError); + } + + exprResult ret; + + const bool ok = + ( + getUniformChecked<scalar>(ret, size, noWarn, parRun) + || getUniformChecked<vector>(ret, size, noWarn, parRun) + || getUniformChecked<tensor>(ret, size, noWarn, parRun) + || getUniformChecked<symmTensor>(ret, size, noWarn, parRun) + || getUniformChecked<sphericalTensor>(ret, size, noWarn, parRun) + ); + + if (!ok) + { + FatalErrorInFunction + << "Cannot get uniform value for type " << valType_ << nl + << exit(FatalError); + } + + return ret; +} + + +void Foam::expressions::exprResult::testIfSingleValue() +{ + if (fieldPtr_ == nullptr) + { + FatalErrorInFunction + << "Not set. Cannot determine if uniform" << nl + << exit(FatalError); + } + + const bool ok = + ( + setAverageValueChecked<scalar>() + || setAverageValueChecked<vector>() + || setAverageValueChecked<tensor>() + || setAverageValueChecked<symmTensor>() + || setAverageValueChecked<sphericalTensor>() + ); + + if (!ok) + { + if (isBool()) + { + FatalErrorInFunction + << "This specialisation is not implemented" << nl + << exit(FatalError); + } + + FatalErrorInFunction + << "Unknown type " << valType_ << nl + << exit(FatalError); + } +} + + +void Foam::expressions::exprResult::operator=(const exprResult& rhs) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + DebugInFunction << "rhs:" << rhs << nl; + + clear(); + + valType_ = rhs.valType_; + isUniform_ = rhs.isUniform_; + isPointVal_ = rhs.isPointVal_; + single_ = rhs.single_; + + if (rhs.fieldPtr_) + { + const bool ok = + ( + duplicateFieldChecked<scalar>(rhs.fieldPtr_) + || duplicateFieldChecked<vector>(rhs.fieldPtr_) + || duplicateFieldChecked<tensor>(rhs.fieldPtr_) + || duplicateFieldChecked<symmTensor>(rhs.fieldPtr_) + || duplicateFieldChecked<sphericalTensor>(rhs.fieldPtr_) + || duplicateFieldChecked<bool>(rhs.fieldPtr_) + ); + + if (!ok) + { + FatalErrorInFunction + << " Type " << valType_ << " can not be copied" << nl + << exit(FatalError); + } + } + else if (objectPtr_.valid()) + { + FatalErrorInFunction + << "Assignment with general content not possible" << nl + << exit(FatalError); + } +} + + +void Foam::expressions::exprResult::operator=(exprResult&& rhs) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + clear(); + + valType_ = rhs.valType_; + isUniform_ = rhs.isUniform_; + isPointVal_ = rhs.isPointVal_; + noReset_ = rhs.noReset_; + needsReset_ = rhs.needsReset_; + size_ = rhs.size_; + + single_ = rhs.single_; + fieldPtr_ = rhs.fieldPtr_; + + objectPtr_.reset(rhs.objectPtr_.release()); + + rhs.fieldPtr_ = nullptr; // Took ownership of field pointer + rhs.clear(); +} + + +void Foam::expressions::exprResult::writeEntry +( + const word& keyword, + Ostream& os +) const +{ + const bool ok = + ( + writeEntryChecked<scalar>(keyword, os) + || writeEntryChecked<vector>(keyword, os) + || writeEntryChecked<tensor>(keyword, os) + || writeEntryChecked<symmTensor>(keyword, os) + || writeEntryChecked<sphericalTensor>(keyword, os) + || writeEntryChecked<bool>(keyword, os) + ); + + if (!ok) + { + WarningInFunction + << "Unknown data type " << valType_ << endl; + } +} + + +void Foam::expressions::exprResult::writeDict +( + Ostream& os, + const bool subDict +) const +{ + // const auto oldFmt = os.format(IOstream::ASCII); + + DebugInFunction + << Foam::name(this) << nl + << "Format: " + << IOstreamOption::formatNames[os.format()] << nl; + + if (subDict) + { + os.beginBlock(); + } + + os.writeEntry("resultType", valueType()); + os.writeEntryIfDifferent<Switch>("noReset_", false, noReset_); + + if (fieldPtr_ == nullptr) + { + os.writeEntry<Switch>("unsetValue", true); + } + else + { + os.writeEntry("valueType", valType_); + + os.writeEntryIfDifferent<Switch>("isPointValue", false, isPointVal_); + os.writeEntry<Switch>("isSingleValue", isUniform_); + + const bool ok = + ( + writeValueChecked<scalar>(os) + || writeValueChecked<vector>(os) + || writeValueChecked<tensor>(os) + || writeValueChecked<symmTensor>(os) + || writeValueChecked<sphericalTensor>(os) + || writeValueChecked<bool>(os) + ); + + if (!ok) + { + WarningInFunction + << "Unknown data type " << valType_ << endl; + } + } + + if (subDict) + { + os.endBlock(); + } + + // os.format(oldFmt); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +Foam::expressions::exprResult& +Foam::expressions::exprResult::operator*= +( + const scalar& b +) +{ + if (isObject()) + { + FatalErrorInFunction + << "Can only multiply Field-type exprResult. Not " + << valType_ << nl + << exit(FatalError); + } + if (!fieldPtr_) + { + FatalErrorInFunction + << "Can not multiply. Unallocated field of type" << valType_ << nl + << exit(FatalError); + } + + const bool ok = + ( + multiplyEqChecked<scalar>(b) + || multiplyEqChecked<vector>(b) + || multiplyEqChecked<tensor>(b) + || multiplyEqChecked<symmTensor>(b) + || multiplyEqChecked<sphericalTensor>(b) + ); + + if (!ok) + { + FatalErrorInFunction + << "Can not multiply field of type " + << valType_ << nl + << exit(FatalError); + } + + return *this; +} + + +Foam::expressions::exprResult& +Foam::expressions::exprResult::operator+= +( + const exprResult& b +) +{ + if (isObject()) + { + FatalErrorInFunction + << "Can only add Field-type, not type: " + << valType_ << nl + << exit(FatalError); + } + if (!fieldPtr_) + { + FatalErrorInFunction + << "Can not add. Unallocated field of type " << valType_ << nl + << exit(FatalError); + } + + if (this->size() != b.size()) + { + FatalErrorInFunction + << "Different sizes " << this->size() << " and " << b.size() << nl + << exit(FatalError); + } + + const bool ok = + ( + plusEqChecked<scalar>(b) + || plusEqChecked<vector>(b) + || plusEqChecked<tensor>(b) + || plusEqChecked<symmTensor>(b) + || plusEqChecked<sphericalTensor>(b) + ); + + if (!ok) + { + FatalErrorInFunction + << "Can not add Field-type exprResult of type" + << valType_ << nl + << exit(FatalError); + } + + return *this; +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>> +( + Istream& is, + expressions::exprResult& data +) +{ + dictionary dict(is); + + data = expressions::exprResult(dict); + + return is; +} + + +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const expressions::exprResult& data +) +{ + data.writeDict(os); + + return os; +} + + +Foam::expressions::exprResult Foam::operator* +( + const scalar& a, + const expressions::exprResult& b +) +{ + expressions::exprResult result(b); + return result *= a; +} + + +Foam::expressions::exprResult Foam::operator* +( + const expressions::exprResult& a, + const scalar& b +) +{ + expressions::exprResult result(a); + result *= b; + + return result; +} + + +Foam::expressions::exprResult Foam::operator+ +( + const expressions::exprResult& a, + const expressions::exprResult& b +) +{ + expressions::exprResult result(a); + result += b; + + return result; +} + + +const void* Foam::expressions::exprResult::dataAddress() const +{ + #undef defineExpressionMethod + #define defineExpressionMethod(Type) \ + if (isType<Type>()) \ + { \ + return static_cast<Field<Type>*>(fieldPtr_)->cdata(); \ + } + + defineExpressionMethod(scalar); + defineExpressionMethod(vector); + defineExpressionMethod(tensor); + defineExpressionMethod(symmTensor); + defineExpressionMethod(sphericalTensor); + + #undef defineExpressionMethod + + FatalErrorInFunction + << "Unsupported type" << valType_ << nl + << exit(FatalError); + + return nullptr; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResult.H b/src/OpenFOAM/expressions/exprResult/exprResult.H new file mode 100644 index 0000000000000000000000000000000000000000..d5dcf4d2f0eea51d524775f5afd9f5f1794310aa --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResult.H @@ -0,0 +1,562 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprResult + +Description + A polymorphic field/result from evaluating an expression + + \heading Dictionary parameters + \table + Property | Description | Required | Default + resultType | The type of result | no | exprResult + unsetValue | Create without reading the dictionary | no | false + noReset | Suppress reset on time | no | false + \endtable + + When creating with values + \table + Property | Description | Required | Default + valueType | Result value type (scalar, vector,..) | yes | + isSingleValue | A single field value | no | false + isPointValue | Interpret values as point values | no | false + value | The field values | yes | + fieldSize | The size of the field (when not single-value) | no | + \endtable + +SourceFiles + exprResult.C + exprResultI.H + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprResult_H +#define expressions_exprResult_H + +#include "vector.H" +#include "tensor.H" +#include "sphericalTensor.H" +#include "symmTensor.H" +#include "dimensionedType.H" +#include "IOField.H" +#include "runTimeSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprResult Declaration +\*---------------------------------------------------------------------------*/ + +class exprResult +: + public refCount +{ + // Private Data + + //- The value type as string, + //- normally corresponds to pTraits or typeName + word valType_; + + //- Is single, uniform value (can be a non-field) + bool isUniform_; + + //- Is a point value + bool isPointVal_; + + //- Whether or not the variable will be reset + bool noReset_; + + //- Allow override of noReset_, but only accessible for subclasses + bool needsReset_; + + //- Size of field or object + label size_; + + //- A %union of single values, including standard VectorSpace types + union singleValue + { + bool bool_; + scalar scalar_; + vector vector_; + tensor tensor_; + symmTensor symmTensor_; + sphericalTensor sphTensor_; + + //- Construct null, zero-initialized + singleValue(); + + //- Copy construct + singleValue(const singleValue& val); + + //- Copy assignment + void operator=(const singleValue& val); + + //- Return current value for specified type. + template<class T> + inline const T& get() const + { + NotImplemented; + return pTraits<T>::zero; + } + + //- Set new value for specified type. Returns updated value. + template<class T> + inline const T& set(const T& val) + { + NotImplemented; + return pTraits<T>::zero; + } + }; + + //- The single value + singleValue single_; + + //- Allocated plain field (eg, scalarField) + void *fieldPtr_; + + //- Alternative storage for non-plain fields (eg, volScalarField) + autoPtr<regIOobject> objectPtr_; + + + // Private Member Functions + + //- Type-checked deletion of the value pointer. + // \return True if the type check was satisfied + template<class Type> + inline bool deleteChecked(); + + //- Dispatch to type-checked pointer deletion + void uglyDelete(); + + //- Type-checked creation of uniform field from dictionary + // \return True if the type check was satisfied + template<class Type> + inline bool createUniformChecked + ( + const word& key, + const dictionary& dict, + const label len + ); + + //- Type-checked creation of non-uniform field from dictionary + // \return True if the type check was satisfied + template<class Type> + inline bool createNonUniformChecked + ( + const word& key, + const dictionary& dict, + const label len + ); + + //- Type-checked retrieval of uniform field from current results + // \return True if the type check was satisfied + template<class Type> + bool getUniformChecked + ( + exprResult& result, + const label size, + const bool noWarn, + const bool parallel + ) const; + + //- Type-checked determination of centre value (min/max) + // \return True if the type check was satisfied + template<class Type> + bool setAverageValueChecked(); + + //- Type-checked copy of field + // \return True if the type check was satisfied + template<class Type> + bool duplicateFieldChecked(const void* ptr); + + //- Type-checked writing of "value" entry + // \return True if the type check was satisfied + template<class Type> + bool writeValueChecked(Ostream& os) const; + + //- Type-checked forwarding to Field::writeEntry + // \return True if the type check was satisfied + template<class Type> + bool writeEntryChecked(const word& keyword, Ostream& os) const; + + //- Type-checked field addition with another expression field + // \return True if the type check was satisfied + template<class Type> + bool plusEqChecked(const exprResult& b); + + //- Type-checked field multiplication with a scalar + // \return True if the type check was satisfied + template<class Type> + bool multiplyEqChecked(const scalar& b); + + + template<class Type> + inline void setResultImpl(Field<Type>*, bool isPointVal=false); + + template<class Type> + inline void setResultImpl(const Field<Type>&, bool isPointVal=false); + + template<class Type> + inline void setResultImpl(Field<Type>&&, bool isPointVal=false); + + template<class Type> + inline void setResultImpl(const Type& val, const label len); + + template<class Type> + inline void setSingleValueImpl(const Type& val); + + template<class Type> + inline void setObjectResultImpl(Type* ptr); + + template<class Type> + inline void setObjectResultImpl(autoPtr<Type>& ap); + + template<class Type> + inline void setObjectResultImpl(autoPtr<Type>&& ap); + + +protected: + + // Protected Member Functions + + //- Simulate virtual templated methods + inline virtual exprResult& target() { return *this; } + + //- Reset at new timestep according to the derived class type + virtual void resetImpl(); + + //- Reset at new timestep according to type + // \return true if it was actually reset + bool reset(bool force=false); + + //- Adjusts the internal needsReset value + void needsReset(bool val) { needsReset_ = val; } + + +public: + + //- An empty result + static const exprResult null; + + //- Friendship with globals + friend class exprResultGlobals; + + + //- Runtime type information + TypeName("exprResult"); + + declareRunTimeSelectionTable + ( + autoPtr, + exprResult, + dictionary, + ( + const dictionary& dict + ), + (dict) + ); + declareRunTimeSelectionTable + ( + autoPtr, + exprResult, + empty, + (), + () + ); + + + // Constructors + + //- Construct null + exprResult(); + + //- Copy construct + exprResult(const exprResult& expr); + + //- Move construct + exprResult(exprResult&& expr); + + //- Construct from a dictionary + explicit exprResult + ( + const dictionary& dict, + const bool uniform = false, + const bool needsValue = false + ); + + //- Construct by copying a field + template<class Type> + exprResult(const Field<Type>& f); + + //- Construct by moving a field + template<class Type> + exprResult(Field<Type>&& f); + + //- Construct for an IOobject + template<class Type> + exprResult(autoPtr<Type>& ap); + + //- Construct for an IOobject + template<class Type> + exprResult(autoPtr<Type>&& ap); + + //- Construct from a dimensioned value + template<class Type> + exprResult(const dimensioned<Type>& f); + + #undef exprResult_Construct + #define exprResult_Construct(Type) \ + /*! Construct from single value of Type */ \ + explicit exprResult(const Type& val) : exprResult() \ + { \ + setSingleValue(val); \ + } + + exprResult_Construct(bool); + exprResult_Construct(scalar); + exprResult_Construct(vector); + exprResult_Construct(tensor); + exprResult_Construct(symmTensor); + exprResult_Construct(sphericalTensor); + + #undef exprResult_Construct + + + // Selectors + + //- Return a reference to the selected value driver + static autoPtr<exprResult> New(const dictionary& dict); + + //- Clone + virtual autoPtr<exprResult> clone() const + { + return autoPtr<exprResult>::New(*this); + } + + + //- Destructor + virtual ~exprResult(); + + + // Member Functions + + // Access + + //- Has a value? + inline bool hasValue() const; + + //- Basic type for the field or single value + inline const word& valueType() const; + + //- True if representing point values, or test if same as isPointVal + inline bool isPointValue(const bool isPointVal = true) const; + + //- True if single, uniform value + inline bool isUniform() const; + + //- True if valueType corresponds to the given Type + template<class Type> + inline bool isType() const; + + //- True if valueType is a bool + inline bool isBool() const; + + //- True if the object pointer is being used + inline bool isObject() const; + + //- The field or object size + inline label size() const; + + //- The address of the field data content. + // Fatal for unknown types. + // Used, for example, for python integration + const void* dataAddress() const; + + + // Edit + + //- Clear (zero) the result + void clear(); + + //- Change reset behaviour + void noReset() { noReset_ = true; } + + //- Change reset behaviour + void allowReset() { noReset_ = false; } + + //- Test if field corresponds to a single-value and thus uniform. + // Uses field min/max to establish uniformity. + void testIfSingleValue(); + + + + // Set results + + //- Set result field, taking ownership of the pointer + template<class Type> + inline void setResult(Field<Type>*, bool isPointVal=false); + + //- Set result field, taking copy of the field contents + template<class Type> + inline void setResult(const Field<Type>& fld, bool isPointVal=false); + + //- Set result field, moving field contents + template<class Type> + inline void setResult(Field<Type>&&, bool isPointVal=false); + + //- Set uniform result field of given size + template<class Type> + inline void setResult(const Type& val, const label size); + + //- Set single-value uniform result + template<class Type> + inline void setSingleValue(const Type& val); + + template<class Type> + inline void setObjectResult(autoPtr<Type>& o); + + template<class Type> + inline void setObjectResult(autoPtr<Type>&& o); + + + // Access/Get results + + //- Return const reference to the field + template<class Type> + inline const Field<Type>& cref() const; + + //- Return non-const reference to the field + template<class Type> + inline Field<Type>& ref(); + + //- Return non-const reference to the field, casting away constness + template<class Type> + inline Field<Type>& getRef() const; + + //- Return tmp field of the contents, + //- optionally keeping a copy in cache + template<class Type> + inline tmp<Field<Type>> getResult(bool cacheCopy=false); + + //- Get object result (Caution - potentially fragile) + //- optionally keeping a copy in cache + template<class Type> + inline tmp<Type> getObjectResult(bool cacheCopy=false); + + //- Construct a uniform field from the current results + // Uses the field average. Optionally warning if the min/max + // deviation is larger than SMALL. + exprResult getUniform + ( + const label size, + const bool noWarn, + const bool parRun = Pstream::parRun() + ) const; + + //- Get a reduced result + template<template<class> class BinaryOp, class Type> + inline Type getReduced + ( + const BinaryOp<Type>& bop, + const Type& initial = pTraits<Type>::zero + ); + + + // Write + + //- Forwarding to Field::writeEntry + void writeEntry(const word& keyword, Ostream& os) const; + + //- Write entry as dictionary contents + void writeDict(Ostream& os, const bool subDict=true) const; + + + // Member Operators + + //- Copy assignment + virtual void operator=(const exprResult& rhs); + + //- Move assignment + virtual void operator=(exprResult&& rhs); + + + //- Scalar multiplication + exprResult& operator*=(const scalar& b); + + //- Addition of results + exprResult& operator+=(const exprResult& b); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Operators + +expressions::exprResult operator* +( + const scalar& a, + const expressions::exprResult& b +); +expressions::exprResult operator* +( + const expressions::exprResult& a, + const scalar& b +); +expressions::exprResult operator+ +( + const expressions::exprResult& a, + const expressions::exprResult& b +); + + +// IO Operator +Istream& operator>>(Istream& os, expressions::exprResult& data); +Ostream& operator<<(Ostream& os, const expressions::exprResult& data); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "exprResultI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultDelayed.C b/src/OpenFOAM/expressions/exprResult/exprResultDelayed.C new file mode 100644 index 0000000000000000000000000000000000000000..dfd43f13a26b010aed5e7dfb7e0e749d6edbdff4 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultDelayed.C @@ -0,0 +1,333 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprResultDelayed.H" +#include "vector.H" +#include "tensor.H" +#include "symmTensor.H" +#include "sphericalTensor.H" +#include "addToRunTimeSelectionTable.H" + +// #include <cassert> + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + defineTypeNameAndDebug(exprResultDelayed, 0); + + addToRunTimeSelectionTable + ( + exprResult, + exprResultDelayed, + dictionary + ); + addToRunTimeSelectionTable + ( + exprResult, + exprResultDelayed, + empty + ); + +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprResultDelayed::exprResultDelayed() +: + exprResult(), + name_("none"), + startExpr_(), + settingResult_(), + storeInterval_(1), + delay_(10) +{} + + +Foam::expressions::exprResultDelayed::exprResultDelayed +( + const exprResultDelayed& rhs +) +: + exprResult(rhs), + name_(rhs.name_), + startExpr_(rhs.startExpr_), + settingResult_(rhs.settingResult_), + storedValues_(rhs.storedValues_), + storeInterval_(rhs.storeInterval_), + delay_(rhs.delay_) +{} + + +Foam::expressions::exprResultDelayed::exprResultDelayed +( + const dictionary& dict +) +: + exprResult(dict.subOrEmptyDict("value")), + name_(dict.get<word>("name")), + startExpr_(dict.get<string>("startupValue"), dict), + storeInterval_(dict.get<scalar>("storeInterval")), + delay_(dict.get<scalar>("delay")) +{ + const entry *eptr = dict.findEntry("storedValues"); + + if (eptr) + { + storedValues_ = DLList<ValueAtTime>(eptr->stream()); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::expressions::exprResultDelayed::updateReadValue +( + const scalar& timeVal +) +{ + if (storedValues_.empty()) + { + return false; + } + + const ValueAtTime& first = storedValues_.first(); + + if (first.first() > (timeVal-delay_)) + { + // No matching data yet + return false; + } + + if (storedValues_.size() <= 1) + { + FatalErrorInFunction + << "Only one stored value at time " << timeVal + << " for delayedVariable " << name() << nl + << "Check the values for the interval " << storeInterval_ + << " and delay " << delay_ << nl + << "Probably the interval is too large" << nl << endl + << exit(FatalError); + } + + auto current = storedValues_.cbegin(); + auto next = current; + ++next; + + // The time without the delay offset + const scalar newTime = (timeVal - delay_); + + while (next != storedValues_.end()) + { + if (newTime >= current().first() && newTime <= next().first()) + { + break; + } + + current = next; + ++next; + } + + const scalar f = + ( + (newTime - current().first()) + / (next().first() - current().first()) + ); + + exprResult val((1-f)*current().second() + f*next().second()); + + setReadValue(val); + + return true; +} + + +void Foam::expressions::exprResultDelayed::setReadValue +( + const exprResult& val +) +{ + exprResult::operator=(val); +} + + +void Foam::expressions::exprResultDelayed::storeValue +( + const scalar& currTime +) +{ + bool append = storedValues_.empty(); + + if (!append) + { + const scalar lastTime = storedValues_.last().first(); + + if (lastTime + SMALL >= currTime) + { + // Times are essentially identical - replace value + } + else if ((currTime - lastTime) >= 0.999*storeInterval_) + { + append = true; + } + else + { + // Cannot store in the middle - abandon the attempt + return; + } + } + + if (append) + { + // Append value + + const scalar oldLastTime = + ( + storedValues_.empty() + ? 0 + : storedValues_.last().first() + ); + + storedValues_.append(ValueAtTime(currTime, settingResult_)); + + while + ( + storedValues_.size() > 1 + && (oldLastTime - storedValues_.first().first()) >= delay_ + ) + { + // Remove values that are older than delay_ + storedValues_.removeHead(); + } + } + else + { + // Replace value + + storedValues_.last().second() = settingResult_; + } +} + + +void Foam::expressions::exprResultDelayed::writeDict(Ostream& os) const +{ + os.beginBlock(); + + os.writeEntry("name", name_); + + os.writeEntry("startupValue", startExpr_); + + if (!settingResult_.valueType().empty()) + { + os.writeEntry("settingResult", settingResult_); + } + + os.writeEntry("storedValues", storedValues_); + os.writeEntry("storeInterval", storeInterval_); + os.writeEntry("delay", delay_); + + os.writeKeyword("value"); + os << static_cast<const exprResult&>(*this); + + os.endBlock(); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::expressions::exprResultDelayed::operator= +( + const exprResultDelayed& rhs +) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + exprResult::operator=(rhs); + + name_ = rhs.name_; + startExpr_ = rhs.startExpr_; + settingResult_ = rhs.settingResult_; + storedValues_ = rhs.storedValues_; + storeInterval_ = rhs.storeInterval_; + delay_ = rhs.delay_; +} + + +void Foam::expressions::exprResultDelayed::operator= +( + const exprResult& rhs +) +{ + settingResult_ = rhs; +} + + +void Foam::expressions::exprResultDelayed::operator= +( + exprResult&& rhs +) +{ + settingResult_ = std::move(rhs); +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>> +( + Istream& is, + expressions::exprResultDelayed& data +) +{ + dictionary dict(is); + + data = expressions::exprResultDelayed(dict); + + return is; +} + + +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const expressions::exprResultDelayed& data +) +{ + data.writeDict(os); + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultDelayed.H b/src/OpenFOAM/expressions/exprResult/exprResultDelayed.H new file mode 100644 index 0000000000000000000000000000000000000000..c969356e0d22d03974d8b5f687f1e7570aa18da1 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultDelayed.H @@ -0,0 +1,210 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprResultDelayed + +Description + An exprResult with an additional delay before evaluation + + \heading Dictionary parameters + \table + Property | Description | Required | Default + name | The result name | yes | + delay | The delay before starting | yes | + storeInterval | The storage interval (time) | yes | + startupValue | The initial startup value | yes | + value | The expression result (dictionary) | no | + storedValues | The list of stored values | yes | + \endtable + +SourceFiles + exprResultDelayed.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprResultDelayed_H +#define expressions_exprResultDelayed_H + +#include "exprResult.H" +#include "exprString.H" +#include "Tuple2.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprResultDelayed Declaration +\*---------------------------------------------------------------------------*/ + +class exprResultDelayed +: + public expressions::exprResult +{ + // Typedefs + + //- Expression at a given time value. + typedef Tuple2<scalar, expressions::exprResult> ValueAtTime; + + + // Private Data + + //- The name of the expression + word name_; + + //- The initial value expression + expressions::exprString startExpr_; + + //- The pending result to be set + expressions::exprResult settingResult_; + + //- The old results + DLList<ValueAtTime> storedValues_; + + //- How often values should be stored + scalar storeInterval_; + + //- The size of the delay + scalar delay_; + + +protected: + + // Protected Member Functions + + //- Simulate virtual templated methods + inline expressions::exprResult& target() { return settingResult_; } + + +public: + + //- Runtime type information + TypeName("exprResultDelayed"); + + + // Constructors + + //- Construct null + exprResultDelayed(); + + //- Copy construct + exprResultDelayed(const exprResultDelayed&); + + //- Construct from a dictionary + exprResultDelayed(const dictionary& dict); + + //- Clone + virtual autoPtr<exprResult> clone() const + { + return autoPtr<exprResult> + ( + new exprResultDelayed(*this) + ); + } + + + //- Destructor + virtual ~exprResultDelayed() = default; + + + // Member Functions + + //- The expression name + const word& name() const + { + return name_; + } + + //- The initial value expression + const expressions::exprString& startupValueExpression() const + { + return startExpr_; + } + + //- Update the read-value + // return true if there was a valid value. + // this does not do the work of setReadValue because we have no + // access to the Parser + bool updateReadValue(const scalar& timeVal); + + //- Set the readValue with a calculated value + void setReadValue(const exprResult& val); + + //- Add a stored value + void storeValue(const scalar& timeVal); + + + // Write + + void writeDict(Ostream& os) const; + + + // Member Operators + + //- Copy assignment + void operator=(const exprResultDelayed& rhs); + + //- Copy assignment + void operator=(const exprResult& rhs); + + //- Move assignment + void operator=(exprResult&& rhs); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +inline bool operator!= +( + const expressions::exprResultDelayed&, + const expressions::exprResultDelayed& +) +{ + return false; +} + +// IO Operators +Istream& operator>>(Istream& is, expressions::exprResultDelayed& data); +Ostream& operator<<(Ostream& os, const expressions::exprResultDelayed& data); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultGlobals.C b/src/OpenFOAM/expressions/exprResult/exprResultGlobals.C new file mode 100644 index 0000000000000000000000000000000000000000..cd3d302fcba462515283c2b796032f84e27afb84 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultGlobals.C @@ -0,0 +1,334 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprResultGlobals.H" +#include "Time.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + + defineTypeNameAndDebug(exprResultGlobals, 0); + +} // End namespace expressions +} // End namespace Foam + + +Foam::autoPtr<Foam::expressions::exprResultGlobals> + Foam::expressions::exprResultGlobals::singleton_; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprResultGlobals::exprResultGlobals +( + const objectRegistry& obr +) +: + regIOobject + ( + IOobject + ( + "exprResultGlobals", + obr.time().timeName(), + "expressions", + obr.time(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ) + ), + timeIndex_(obr.time().timeIndex()) +{ + if (headerOk()) + { + readData + ( + readStream("exprResultGlobals", true) + ); + } +} + + +Foam::expressions::exprResultGlobals::Table::Table() +: + HashPtrTable<exprResult>() +{} + + +Foam::expressions::exprResultGlobals::Table::Table(const Table& tbl) +: + HashPtrTable<exprResult>(tbl.capacity()) +{ + for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter) + { + this->set(iter.key(), (*iter)->clone()); + } +} + + +Foam::expressions::exprResultGlobals::Table::Table(Table&& tbl) +: + HashPtrTable<exprResult>(std::move(tbl)) +{} + + +Foam::expressions::exprResultGlobals::Table::Table(Istream& is) +: + HashPtrTable<exprResult>(is) +{} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::expressions::exprResultGlobals::reset() +{ + forAllIters(variables_, tablesIter) + { + forAllIters((*tablesIter), iter) + { + (*iter)->reset(); + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::expressions::exprResultGlobals::writeData(Ostream& os) const +{ + // Enforce ASCII to avoid any potential binary issues + const auto oldFmt = os.format(IOstream::ASCII); + + os << variables_; + + os.format(oldFmt); + + return os.good(); +} + + +bool Foam::expressions::exprResultGlobals::readData(Istream& is) +{ + // Enforce ASCII to avoid any potential binary issues + const auto oldFmt = is.format(IOstream::ASCII); + + is >> variables_; + + is.format(oldFmt); + + return !is.bad(); +} + + +Foam::expressions::exprResultGlobals& +Foam::expressions::exprResultGlobals::New +( + const objectRegistry& obr +) +{ + if (!singleton_) + { + singleton_.reset(new exprResultGlobals(obr)); + } + + if (singleton_->timeIndex_ != obr.time().timeIndex()) + { + // Time changes, reset variables + + singleton_->timeIndex_ = obr.time().timeIndex(); + singleton_->reset(); + } + + return *singleton_; +} + + +Foam::expressions::exprResultGlobals::Table& +Foam::expressions::exprResultGlobals::getNamespace(const word& name) +{ + return variables_[name]; +} + + +const Foam::expressions::exprResult& +Foam::expressions::exprResultGlobals::get +( + const word& name, + const wordUList& scopes +) const +{ + for (const word& scopeName : scopes) + { + const auto tableIter = variables_.find(scopeName); + + if (tableIter.found()) + { + const auto resultIter = (*tableIter).find(name); + + if (resultIter.found()) + { + return *(*resultIter); + } + } + #ifdef FULLDEBUG + else + { + WarningInFunction + << "No scope " << scopeName << " for " << name << nl + << "Known global scopes: " << variables_.sortToc() << nl; + } + #endif + } + + return exprResult::null; +} + + +Foam::expressions::exprResult& +Foam::expressions::exprResultGlobals::addValue +( + const word& name, + const word& scope, + const exprResult& value, + const bool overwrite +) +{ + Table& tbl = getOrCreateScope(scope); + + auto iter = tbl.find(name); + + if (!iter.found()) + { + tbl.set(name, new exprResult(value)); + iter = tbl.find(name); + } + else if (overwrite) + { + *(*iter) = value; + } + + return *(*iter); +} + + +Foam::expressions::exprResult& +Foam::expressions::exprResultGlobals::addValue +( + const word& name, + const word& scope, + autoPtr<exprResult>& value, + const bool overwrite +) +{ + Table& tbl = getOrCreateScope(scope); + + if (overwrite || !tbl.found(name)) + { + tbl.set(name, value); + } + + return *tbl[name]; +} + + +Foam::expressions::exprResult& +Foam::expressions::exprResultGlobals::addValue +( + const word& name, + const word& scope, + autoPtr<exprResult>&& value, + const bool overwrite +) +{ + Table& tbl = getOrCreateScope(scope); + + if (overwrite || !tbl.found(name)) + { + tbl.set(name, value); + } + + return *tbl[name]; +} + + +Foam::expressions::exprResult& +Foam::expressions::exprResultGlobals::addValue +( + const dictionary& dict, + const word& scope, + const bool overwrite +) +{ + word scopeName(scope); + + const word name(dict.get<word>("globalName")); + + if (scopeName.empty()) + { + scopeName = dict.get<word>("globalScope"); + } + + if (dict.found("resultType")) + { + return addValue + ( + name, + scopeName, + exprResult::New(dict), + overwrite + ); + } + else + { + return addValue + ( + name, + scopeName, + exprResult(dict, true), + overwrite + ); + } +} + + +bool Foam::expressions::exprResultGlobals::removeValue +( + const word& name, + const word& scope +) +{ + auto iter = variables_.find(scope); + + return (iter.found() && (*iter).erase(name)); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultGlobals.H b/src/OpenFOAM/expressions/exprResult/exprResultGlobals.H new file mode 100644 index 0000000000000000000000000000000000000000..764017b7a6acd5aa021ca25aef6f6a1c8f21d970 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultGlobals.H @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprResultGlobals + +Description + A globally available registry of expression results + +SourceFiles + exprResultGlobals.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprResultGlobals_H +#define expressions_exprResultGlobals_H + +#include "exprResult.H" +#include "autoPtr.H" +#include "HashPtrTable.H" +#include "regIOobject.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprResultGlobals Declaration +\*---------------------------------------------------------------------------*/ + +class exprResultGlobals +: + public regIOobject +{ +public: + + // Public Classes + + //- The table of results + class Table + : + public HashPtrTable<exprResult> + { + public: + + Table(); + Table(const Table& tbl); + Table(Table&& tbl); + Table(Istream& is); + }; + + +private: + + // Private Data + + //- The scoped table of results + HashTable<Table> variables_; + + //- The currently (or previously) used time-index + label timeIndex_; + + //- Only one instance of this repository + static autoPtr<exprResultGlobals> singleton_; + + + // Private Member Functions + + //- Construct + explicit exprResultGlobals(const objectRegistry& obr); + + //- Reset all variables + void reset(); + + //- Get or create a table for the scope + Table& getOrCreateScope(const word& scope) + { + return variables_(scope); + } + + +public: + + //- Runtime type information + TypeName("exprResultGlobals"); + + + // Constructors + + //- Get the singleton + static exprResultGlobals& New(const objectRegistry& obr); + + + //- Destructor + virtual ~exprResultGlobals() = default; + + + // Member Functions + + //- Get an existing table for the namespace + Table& getNamespace(const word& name); + + + //- Return a global variable, if it exists, or a exprResult::null + const exprResult& get + ( + const word& name, + const wordUList& scopes + ) const; + + //- Add named result to specified scope + exprResult& addValue + ( + const word& name, + const word& scope, + const exprResult& value, + const bool overwrite = true + ); + + //- Add named result to specified scope + exprResult& addValue + ( + const word& name, + const word& scope, + autoPtr<exprResult>& value, + const bool overwrite = true + ); + + //- Add named result to specified scope + exprResult& addValue + ( + const word& name, + const word& scope, + autoPtr<exprResult>&& value, + const bool overwrite = true + ); + + //- Extract result from dictionary and add to the scope + // + // Controlled by dictionary entries: + // - globalName (mandatory) + // - globalScope (optional) + // - resultType (optional) + exprResult& addValue + ( + const dictionary& dict, + const word& scope = "", + const bool overwrite = true + ); + + //- Remove named result from specified scope + // \return true if result was removed + bool removeValue + ( + const word& name, + const word& scope + ); + + //- Write variables + virtual bool writeData(Ostream& os) const; + + //- Read variables + virtual bool readData(Istream& os); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultI.H b/src/OpenFOAM/expressions/exprResult/exprResultI.H new file mode 100644 index 0000000000000000000000000000000000000000..2ff92efb8674308e1081f6691a23b18d6da157f0 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultI.H @@ -0,0 +1,790 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * // + +namespace Foam +{ + #undef defineExpressionMethod + #define defineExpressionMethod(Type, Var) \ + template<> inline const Type& \ + expressions::exprResult::singleValue::get<Type>() const \ + { \ + return Var; \ + } \ + \ + template<> inline const Type& \ + expressions::exprResult::singleValue::set(const Type& val) \ + { \ + Var = val; \ + return Var; \ + } + + defineExpressionMethod(bool, bool_); + defineExpressionMethod(scalar, scalar_); + defineExpressionMethod(vector, vector_); + defineExpressionMethod(tensor, tensor_); + defineExpressionMethod(symmTensor, symmTensor_); + defineExpressionMethod(sphericalTensor, sphTensor_); + + #undef defineExpressionMethod +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template<class Type> +inline bool Foam::expressions::exprResult::deleteChecked() +{ + const bool ok = isType<Type>(); + if (ok && fieldPtr_ != nullptr) + { + delete static_cast<Field<Type>*>(fieldPtr_); + fieldPtr_ = nullptr; + size_ = 0; + } + + return ok; +} + + +template<class Type> +inline bool Foam::expressions::exprResult::createUniformChecked +( + const word& key, + const dictionary& dict, + const label len +) +{ + const bool ok = isType<Type>(); + if (ok) + { + uglyDelete(); + + const Type val(dict.get<Type>(key)); + + size_ = len; + fieldPtr_ = new Field<Type>(size_, val); + + single_.set(val); + isUniform_ = true; + } + + return ok; +} + + +template<class Type> +inline bool Foam::expressions::exprResult::createNonUniformChecked +( + const word& key, + const dictionary& dict, + const label len +) +{ + const bool ok = isType<Type>(); + if (ok) + { + uglyDelete(); + + size_ = len; + fieldPtr_ = new Field<Type>(key, dict, size_); + + isUniform_ = false; + } + + return ok; +} + + +template<class Type> +bool Foam::expressions::exprResult::getUniformChecked +( + exprResult& result, + const label size, + const bool noWarn, + const bool parRun +) const +{ + if (!isType<Type>()) + { + return false; + } + + result.clear(); + + const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_); + + const Type avg = (parRun ? gAverage(fld) : average(fld)); + + if (!noWarn) + { + const MinMax<Type> limits = (parRun ? gMinMax(fld) : minMax(fld)); + + if (limits.mag() > SMALL) + { + WarningInFunction + << "Different min/max values: " << limits + << " Using the average " << avg << nl; + } + } + + result.setResult(avg, size); + + return true; +} + + +template<class Type> +bool Foam::expressions::exprResult::plusEqChecked +( + const exprResult& b +) +{ + const bool ok = isType<Type>(); + + if (ok) + { + *static_cast<Field<Type>*>(fieldPtr_) + += *static_cast<const Field<Type>*>(b.fieldPtr_); + } + + return ok; +} + + +template<class Type> +bool Foam::expressions::exprResult::multiplyEqChecked +( + const scalar& b +) +{ + const bool ok = isType<Type>(); + + if (ok) + { + *static_cast<Field<Type>*>(fieldPtr_) *= b; + } + + return ok; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class Type> +Foam::expressions::exprResult::exprResult(const Field<Type>& f) +: + exprResult() +{ + DebugInFunction << nl; + + setResult(f); +} + + +template<class Type> +Foam::expressions::exprResult::exprResult(Field<Type>&& f) +: + exprResult() +{ + DebugInFunction << nl; + + setResult(std::move(f)); +} + + +template<class Type> +Foam::expressions::exprResult::exprResult(autoPtr<Type>& o) +: + exprResult() +{ + setObjectResult(o); +} + + +template<class Type> +Foam::expressions::exprResult::exprResult(autoPtr<Type>&& o) +: + exprResult() +{ + setObjectResult(o); +} + + +template<class Type> +Foam::expressions::exprResult::exprResult(const dimensioned<Type>& f) +: + exprResult() +{ + DebugInFunction << nl; + setSingleValue(f.value()); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline bool Foam::expressions::exprResult::hasValue() const +{ + return (!valType_.empty() && fieldPtr_ != nullptr); +} + + +inline const Foam::word& Foam::expressions::exprResult::valueType() const +{ + return valType_; +} + + +inline bool Foam::expressions::exprResult::isPointValue +( + const bool isPointVal +) const +{ + return isPointVal_ == isPointVal; +} + + +inline bool Foam::expressions::exprResult::isUniform() const +{ + return isUniform_; +} + + +template<class Type> +inline bool Foam::expressions::exprResult::isType() const +{ + return valType_ == pTraits<Type>::typeName; +} + + +inline bool Foam::expressions::exprResult::isBool() const +{ + return valType_ == pTraits<bool>::typeName; +} + + +inline bool Foam::expressions::exprResult::isObject() const +{ + return objectPtr_.valid(); +} + + +inline Foam::label Foam::expressions::exprResult::size() const +{ + return size_; +} + + +template<class Type> +void Foam::expressions::exprResult::setResult +( + const Field<Type>& val, + bool isPointVal +) +{ + DebugInFunction << nl; + + target().setResultImpl(val, isPointVal); +} + + +template<class Type> +void Foam::expressions::exprResult::setResult +( + Field<Type>&& val, + bool isPointVal +) +{ + DebugInFunction << nl; + + target().setResultImpl(val, isPointVal); +} + + +template<class Type> +void Foam::expressions::exprResult::setResultImpl +( + const Field<Type>& fld, + bool isPointVal +) +{ + DebugInFunction << nl; + + clear(); + + isUniform_ = false; + isPointVal_ = isPointVal; + + size_ = fld.size(); + valType_ = pTraits<Type>::typeName; + fieldPtr_ = new Field<Type>(fld); + + DebugInFunction << nl; +} + + +template<class Type> +void Foam::expressions::exprResult::setResultImpl +( + Field<Type>&& fld, + bool isPointVal +) +{ + DebugInFunction << nl; + + clear(); + + isUniform_ = false; + isPointVal_ = isPointVal; + + size_ = fld.size(); + valType_ = pTraits<Type>::typeName; + fieldPtr_ = new Field<Type>(std::move(fld)); + + DebugInFunction << nl; +} + + +template<class Type> +void Foam::expressions::exprResult::setObjectResult(autoPtr<Type>& ap) +{ + target().setObjectResultImpl(ap.ptr()); +} + + +template<class Type> +void Foam::expressions::exprResult::setObjectResult(autoPtr<Type>&& ap) +{ + target().setObjectResultImpl(ap.ptr()); +} + + +template<class T> +void Foam::expressions::exprResult::setObjectResultImpl(T* ptr) +{ + DebugInFunction << nl; + + isUniform_ = false; + isPointVal_ = false; + + size_ = ptr->size(); + valType_ = ptr->typeName; + objectPtr_.reset(ptr); +} + + +template<class T> +void Foam::expressions::exprResult::setObjectResultImpl(autoPtr<T>& o) +{ + setObjectResultImpl(o.ptr()); +} + + +template<class T> +void Foam::expressions::exprResult::setObjectResultImpl(autoPtr<T>&& o) +{ + setObjectResultImpl(o.ptr()); +} + + +template<class Type> +void Foam::expressions::exprResult::setResult +( + Field<Type>* fldPtr, + bool isPointVal +) +{ + target().setResultImpl(fldPtr, isPointVal); +} + + +template<class Type> +void Foam::expressions::exprResult::setResultImpl +( + Field<Type>* fldPtr, + bool isPointVal +) +{ + DebugInFunction << nl; + + clear(); + + isPointVal_ = isPointVal; + isUniform_ = false; + + size_ = fldPtr->size(); + valType_ = pTraits<Type>::typeName; + fieldPtr_ = fldPtr; +} + + +template<class Type> +void Foam::expressions::exprResult::setResult +( + const Type& val, + const label size +) +{ + target().setResultImpl(val, size); +} + + +template<class Type> +void Foam::expressions::exprResult::setResultImpl +( + const Type& val, + const label len +) +{ + DebugInFunction << nl; + + clear(); + + isPointVal_ = false; + + size_ = len; + valType_ = pTraits<Type>::typeName; + fieldPtr_ = new Field<Type>(size_, val); + + isUniform_ = true; + single_.set(val); +} + + +template<class Type> +void Foam::expressions::exprResult::setSingleValue(const Type& val) +{ + target().setSingleValueImpl(val); +} + + +template<class Type> +bool Foam::expressions::exprResult::writeValueChecked(Ostream& os) const +{ + if (!isType<Type>()) + { + return false; + } + + if (this->size() <= 0) + { + if (isUniform_) + { + const Type& val = single_.get<Type>(); + os.writeEntry("value", val); + } + else + { + // Zero-sized + const Field<Type> fld; + fld.writeEntry("value", os); + } + } + else + { + const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_); + + if (isUniform_) + { + os.writeEntry("value", fld.first()); + } + else + { + fld.writeEntry("value", os); + } + } + + return true; +} + + +template<class Type> +bool Foam::expressions::exprResult::writeEntryChecked +( + const word& keyword, + Ostream& os +) const +{ + if (!isType<Type>()) + { + return false; + } + + if (this->size() <= 0) + { + if (isUniform_ && is_contiguous<Type>::value) + { + const Type& val = single_.get<Type>(); + + os << "uniform " << val + << token::END_STATEMENT << nl; + } + else + { + // Zero-sized + const Field<Type> fld; + fld.writeEntry(keyword, os); + } + } + else + { + const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_); + + if (isUniform_ && is_contiguous<Type>::value) + { + os << "uniform " << fld.first() + << token::END_STATEMENT << nl; + } + else + { + fld.writeEntry(keyword, os); + } + } + + return true; +} + + +template<class Type> +bool Foam::expressions::exprResult::setAverageValueChecked() +{ + if (!isType<Type>()) + { + return false; + } + + const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_); + + const MinMax<Type> limits = gMinMax(fld); + + isUniform_ = (limits.mag() <= SMALL); + + const Type avg = limits.centre(); + + single_.set(avg); + + return true; +} + + +template<class Type> +bool Foam::expressions::exprResult::duplicateFieldChecked(const void* ptr) +{ + if (!isType<Type>()) + { + return false; + } + + if (fieldPtr_) + { + deleteChecked<Type>(); + } + + const Field<Type>& fld = *static_cast<const Field<Type>*>(ptr); + + size_ = fld.size(); + fieldPtr_ = new Field<Type>(fld); + + return true; +} + + +template<class Type> +void Foam::expressions::exprResult::setSingleValueImpl(const Type& val) +{ + DebugInFunction << nl; + + clear(); + + isPointVal_ = false; + isUniform_ = true; + + single_.set(val); + size_ = 1; + + valType_ = pTraits<Type>::typeName; + fieldPtr_ = new Field<Type>(size_, val); +} + + +template<class Type> +inline Foam::tmp<Foam::Field<Type>> +Foam::expressions::exprResult::getResult(bool cacheCopy) +{ + DebugInFunction << nl; + + if (!isType<Type>()) + { + FatalErrorInFunction + << "The expected return type " << pTraits<Type>::typeName + << " is different from the stored result type " + << valType_ << nl << nl + << exit(FatalError); + } + + if (fieldPtr_ == nullptr) + { + FatalErrorInFunction + << "Cannot create tmp from nullptr." << nl + << "This error message should never appear!!" << nl + << exit(FatalError); + } + + Field<Type>* ptr = static_cast<Field<Type>*>(fieldPtr_); + + if (cacheCopy) + { + // Leave field intact, return a duplicate field + // Or return reference instead?? + return tmp<Field<Type>>::New(*ptr); + } + + + tmp<Field<Type>> result(ptr); + + fieldPtr_ = nullptr; // Took ownership of field pointer + clear(); + + return result; +} + + +template<class Type> +inline const Foam::Field<Type>& +Foam::expressions::exprResult::cref() const +{ + DebugInFunction << nl; + + if (!isType<Type>()) + { + FatalErrorInFunction + << "The expected return type " << pTraits<Type>::typeName + << " is different from the stored result type " + << valType_ << nl << nl + << exit(FatalError); + } + + if (fieldPtr_ == nullptr) + { + FatalErrorInFunction + << "Cannot return reference from nullptr." << nl + << "This error message should never appear!!" << nl + << exit(FatalError); + } + + return *static_cast<const Field<Type>*>(fieldPtr_); +} + + +template<class Type> +inline Foam::Field<Type>& +Foam::expressions::exprResult::ref() +{ + return const_cast<Field<Type>&>(this->cref<Type>()); +} + + +template<class Type> +inline Foam::Field<Type>& +Foam::expressions::exprResult::getRef() const +{ + return const_cast<Field<Type>&>(this->cref<Type>()); +} + + +template<class Type> +inline Foam::tmp<Type> +Foam::expressions::exprResult::getObjectResult(bool cacheCopy) +{ + DebugInFunction << nl; + + if (!isType<Type>()) + { + FatalErrorInFunction + << "The expected return type " << pTraits<Type>::typeName + << " is different from the stored result type " + << valType_ << nl << nl + << exit(FatalError); + } + + Type* ptr = dynamic_cast<Type*>(objectPtr_.get()); + + if (!ptr) + { + WarningInFunction + << "Cannot cast object pointer to " << pTraits<Type>::typeName + << nl << nl; + + return nullptr; + } + + if (cacheCopy) + { + // Return duplicated content + return tmp<Type>::New(*ptr); + } + + objectPtr_.release(); // Take ownership in ptr + + clear(); + + return tmp<Type>(ptr); +} + + +template<template<class> class BinaryOp, class Type> +inline Type Foam::expressions::exprResult::getReduced +( + const BinaryOp<Type>& bop, + const Type& initial +) +{ + if (!isType<Type>()) + { + FatalErrorInFunction + << "The expected return type " << pTraits<Type>::typeName + << " is different from the stored result type " + << valType_ << nl << nl + << exit(FatalError); + } + + Type result = initial; + + const Field<Type>& fld = *static_cast<Field<Type>*>(fieldPtr_); + + for (const Type& val : fld) + { + result = bop(result, val); + } + + return returnReduce(result, bop); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStack.C b/src/OpenFOAM/expressions/exprResult/exprResultStack.C new file mode 100644 index 0000000000000000000000000000000000000000..3431d27535769650884d2f84c65243ede6cffe61 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStack.C @@ -0,0 +1,207 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprResultStack.H" +#include "vector.H" +#include "tensor.H" +#include "symmTensor.H" +#include "sphericalTensor.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + + defineTypeNameAndDebug(exprResultStack, 0); + addToRunTimeSelectionTable + ( + exprResult, + exprResultStack, + dictionary + ); + addToRunTimeSelectionTable + ( + exprResult, + exprResultStack, + empty + ); + +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprResultStack::exprResultStack() +: + expressions::exprResult() +{ + needsReset(true); // Requires reset every timestep to work +} + + +Foam::expressions::exprResultStack::exprResultStack +( + const exprResultStack& rhs +) +: + expressions::exprResult(rhs) +{ + needsReset(true); // Requires reset every timestep to work +} + + +Foam::expressions::exprResultStack::exprResultStack +( + const dictionary &dict +) +: + expressions::exprResult(dict) +{ + needsReset(true); // Requires reset every timestep to work +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::expressions::exprResult +Foam::expressions::exprResultStack::pop() +{ + exprResult result; + + if (this->size() <= 0) + { + FatalErrorInFunction + << "Trying to pop result from a empty queue" << endl + << abort(FatalError); + + return result; + } + + const bool ok = + ( + popChecked<scalar>(result) + || popChecked<vector>(result) + || popChecked<tensor>(result) + || popChecked<symmTensor>(result) + || popChecked<sphericalTensor>(result) + ); + + if (!ok) + { + FatalErrorInFunction + << "Unsupported value type " << valueType() << nl + << abort(FatalError); + } + + return result; +} + + +void Foam::expressions::exprResultStack::push(const exprResult& result) +{ + DebugInFunction << nl << "Pushing: " << result << nl; + + if (!hasValue()) + { + // This is the first push + exprResult::operator=(result); + } + else + { + if (valueType() != result.valueType()) + { + FatalErrorInFunction + << "Type of pushed value " << result.valueType() + << " is not the expected type " << valueType() << nl + << abort(FatalError); + } + + const bool ok = + ( + pushChecked<scalar>(result) + || pushChecked<vector>(result) + || pushChecked<tensor>(result) + || pushChecked<symmTensor>(result) + || pushChecked<sphericalTensor>(result) + ); + + if (!ok) + { + FatalErrorInFunction + << "Unsupported value type " << valueType() << nl + << abort(FatalError); + } + } + + DebugInFunction << "After push: " << *this << nl; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::expressions::exprResultStack::operator= +( + const exprResultStack& rhs +) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + static_cast<exprResult&>(*this) = rhs; +} + + +void Foam::expressions::exprResultStack::operator= +( + const exprResult& rhs +) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + DebugInFunction << nl; + + exprResult exprValue + ( + // Issue warning if the other result is not really uniform + rhs.getUniform(1, false) + ); + + this->push(exprValue); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStack.H b/src/OpenFOAM/expressions/exprResult/exprResultStack.H new file mode 100644 index 0000000000000000000000000000000000000000..6efdd0b1279e74a2d97e10ba4ffc0ab5deacb2a6 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStack.H @@ -0,0 +1,140 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprResultStack + +Description + A stack of polymorphic fields. + Can be used to build a list of results one at a time. + +SourceFiles + exprResultStack.C + exprResultStackTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprResultStack_H +#define expressions_exprResultStack_H + +#include "exprResult.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprResultStack Declaration +\*---------------------------------------------------------------------------*/ + +class exprResultStack +: + public expressions::exprResult +{ + // Private Data + + //- Type-checked pop value. + // \return True if the type check was satisfied + template<class T> + bool popChecked(exprResult& result); + + //- Type-checked push value. + // \return True if the type check was satisfied + template<class T> + bool pushChecked(const exprResult& result); + + +public: + + //- Runtime type information + TypeName("exprResultStack"); + + + // Constructors + + //- Construct null + exprResultStack(); + + //- Copy construct + exprResultStack(const exprResultStack& rhs); + + //- Construct from a dictionary + explicit exprResultStack(const dictionary& dict); + + + // Selectors + + virtual autoPtr<exprResult> clone() const + { + return autoPtr<exprResult> + ( + new exprResultStack(*this) + ); + } + + + //- Destructor + virtual ~exprResultStack() = default; + + + // Member Functions + + //- Pop the last value as an expression result + exprResult pop(); + + //- Push an expression result value + void push(const exprResult& result); + + + // Member Operators + + //- Copy assignment + void operator=(const exprResultStack& rhs); + + //- Copy assignment + void operator=(const exprResult& rhs); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "exprResultStackTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStackTemplates.C b/src/OpenFOAM/expressions/exprResult/exprResultStackTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..e85d66c9fefba901d35f9632ac59159600b779a1 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStackTemplates.C @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +template<class T> +bool Foam::expressions::exprResultStack::pushChecked +( + const exprResult& result +) +{ + if (!isType<T>()) + { + return false; + } + + // The value to push + T val(Zero); + + const Field<T>& resultField = result.cref<T>(); + + if (!resultField.empty()) + { + val = resultField.first(); + } + + this->ref<T>().append(val); + + return true; +} + + +template<class T> +bool Foam::expressions::exprResultStack::popChecked +( + exprResult& result +) +{ + if (!isType<T>()) + { + return false; + } + + // The popped value + T val(Zero); + + Field<T>& oldField = this->ref<T>(); + + if (!oldField.empty()) + { + val = oldField.last(); + oldField.resize(oldField.size()-1); + } + + result.setSingleValue(val); + + return true; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStored.C b/src/OpenFOAM/expressions/exprResult/exprResultStored.C new file mode 100644 index 0000000000000000000000000000000000000000..9530ea9026fe33e9190cfcb73bfee05fd47434c0 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStored.C @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprResultStored.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + defineTypeNameAndDebug(exprResultStored, 0); + + addToRunTimeSelectionTable + ( + exprResult, + exprResultStored, + dictionary + ); + addToRunTimeSelectionTable + ( + exprResult, + exprResultStored, + empty + ); + +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprResultStored::exprResultStored() +: + expressions::exprResult(), + name_("none"), + startExpr_() +{} + + +Foam::expressions::exprResultStored::exprResultStored +( + const exprResultStored& rhs +) +: + expressions::exprResult(rhs), + name_(rhs.name_), + startExpr_(rhs.startExpr_) +{} + + +Foam::expressions::exprResultStored::exprResultStored +( + const dictionary& dict +) +: + expressions::exprResult(dict.subOrEmptyDict("value")), + name_(dict.get<word>("name")), + startExpr_(dict.get<string>("initialValue"), dict) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::expressions::exprResultStored::writeDict(Ostream& os) const +{ + os.beginBlock(); + + os.writeEntry("name", name_); + os.writeEntry("initialValue", startExpr_); + + os.writeKeyword("value"); + os << static_cast<const exprResult&>(*this); + + os.endBlock(); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::expressions::exprResultStored::operator= +( + const exprResultStored& rhs +) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + this->exprResult::operator=(rhs); + + name_ = rhs.name_; + startExpr_ = rhs.startExpr_; +} + + +void Foam::expressions::exprResultStored::operator= +( + const exprResult& rhs +) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + this->exprResult::operator=(rhs); +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>> +( + Istream& is, + expressions::exprResultStored& data +) +{ + dictionary dict(is); + data = expressions::exprResultStored(dict); + + return is; +} + + +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const expressions::exprResultStored& data +) +{ + data.writeDict(os); + + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStored.H b/src/OpenFOAM/expressions/exprResult/exprResultStored.H new file mode 100644 index 0000000000000000000000000000000000000000..5d0a9a07d1e8a8eb1cf5f2f972a93f237c16ff9f --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStored.H @@ -0,0 +1,174 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprResultStored + +Description + An exprResult with persistence. + + \heading Dictionary parameters + \table + Property | Description | Required | Default + name | The result name | yes | + initialValue | The initial value | yes | + value | The expression result (dictionary) | no | + \endtable + +SourceFiles + StoredExpressionResult.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprResultStored_H +#define expressions_exprResultStored_H + +#include "exprResult.H" +#include "exprString.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprResultStored Declaration +\*---------------------------------------------------------------------------*/ + +class exprResultStored +: + public expressions::exprResult +{ + // Private Data + + //- The name of the expression + word name_; + + //- The initial value expression + expressions::exprString startExpr_; + + +protected: + + // Protected Member Functions + + //- Reset at new timestep - disabling locally + virtual void resetImpl() {} + + +public: + + //- Runtime type information + TypeName("exprResultStored"); + + + // Constructors + + //- Construct null + exprResultStored(); + + //- Copy construct + exprResultStored(const exprResultStored& rhs); + + //- Construct from a dictionary + explicit exprResultStored(const dictionary& dict); + + + // Selectors + + virtual autoPtr<exprResult> clone() const + { + return autoPtr<exprResult> + ( + new exprResultStored(*this) + ); + } + + + //- Destructor + virtual ~exprResultStored() = default; + + + // Member Functions + + //- The name of the expression + const word& name() const + { + return name_; + } + + //- The initial value expression + const expressions::exprString& initialValueExpression() const + { + return startExpr_; + } + + + void writeDict(Ostream& os) const; + + + // Member Operators + + //- Copy assignment + void operator=(const exprResultStored& rhs); + + //- Copy assignment + void operator=(const exprResult& rhs); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// IO Operators +Istream& operator>>(Istream& is, expressions::exprResultStored& data); +Ostream& operator<<(Ostream& is, const expressions::exprResultStored& data); + +// Comparison +inline bool operator!= +( + const expressions::exprResultStored& a, + const expressions::exprResultStored& b +) +{ + return (&a != &b); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.C b/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.C new file mode 100644 index 0000000000000000000000000000000000000000..528b71ebdf3c106b0c2c3fa81b726becb3be40a8 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.C @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprResultStoredStack.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + + defineTypeNameAndDebug(exprResultStoredStack,0); + + addToRunTimeSelectionTable + ( + exprResult, + exprResultStoredStack, + dictionary + ); + addToRunTimeSelectionTable + ( + exprResult, + exprResultStoredStack, + empty + ); + +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprResultStoredStack::exprResultStoredStack() +: + expressions::exprResultStack() +{ + needsReset(false); // Override parent: does not reset every timestep +} + + +Foam::expressions::exprResultStoredStack::exprResultStoredStack +( + const exprResultStoredStack& rhs +) +: + expressions::exprResultStack(rhs) +{ + needsReset(false); // Override parent: does not reset every timestep +} + + +Foam::expressions::exprResultStoredStack::exprResultStoredStack +( + const dictionary& dict +) +: + expressions::exprResultStack(dict) +{ + needsReset(false); // Override parent: does not reset every timestep +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::expressions::exprResultStoredStack::operator= +( + const exprResultStoredStack& rhs +) +{ + if (this == &rhs) + { + return; // Self-assignment is a no-op + } + + exprResultStack::operator=(rhs); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H b/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H new file mode 100644 index 0000000000000000000000000000000000000000..8475e49f8fe7fd1d229c7f53b4e79b28b9cceaa6 --- /dev/null +++ b/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprResultStoredStack + +Description + An exprResultStack with persistence. + +SourceFiles + exprResultStoredStack.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprResultStoredStack_H +#define expressions_exprResultStoredStack_H + +#include "exprResultStack.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprResultStoredStack Declaration +\*---------------------------------------------------------------------------*/ + +class exprResultStoredStack +: + public expressions::exprResultStack +{ +protected: + + // Protected Member Functions + + //- Reset at new timestep - disabling locally + virtual void resetImpl() {} + + +public: + + //- Runtime type information + TypeName("exprResultStoredStack"); + + + // Constructors + + //- Construct null + exprResultStoredStack(); + + //- Copy construct + exprResultStoredStack(const exprResultStoredStack& rhs); + + //- Construct from a dictionary + explicit exprResultStoredStack(const dictionary& dict); + + + // Selectors + + virtual autoPtr<exprResult> clone() const + { + return autoPtr<exprResult> + ( + new exprResultStoredStack(*this) + ); + } + + + //- Destructor + virtual ~exprResultStoredStack() = default; + + + // Member Operators + + //- Copy assignment + void operator=(const exprResultStoredStack& rhs); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* //