You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							641 lines
						
					
					
						
							21 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							641 lines
						
					
					
						
							21 KiB
						
					
					
				
								// This file is part of Bertini 2.
							 | 
						|
								//
							 | 
						|
								// base_tracker.hpp is free software: you can redistribute it and/or modify
							 | 
						|
								// it under the terms of the GNU General Public License as published by
							 | 
						|
								// the Free Software Foundation, either version 3 of the License, or
							 | 
						|
								//(at your option) any later version.
							 | 
						|
								//
							 | 
						|
								// base_tracker.hpp is distributed in the hope that it will be useful,
							 | 
						|
								// but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						|
								// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						|
								// GNU General Public License for more details.
							 | 
						|
								//
							 | 
						|
								// You should have received a copy of the GNU General Public License
							 | 
						|
								// along with base_tracker.hpp.  If not, see <http://www.gnu.org/licenses/>.
							 | 
						|
								//
							 | 
						|
								//  Copyright(C) 2015 - 2021 by Bertini2 Development Team
							 | 
						|
								//
							 | 
						|
								//  See <http://www.gnu.org/licenses/> for a copy of the license,
							 | 
						|
								//  as well as COPYING.  Bertini2 is provided with permitted
							 | 
						|
								//  additional terms in the b2/licenses/ directory.
							 | 
						|
								
							 | 
						|
								// individual authors of this file include:
							 | 
						|
								// silviana amethyst, university of wisconsin eau claire
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								\file base_tracker.hpp
							 | 
						|
								
							 | 
						|
								\brief
							 | 
						|
								
							 | 
						|
								\brief Contains the abstract base Tracker type, from which all other Trackers
							 | 
						|
								inherit.
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								#ifndef BERTINI_BASE_TRACKER_HPP
							 | 
						|
								#define BERTINI_BASE_TRACKER_HPP
							 | 
						|
								
							 | 
						|
								#include <algorithm>
							 | 
						|
								// #include "tracking/step.hpp"
							 | 
						|
								#include "detail/observable.hpp"
							 | 
						|
								#include "logging.hpp"
							 | 
						|
								#include "trackers/newton_corrector.hpp"
							 | 
						|
								#include "trackers/ode_predictors.hpp"
							 | 
						|
								
							 | 
						|
								// Must be at the end of the include list
							 | 
						|
								#include "detail/configured.hpp"
							 | 
						|
								#include "detail/is_template_parameter.hpp"
							 | 
						|
								#include "trackers/events.hpp"
							 | 
						|
								
							 | 
						|
								namespace bertini {
							 | 
						|
								
							 | 
						|
								namespace tracking {
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								\class Tracker
							 | 
						|
								
							 | 
						|
								\brief Base tracker class for trackers offered in Bertini2.
							 | 
						|
								
							 | 
						|
								\see AMPTracker
							 | 
						|
								
							 | 
						|
								## Using a tracker
							 | 
						|
								
							 | 
						|
								Trackers in Bertini2 are the engine for tracking a path from one space-time pair
							 | 
						|
								to another.  The path is implicitly described by the system being tracked.
							 | 
						|
								
							 | 
						|
								1. Create a system.
							 | 
						|
								2. Create a tracker, associating it to the system.
							 | 
						|
								3. Set the config for the track.
							 | 
						|
								4. Track from your start point and time, to the target time.
							 | 
						|
								5. Profit.
							 | 
						|
								
							 | 
						|
								Specific examples are given with the implemented tracker types.  So far, these
							 | 
						|
								types are avaiable:
							 | 
						|
								
							 | 
						|
								* AMPTracker
							 | 
						|
								
							 | 
						|
								Please see their detailed documentation for description of how to use them
							 | 
						|
								correctly.
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								## Purpose
							 | 
						|
								
							 | 
						|
								Since the Bertini trackers have common functionality, and we want to be able to
							 | 
						|
								call arbitrary algorithms using and tracker type, we use inheritance.  That is,
							 | 
						|
								there is common functionality in all trackers, such as
							 | 
						|
								
							 | 
						|
								* Setup
							 | 
						|
								* TrackPath
							 | 
						|
								* Refine
							 | 
						|
								
							 | 
						|
								which we want all Trackers to be able to do.  However, the internal behaviour of
							 | 
						|
								a particular tracker varies -- which is why it is a different type.  In
							 | 
						|
								particular, the fixed precision trackers produce and work in a fixed precision,
							 | 
						|
								whereas the AMPTracker varies precision to get around or near branch points
							 | 
						|
								while tracking.
							 | 
						|
								
							 | 
						|
								Hence, the use of trackers in Bertini2 is through pointers or references to
							 | 
						|
								Trackers, enabling the use of any kind of tracking in any algorithm, and further
							 | 
						|
								allowing the development of new tracker types as the theory and practice
							 | 
						|
								advance.
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								## Creating a new tracker type
							 | 
						|
								
							 | 
						|
								To create a new Tracker type, inherit from this, and override the following
							 | 
						|
								functions:
							 | 
						|
								
							 | 
						|
								\code
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								SuccessCode Refine(Vec<mpfr> & new_space,
							 | 
						|
								                                        Vec<mpfr> const& start_point, mpfr
							 | 
						|
								const& current_time) override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								private:
							 | 
						|
								
							 | 
						|
								void TrackerLoopInitialization(mpfr const& start_time, Vec<mpfr> const&
							 | 
						|
								start_point) override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								SuccessCode InitialRefinement() override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								SuccessCode PreIterationCheck() const override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								SuccessCode TrackerIteration() override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								void CopyFinalSolution(Vec<mpfr> & solution_at_endtime) const override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								\endcode
							 | 
						|
								
							 | 
						|
								and optionally override the following functions
							 | 
						|
								
							 | 
						|
								\code
							 | 
						|
								void ResetCounters() override
							 | 
						|
								{}
							 | 
						|
								
							 | 
						|
								void PostTrackCleanup() override
							 | 
						|
								{}
							 | 
						|
								\endcode
							 | 
						|
								where you probably want to call this base function, which is why it is
							 | 
						|
								protected, not private.
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								template <class D>
							 | 
						|
								class Tracker
							 | 
						|
								    : public Observable,
							 | 
						|
								      public detail::Configured<typename TrackerTraits<D>::NeededConfigs> {
							 | 
						|
								  using NeededTypes = typename TrackerTraits<D>::NeededTypes;
							 | 
						|
								  using BaseComplexType = typename TrackerTraits<D>::BaseComplexType;
							 | 
						|
								  using BaseRealType = typename TrackerTraits<D>::BaseRealType;
							 | 
						|
								
							 | 
						|
								  using CT = BaseComplexType;
							 | 
						|
								  using RT = BaseRealType;
							 | 
						|
								
							 | 
						|
								 public:
							 | 
						|
								  using Config = detail::Configured<typename TrackerTraits<D>::NeededConfigs>;
							 | 
						|
								  using Stepping = SteppingConfig;
							 | 
						|
								  using Newton = NewtonConfig;
							 | 
						|
								  using PrecConf = typename TrackerTraits<D>::PrecisionConfig;
							 | 
						|
								
							 | 
						|
								  Tracker(System const& sys) : tracked_system_(std::ref(sys)) {
							 | 
						|
								    predictor_ = std::make_shared<predict::ExplicitRKPredictor>(
							 | 
						|
								        predict::DefaultPredictor(), tracked_system_);
							 | 
						|
								    corrector_ = std::make_shared<correct::NewtonCorrector>(tracked_system_);
							 | 
						|
								    SetPredictor(predict::DefaultPredictor());
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Get the tracker set up for tracking.
							 | 
						|
								
							 | 
						|
								  Pass the tracker the configuration for tracking, to get it set up.
							 | 
						|
								  */
							 | 
						|
								  void Setup(Predictor new_predictor_choice, double const& tracking_tolerance,
							 | 
						|
								             double const& path_truncation_threshold,
							 | 
						|
								             SteppingConfig const& stepping, NewtonConfig const& newton) {
							 | 
						|
								    SetPredictor(new_predictor_choice);
							 | 
						|
								    corrector_->Settings(newton);
							 | 
						|
								
							 | 
						|
								    SetTrackingTolerance(tracking_tolerance);
							 | 
						|
								
							 | 
						|
								    path_truncation_threshold_ = path_truncation_threshold;
							 | 
						|
								
							 | 
						|
								    this->template Set(stepping);
							 | 
						|
								    this->template Set(newton);
							 | 
						|
								
							 | 
						|
								    current_stepsize_ = BaseRealType(stepping.initial_step_size);
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  using Config::Get;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Set how tightly to track the path.
							 | 
						|
								
							 | 
						|
								  Smaller values tracks the path more tightly, at the expense of higher
							 | 
						|
								  computational time.
							 | 
						|
								
							 | 
						|
								  \param tracking_tolerance The new value.  Newton iterations are performed
							 | 
						|
								  until the step length is less than this number, or the max number of
							 | 
						|
								  iterations has been reached, in which case the overall predict-correct step is
							 | 
						|
								  viewed as a failure, and the step is undone.  This number must be positive.
							 | 
						|
								  */
							 | 
						|
								  void SetTrackingTolerance(double const& tracking_tolerance) {
							 | 
						|
								    if (tracking_tolerance <= 0)
							 | 
						|
								      throw std::runtime_error("tracking tolerance must be strictly positive");
							 | 
						|
								
							 | 
						|
								    tracking_tolerance_ = tracking_tolerance;
							 | 
						|
								    digits_tracking_tolerance_ =
							 | 
						|
								        NumTraits<double>::TolToDigits(tracking_tolerance);
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  void SetInfiniteTruncationTolerance(double const& tol) {
							 | 
						|
								    if (tol <= 0)
							 | 
						|
								      throw std::runtime_error(
							 | 
						|
								          "truncation threshold must be strictly positive");
							 | 
						|
								
							 | 
						|
								    path_truncation_threshold_ = tol;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Track a start point through time, from a start time to a target time.
							 | 
						|
								
							 | 
						|
								  \param[out] solution_at_endtime The value of the solution at the end time.
							 | 
						|
								  \param start_time The time at which to start tracking.
							 | 
						|
								  \param endtime The time to track to.
							 | 
						|
								  \param start_point The intial space values for tracking.
							 | 
						|
								  \return A success code indicating whether tracking was successful.  Will be
							 | 
						|
								  SuccessCode::Success if was successful, and something else otherwise.
							 | 
						|
								
							 | 
						|
								  The is the fundamental method for the tracker.  First, you create and set up
							 | 
						|
								  the tracker, telling it what system you will solve, and the settings to use.
							 | 
						|
								  Then, you actually do the tracking.
							 | 
						|
								  */
							 | 
						|
								  SuccessCode TrackPath(Vec<CT>& solution_at_endtime, CT const& start_time,
							 | 
						|
								                        CT const& endtime, Vec<CT> const& start_point) const {
							 | 
						|
								    if (start_point.size() != GetSystem().NumVariables())
							 | 
						|
								      throw std::runtime_error(
							 | 
						|
								          "start point size must match the number of variables in the system "
							 | 
						|
								          "to be tracked");
							 | 
						|
								
							 | 
						|
								    SuccessCode initialization_code =
							 | 
						|
								        TrackerLoopInitialization(start_time, endtime, start_point);
							 | 
						|
								    if (initialization_code != SuccessCode::Success) {
							 | 
						|
								      PostTrackCleanup();
							 | 
						|
								      return initialization_code;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // as precondition to this while loop, the correct container, either dbl or
							 | 
						|
								    // mpfr, must have the correct data.
							 | 
						|
								    while (!IsSymmRelDiffSmall(current_time_, endtime_,
							 | 
						|
								                               Eigen::NumTraits<CT>::epsilon())) {
							 | 
						|
								      SuccessCode pre_iteration_code = PreIterationCheck();
							 | 
						|
								      if (pre_iteration_code != SuccessCode::Success) {
							 | 
						|
								        PostTrackCleanup();
							 | 
						|
								        return pre_iteration_code;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      using std::abs;
							 | 
						|
								      // compute the next delta_t
							 | 
						|
								      if (abs(endtime_ - current_time_) < abs(current_stepsize_))
							 | 
						|
								        delta_t_ = endtime_ - current_time_;
							 | 
						|
								      else
							 | 
						|
								        delta_t_ = current_stepsize_ * (endtime_ - current_time_) /
							 | 
						|
								                   abs(endtime_ - current_time_);
							 | 
						|
								
							 | 
						|
								      step_success_code_ = TrackerIteration();
							 | 
						|
								
							 | 
						|
								      if (infinite_path_truncation_ &&
							 | 
						|
								          (CheckGoingToInfinity() == SuccessCode::GoingToInfinity)) {
							 | 
						|
								        OnInfiniteTruncation();
							 | 
						|
								        PostTrackCleanup();
							 | 
						|
								        return SuccessCode::GoingToInfinity;
							 | 
						|
								      } else if (step_success_code_ == SuccessCode::Success)
							 | 
						|
								        OnStepSuccess();
							 | 
						|
								      else
							 | 
						|
								        OnStepFail();
							 | 
						|
								
							 | 
						|
								    }  // re: while
							 | 
						|
								
							 | 
						|
								    CopyFinalSolution(solution_at_endtime);
							 | 
						|
								    PostTrackCleanup();
							 | 
						|
								    return SuccessCode::Success;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Refine a point to tolerance implicitly internally set.
							 | 
						|
								
							 | 
						|
								  Runs Newton's method using the current settings for tracking, including the
							 | 
						|
								  min and max number of iterations allowed, the tracking tolerance, precision,
							 | 
						|
								  etc.  YOU must ensure that the input point has the correct precision.
							 | 
						|
								
							 | 
						|
								  \return The SuccessCode indicating whether the refinement completed.
							 | 
						|
								
							 | 
						|
								  \param[out] new_space The result of refinement.
							 | 
						|
								  \param start_point The seed for Newton's method for refinement.
							 | 
						|
								  \param current_time The current time value for refinement.
							 | 
						|
								  */
							 | 
						|
								  template <typename C>
							 | 
						|
								  SuccessCode Refine(Vec<C>& new_space, Vec<C> const& start_point,
							 | 
						|
								                     C const& current_time) const {
							 | 
						|
								    static_assert(
							 | 
						|
								        detail::IsTemplateParameter<C, NeededTypes>::value,
							 | 
						|
								        "complex type for refinement must be a used type for the tracker");
							 | 
						|
								    return this->AsDerived().RefineImpl(new_space, start_point, current_time);
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Refine a point to a given tolerance.
							 | 
						|
								
							 | 
						|
								  Runs Newton's method using the current settings for tracking, including the
							 | 
						|
								  min and max number of iterations allowed, precision, etc, EXCEPT for the
							 | 
						|
								  tracking tolerance and max number of iterations, which you feed in here.  YOU
							 | 
						|
								  must ensure that the input point has the correct precision.
							 | 
						|
								
							 | 
						|
								  \return The SuccessCode indicating whether the refinement completed.
							 | 
						|
								
							 | 
						|
								  \param[out] new_space The result of refinement.
							 | 
						|
								  \param start_point The seed for Newton's method for refinement.
							 | 
						|
								  \param current_time The current time value for refinement.
							 | 
						|
								  \param tolerance The tolerance to which to refine.
							 | 
						|
								  \param max_iterations The maximum number of iterations to use to refine.
							 | 
						|
								  */
							 | 
						|
								  template <typename C>
							 | 
						|
								  SuccessCode Refine(Vec<C>& new_space, Vec<C> const& start_point,
							 | 
						|
								                     C const& current_time, double const& tolerance,
							 | 
						|
								                     unsigned max_iterations) const {
							 | 
						|
								    static_assert(
							 | 
						|
								        detail::IsTemplateParameter<C, NeededTypes>::value,
							 | 
						|
								        "complex type for refinement must be a used type for the tracker");
							 | 
						|
								
							 | 
						|
								    return this->AsDerived().RefineImpl(new_space, start_point, current_time,
							 | 
						|
								                                        tolerance, max_iterations);
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Change tracker to use a predictor
							 | 
						|
								
							 | 
						|
								  \param new_predictor_choice The new predictor to be used.
							 | 
						|
								
							 | 
						|
								  \see Predictor
							 | 
						|
								  */
							 | 
						|
								  void SetPredictor(Predictor new_predictor_choice) {
							 | 
						|
								    predictor_->PredictorMethod(new_predictor_choice);
							 | 
						|
								    predictor_order_ = predictor_->Order();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Query the currently set predictor
							 | 
						|
								  */
							 | 
						|
								  Predictor GetPredictor() const { return predictor_->PredictorMethod(); }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief get a const reference to the system.
							 | 
						|
								  */
							 | 
						|
								  void SetSystem(const System& new_sys) {
							 | 
						|
								    tracked_system_ = std::ref(new_sys);
							 | 
						|
								    predictor_->ChangeSystem(tracked_system_);
							 | 
						|
								    corrector_->ChangeSystem(tracked_system_);
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief get a const reference to the system.
							 | 
						|
								  */
							 | 
						|
								  const System& GetSystem() const { return tracked_system_.get(); }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief See how many steps have been taken.
							 | 
						|
								
							 | 
						|
								  \return The total number of steps taken, including successes and fails.
							 | 
						|
								  */
							 | 
						|
								  unsigned NumTotalStepsTaken() const {
							 | 
						|
								    return num_failed_steps_taken_ + num_successful_steps_taken_;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Set how large the stepsize should be.
							 | 
						|
								
							 | 
						|
								  \param new_stepsize The new value.
							 | 
						|
								  */
							 | 
						|
								  void SetStepSize(RT const& new_stepsize) const {
							 | 
						|
								    current_stepsize_ = new_stepsize;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Switch resetting of initial step size to that of the stepping settings.
							 | 
						|
								
							 | 
						|
								  By default, initial step size is retrieved from the stepping settings at the
							 | 
						|
								  start of each path track.  To turn this off, and re-use the previous step size
							 | 
						|
								  from the previously tracked path, turn off by calling this function with
							 | 
						|
								  false.
							 | 
						|
								  */
							 | 
						|
								  void ReinitializeInitialStepSize(bool should_reinitialize_stepsize) {
							 | 
						|
								    reinitialize_stepsize_ = should_reinitialize_stepsize;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  virtual ~Tracker() = default;
							 | 
						|
								
							 | 
						|
								  auto TrackingTolerance() const { return tracking_tolerance_; }
							 | 
						|
								
							 | 
						|
								  auto InfiniteTruncationTolerance() const {
							 | 
						|
								    return path_truncation_threshold_;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								 private:
							 | 
						|
								  // convert the base tracker into the derived type.
							 | 
						|
								  const D& AsDerived() const { return static_cast<const D&>(*this); }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Set up initialization of the internals for tracking a path.
							 | 
						|
								
							 | 
						|
								  \param start_time The time at which to start tracking.
							 | 
						|
								  \param end_time The time to which to track.
							 | 
						|
								  \param start_point The point from which to start tracking.
							 | 
						|
								  */
							 | 
						|
								  virtual SuccessCode TrackerLoopInitialization(
							 | 
						|
								      CT const& start_time, CT const& end_time,
							 | 
						|
								      Vec<CT> const& start_point) const = 0;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Check internal state for whether tracking should continue.
							 | 
						|
								
							 | 
						|
								  \return Code for whether to go on.  Tracking will terminate if the returned
							 | 
						|
								  value is not Success.
							 | 
						|
								  */
							 | 
						|
								  virtual SuccessCode PreIterationCheck() const = 0;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief A single iteration of the tracker loop.
							 | 
						|
								
							 | 
						|
								  \return Whether the tracker loop was successful or not.  Incrementing of
							 | 
						|
								  counters for the base class happens automatically.
							 | 
						|
								  */
							 | 
						|
								  virtual SuccessCode TrackerIteration() const = 0;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Copy the solution from whatever internal variable it is stored in, into
							 | 
						|
								  the output variable.
							 | 
						|
								
							 | 
						|
								  \param solution_at_endtime The output variable into which to copy the final
							 | 
						|
								  solution.
							 | 
						|
								  */
							 | 
						|
								  virtual void CopyFinalSolution(Vec<CT>& solution_at_endtime) const = 0;
							 | 
						|
								
							 | 
						|
								  // virtual
							 | 
						|
								  // void CopyFinalSolution(Vec<dbl> & solution_at_endtime) const = 0;
							 | 
						|
								
							 | 
						|
								 protected:
							 | 
						|
								  template <typename ComplexType>
							 | 
						|
								  SuccessCode CheckGoingToInfinity() const {
							 | 
						|
								    if (GetSystem()
							 | 
						|
								            .DehomogenizePoint(std::get<Vec<ComplexType> >(current_space_))
							 | 
						|
								            .norm() > path_truncation_threshold_)
							 | 
						|
								      return SuccessCode::GoingToInfinity;
							 | 
						|
								    else
							 | 
						|
								      return SuccessCode::Success;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Function to be called before exiting the tracker loop.
							 | 
						|
								  */
							 | 
						|
								  virtual void PostTrackCleanup() const {}
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Reset counters used during tracking.
							 | 
						|
								
							 | 
						|
								  Your custom tracker type should almost certainly call this function.
							 | 
						|
								  */
							 | 
						|
								  virtual void ResetCounters() const = 0;
							 | 
						|
								
							 | 
						|
								  void ResetCountersBase() const {
							 | 
						|
								    // reset a bunch of counters to 0.
							 | 
						|
								    num_consecutive_successful_steps_ = 0;
							 | 
						|
								    num_successful_steps_taken_ = 0;
							 | 
						|
								    num_failed_steps_taken_ = 0;
							 | 
						|
								    num_consecutive_failed_steps_ = 0;
							 | 
						|
								    num_total_steps_taken_ = 0;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Increment and reset counters after a successful TrackerIteration()
							 | 
						|
								
							 | 
						|
								  Your custom override, if provided, should almost certainly call this function.
							 | 
						|
								  */
							 | 
						|
								  void IncrementBaseCountersSuccess() const {
							 | 
						|
								    num_successful_steps_taken_++;
							 | 
						|
								    num_consecutive_successful_steps_++;
							 | 
						|
								    current_time_ += delta_t_;
							 | 
						|
								    num_consecutive_failed_steps_ = 0;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  virtual void OnStepSuccess() const = 0;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Increment and reset counters after a failed TrackerIteration()
							 | 
						|
								
							 | 
						|
								  Your custom override, if provided, should almost certainly call this function.
							 | 
						|
								  */
							 | 
						|
								  void IncrementBaseCountersFail() const {
							 | 
						|
								    num_consecutive_successful_steps_ = 0;
							 | 
						|
								    num_failed_steps_taken_++;
							 | 
						|
								    num_consecutive_failed_steps_++;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  virtual void OnStepFail() const = 0;
							 | 
						|
								
							 | 
						|
								  /**
							 | 
						|
								  \brief Check whether the path is going to infinity, as it tracks.
							 | 
						|
								
							 | 
						|
								  This check is necessary because a homotopy may be malformed, or may have
							 | 
						|
								  encountered a probability-0 event.  That it is a 0 probability event is why
							 | 
						|
								  this check is disable-able via a toggle.
							 | 
						|
								  */
							 | 
						|
								  virtual SuccessCode CheckGoingToInfinity() const = 0;
							 | 
						|
								
							 | 
						|
								  virtual void OnInfiniteTruncation() const = 0;
							 | 
						|
								
							 | 
						|
								  std::reference_wrapper<const System>
							 | 
						|
								      tracked_system_;  ///< Reference to the system being tracked.
							 | 
						|
								
							 | 
						|
								  bool infinite_path_truncation_ =
							 | 
						|
								      true;  /// Whether should check if the path is going to infinity while
							 | 
						|
								             /// tracking.  On by default.
							 | 
						|
								  bool reinitialize_stepsize_ =
							 | 
						|
								      true;  ///< Whether should re-initialize the stepsize with each call to
							 | 
						|
								             ///< Trackpath.  On by default.
							 | 
						|
								
							 | 
						|
								  // tracking the numbers of things
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_total_steps_taken_;  ///< The number of steps taken, including
							 | 
						|
								                               ///< failures and successes.
							 | 
						|
								  mutable unsigned num_successful_steps_taken_;  ///< The number of successful
							 | 
						|
								                                                 ///< steps taken so far.
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_consecutive_successful_steps_;  ///< The number of CONSECUTIVE
							 | 
						|
								                                          ///< successful steps taken in a row.
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_consecutive_failed_steps_;  ///< The number of CONSECUTIVE failed
							 | 
						|
								                                      ///< steps taken in a row.
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_failed_steps_taken_;  ///< The total number of failed steps taken.
							 | 
						|
								
							 | 
						|
								  // configuration for tracking
							 | 
						|
								  std::shared_ptr<predict::ExplicitRKPredictor>
							 | 
						|
								      predictor_;             // The predictor to use while tracking
							 | 
						|
								  unsigned predictor_order_;  ///< The order of the predictor -- one less than
							 | 
						|
								                              ///< the error estimate order.
							 | 
						|
								
							 | 
						|
								  std::shared_ptr<correct::NewtonCorrector> corrector_;
							 | 
						|
								
							 | 
						|
								  unsigned digits_final_ =
							 | 
						|
								      0;  ///< The number of digits to track to, due to being in endgame zone.
							 | 
						|
								  unsigned digits_tracking_tolerance_ =
							 | 
						|
								      5;  ///< The number of digits required for tracking to given tolerance,
							 | 
						|
								          ///< condition number notwithstanding.
							 | 
						|
								  NumErrorT tracking_tolerance_ = 1e-5;  ///< The tracking tolerance.
							 | 
						|
								  NumErrorT path_truncation_threshold_ =
							 | 
						|
								      1e5;  ///< The threshold for path truncation.
							 | 
						|
								
							 | 
						|
								  mutable CT endtime_;           ///< The time we are tracking to.
							 | 
						|
								  mutable CT current_time_;      ///< The current time.
							 | 
						|
								  mutable CT delta_t_;           ///< The current delta_t.
							 | 
						|
								  mutable RT current_stepsize_;  ///< The current stepsize.
							 | 
						|
								
							 | 
						|
								  // permanent temporaries
							 | 
						|
								  mutable RT next_stepsize_;               /// The next stepsize
							 | 
						|
								  mutable SuccessCode step_success_code_;  ///< The code for step success.
							 | 
						|
								
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_steps_since_last_condition_number_computation_;  ///< How many steps
							 | 
						|
								                                                           ///< have passed
							 | 
						|
								                                                           ///< since the most
							 | 
						|
								                                                           ///< recent condition
							 | 
						|
								                                                           ///< number estimate.
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_successful_steps_since_stepsize_increase_;  ///< How many successful
							 | 
						|
								                                                      ///< steps have been taken
							 | 
						|
								                                                      ///< since increased
							 | 
						|
								                                                      ///< stepsize.
							 | 
						|
								  mutable unsigned
							 | 
						|
								      num_successful_steps_since_precision_decrease_;  ///< The number of
							 | 
						|
								                                                       ///< successful steps
							 | 
						|
								                                                       ///< since decreased
							 | 
						|
								                                                       ///< precision.
							 | 
						|
								
							 | 
						|
								  using TupOfVec = typename NeededTypes::ToTupleOfVec;
							 | 
						|
								  using TupOfReal = typename NeededTypes::ToTupleOfReal;
							 | 
						|
								
							 | 
						|
								  mutable TupOfVec current_space_;  ///< The current space value.
							 | 
						|
								  mutable TupOfVec
							 | 
						|
								      tentative_space_;  ///< After correction, the tentative next space value
							 | 
						|
								  mutable TupOfVec
							 | 
						|
								      temporary_space_;  ///< After prediction, the tentative next space value.
							 | 
						|
								
							 | 
						|
								  mutable NumErrorT
							 | 
						|
								      condition_number_estimate_;  ///< An estimate on the condition number of
							 | 
						|
								                                   ///< the Jacobian
							 | 
						|
								  mutable NumErrorT error_estimate_;  ///< An estimate on the error of a step.
							 | 
						|
								  mutable NumErrorT norm_J_;  ///< An estimate on the norm of the Jacobian
							 | 
						|
								  mutable NumErrorT norm_J_inverse_;  ///< An estimate on the norm of the
							 | 
						|
								                                      ///< inverse of the Jacobian
							 | 
						|
								  mutable NumErrorT norm_delta_z_;    ///< The norm of the change in space
							 | 
						|
								                                      ///< resulting from a step.
							 | 
						|
								  mutable NumErrorT
							 | 
						|
								      size_proportion_;  ///< The proportion of the space step size, taking into
							 | 
						|
								                         ///< account the order of the predictor.
							 | 
						|
								
							 | 
						|
								 public:
							 | 
						|
								  NumErrorT LatestConditionNumber() const {
							 | 
						|
								    return this->condition_number_estimate_;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  NumErrorT LatestErrorEstimate() const { return this->error_estimate_; }
							 | 
						|
								
							 | 
						|
								  NumErrorT LatestNormOfStep() const { return this->norm_delta_z_; }
							 | 
						|
								
							 | 
						|
								  void SetInfiniteTruncation(bool b) { infinite_path_truncation_ = b; }
							 | 
						|
								
							 | 
						|
								  auto InfiniteTruncation() { return infinite_path_truncation_; }
							 | 
						|
								
							 | 
						|
								  unsigned NumVariables() const { return GetSystem().NumVariables(); }
							 | 
						|
								
							 | 
						|
								  auto CurrentTime() const { return current_time_; }
							 | 
						|
								
							 | 
						|
								  auto DeltaT() const { return delta_t_; }
							 | 
						|
								
							 | 
						|
								  auto CurrentStepsize() const { return current_stepsize_; }
							 | 
						|
								
							 | 
						|
								  virtual Vec<CT> CurrentPoint() const = 0;
							 | 
						|
								
							 | 
						|
								  virtual unsigned CurrentPrecision() const = 0;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								}  // namespace tracking
							 | 
						|
								}  // namespace bertini
							 | 
						|
								
							 | 
						|
								#endif
							 | 
						|
								
							 |