interpolationTable.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "interpolationTable.H"
27 #include "IFstream.H"
28 #include "openFoamTableReader.H"
29 
30 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
31 
32 template<class Type>
34 {
35  // preserve the original (unexpanded) fileName to avoid absolute paths
36  // appearing subsequently in the write() method
37  fileName fName(fileName_);
38 
39  fName.expand();
40 
41  // Read data from file
42  reader_()(fName, *this);
43 
44  if (this->empty())
45  {
47  (
48  "Foam::interpolationTable<Type>::readTable()"
49  ) << "table read from " << fName << " is empty" << nl
50  << exit(FatalError);
51  }
52 
53  // Check that the data are okay
54  check();
55 }
56 
57 
58 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
59 
60 template<class Type>
62 :
63  List<Tuple2<scalar, Type> >(),
64  boundsHandling_(interpolationTable::WARN),
65  fileName_("fileNameIsUndefined"),
66  reader_(NULL)
67 {}
68 
69 
70 template<class Type>
72 (
73  const List<Tuple2<scalar, Type> >& values,
74  const boundsHandling bounds,
75  const fileName& fName
76 )
77 :
78  List<Tuple2<scalar, Type> >(values),
79  boundsHandling_(bounds),
80  fileName_(fName),
81  reader_(NULL)
82 {}
83 
84 
85 template<class Type>
87 :
88  List<Tuple2<scalar, Type> >(),
89  boundsHandling_(interpolationTable::WARN),
90  fileName_(fName),
91  reader_(new openFoamTableReader<Type>(dictionary()))
92 {
93  readTable();
94 }
95 
96 
97 template<class Type>
99 :
100  List<Tuple2<scalar, Type> >(),
101  boundsHandling_(wordToBoundsHandling(dict.lookup("outOfBounds"))),
102  fileName_(dict.lookup("fileName")),
103  reader_(tableReader<Type>::New(dict))
104 {
105  readTable();
106 }
107 
108 
109 template<class Type>
111 (
112  const interpolationTable& interpTable
113 )
114 :
115  List<Tuple2<scalar, Type> >(interpTable),
116  boundsHandling_(interpTable.boundsHandling_),
117  fileName_(interpTable.fileName_),
118  reader_(interpTable.reader_) // note: steals reader. Used in write().
119 {}
120 
121 
122 
123 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
124 
125 template<class Type>
127 (
128  const boundsHandling& bound
129 ) const
130 {
131  word enumName("warn");
132 
133  switch (bound)
134  {
136  {
137  enumName = "error";
138  break;
139  }
141  {
142  enumName = "warn";
143  break;
144  }
146  {
147  enumName = "clamp";
148  break;
149  }
151  {
152  enumName = "repeat";
153  break;
154  }
155  }
156 
157  return enumName;
158 }
159 
160 
161 template<class Type>
164 (
165  const word& bound
166 ) const
167 {
168  if (bound == "error")
169  {
171  }
172  else if (bound == "warn")
173  {
175  }
176  else if (bound == "clamp")
177  {
179  }
180  else if (bound == "repeat")
181  {
183  }
184  else
185  {
186  WarningIn
187  (
188  "Foam::interpolationTable<Type>::wordToBoundsHandling(const word&)"
189  ) << "bad outOfBounds specifier " << bound << " using 'warn'" << endl;
190 
192  }
193 }
194 
195 
196 template<class Type>
199 (
200  const boundsHandling& bound
201 )
202 {
203  boundsHandling prev = boundsHandling_;
204  boundsHandling_ = bound;
205  return prev;
206 }
207 
208 
209 template<class Type>
211 {
212  label n = this->size();
213  scalar prevValue = List<Tuple2<scalar, Type> >::operator[](0).first();
214 
215  for (label i=1; i<n; ++i)
216  {
217  const scalar currValue =
218  List<Tuple2<scalar, Type> >::operator[](i).first();
219 
220  // avoid duplicate values (divide-by-zero error)
221  if (currValue <= prevValue)
222  {
224  (
225  "Foam::interpolationTable<Type>::checkOrder() const"
226  ) << "out-of-order value: "
227  << currValue << " at index " << i << nl
228  << exit(FatalError);
229  }
230  prevValue = currValue;
231  }
232 }
233 
234 
235 template<class Type>
237 {
238  os.writeKeyword("fileName")
239  << fileName_ << token::END_STATEMENT << nl;
240  os.writeKeyword("outOfBounds")
241  << boundsHandlingToWord(boundsHandling_) << token::END_STATEMENT << nl;
242  if (reader_.valid())
243  {
244  reader_->write(os);
245  }
246 }
247 
248 
249 template<class Type>
250 Type Foam::interpolationTable<Type>::rateOfChange(const scalar value) const
251 {
252  label n = this->size();
253 
254  if (n <= 1)
255  {
256  // There are not enough entries to provide a rate of change
257  return 0;
258  }
259 
260  scalar minLimit = List<Tuple2<scalar, Type> >::operator[](0).first();
261  scalar maxLimit = List<Tuple2<scalar, Type> >::operator[](n-1).first();
262  scalar lookupValue = value;
263 
264  if (lookupValue < minLimit)
265  {
266  switch (boundsHandling_)
267  {
269  {
271  (
272  "Foam::interpolationTable<Type>::operator[]"
273  "(const scalar) const"
274  ) << "value (" << lookupValue << ") underflow" << nl
275  << exit(FatalError);
276  break;
277  }
279  {
280  WarningIn
281  (
282  "Foam::interpolationTable<Type>::operator[]"
283  "(const scalar) const"
284  ) << "value (" << lookupValue << ") underflow" << nl
285  << " Zero rate of change."
286  << endl;
287  // fall-through to 'CLAMP'
288  }
290  {
291  return 0;
292  break;
293  }
295  {
296  // adjust lookupValue to >= minLimit
297  scalar span = maxLimit-minLimit;
298  lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
299  break;
300  }
301  }
302  }
303  else if (lookupValue >= maxLimit)
304  {
305  switch (boundsHandling_)
306  {
308  {
310  (
311  "Foam::interpolationTable<Type>::operator[]"
312  "(const label) const"
313  ) << "value (" << lookupValue << ") overflow" << nl
314  << exit(FatalError);
315  break;
316  }
318  {
319  WarningIn
320  (
321  "Foam::interpolationTable<Type>::operator[]"
322  "(const label) const"
323  ) << "value (" << lookupValue << ") overflow" << nl
324  << " Zero rate of change."
325  << endl;
326  // fall-through to 'CLAMP'
327  }
329  {
330  return 0;
331  break;
332  }
334  {
335  // adjust lookupValue <= maxLimit
336  scalar span = maxLimit-minLimit;
337  lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
338  break;
339  }
340  }
341  }
342 
343  label lo = 0;
344  label hi = 0;
345 
346  // look for the correct range
347  for (label i = 0; i < n; ++i)
348  {
349  if (lookupValue >= List<Tuple2<scalar, Type> >::operator[](i).first())
350  {
351  lo = hi = i;
352  }
353  else
354  {
355  hi = i;
356  break;
357  }
358  }
359 
360  if (lo == hi)
361  {
362  // we are at the end of the table - or there is only a single entry
363  return 0;
364  }
365  else if (hi == 0)
366  {
367  // this treatment should should only occur under these conditions:
368  // -> the 'REPEAT' treatment
369  // -> (0 <= value <= minLimit)
370  // -> minLimit > 0
371  // Use the value at maxLimit as the value for value=0
372  lo = n - 1;
373 
374  return
375  (
376  (
377  List<Tuple2<scalar, Type> >::operator[](hi).second()
378  - List<Tuple2<scalar, Type> >::operator[](lo).second()
379  )
380  /(
381  List<Tuple2<scalar, Type> >::operator[](hi).first()
382  + minLimit
383  - List<Tuple2<scalar, Type> >::operator[](lo).first()
384  )
385  );
386  }
387  else
388  {
389  // normal rate of change
390  return
391  (
392  (
393  List<Tuple2<scalar, Type> >::operator[](hi).second()
394  - List<Tuple2<scalar, Type> >::operator[](lo).second()
395  )
396  /(
397  List<Tuple2<scalar, Type> >::operator[](hi).first()
398  - List<Tuple2<scalar, Type> >::operator[](lo).first()
399  )
400  );
401  }
402 }
403 
404 
405 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
406 
407 template<class Type>
410 {
411  label ii = i;
412  label n = this->size();
413 
414  if (n <= 1)
415  {
416  ii = 0;
417  }
418  else if (ii < 0)
419  {
420  switch (boundsHandling_)
421  {
423  {
425  (
426  "Foam::interpolationTable<Type>::operator[]"
427  "(const label) const"
428  ) << "index (" << ii << ") underflow" << nl
429  << exit(FatalError);
430  break;
431  }
433  {
434  WarningIn
435  (
436  "Foam::interpolationTable<Type>::operator[]"
437  "(const label) const"
438  ) << "index (" << ii << ") underflow" << nl
439  << " Continuing with the first entry"
440  << endl;
441  // fall-through to 'CLAMP'
442  }
444  {
445  ii = 0;
446  break;
447  }
449  {
450  while (ii < 0)
451  {
452  ii += n;
453  }
454  break;
455  }
456  }
457  }
458  else if (ii >= n)
459  {
460  switch (boundsHandling_)
461  {
463  {
465  (
466  "Foam::interpolationTable<Type>::operator[]"
467  "(const label) const"
468  ) << "index (" << ii << ") overflow" << nl
469  << exit(FatalError);
470  break;
471  }
473  {
474  WarningIn
475  (
476  "Foam::interpolationTable<Type>::operator[]"
477  "(const label) const"
478  ) << "index (" << ii << ") overflow" << nl
479  << " Continuing with the last entry"
480  << endl;
481  // fall-through to 'CLAMP'
482  }
484  {
485  ii = n - 1;
486  break;
487  }
489  {
490  while (ii >= n)
491  {
492  ii -= n;
493  }
494  break;
495  }
496  }
497  }
498 
500 }
501 
502 
503 template<class Type>
504 Type Foam::interpolationTable<Type>::operator()(const scalar value) const
505 {
506  label n = this->size();
507 
508  if (n <= 1)
509  {
510  return List<Tuple2<scalar, Type> >::operator[](0).second();
511  }
512 
513  scalar minLimit = List<Tuple2<scalar, Type> >::operator[](0).first();
514  scalar maxLimit = List<Tuple2<scalar, Type> >::operator[](n-1).first();
515  scalar lookupValue = value;
516 
517  if (lookupValue < minLimit)
518  {
519  switch (boundsHandling_)
520  {
522  {
524  (
525  "Foam::interpolationTable<Type>::operator[]"
526  "(const scalar) const"
527  ) << "value (" << lookupValue << ") underflow" << nl
528  << exit(FatalError);
529  break;
530  }
532  {
533  WarningIn
534  (
535  "Foam::interpolationTable<Type>::operator[]"
536  "(const scalar) const"
537  ) << "value (" << lookupValue << ") underflow" << nl
538  << " Continuing with the first entry"
539  << endl;
540  // fall-through to 'CLAMP'
541  }
543  {
544  return List<Tuple2<scalar, Type> >::operator[](0).second();
545  break;
546  }
548  {
549  // adjust lookupValue to >= minLimit
550  scalar span = maxLimit-minLimit;
551  lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
552  break;
553  }
554  }
555  }
556  else if (lookupValue >= maxLimit)
557  {
558  switch (boundsHandling_)
559  {
561  {
563  (
564  "Foam::interpolationTable<Type>::operator[]"
565  "(const label) const"
566  ) << "value (" << lookupValue << ") overflow" << nl
567  << exit(FatalError);
568  break;
569  }
571  {
572  WarningIn
573  (
574  "Foam::interpolationTable<Type>::operator[]"
575  "(const label) const"
576  ) << "value (" << lookupValue << ") overflow" << nl
577  << " Continuing with the last entry"
578  << endl;
579  // fall-through to 'CLAMP'
580  }
582  {
583  return List<Tuple2<scalar, Type> >::operator[](n-1).second();
584  break;
585  }
587  {
588  // adjust lookupValue <= maxLimit
589  scalar span = maxLimit-minLimit;
590  lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
591  break;
592  }
593  }
594  }
595 
596  label lo = 0;
597  label hi = 0;
598 
599  // look for the correct range
600  for (label i = 0; i < n; ++i)
601  {
602  if (lookupValue >= List<Tuple2<scalar, Type> >::operator[](i).first())
603  {
604  lo = hi = i;
605  }
606  else
607  {
608  hi = i;
609  break;
610  }
611  }
612 
613  if (lo == hi)
614  {
615  // we are at the end of the table - or there is only a single entry
616  return List<Tuple2<scalar, Type> >::operator[](hi).second();
617  }
618  else if (hi == 0)
619  {
620  // this treatment should should only occur under these conditions:
621  // -> the 'REPEAT' treatment
622  // -> (0 <= value <= minLimit)
623  // -> minLimit > 0
624  // Use the value at maxLimit as the value for value=0
625  lo = n - 1;
626 
627  return
628  (
629  List<Tuple2<scalar, Type> >::operator[](lo).second()
630  + (
631  List<Tuple2<scalar, Type> >::operator[](hi).second()
632  - List<Tuple2<scalar, Type> >::operator[](lo).second()
633  )
634  *(lookupValue / minLimit)
635  );
636  }
637  else
638  {
639  // normal interpolation
640  return
641  (
642  List<Tuple2<scalar, Type> >::operator[](lo).second()
643  + (
644  List<Tuple2<scalar, Type> >::operator[](hi).second()
645  - List<Tuple2<scalar, Type> >::operator[](lo).second()
646  )
647  *(
648  lookupValue
649  - List<Tuple2<scalar, Type> >::operator[](lo).first()
650  )
651  /(
652  List<Tuple2<scalar, Type> >::operator[](hi).first()
653  - List<Tuple2<scalar, Type> >::operator[](lo).first()
654  )
655  );
656  }
657 }
658 
659 
660 // ************************************************************************* //
An interpolation/look-up table of scalar vs <Type> values. The reference scalar values must be monoto...
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:47
string & expand(const bool allowEmpty=false)
Expand initial tildes and all occurences of environment variables.
Definition: string.C:98
Type rateOfChange(const scalar) const
Return the rate of change at the interpolation location.
volScalarField & bound(volScalarField &, const dimensionedScalar &lowerBound)
Bound the given scalar field if it has gone unbounded.
Definition: bound.C:33
A class for handling words, derived from string.
Definition: word.H:59
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Reads an interpolation table from a file - OpenFOAM-format.
friend Ostream & operator(Ostream &, const UList< T > &)
Type operator()(const scalar) const
Return an interpolated value.
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
void write(Ostream &os) const
Write.
T & first()
Return the first element of the list.
Definition: UListI.H:117
boundsHandling wordToBoundsHandling(const word &bound) const
Return the out-of-bounds handling as an enumeration.
autoPtr< BasicCompressibleTurbulenceModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const typename BasicCompressibleTurbulenceModel::transportModel &transport, const word &propertiesName)
label n
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
dictionary dict
static const char nl
Definition: Ostream.H:260
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
stressControl lookup("compactNormalStress") >> compactNormalStress
#define WarningIn(functionName)
Report a warning using Foam::Warning.
boundsHandling outOfBounds(const boundsHandling &bound)
Set the out-of-bounds handling from enum, return previous setting.
void check() const
Check that list is monotonically increasing.
Base class to read table data for the interpolationTable.
Definition: tableReader.H:57
boundsHandling
Enumeration for handling out-of-bound values.
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:59
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
error FatalError
word boundsHandlingToWord(const boundsHandling &bound) const
Return the out-of-bounds handling as a word.
A class for handling file names.
Definition: fileName.H:69
interpolationTable()
Construct null.
label size() const
Return the number of elements in the UList.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
const Tuple2< scalar, Type > & operator[](const label) const
Return an element of constant Tuple2<scalar, Type>