/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "IFstream.H" #include "openFoamTableReader.H" // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // template void Foam::interpolation2DTable::readTable() { fileName fName(fileName_); fName.expand(); // Read data from file reader_()(fName, *this); if (this->empty()) { FatalErrorIn ( "Foam::interpolation2DTable::readTable()" ) << "table read from " << fName << " is empty" << nl << exit(FatalError); } // Check that the data are in ascending order checkOrder(); } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template Foam::interpolation2DTable::interpolation2DTable() : List > > >(), boundsHandling_(interpolation2DTable::WARN), fileName_("fileNameIsUndefined"), reader_(NULL) {} template Foam::interpolation2DTable::interpolation2DTable ( const List > > >& values, const boundsHandling bounds, const fileName& fName ) : List > > >(values), boundsHandling_(bounds), fileName_(fName), reader_(NULL) {} template Foam::interpolation2DTable::interpolation2DTable(const fileName& fName) : List > > >(), boundsHandling_(interpolation2DTable::WARN), fileName_(fName), reader_(new openFoamTableReader(dictionary())) { readTable(); } template Foam::interpolation2DTable::interpolation2DTable(const dictionary& dict) : List > > >(), boundsHandling_(wordToBoundsHandling(dict.lookup("outOfBounds"))), fileName_(dict.lookup("fileName")), reader_(tableReader::New(dict)) { readTable(); } template Foam::interpolation2DTable::interpolation2DTable ( const interpolation2DTable& interpTable ) : List > > >(interpTable), boundsHandling_(interpTable.boundsHandling_), 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 { label n = data.size(); scalar minLimit = data.first().first(); scalar maxLimit = data.last().first(); if (lookupValue < minLimit) { switch (boundsHandling_) { case interpolation2DTable::ERROR: { FatalErrorIn ( "Foam::interpolation2DTable::interpolateValue" "(" "List >&, " "const scalar" ")" ) << "value (" << lookupValue << ") less than lower " << "bound (" << minLimit << ")" << nl << exit(FatalError); break; } case interpolation2DTable::WARN: { WarningIn ( "Foam::interpolation2DTable::interpolateValue" "(" "List >&, " "const scalar" ")" ) << "value (" << lookupValue << ") less than lower " << "bound (" << minLimit << ")" << nl << " Continuing with the first entry" << endl; // fall-through to 'CLAMP' } case interpolation2DTable::CLAMP: { return data.first().second(); break; } } } else if (lookupValue >= maxLimit) { switch (boundsHandling_) { case interpolation2DTable::ERROR: { FatalErrorIn ( "Foam::interpolation2DTable::interpolateValue" "(" "List >&, " "const scalar" ")" ) << "value (" << lookupValue << ") greater than upper " << "bound (" << maxLimit << ")" << nl << exit(FatalError); break; } case interpolation2DTable::WARN: { WarningIn ( "Foam::interpolation2DTable::interpolateValue" "(" "List >&, " "const scalar" ")" ) << "value (" << lookupValue << ") greater than upper " << "bound (" << maxLimit << ")" << nl << " Continuing with the last entry" << endl; // fall-through to 'CLAMP' } case interpolation2DTable::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()); } } template template Foam::label Foam::interpolation2DTable::Xi ( const BinaryOp& bop, const scalar valueX, const bool reverse ) const { const table& t = *this; label limitI = 0; if (reverse) { limitI = t.size() - 1; } if (bop(valueX, t[limitI].first())) { switch (boundsHandling_) { case interpolation2DTable::ERROR: { FatalErrorIn ( "Foam::label Foam::interpolation2DTable::Xi" "(" "const BinaryOp&, " "const scalar, " "const bool" ") const" ) << "value (" << valueX << ") out of bounds" << exit(FatalError); break; } case interpolation2DTable::WARN: { WarningIn ( "Foam::label Foam::interpolation2DTable::Xi" "(" "const BinaryOp&, " "const scalar, " "const bool" ) << "value (" << valueX << ") out of bounds" << endl; // fall-through to 'CLAMP' } case interpolation2DTable::CLAMP: { return limitI; } default: { FatalErrorIn ( "Foam::label Foam::interpolation2DTable::Xi" "(" "const BinaryOp&, " "const scalar, " "const bool" ") const" ) << "Un-handled enumeration " << boundsHandling_ << abort(FatalError); } } } label i = 0; if (reverse) { label nX = t.size(); i = 0; while ((i < nX) && (valueX > t[i].first())) { i++; } } else { i = t.size() - 1; while ((i > 0) && (valueX < t[i].first())) { i--; } } return i; } // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template Type Foam::interpolation2DTable::operator() ( const scalar valueX, const scalar valueY ) const { // Considers all of the list in Y being equal label nX = this->size(); const table& t = *this; if (nX == 0) { WarningIn ( "Type Foam::interpolation2DTable::operator()" "(" "const scalar, " "const scalar" ") const" ) << "cannot interpolate a zero-sized table - returning zero" << endl; return pTraits::zero; } else if (nX == 1) { // only 1 column (in X) - interpolate to find Y value return interpolateValue(t.first().second(), valueY); } else { // have 2-D data, interpolate // find low and high indices in the X range that bound valueX label x0i = Xi(lessOp(), valueX, false); 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 scalar x0 = t[x0i].first(); scalar x1 = t[x1i].first(); Type mX = (y1 - y0)/(x1 - x0); // interpolate return y0 + mX*(valueX - x0); } } } template Foam::word Foam::interpolation2DTable::boundsHandlingToWord ( const boundsHandling& bound ) const { word enumName("warn"); switch (bound) { case interpolation2DTable::ERROR: { enumName = "error"; break; } case interpolation2DTable::WARN: { enumName = "warn"; break; } case interpolation2DTable::CLAMP: { enumName = "clamp"; break; } } return enumName; } template typename Foam::interpolation2DTable::boundsHandling Foam::interpolation2DTable::wordToBoundsHandling ( const word& bound ) const { if (bound == "error") { return interpolation2DTable::ERROR; } else if (bound == "warn") { return interpolation2DTable::WARN; } else if (bound == "clamp") { return interpolation2DTable::CLAMP; } else { WarningIn ( "Foam::interpolation2DTable::wordToBoundsHandling" "(" " const word&" ")" ) << "bad outOfBounds specifier " << bound << " using 'warn'" << endl; return interpolation2DTable::WARN; } } template typename Foam::interpolation2DTable::boundsHandling Foam::interpolation2DTable::outOfBounds ( const boundsHandling& bound ) { boundsHandling prev = boundsHandling_; boundsHandling_ = bound; return prev; } template void Foam::interpolation2DTable::checkOrder() const { label n = this->size(); const table& t = *this; scalar prevValue = t[0].first(); for (label i=1; i::checkOrder() const" ) << "out-of-order value: " << currValue << " at index " << i << nl << exit(FatalError); } prevValue = currValue; } } template void Foam::interpolation2DTable::write(Ostream& os) const { os.writeKeyword("fileName") << fileName_ << token::END_STATEMENT << nl; os.writeKeyword("outOfBounds") << boundsHandlingToWord(boundsHandling_) << token::END_STATEMENT << nl; *this >> os; } // ************************************************************************* //