Program Listing for File extended_mixed_descent.hpp#

↰ Return to documentation for file (source/pele/extended_mixed_descent.hpp)

#ifndef _PELE_EXTENDED_MIXED_DESCENT_H__
#define _PELE_EXTENDED_MIXED_DESCENT_H__

#include "array.hpp"
#include "base_potential.hpp"
#include "preprocessor_directives.hpp"

// #define EIGEN_USE_MKL_ALL
// Eigen linear algebra library
#include <Eigen/Dense>
#include <array>
#include <fstream>
#include <memory>
#include <sundials/sundials_context.h>

#include "eigen_interface.hpp"
#include "pele/combine_potentials.hpp"
#include "pele/lbfgs.hpp"

// Lapack for cholesky
extern "C" {
#include <lapack.h>
}

// line search methods
#include <cvode/cvode.h>               /* access to CVODE                 */
#include <nvector/nvector_serial.h>    /* access to serial N_Vector       */
#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver */
#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix       */

#include "backtracking.hpp"
#include "bracketing.hpp"
#include "cvode.hpp"
#include "linesearch.hpp"
#include "more_thuente.hpp"
#include "nwpele.hpp"
#include "optimizer.hpp"

extern "C" {
#include "xsum.h"
}

namespace pele {

class ExtendedMixedOptimizer : public GradientOptimizer {
 private:
  UserData_ udata;
  void *cvode_mem; /* CVODE memory         */
  size_t N_size;
  SUNMatrix A;
  SUNLinearSolver LS;
  SUNContext sunctx;
  double t0;
  double tN;
  N_Vector x0_N;
  double rtol;
  double atol;

  // return val from CVODE
  int retval;
  // instatiate if you want to print to file
#if PRINT_TO_FILE == 1
  std::ofstream trajectory_file;
  std::ofstream hessian_eigvals_file;
#endif
  std::shared_ptr<pele::ExtendedPotential> extended_potential;

  Array<double> xold;
  Array<double> gold;
  Array<double> step;

  Array<double> xold_old;

  Array<double> x_last_cvode;

  double inv_sqrt_size;
  // Preconditioning
  int T_;  // number of steps after which the lowest eigenvalues are
           // recalculated in the first phase
  // std::shared_ptr<Eigen::ColPivHouseholderQR<Eigen::MatrixXd>> solver;
  // solver for H x = b
  Eigen::VectorXd update_solver(
      Eigen::VectorXd r);  // updates the solver with the new hessian
  char uplo;               /* We ask LAPACK for the lower diagonal matrix L */
  int info;                /* "Info" return value, used for error-checking */

  // Calculates hess + delta I where delta makes the new eigenvalue positive
  Eigen::MatrixXd hessian;
  Eigen::MatrixXd hessian_copy_for_cholesky;

  double *hess_data;
  bool use_phase_1;
  bool phase_2_failed_;  // if true, we've failed in phase 2 and need to revert
                         // back to where we were in phase 1
  // what phase was used in previous step
  bool prev_phase_is_phase1;
  size_t n_phase_1_steps;
  size_t n_phase_2_steps;

  size_t n_failed_phase_2_steps;

  double conv_tol_;
  // Need to refactor line searches
  BacktrackingLineSearch line_search_method;

  bool iterative_;  // if true, use iterative solver for hessian solve
  HessianType hessian_type_;

  const Array<double>
      m_global_symmetry_offset;  // global symmetry offset for hessian
                                 // to account for numerical issues with
                                 // cholesky finding negative eigenvalues
                                 // If size zero defaults to using 2d
                                 // translational symmetries to maintain
                                 // backwards compatibility TODO: deprecate
                                 // this default

 public:
  ExtendedMixedOptimizer(
      std::shared_ptr<pele::BasePotential> potential,
      const pele::Array<double> x0,
      std::shared_ptr<pele::BasePotential> potential_extension = nullptr,
      double tol = 1e-4, int T = 10, double step = 1, double conv_tol = 1e-8,
      double rtol = 1e-5, double atol = 1e-5, bool iterative = false,
      Array<double> global_symmetry_offset = Array<double>(0),
      bool save_trajectory = false, int iterations_before_save = 1,
      StopCriterionType stop_criterion = StopCriterionType::GRADIENT);
  virtual ~ExtendedMixedOptimizer();

  void free_cvode_objects();

  void one_iteration();

  // functions for accessing the results

  void reset(pele::Array<double> &x0);

  void reset_cvode();

  void reset_newton();

  inline int get_nhev() const { return udata.nhev; }
  inline int get_nhev_extended() const {
    return extended_potential->get_nhev_extension();
  }
  inline int get_n_phase_1_steps() { return n_phase_1_steps; }
  inline int get_n_phase_2_steps() { return n_phase_2_steps; }
  inline int get_n_failed_phase_2_steps() { return n_failed_phase_2_steps; }

 private:
  bool hessian_calculated;  // checks whether the hessian has been calculated
                            // for updating.
  void compute_phase_1_step();
  void compute_phase_2_step();
  bool convexity_check();
  void get_hess(Eigen::MatrixXd &hess);
  void get_hess_extended(Eigen::MatrixXd &hess);
  void setup_cvode();

  void update_H0_(Array<double> x_old, Array<double> &g_old,
                  Array<double> x_new, Array<double> &g_new);
};

}  // namespace pele

#endif  // _PELE_EXTENDED_MIXED_DESCENT_H__