diff --git a/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C b/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C index 887255a294..f417b3a24a 100644 --- a/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C +++ b/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2016 OpenCFD Ltd. + Copyright (C) 2016-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -47,7 +47,7 @@ void Foam::interpolation2DTable::readTable() } // Check that the data are in ascending order - checkOrder(); + check(); } @@ -56,7 +56,7 @@ void Foam::interpolation2DTable::readTable() template Foam::interpolation2DTable::interpolation2DTable() : - List>>>(), + List(), bounding_(bounds::normalBounding::WARN), fileName_("fileNameIsUndefined"), reader_(nullptr) @@ -71,7 +71,7 @@ Foam::interpolation2DTable::interpolation2DTable const fileName& fName ) : - List>>>(values), + List(values), bounding_(bounding), fileName_(fName), reader_(nullptr) @@ -81,7 +81,7 @@ Foam::interpolation2DTable::interpolation2DTable template Foam::interpolation2DTable::interpolation2DTable(const fileName& fName) : - List>>>(), + List(), bounding_(bounds::normalBounding::WARN), fileName_(fName), reader_(new openFoamTableReader(dictionary())) @@ -93,7 +93,7 @@ Foam::interpolation2DTable::interpolation2DTable(const fileName& fName) template Foam::interpolation2DTable::interpolation2DTable(const dictionary& dict) : - List>>>(), + List(), bounding_ ( bounds::normalBoundingNames.lookupOrDefault @@ -104,7 +104,7 @@ Foam::interpolation2DTable::interpolation2DTable(const dictionary& dict) true // Failsafe behaviour ) ), - fileName_(dict.lookup("file")), + fileName_(dict.get("file")), reader_(tableReader::New(dict)) { readTable(); @@ -117,121 +117,28 @@ Foam::interpolation2DTable::interpolation2DTable const interpolation2DTable& interpTable ) : - List>>>(interpTable), + List(interpTable), bounding_(interpTable.bounding_), fileName_(interpTable.fileName_), reader_(interpTable.reader_) // note: steals reader. Used in write(). {} - // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template Type Foam::interpolation2DTable::interpolateValue ( - const List>& data, - const scalar lookupValue + const List>& list, + scalar lookupValue ) const { - const label n = data.size(); - - const scalar minLimit = data.first().first(); - const scalar maxLimit = data.last().first(); - - if (lookupValue < minLimit) - { - switch (bounding_) - { - case bounds::normalBounding::ERROR: - { - FatalErrorInFunction - << "value (" << lookupValue << ") less than lower " - << "bound (" << minLimit << ")" << nl - << exit(FatalError); - break; - } - case bounds::normalBounding::WARN: - { - WarningInFunction - << "value (" << lookupValue << ") less than lower " - << "bound (" << minLimit << ")" << nl - << " Continuing with the first entry" - << endl; - - // Behaviour as per CLAMP - return data.first().second(); - break; - } - case bounds::normalBounding::CLAMP: - { - return data.first().second(); - break; - } - } - } - else if (lookupValue >= maxLimit) - { - switch (bounding_) - { - case bounds::normalBounding::ERROR: - { - FatalErrorInFunction - << "value (" << lookupValue << ") greater than upper " - << "bound (" << maxLimit << ")" << nl - << exit(FatalError); - break; - } - case bounds::normalBounding::WARN: - { - WarningInFunction - << "value (" << lookupValue << ") greater than upper " - << "bound (" << maxLimit << ")" << nl - << " Continuing with the last entry" - << endl; - - // Behaviour as per CLAMP - return data.last().second(); - break; - } - case bounds::normalBounding::CLAMP: - { - return data.last().second(); - break; - } - } - } - - // look for the correct range in X - label lo = 0; - label hi = 0; - - for (label i = 0; i < n; ++i) - { - if (lookupValue >= data[i].first()) - { - lo = hi = i; - } - else - { - hi = i; - break; - } - } - - if (lo == hi) - { - return data[lo].second(); - } - else - { - Type m = - (data[hi].second() - data[lo].second()) - /(data[hi].first() - data[lo].first()); - - // normal interpolation - return data[lo].second() + m*(lookupValue - data[lo].first()); - } + return interpolationTable::interpolateValue + ( + list, + lookupValue, + bounds::repeatableBounding(bounding_) + ); } @@ -244,7 +151,7 @@ Foam::label Foam::interpolation2DTable::Xi const bool reverse ) const { - const table& t = *this; + const List& t = *this; label limitI = 0; if (reverse) @@ -259,15 +166,14 @@ Foam::label Foam::interpolation2DTable::Xi case bounds::normalBounding::ERROR: { FatalErrorInFunction - << "value (" << valueX << ") out of bounds" + << "value (" << valueX << ") out of bounds" << nl << exit(FatalError); break; } case bounds::normalBounding::WARN: { WarningInFunction - << "value (" << valueX << ") out of bounds" - << endl; + << "value (" << valueX << ") out of bounds" << nl; // Behaviour as per CLAMP return limitI; @@ -290,11 +196,11 @@ Foam::label Foam::interpolation2DTable::Xi label i = 0; if (reverse) { - label nX = t.size(); + const label nX = t.size(); i = 0; while ((i < nX) && (valueX > t[i].first())) { - i++; + ++i; } } else @@ -302,7 +208,7 @@ Foam::label Foam::interpolation2DTable::Xi i = t.size() - 1; while ((i > 0) && (valueX < t[i].first())) { - i--; + --i; } } @@ -319,66 +225,61 @@ Type Foam::interpolation2DTable::operator() const scalar valueY ) const { - // Considers all of the list in Y being equal - const label nX = this->size(); + const List& t = *this; - const table& t = *this; + // Assumes all of the list in Y being equal length + const label nX = t.size(); if (nX == 0) { WarningInFunction - << "cannot interpolate a zero-sized table - returning zero" << endl; + << "Cannot interpolate zero-sized table - returning zero" << nl; return Zero; } else if (nX == 1) { - // only 1 column (in X) - interpolate to find Y value + // Only 1 column (in X) - simply interpolate to find Y value return interpolateValue(t.first().second(), valueY); } - else + + + // Find low and high indices in the X range that bound valueX + const label lo = Xi(lessOp(), valueX, false); + const label hi = Xi(greaterOp(), valueX, true); + + if (lo == hi) { - // have 2-D data, interpolate - - // find low and high indices in the X range that bound valueX - const label x0i = Xi(lessOp(), valueX, false); - const label x1i = Xi(greaterOp(), valueX, true); - - if (x0i == x1i) - { - return interpolateValue(t[x0i].second(), valueY); - } - else - { - Type y0(interpolateValue(t[x0i].second(), valueY)); - Type y1(interpolateValue(t[x1i].second(), valueY)); - - // gradient in X - const scalar x0 = t[x0i].first(); - const scalar x1 = t[x1i].first(); - Type mX = (y1 - y0)/(x1 - x0); - - // interpolate - return y0 + mX*(valueX - x0); - } + return interpolateValue(t[lo].second(), valueY); } + + + // Normal interpolation + + const Type y0(interpolateValue(t[lo].second(), valueY)); + const Type y1(interpolateValue(t[hi].second(), valueY)); + + const scalar& x0 = t[lo].first(); + const scalar& x1 = t[hi].first(); + + return (y0 + (y1 - y0)*(valueX - x0)/(x1 - x0)); } template -void Foam::interpolation2DTable::checkOrder() const +void Foam::interpolation2DTable::check() const { - const label n = this->size(); - const table& t = *this; + const List& list = *this; - scalar prevValue = t[0].first(); + scalar prevValue(0); - for (label i=1; i::checkOrder() const << exit(FatalError); } prevValue = currValue; + ++i; } } diff --git a/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.H b/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.H index a515dcd832..10aae764b6 100644 --- a/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.H +++ b/src/OpenFOAM/interpolations/interpolation2DTable/interpolation2DTable.H @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,8 +28,8 @@ Class Foam::interpolation2DTable Description - 2D table interpolation. The data must be in ascending order in both - dimensions x and y. + 2D table interpolation. + The data must be in ascending order in both dimensions x and y. SourceFiles interpolation2DTable.C @@ -38,10 +39,7 @@ SourceFiles #ifndef interpolation2DTable_H #define interpolation2DTable_H -#include "List.H" -#include "Tuple2.H" -#include "tableBounds.H" -#include "tableReader.H" +#include "interpolationTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -57,17 +55,7 @@ class interpolation2DTable : public List>>> { -public: - - // Public data types - - //- Convenience typedef - typedef List>>> table; - - -private: - - // Private data + // Private Data //- Handling for out-of-bound values bounds::normalBounding bounding_; @@ -84,11 +72,11 @@ private: //- Read the table of data from file void readTable(); - //- Return interpolated value in List + //- Interpolated value within 1-D list Type interpolateValue ( - const List>& data, - const scalar + const List>& list, + scalar lookupValue ) const; //- Return an X index from the matrix @@ -103,6 +91,15 @@ private: public: + // Public Data Types + + //- The element data type + typedef Tuple2>> value_type; + + //- Convenience typedef + typedef List>>> table; + + // Constructors //- Construct null @@ -117,12 +114,12 @@ public: ); //- Construct given the name of the file containing the table of data - interpolation2DTable(const fileName& fName); + explicit interpolation2DTable(const fileName& fName); //- Construct by reading file name and outOfBounds from dictionary - interpolation2DTable(const dictionary& dict); + explicit interpolation2DTable(const dictionary& dict); - //- Construct copy + //- Copy construct interpolation2DTable(const interpolation2DTable& interpTable); @@ -130,7 +127,7 @@ public: //- Check that list is monotonically increasing // Exit with a FatalError if there is a problem - void checkOrder() const; + void check() const; //- Write void write(Ostream& os) const; @@ -138,11 +135,15 @@ public: // Member Operators - //- Return an element of constant List> - const List>& operator[](const label) const; - //- Return an interpolated value Type operator()(const scalar valueX, const scalar valueY) const; + + + // Housekeeping + + //- Deprecated(2019-08) check list is monotonically increasing + // \deprecated(2019-08) - older name for check() method + void checkOrder() const { check(); } }; diff --git a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C index 7d85a7bc9a..e101a55668 100644 --- a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C +++ b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.C @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -59,7 +60,7 @@ void Foam::interpolationTable::readTable() template Foam::interpolationTable::interpolationTable() : - List>(), + List(), bounding_(bounds::repeatableBounding::WARN), fileName_("fileNameIsUndefined"), reader_(nullptr) @@ -74,7 +75,7 @@ Foam::interpolationTable::interpolationTable const fileName& fName ) : - List>(values), + List(values), bounding_(bounding), fileName_(fName), reader_(nullptr) @@ -84,7 +85,7 @@ Foam::interpolationTable::interpolationTable template Foam::interpolationTable::interpolationTable(const fileName& fName) : - List>(), + List(), bounding_(bounds::repeatableBounding::WARN), fileName_(fName), reader_(new openFoamTableReader(dictionary())) @@ -96,7 +97,7 @@ Foam::interpolationTable::interpolationTable(const fileName& fName) template Foam::interpolationTable::interpolationTable(const dictionary& dict) : - List>(), + List(), bounding_ ( bounds::repeatableBoundingNames.lookupOrDefault @@ -107,7 +108,7 @@ Foam::interpolationTable::interpolationTable(const dictionary& dict) true // Failsafe behaviour ) ), - fileName_(dict.lookup("file")), + fileName_(dict.get("file")), reader_(tableReader::New(dict)) { readTable(); @@ -120,7 +121,7 @@ Foam::interpolationTable::interpolationTable const interpolationTable& interpTable ) : - List>(interpTable), + List(interpTable), bounding_(interpTable.bounding_), fileName_(interpTable.fileName_), reader_(interpTable.reader_) // note: steals reader. Used in write(). @@ -133,16 +134,17 @@ Foam::interpolationTable::interpolationTable template void Foam::interpolationTable::check() const { - const label n = this->size(); - scalar prevValue = this->first().first(); + const List& list = *this; - for (label i=1; i>::operator[](i).first(); + const scalar& currValue = item.first(); - // avoid duplicate values (divide-by-zero error) - if (currValue <= prevValue) + // Avoid duplicate values (divide-by-zero error) + if (i && currValue <= prevValue) { FatalErrorInFunction << "out-of-order value: " @@ -150,6 +152,7 @@ void Foam::interpolationTable::check() const << exit(FatalError); } prevValue = currValue; + ++i; } } @@ -167,19 +170,20 @@ void Foam::interpolationTable::write(Ostream& os) const template -Type Foam::interpolationTable::rateOfChange(const scalar value) const +Type Foam::interpolationTable::rateOfChange(scalar lookupValue) const { - label n = this->size(); + const List& list = *this; + + const label n = list.size(); if (n <= 1) { - // There are not enough entries to provide a rate of change - return 0; + // Not enough entries for a rate of change + return Zero; } - const scalar minLimit = this->first().first(); - const scalar maxLimit = this->last().first(); - scalar lookupValue = value; + const scalar minLimit = list.first().first(); + const scalar maxLimit = list.last().first(); if (lookupValue < minLimit) { @@ -188,31 +192,32 @@ Type Foam::interpolationTable::rateOfChange(const scalar value) const case bounds::repeatableBounding::ERROR: { FatalErrorInFunction - << "value (" << lookupValue << ") underflow" << nl + << "value (" << lookupValue << ") less than lower " + << "bound (" << minLimit << ")\n" << exit(FatalError); break; } case bounds::repeatableBounding::WARN: { WarningInFunction - << "value (" << lookupValue << ") underflow" << nl - << " Zero rate of change." - << endl; + << "value (" << lookupValue << ") less than lower " + << "bound (" << minLimit << ")\n" + << " Zero rate of change." << endl; // Behaviour as per CLAMP - return 0; + return Zero; break; } case bounds::repeatableBounding::CLAMP: { - return 0; + return Zero; break; } case bounds::repeatableBounding::REPEAT: { // Adjust lookupValue to >= minLimit scalar span = maxLimit-minLimit; - lookupValue = fmod(lookupValue-minLimit, span) + minLimit; + lookupValue = fmod(lookupValue - minLimit, span) + minLimit; break; } } @@ -224,31 +229,32 @@ Type Foam::interpolationTable::rateOfChange(const scalar value) const case bounds::repeatableBounding::ERROR: { FatalErrorInFunction - << "value (" << lookupValue << ") overflow" << nl + << "value (" << lookupValue << ") greater than upper " + << "bound (" << maxLimit << ")\n" << exit(FatalError); break; } case bounds::repeatableBounding::WARN: { WarningInFunction - << "value (" << lookupValue << ") overflow" << nl - << " Zero rate of change." - << endl; + << "value (" << lookupValue << ") greater than upper " + << "bound (" << maxLimit << ")\n" + << " Zero rate of change." << endl; // Behaviour as per CLAMP - return 0; + return Zero; break; } case bounds::repeatableBounding::CLAMP: { - return 0; + return Zero; break; } case bounds::repeatableBounding::REPEAT: { // Adjust lookupValue <= maxLimit scalar span = maxLimit-minLimit; - lookupValue = fmod(lookupValue-minLimit, span) + minLimit; + lookupValue = fmod(lookupValue - minLimit, span) + minLimit; break; } } @@ -257,10 +263,10 @@ Type Foam::interpolationTable::rateOfChange(const scalar value) const label lo = 0; label hi = 0; - // look for the correct range + // Look for the correct range for (label i = 0; i < n; ++i) { - if (lookupValue >= List>::operator[](i).first()) + if (lookupValue >= list[i].first()) { lo = hi = i; } @@ -273,12 +279,11 @@ Type Foam::interpolationTable::rateOfChange(const scalar value) const if (lo == hi) { - // we are at the end of the table - or there is only a single entry - return 0; + return Zero; } else if (hi == 0) { - // this treatment should only occur under these conditions: + // This treatment should only occur under these conditions: // -> the 'REPEAT' treatment // -> (0 <= value <= minLimit) // -> minLimit > 0 @@ -287,32 +292,200 @@ Type Foam::interpolationTable::rateOfChange(const scalar value) const return ( - ( - List>::operator[](hi).second() - - List>::operator[](lo).second() - ) - /( - List>::operator[](hi).first() - + minLimit - - List>::operator[](lo).first() - ) + (list[hi].second() - list[lo].second()) + / (list[hi].first() + minLimit - list[lo].first()) ); } - else + + + // Normal rate of change + return + ( + (list[hi].second() - list[lo].second()) + / (list[hi].first() - list[lo].first()) + ); +} + + +template +Type Foam::interpolationTable::interpolateValue +( + const List>& list, + scalar lookupValue, + bounds::repeatableBounding bounding +) +{ + const label n = list.size(); + + if (n <= 1) { - // normal rate of change + #ifdef FULLDEBUG + if (!n) + { + FatalErrorInFunction + << "Cannot interpolate from zero-sized table" << nl + << exit(FatalError); + } + #endif + + return list.first().second(); + } + + const scalar minLimit = list.first().first(); + const scalar maxLimit = list.last().first(); + + if (lookupValue < minLimit) + { + switch (bounding) + { + case bounds::repeatableBounding::ERROR: + { + FatalErrorInFunction + << "value (" << lookupValue << ") less than lower " + << "bound (" << minLimit << ")\n" + << exit(FatalError); + break; + } + case bounds::repeatableBounding::WARN: + { + WarningInFunction + << "value (" << lookupValue << ") less than lower " + << "bound (" << minLimit << ")\n" + << " Continuing with the first entry" << endl; + + // Behaviour as per CLAMP + return list.first().second(); + break; + } + case bounds::repeatableBounding::CLAMP: + { + return list.first().second(); + break; + } + case bounds::repeatableBounding::REPEAT: + { + // adjust lookupValue to >= minLimit + const scalar span = maxLimit-minLimit; + lookupValue = fmod(lookupValue - minLimit, span) + minLimit; + break; + } + } + } + else if (lookupValue >= maxLimit) + { + switch (bounding) + { + case bounds::repeatableBounding::ERROR: + { + FatalErrorInFunction + << "value (" << lookupValue << ") greater than upper " + << "bound (" << maxLimit << ")\n" + << exit(FatalError); + break; + } + case bounds::repeatableBounding::WARN: + { + WarningInFunction + << "value (" << lookupValue << ") greater than upper " + << "bound (" << maxLimit << ")\n" + << " Continuing with the last entry" << endl; + + // Behaviour as per 'CLAMP' + return list.last().second(); + break; + } + case bounds::repeatableBounding::CLAMP: + { + return list.last().second(); + break; + } + case bounds::repeatableBounding::REPEAT: + { + // Adjust lookupValue <= maxLimit + const scalar span = maxLimit-minLimit; + lookupValue = fmod(lookupValue - minLimit, span) + minLimit; + break; + } + } + } + + + label lo = 0; + label hi = 0; + + // Look for the correct range + for (label i = 0; i < n; ++i) + { + if (lookupValue >= list[i].first()) + { + lo = hi = i; + } + else + { + hi = i; + break; + } + } + + if (lo == hi) + { + return list[hi].second(); + } + else if (hi == 0) + { + // This treatment should only occur under these conditions: + // -> the 'REPEAT' treatment + // -> (0 <= value <= minLimit) + // -> minLimit > 0 + // Use the value at maxLimit as the value for value=0 + lo = n - 1; + return ( - ( - List>::operator[](hi).second() - - List>::operator[](lo).second() - ) - /( - List>::operator[](hi).first() - - List>::operator[](lo).first() - ) + list[lo].second() + + (list[hi].second() - list[lo].second()) + * (lookupValue / minLimit) ); } + + + // Normal interpolation + return + ( + list[lo].second() + + (list[hi].second() - list[lo].second()) + * (lookupValue - list[lo].first()) + / (list[hi].first() - list[lo].first()) + ); +} + + +template +Type Foam::interpolationTable::interpolateValue +( + scalar lookupValue +) const +{ + return interpolateValue(*this, lookupValue, bounding_); +} + + +template +Foam::tmp> +Foam::interpolationTable::interpolateValues +( + const UList& vals +) const +{ + auto tfld = tmp>::New(vals.size()); + auto& fld = tfld.ref(); + + forAll(fld, i) + { + fld[i] = interpolateValue(vals[i]); + } + + return tfld; } @@ -320,242 +493,105 @@ Type Foam::interpolationTable::rateOfChange(const scalar value) const template const Foam::Tuple2& -Foam::interpolationTable::operator[](const label i) const +Foam::interpolationTable::operator[](label idx) const { - label ii = i; - label n = this->size(); + const List& list = *this; + const label n = list.size(); if (n <= 1) { - ii = 0; + idx = 0; + + #ifdef FULLDEBUG + if (!n) + { + FatalErrorInFunction + << "Cannot interpolate from zero-sized table" << nl + << exit(FatalError); + } + #endif } - else if (ii < 0) + else if (idx < 0) { switch (bounding_) { case bounds::repeatableBounding::ERROR: { FatalErrorInFunction - << "index (" << ii << ") underflow" << nl + << "index (" << idx << ") underflow" << nl << exit(FatalError); break; } case bounds::repeatableBounding::WARN: { WarningInFunction - << "index (" << ii << ") underflow" << nl - << " Continuing with the first entry" - << endl; + << "index (" << idx << ") underflow" << nl + << " Continuing with the first entry" << nl; // Behaviour as per 'CLAMP' - ii = 0; + idx = 0; break; } case bounds::repeatableBounding::CLAMP: { - ii = 0; + idx = 0; break; } case bounds::repeatableBounding::REPEAT: { - while (ii < 0) + while (idx < 0) { - ii += n; + idx += n; } break; } } } - else if (ii >= n) + else if (idx >= n) { switch (bounding_) { case bounds::repeatableBounding::ERROR: { FatalErrorInFunction - << "index (" << ii << ") overflow" << nl + << "index (" << idx << ") overflow" << nl << exit(FatalError); break; } case bounds::repeatableBounding::WARN: { WarningInFunction - << "index (" << ii << ") overflow" << nl - << " Continuing with the last entry" - << endl; + << "index (" << idx << ") overflow" << nl + << " Continuing with the last entry" << nl; // Behaviour as per 'CLAMP' - ii = n - 1; + idx = n - 1; break; } case bounds::repeatableBounding::CLAMP: { - ii = n - 1; + idx = n - 1; break; } case bounds::repeatableBounding::REPEAT: { - while (ii >= n) + while (idx >= n) { - ii -= n; + idx -= n; } break; } } } - return List>::operator[](ii); + return list[idx]; } template -Type Foam::interpolationTable::operator()(const scalar value) const +Type Foam::interpolationTable::operator()(scalar lookupValue) const { - label n = this->size(); - - if (n <= 1) - { - return this->first().second(); - } - - const scalar minLimit = this->first().first(); - const scalar maxLimit = this->last().first(); - scalar lookupValue = value; - - if (lookupValue < minLimit) - { - switch (bounding_) - { - case bounds::repeatableBounding::ERROR: - { - FatalErrorInFunction - << "value (" << lookupValue << ") underflow" << nl - << exit(FatalError); - break; - } - case bounds::repeatableBounding::WARN: - { - WarningInFunction - << "value (" << lookupValue << ") underflow" << nl - << " Continuing with the first entry" - << endl; - - // Behaviour as per CLAMP - return this->first().second(); - break; - } - case bounds::repeatableBounding::CLAMP: - { - return this->first().second(); - break; - } - case bounds::repeatableBounding::REPEAT: - { - // adjust lookupValue to >= minLimit - const scalar span = maxLimit-minLimit; - lookupValue = fmod(lookupValue-minLimit, span) + minLimit; - break; - } - } - } - else if (lookupValue >= maxLimit) - { - switch (bounding_) - { - case bounds::repeatableBounding::ERROR: - { - FatalErrorInFunction - << "value (" << lookupValue << ") overflow" << nl - << exit(FatalError); - break; - } - case bounds::repeatableBounding::WARN: - { - WarningInFunction - << "value (" << lookupValue << ") overflow" << nl - << " Continuing with the last entry" - << endl; - - // Behaviour as per 'CLAMP' - return this->last().second(); - break; - } - case bounds::repeatableBounding::CLAMP: - { - return this->last().second(); - break; - } - case bounds::repeatableBounding::REPEAT: - { - // adjust lookupValue <= maxLimit - const scalar span = maxLimit-minLimit; - lookupValue = fmod(lookupValue-minLimit, span) + minLimit; - break; - } - } - } - - label lo = 0; - label hi = 0; - - // look for the correct range - for (label i = 0; i < n; ++i) - { - if (lookupValue >= List>::operator[](i).first()) - { - lo = hi = i; - } - else - { - hi = i; - break; - } - } - - if (lo == hi) - { - // we are at the end of the table - or there is only a single entry - return List>::operator[](hi).second(); - } - else if (hi == 0) - { - // this treatment should only occur under these conditions: - // -> the 'REPEAT' treatment - // -> (0 <= value <= minLimit) - // -> minLimit > 0 - // Use the value at maxLimit as the value for value=0 - lo = n - 1; - - return - ( - List>::operator[](lo).second() - + ( - List>::operator[](hi).second() - - List>::operator[](lo).second() - ) - *(lookupValue / minLimit) - ); - } - else - { - // normal interpolation - return - ( - List>::operator[](lo).second() - + ( - List>::operator[](hi).second() - - List>::operator[](lo).second() - ) - *( - lookupValue - - List>::operator[](lo).first() - ) - /( - List>::operator[](hi).first() - - List>::operator[](lo).first() - ) - ); - } + return interpolateValue(*this, lookupValue, bounding_); } diff --git a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H index d8cd3d806c..97ecbc051c 100644 --- a/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H +++ b/src/OpenFOAM/interpolations/interpolationTable/interpolationTable.H @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,7 +37,6 @@ Description If \c repeat is chosen for the out-of-bounds handling, the final time value is treated as being equivalent to time=0 for the following periods. - The construct from dictionary reads a filename from a dictionary and has an optional readerType. Default is to read OpenFOAM format. The only other format is csv (comma separated values): @@ -65,10 +65,10 @@ SourceFiles #include "List.H" #include "Tuple2.H" - #include "tableBounds.H" #include "tableReader.H" #include "autoPtr.H" +#include "Field.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -84,7 +84,7 @@ class interpolationTable : public List> { - // Private data + // Private Data //- Handling for out-of-bound values bounds::repeatableBounding bounding_; @@ -104,6 +104,15 @@ class interpolationTable public: + // Public Data Types + + //- The element data type + typedef Tuple2 value_type; + + //- The mapped data type + typedef Type mapped_type; + + // Constructors //- Construct null @@ -118,19 +127,28 @@ public: ); //- Construct given the name of the file containing the table of data - interpolationTable(const fileName& fName); + explicit interpolationTable(const fileName& fName); //- Construct by reading file name and outOfBounds from dictionary - // and read the table from that file. + //- and read the table from that file. // This is a specialised constructor used by patchFields - interpolationTable(const dictionary& dict); + explicit interpolationTable(const dictionary& dict); - //- Construct copy + //- Copy construct interpolationTable(const interpolationTable& interpTable); // Member Functions + //- Return an interpolated value in List + static Type interpolateValue + ( + const List>& list, + scalar lookupValue, + bounds::repeatableBounding = bounds::repeatableBounding::CLAMP + ); + + //- Check that list is monotonically increasing // Exit with a FatalError if there is a problem void check() const; @@ -139,17 +157,26 @@ public: void write(Ostream& os) const; //- Return the rate of change at the interpolation location - // for the give value - Type rateOfChange(const scalar) const; + //- for the given lookup value + Type rateOfChange(scalar lookupValue) const; + + //- Return an interpolated value + Type interpolateValue(scalar lookupValue) const; + + //- Return multiple interpolated values + tmp> interpolateValues + ( + const UList& vals + ) const; // Member Operators //- Return an element of constant Tuple2 - const Tuple2& operator[](const label) const; + const Tuple2& operator[](label idx) const; //- Return an interpolated value - Type operator()(const scalar) const; + Type operator()(scalar lookupValue) const; }; diff --git a/src/OpenFOAM/primitives/functions/Function1/Table/Table.C b/src/OpenFOAM/primitives/functions/Function1/Table/Table.C index 8aeb47eba4..1ba0c5a84c 100644 --- a/src/OpenFOAM/primitives/functions/Function1/Table/Table.C +++ b/src/OpenFOAM/primitives/functions/Function1/Table/Table.C @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,7 +39,7 @@ Foam::Function1Types::Table::Table : TableBase(entryName, dict) { - Istream& is(dict.lookup(entryName)); + Istream& is = dict.lookup(entryName); word entryType(is); is >> this->table_; TableBase::check(); @@ -52,11 +53,4 @@ Foam::Function1Types::Table::Table(const Table& tbl) {} -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -template -Foam::Function1Types::Table::~Table() -{} - - // ************************************************************************* // diff --git a/src/OpenFOAM/primitives/functions/Function1/Table/Table.H b/src/OpenFOAM/primitives/functions/Function1/Table/Table.H index 5494fc5b7b..279ac939ba 100644 --- a/src/OpenFOAM/primitives/functions/Function1/Table/Table.H +++ b/src/OpenFOAM/primitives/functions/Function1/Table/Table.H @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -72,7 +73,6 @@ class Table //- No copy assignment void operator=(const Table&) = delete; - public: //- Runtime type information @@ -81,7 +81,7 @@ public: // Constructors - //- Construct from entry name and Istream + //- Construct from entry name and dictionary Table(const word& entryName, const dictionary& dict); //- Copy constructor @@ -95,7 +95,7 @@ public: //- Destructor - virtual ~Table(); + virtual ~Table() = default; }; diff --git a/src/OpenFOAM/primitives/functions/Function1/Table/TableBase.C b/src/OpenFOAM/primitives/functions/Function1/Table/TableBase.C index 475aaa483e..b8c0fcffe3 100644 --- a/src/OpenFOAM/primitives/functions/Function1/Table/TableBase.C +++ b/src/OpenFOAM/primitives/functions/Function1/Table/TableBase.C @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,15 +40,15 @@ Foam::Function1Types::TableBase::interpolator() const { // Re-work table into linear list tableSamplesPtr_.reset(new scalarField(table_.size())); - scalarField& tableSamples = tableSamplesPtr_(); + scalarField& samples = *tableSamplesPtr_; forAll(table_, i) { - tableSamples[i] = table_[i].first(); + samples[i] = table_[i].first(); } interpolatorPtr_ = interpolationWeights::New ( interpolationScheme_, - tableSamples + samples ); } @@ -116,21 +117,23 @@ void Foam::Function1Types::TableBase::check() const << nl << exit(FatalError); } - const label n = table_.size(); - scalar prevValue = table_[0].first(); + scalar prevValue(0); - for (label i = 1; i < n; ++i) + label i = 0; + for (const auto& item : table_) { - const scalar currValue = table_[i].first(); + const scalar& currValue = item.first(); - // avoid duplicate values (divide-by-zero error) - if (currValue <= prevValue) + // Avoid duplicate values (divide-by-zero error) + if (i && currValue <= prevValue) { FatalErrorInFunction - << "out-of-order value: " << currValue << " at index " << i + << "out-of-order value: " + << currValue << " at index " << i << nl << exit(FatalError); } prevValue = currValue; + ++i; } } @@ -142,45 +145,44 @@ bool Foam::Function1Types::TableBase::checkMinBounds scalar& xDash ) const { - if (x < table_.first().first()) + const scalar minLimit = table_.first().first(); + const scalar maxLimit = table_.last().first(); + + if (x < minLimit) { switch (bounding_) { case bounds::repeatableBounding::ERROR: { FatalErrorInFunction - << "value (" << x << ") underflow" + << "value (" << x << ") less than lower " + << "bound (" << minLimit << ")" << nl << exit(FatalError); break; } case bounds::repeatableBounding::WARN: { WarningInFunction - << "value (" << x << ") underflow" << nl - << endl; + << "value (" << x << ") less than lower " + << "bound (" << minLimit << ")" << nl + << " Continuing with the first entry" << endl; // Behaviour as per CLAMP - xDash = table_.first().first(); + xDash = minLimit; return true; break; } case bounds::repeatableBounding::CLAMP: { - xDash = table_.first().first(); + xDash = minLimit; return true; break; } case bounds::repeatableBounding::REPEAT: { - // adjust x to >= minX - const scalar span = - table_.last().first() - table_.first().first(); - - xDash = - ( - fmod(x - table_.first().first(), span) - + table_.first().first() - ); + // Adjust x to >= minX + const scalar span = maxLimit - minLimit; + xDash = fmod(x - minLimit, span) + minLimit; break; } } @@ -201,45 +203,44 @@ bool Foam::Function1Types::TableBase::checkMaxBounds scalar& xDash ) const { - if (x > table_.last().first()) + const scalar minLimit = table_.first().first(); + const scalar maxLimit = table_.last().first(); + + if (x > maxLimit) { switch (bounding_) { case bounds::repeatableBounding::ERROR: { FatalErrorInFunction - << "value (" << x << ") overflow" + << "value (" << x << ") greater than upper " + << "bound (" << maxLimit << ")" << nl << exit(FatalError); break; } case bounds::repeatableBounding::WARN: { WarningInFunction - << "value (" << x << ") overflow" << nl - << endl; + << "value (" << x << ") greater than upper " + << "bound (" << maxLimit << ")" << nl + << " Continuing with the last entry" << endl; // Behaviour as per CLAMP - xDash = table_.last().first(); + xDash = maxLimit; return true; break; } case bounds::repeatableBounding::CLAMP: { - xDash = table_.last().first(); + xDash = maxLimit; return true; break; } case bounds::repeatableBounding::REPEAT: { - // adjust x to >= minX - const scalar span = - table_.last().first() - table_.first().first(); - - xDash = - ( - fmod(x - table_.first().first(), span) - + table_.first().first() - ); + // Adjust x to >= minX + const scalar span = maxLimit - minLimit; + xDash = fmod(x - minLimit, span) + minLimit; break; } } @@ -256,10 +257,9 @@ bool Foam::Function1Types::TableBase::checkMaxBounds template void Foam::Function1Types::TableBase::convertTimeBase(const Time& t) { - forAll(table_, i) + for (auto& item : table_) { - scalar value = table_[i].first(); - table_[i].first() = t.userTimeToTime(value); + item.first() = t.userTimeToTime(item.first()); } tableSamplesPtr_.clear(); @@ -318,8 +318,8 @@ Type Foam::Function1Types::TableBase::integrate template Foam::tmp Foam::Function1Types::TableBase::x() const { - tmp tfld(new scalarField(table_.size(), Zero)); - scalarField& fld = tfld.ref(); + auto tfld = tmp::New(table_.size(), Zero); + auto& fld = tfld.ref(); forAll(table_, i) { @@ -333,8 +333,8 @@ Foam::tmp Foam::Function1Types::TableBase::x() const template Foam::tmp> Foam::Function1Types::TableBase::y() const { - tmp> tfld(new Field(table_.size(), Zero)); - Field& fld = tfld.ref(); + auto tfld = tmp>::New(table_.size(), Zero); + auto& fld = tfld.ref(); forAll(table_, i) { @@ -348,12 +348,14 @@ Foam::tmp> Foam::Function1Types::TableBase::y() const template void Foam::Function1Types::TableBase::writeEntries(Ostream& os) const { - os.writeEntryIfDifferent - ( - "outOfBounds", - bounds::repeatableBoundingNames[bounds::repeatableBounding::CLAMP], - bounds::repeatableBoundingNames[bounding_] - ); + if (bounds::repeatableBounding::CLAMP != bounding_) + { + os.writeEntry + ( + "outOfBounds", + bounds::repeatableBoundingNames[bounding_] + ); + } os.writeEntryIfDifferent (