QMCPACK
MultiSlaterDetTableMethod.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: Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
10 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 //
12 // File created by: Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
20 
21 namespace qmcplusplus
22 {
24 {
25  MultiSlaterDetTableMethodMultiWalkerResource() : Resource("MultiSlaterDetTableMethod") {}
28  {}
29 
30  std::unique_ptr<Resource> makeClone() const override
31  {
32  return std::make_unique<MultiSlaterDetTableMethodMultiWalkerResource>(*this);
33  }
34 
35  /// grads of each unique determinants for multiple walkers
37  /// a collection of device pointers of multiple walkers fused for fast H2D transfer.
40 };
41 
43  std::vector<std::unique_ptr<MultiDiracDeterminant>>&& dets,
44  bool use_pre_computing)
45  : OptimizableObject("CI"),
46  RatioTimer(createGlobalTimer(getClassName() + "::ratio")),
47  offload_timer(createGlobalTimer(getClassName() + "::offload")),
48  EvalGradTimer(createGlobalTimer(getClassName() + "::evalGrad")),
49  RatioGradTimer(createGlobalTimer(getClassName() + "::ratioGrad")),
50  PrepareGroupTimer(createGlobalTimer(getClassName() + "::prepareGroup")),
51  UpdateTimer(createGlobalTimer(getClassName() + "::updateBuffer")),
52  AccRejTimer(createGlobalTimer(getClassName() + "::Accept_Reject")),
53  EvaluateTimer(createGlobalTimer(getClassName() + "::evaluate")),
54  CI_Optimizable(false),
55  use_pre_computing_(use_pre_computing)
56 {
57  Dets = std::move(dets);
58  C_otherDs.resize(Dets.size());
59  int NP = targetPtcl.getTotalNum();
60  myG.resize(NP);
61  myL.resize(NP);
62  myG_temp.resize(NP);
63  myL_temp.resize(NP);
64 
65  Last.resize(targetPtcl.groups());
66  for (int i = 0; i < Last.size(); ++i)
67  Last[i] = targetPtcl.last(i) - 1;
68 }
69 
70 void MultiSlaterDetTableMethod::initialize(std::unique_ptr<std::vector<std::vector<size_t>>> C2node_in,
71  std::unique_ptr<std::vector<ValueType>> C_in,
72  std::unique_ptr<opt_variables_type> myVars_in,
73  std::unique_ptr<CSFData> csf_data_in,
74  bool optimizable,
75  bool CI_optimizable)
76 {
77  C2node = std::move(C2node_in);
78  C = std::move(C_in);
79  myVars = std::move(myVars_in);
80  csf_data_ = std::move(csf_data_in);
81  CI_Optimizable = CI_optimizable;
82 }
83 
85 
86 std::unique_ptr<WaveFunctionComponent> MultiSlaterDetTableMethod::makeClone(ParticleSet& tqp) const
87 {
88  std::vector<std::unique_ptr<MultiDiracDeterminant>> dets_clone;
89  for (auto& det : Dets)
90  dets_clone.emplace_back(std::make_unique<MultiDiracDeterminant>(*det));
91 
92  auto clone = std::make_unique<MultiSlaterDetTableMethod>(tqp, std::move(dets_clone), use_pre_computing_);
93 
94  clone->CI_Optimizable = CI_Optimizable;
95  clone->C2node = C2node;
96  clone->C = C;
97  clone->myVars = myVars;
98 
99  clone->csf_data_ = csf_data_;
100 
101  return clone;
102 }
103 
104 /** Compute VGL of this MultiSlaterDetTableMethod
105  *
106  * THis is introduced to remove redundant code in
107  * - evaluate(P,G,L)
108  * - evaluateLog(P,G,L,buf,fillbuffer)
109  * Miguel's note: can this change over time??? I don't know yet
110  */
114 {
115  const ValueType czero(0);
117  g_tmp = czero;
118  l_tmp = czero;
119 
120  for (size_t ig = 0; ig < Dets.size(); ig++)
121  precomputeC_otherDs(P, ig);
122 
123  for (size_t i = 0; i < Dets[0]->getNumDets(); ++i)
124  psi_ratio_to_ref_det_ += C_otherDs[0][i] * Dets[0]->getRatiosToRefDet()[i];
125 
126  for (size_t id = 0; id < Dets.size(); id++)
127  for (size_t i = 0; i < Dets[id]->getNumDets(); ++i)
128  for (int k = 0, n = Dets[id]->getFirstIndex(); k < Dets[id]->getNumPtcls(); k++, n++)
129  {
130  g_tmp[n] += C_otherDs[id][i] * Dets[id]->getGrads()(i, k);
131  l_tmp[n] += C_otherDs[id][i] * Dets[id]->getLapls()(i, k);
132  }
133 
134  ValueType psiinv = static_cast<ValueType>(PsiValue(1.0) / psi_ratio_to_ref_det_);
135  g_tmp *= psiinv;
136  l_tmp *= psiinv;
138  for (size_t id = 0; id < Dets.size(); id++)
139  log_psi += Dets[id]->getLogValueRefDet();
140  return log_psi;
141 }
142 
146 {
147  ScopedTimer local_timer(EvaluateTimer);
148  for (size_t id = 0; id < Dets.size(); id++)
149  {
150  if (P.isSpinor())
151  Dets[id]->evaluateForWalkerMoveWithSpin(P);
152  else
153  Dets[id]->evaluateForWalkerMove(P);
154  }
156 
157  G += myG;
158  for (size_t i = 0; i < L.size(); i++)
159  L[i] += myL[i] - dot(myG[i], myG[i]);
160 
161  return log_value_;
162 }
163 /*
164 void MultiSlaterDetTableMethod::mw_evaluateLog(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
165  const RefVectorWithLeader<ParticleSet>& p_list,
166  const RefVector<ParticleSet::ParticleGradient>& G_list,
167  const RefVector<ParticleSet::ParticleLaplacian>& L_list)
168 {
169  APP_ABORT("Iam In MW_LOG");
170 }
171 */
172 
173 
175  int iat,
176  bool newpos,
177  GradType& g_at)
178 {
179  const int det_id = getDetID(iat);
180 
181  if (newpos)
182  Dets[det_id]->evaluateDetsAndGradsForPtclMove(P, iat);
183  else
184  Dets[det_id]->evaluateGrads(P, iat);
185 
186  const auto& grads = (newpos) ? Dets[det_id]->getNewGrads() : Dets[det_id]->getGrads();
187  const OffloadVector<ValueType>& detValues0 =
188  (newpos) ? Dets[det_id]->getNewRatiosToRefDet() : Dets[det_id]->getRatiosToRefDet();
189  const size_t noffset = Dets[det_id]->getFirstIndex();
190 
191  PsiValue psi(0);
192  // enforce full precision reduction due to numerical sensitivity
193  QTFull::GradType g_sum;
194  for (size_t i = 0; i < Dets[det_id]->getNumDets(); i++)
195  {
196  psi += detValues0[i] * C_otherDs[det_id][i];
197  g_sum += C_otherDs[det_id][i] * grads(i, iat - noffset);
198  }
199 
200  g_at = g_sum / psi;
201  return psi;
202 }
203 
205  int iat,
206  bool newpos,
207  GradType& g_at,
208  ComplexType& sg_at)
209 {
210  const int det_id = getDetID(iat);
211 
212  if (newpos)
213  Dets[det_id]->evaluateDetsAndGradsForPtclMoveWithSpin(P, iat);
214  else
215  Dets[det_id]->evaluateGradsWithSpin(P, iat);
216 
217  const auto& grads = (newpos) ? Dets[det_id]->getNewGrads() : Dets[det_id]->getGrads();
218  const OffloadVector<ValueType>& detValues0 =
219  (newpos) ? Dets[det_id]->getNewRatiosToRefDet() : Dets[det_id]->getRatiosToRefDet();
220  const Matrix<ValueType>& spingrads = (newpos) ? Dets[det_id]->getNewSpinGrads() : Dets[det_id]->getSpinGrads();
221  const size_t noffset = Dets[det_id]->getFirstIndex();
222 
223  PsiValue psi(0);
224  for (size_t i = 0; i < Dets[det_id]->getNumDets(); i++)
225  {
226  psi += detValues0[i] * C_otherDs[det_id][i];
227  g_at += C_otherDs[det_id][i] * grads(i, iat - noffset);
228  sg_at += C_otherDs[det_id][i] * spingrads(i, iat - noffset);
229  }
230  g_at *= PsiValue(1.0) / psi;
231  sg_at *= PsiValue(1.0) / psi;
232  return psi;
233 }
234 
236  const RefVectorWithLeader<ParticleSet>& P_list,
237  int iat,
238  bool newpos,
239  std::vector<GradType>& grad_now,
240  std::vector<PsiValue>& psi_list)
241 {
242  auto& det_leader = WFC_list.getCastedLeader<MultiSlaterDetTableMethod>();
243  const int det_id = det_leader.getDetID(iat);
244  const int nw = WFC_list.size();
245  const int ndets = det_leader.Dets[det_id]->getNumDets();
246 
247  RefVectorWithLeader<MultiDiracDeterminant> det_list(*det_leader.Dets[det_id]);
248  det_list.reserve(WFC_list.size());
249  for (int iw = 0; iw < WFC_list.size(); iw++)
250  {
251  auto& det = WFC_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
252  det_list.push_back(*det.Dets[det_id]);
253  }
254 
255  auto& mw_res = det_leader.mw_res_handle_.getResource();
256  auto& mw_grads = mw_res.mw_grads;
257  mw_grads.resize(3 * nw, ndets);
258  if (newpos)
259  det_leader.Dets[det_id]->mw_evaluateDetsAndGradsForPtclMove(det_list, P_list, iat, mw_grads);
260  else
261  det_leader.Dets[det_id]->mw_evaluateGrads(det_list, P_list, iat, mw_grads);
262 
263  auto& det_value_ptr_list = mw_res.det_value_ptr_list;
264  det_value_ptr_list.resize(nw);
265  for (size_t iw = 0; iw < nw; iw++)
266  {
267  auto& det = WFC_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
268  det_value_ptr_list[iw] = (newpos) ? det.Dets[det_id]->getNewRatiosToRefDet().device_data()
269  : det.Dets[det_id]->getRatiosToRefDet().device_data();
270  }
271 
272  std::vector<ValueType> grad_now_list(nw * 3, 0);
273  auto* grad_now_list_ptr = grad_now_list.data();
274  auto* mw_grads_ptr = mw_grads.data();
275  auto* psi_list_ptr = psi_list.data();
276  auto* C_otherDs_ptr_list_ptr = mw_res.C_otherDs_ptr_list.data();
277  auto* det_value_ptr_list_ptr = det_value_ptr_list.data();
278  {
279  ScopedTimer local_timer(det_leader.offload_timer);
280  PRAGMA_OFFLOAD("omp target teams distribute map(from: psi_list_ptr[:nw]) \
281  map(from: grad_now_list_ptr[:3 * nw]) \
282  map(always, to: det_value_ptr_list_ptr[:nw]) \
283  map(to: mw_grads_ptr[:mw_grads.size()])")
284  for (uint32_t iw = 0; iw < nw; iw++)
285  {
286  // enforce full precision reduction due to numerical sensitivity
287  PsiValue psi_local(0);
288  PsiValue grad_local_x(0);
289  PsiValue grad_local_y(0);
290  PsiValue grad_local_z(0);
291  PRAGMA_OFFLOAD("omp parallel for reduction(+:psi_local, grad_local_x, grad_local_y, grad_local_z)")
292  for (uint32_t i = 0; i < ndets; i++)
293  {
294  psi_local += det_value_ptr_list_ptr[iw][i] * C_otherDs_ptr_list_ptr[iw][i];
295  grad_local_x += C_otherDs_ptr_list_ptr[iw][i] * mw_grads_ptr[(3 * iw + 0) * ndets + i];
296  grad_local_y += C_otherDs_ptr_list_ptr[iw][i] * mw_grads_ptr[(3 * iw + 1) * ndets + i];
297  grad_local_z += C_otherDs_ptr_list_ptr[iw][i] * mw_grads_ptr[(3 * iw + 2) * ndets + i];
298  }
299  psi_list_ptr[iw] = psi_local;
300  grad_now_list_ptr[iw * 3 + 0] = grad_local_x;
301  grad_now_list_ptr[iw * 3 + 1] = grad_local_y;
302  grad_now_list_ptr[iw * 3 + 2] = grad_local_z;
303  }
304  }
305 
306  for (size_t iw = 0; iw < nw; iw++)
307  {
308  auto psi_inv = static_cast<ValueType>(PsiValue(1.0) / psi_list[iw]);
309  grad_now[iw][0] = grad_now_list[iw * 3 + 0] * psi_inv;
310  grad_now[iw][1] = grad_now_list[iw * 3 + 1] * psi_inv;
311  grad_now[iw][2] = grad_now_list[iw * 3 + 2] * psi_inv;
312  }
313 }
314 
316  int iat,
317  bool newpos,
318  GradType& g_at)
319 {
320  const int det_id = getDetID(iat);
321 
322  if (newpos)
323  Dets[det_id]->evaluateDetsAndGradsForPtclMove(P, iat);
324  else
325  Dets[det_id]->evaluateGrads(P, iat);
326 
327  const auto& grads = (newpos) ? Dets[det_id]->getNewGrads() : Dets[det_id]->getGrads();
328  const auto& detValues0 = (newpos) ? Dets[det_id]->getNewRatiosToRefDet() : Dets[det_id]->getRatiosToRefDet();
329  const size_t* restrict det0 = (*C2node)[det_id].data();
330  const ValueType* restrict cptr = C->data();
331  const size_t nc = C->size();
332  const size_t noffset = Dets[det_id]->getFirstIndex();
333  PsiValue psi(0);
334  for (size_t i = 0; i < nc; ++i)
335  {
336  const size_t d0 = det0[i];
337  ValueType t = cptr[i];
338  for (size_t id = 0; id < Dets.size(); id++)
339  if (id != det_id)
340  t *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][i]];
341  psi += t * detValues0[d0];
342  g_at += t * grads(d0, iat - noffset);
343  }
344  g_at *= PsiValue(1.0) / psi;
345  return psi;
346 }
347 
349  int iat,
350  bool newpos,
351  GradType& g_at,
352  ComplexType& sg_at)
353 {
354  const int det_id = getDetID(iat);
355 
356  if (newpos)
357  Dets[det_id]->evaluateDetsAndGradsForPtclMoveWithSpin(P, iat);
358  else
359  Dets[det_id]->evaluateGradsWithSpin(P, iat);
360 
361  const auto& grads = (newpos) ? Dets[det_id]->getNewGrads() : Dets[det_id]->getGrads();
362  const auto& detValues0 = (newpos) ? Dets[det_id]->getNewRatiosToRefDet() : Dets[det_id]->getRatiosToRefDet();
363  const auto& spingrads = (newpos) ? Dets[det_id]->getNewSpinGrads() : Dets[det_id]->getSpinGrads();
364  const size_t* restrict det0 = (*C2node)[det_id].data();
365  const ValueType* restrict cptr = C->data();
366  const size_t nc = C->size();
367  const size_t noffset = Dets[det_id]->getFirstIndex();
368  PsiValue psi(0);
369  for (size_t i = 0; i < nc; ++i)
370  {
371  const size_t d0 = det0[i];
372  ValueType t = cptr[i];
373  for (size_t id = 0; id < Dets.size(); id++)
374  if (id != det_id)
375  t *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][i]];
376  psi += t * detValues0[d0];
377  g_at += t * grads(d0, iat - noffset);
378  sg_at += t * spingrads(d0, iat - noffset);
379  }
380  g_at *= PsiValue(1.0) / psi;
381  sg_at *= PsiValue(1.0) / psi;
382  return psi;
383 }
384 
386 {
387  ScopedTimer local_timer(EvalGradTimer);
388 
389  GradType grad_iat;
390  if (use_pre_computing_)
391  evalGrad_impl(P, iat, false, grad_iat);
392  else
393  evalGrad_impl_no_precompute(P, iat, false, grad_iat);
394 
395  return grad_iat;
396 }
397 
399  int iat,
400  ComplexType& spingrad)
401 {
402  ScopedTimer local_timer(EvalGradTimer);
403 
404  GradType grad_iat;
405  ComplexType spingrad_iat;
406  if (use_pre_computing_)
407  evalGradWithSpin_impl(P, iat, false, grad_iat, spingrad_iat);
408  else
409  evalGradWithSpin_impl_no_precompute(P, iat, false, grad_iat, spingrad_iat);
410 
411  spingrad += spingrad_iat;
412 
413  return grad_iat;
414 }
415 
417  const RefVectorWithLeader<ParticleSet>& P_list,
418  int iat,
419  std::vector<GradType>& grad_now) const
420 {
421  if (!use_pre_computing_)
422  {
423  WaveFunctionComponent::mw_evalGrad(WFC_list, P_list, iat, grad_now);
424  return;
425  }
426 
427  auto& det_leader = WFC_list.getCastedLeader<MultiSlaterDetTableMethod>();
428  ScopedTimer local_timer(det_leader.EvalGradTimer);
429 
430  const int nw = WFC_list.size();
431 
432  std::vector<PsiValue> psi_list(nw, 0);
433  mw_evalGrad_impl(WFC_list, P_list, iat, false, grad_now, psi_list);
434 }
435 
436 
438 {
439  ScopedTimer local_timer(RatioGradTimer);
441 
442  GradType dummy;
443  if (use_pre_computing_)
444  new_psi_ratio_to_new_ref_det_ = evalGrad_impl(P, iat, true, dummy);
445  else
447 
448  const int det_id = getDetID(iat);
449  curRatio = Dets[det_id]->getRefDetRatio();
450  if (curRatio != PsiValue(0))
452  grad_iat += dummy;
453  return curRatio;
454 }
455 
457  int iat,
458  GradType& grad_iat,
459  ComplexType& spingrad_iat)
460 {
461  ScopedTimer local_timer(RatioGradTimer);
463 
464  GradType dummy;
465  ComplexType spindummy;
466  if (use_pre_computing_)
467  new_psi_ratio_to_new_ref_det_ = evalGradWithSpin_impl(P, iat, true, dummy, spindummy);
468  else
469  new_psi_ratio_to_new_ref_det_ = evalGradWithSpin_impl_no_precompute(P, iat, true, dummy, spindummy);
470 
471  const int det_id = getDetID(iat);
472  curRatio = Dets[det_id]->getRefDetRatio();
473  if (curRatio != PsiValue(0))
475  grad_iat += dummy;
476  spingrad_iat += spindummy;
477  return curRatio;
478 }
479 
481  const RefVectorWithLeader<ParticleSet>& P_list,
482  int iat,
483  std::vector<WaveFunctionComponent::PsiValue>& ratios,
484  std::vector<GradType>& grad_new) const
485 {
486  if (!use_pre_computing_)
487  {
488  WaveFunctionComponent::mw_ratioGrad(WFC_list, P_list, iat, ratios, grad_new);
489  return;
490  }
491 
492  auto& det_leader = WFC_list.getCastedLeader<MultiSlaterDetTableMethod>();
493  const int nw = WFC_list.size();
494 
495  ScopedTimer local_timer(det_leader.RatioGradTimer);
496  std::vector<PsiValue> psi_list(nw, 0);
497  std::vector<GradType> dummy;
498  dummy.resize(nw);
499 
500  mw_evalGrad_impl(WFC_list, P_list, iat, true, dummy, psi_list);
501 
502  const int det_id = getDetID(iat);
503  for (size_t iw = 0; iw < nw; iw++)
504  {
505  auto& det = WFC_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
506  det.new_psi_ratio_to_new_ref_det_ = psi_list[iw];
507  grad_new[iw] += dummy[iw];
508  det.curRatio = det.Dets[det_id]->getRefDetRatio();
509  if (det.curRatio != PsiValue(0))
510  det.curRatio *= psi_list[iw] / det.psi_ratio_to_ref_det_;
511  ratios[iw] = det.curRatio;
512  }
513 }
514 
516 {
517  const auto& detValues0 = Dets[det_id]->getNewRatiosToRefDet();
518 
519  PsiValue psi = 0;
520  if (use_pre_computing_)
521  {
522  // This function computes
523  // psi=Det_Coeff[i]*Det_Value[unique_det_up]*Det_Value[unique_det_dn]*Det_Value[unique_det_AnyOtherType]
524  // Since only one electron group is moved at the time, identified by det_id, We precompute:
525  // C_otherDs[det_id][i]=Det_Coeff[i]*Det_Value[unique_det_dn]*Det_Value[unique_det_AnyOtherType]
526  for (size_t i = 0; i < Dets[det_id]->getNumDets(); i++)
527  psi += detValues0[i] * C_otherDs[det_id][i];
528  }
529  else
530  {
531  const size_t* restrict det0 = (*C2node)[det_id].data();
532  const ValueType* restrict cptr = C->data();
533  const size_t nc = C->size();
534 
535  for (size_t i = 0; i < nc; ++i)
536  {
537  ValueType t = cptr[i];
538  for (size_t id = 0; id < Dets.size(); id++)
539  if (id != det_id)
540  t *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][i]];
541  t *= detValues0[det0[i]];
542  psi += t;
543  }
544  }
545  return psi;
546 }
547 
548 // use ci_node for this routine only
550 {
551  ScopedTimer local_timer(RatioTimer);
553 
554  const int det_id = getDetID(iat);
555  Dets[det_id]->evaluateDetsForPtclMove(P, iat);
556 
558  curRatio = Dets[det_id]->getRefDetRatio();
559  if (curRatio != PsiValue(0))
561  return curRatio;
562 }
563 
565  const RefVectorWithLeader<ParticleSet>& P_list,
566  int iat,
567  std::vector<PsiValue>& ratios) const
568 {
569  if (!use_pre_computing_)
570  {
571  WaveFunctionComponent::mw_calcRatio(WFC_list, P_list, iat, ratios);
572  return;
573  }
574 
575 
576  auto& det_leader = WFC_list.getCastedLeader<MultiSlaterDetTableMethod>();
577  ScopedTimer local_timer(det_leader.RatioTimer);
578 
579  const int det_id = getDetID(iat);
580  const int nw = WFC_list.size();
581  const int ndets = det_leader.Dets[det_id]->getNumDets();
582 
583  RefVectorWithLeader<MultiDiracDeterminant> det_list(*det_leader.Dets[det_id]);
584  det_list.reserve(WFC_list.size());
585  for (int iw = 0; iw < WFC_list.size(); iw++)
586  {
587  auto& det = WFC_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
588  det_list.push_back(*det.Dets[det_id]);
589  }
590 
591  det_leader.Dets[det_id]->mw_evaluateDetsForPtclMove(det_list, P_list, iat);
592 
593  auto& mw_res = det_leader.mw_res_handle_.getResource();
594  auto& det_value_ptr_list = mw_res.det_value_ptr_list;
595  det_value_ptr_list.resize(nw);
596  for (size_t iw = 0; iw < nw; iw++)
597  {
598  auto& det = WFC_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
599  det.UpdateMode = ORB_PBYP_RATIO;
600 
601  det_value_ptr_list[iw] = det.Dets[det_id]->getNewRatiosToRefDet().device_data();
602  }
603 
604  std::vector<PsiValue> psi_list(nw, 0);
605  auto* psi_list_ptr = psi_list.data();
606  auto* C_otherDs_ptr_list_ptr = mw_res.C_otherDs_ptr_list.data();
607  auto* det_value_ptr_list_ptr = det_value_ptr_list.data();
608  {
609  ScopedTimer local_timer(det_leader.offload_timer);
610  PRAGMA_OFFLOAD("omp target teams distribute map(always,from: psi_list_ptr[:nw]) \
611  map(always, to: det_value_ptr_list_ptr[:nw])")
612  for (uint32_t iw = 0; iw < nw; iw++)
613  {
614  PsiValue psi_local(0);
615  PRAGMA_OFFLOAD("omp parallel for reduction(+ : psi_local)")
616  for (uint32_t i = 0; i < ndets; i++)
617  psi_local += det_value_ptr_list_ptr[iw][i] * C_otherDs_ptr_list_ptr[iw][i];
618  psi_list_ptr[iw] = psi_local;
619  }
620  }
621 
622  for (size_t iw = 0; iw < nw; iw++)
623  {
624  auto& det = WFC_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
625  det.new_psi_ratio_to_new_ref_det_ = psi_list[iw];
626  det.curRatio = det.Dets[det_id]->getRefDetRatio();
627  if (det.curRatio != PsiValue(0))
628  det.curRatio *= psi_list[iw] / det.psi_ratio_to_ref_det_;
629  ratios[iw] = det.curRatio;
630  }
631 }
632 
633 void MultiSlaterDetTableMethod::evaluateRatios(const VirtualParticleSet& VP, std::vector<ValueType>& ratios)
634 {
635  ScopedTimer local_timer(RatioTimer);
636 
637  const int det_id = getDetID(VP.refPtcl);
638 
639  for (size_t iat = 0; iat < VP.getTotalNum(); ++iat)
640  {
641  Dets[det_id]->evaluateDetsForPtclMove(VP, iat, VP.refPtcl);
642  const OffloadVector<ValueType>& detValues0 = Dets[det_id]->getNewRatiosToRefDet();
643 
645  ratios[iat] = Dets[det_id]->getRefDetRatio();
646  if (ratios[iat] != ValueType(0))
647  ratios[iat] *= psiNew / psi_ratio_to_ref_det_;
648  }
649 }
650 
651 void MultiSlaterDetTableMethod::acceptMove(ParticleSet& P, int iat, bool safe_to_delay)
652 {
653  // this should depend on the type of update, ratio / ratioGrad
654  // for now is incorrect fot ratio(P,iat,dG,dL) updates
655  ScopedTimer local_timer(AccRejTimer);
656  // update psi_ratio_to_ref_det_,myG_temp,myL_temp
659  curRatio = 1.0;
660 
661  Dets[getDetID(iat)]->acceptMove(P, iat, safe_to_delay);
662 }
663 
665 {
666  ScopedTimer local_timer(AccRejTimer);
667  Dets[getDetID(iat)]->restore(iat);
668  curRatio = 1.0;
669 }
670 
672  const RefVectorWithLeader<ParticleSet>& p_list,
673  int iat,
674  const std::vector<bool>& isAccepted,
675  bool safe_to_delay) const
676 {
677  ScopedTimer local_timer(AccRejTimer);
678  for (size_t iw = 0; iw < isAccepted.size(); iw++)
679  {
680  auto& det = wfc_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
681  if (isAccepted[iw])
682  {
683  det.psi_ratio_to_ref_det_ = det.new_psi_ratio_to_new_ref_det_;
684  det.log_value_ += convertValueToLog(det.curRatio);
685  }
686  det.curRatio = 1.0;
687  }
688  const auto det_id = getDetID(iat);
689  const auto det_list(extract_DetRef_list(wfc_list, det_id));
690  Dets[det_id]->mw_accept_rejectMove(det_list, p_list, iat, isAccepted);
691 }
692 
694 {
695  for (size_t id = 0; id < Dets.size(); id++)
696  Dets[id]->registerData(P, buf);
697 
698  buf.add(log_value_);
700 }
701 
703  WFBufferType& buf,
704  bool fromscratch)
705 {
706  ScopedTimer local_timer(UpdateTimer);
707 
708  for (size_t id = 0; id < Dets.size(); id++)
709  Dets[id]->updateBuffer(P, buf, fromscratch);
710 
712 
713  P.G += myG;
714  for (int i = 0; i < P.L.size(); i++)
715  P.L[i] += myL[i] - dot(myG[i], myG[i]);
716 
717  buf.put(log_value_);
719 
720  return log_value_;
721 }
722 
724 {
725  for (size_t id = 0; id < Dets.size(); id++)
726  Dets[id]->copyFromBuffer(P, buf);
727 
728  buf.get(log_value_);
730 }
731 
733 {
734  opt_obj_refs.push_back(*this);
735  for (int i = 0; i < Dets.size(); i++)
736  Dets[i]->extractOptimizableObjectRefs(opt_obj_refs);
737 }
738 
740 {
741  if (CI_Optimizable && myVars->size())
742  {
743  myVars->setIndexDefault();
744  active.insertFrom(*myVars);
745  }
746 }
747 
749 {
750  if (CI_Optimizable)
751  myVars->getIndex(active);
752 
753  for (size_t id = 0; id < Dets.size(); id++)
754  if (Dets[id]->isOptimizable())
755  Dets[id]->checkOutVariables(active);
756 }
757 
759 {
760  if (CI_Optimizable)
761  {
762  if (csf_data_)
763  {
764  ValueType* restrict CSFcoeff_p = csf_data_->coeffs.data();
765  for (int i = 0; i < csf_data_->coeffs.size() - 1; i++)
766  {
767  int loc = myVars->where(i);
768  if (loc >= 0)
769  {
770  CSFcoeff_p[i + 1] = (*myVars)[i] = active[loc];
771  }
772  }
773  int cnt = 0;
774  ValueType* restrict C_p = C->data();
775  const RealType* restrict CSFexpansion_p = csf_data_->expansion.data();
776  for (int i = 0; i < csf_data_->dets_per_csf.size(); i++)
777  {
778  for (int k = 0; k < csf_data_->dets_per_csf[i]; k++)
779  {
780  C_p[cnt] = CSFcoeff_p[i] * CSFexpansion_p[cnt];
781  cnt++;
782  }
783  }
784  //for(int i=0; i<Dets.size(); i++) Dets[i]->resetParameters(active);
785  }
786  else
787  {
788  ValueType* restrict C_p = C->data();
789  for (int i = 0; i < C->size() - 1; i++)
790  {
791  int loc = myVars->where(i);
792  if (loc >= 0)
793  {
794  C_p[i + 1] = (*myVars)[i] = active[loc];
795  }
796  }
797  //for(int i=0; i<Dets.size(); i++) Dets[i]->resetParameters(active);
798  }
799  }
800 }
801 
803  const opt_variables_type& optvars,
804  Vector<ValueType>& dlogpsi,
805  Vector<ValueType>& dhpsioverpsi)
806 {
807  evaluateDerivativesWF(P, optvars, dlogpsi);
808  if (CI_Optimizable)
809  {
810  bool recalculate(false);
811  for (int k = 0; k < myVars->size(); ++k)
812  {
813  int kk = myVars->where(k);
814  if (kk < 0)
815  continue;
816  if (optvars.recompute(kk))
817  recalculate = true;
818  }
819  // need to modify for CSF later on, right now assume Slater Det basis
820  if (recalculate)
821  {
822  ValueType psiinv = static_cast<ValueType>(PsiValue(1.0) / psi_ratio_to_ref_det_);
823  laplSum.resize(Dets.size());
824  for (size_t id = 0; id < Dets.size(); id++)
825  {
826  laplSum[id].resize(Dets[id]->getNumDets());
827  // assume that evaluateLog has been called in opt routine before
828  // Dets[id]->evaluateForWalkerMove(P);
829  // myG,myL should already be calculated
830  for (size_t i = 0; i < laplSum[id].size(); i++)
831  {
832  laplSum[id][i] = 0.0;
833  for (size_t k = 0; k < Dets[id]->getNumPtcls(); k++)
834  laplSum[id][i] += Dets[id]->getLapls()[i][k];
835  }
836  }
837 
838  ValueType lapl_sum = 0.0;
839  myG_temp = 0.0;
840  for (size_t id = 0; id < Dets.size(); id++)
841  for (size_t i = 0; i < Dets[id]->getNumDets(); i++)
842  {
843  // assume C_otherDs prepared by evaluateLog already
844  ValueType tmp = C_otherDs[id][i] * psiinv;
845  lapl_sum += tmp * laplSum[id][i];
846  for (size_t k = 0, j = Dets[id]->getFirstIndex(); k < Dets[id]->getNumPtcls(); k++, j++)
847  myG_temp[j] += tmp * Dets[id]->getGrads()(i, k);
848  }
849 
850  ValueType gg = 0.0;
851  for (size_t i = 0; i < P.getTotalNum(); i++)
852  gg += dot(myG_temp[i], myG_temp[i]) - dot(P.G[i], myG_temp[i]);
853 
854  if (csf_data_)
855  {
856  const int num = csf_data_->coeffs.size() - 1;
857  int cnt = 0;
858  // this one is not optable
859  cnt += csf_data_->dets_per_csf[0];
860  int ip(1);
861  for (int i = 0; i < num; i++, ip++)
862  {
863  int kk = myVars->where(i);
864  if (kk < 0)
865  {
866  cnt += csf_data_->dets_per_csf[ip];
867  continue;
868  }
869  ValueType q0 = 0.0;
870  std::vector<ValueType> v(Dets.size());
871  const RealType* restrict CSFexpansion_p = csf_data_->expansion.data();
872  for (int k = 0; k < csf_data_->dets_per_csf[ip]; k++)
873  {
874  for (size_t id = 0; id < Dets.size(); id++)
875  {
876  const auto& grads_spin = Dets[id]->getGrads();
877  size_t spinC = (*C2node)[id][cnt];
878  ValueType tmp = CSFexpansion_p[cnt] * psiinv;
879  for (size_t other_id = 0; other_id < Dets.size(); other_id++)
880  {
881  if (id == other_id)
882  continue;
883  const OffloadVector<ValueType>& detValues_otherspin = Dets[other_id]->getRatiosToRefDet();
884  size_t otherspinC = (*C2node)[other_id][cnt];
885  tmp *= detValues_otherspin[otherspinC];
886  }
887  q0 += tmp * laplSum[id][spinC];
888  for (size_t l = 0, j = Dets[id]->getFirstIndex(); l < Dets[id]->getNumPtcls(); l++, j++)
889  v[id] += tmp *
890  static_cast<ValueType>(dot(P.G[j], grads_spin(spinC, l)) - dot(myG_temp[j], grads_spin(spinC, l)));
891  }
892  cnt++;
893  }
894  ValueType dhpsi = (RealType)-0.5 * (q0 - dlogpsi[kk] * lapl_sum) - dlogpsi[kk] * gg;
895  for (size_t id = 0; id < Dets.size(); id++)
896  dhpsi -= v[id];
897  dhpsioverpsi[kk] = dhpsi;
898  }
899  }
900  else
901  { //usingDETS
902  for (size_t i = 1; i < C->size(); i++)
903  {
904  int kk = myVars->where(i - 1);
905  if (kk < 0)
906  continue;
907 
908  ValueType q0 = 0.0;
909  std::vector<ValueType> v(Dets.size());
910  for (size_t id = 0; id < Dets.size(); id++)
911  {
912  const auto& grads_spin = Dets[id]->getGrads();
913  size_t spinC = (*C2node)[id][i];
914  ValueType tmp = psiinv;
915  for (size_t other_id = 0; other_id < Dets.size(); other_id++)
916  {
917  if (id == other_id)
918  continue;
919  size_t otherspinC = (*C2node)[other_id][i];
920  tmp *= Dets[other_id]->getRatiosToRefDet()[otherspinC];
921  }
922  q0 += tmp * laplSum[id][spinC];
923  for (size_t l = 0, j = Dets[id]->getFirstIndex(); l < Dets[id]->getNumPtcls(); l++, j++)
924  v[id] += tmp *
925  static_cast<ValueType>(dot(P.G[j], grads_spin(spinC, l)) - dot(myG_temp[j], grads_spin(spinC, l)));
926  }
927  ValueType dhpsi = (RealType)-0.5 * (q0 - dlogpsi[kk] * lapl_sum) - dlogpsi[kk] * gg;
928  for (size_t id = 0; id < Dets.size(); id++)
929  dhpsi -= v[id];
930  dhpsioverpsi[kk] = dhpsi;
931  }
932  }
933  }
934  }
935 
936  evaluateMultiDiracDeterminantDerivatives(P, optvars, dlogpsi, dhpsioverpsi);
937 }
938 
940  const opt_variables_type& optvars,
941  Vector<ValueType>& dlogpsi,
942  Vector<ValueType>& dhpsioverpsi)
943 {
944  //Currently, the MultiDiracDeterminant::evaluateDerivatives works with a legacy design, essentially requiring only up and down determinants.
945  //e.g. for spinor cases, we only have one determinant so this interface doesn't work.
946  //Here we throw an error only if the optimization is turned on for MultiDiracDeterminants until the code is updated
947  for (auto const& det : Dets)
948  if (!det->isOptimizable())
949  return;
950 
951  if (Dets.size() != 2)
952  {
953  throw std::runtime_error(
954  "MultiSlaterDetTableMethod::evaluateDerivatives only compatible with two quantum particle types.");
955  }
956  else
957  {
958  Dets[0]->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi, *Dets[1],
959  static_cast<ValueType>(psi_ratio_to_ref_det_), *C, (*C2node)[0], (*C2node)[1]);
960  Dets[1]->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi, *Dets[0],
961  static_cast<ValueType>(psi_ratio_to_ref_det_), *C, (*C2node)[1], (*C2node)[0]);
962  }
963 
964  //note: the future redesign of MultiDiracDeterminant::evaluateDerivatives should look something like this
965  //for (size_t id = 0; id < Dets.size(); id++)
966  // Dets[id]->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi, *Dets, static_cast<ValueType>(psi_ratio_to_ref_det_), *C, *C2node, id);
967 }
968 
970  const opt_variables_type& optvars,
971  Vector<ValueType>& dlogpsi)
972 {
973  if (CI_Optimizable)
974  {
975  bool recalculate(false);
976  for (int k = 0; k < myVars->size(); ++k)
977  {
978  int kk = myVars->where(k);
979  if (kk < 0)
980  continue;
981  if (optvars.recompute(kk))
982  recalculate = true;
983  }
984 
985  if (recalculate)
986  {
987  Vector<ValueType> dlogpsi_local;
988  evaluateDerivativesMSD(dlogpsi_local);
989 
990  const size_t nparams = csf_data_ ? csf_data_->coeffs.size() - 1 : C->size() - 1;
991  assert(dlogpsi_local.size() == nparams);
992  for (int i = 0; i < nparams; i++)
993  {
994  int kk = myVars->where(i);
995  if (kk < 0)
996  continue;
997  dlogpsi[kk] = dlogpsi_local[i];
998  }
999  }
1000  }
1001 
1002  evaluateMultiDiracDeterminantDerivativesWF(P, optvars, dlogpsi);
1003 }
1004 
1006 {
1007  ValueType psiinv = static_cast<ValueType>(PsiValue(1.0) / psi_ratio_to_ref_det_);
1008 
1009  // CI only for now
1010  assert(!csf_data_);
1011  ratios.resize(C->size());
1012  for (size_t i = 0; i < C->size(); i++)
1013  {
1014  ValueType cdet = psiinv;
1015  // assume that evaluateLog has been called in opt routine before
1016  for (size_t id = 0; id < Dets.size(); id++)
1017  cdet *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][i]];
1018  ratios[i] = cdet;
1019  }
1020 }
1021 
1022 const std::vector<WaveFunctionComponent::ValueType>& MultiSlaterDetTableMethod::getLinearExpansionCoefs() const
1023 {
1024  // CI only for now
1025  assert(!csf_data_);
1026  return *C;
1027 }
1028 
1029 
1030 void MultiSlaterDetTableMethod::evaluateDerivativesMSD(Vector<ValueType>& dlogpsi, std::optional<std::pair<unsigned, PsiValue>> move) const
1031 {
1032  // when not using a new position, the result doesn't get affected by det_id, thus choose 0.
1033  const unsigned det_id = move? move->first : 0;
1034  const auto& detValues0 = move? Dets[det_id]->getNewRatiosToRefDet() : Dets[det_id]->getRatiosToRefDet();
1035  const ValueType psiinv = static_cast<ValueType>(PsiValue(1.0) / (move? move->second : psi_ratio_to_ref_det_));
1036 
1037  if (csf_data_) // CSF
1038  {
1039  dlogpsi.resize(csf_data_->coeffs.size() - 1);
1040  // this one is not optimizable
1041  int cnt = csf_data_->dets_per_csf[0];
1042  for (int i = 1; i < csf_data_->coeffs.size(); i++)
1043  {
1044  ValueType cdet = 0.0;
1045  for (int k = 0; k < csf_data_->dets_per_csf[i]; k++)
1046  {
1047  ValueType t = csf_data_->expansion[cnt] * psiinv * detValues0[(*C2node)[det_id][cnt]];
1048  // assume that evaluateLog has been called in opt routine before
1049  for (size_t id = 0; id < Dets.size(); id++)
1050  if (id != det_id)
1051  t *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][cnt]];
1052  cdet += t;
1053  cnt++;
1054  }
1055  dlogpsi[i - 1] = cdet;
1056  }
1057  }
1058  else // CI
1059  {
1060  dlogpsi.resize(C->size() - 1);
1061  for (size_t i = 1; i < C->size(); i++)
1062  {
1063  ValueType cdet = psiinv * detValues0[(*C2node)[det_id][i]];
1064  // assume that evaluateLog has been called in opt routine before
1065  for (size_t id = 0; id < Dets.size(); id++)
1066  if (id != det_id)
1067  cdet *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][i]];
1068  dlogpsi[i - 1] = cdet;
1069  }
1070  }
1071 }
1072 
1074  const opt_variables_type& optvars,
1075  std::vector<ValueType>& ratios,
1076  Matrix<ValueType>& dratios)
1077 {
1078  const unsigned det_id = getDetID(VP.refPtcl);
1079 
1080  bool recalculate(false);
1081  if (CI_Optimizable)
1082  for (int k = 0; k < myVars->size(); ++k)
1083  {
1084  int kk = myVars->where(k);
1085  if (kk < 0)
1086  continue;
1087  if (optvars.recompute(kk))
1088  recalculate = true;
1089  }
1090 
1091  // calculate derivatives based on the reference electron position
1092  Vector<ValueType> dlogpsi_ref, dlogpsi_vp;
1093  if (recalculate)
1094  evaluateDerivativesMSD(dlogpsi_ref);
1095 
1096  for (size_t iat = 0; iat < VP.getTotalNum(); ++iat)
1097  {
1098  Dets[det_id]->evaluateDetsForPtclMove(VP, iat, VP.refPtcl);
1099  const OffloadVector<ValueType>& detValues0 = Dets[det_id]->getNewRatiosToRefDet();
1100 
1101  // calculate VP ratios
1103  ratios[iat] = Dets[det_id]->getRefDetRatio();
1104  if (ratios[iat] != ValueType(0))
1105  ratios[iat] *= psiNew / psi_ratio_to_ref_det_;
1106 
1107  // calculate VP ratios derivatives
1108  if (recalculate)
1109  {
1110  evaluateDerivativesMSD(dlogpsi_vp, std::make_pair(det_id, psiNew));
1111 
1112  const size_t nparams = csf_data_ ? csf_data_->coeffs.size() - 1 : C->size() - 1;
1113  assert(dlogpsi_vp.size() == nparams);
1114 
1115  for (int i = 0; i < nparams; i++)
1116  {
1117  int kk = myVars->where(i);
1118  if (kk < 0)
1119  continue;
1120  dratios[iat][kk] = dlogpsi_vp[i] - dlogpsi_ref[i];
1121  }
1122  }
1123  }
1124 }
1125 
1127  const opt_variables_type& optvars,
1128  Vector<ValueType>& dlogpsi)
1129 {
1130  //Currently, the MultiDiracDeterminant::evaluateDerivativesWF works with a legacy design, essentially requiring only up and down determinants.
1131  //e.g. for spinor cases, we only have one determinant so this interface doesn't work.
1132  //Here we throw an error only if the optimization is turned on for MultiDiracDeterminants until the code is updated
1133  for (auto const& det : Dets)
1134  if (!det->isOptimizable())
1135  return;
1136 
1137  if (Dets.size() != 2)
1138  {
1139  throw std::runtime_error(
1140  "MultiSlaterDetTableMethod::evaluateDerivativesWF only compatible with two quantum particle types.");
1141  }
1142  else
1143  {
1144  // FIXME this needs to be fixed by SPF to separate evaluateDerivatives and evaluateDerivativesWF for orbital rotation matrix
1145  Dets[0]->evaluateDerivativesWF(P, optvars, dlogpsi, *Dets[1], psi_ratio_to_ref_det_, *C, (*C2node)[0],
1146  (*C2node)[1]);
1147  Dets[1]->evaluateDerivativesWF(P, optvars, dlogpsi, *Dets[0], psi_ratio_to_ref_det_, *C, (*C2node)[1],
1148  (*C2node)[0]);
1149  }
1150  //note: the future redesign of MultiDiracDeterminant::evaluateDerivativesWF should look something like this
1151  // for (size_t id = 0; id < Dets.size(); id++)
1152  // Dets[id]->evaluateDerivativesWF(P, optvars, dlogpsi, *Dets, psi_ratio_to_ref_det_, *C, *C2node, id);
1153 }
1154 
1156 {
1157  for (size_t id = 0; id < Dets.size(); id++)
1158  Dets[id]->buildOptVariables((*C2node)[id]);
1159 }
1160 
1162 {
1163  if (!use_pre_computing_)
1164  return;
1165  precomputeC_otherDs(P, ig);
1166 }
1167 
1169  const RefVectorWithLeader<ParticleSet>& p_list,
1170  int ig) const
1171 {
1172  if (!use_pre_computing_)
1173  return;
1174 
1175  auto& det_leader = wfc_list.getCastedLeader<MultiSlaterDetTableMethod>();
1176  const size_t nw = wfc_list.size();
1177  assert(this == &det_leader);
1178 
1179  auto& C_otherDs_ptr_list = det_leader.mw_res_handle_.getResource().C_otherDs_ptr_list;
1180  C_otherDs_ptr_list.resize(nw);
1181  for (int iw = 0; iw < nw; iw++)
1182  {
1183  auto& det = wfc_list.getCastedElement<MultiSlaterDetTableMethod>(iw);
1184  det.prepareGroup(p_list[iw], ig);
1185  C_otherDs_ptr_list[iw] = det.C_otherDs[ig].device_data();
1186  }
1187  C_otherDs_ptr_list.updateTo();
1188 }
1189 
1190 
1192 {
1193  // This function computes
1194  // C_otherDs[det_id][i]=Det_Coeff[i]*Det_Value[unique_det_dn]*Det_Value[unique_det_AnyOtherType]
1195  // Since only one electron group is moved at the time, identified by det_id, We precompute C_otherDs[det_id][i]:
1196  // psi=Det_Coeff[i]*Det_Value[unique_det_up]*Det_Value[unique_det_dn]*Det_Value[unique_det_AnyOtherType]
1197  // becomes:
1198  // psi=Det_Value[unique_det_up]*C_otherDs[det_id][i]
1199  // ig is the id of the group electron being moved. In this function, we compute the other groups
1200  // of electrons.
1201  // We loop over the number of type of determinants (up, diwn, positrons, etc), but we only multiply for ll types BUT ig
1202  // C_otherDs(0, :) stores C x D_dn x D_pos
1203  // C_otherDs(1, :) stores C x D_up x D_pos
1204  // C_otherDs(2, :) stores C x D_up x D_dn
1205 
1206  ScopedTimer local_timer(PrepareGroupTimer);
1207  C_otherDs[ig].resize(Dets[ig]->getNumDets());
1208  std::fill(C_otherDs[ig].begin(), C_otherDs[ig].end(), ValueType(0));
1209  for (size_t i = 0; i < C->size(); i++)
1210  {
1211  // enforce full precision reduction on C_otherDs due to numerical sensitivity
1212  PsiValue product = (*C)[i];
1213  for (size_t id = 0; id < Dets.size(); id++)
1214  if (id != ig)
1215  product *= Dets[id]->getRatiosToRefDet()[(*C2node)[id][i]];
1216  C_otherDs[ig][(*C2node)[ig][i]] += product;
1217  }
1218  //put C_otherDs in device
1219  C_otherDs[ig].updateTo();
1220 }
1221 
1223 {
1224  collection.addResource(std::make_unique<MultiSlaterDetTableMethodMultiWalkerResource>());
1225  for (auto& det : Dets)
1226  det->createResource(collection);
1227 }
1228 
1230  const RefVectorWithLeader<WaveFunctionComponent>& wfc_list) const
1231 {
1232  auto& wfc_leader = wfc_list.getCastedLeader<MultiSlaterDetTableMethod>();
1234  for (int idet = 0; idet < Dets.size(); idet++)
1235  {
1236  const auto det_list(extract_DetRef_list(wfc_list, idet));
1237  Dets[idet]->acquireResource(collection, det_list);
1238  }
1239 }
1240 
1242  const RefVectorWithLeader<WaveFunctionComponent>& wfc_list) const
1243 {
1244  auto& wfc_leader = wfc_list.getCastedLeader<MultiSlaterDetTableMethod>();
1245  collection.takebackResource(wfc_leader.mw_res_handle_);
1246  for (int idet = 0; idet < Dets.size(); idet++)
1247  {
1248  const auto det_list(extract_DetRef_list(wfc_list, idet));
1249  Dets[idet]->releaseResource(collection, det_list);
1250  }
1251 }
1252 } // namespace qmcplusplus
const std::vector< ValueType > & getLinearExpansionCoefs() const
void resize(size_type n, Type_t val=Type_t())
Resize the container.
Definition: OhmmsVector.h:166
std::shared_ptr< CSFData > csf_data_
CSF data set. If nullptr, not using CSF.
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
bool recompute(int i) const
Definition: VariableSet.h:206
size_t addResource(std::unique_ptr< Resource > &&res, bool noprint=false)
void takebackResource(ResourceHandle< RS > &res_handle)
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
void registerData(ParticleSet &P, WFBufferType &buf) override
For particle-by-particle move.
Tensor< T, D >::Type_t det(const Tensor< T, D > &a)
Definition: TensorOps.h:838
bool CI_Optimizable
if true, the CI coefficients are optimized
void evaluateMultiDiracDeterminantDerivatives(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi)
QTBase::RealType RealType
Definition: Configuration.h:58
MultiSlaterDetTableMethod(ParticleSet &targetPtcl, std::vector< std::unique_ptr< MultiDiracDeterminant >> &&dets, bool use_pre_computing)
constructor
void evaluateDerivatives(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi) override
std::shared_ptr< opt_variables_type > myVars
void mw_calcRatio(const RefVectorWithLeader< WaveFunctionComponent > &WFC_list, const RefVectorWithLeader< ParticleSet > &P_list, int iat, std::vector< PsiValue > &ratios) const override
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::shared_ptr< std::vector< ValueType > > C
CI coefficients.
constexpr std::complex< float > czero
Definition: BLAS.hpp:51
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
PsiValue evalGrad_impl_no_precompute(ParticleSet &P, int iat, bool newpos, GradType &g_at)
an implementation shared by evalGrad and ratioGrad.
int refPtcl
Reference particle.
LogValue evaluateLog(const ParticleSet &P, ParticleSet::ParticleGradient &G, ParticleSet::ParticleLaplacian &L) override
evaluate the value of the WaveFunctionComponent from scratch
LatticeGaussianProduct::GradType GradType
void extractOptimizableObjectRefs(UniqueOptObjRefs &opt_obj_refs) override
extract underlying OptimizableObject references
QTBase::ComplexType ComplexType
Definition: Configuration.h:59
void precomputeC_otherDs(const ParticleSet &P, int ig)
precompute C_otherDs for a given particle group
void evaluateDerivativesMSD(Vector< ValueType > &dlogpsi, std::optional< std::pair< unsigned, PsiValue >> move=std::nullopt) const
compute parameter derivatives of CI/CSF coefficients
std::unique_ptr< WaveFunctionComponent > makeClone(ParticleSet &tqp) const override
make clone
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
ParticleLaplacian L
laplacians of the particles
Definition: ParticleSet.h:85
void evaluateMultiDiracDeterminantDerivativesWF(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi)
void resetParametersExclusive(const opt_variables_type &active) override
reset the parameters during optimizations.
void releaseResource(ResourceCollection &collection, const RefVectorWithLeader< WaveFunctionComponent > &wfc_list) const override
return a shared resource to a collection
void mw_evalGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, const int iat, TWFGrads< CT > &grads_now) const
compute the current gradients for the iat-th particle of multiple walkers
RefVectorWithLeader< MultiDiracDeterminant > extract_DetRef_list(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, int det_id) const
std::complex< QTFull::RealType > LogValue
void prepareGroup(ParticleSet &P, int ig) override
Prepare internal data for updating WFC correspond to a particle group It should be called before movi...
void restore(int iat) override
If a move for iat-th particle is rejected, restore to the content.
int groups() const
return the number of groups
Definition: ParticleSet.h:511
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
PsiValue evalGradWithSpin_impl_no_precompute(ParticleSet &P, int iat, bool newpos, GradType &g_at, ComplexType &sg_at)
size_type size() const
return the current size
Definition: OhmmsVector.h:162
PsiValue ratioGradWithSpin(ParticleSet &P, int iat, GradType &grad_iat, ComplexType &spingrad_iat) override
evaluate the ratio of the new to old WaveFunctionComponent value and the new spin gradient Default im...
void calcIndividualDetRatios(Vector< ValueType > &ratios)
Compute ratios of the individual Slater determinants and the total MSD value.
QTBase::ValueType ValueType
Definition: Configuration.h:60
void product(const Matrix< T > &A, const Matrix< T > &B, Matrix< T > &C)
static function to perform C=AB for real matrices
static void mw_evalGrad_impl(const RefVectorWithLeader< WaveFunctionComponent > &WFC_list, const RefVectorWithLeader< ParticleSet > &P_list, int iat, bool newpos, std::vector< GradType > &grad_now, std::vector< PsiValue > &psi_list)
multi walker version of evalGrad_impl
std::vector< OffloadVector< ValueType > > C_otherDs
C_n x D^1_n x D^2_n ... D^3_n with one D removed. Summed by group. [spin, unique det id]...
std::vector< std::unique_ptr< MultiDiracDeterminant > > Dets
determinant collection
void createResource(ResourceCollection &collection) const override
initialize a shared resource and hand it to a collection
ParticleGradient G
gradients of the particles
Definition: ParticleSet.h:83
PsiValue evalGradWithSpin_impl(ParticleSet &P, int iat, bool newpos, GradType &g_at, ComplexType &sg_at)
std::vector< int > Last
the last particle of each group
CASTTYPE & getCastedElement(size_t i) const
NewTimer & createGlobalTimer(const std::string &myname, timer_levels mylevel)
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
std::shared_ptr< std::vector< std::vector< size_t > > > C2node
map determinant in linear combination to unique det list map global det id to unique det id...
MultiSlaterDetTableMethodMultiWalkerResource(const MultiSlaterDetTableMethodMultiWalkerResource &)
void initialize(std::unique_ptr< std::vector< std::vector< size_t >>> C2node_in, std::unique_ptr< std::vector< ValueType >> C_in, std::unique_ptr< opt_variables_type > myVars_in, std::unique_ptr< CSFData > csf_data_in, bool optimizable, bool CI_optimizable)
initialize a few objects and states by the builder YL: it should be part of the constructor.
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
bool isOptimizable() const override
if true, this contains optimizable components
GradType evalGrad(ParticleSet &P, int iat) override
return the current gradient for the iat-th particle
void evaluateDerivRatios(const VirtualParticleSet &VP, const opt_variables_type &optvars, std::vector< ValueType > &ratios, Matrix< ValueType > &dratios) override
const bool use_pre_computing_
use pre-compute (fast) algorithm
LogValue updateBuffer(ParticleSet &P, WFBufferType &buf, bool fromscratch=false) override
For particle-by-particle move.
PsiValue psi_ratio_to_ref_det_
current psi over ref single det
ResourceHandle< MultiSlaterDetTableMethodMultiWalkerResource > mw_res_handle_
void mw_ratioGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, TWFGrads< CT > &grad_new) const
void acquireResource(ResourceCollection &collection, const RefVectorWithLeader< WaveFunctionComponent > &wfc_list) const override
acquire a shared resource from a collection
void evaluateDerivativesWF(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi) override
PsiValue evalGrad_impl(ParticleSet &P, int iat, bool newpos, GradType &g_at)
an implementation shared by evalGrad and ratioGrad.
~MultiSlaterDetTableMethod() override
destructor
Declaraton of ParticleAttrib<T>
Matrix< ValueType, OffloadAllocator< ValueType > > mw_grads
grads of each unique determinants for multiple walkers
GradType evalGradWithSpin(ParticleSet &P, int iat, ComplexType &spingrad) override
return the current spin gradient for the iat-th particle Default implementation assumes that WaveFunc...
void mw_evalGrad(const RefVectorWithLeader< WaveFunctionComponent > &WFC_list, const RefVectorWithLeader< ParticleSet > &P_list, int iat, std::vector< GradType > &grad_now) const override
compute the current gradients for the iat-th particle of multiple walkers
void evaluateRatios(const VirtualParticleSet &VP, std::vector< ValueType > &ratios) override
PsiValue ratioGrad(ParticleSet &P, int iat, GradType &grad_iat) override
evaluate the ratio of the new to old WaveFunctionComponent value and the new gradient ...
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
LatticeGaussianProduct::ValueType ValueType
void checkOutVariables(const opt_variables_type &active) override
check out variational optimizable variables
void insertFrom(const VariableSet &input)
insert a VariableSet to the list
Definition: VariableSet.cpp:37
ResourceHandle< RS > lendResource()
PsiValue ratio(ParticleSet &P, int iat) override
evaluate the ratio of the new to old WaveFunctionComponent value
void mw_prepareGroup(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int ig) const override
virtual void mw_calcRatio(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios) const
compute the ratio of the new to old WaveFunctionComponent value of multiple walkers ...
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
PsiValue computeRatio_NewMultiDet_to_NewRefDet(int det_id) const
void mw_accept_rejectMove(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, const std::vector< bool > &isAccepted, bool safe_to_delay=false) const override
moves of the iat-th particle on some walkers in a batch is accepted.
void push_back(OptimizableObject &obj)
void put(std::complex< T1 > &x)
Definition: PooledMemory.h:165
LogValue evaluate_vgl_impl(const ParticleSet &P, ParticleSet::ParticleGradient &g_tmp, ParticleSet::ParticleLaplacian &l_tmp)
Compute VGL of this MultiSlaterDetTableMethod.
OffloadVector< const ValueType * > C_otherDs_ptr_list
a collection of device pointers of multiple walkers fused for fast H2D transfer.
void copyFromBuffer(ParticleSet &P, WFBufferType &buf) override
For particle-by-particle move.
PsiValue new_psi_ratio_to_new_ref_det_
new psi over new ref single det when one particle is moved
An AntiSymmetric WaveFunctionComponent composed of a linear combination of SlaterDeterminants.
void acceptMove(ParticleSet &P, int iat, bool safe_to_delay=false) override
a move for iat-th particle is accepted.
void checkInVariablesExclusive(opt_variables_type &active) override
check in variational parameters to the global list of parameters used by the optimizer.
void add(std::complex< T1 > &x)
Definition: PooledMemory.h:113
void get(std::complex< T1 > &x)
Definition: PooledMemory.h:132