QMCPACK
SPOSetBuilderFactory.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) 2020 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 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
11 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
12 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
14 //
15 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
16 //////////////////////////////////////////////////////////////////////////////////////
17 
18 
19 #include "SPOSetBuilderFactory.h"
20 #include "SPOSetScanner.h"
23 #include "ModernStringUtils.hpp"
25 #if OHMMS_DIM == 3
26 #include "LCAO/LCAOrbitalBuilder.h"
27 
28 #if defined(QMC_COMPLEX)
30 #include "LCAO/LCAOSpinorBuilder.h"
31 #endif
32 
33 #if defined(HAVE_EINSPLINE)
35 #endif
36 #endif
37 #include "CompositeSPOSet.h"
40 #include "OhmmsData/AttributeSet.h"
41 #include "Message/MPIObjectBase.h"
42 
43 
44 namespace qmcplusplus
45 {
46 const SPOSet* SPOSetBuilderFactory::getSPOSet(const std::string& name) const
47 {
48  if (auto spoit = sposets.find(name); spoit == sposets.end())
49  {
50  // keep this commented until legacy input styles are moved.
51  // In legacy input styles, this look up may fail and need to build SPOSet on the fly.
52  return nullptr;
53  }
54  else
55  return spoit->second.get();
56 }
57 
58 /** constructor
59  * \param els reference to the electrons
60  * \param psi reference to the wavefunction
61  * \param ions reference to the ions
62  */
64  : MPIObjectBase(comm), targetPtcl(els), ptclPool(psets)
65 {
66  ClassName = "SPOSetBuilderFactory";
67 }
68 
69 SPOSetBuilderFactory::~SPOSetBuilderFactory() { DEBUG_MEMORY("SPOSetBuilderFactory::~SPOSetBuilderFactory"); }
70 
71 std::unique_ptr<SPOSetBuilder> SPOSetBuilderFactory::createSPOSetBuilder(xmlNodePtr rootNode)
72 {
73  ReportEngine PRE(ClassName, "createSPOSetBuilder");
74  std::string sourceOpt("ion0");
75  std::string type("");
76  std::string name("");
77  OhmmsAttributeSet aAttrib;
78  aAttrib.add(sourceOpt, "source");
79  aAttrib.add(type, "type");
80  aAttrib.add(name, "name");
81 
82  if (rootNode != NULL)
83  aAttrib.put(rootNode);
84 
85  std::string type_in = type;
86  type = lowerCase(type);
87 
88  //when name is missing, type becomes the input
89  if (name.empty())
90  name = type_in;
91 
92  std::unique_ptr<SPOSetBuilder> bb;
93 
94  if (type == "composite")
95  {
96  app_log() << "Composite SPO set with existing SPOSets." << std::endl;
97  bb = std::make_unique<CompositeSPOSetBuilder>(myComm, *this);
98  }
99  else if (type == "jellium" || type == "heg" || type == "free")
100  {
101  app_log() << "Free-particle SPO set" << std::endl;
102  bb = std::make_unique<FreeOrbitalBuilder>(targetPtcl, myComm, rootNode);
103  }
104  else if (type == "sho")
105  {
106  app_log() << "Harmonic Oscillator SPO set" << std::endl;
107  bb = std::make_unique<SHOSetBuilder>(targetPtcl, myComm);
108  }
109  else if (type == "PWBasis" || type == "PW" || type == "pw")
110  {
111  app_log() << "Planewave basis SPO set" << std::endl;
112  bb = std::make_unique<PWOrbitalSetBuilder>(targetPtcl, myComm, rootNode);
113  }
114 #if OHMMS_DIM == 3
115  else if (type.find("spline") < type.size())
116  {
117  if (targetPtcl.isSpinor())
118  {
119 #ifdef QMC_COMPLEX
120  app_log() << "Einspline Spinor Set\n";
121  bb = std::make_unique<EinsplineSpinorSetBuilder>(targetPtcl, ptclPool, myComm, rootNode);
122 #else
123  PRE.error("Use of einspline spinors requires QMC_COMPLEX=1. Rebuild with this option");
124 #endif
125  }
126  else
127  {
128 #if defined(HAVE_EINSPLINE)
129  PRE << "EinsplineSetBuilder: using libeinspline for B-spline orbitals.\n";
130  bb = std::make_unique<EinsplineSetBuilder>(targetPtcl, ptclPool, myComm, rootNode);
131 #else
132  PRE.error("Einspline is missing for B-spline orbitals", true);
133 #endif
134  }
135  }
136  else if (type == "molecularorbital" || type == "mo")
137  {
138  ParticleSet* ions = nullptr;
139  //initialize with the source tag
140  auto pit(ptclPool.find(sourceOpt));
141  if (pit == ptclPool.end())
142  PRE.error("Missing basisset/@source.", true);
143  else
144  ions = pit->second.get();
145  if (targetPtcl.isSpinor())
146 #ifdef QMC_COMPLEX
147  bb = std::make_unique<LCAOSpinorBuilder>(targetPtcl, *ions, myComm, rootNode);
148 #else
149  PRE.error("Use of lcao spinors requires QMC_COMPLEX=1. Rebuild with this option");
150 #endif
151  else
152  bb = std::make_unique<LCAOrbitalBuilder>(targetPtcl, *ions, myComm, rootNode);
153  }
154 #endif //OHMMS_DIM==3
155  PRE.flush();
156 
157  if (!bb)
158  myComm->barrier_and_abort("SPOSetBuilderFactory::createSPOSetBuilder SPOSetBuilder creation failed.");
159 
160  app_log() << " Created SPOSet builder named '" << name << "' of type " << type << std::endl;
161  return bb;
162 }
163 
164 
166 {
167  std::string collection_name;
168  std::string collection_type;
169  OhmmsAttributeSet attrib;
170  attrib.add(collection_name, "name");
171  attrib.add(collection_type, "type");
172  attrib.put(cur);
173 
174  // use collection_type as collection_name if collection_name is not given
175  if (collection_name.empty())
176  collection_name = collection_type;
177 
178  app_summary() << std::endl;
179  app_summary() << " Single particle orbitals (SPO) collection" << std::endl;
180  app_summary() << " -----------------------------------------" << std::endl;
181  app_summary() << " Name: " << collection_name << " Type input: " << collection_type << std::endl;
182  app_summary() << std::endl;
183 
184  // create the SPOSet builder
185  auto bb = createSPOSetBuilder(cur);
186 
187  // going through a list of sposet entries
188  int nsposets = 0;
189  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
190  if (cname == "sposet")
191  {
192  addSPOSet(std::unique_ptr<SPOSet>(bb->createSPOSet(element)));
193  nsposets++;
194  }
195  if (cname == "rotated_sposet")
196  {
197  addSPOSet(std::unique_ptr<SPOSet>(bb->createRotatedSPOSet(element)));
198  nsposets++;
199  }
200  });
201 
202  if (nsposets == 0)
203  myComm->barrier_and_abort("SPOSetBuilderFactory::buildSPOSetCollection no <sposet/> elements found");
204 
205  // going through a list of spo_scanner entries
206  processChildren(cur, [&](const std::string& cname, const xmlNodePtr element) {
207  if (cname == "spo_scanner")
208  if (myComm->rank() == 0)
209  {
211  ascanner.put(element);
212  }
213  });
214 }
215 
216 void SPOSetBuilderFactory::addSPOSet(std::unique_ptr<SPOSet> spo)
217 {
218  if (spo->getName().empty())
219  myComm->barrier_and_abort("sposet created in sposet_collection must have a name!");
220 
221  if (sposets.find(spo->getName()) != sposets.end())
222  myComm->barrier_and_abort("The name of each sposet must be unique! '" + spo->getName() + "' exists.");
223  else
224  sposets.emplace(spo->getName(), std::move(spo));
225 }
226 
227 std::string SPOSetBuilderFactory::basisset_tag = "basisset";
228 
229 } // namespace qmcplusplus
base class for Single-particle orbital sets
Definition: SPOSet.h:46
const PSetMap & ptclPool
reference to the particle pool
Base class for any object which needs to know about a MPI communicator.
Definition: MPIObjectBase.h:26
std::map< std::string, const std::unique_ptr< ParticleSet > > PSetMap
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
Builder class for einspline-based SPOSet objects.
Derives EinsplineSetBuilder.
declaration of MPIObjectBase
const SPOSet * getSPOSet(const std::string &name) const
returns a named sposet from the pool only use in serial portion of execution ie during initialization...
SPOSetBuilderFactory(Communicate *comm, ParticleSet &els, const PSetMap &psets)
constructor
Wrapping information on parallelism.
Definition: Communicate.h:68
void addSPOSet(std::unique_ptr< SPOSet >)
add an SPOSet to sposets map.
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
Final class and should not be derived.
Communicate * myComm
pointer to Communicate
Definition: MPIObjectBase.h:62
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
declaration of ProgressReportEngine
a scanner for all the SPO sets.
Definition: SPOSetScanner.h:25
std::string lowerCase(const std::string_view s)
++17
std::string ClassName
class Name
Definition: MPIObjectBase.h:65
ParticleSet & targetPtcl
reference to the target particle
#define DEBUG_MEMORY(msg)
Definition: Configuration.h:31
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
void error(const std::string &msg, bool fatal=false)
SPOMap sposets
list of all sposets created by the builders of this factory
Declaration of a builder class for PWOrbitalSet.
std::unique_ptr< SPOSetBuilder > createSPOSetBuilder(xmlNodePtr rootNode)
void put(xmlNodePtr cur)
Definition: SPOSetScanner.h:59
void barrier_and_abort(const std::string &msg) const
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