FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

interpolationTable.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2011 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "interpolationTable.H"
00027 #include <OpenFOAM/IFstream.H>
00028 #include <OpenFOAM/openFoamTableReader.H>
00029 
00030 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
00031 
00032 template<class Type>
00033 void Foam::interpolationTable<Type>::readTable()
00034 {
00035     // preserve the original (unexpanded) fileName to avoid absolute paths
00036     // appearing subsequently in the write() method
00037     fileName fName(fileName_);
00038 
00039     fName.expand();
00040 
00041     // Read data from file
00042     reader_()(fName, *this);
00043 
00044     if (this->empty())
00045     {
00046         FatalErrorIn
00047         (
00048             "Foam::interpolationTable<Type>::readTable()"
00049         )   << "table read from " << fName << " is empty" << nl
00050             << exit(FatalError);
00051     }
00052 
00053     // Check that the data are okay
00054     check();
00055 }
00056 
00057 
00058 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00059 
00060 template<class Type>
00061 Foam::interpolationTable<Type>::interpolationTable()
00062 :
00063     List<Tuple2<scalar, Type> >(),
00064     boundsHandling_(interpolationTable::WARN),
00065     fileName_("fileNameIsUndefined"),
00066     reader_(NULL)
00067 {}
00068 
00069 
00070 template<class Type>
00071 Foam::interpolationTable<Type>::interpolationTable
00072 (
00073     const List<Tuple2<scalar, Type> >& values,
00074     const boundsHandling bounds,
00075     const fileName& fName
00076 )
00077 :
00078     List<Tuple2<scalar, Type> >(values),
00079     boundsHandling_(bounds),
00080     fileName_(fName),
00081     reader_(NULL)
00082 {}
00083 
00084 
00085 template<class Type>
00086 Foam::interpolationTable<Type>::interpolationTable(const fileName& fName)
00087 :
00088     List<Tuple2<scalar, Type> >(),
00089     boundsHandling_(interpolationTable::WARN),
00090     fileName_(fName),
00091     reader_(new openFoamTableReader<Type>())
00092 {
00093     readTable();
00094 }
00095 
00096 
00097 template<class Type>
00098 Foam::interpolationTable<Type>::interpolationTable(const dictionary& dict)
00099 :
00100     List<Tuple2<scalar, Type> >(),
00101     boundsHandling_(wordToBoundsHandling(dict.lookup("outOfBounds"))),
00102     fileName_(dict.lookup("fileName")),
00103     reader_(tableReader<Type>::New(dict))
00104 {
00105     readTable();
00106 }
00107 
00108 
00109 template<class Type>
00110 Foam::interpolationTable<Type>::interpolationTable
00111 (
00112      const interpolationTable& interpTable
00113 )
00114 :
00115     List<Tuple2<scalar, Type> >(interpTable),
00116     boundsHandling_(interpTable.boundsHandling_),
00117     fileName_(interpTable.fileName_),
00118     reader_(interpTable.reader_)    // note: steals reader. Used in write().
00119 {}
00120 
00121 
00122 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00123 
00124 template<class Type>
00125 Foam::word Foam::interpolationTable<Type>::boundsHandlingToWord
00126 (
00127      const boundsHandling& bound
00128 ) const
00129 {
00130     word enumName("warn");
00131 
00132     switch (bound)
00133     {
00134         case interpolationTable::ERROR:
00135         {
00136             enumName = "error";
00137             break;
00138         }
00139         case interpolationTable::WARN:
00140         {
00141             enumName = "warn";
00142             break;
00143         }
00144         case interpolationTable::CLAMP:
00145         {
00146             enumName = "clamp";
00147             break;
00148         }
00149         case interpolationTable::REPEAT:
00150         {
00151             enumName = "repeat";
00152             break;
00153         }
00154     }
00155 
00156     return enumName;
00157 }
00158 
00159 
00160 template<class Type>
00161 typename Foam::interpolationTable<Type>::boundsHandling
00162 Foam::interpolationTable<Type>::wordToBoundsHandling
00163 (
00164     const word& bound
00165 ) const
00166 {
00167     if (bound == "error")
00168     {
00169         return interpolationTable::ERROR;
00170     }
00171     else if (bound == "warn")
00172     {
00173         return interpolationTable::WARN;
00174     }
00175     else if (bound == "clamp")
00176     {
00177         return interpolationTable::CLAMP;
00178     }
00179     else if (bound == "repeat")
00180     {
00181         return interpolationTable::REPEAT;
00182     }
00183     else
00184     {
00185         WarningIn
00186         (
00187             "Foam::interpolationTable<Type>::wordToBoundsHandling(const word&)"
00188         )   << "bad outOfBounds specifier " << bound << " using 'warn'" << endl;
00189 
00190         return interpolationTable::WARN;
00191     }
00192 }
00193 
00194 
00195 template<class Type>
00196 typename Foam::interpolationTable<Type>::boundsHandling
00197 Foam::interpolationTable<Type>::outOfBounds
00198 (
00199     const boundsHandling& bound
00200 )
00201 {
00202     boundsHandling prev = boundsHandling_;
00203     boundsHandling_ = bound;
00204     return prev;
00205 }
00206 
00207 
00208 template<class Type>
00209 void Foam::interpolationTable<Type>::check() const
00210 {
00211     label n = this->size();
00212     scalar prevValue = List<Tuple2<scalar, Type> >::operator[](0).first();
00213 
00214     for (label i=1; i<n; ++i)
00215     {
00216         const scalar currValue =
00217             List<Tuple2<scalar, Type> >::operator[](i).first();
00218 
00219         // avoid duplicate values (divide-by-zero error)
00220         if (currValue <= prevValue)
00221         {
00222             FatalErrorIn
00223             (
00224                 "Foam::interpolationTable<Type>::checkOrder() const"
00225             )   << "out-of-order value: "
00226                 << currValue << " at index " << i << nl
00227                 << exit(FatalError);
00228         }
00229         prevValue = currValue;
00230     }
00231 }
00232 
00233 
00234 template<class Type>
00235 void Foam::interpolationTable<Type>::write(Ostream& os) const
00236 {
00237     os.writeKeyword("fileName")
00238         << fileName_ << token::END_STATEMENT << nl;
00239     os.writeKeyword("outOfBounds")
00240         << boundsHandlingToWord(boundsHandling_) << token::END_STATEMENT << nl;
00241     if (reader_.valid())
00242     {
00243         reader_->write(os);
00244     }
00245 }
00246 
00247 
00248 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
00249 
00250 template<class Type>
00251 const Foam::Tuple2<Foam::scalar, Type>&
00252 Foam::interpolationTable<Type>::operator[](const label i) const
00253 {
00254     label ii = i;
00255     label n  = this->size();
00256 
00257     if (n <= 1)
00258     {
00259         ii = 0;
00260     }
00261     else if (ii < 0)
00262     {
00263         switch (boundsHandling_)
00264         {
00265             case interpolationTable::ERROR:
00266             {
00267                 FatalErrorIn
00268                 (
00269                     "Foam::interpolationTable<Type>::operator[]"
00270                     "(const label) const"
00271                 )   << "index (" << ii << ") underflow" << nl
00272                     << exit(FatalError);
00273                 break;
00274             }
00275             case interpolationTable::WARN:
00276             {
00277                 WarningIn
00278                 (
00279                     "Foam::interpolationTable<Type>::operator[]"
00280                     "(const label) const"
00281                 )   << "index (" << ii << ") underflow" << nl
00282                     << "    Continuing with the first entry"
00283                     << endl;
00284                 // fall-through to 'CLAMP'
00285             }
00286             case interpolationTable::CLAMP:
00287             {
00288                 ii = 0;
00289                 break;
00290             }
00291             case interpolationTable::REPEAT:
00292             {
00293                 while (ii < 0)
00294                 {
00295                     ii += n;
00296                 }
00297                 break;
00298             }
00299         }
00300     }
00301     else if (ii >= n)
00302     {
00303         switch (boundsHandling_)
00304         {
00305             case interpolationTable::ERROR:
00306             {
00307                 FatalErrorIn
00308                 (
00309                     "Foam::interpolationTable<Type>::operator[]"
00310                     "(const label) const"
00311                 )   << "index (" << ii << ") overflow" << nl
00312                     << exit(FatalError);
00313                 break;
00314             }
00315             case interpolationTable::WARN:
00316             {
00317                 WarningIn
00318                 (
00319                     "Foam::interpolationTable<Type>::operator[]"
00320                     "(const label) const"
00321                 )   << "index (" << ii << ") overflow" << nl
00322                     << "    Continuing with the last entry"
00323                     << endl;
00324                 // fall-through to 'CLAMP'
00325             }
00326             case interpolationTable::CLAMP:
00327             {
00328                 ii = n - 1;
00329                 break;
00330             }
00331             case interpolationTable::REPEAT:
00332             {
00333                 while (ii >= n)
00334                 {
00335                     ii -= n;
00336                 }
00337                 break;
00338             }
00339         }
00340     }
00341 
00342     return List<Tuple2<scalar, Type> >::operator[](ii);
00343 }
00344 
00345 
00346 template<class Type>
00347 Type Foam::interpolationTable<Type>::operator()(const scalar value) const
00348 {
00349     label n = this->size();
00350 
00351     if (n <= 1)
00352     {
00353         return List<Tuple2<scalar, Type> >::operator[](0).second();
00354     }
00355 
00356     scalar minLimit = List<Tuple2<scalar, Type> >::operator[](0).first();
00357     scalar maxLimit = List<Tuple2<scalar, Type> >::operator[](n-1).first();
00358     scalar lookupValue = value;
00359 
00360     if (lookupValue < minLimit)
00361     {
00362         switch (boundsHandling_)
00363         {
00364             case interpolationTable::ERROR:
00365             {
00366                 FatalErrorIn
00367                 (
00368                     "Foam::interpolationTable<Type>::operator[]"
00369                     "(const scalar) const"
00370                 )   << "value (" << lookupValue << ") underflow" << nl
00371                     << exit(FatalError);
00372                 break;
00373             }
00374             case interpolationTable::WARN:
00375             {
00376                 WarningIn
00377                 (
00378                     "Foam::interpolationTable<Type>::operator[]"
00379                     "(const scalar) const"
00380                 )   << "value (" << lookupValue << ") underflow" << nl
00381                     << "    Continuing with the first entry"
00382                     << endl;
00383                 // fall-through to 'CLAMP'
00384             }
00385             case interpolationTable::CLAMP:
00386             {
00387                 return List<Tuple2<scalar, Type> >::operator[](0).second();
00388                 break;
00389             }
00390             case interpolationTable::REPEAT:
00391             {
00392                 // adjust lookupValue to >= minLimit
00393                 scalar span = maxLimit-minLimit;
00394                 lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
00395                 break;
00396             }
00397         }
00398     }
00399     else if (lookupValue >= maxLimit)
00400     {
00401         switch (boundsHandling_)
00402         {
00403             case interpolationTable::ERROR:
00404             {
00405                 FatalErrorIn
00406                 (
00407                     "Foam::interpolationTable<Type>::operator[]"
00408                     "(const label) const"
00409                 )   << "value (" << lookupValue << ") overflow" << nl
00410                     << exit(FatalError);
00411                 break;
00412             }
00413             case interpolationTable::WARN:
00414             {
00415                 WarningIn
00416                 (
00417                     "Foam::interpolationTable<Type>::operator[]"
00418                     "(const label) const"
00419                 )   << "value (" << lookupValue << ") overflow" << nl
00420                     << "    Continuing with the last entry"
00421                     << endl;
00422                 // fall-through to 'CLAMP'
00423             }
00424             case interpolationTable::CLAMP:
00425             {
00426                 return List<Tuple2<scalar, Type> >::operator[](n-1).second();
00427                 break;
00428             }
00429             case interpolationTable::REPEAT:
00430             {
00431                 // adjust lookupValue <= maxLimit
00432                 scalar span = maxLimit-minLimit;
00433                 lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
00434                 break;
00435             }
00436         }
00437     }
00438 
00439     label lo = 0;
00440     label hi = 0;
00441 
00442     // look for the correct range
00443     for (label i = 0; i < n; ++i)
00444     {
00445         if (lookupValue >= List<Tuple2<scalar, Type> >::operator[](i).first())
00446         {
00447             lo = hi = i;
00448         }
00449         else
00450         {
00451             hi = i;
00452             break;
00453         }
00454     }
00455 
00456     if (lo == hi)
00457     {
00458         // we are at the end of the table - or there is only a single entry
00459         return List<Tuple2<scalar, Type> >::operator[](hi).second();
00460     }
00461     else if (hi == 0)
00462     {
00463         // this treatment should should only occur under these conditions:
00464         //  -> the 'REPEAT' treatment
00465         //  -> (0 <= value <= minLimit)
00466         //  -> minLimit > 0
00467         // Use the value at maxLimit as the value for value=0
00468         lo = n - 1;
00469 
00470         return
00471         (
00472             List<Tuple2<scalar, Type> >::operator[](lo).second()
00473           + (
00474                 List<Tuple2<scalar, Type> >::operator[](hi).second()
00475               - List<Tuple2<scalar, Type> >::operator[](lo).second()
00476             )
00477            *(lookupValue / minLimit)
00478         );
00479     }
00480     else
00481     {
00482         // normal interpolation
00483         return
00484         (
00485             List<Tuple2<scalar, Type> >::operator[](lo).second()
00486           + (
00487                 List<Tuple2<scalar, Type> >::operator[](hi).second()
00488               - List<Tuple2<scalar, Type> >::operator[](lo).second()
00489             )
00490            *(
00491                 lookupValue
00492               - List<Tuple2<scalar, Type> >::operator[](lo).first()
00493             )
00494            /(
00495                 List<Tuple2<scalar, Type> >::operator[](hi).first()
00496               - List<Tuple2<scalar, Type> >::operator[](lo).first()
00497             )
00498         );
00499     }
00500 }
00501 
00502 
00503 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines