https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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.
 
 MultiDimensionalInterpolationTempl ()
 
virtual ~MultiDimensionalInterpolationTempl ()=default
 
unsigned int dim () const
 returns the dimensionality of this interpolation object
 
void setData (const std::vector< std::vector< Real > > &base_points, const MultiIndex< Real > &data)
 sets data but also fixes degenerate dimensions in data
 
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
 
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.
 

Protected Member Functions

void errorCheck ()
 checks consistency of the data
 
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
 

Protected Attributes

unsigned int _original_dim
 original dimension is to allow checks on user inputs for cases where arrays are sliced
 
std::vector< bool > _degenerate_index
 this variable keeps track on which dimension is degenerate and was removed
 
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
 

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
Implements a container class for multi-indexed objects with an arbitrary number of indices.
Definition MultiIndex.h:23

◆ MultiDimensionalInterpolationTempl() [2/2]

Definition at line 25 of file MultiDimensionalInterpolation.C.

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

◆ ~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< unsigned int > size_type
Definition MultiIndex.h:31
const size_type & size() const
container size as dim dimensional vector
Definition MultiIndex.h:59
unsigned int dim() const
dimension of the container
Definition MultiIndex.h:62

◆ 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}
std::array< Real, 2 > values
Definition MortarUtils.C:52
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...
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}
bool _degenerate_interpolation
if all dimensions have size one then there is only one value to return this corner case should be sup...
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< bool > _degenerate_index
this variable keeps track on which dimension is degenerate and was removed
unsigned int stride(unsigned int j) const
access the stride
Definition MultiIndex.h:389
unsigned int flatIndex(const size_type &indices) const
compute the flat index for a size_type index
Definition MultiIndex.h:477
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ 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;
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}
void errorCheck()
checks consistency of the data
MultiIndex< T > slice(unsigned int dimension, unsigned int index) const
accesses a slice of the multi index object
Definition MultiIndex.h:281

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: