mcpele
1.0.0
The Monte Carlo Python Energy Landscape Explorer
|
00001 #ifndef _PELE_CELL_LIST_POTENTIAL_H 00002 #define _PELE_CELL_LIST_POTENTIAL_H 00003 00004 #include <iostream> 00005 #include <memory> 00006 #include <vector> 00007 #include <utility> 00008 #include <stdexcept> 00009 00010 #include "base_potential.h" 00011 #include "array.h" 00012 #include "distance.h" 00013 #include "neighbor_iterator.h" 00014 00015 namespace pele{ 00016 00023 template <typename pairwise_interaction, typename distance_policy, typename pair_iterator> 00024 class PairIteratorPotential : public BasePotential { 00025 protected: 00026 const static size_t m_ndim = distance_policy::_ndim; 00027 std::shared_ptr<pairwise_interaction> m_interaction; 00028 std::shared_ptr<distance_policy> m_dist; 00029 std::shared_ptr<pair_iterator > m_pair_iter; 00030 public: 00031 virtual ~PairIteratorPotential() {} 00032 PairIteratorPotential(std::shared_ptr<pairwise_interaction> interaction, 00033 std::shared_ptr<distance_policy> dist, 00034 std::shared_ptr<pair_iterator> pair_iter) 00035 : m_interaction(interaction), 00036 m_dist(dist), 00037 m_pair_iter(pair_iter) 00038 {} 00039 00040 virtual double get_energy(Array<double> xa) 00041 { 00042 refresh_iterator(xa); 00043 const double* x = xa.data(); 00044 double result = 0; 00045 for (auto ijpair = m_pair_iter->begin(); ijpair != m_pair_iter->end(); ++ijpair) { 00046 const size_t i = ijpair->first; 00047 const size_t j = ijpair->second; 00048 const size_t xi_off = m_ndim * i; 00049 const size_t xj_off = m_ndim * j; 00050 double dr[m_ndim]; 00051 m_dist->get_rij(dr, x + xi_off, x + xj_off); 00052 double r2 = 0; 00053 for (size_t k = 0; k < m_ndim; ++k) { 00054 r2 += dr[k] * dr[k]; 00055 } 00056 result += m_interaction->energy(r2, i, j); 00057 } 00058 return result; 00059 } 00060 00061 virtual double get_energy_gradient(Array<double> xa, Array<double> grad) 00062 { 00063 refresh_iterator(xa); 00064 const double* x = xa.data(); 00065 double result = 0; 00066 grad.assign(double(0)); 00067 if (xa.size() != grad.size()) { 00068 throw std::runtime_error("CellListPotential::get_energy_gradient: illegal input"); 00069 } 00070 for (auto ijpair = m_pair_iter->begin(); ijpair != m_pair_iter->end(); ++ijpair) { 00071 const size_t i = ijpair->first; 00072 const size_t j = ijpair->second; 00073 const size_t xi_off = m_ndim * i; 00074 const size_t xj_off = m_ndim * j; 00075 double dr[m_ndim]; 00076 m_dist->get_rij(dr, x + xi_off, x + xj_off); 00077 double r2 = 0; 00078 for (size_t k = 0; k < m_ndim; ++k) { 00079 r2 += dr[k] * dr[k]; 00080 } 00081 double gij; 00082 result += m_interaction->energy_gradient(r2, &gij, i, j); 00083 for (size_t k = 0; k < m_ndim; ++k) { 00084 grad[xi_off + k] -= gij * dr[k]; 00085 } 00086 for (size_t k = 0; k < m_ndim; ++k) { 00087 grad[xj_off + k] += gij * dr[k]; 00088 } 00089 } 00090 return result; 00091 } 00092 00093 virtual double get_energy_gradient_hessian(Array<double> xa, 00094 Array<double> grad, Array<double> hess) 00095 { 00096 if (xa.size() != grad.size()) { 00097 throw std::runtime_error("CellListPotential::get_energy_gradient_hessian: illegal input grad"); 00098 } 00099 if (hess.size() != xa.size() * xa.size()) { 00100 throw std::runtime_error("CellListPotential::get_energy_gradient_hessian: illegal input hess"); 00101 } 00102 refresh_iterator(xa); 00103 const double* x = xa.data(); 00104 double result = 0; 00105 grad.assign(double(0)); 00106 hess.assign(double(0)); 00107 for (auto ijpair = m_pair_iter->begin(); ijpair != m_pair_iter->end(); ++ijpair) { 00108 const size_t i = ijpair->first; 00109 const size_t j = ijpair->second; 00110 const size_t xi_off = m_ndim * i; 00111 const size_t xj_off = m_ndim * j; 00112 double dr[m_ndim]; 00113 m_dist->get_rij(dr, x + xi_off, x + xj_off); 00114 double r2 = 0; 00115 for (size_t k = 0; k < m_ndim; ++k) { 00116 r2 += dr[k] * dr[k]; 00117 } 00118 double gij, hij; 00119 result += m_interaction->energy_gradient_hessian(r2, &gij, &hij, i, j); 00120 for (size_t k = 0; k < m_ndim; ++k) { 00121 grad[xi_off + k] -= gij * dr[k]; 00122 } 00123 for (size_t k = 0; k < m_ndim; ++k) { 00124 grad[xj_off + k] += gij * dr[k]; 00125 } 00126 //this part is copied from simple_pairwise_potential.h 00127 //(even more so than the rest) 00128 const size_t N = xa.size(); 00129 const size_t i1 = xi_off; 00130 const size_t j1 = xj_off; 00131 for (size_t k = 0; k < m_ndim; ++k) { 00132 //diagonal block - diagonal terms 00133 const double Hii_diag = (hij + gij) * dr[k] * dr[k] / r2 - gij; 00134 hess[N * (i1 + k) + i1 + k] += Hii_diag; 00135 hess[N * (j1 + k) + j1 + k] += Hii_diag; 00136 //off diagonal block - diagonal terms 00137 const double Hij_diag = -Hii_diag; 00138 hess[N * (i1 + k) + j1 + k] = Hij_diag; 00139 hess[N * (j1 + k) + i1 + k] = Hij_diag; 00140 for (size_t l = k + 1; l < m_ndim; ++l) { 00141 //diagonal block - off diagonal terms 00142 const double Hii_off = (hij + gij) * dr[k] * dr[l] / r2; 00143 hess[N * (i1 + k) + i1 + l] += Hii_off; 00144 hess[N * (i1 + l) + i1 + k] += Hii_off; 00145 hess[N * (j1 + k) + j1 + l] += Hii_off; 00146 hess[N * (j1 + l) + j1 + k] += Hii_off; 00147 //off diagonal block - off diagonal terms 00148 const double Hij_off = -Hii_off; 00149 hess[N * (i1 + k) + j1 + l] = Hij_off; 00150 hess[N * (i1 + l) + j1 + k] = Hij_off; 00151 hess[N * (j1 + k) + i1 + l] = Hij_off; 00152 hess[N * (j1 + l) + i1 + k] = Hij_off; 00153 } 00154 } 00155 } 00156 return result; 00157 } 00158 protected: 00159 void refresh_iterator(Array<double> x) 00160 { 00161 m_pair_iter->reset(x); 00162 } 00163 }; //class CellListPotential 00164 00171 template <typename pairwise_interaction, typename distance_policy> 00172 class CellListPotential : public PairIteratorPotential<pairwise_interaction, 00173 distance_policy, CellIter<distance_policy> > { 00174 public: 00175 CellListPotential(std::shared_ptr<pairwise_interaction> interaction, 00176 std::shared_ptr<distance_policy> dist, 00177 pele::Array<double> boxv, 00178 double rcut, double ncellx_scale) 00179 : PairIteratorPotential<pairwise_interaction, distance_policy, CellIter<distance_policy> > ( 00180 interaction, dist, 00181 std::make_shared<CellIter<distance_policy> >(dist, boxv, rcut, ncellx_scale)) 00182 {} 00183 virtual ~CellListPotential() {} 00184 }; 00185 00186 //template <typename pairwise_interaction, typename distance_policy> 00187 //class CellListPotential : public PairIteratorPotential<pairwise_interaction, 00188 // distance_policy, CellIter<distance_policy> > { 00189 //public: 00190 // CellListPotential(std::shared_ptr<pairwise_interaction> interaction, 00191 // std::shared_ptr<distance_policy> dist, 00192 // std::shared_ptr<CellIter<distance_policy> > pair_iterator) 00193 // : PairIteratorPotential<pairwise_interaction, 00194 // distance_policy, CellIter<distance_policy> > (interaction, dist, pair_iterator) 00195 // {} 00196 // virtual ~CellListPotential() {} 00197 //}; 00198 00199 00200 } //namespace pele 00201 00202 #endif //#ifndef _PELE_CELL_LIST_POTENTIAL_H