QMCPACK
HamiltonianFactory.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: John R. Gergely, University of Illinois at Urbana-Champaign
8 // Bryan Clark, bclark@Princeton.edu, Princeton University
9 // D.C. Yang, University of Illinois at Urbana-Champaign
10 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
11 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
12 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
13 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
15 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
16 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
17 //
18 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
19 //////////////////////////////////////////////////////////////////////////////////////
20 
21 
22 /**@file HamiltonianFactory.cpp
23  *@brief Definition of a HamiltonianFactory
24  */
25 #include "HamiltonianFactory.h"
43 #if !defined(REMOVE_TRACEMANAGER)
46 #endif
47 #if OHMMS_DIM == 3
50 #endif
51 #include "QMCHamiltonians/SkPot.h"
52 #include "OhmmsData/AttributeSet.h"
53 
54 namespace qmcplusplus
55 {
56 HamiltonianFactory::HamiltonianFactory(const std::string& hName,
57  ParticleSet& qp,
58  const PSetMap& pset,
59  const PsiPoolType& oset,
60  Communicate* c)
61  : MPIObjectBase(c),
62  targetH(std::make_unique<QMCHamiltonian>(hName)),
63  targetPtcl(qp),
64  ptclPool(pset),
65  psiPool(oset),
66  psiName("psi0")
67 {
68  //PBCType is zero or 1 but should be generalized
69  PBCType = targetPtcl.getLattice().SuperCellEnum;
70  ClassName = "HamiltonianFactory";
71  myName = hName;
73 }
74 
75 /** main hamiltonian build function
76  * @param cur element node <hamiltonian/>
77  * @param buildtree if true, build xml tree for a reuse
78  *
79  * A valid hamiltonian node contains
80  * \xmlonly
81  * <hamiltonian target="e">
82  * <pairpot type="coulomb" name="ElecElec" source="e"/>
83  * <pairpot type="coulomb" name="IonElec" source="i"/>
84  * <pairpot type="coulomb" name="IonIon" source="i" target="i"/>
85  * </hamiltonian>
86  * \endxmlonly
87  */
88 bool HamiltonianFactory::build(xmlNodePtr cur)
89 {
90  if (cur == NULL)
91  return false;
92 
93  app_summary() << std::endl;
94  app_summary() << " Hamiltonian and observables" << std::endl;
95  app_summary() << " ---------------------------" << std::endl;
96  app_summary() << " Name: " << myName << std::endl;
97  app_summary() << std::endl;
98 
99  std::string htype("generic"), source("i"), defaultKE("yes");
100  OhmmsAttributeSet hAttrib;
101  hAttrib.add(htype, "type");
102  hAttrib.add(source, "source");
103  hAttrib.add(defaultKE, "default");
104  hAttrib.put(cur);
105  renameProperty(source);
106  auto psi_it(psiPool.find(psiName));
107  if (psi_it == psiPool.end())
108  APP_ABORT("Unknown psi \"" + psiName + "\" for target Psi");
109  TrialWaveFunction* targetPsi = psi_it->second.get();
110  // KineticEnergy must be the first element in the hamiltonian array.
111  if (defaultKE != "no")
112  targetH->addOperator(std::make_unique<BareKineticEnergy>(targetPtcl, *targetPsi), "Kinetic");
113 
114  // Virtual particle sets only need to carry distance tables used by the wavefunction.
115  // Other Hamiltonian elements or estimators may add distance tables in particle sets.
116  // Process pseudopotentials first to minimize the needed distance tables in virtual particle sets.
117  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
118  if (cname == "pairpot" && getXMLAttributeValue(element, "type") == "pseudo")
119  addPseudoPotential(element);
120  });
121 
122  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
123  std::string notype = "0";
124  std::string noname = "any";
125  std::string potType(notype);
126  std::string potName(noname);
127  std::string potUnit("hartree");
128  std::string estType("coulomb");
129  std::string sourceInp(targetPtcl.getName());
130  std::string targetInp(targetPtcl.getName());
131  OhmmsAttributeSet attrib;
132  attrib.add(sourceInp, "source");
133  attrib.add(sourceInp, "sources");
134  attrib.add(targetInp, "target");
135  attrib.add(potType, "type");
136  attrib.add(potName, "name");
137  attrib.add(potUnit, "units");
138  attrib.add(estType, "potential");
139  attrib.put(element);
140  renameProperty(sourceInp);
141  renameProperty(targetInp);
142 
143  int nham = targetH->total_size();
144  if (cname == "pairpot")
145  {
146  if (potType == "coulomb")
147  addCoulombPotential(element);
148  else if (potType == "skpot")
149  {
150  std::unique_ptr<SkPot> hs = std::make_unique<SkPot>(targetPtcl);
151  hs->put(element);
152  targetH->addOperator(std::move(hs), "SkPot", true);
153  }
154 #if OHMMS_DIM == 3
155  else if (potType == "MPC" || potType == "mpc")
156  addMPCPotential(element);
157 #endif
158  }
159  else if (cname == "constant")
160  {
161  //just to support old input
162  if (potType == "coulomb")
163  addCoulombPotential(element);
164  }
165  else if (cname == "extpot")
166  {
167  if (potType == "harmonic_ext" || potType == "HarmonicExt")
168  {
169  std::unique_ptr<HarmonicExternalPotential> hs = std::make_unique<HarmonicExternalPotential>(targetPtcl);
170  hs->put(element);
171  targetH->addOperator(std::move(hs), "HarmonicExt", true);
172  }
173  if (potType == "grid")
174  {
175  std::unique_ptr<GridExternalPotential> hs = std::make_unique<GridExternalPotential>(targetPtcl);
176  hs->put(element);
177  targetH->addOperator(std::move(hs), "Grid", true);
178  }
179  }
180  else if (cname == "estimator")
181  {
182  if (potType == "flux")
183  targetH->addOperator(std::make_unique<ConservedEnergy>(), potName, false);
184  else if (potType == "specieskinetic")
185  {
186  std::unique_ptr<SpeciesKineticEnergy> apot = std::make_unique<SpeciesKineticEnergy>(targetPtcl);
187  apot->put(element);
188  targetH->addOperator(std::move(apot), potName, false);
189  }
190  else if (potType == "latticedeviation")
191  {
192  // find target particle set
193  auto pit(ptclPool.find(targetInp));
194  if (pit == ptclPool.end())
195  {
196  APP_ABORT("Unknown target \"" + targetInp + "\" for LatticeDeviation.");
197  }
198 
199  // find source particle set
200  auto spit(ptclPool.find(sourceInp));
201  if (spit == ptclPool.end())
202  {
203  APP_ABORT("Unknown source \"" + sourceInp + "\" for LatticeDeviation.");
204  }
205 
206  // read xml node
207  OhmmsAttributeSet local_attrib;
208  std::string target_group, source_group;
209  local_attrib.add(target_group, "tgroup");
210  local_attrib.add(source_group, "sgroup");
211  local_attrib.put(element);
212 
213  std::unique_ptr<LatticeDeviationEstimator> apot =
214  std::make_unique<LatticeDeviationEstimator>(*pit->second, *spit->second, target_group, source_group);
215  apot->put(element);
216  targetH->addOperator(std::move(apot), potName, false);
217  }
218  else if (potType == "Force")
219  addForceHam(element);
220  else if (potType == "gofr")
221  {
222  std::unique_ptr<PairCorrEstimator> apot = std::make_unique<PairCorrEstimator>(targetPtcl, sourceInp);
223  apot->put(element);
224  targetH->addOperator(std::move(apot), potName, false);
225  }
226  else if (potType == "density")
227  {
228  std::unique_ptr<DensityEstimator> apot = std::make_unique<DensityEstimator>(targetPtcl);
229  apot->put(element);
230  targetH->addOperator(std::move(apot), potName, false);
231  }
232  else if (potType == "spindensity")
233  {
234  app_log() << " Adding SpinDensity" << std::endl;
235  std::unique_ptr<SpinDensity> apot = std::make_unique<SpinDensity>(targetPtcl);
236  apot->put(element);
237  targetH->addOperator(std::move(apot), potName, false);
238  }
239  else if (potType == "structurefactor")
240  {
241  app_log() << " Adding StaticStructureFactor" << std::endl;
242  std::unique_ptr<StaticStructureFactor> apot = std::make_unique<StaticStructureFactor>(targetPtcl);
243  apot->put(element);
244  targetH->addOperator(std::move(apot), potName, false);
245  }
246  else if (potType == "selfhealingoverlap" || potType == "SelfHealingOverlap")
247  {
248  app_log() << " Adding SelfHealingOverlap" << std::endl;
249  std::unique_ptr<SelfHealingOverlapLegacy> apot = std::make_unique<SelfHealingOverlapLegacy>(*targetPsi);
250  apot->put(element);
251  targetH->addOperator(std::move(apot), potName, false);
252  }
253  else if (potType == "orbitalimages")
254  {
255  app_log() << " Adding OrbitalImages" << std::endl;
256  std::unique_ptr<OrbitalImages> apot =
257  std::make_unique<OrbitalImages>(targetPtcl, ptclPool, myComm, targetPsi->getSPOMap());
258  apot->put(element);
259  targetH->addOperator(std::move(apot), potName, false);
260  }
261 #if !defined(REMOVE_TRACEMANAGER)
262  else if (potType == "energydensity" || potType == "EnergyDensity")
263  {
264  app_log() << " Adding EnergyDensityEstimator" << std::endl;
265  std::unique_ptr<EnergyDensityEstimator> apot = std::make_unique<EnergyDensityEstimator>(ptclPool, defaultKE);
266  apot->put(element);
267  targetH->addOperator(std::move(apot), potName, false);
268  }
269  else if (potType == "dm1b")
270  {
271  app_log() << " Adding DensityMatrices1B" << std::endl;
272  std::string source = "";
273  OhmmsAttributeSet attrib;
274  attrib.add(source, "source");
275  attrib.put(element);
276  auto pit(ptclPool.find(source));
277  ParticleSet* Pc = nullptr;
278  if (source == "")
279  Pc = nullptr;
280  else if (pit != ptclPool.end())
281  Pc = pit->second.get();
282  else
283  {
284  APP_ABORT("Unknown source \"" + source + "\" for DensityMatrices1B");
285  }
286  std::unique_ptr<DensityMatrices1B> apot = std::make_unique<DensityMatrices1B>(targetPtcl, *targetPsi, Pc);
287  apot->put(element);
288  targetH->addOperator(std::move(apot), potName, false);
289  }
290 #endif
291  else if (potType == "sk")
292  {
293  if (PBCType) //only if perioidic
294  {
295  std::unique_ptr<SkEstimator> apot = std::make_unique<SkEstimator>(targetPtcl);
296  apot->put(element);
297  targetH->addOperator(std::move(apot), potName, false);
298  app_log() << "Adding S(k) estimator" << std::endl;
299  }
300  }
301 #if OHMMS_DIM == 3
302  else if (potType == "chiesa")
303  {
304  std::string PsiName = "psi0";
305  std::string SourceName = "e";
306  OhmmsAttributeSet hAttrib;
307  hAttrib.add(PsiName, "psi");
308  hAttrib.add(SourceName, "source");
309  hAttrib.put(element);
310  auto pit(ptclPool.find(SourceName));
311  if (pit == ptclPool.end())
312  {
313  APP_ABORT("Unknown source \"" + SourceName + "\" for Chiesa correction.");
314  }
315  ParticleSet& source = *pit->second;
316  auto psi_it(psiPool.find(PsiName));
317  if (psi_it == psiPool.end())
318  {
319  APP_ABORT("Unknown psi \"" + PsiName + "\" for Chiesa correction.");
320  }
321  const TrialWaveFunction& psi = *psi_it->second;
322  std::unique_ptr<ChiesaCorrection> chiesa = std::make_unique<ChiesaCorrection>(source, psi);
323  targetH->addOperator(std::move(chiesa), "KEcorr", false);
324  }
325  else if (potType == "skall")
326  {
327  std::string SourceName = "";
328  OhmmsAttributeSet attrib;
329  attrib.add(SourceName, "source");
330  attrib.put(element);
331 
332  auto pit(ptclPool.find(SourceName));
333  if (pit == ptclPool.end())
334  {
335  APP_ABORT("Unknown source \"" + SourceName + "\" for SkAll.");
336  }
337 
338  if (PBCType)
339  {
340  std::unique_ptr<SkAllEstimator> apot = std::make_unique<SkAllEstimator>(*pit->second, targetPtcl);
341  apot->put(element);
342  targetH->addOperator(std::move(apot), potName, false);
343  app_log() << "Adding S(k) ALL estimator" << std::endl;
344  }
345  }
346 
347 #endif
348  else if (potType == "Pressure")
349  {
350  if (estType == "coulomb")
351  {
352  std::unique_ptr<Pressure> BP = std::make_unique<Pressure>(targetPtcl);
353  BP->put(element);
354  targetH->addOperator(std::move(BP), "Pressure", false);
355  int nlen(100);
356  attrib.add(nlen, "truncateSum");
357  attrib.put(element);
358  // DMCPressureCorr* DMCP = new DMCPressureCorr(targetPtcl,nlen);
359  // targetH->addOperator(DMCP,"PressureSum",false);
360  }
361  }
362  else if (potType == "momentum")
363  {
364  app_log() << " Adding Momentum Estimator" << std::endl;
365  std::string PsiName = "psi0";
366  OhmmsAttributeSet hAttrib;
367  hAttrib.add(PsiName, "wavefunction");
368  hAttrib.put(element);
369  auto psi_it(psiPool.find(PsiName));
370  if (psi_it == psiPool.end())
371  {
372  APP_ABORT("Unknown psi \"" + PsiName + "\" for momentum.");
373  }
374  std::unique_ptr<MomentumEstimator> ME = std::make_unique<MomentumEstimator>(targetPtcl, *psi_it->second);
375  bool rt(myComm->rank() == 0);
376  ME->putSpecial(element, targetPtcl, rt);
377  targetH->addOperator(std::move(ME), "MomentumEstimator", false);
378  }
379  }
380 
381  if (nham < targetH->total_size()) //if(cname!="text" && cname !="comment")
382  {
383  if (potName == noname)
384  {
385  potName = potType;
386  app_log() << "Provide name for hamiltonian element for type " << potType << std::endl;
387  }
388  //APP_ABORT("HamiltonianFactory::build\n a name for operator of type "+cname+" "+potType+" must be provided in the xml input");
389  targetH->addOperatorType(potName, potType);
390  }
391  });
392 
393  //add observables with physical and simple estimators
394  targetH->addObservables(targetPtcl);
395  //do correction
396  bool dmc_correction = false;
397  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
398  std::string potType("0");
399  OhmmsAttributeSet attrib;
400  attrib.add(potType, "type");
401  attrib.put(element);
402  if (cname == "estimator" && potType == "ForwardWalking")
403  {
404  app_log() << " Adding Forward Walking Operator" << std::endl;
405  std::unique_ptr<ForwardWalking> FW = std::make_unique<ForwardWalking>();
406  FW->putSpecial(element, *targetH, targetPtcl);
407  targetH->addOperator(std::move(FW), "ForwardWalking", false);
408  dmc_correction = true;
409  }
410  });
411  //evaluate the observables again
412  if (dmc_correction)
413  targetH->addObservables(targetPtcl);
414  return true;
415 }
416 
417 
418 void HamiltonianFactory::renameProperty(const std::string& a, const std::string& b) { RenamedProperty[a] = b; }
419 
420 void HamiltonianFactory::renameProperty(std::string& aname)
421 {
422  std::map<std::string, std::string>::iterator it(RenamedProperty.find(aname));
423  if (it != RenamedProperty.end())
424  {
425  aname = (*it).second;
426  }
427 }
428 
429 bool HamiltonianFactory::put(xmlNodePtr cur)
430 {
431  bool success = build(cur);
432  return success;
433 }
434 
435 } // namespace qmcplusplus
const std::string & getName() const
return the name
Declare SkEstimator.
Base class for any object which needs to know about a MPI communicator.
Definition: MPIObjectBase.h:26
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
std::ostream & app_log()
Definition: OutputManager.h:65
std::ostream & app_summary()
Definition: OutputManager.h:63
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
std::string myName
name of the object
Definition: MPIObjectBase.h:67
Declare SkPot.
std::map< std::string, const std::unique_ptr< ParticleSet > > PSetMap
int PBCType
type of the lattice. 0=non-periodic, 1=periodic
Declare SkAllEstimator.
Collection of Local Energy Operators.
bool build(xmlNodePtr cur)
process xmlNode to populate targetPsi
HamiltonianFactory(const std::string &hName, ParticleSet &qp, const PSetMap &pset, const PsiPoolType &oset, Communicate *c)
constructor
const PsiPoolType & psiPool
reference to the TrialWaveFunction Pool
std::map< std::string, std::string > RenamedProperty
list of the old to new name
Wrapping information on parallelism.
Definition: Communicate.h:68
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
Communicate * myComm
pointer to Communicate
Definition: MPIObjectBase.h:62
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
bool put(xmlNodePtr cur)
read from xmlNode
std::string ClassName
class Name
Definition: MPIObjectBase.h:65
Declaration of a HamiltonianFactory.
const SPOMap & getSPOMap() const
spomap_ reference accessor
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
Declarations of ForwardWalking.
std::map< std::string, const std::unique_ptr< TrialWaveFunction > > PsiPoolType
std::unique_ptr< QMCHamiltonian > targetH
many-body wavefunction object
std::string getXMLAttributeValue(const xmlNodePtr cur, const std::string_view name)
get the value string for attribute name if name is unfound in cur you get an empty string back this i...
void renameProperty(const std::string &a, const std::string &b)
add a property whose name will be renamed by b
void processChildren(const xmlNodePtr cur, const F &functor)
process through all the children of an XML element F is a lambda or functor void F/[](const std::stri...
Definition: libxmldefs.h:175
const PSetMap & ptclPool
reference to the PSetMap
Class to represent a many-body trial wave function.
std::string psiName
name of the TrialWaveFunction
ParticleSet & targetPtcl
target ParticleSet
const auto & getLattice() const
Definition: ParticleSet.h:251
void addMPCPotential(xmlNodePtr cur, bool physical=false)
bool get(std::ostream &os) const override
dummy. For satisfying OhmmsElementBase.
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
Declaration of QMCHamiltonian.