QMCPACK
DiracDeterminant.cpp
Go to the documentation of this file.
1 // See LICENSE file in top directory for details.
2 //
3 // Copyright (c) 2020 QMCPACK developers.
4 //
5 // File developed by: Bryan Clark, bclark@Princeton.edu, Princeton University
6 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
7 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
11 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
12 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
13 // Jeongnim Kim, jeongnim.kim@intel.com, Intel Corp.
14 //
15 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
16 //////////////////////////////////////////////////////////////////////////////////////
17 
18 #include "DiracDeterminant.h"
19 #include <stdexcept>
20 #include "CPU/BLAS.hpp"
25 
26 namespace qmcplusplus
27 {
28 /** constructor
29  *@param spos the single-particle orbital set
30  *@param first index of the first particle
31  */
32 template<typename DU_TYPE>
33 DiracDeterminant<DU_TYPE>::DiracDeterminant(std::unique_ptr<SPOSet>&& spos,
34  int first,
35  int last,
36  int ndelay,
37  DetMatInvertor matrix_inverter_kind)
38  : DiracDeterminantBase(getClassName(), std::move(spos), first, last),
39  ndelay_(ndelay),
40  invRow_id(-1),
41  matrix_inverter_kind_(matrix_inverter_kind)
42 {
44 
45  RotatedSPOs* rot_spo = dynamic_cast<RotatedSPOs*>(Phi.get());
46  if (rot_spo)
47  rot_spo->buildOptVariables(NumPtcls);
48 
49  if (Phi->getOrbitalSetSize() < NumPtcls)
50  {
51  std::ostringstream err_msg;
52  err_msg << "The SPOSet " << Phi->getName() << " only has " << Phi->getOrbitalSetSize() << " orbitals "
53  << "but this determinant needs at least " << NumPtcls << std::endl;
54  throw std::runtime_error(err_msg.str());
55  }
56 }
57 
58 template<typename DU_TYPE>
60 {
61  ScopedTimer local_timer(InverseTimer);
62  if (matrix_inverter_kind_ == DetMatInvertor::ACCEL)
63  {
64  bool success = false;
65  int failure_counter = 0;
66  do
67  {
68  try
69  {
70  updateEng.invert_transpose(logdetT, invMat, log_value_);
71  if (failure_counter > 0)
72  {
73  std::ostringstream success_msg;
74  success_msg << "Successful rerun matrix inversion on Rank " << OHMMS::Controller->rank() << " Thread "
75  << omp_get_thread_num() << std::endl;
76  std::cerr << success_msg.str();
77  }
78  success = true;
79  }
80  catch (const std::exception& e)
81  {
82  failure_counter++;
83  std::ostringstream err_msg;
84  err_msg << failure_counter << "th matrix inversion on Rank " << OHMMS::Controller->rank() << " Thread "
85  << omp_get_thread_num() << " which failed earlier with an error:\n " << e.what() << std::endl;
86  std::cerr << err_msg.str();
87  if (failure_counter == 1)
88  {
89  //record the bad matrix to a file at the first failure
90  std::ostringstream matfname;
91  matfname << "badmatrix.r" << OHMMS::Controller->rank() << "t" << omp_get_thread_num() << ".txt";
92  std::ofstream matfile(matfname.str().c_str(), std::ios::app);
93  matfile << std::setprecision(14) << std::scientific;
94  for (size_t i = 0; i < logdetT.rows(); i++)
95  {
96  for (size_t j = 0; j < logdetT.cols(); j++)
97  matfile << " " << logdetT[i][j];
98  matfile << std::endl;
99  }
100  }
101  }
102  } while (!success && failure_counter < 5); // try 5 times at maximum
103  if (!success)
104  throw std::runtime_error("Matrix inversion failed after " + std::to_string(failure_counter) + " attempts.\n");
105  }
106  else
107  {
108  host_inverter_.invert_transpose(logdetT, invMat, log_value_);
109  updateEng.initializeInv(psiM);
110  }
111 }
112 
113 
114 ///reset the size: with the number of particles and number of orbtials
115 template<typename DU_TYPE>
116 void DiracDeterminant<DU_TYPE>::resize(int nel, int morb)
117 {
118  if (Bytes_in_WFBuffer > 0)
119  throw std::runtime_error("DiracDeterimnant just went out of sync with buffer");
120  int norb = morb;
121  if (norb <= 0)
122  norb = nel; // for morb == -1 (default)
123  updateEng.resize(norb, ndelay_);
124  psiM.resize(nel, norb);
125  dpsiM.resize(nel, norb);
126  d2psiM.resize(nel, norb);
127  psiV.resize(norb);
128  invRow.resize(norb);
129  psiM_temp.resize(nel, norb);
130 
131  dpsiV.resize(NumOrbitals);
132  dspin_psiV.resize(NumOrbitals);
133  d2psiV.resize(NumOrbitals);
134  FirstAddressOfdV = &(dpsiM(0, 0)[0]); //(*dpsiM.begin())[0]);
135  LastAddressOfdV = FirstAddressOfdV + NumPtcls * NumOrbitals * DIM;
136 }
137 
138 template<typename DU_TYPE>
140 {
141  ScopedTimer local_timer(RatioTimer);
142  const int WorkingIndex = iat - FirstIndex;
143  assert(WorkingIndex >= 0);
144  invRow_id = WorkingIndex;
145  updateEng.getInvRow(psiM, WorkingIndex, invRow);
146  GradType g = simd::dot(invRow.data(), dpsiM[WorkingIndex], invRow.size());
147  assert(checkG(g));
148  return g;
149 }
150 
151 template<typename DU_TYPE>
153  int iat,
154  ComplexType& spingrad)
155 {
156  Phi->evaluate_spin(P, iat, psiV, dspin_psiV);
157  ScopedTimer local_timer(RatioTimer);
158  const int WorkingIndex = iat - FirstIndex;
159  assert(WorkingIndex >= 0);
160  invRow_id = WorkingIndex;
161  updateEng.getInvRow(psiM, WorkingIndex, invRow);
162  GradType g = simd::dot(invRow.data(), dpsiM[WorkingIndex], invRow.size());
163  ComplexType spin_g = simd::dot(invRow.data(), dspin_psiV.data(), invRow.size());
164  spingrad += spin_g;
165 
166  return g;
167 }
168 
169 template<typename DU_TYPE>
171  int iat,
172  GradType& grad_iat)
173 {
174  {
175  ScopedTimer local_timer(SPOVGLTimer);
176  Phi->evaluateVGL(P, iat, psiV, dpsiV, d2psiV);
177  }
178  return ratioGrad_compute(iat, grad_iat);
179 }
180 
181 template<typename DU_TYPE>
183 {
184  ScopedTimer local_timer(RatioTimer);
185 
186  UpdateMode = ORB_PBYP_PARTIAL;
187  const int WorkingIndex = iat - FirstIndex;
188  assert(WorkingIndex >= 0);
189  // This is an satefy mechanism.
190  // check invRow_id against WorkingIndex to see if getInvRow() has been called already
191  // when evalGrad has not been called already or the particle id is not consistent,
192  // invRow is recomputed.
193  if (invRow_id != WorkingIndex)
194  {
195  invRow_id = WorkingIndex;
196  updateEng.getInvRow(psiM, WorkingIndex, invRow);
197  }
198  curRatio = simd::dot(invRow.data(), psiV.data(), invRow.size());
199  grad_iat += static_cast<ValueType>(static_cast<PsiValue>(1.0) / curRatio) *
200  simd::dot(invRow.data(), dpsiV.data(), invRow.size());
201  return curRatio;
202 }
203 
204 template<typename DU_TYPE>
206  int iat,
207  GradType& grad_iat,
208  ComplexType& spingrad_iat)
209 {
210  {
211  ScopedTimer local_timer(SPOVGLTimer);
212  Phi->evaluateVGL_spin(P, iat, psiV, dpsiV, d2psiV, dspin_psiV);
213  }
214 
215  {
216  ScopedTimer local_timer(RatioTimer);
217  UpdateMode = ORB_PBYP_PARTIAL;
218  const int WorkingIndex = iat - FirstIndex;
219  assert(WorkingIndex >= 0);
220  // This is an optimization.
221  // check invRow_id against WorkingIndex to see if getInvRow() has been called already
222  // Some code paths call evalGrad before calling ratioGrad.
223  if (invRow_id != WorkingIndex)
224  {
225  invRow_id = WorkingIndex;
226  updateEng.getInvRow(psiM, WorkingIndex, invRow);
227  }
228  curRatio = simd::dot(invRow.data(), psiV.data(), invRow.size());
229  grad_iat += static_cast<ValueType>(static_cast<PsiValue>(1.0) / curRatio) *
230  simd::dot(invRow.data(), dpsiV.data(), invRow.size());
231 
232  spingrad_iat += static_cast<ValueType>(static_cast<PsiValue>(1.0) / curRatio) *
233  simd::dot(invRow.data(), dspin_psiV.data(), invRow.size());
234  }
235 
236  return curRatio;
237 }
238 
239 template<typename DU_TYPE>
241  const RefVectorWithLeader<ParticleSet>& p_list,
242  int iat,
243  std::vector<PsiValue>& ratios,
244  std::vector<GradType>& grad_new) const
245 {
246  {
247  ScopedTimer local_timer(SPOVGLTimer);
248  RefVectorWithLeader<SPOSet> phi_list(*Phi);
249  phi_list.reserve(wfc_list.size());
250  RefVector<ValueVector> psi_v_list;
251  psi_v_list.reserve(wfc_list.size());
252  RefVector<GradVector> dpsi_v_list;
253  dpsi_v_list.reserve(wfc_list.size());
254  RefVector<ValueVector> d2psi_v_list;
255  d2psi_v_list.reserve(wfc_list.size());
256 
257  for (WaveFunctionComponent& wfc : wfc_list)
258  {
259  auto& det = static_cast<DiracDeterminant<DU_TYPE>&>(wfc);
260  phi_list.push_back(*det.Phi);
261  psi_v_list.push_back(det.psiV);
262  dpsi_v_list.push_back(det.dpsiV);
263  d2psi_v_list.push_back(det.d2psiV);
264  }
265 
266  Phi->mw_evaluateVGL(phi_list, p_list, iat, psi_v_list, dpsi_v_list, d2psi_v_list);
267  }
268 
269  for (int iw = 0; iw < wfc_list.size(); iw++)
270  ratios[iw] = wfc_list.getCastedElement<DiracDeterminant<DU_TYPE>>(iw).ratioGrad_compute(iat, grad_new[iw]);
271 }
272 
273 
274 /** move was accepted, update the real container
275 */
276 template<typename DU_TYPE>
277 void DiracDeterminant<DU_TYPE>::acceptMove(ParticleSet& P, int iat, bool safe_to_delay)
278 {
279  if (curRatio == PsiValue(0))
280  {
281  std::ostringstream msg;
282  msg << "DiracDeterminant::acceptMove curRatio is " << curRatio << "! Report a bug." << std::endl;
283  throw std::runtime_error(msg.str());
284  }
285  ScopedTimer local_timer(UpdateTimer);
286  const int WorkingIndex = iat - FirstIndex;
287  assert(WorkingIndex >= 0);
288  log_value_ += convertValueToLog(curRatio);
289  updateEng.acceptRow(psiM, WorkingIndex, psiV, curRatio);
290  if (!safe_to_delay)
291  updateEng.updateInvMat(psiM);
292  // invRow becomes invalid after accepting a move
293  invRow_id = -1;
294  if (UpdateMode == ORB_PBYP_PARTIAL)
295  {
296  simd::copy(dpsiM[WorkingIndex], dpsiV.data(), NumOrbitals);
297  simd::copy(d2psiM[WorkingIndex], d2psiV.data(), NumOrbitals);
298  }
299  curRatio = 1.0;
300 }
301 
302 /** move was rejected. copy the real container to the temporary to move on
303 */
304 template<typename DU_TYPE>
306 {
307  curRatio = 1.0;
308 }
309 
310 template<typename DU_TYPE>
312 {
313  ScopedTimer local_timer(UpdateTimer);
314  // invRow becomes invalid after updating the inverse matrix
315  invRow_id = -1;
316  updateEng.updateInvMat(psiM);
317 }
318 
319 template<typename DU_TYPE>
323 {
324  if (UpdateMode == ORB_PBYP_RATIO)
325  { //need to compute dpsiM and d2psiM. Do not touch psiM!
326  ScopedTimer local_timer(SPOVGLTimer);
327  Phi->evaluate_notranspose(P, FirstIndex, LastIndex, psiM_temp, dpsiM, d2psiM);
328  UpdateMode = ORB_WALKER;
329  }
330 
331  for (size_t i = 0, iat = FirstIndex; i < NumPtcls; ++i, ++iat)
332  {
333  mValueType dot_temp = simd::dot(psiM[i], d2psiM[i], NumOrbitals);
334  mGradType rv = simd::dot(psiM[i], dpsiM[i], NumOrbitals);
335  G[iat] += rv;
336  L[iat] += dot_temp - dot(rv, rv);
337  }
338 }
339 
340 template<typename DU_TYPE>
342 {
343  if (Bytes_in_WFBuffer == 0)
344  {
345  //add the data: inverse, gradient and laplacian
346  Bytes_in_WFBuffer = buf.current();
347  buf.add(psiM.first_address(), psiM.last_address());
348  buf.add(FirstAddressOfdV, LastAddressOfdV);
349  buf.add(d2psiM.first_address(), d2psiM.last_address());
350  Bytes_in_WFBuffer = buf.current() - Bytes_in_WFBuffer;
351  // free local space
352  psiM.free();
353  dpsiM.free();
354  d2psiM.free();
355  }
356  else
357  {
358  buf.forward(Bytes_in_WFBuffer);
359 #ifndef NDEBUG
360  // this causes too much output in the legacy code.
361  // \todo turn this back on after legacy is dropped,
362  // I don't think it should print at all in the new design
363  // std::cerr << ("You really should know whether you have registered this objects data previously!, consider this an error in the unified code");
364 #endif
365  }
366  buf.add(log_value_);
367 }
368 
369 template<typename DU_TYPE>
373  bool fromscratch)
374 {
375  if (fromscratch)
376  evaluateLog(P, G, L);
377  else
378  updateAfterSweep(P, G, L);
379  return log_value_;
380 }
381 
382 template<typename DU_TYPE>
384  WFBufferType& buf,
385  bool fromscratch)
386 {
387  evaluateGL(P, P.G, P.L, fromscratch);
388  {
389  ScopedTimer local_timer(BufferTimer);
390  buf.forward(Bytes_in_WFBuffer);
391  buf.put(log_value_);
392  }
393  return log_value_;
394 }
395 
396 template<typename DU_TYPE>
398 {
399  ScopedTimer local_timer(BufferTimer);
400  psiM.attachReference(buf.lendReference<ValueType>(psiM.size()));
401  dpsiM.attachReference(buf.lendReference<GradType>(dpsiM.size()));
402  d2psiM.attachReference(buf.lendReference<ValueType>(d2psiM.size()));
403  buf.get(log_value_);
404  // start with invRow labelled invalid
405  invRow_id = -1;
406  updateEng.initializeInv(psiM);
407 }
408 
409 template<typename DU_TYPE>
411 {
412  twf.addGroup(P, P.getGroupID(FirstIndex), Phi.get());
413 }
414 
415 /** return the ratio only for the iat-th partcle move
416  * @param P current configuration
417  * @param iat the particle thas is being moved
418  */
419 template<typename DU_TYPE>
421 {
422  UpdateMode = ORB_PBYP_RATIO;
423  const int WorkingIndex = iat - FirstIndex;
424  assert(WorkingIndex >= 0);
425  {
426  ScopedTimer local_timer(SPOVTimer);
427  Phi->evaluateValue(P, iat, psiV);
428  }
429  {
430  ScopedTimer local_timer(RatioTimer);
431  // This is an optimization.
432  // check invRow_id against WorkingIndex to see if getInvRow() has been called
433  // This is intended to save redundant compuation in TM1 and TM3
434  if (invRow_id != WorkingIndex)
435  {
436  invRow_id = WorkingIndex;
437  updateEng.getInvRow(psiM, WorkingIndex, invRow);
438  }
439  curRatio = simd::dot(invRow.data(), psiV.data(), invRow.size());
440  }
441  return curRatio;
442 }
443 
444 template<typename DU_TYPE>
445 void DiracDeterminant<DU_TYPE>::evaluateRatios(const VirtualParticleSet& VP, std::vector<ValueType>& ratios)
446 {
447  {
448  ScopedTimer local_timer(RatioTimer);
449  const int WorkingIndex = VP.refPtcl - FirstIndex;
450  assert(WorkingIndex >= 0);
451  std::copy_n(psiM[WorkingIndex], invRow.size(), invRow.data());
452  }
453  {
454  ScopedTimer local_timer(SPOVTimer);
455  Phi->evaluateDetRatios(VP, psiV, invRow, ratios);
456  }
457 }
458 
459 template<typename DU_TYPE>
460 void DiracDeterminant<DU_TYPE>::evaluateSpinorRatios(const VirtualParticleSet& VP, const std::pair<ValueVector, ValueVector>& spinor_multiplier, std::vector<ValueType>& ratios)
461 {
462  {
463  ScopedTimer local_timer(RatioTimer);
464  const int WorkingIndex = VP.refPtcl - FirstIndex;
465  assert(WorkingIndex >= 0);
466  std::copy_n(psiM[WorkingIndex], invRow.size(), invRow.data());
467  }
468  {
469  ScopedTimer local_timer(SPOVTimer);
470  Phi->evaluateDetSpinorRatios(VP, psiV, spinor_multiplier, invRow, ratios);
471  }
472 }
473 
474 template<typename DU_TYPE>
477  std::vector<std::vector<ValueType>>& ratios) const
478 {
479  const size_t nw = wfc_list.size();
480 
481  RefVectorWithLeader<SPOSet> phi_list(*Phi);
482  RefVector<ValueVector> psiV_list;
483  std::vector<const ValueType*> invRow_ptr_list;
484  phi_list.reserve(nw);
485  psiV_list.reserve(nw);
486  invRow_ptr_list.reserve(nw);
487 
488  {
489  ScopedTimer local_timer(RatioTimer);
490  for (size_t iw = 0; iw < nw; iw++)
491  {
492  auto& det = wfc_list.getCastedElement<DiracDeterminant<DU_TYPE>>(iw);
493  const VirtualParticleSet& vp(vp_list[iw]);
494  const int WorkingIndex = vp.refPtcl - FirstIndex;
495  assert(WorkingIndex >= 0);
496  // If DiracDeterminant is in a valid state this copy_n is not necessary.
497  // That is at minimum a call to evaluateLog and ...
498  // std::copy_n(det.psiM[WorkingIndex], det.invRow.s.ize(), det.invRow.data());
499  // build lists
500  phi_list.push_back(*det.Phi);
501  psiV_list.push_back(det.psiV);
502  invRow_ptr_list.push_back(det.psiM[WorkingIndex]);
503  }
504  }
505 
506  {
507  ScopedTimer local_timer(SPOVTimer);
508  // Phi->isOMPoffload() requires device invRow pointers for mw_evaluateDetRatios.
509  // evaluateDetRatios only requires host invRow pointers.
510  if (Phi->isOMPoffload())
511  for (int iw = 0; iw < phi_list.size(); iw++)
512  {
513  Vector<ValueType> invRow(const_cast<ValueType*>(invRow_ptr_list[iw]), psiV_list[iw].get().size());
514  phi_list[iw].evaluateDetRatios(vp_list[iw], psiV_list[iw], invRow, ratios[iw]);
515  }
516  else
517  Phi->mw_evaluateDetRatios(phi_list, vp_list, psiV_list, invRow_ptr_list, ratios);
518  }
519 }
520 
521 template<typename DU_TYPE>
523  const opt_variables_type& optvars,
524  std::vector<ValueType>& ratios,
525  Matrix<ValueType>& dratios)
526 {
527  const int WorkingIndex = VP.refPtcl - FirstIndex;
528  assert(WorkingIndex >= 0);
529  std::copy_n(psiM[WorkingIndex], invRow.size(), invRow.data());
530  Phi->evaluateDerivRatios(VP, optvars, psiV, invRow, ratios, dratios, FirstIndex, LastIndex);
531 }
532 
533 template<typename DU_TYPE>
534 void DiracDeterminant<DU_TYPE>::evaluateRatiosAlltoOne(ParticleSet& P, std::vector<ValueType>& ratios)
535 {
536  ScopedTimer local_timer(SPOVTimer);
537  Phi->evaluateValue(P, -1, psiV);
538  Vector<ValueType> ratios_this_det(ratios.data() + FirstIndex, NumPtcls);
539  MatrixOperators::product(psiM, psiV, ratios_this_det);
540 }
541 
542 
543 template<typename DU_TYPE>
545 {
546  grad_source_psiM.resize(NumPtcls, NumOrbitals);
547  grad_lapl_source_psiM.resize(NumPtcls, NumOrbitals);
548  grad_grad_source_psiM.resize(NumPtcls, NumOrbitals);
549  phi_alpha_Minv.resize(NumPtcls, NumOrbitals);
550  grad_phi_Minv.resize(NumPtcls, NumOrbitals);
551  lapl_phi_Minv.resize(NumPtcls, NumOrbitals);
552  grad_phi_alpha_Minv.resize(NumPtcls, NumOrbitals);
553 }
554 
555 template<typename DU_TYPE>
557  ParticleSet& source,
558  int iat)
559 {
560  GradType g(0.0);
561  if (Phi->hasIonDerivs())
562  {
563  resizeScratchObjectsForIonDerivs();
564  Phi->evaluateGradSource(P, FirstIndex, LastIndex, source, iat, grad_source_psiM);
565  g = simd::dot(psiM.data(), grad_source_psiM.data(), psiM.size());
566  }
567 
568  return g;
569 }
570 
571 template<typename DU_TYPE>
573 {
574  // Hessian is not often used, so only resize/allocate if used
575  grad_grad_source_psiM.resize(psiM.rows(), psiM.cols());
576  //IM A HACK. Assumes evaluateLog has already been executed.
577  Phi->evaluate_notranspose(P, FirstIndex, LastIndex, psiM_temp, dpsiM, grad_grad_source_psiM);
578  invertPsiM(psiM_temp, psiM);
579 
580  phi_alpha_Minv = 0.0;
581  grad_phi_Minv = 0.0;
582  lapl_phi_Minv = 0.0;
583  grad_phi_alpha_Minv = 0.0;
584  //grad_grad_psi.resize(NumPtcls);
585 
586  for (int i = 0, iat = FirstIndex; i < NumPtcls; i++, iat++)
587  {
588  GradType rv = simd::dot(psiM[i], dpsiM[i], NumOrbitals);
589  // HessType hess_tmp=simd::dot(psiM[i],grad_grad_source_psiM[i],NumOrbitals);
590  HessType hess_tmp;
591  hess_tmp = 0.0;
592  hess_tmp = simd::dot(psiM[i], grad_grad_source_psiM[i], NumOrbitals);
593  grad_grad_psi[iat] = hess_tmp - outerProduct(rv, rv);
594  }
595 }
596 
597 template<typename DU_TYPE>
599  ParticleSet& P,
600  ParticleSet& source,
601  int iat,
604 {
605  GradType gradPsi(0.0);
606  if (Phi->hasIonDerivs())
607  {
608  resizeScratchObjectsForIonDerivs();
609  Phi->evaluateGradSource(P, FirstIndex, LastIndex, source, iat, grad_source_psiM, grad_grad_source_psiM,
610  grad_lapl_source_psiM);
611  // HACK HACK HACK
612  // Phi->evaluateVGL(P, FirstIndex, LastIndex, psiM, dpsiM, d2psiM);
613  // psiM_temp = psiM;
614  // LogValue=InvertWithLog(psiM.data(),NumPtcls,NumOrbitals,
615  // WorkSpace.data(),Pivot.data(),PhaseValue);
616  // for (int i=0; i<NumPtcls; i++)
617  // for (int j=0; j<NumPtcls; j++) {
618  // double val = 0.0;
619  // for (int k=0; k<NumPtcls; k++)
620  // val += psiM(i,k) * psiM_temp(k,j);
621  // val -= (i == j) ? 1.0 : 0.0;
622  // if (std::abs(val) > 1.0e-12)
623  // std::cerr << "Error in inverse.\n";
624  // }
625  // for (int i=0; i<NumPtcls; i++) {
626  // P.G[FirstIndex+i] = GradType();
627  // for (int j=0; j<NumOrbitals; j++)
628  // P.G[FirstIndex+i] += psiM(i,j)*dpsiM(i,j);
629  // }
630  // Compute matrices
631  phi_alpha_Minv = 0.0;
632  grad_phi_Minv = 0.0;
633  lapl_phi_Minv = 0.0;
634  grad_phi_alpha_Minv = 0.0;
635  for (int i = 0; i < NumPtcls; i++)
636  for (int j = 0; j < NumOrbitals; j++)
637  {
638  lapl_phi_Minv(i, j) = 0.0;
639  for (int k = 0; k < NumOrbitals; k++)
640  lapl_phi_Minv(i, j) += d2psiM(i, k) * psiM(j, k);
641  }
642  for (int dim = 0; dim < OHMMS_DIM; dim++)
643  {
644  for (int i = 0; i < NumPtcls; i++)
645  for (int j = 0; j < NumOrbitals; j++)
646  {
647  for (int k = 0; k < NumOrbitals; k++)
648  {
649  phi_alpha_Minv(i, j)[dim] += grad_source_psiM(i, k)[dim] * psiM(j, k);
650  grad_phi_Minv(i, j)[dim] += dpsiM(i, k)[dim] * psiM(j, k);
651  for (int dim_el = 0; dim_el < OHMMS_DIM; dim_el++)
652  grad_phi_alpha_Minv(i, j)(dim, dim_el) += grad_grad_source_psiM(i, k)(dim, dim_el) * psiM(j, k);
653  }
654  }
655  }
656  for (int i = 0, iel = FirstIndex; i < NumPtcls; i++, iel++)
657  {
658  HessType dval(0.0);
659  GradType d2val(0.0);
660  for (int dim = 0; dim < OHMMS_DIM; dim++)
661  for (int dim_el = 0; dim_el < OHMMS_DIM; dim_el++)
662  dval(dim, dim_el) = grad_phi_alpha_Minv(i, i)(dim, dim_el);
663  for (int j = 0; j < NumOrbitals; j++)
664  {
665  gradPsi += grad_source_psiM(i, j) * psiM(i, j);
666  for (int dim = 0; dim < OHMMS_DIM; dim++)
667  for (int k = 0; k < OHMMS_DIM; k++)
668  dval(dim, k) -= phi_alpha_Minv(j, i)[dim] * grad_phi_Minv(i, j)[k];
669  }
670  for (int dim = 0; dim < OHMMS_DIM; dim++)
671  {
672  for (int k = 0; k < OHMMS_DIM; k++)
673  grad_grad[dim][iel][k] += dval(dim, k);
674  for (int j = 0; j < NumOrbitals; j++)
675  {
676  // First term, eq 9
677  lapl_grad[dim][iel] += grad_lapl_source_psiM(i, j)[dim] * psiM(i, j);
678  // Second term, eq 9
679  if (j == i)
680  for (int dim_el = 0; dim_el < OHMMS_DIM; dim_el++)
681  lapl_grad[dim][iel] -=
682  (RealType)2.0 * grad_phi_alpha_Minv(j, i)(dim, dim_el) * grad_phi_Minv(i, j)[dim_el];
683  // Third term, eq 9
684  // First term, eq 10
685  lapl_grad[dim][iel] -= phi_alpha_Minv(j, i)[dim] * lapl_phi_Minv(i, j);
686  // Second term, eq 11
687  for (int dim_el = 0; dim_el < OHMMS_DIM; dim_el++)
688  lapl_grad[dim][iel] +=
689  (RealType)2.0 * phi_alpha_Minv(j, i)[dim] * grad_phi_Minv(i, i)[dim_el] * grad_phi_Minv(i, j)[dim_el];
690  }
691  }
692  }
693  }
694  return gradPsi;
695 }
696 
697 
698 /** Calculate the log value of the Dirac determinant for particles
699  *@param P input configuration containing N particles
700  *@param G a vector containing N gradients
701  *@param L a vector containing N laplacians
702  *@return the value of the determinant
703  *
704  *\f$ (first,first+nel). \f$ Add the gradient and laplacian
705  *contribution of the determinant to G(radient) and L(aplacian)
706  *for local energy calculations.
707  */
708 template<typename DU_TYPE>
712 {
713  recompute(P);
714 
715  for (int i = 0, iat = FirstIndex; i < NumPtcls; i++, iat++)
716  {
717  mGradType rv = simd::dot(psiM[i], dpsiM[i], NumOrbitals);
718  mValueType lap = simd::dot(psiM[i], d2psiM[i], NumOrbitals);
719  G[iat] += rv;
720  L[iat] += lap - dot(rv, rv);
721  }
722  return log_value_;
723 }
724 
725 template<typename DU_TYPE>
727 {
728  {
729  ScopedTimer local_timer(SPOVGLTimer);
730  UpdateMode = ORB_WALKER;
731  Phi->evaluate_notranspose(P, FirstIndex, LastIndex, psiM_temp, dpsiM, d2psiM);
732  }
733 
734  invertPsiM(psiM_temp, psiM);
735 
736  // invRow becomes invalid after updating the inverse matrix
737  invRow_id = -1;
738 }
739 
740 template<typename DU_TYPE>
742  const opt_variables_type& active,
743  Vector<ValueType>& dlogpsi,
744  Vector<ValueType>& dhpsioverpsi)
745 {
746  Phi->evaluateDerivatives(P, active, dlogpsi, dhpsioverpsi, FirstIndex, LastIndex);
747 }
748 
749 template<typename DU_TYPE>
751  const opt_variables_type& active,
752  Vector<ValueType>& dlogpsi)
753 {
754  Phi->evaluateDerivativesWF(P, active, dlogpsi, FirstIndex, LastIndex);
755 }
756 
757 template<typename DU_TYPE>
758 std::unique_ptr<DiracDeterminantBase> DiracDeterminant<DU_TYPE>::makeCopy(std::unique_ptr<SPOSet>&& spo) const
759 {
760  return std::make_unique<DiracDeterminant<DU_TYPE>>(std::move(spo), FirstIndex, LastIndex, ndelay_,
761  matrix_inverter_kind_);
762 }
763 
764 template<typename DU_TYPE>
766 {
767  Phi->createResource(collection);
768 }
769 
770 template<typename DU_TYPE>
772  const RefVectorWithLeader<WaveFunctionComponent>& wfc_list) const
773 {
774  auto& wfc_leader = wfc_list.getCastedLeader<DiracDeterminant<DU_TYPE>>();
775  RefVectorWithLeader<SPOSet> phi_list(*wfc_leader.Phi);
776  for (WaveFunctionComponent& wfc : wfc_list)
777  {
778  auto& det = static_cast<DiracDeterminant<DU_TYPE>&>(wfc);
779  phi_list.push_back(*det.Phi);
780  }
781  wfc_leader.Phi->acquireResource(collection, phi_list);
782 }
783 
784 template<typename DU_TYPE>
786  const RefVectorWithLeader<WaveFunctionComponent>& wfc_list) const
787 {
788  auto& wfc_leader = wfc_list.getCastedLeader<DiracDeterminant<DU_TYPE>>();
789  RefVectorWithLeader<SPOSet> phi_list(*wfc_leader.Phi);
790  for (WaveFunctionComponent& wfc : wfc_list)
791  {
792  auto& det = static_cast<DiracDeterminant<DU_TYPE>&>(wfc);
793  phi_list.push_back(*det.Phi);
794  }
795  wfc_leader.Phi->releaseResource(collection, phi_list);
796 }
797 
798 template class DiracDeterminant<>;
799 #if defined(ENABLE_CUDA)
801 #endif
802 #if defined(ENABLE_SYCL)
804 #endif
805 
806 } // namespace qmcplusplus
void mw_evaluateRatios(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< const VirtualParticleSet > &vp_list, std::vector< std::vector< ValueType >> &ratios) const override
evaluate ratios to evaluate the non-local PP multiple walkers
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
void acquireResource(ResourceCollection &collection, const RefVectorWithLeader< WaveFunctionComponent > &wf_list) const override
acquire a shared resource from a collection
void recompute(const ParticleSet &P) override
recompute the value of the WaveFunctionComponents which require critical accuracy.
WaveFunctionComponent::PsiValue PsiValue
Definition: SlaterDet.cpp:25
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
Tensor< T, D >::Type_t det(const Tensor< T, D > &a)
Definition: TensorOps.h:838
void resizeScratchObjectsForIonDerivs()
Resize all temporary arrays required for force computation.
T dot(const T *restrict a, const T *restrict b, int n, TRES res=TRES())
dot product
void acceptMove(ParticleSet &P, int iat, bool safe_to_delay=false) override
move was accepted, update the real container
QTBase::RealType RealType
Definition: Configuration.h:58
void forward(size_type n)
Definition: PooledMemory.h:162
void evaluateSpinorRatios(const VirtualParticleSet &VP, const std::pair< ValueVector, ValueVector > &spinor_multipler, std::vector< ValueType > &ratios) override
Used by SOECPComponent for faster SOC evaluation.
void resize(int nel, int morb)
reset the size: with the number of particles and number of orbtials
DetMatInvertor
determinant matrix inverter select
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
LogValue evaluateGL(const ParticleSet &P, ParticleSet::ParticleGradient &G, ParticleSet::ParticleLaplacian &L, bool fromscratch) override
compute gradients and laplacian of the TWF with respect to each particle.
void evaluateDerivativesWF(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi) override
Compute the derivatives of the log of the wavefunction with respect to optimizable parameters...
GradType evalGradWithSpin(ParticleSet &P, int iat, ComplexType &spingrad) final
return the current spin gradient for the iat-th particle Default implementation assumes that WaveFunc...
int refPtcl
Reference particle.
PsiValue ratioGrad(ParticleSet &P, int iat, GradType &grad_iat) override
evaluate the ratio of the new to old WaveFunctionComponent value and the new gradient ...
QTBase::ComplexType ComplexType
Definition: Configuration.h:59
LogValue evaluateLog(const ParticleSet &P, ParticleSet::ParticleGradient &G, ParticleSet::ParticleLaplacian &L) override
evaluate log of a determinant for a particle set
void copyFromBuffer(ParticleSet &P, WFBufferType &buf) override
For particle-by-particle move.
void mw_ratioGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, std::vector< GradType > &grad_new) const override
compute the ratio of the new to old WaveFunctionComponent value and the new gradient of multiple walk...
void copy(T1 *restrict target, const T2 *restrict source, size_t n)
copy function using memcpy
Definition: algorithm.hpp:40
Attaches a unit to a Vector for IO.
std::complex< T > convertValueToLog(const std::complex< T > &logpsi)
evaluate log(psi) as log(|psi|) and phase
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
ParticleLaplacian L
laplacians of the particles
Definition: ParticleSet.h:85
TWFFastDerivWrapper is a wrapper class for TrialWavefunction that provides separate and low level acc...
OrbitalSetTraits< ValueType >::HessType HessType
GradType evalGrad(ParticleSet &P, int iat) override
return the current gradient for the iat-th particle
#define OHMMS_DIM
Definition: config.h:64
SPOSet::ValueMatrix ValueMatrix
DiracDeterminant(std::unique_ptr< SPOSet > &&spos, int first, int last, int ndelay=1, DetMatInvertor matrix_inverter_kind=DetMatInvertor::ACCEL)
constructor
std::complex< QTFull::RealType > LogValue
void buildOptVariables(size_t nel)
An abstract class for a component of a many-body trial wave function.
omp_int_t omp_get_thread_num()
Definition: OpenMP.h:25
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
void evaluateRatiosAlltoOne(ParticleSet &P, std::vector< ValueType > &ratios) override
evaluate the ratios of one virtual move with respect to all the particles
const std::unique_ptr< SPOSet > Phi
a set of single-particle orbitals used to fill in the values of the matrix
void createResource(ResourceCollection &collection) const override
initialize a shared resource and hand it to a collection
void completeUpdates() override
complete all the delayed or asynchronous operations before leaving the p-by-p move region...
void product(const Matrix< T > &A, const Matrix< T > &B, Matrix< T > &C)
static function to perform C=AB for real matrices
void evaluateDerivRatios(const VirtualParticleSet &VP, const opt_variables_type &optvars, std::vector< ValueType > &ratios, Matrix< ValueType > &dratios) override
evaluate ratios to evaluate the non-local PP
void updateAfterSweep(const ParticleSet &P, ParticleSet::ParticleGradient &G, ParticleSet::ParticleLaplacian &L)
void restore(int iat) override
move was rejected.
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > outerProduct(const TinyVector< T1, D > &lhs, const TinyVector< T2, D > &rhs)
Definition: TinyVector.h:211
void evaluateRatios(const VirtualParticleSet &VP, std::vector< ValueType > &ratios) override
compute multiple ratios for a particle move
void releaseResource(ResourceCollection &collection, const RefVectorWithLeader< WaveFunctionComponent > &wf_list) const override
return a shared resource to a collection
ParticleGradient G
gradients of the particles
Definition: ParticleSet.h:83
CASTTYPE & getCastedElement(size_t i) const
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
PsiValue ratioGrad_compute(int iat, GradType &grad_iat)
internal function computing ratio and gradients after computing the SPOs, used by ratioGrad...
LogValue updateBuffer(ParticleSet &P, WFBufferType &buf, bool fromscratch=false) override
For particle-by-particle move.
PsiValue ratioGradWithSpin(ParticleSet &P, int iat, GradType &grad_iat, ComplexType &spingrad) final
evaluate the ratio of the new to old WaveFunctionComponent value and the new spin gradient Default im...
size_type current() const
Definition: PooledMemory.h:76
std::vector< std::reference_wrapper< T > > RefVector
void registerData(ParticleSet &P, WFBufferType &buf) override
For particle-by-particle move.
void evaluateDerivatives(ParticleSet &P, const opt_variables_type &active, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi) override
Compute the derivatives of both the log of the wavefunction and kinetic energy with respect to optimi...
sycl::event copy_n(sycl::queue &aq, const T1 *restrict VA, size_t array_size, T2 *restrict VC, const std::vector< sycl::event > &events)
Definition: syclBLAS.cpp:548
void registerTWFFastDerivWrapper(const ParticleSet &P, TWFFastDerivWrapper &twf) const final
Finds the SPOSet associated with this determinant, and registers it with WFN wrapper.
void invertPsiM(const ValueMatrix &logdetT, ValueMatrix &invMat)
invert psiM or its copies
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
LatticeGaussianProduct::ValueType ValueType
Declaration of DiracDeterminant with a S(ingle)P(article)O(rbital)Set.
const int NumPtcls
number of particles which belong to this Dirac determinant
QMCTraits::QTFull::ValueType mValueType
PsiValue ratio(ParticleSet &P, int iat) override
return the ratio only for the iat-th partcle move
T1 * lendReference(size_type n)
Definition: PooledMemory.h:154
void put(std::complex< T1 > &x)
Definition: PooledMemory.h:165
std::unique_ptr< DiracDeterminantBase > makeCopy(std::unique_ptr< SPOSet > &&spo) const override
cloning function
GradType evalGradSource(ParticleSet &P, ParticleSet &source, int iat) override
return the logarithmic gradient for the iat-th particle of the source particleset ...
void evaluateHessian(ParticleSet &P, HessVector &grad_grad_psi) override
int getGroupID(int iat) const
return the group id of a given particle in the particle set.
Definition: ParticleSet.h:520
void add(std::complex< T1 > &x)
Definition: PooledMemory.h:113
void get(std::complex< T1 > &x)
Definition: PooledMemory.h:132