pele
Python energy landscape explorer
/home/js850/projects/pele/source/pele/simple_pairwise_ilist.h
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
 All Classes Namespaces Functions Variables Typedefs