mcpele  1.0.0
The Monte Carlo Python Energy Landscape Explorer
/home/sm958/Work/pele/source/pele/cell_list_potential.h
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
 All Classes Namespaces Functions Variables Typedefs