Table.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 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 "Table.H"
28 
29 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
30 
31 template<class Type>
34 {
35  if (interpolatorPtr_.empty())
36  {
37  // Re-work table into linear list
38  tableSamplesPtr_.reset(new scalarField(values_.size()));
39  scalarField& tableSamples = tableSamplesPtr_();
40  forAll(values_, i)
41  {
42  tableSamples[i] = values_[i].first();
43  }
44  interpolatorPtr_ = interpolationWeights::New
45  (
46  interpolationScheme_,
47  tableSamples
48  );
49  }
50 
51  return interpolatorPtr_();
52 }
53 
54 
55 template<class Type>
57 {
58  if (!values_.size())
59  {
61  << "Table for entry " << this->name() << " is invalid (empty)"
62  << nl << exit(FatalError);
63  }
64 
65  label n = values_.size();
66  scalar prevValue = values_[0].first();
67 
68  for (label i = 1; i < n; ++i)
69  {
70  const scalar currValue = values_[i].first();
71 
72  // avoid duplicate values (divide-by-zero error)
73  if (currValue <= prevValue)
74  {
76  << "out-of-order value: " << currValue << " at index " << i
77  << exit(FatalError);
78  }
79  prevValue = currValue;
80  }
81 }
82 
83 
84 template<class Type>
85 void Foam::Function1s::Table<Type>::checkX(const scalar x) const
86 {
87  const bool under = x < values_.first().first();
88  const bool over = x > values_.last().first();
89 
90  auto errorMessage = [&]()
91  {
92  return "value (" + name(x) + ") " + (under ? "under" : "over") + "flow";
93  };
94 
95  if (under || over)
96  {
97  switch (boundsHandling_)
98  {
99  case tableBase::boundsHandling::error:
100  {
102  << errorMessage() << nl << exit(FatalError);
103  break;
104  }
105  case tableBase::boundsHandling::warn:
106  {
108  << errorMessage() << nl << endl;
109  break;
110  }
111  default:
112  {
113  break;
114  }
115  }
116  }
117 }
118 
119 
120 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
121 
122 template<class Type>
124 (
125  const word& name,
127  const word& interpolationScheme,
128  const autoPtr<TableReader<scalar, Type>>& reader,
130 )
131 :
132  FieldFunction1<Type, Table<Type>>(name),
133  boundsHandling_(boundsHandling),
134  interpolationScheme_(interpolationScheme),
135  reader_(reader, false),
136  values_(table)
137 {}
138 
139 
140 template<class Type>
142 (
143  const word& name,
144  const unitSets& units,
145  const dictionary& dict
146 )
147 :
148  FieldFunction1<Type, Table<Type>>(name),
149  boundsHandling_
150  (
151  tableBase::boundsHandlingNames.lookupOrDefault
152  (
153  "outOfBounds",
154  dict,
155  tableBase::boundsHandling::clamp
156  )
157  ),
158  interpolationScheme_
159  (
160  dict.lookupOrDefault<word>
161  (
162  "interpolationScheme",
164  )
165  ),
166  reader_(TableReader<scalar, Type>::New(name, units, dict)),
167  values_(reader_->read(units, dict))
168 {
169  check();
170 }
171 
172 
173 template<class Type>
175 (
176  const word& name,
177  const unitSet& xUnits,
178  const unitSet& valueUnits,
179  const dictionary& dict
180 )
181 :
182  Table(name, {xUnits, valueUnits}, dict)
183 {}
184 
185 
186 template<class Type>
188 (
189  const word& name,
190  const unitSets& units,
191  Istream& is
192 )
193 :
194  FieldFunction1<Type, Table<Type>>(name),
195  boundsHandling_(tableBase::boundsHandling::clamp),
196  interpolationScheme_(linearInterpolationWeights::typeName),
197  reader_(new TableReaders::Embedded<scalar, Type>()),
198  values_(TableReaders::Embedded<scalar, Type>().read(units, is))
199 {
200  check();
201 }
202 
203 
204 template<class Type>
206 :
207  FieldFunction1<Type, Table<Type>>(tbl),
208  boundsHandling_(tbl.boundsHandling_),
209  interpolationScheme_(tbl.interpolationScheme_),
210  reader_(tbl.reader_, false),
211  values_(tbl.values_),
212  tableSamplesPtr_(tbl.tableSamplesPtr_),
213  interpolatorPtr_(tbl.interpolatorPtr_)
214 {}
215 
216 
217 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
218 
219 template<class Type>
221 {}
222 
223 
224 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
225 
226 template<class Type>
228 (
229  const scalar xArg
230 ) const
231 {
232  scalar x(xArg);
233 
234  checkX(x);
235 
236  const scalar x0 = values_.first().first();
237  const scalar x1 = values_.last().first();
238 
239  Type y = Zero;
240 
241  switch (boundsHandling_)
242  {
244  {
245  // Integration weights clamp by default, so do nothing
246  break;
247  }
249  {
250  // Return zero if outside the range
251  if (x <= x0 || x >= x1)
252  {
253  return Zero;
254  }
255  break;
256  }
258  {
259  // Shift the value into the range of the table
260  const scalar n = floor((x - x0)/(x1 - x0));
261  x -= n*(x1 - x0);
262  break;
263  }
264  default:
265  {
266  break;
267  }
268  }
269 
270  // Evaluate
271  interpolator().valueWeights(x, indices_, weights_);
272  forAll(indices_, i)
273  {
274  y += weights_[i]*values_[indices_[i]].second();
275  }
276 
277  return y;
278 }
279 
280 
281 template<class Type>
283 (
284  const scalar xAarg,
285  const scalar xBarg
286 ) const
287 {
288  scalar xA(xAarg), xB(xBarg);
289 
290  checkX(xA);
291  checkX(xB);
292 
293  const scalar x0 = values_.first().first();
294  const scalar x1 = values_.last().first();
295 
296  Type sumY = Zero;
297 
298  switch (boundsHandling_)
299  {
301  {
302  // Integration weights clamp by default, so do nothing
303  break;
304  }
306  {
307  // Actually clamp to remove any integral components from the ends
308  xA = min(max(xA, x0), x1);
309  xB = min(max(xB, x0), x1);
310  break;
311  }
313  {
314  // Shift the values into the range of the table and add any
315  // repetitions necessary to the integral
316  const scalar nA = floor((xA - x0)/(x1 - x0));
317  const scalar nB = floor((xB - x0)/(x1 - x0));
318  if (nA != nB)
319  {
320  interpolator().integrationWeights(x0, x1, indices_, weights_);
321  forAll(indices_, i)
322  {
323  sumY += (nB - nA)*weights_[i]*values_[indices_[i]].second();
324  }
325  }
326  xA -= nA*(x1 - x0);
327  xB -= nB*(x1 - x0);
328  break;
329  }
330  default:
331  {
332  break;
333  }
334  }
335 
336  // Integrate between the bounds
337  interpolator().integrationWeights(xA, xB, indices_, weights_);
338  forAll(indices_, i)
339  {
340  sumY += weights_[i]*values_[indices_[i]].second();
341  }
342 
343  return sumY;
344 }
345 
346 
347 template<class Type>
350 {
351  tmp<scalarField> tfld(new scalarField(values_.size(), 0.0));
352  scalarField& fld = tfld.ref();
353 
354  forAll(values_, i)
355  {
356  fld[i] = values_[i].first();
357  }
358 
359  return tfld;
360 }
361 
362 
363 template<class Type>
366 {
367  tmp<Field<Type>> tfld(new Field<Type>(values_.size(), Zero));
368  Field<Type>& fld = tfld.ref();
369 
370  forAll(values_, i)
371  {
372  fld[i] = values_[i].second();
373  }
374 
375  return tfld;
376 }
377 
378 
379 template<class Type>
381 (
382  Ostream& os,
383  const unitSets& units
384 ) const
385 {
387  (
388  os,
389  "outOfBounds",
391  tableBase::boundsHandlingNames[boundsHandling_]
392  );
393 
395  (
396  os,
397  "interpolationScheme",
399  interpolationScheme_
400  );
401 
402  reader_->write(os, units, values_);
403 }
404 
405 
406 // ************************************************************************* //
scalar y
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Templated interpolated tabulated data Function1.
Definition: Table.H:122
virtual Type integral(const scalar xA, const scalar xB) const
Integrate between two scalars.
Definition: Table.C:283
virtual tmp< scalarField > x() const
Return the reference values.
Definition: Table.C:349
virtual void write(Ostream &os, const unitSets &units) const
Write data to dictionary stream.
Definition: Table.C:381
virtual tmp< Field< Type > > y() const
Return the dependent values.
Definition: Table.C:365
virtual Type value(const scalar x) const
Return Table value as a function of scalar x.
Definition: Table.C:228
Table(const word &name, const tableBase::boundsHandling boundsHandling, const word &interpolationScheme, const autoPtr< TableReader< scalar, Type >> &reader, const List< Tuple2< scalar, Type >> &table)
Construct from components.
Definition: Table.C:124
virtual ~Table()
Destructor.
Definition: Table.C:220
static const NamedEnum< boundsHandling, 5 > boundsHandlingNames
Enumeration names for handling out-of-bound values.
Definition: tableBase.H:64
boundsHandling
Enumeration for handling out-of-bound values.
Definition: tableBase.H:55
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
Base class to read table data for tables.
Definition: TableReader.H:51
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:66
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Abstract base class for interpolating in 1D.
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
Unit conversion structure. Contains the associated dimensions and the multiplier with which to conver...
Definition: unitSet.H:68
A class for handling words, derived from string.
Definition: word.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
volScalarField scalarField(fieldObject, mesh)
gmvFile<< "tracers "<< particles.size()<< nl;{ pointField positions(particles.size());label particlei=0;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter) { positions[particlei++]=iter().position(mesh);} for(i=0;i< pTraits< point >::nComponents;i++) { forAll(positions, particlei) { gmvFile<< component(positions[particlei], i)<< ' ';} gmvFile<< nl;}}forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define WarningInFunction
Report a warning using Foam::Warning.
const HashTable< dimensionSet > table
Table of dimensions.
Definition: dimensions.C:74
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
bool read(const char *, int32_t &)
Definition: int32IO.C:85
void writeEntryIfDifferent(Ostream &os, const word &entryName, const EntryType &value1, const EntryType &value2)
Helper function to write the keyword and entry only if the.
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
labelList second(const UList< labelPair > &p)
Definition: patchToPatch.C:49
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
static const char nl
Definition: Ostream.H:297
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dictionary dict
Struct containing two unitSets for use in converting both the argument and the value of a Function1.