https://mooseframework.inl.gov
Public Member Functions | Protected Member Functions | Protected Attributes | Private Attributes | List of all members
MultiDimensionalInterpolationTempl< T > Class Template Reference

This class interpolates multi-dimensional data sets. More...

#include <MultiDimensionalInterpolation.h>

Public Member Functions

 MultiDimensionalInterpolationTempl (const std::vector< std::vector< Real >> &base_points, const MultiIndex< Real > &data)
 Constructor, Takes a double vector containing the interpolation base points, and a MultiIndex object. More...
 
 MultiDimensionalInterpolationTempl ()
 
virtual ~MultiDimensionalInterpolationTempl ()=default
 
unsigned int dim () const
 returns the dimensionality of this interpolation object More...
 
void setData (const std::vector< std::vector< Real >> &base_points, const MultiIndex< Real > &data)
 sets data but also fixes degenerate dimensions in data More...
 
void linearSearch (std::vector< T > &values, MultiIndex< Real >::size_type &indices) const
 linearSearch finds the indices i_k of the base point such that base_point[d][i_k] <= values[d] < base_point[d][i_k + 1] Note that argument is non-const to handle smaller/larger than tabulation range For tabulations < 100 entries, linearSearch is expected to be better than bisection search More...
 
multiLinearInterpolation (const std::vector< T > &x) const
 This function will take an independent variable input and will return the dependent variable based on multi-linear interpolation. More...
 

Protected Member Functions

void errorCheck ()
 checks consistency of the data More...
 
unsigned int linearSearchHelper (T &x, const std::vector< Real > &vector) const
 linear search helper for a single std::vector; note that argument is non-const to handle smaller/larger than tabulation range More...
 

Protected Attributes

unsigned int _original_dim
 original dimension is to allow checks on user inputs for cases where arrays are sliced More...
 
std::vector< bool > _degenerate_index
 this variable keeps track on which dimension is degenerate and was removed More...
 
bool _degenerate_interpolation = false
 if all dimensions have size one then there is only one value to return this corner case should be supported so the calling routine does not need to check for it More...
 

Private Attributes

std::vector< std::vector< Real > > _base_points
 
MultiIndex< Real_data
 
bool _setup_complete = false
 

Detailed Description

template<typename T>
class MultiDimensionalInterpolationTempl< T >

This class interpolates multi-dimensional data sets.

Definition at line 23 of file MultiDimensionalInterpolation.h.

Constructor & Destructor Documentation

◆ MultiDimensionalInterpolationTempl() [1/2]

template<typename T >
MultiDimensionalInterpolationTempl< T >::MultiDimensionalInterpolationTempl ( const std::vector< std::vector< Real >> &  base_points,
const MultiIndex< Real > &  data 
)

Constructor, Takes a double vector containing the interpolation base points, and a MultiIndex object.

The double vector base_points and the MultiIndex object data must

Definition at line 17 of file MultiDimensionalInterpolation.C.

19  : _base_points(std::vector<std::vector<Real>>()), _data(MultiIndex<Real>({}))
20 {
21  setData(base_points, data);
22 }
void setData(const std::vector< std::vector< Real >> &base_points, const MultiIndex< Real > &data)
sets data but also fixes degenerate dimensions in data
std::vector< std::vector< Real > > _base_points

◆ MultiDimensionalInterpolationTempl() [2/2]

Definition at line 25 of file MultiDimensionalInterpolation.C.

26  : _base_points(std::vector<std::vector<Real>>()), _data(MultiIndex<Real>({}))
27 {
28 }
std::vector< std::vector< Real > > _base_points

◆ ~MultiDimensionalInterpolationTempl()

template<typename T >
virtual MultiDimensionalInterpolationTempl< T >::~MultiDimensionalInterpolationTempl ( )
virtualdefault

Member Function Documentation

◆ dim()

template<typename T >
unsigned int MultiDimensionalInterpolationTempl< T >::dim ( ) const
inline

returns the dimensionality of this interpolation object

Definition at line 37 of file MultiDimensionalInterpolation.h.

37 { return _original_dim; }
unsigned int _original_dim
original dimension is to allow checks on user inputs for cases where arrays are sliced ...

◆ errorCheck()

template<typename T >
void MultiDimensionalInterpolationTempl< T >::errorCheck ( )
protected

checks consistency of the data

Definition at line 91 of file MultiDimensionalInterpolation.C.

92 {
93  if (_base_points.size() != _data.dim())
94  throw std::domain_error("Size of the leading dimension of base points must be equal to "
95  "dimensionality of data array");
96 
98  for (unsigned int j = 0; j < _data.dim(); ++j)
99  {
100  if (shape[j] != _base_points[j].size())
101  {
102  std::ostringstream oss;
103  oss << "Dimension " << j << " has " << _base_points[j].size()
104  << " base points but dimension of data array is " << shape[j];
105  throw std::domain_error(oss.str());
106  }
107 
108  for (unsigned int i = 1; i < _base_points[j].size(); ++i)
109  {
110  if (_base_points[j][i - 1] >= _base_points[j][i])
111  {
112  std::ostringstream oss;
113  oss << "Base point values for dimension " << j << " are not strictly increasing: bp["
114  << i - 1 << "]: " << _base_points[j][i - 1] << " bc[" << i
115  << "]: " << _base_points[j][i];
116  throw std::domain_error(oss.str());
117  }
118  }
119  }
120 
121  // now the setup is complete
122  _setup_complete = true;
123 }
std::vector< std::vector< Real > > _base_points
unsigned int dim() const
dimension of the container
Definition: MultiIndex.h:62
const size_type & size() const
container size as dim dimensional vector
Definition: MultiIndex.h:59
Implements a container class for multi-indexed objects with an arbitrary number of indices...
Definition: MultiIndex.h:22

◆ linearSearch()

template<typename T >
void MultiDimensionalInterpolationTempl< T >::linearSearch ( std::vector< T > &  values,
MultiIndex< Real >::size_type &  indices 
) const

linearSearch finds the indices i_k of the base point such that base_point[d][i_k] <= values[d] < base_point[d][i_k + 1] Note that argument is non-const to handle smaller/larger than tabulation range For tabulations < 100 entries, linearSearch is expected to be better than bisection search

Definition at line 127 of file MultiDimensionalInterpolation.C.

129 {
130  assert(values.size() == _data.dim());
131 
132  indices.resize(_data.dim());
133  for (unsigned int d = 0; d < _data.dim(); ++d)
134  indices[d] = linearSearchHelper(values[d], _base_points[d]);
135 }
unsigned int linearSearchHelper(T &x, const std::vector< Real > &vector) const
linear search helper for a single std::vector; note that argument is non-const to handle smaller/larg...
std::vector< std::vector< Real > > _base_points
unsigned int dim() const
dimension of the container
Definition: MultiIndex.h:62
void resize(const size_type &shape)
Resize container. Must keep dimensionality constant.
Definition: MultiIndex.h:345

◆ linearSearchHelper()

template<typename T >
unsigned int MultiDimensionalInterpolationTempl< T >::linearSearchHelper ( T &  x,
const std::vector< Real > &  vector 
) const
protected

linear search helper for a single std::vector; note that argument is non-const to handle smaller/larger than tabulation range

Definition at line 139 of file MultiDimensionalInterpolation.C.

141 {
142 // check order of vector only in debug
143 #ifndef NDEBUG
144  for (unsigned int i = 1; i < vector.size(); ++i)
145  {
146  if (vector[i - 1] >= vector[i])
147  {
148  std::ostringstream oss;
149  oss << "In linearSearchHelper vector is not strictly increasing: vector[" << i - 1
150  << "]: " << vector[i - 1] << " vector[" << i << "]: " << vector[i];
151  throw std::domain_error(oss.str());
152  }
153  }
154 #endif
155 
156  // smaller/larger cases for tabulation
157  if (x < vector[0])
158  {
159  x = vector[0];
160  return 0;
161  }
162  else if (x >= vector.back())
163  {
164  // this requires explanation because it looks like a bug (I swear it isn't, it's a feature)
165  // if x >= largest base point value and the index i = vector.size() - 1 is returned, then during
166  // the interpolation, i + 1 will be accessed, causing a segementation fault. Logic in the
167  // interpolation is also bad because it may slow it down. By returning i = vector.size() - 2,
168  // the last two values in the base point array are used, but x is reset to be equal to the last
169  // value. This will give the right interpolation behavior.
170  x = vector.back();
171  return vector.size() - 2;
172  }
173 
174  for (unsigned int j = 0; j < vector.size() - 2; ++j)
175  if (x >= vector[j] && x < vector[j + 1])
176  return j;
177  return vector.size() - 2;
178 }

◆ multiLinearInterpolation()

template<typename T >
T MultiDimensionalInterpolationTempl< T >::multiLinearInterpolation ( const std::vector< T > &  x) const

This function will take an independent variable input and will return the dependent variable based on multi-linear interpolation.

Multi-linear interpolation uses all 2^d values in the base points surrounding x.

Definition at line 182 of file MultiDimensionalInterpolation.C.

183 {
184  // ensure that object has been set up properly
185  if (!_setup_complete)
186  throw std::domain_error(
187  "Object has been constructed properly. This happens when the empty constructor is called "
188  "and setData is not called before interpolation.");
189 
190  // assert does not seem to be enough to check data consistency here
191  // because this function is exposed to user and will be frequently used
192  if (x.size() != _original_dim)
193  {
194  std::ostringstream oss;
195  oss << "In sample the parameter x has size " << x.size() << " but data has dimension "
196  << _data.dim();
197  throw std::domain_error(oss.str());
198  }
199 
200  // in this case there is only one entry that resides at flat index 0
202  return _data[0];
203 
204  // make a copy of x because linearSearch needs to be able to modify it
205  // also adjust for degenerate indices that were removed
206  std::vector<T> y(_data.dim());
207  unsigned int l = 0;
208  for (unsigned int j = 0; j < _original_dim; ++j)
209  if (!_degenerate_index[j])
210  {
211  y[l] = x[j];
212  ++l;
213  }
214 
215  // obtain the indices using linearSearch & get flat index in _data array
217  linearSearch(y, indices);
218 
219  // pre-compute the volume of the hypercube and weights used for the interpolation
220  Real volume = 1;
221  std::vector<std::vector<T>> weights(_data.dim());
222  for (unsigned int j = 0; j < _data.dim(); ++j)
223  {
224  volume *= _base_points[j][indices[j] + 1] - _base_points[j][indices[j]];
225 
226  // now compute weight for each dimension, note that
227  // weight[j][0] = bp[j][high] - y[j]
228  // weight[j][0] = y[j] - bp[j][low]
229  // because in the interpolation the value on the "left" is weighted with the
230  // distance of y to the "right"
231  weights[j].resize(2);
232  weights[j][0] = _base_points[j][indices[j] + 1] - y[j];
233  weights[j][1] = y[j] - _base_points[j][indices[j]];
234  }
235 
236  // get flat index and stride
237  unsigned int flat_index = _data.flatIndex(indices);
239 
240  // this is the interpolation routine, evaluation can be expensive if dim is large
241 
242  // first we retrieve the data around the point y
243  // we use a 2^dim MultiIndex hypercube for generating the permulations
245  MultiIndex<Real> hypercube = MultiIndex<Real>(shape);
246  T interpolated_value = 0;
247  for (const auto & p : hypercube)
248  {
249  // this loop computes the flat index for the point in the
250  // hypercube and accumulates the total weight for this point
251  // the selection of the dimensional weight is based on the swapping
252  // done in the pre-computing loop before
253  unsigned int index = flat_index;
254  T w = 1;
255  for (unsigned int j = 0; j < p.first.size(); ++j)
256  {
257  index += stride[j] * p.first[j];
258  w *= weights[j][p.first[j]];
259  }
260 
261  // add the contribution of this base point to the interpolated value
262  interpolated_value += w * _data[index];
263  }
264 
265  return interpolated_value / volume;
266 }
void linearSearch(std::vector< T > &values, MultiIndex< Real >::size_type &indices) const
linearSearch finds the indices i_k of the base point such that base_point[d][i_k] <= values[d] < base...
std::vector< std::vector< Real > > _base_points
unsigned int dim() const
dimension of the container
Definition: MultiIndex.h:62
std::vector< bool > _degenerate_index
this variable keeps track on which dimension is degenerate and was removed
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int stride(unsigned int j) const
access the stride
Definition: MultiIndex.h:389
unsigned int _original_dim
original dimension is to allow checks on user inputs for cases where arrays are sliced ...
unsigned int flatIndex(const size_type &indices) const
compute the flat index for a size_type index
Definition: MultiIndex.h:477
bool _degenerate_interpolation
if all dimensions have size one then there is only one value to return this corner case should be sup...
Implements a container class for multi-indexed objects with an arbitrary number of indices...
Definition: MultiIndex.h:22

◆ setData()

template<typename T >
void MultiDimensionalInterpolationTempl< T >::setData ( const std::vector< std::vector< Real >> &  base_points,
const MultiIndex< Real > &  data 
)

sets data but also fixes degenerate dimensions in data

Definition at line 32 of file MultiDimensionalInterpolation.C.

34 {
36  _setup_complete = false;
37 
38  // stash away original dimension of data because we might modify it
39  _original_dim = data.dim();
40  _degenerate_index.resize(_original_dim, false);
41 
42  // need to check this here to make sure the next loop is safe
43  if (data.dim() != base_points.size())
44  {
45  std::ostringstream oss;
46  oss << "Leading dimension of base_points " << base_points.size() << " and data dimensionality "
47  << data.dim() << " are inconsistent.";
48  throw std::domain_error(oss.str());
49  }
50 
51  // first a corner case is addressed; if the size of the MultiIndex in one
52  // dimension is 1, then finding the interpolation "stencil" becomes much
53  // harder. It is easier to slice the data array and keep track of which values
54  // to discard in the interpolation routines
55  MultiIndex<Real>::size_type slice_dimensions;
56  MultiIndex<Real>::size_type slice_indices;
57  MultiIndex<Real>::size_type size = data.size();
58  std::vector<std::vector<Real>> modified_base_points;
59  for (unsigned int j = 0; j < data.dim(); ++j)
60  if (size[j] == 1)
61  {
62  slice_dimensions.push_back(j);
63  slice_indices.push_back(0);
64  _degenerate_index[j] = true;
65  }
66  else
67  modified_base_points.push_back(base_points[j]);
68 
69  // if all dimensions have size 1, then there is only one value to return
70  // this is a weird corner case that we should support to make life easier
71  // for whoever uses this object
72  // In this case, we can just use the passed base_points and data objects
73  // and short-cut the computation in the interpolation function
74  if (modified_base_points.size() == 0)
75  {
77  _base_points = base_points;
78  _data = data;
79  }
80  else
81  {
82  // set the data
83  _base_points = modified_base_points;
84  _data = data.slice(slice_dimensions, slice_indices);
85  }
86  errorCheck();
87 }
std::vector< std::vector< Real > > _base_points
unsigned int dim() const
dimension of the container
Definition: MultiIndex.h:62
std::vector< bool > _degenerate_index
this variable keeps track on which dimension is degenerate and was removed
const size_type & size() const
container size as dim dimensional vector
Definition: MultiIndex.h:59
unsigned int _original_dim
original dimension is to allow checks on user inputs for cases where arrays are sliced ...
bool _degenerate_interpolation
if all dimensions have size one then there is only one value to return this corner case should be sup...
MultiIndex< T > slice(unsigned int dimension, unsigned int index) const
accesses a slice of the multi index object
Definition: MultiIndex.h:281
void errorCheck()
checks consistency of the data
Implements a container class for multi-indexed objects with an arbitrary number of indices...
Definition: MultiIndex.h:22

Member Data Documentation

◆ _base_points

template<typename T >
std::vector<std::vector<Real> > MultiDimensionalInterpolationTempl< T >::_base_points
private

Definition at line 81 of file MultiDimensionalInterpolation.h.

◆ _data

template<typename T >
MultiIndex<Real> MultiDimensionalInterpolationTempl< T >::_data
private

Definition at line 82 of file MultiDimensionalInterpolation.h.

◆ _degenerate_index

template<typename T >
std::vector<bool> MultiDimensionalInterpolationTempl< T >::_degenerate_index
protected

this variable keeps track on which dimension is degenerate and was removed

Definition at line 71 of file MultiDimensionalInterpolation.h.

◆ _degenerate_interpolation

template<typename T >
bool MultiDimensionalInterpolationTempl< T >::_degenerate_interpolation = false
protected

if all dimensions have size one then there is only one value to return this corner case should be supported so the calling routine does not need to check for it

Definition at line 78 of file MultiDimensionalInterpolation.h.

◆ _original_dim

template<typename T >
unsigned int MultiDimensionalInterpolationTempl< T >::_original_dim
protected

original dimension is to allow checks on user inputs for cases where arrays are sliced

Definition at line 68 of file MultiDimensionalInterpolation.h.

Referenced by MultiDimensionalInterpolationTempl< T >::dim().

◆ _setup_complete

template<typename T >
bool MultiDimensionalInterpolationTempl< T >::_setup_complete = false
private

Definition at line 83 of file MultiDimensionalInterpolation.h.


The documentation for this class was generated from the following files: