mcpele
1.0.0
The Monte Carlo Python Energy Landscape Explorer
|
00001 #ifndef _PELE_HARMONIC_H 00002 #define _PELE_HARMONIC_H 00003 00004 #include "base_potential.h" 00005 #include "distance.h" 00006 #include "atomlist_potential.h" 00007 #include "simple_pairwise_ilist.h" 00008 #include <algorithm> 00009 #include <functional> 00010 00011 namespace pele { 00012 00013 class BaseHarmonic : public BasePotential { 00014 protected: 00015 virtual void _get_distance(const pele::Array<double>& x)=0; 00016 pele::Array<double> _origin, _distance; 00017 double _k; 00018 size_t _ndim, _nparticles; 00019 BaseHarmonic(pele::Array<double> origin, double k, size_t ndim) 00020 : _origin(origin.copy()), _distance(origin.size()), 00021 _k(k), _ndim(ndim), _nparticles(origin.size()/_ndim) 00022 {} 00023 00024 public: 00025 virtual ~BaseHarmonic(){} 00026 virtual double inline get_energy(pele::Array<double> x); 00027 virtual double inline get_energy_gradient(pele::Array<double> x, pele::Array<double> grad); 00028 void set_k(double newk) {_k = newk;}; 00029 double get_k() {return _k;}; 00030 }; 00031 00032 00033 /* calculate energy from distance squared, r0 is the hard core distance, r is the distance between the centres */ 00034 double inline BaseHarmonic::get_energy(pele::Array<double> x) 00035 { 00036 double norm2 = 0; 00037 this->_get_distance(x); 00038 for(size_t i=0;i<x.size();++i) 00039 norm2 += _distance[i]*_distance[i]; 00040 return 0.5 * _k * norm2; 00041 } 00042 00043 /* calculate energy and gradient from distance squared, gradient is in g/|rij|, r0 is the hard core distance, r is the distance between the centres */ 00044 double inline BaseHarmonic::get_energy_gradient(pele::Array<double> x, pele::Array<double> grad) 00045 { 00046 assert(grad.size() == _origin.size()); 00047 double norm2 = 0; 00048 this->_get_distance(x); 00049 for(size_t i=0;i<x.size();++i){ 00050 norm2 += _distance[i]*_distance[i]; 00051 grad[i] = _k * _distance[i]; 00052 } 00053 return 0.5 * _k * norm2; 00054 } 00055 00059 class Harmonic : public BaseHarmonic{ 00060 public: 00061 Harmonic(pele::Array<double> origin, double k, size_t ndim) 00062 : BaseHarmonic(origin, k, ndim) 00063 {} 00064 00065 virtual void inline _get_distance(const pele::Array<double>& x) 00066 { 00067 assert(x.size() == _origin.size()); 00068 for(size_t i=0;i<x.size();++i) 00069 { 00070 _distance[i] = x[i] - _origin[i];; 00071 } 00072 } 00073 }; 00074 00078 class HarmonicCOM : public BaseHarmonic{ 00079 public: 00080 HarmonicCOM(pele::Array<double> origin, double k, size_t ndim) 00081 : BaseHarmonic(origin, k, ndim) 00082 {} 00083 00084 virtual void inline _get_distance(const pele::Array<double>& x) 00085 { 00086 assert(x.size() == _origin.size()); 00087 pele::Array<double> delta_com(_ndim,0); 00088 00089 for(size_t i=0;i<_nparticles;++i) 00090 { 00091 size_t i1 = i*_ndim; 00092 for(size_t j=0;j<_ndim;++j){ 00093 double d = x[i1+j] - _origin[i1+j]; 00094 _distance[i1+j] = d; 00095 delta_com[j] += d; 00096 } 00097 } 00098 00099 delta_com /= _nparticles; 00100 00101 for(size_t i=0;i<_nparticles;++i) 00102 { 00103 size_t i1 = i*_ndim; 00104 for(size_t j=0;j<_ndim;++j) 00105 _distance[i1+j] -= delta_com[j]; 00106 } 00107 } 00108 }; 00109 00110 00111 /* 00112 * redo the harmonic potential in the pair potential framework 00113 */ 00114 00115 struct harmonic_interaction { 00116 double const m_k; 00117 harmonic_interaction(double k) 00118 : m_k(k) 00119 {} 00120 00121 /* calculate energy from distance squared */ 00122 double inline energy(double r2, size_t atom_i, size_t atom_j) const 00123 { 00124 return 0.5 * m_k * r2; 00125 } 00126 00127 /* calculate energy and gradient from distance squared, gradient is in g/|rij| */ 00128 double inline energy_gradient(double r2, double *gij, size_t atom_i, size_t atom_j) const 00129 { 00130 *gij = -m_k; 00131 return 0.5 * m_k * r2; 00132 } 00133 00134 double inline energy_gradient_hessian(double r2, double *gij, double *hij, 00135 size_t atom_i, size_t atom_j) const 00136 { 00137 *gij = -m_k; 00138 *hij = 1.; 00139 return 0.5 * m_k * r2; 00140 } 00141 }; 00142 00146 class HarmonicAtomList : public AtomListPotential<harmonic_interaction, cartesian_distance<3>> { 00147 public: 00148 HarmonicAtomList(double k, Array<size_t> atoms1, Array<size_t> atoms2) 00149 : AtomListPotential<harmonic_interaction, cartesian_distance<3>>( 00150 std::make_shared<harmonic_interaction>(k), 00151 std::make_shared<cartesian_distance<3>>(), atoms1, atoms2) 00152 {} 00153 00154 HarmonicAtomList(double k, Array<size_t> atoms1) 00155 : AtomListPotential<harmonic_interaction, cartesian_distance<3>>( 00156 std::make_shared<harmonic_interaction>(k), 00157 std::make_shared<cartesian_distance<3>>(), atoms1) 00158 {} 00159 }; 00160 00164 class HarmonicNeighborList : public SimplePairwiseNeighborList<harmonic_interaction> { 00165 public: 00166 HarmonicNeighborList(double k, Array<size_t> ilist) 00167 : SimplePairwiseNeighborList<harmonic_interaction>( 00168 std::make_shared<harmonic_interaction>(k), ilist) 00169 {} 00170 }; 00171 00172 } 00173 #endif