pele
Python energy landscape explorer
/home/js850/projects/pele/source/pele/lowest_eig_potential.h
00001 #ifndef _PELE_LOWEST_EIG_POTENTIAL_H
00002 #define _PELE_LOWEST_EIG_POTENTIAL_H
00003 
00004 #include "base_potential.h"
00005 #include "array.h"
00006 #include <algorithm>
00007 #include <vector>
00008 #include <cmath>
00009 #include <memory>
00010 
00011 namespace pele {
00012 
00013 inline void zero_modes_translational(std::vector<pele::Array<double> > & zev,
00014         size_t natoms, size_t bdim)
00015 {
00016     double v = 1 / sqrt(natoms);
00017     size_t N = natoms * bdim;
00018     for(size_t i=0; i<bdim; ++i) {
00019         pele::Array<double> evec(N, 0); //initialize array of zeros
00020         for(size_t j=i; j<N; j+=bdim) {
00021             evec[j] = v;
00022         }
00023         zev.push_back(evec);
00024     }
00025 }
00026 
00027 class Orthogonalize{
00028 public:
00029     virtual ~Orthogonalize(){};
00030     virtual void orthogonalize(Array<double>& coords, Array<double>& vector) =0;
00031 };
00032 
00033 class OrthogonalizeTranslational : public Orthogonalize{
00034 protected:
00035     std::vector<pele::Array<double>> _tr_evec;
00036     size_t _natoms, _bdim, _ndim;
00037     double _d, _tol;
00038 public:
00039 
00040     //OrthogonalizeTranslational(size_t natoms, size_t bdim, double tol=1e-6);
00041     OrthogonalizeTranslational(size_t natoms, size_t bdim, double tol=1e-6)
00042         : _natoms(natoms), _bdim(bdim), _ndim(bdim*natoms), _tol(tol)
00043     {
00044         /*initialize translational eigenvectors to canonical orthonormal basis*/
00045         zero_modes_translational(_tr_evec, _natoms, _bdim);
00046     }
00047 
00048     virtual ~OrthogonalizeTranslational() {}
00049 
00050     //virtual inline void orthogonalize(Array<double>& coords, Array<double>& vector);
00051     virtual inline void orthogonalize(Array<double>& coords, Array<double>& vector)
00052     {
00053         bool success = true;
00054         pele::Array<double> dot_prod(_bdim);
00055         vector /= norm(vector);
00056         //generally in this loop success will be set to false
00057         for (size_t i=0; i<_bdim;++i) {
00058           dot_prod[i] = dot(_tr_evec[i],vector);
00059           if(std::abs(dot_prod[i]) > _tol){success = false;};
00060         }
00061 
00062         while (success == false) {
00063             success = true;
00064             for (size_t i=0; i<_bdim;++i) {
00065                 for(size_t j=0;j<_ndim;++j) {
00066                     vector[j] -= dot_prod[i]*_tr_evec[i][j];
00067                 }
00068             }
00069             vector /= norm(vector);
00070             for (size_t i=0; i<_bdim;++i) {
00071                 dot_prod[i] = dot(_tr_evec[i],vector);
00072                 if (std::abs(dot_prod[i]) > _tol) {
00073                     success = false;
00074                 };
00075             }
00076         }
00077     }
00078 
00079 }; //class OrthogonalizeTranslational
00080 
00081 /*
00082  * Lowest Eigenvalue Potential:
00083  * gd = g(x+d)
00084  * _v: normal unit vector in arbitrary direction
00085  * _d: finite difference step
00086  * */
00087 
00088 class LowestEigPotential : public BasePotential {
00089 protected:
00090     std::shared_ptr<pele::BasePotential> _potential;
00091     pele::Array<double> _coords, _coordsd, _g, _gd;
00092     size_t _bdim, _natoms;
00093     double _d;
00094     OrthogonalizeTranslational _orthog;
00095 public:
00096 
00097     //LowestEigPotential(std::shared_ptr<pele::BasePotential> potential, pele::Array<double>
00098     //        coords, size_t bdim, double d=1e-6);
00099     /*constructor*/
00100     LowestEigPotential(std::shared_ptr<pele::BasePotential> potential, pele::Array<double>coords,
00101             size_t bdim, double d=1e-6)
00102         : _potential(potential), _coords(coords), _coordsd(coords.size()),
00103           _g(_coords.size()), _gd(_coords.size()), _bdim(bdim),
00104           _natoms(_coords.size()/_bdim), _d(d), _orthog(_natoms,_bdim)
00105     {
00106         _potential->get_energy_gradient(_coords,_g);
00107     }
00108 
00109 
00110     virtual ~LowestEigPotential(){}
00111 
00112 
00113     //virtual double inline get_energy(pele::Array<double> x);
00114     /* calculate energy from distance squared, r0 is the hard core distance, r is the distance between the centres */
00115     virtual double inline get_energy(pele::Array<double> x)
00116     {
00117         _orthog.orthogonalize(_coords, x); //takes care of orthogonalizing and normalizing x
00118 
00119         for (size_t i=0;i<x.size();++i) {
00120             _coordsd[i] = _coords[i] + _d*x[i];
00121         }
00122 
00123         _potential->get_energy_gradient(_coordsd,_gd);
00124         _gd -= _g;
00125         double mu = dot(_gd,x)/_d;
00126 
00127         return mu;
00128     }
00129 
00130     //virtual double inline get_energy_gradient(pele::Array<double> x,
00131     //        pele::Array<double> grad);
00132     /* 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 */
00133     virtual double inline get_energy_gradient(pele::Array<double> x, pele::Array<double> grad)
00134     {
00135         _orthog.orthogonalize(_coords, x);  //takes care of orthogonalizing and normalizing x
00136 
00137         for (size_t i=0;i<x.size();++i) {
00138             _coordsd[i] = _coords[i] + _d*x[i];
00139         }
00140 
00141         _potential->get_energy_gradient(_coordsd,_gd);
00142         _gd -= _g;
00143         double mu = dot(_gd,x)/_d;
00144         for (size_t i=0;i<x.size();++i) {
00145             grad[i] = 2*_gd[i]/_d - 2*mu*x[i];
00146         }
00147 
00148         return mu;
00149     }
00150 
00151     //void reset_coords(pele::Array<double> new_coords);
00152     void reset_coords(pele::Array<double> new_coords)
00153     {
00154         _coords.assign(new_coords);
00155         _potential->get_energy_gradient(_coords,_g);
00156     }
00157 
00158 
00159 };
00160 
00161 }//namespace pele
00162 
00163 #endif//#ifndef _PELE_LOWEST_EIG_POTENTIAL_H
 All Classes Namespaces Functions Variables Typedefs