QMCPACK
PairCorrEstimator.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
8 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
10 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 //
13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 #include "PairCorrEstimator.h"
18 #include "Particle/DistanceTable.h"
19 #include "OhmmsData/AttributeSet.h"
20 #include "Utilities/SimpleParser.h"
21 #include <set>
22 
23 namespace qmcplusplus
24 {
26  : Dmax(10.),
27  Delta(0.5),
28  num_species(2),
29  d_aa_ID_(elns.addTable(elns, DTModes::NEED_FULL_TABLE_ON_HOST_AFTER_DONEPBYP))
30 {
31  update_mode_.set(COLLECTABLE, 1);
32  num_species = elns.groups();
33  n_vec.resize(num_species, 0);
34  for (int i = 0; i < num_species; i++)
35  n_vec[i] = elns.last(i) - elns.first(i);
36  N_e = elns.getTotalNum();
37 
38  // use the simulation cell radius if any direction is periodic
39  if (elns.getLattice().SuperCellEnum)
40  {
41  Dmax = elns.getLattice().WignerSeitzRadius;
42  Volume = elns.getLattice().Volume;
43  }
44  else // Open BC's
45  Volume = 1.0;
46  NumBins = static_cast<int>(Dmax / Delta);
47  Delta = Dmax / static_cast<RealType>(NumBins);
48  DeltaInv = 1.0 / Delta;
49  //ostringstream h;
50  //h<<"gofr_" << elns.getName();
51  //gof_r_prefix.push_back(h.str());
52  std::map<int, int> pair_map;
53  int npairs = 0;
54  for (int i = 0; i < num_species; ++i)
55  for (int j = i; j < num_species; ++j)
56  {
57  std::ostringstream os;
58  os << "gofr_" << elns.getName() << "_" << i << "_" << j;
59  gof_r_prefix.push_back(os.str());
60  pair_map[i * num_species + j] = npairs;
61  ++npairs;
62  }
63 
64  // source-target tables
65  std::vector<std::string> slist, dlist;
66  const int ntables = elns.getNumDistTables();
67  for (int k = 0; k < ntables; ++k)
68  if (elns.getName() != elns.getDistTable(k).get_origin().getName())
69  dlist.push_back(elns.getDistTable(k).get_origin().getName());
70  parsewords(sources.c_str(), slist);
71  std::set<int> others_sorted;
72  for (int i = 0; i < slist.size(); ++i)
73  {
74  int k = 0;
75  while (k < dlist.size())
76  {
77  if (slist[i] == dlist[k])
78  {
79  others_sorted.insert(k + 1);
80  break;
81  }
82  ++k;
83  }
84  }
85  other_ids.resize(others_sorted.size());
86  other_offsets.resize(others_sorted.size());
87  copy(others_sorted.begin(), others_sorted.end(), other_ids.begin());
88  int toff = gof_r_prefix.size();
89  for (int k = 0; k < other_ids.size(); ++k)
90  {
91  const DistanceTable& t(elns.getDistTable(other_ids[k]));
92  app_log() << " GOFR for " << t.getName() << " starts at " << toff << std::endl;
93  other_offsets[k] = toff;
94  const SpeciesSet& species(t.get_origin().getSpeciesSet());
95  int ng = species.size();
96  for (int i = 0; i < ng; ++i)
97  {
98  std::ostringstream os;
99  os << "gofr_" << t.getName() << "_" << species.speciesName[i];
100  gof_r_prefix.push_back(os.str());
101  }
102  toff += ng;
103  }
104 }
105 
107 
108 // The value should match the index to norm_factor in set_norm_factor
109 int PairCorrEstimator::gen_pair_id(const int ig, const int jg, const int ns)
110 {
111  if (jg < ig)
112  return ns * (ns - 1) / 2 - (ns - jg) * (ns - jg - 1) / 2 + ig;
113  else
114  return ns * (ns - 1) / 2 - (ns - ig) * (ns - ig - 1) / 2 + jg;
115 }
116 
118 {
119  BufferType& collectables(P.Collectables);
120  const auto& dii(P.getDistTableAA(d_aa_ID_));
121  for (int iat = 1; iat < dii.centers(); ++iat)
122  {
123  const auto& dist = dii.getDistRow(iat);
124  const int ig = P.GroupID[iat];
125  for (int j = 0; j < iat; ++j)
126  {
127  const RealType r = dist[j];
128  if (r < Dmax)
129  {
130  const int loc = static_cast<int>(DeltaInv * r);
131  const int jg = P.GroupID[j];
132  const int pair_id = gen_pair_id(ig, jg, num_species);
133  collectables[pair_id * NumBins + loc + my_index_] += norm_factor(pair_id + 1, loc);
134  }
135  }
136  }
137  for (int k = 0; k < other_ids.size(); ++k)
138  {
139  const auto& d1(P.getDistTableAB(other_ids[k]));
140  const ParticleSet::ParticleIndex& gid(d1.get_origin().GroupID);
141  int koff = other_offsets[k];
142  RealType overNI = 1.0 / d1.centers();
143  for (int iat = 0; iat < d1.targets(); ++iat)
144  {
145  const auto& dist = d1.getDistRow(iat);
146  for (int j = 0; j < d1.centers(); ++j)
147  {
148  const RealType r = dist[j];
149  if (r < Dmax)
150  {
151  int toff = (gid[j] + koff) * NumBins;
152  int loc = static_cast<int>(DeltaInv * r);
153  collectables[toff + loc + my_index_] += norm_factor(0, loc) * overNI;
154  }
155  }
156  }
157  }
158  return 0.0;
159 }
160 
161 void PairCorrEstimator::registerCollectables(std::vector<ObservableHelper>& h5list, hdf_archive& file) const
162 {
163  std::vector<int> onedim(1, NumBins);
164  int offset = my_index_;
165  for (int i = 0; i < gof_r_prefix.size(); ++i)
166  {
167  h5list.emplace_back(hdf_path{gof_r_prefix[i]});
168  auto& h5o = h5list.back();
169  h5o.set_dimensions(onedim, offset);
170  h5o.addProperty(const_cast<RealType&>(Delta), "delta", file);
171  h5o.addProperty(const_cast<RealType&>(Dmax), "cutoff", file);
172  offset += NumBins;
173  }
174 }
175 
176 
178 {
179  my_index_ = collectables.size();
180  std::vector<RealType> g(gof_r_prefix.size() * NumBins, 0);
181  collectables.add(g.begin(), g.end());
182  ////only while debugging
183  //if(gof_r.size())
184  //{
185  // myDebugIndex=plist.size();
186  // for(int i=0; i<gof_r_prefix.size(); ++i)
187  // {
188  // for(int k=0; k<gof_r.cols(); ++k)
189  // {
190  // std::ostringstream h;
191  // h << gof_r_prefix[i]<< "_" << k;
192  // int dum=plist.add(h.str());
193  // }
194  // }
195  //}
196 }
197 
198 
200 {
201  //std::copy(gof_r.first_address(),gof_r.last_address(),plist.begin()+myIndex);
202 }
203 
205 {
206  //std::copy(gof_r.first_address(),gof_r.last_address(),plist.begin()+myDebugIndex+offset);
207 }
208 
209 bool PairCorrEstimator::put(xmlNodePtr cur)
210 {
211  //set resolution
212  int nbins = (int)std::ceil(Dmax * DeltaInv);
213  std::string debug("no");
214  OhmmsAttributeSet attrib;
215  attrib.add(nbins, "num_bin");
216  attrib.add(Dmax, "rmax");
217  attrib.add(Delta, "dr");
218  attrib.add(debug, "debug");
219  attrib.put(cur);
220  Delta = Dmax / static_cast<RealType>(nbins);
221  DeltaInv = 1.0 / Delta;
222  NumBins = nbins;
223 
224  // Set normalization based on updated parameters & report status
225  set_norm_factor();
226  report();
227 
228  return true;
229 }
230 
231 
232 // Called from inside put() after internals are set
233 // Sets the normalization, or norm_factor, for each channel and bin
235 {
236  /*
237  Number of species-pair-specific gofr's to compute
238  E.g. "uu", "dd", "ud", & etc.
239  Note the addition +1 bin, which is for the total gofr of the system
240  (which seems not to get saved to h5 file. Why compute it then?)
241  */
242  const RealType n_channels = num_species * (num_species - 1) / 2 + num_species + 1;
243  norm_factor.resize(n_channels, NumBins);
244 
245  /*
246  Compute the normalization V/Npairs/Nid, with
247  V the volume of the system
248  Npairs the number of (unique) pairs of particles of given types
249  Nid the number of particles expected for a uniformly random distribution
250  with the same number density
251  */
252  RealType r = 0.;
253  const RealType ftpi = 4. / 3 * M_PI;
254  const RealType N_tot_pairs = N_e * (N_e - 1) / 2;
255  for (int i = 0; i < NumBins; i++)
256  {
257  // Separation for current bin
258  r = static_cast<RealType>(i) * Delta;
259 
260  // Number density of pairs
261  RealType rho = N_tot_pairs / Volume;
262 
263  // Volume of spherical shell of thickness Delta
264  RealType bin_volume = ftpi * (std::pow(r + Delta, 3) - std::pow(r, 3));
265 
266  // Expected number of pairs of particles separated by distance r assuming
267  // they are uniformly randomly distributed (ideal gas-like)
268  RealType nid = rho * bin_volume;
269  norm_factor(0, i) = 1. / nid;
270  int indx(1);
271 
272  // Do same as above, but for each unique pair of species
273  // e.g. uu, ud, dd...
274  for (int m = 0; m < num_species; m++)
275  {
276  const RealType nm = n_vec[m];
277  for (int n = m; n < num_species; n++)
278  {
279  const RealType nn = n_vec[n];
280  const RealType npairs = (m == n ? (nn * (nn - 1) / 2.) : (nn * nm));
281  rho = npairs / Volume;
282  nid = rho * bin_volume;
283  norm_factor(indx, i) = 1. / nid;
284  indx++;
285  }
286  }
287  }
288 
289  // ***DEBUG*** print norm_factor
290  /*
291  std::cout << "norm_factor:\n";
292  std::cout << std::fixed;
293  for( int j=0; j<norm_factor.size2(); j++ )
294  {
295  std::cout << std::setw(4) << j;
296  std::cout << std::setw(8) << std::setprecision(4) << j*Delta;
297  for( int i=0; i<norm_factor.size1(); i++ )
298  {
299  std::cout << " " << std::setw(10) << std::setprecision(4) << norm_factor(i,j);
300  }
301  std::cout << std::endl;
302  }
303  std::cout << std::endl;
304  */
305 }
306 
307 
309 {
310  app_log() << "PairCorrEstimator report" << std::endl;
311  app_log() << " num_species = " << num_species << std::endl;
312  app_log() << " Volume = " << Volume << std::endl;
313  app_log() << " Dmax = " << Dmax << std::endl;
314  app_log() << " NumBins = " << NumBins << std::endl;
315  app_log() << " Delta = " << Delta << std::endl;
316  app_log() << " DeltaInv = " << DeltaInv << std::endl;
317  //app_log()<<" x = "<< x << std::endl;
318  app_log() << "end PairCorrEstimator report" << std::endl;
319 }
320 
321 bool PairCorrEstimator::get(std::ostream& os) const
322 {
323  os << name_ << " dmax=" << Dmax << std::endl;
324  return true;
325 }
326 
327 std::unique_ptr<OperatorBase> PairCorrEstimator::makeClone(ParticleSet& qp, TrialWaveFunction& psi)
328 {
329  //default constructor is sufficient
330  return std::make_unique<PairCorrEstimator>(*this);
331 }
332 
334 {
335  NumBins = nbins;
337  RealType r = Delta * 0.5;
338  RealType pf = Volume * DeltaInv / (4 * M_PI);
339  for (int i = 0; i < NumBins; ++i, r += Delta)
340  {
341  RealType rm2 = pf / r / r;
342  norm_factor(0, i) = rm2 / N_e;
343  int indx(1);
344  for (int m(0); m < num_species; m++)
345  for (int n(m); n < num_species; n++, indx++)
346  norm_factor(indx, i) = rm2 * n_vec[n] * n_vec[m];
347  }
348  // norm_factor.resize(nbins);
349  // RealType r=Delta*0.5;
350  // for(int i=0; i<norm_factor.size(); ++i, r+=Delta)
351  // {
352  // norm_factor[i]=1.0/r/r;
353  // }
354 }
355 } // namespace qmcplusplus
std::unique_ptr< OperatorBase > makeClone(ParticleSet &qp, TrialWaveFunction &psi) final
size_type size() const
return the size of the data
Definition: PooledData.h:48
const std::string & getName() const
return the name
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
const DistanceTableAA & getDistTableAA(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAA
size_t getTotalNum() const
Definition: ParticleSet.h:493
Return_t evaluate(ParticleSet &P) override
Evaluate the local energy contribution of this component.
int my_index_
starting index of this object
Definition: OperatorBase.h:535
std::ostream & app_log()
Definition: OutputManager.h:65
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
Abstract class to manage operations on pair data between two ParticleSets.
Definition: DistanceTable.h:38
void setObservables(PropertySetType &plist) override
Set the values evaluated by this object to plist Default implementation is to assign Value which is u...
bool get(std::ostream &os) const override
write about the class
void resetTargetParticleSet(ParticleSet &P) override
Reset the data with the target ParticleSet.
std::vector< int > other_offsets
offset of the gofr&#39;s associated with others_id
int getNumDistTables() const
Definition: ParticleSet.h:566
class to handle hdf file
Definition: hdf_archive.h:51
int first(int igroup) const
return the first index of a group i
Definition: ParticleSet.h:514
bool put(xmlNodePtr cur) override
Read the input parameter.
Vectorized record engine for scalar properties.
Matrix< RealType > norm_factor
normalization factor
void resize(size_type n, size_type m)
Resize the container.
Definition: OhmmsMatrix.h:99
Attaches a unit to a Vector for IO.
int size() const
return the number of species
Definition: SpeciesSet.h:53
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
const DistanceTableAB & getDistTableAB(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAB
int groups() const
return the number of groups
Definition: ParticleSet.h:511
MakeReturn< BinaryNode< FnPow, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t, typename CreateLeaf< Vector< T2, C2 > >::Leaf_t > >::Expression_t pow(const Vector< T1, C1 > &l, const Vector< T2, C2 > &r)
std::string name_
name of this object
Definition: OperatorBase.h:527
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
PairCorrEstimator(ParticleSet &elns, std::string &sources)
constructor
void add(T &x)
Definition: PooledData.h:88
MakeReturn< UnaryNode< FnCeil, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t ceil(const Vector< T1, C1 > &l)
unsigned parsewords(const char *inbuf, std::vector< std::string > &slist, const std::string &extra_tokens)
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
std::vector< std::string > gof_r_prefix
prefix of each gof_r
RealType DeltaInv
one of bin size
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
void addObservables(PropertySetType &plist)
auto & getDistTable(int table_ID) const
get a distance table by table_ID
Definition: ParticleSet.h:190
Buffer_t Collectables
observables in addition to those registered in Properties/PropertyList
Definition: ParticleSet.h:126
std::vector< int > other_ids
table indexs for other type
void setParticlePropertyList(PropertySetType &plist, int offset) override
RealType Dmax
maximum distance
FullPrecRealType Return_t
type of return value of evaluate
Definition: OperatorBase.h:64
Class to represent a many-body trial wave function.
void registerCollectables(std::vector< ObservableHelper > &h5list, hdf_archive &file) const override
static int gen_pair_id(const int ig, const int jg, const int ns)
generate the unique pair id from the group ids of particle i and j and the number of species ...
const auto & getLattice() const
Definition: ParticleSet.h:251
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
void add(PDT &aparam, const std::string &aname, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new attribute
Definition: AttributeSet.h:42
whether full table needs to be ready at anytime or not after donePbyP Optimization can be implemented...
std::vector< RealType > n_vec
std::bitset< 8 > update_mode_
set the current update mode
Definition: OperatorBase.h:521
RealType Volume
volume of the cell
void resize(int nbins)
resize the internal data