mcpele
1.0.0
The Monte Carlo Python Energy Landscape Explorer
|
00001 #ifndef _MCPELE_PAIR_DIST_HISTOGRAM_H 00002 #define _MCPELE_PAIR_DIST_HISTOGRAM_H 00003 00004 #include <algorithm> 00005 #include <stdexcept> 00006 #include <cmath> 00007 #include <utility> 00008 00009 #include "pele/distance.h" 00010 00011 #include "mcpele/histogram.h" 00012 00013 namespace mcpele{ 00014 00015 template<size_t BOXDIM> 00016 class PairDistHistogram{ 00017 private: 00018 pele::periodic_distance<BOXDIM> m_distance; 00019 const size_t m_nr_bins; 00020 const double m_min_dist; 00021 const double m_max_dist; 00022 const double m_delta_bin; 00023 mcpele::Histogram m_hist; 00024 size_t m_nr_configs; 00025 public: 00026 PairDistHistogram(pele::Array<double> boxvector, const size_t nr_bins) 00027 : m_distance(boxvector), 00028 m_nr_bins(nr_bins), 00029 m_min_dist(0), 00030 m_max_dist(0.5 * *std::min_element(boxvector.data(), boxvector.data() + BOXDIM)), 00031 m_delta_bin((m_max_dist - m_min_dist) / static_cast<double>(m_nr_bins)), 00032 m_hist(m_min_dist, m_max_dist, m_delta_bin), 00033 m_nr_configs(0) 00034 { 00035 if (BOXDIM != boxvector.size()) { 00036 throw std::runtime_error("PairDistHistogram: illegal boxvector size"); 00037 } 00038 } 00039 virtual ~PairDistHistogram() {} 00040 void add_configuration(pele::Array<double> coords) 00041 { 00042 ++m_nr_configs; 00043 const size_t nr_particles(coords.size() / BOXDIM); 00044 for (size_t i = 0; i < nr_particles; ++i) { 00045 for (size_t j = i + 1; j < nr_particles; ++j) { 00046 add_distance(i, j, coords.data()); 00047 } 00048 } 00049 } 00050 void add_distance(const size_t i, const size_t j, const double* coor) 00051 { 00052 double* rij = new double[BOXDIM]; 00053 m_distance.get_rij(rij, coor + i * BOXDIM, coor + j * BOXDIM); 00054 double r2 = 0; 00055 for (size_t k = 0; k < BOXDIM; ++k) { 00056 r2 += rij[k] * rij[k]; 00057 } 00058 delete[] rij; 00059 const double r = sqrt(r2); 00060 if (r > m_max_dist) { 00061 // here, g(r) measurement is resticted to a disc domain of radius 00062 // m_max_dist in distance space; could be done differently 00063 return; 00064 } 00065 m_hist.add_entry(r); 00066 } 00067 double volume_nball(const double radius, const size_t ndim) const 00068 { 00069 return pow(M_PI, 0.5 * ndim) * pow(radius, ndim) / tgamma(0.5 * ndim + 1); 00070 } 00071 std::vector<double> get_vecdata_r() const 00072 { 00073 std::vector<double> result(m_hist.size()); 00074 for (size_t i = 0; i < m_hist.size(); ++i) { 00075 const double r = m_hist.get_position(i); 00076 result.at(i) = r; 00077 } 00078 return result; 00079 } 00080 std::vector<double> get_vecdata_gr(const double number_density, const size_t nr_particles) const 00081 { 00082 std::vector<double> result(m_hist.size()); 00083 for (size_t i = 0; i < m_hist.size(); ++i) { 00084 const double r = m_hist.get_position(i); 00085 const double delta_r = m_hist.bin(); 00086 const double shell_volume_r = volume_nball(r + 0.5 * delta_r, BOXDIM) - volume_nball(r - 0.5 * delta_r, BOXDIM); 00087 const double nid = shell_volume_r * number_density; 00088 const double normalization = 2.0 / (static_cast<double>(m_nr_configs) * static_cast<double>(nr_particles) * nid); 00089 const double g_of_r = normalization * static_cast<double>(m_hist.get_entry(i)); 00090 result.at(i) = g_of_r; 00091 } 00092 return result; 00093 } 00094 }; 00095 00096 } //namespace mcpele 00097 00098 #endif//#ifndef _MCPELE_PAIR_DIST_HISTOGRAM_H