pele
Python energy landscape explorer
/home/js850/projects/pele/source/pele/base_potential.h
00001 #ifndef PYGMIN_POTENTIAL_H
00002 #define PYGMIN_POTENTIAL_H
00003 
00004 #include <assert.h>
00005 #include <vector>
00006 #include <stdexcept>
00007 #include <iostream>
00008 #include "array.h"
00009 
00010 namespace pele {
00011 
00012 /***
00013  * basic potential interface for native potentials
00014  */
00015 class BasePotential {
00016 public:
00017     virtual ~BasePotential() {}
00018 
00023     virtual double get_energy(Array<double> x)
00024     {
00025         throw std::runtime_error("BasePotential::get_energy must be overloaded");
00026     }
00027 
00031     virtual double add_energy_gradient(Array<double> x, Array<double> grad)
00032     {
00033         throw std::runtime_error("BasePotential::add_energy_gradient must be overloaded");
00034     }
00035 
00041     virtual double get_energy_gradient(Array<double> x, Array<double> grad)
00042     {
00043         double energy = get_energy(x);
00044         numerical_gradient(x, grad);
00045         return energy;
00046     }
00047 
00048 
00052     virtual double add_energy_gradient_hessian(Array<double> x, Array<double> grad,
00053             Array<double> hess)
00054     {
00055         throw std::runtime_error("BasePotential::add_energy_gradient_hessian must be overloaded");
00056     }
00057 
00064     virtual double get_energy_gradient_hessian(Array<double> x, Array<double> grad,
00065             Array<double> hess)
00066     {
00067         double energy = get_energy_gradient(x, grad);
00068         numerical_hessian(x, hess);
00069         return energy;
00070     }
00071 
00075     virtual void numerical_gradient(Array<double> x, Array<double> grad, double eps=1e-6)
00076     {
00077         if (x.size() != grad.size()) {
00078             throw std::invalid_argument("grad.size() be the same as x.size()");
00079         }
00080 
00081         Array<double> xnew(x.copy());
00082         for (size_t i=0; i<xnew.size(); ++i){
00083             xnew[i] -= eps;
00084             double eminus = get_energy(xnew);
00085             xnew[i] += 2. * eps;
00086             double eplus = get_energy(xnew);
00087             grad[i] = (eplus - eminus) / (2. * eps);
00088             xnew[i] = x[i];
00089         }
00090     }
00091 
00097     virtual void get_hessian(Array<double> x, Array<double> hess)
00098     {
00099         Array<double> grad(x.size());
00100         get_energy_gradient_hessian(x, grad, hess);
00101     }
00102 
00106     virtual void numerical_hessian(Array<double> x, Array<double> hess, double eps=1e-6)
00107     {
00108         if (hess.size() != x.size()*x.size()) {
00109             throw std::invalid_argument("hess.size() be the same as x.size()*x.size()");
00110         }
00111         size_t const N = x.size();
00112 
00113         Array<double> gplus(x.size());
00114         Array<double> gminus(x.size());
00115 
00116         for (size_t i=0; i<x.size(); ++i){
00117             double xbackup = x[i];
00118             x[i] -= eps;
00119             get_energy_gradient(x, gminus);
00120             x[i] += 2. * eps;
00121             get_energy_gradient(x, gplus);
00122             x[i] = xbackup;
00123 
00124             for (size_t j=0; j<x.size(); ++j){
00125                 hess[N*i + j] = (gplus[j] - gminus[j]) / (2.*eps);
00126             }
00127         }
00128         /*//print hessian
00129         std::cout<<""<<std::endl;
00130         std::cout<<""<<std::endl;
00131         for (size_t i=0; i<hess.size(); ++i){
00132             std::cout<<hess[i]<<" ";
00133             int j = i+1;
00134             if (j % (int) (3*sqrt(hess.size())) == 0)
00135                 std::cout<<"\n"<<std::endl;
00136             else if (j % (int) sqrt(hess.size()) == 0)
00137                 std::cout<<""<<std::endl;
00138             else if (j % 3 == 0){
00139                 std::cout<<"  ";
00140             }
00141         }*/
00142     }
00143 
00144 };
00145 }
00146 
00147 #endif
 All Classes Namespaces Functions Variables Typedefs