FreeFOAM The Cross-Platform CFD Toolkit
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) 1991-2011 OpenCFD Ltd.
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 <OpenFOAM/IFstream.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>())
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 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
123 
124 template<class Type>
126 (
127  const boundsHandling& bound
128 ) const
129 {
130  word enumName("warn");
131 
132  switch (bound)
133  {
135  {
136  enumName = "error";
137  break;
138  }
140  {
141  enumName = "warn";
142  break;
143  }
145  {
146  enumName = "clamp";
147  break;
148  }
150  {
151  enumName = "repeat";
152  break;
153  }
154  }
155 
156  return enumName;
157 }
158 
159 
160 template<class Type>
163 (
164  const word& bound
165 ) const
166 {
167  if (bound == "error")
168  {
170  }
171  else if (bound == "warn")
172  {
174  }
175  else if (bound == "clamp")
176  {
178  }
179  else if (bound == "repeat")
180  {
182  }
183  else
184  {
185  WarningIn
186  (
187  "Foam::interpolationTable<Type>::wordToBoundsHandling(const word&)"
188  ) << "bad outOfBounds specifier " << bound << " using 'warn'" << endl;
189 
191  }
192 }
193 
194 
195 template<class Type>
198 (
199  const boundsHandling& bound
200 )
201 {
202  boundsHandling prev = boundsHandling_;
203  boundsHandling_ = bound;
204  return prev;
205 }
206 
207 
208 template<class Type>
210 {
211  label n = this->size();
212  scalar prevValue = List<Tuple2<scalar, Type> >::operator[](0).first();
213 
214  for (label i=1; i<n; ++i)
215  {
216  const scalar currValue =
217  List<Tuple2<scalar, Type> >::operator[](i).first();
218 
219  // avoid duplicate values (divide-by-zero error)
220  if (currValue <= prevValue)
221  {
223  (
224  "Foam::interpolationTable<Type>::checkOrder() const"
225  ) << "out-of-order value: "
226  << currValue << " at index " << i << nl
227  << exit(FatalError);
228  }
229  prevValue = currValue;
230  }
231 }
232 
233 
234 template<class Type>
236 {
237  os.writeKeyword("fileName")
238  << fileName_ << token::END_STATEMENT << nl;
239  os.writeKeyword("outOfBounds")
240  << boundsHandlingToWord(boundsHandling_) << token::END_STATEMENT << nl;
241  if (reader_.valid())
242  {
243  reader_->write(os);
244  }
245 }
246 
247 
248 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
249 
250 template<class Type>
253 {
254  label ii = i;
255  label n = this->size();
256 
257  if (n <= 1)
258  {
259  ii = 0;
260  }
261  else if (ii < 0)
262  {
263  switch (boundsHandling_)
264  {
266  {
268  (
269  "Foam::interpolationTable<Type>::operator[]"
270  "(const label) const"
271  ) << "index (" << ii << ") underflow" << nl
272  << exit(FatalError);
273  break;
274  }
276  {
277  WarningIn
278  (
279  "Foam::interpolationTable<Type>::operator[]"
280  "(const label) const"
281  ) << "index (" << ii << ") underflow" << nl
282  << " Continuing with the first entry"
283  << endl;
284  // fall-through to 'CLAMP'
285  }
287  {
288  ii = 0;
289  break;
290  }
292  {
293  while (ii < 0)
294  {
295  ii += n;
296  }
297  break;
298  }
299  }
300  }
301  else if (ii >= n)
302  {
303  switch (boundsHandling_)
304  {
306  {
308  (
309  "Foam::interpolationTable<Type>::operator[]"
310  "(const label) const"
311  ) << "index (" << ii << ") overflow" << nl
312  << exit(FatalError);
313  break;
314  }
316  {
317  WarningIn
318  (
319  "Foam::interpolationTable<Type>::operator[]"
320  "(const label) const"
321  ) << "index (" << ii << ") overflow" << nl
322  << " Continuing with the last entry"
323  << endl;
324  // fall-through to 'CLAMP'
325  }
327  {
328  ii = n - 1;
329  break;
330  }
332  {
333  while (ii >= n)
334  {
335  ii -= n;
336  }
337  break;
338  }
339  }
340  }
341 
342  return List<Tuple2<scalar, Type> >::operator[](ii);
343 }
344 
345 
346 template<class Type>
347 Type Foam::interpolationTable<Type>::operator()(const scalar value) const
348 {
349  label n = this->size();
350 
351  if (n <= 1)
352  {
353  return List<Tuple2<scalar, Type> >::operator[](0).second();
354  }
355 
356  scalar minLimit = List<Tuple2<scalar, Type> >::operator[](0).first();
357  scalar maxLimit = List<Tuple2<scalar, Type> >::operator[](n-1).first();
358  scalar lookupValue = value;
359 
360  if (lookupValue < minLimit)
361  {
362  switch (boundsHandling_)
363  {
365  {
367  (
368  "Foam::interpolationTable<Type>::operator[]"
369  "(const scalar) const"
370  ) << "value (" << lookupValue << ") underflow" << nl
371  << exit(FatalError);
372  break;
373  }
375  {
376  WarningIn
377  (
378  "Foam::interpolationTable<Type>::operator[]"
379  "(const scalar) const"
380  ) << "value (" << lookupValue << ") underflow" << nl
381  << " Continuing with the first entry"
382  << endl;
383  // fall-through to 'CLAMP'
384  }
386  {
387  return List<Tuple2<scalar, Type> >::operator[](0).second();
388  break;
389  }
391  {
392  // adjust lookupValue to >= minLimit
393  scalar span = maxLimit-minLimit;
394  lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
395  break;
396  }
397  }
398  }
399  else if (lookupValue >= maxLimit)
400  {
401  switch (boundsHandling_)
402  {
404  {
406  (
407  "Foam::interpolationTable<Type>::operator[]"
408  "(const label) const"
409  ) << "value (" << lookupValue << ") overflow" << nl
410  << exit(FatalError);
411  break;
412  }
414  {
415  WarningIn
416  (
417  "Foam::interpolationTable<Type>::operator[]"
418  "(const label) const"
419  ) << "value (" << lookupValue << ") overflow" << nl
420  << " Continuing with the last entry"
421  << endl;
422  // fall-through to 'CLAMP'
423  }
425  {
426  return List<Tuple2<scalar, Type> >::operator[](n-1).second();
427  break;
428  }
430  {
431  // adjust lookupValue <= maxLimit
432  scalar span = maxLimit-minLimit;
433  lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
434  break;
435  }
436  }
437  }
438 
439  label lo = 0;
440  label hi = 0;
441 
442  // look for the correct range
443  for (label i = 0; i < n; ++i)
444  {
445  if (lookupValue >= List<Tuple2<scalar, Type> >::operator[](i).first())
446  {
447  lo = hi = i;
448  }
449  else
450  {
451  hi = i;
452  break;
453  }
454  }
455 
456  if (lo == hi)
457  {
458  // we are at the end of the table - or there is only a single entry
459  return List<Tuple2<scalar, Type> >::operator[](hi).second();
460  }
461  else if (hi == 0)
462  {
463  // this treatment should should only occur under these conditions:
464  // -> the 'REPEAT' treatment
465  // -> (0 <= value <= minLimit)
466  // -> minLimit > 0
467  // Use the value at maxLimit as the value for value=0
468  lo = n - 1;
469 
470  return
471  (
472  List<Tuple2<scalar, Type> >::operator[](lo).second()
473  + (
474  List<Tuple2<scalar, Type> >::operator[](hi).second()
475  - List<Tuple2<scalar, Type> >::operator[](lo).second()
476  )
477  *(lookupValue / minLimit)
478  );
479  }
480  else
481  {
482  // normal interpolation
483  return
484  (
485  List<Tuple2<scalar, Type> >::operator[](lo).second()
486  + (
487  List<Tuple2<scalar, Type> >::operator[](hi).second()
488  - List<Tuple2<scalar, Type> >::operator[](lo).second()
489  )
490  *(
491  lookupValue
492  - List<Tuple2<scalar, Type> >::operator[](lo).first()
493  )
494  /(
495  List<Tuple2<scalar, Type> >::operator[](hi).first()
496  - List<Tuple2<scalar, Type> >::operator[](lo).first()
497  )
498  );
499  }
500 }
501 
502 
503 // ************************ vim: set sw=4 sts=4 et: ************************ //