31#ifndef BERTINI_FIXED_PRECISION_TRACKER_HPP
32#define BERTINI_FIXED_PRECISION_TRACKER_HPP
58 template<
class DerivedT>
59 class FixedPrecisionTracker :
public Tracker<FixedPrecisionTracker<DerivedT>>
63 using BaseComplexType =
typename TrackerTraits<DerivedT>::BaseComplexType;
64 using BaseRealType =
typename TrackerTraits<DerivedT>::BaseRealType;
66 using CT = BaseComplexType;
67 using RT = BaseRealType;
69 virtual ~FixedPrecisionTracker() =
default;
71 using EmitterType = FixedPrecisionTracker<DerivedT>;
72 using Base = Tracker<FixedPrecisionTracker<DerivedT>>;
74 using Config =
typename Base::Config;
75 FORWARD_GET_CONFIGURED
76 using Stepping =
typename Base::Stepping;
77 using Newton =
typename Base::Newton;
79 FixedPrecisionTracker(System
const& sys) : Base(sys){}
84 void PrecisionSetup(FixedPrecisionConfig
const&)
88 Vec<CT> CurrentPoint()
const override
95 void ResetCounters()
const override
97 Base::ResetCountersBase();
110 SuccessCode PreIterationCheck()
const override
113 return SuccessCode::MaxNumStepsTaken;
115 return SuccessCode::MinStepSizeReached;
117 return SuccessCode::Success;
129 void PostTrackCleanup()
const override
141 void CopyFinalSolution(Vec<CT> & solution_at_endtime)
const override
147 solution_at_endtime.resize(num_vars);
148 for (
unsigned ii=0; ii<num_vars; ii++)
150 solution_at_endtime(ii) = std::get<Vec<CT> >(this->
current_space_)(ii);
165 SuccessCode TrackerIteration()
const override
167 static_assert(std::is_same< typename Eigen::NumTraits<RT>::Real,
168 typename Eigen::NumTraits<CT>::Real>::value,
169 "underlying complex type and the type for comparisons must match");
174 Vec<CT>& current_space = std::get<Vec<CT> >(this->
current_space_);
178 SuccessCode predictor_code = Predict(predicted_space, current_space, current_time, delta_t);
180 if (predictor_code!=SuccessCode::Success)
182 this->
NotifyObservers(FirstStepPredictorMatrixSolveFailure<EmitterType >(*
this));
184 this->next_stepsize_ = RT(Get<Stepping>().step_size_fail_factor)*this->
current_stepsize_;
188 return predictor_code;
191 this->
NotifyObservers(SuccessfulPredict<EmitterType , CT>(*
this, predicted_space));
195 CT tentative_next_time = current_time + delta_t;
197 SuccessCode corrector_code = Correct(tentative_next_space,
199 tentative_next_time);
201 if (corrector_code == SuccessCode::GoingToInfinity)
204 return corrector_code;
206 else if (corrector_code!=SuccessCode::Success)
208 this->
NotifyObservers(CorrectorMatrixSolveFailure<EmitterType >(*
this));
210 this->next_stepsize_ = RT(Get<Stepping>().step_size_fail_factor)*this->
current_stepsize_;
213 return corrector_code;
217 this->
NotifyObservers(SuccessfulCorrect<EmitterType , CT>(*
this, tentative_next_space));
220 current_space = tentative_next_space;
221 return SuccessCode::Success;
228 SuccessCode CheckGoingToInfinity()
const override
230 return Base::template CheckGoingToInfinity<CT>();
240 SuccessCode UpdateStepsize()
const
243 return SuccessCode::Success;
259 void OnStepSuccess()
const override
268 void OnStepFail()
const override
277 void OnInfiniteTruncation()
const override
299 SuccessCode Predict(Vec<CT> & predicted_space,
300 Vec<CT>
const& current_space,
301 CT
const& current_time, CT
const& delta_t)
const
304 return this->predictor_->Predict(
307 current_space, current_time,
311 Get<Stepping>().frequency_of_CN_estimation,
328 SuccessCode Correct(Vec<CT> & corrected_space,
329 Vec<CT>
const& current_space,
330 CT
const& current_time)
const
332 return this->corrector_->Correct(corrected_space,
337 Get<Newton>().min_num_newton_iterations,
338 Get<Newton>().max_num_newton_iterations);
355 SuccessCode RefineImpl(Vec<CT> & new_space,
356 Vec<CT>
const& start_point, CT
const& current_time)
const
358 return this->corrector_->Correct(new_space,
363 Get<Newton>().min_num_newton_iterations,
364 Get<Newton>().max_num_newton_iterations);
386 SuccessCode RefineImpl(Vec<CT> & new_space,
387 Vec<CT>
const& start_point, CT
const& current_time,
388 NumErrorT
const& tolerance,
unsigned max_iterations)
const
390 return this->corrector_->Correct(new_space,
415 class DoublePrecisionTracker :
public FixedPrecisionTracker<DoublePrecisionTracker>
418 using BaseComplexType = dbl;
419 using BaseRealType = double;
421 using EmitterType =
typename TrackerTraits<DoublePrecisionTracker>::EventEmitterType;
427 DoublePrecisionTracker(
class System
const& sys) : FixedPrecisionTracker<DoublePrecisionTracker>(sys)
431 DoublePrecisionTracker() =
delete;
433 virtual ~DoublePrecisionTracker() =
default;
436 unsigned CurrentPrecision()
const override
438 return DoublePrecision();
451 SuccessCode TrackerLoopInitialization(BaseComplexType
const& start_time,
452 BaseComplexType
const& end_time,
453 Vec<BaseComplexType>
const& start_point)
const override
455 this->
NotifyObservers(Initializing<EmitterType,BaseComplexType>(*
this,start_time, end_time, start_point));
460 std::get<Vec<BaseComplexType> >(this->
current_space_) = start_point;
462 this->
SetStepSize(min(BaseRealType(Get<Stepping>().initial_step_size),abs(start_time-end_time)/Get<Stepping>().min_num_steps));
466 return SuccessCode::Success;
475 class MultiplePrecisionTracker :
public FixedPrecisionTracker<MultiplePrecisionTracker>
478 using BaseComplexType = mpfr_complex;
479 using BaseRealType = mpfr_float;
481 using EmitterType = FixedPrecisionTracker<MultiplePrecisionTracker>;
489 MultiplePrecisionTracker(
class System
const& sys) : FixedPrecisionTracker<MultiplePrecisionTracker>(sys), precision_(DefaultPrecision())
493 MultiplePrecisionTracker() =
delete;
495 virtual ~MultiplePrecisionTracker() =
default;
498 unsigned CurrentPrecision()
const override
513 SuccessCode TrackerLoopInitialization(BaseComplexType
const& start_time,
514 BaseComplexType
const& end_time,
515 Vec<BaseComplexType>
const& start_point)
const override
518 if (start_point(0).precision()!=DefaultPrecision())
520 std::stringstream err_msg;
521 err_msg <<
"start point for fixed multiple precision tracker has differing precision from default (" << start_point(0).precision() <<
"!=" << DefaultPrecision() <<
"), tracking cannot start";
522 throw std::runtime_error(err_msg.str());
525 if (start_point(0).precision()!=this->CurrentPrecision())
527 std::stringstream err_msg;
528 err_msg <<
"start point for fixed multiple precision tracker has differing precision from tracker's precision (" << start_point(0).precision() <<
"!=" << this->CurrentPrecision() <<
"), tracking cannot start";
529 throw std::runtime_error(err_msg.str());
532 if (DefaultPrecision()!=this->CurrentPrecision())
534 std::stringstream err_msg;
535 err_msg <<
"current default precision differs from tracker's precision (" << DefaultPrecision() <<
"!=" << this->CurrentPrecision() <<
"), tracking cannot start";
536 throw std::runtime_error(err_msg.str());
540 this->
NotifyObservers(Initializing<EmitterType,BaseComplexType>(*
this,start_time, end_time, start_point));
545 std::get<Vec<BaseComplexType> >(this->
current_space_) = start_point;
547 this->
SetStepSize(min(mpfr_float(Get<Stepping>().initial_step_size),mpfr_float(abs(start_time-end_time)/Get<Stepping>().min_num_steps)));
551 return SuccessCode::Success;
554 bool PrecisionSanityCheck()
const
557 DefaultPrecision()==precision_ &&
558 std::get<Vec<mpfr_complex> >(
current_space_)(0).precision() == precision_ &&
559 std::get<Vec<mpfr_complex> >(
tentative_space_)(0).precision() == precision_ &&
560 std::get<Vec<mpfr_complex> >(
temporary_space_)(0).precision() == precision_ &&
Contains the abstract base Tracker type, from which all other Trackers inherit.
void NotifyObservers(AnyEvent const &e) const
Sends an Event (more particularly, AnyEvent) to all watching observers of this object.
Definition observable.hpp:90
void precision(unsigned new_precision) const
size_t NumVariables() const
CT current_time_
Definition base_tracker.hpp:586
const System & GetSystem() const
Definition base_tracker.hpp:373
unsigned num_successful_steps_since_stepsize_increase_
Definition base_tracker.hpp:598
CT endtime_
Definition base_tracker.hpp:585
RT current_stepsize_
Definition base_tracker.hpp:588
virtual void ResetCounters() const=0
NumErrorT condition_number_estimate_
Definition base_tracker.hpp:609
TupOfVec current_space_
Definition base_tracker.hpp:604
unsigned num_steps_since_last_condition_number_computation_
Definition base_tracker.hpp:597
bool reinitialize_stepsize_
Definition base_tracker.hpp:562
TupOfVec temporary_space_
Definition base_tracker.hpp:606
void IncrementBaseCountersFail() const
Definition base_tracker.hpp:536
CT delta_t_
Definition base_tracker.hpp:587
void SetStepSize(RT const &new_stepsize) const
Definition base_tracker.hpp:393
unsigned num_successful_steps_taken_
Definition base_tracker.hpp:566
TupOfVec tentative_space_
Definition base_tracker.hpp:605
std::reference_wrapper< const System > tracked_system_
Definition base_tracker.hpp:559
NumErrorT tracking_tolerance_
Definition base_tracker.hpp:582
void IncrementBaseCountersSuccess() const
Definition base_tracker.hpp:519
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object. If the object is empty, it's the precision of a default-constru...
Definition eigen_extensions.hpp:292
T max(T const &a, T const &b, T const &c)
Three-argument form of max.
Definition mpfr_extensions.hpp:98