203 friend LUSelector<dbl>;
204 friend LUSelector<mpfr_complex>;
244 case Predictor::Constant:
247 Mat<double>& arefd = std::get< Mat<double> >(a_);
248 Vec<double>& brefd = std::get< Vec<double> >(b_);
249 Vec<double>& crefd = std::get< Vec<double> >(c_);
250 crefd.resize(s_); crefd(0) = 0;
251 arefd.resize(s_,s_); arefd(0,0) = 0;
252 brefd.resize(s_); brefd(0) = 0;
253 Mat<mpfr_float>& arefmp = std::get< Mat<mpfr_float> >(a_);
254 Vec<mpfr_float>& brefmp = std::get< Vec<mpfr_float> >(b_);
255 Vec<mpfr_float>& crefmp = std::get< Vec<mpfr_float> >(c_);
256 crefmp.resize(s_); crefmp(0) = 0;
257 arefmp.resize(s_,s_); arefmp(0,0) = 0;
258 brefmp.resize(s_); brefmp(0) = 0;
259 uses_embedded_ =
false;
263 case Predictor::Euler:
266 Mat<double>& arefd = std::get< Mat<double> >(a_);
267 Vec<double>& brefd = std::get< Vec<double> >(b_);
268 Vec<double>& crefd = std::get< Vec<double> >(c_);
269 crefd.resize(s_); crefd(0) =
static_cast<double>(cEuler_(0));
270 arefd.resize(s_,s_); arefd(0,0) =
static_cast<double>(aEuler_(0,0));
271 brefd.resize(s_); brefd(0) =
static_cast<double>(bEuler_(0));
272 Mat<mpfr_float>& arefmp = std::get< Mat<mpfr_float> >(a_);
273 Vec<mpfr_float>& brefmp = std::get< Vec<mpfr_float> >(b_);
274 Vec<mpfr_float>& crefmp = std::get< Vec<mpfr_float> >(c_);
275 crefmp.resize(s_); crefmp(0) =
static_cast<mpfr_float
>(cEuler_(0));
276 arefmp.resize(s_,s_); arefmp(0,0) =
static_cast<mpfr_float
>(aEuler_(0,0));
277 brefmp.resize(s_); brefmp(0) =
static_cast<mpfr_float
>(bEuler_(0));
278 uses_embedded_ =
false;
281 case Predictor::HeunEuler:
285 FillButcherTable<double>(s_, aHeunEuler_, bHeunEuler_, b_minus_bstarHeunEuler_, cHeunEuler_);
286 FillButcherTable<mpfr_float>(s_, aHeunEuler_, bHeunEuler_, b_minus_bstarHeunEuler_, cHeunEuler_);
294 FillButcherTable<double>(s_, aRK4_, bRK4_, cRK4_);
295 FillButcherTable<mpfr_float>(s_, aRK4_, bRK4_, cRK4_);
300 case Predictor::RKF45:
304 FillButcherTable<double>(s_, aRKF45_, bRKF45_, b_minus_bstarRKF45_, cRKF45_);
305 FillButcherTable<mpfr_float>(s_, aRKF45_, bRKF45_, b_minus_bstarRKF45_, cRKF45_);
310 case Predictor::RKCashKarp45:
314 FillButcherTable<double>(s_, aRKCK45_, bRKCK45_, b_minus_bstarRKCK45_, cRKCK45_);
315 FillButcherTable<mpfr_float>(s_, aRKCK45_, bRKCK45_, b_minus_bstarRKCK45_, cRKCK45_);
320 case Predictor::RKDormandPrince56:
324 FillButcherTable<double>(s_, aRKDP56_, bRKDP56_, b_minus_bstarRKDP56_, cRKDP56_);
325 FillButcherTable<mpfr_float>(s_, aRKDP56_, bRKDP56_, b_minus_bstarRKDP56_, cRKDP56_);
330 case Predictor::RKVerner67:
334 FillButcherTable<double>(s_, aRKV67_, bRKV67_, b_minus_bstarRKV67_, cRKV67_);
335 FillButcherTable<mpfr_float>(s_, aRKV67_, bRKV67_, b_minus_bstarRKV67_, cRKV67_);
342 throw std::runtime_error(
"incompatible predictor choice in ExplicitPredict");
362 std::get< Mat<dbl> >(dh_dx_0_).resize(numTotalFunctions_, numVariables_);
363 std::get< Mat<mpfr_complex> >(dh_dx_0_).resize(numTotalFunctions_, numVariables_);
364 std::get< Mat<dbl> >(dh_dx_temp_).resize(numTotalFunctions_, numVariables_);
365 std::get< Mat<mpfr_complex> >(dh_dx_temp_).resize(numTotalFunctions_, numVariables_);
366 std::get< Vec<dbl> >(dh_dt_temp_).resize(numTotalFunctions_);
367 std::get< Vec<mpfr_complex> >(dh_dt_temp_).resize(numTotalFunctions_);
375 std::get< Mat<dbl> >(K_).resize(numTotalFunctions_, s_);
376 std::get< Mat<mpfr_complex> >(K_).resize(numTotalFunctions_, s_);
385 return current_precision_;
396 Precision(std::get< Mat<mpfr_complex> >(K_),new_precision);
398 Precision(std::get< Vec<mpfr_complex> >(dh_dt_temp_),new_precision);
399 Precision(std::get< Mat<mpfr_complex> >(dh_dx_0_),new_precision);
400 Precision(std::get< Mat<mpfr_complex> >(dh_dx_temp_),new_precision);
402 Precision(std::get< Mat<mpfr_float> >(a_),new_precision);
403 Precision(std::get< Vec<mpfr_float> >(b_),new_precision);
404 Precision(std::get< Vec<mpfr_float> >(b_minus_bstar_),new_precision);
405 Precision(std::get< Vec<mpfr_float> >(c_),new_precision);
409 current_precision_ = new_precision;
411 PrecisionSanityCheck();
414 void PrecisionSanityCheck()
const
416 assert(current_precision_==DefaultPrecision());
418 Vec<mpfr_complex>& dhdttemp = std::get< Vec<mpfr_complex> >(dh_dt_temp_);
419 Mat<mpfr_complex>& dhdx0 = std::get< Mat<mpfr_complex> >(dh_dx_0_);
420 Mat<mpfr_complex>& dhdxtemp = std::get< Mat<mpfr_complex> >(dh_dx_temp_);
422 Mat<mpfr_float>& a = std::get< Mat<mpfr_float> >(a_);
423 Vec<mpfr_float>& b = std::get< Vec<mpfr_float> >(b_);
424 Vec<mpfr_float>& bstar = std::get< Vec<mpfr_float> >(b_minus_bstar_);
425 Vec<mpfr_float>& c = std::get< Vec<mpfr_float> >(c_);
429 assert(
Precision(dhdttemp)==current_precision_);
430 assert(
Precision(dhdx0)==current_precision_);
431 assert(
Precision(dhdxtemp)==current_precision_);
433 assert(
Precision(a)==current_precision_);
434 assert(
Precision(b)==current_precision_);
436 assert(
Precision(bstar)==current_precision_);
437 assert(
Precision(c)==current_precision_);
459 template<
typename ComplexType>
460 SuccessCode
Predict(Vec<ComplexType> & next_space,
462 const Vec<ComplexType>& current_space, ComplexType current_time,
463 ComplexType
const& delta_t,
464 NumErrorT & condition_number_estimate,
465 unsigned & num_steps_since_last_condition_number_computation,
466 unsigned frequency_of_CN_estimation,
467 NumErrorT
const& tracking_tolerance)
470 auto step_success =
FullStep(next_space, S, current_space, current_time, delta_t);
472 NumErrorT norm_J, norm_J_inverse;
473 SetNormsCond<ComplexType>(norm_J, norm_J_inverse, condition_number_estimate, num_steps_since_last_condition_number_computation, frequency_of_CN_estimation);
502 template<
typename ComplexType>
503 SuccessCode
Predict(Vec<ComplexType> & next_space,
504 NumErrorT & size_proportion,
506 NumErrorT & norm_J_inverse,
508 const Vec<ComplexType>& current_space, ComplexType current_time,
509 ComplexType
const& delta_t,
510 NumErrorT & condition_number_estimate,
511 unsigned & num_steps_since_last_condition_number_computation,
512 unsigned frequency_of_CN_estimation,
513 NumErrorT
const& tracking_tolerance,
519 condition_number_estimate, num_steps_since_last_condition_number_computation,
520 frequency_of_CN_estimation, tracking_tolerance);
522 SetNormsCond<ComplexType>(norm_J, norm_J_inverse, condition_number_estimate, num_steps_since_last_condition_number_computation, frequency_of_CN_estimation);
527 if(success_code != SuccessCode::Success)
535 return SuccessCode::HigherPrecisionNecessary;
539 return SuccessCode::HigherPrecisionNecessary;
570 template<
typename ComplexType>
571 SuccessCode
Predict(Vec<ComplexType> & next_space,
572 NumErrorT & error_estimate,
573 NumErrorT & size_proportion,
575 NumErrorT & norm_J_inverse,
577 const Vec<ComplexType>& current_space, ComplexType current_time,
578 ComplexType
const& delta_t,
579 NumErrorT & condition_number_estimate,
580 unsigned & num_steps_since_last_condition_number_computation,
581 unsigned frequency_of_CN_estimation,
582 NumErrorT
const& tracking_tolerance,
589 throw std::runtime_error(
"incompatible predictor choice in ExplicitPredict, no error estimator");
592 auto success_code =
Predict(next_space, size_proportion, norm_J, norm_J_inverse,
593 S, current_space, current_time, delta_t,
594 condition_number_estimate, num_steps_since_last_condition_number_computation,
595 frequency_of_CN_estimation, tracking_tolerance, AMP_config);
654 template <
typename T>
655 Eigen::PartialPivLU<Mat<T>>& GetLU()
657 return LUSelector<T>::Run(*
this);
661 Eigen::PartialPivLU<Mat<dbl>>& GetLU_d()
666 Eigen::PartialPivLU<Mat<mpfr_complex>>& GetLU_mp()
668 assert(current_precision_==DefaultPrecision());
669 return LU_mp_[current_precision_];
684 template<
typename ComplexType>
685 SuccessCode
FullStep(Vec<ComplexType> & next_space,
687 Vec<ComplexType>
const& current_space, ComplexType
const& current_time,
688 ComplexType
const& delta_t)
694 next_space = current_space;
695 return SuccessCode::Success;
698 using RealType =
typename Eigen::NumTraits<ComplexType>::Real;
700 Mat<ComplexType>& Kref = std::get< Mat<ComplexType> >(K_);
701 Mat<RealType>& aref = std::get< Mat<RealType> >(a_);
702 Vec<RealType>& bref = std::get< Vec<RealType> >(b_);
703 Vec<RealType>& cref = std::get< Vec<RealType> >(c_);
704 Kref.fill(ComplexType(0));
707 if(
EvalRHS(S, current_space, current_time, Kref, 0) != SuccessCode::Success)
709 return SuccessCode::MatrixSolveFailureFirstPartOfPrediction;
712 for(
int ii = 1; ii < s_; ++ii)
715 for(
int jj = 0; jj < ii; ++jj)
716 temp += aref(ii,jj)*Kref.col(jj);
719 if(
EvalRHS<ComplexType>(S, current_space + delta_t*temp, current_time + cref(ii)*delta_t, Kref, ii) != SuccessCode::Success)
720 return SuccessCode::MatrixSolveFailure;
725 for(
int ii = 0; ii < s_; ++ii)
726 temp += bref(ii)*Kref.col(ii);
728 next_space = current_space + delta_t*temp;
730 return SuccessCode::Success;
734 template<
typename ComplexType>
735 void SetNormsCond(NumErrorT & norm_J, NumErrorT & norm_J_inverse, NumErrorT & condition_number_estimate,
unsigned num_steps_since_last_condition_number_computation,
unsigned frequency_of_CN_estimation)
738 Eigen::PartialPivLU<Mat<ComplexType>>& LUref = GetLU<ComplexType>();
739 Mat<ComplexType>& dhdxref = std::get< Mat<ComplexType> >(dh_dx_0_);
743 Vec<ComplexType> temp_soln = LUref.solve(randy);
745 norm_J = NumErrorT(dhdxref.norm());
746 norm_J_inverse = NumErrorT(temp_soln.norm());
748 if (num_steps_since_last_condition_number_computation >= frequency_of_CN_estimation)
750 condition_number_estimate = NumErrorT(norm_J * norm_J_inverse);
751 num_steps_since_last_condition_number_computation = 1;
754 num_steps_since_last_condition_number_computation++;
768 template<
typename ComplexType>
771 using RealType =
typename Eigen::NumTraits<ComplexType>::Real;
773 Mat<ComplexType>& Kref = std::get< Mat<ComplexType> >(K_);
774 Vec<RealType>& b_minus_bstar_ref = std::get< Vec<RealType> >(b_minus_bstar_);
776 auto numFuncs = Kref.rows();
777 Vec<ComplexType> err(numFuncs);
780 for(
int ii = 0; ii < s_; ++ii)
782 err += (b_minus_bstar_ref(ii))*Kref.col(ii);
787 error_estimate = NumErrorT(err.norm());
789 return SuccessCode::Success;
807 template<
typename ComplexType>
816 size_proportion = err_est/NumErrorT(
pow(abs(delta_t), p_+1));
818 return SuccessCode::Success;
822 Mat<ComplexType>& Kref = std::get< Mat<ComplexType> >(K_);
824 size_proportion = NumErrorT(Kref.array().abs().maxCoeff()/(
pow(abs(delta_t), p_)));
825 return SuccessCode::Success;
843 template<
typename ComplexType>
845 const Vec<ComplexType>& space,
const ComplexType& time, Mat<ComplexType> & K,
unsigned stage)
848 if (std::is_same<ComplexType, mpfr_complex>::value)
849 PrecisionSanityCheck();
853 Eigen::PartialPivLU<Mat<ComplexType>>& LUref = GetLU<ComplexType>();
854 Mat<ComplexType>& dhdxref = std::get< Mat<ComplexType> >(dh_dx_0_);
856 if (!std::is_same<ComplexType,dbl>::value)
858 assert(DefaultPrecision()==current_precision_);
860 assert(
Precision(space)==current_precision_);
861 assert(
Precision(time)==current_precision_);
862 assert(
Precision(dhdxref)==current_precision_);
863 assert(
Precision(K)==current_precision_);
865 S.SetAndReset<ComplexType>(space, time);
867 LUref = dhdxref.lu();
868 if (!std::is_same<ComplexType,dbl>::value)
870 assert(
Precision(dhdxref)==current_precision_);
871 assert(
Precision(LUref.matrixLU())==current_precision_);
875 return SuccessCode::MatrixSolveFailureFirstPartOfPrediction;
877 Vec<ComplexType>& dhdtref = std::get< Vec<ComplexType> >(dh_dt_temp_);
879 K.col(stage) = LUref.solve(-dhdtref);
881 return SuccessCode::Success;
886 S.SetAndReset<ComplexType>(space, time);
888 Mat<ComplexType>& dhdxtempref = std::get< Mat<ComplexType> >(dh_dx_temp_);
890 auto LU = dhdxtempref.lu();
893 return SuccessCode::MatrixSolveFailure;
895 Vec<ComplexType>& dhdtref = std::get< Vec<ComplexType> >(dh_dt_temp_);
897 K.col(stage) = LU.solve(-dhdtref);
899 return SuccessCode::Success;
930 template<
typename RealType>
931 void FillButcherTable(
int stages,
const Mat<mpq_rational>& a,
932 const Mat<mpq_rational> & b,
933 const Mat<mpq_rational> & b_minus_bstar,
934 const Mat<mpq_rational> & c)
936 Mat<RealType>& aref = std::get< Mat<RealType> >(a_);
937 aref.resize(stages, stages);
938 for(
int ii = 0; ii < stages; ++ii)
940 for(
int jj = 0; jj < s_; ++jj)
942 aref(ii,jj) =
static_cast<RealType
>(a(ii,jj));
946 Vec<RealType>& bref = std::get< Vec<RealType> >(b_);
948 for(
int ii = 0; ii < stages; ++ii)
950 bref(ii) =
static_cast<RealType
>(b(ii));
953 Vec<RealType>& b_minus_bstar_ref = std::get< Vec<RealType> >(b_minus_bstar_);
954 b_minus_bstar_ref.resize(stages);
955 for(
int ii = 0; ii < stages; ++ii)
957 b_minus_bstar_ref(ii) =
static_cast<RealType
>(b_minus_bstar(ii));
960 Vec<RealType>& cref = std::get< Vec<RealType> >(c_);
962 for(
int ii = 0; ii < stages; ++ii)
964 cref(ii) =
static_cast<RealType
>(c(ii));
967 uses_embedded_ =
true;
984 template<
typename RealType>
985 void FillButcherTable(
int stages,
const Mat<mpq_rational>& a,
986 const Mat<mpq_rational> & b,
987 const Mat<mpq_rational> & c)
989 Mat<RealType>& aref = std::get< Mat<RealType> >(a_);
990 aref.resize(stages, stages);
991 for(
int ii = 0; ii < stages; ++ii)
993 for(
int jj = 0; jj < s_; ++jj)
995 aref(ii,jj) =
static_cast<RealType
>(a(ii,jj));
999 Vec<RealType>& bref = std::get< Vec<RealType> >(b_);
1000 bref.resize(stages);
1001 for(
int ii = 0; ii < stages; ++ii)
1003 bref(ii) =
static_cast<RealType
>(b(ii));
1006 Vec<RealType>& cref = std::get< Vec<RealType> >(c_);
1007 cref.resize(stages);
1008 for(
int ii = 0; ii < stages; ++ii)
1010 cref(ii) =
static_cast<RealType
>(c(ii));
1013 uses_embedded_ =
false;
1027 unsigned numTotalFunctions_;
1028 unsigned numVariables_;
1029 mutable std::tuple< Mat<dbl>, Mat<mpfr_complex> > K_;
1030 Predictor predictor_;
1032 mutable std::tuple< Mat<dbl>, Mat<mpfr_complex> > dh_dx_0_;
1033 mutable std::tuple< Mat<dbl>, Mat<mpfr_complex> > dh_dx_temp_;
1034 mutable std::tuple< Vec<dbl>, Vec<mpfr_complex> > dh_dt_temp_;
1037 mutable Eigen::PartialPivLU<Mat<dbl>> LU_d_;
1038 mutable std::map<unsigned,Eigen::PartialPivLU<Mat<mpfr_complex>>> LU_mp_;
1042 mutable unsigned s_;
1043 mutable std::tuple< Mat<double>, Mat<mpfr_float> > a_;
1044 mutable std::tuple< Vec<double>, Vec<mpfr_float> > b_;
1045 mutable std::tuple< Vec<double>, Vec<mpfr_float> > b_minus_bstar_;
1046 mutable std::tuple< Vec<double>, Vec<mpfr_float> > c_;
1048 mutable bool uses_embedded_;
1049 mutable unsigned current_precision_;
1057 static const mpq_rational aEulerPtr_[];
1058 static const Eigen::Matrix<mpq_rational,1,1> aEuler_;
1059 static const mpq_rational bEulerPtr_[];
1060 static const Eigen::Matrix<mpq_rational,1,1> bEuler_;
1061 static const mpq_rational cEulerPtr_[];
1062 static const Eigen::Matrix<mpq_rational,1,1> cEuler_;
1065 static const mpq_rational aHeunEulerPtr_[];
1066 static const Eigen::Matrix<mpq_rational,2,2> aHeunEuler_;
1067 static const mpq_rational bHeunEulerPtr_[];
1068 static const Eigen::Matrix<mpq_rational,2,1> bHeunEuler_;
1069 static const mpq_rational b_minus_bstarHeunEulerPtr_[];
1070 static const Eigen::Matrix<mpq_rational,2,1> b_minus_bstarHeunEuler_;
1071 static const mpq_rational cHeunEulerPtr_[];
1072 static const Eigen::Matrix<mpq_rational,2,1> cHeunEuler_;
1075 static const mpq_rational aRK4Ptr_[];
1076 static const Eigen::Matrix<mpq_rational,4,4> aRK4_;
1077 static const mpq_rational bRK4Ptr_[];
1078 static const Eigen::Matrix<mpq_rational,4,1> bRK4_;
1079 static const mpq_rational cRK4Ptr_[];
1080 static const Eigen::Matrix<mpq_rational,4,1> cRK4_;
1083 static const mpq_rational aRKF45Ptr_[];
1084 static const Eigen::Matrix<mpq_rational,6,6> aRKF45_;
1085 static const mpq_rational bRKF45Ptr_[];
1086 static const Eigen::Matrix<mpq_rational,6,1> bRKF45_;
1087 static const mpq_rational b_minus_bstarRKF45Ptr_[];
1088 static const Eigen::Matrix<mpq_rational,6,1> b_minus_bstarRKF45_;
1089 static const mpq_rational cRKF45Ptr_[];
1090 static const Eigen::Matrix<mpq_rational,6,1> cRKF45_;
1093 static const mpq_rational aRKCK45Ptr_[];
1094 static const Eigen::Matrix<mpq_rational,6,6> aRKCK45_;
1095 static const mpq_rational bRKCK45Ptr_[];
1096 static const Eigen::Matrix<mpq_rational,6,1> bRKCK45_;
1097 static const mpq_rational b_minus_bstarRKCK45Ptr_[];
1098 static const Eigen::Matrix<mpq_rational,6,1> b_minus_bstarRKCK45_;
1099 static const mpq_rational cRKCK45Ptr_[];
1100 static const Eigen::Matrix<mpq_rational,6,1> cRKCK45_;
1103 static const mpq_rational aRKDP56Ptr_[];
1104 static const Eigen::Matrix<mpq_rational,8,8> aRKDP56_;
1105 static const mpq_rational bRKDP56Ptr_[];
1106 static const Eigen::Matrix<mpq_rational,8,1> bRKDP56_;
1107 static const mpq_rational b_minus_bstarRKDP56Ptr_[];
1108 static const Eigen::Matrix<mpq_rational,8,1> b_minus_bstarRKDP56_;
1109 static const mpq_rational cRKDP56Ptr_[];
1110 static const Eigen::Matrix<mpq_rational,8,1> cRKDP56_;
1113 static const mpq_rational aRKV67Ptr_[];
1114 static const Eigen::Matrix<mpq_rational,10,10> aRKV67_;
1115 static const mpq_rational bRKV67Ptr_[];
1116 static const Eigen::Matrix<mpq_rational,10,1> bRKV67_;
1117 static const mpq_rational b_minus_bstarRKV67Ptr_[];
1118 static const Eigen::Matrix<mpq_rational,10,1> b_minus_bstarRKV67_;
1119 static const mpq_rational cRKV67Ptr_[];
1120 static const Eigen::Matrix<mpq_rational,10,1> cRKV67_;