QMCPACK
SlaterDetBuilder.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: 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 "SlaterDetBuilder.h"
20 #include <type_traits>
21 #include <bitset>
22 #include <unordered_map>
25 #include "OhmmsData/AttributeSet.h"
26 #include "PlatformSelector.hpp"
27 
35 #include <vector>
36 //#include "QMCWaveFunctions/Fermion/ci_node.h"
39 
40 namespace qmcplusplus
41 {
43  SPOSetBuilderFactory& factory,
44  ParticleSet& els,
45  TrialWaveFunction& psi,
46  const PSetMap& psets)
47  : WaveFunctionComponentBuilder(comm, els), sposet_builder_factory_(factory), targetPsi(psi), ptclPool(psets)
48 {
49  ClassName = "SlaterDetBuilder";
50 }
51 
52 /** process <determinantset>
53  *
54  * determinantset
55  * - basiset 0..1
56  * - sposet 0..*
57  * - slaterdeterminant
58  * - determinant 0..*
59  * - ci
60  */
61 std::unique_ptr<WaveFunctionComponent> SlaterDetBuilder::buildComponent(xmlNodePtr cur)
62 {
63  ReportEngine PRE(ClassName, "put(xmlNodePtr)");
64  ///save the current node
65  xmlNodePtr curRoot = cur;
66  bool multiDet = false;
67  std::string msd_algorithm;
68 
69  std::unique_ptr<WaveFunctionComponent> built_singledet_or_multidets;
70 
71  std::unique_ptr<SPOSetBuilder> legacy_input_sposet_builder;
72 
74  { //always create one, using singleton and just to access the member functions
75  app_warning() << "!!!!!!! Deprecated input style: creating SPO set inside determinantset. Support for this usage "
76  "will soon be removed. SPO sets should be built outside using sposet_collection."
77  << std::endl;
78  legacy_input_sposet_builder = sposet_builder_factory_.createSPOSetBuilder(curRoot);
79  }
80 
81  //check the basis set and backflow transformation
82  std::unique_ptr<BackflowTransformation> BFTrans;
83  cur = curRoot->children;
84  while (cur != NULL) //check the basis set
85  {
86  std::string cname(getNodeName(cur));
87  if (cname == sposet_tag)
88  {
89  app_warning() << "!!!!!!! Deprecated input style: creating SPO set inside determinantset. Support for this usage "
90  "will soon be removed. SPO sets should be built outside using sposet_collection."
91  << std::endl;
92  app_log() << "Creating SPOSet in SlaterDetBuilder::put(xmlNodePtr cur).\n";
93  assert(legacy_input_sposet_builder);
94  sposet_builder_factory_.addSPOSet(legacy_input_sposet_builder->createSPOSet(cur));
95  }
96  else if (cname == backflow_tag)
97  {
98  app_log() << "Creating Backflow transformation in SlaterDetBuilder::put(xmlNodePtr cur).\n";
99  // to simplify the logic inside DiracDeterminantWithBackflow,
100  // I'm requiring that only a single <backflow> block appears
101  // in the xml file
102  if (BFTrans)
103  myComm->barrier_and_abort("Only a single backflow block is allowed in the xml. "
104  "Please collect all transformations into a single block.");
105 
106  BackflowBuilder bfbuilder(targetPtcl, ptclPool);
107  BFTrans = bfbuilder.buildBackflowTransformation(cur);
108  }
109  cur = cur->next;
110  }
111 
112  cur = curRoot->children;
113  while (cur != NULL)
114  {
115  std::string cname(getNodeName(cur));
116  if (cname == sd_tag)
117  {
118  app_summary() << std::endl;
119  app_summary() << " Single Slater determinant" << std::endl;
120  app_summary() << " -------------------------" << std::endl;
121 
122  if (built_singledet_or_multidets)
123  myComm->barrier_and_abort("Only one slaterdeterminant or multideterminant entry allowed in XML");
124 
125  std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets;
126  size_t spin_group = 0;
127  xmlNodePtr tcur = cur->children;
128  while (tcur != NULL)
129  {
130  std::string tname(getNodeName(tcur));
131  if (tname == det_tag || tname == rn_tag)
132  {
133  if (spin_group >= targetPtcl.groups())
134  {
135  std::ostringstream err_msg;
136  err_msg << "Need only " << targetPtcl.groups() << " determinant input elements. Found more." << std::endl;
137  throw std::runtime_error(err_msg.str());
138  }
139  dirac_dets.push_back(putDeterminant(tcur, spin_group, legacy_input_sposet_builder, BFTrans));
140  spin_group++;
141  }
142  tcur = tcur->next;
143  }
144  if (spin_group < targetPtcl.groups())
145  {
146  std::ostringstream err_msg;
147  err_msg << "Not enough determinant input elements. "
148  << "Need " << targetPtcl.groups() << " but only found " << spin_group << "." << std::endl;
149  throw std::runtime_error(err_msg.str());
150  }
151 
152  if (BFTrans)
153  {
154  app_summary() << " Using backflow transformation." << std::endl;
155  std::vector<std::unique_ptr<DiracDeterminantWithBackflow>> dirac_dets_bf;
156  for (auto& det : dirac_dets)
157  dirac_dets_bf.emplace_back(dynamic_cast<DiracDeterminantWithBackflow*>(det.release()));
158  auto single_det =
159  std::make_unique<SlaterDetWithBackflow>(targetPtcl, std::move(dirac_dets_bf), std::move(BFTrans));
160  built_singledet_or_multidets = std::move(single_det);
161  }
162  else
163  built_singledet_or_multidets = std::make_unique<SlaterDet>(targetPtcl, std::move(dirac_dets));
164  }
165  else if (cname == multisd_tag)
166  {
167  app_summary() << std::endl;
168  app_summary() << " Multi Slater determinants" << std::endl;
169  app_summary() << " -------------------------" << std::endl;
170  app_summary() << std::endl;
171 
172  if (built_singledet_or_multidets)
173  myComm->barrier_and_abort("Only one slaterdeterminant or multideterminant entry allowed in XML");
174 
175  const int nGroups = targetPtcl.groups();
176  std::vector<std::string> spoNames(nGroups);
177 
178  std::string fastAlg;
179  OhmmsAttributeSet spoAttrib;
180  for (int grp = 0; grp < nGroups; grp++)
181  spoAttrib.add(spoNames[grp], "spo_" + std::to_string(grp));
182  if (nGroups == 2)
183  { //for legacy
184  spoAttrib.add(spoNames[0], "spo_up");
185  spoAttrib.add(spoNames[1], "spo_dn");
186  }
187  spoAttrib.add(fastAlg, "Fast", {"", "yes", "no"}, TagStatus::DELETED);
188  spoAttrib.add(msd_algorithm, "algorithm", {"precomputed_table_method", "table_method"});
189  spoAttrib.put(cur);
190 
191  //new format
192  std::vector<std::unique_ptr<SPOSet>> spo_clones;
193 
194  for (int grp = 0; grp < nGroups; grp++)
195  {
196  const SPOSet* spo_tmp = sposet_builder_factory_.getSPOSet(spoNames[grp]);
197  if (spo_tmp == nullptr)
198  {
199  std::stringstream err_msg;
200  err_msg << "In SlaterDetBuilder: SPOSet \"" << spoNames[grp]
201  << "\" is not found. Expected for MultiSlaterDeterminant." << std::endl;
202  myComm->barrier_and_abort(err_msg.str());
203  }
204  spo_clones.emplace_back(spo_tmp->makeClone());
205  }
206 
207  app_summary() << " Using Bryan's table method." << std::endl;
208  if (BFTrans)
209  myComm->barrier_and_abort("Backflow is not supported by Multi-Slater determinants using the table method!");
210 
211  if (msd_algorithm == "precomputed_table_method")
212  app_summary() << " Using the table method with precomputing. Faster" << std::endl;
213  else
214  app_summary() << " Using the table method without precomputing. Slower." << std::endl;
215 
216  auto msd_fast = createMSDFast(cur, targetPtcl, std::move(spo_clones), targetPtcl.isSpinor(),
217  msd_algorithm == "precomputed_table_method");
218 
219  // The primary purpose of this function is to create all the optimizable orbital rotation parameters.
220  // But if orbital rotation parameters were supplied by the user it will also apply a unitary transformation
221  // and then remove the orbital rotation parameters
222  msd_fast->buildOptVariables();
223  built_singledet_or_multidets = std::move(msd_fast);
224  }
225  cur = cur->next;
226  }
227 
228  if (built_singledet_or_multidets)
229  return built_singledet_or_multidets;
230  else
231  {
232  //fatal
233  PRE.error("Failed to create a Single Slater determinant or Multi Slater determinants object.", true);
234  return nullptr;
235  }
236 }
237 
238 
239 /** process determiment element
240  *
241  * determinant has
242  * - id unique name
243  * - sposet reference to the pre-defined sposet; when missing, use id
244  * - group electron species name, u or d
245 magnetic system
246  * Extra attributes to handled the original released-node case
247  */
248 std::unique_ptr<DiracDeterminantBase> SlaterDetBuilder::putDeterminant(
249  xmlNodePtr cur,
250  int spin_group,
251  const std::unique_ptr<SPOSetBuilder>& legacy_input_sposet_builder,
252  const std::unique_ptr<BackflowTransformation>& BFTrans)
253 {
254  ReportEngine PRE(ClassName, "putDeterminant(xmlNodePtr,int)");
255 
256  const SpeciesSet& target_species = targetPtcl.getSpeciesSet();
257 
258  std::string spin_name = target_species.speciesName[spin_group];
259  std::string sposet_name;
260  std::string basisName("invalid");
261  std::string detname("0"), refname("0");
262  std::string s_detSize("0");
263 
264  OhmmsAttributeSet aAttrib;
265  aAttrib.add(basisName, "basisset");
266  aAttrib.add(detname, "id");
267  aAttrib.add(sposet_name, "sposet");
268  aAttrib.add(refname, "ref");
269  aAttrib.add(s_detSize, "DetSize");
270 
271  std::string s_cutoff("0.0");
272  std::string s_radius("0.0");
273  int s_smallnumber(-999999);
274  int rntype(0);
275  aAttrib.add(s_cutoff, "Cutoff");
276  aAttrib.add(s_radius, "Radius");
277  aAttrib.add(s_smallnumber, "smallnumber");
278  aAttrib.add(s_smallnumber, "eps");
279  aAttrib.add(rntype, "primary");
280  aAttrib.add(spin_name, "group");
281  aAttrib.put(cur);
282 
283  // whether to use an optimizable slater determinant
284  std::string optimize;
285  std::string matrix_inverter;
286  std::string use_batch;
287  std::string useGPU;
288  int delay_rank(0);
289 
290  OhmmsAttributeSet sdAttrib;
291  sdAttrib.add(delay_rank, "delay_rank");
292  sdAttrib.add(optimize, "optimize", {"no", "yes"});
293  sdAttrib.add(matrix_inverter, "matrix_inverter", {"gpu", "host"});
294 #if defined(ENABLE_OFFLOAD)
295  sdAttrib.add(use_batch, "batch", {"yes", "no"});
296 #else
297  sdAttrib.add(use_batch, "batch", {"no", "yes"});
298 #endif
299 #if defined(ENABLE_OFFLOAD)
300 #if defined(ENABLE_CUDA) || defined(ENABLE_SYCL)
301  sdAttrib.add(useGPU, "gpu", CPUOMPTargetVendorSelector::candidate_values);
302 #else
304 #endif
305 #endif
306  sdAttrib.put(cur->parent);
307 
308  { //check determinant@group
309  int spin_group_in = spin_group;
310  if (isdigit(spin_name[0]))
311  spin_group_in = atoi(spin_name.c_str());
312  else
313  spin_group_in = target_species.findSpecies(spin_name);
314  if (spin_group_in < target_species.size() && spin_group_in != spin_group)
315  {
316  spin_group = spin_group_in;
317  app_log() << " Overwrite group = " << spin_group << std::endl;
318  }
319  }
320 
321  //old input does not have sposet
322  if (sposet_name.empty())
323  sposet_name = detname;
324 
325  app_summary() << std::endl;
326  app_summary() << " Determinant" << std::endl;
327  app_summary() << " -----------" << std::endl;
328  app_summary() << " Name: " << detname << " Spin group: " << spin_group << " SPO name: " << sposet_name
329  << std::endl;
330  app_summary() << std::endl;
331 
332  const SPOSet* psi = sposet_builder_factory_.getSPOSet(sposet_name);
333  //check if the named sposet exists
334  if (psi == 0)
335  {
336  app_warning() << "!!!!!!! Deprecated input style: creating SPO set inside determinantset. Support for this usage "
337  "will soon be removed. SPO sets should be built outside using sposet_collection."
338  << std::endl;
339  app_log() << " Create a new SPO set " << sposet_name << std::endl;
340  assert(legacy_input_sposet_builder);
341  auto sposet = legacy_input_sposet_builder->createSPOSet(cur);
342  psi = sposet.get();
343  sposet_builder_factory_.addSPOSet(std::move(sposet));
344  }
345 
346  std::unique_ptr<SPOSet> psi_clone(psi->makeClone());
347  psi_clone->checkObject();
348 
349  const int firstIndex = targetPtcl.first(spin_group);
350  const int lastIndex = targetPtcl.last(spin_group);
351 
352  if (delay_rank < 0 || delay_rank > lastIndex - firstIndex)
353  {
354  std::ostringstream err_msg;
355  err_msg << "SlaterDetBuilder::putDeterminant delay_rank must be positive "
356  << "and no larger than the electron count within a determinant!\n"
357  << "Acceptable value [1," << lastIndex - firstIndex << "], "
358  << "user input " + std::to_string(delay_rank);
359  APP_ABORT(err_msg.str());
360  }
361  else if (delay_rank == 0)
362  {
363  if (lastIndex - firstIndex >= 192)
364  delay_rank = 32;
365  else
366  delay_rank = 1;
367  app_summary() << " Setting delay_rank to default value " << delay_rank << std::endl;
368  }
369 
370  if (delay_rank > 1)
371  app_summary() << " Using rank-" << delay_rank << " delayed update" << std::endl;
372  else
373  app_summary() << " Using rank-1 Sherman-Morrison Fahy update (SM1)" << std::endl;
374 
375  std::unique_ptr<DiracDeterminantBase> adet;
376 
377  if (BFTrans)
378  {
379  app_summary() << " Using backflow transformation." << std::endl;
380  adet = std::make_unique<DiracDeterminantWithBackflow>(std::move(psi_clone), *BFTrans, firstIndex, lastIndex);
381  }
382  else
383  {
384  const DetMatInvertor matrix_inverter_kind =
385  (matrix_inverter == "host") ? DetMatInvertor::HOST : DetMatInvertor::ACCEL;
386  if (matrix_inverter_kind == DetMatInvertor::HOST)
387  app_summary() << " Matrix inversion running on host." << std::endl;
388 
389  if (use_batch == "yes")
390  {
391  app_summary() << " Using walker batching." << std::endl;
392 
393 #if defined(ENABLE_CUDA) && defined(ENABLE_OFFLOAD)
395  {
396  app_summary() << " Running on a GPU via CUDA/HIP acceleration and OpenMP offload." << std::endl;
397  adet = std::make_unique<DiracDeterminantBatched<PlatformKind::CUDA, QMCTraits::ValueType, QMCTraits::QTFull::ValueType>>(std::move(psi_clone),
398  firstIndex, lastIndex,
399  delay_rank,
400  matrix_inverter_kind);
401  }
402  else
403 #endif
404 #if defined(ENABLE_SYCL) && defined(ENABLE_OFFLOAD)
406  {
407  app_summary() << " Running on a GPU via SYCL acceleration and OpenMP offload." << std::endl;
408  adet = std::make_unique<DiracDeterminantBatched<PlatformKind::SYCL, QMCTraits::ValueType, QMCTraits::QTFull::ValueType>>(std::move(psi_clone),
409  firstIndex, lastIndex,
410  delay_rank,
411  matrix_inverter_kind);
412  }
413  else
414 #endif
415  {
416 #if defined(ENABLE_OFFLOAD)
418  throw std::runtime_error("No pure CPU implementation of walker-batched Slater determinant.");
419  app_summary() << " Running OpenMP offload code path on a GPU. " << std::endl;
420 #else
421  app_summary() << " Running OpenMP offload code path on a CPU. " << std::endl;
422 #endif
423  adet = std::make_unique<DiracDeterminantBatched<PlatformKind::OMPTARGET, QMCTraits::ValueType, QMCTraits::QTFull::ValueType>>(std::move(psi_clone), firstIndex, lastIndex, delay_rank,
424  matrix_inverter_kind);
425  }
426  }
427  else
428  {
429  if (useGPU == "omptarget")
430  throw std::runtime_error("No OpenMP offload implementation of single-walker Slater determinant.");
431 #if defined(ENABLE_CUDA)
433  {
434  app_summary() << " Running on a GPU via CUDA/HIP acceleration." << std::endl;
435  adet = std::make_unique<
437  firstIndex, lastIndex,
438  delay_rank,
439  matrix_inverter_kind);
440  }
441 #elif defined(ENABLE_SYCL)
443  {
444  app_summary() << " Running on a GPU via SYCL acceleration." << std::endl;
445  adet = std::make_unique<
447  firstIndex, lastIndex,
448  delay_rank,
449  matrix_inverter_kind);
450  }
451 #endif
452  else
453  {
454  app_summary() << " Running on CPU." << std::endl;
455  adet = std::make_unique<DiracDeterminant<>>(std::move(psi_clone), firstIndex, lastIndex, delay_rank,
456  matrix_inverter_kind);
457  }
458  }
459  }
460 
461  app_log() << std::endl;
462  app_log().flush();
463  return adet;
464 }
465 
466 std::unique_ptr<MultiSlaterDetTableMethod> SlaterDetBuilder::createMSDFast(
467  xmlNodePtr cur,
468  ParticleSet& target_ptcl,
469  std::vector<std::unique_ptr<SPOSet>>&& spo_clones,
470  const bool spinor,
471  const bool use_precompute) const
472 {
473  const size_t nGroups = targetPtcl.groups();
474 
475  std::vector<std::vector<size_t>> C2nodes(nGroups);
476  auto C2nodes_sorted_ptr = std::make_unique<std::vector<std::vector<size_t>>>(nGroups);
477  auto& C2nodes_sorted(*C2nodes_sorted_ptr);
478 
479  auto C_ptr = std::make_unique<std::vector<ValueType>>();
480  auto& C(*C_ptr);
481 
482  auto myVars_ptr = std::make_unique<opt_variables_type>();
483  auto& myVars(*myVars_ptr);
484 
485  bool Optimizable = false;
486  bool CI_Optimizable = false;
487 
488  bool optimizeCI;
489 
490  std::vector<int> nptcls(nGroups);
491  for (int grp = 0; grp < nGroups; grp++)
492  nptcls[grp] = targetPtcl.groupsize(grp);
493 
494  std::vector<std::vector<ci_configuration>> uniqueConfgs(nGroups);
495  std::vector<std::string> CItags;
496 
497  //Check id multideterminants are in HDF5
498 
499  xmlNodePtr curTemp = cur, DetListNode = nullptr;
500  curTemp = curTemp->children;
501  while (curTemp != NULL) //check the basis set
502  {
503  std::string cname(getNodeName(curTemp));
504  if (cname == "detlist")
505  DetListNode = curTemp;
506  curTemp = curTemp->next;
507  }
508 
509  std::unique_ptr<CSFData> csf_data_ptr;
510 
511  std::string HDF5Path(getXMLAttributeValue(DetListNode, "href"));
512  if (!HDF5Path.empty())
513  {
514  app_log() << "Found Multideterminants in H5 File" << std::endl;
515  readDetListH5(cur, uniqueConfgs, C2nodes, CItags, C, optimizeCI, nptcls);
516  }
517  else
518  readDetList(cur, uniqueConfgs, C2nodes, CItags, C, optimizeCI, nptcls, csf_data_ptr);
519 
520  const auto maxloc = std::max_element(C.begin(), C.end(), [](ValueType const& lhs, ValueType const& rhs) {
521  return std::norm(lhs) < std::norm(rhs);
522  });
523  const int refdet_id = std::distance(C.begin(), maxloc);
524  app_log() << "max CI coeff at det number " << refdet_id << " with value " << std::abs(C[refdet_id]) << std::endl;
525 
526  assert(nGroups == spo_clones.size());
527  std::vector<std::unique_ptr<MultiDiracDeterminant>> dets;
528  for (int grp = 0; grp < nGroups; grp++)
529  {
530  dets.emplace_back(std::make_unique<MultiDiracDeterminant>(std::move(spo_clones[grp]), spinor, targetPtcl.first(grp),
531  nptcls[grp]));
532  std::vector<ci_configuration2> list(uniqueConfgs[grp].size());
533  for (int i = 0; i < list.size(); i++)
534  {
535  list[i].occup.resize(nptcls[grp]);
536  int cnt = 0;
537  for (int k = 0; k < uniqueConfgs[grp][i].occup.size(); k++)
538  if (uniqueConfgs[grp][i].occup[k])
539  list[i].occup[cnt++] = k;
540  if (cnt != nptcls[grp])
541  {
542  APP_ABORT("Error in SlaterDetBuilder::createMSDFast for ptcl group "
543  << grp << ", problems with ci configuration list. \n");
544  }
545  }
546  // reorder unique determinants for a given spin based on the selected reference determinant
547  dets[grp]->createDetData(C2nodes[grp][refdet_id], list, C2nodes[grp], C2nodes_sorted[grp]);
548  }
549 
550  if (csf_data_ptr && csf_data_ptr->coeffs.size() == 1)
551  optimizeCI = false;
552 
553  if (optimizeCI)
554  {
555  app_log() << "CI coefficients are optimizable. \n";
556  std::string resetCI("no");
557  OhmmsAttributeSet spoAttrib;
558  spoAttrib.add(resetCI, "reset_coeff");
559  spoAttrib.put(cur);
560  if (resetCI == "yes")
561  {
562  if (csf_data_ptr)
563  for (int i = 1; i < csf_data_ptr->coeffs.size(); i++)
564  csf_data_ptr->coeffs[i] = 0;
565  else
566  for (int i = 1; i < C.size(); i++)
567  C[i] = 0;
568  app_log() << "CI coefficients are reset. \n";
569  }
570  Optimizable = CI_Optimizable = true;
571  if (csf_data_ptr)
572  for (int i = 1; i < csf_data_ptr->coeffs.size(); i++)
573  myVars.insert(CItags[i], std::real(csf_data_ptr->coeffs[i]), true, optimize::LINEAR_P);
574  else
575  for (int i = 1; i < C.size(); i++)
576  myVars.insert(CItags[i], std::real(C[i]), true, optimize::LINEAR_P);
577  }
578  else
579  {
580  app_log() << "CI coefficients are not optimizable. \n";
581  CI_Optimizable = false;
582  }
583 
584  bool any_optimizable = false;
585  for (int grp = 0; grp < nGroups; grp++)
586  {
587  if (dets[grp]->isOptimizable() == true)
588  {
589  any_optimizable = true;
590  break;
591  }
592  }
593  if (any_optimizable)
594  {
595  for (int grp = 0; grp < nGroups; grp++)
596  {
597  if (dets[grp]->isOptimizable() != true)
598  APP_ABORT("Optimizing the SPOSet of only only species is not supported!\n");
599  }
600  if (csf_data_ptr)
601  APP_ABORT("Currently, Using CSF is not available with MSJ Orbital Optimization!\n");
602 
603  for (int grp = 0; grp < nGroups; grp++)
604  {
605  for (int i = 0; i < nptcls[grp]; i++)
606  {
607  if (uniqueConfgs[grp][0].occup[i] != true)
608  APP_ABORT(
609  "The Hartee Fock Reference Determinant must be the first in the Multi-Slater expansion for the input!\n");
610  }
611  }
612  app_warning() << "Unrestricted Orbital Optimization will be performed. Spin symmetry is not guaranteed to be "
613  "preserved!\n";
614 
615  Optimizable = true;
616  }
617 
618  auto msd_fast = std::make_unique<MultiSlaterDetTableMethod>(targetPtcl, std::move(dets), use_precompute);
619  msd_fast->initialize(std::move(C2nodes_sorted_ptr), std::move(C_ptr), std::move(myVars_ptr), std::move(csf_data_ptr),
620  Optimizable, CI_Optimizable);
621 
622  return msd_fast;
623 }
624 
625 bool SlaterDetBuilder::readDetList(xmlNodePtr cur,
626  std::vector<std::vector<ci_configuration>>& uniqueConfgs,
627  std::vector<std::vector<size_t>>& C2nodes,
628  std::vector<std::string>& CItags,
629  std::vector<ValueType>& coeff,
630  bool& optimizeCI,
631  std::vector<int>& nptcls,
632  std::unique_ptr<CSFData>& csf_data_ptr) const
633 {
634  bool success = true;
635 
636  const int nGroups = uniqueConfgs.size();
637  for (int grp = 0; grp < nGroups; grp++)
638  {
639  uniqueConfgs[grp].clear();
640  C2nodes[grp].clear();
641  }
642  CItags.clear();
643  coeff.clear();
644  std::vector<std::vector<ci_configuration>> confgLists(nGroups);
645  std::string optCI = "no";
646  RealType cutoff = 0.0;
647  RealType zero_cutoff = 0.0;
648  OhmmsAttributeSet ciAttrib;
649  ciAttrib.add(optCI, "optimize");
650  ciAttrib.add(optCI, "Optimize");
651  ciAttrib.put(cur);
652  optimizeCI = (optCI == "yes");
653  xmlNodePtr curRoot = cur, DetListNode = nullptr;
654  cur = curRoot->children;
655  while (cur != NULL) //check the basis set
656  {
657  std::string cname(getNodeName(cur));
658  if (cname == "detlist")
659  {
660  DetListNode = cur;
661  app_log() << "Found determinant list. \n";
662  }
663  cur = cur->next;
664  }
665 
666  std::vector<size_t> NCs(nGroups);
667  std::vector<size_t> NEs(nGroups);
668  size_t nstates = 0;
669  size_t ndets = 0;
670  size_t cnt0 = 0;
671  std::string Dettype = "DETS";
672  std::string CSFChoice = "qchem_coeff";
673  OhmmsAttributeSet spoAttrib;
674  for (int grp = 0; grp < nGroups; grp++)
675  {
676  spoAttrib.add(NCs[grp], "nc" + std::to_string(grp));
677  spoAttrib.add(NEs[grp], "ne" + std::to_string(grp));
678  }
679  if (nGroups == 2)
680  { //for legacy
681  spoAttrib.add(NCs[0], "nca");
682  spoAttrib.add(NCs[1], "ncb");
683  spoAttrib.add(NEs[0], "nea");
684  spoAttrib.add(NEs[1], "neb");
685  }
686  spoAttrib.add(ndets, "size");
687  spoAttrib.add(nstates, "nstates");
688  spoAttrib.add(Dettype, "type");
689  spoAttrib.add(cutoff, "cutoff");
690  spoAttrib.add(zero_cutoff, "zero_cutoff");
691  spoAttrib.add(zero_cutoff, "zerocutoff");
692  spoAttrib.add(CSFChoice, "sortby");
693  spoAttrib.put(DetListNode);
694 
695  if (ndets == 0)
696  {
697  APP_ABORT("size==0 in detlist is not allowed. Use slaterdeterminant in this case.\n");
698  }
699 
700  if (Dettype == "CSF")
701  csf_data_ptr = std::make_unique<CSFData>();
702  else if (Dettype != "DETS" && Dettype != "Determinants")
703  {
704  APP_ABORT("Only allowed type in detlist is DETS or CSF.\n");
705  }
706 
707  if (zero_cutoff > 0)
708  app_log() << " Initializing CI coeffs less than " << zero_cutoff << " to zero." << std::endl;
709 
710  for (int grp = 0; grp < nGroups; grp++)
711  {
712  if (NEs[grp] == 0)
713  NEs[grp] = nptcls[grp] - NCs[grp];
714  else if (NEs[grp] != nptcls[grp] - NCs[grp])
715  throw std::runtime_error("ne is not equal to n - nc for group " + std::to_string(grp));
716  }
717 
718  cur = DetListNode->children;
719  std::vector<ci_configuration> dummyCs(nGroups);
720  for (int grp = 0; grp < nGroups; grp++)
721  {
722  dummyCs[grp].occup.resize(NCs[grp] + nstates, false);
723  for (size_t i = 0; i < NCs[grp] + NEs[grp]; i++)
724  dummyCs[grp].occup[i] = true;
725  }
726  RealType sumsq_qc = 0.0;
727  RealType sumsq = 0.0;
728  if (csf_data_ptr)
729  {
730  auto& CSFcoeff = csf_data_ptr->coeffs;
731  auto& DetsPerCSF = csf_data_ptr->dets_per_csf;
732  auto& CSFexpansion = csf_data_ptr->expansion;
733 
734  app_log() << "Reading CSFs." << std::endl;
735  while (cur != NULL) //check the basis set
736  {
737  std::string cname(getNodeName(cur));
738  if (cname == "csf")
739  {
740  RealType exctLvl, qc_ci = 0.0;
741  OhmmsAttributeSet confAttrib;
742  std::string tag, OccString;
743  RealType ci_real = 0.0, ci_imag = 0.0;
744  confAttrib.add(ci_real, "coeff");
745  confAttrib.add(ci_real, "coeff_real");
746  confAttrib.add(ci_imag, "coeff_imag");
747  confAttrib.add(qc_ci, "qchem_coeff");
748  confAttrib.add(tag, "id");
749  confAttrib.add(OccString, "occ");
750  confAttrib.add(exctLvl, "exctLvl");
751  confAttrib.put(cur);
752 
753  if (qc_ci == 0.0)
754  qc_ci = ci_real;
755 
756  ValueType ci;
757 #ifdef QMC_COMPLEX
758  ci = ValueType(ci_real, ci_imag);
759 #else
760  if (ci_imag != RealType(0))
762  "SlaterDetBuilder::readDetList. Build with QMC_COMPLEX if using complex CI expansion coefficients.");
763  ci = ci_real;
764 #endif
765  //Can discriminate based on any of 3 criterion
766  if (((std::abs(qc_ci) < cutoff) && (CSFChoice == "qchem_coeff")) ||
767  ((CSFChoice == "exctLvl") && (exctLvl > cutoff)) || ((CSFChoice == "coeff") && (std::abs(ci) < cutoff)))
768  {
769  cur = cur->next;
770  cnt0++;
771  continue;
772  }
773  cnt0++;
774  if (std::abs(qc_ci) < zero_cutoff)
775  ci = 0.0;
776  CSFcoeff.push_back(ci);
777  sumsq_qc += qc_ci * qc_ci;
778  DetsPerCSF.push_back(0);
779  CItags.push_back(tag);
780  xmlNodePtr csf = cur->children;
781  while (csf != NULL)
782  {
783  std::string cname0(getNodeName(csf));
784  if (cname0 == "det")
785  {
786  std::vector<std::string> occs(nGroups);
787  std::string tag0;
788  RealType coef = 0.0;
789  OhmmsAttributeSet detAttrib;
790  detAttrib.add(tag0, "id");
791  detAttrib.add(coef, "coeff");
792  for (int grp = 0; grp < nGroups; grp++)
793  detAttrib.add(occs[grp], "occ" + std::to_string(grp));
794  if (nGroups == 2)
795  { //for legacy
796  detAttrib.add(occs[0], "alpha");
797  detAttrib.add(occs[1], "beta");
798  }
799  detAttrib.put(csf);
800  for (int grp = 0; grp < nGroups; grp++)
801  {
802  size_t nq = 0;
803  if (occs[grp].size() < nstates)
804  {
805  std::cerr << "occ" << grp << ": " << occs[grp] << std::endl;
806  APP_ABORT("Found incorrect group" + std::to_string(grp) + " determinant label. size < nc+nstates");
807  }
808  for (size_t i = 0; i < nstates; i++)
809  {
810  if (occs[grp][i] != '0' && occs[grp][i] != '1')
811  {
812  std::cerr << occs[grp] << std::endl;
813  APP_ABORT("Found incorrect determinant label.");
814  }
815  if (occs[grp][i] == '1')
816  nq++;
817  }
818  if (nq != NEs[grp])
819  {
820  std::cerr << "occ" << grp << ": " << occs[grp] << std::endl;
821  APP_ABORT("Found incorrect group" + std::to_string(grp) + " determinant label. nocc != nc+ne");
822  }
823  }
824  DetsPerCSF.back()++;
825  CSFexpansion.push_back(coef);
826  coeff.push_back(coef * ci);
827  for (int grp = 0; grp < nGroups; grp++)
828  {
829  confgLists[grp].push_back(dummyCs[grp]);
830  for (size_t i = 0; i < NCs[grp]; i++)
831  confgLists[grp].back().occup[i] = true;
832  for (size_t i = NCs[grp]; i < NCs[grp] + nstates; i++)
833  confgLists[grp].back().occup[i] = (occs[grp][i - NCs[grp]] == '1');
834  }
835  } // if(name=="det")
836  csf = csf->next;
837  } // csf loop
838  if (DetsPerCSF.back() == 0)
839  {
840  APP_ABORT("Found empty CSF (no det blocks).");
841  }
842  } // if (name == "csf")
843  cur = cur->next;
844  }
845  if (cnt0 != ndets)
846  {
847  std::cerr << "count, ndets: " << cnt0 << " " << ndets << std::endl;
848  APP_ABORT("Problems reading determinant ci_configurations. Found a number of determinants inconsistent with xml "
849  "file size parameter.\n");
850  }
851 
852  for (int grp = 0; grp < nGroups; grp++)
853  C2nodes[grp].resize(coeff.size());
854  app_log() << "Found " << coeff.size() << " terms in the MSD expansion.\n";
855  RealType sumsq = 0.0;
856  for (size_t i = 0; i < coeff.size(); i++)
857  sumsq += std::abs(coeff[i] * coeff[i]);
858  app_log() << "Norm of ci vector (sum of ci^2): " << sumsq << std::endl;
859  app_log() << "Norm of qchem ci vector (sum of qchem_ci^2): " << sumsq_qc << std::endl;
860  for (int grp = 0; grp < nGroups; grp++)
861  {
862  for (size_t i = 0; i < confgLists[grp].size(); i++)
863  {
864  bool found = false;
865  int k = -1;
866  for (size_t j = 0; j < uniqueConfgs[grp].size(); j++)
867  {
868  if (confgLists[grp][i] == uniqueConfgs[grp][j])
869  {
870  found = true;
871  k = j;
872  break;
873  }
874  }
875  if (found)
876  {
877  C2nodes[grp][i] = k;
878  }
879  else
880  {
881  uniqueConfgs[grp].push_back(confgLists[grp][i]);
882  C2nodes[grp][i] = uniqueConfgs[grp].size() - 1;
883  }
884  }
885  }
886  }
887  else
888  {
889  app_log() << "Reading CI expansion." << std::endl;
890 
891  std::vector<int> cnts(nGroups, 0);
892  std::vector<std::unordered_map<std::string, int>> MyMaps(nGroups);
893  while (cur != NULL) //check the basis set
894  {
895  std::string cname(getNodeName(cur));
896  if (cname == "configuration" || cname == "ci")
897  {
898  RealType qc_ci = 0.0;
899  std::vector<std::string> occs(nGroups);
900  std::string tag;
901  OhmmsAttributeSet confAttrib;
902  RealType ci_real = 0.0, ci_imag = 0.0;
903  confAttrib.add(ci_real, "coeff");
904  confAttrib.add(ci_real, "coeff_real");
905  confAttrib.add(ci_imag, "coeff_imag");
906  confAttrib.add(qc_ci, "qchem_coeff");
907  for (int grp = 0; grp < nGroups; grp++)
908  confAttrib.add(occs[grp], "occ" + std::to_string(grp));
909  if (nGroups == 2)
910  { //legacy
911  confAttrib.add(occs[0], "alpha");
912  confAttrib.add(occs[1], "beta");
913  }
914  confAttrib.add(tag, "id");
915  confAttrib.put(cur);
916 
917  ValueType ci;
918 #ifdef QMC_COMPLEX
919  ci = ValueType(ci_real, ci_imag);
920 #else
921  if (ci_imag != RealType(0))
923  "SlaterDetBuilder::readDetList. Build with QMC_COMPLEX if using complex CI expansion coefficients.");
924  ci = ci_real;
925 #endif
926 
927  //Will always loop through the whole determinant set as no assumption on the order of the determinant is made
928  if (std::abs(ci) < cutoff)
929  {
930  cur = cur->next;
931  continue;
932  }
933 
934  for (int grp = 0; grp < nGroups; grp++)
935  {
936  for (size_t i = 0; i < nstates; i++)
937  {
938  if (occs[grp][i] != '0' && occs[grp][i] != '1')
939  {
940  std::cerr << occs[grp] << std::endl;
941  APP_ABORT("Found incorrect determinant label for group " + std::to_string(grp));
942  }
943  }
944  if (occs[grp].size() < nstates)
945  {
946  std::cerr << "occ" << grp << ": " << occs[grp] << std::endl;
947  APP_ABORT("Found incorrect group" + std::to_string(grp) + " determinant label. size < nc+nstates");
948  }
949  }
950 
951  coeff.push_back(ci);
952  CItags.push_back(tag);
953 
954  for (int grp = 0; grp < nGroups; grp++)
955  {
956  std::unordered_map<std::string, int>::const_iterator got = MyMaps[grp].find(occs[grp]);
957  if (got == MyMaps[grp].end())
958  {
959  uniqueConfgs[grp].push_back(dummyCs[grp]);
960  uniqueConfgs[grp].back().add_occupation(occs[grp]);
961  C2nodes[grp].push_back(cnts[grp]);
962  MyMaps[grp].insert(std::pair<std::string, int>(occs[grp], cnts[grp]));
963  cnts[grp]++;
964  }
965  else
966  {
967  C2nodes[grp].push_back(got->second);
968  }
969  }
970 
971  cnt0++;
972  sumsq_qc += qc_ci * qc_ci;
973  sumsq += std::abs(ci * ci);
974  }
975  cur = cur->next;
976  }
977 
978  app_log() << "Found " << coeff.size() << " terms in the MSD expansion.\n";
979 
980  if (coeff.size() == 0)
981  throw std::runtime_error(
982  "MSD expansion is empty with either zero determinants input or remaining after cutoff applied.");
983 
984  app_log() << "Norm of ci vector (sum of ci^2): " << sumsq << std::endl;
985  app_log() << "Norm of qchem ci vector (sum of qchem_ci^2): " << sumsq_qc << std::endl;
986 
987  } //usingCSF
988 
989  for (auto grp = 0; grp < nGroups; grp++)
990  app_log() << "Found " << uniqueConfgs[grp].size() << " unique group " << grp << " determinants.\n";
991 
992  return success;
993 }
994 
996  std::vector<std::vector<ci_configuration>>& uniqueConfgs,
997  std::vector<std::vector<size_t>>& C2nodes,
998  std::vector<std::string>& CItags,
999  std::vector<ValueType>& coeff,
1000  bool& optimizeCI,
1001  std::vector<int>& nptcls) const
1002 {
1003  bool success = true;
1004  int extlevel(0);
1005  const int nGroups = uniqueConfgs.size();
1006  for (int grp = 0; grp < nGroups; grp++)
1007  {
1008  uniqueConfgs[grp].clear();
1009  C2nodes[grp].clear();
1010  }
1011  CItags.clear();
1012  coeff.clear();
1013  std::string CICoeffH5path("");
1014  std::vector<std::vector<ci_configuration>> confgLists(nGroups);
1015  std::vector<ValueType> CIcoeff;
1016  std::vector<std::string> ConfigTag;
1017  std::string optCI = "no";
1018  RealType cutoff = 0.0;
1019  OhmmsAttributeSet ciAttrib;
1020  ciAttrib.add(optCI, "optimize");
1021  ciAttrib.put(cur);
1022  optimizeCI = (optCI == "yes");
1023  xmlNodePtr curRoot = cur, DetListNode = nullptr;
1024  std::string multidetH5path;
1025  cur = curRoot->children;
1026  while (cur != NULL) //check the basis set
1027  {
1028  std::string cname(getNodeName(cur));
1029  if (cname == "detlist")
1030  {
1031  DetListNode = cur;
1032  app_log() << "Found determinant list. \n";
1033  }
1034  cur = cur->next;
1035  }
1036 
1037  app_log() << " H5 code path implicitly assumes NC0 = NC1 = ... = 0" << std::endl;
1038  for (int grp = 0; grp < nGroups; grp++)
1039  app_log() << "NE" << grp << " = " << nptcls[grp] << ", ";
1040  app_log() << std::endl;
1041  size_t nstates = 0;
1042  size_t ndets = 0;
1043  size_t H5_ndets, H5_nstates;
1044  /// 64 bit fixed width integer
1045  const unsigned bit_kind = 64;
1046  static_assert(bit_kind == sizeof(uint64_t) * 8, "Must be 64 bit fixed width integer");
1047  /// the number of 64 bit integers which represent the binary string for occupation
1048  int N_int;
1049  std::string Dettype = "DETS";
1050  ValueType sumsq = 0.0;
1051  OhmmsAttributeSet spoAttrib;
1052  spoAttrib.add(ndets, "size");
1053  spoAttrib.add(Dettype, "type");
1054  spoAttrib.add(nstates, "nstates");
1055  spoAttrib.add(extlevel, "ext_level");
1056  spoAttrib.add(cutoff, "cutoff");
1057  spoAttrib.add(multidetH5path, "href");
1058  spoAttrib.add(CICoeffH5path, "opt_coeffs");
1059  spoAttrib.put(DetListNode);
1060  if (ndets == 0)
1061  {
1062  APP_ABORT("size==0 in detlist is not allowed. Use slaterdeterminant in this case.\n");
1063  }
1064  if (Dettype != "DETS" && Dettype != "Determinants")
1065  APP_ABORT("Reading from HDF5 is only enabled for CI DETS. Must be accessed through (type=\"DETS\") or "
1066  "(type=\"Determinants\") .\n");
1067  app_log() << "Reading CI expansion from HDF5:" << multidetH5path << std::endl;
1068 
1069  hdf_archive hin;
1070  if (!hin.open(multidetH5path.c_str(), H5F_ACC_RDONLY))
1071  {
1072  std::cerr << "Could not open H5 file" << std::endl;
1073  abort();
1074  }
1075 
1076 
1077  hin.push("MultiDet", false);
1078 
1079  hin.read(H5_ndets, "NbDet");
1080  if (ndets != H5_ndets)
1081  {
1082  std::cerr << "Number of determinants in H5 file (" << H5_ndets << ") different from number of dets in XML ("
1083  << ndets << ")" << std::endl;
1084  abort();
1085  }
1086 
1087  hin.read(H5_nstates, "nstate");
1088  if (nstates == 0)
1089  nstates = H5_nstates;
1090  else if (nstates != H5_nstates)
1091  {
1092  std::cerr << "Number of states/orbitals in H5 file (" << H5_nstates
1093  << ") different from number of states/orbitals in XML (" << nstates << ")" << std::endl;
1094  abort();
1095  }
1096 
1097  hin.read(N_int, "Nbits");
1098  CIcoeff.resize(ndets);
1099  ConfigTag.resize(ndets);
1100 
1101  readCoeffs(hin, CIcoeff, ndets, extlevel);
1102 
1103  ///IF OPTIMIZED COEFFICIENTS ARE PRESENT IN opt_coeffs Path
1104  ///THEY ARE READ FROM DIFFERENT HDF5 the replace the previous coeff
1105  ///It is important to still read all old coeffs and only replace the optimized ones
1106  ///in order to keep coherence with the cutoff on the number of determinants
1107  ///REMEMBER!! FIRST COEFF IS FIXED. THEREFORE WE DO NOT REPLACE IT!!!
1108  if (CICoeffH5path != "")
1109  {
1110  int OptCiSize = 0;
1111  std::vector<ValueType> CIcoeffopt;
1112  hdf_archive coeffin;
1113  if (!coeffin.open(CICoeffH5path.c_str(), H5F_ACC_RDONLY))
1114  {
1115  std::cerr << "Could not open H5 file containing Optimized Coefficients" << std::endl;
1116  abort();
1117  }
1118 
1119  coeffin.push("MultiDet", false);
1120 
1121  coeffin.read(OptCiSize, "NbDet");
1122  CIcoeffopt.resize(OptCiSize);
1123 
1124  readCoeffs(coeffin, CIcoeffopt, ndets, extlevel);
1125 
1126  coeffin.close();
1127 
1128  for (int i = 0; i < OptCiSize; i++)
1129  CIcoeff[i + 1] = CIcoeffopt[i];
1130 
1131  app_log() << "The first " << OptCiSize
1132  << " Optimized coefficients were substituted to the original set of coefficients." << std::endl;
1133  }
1134 
1135  std::vector<Matrix<uint64_t>> temps;
1136  for (int grp = 0; grp < nGroups; grp++)
1137  {
1138  Matrix<uint64_t> tmp(ndets, N_int);
1139  temps.push_back(tmp);
1140  std::string ci_str;
1141 
1142  std::string ds_tag = "CI_" + std::to_string(grp);
1143  if (!hin.is_dataset(ds_tag))
1144  {
1145  //for backwards compatibility
1146  if (grp == 0)
1147  ds_tag = "CI_Alpha";
1148  else if (grp == 1)
1149  ds_tag = "CI_Beta";
1150  }
1151 
1152  if (!hin.is_dataset_of_type<uint64_t>(ds_tag))
1153  {
1154  if (hin.is_dataset_of_type<int64_t>(ds_tag))
1155  APP_ABORT(
1156  "QMCPACK expects the HDF5 CI vectors to be stored as unsigned 64 bit integers. This HDF5 uses signed 64 "
1157  "bit integers. The determinants_tools.py script can transform this file using the 'transform' flag.");
1158  APP_ABORT("Unknown HDF5 CI format");
1159  }
1160 
1161  if (!hin.readEntry(temps[grp], ds_tag))
1162  throw std::runtime_error("Unknown HDF5 CI format");
1163  }
1164 
1165  std::vector<std::string> MyCIs(nGroups);
1166  std::vector<ci_configuration> dummyCs(nGroups);
1167  for (int grp = 0; grp < nGroups; grp++)
1168  {
1169  MyCIs[grp].resize(nstates);
1170  dummyCs[grp].occup.resize(nstates, false);
1171  for (size_t i = 0; i < nstates; i++)
1172  dummyCs[grp].occup[i] = true;
1173  }
1174 
1175  hin.close();
1176  app_log() << " Done reading " << ndets << " CIs from H5!" << std::endl;
1177 
1178  std::vector<int> cnts(nGroups, 0);
1179  std::vector<std::unordered_map<std::string, int>> MyMaps(nGroups);
1180 
1181  app_log() << " Sorting unique CIs" << std::endl;
1182  ///This loop will find all unique Determinants in and store them "unsorted" in a new container uniqueConfg_up
1183  ///and uniqueConfg_dn. The sorting is not done here
1184  for (int ni = 0; ni < ndets; ni++)
1185  {
1186  if (std::abs(CIcoeff[ni]) < cutoff)
1187  continue;
1188 
1189  int j = 0;
1190  for (int k = 0; k < N_int; k++)
1191  {
1192  std::vector<std::bitset<bit_kind>> a2s(nGroups);
1193  for (int grp = 0; grp < nGroups; grp++)
1194  {
1195  uint64_t a = temps[grp][ni][k];
1196  a2s[grp] = a;
1197  }
1198 
1199  for (int i = 0; i < bit_kind; i++)
1200  {
1201  if (j < nstates)
1202  {
1203  for (int grp = 0; grp < nGroups; grp++)
1204  MyCIs[grp][j] = a2s[grp][i] ? '1' : '0';
1205  j++;
1206  }
1207  }
1208  }
1209  coeff.push_back(CIcoeff[ni]);
1210  std::ostringstream h5tag;
1211  h5tag << "CIcoeff_" << ni;
1212  CItags.push_back(h5tag.str());
1213 
1214  for (int grp = 0; grp < nGroups; grp++)
1215  {
1216  std::unordered_map<std::string, int>::const_iterator got = MyMaps[grp].find(MyCIs[grp]);
1217 
1218  if (got == MyMaps[grp].end())
1219  {
1220  uniqueConfgs[grp].push_back(dummyCs[grp]);
1221  uniqueConfgs[grp].back().add_occupation(MyCIs[grp]);
1222  C2nodes[grp].push_back(cnts[grp]);
1223  MyMaps[grp].insert(std::pair<std::string, int>(MyCIs[grp], cnts[grp]));
1224  cnts[grp]++;
1225  }
1226  else
1227  {
1228  C2nodes[grp].push_back(got->second);
1229  }
1230  }
1231  sumsq += CIcoeff[ni] * CIcoeff[ni];
1232  }
1233 
1234  app_log() << " Done Sorting unique CIs" << std::endl;
1235  app_log() << "Found " << coeff.size() << " terms in the MSD expansion.\n";
1236  if (coeff.size() == 0)
1237  throw std::runtime_error(
1238  "MSD expansion is empty with either zero determinants input or remaining after cutoff applied.");
1239 
1240  app_log() << "Norm of ci vector (sum of ci^2): " << sumsq << std::endl;
1241 
1242  for (auto grp = 0; grp < nGroups; grp++)
1243  app_log() << "Found " << uniqueConfgs[grp].size() << " unique group " << grp << " determinants.\n";
1244 
1245  return success;
1246 }
1247 } // namespace qmcplusplus
base class for Single-particle orbital sets
Definition: SPOSet.h:46
static std::string det_tag
the element name for a determinant, may contain (0..*) orbital or parameter element ...
static std::string multisd_tag
the element name for a multi slater determinant wavefunction
std::ostream & app_warning()
Definition: OutputManager.h:69
std::unique_ptr< MultiSlaterDetTableMethod > createMSDFast(xmlNodePtr cur, ParticleSet &target_ptcl, std::vector< std::unique_ptr< SPOSet >> &&spo_clones, const bool spinor, const bool use_precompute) const
std::unique_ptr< WaveFunctionComponent > buildComponent(xmlNodePtr cur) override
initialize the Antisymmetric wave function for electrons
bool open(const std::filesystem::path &fname, unsigned flags=H5F_ACC_RDWR)
open a file
QMCTraits::RealType real
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
An abstract class for wave function builders.
Tensor< T, D >::Type_t det(const Tensor< T, D > &a)
Definition: TensorOps.h:838
virtual std::unique_ptr< SPOSet > makeClone() const
make a clone of itself every derived class must implement this to have threading working correctly...
Definition: SPOSet.cpp:225
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
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
DetMatInvertor
determinant matrix inverter select
void close()
close all the open groups and file
Definition: hdf_archive.cpp:38
std::unique_ptr< DiracDeterminantBase > putDeterminant(xmlNodePtr cur, int spin_group, const std::unique_ptr< SPOSetBuilder > &legacy_input_sposet_builder, const std::unique_ptr< BackflowTransformation > &BFTrans)
process a determinant element
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
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...
static std::string rn_tag
the element name for a released node determinant, may contain (0..*) orbital or parameter element ...
bool is_dataset_of_type(const std::string &aname)
check if aname is a dataset of type T
Definition: hdf_archive.h:180
int size() const
return the number of species
Definition: SpeciesSet.h:53
std::map< std::string, const std::unique_ptr< ParticleSet > > PSetMap
ParticleSet & targetPtcl
reference to the particle set on which targetPsi is defined
for(int i=0;i< size_test;++i) CHECK(Approx(gauss_random_vals[offset_for_rs+i])
Wrapping information on parallelism.
Definition: Communicate.h:68
int groups() const
return the number of groups
Definition: ParticleSet.h:511
void addSPOSet(std::unique_ptr< SPOSet >)
add an SPOSet to sposets map.
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
double norm(const zVec &c)
Definition: VectorOps.h:118
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
bool is_dataset(const std::string &aname)
check if aname is a dataset
Definition: hdf_archive.h:165
int groupsize(int igroup) const
return the size of a group
Definition: ParticleSet.h:527
std::string ClassName
class Name
Definition: MPIObjectBase.h:65
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
static PlatformKind selectPlatform(std::string_view value)
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...
SlaterDetBuilder(Communicate *comm, SPOSetBuilderFactory &factory, ParticleSet &els, TrialWaveFunction &psi, const PSetMap &psets)
constructor
static std::string sd_tag
the element name for a Slater determinant, contains 1..* determinants
std::unique_ptr< BackflowTransformation > buildBackflowTransformation(xmlNodePtr cur)
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void push(const std::string &gname, bool createit=true)
push a group to the group stack
std::vector< std::string > speciesName
Species name list.
Definition: SpeciesSet.h:44
void readCoeffs(hdf_archive &hin, std::vector< VT > &ci_coeff, size_t n_dets, int ext_level) const
Declaration of DiracDeterminantBatched with a S(ingle)P(article)O(rbital)Set.
Class to represent a many-body trial wave function.
void error(const std::string &msg, bool fatal=false)
static std::string backflow_tag
the element name for a backflow transformation
void read(T &data, const std::string &aname)
read the data from the group aname and check status runtime error is issued on I/O error ...
Definition: hdf_archive.h:306
Declaration of DiracDeterminant with a S(ingle)P(article)O(rbital)Set.
std::unique_ptr< SPOSetBuilder > createSPOSetBuilder(xmlNodePtr rootNode)
static std::string sposet_tag
the element name for single-particle orbital set
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
bool readDetList(xmlNodePtr cur, std::vector< std::vector< ci_configuration >> &uniqueConfgs, std::vector< std::vector< size_t >> &C2nodes, std::vector< std::string > &CItags, std::vector< ValueType > &coeff, bool &optimizeCI, std::vector< int > &nptcls, std::unique_ptr< CSFData > &csf_data_ptr) const
int findSpecies(const std::string &name) const
if the input species is not found, add a new species
Definition: SpeciesSet.h:114
void barrier_and_abort(const std::string &msg) const
bool readEntry(T &data, const std::string &aname)
read the data from the group aname and return status use read() for inbuilt error checking ...
Definition: hdf_archive.h:293
Declaration of DiracDeterminantWithBackflow with a S(ingle)P(article)O(rbital)Set.
SPOSetBuilderFactory & sposet_builder_factory_
reference to the sposet_builder_factory, should be const once the legacy input style is removed ...
bool readDetListH5(xmlNodePtr cur, std::vector< std::vector< ci_configuration >> &uniqueConfgs, std::vector< std::vector< size_t >> &C2nodes, std::vector< std::string > &CItags, std::vector< ValueType > &coeff, bool &optimizeCI, std::vector< int > &nptcls) const
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
std::string getNodeName(xmlNodePtr cur)
Definition: libxmldefs.cpp:15
const PSetMap & ptclPool
reference to a PSetMap
const std::vector< std::string > candidate_values