QMCPACK
CuspCorrectionConstruction.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) 2023 QMCPACK developers.
6 //
7 // File developed by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
8 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
9 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 //
13 // File created by: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
18 #include "Message/Communicate.h"
20 #include "Utilities/FairDivide.h"
21 #include "SoaLocalizedBasisSet.h"
22 #include "SoaAtomicBasisSet.h"
23 #include "MultiQuinticSpline1D.h"
25 #include "OhmmsData/AttributeSet.h"
26 
27 
28 namespace qmcplusplus
29 {
30 bool readCuspInfo(const std::string& cuspInfoFile,
31  const std::string& objectName,
32  int OrbitalSetSize,
34 {
35  bool success = true;
36  int ncenter = info.rows();
37  app_log() << "Reading cusp info from : " << cuspInfoFile << std::endl;
38  Libxml2Document adoc;
39  if (!adoc.parse(cuspInfoFile))
40  {
41  app_log() << "Could not find precomputed cusp data for spo set: " << objectName << std::endl;
42  app_log() << "Recalculating data.\n";
43  return false;
44  }
45  xmlNodePtr head = adoc.getRoot();
46  head = head->children;
47  xmlNodePtr cur = NULL, ctr;
48  while (head != NULL)
49  {
50  std::string cname(getNodeName(head));
51  if (cname == "sposet")
52  {
53  std::string name;
54  OhmmsAttributeSet spoAttrib;
55  spoAttrib.add(name, "name");
56  spoAttrib.put(head);
57  if (name == objectName)
58  {
59  cur = head;
60  break;
61  }
62  }
63  head = head->next;
64  }
65  if (cur == NULL)
66  {
67  app_log() << "Could not find precomputed cusp data for spo set: " << objectName << std::endl;
68  app_log() << "Recalculating data.\n";
69  return false;
70  }
71  else
72  {
73  app_log() << "Found precomputed cusp data for spo set: " << objectName << std::endl;
74  }
75  cur = cur->children;
76  while (cur != NULL)
77  {
78  std::string cname(getNodeName(cur));
79  if (cname == "center")
80  {
81  int num = -1;
82  OhmmsAttributeSet Attrib;
83  Attrib.add(num, "num");
84  Attrib.put(cur);
85  if (num < 0 || num >= ncenter)
86  {
87  APP_ABORT("Error with cusp info xml block. incorrect center number. \n");
88  }
89  ctr = cur->children;
90  while (ctr != NULL)
91  {
92  std::string cname(getNodeName(ctr));
93  if (cname == "orbital")
94  {
95  int orb = -1;
96  OhmmsAttributeSet orbAttrib;
97  QMCTraits::RealType a1(0.0), a2, a3, a4, a5, a6, a7, a8, a9;
98  orbAttrib.add(orb, "num");
99  orbAttrib.add(a1, "redo");
100  orbAttrib.add(a2, "C");
101  orbAttrib.add(a3, "sg");
102  orbAttrib.add(a4, "rc");
103  orbAttrib.add(a5, "a1");
104  orbAttrib.add(a6, "a2");
105  orbAttrib.add(a7, "a3");
106  orbAttrib.add(a8, "a4");
107  orbAttrib.add(a9, "a5");
108  orbAttrib.put(ctr);
109  if (orb < OrbitalSetSize)
110  {
111  info(num, orb).redo = a1;
112  info(num, orb).C = a2;
113  info(num, orb).sg = a3;
114  info(num, orb).Rc = a4;
115  info(num, orb).alpha[0] = a5;
116  info(num, orb).alpha[1] = a6;
117  info(num, orb).alpha[2] = a7;
118  info(num, orb).alpha[3] = a8;
119  info(num, orb).alpha[4] = a9;
120  }
121  }
122  ctr = ctr->next;
123  }
124  }
125  cur = cur->next;
126  }
127  return success;
128 }
129 
130 void saveCusp(const std::string& filename, const Matrix<CuspCorrectionParameters>& info, const std::string& id)
131 {
132  const int num_centers = info.rows();
133  const int orbital_set_size = info.cols();
134  xmlDocPtr doc = xmlNewDoc((const xmlChar*)"1.0");
135  xmlNodePtr cuspRoot = xmlNewNode(NULL, BAD_CAST "qmcsystem");
136  xmlNodePtr spo = xmlNewNode(NULL, (const xmlChar*)"sposet");
137  xmlNewProp(spo, (const xmlChar*)"name", (const xmlChar*)id.c_str());
138  xmlAddChild(cuspRoot, spo);
139  xmlDocSetRootElement(doc, cuspRoot);
140 
141  for (int center_idx = 0; center_idx < num_centers; center_idx++)
142  {
143  xmlNodePtr ctr = xmlNewNode(NULL, (const xmlChar*)"center");
144  std::ostringstream num;
145  num << center_idx;
146  xmlNewProp(ctr, (const xmlChar*)"num", (const xmlChar*)num.str().c_str());
147 
148  for (int mo_idx = 0; mo_idx < orbital_set_size; mo_idx++)
149  {
150  std::ostringstream num0, C, sg, rc, a1, a2, a3, a4, a5;
151  xmlNodePtr orb = xmlNewNode(NULL, (const xmlChar*)"orbital");
152  num0 << mo_idx;
153  xmlNewProp(orb, (const xmlChar*)"num", (const xmlChar*)num0.str().c_str());
154 
155 
156  C.setf(std::ios::scientific, std::ios::floatfield);
157  C.precision(14);
158  C << info(center_idx, mo_idx).C;
159  sg.setf(std::ios::scientific, std::ios::floatfield);
160  sg.precision(14);
161  sg << info(center_idx, mo_idx).sg;
162  rc.setf(std::ios::scientific, std::ios::floatfield);
163  rc.precision(14);
164  rc << info(center_idx, mo_idx).Rc;
165  a1.setf(std::ios::scientific, std::ios::floatfield);
166  a1.precision(14);
167  a1 << info(center_idx, mo_idx).alpha[0];
168  a2.setf(std::ios::scientific, std::ios::floatfield);
169  a2.precision(14);
170  a2 << info(center_idx, mo_idx).alpha[1];
171  a3.setf(std::ios::scientific, std::ios::floatfield);
172  a3.precision(14);
173  a3 << info(center_idx, mo_idx).alpha[2];
174  a4.setf(std::ios::scientific, std::ios::floatfield);
175  a4.precision(14);
176  a4 << info(center_idx, mo_idx).alpha[3];
177  a5.setf(std::ios::scientific, std::ios::floatfield);
178  a5.precision(14);
179  a5 << info(center_idx, mo_idx).alpha[4];
180  xmlNewProp(orb, (const xmlChar*)"C", (const xmlChar*)C.str().c_str());
181  xmlNewProp(orb, (const xmlChar*)"sg", (const xmlChar*)sg.str().c_str());
182  xmlNewProp(orb, (const xmlChar*)"rc", (const xmlChar*)rc.str().c_str());
183  xmlNewProp(orb, (const xmlChar*)"a1", (const xmlChar*)a1.str().c_str());
184  xmlNewProp(orb, (const xmlChar*)"a2", (const xmlChar*)a2.str().c_str());
185  xmlNewProp(orb, (const xmlChar*)"a3", (const xmlChar*)a3.str().c_str());
186  xmlNewProp(orb, (const xmlChar*)"a4", (const xmlChar*)a4.str().c_str());
187  xmlNewProp(orb, (const xmlChar*)"a5", (const xmlChar*)a5.str().c_str());
188  xmlAddChild(ctr, orb);
189  }
190  xmlAddChild(spo, ctr);
191  }
192 
193  app_log() << "Saving resulting cusp Info xml block to: " << filename << std::endl;
194  xmlSaveFormatFile(filename.c_str(), doc, 1);
195  xmlFreeDoc(doc);
196 }
197 
199 {
200 #ifdef HAVE_MPI
201  std::vector<double> buffer(9);
202  buffer[0] = param.Rc;
203  buffer[1] = param.C;
204  buffer[2] = param.sg;
205  buffer[3] = param.alpha[0];
206  buffer[4] = param.alpha[1];
207  buffer[5] = param.alpha[2];
208  buffer[6] = param.alpha[3];
209  buffer[7] = param.alpha[4];
210  buffer[8] = param.redo;
211 
212  Comm.comm.broadcast(buffer.begin(), buffer.end(), root);
213 
214  param.Rc = buffer[0];
215  param.C = buffer[1];
216  param.sg = buffer[2];
217  param.alpha[0] = buffer[3];
218  param.alpha[1] = buffer[4];
219  param.alpha[2] = buffer[5];
220  param.alpha[3] = buffer[6];
221  param.alpha[4] = buffer[7];
222  param.redo = buffer[8] == 0.0 ? 0 : 1;
223 #endif
224 }
225 
226 void splitPhiEta(int center, const std::vector<bool>& corrCenter, LCAOrbitalSet& Phi, LCAOrbitalSet& Eta)
227 {
229 
230  std::vector<bool> is_s_orbital(Phi.myBasisSet->BasisSetSize, false);
231  std::vector<bool> correct_this_center(corrCenter.size(), false);
232  correct_this_center[center] = corrCenter[center];
233 
234  Phi.myBasisSet->queryOrbitalsForSType(correct_this_center, is_s_orbital);
235 
236  int nOrbs = Phi.getOrbitalSetSize();
237  int bss = Phi.getBasisSetSize();
238 
239  for (int i = 0; i < bss; i++)
240  {
241  if (is_s_orbital[i])
242  {
243  auto& cref(*(Eta.C));
244  for (int k = 0; k < nOrbs; k++)
245  cref(k, i) = 0.0; //Eta->C(k,i) = 0.0;
246  }
247  else
248  {
249  auto& cref(*(Phi.C));
250  for (int k = 0; k < nOrbs; k++)
251  cref(k, i) = 0.0; //Phi->C(k,i) = 0.0;
252  }
253  }
254 }
255 
256 void removeSTypeOrbitals(const std::vector<bool>& corrCenter, LCAOrbitalSet& Phi)
257 {
259 
260  std::vector<bool> is_s_orbital(Phi.myBasisSet->BasisSetSize, false);
261 
262  Phi.myBasisSet->queryOrbitalsForSType(corrCenter, is_s_orbital);
263 
264  int nOrbs = Phi.getOrbitalSetSize();
265  int bss = Phi.getBasisSetSize();
266 
267  for (int i = 0; i < bss; i++)
268  {
269  if (is_s_orbital[i])
270  {
271  auto& cref(*(Phi.C));
272  for (int k = 0; k < nOrbs; k++)
273  cref(k, i) = 0.0;
274  }
275  }
276 }
277 
278 
279 // Will be the corrected value for r < rc and the original wavefunction for r > rc
281  ParticleSet* sourceP,
282  int curOrb_,
283  int curCenter_,
284  SPOSet* Phi,
287  const CuspCorrectionParameters& data)
288 {
289  OneMolecularOrbital phiMO(targetP, sourceP, Phi);
290  phiMO.changeOrbital(curCenter_, curOrb_);
291  CuspCorrection cusp(data);
292 
293  for (int i = 0; i < xgrid.size(); i++)
294  {
295  rad_orb[i] = phiBar(cusp, xgrid[i], phiMO);
296  }
297 }
298 
300 
301 // Get the ideal local energy at one point
302 // Eq. 17 in the paper. Coefficients are taken from the paper.
304 {
305  RealType beta[7] = {3.25819, -15.0126, 33.7308, -42.8705, 31.2276, -12.1316, 1.94692};
306  RealType idealEL = beta0;
307  RealType r1 = r * r;
308  for (int i = 0; i < 7; i++)
309  {
310  idealEL += beta[i] * r1;
311  r1 *= r;
312  }
313  return idealEL * Z * Z;
314 }
315 
316 // Get the ideal local energy for a vector of positions
317 void getIdealLocalEnergy(const ValueVector& pos, RealType Z, RealType Rc, RealType ELorigAtRc, ValueVector& ELideal)
318 {
319  // assert(pos.size() == ELideal.size()
320  RealType beta0 = 0.0;
321  RealType tmp = getOneIdealLocalEnergy(Rc, Z, beta0);
322  beta0 = (ELorigAtRc - tmp) / (Z * Z);
323  for (int i = 0; i < pos.size(); i++)
324  {
325  ELideal[i] = getOneIdealLocalEnergy(pos[i], Z, beta0);
326  }
327 }
328 
329 // Evaluate constraints. Equations 9-13 in the paper.
330 void evalX(RealType valRc,
331  GradType gradRc,
332  ValueType lapRc,
333  RealType Rc,
334  RealType Z,
335  RealType C,
336  RealType valAtZero,
337  RealType eta0,
339 {
340  X[0] = std::log(std::abs(valRc - C));
341  X[1] = gradRc[0] / (valRc - C);
342  X[2] = (lapRc - 2.0 * gradRc[0] / Rc) / (valRc - C);
343  X[3] = -Z * (valAtZero + eta0) / (valAtZero - C);
344  X[4] = std::log(std::abs(valAtZero - C));
345 }
346 
347 // Compute polynomial coefficients from constraints. Eq. 14 in the paper.
349 {
350  RealType RcInv = 1.0 / Rc, RcInv2 = RcInv * RcInv;
351  alpha[0] = X[4];
352  alpha[1] = X[3];
353  alpha[2] = 6.0 * X[0] * RcInv2 - 3.0 * X[1] * RcInv + X[2] * 0.5 - 3.0 * X[3] * RcInv - 6.0 * X[4] * RcInv2 -
354  0.5 * X[1] * X[1];
355  alpha[3] = -8.0 * X[0] * RcInv2 * RcInv + 5.0 * X[1] * RcInv2 - X[2] * RcInv + 3.0 * X[3] * RcInv2 +
356  8.0 * X[4] * RcInv2 * RcInv + X[1] * X[1] * RcInv;
357  alpha[4] = 3.0 * X[0] * RcInv2 * RcInv2 - 2.0 * X[1] * RcInv2 * RcInv + 0.5 * X[2] * RcInv2 - X[3] * RcInv2 * RcInv -
358  3.0 * X[4] * RcInv2 * RcInv2 - 0.5 * X[1] * X[1] * RcInv2;
359 }
360 
361 // Eq. 16 in the paper.
362 RealType getZeff(RealType Z, RealType etaAtZero, RealType phiBarAtZero) { return Z * (1.0 + etaAtZero / phiBarAtZero); }
363 
365 {
366  if (r <= cusp.cparam.Rc)
367  return cusp.cparam.C + cusp.Rr(r);
368  else
369  return phiMO.phi(r);
370 }
371 
372 // Compute the effective one-electron local energy at a vector of points.
373 // Eq. 15 in the paper for r < Rc. Normal local energy for R > Rc.
375  RealType Zeff,
376  RealType Rc,
377  RealType originalELatRc,
378  CuspCorrection& cusp,
379  OneMolecularOrbital& phiMO,
380  ValueVector& ELcurr)
381 {
382  // assert(pos.size() == ELcurr.size());
383  ValueType val;
384  GradType grad;
385  ValueType lap;
386  phiMO.phi_vgl(Rc, val, grad, lap);
387  RealType dE = originalELatRc - (-0.5 * lap / val - Zeff / Rc);
388  for (int i = 0; i < pos.size(); i++)
389  {
390  RealType r = pos[i];
391  // prevent NaN's if phiBar is zero
392  RealType offset = 1e-12;
393  if (r <= Rc)
394  {
395  RealType dp = cusp.dpr(r);
396  ELcurr[i] = -0.5 * cusp.Rr(r) * (2.0 * dp / r + cusp.d2pr(r) + dp * dp) / (offset + phiBar(cusp, r, phiMO)) -
397  Zeff / r + dE;
398  }
399  else
400  {
401  phiMO.phi_vgl(pos[i], val, grad, lap);
402  ELcurr[i] = -0.5 * lap / val - Zeff / r + dE;
403  }
404  }
405 }
406 
407 // Return value is local energy at Rc
409  RealType Zeff,
410  RealType Rc,
411  OneMolecularOrbital& phiMO,
412  ValueVector& ELorig)
413 {
414  // assert(pos.size() == ELorig.size());
415 
416  ValueType val;
417  GradType grad;
418  ValueType lap;
419  for (int i = 0; i < pos.size(); i++)
420  {
421  RealType r = pos[i];
422  phiMO.phi_vgl(r, val, grad, lap);
423  ELorig[i] = -0.5 * lap / val - Zeff / r;
424  }
425 
426  phiMO.phi_vgl(Rc, val, grad, lap);
427  return -0.5 * lap / val - Zeff / Rc;
428 }
429 
430 // Sum of squares difference between the current local energy and the ideal local energy.
431 // This is the objective function to minimize.
432 RealType getELchi2(const ValueVector& ELcurr, const ValueVector& ELideal)
433 {
434  assert(ELcurr.size() == ELideal.size());
435 
436  RealType chi2 = 0.0;
437  for (int i = 0; i < ELcurr.size(); i++)
438  {
439  RealType diff = ELcurr[i] - ELideal[i];
440  chi2 += diff * diff;
441  }
442  return chi2;
443 }
444 
446 {
450 };
451 
452 // Compute the chi squared distance given a value for phi at zero.
454  ValueVector& pos,
455  ValueVector& ELcurr,
456  ValueVector& ELideal,
457  CuspCorrection& cusp,
458  OneMolecularOrbital& phiMO,
459  ValGradLap phiAtRc,
460  RealType etaAtZero,
461  RealType ELorigAtRc,
462  RealType Z)
463 {
464  cusp.cparam.sg = phi0 > 0.0 ? 1.0 : -1.0;
465  cusp.cparam.C = (phiAtRc.val * phi0 < 0.0) ? 1.5 * phiAtRc.val : 0.0;
467  evalX(phiAtRc.val, phiAtRc.grad, phiAtRc.lap, cusp.cparam.Rc, Z, cusp.cparam.C, phi0, etaAtZero, X);
468  X2alpha(X, cusp.cparam.Rc, cusp.cparam.alpha);
469  RealType Zeff = getZeff(Z, etaAtZero, phiBar(cusp, 0.0, phiMO));
470  getCurrentLocalEnergy(pos, Zeff, cusp.cparam.Rc, ELorigAtRc, cusp, phiMO, ELcurr);
471  RealType chi2 = getELchi2(ELcurr, ELideal);
472  return chi2;
473 }
474 
475 // Optimize free parameter (value of phi at zero) to minimize distance to ideal local energy.
476 // Output is return value and parameter values are in cusp.cparam
478  OneMolecularOrbital& phiMO,
479  RealType Z,
480  RealType eta0,
481  ValueVector& pos,
482  ValueVector& ELcurr,
483  ValueVector& ELideal,
484  RealType start_phi0)
485 {
486  ValGradLap vglAtRc;
487  ValueVector tmp_pos(0);
488  ValueVector ELorig(0);
489  RealType Zeff = getZeff(Z, eta0, phiBar(cusp, 0.0, phiMO));
490 
491  RealType ELorigAtRc = getOriginalLocalEnergy(tmp_pos, Zeff, cusp.cparam.Rc, phiMO, ELorig);
492  getIdealLocalEnergy(pos, Z, cusp.cparam.Rc, ELorigAtRc, ELideal);
493  phiMO.phi_vgl(cusp.cparam.Rc, vglAtRc.val, vglAtRc.grad, vglAtRc.lap);
494 
495  Bracket_min_t<RealType> bracket(start_phi0, 0.0, 0.0, false);
496  try
497  {
498  bracket = bracket_minimum(
499  [&](RealType x) -> RealType {
500  return evaluateForPhi0Body(x, pos, ELcurr, ELideal, cusp, phiMO, vglAtRc, eta0, ELorigAtRc, Z);
501  },
502  start_phi0);
503  }
504  catch (const std::runtime_error& e)
505  {
506  APP_ABORT("Bracketing minimum failed for finding phi0. \n");
507  }
508 
509  auto min_res = find_minimum(
510  [&](RealType x) -> RealType {
511  return evaluateForPhi0Body(x, pos, ELcurr, ELideal, cusp, phiMO, vglAtRc, eta0, ELorigAtRc, Z);
512  },
513  bracket);
514 
515  start_phi0 = min_res.first;
516 
517  return min_res.second;
518 }
519 
520 
521 // Optimize the cutoff radius. There is an inner loop optimizing for phi0 for each value of Rc.
522 // Elcurr and ELideal are expected to have the correct size on input (same size as pos)
523 // Output is parameter values in cusp.cparam
525  OneMolecularOrbital& phiMO,
526  RealType Z,
527  RealType Rc_init,
528  RealType Rc_max,
529  RealType eta0,
530  ValueVector& pos,
531  ValueVector& ELcurr,
532  ValueVector& ELideal)
533 {
534  Bracket_min_t<RealType> bracket(Rc_init, 0.0, 0.0, false);
535  RealType start_phi0 = phiMO.phi(0.0);
536  try
537  {
538  bracket = bracket_minimum(
539  [&](RealType x) -> RealType {
540  cusp.cparam.Rc = x;
541  return minimizeForPhiAtZero(cusp, phiMO, Z, eta0, pos, ELcurr, ELideal, start_phi0);
542  },
543  Rc_init, Rc_max);
544  }
545  catch (const std::runtime_error& e)
546  {
547  APP_ABORT("Bracketing minimum failed for finding rc. \n");
548  }
549 
550 
551  if (bracket.success)
552  {
553  auto min_res = find_minimum(
554  [&](RealType x) -> RealType {
555  cusp.cparam.Rc = x;
556  return minimizeForPhiAtZero(cusp, phiMO, Z, eta0, pos, ELcurr, ELideal, start_phi0);
557  },
558  bracket);
559  }
560  else
561  {
562  cusp.cparam.Rc = bracket.a;
563  minimizeForPhiAtZero(cusp, phiMO, Z, eta0, pos, ELcurr, ELideal, start_phi0);
564  }
565 }
566 
567 // Modifies orbital set lcwc
569  ParticleSet& targetPtcl,
570  ParticleSet& sourcePtcl,
571  LCAOrbitalSet& lcao,
572  SoaCuspCorrection& cusp,
573  const std::string& id)
574 {
575  const int num_centers = info.rows();
576  const int orbital_set_size = info.cols();
578 
579  NewTimer& cuspApplyTimer = createGlobalTimer("CuspCorrectionConstruction::applyCuspCorrection", timer_level_medium);
580 
581  ScopedTimer cuspApplyTimerWrapper(cuspApplyTimer);
582 
583  LCAOrbitalSet phi("phi", std::unique_ptr<LCAOrbitalSet::basis_type>(lcao.myBasisSet->makeClone()),
584  lcao.getOrbitalSetSize(), lcao.isIdentity(), lcao.isOMPoffload());
585 
586  LCAOrbitalSet eta("eta", std::unique_ptr<LCAOrbitalSet::basis_type>(lcao.myBasisSet->makeClone()),
587  lcao.getOrbitalSetSize(), lcao.isIdentity(), lcao.isOMPoffload());
588 
589  std::vector<bool> corrCenter(num_centers, "true");
590 
591  //What's this grid's lifespan? Why on the heap?
592  auto radial_grid = std::make_unique<LogGrid<RealType>>();
593  radial_grid->set(0.000001, 100.0, 1001);
594 
595 
596  Vector<RealType> xgrid;
597  Vector<RealType> rad_orb;
598  xgrid.resize(radial_grid->size());
599  rad_orb.resize(radial_grid->size());
600  for (int ig = 0; ig < radial_grid->size(); ig++)
601  {
602  xgrid[ig] = radial_grid->r(ig);
603  }
604 
605  for (int ic = 0; ic < num_centers; ic++)
606  {
607  *eta.C = *lcao.C;
608  *phi.C = *lcao.C;
609 
610  splitPhiEta(ic, corrCenter, phi, eta);
611 
612  // loop over MO index - cot must be an array (of len MO size)
613  // the loop is inside cot - in the multiqunitic
614  auto cot = std::make_unique<CuspCorrectionAtomicBasis<RealType>>();
615  cot->initializeRadialSet(*radial_grid, orbital_set_size);
616  //How is this useful?
617  // cot->ID.resize(orbital_set_size);
618  // for (int mo_idx = 0; mo_idx < orbital_set_size; mo_idx++) {
619  // cot->ID[mo_idx] = mo_idx;
620  // }
621 
622  for (int mo_idx = 0; mo_idx < orbital_set_size; mo_idx++)
623  {
624  computeRadialPhiBar(&targetPtcl, &sourcePtcl, mo_idx, ic, &phi, xgrid, rad_orb, info(ic, mo_idx));
625  RealType yprime_i = (rad_orb[1] - rad_orb[0]) / (radial_grid->r(1) - radial_grid->r(0));
626  OneDimQuinticSpline<RealType> radial_spline(radial_grid->makeClone(), rad_orb);
627  radial_spline.spline(0, yprime_i, rad_orb.size() - 1, 0.0);
628  cot->addSpline(mo_idx, radial_spline);
629 
631  {
632  // For testing against AoS output
633  // Output phiBar to soaOrbs.downdet.C0.MO0
634  int nElms = 500;
635  RealType dx = info(ic, mo_idx).Rc * 1.2 / nElms;
636  Vector<RealType> pos;
637  Vector<RealType> output_orb;
638  pos.resize(nElms);
639  output_orb.resize(nElms);
640  for (int i = 0; i < nElms; i++)
641  {
642  pos[i] = (i + 1.0) * dx;
643  }
644  computeRadialPhiBar(&targetPtcl, &sourcePtcl, mo_idx, ic, &phi, pos, output_orb, info(ic, mo_idx));
645  std::string filename = "soaOrbs." + id + ".C" + std::to_string(ic) + ".MO" + std::to_string(mo_idx);
646  std::cout << "Writing to " << filename << std::endl;
647  std::ofstream out(filename.c_str());
648  out << "# r phiBar(r)" << std::endl;
649  for (int i = 0; i < nElms; i++)
650  {
651  out << pos[i] << " " << output_orb[i] << std::endl;
652  }
653  out.close();
654  }
655  }
656  cusp.add(ic, std::move(cot));
657  }
658  removeSTypeOrbitals(corrCenter, lcao);
659 }
660 
662  const ParticleSet& targetPtcl,
663  const ParticleSet& sourcePtcl,
664  const LCAOrbitalSet& lcao,
665  const std::string& id,
666  Communicate& Comm)
667 {
668  const int num_centers = info.rows();
669  const int orbital_set_size = info.cols();
671 
672  NewTimer& cuspCreateTimer = createGlobalTimer("CuspCorrectionConstruction::createCuspParameters", timer_level_medium);
673  NewTimer& splitPhiEtaTimer = createGlobalTimer("CuspCorrectionConstruction::splitPhiEta", timer_level_fine);
674  NewTimer& computeTimer = createGlobalTimer("CuspCorrectionConstruction::computeCorrection", timer_level_fine);
675 
676  ScopedTimer createCuspTimerWrapper(cuspCreateTimer);
677 
678  LCAOrbitalSet phi("phi", std::unique_ptr<LCAOrbitalSet::basis_type>(lcao.myBasisSet->makeClone()),
679  lcao.getOrbitalSetSize(), lcao.isIdentity(), lcao.isOMPoffload());
680 
681  LCAOrbitalSet eta("eta", std::unique_ptr<LCAOrbitalSet::basis_type>(lcao.myBasisSet->makeClone()),
682  lcao.getOrbitalSetSize(), lcao.isIdentity(), lcao.isOMPoffload());
683 
684  std::vector<bool> corrCenter(num_centers, "true");
685 
687  int npts = 500;
688 
689  // Parallelize correction of MO's across MPI ranks
690  std::vector<int> offset;
691  FairDivideLow(orbital_set_size, Comm.size(), offset);
692 
693  int start_mo = offset[Comm.rank()];
694  int end_mo = offset[Comm.rank() + 1];
695  app_log() << " Number of molecular orbitals to compute correction on this rank: " << end_mo - start_mo << std::endl;
696 
697 // Specify dynamic scheduling explicitly for load balancing. Each iteration should take enough
698 // time that scheduling overhead is not an issue.
699 #pragma omp parallel for schedule(dynamic) collapse(2)
700  for (int center_idx = 0; center_idx < num_centers; center_idx++)
701  {
702  for (int mo_idx = start_mo; mo_idx < end_mo; mo_idx++)
703  {
704  ParticleSet localTargetPtcl(targetPtcl);
705  ParticleSet localSourcePtcl(sourcePtcl);
706 
707  LCAOrbitalSet local_phi("local_phi", std::unique_ptr<LCAOrbitalSet::basis_type>(phi.myBasisSet->makeClone()),
708  phi.getOrbitalSetSize(), phi.isIdentity(), phi.isOMPoffload());
709 
710  LCAOrbitalSet local_eta("local_eta", std::unique_ptr<LCAOrbitalSet::basis_type>(eta.myBasisSet->makeClone()),
711  eta.getOrbitalSetSize(), eta.isIdentity(), eta.isOMPoffload());
712 
713 #pragma omp critical
714  app_log() << " Working on MO: " << mo_idx << " Center: " << center_idx << std::endl;
715 
716  {
717  ScopedTimer local_timer(splitPhiEtaTimer);
718 
719  *local_eta.C = *lcao.C;
720  *local_phi.C = *lcao.C;
721  splitPhiEta(center_idx, corrCenter, local_phi, local_eta);
722  }
723 
724  bool corrO = false;
725  auto& cref(*(local_phi.C));
726  for (int ip = 0; ip < cref.cols(); ip++)
727  {
728  if (std::abs(cref(mo_idx, ip)) > 0)
729  {
730  corrO = true;
731  break;
732  }
733  }
734 
735  if (corrO)
736  {
737  OneMolecularOrbital etaMO(&localTargetPtcl, &localSourcePtcl, &local_eta);
738  etaMO.changeOrbital(center_idx, mo_idx);
739 
740  OneMolecularOrbital phiMO(&localTargetPtcl, &localSourcePtcl, &local_phi);
741  phiMO.changeOrbital(center_idx, mo_idx);
742 
743  SpeciesSet& tspecies(localSourcePtcl.getSpeciesSet());
744  int iz = tspecies.addAttribute("charge");
745  RealType Z = tspecies(iz, localSourcePtcl.GroupID[center_idx]);
746 
747  RealType Rc_max = 0.2;
748  RealType rc = 0.1;
749 
750  RealType dx = rc * 1.2 / npts;
751  ValueVector pos(npts);
752  ValueVector ELideal(npts);
753  ValueVector ELcurr(npts);
754  for (int i = 0; i < npts; i++)
755  {
756  pos[i] = (i + 1.0) * dx;
757  }
758 
759  RealType eta0 = etaMO.phi(0.0);
760  ValueVector ELorig(npts);
761  CuspCorrection cusp(info(center_idx, mo_idx));
762  {
763  ScopedTimer local_timer(computeTimer);
764  minimizeForRc(cusp, phiMO, Z, rc, Rc_max, eta0, pos, ELcurr, ELideal);
765  }
766  // Update shared object. Each iteration accesses a different element and
767  // this is an array (no bookkeeping data to update), so no synchronization
768  // is necessary.
769  info(center_idx, mo_idx) = cusp.cparam;
770  }
771  }
772  }
773 
774  for (int root = 0; root < Comm.size(); root++)
775  {
776  int start_mo = offset[root];
777  int end_mo = offset[root + 1];
778  for (int mo_idx = start_mo; mo_idx < end_mo; mo_idx++)
779  {
780  for (int center_idx = 0; center_idx < num_centers; center_idx++)
781  {
782  broadcastCuspInfo(info(center_idx, mo_idx), Comm, root);
783  }
784  }
785  }
786 }
787 
788 } // namespace qmcplusplus
base class for Single-particle orbital sets
Definition: SPOSet.h:46
void resize(size_type n, Type_t val=Type_t())
Resize the container.
Definition: OhmmsVector.h:166
Convert CorrectingOrbitalBasisSet using MultiQuinticSpline1D<T>
class that handles xmlDoc
Definition: Libxml2Doc.h:76
TinyVector< ValueType, 5 > alpha
The coefficients of the polynomial in Eq 8.
One-Dimensional linear-grid.
void minimizeForRc(CuspCorrection &cusp, OneMolecularOrbital &phiMO, RealType Z, RealType Rc_init, RealType Rc_max, RealType eta0, ValueVector &pos, ValueVector &ELcurr, ValueVector &ELideal)
Minimize chi2 with respect to Rc and phi at zero.
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
int getBasisSetSize() const
return the size of the basis set
Definition: LCAOrbitalSet.h:78
QTBase::RealType RealType
Definition: Configuration.h:58
RealType dpr(RealType r) const
RealType phiBar(const CuspCorrection &cusp, RealType r, OneMolecularOrbital &phiMO)
Cusp correction parameters.
Bracket_min_t< T > bracket_minimum(const F &f, T initial_value, T bound_max=-1.0)
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
RealType evaluateForPhi0Body(RealType phi0, ValueVector &pos, ValueVector &ELcurr, ValueVector &ELideal, CuspCorrection &cusp, OneMolecularOrbital &phiMO, ValGradLap phiAtRc, RealType etaAtZero, RealType ELorigAtRc, RealType Z)
std::ostream & app_log()
Definition: OutputManager.h:65
RealType sg
The sign of the wavefunction at the nucleus.
CuspCorrectionParameters cparam
RealType Rc
The cutoff radius.
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
void getCurrentLocalEnergy(const ValueVector &pos, RealType Zeff, RealType Rc, RealType originalELatRc, CuspCorrection &cusp, OneMolecularOrbital &phiMO, ValueVector &ELcurr)
Compute effective local energy at vector of points.
xmlNodePtr getRoot()
Definition: Libxml2Doc.h:88
RealType Rr(RealType r) const
std::unique_ptr< basis_type > myBasisSet
pointer to the basis set
Definition: LCAOrbitalSet.h:40
LatticeGaussianProduct::GradType GradType
Timer accumulates time and call counts.
Definition: NewTimer.h:135
void evalX(RealType valRc, GradType gradRc, ValueType lapRc, RealType Rc, RealType Z, RealType C, RealType valAtZero, RealType eta0, TinyVector< ValueType, 5 > &X)
Evaluate various orbital quantities that enter as constraints on the correction.
void saveCusp(const std::string &filename, const Matrix< CuspCorrectionParameters > &info, const std::string &id)
save cusp correction info to a file.
int addAttribute(const std::string &aname)
for a new attribute, allocate the data, !More often used to get the index of a species ...
Definition: SpeciesSet.cpp:45
void broadcastCuspInfo(CuspCorrectionParameters &param, Communicate &Comm, int root)
Broadcast cusp correction parameters.
OrbitalSetTraits< ValueType >::ValueVector ValueVector
int size() const
return the number of tasks
Definition: Communicate.h:118
void applyCuspCorrection(const Matrix< CuspCorrectionParameters > &info, ParticleSet &targetPtcl, ParticleSet &sourcePtcl, LCAOrbitalSet &lcao, SoaCuspCorrection &cusp, const std::string &id)
OutputManagerClass outputManager(Verbosity::HIGH)
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
size_type cols() const
Definition: OhmmsMatrix.h:78
void FairDivideLow(int ntot, int npart, IV &adist)
partition ntot elements among npart
Definition: FairDivide.h:114
int redo
Flag to indicate the correction should be recalculated.
An abstract base class to implement a One-Dimensional grid.
bool readCuspInfo(const std::string &cuspInfoFile, const std::string &objectName, int OrbitalSetSize, Matrix< CuspCorrectionParameters > &info)
Read cusp correction parameters from XML file.
void getIdealLocalEnergy(const ValueVector &pos, RealType Z, RealType Rc, RealType ELorigAtRc, ValueVector &ELideal)
Ideal local energy at a vector of points.
Wrapping information on parallelism.
Definition: Communicate.h:68
RealType getOriginalLocalEnergy(const ValueVector &pos, RealType Zeff, RealType Rc, OneMolecularOrbital &phiMO, ValueVector &ELorig)
Local energy from uncorrected orbital.
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
void removeSTypeOrbitals(const std::vector< bool > &corrCenter, LCAOrbitalSet &Phi)
Remove S atomic orbitals from all molecular orbitals on all centers.
A collection of functions for dividing fairly.
size_type size() const
return the current size
Definition: OhmmsVector.h:162
RealType d2pr(RealType r) const
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
void changeOrbital(int centerIdx, int orbIdx)
std::pair< T, T > find_minimum(const F &f, Bracket_min_t< T > &bracket)
void generateCuspInfo(Matrix< CuspCorrectionParameters > &info, const ParticleSet &targetPtcl, const ParticleSet &sourcePtcl, const LCAOrbitalSet &lcao, const std::string &id, Communicate &Comm)
NewTimer & createGlobalTimer(const std::string &myname, timer_levels mylevel)
std::shared_ptr< OffloadValueMatrix > C
pointer to matrix containing the coefficients
Definition: LCAOrbitalSet.h:42
A localized basis set derived from BasisSetBase<typename COT::ValueType>
Formulas for applying the cusp correction.
int getOrbitalSetSize() const
return the size of the orbitals
Definition: SPOSet.h:88
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
RealType getOneIdealLocalEnergy(RealType r, RealType Z, RealType beta0)
Ideal local energy at one point.
size_type rows() const
Definition: OhmmsMatrix.h:77
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
MakeReturn< UnaryNode< FnLog, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t log(const Vector< T1, C1 > &l)
QMCTraits::RealType RealType
bool isDebugActive() const
Definition: OutputManager.h:45
void computeRadialPhiBar(ParticleSet *targetP, ParticleSet *sourceP, int curOrb_, int curCenter_, SPOSet *Phi, Vector< QMCTraits::RealType > &xgrid, Vector< QMCTraits::RealType > &rad_orb, const CuspCorrectionParameters &data)
Compute the radial part of the corrected wavefunction.
void add(int icenter, std::unique_ptr< COT > aos)
add a new set of Centered Atomic Orbitals
bool parse(const std::string &fname)
Definition: Libxml2Doc.cpp:180
void X2alpha(const TinyVector< ValueType, 5 > &X, RealType Rc, TinyVector< ValueType, 5 > &alpha)
Convert constraints to polynomial parameters.
LatticeGaussianProduct::ValueType ValueType
RealType minimizeForPhiAtZero(CuspCorrection &cusp, OneMolecularOrbital &phiMO, RealType Z, RealType eta0, ValueVector &pos, ValueVector &ELcurr, ValueVector &ELideal, RealType start_phi0)
Minimize chi2 with respect to phi at zero for a fixed Rc.
class to handle linear combinations of basis orbitals used to evaluate the Dirac determinants.
Definition: LCAOrbitalSet.h:30
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
RealType C
A shift to keep correction to a single sign.
void spline(int imin, value_type yp1, int imax, value_type ypn) override
bool isOMPoffload() const override
Query if this SPOSet uses OpenMP offload.
Definition: LCAOrbitalSet.h:58
A derived class from BasisSetBase.
void phi_vgl(RealType r, RealType &val, GradType &grad, RealType &lap)
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
RealType getZeff(RealType Z, RealType etaAtZero, RealType phiBarAtZero)
Effective nuclear charge to keep effective local energy finite at zero.
std::string getNodeName(xmlNodePtr cur)
Definition: libxmldefs.cpp:15
RealType getELchi2(const ValueVector &ELcurr, const ValueVector &ELideal)
Sum of squares difference between the current and ideal local energies This is the objective function...
void splitPhiEta(int center, const std::vector< bool > &corrCenter, LCAOrbitalSet &Phi, LCAOrbitalSet &Eta)
Divide molecular orbital into atomic S-orbitals on this center (phi), and everything else (eta)...
Assume that coeffs.D1 and the LogLightGrid r_values.size() are equal Therefore r must be < r_max...