29 #ifndef Rythmos_CUBIC_SPLINE_INTERPOLATOR_DEF_H
30 #define Rythmos_CUBIC_SPLINE_INTERPOLATOR_DEF_H
32 #include "Rythmos_CubicSplineInterpolator_decl.hpp"
33 #include "Rythmos_InterpolatorBaseHelpers.hpp"
34 #include "Thyra_VectorStdOps.hpp"
35 #include "Thyra_VectorSpaceBase.hpp"
36 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
40 template<
class Scalar>
41 Teuchos::RCP<Rythmos::CubicSplineInterpolator<Scalar> >
42 cubicSplineInterpolator()
44 RCP<CubicSplineInterpolator<Scalar> > csi = Teuchos::rcp(
new CubicSplineInterpolator<Scalar>() );
48 template<
class Scalar>
49 void computeCubicSplineCoeff(
50 const typename DataStore<Scalar>::DataStoreVector_t & data,
51 const Ptr<CubicSplineCoeff<Scalar> > & coeffPtr
54 using Teuchos::outArg;
55 typedef Teuchos::ScalarTraits<Scalar> ST;
56 using Thyra::createMember;
57 TEUCHOS_TEST_FOR_EXCEPTION(
58 (data.size() < 2), std::logic_error,
59 "Error! A minimum of two data points is required for this cubic spline."
63 Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > > x_vec, xdot_vec;
64 dataStoreVectorToVector<Scalar>( data, &t, &x_vec, &xdot_vec, NULL );
65 #ifdef HAVE_RYTHMOS_DEBUG
66 assertTimePointsAreSorted<Scalar>( t );
67 #endif // HAVE_RYTHMOS_DEBUG
70 CubicSplineCoeff<Scalar>& coeff = *coeffPtr;
75 coeff.a.clear(); coeff.b.clear(); coeff.c.clear(); coeff.d.clear();
77 coeff.a.reserve(1); coeff.b.reserve(1); coeff.c.reserve(1); coeff.d.reserve(1);
78 coeff.t.push_back(t[0]);
79 coeff.t.push_back(t[1]);
80 coeff.a.push_back(x_vec[0]->clone_v());
81 coeff.b.push_back(createMember(x_vec[0]->space()));
82 coeff.c.push_back(createMember(x_vec[0]->space()));
83 coeff.d.push_back(createMember(x_vec[0]->space()));
84 Scalar h = coeff.t[1] - coeff.t[0];
85 V_StVpStV(outArg(*coeff.b[0]),ST::one()/h,*x_vec[1],-ST::one()/h,*x_vec[0]);
86 V_S(outArg(*coeff.c[0]),ST::zero());
87 V_S(outArg(*coeff.d[0]),ST::zero());
92 coeff.t.clear(); coeff.t.reserve(n+1);
93 coeff.a.clear(); coeff.a.reserve(n+1);
94 coeff.b.clear(); coeff.b.reserve(n);
95 coeff.c.clear(); coeff.c.reserve(n+1);
96 coeff.d.clear(); coeff.d.reserve(n);
99 Array<RCP<Thyra::VectorBase<Scalar> > > alpha(n), z(n+1);
100 Array<Scalar> l(n+1), mu(n);
101 for (
int i=0 ; i<n ; ++i) {
102 coeff.t.push_back(t[i]);
103 coeff.a.push_back(x_vec[i]->clone_v());
104 coeff.b.push_back(Thyra::createMember(x_vec[0]->space()));
105 coeff.c.push_back(Thyra::createMember(x_vec[0]->space()));
106 coeff.d.push_back(Thyra::createMember(x_vec[0]->space()));
107 alpha[i] = Thyra::createMember(x_vec[0]->space());
108 z[i] = Thyra::createMember(x_vec[0]->space());
110 coeff.a.push_back(x_vec[n]->clone_v());
111 coeff.t.push_back(t[n]);
112 coeff.c.push_back(Thyra::createMember(x_vec[0]->space()));
113 z[n] = Thyra::createMember(x_vec[0]->space());
114 Scalar zero = ST::zero();
115 Scalar one = ST::one();
116 Scalar two = Scalar(2*ST::one());
117 Scalar three = Scalar(3*ST::one());
120 for (
int i=0 ; i<n ; ++i) {
121 h[i] = coeff.t[i+1]-coeff.t[i];
123 for (
int i=1 ; i<n ; ++i) {
124 V_StVpStV(outArg(*(alpha[i])),three/h[i],*coeff.a[i+1],-3/h[i],*coeff.a[i]);
125 Vp_StV(outArg(*(alpha[i])),-three/h[i-1],*coeff.a[i]);
126 Vp_StV(outArg(*(alpha[i])),+three/h[i-1],*coeff.a[i-1]);
130 V_S(outArg(*(z[0])),zero);
131 for (
int i=1 ; i<n ; ++i) {
132 l[i] = 2*(coeff.t[i+1]-coeff.t[i-1])-h[i-1]*mu[i-1];
134 V_StVpStV(outArg(*(z[i])),one/l[i],*alpha[i],-h[i-1]/l[i],*z[i-1]);
137 V_S(outArg(*(z[n])),zero);
138 V_S(outArg(*(coeff.c[n])),zero);
139 for (
int j=n-1 ; j >= 0 ; --j) {
140 V_StVpStV(outArg(*(coeff.c[j])),one,*z[j],-mu[j],*coeff.c[j+1]);
141 V_StVpStV(outArg(*(coeff.b[j])),one/h[j],*coeff.a[j+1],-one/h[j],*coeff.a[j]);
142 Vp_StV(outArg(*(coeff.b[j])),-h[j]/three,*coeff.c[j+1]);
143 Vp_StV(outArg(*(coeff.b[j])),-h[j]*two/three,*coeff.c[j]);
144 V_StVpStV(outArg(*(coeff.d[j])),one/(three*h[j]),*coeff.c[j+1],-one/(three*h[j]),*coeff.c[j]);
147 coeff.a.erase(coeff.a.end()-1);
148 coeff.c.erase(coeff.c.end()-1);
152 template<
class Scalar>
153 void validateCubicSplineCoeff(
const CubicSplineCoeff<Scalar>& coeff)
155 int t_n = coeff.t.size();
156 int a_n = coeff.a.size();
157 int b_n = coeff.b.size();
158 int c_n = coeff.c.size();
159 int d_n = coeff.d.size();
160 TEUCHOS_TEST_FOR_EXCEPTION(
161 ((a_n != t_n-1) || (a_n != b_n) || (a_n != c_n) || (a_n != d_n)),
163 "Error! The sizes of the data structures in the CubicSplineCoeff object do not match"
168 template<
class Scalar>
169 void evaluateCubicSpline(
170 const CubicSplineCoeff<Scalar>& coeff,
173 const Ptr<Thyra::VectorBase<Scalar> >& S,
174 const Ptr<Thyra::VectorBase<Scalar> >& Sp,
175 const Ptr<Thyra::VectorBase<Scalar> >& Spp
178 using Teuchos::outArg;
180 typedef Teuchos::ScalarTraits<Scalar> ST;
182 validateCubicSplineCoeff<Scalar>(coeff);
183 TEUCHOS_TEST_FOR_EXCEPTION( as<Teuchos::Ordinal>(j) >= coeff.a.size(),
184 std::out_of_range,
"Error!, j is out of range" );
186 Scalar dt = t-coeff.t[j];
187 const Thyra::VectorBase<Scalar>& a = *(coeff.a[j]);
188 const Thyra::VectorBase<Scalar>& b = *(coeff.b[j]);
189 const Thyra::VectorBase<Scalar>& c = *(coeff.c[j]);
190 const Thyra::VectorBase<Scalar>& d = *(coeff.d[j]);
192 if (!Teuchos::is_null(S)) {
195 V_StVpStV(outArg(*S),dt*dt*dt,d,dt*dt,c);
196 Vp_StV(outArg(*S),dt,b);
197 Vp_StV(outArg(*S),ST::one(),a);
199 if (!Teuchos::is_null(Sp)) {
202 V_StVpStV(outArg(*Sp),Scalar(3*ST::one())*dt*dt,d,Scalar(2*ST::one())*dt,c);
203 Vp_StV(outArg(*Sp),ST::one(),b);
205 if (!Teuchos::is_null(Spp)) {
208 V_StVpStV(outArg(*Spp),Scalar(6*ST::one())*dt,d,Scalar(2*ST::one()),c);
215 template<
class Scalar>
218 splineCoeffComputed_ =
false;
223 template<
class Scalar>
230 template<
class Scalar>
231 RCP<InterpolatorBase<Scalar> >
234 RCP<CubicSplineInterpolator<Scalar> >
236 if (!is_null(parameterList_))
237 interpolator->parameterList_ = parameterList(*parameterList_);
241 template<
class Scalar>
243 const RCP<
const typename DataStore<Scalar>::DataStoreVector_t> & nodesPtr
248 splineCoeffComputed_ =
false;
249 #ifdef HAVE_RYTHMOS_DEBUG
250 const typename DataStore<Scalar>::DataStoreVector_t & nodes = *nodesPtr;
252 nodes_copy_ = Teuchos::rcp(
new typename DataStore<Scalar>::DataStoreVector_t);
253 nodes_copy_->reserve(nodes.size());
254 for (
int i=0 ; i<Teuchos::as<int>(nodes.size()) ; ++i) {
255 nodes_copy_->push_back(*nodes[i].clone());
257 #endif // HAVE_RYTHMOS_DEBUG
260 template<
class Scalar>
262 const Array<Scalar> &t_values,
263 typename DataStore<Scalar>::DataStoreVector_t *data_out
267 using Teuchos::outArg;
268 typedef Teuchos::ScalarTraits<Scalar> ST;
270 TEUCHOS_TEST_FOR_EXCEPTION( nodesSet_ ==
false, std::logic_error,
271 "Error!, setNodes must be called before interpolate"
273 #ifdef HAVE_RYTHMOS_DEBUG
275 assertNodesUnChanged<Scalar>(*nodes_,*nodes_copy_);
277 assertBaseInterpolatePreconditions(*nodes_,t_values,data_out);
278 #endif // HAVE_RYTHMOS_DEBUG
281 const RCP<FancyOStream> out = this->getOStream();
282 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
283 Teuchos::OSTab ostab(out,1,
"CSI::interpolator");
284 if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
285 *out <<
"nodes_:" << std::endl;
286 for (Teuchos::Ordinal i=0 ; i<(*nodes_).size() ; ++i) {
287 *out <<
"nodes_[" << i <<
"] = " << std::endl;
288 (*nodes_)[i].describe(*out,Teuchos::VERB_EXTREME);
290 *out <<
"t_values = " << std::endl;
291 for (Teuchos::Ordinal i=0 ; i<t_values.size() ; ++i) {
292 *out <<
"t_values[" << i <<
"] = " << t_values[i] << std::endl;
299 if (t_values.size() == 0) {
303 if ((*nodes_).size() == 1) {
306 DataStore<Scalar> DS((*nodes_)[0]);
307 data_out->push_back(DS);
315 for (Teuchos::Ordinal i=0 ; i < (*nodes_).size()-1; ++i) {
316 const Scalar& ti = (*nodes_)[i].time;
317 const Scalar& tip1 = (*nodes_)[i+1].time;
321 while ( range_i.
isInRange(t_values[n]) ) {
323 if (compareTimeValues(t_values[n],ti)==0) {
324 DataStore<Scalar> DS((*nodes_)[i]);
325 data_out->push_back(DS);
327 else if (compareTimeValues(t_values[n],tip1)==0) {
328 DataStore<Scalar> DS((*nodes_)[i+1]);
329 data_out->push_back(DS);
331 if (!splineCoeffComputed_) {
332 computeCubicSplineCoeff<Scalar>(*nodes_,outArg(splineCoeff_));
333 splineCoeffComputed_ =
true;
335 DataStore<Scalar> DS;
336 RCP<Thyra::VectorBase<Scalar> > x = createMember((*nodes_)[i].x->space());
337 evaluateCubicSpline<Scalar>( splineCoeff_, i, t_values[n], outArg(*x) );
338 DS.time = t_values[n];
340 DS.accuracy = ST::zero();
341 data_out->push_back(DS);
345 if (n == as<int>(t_values.size())) {
356 template<
class Scalar>
363 template<
class Scalar>
366 std::string name =
"Rythmos::CubicSplineInterpolator";
371 template<
class Scalar>
374 const Teuchos::EVerbosityLevel verbLevel
378 if ( (as<int>(verbLevel) == as<int>(Teuchos::VERB_DEFAULT) ) ||
379 (as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) )
382 out << description() <<
"::describe" << std::endl;
384 else if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW))
386 else if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM))
388 else if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH))
393 template <
class Scalar>
395 RCP<ParameterList>
const& paramList
398 TEUCHOS_TEST_FOR_EXCEPT(is_null(paramList));
399 paramList->validateParametersAndSetDefaults(*this->getValidParameters());
400 parameterList_ = paramList;
401 Teuchos::readVerboseObjectSublist(&*parameterList_,
this);
405 template <
class Scalar>
409 return(parameterList_);
413 template <
class Scalar>
417 RCP<ParameterList> temp_param_list;
418 std::swap( temp_param_list, parameterList_ );
419 return(temp_param_list);
422 template<
class Scalar>
423 RCP<const Teuchos::ParameterList>
426 static RCP<Teuchos::ParameterList> validPL;
427 if (is_null(validPL)) {
428 RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
429 Teuchos::setupVerboseObjectSublist(&*pl);
443 #define RYTHMOS_CUBIC_SPLINE_INTERPOLATOR_INSTANT(SCALAR) \
445 template class CubicSplineInterpolator< SCALAR >; \
447 template class CubicSplineCoeff< SCALAR >; \
448 template RCP<CubicSplineInterpolator< SCALAR > > cubicSplineInterpolator(); \
449 template void computeCubicSplineCoeff( \
450 const DataStore< SCALAR >::DataStoreVector_t & data, \
451 const Ptr<CubicSplineCoeff< SCALAR > > & coeffPtr \
453 template void validateCubicSplineCoeff(const CubicSplineCoeff< SCALAR >& coeff); \
454 template void evaluateCubicSpline( \
455 const CubicSplineCoeff< SCALAR >& coeff, \
456 Teuchos::Ordinal j, \
458 const Ptr<Thyra::VectorBase< SCALAR > >& S, \
459 const Ptr<Thyra::VectorBase< SCALAR > >& Sp, \
460 const Ptr<Thyra::VectorBase< SCALAR > >& Spp \
468 #endif // Rythmos_CUBIC_SPLINE_INTERPOLATOR_DEF_H
CubicSplineInterpolator()
virtual bool isInRange(const TimeType &t) const
void setNodes(const RCP< const typename DataStore< Scalar >::DataStoreVector_t > &nodes)
RCP< const Teuchos::ParameterList > getValidParameters() const
RCP< ParameterList > unsetParameterList()
RCP< InterpolatorBase< Scalar > > cloneInterpolator() const
Concrete implemenation of InterpolatorBase that implements cubic spline interpolation.
std::string description() const
void describe(FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
void setParameterList(RCP< ParameterList > const ¶mList)
void interpolate(const Array< Scalar > &t_values, typename DataStore< Scalar >::DataStoreVector_t *data_out) const
RCP< ParameterList > getNonconstParameterList()
bool supportsCloning() const