QMCPACK
QMCHamiltonian.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) 2022 QMCPACK developers.
6 //
7 // File developed by: Bryan Clark, bclark@Princeton.edu, Princeton University
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 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 // Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
12 // Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
13 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
14 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
15 // Peter W. Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
16 //
17 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
18 //////////////////////////////////////////////////////////////////////////////////////
19 
20 #include "QMCHamiltonian.h"
21 #include "Particle/DistanceTable.h"
24 #include "Utilities/TimerManager.h"
25 #include "BareKineticEnergy.h"
28 #include "CPU/math.hpp"
29 
30 namespace qmcplusplus
31 {
33 {
35  // the listeners represet the connection of a particular crowds estimators to the crowds lead QMCHamiltonian.
36  // So you can not clone them.
37  std::unique_ptr<Resource> makeClone() const override
38  {
39  return std::make_unique<QMCHamiltonianMultiWalkerResource>(*this);
40  }
41  std::vector<ListenerVector<RealType>> kinetic_listeners_;
42  std::vector<ListenerVector<RealType>> potential_listeners_;
43  std::vector<ListenerVector<RealType>> ion_kinetic_listeners_;
44  std::vector<ListenerVector<RealType>> ion_potential_listeners_;
45 };
46 
47 /** constructor
48 */
49 QMCHamiltonian::QMCHamiltonian(const std::string& aname)
50  : myIndex(0),
51  numCollectables(0),
52  myName(aname),
53  nlpp_ptr(nullptr),
54  l2_ptr(nullptr),
55  ham_timer_(createGlobalTimer("Hamiltonian:" + aname + "::evaluate", timer_level_medium)),
56  eval_vals_derivs_timer_(createGlobalTimer("Hamiltonian:" + aname + "::ValueParamDerivs", timer_level_medium)),
57  eval_ion_derivs_fast_timer_(
58  createGlobalTimer("Hamiltonian:" + aname + ":::evaluateIonDerivsDeterministicFast", timer_level_medium))
59 #if !defined(REMOVE_TRACEMANAGER)
60  ,
61  streaming_position(false),
62  id_sample(nullptr),
63  pid_sample(nullptr),
64  step_sample(nullptr),
65  gen_sample(nullptr),
66  age_sample(nullptr),
67  mult_sample(nullptr),
68  weight_sample(nullptr),
69  position_sample(nullptr)
70 #endif
71 {}
72 
73 ///// copy constructor is distable by declaring it as private
74 //QMCHamiltonian::QMCHamiltonian(const QMCHamiltonian& qh) {}
75 
76 /** destructor
77  */
79 {
80  //@todo clean up H and auxH
81 }
82 
83 bool QMCHamiltonian::get(std::ostream& os) const
84 {
85  for (int i = 0; i < H.size(); i++)
86  {
87  os << " " << std::setw(16) << std::left << H[i]->getName();
88  H[i]->get(os);
89  os << "\n";
90  }
91  return true;
92 }
93 
94 /** add a new Hamiltonian the the list of Hamiltonians.
95  * @param h an operator
96  * @param aname name of h
97  * @param physical if true, a physical operator
98  */
99 void QMCHamiltonian::addOperator(std::unique_ptr<OperatorBase>&& h, const std::string& aname, bool physical)
100 {
101  //change UpdateMode[PHYSICAL] of h so that cloning can be done correctly
102  h->getUpdateMode()[OperatorBase::PHYSICAL] = physical;
103  if (physical)
104  {
105  for (int i = 0; i < H.size(); ++i)
106  {
107  if (H[i]->getName() == aname)
108  {
109  app_warning() << "QMCHamiltonian::addOperator cannot " << aname << ". The name is already used" << std::endl;
110  return;
111  }
112  }
113  app_log() << " QMCHamiltonian::addOperator " << aname << " to H, physical Hamiltonian " << std::endl;
114  h->setName(aname);
115  H.push_back(std::move(h));
116  std::string tname = "Hamiltonian:" + aname;
117  my_timers_.push_back(createGlobalTimer(tname, timer_level_fine));
118  }
119  else
120  {
121  //ignore timers for now
122  for (int i = 0; i < auxH.size(); ++i)
123  {
124  if (auxH[i]->getName() == aname)
125  {
126  app_warning() << "QMCHamiltonian::addOperator cannot " << aname << ". The name is already used" << std::endl;
127  return;
128  }
129  }
130  app_log() << " QMCHamiltonian::addOperator " << aname << " to auxH " << std::endl;
131  h->setName(aname);
132  auxH.push_back(std::move(h));
133  }
134 
135  //assign save NLPP if found
136  // name is fixed in ECPotentialBuilder::put()
137  if (aname == "NonLocalECP")
138  {
139  if (nlpp_ptr == nullptr)
140  {
141  // original h arguments moved to either H or auxH
142  nlpp_ptr = physical ? dynamic_cast<NonLocalECPotential*>(H.back().get())
143  : dynamic_cast<NonLocalECPotential*>(auxH.back().get());
144  }
145  else
146  {
147  APP_ABORT("QMCHamiltonian::addOperator nlpp_ptr is supposed to be null. Something went wrong!");
148  }
149  }
150 
151  //save L2 potential if found
152  // name is fixed in ECPotentialBuilder::put()
153  if (aname == "L2")
154  {
155  if (l2_ptr == nullptr)
156  {
157  l2_ptr = physical ? dynamic_cast<L2Potential*>(H.back().get()) : dynamic_cast<L2Potential*>(auxH.back().get());
158  }
159  else
160  {
161  APP_ABORT("QMCHamiltonian::addOperator l2_ptr is supposed to be null. Something went wrong!");
162  }
163  }
164 }
165 
166 
167 void QMCHamiltonian::addOperatorType(const std::string& name, const std::string& type)
168 {
169  app_log() << "QMCHamiltonian::addOperatorType added type " << type << " named " << name << std::endl;
170  operator_types[name] = type;
171 }
172 
173 
174 const std::string& QMCHamiltonian::getOperatorType(const std::string& name)
175 {
176  std::map<std::string, std::string>::iterator type = operator_types.find(name);
177  if (type == operator_types.end())
178  APP_ABORT("QMCHamiltonian::getOperatorType\n operator type not found for name " + name);
179  return type->second;
180 }
181 
182 ///** remove a named Hamiltonian from the list
183 // *@param aname the name of the Hamiltonian
184 // *@return true, if the request hamiltonian exists and is removed.
185 // */
186 //bool
187 //QMCHamiltonian::remove(const std::string& aname)
188 //{
189 // return false;
190 //}
191 
193 {
194  for (int i = 0; i < H.size(); ++i)
195  H[i]->updateSource(s);
196  for (int i = 0; i < auxH.size(); ++i)
197  auxH[i]->updateSource(s);
198 }
199 
200 /** add a number of properties to the ParticleSet
201  * @param P ParticleSet to which multiple columns to be added
202  *
203  * QMCHamiltonian can add any number of properties to a ParticleSet.
204  * Hindex contains the index map to the ParticleSet::PropertyList.
205  * This enables assigning the properties evaluated by each OperatorBase
206  * object to the correct property column.
207  */
208 //void
209 //QMCHamiltonian::addObservables(PropertySetType& plist)
210 //{
211 // //first add properties to Observables
212 // Observables.clear();
213 // for(int i=0; i<H.size(); ++i) H[i]->addObservables(Observables);
214 // for(int i=0; i<auxH.size(); ++i) auxH[i]->addObservables(Observables);
215 //
216 // myIndex=plist.add(Observables.Names[0]);
217 // for(int i=1; i<Observables.size(); ++i) plist.add(Observables.Names[i]);
218 //
219 // app_log() << " QMCHamiltonian::add2WalkerProperty added " << Observables.size() << " data to PropertyList" << std::endl;
220 // app_log() << " starting Index = " << myIndex << std::endl;
221 //}
222 //
224 {
225  //first add properties to Observables
226  Observables.clear();
227  //ParticleSet::mcObservables (large data, e.g. density) are accumulated while evaluations
228  P.Collectables.clear();
229  P.Collectables.rewind();
230  for (int i = 0; i < H.size(); ++i)
232  for (int i = 0; i < auxH.size(); ++i)
234  myIndex = P.PropertyList.add(Observables.Names[0]);
235  for (int i = 1; i < Observables.size(); ++i)
236  P.PropertyList.add(Observables.Names[i]);
238  app_log() << "\n QMCHamiltonian::add2WalkerProperty added"
239  << "\n " << Observables.size() << " to P::PropertyList "
240  << "\n " << P.Collectables.size() << " to P::Collectables "
241  << "\n starting Index of the observables in P::PropertyList = " << myIndex << std::endl;
242  return Observables.size();
243 }
244 
245 void QMCHamiltonian::resetObservables(int start, int ncollects)
246 {
247  Observables.clear();
248  BufferType collectables;
249  collectables.rewind();
250  for (int i = 0; i < H.size(); ++i)
251  H[i]->addObservables(Observables, collectables);
252  for (int i = 0; i < auxH.size(); ++i)
253  auxH[i]->addObservables(Observables, collectables);
254  if (collectables.size() != ncollects)
255  {
256  APP_ABORT(" QMCHamiltonian::resetObservables numCollectables != ncollects");
257  }
258  myIndex = start;
259  numCollectables = ncollects;
260 }
261 
262 void QMCHamiltonian::registerObservables(std::vector<ObservableHelper>& h5desc, hdf_archive& file) const
263 {
264  for (int i = 0; i < H.size(); ++i)
265  H[i]->registerObservables(h5desc, file);
266  for (int i = 0; i < auxH.size(); ++i)
267  auxH[i]->registerObservables(h5desc, file);
268 }
269 
270 void QMCHamiltonian::registerCollectables(std::vector<ObservableHelper>& h5desc, hdf_archive& file) const
271 {
272  //The physical operators cannot add to collectables
273  for (int i = 0; i < auxH.size(); ++i)
274  auxH[i]->registerCollectables(h5desc, file);
275 }
276 
278 {
279  // This creates a state replication burder of unknown scope when operators are cloned.
280  ham_leader.mw_res_handle_.getResource().kinetic_listeners_.push_back(listener);
281 }
282 
284 {
285  // This creates a state replication burder of unknown scope when operators are cloned.
286  // A local energy listener listens to both the kinetic operator and all involved in the potential.
287  ham_leader.mw_res_handle_.getResource().kinetic_listeners_.push_back(listener);
288  ham_leader.mw_res_handle_.getResource().potential_listeners_.push_back(listener);
289 }
290 
292 {
293  // This creates a state replication burder of unknown scope when operators are cloned.
294  ham_leader.mw_res_handle_.getResource().potential_listeners_.push_back(listener);
295 }
296 
298 {
299  // This creates a state replication burder of unknown scope when operators are cloned.
300  ham_leader.mw_res_handle_.getResource().ion_potential_listeners_.push_back(listener);
301 }
302 
304 {
305  for (int i = 0; i < H.size(); ++i)
306  H[i]->informOfPerParticleListener();
307 }
308 
309 #if !defined(REMOVE_TRACEMANAGER)
311 {
312  static bool first_init = true;
313  bool trace_log = first_init && tm.verbose && omp_get_thread_num() == 0;
314  if (trace_log)
315  app_log() << "\n Hamiltonian is initializing traces" << std::endl;
316 
317  //fill std::string vectors for combined trace quantities
318  std::vector<std::string> Eloc;
319  std::vector<std::string> Vloc;
320  std::vector<std::string> Vq, Vc, Vqq, Vqc, Vcc;
321  for (int i = 0; i < H.size(); ++i)
322  Eloc.push_back(H[i]->getName());
323  for (int i = 1; i < H.size(); ++i)
324  Vloc.push_back(H[i]->getName());
325 
326  // These contributions are based on the potential energy components.
327  // Loop starts at one to skip the kinetic energy component.
328  for (int i = 1; i < H.size(); ++i)
329  {
330  OperatorBase& h = *H[i];
331  if (h.isQuantum())
332  Vq.push_back(h.getName());
333  else if (h.isClassical())
334  Vc.push_back(h.getName());
335  else if (h.isQuantumQuantum())
336  Vqq.push_back(h.getName());
337  else if (h.isQuantumClassical())
338  Vqc.push_back(h.getName());
339  else if (h.isClassicalClassical())
340  Vcc.push_back(h.getName());
341  else if (omp_get_thread_num() == 0)
342  app_log() << " warning: potential named " << h.getName()
343  << " has not been classified according to its quantum domain (q,c,qq,qc,cc)\n estimators depending "
344  "on this classification may not function properly"
345  << std::endl;
346  }
347 
348 
349  //make trace quantities available
350  request.contribute_scalar("id", true); //default trace quantity
351  request.contribute_scalar("parent_id", true); //default trace quantity
352  request.contribute_scalar("step", true); //default trace quantity
353  request.contribute_scalar("generation", true); //default trace quantity
354  request.contribute_scalar("age", true); //default trace quantity
355  request.contribute_scalar("multiplicity", true); //default trace quantity
356  request.contribute_scalar("weight", true); //default trace quantity
357  request.contribute_array("position");
358  for (int i = 0; i < H.size(); ++i)
359  H[i]->contributeTraceQuantities();
360  for (int i = 0; i < auxH.size(); ++i)
361  auxH[i]->contributeTraceQuantities();
362 
363 
364  //note availability of combined quantities
365  request.contribute_combined("LocalEnergy", Eloc, true);
366  request.contribute_combined("LocalPotential", Vloc, true, true);
367  if (Vq.size() > 0)
368  request.contribute_combined("Vq", Vq, true, true);
369  if (Vc.size() > 0)
370  request.contribute_combined("Vc", Vc, true, true);
371  if (Vqq.size() > 0)
372  request.contribute_combined("Vqq", Vqq, true, true);
373  if (Vqc.size() > 0)
374  request.contribute_combined("Vqc", Vqc, true, true);
375  if (Vcc.size() > 0)
376  request.contribute_combined("Vcc", Vcc, true, true);
377 
378 
379  //collect trace requests
380  std::vector<TraceRequest*> requests;
381  // Hamiltonian request (id, step, weight, positions)
382  requests.push_back(&request);
383  // requests from Hamiltonian components
384  for (int i = 0; i < H.size(); ++i)
385  requests.push_back(&H[i]->getRequest());
386  // requests from other observables
387  for (int i = 0; i < auxH.size(); ++i)
388  requests.push_back(&auxH[i]->getRequest());
389 
390  //collect trace quantity availability/requests from contributors/requestors
391  for (int i = 0; i < requests.size(); ++i)
392  tm.request.incorporate(*requests[i]);
393 
394  //balance requests with availability, mark quantities as streaming/writing
396 
397  //relay updated streaming information to all contributors/requestors
398  for (int i = 0; i < requests.size(); ++i)
399  tm.request.relay_stream_info(*requests[i]);
400 
401  //set streaming/writing traces in general
402  tm.update_status();
403 
404  // setup traces, if any quantities should be streaming
405 
406  // tracing
407  bool tracing = request.streaming();
408  if (tracing != tm.streaming_traces)
409  APP_ABORT("QMCHamiltonian::initialize_traces trace request failed to initialize properly");
410  if (!tracing)
411  {
412  // Empty. Do not log if nothing will be done
413 
414  if (trace_log)
415  app_log() << " no traces streaming" << std::endl;
416  }
417  else
418  {
419  if (trace_log)
420  app_log() << " traces streaming" << std::endl;
421  //checkout trace quantities
422  //(requested sources checkout arrays to place samples in for streaming)
423  // checkout walker trace quantities
426  {
427  id_sample = tm.checkout_int<1>("id");
428  pid_sample = tm.checkout_int<1>("parent_id");
429  step_sample = tm.checkout_int<1>("step");
430  gen_sample = tm.checkout_int<1>("generation");
431  age_sample = tm.checkout_int<1>("age");
432  mult_sample = tm.checkout_int<1>("multiplicity");
433  weight_sample = tm.checkout_real<1>("weight");
434  }
435  if (streaming_position)
436  position_sample = tm.checkout_real<2>("position", P, DIM);
437  // checkout observable trace quantities
438  for (int i = 0; i < H.size(); ++i)
439  {
440  if (trace_log)
441  app_log() << " OperatorBase::checkoutTraceQuantities " << H[i]->getName() << std::endl;
442  H[i]->checkoutTraceQuantities(tm);
443  }
444  for (int i = 0; i < auxH.size(); ++i)
445  {
446  if (trace_log)
447  app_log() << " OperatorBase::checkoutTraceQuantities " << auxH[i]->getName() << std::endl;
448  auxH[i]->checkoutTraceQuantities(tm);
449  }
450  //setup combined traces that depend on H information
451  // LocalEnergy, LocalPotential, Vq, Vc, Vqq, Vqc, Vcc
452  if (Vloc.size() > 0 && request.streaming("LocalPotential"))
453  tm.make_combined_trace("LocalPotential", Vloc);
454  if (Eloc.size() > 0 && request.streaming("LocalEnergy"))
455  tm.make_combined_trace("LocalEnergy", Eloc);
456  if (Vq.size() > 0 && request.streaming("Vq"))
457  tm.make_combined_trace("Vq", Eloc);
458  if (Vc.size() > 0 && request.streaming("Vc"))
459  tm.make_combined_trace("Vc", Eloc);
460  if (Vqq.size() > 0 && request.streaming("Vqq"))
461  tm.make_combined_trace("Vqq", Eloc);
462  if (Vqc.size() > 0 && request.streaming("Vqc"))
463  tm.make_combined_trace("Vqc", Eloc);
464  if (Vcc.size() > 0 && request.streaming("Vcc"))
465  tm.make_combined_trace("Vcc", Eloc);
466 
467  //all trace samples have been created ( streaming instances)
468  // mark the ones that will be writing also
469  tm.screen_writes();
470 
471  //observables that depend on traces check them out
472  if (trace_log)
473  app_log() << "\n Hamiltonian is fulfilling trace requests from observables" << std::endl;
474  for (int i = 0; i < auxH.size(); ++i)
475  {
476  if (trace_log)
477  app_log() << " OperatorBase::getRequiredTraces " << auxH[i]->getName() << std::endl;
478  auxH[i]->getRequiredTraces(tm);
479  }
480  //report
481 
482  //write traces status to the log
483  if (trace_log)
484  tm.user_report();
485 
486  first_init = false;
487  }
488 }
489 
490 
492 {
494  {
495  (*id_sample)(0) = walker.getWalkerID();
496  (*pid_sample)(0) = walker.getParentID();
497  (*step_sample)(0) = step;
498  (*gen_sample)(0) = walker.Generation;
499  (*age_sample)(0) = walker.Age;
500  (*mult_sample)(0) = walker.Multiplicity;
501  (*weight_sample)(0) = walker.Weight;
502  }
503  if (streaming_position)
504  for (int i = 0; i < walker.R.size(); ++i)
505  for (int d = 0; d < DIM; ++d)
506  (*position_sample)(i, d) = walker.R[i][d];
507 }
508 
509 
511 {
513  {
514  delete id_sample;
515  delete pid_sample;
516  delete step_sample;
517  delete gen_sample;
518  delete age_sample;
519  delete mult_sample;
520  delete weight_sample;
521  }
522  if (streaming_position)
523  delete position_sample;
524  if (request.streaming())
525  {
526  for (int i = 0; i < H.size(); ++i)
527  H[i]->deleteTraceQuantities();
528  for (int i = 0; i < auxH.size(); ++i)
529  auxH[i]->deleteTraceQuantities();
530  }
531  streaming_position = false;
532  request.reset();
533 }
534 #endif
535 
536 /** Evaluate all the Hamiltonians for the N-particle configuration
537  *@param P input configuration containing N particles
538  *@return the local energy
539  */
541 {
542  ScopedTimer local_timer(ham_timer_);
543  LocalEnergy = 0.0;
544  for (int i = 0; i < H.size(); ++i)
545  {
546  ScopedTimer h_timer(my_timers_[i]);
547  H[i]->evaluate(P);
548  updateComponent(*H[i], *this, P);
549 #if !defined(REMOVE_TRACEMANAGER)
550  H[i]->collectScalarTraces();
551 #endif
552  }
553  updateKinetic(*this, P);
554  return LocalEnergy;
555 }
556 
558 {
559  ScopedTimer local_timer(ham_timer_);
560  LocalEnergy = 0.0;
561  for (int i = 0; i < H.size(); ++i)
562  {
563  ScopedTimer h_timer(my_timers_[i]);
564  H[i]->evaluateDeterministic(P);
565  updateComponent(*H[i], *this, P);
566 #if !defined(REMOVE_TRACEMANAGER)
567  H[i]->collectScalarTraces();
568 #endif
569  }
570  updateKinetic(*this, P);
571  return LocalEnergy;
572 }
574 {
575  // It's much better to be able to see where this is coming from. It is caught just fine.
576  if (qmcplusplus::isnan(op.getValue()))
577  {
578  std::ostringstream msg;
579  msg << "QMCHamiltonian::updateComponent component " << op.getName() << " returns NaN." << std::endl;
580  pset.print(msg);
581  throw std::runtime_error(msg.str());
582  }
583  // The following is a ridiculous breach of encapsulation.
584  ham.LocalEnergy += op.getValue();
586  op.setParticlePropertyList(pset.PropertyList, ham.myIndex);
587 }
588 
590 {
591  ham.KineticEnergy = ham.H[0]->getValue();
592  pset.PropertyList[WP::LOCALENERGY] = ham.LocalEnergy;
593  pset.PropertyList[WP::LOCALPOTENTIAL] = ham.LocalEnergy - ham.KineticEnergy;
594 }
595 
596 std::vector<QMCHamiltonian::FullPrecRealType> QMCHamiltonian::mw_evaluate(
597  const RefVectorWithLeader<QMCHamiltonian>& ham_list,
599  const RefVectorWithLeader<ParticleSet>& p_list)
600 {
601  auto& ham_leader = ham_list.getLeader();
602  ScopedTimer local_timer(ham_leader.ham_timer_);
603  for (QMCHamiltonian& ham : ham_list)
604  ham.LocalEnergy = 0.0;
605 
606  const int num_ham_operators = ham_leader.H.size();
607 
608  // It is an invariant of the class that H[0] be the kinetic energy operator.
609  // This is enforced by HamiltonianFactory's constuctor and not QMCHamiltonians
610  int kinetic_index = 0;
611  {
612  ScopedTimer h_timer(ham_leader.my_timers_[kinetic_index]);
613  const auto HC_list(extract_HC_list(ham_list, kinetic_index));
614  if (ham_leader.mw_res_handle_.getResource().kinetic_listeners_.size() > 0)
615  ham_leader.H[kinetic_index]
616  ->mw_evaluatePerParticle(HC_list, wf_list, p_list, ham_leader.mw_res_handle_.getResource().kinetic_listeners_,
617  ham_leader.mw_res_handle_.getResource().ion_kinetic_listeners_);
618  else
619  ham_leader.H[kinetic_index]->mw_evaluate(HC_list, wf_list, p_list);
620  for (int iw = 0; iw < ham_list.size(); iw++)
621  updateComponent(HC_list[iw], ham_list[iw], p_list[iw]);
622  }
623 
624  for (int i_ham_op = 1; i_ham_op < num_ham_operators; ++i_ham_op)
625  {
626  ScopedTimer h_timer(ham_leader.my_timers_[i_ham_op]);
627  const auto HC_list(extract_HC_list(ham_list, i_ham_op));
628 
629  if (ham_leader.mw_res_handle_.getResource().potential_listeners_.size() > 0)
630  ham_leader.H[i_ham_op]->mw_evaluatePerParticle(HC_list, wf_list, p_list,
631  ham_leader.mw_res_handle_.getResource().potential_listeners_,
632  ham_leader.mw_res_handle_.getResource().ion_potential_listeners_);
633  else
634  ham_leader.H[i_ham_op]->mw_evaluate(HC_list, wf_list, p_list);
635  for (int iw = 0; iw < ham_list.size(); iw++)
636  updateComponent(HC_list[iw], ham_list[iw], p_list[iw]);
637  }
638 
639  for (int iw = 0; iw < ham_list.size(); iw++)
640  updateKinetic(ham_list[iw], p_list[iw]);
641 
642  std::vector<FullPrecRealType> local_energies(ham_list.size(), 0.0);
643  for (int iw = 0; iw < ham_list.size(); ++iw)
644  local_energies[iw] = ham_list[iw].getLocalEnergy();
645 
646  return local_energies;
647 }
648 
650  const opt_variables_type& optvars,
651  Vector<ValueType>& dlogpsi,
652  Vector<ValueType>& dhpsioverpsi)
653 {
654  // The first componennt must be BareKineticEnergy for both handling KineticEnergy and dlogpsi computation
655  // by calling TWF::evaluateDerivatives inside BareKineticEnergy::evaluateValueAndDerivatives
656  assert(dynamic_cast<BareKineticEnergy*>(H[0].get()) &&
657  "BUG: The first componennt in Hamiltonian must be BareKineticEnergy.");
659 
660  {
661  ScopedTimer h_timer(my_timers_[0]);
662  LocalEnergy = KineticEnergy = H[0]->evaluateValueAndDerivatives(P, optvars, dlogpsi, dhpsioverpsi);
663  }
664 
665  for (int i = 1; i < H.size(); ++i)
666  {
667  ScopedTimer h_timer(my_timers_[i]);
668  LocalEnergy += H[i]->evaluateValueAndDerivatives(P, optvars, dlogpsi, dhpsioverpsi);
669  }
670  return LocalEnergy;
671 }
672 
673 std::vector<QMCHamiltonian::FullPrecRealType> QMCHamiltonian::mw_evaluateValueAndDerivatives(
674  const RefVectorWithLeader<QMCHamiltonian>& ham_list,
676  const RefVectorWithLeader<ParticleSet>& p_list,
677  const opt_variables_type& optvars,
678  RecordArray<ValueType>& dlogpsi,
679  RecordArray<ValueType>& dhpsioverpsi)
680 {
681  std::vector<FullPrecRealType> local_energies(ham_list.size(), 0.0);
682  for (int iw = 0; iw < ham_list.size(); iw++)
683  ham_list[iw].LocalEnergy = 0.0;
684 
685  if (ham_list.size() > 0)
686  {
687  auto& ham_leader = ham_list.getLeader();
688  const int num_ham_operators = ham_leader.H.size();
689  for (int i_ham_op = 0; i_ham_op < num_ham_operators; ++i_ham_op)
690  {
691  ScopedTimer local_timer(ham_leader.my_timers_[i_ham_op]);
692  const auto HC_list(extract_HC_list(ham_list, i_ham_op));
693 
694  ham_leader.H[i_ham_op]->mw_evaluateWithParameterDerivatives(HC_list, p_list, optvars, dlogpsi, dhpsioverpsi);
695 
696  for (int iw = 0; iw < ham_list.size(); iw++)
697  updateComponent(HC_list[iw], ham_list[iw], p_list[iw]);
698  }
699 
700  for (int iw = 0; iw < ham_list.size(); iw++)
701  updateKinetic(ham_list[iw], p_list[iw]);
702 
703  for (int iw = 0; iw < ham_list.size(); ++iw)
704  local_energies[iw] = ham_list[iw].getLocalEnergy();
705  }
706 
707  return local_energies;
708 }
709 
711 {
712  RealType nlpp = 0.0;
713  RealType ke = H[0]->evaluate(P);
714  if (free_nlpp)
715  for (int i = 1; i < H.size(); ++i)
716  {
717  if (H[i]->isNonLocal())
718  nlpp += H[i]->evaluate(P);
719  }
720  return ke + nlpp;
721 }
722 
724 {
725  for (int i = 0; i < auxH.size(); ++i)
726  {
727  RealType sink = auxH[i]->evaluate(P);
728  auxH[i]->setObservables(Observables);
729 #if !defined(REMOVE_TRACEMANAGER)
730  auxH[i]->collectScalarTraces();
731 #endif
732  auxH[i]->setParticlePropertyList(P.PropertyList, myIndex);
733  //H[i]->setParticlePropertyList(P.PropertyList,myIndex);
734  }
735 }
736 
737 ///This is more efficient. Only calculate auxH elements if moves are accepted.
739 {
740 #if !defined(REMOVE_TRACEMANAGER)
741  collect_walker_traces(ThisWalker, P.current_step);
742 #endif
743  for (int i = 0; i < auxH.size(); ++i)
744  {
745  auxH[i]->setHistories(ThisWalker);
746  RealType sink = auxH[i]->evaluate(P);
747  auxH[i]->setObservables(Observables);
748 #if !defined(REMOVE_TRACEMANAGER)
749  auxH[i]->collectScalarTraces();
750 #endif
751  auxH[i]->setParticlePropertyList(P.PropertyList, myIndex);
752  }
753 }
754 ///Evaluate properties only.
755 void QMCHamiltonian::auxHevaluate(ParticleSet& P, Walker_t& ThisWalker, bool do_properties, bool do_collectables)
756 {
757 #if !defined(REMOVE_TRACEMANAGER)
758  collect_walker_traces(ThisWalker, P.current_step);
759 #endif
760  for (int i = 0; i < auxH.size(); ++i)
761  {
762  bool is_property = !(auxH[i]->getMode(OperatorBase::COLLECTABLE));
763  bool is_collectable = (auxH[i]->getMode(OperatorBase::COLLECTABLE));
764  if ((is_property && do_properties) || (is_collectable && do_collectables))
765  {
766  auxH[i]->setHistories(ThisWalker);
767  RealType sink = auxH[i]->evaluate(P);
768  auxH[i]->setObservables(Observables);
769 #if !defined(REMOVE_TRACEMANAGER)
770  auxH[i]->collectScalarTraces();
771 #endif
772  auxH[i]->setParticlePropertyList(P.PropertyList, myIndex);
773  }
774  }
775 }
776 
777 /** Looks like a hack see DMCBatched.cpp and DMC.cpp weight is used like temporary flag
778  * from DMC.
779  */
781 {
782  // weight should be 0 from DMC
783  // since other traced properties will be invalid
784  // (they will be from the walker moved before this one)
785 #if !defined(REMOVE_TRACEMANAGER)
786  collect_walker_traces(ThisWalker, P.current_step);
787 #endif
788  // ThisWalker.rejectedMove();
789  for (int i = 0; i < auxH.size(); ++i)
790  {
791  auxH[i]->setHistories(ThisWalker);
792  RealType sink = auxH[i]->rejectedMove(P);
793  }
794 }
795 
797 {
798  ScopedTimer local_timer(ham_timer_);
799  LocalEnergy = 0.0;
800  for (int i = 0; i < H.size(); ++i)
801  {
802  ScopedTimer h_timer(my_timers_[i]);
803  H[i]->evaluateWithToperator(P);
804  updateComponent(*H[i], *this, P);
805 #if !defined(REMOVE_TRACEMANAGER)
806  H[i]->collectScalarTraces();
807 #endif
808  }
809  updateKinetic(*this, P);
810  return LocalEnergy;
811 }
812 
813 std::vector<QMCHamiltonian::FullPrecRealType> QMCHamiltonian::mw_evaluateWithToperator(
814  const RefVectorWithLeader<QMCHamiltonian>& ham_list,
816  const RefVectorWithLeader<ParticleSet>& p_list)
817 {
818  for (QMCHamiltonian& ham : ham_list)
819  ham.LocalEnergy = 0.0;
820 
821  auto& ham_leader = ham_list.getLeader();
822  const int num_ham_operators = ham_leader.H.size();
823 
824  const int kinetic_index = 0;
825  {
826  ScopedTimer h_timer(ham_leader.my_timers_[kinetic_index]);
827  const auto HC_list(extract_HC_list(ham_list, kinetic_index));
828  if (ham_leader.mw_res_handle_.getResource().kinetic_listeners_.size() > 0)
829  ham_leader.H[kinetic_index]
830  ->mw_evaluatePerParticleWithToperator(HC_list, wf_list, p_list,
831  ham_leader.mw_res_handle_.getResource().kinetic_listeners_,
832  ham_leader.mw_res_handle_.getResource().ion_kinetic_listeners_);
833  else
834  ham_leader.H[kinetic_index]->mw_evaluateWithToperator(HC_list, wf_list, p_list);
835  for (int iw = 0; iw < ham_list.size(); iw++)
836  updateComponent(HC_list[iw], ham_list[iw], p_list[iw]);
837  }
838 
839  for (int i_ham_op = 1; i_ham_op < num_ham_operators; ++i_ham_op)
840  {
841  ScopedTimer local_timer(ham_leader.my_timers_[i_ham_op]);
842  const auto HC_list(extract_HC_list(ham_list, i_ham_op));
843  if (ham_leader.mw_res_handle_.getResource().potential_listeners_.size() > 0)
844  ham_leader.H[i_ham_op]
845  ->mw_evaluatePerParticleWithToperator(HC_list, wf_list, p_list,
846  ham_leader.mw_res_handle_.getResource().potential_listeners_,
847  ham_leader.mw_res_handle_.getResource().ion_potential_listeners_);
848  else
849  ham_leader.H[i_ham_op]->mw_evaluateWithToperator(HC_list, wf_list, p_list);
850  for (int iw = 0; iw < ham_list.size(); ++iw)
851  updateComponent(HC_list[iw], ham_list[iw], p_list[iw]);
852  }
853 
854  for (int iw = 0; iw < ham_list.size(); iw++)
855  updateKinetic(ham_list[iw], p_list[iw]);
856 
857  std::vector<FullPrecRealType> local_energies(ham_list.size());
858  for (int iw = 0; iw < ham_list.size(); ++iw)
859  local_energies[iw] = ham_list[iw].getLocalEnergy();
860 
861  return local_energies;
862 }
864  TrialWaveFunction& psi,
866  RealType delta)
867 {
868  int nelec = P.getTotalNum();
869  RealType ep(0.0);
870  RealType em(0.0);
871  RealType e0(0.0);
872  for (int iel = 0; iel < nelec; iel++)
873  {
874  for (int dim = 0; dim < OHMMS_DIM; dim++)
875  {
876  RealType r0 = P.R[iel][dim];
877  ep = 0;
878  em = 0;
879  //Plus
880  RealType rp = r0 + delta;
881  P.R[iel][dim] = rp;
882  P.update();
883  psi.evaluateLog(P);
884  ep = evaluateDeterministic(P);
885 
886  //minus
887  RealType rm = r0 - delta;
888  P.R[iel][dim] = rm;
889  P.update();
890  psi.evaluateLog(P);
891  em = evaluateDeterministic(P);
892 
893  Egrad[iel][dim] = (ep - em) / (2.0 * delta);
894  P.R[iel][dim] = r0;
895  P.update();
896  psi.evaluateLog(P);
897  }
898  }
899 }
901  ParticleSet& ions,
902  TrialWaveFunction& psi,
903  ParticleSet::ParticlePos& hf_term,
904  ParticleSet::ParticlePos& pulay_terms,
905  ParticleSet::ParticlePos& wf_grad)
906 {
907  ParticleSet::ParticleGradient wfgradraw_(ions.getTotalNum());
908  wfgradraw_ = 0.0;
909  RealType localEnergy = 0.0;
910 
911  for (int i = 0; i < H.size(); ++i)
912  localEnergy += H[i]->evaluateWithIonDerivs(P, ions, psi, hf_term, pulay_terms);
913 
914  for (int iat = 0; iat < ions.getTotalNum(); iat++)
915  {
916  wfgradraw_[iat] = psi.evalGradSource(P, ions, iat);
917  convertToReal(wfgradraw_[iat], wf_grad[iat]);
918  }
919  return localEnergy;
920 }
921 
923  ParticleSet& ions,
924  TrialWaveFunction& psi,
925  ParticleSet::ParticlePos& hf_term,
926  ParticleSet::ParticlePos& pulay_terms,
927  ParticleSet::ParticlePos& wf_grad)
928 {
929  ParticleSet::ParticleGradient wfgradraw_(ions.getTotalNum());
930  wfgradraw_ = 0.0;
931  RealType localEnergy = 0.0;
932 
933  for (int i = 0; i < H.size(); ++i)
934  localEnergy += H[i]->evaluateWithIonDerivsDeterministic(P, ions, psi, hf_term, pulay_terms);
935 
936  for (int iat = 0; iat < ions.getTotalNum(); iat++)
937  {
938  wfgradraw_[iat] = psi.evalGradSource(P, ions, iat);
939  convertToReal(wfgradraw_[iat], wf_grad[iat]);
940  }
941  return localEnergy;
942 }
943 
945 {
946  FullPrecRealType sum = 0.0;
947  for (int i = 0; i < H.size(); i++)
948  sum += H[i]->getEnsembleAverage();
949  return sum;
950 }
951 
952 /** return pointer to the QMCHamtiltonian with the name
953  *@param aname the name of Hamiltonian
954  *@return the pointer to the named term.
955  *
956  * If not found, return 0
957  */
959 {
960  for (int i = 0; i < H.size(); ++i)
961  if (H[i]->getName() == aname)
962  return H[i].get();
963  for (int i = 0; i < auxH.size(); ++i)
964  if (auxH[i]->getName() == aname)
965  return auxH[i].get();
966  return nullptr;
967 }
968 
970 {
971  RefVector<OperatorBase> components;
972  for (int i = 0; i < H.size(); i++)
973  if (H[i]->dependsOnWaveFunction())
974  components.push_back(*H[i]);
975  return components;
976 }
977 
979 {
980  for (int i = 0; i < H.size(); i++)
981  H[i]->resetTargetParticleSet(P);
982  for (int i = 0; i < auxH.size(); i++)
984 }
985 
987 {
988  for (int i = 0; i < H.size(); i++)
989  H[i]->setRandomGenerator(rng);
990  for (int i = 0; i < auxH.size(); i++)
991  auxH[i]->setRandomGenerator(rng);
992  if (nlpp_ptr)
994 }
995 
997 {
998  if (nlpp_ptr != nullptr)
1000 }
1001 
1002 void QMCHamiltonian::setNonLocalMoves(const std::string& non_local_move_option,
1003  const double tau,
1004  const double alpha,
1005  const double gamma)
1006 {
1007  if (nlpp_ptr != nullptr)
1008  nlpp_ptr->setNonLocalMoves(non_local_move_option, tau, alpha, gamma);
1009 }
1010 
1012 {
1013  if (nlpp_ptr == nullptr)
1014  return 0;
1015  else
1016  return nlpp_ptr->makeNonLocalMovesPbyP(P);
1017 }
1018 
1019 
1022  const RefVectorWithLeader<ParticleSet>& p_list)
1023 {
1024  auto& ham_leader = ham_list.getLeader();
1025 
1026  std::vector<int> num_accepts(ham_list.size(), 0);
1027  if (ham_list.getLeader().nlpp_ptr)
1028  {
1029  for (int iw = 0; iw < ham_list.size(); ++iw)
1030  num_accepts[iw] = ham_list[iw].nlpp_ptr->makeNonLocalMovesPbyP(p_list[iw]);
1031  }
1032  return num_accepts;
1033 }
1034 
1036 {
1037  auto resource_index = collection.addResource(std::make_unique<QMCHamiltonianMultiWalkerResource>());
1038  for (int i = 0; i < H.size(); ++i)
1039  H[i]->createResource(collection);
1040 }
1041 
1043  const RefVectorWithLeader<QMCHamiltonian>& ham_list)
1044 {
1045  auto& ham_leader = ham_list.getLeader();
1046  ham_leader.mw_res_handle_ = collection.lendResource<QMCHamiltonianMultiWalkerResource>();
1047  for (int i_ham_op = 0; i_ham_op < ham_leader.H.size(); ++i_ham_op)
1048  {
1049  const auto HC_list(extract_HC_list(ham_list, i_ham_op));
1050  ham_leader.H[i_ham_op]->acquireResource(collection, HC_list);
1051  }
1052 }
1053 
1055  const RefVectorWithLeader<QMCHamiltonian>& ham_list)
1056 {
1057  auto& ham_leader = ham_list.getLeader();
1058  collection.takebackResource(ham_leader.mw_res_handle_);
1059  for (int i_ham_op = 0; i_ham_op < ham_leader.H.size(); ++i_ham_op)
1060  {
1061  const auto HC_list(extract_HC_list(ham_list, i_ham_op));
1062  ham_leader.H[i_ham_op]->releaseResource(collection, HC_list);
1063  }
1064 }
1065 
1066 std::unique_ptr<QMCHamiltonian> QMCHamiltonian::makeClone(ParticleSet& qp, TrialWaveFunction& psi) const
1067 {
1068  auto myclone = std::make_unique<QMCHamiltonian>(myName);
1069  for (int i = 0; i < H.size(); ++i)
1070  H[i]->add2Hamiltonian(qp, psi, *myclone);
1071  for (int i = 0; i < auxH.size(); ++i)
1072  auxH[i]->add2Hamiltonian(qp, psi, *myclone);
1073  //sync indices
1074  myclone->resetObservables(myIndex, numCollectables);
1075  //Hamiltonian needs to make sure qp.Collectables are the same as defined by the original Hamiltonian
1076  if (numCollectables)
1077  {
1078  qp.Collectables.clear();
1080  }
1081  //Assume tau is correct for the Kinetic energy operator and assign to the rest of the clones
1082  //Return_t tau = H[0]->Tau;
1083  //myclone->setTau(tau);
1084  return myclone;
1085 }
1086 
1088  int id)
1089 {
1090  RefVectorWithLeader<OperatorBase> HC_list(*ham_list.getLeader().H[id]);
1091  HC_list.reserve(ham_list.size());
1092  for (QMCHamiltonian& H : ham_list)
1093  HC_list.push_back(*(H.H[id]));
1094  return HC_list;
1095 }
1096 
1098  ParticleSet& ions,
1099  TrialWaveFunction& psi_in,
1100  TWFFastDerivWrapper& psi_wrapper_in,
1102  ParticleSet::ParticlePos& wf_grad)
1103 {
1105  P.update();
1106  //resize everything;
1107  const int ngroups = psi_wrapper_in.numGroups();
1108 
1109  std::vector<ValueMatrix> X_; //Working arrays for derivatives
1110  std::vector<ValueMatrix> Minv_; //Working array for derivatives.
1111  std::vector<ValueMatrix> B_;
1112  std::vector<ValueMatrix> B_gs_;
1113  std::vector<ValueMatrix> M_;
1114  std::vector<ValueMatrix> M_gs_;
1115 
1116  std::vector<std::vector<ValueMatrix>> dM_;
1117  std::vector<std::vector<ValueMatrix>> dM_gs_;
1118  std::vector<std::vector<ValueMatrix>> dB_;
1119  std::vector<std::vector<ValueMatrix>> dB_gs_;
1120 
1121  {
1122  M_.resize(ngroups);
1123  M_gs_.resize(ngroups);
1124  X_.resize(ngroups);
1125  B_.resize(ngroups);
1126  B_gs_.resize(ngroups);
1127  Minv_.resize(ngroups);
1128 
1129  for (int gid = 0; gid < ngroups; gid++)
1130  {
1131  const int sid = psi_wrapper_in.getTWFGroupIndex(gid);
1132  const int norbs = psi_wrapper_in.numOrbitals(sid);
1133  const int first = P.first(gid);
1134  const int last = P.last(gid);
1135  const int nptcls = last - first;
1136 
1137  M_[sid].resize(nptcls, norbs);
1138  B_[sid].resize(nptcls, norbs);
1139 
1140  M_gs_[sid].resize(nptcls, nptcls);
1141  Minv_[sid].resize(nptcls, nptcls);
1142  B_gs_[sid].resize(nptcls, nptcls);
1143  X_[sid].resize(nptcls, nptcls);
1144  }
1145 
1146  dM_.resize(OHMMS_DIM);
1147  dM_gs_.resize(OHMMS_DIM);
1148  dB_.resize(OHMMS_DIM);
1149  dB_gs_.resize(OHMMS_DIM);
1150 
1151  for (int idim = 0; idim < OHMMS_DIM; idim++)
1152  {
1153  dM_[idim].resize(ngroups);
1154  dB_[idim].resize(ngroups);
1155  dM_gs_[idim].resize(ngroups);
1156  dB_gs_[idim].resize(ngroups);
1157 
1158  for (int gid = 0; gid < ngroups; gid++)
1159  {
1160  const int sid = psi_wrapper_in.getTWFGroupIndex(gid);
1161  const int norbs = psi_wrapper_in.numOrbitals(sid);
1162  const int first = P.first(gid);
1163  const int last = P.last(gid);
1164  const int nptcls = last - first;
1165 
1166  dM_[idim][sid].resize(nptcls, norbs);
1167  dB_[idim][sid].resize(nptcls, norbs);
1168  dM_gs_[idim][sid].resize(nptcls, nptcls);
1169  dB_gs_[idim][sid].resize(nptcls, nptcls);
1170  }
1171  }
1172  psi_wrapper_in.wipeMatrices(M_);
1173  psi_wrapper_in.wipeMatrices(M_gs_);
1174  psi_wrapper_in.wipeMatrices(X_);
1175  psi_wrapper_in.wipeMatrices(B_);
1176  psi_wrapper_in.wipeMatrices(Minv_);
1177  psi_wrapper_in.wipeMatrices(B_gs_);
1178 
1179  for (int idim = 0; idim < OHMMS_DIM; idim++)
1180  {
1181  psi_wrapper_in.wipeMatrices(dM_[idim]);
1182  psi_wrapper_in.wipeMatrices(dM_gs_[idim]);
1183  psi_wrapper_in.wipeMatrices(dB_[idim]);
1184  psi_wrapper_in.wipeMatrices(dB_gs_[idim]);
1185  }
1186  }
1187  ParticleSet::ParticleGradient wfgradraw_(ions.getTotalNum());
1190  ParticleSet::ParticleGradient dedr_complex(ions.getTotalNum());
1191  ParticleSet::ParticlePos pulayterms_(ions.getTotalNum());
1192  ParticleSet::ParticlePos hfdiag_(ions.getTotalNum());
1193  wfgradraw_ = 0.0;
1194  RealType localEnergy = 0.0;
1195 
1196  {
1197  psi_wrapper_in.getM(P, M_);
1198  }
1199  {
1200  psi_wrapper_in.getGSMatrices(M_, M_gs_);
1201  psi_wrapper_in.invertMatrices(M_gs_, Minv_);
1202  }
1203  //Build B-matrices. Only for non-diagonal observables right now.
1204  for (int i = 0; i < H.size(); ++i)
1205  {
1206  if (H[i]->dependsOnWaveFunction())
1207  {
1208  H[i]->evaluateOneBodyOpMatrix(P, psi_wrapper_in, B_);
1209  }
1210  else
1211  {
1212  localEnergy += H[i]->evaluateWithIonDerivsDeterministic(P, ions, psi_in, hfdiag_, pulayterms_);
1213  }
1214  }
1215 
1216  ValueType nondiag_cont = 0.0;
1217  RealType nondiag_cont_re = 0.0;
1218 
1219  psi_wrapper_in.getGSMatrices(B_, B_gs_);
1220  nondiag_cont = psi_wrapper_in.trAB(Minv_, B_gs_);
1221  convertToReal(nondiag_cont, nondiag_cont_re);
1222  localEnergy += nondiag_cont_re;
1223 
1224  {
1225  psi_wrapper_in.buildX(Minv_, B_gs_, X_);
1226  }
1227  //And now we compute the 3N force derivatives. 3 at a time for each atom.
1228  for (int iat = 0; iat < ions.getTotalNum(); iat++)
1229  {
1230  //The total wavefunction derivative has two contributions. One from determinantal piece,
1231  //One from the Jastrow. Jastrow is easy, so we evaluate it here, then add on the
1232  //determinantal piece at the end of this block.
1233 
1234  wfgradraw_[iat] = psi_wrapper_in.evaluateJastrowGradSource(P, ions, iat);
1235  for (int idim = 0; idim < OHMMS_DIM; idim++)
1236  {
1237  psi_wrapper_in.wipeMatrices(dM_[idim]);
1238  psi_wrapper_in.wipeMatrices(dM_gs_[idim]);
1239  psi_wrapper_in.wipeMatrices(dB_[idim]);
1240  psi_wrapper_in.wipeMatrices(dB_gs_[idim]);
1241  }
1242 
1243  {
1244  //ion derivative of slater matrix.
1245  psi_wrapper_in.getIonGradM(P, ions, iat, dM_);
1246  }
1247  for (int i = 0; i < H.size(); ++i)
1248  {
1249  if (H[i]->dependsOnWaveFunction())
1250  {
1251  H[i]->evaluateOneBodyOpMatrixForceDeriv(P, ions, psi_wrapper_in, iat, dB_);
1252  }
1253  }
1254 
1255  for (int idim = 0; idim < OHMMS_DIM; idim++)
1256  {
1257  psi_wrapper_in.getGSMatrices(dB_[idim], dB_gs_[idim]);
1258  psi_wrapper_in.getGSMatrices(dM_[idim], dM_gs_[idim]);
1259 
1260  ValueType fval = 0.0;
1261  fval = psi_wrapper_in.computeGSDerivative(Minv_, X_, dM_gs_[idim], dB_gs_[idim]);
1262  dedr_complex[iat][idim] = fval;
1263 
1264  ValueType wfcomp = 0.0;
1265  wfcomp = psi_wrapper_in.trAB(Minv_, dM_gs_[idim]);
1266  wfgradraw_[iat][idim] += wfcomp; //The determinantal piece of the WF grad.
1267  }
1268  convertToReal(dedr_complex[iat], dEdR[iat]);
1269  convertToReal(wfgradraw_[iat], wf_grad[iat]);
1270  }
1271  dEdR += hfdiag_;
1272  return localEnergy;
1273 }
1274 } // namespace qmcplusplus
RealType evaluateLog(ParticleSet &P)
evalaute the log (internally gradients and laplacian) of the trial wavefunction.
int addObservables(ParticleSet &P)
add each term to the PropertyList for averages
FullPrecRealType evaluateIonDerivsDeterministicFast(ParticleSet &P, ParticleSet &ions, TrialWaveFunction &psi_in, TWFFastDerivWrapper &psi_wrapper, ParticleSet::ParticlePos &dedr, ParticleSet::ParticlePos &wf_grad)
evaluate local energy and derivatives w.r.t ionic coordinates, but deterministically.
void registerCollectables(std::vector< ObservableHelper > &h5desc, hdf_archive &file) const
register collectables so that their averages can be dumped to hdf5
Array< TraceInt, 1 > * gen_sample
void informOperatorsOfListener()
Some Hamiltonian components need to be informed that they are in a per particle reporting situation s...
Evaluate the L2 potentials around each ion.
Definition: L2Potential.h:57
size_type size() const
return the size of the data
Definition: PooledData.h:48
void setNonLocalMoves(xmlNodePtr cur)
set non local moves options
NewTimer & ham_timer_
Total timer for H evaluation.
size_t addResource(std::unique_ptr< Resource > &&res, bool noprint=false)
std::ostream & app_warning()
Definition: OutputManager.h:69
void takebackResource(ResourceHandle< RS > &res_handle)
IndexType numGroups() const
These are query functions to the internal state of various groups and SPOSet info.
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
bool isQuantumClassical() const noexcept
Array< TraceInt, 1 > * step_sample
Array< TraceInt, 1 > * pid_sample
timer_manager class.
static std::vector< QMCHamiltonian::FullPrecRealType > mw_evaluateWithToperator(const RefVectorWithLeader< QMCHamiltonian > &ham_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list)
batched version of evaluate Local energy with Toperators updated.
bool streaming_array(const std::string &name)
Definition: TraceManager.h:249
RefVector< OperatorBase > getTWFDependentComponents()
return components, auxH not included, depending on TWF.
std::vector< ListenerVector< RealType > > ion_kinetic_listeners_
NewTimer & eval_vals_derivs_timer_
Total timer for H evaluation.
void addOperator(std::unique_ptr< OperatorBase > &&h, const std::string &aname, bool physical=true)
add an operator
OperatorBase * getHamiltonian(const std::string &aname)
return OperatorBase with the name aname
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
void addOperatorType(const std::string &name, const std::string &type)
record the name-type pair of an operator
if(c->rank()==0)
bool get(std::ostream &os) const
QMCTraits::FullPrecRealType FullPrecRealType
ValueType trAB(const std::vector< ValueMatrix > &A, const std::vector< ValueMatrix > &B)
Returns Tr(A*B).
FullPrecRealType evaluateValueAndDerivatives(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi)
evaluate energy and derivatives wrt to the variables
FullPrecRealType KineticEnergy
Current Kinetic Energy.
ResourceHandle< QMCHamiltonianMultiWalkerResource > mw_res_handle_
std::vector< std::reference_wrapper< NewTimer > > my_timers_
timers for H components
void convertToReal(const T1 &in, T2 &out)
generic conversion from type T1 to type T2 using implicit conversion
Definition: ConvertToReal.h:32
GradType evaluateJastrowGradSource(ParticleSet &P, ParticleSet &source, const int iat) const
Return ionic gradient of J(r).
Collection of Local Energy Operators.
An object of this type is a listener expecting a callback to the report function with a vector of val...
Definition: Listener.hpp:38
OperatorBase::RealType RealType
static void updateComponent(OperatorBase &op, QMCHamiltonian &ham, ParticleSet &pset)
accumulate local energy and update Observables and PropertyList
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
static void mw_registerLocalEnergyListener(QMCHamiltonian &ham_leader, ListenerVector< RealType > listener)
IndexType numOrbitals(const IndexType sid) const
int current_step
current MC step
Definition: ParticleSet.h:134
void update(bool skipSK=false)
update the internal data
Array< TraceInt, D > * checkout_int(const std::string &name, int n1=1, int n2=0, int n3=0, int n4=0)
NonLocalECPotential * nlpp_ptr
pointer to NonLocalECP
Attaches a unit to a Vector for IO.
void resetObservables(int start, int ncollects)
reset Observables and counters
TWFFastDerivWrapper is a wrapper class for TrialWavefunction that provides separate and low level acc...
void rewind(size_type cur=0)
set the Current to a cursor
Definition: PooledData.h:56
void getIonGradM(const ParticleSet &P, const ParticleSet &source, const int iat, std::vector< std::vector< ValueMatrix >> &dmvec) const
Returns x,y,z components of ion gradient of slater matrices.
ValueType computeGSDerivative(const std::vector< ValueMatrix > &Minv, const std::vector< ValueMatrix > &X, const std::vector< ValueMatrix > &dM, const std::vector< ValueMatrix > &dB) const
Calculates derivative of observable via Tr[M^{-1} dB - X * dM ].
void getGSMatrices(const std::vector< ValueMatrix > &A, std::vector< ValueMatrix > &Aslice) const
Takes sub matrices of full SPOSet quantities (evaluated on all particles and all orbitals), consistent with ground state occupations.
void createResource(ResourceCollection &collection) const
initialize a shared resource and hand it to a collection
#define OHMMS_DIM
Definition: config.h:64
static std::vector< QMCHamiltonian::FullPrecRealType > mw_evaluate(const RefVectorWithLeader< QMCHamiltonian > &ham_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list)
batched version of evaluate for LocalEnergy
static std::vector< QMCHamiltonian::FullPrecRealType > mw_evaluateValueAndDerivatives(const RefVectorWithLeader< QMCHamiltonian > &ham_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, const opt_variables_type &optvars, RecordArray< ValueType > &dlogpsi, RecordArray< ValueType > &dhpsioverpsi)
PropertySetType PropertyList
name-value map of Walker Properties
Definition: ParticleSet.h:112
bool streaming(const std::string &name)
Definition: TraceManager.h:256
NewTimer & eval_ion_derivs_fast_timer_
Total timer for H ion deriv evaluation;.
static void mw_registerKineticListener(QMCHamiltonian &ham_leader, ListenerVector< RealType > listener)
Listener Registration This must be called on a QMCHamiltonian that has acquired multiwalker resources...
omp_int_t omp_get_thread_num()
Definition: OpenMP.h:25
Array< TraceReal, 1 > * weight_sample
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
int myIndex
starting index
int makeNonLocalMovesPbyP(ParticleSet &P)
make non local moves with particle-by-particle moves
FullPrecRealType LocalEnergy
Current Local Energy.
int numCollectables
starting index
FullPrecRealType evaluateWithToperator(ParticleSet &P)
evaluate Local energy with Toperators updated.
std::vector< ListenerVector< RealType > > kinetic_listeners_
void make_combined_trace(const std::string &name, std::vector< std::string > &names)
int add(const std::string &aname)
TraceRequest request
traces variables
void collect_walker_traces(Walker_t &walker, int step)
collect walker trace data
static void mw_registerLocalIonPotentialListener(QMCHamiltonian &ham_leader, ListenerVector< RealType > listener)
void clear()
clear the data and set Current=0
Definition: PooledData.h:65
void contribute_scalar(const std::string &name, bool default_quantity=false)
Definition: TraceManager.h:189
NewTimer & createGlobalTimer(const std::string &myname, timer_levels mylevel)
bool isQuantum() const noexcept
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
GradType evalGradSource(ParticleSet &P, ParticleSet &source, int iat)
Returns the logarithmic gradient of the trial wave function with respect to the iat^th atom of the so...
bool isClassicalClassical() const noexcept
void getM(const ParticleSet &P, std::vector< ValueMatrix > &mmat) const
Returns the non-rectangular slater matrices M_ij=phi_j(r_i) (N_particle x N_orbs) for each species gr...
Array< TraceInt, 1 > * age_sample
FullPrecRealType evaluateIonDerivsDeterministic(ParticleSet &P, ParticleSet &ions, TrialWaveFunction &psi, ParticleSet::ParticlePos &hf_terms, ParticleSet::ParticlePos &pulay_terms, ParticleSet::ParticlePos &wf_grad)
evaluate local energy and derivatives w.r.t ionic coordinates, but deterministically.
FullPrecRealType evaluateDeterministic(ParticleSet &P)
evaluate Local Energy deterministically.
ParticlePos R
Position.
Definition: ParticleSet.h:79
FullPrecRealType getEnsembleAverage()
return an average value of the LocalEnergy
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
void user_report(std::string pad=" ")
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
L2Potential * l2_ptr
pointer to L2Potential
FullPrecRealType getLocalEnergy()
const std::string myName
getName is in the way
void incorporate(TraceRequest &other)
Definition: TraceManager.h:282
const std::string & getName() const
static void updateKinetic(QMCHamiltonian &ham, ParticleSet &pset)
extract kinetic and potential energies.
void evaluateElecGrad(ParticleSet &P, TrialWaveFunction &psi, ParticleSet::ParticlePos &EGrad, RealType delta=1e-5)
Evaluate the electron gradient of the local energy.
Return_t getValue() const noexcept
get a copy of value_
void setNonLocalMoves(xmlNodePtr cur)
set non local moves options
static std::vector< int > mw_makeNonLocalMoves(const RefVectorWithLeader< QMCHamiltonian > &ham_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list)
void resize(size_type n, T val=T())
resize
Definition: PooledData.h:77
Buffer_t Collectables
observables in addition to those registered in Properties/PropertyList
Definition: ParticleSet.h:126
Array< TraceReal, D > * checkout_real(const std::string &name, int n1=1, int n2=0, int n3=0, int n4=0)
const std::string & getOperatorType(const std::string &name)
return type of named H element or fail
void initialize_traces(TraceManager &tm, ParticleSet &P)
initialize trace data
Declaration of a TrialWaveFunction.
void auxHevaluate(ParticleSet &P)
An abstract class for Local Energy operators.
Definition: OperatorBase.h:59
Array< TraceReal, 2 > * position_sample
void contribute_combined(const std::string &name, std::vector< std::string > &deps, bool scalar=false, bool array=false, bool default_quantity=false)
Definition: TraceManager.h:207
std::vector< std::reference_wrapper< T > > RefVector
void rejectedMove(ParticleSet &P, Walker_t &ThisWalker)
Looks like a hack see DMCBatched.cpp and DMC.cpp weight is used like temporary flag from DMC...
static void acquireResource(ResourceCollection &collection, const RefVectorWithLeader< QMCHamiltonian > &ham_list)
acquire external resource Note: use RAII ResourceCollectionLock whenever possible ...
void relay_stream_info(TraceRequest &other)
Definition: TraceManager.h:371
void registerObservables(std::vector< ObservableHelper > &h5desc, hdf_archive &file) const
register obsevables so that their averages can be dumped to hdf5
static void releaseResource(ResourceCollection &collection, const RefVectorWithLeader< QMCHamiltonian > &ham_list)
release external resource Note: use RAII ResourceCollectionLock whenever possible ...
std::vector< std::unique_ptr< OperatorBase > > H
vector of Hamiltonians
void setRandomGenerator(RandomBase< FullPrecRealType > *rng) override
set the internal RNG pointer as the given pointer
virtual void setParticlePropertyList(PropertySetType &plist, int offset)
Evaluate the semi local potentials.
Class to represent a many-body trial wave function.
bool isQuantumQuantum() const noexcept
static void mw_registerLocalPotentialListener(QMCHamiltonian &ham_leader, ListenerVector< RealType > listener)
PropertySetType Observables
data
std::vector< ListenerVector< RealType > > ion_potential_listeners_
std::vector< ListenerVector< RealType > > potential_listeners_
FullPrecRealType evaluate(ParticleSet &P)
evaluate Local Energy
std::string getName() const noexcept
getter a copy of my_name_, rvalue small string optimization
void contribute_array(const std::string &name, bool default_quantity=false)
Definition: TraceManager.h:198
std::vector< std::unique_ptr< OperatorBase > > auxH
vector of Hamiltonians
void updateSource(ParticleSet &s)
remove a named Hamiltonian from the list
void finalize_traces()
finalize trace data
int makeNonLocalMoves(ParticleSet &P)
make non local moves
void wipeMatrices(std::vector< ValueMatrix > &A)
Goes through a list of matrices and zeros them out.
void resetTargetParticleSet(ParticleSet &P)
bool isClassical() const noexcept
virtual void setObservables(PropertySetType &plist)
Set the values evaluated by this object to plist Default implementation is to assign Value which is u...
Array< TraceInt, 1 > * mult_sample
ResourceHandle< RS > lendResource()
IndexType getTWFGroupIndex(const IndexType gid) const
Takes particle set groupID and returns the TWF internal index for it.
std::map< std::string, std::string > operator_types
types of component operators
OperatorBase::ValueType ValueType
FullPrecRealType evaluateVariableEnergy(ParticleSet &P, bool free_nlpp)
evaluate energy
void buildX(const std::vector< ValueMatrix > &Minv, const std::vector< ValueMatrix > &B, std::vector< ValueMatrix > &X)
Build the auxiliary X=M^-1 B M^-1 matrix.
Array< TraceInt, 1 > * id_sample
void setRandomGenerator(RandomBase< FullPrecRealType > *rng)
static RefVectorWithLeader< OperatorBase > extract_HC_list(const RefVectorWithLeader< QMCHamiltonian > &ham_list, int id)
std::unique_ptr< QMCHamiltonian > makeClone(ParticleSet &qp, TrialWaveFunction &psi) const
return a clone
void invertMatrices(const std::vector< ValueMatrix > &M, std::vector< ValueMatrix > &Minv)
Helper function that inverts all slater matrices in our species list.
A container class to represent a walker.
Definition: Walker.h:49
std::unique_ptr< Resource > makeClone() const override
Declaration of QMCHamiltonian.
bool isnan(float a)
return true if the value is NaN.
Definition: math.cpp:18
FullPrecRealType evaluateIonDerivs(ParticleSet &P, ParticleSet &ions, TrialWaveFunction &psi, ParticleSet::ParticlePos &hf_terms, ParticleSet::ParticlePos &pulay_terms, ParticleSet::ParticlePos &wf_grad)
evaluate local energy and derivatives w.r.t ionic coordinates.
QMCHamiltonian(const std::string &aname="psi0")
constructor