interpolation2DTable.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-2017 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 "IFstream.H"
27 #include "openFoamTableReader.H"
28 
29 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
30 
31 template<class Type>
33 {
34  fileName fName(fileName_);
35  fName.expand();
36 
37  // Read data from file
38  reader_()(fName, *this);
39 
40  if (this->empty())
41  {
43  << "table read from " << fName << " is empty" << nl
44  << exit(FatalError);
45  }
46 
47  // Check that the data are in ascending order
48  checkOrder();
49 }
50 
51 
52 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
53 
54 template<class Type>
56 :
57  List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(),
58  boundsHandling_(interpolation2DTable::WARN),
59  fileName_("fileNameIsUndefined"),
60  reader_(nullptr)
61 {}
62 
63 
64 template<class Type>
66 (
67  const List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>& values,
68  const boundsHandling bounds,
69  const fileName& fName
70 )
71 :
73  boundsHandling_(bounds),
74  fileName_(fName),
75  reader_(nullptr)
76 {}
77 
78 
79 template<class Type>
81 :
82  List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(),
83  boundsHandling_(interpolation2DTable::WARN),
84  fileName_(fName),
85  reader_(new openFoamTableReader<Type>(dictionary()))
86 {
87  readTable();
88 }
89 
90 
91 template<class Type>
93 :
94  List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(),
95  boundsHandling_(wordToBoundsHandling(dict.lookup("outOfBounds"))),
96  fileName_(dict.lookup("file")),
97  reader_(tableReader<Type>::New(dict))
98 {
99  readTable();
100 }
101 
102 
103 template<class Type>
105 (
106  const interpolation2DTable& interpTable
107 )
108 :
110  boundsHandling_(interpTable.boundsHandling_),
111  fileName_(interpTable.fileName_),
112  reader_(interpTable.reader_) // note: steals reader. Used in write().
113 {}
114 
115 
116 
117 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
118 
119 template<class Type>
121 (
123  const scalar lookupValue
124 ) const
125 {
126  label n = data.size();
127 
128  scalar minLimit = data.first().first();
129  scalar maxLimit = data.last().first();
130 
131  if (lookupValue < minLimit)
132  {
133  switch (boundsHandling_)
134  {
135  case interpolation2DTable::ERROR:
136  {
138  << "value (" << lookupValue << ") less than lower "
139  << "bound (" << minLimit << ")" << nl
140  << exit(FatalError);
141  break;
142  }
143  case interpolation2DTable::WARN:
144  {
146  << "value (" << lookupValue << ") less than lower "
147  << "bound (" << minLimit << ")" << nl
148  << " Continuing with the first entry"
149  << endl;
150  // fall-through to 'CLAMP'
151  }
152  case interpolation2DTable::CLAMP:
153  {
154  return data.first().second();
155  break;
156  }
157  }
158  }
159  else if (lookupValue >= maxLimit)
160  {
161  switch (boundsHandling_)
162  {
163  case interpolation2DTable::ERROR:
164  {
166  << "value (" << lookupValue << ") greater than upper "
167  << "bound (" << maxLimit << ")" << nl
168  << exit(FatalError);
169  break;
170  }
171  case interpolation2DTable::WARN:
172  {
174  << "value (" << lookupValue << ") greater than upper "
175  << "bound (" << maxLimit << ")" << nl
176  << " Continuing with the last entry"
177  << endl;
178  // fall-through to 'CLAMP'
179  }
180  case interpolation2DTable::CLAMP:
181  {
182  return data.last().second();
183  break;
184  }
185  }
186  }
187 
188  // look for the correct range in X
189  label lo = 0;
190  label hi = 0;
191 
192  for (label i = 0; i < n; ++i)
193  {
194  if (lookupValue >= data[i].first())
195  {
196  lo = hi = i;
197  }
198  else
199  {
200  hi = i;
201  break;
202  }
203  }
204 
205  if (lo == hi)
206  {
207  return data[lo].second();
208  }
209  else
210  {
211  Type m =
212  (data[hi].second() - data[lo].second())
213  /(data[hi].first() - data[lo].first());
214 
215  // normal interpolation
216  return data[lo].second() + m*(lookupValue - data[lo].first());
217  }
218 }
219 
220 
221 template<class Type>
222 template<class BinaryOp>
224 (
225  const BinaryOp& bop,
226  const scalar valueX,
227  const bool reverse
228 ) const
229 {
230  const table& t = *this;
231 
232  label limitI = 0;
233  if (reverse)
234  {
235  limitI = t.size() - 1;
236  }
237 
238  if (bop(valueX, t[limitI].first()))
239  {
240  switch (boundsHandling_)
241  {
242  case interpolation2DTable::ERROR:
243  {
245  << "value (" << valueX << ") out of bounds"
246  << exit(FatalError);
247  break;
248  }
249  case interpolation2DTable::WARN:
250  {
252  << "value (" << valueX << ") out of bounds"
253  << endl;
254  // fall-through to 'CLAMP'
255  }
256  case interpolation2DTable::CLAMP:
257  {
258  return limitI;
259  }
260  default:
261  {
263  << "Un-handled enumeration " << boundsHandling_
264  << abort(FatalError);
265  }
266  }
267  }
268 
269  label i = 0;
270  if (reverse)
271  {
272  label nX = t.size();
273  i = 0;
274  while ((i < nX) && (valueX > t[i].first()))
275  {
276  i++;
277  }
278  }
279  else
280  {
281  i = t.size() - 1;
282  while ((i > 0) && (valueX < t[i].first()))
283  {
284  i--;
285  }
286  }
287 
288  return i;
289 }
290 
291 
292 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
293 
294 template<class Type>
296 (
297  const scalar valueX,
298  const scalar valueY
299 ) const
300 {
301  // Considers all of the list in Y being equal
302  label nX = this->size();
303 
304  const table& t = *this;
305 
306  if (nX == 0)
307  {
309  << "cannot interpolate a zero-sized table - returning zero" << endl;
310 
311  return Zero;
312  }
313  else if (nX == 1)
314  {
315  // only 1 column (in X) - interpolate to find Y value
316  return interpolateValue(t.first().second(), valueY);
317  }
318  else
319  {
320  // have 2-D data, interpolate
321 
322  // find low and high indices in the X range that bound valueX
323  label x0i = Xi(lessOp<scalar>(), valueX, false);
324  label x1i = Xi(greaterOp<scalar>(), valueX, true);
325 
326  if (x0i == x1i)
327  {
328  return interpolateValue(t[x0i].second(), valueY);
329  }
330  else
331  {
332  Type y0(interpolateValue(t[x0i].second(), valueY));
333  Type y1(interpolateValue(t[x1i].second(), valueY));
334 
335  // gradient in X
336  scalar x0 = t[x0i].first();
337  scalar x1 = t[x1i].first();
338  Type mX = (y1 - y0)/(x1 - x0);
339 
340  // interpolate
341  return y0 + mX*(valueX - x0);
342  }
343  }
344 }
345 
346 
347 template<class Type>
349 (
350  const boundsHandling& bound
351 ) const
352 {
353  word enumName("warn");
354 
355  switch (bound)
356  {
357  case interpolation2DTable::ERROR:
358  {
359  enumName = "error";
360  break;
361  }
362  case interpolation2DTable::WARN:
363  {
364  enumName = "warn";
365  break;
366  }
367  case interpolation2DTable::CLAMP:
368  {
369  enumName = "clamp";
370  break;
371  }
372  }
373 
374  return enumName;
375 }
376 
377 
378 template<class Type>
381 (
382  const word& bound
383 ) const
384 {
385  if (bound == "error")
386  {
387  return interpolation2DTable::ERROR;
388  }
389  else if (bound == "warn")
390  {
391  return interpolation2DTable::WARN;
392  }
393  else if (bound == "clamp")
394  {
395  return interpolation2DTable::CLAMP;
396  }
397  else
398  {
400  << "bad outOfBounds specifier " << bound << " using 'warn'" << endl;
401 
402  return interpolation2DTable::WARN;
403  }
404 }
405 
406 
407 template<class Type>
410 (
411  const boundsHandling& bound
412 )
413 {
414  boundsHandling prev = boundsHandling_;
415  boundsHandling_ = bound;
416  return prev;
417 }
418 
419 
420 template<class Type>
422 {
423  label n = this->size();
424  const table& t = *this;
425 
426  scalar prevValue = t[0].first();
427 
428  for (label i=1; i<n; ++i)
429  {
430  const scalar currValue = t[i].first();
431 
432  // avoid duplicate values (divide-by-zero error)
433  if (currValue <= prevValue)
434  {
436  << "out-of-order value: "
437  << currValue << " at index " << i << nl
438  << exit(FatalError);
439  }
440  prevValue = currValue;
441  }
442 }
443 
444 
445 template<class Type>
447 {
448  os.writeKeyword("file")
449  << fileName_ << token::END_STATEMENT << nl;
450  os.writeKeyword("outOfBounds")
451  << boundsHandlingToWord(boundsHandling_) << token::END_STATEMENT << nl;
452 
453  *this >> os;
454 }
455 
456 
457 // ************************************************************************* //
dictionary dict
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
A class for handling file names.
Definition: fileName.H:69
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
friend Ostream & operator(Ostream &, const UList< T > &)
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
A 2-tuple for storing two objects of different types.
Definition: HashTable.H:66
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:60
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
2D table interpolation. The data must be in ascending order in both dimensions x and y...
dimensionedScalar y0(const dimensionedScalar &ds)
Reads an interpolation table from a file - OpenFOAM-format.
T * last()
Return the last entry.
Definition: UILList.H:118
T & first()
Return the first element of the list.
Definition: UListI.H:114
Base class to read table data for the interpolationTable.
Definition: tableReader.H:57
word boundsHandlingToWord(const boundsHandling &bound) const
Return the out-of-bounds handling as a word.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
stressControl lookup("compactNormalStress") >> compactNormalStress
interpolation2DTable()
Construct null.
A class for handling words, derived from string.
Definition: word.H:59
static const zero Zero
Definition: zero.H:91
errorManip< error > abort(error &err)
Definition: errorManip.H:131
dimensionedScalar y1(const dimensionedScalar &ds)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
void reverse(UList< T > &, const label n)
Definition: UListI.H:322
static const char nl
Definition: Ostream.H:262
void write(Ostream &os) const
Write.
Database for solution data, solver performance and other reduced data.
Definition: data.H:52
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:54
boundsHandling outOfBounds(const boundsHandling &bound)
Set the out-of-bounds handling from enum, return previous setting.
volScalarField & bound(volScalarField &, const dimensionedScalar &lowerBound)
Bound the given scalar field if it has gone unbounded.
Definition: bound.C:33
#define WarningInFunction
Report a warning using Foam::Warning.
string & expand(const bool allowEmpty=false)
Expand initial tildes and all occurences of environment variables.
Definition: string.C:95
void checkOrder() const
Check that list is monotonically increasing.
boundsHandling wordToBoundsHandling(const word &bound) const
Return the out-of-bounds handling as an enumeration.
boundsHandling
Enumeration for handling out-of-bound values.
label n
T * first()
Return the first entry.
Definition: UILList.H:106