QMCPACK
CountingGaussianRegion.h
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: Brett Van Der Goetz, bvdg@berkeley.edu, University of California at Berkeley
8 //
9 // File created by: Brett Van Der Goetz, bvdg@berkeley.edu, University of California at Berkeley
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef QMCPLUSPLUS_NORMALIZED_GAUSSIAN_REGION_H
13 #define QMCPLUSPLUS_NORMALIZED_GAUSSIAN_REGION_H
14 
15 #include "Configuration.h"
17 #include "VariableSet.h"
18 #include "Particle/ParticleSet.h"
19 
20 namespace qmcplusplus
21 {
22 
24 {
25 public:
26 
28  //using ValueType = QMCTraits::ValueType;
31 
34 
35  // counting function pointers
36  std::vector<std::unique_ptr<CountingGaussian>> C;
37 
39 
40  // reference gaussian id, pointer
41  std::string Cref_id;
42  std::unique_ptr<CountingGaussian> Cref;
43 
44  // number of electrons
45  int num_els;
46  // number of regions
48  // counting function id
49  std::vector<std::string> C_id;
50 
51  // value arrays
53  std::vector<RealType> sum;
56  std::vector<RealType> Nval;
57 
58  // log values arrays
62  std::vector<RealType> Lmax;
63 
64  // temporary value arrays
65  std::vector<RealType> val_t;
66  std::vector<RealType> sum_t;
67  std::vector<PosType> grad_t;
68  std::vector<RealType> lap_t;
69 
70  //memory for temporary log value arrays
71  std::vector<RealType> Lval_t;
72  std::vector<PosType> Lgrad_t;
73  std::vector<RealType> Llap_t;
75 
76  std::vector<RealType> _dLval_saved;
77 
78 
79 public:
82 
83  int size() const { return num_regions; }
84 
85  const opt_variables_type& getVars(int I) { return C[I]->myVars; }
86 
88  {
89  int tnd = 0;
90  for(int I = 0; I < C.size(); ++I)
91  tnd += getVars(I).size_of_active();
92  return tnd;
93  }
94 
95  int max_num_derivs() const
96  {
97  auto comp = [](const auto& a, const auto& b) { return a->myVars.size_of_active() < b->myVars.size_of_active(); };
98  auto& Cmax = *(std::max_element(C.begin(), C.end(), comp));
99  return Cmax->myVars.size();
100  }
101 
102  inline RealType& dLval_saved(int I, int p, int i)
103  {
104  return _dLval_saved[I * max_num_derivs() * num_els + p * num_els + i];
105  }
106 
107  void addFunc(std::unique_ptr<CountingGaussian> func, std::string fid)
108  {
109  C_id.push_back(fid);
110  C.push_back(std::move(func));
111  }
112 
113  void initialize()
114  {
115  num_regions = C.size();
116 
117  // resize arrays
119  sum.resize(num_regions);
120  grad.resize(num_regions, num_els);
122  Nval.resize(num_els);
123 
124  val_t.resize(num_regions);
125  sum_t.resize(num_regions);
126  grad_t.resize(num_regions);
127  lap_t.resize(num_regions);
128 
130  Lgrad.resize(num_regions, num_els);
132  Lmax.resize(num_els);
133 
134  Lval_t.resize(num_regions);
135  Lgrad_t.resize(num_regions);
136  Llap_t.resize(num_regions);
137 
138  // store log derivative values for single particle moves
140  for(int I = 0; I < C.size(); ++I)
141  C[I]->myVars.resetIndex();
142  }
143 
145  {
146  for (auto it = C.begin(); it != C.end(); ++it)
147  (*it)->checkInVariables(active);
148  }
150  {
151  for (auto it = C.begin(); it != C.end(); ++it)
152  (*it)->checkOutVariables(active);
153  }
155  {
156  for (auto it = C.begin(); it != C.end(); ++it)
157  (*it)->resetParameters(active);
158  }
159 
160  void acceptMove(ParticleSet& P, int iat)
161  {
162  Nval[iat] = Nval_t;
163  Lmax[iat] = Lmax_t;
164  for (int I = 0; I < num_regions; ++I)
165  {
166  sum[I] = sum_t[I];
167  val(I, iat) = val_t[I];
168  grad(I, iat) = grad_t[I];
169  lap(I, iat) = lap_t[I];
170 
171  Lval(I, iat) = Lval_t[I];
172  Lgrad(I, iat) = Lgrad_t[I];
173  Llap(I, iat) = Llap_t[I];
174  }
175  }
176 
177  void restore(int iat)
178  {
179  for (int I = 0; I < C.size(); ++I)
180  C[I]->restore(iat);
181  }
182 
183  void reportStatus(std::ostream& os)
184  {
185  // print some class variables:
186  os << " Region type: CountingGaussianRegion" << std::endl;
187  os << " Region optimizable parameters: " << total_num_derivs() << std::endl << std::endl;
188  os << " Counting Functions: " << std::endl;
189  for (int I = 0; I < C.size(); ++I)
190  C[I]->reportStatus(os);
191  }
192 
193  std::unique_ptr<CountingGaussianRegion> makeClone()
194  {
195  // create a new object and clone counting functions
196  auto cr = std::make_unique<CountingGaussianRegion>(num_els);
197  for (int i = 0; i < C.size(); ++i)
198  {
199  auto Ci = C[i]->makeClone(C_id[i]);
200  cr->addFunc(std::move(Ci), C_id[i]);
201  }
202  // get the index of the reference gaussian
203  cr->Cref_id = Cref_id;
204  auto C_id_it = std::find(C_id.begin(), C_id.end(), Cref_id);
205  int ref_index = std::distance(C_id.begin(), C_id_it);
206  // initialize each of the counting functions using the reference gaussian
207  cr->Cref = cr->C[ref_index]->makeClone(Cref_id + "_ref");
208  for(auto& ptr : cr->C)
209  ptr->initialize(cr->Cref.get());
210  cr->initialize();
211  return cr;
212  }
213 
214  bool put(xmlNodePtr cur)
215  {
216  // get the reference function
217  OhmmsAttributeSet rAttrib;
218  Cref_id = "g0";
219  rAttrib.add(Cref_id, "reference_id");
220  rAttrib.put(cur);
221  // loop through array, find where Cref is
222  auto C_id_it = std::find(C_id.begin(), C_id.end(), Cref_id);
223  int ref_index = std::distance(C_id.begin(), C_id_it);
224  if (C_id_it == C_id.end())
225  APP_ABORT("CountingGaussianRegion::put: reference function not found:" +
226  (Cref_id == "none" ? " Cref not specified" : "\"" + Cref_id + "\""));
227  // make a copy of the reference gaussian
228  Cref = C[ref_index]->makeClone(Cref_id + "_ref");
229  // initialize with reference gaussian
230  for(auto& ptr : C)
231  ptr->initialize(Cref.get());
232  initialize();
233  return true;
234  }
235 
236  // evaluate using the log of the counting basis
237  void evaluate(const ParticleSet& P)
238  {
239  // clear arrays
240  std::fill(val.begin(), val.end(), 0);
241  std::fill(sum.begin(), sum.end(), 0);
242  std::fill(grad.begin(), grad.end(), 0);
243  std::fill(lap.begin(), lap.end(), 0);
244  std::fill(Lval.begin(), Lval.end(), 0);
245  std::fill(Lgrad.begin(), Lgrad.end(), 0);
246  std::fill(Llap.begin(), Llap.end(), 0);
247  std::fill(Nval.begin(), Nval.end(), 0);
248  std::fill(Lmax.begin(), Lmax.end(), 0);
249  // temporary variables: Lval = ln(C), Lgrad = \nabla ln(C), Llap = \nabla^2 ln(C)
250  for (int i = 0; i < num_els; ++i)
251  {
252  for (int I = 0; I < num_regions; ++I)
253  {
254  C[I]->evaluateLog(P.R[i], Lval(I, i), Lgrad(I, i), Llap(I, i));
255  if (Lval(I, i) > Lmax[i])
256  Lmax[i] = Lval(I, i);
257  }
258  // build counting function values; subtract off largest log value
259  for (int I = 0; I < num_regions; ++I)
260  {
261  val(I, i) = std::exp(Lval(I, i) - Lmax[i]);
262  Nval[i] += val(I, i);
263  }
264  PosType gLN_sum = 0; // \sum\limits_I \nabla L_{Ii} N_{Ii}
265  RealType lLN_sum = 0; // \sum\limits_I \nabla^2 L_{Ii} N_{Ii}
266  // build normalized counting function value, intermediate values for gradient
267  for (int I = 0; I < num_regions; ++I)
268  {
269  val(I, i) = val(I, i) / Nval[i];
270  sum[I] += val(I, i);
271  gLN_sum += Lgrad(I, i) * val(I, i);
272  lLN_sum += Llap(I, i) * val(I, i);
273  }
274  RealType gLgN_sum = 0; // \sum\limits_{I} \nabla L_{Ii} \cdot \nabla N_{Ii}
275  // build gradient, intermediate values for laplacian
276  for (int I = 0; I < num_regions; ++I)
277  {
278  grad(I, i) = (Lgrad(I, i) - gLN_sum) * val(I, i);
279  gLgN_sum += dot(Lgrad(I, i), grad(I, i));
280  }
281  //build laplacian
282  for (int I = 0; I < num_regions; ++I)
283  {
284  lap(I, i) = (Llap(I, i) - lLN_sum - gLgN_sum) * val(I, i) + dot(grad(I, i), Lgrad(I, i) - gLN_sum);
285  }
286  }
287  }
288 
289  void evaluate_print(std::ostream& os, const ParticleSet& P)
290  {
291  for (auto it = C.begin(); it != C.end(); ++it)
292  (*it)->evaluate_print(os, P);
293  os << "CountingGaussianRegions::evaluate_print" << std::endl;
294  os << "val: ";
295  std::copy(val.begin(), val.end(), std::ostream_iterator<RealType>(os, ", "));
296  os << std::endl << "sum: ";
297  std::copy(sum.begin(), sum.end(), std::ostream_iterator<RealType>(os, ", "));
298  os << std::endl << "grad: ";
299  std::copy(grad.begin(), grad.end(), std::ostream_iterator<PosType>(os, ", "));
300  os << std::endl << "lap: ";
301  std::copy(lap.begin(), lap.end(), std::ostream_iterator<RealType>(os, ", "));
302  os << std::endl << "Nval: ";
303  std::copy(Nval.begin(), Nval.end(), std::ostream_iterator<RealType>(os, ", "));
304  os << std::endl << "Lmax: ";
305  std::copy(Lmax.begin(), Lmax.end(), std::ostream_iterator<RealType>(os, ", "));
306  os << std::endl;
307  }
308 
309 
310  void evaluateTemp(const ParticleSet& P, int iat)
311  {
312  // clear arrays
313  std::fill(val_t.begin(), val_t.end(), 0);
314  std::fill(sum_t.begin(), sum_t.end(), 0);
315  std::fill(grad_t.begin(), grad_t.end(), 0);
316  std::fill(lap_t.begin(), lap_t.end(), 0);
317  std::fill(Lval_t.begin(), Lval_t.end(), 0);
318  std::fill(Lgrad_t.begin(), Lgrad_t.end(), 0);
319  std::fill(Llap_t.begin(), Llap_t.end(), 0);
320 
321  Lmax_t = Lmax[iat];
322  Nval_t = 0;
323  // temporary variables
324  for (int I = 0; I < num_regions; ++I)
325  {
326  C[I]->evaluateLog(P.getActivePos(), Lval_t[I], Lgrad_t[I], Llap_t[I]);
327  if (Lval_t[I] > Lmax_t)
328  Lmax_t = Lval_t[I];
329  }
330  // build counting function values; subtract off largest log value
331  for (int I = 0; I < num_regions; ++I)
332  {
333  val_t[I] = std::exp(Lval_t[I] - Lmax_t);
334  Nval_t += val_t[I];
335  }
336  PosType gLN_sum_t = 0; // \sum\limits_I \nabla L_{Ii} N_{Ii}
337  RealType lLN_sum_t = 0; // \sum\limits_I \nabla^2 L_{Ii} N_{Ii}
338  // build normalized counting function value, intermediate values for gradient
339  for (int I = 0; I < num_regions; ++I)
340  {
341  val_t[I] = val_t[I] / Nval_t;
342  sum_t[I] = sum[I] + val_t[I] - val(I, iat);
343  gLN_sum_t += Lgrad_t[I] * val_t[I];
344  lLN_sum_t += Llap_t[I] * val_t[I];
345  }
346  RealType gLgN_sum_t = 0; // \sum\limits_{I} \nabla L_{Ii} \cdot \nabla N_{Ii}
347  // build gradient, intermediate values for laplacian
348  for (int I = 0; I < num_regions; ++I)
349  {
350  grad_t[I] = (Lgrad_t[I] - gLN_sum_t) * val_t[I];
351  gLgN_sum_t += dot(Lgrad_t[I], grad_t[I]);
352  }
353  //build laplacian
354  for (int I = 0; I < num_regions; ++I)
355  {
356  lap_t[I] = (Llap_t[I] - lLN_sum_t - gLgN_sum_t) * val_t[I] + dot(grad_t[I], Lgrad_t[I] - gLN_sum_t);
357  }
358  }
359 
360  void evaluateTemp_print(std::ostream& os, const ParticleSet& P)
361  {
362  os << "CountingGaussianRegion::evaluateTemp_print" << std::endl;
363  os << "val_t: ";
364  std::copy(val_t.begin(), val_t.end(), std::ostream_iterator<RealType>(os, ", "));
365  os << std::endl << "sum_t: ";
366  std::copy(sum_t.begin(), sum_t.end(), std::ostream_iterator<RealType>(os, ", "));
367  os << std::endl << "grad_t: ";
368  std::copy(grad_t.begin(), grad_t.end(), std::ostream_iterator<PosType>(os, ", "));
369  os << std::endl << "lap_t: ";
370  std::copy(lap_t.begin(), lap_t.end(), std::ostream_iterator<RealType>(os, ", "));
371  os << std::endl << "Nval_t: " << Nval_t;
372  os << std::endl << "Lmax_t: " << Lmax_t;
373  os << std::endl;
374  }
375 
376 
377  // calculates derivatives of single particle move of particle with index iat
379  const int I, // index of the counting function parameter derivatives are associated with
380  int iat,
381  Matrix<RealType>& dNdiff)
382  {
383  // may assume evaluate and evaluateTemp has already been called
384  int num_derivs = getVars(I).size();
385  // get log derivatives
386  static std::vector<RealType> dLval_t;
387  static int mnd = max_num_derivs();
388  dLval_t.resize(mnd);
389 
390  C[I]->evaluateLogTempDerivatives(P.getActivePos(), dLval_t);
391  for (int J = 0; J < num_regions; ++J)
392  {
393  for (int p = 0; p < num_derivs; ++p)
394  {
395  RealType val_Ii = (I == J) - val(I, iat);
396  RealType val_It = (I == J) - val_t[I];
397  dNdiff(J, p) = val_t[J] * dLval_t[p] * val_It - val(J, iat) * dLval_saved(I, p, iat) * val_Ii;
398  }
399  }
400  }
401 
403  int I,
404  Matrix<PosType>& FCgrad,
405  Matrix<RealType>& dNsum,
406  Matrix<RealType>& dNggsum,
407  Matrix<RealType>& dNlapsum,
408  std::vector<RealType>& dNFNggsum)
409  {
410  evaluate(P);
411  static std::vector<RealType> dLval;
412  static std::vector<PosType> dLgrad;
413  static std::vector<RealType> dLlap;
414  static int mnd = max_num_derivs();
415  dLval.resize(mnd);
416  dLgrad.resize(mnd);
417  dLlap.resize(mnd);
418 
419  int num_derivs = getVars(I).size();
420  for (int i = 0; i < num_els; ++i)
421  {
422  // get log derivatives
423  C[I]->evaluateLogDerivatives(P.R[i], dLval, dLgrad, dLlap);
424  for (int J = 0; J < num_regions; ++J)
425  {
426  for (int p = 0; p < num_derivs; ++p)
427  {
428  RealType val_Ii = (I == J) - val(I, i);
429 
430  RealType dNval = val(J, i) * dLval[p] * val_Ii;
431  PosType dNgrad =
432  grad(J, i) * dLval[p] * val_Ii + val(J, i) * dLgrad[p] * val_Ii - val(J, i) * dLval[p] * grad(I, i);
433 
434  RealType dNlap = lap(J, i) * dLval[p] * val_Ii + 2 * dot(grad(J, i), dLgrad[p]) * val_Ii -
435  2 * dot(grad(J, i), grad(I, i)) * dLval[p] + val(J, i) * dLlap[p] * val_Ii -
436  2 * val(J, i) * dot(dLgrad[p], grad(I, i)) - val(J, i) * dLval[p] * lap(I, i);
437  // accumulate
438  dLval_saved(I, p, i) = dLval[p];
439  PosType grad_i( std::real(P.G[i][0]), std::real(P.G[i][1]), std::real(P.G[i][2]) );
440  dNsum(J, p) += dNval;
441  dNggsum(J, p) += dot(dNgrad, grad_i);
442  dNlapsum(J, p) += dNlap;
443  dNFNggsum[p] += dot(dNgrad, FCgrad(J, i));
444  }
445  }
446  }
447  } // end evaluateDerivatives
448 };
449 
450 } // namespace qmcplusplus
451 #endif
Container_t::iterator begin()
Definition: OhmmsMatrix.h:89
RealType & dLval_saved(int I, int p, int i)
QMCTraits::RealType real
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
void checkOutVariables(const opt_variables_type &active)
QTBase::RealType RealType
Definition: Configuration.h:58
void resetParameters(const opt_variables_type &active)
size_t getTotalNum() const
Definition: ParticleSet.h:493
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
void addFunc(std::unique_ptr< CountingGaussian > func, std::string fid)
void resize(size_type n, size_type m)
Resize the container.
Definition: OhmmsMatrix.h:99
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
std::vector< std::unique_ptr< CountingGaussian > > C
const PosType & getActivePos() const
Definition: ParticleSet.h:261
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
void evaluate_print(std::ostream &os, const ParticleSet &P)
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
ParticleGradient G
gradients of the particles
Definition: ParticleSet.h:83
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
optimize::VariableSet::real_type real_type
ParticlePos R
Position.
Definition: ParticleSet.h:79
QTBase::PosType PosType
Definition: Configuration.h:61
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
int size_of_active() const
return the number of active variables
Definition: VariableSet.h:78
MakeReturn< UnaryNode< FnExp, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t exp(const Vector< T1, C1 > &l)
size_type size() const
return the size
Definition: VariableSet.h:88
std::complex< double > I
void evaluateTemp_print(std::ostream &os, const ParticleSet &P)
void evaluateTempDerivatives(ParticleSet &P, const int I, int iat, Matrix< RealType > &dNdiff)
void checkInVariables(opt_variables_type &active)
void evaluateTemp(const ParticleSet &P, int iat)
const opt_variables_type & getVars(int I)
qmcplusplus::QMCTraits::RealType real_type
Definition: VariableSet.h:51
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
Container_t::iterator end()
Definition: OhmmsMatrix.h:90
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
void acceptMove(ParticleSet &P, int iat)
QTBase::TensorType TensorType
Definition: Configuration.h:63
std::unique_ptr< CountingGaussianRegion > makeClone()
std::unique_ptr< CountingGaussian > Cref
void evaluateDerivatives(ParticleSet &P, int I, Matrix< PosType > &FCgrad, Matrix< RealType > &dNsum, Matrix< RealType > &dNggsum, Matrix< RealType > &dNlapsum, std::vector< RealType > &dNFNggsum)