Minsky
civita::InterpolateHC Class Reference

Interpolates its argument to its hypercube rank must equal arg->rank(), and xvectors type must match. More...

#include <interpolateHypercube.h>

Inheritance diagram for civita::InterpolateHC:
Inheritance graph
Collaboration diagram for civita::InterpolateHC:
Collaboration graph

Classes

struct  WeightedIndex
 structure for referring to an argument index and its weight More...
 
struct  WeightedIndexVector
 

Public Member Functions

void setArgument (const TensorPtr &a, const ITensor::Args &args={"", 0}) override
 
double operator[] (std::size_t) const override
 return or compute data at a location More...
 
Timestamp timestamp () const override
 timestamp indicating how old the dependendent data might be. Used in CachedTensorOp to determine when to invalidate the cache More...
 
- Public Member Functions inherited from civita::ITensor
 CLASSDESC_ACCESS (ITensor)
 
 ITensor ()
 
 ITensor (const Hypercube &hc)
 
 ITensor (Hypercube &&hc)
 
 ITensor (const std::vector< unsigned > &dims)
 
 ITensor (const ITensor &)=default
 
 ITensor (ITensor &&)=default
 
ITensoroperator= (const ITensor &)=default
 
ITensoroperator= (ITensor &&)=default
 
virtual ~ITensor ()
 
virtual const Hypercube & hypercube () const
 information describing the axes, types and labels of this tensor More...
 
virtual const Hypercube & hypercube (const Hypercube &hc)
 
virtual const Hypercube & hypercube (Hypercube &&hc)
 
std::size_t rank () const
 
std::vector< unsigned > shape () const
 
void imposeDimensions (const Dimensions &dimensions)
 impose dimensions according to dimension map dimensions More...
 
virtual const Index & index () const
 the index vector - assumed to be ordered and unique More...
 
virtual std::size_t size () const
 return number of elements in tensor - maybe less than hypercube.numElements if sparse More...
 
double atHCIndex (std::size_t hcIdx) const
 returns the data value at hypercube index hcIdx, or NaN if More...
 
template<class T >
std::size_t hcIndex (const std::initializer_list< T > &indices) const
 
template<class T >
double operator() (const std::initializer_list< T > &indices) const
 
virtual void setArguments (const TensorPtr &, const TensorPtr &, const ITensor::Args &args={})
 
virtual void setArguments (const std::vector< TensorPtr > &a, const ITensor::Args &args={"", 0})
 
virtual void setArguments (const std::vector< TensorPtr > &a1, const std::vector< TensorPtr > &a2, const ITensor::Args &args={"", 0})
 

Private Member Functions

void sortAndAdd (const XVector &)
 
vector< std::size_t > splitAndRotate (std::size_t) const
 
WeightedIndexVector bodyCentredNeighbourhood (std::size_t idx) const
 computes the neighbourhood around a target argument index when the target index is not on the hypercube More...
 

Private Attributes

TensorPtr arg
 
Hypercube interimHC
 hypercube that's been rotated to match the arguments hypercube More...
 
std::vector< std::size_t > strides
 strides along each dimension of this->hypercube() More...
 
std::vector< std::size_t > rotation
 permutation of axes of interimHC and this->hypercube() More...
 
std::vector< std::pair< XVector, std::vector< std::size_t > > > sortedArgHC
 
vector< WeightedIndexVectorweightedIndices
 map from this tensor's index into the argument tensor More...
 

Additional Inherited Members

- Public Types inherited from civita::ITensor
using Timestamp = std::chrono::time_point< std::chrono::high_resolution_clock >
 
- Protected Member Functions inherited from civita::ITensor
void notImpl () const
 
- Protected Attributes inherited from civita::ITensor
Hypercube m_hypercube
 
Index m_index
 

Detailed Description

Interpolates its argument to its hypercube rank must equal arg->rank(), and xvectors type must match.

Definition at line 29 of file interpolateHypercube.h.

Member Function Documentation

◆ bodyCentredNeighbourhood()

InterpolateHC::WeightedIndexVector civita::InterpolateHC::bodyCentredNeighbourhood ( std::size_t  idx) const
private

computes the neighbourhood around a target argument index when the target index is not on the hypercube

Definition at line 140 of file interpolateHypercube.cc.

References arg, civita::ITensor::index(), interimHC, civita::ITensor::rank(), anonymous_namespace{interpolateHypercube.cc}::sorted(), sortedArgHC, splitAndRotate(), and minsky::to_string().

Referenced by setArgument().

141  {
142  // note this agorithm is limited in rank (typically 32 dims on 32bit machine, or 64 dims on 64bit)
143  if (rank()>sizeof(size_t)*8)
144  throw runtime_error("Ranks > "+to_string(sizeof(size_t)*8)+" not supported");
145  size_t numNeighbours=size_t(1)<<rank();
146  vector<size_t> iIdx=splitAndRotate(destIdx);
147  const auto& argHC=arg->hypercube();
148  // loop over the nearest neighbours in argument hypercube space of
149  // this point in interimHypercube space
150  double sumWeight=0;
151  WeightedIndexVector r;
152  auto argIndexVector=arg->index();
153  // multivariate interpolation - eg see Abramowitz & Stegun 25.2.66
154  for (size_t nbr=0; nbr<numNeighbours; ++nbr)
155  {
156  size_t argIdx=0;
157  double weight=1;
158  size_t idx=0;
159  for (size_t dim=0, stride=1; dim<rank(); stride*=argHC.xvectors[dim].size(), ++dim)
160  {
161  const auto& x=sortedArgHC[dim].first;
162  assert(!x.empty());
163  assert(sorted(x.begin(),x.end()));
164  auto v=interimHC.xvectors[dim][iIdx[dim]];
165  auto lesserIt=std::upper_bound(x.begin(), x.end(), v, AnyLess());
166  if (lesserIt!=x.begin()) --lesserIt; // find greatest value <= v,
167  boost::any lesser=*lesserIt, greater;
168  if (diff(lesser, v)>=0)
169  greater=lesser; // one sided interpolation for beginning or exact match
170  else if (lesserIt+1==x.end())
171  greater=x.back(); // one sided interpolation for end
172  else
173  greater=*(lesserIt+1);
174 
175  bool greaterSide = nbr&(size_t(1)<<dim); // on higher side of hypercube
176  double d=diff(greater,lesser);
177  if (d==0 && greaterSide) goto nextNeighbour; // already taken lesserVal at weight 1.
178 
179  idx += sortedArgHC[dim].second[(lesserIt-x.begin()+greaterSide)]*stride;
180  assert(idx<argHC.numElements());
181  if (d>0)
182  weight *= greaterSide? diff(v,lesser): d-diff(v,lesser);
183  }
184  if (index().empty())
185  {
186  r.emplace_back(WeightedIndex{idx,weight});
187  sumWeight+=weight;
188  }
189  else
190  {
191  auto indexV=index();
192  if (binary_search(indexV.begin(), indexV.end(), idx))
193  {
194  r.emplace_back(WeightedIndex{idx,weight});
195  sumWeight+=weight;
196  }
197  }
198  nextNeighbour:;
199  }
200 
201  // normalise weights
202  for (auto& i: r) i.weight/=sumWeight;
203  return r;
204  }
std::size_t rank() const
virtual const Index & index() const
the index vector - assumed to be ordered and unique
std::vector< std::pair< XVector, std::vector< std::size_t > > > sortedArgHC
vector< std::size_t > splitAndRotate(std::size_t) const
string to_string(CONST84 char *x)
Definition: minskyTCLObj.h:33
Hypercube interimHC
hypercube that&#39;s been rotated to match the arguments hypercube
bool sorted(civita::XVector::const_iterator begin, civita::XVector::const_iterator end)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator[]()

double civita::InterpolateHC::operator[] ( std::size_t  ) const
overridevirtual

return or compute data at a location

Implements civita::ITensor.

Definition at line 124 of file interpolateHypercube.cc.

References arg, and weightedIndices.

125  {
126  if (idx<weightedIndices.size())
127  {
128  if (weightedIndices[idx].empty()) return nan("");
129  double r=0;
130  for (const auto& i: weightedIndices[idx])
131  {
132  assert(i.index<arg->hypercube().numElements());
133  r+=i.weight * arg->atHCIndex(i.index);
134  }
135  return r;
136  }
137  return nan("");
138  }
vector< WeightedIndexVector > weightedIndices
map from this tensor&#39;s index into the argument tensor

◆ setArgument()

void civita::InterpolateHC::setArgument ( const TensorPtr a,
const ITensor::Args args = {"",0} 
)
overridevirtual

Reimplemented from civita::ITensor.

Definition at line 49 of file interpolateHypercube.cc.

References arg, bodyCentredNeighbourhood(), civita::ITensor::hypercube(), civita::ITensor::index(), interimHC, civita::ITensor::rank(), rotation, civita::ITensor::size(), sortAndAdd(), strides, and weightedIndices.

50  {
51  arg=a;
52  if (rank()!=arg->rank())
53  throw runtime_error("Rank of interpolated tensor doesn't match its argument");
54  // reorder hypercube for type and name
55  interimHC.xvectors.clear();
56  size_t stride=1;
57  const auto& targetHC=hypercube().xvectors;
58  rotation.clear();
59  rotation.resize(rank(), rank());
60  // ensure rotation vector will contain unique indices
61  std::map<size_t,size_t> tmpRotation;
62  // construct interim hypercube and its rotation permutation
63  for (size_t i=0; i<rank(); ++i)
64  {
65  const auto& src=arg->hypercube().xvectors[i];
66  sortAndAdd(src);
67  if (src.name.empty())
68  {
69  const auto& dst=targetHC[i];
70  if (!dst.name.empty() || src.dimension.type!=dst.dimension.type ||
71  src.dimension.units!=dst.dimension.units) //TODO handle conversion between different units
72  throw runtime_error("mismatch between unnamed dimensions");
73  interimHC.xvectors.push_back(dst);
74  tmpRotation.emplace(make_pair(i,i));
75  }
76  else // find matching names dimension
77  {
78  auto dst=find_if(targetHC.begin(), targetHC.end(),
79  [&](const XVector& i){return i.name==src.name;});
80  if (dst==targetHC.end())
81  {
82  // possible alternative when targetHC has no xvectors or undefined ones. for feature 147
83  interimHC.xvectors.push_back(src);
84  tmpRotation.emplace(make_pair(i,i));
85  }
86  else
87  {
88  interimHC.xvectors.push_back(*dst);
89  tmpRotation.emplace(make_pair(dst-targetHC.begin(),i));
90  }
91  }
92  strides.push_back(stride);
93  stride*=targetHC[i].size();
94  }
95  if (tmpRotation.size()!=rank()) throw runtime_error("rotation of indices is not a permutation");
96  for (auto& i: tmpRotation) rotation[i.first]=i.second;
97 #ifndef NDEBUG
98  for (auto& i: rotation) assert(i<rank()); // check that no indices have been doubly assigned.
99  // Now we're sure rotation is a permutation
100 #endif
101  if (index().empty())
102  for (size_t i=0; i<size(); ++i)
104  else
105  for (auto i: index())
107  }
std::vector< std::size_t > rotation
permutation of axes of interimHC and this->hypercube()
virtual const Hypercube & hypercube() const
information describing the axes, types and labels of this tensor
std::vector< std::size_t > strides
strides along each dimension of this->hypercube()
std::size_t rank() const
virtual const Index & index() const
the index vector - assumed to be ordered and unique
virtual std::size_t size() const
return number of elements in tensor - maybe less than hypercube.numElements if sparse ...
vector< WeightedIndexVector > weightedIndices
map from this tensor&#39;s index into the argument tensor
WeightedIndexVector bodyCentredNeighbourhood(std::size_t idx) const
computes the neighbourhood around a target argument index when the target index is not on the hypercu...
Hypercube interimHC
hypercube that&#39;s been rotated to match the arguments hypercube
void sortAndAdd(const XVector &)
Here is the call graph for this function:

◆ sortAndAdd()

void civita::InterpolateHC::sortAndAdd ( const XVector &  xv)
private

Definition at line 109 of file interpolateHypercube.cc.

References anonymous_namespace{interpolateHypercube.cc}::sorted(), and sortedArgHC.

Referenced by setArgument().

110  {
111  sortedArgHC.emplace_back();
112  auto& s=sortedArgHC.back();
113  for (size_t i=0; i<xv.size(); ++i)
114  s.second.push_back(i);
115  AnyLess less;
116  sort(s.second.begin(), s.second.end(),
117  [&](size_t i, size_t j){return less(xv[i],xv[j]);});
118  for (auto i: s.second)
119  s.first.push_back(xv[i]);
120  assert(sorted(s.first.begin(), s.first.end()));
121  }
std::vector< std::pair< XVector, std::vector< std::size_t > > > sortedArgHC
bool sorted(civita::XVector::const_iterator begin, civita::XVector::const_iterator end)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ splitAndRotate()

vector< size_t > civita::InterpolateHC::splitAndRotate ( std::size_t  ) const
private

Definition at line 39 of file interpolateHypercube.cc.

References civita::ITensor::hcIndex(), civita::ITensor::hypercube(), civita::ITensor::rank(), rotation, and strides.

Referenced by bodyCentredNeighbourhood().

40  {
41  vector<size_t> r(rank());
42  const auto& h=hypercube();
43  for (size_t dim=0; dim<rank(); ++dim)
44  r[rotation[dim]] = (hcIndex/strides[dim]) % h.xvectors[dim].size();
45  return r;
46  }
std::vector< std::size_t > rotation
permutation of axes of interimHC and this->hypercube()
virtual const Hypercube & hypercube() const
information describing the axes, types and labels of this tensor
std::vector< std::size_t > strides
strides along each dimension of this->hypercube()
std::size_t rank() const
std::size_t hcIndex(const std::initializer_list< T > &indices) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ timestamp()

Timestamp civita::InterpolateHC::timestamp ( ) const
inlineoverridevirtual

timestamp indicating how old the dependendent data might be. Used in CachedTensorOp to determine when to invalidate the cache

Implements civita::ITensor.

Definition at line 66 of file interpolateHypercube.h.

66 {return arg? arg->timestamp(): Timestamp();}
std::chrono::time_point< std::chrono::high_resolution_clock > Timestamp

Member Data Documentation

◆ arg

TensorPtr civita::InterpolateHC::arg
private

Definition at line 31 of file interpolateHypercube.h.

Referenced by bodyCentredNeighbourhood(), operator[](), and setArgument().

◆ interimHC

Hypercube civita::InterpolateHC::interimHC
private

hypercube that's been rotated to match the arguments hypercube

Definition at line 33 of file interpolateHypercube.h.

Referenced by bodyCentredNeighbourhood(), and setArgument().

◆ rotation

std::vector<std::size_t> civita::InterpolateHC::rotation
private

permutation of axes of interimHC and this->hypercube()

Definition at line 35 of file interpolateHypercube.h.

Referenced by setArgument(), and splitAndRotate().

◆ sortedArgHC

std::vector<std::pair<XVector, std::vector<std::size_t> > > civita::InterpolateHC::sortedArgHC
private

Definition at line 37 of file interpolateHypercube.h.

Referenced by bodyCentredNeighbourhood(), and sortAndAdd().

◆ strides

std::vector<std::size_t> civita::InterpolateHC::strides
private

strides along each dimension of this->hypercube()

Definition at line 34 of file interpolateHypercube.h.

Referenced by setArgument(), and splitAndRotate().

◆ weightedIndices

vector<WeightedIndexVector> civita::InterpolateHC::weightedIndices
private

map from this tensor's index into the argument tensor

Definition at line 57 of file interpolateHypercube.h.

Referenced by operator[](), and setArgument().


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