mcpele
1.0.0
The Monte Carlo Python Energy Landscape Explorer
|
00001 #ifndef PYGMIN_SIMPLE_PAIRWISE_ILIST_H 00002 #define PYGMIN_SIMPLE_PAIRWISE_ILIST_H 00003 00004 #include <assert.h> 00005 #include <vector> 00006 #include "base_potential.h" 00007 #include "array.h" 00008 #include "distance.h" 00009 #include <iostream> 00010 #include <memory> 00011 00012 namespace pele 00013 { 00020 template<typename pairwise_interaction, typename distance_policy=cartesian_distance<3> > 00021 class SimplePairwiseNeighborList : public BasePotential 00022 { 00023 protected: 00024 std::shared_ptr<pairwise_interaction> _interaction; 00025 std::shared_ptr<distance_policy> _dist; 00026 std::vector<size_t> const _neighbor_list; 00027 static const size_t _ndim = distance_policy::_ndim; 00028 00029 SimplePairwiseNeighborList(std::shared_ptr<pairwise_interaction> interaction, 00030 Array<size_t> const & neighbor_list, std::shared_ptr<distance_policy> dist=NULL ) 00031 : _interaction(interaction), 00032 _dist(dist), 00033 _neighbor_list(neighbor_list.begin(), neighbor_list.end()) 00034 { 00035 if(_dist == NULL) _dist = std::make_shared<distance_policy>(); 00036 } 00037 00038 public: 00039 virtual ~SimplePairwiseNeighborList() {} 00040 00041 virtual double get_energy(Array<double> x); 00042 virtual double get_energy_gradient(Array<double> x, Array<double> grad) 00043 { 00044 grad.assign(0); 00045 return add_energy_gradient(x, grad); 00046 } 00047 // virtual double get_energy_gradient_hessian(Array<double> x, Array<double> grad, Array<double> hess) 00048 // { 00049 // grad.assign(0); 00050 // hess.assign(0); 00051 // return add_energy_gradient_hessian(x, grad, hess); 00052 // } 00053 virtual double add_energy_gradient(Array<double> x, Array<double> grad); 00054 // virtual double add_energy_gradient_hessian(Array<double> x, Array<double> grad, Array<double> hess); 00055 }; 00056 00057 template<typename pairwise_interaction, typename distance_policy> 00058 inline double SimplePairwiseNeighborList<pairwise_interaction, 00059 distance_policy>::add_energy_gradient(Array<double> x, Array<double> grad) 00060 { 00061 double e=0.; 00062 double gij, dr[_ndim]; 00063 const size_t nlist = _neighbor_list.size(); 00064 assert(x.size() == grad.size()); 00065 00066 // grad.assign(0.); 00067 00068 #ifndef NDEBUG 00069 const size_t natoms = x.size()/_ndim; 00070 for (size_t i=0; i<nlist; ++i) { 00071 assert(_neighbor_list[i] < natoms); 00072 } 00073 #endif 00074 00075 for (size_t i=0; i<nlist; i+=2) { 00076 size_t atom1 = _neighbor_list[i]; 00077 size_t atom2 = _neighbor_list[i+1]; 00078 size_t i1 = _ndim * atom1; 00079 size_t i2 = _ndim * atom2; 00080 00081 for (size_t k=0; k<_ndim; ++k) { 00082 dr[k] = x[i1+k] - x[i2+k]; 00083 } 00084 00085 double r2 = 0; 00086 for (size_t k=0;k<_ndim;++k) { 00087 r2 += dr[k]*dr[k]; 00088 } 00089 00090 e += _interaction->energy_gradient(r2, &gij, atom1, atom2); 00091 for (size_t k=0; k<_ndim; ++k) { 00092 grad[i1+k] -= gij * dr[k]; 00093 } 00094 for (size_t k=0; k<_ndim; ++k) { 00095 grad[i2+k] += gij * dr[k]; 00096 } 00097 } 00098 00099 return e; 00100 } 00101 00102 template<typename pairwise_interaction, typename distance_policy> 00103 inline double SimplePairwiseNeighborList<pairwise_interaction, 00104 distance_policy>::get_energy(Array<double> x) 00105 { 00106 double e=0.; 00107 size_t const nlist = _neighbor_list.size(); 00108 00109 for (size_t i=0; i<nlist; i+=2) { 00110 size_t atom1 = _neighbor_list[i]; 00111 size_t atom2 = _neighbor_list[i+1]; 00112 size_t i1 = _ndim * atom1; 00113 size_t i2 = _ndim * atom2; 00114 double dr[_ndim]; 00115 for (size_t k=0; k<_ndim; ++k) { 00116 dr[k] = x[i1+k] - x[i2+k]; 00117 } 00118 double r2 = 0; 00119 for (size_t k=0;k<_ndim;++k) { 00120 r2 += dr[k]*dr[k]; 00121 } 00122 e += _interaction->energy(r2, atom1, atom2); 00123 } 00124 00125 return e; 00126 } 00127 } 00128 00129 #endif