Bertini 2 - C++ Core
Software for Numerical Algebraic Geometry
Loading...
Searching...
No Matches
fixed_precision_tracker.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//fixed_precision_tracker.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//fixed_precision_tracker.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with fixed_precision_tracker.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) 2015 - 2021 by Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
22// individual authors of this file include:
23// silviana amethyst, university of wisconsin eau claire
24
25
30
31#ifndef BERTINI_FIXED_PRECISION_TRACKER_HPP
32#define BERTINI_FIXED_PRECISION_TRACKER_HPP
33
35
36
37namespace bertini{
38
39 namespace tracking{
40
41 using std::max;
42 using std::min;
43 using std::pow;
44
45 using bertini::max;
46
47
48
49
50
51
52
58 template<class DerivedT>
59 class FixedPrecisionTracker : public Tracker<FixedPrecisionTracker<DerivedT>>
60 {
61 public:
62
63 using BaseComplexType = typename TrackerTraits<DerivedT>::BaseComplexType;
64 using BaseRealType = typename TrackerTraits<DerivedT>::BaseRealType;
65
66 using CT = BaseComplexType;
67 using RT = BaseRealType;
68
69 virtual ~FixedPrecisionTracker() = default;
70
71 using EmitterType = FixedPrecisionTracker<DerivedT>;
72 using Base = Tracker<FixedPrecisionTracker<DerivedT>>;
73
74 using Config = typename Base::Config;
75 FORWARD_GET_CONFIGURED
76 using Stepping = typename Base::Stepping;
77 using Newton = typename Base::Newton;
78
79 FixedPrecisionTracker(System const& sys) : Base(sys){}
80
84 void PrecisionSetup(FixedPrecisionConfig const&)
85 { }
86
87
88 Vec<CT> CurrentPoint() const override
89 {
90 return std::get<Vec<CT>>(this->current_space_);
91 }
92
93
94
95 void ResetCounters() const override
96 {
97 Base::ResetCountersBase();
98
100 // initialize to the frequency so guaranteed to compute it the first try
101 this->num_steps_since_last_condition_number_computation_ = this->Get<Stepping>().frequency_of_CN_estimation;
102 }
103
104
110 SuccessCode PreIterationCheck() const override
111 {
112 if (this->num_successful_steps_taken_ >= Get<Stepping>().max_num_steps)
113 return SuccessCode::MaxNumStepsTaken;
114 if (this->current_stepsize_ < Get<Stepping>().min_step_size)
115 return SuccessCode::MinStepSizeReached;
116
117 return SuccessCode::Success;
118 }
119
120
121
122
123
124
125
126
127
128
129 void PostTrackCleanup() const override
130 {
131 this->NotifyObservers(TrackingEnded<EmitterType>(*this));
132 }
133
141 void CopyFinalSolution(Vec<CT> & solution_at_endtime) const override
142 {
143
144 // the current precision is the precision of the output solution point.
145
146 unsigned num_vars = this->GetSystem().NumVariables();
147 solution_at_endtime.resize(num_vars);
148 for (unsigned ii=0; ii<num_vars; ii++)
149 {
150 solution_at_endtime(ii) = std::get<Vec<CT> >(this->current_space_)(ii);
151 }
152
153 }
154
155
156
157
165 SuccessCode TrackerIteration() const override
166 {
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");
170
171 this->NotifyObservers(NewStep<EmitterType >(*this));
172
173 Vec<CT>& predicted_space = std::get<Vec<CT> >(this->temporary_space_); // this will be populated in the Predict step
174 Vec<CT>& current_space = std::get<Vec<CT> >(this->current_space_); // the thing we ultimately wish to update
175 CT current_time = CT(this->current_time_);
176 CT delta_t = CT(this->delta_t_);
177
178 SuccessCode predictor_code = Predict(predicted_space, current_space, current_time, delta_t);
179
180 if (predictor_code!=SuccessCode::Success)
181 {
182 this->NotifyObservers(FirstStepPredictorMatrixSolveFailure<EmitterType >(*this));
183
184 this->next_stepsize_ = RT(Get<Stepping>().step_size_fail_factor)*this->current_stepsize_;
185
186 UpdateStepsize();
187
188 return predictor_code;
189 }
190
191 this->NotifyObservers(SuccessfulPredict<EmitterType , CT>(*this, predicted_space));
192
193 Vec<CT>& tentative_next_space = std::get<Vec<CT> >(this->tentative_space_); // this will be populated in the Correct step
194
195 CT tentative_next_time = current_time + delta_t;
196
197 SuccessCode corrector_code = Correct(tentative_next_space,
198 predicted_space,
199 tentative_next_time);
200
201 if (corrector_code == SuccessCode::GoingToInfinity)
202 {
203 // there is no corrective action possible...
204 return corrector_code;
205 }
206 else if (corrector_code!=SuccessCode::Success)
207 {
208 this->NotifyObservers(CorrectorMatrixSolveFailure<EmitterType >(*this));
209
210 this->next_stepsize_ = RT(Get<Stepping>().step_size_fail_factor)*this->current_stepsize_;
211 UpdateStepsize();
212
213 return corrector_code;
214 }
215
216
217 this->NotifyObservers(SuccessfulCorrect<EmitterType , CT>(*this, tentative_next_space));
218
219 // copy the tentative vector into the current space vector;
220 current_space = tentative_next_space;
221 return SuccessCode::Success;
222 }
223
224
228 SuccessCode CheckGoingToInfinity() const override
229 {
230 return Base::template CheckGoingToInfinity<CT>();
231 }
232
233
234
235
236
240 SuccessCode UpdateStepsize() const
241 {
242 this->SetStepSize(this->next_stepsize_);
243 return SuccessCode::Success;
244 }
245
246
247
248
249
251 //
252 // overrides for counter adjustment after a TrackerIteration()
253 //
255
259 void OnStepSuccess() const override
260 {
262 this->NotifyObservers(SuccessfulStep<EmitterType >(*this));
263 }
264
268 void OnStepFail() const override
269 {
272 this->NotifyObservers(FailedStep<EmitterType >(*this));
273 }
274
275
276
277 void OnInfiniteTruncation() const override
278 {
279 this->NotifyObservers(InfinitePathTruncation<EmitterType>(*this));
280 }
281
283 //
284 //
285
286
299 SuccessCode Predict(Vec<CT> & predicted_space,
300 Vec<CT> const& current_space,
301 CT const& current_time, CT const& delta_t) const
302 {
303
304 return this->predictor_->Predict(
305 predicted_space,
306 this->tracked_system_,
307 current_space, current_time,
308 delta_t,
311 Get<Stepping>().frequency_of_CN_estimation,
312 this->tracking_tolerance_);
313 }
314
315
316
328 SuccessCode Correct(Vec<CT> & corrected_space,
329 Vec<CT> const& current_space,
330 CT const& current_time) const
331 {
332 return this->corrector_->Correct(corrected_space,
333 this->tracked_system_,
334 current_space,
335 current_time,
337 Get<Newton>().min_num_newton_iterations,
338 Get<Newton>().max_num_newton_iterations);
339 }
340
341
342
355 SuccessCode RefineImpl(Vec<CT> & new_space,
356 Vec<CT> const& start_point, CT const& current_time) const
357 {
358 return this->corrector_->Correct(new_space,
359 this->tracked_system_,
360 start_point,
361 current_time,
363 Get<Newton>().min_num_newton_iterations,
364 Get<Newton>().max_num_newton_iterations);
365 }
366
367
368
369
370
371
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
389 {
390 return this->corrector_->Correct(new_space,
391 this->tracked_system_,
392 start_point,
393 current_time,
394 tolerance,
395 1,
396 max_iterations);
397 }
398
399
406 //
407
408 // no additional state variables needed for the FixedPrecision base tracker types
409
410 };
411
412
413
414
415 class DoublePrecisionTracker : public FixedPrecisionTracker<DoublePrecisionTracker>
416 {
417 public:
418 using BaseComplexType = dbl;
419 using BaseRealType = double;
420
421 using EmitterType = typename TrackerTraits<DoublePrecisionTracker>::EventEmitterType;
422
423
427 DoublePrecisionTracker(class System const& sys) : FixedPrecisionTracker<DoublePrecisionTracker>(sys)
428 { }
429
430
431 DoublePrecisionTracker() = delete;
432
433 virtual ~DoublePrecisionTracker() = default;
434
435
436 unsigned CurrentPrecision() const override
437 {
438 return DoublePrecision();
439 }
440
441
451 SuccessCode TrackerLoopInitialization(BaseComplexType const& start_time,
452 BaseComplexType const& end_time,
453 Vec<BaseComplexType> const& start_point) const override
454 {
455 this->NotifyObservers(Initializing<EmitterType,BaseComplexType>(*this,start_time, end_time, start_point));
456
457 // set up the master current time and the current step size
458 this->current_time_ = start_time;
459 this->endtime_ = end_time;
460 std::get<Vec<BaseComplexType> >(this->current_space_) = start_point;
461 if (this->reinitialize_stepsize_)
462 this->SetStepSize(min(BaseRealType(Get<Stepping>().initial_step_size),abs(start_time-end_time)/Get<Stepping>().min_num_steps));
463
465
466 return SuccessCode::Success;
467 }
468
469
470 private:
471
472 }; // re: DoublePrecisionTracker
473
474
475 class MultiplePrecisionTracker : public FixedPrecisionTracker<MultiplePrecisionTracker>
476 {
477 public:
478 using BaseComplexType = mpfr_complex;
479 using BaseRealType = mpfr_float;
480
481 using EmitterType = FixedPrecisionTracker<MultiplePrecisionTracker>;
482
483
489 MultiplePrecisionTracker(class System const& sys) : FixedPrecisionTracker<MultiplePrecisionTracker>(sys), precision_(DefaultPrecision())
490 { }
491
492
493 MultiplePrecisionTracker() = delete;
494
495 virtual ~MultiplePrecisionTracker() = default;
496
497
498 unsigned CurrentPrecision() const override
499 {
500 return precision_;
501 }
502
503
513 SuccessCode TrackerLoopInitialization(BaseComplexType const& start_time,
514 BaseComplexType const& end_time,
515 Vec<BaseComplexType> const& start_point) const override
516 {
517
518 if (start_point(0).precision()!=DefaultPrecision())
519 {
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());
523 }
524
525 if (start_point(0).precision()!=this->CurrentPrecision())
526 {
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());
530 }
531
532 if (DefaultPrecision()!=this->CurrentPrecision())
533 {
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());
537 }
538
539
540 this->NotifyObservers(Initializing<EmitterType,BaseComplexType>(*this,start_time, end_time, start_point));
541
542 // set up the master current time and the current step size
543 this->current_time_ = start_time;
544 this->endtime_ = end_time;
545 std::get<Vec<BaseComplexType> >(this->current_space_) = start_point;
546 if (this->reinitialize_stepsize_)
547 this->SetStepSize(min(mpfr_float(Get<Stepping>().initial_step_size),mpfr_float(abs(start_time-end_time)/Get<Stepping>().min_num_steps)));
548
550
551 return SuccessCode::Success;
552 }
553
554 bool PrecisionSanityCheck() const
555 {
556 return GetSystem().precision() == precision_ &&
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_ &&
561 Precision(this->endtime_)==precision_
562 ;
563 }
564 private:
565
566 unsigned precision_;
567 }; // re: MultiplePrecisionTracker
568 } // namespace tracking
569} // namespace bertini
570
571
572#endif
573
574
575
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
const System & GetSystem() const
Definition base_tracker.hpp:373
unsigned num_successful_steps_since_stepsize_increase_
Definition base_tracker.hpp:598
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
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