00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "interpolationTable.H"
00027 #include <OpenFOAM/IFstream.H>
00028 #include <OpenFOAM/openFoamTableReader.H>
00029
00030
00031
00032 template<class Type>
00033 void Foam::interpolationTable<Type>::readTable()
00034 {
00035
00036
00037 fileName fName(fileName_);
00038
00039 fName.expand();
00040
00041
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
00054 check();
00055 }
00056
00057
00058
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_)
00119 {}
00120
00121
00122
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
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
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
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
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
00384 }
00385 case interpolationTable::CLAMP:
00386 {
00387 return List<Tuple2<scalar, Type> >::operator[](0).second();
00388 break;
00389 }
00390 case interpolationTable::REPEAT:
00391 {
00392
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
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
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
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
00459 return List<Tuple2<scalar, Type> >::operator[](hi).second();
00460 }
00461 else if (hi == 0)
00462 {
00463
00464
00465
00466
00467
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
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