pele
Python energy landscape explorer
|
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