17 #include "PCHIPInterpolator.h"
22 #include "linalg/Vector.h"
26 #if __cplusplus >= 201103L
29 #include <boost/shared_ptr.hpp>
35 void PCHIPInterpolator::interpolate(std::vector<Vector>& snapshot_ts,
36 std::vector<std::shared_ptr<Vector>>& snapshots,
37 std::vector<Vector>& output_ts,
38 std::vector<std::shared_ptr<Vector>>& output_snapshots)
40 CAROM_VERIFY(snapshot_ts.size() == snapshots.size());
41 CAROM_VERIFY(snapshot_ts.size() > 2);
42 CAROM_VERIFY(output_ts.size() > 1);
43 CAROM_VERIFY(output_snapshots.size() == 0);
44 CAROM_VERIFY(snapshot_ts[0](0) - FLT_EPSILON <= output_ts[0](0) &&
45 output_ts[output_ts.size()-1](0) <=
46 snapshot_ts[snapshot_ts.size()-1](0) + FLT_EPSILON);
47 for(
int i = 1; i < snapshot_ts.size(); ++i)
49 CAROM_VERIFY(snapshots[i-1]->dim() == snapshots[i]->dim());
50 CAROM_VERIFY(snapshot_ts[i-1](0) < snapshot_ts[i](0));
51 CAROM_VERIFY(output_ts[i-1](0) < output_ts[i](0));
54 int n_out = output_ts.size();
55 int n_snap = snapshots.size();
56 int n_dim = snapshots[0]->dim();
58 for(
int i = 0; i < n_out; ++i)
61 snapshots[0]->distributed());
62 output_snapshots.push_back(std::shared_ptr<Vector>(temp_snapshot));
65 for(
int i = 0; i < n_dim; ++i)
67 double h_temp,delta_temp, t;
68 std::vector<double> h,d,delta,t_in,y_in;
69 for(
int j = 0; j < n_snap-1; ++j)
71 h_temp = snapshot_ts[j+1](0) - snapshot_ts[j](0);
73 delta_temp = (snapshots[j+1]->getData()[i] - snapshots[j]->getData()[i])/h_temp;
74 delta.push_back(delta_temp);
75 t_in.push_back(snapshot_ts[j](0));
76 y_in.push_back(snapshots[j]->getData()[i]);
78 t_in.push_back(snapshot_ts[n_snap-1](0));
79 y_in.push_back(snapshots[n_snap-1]->getData()[i]);
81 double d_temp = ((2*h[0] + h[1])*delta[0] - h[0]*delta[1])/(h[0]+h[1]);
82 if(sign(d_temp)!=sign(delta[0]))
86 else if (sign(delta[0]) != sign(delta[1]) && abs(d_temp) > abs(3*delta[0]))
92 for(
int j = 0; j < n_snap-2; ++j)
94 d_temp = computeDerivative(delta[j],delta[j+1],h[j],h[j+1]);
96 while(output_ts[counter](0) <= t_in[j+1])
98 t = output_ts[counter](0);
99 output_snapshots[counter]->getData()[i] = y_in[j]*computeH1(t,t_in[j],
101 y_in[j+1]*computeH2(t,t_in[j],t_in[j+1]) +
102 d[j]*computeH3(t,t_in[j],t_in[j+1]) +
103 d[j+1]*computeH4(t,t_in[j],t_in[j+1]);
108 d_temp = ((2*h[n_snap-2]+h[n_snap-3])*delta[n_snap-2] - h[n_snap-2]*delta[n_snap
109 -3])/(h[n_snap-2]+h[n_snap-3]);
110 if(sign(d_temp) != sign(delta[n_snap-2]))
114 else if (sign(delta[n_snap-2]) != sign(delta[n_snap-3])
115 && abs(d_temp) > abs(3*delta[n_snap-2]))
117 d_temp = 3*delta[n_snap-2];
121 while(counter < n_out
122 && output_ts[counter](0) <= t_in[n_snap-1] + FLT_EPSILON )
124 t = output_ts[counter](0);
125 output_snapshots[counter]->getData()[i] = y_in[n_snap-2]*computeH1(t,
126 t_in[n_snap-2],t_in[n_snap-1]) +
127 y_in[n_snap-1]*computeH2(t,t_in[n_snap-2],t_in[n_snap-1]) +
128 d[n_snap-2]*computeH3(t,t_in[n_snap-2],t_in[n_snap-1]) +
129 d[n_snap-1]*computeH4(t,t_in[n_snap-2],t_in[n_snap-1]);
132 CAROM_VERIFY(counter == n_out);
136 void PCHIPInterpolator::interpolate(std::vector<Vector>& snapshot_ts,
137 std::vector<std::shared_ptr<Vector>>& snapshots,
139 std::vector<Vector>& output_ts,
140 std::vector<std::shared_ptr<Vector>>& output_snapshots)
142 CAROM_VERIFY(snapshot_ts.size() == snapshots.size());
143 CAROM_VERIFY(snapshot_ts.size() > 0);
144 CAROM_VERIFY(n_out > 2);
145 CAROM_VERIFY(output_ts.size() == 0 && output_snapshots.size() == 0);
147 int n_snap = snapshots.size();
148 int n_dim = snapshots[0]->dim();
150 double t_min = snapshot_ts[0](0);
151 double t_max = snapshot_ts[n_snap-1](0);
152 double dt = (t_max-t_min)/(n_out-1);
155 for(
int i = 0; i < n_out; ++i)
158 temp_t(0) = t_min + i*dt;
159 output_ts.push_back(temp_t);
161 interpolate(snapshot_ts,snapshots,output_ts, output_snapshots);
164 double PCHIPInterpolator::computeDerivative(
double S1,
double S2,
169 double alpha = (h1 + 2*h2)/(3*(h1+h2));
172 d = S1*S2/(alpha*S2 + (1-alpha)*S1);
177 double PCHIPInterpolator::computeH1(
double x,
double xl,
double xr)
const
179 const double h = xr - xl;
180 return computePhi((xr-x)/h);
183 double PCHIPInterpolator::computeH2(
double x,
double xl,
double xr)
const
185 const double h = xr - xl;
186 return computePhi((x-xl)/h);
189 double PCHIPInterpolator::computeH3(
double x,
double xl,
double xr)
const
191 const double h = xr-xl;
192 return -h*computePsi((xr-x)/h);
195 double PCHIPInterpolator::computeH4(
double x,
double xl,
double xr)
const
197 const double h = xr-xl;
198 return h*computePsi((x-xl)/h);
201 double PCHIPInterpolator::computePhi(
double t)
const
203 return 3.*pow(t,2.) - 2*pow(t,3.);
206 double PCHIPInterpolator::computePsi(
double t)
const
208 return pow(t,3.) - pow(t,2.);
211 int PCHIPInterpolator::sign(
double a)
const
213 constexpr
double TOL = 1e-15;
214 if(abs(a) < TOL)
return 0;
215 else if(a > 0)
return 1;
216 else if (a < 0)
return -1;