1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2020 QMCPACK developers.
6 //
7 // File developed by: Bryan Clark, bclark@Princeton.edu, Princeton University
8 //                    Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
9 //                    Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 //                    Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
11 //                    Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
12 //                    Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
13 //                    Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
14 //
15 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
16 //////////////////////////////////////////////////////////////////////////////////////
17 
18 
19 /**@file DiracDeterminant.h
20  * @brief Declaration of DiracDeterminant with a S(ingle)P(article)O(rbital)Set
21  */
22 #ifndef QMCPLUSPLUS_DIRACDETERMINANT_H
23 #define QMCPLUSPLUS_DIRACDETERMINANT_H
24 
25 #include "QMCWaveFunctions/Fermion/DiracDeterminantBase.h"
26 #include "QMCWaveFunctions/Fermion/DelayedUpdate.h"
27 #if defined(ENABLE_CUDA)
28 #include "QMCWaveFunctions/Fermion/DelayedUpdateCUDA.h"
29 #endif
30 
31 namespace qmcplusplus
32 {
33 template<typename DU_TYPE = DelayedUpdate<QMCTraits::ValueType, QMCTraits::QTFull::ValueType>>
34 class DiracDeterminant : public DiracDeterminantBase
35 {
36 protected:
37   int ndelay;
38 
39 public:
40   using ValueVector_t = SPOSet::ValueVector_t;
41   using ValueMatrix_t = SPOSet::ValueMatrix_t;
42   using GradVector_t  = SPOSet::GradVector_t;
43   using GradMatrix_t  = SPOSet::GradMatrix_t;
44   using HessMatrix_t  = SPOSet::HessMatrix_t;
45   using HessVector_t  = SPOSet::HessVector_t;
46   using HessType      = SPOSet::HessType;
47 
48   using mValueType = QMCTraits::QTFull::ValueType;
49   using mGradType  = TinyVector<mValueType, DIM>;
50 
51   /** constructor
52    *@param spos the single-particle orbital set
53    *@param first index of the first particle
54    */
55   DiracDeterminant(std::shared_ptr<SPOSet>&& spos, int first = 0);
56 
57   // copy constructor and assign operator disabled
58   DiracDeterminant(const DiracDeterminant& s) = delete;
59   DiracDeterminant& operator=(const DiracDeterminant& s) = delete;
60 
61   /** set the index of the first particle in the determinant and reset the size of the determinant
62    *@param first index of first particle
63    *@param nel number of particles in the determinant
64    */
65   void set(int first, int nel, int delay = 1) override final;
66 
67   void evaluateDerivatives(ParticleSet& P,
68                            const opt_variables_type& active,
69                            std::vector<ValueType>& dlogpsi,
70                            std::vector<ValueType>& dhpsioverpsi) override;
71 
72   ///reset the size: with the number of particles and number of orbtials
73   void resize(int nel, int morb);
74 
75   void registerData(ParticleSet& P, WFBufferType& buf) override;
76 
77   void updateAfterSweep(const ParticleSet& P, ParticleSet::ParticleGradient_t& G, ParticleSet::ParticleLaplacian_t& L);
78 
79   LogValueType updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch = false) override;
80 
81   void copyFromBuffer(ParticleSet& P, WFBufferType& buf) override;
82 
83   /** return the ratio only for the  iat-th partcle move
84    * @param P current configuration
85    * @param iat the particle thas is being moved
86    */
87   PsiValueType ratio(ParticleSet& P, int iat) override;
88 
89   //Ye: TODO, good performance needs batched SPO evaluation.
90   //void mw_calcRatio(const std::vector<WaveFunctionComponent*>& wfc_list,
91   //                  const std::vector<ParticleSet*>& p_list,
92   //                  int iat,
93   //                  std::vector<PsiValueType>& ratios) override;
94 
95   /** compute multiple ratios for a particle move
96    */
97   void evaluateRatios(const VirtualParticleSet& VP, std::vector<ValueType>& ratios) override;
98 
99   void mw_evaluateRatios(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
100                          const RefVector<const VirtualParticleSet>& vp_list,
101                          std::vector<std::vector<ValueType>>& ratios) const override;
102 
103   PsiValueType ratioGrad(ParticleSet& P, int iat, GradType& grad_iat) override;
104 
105   PsiValueType ratioGradWithSpin(ParticleSet& P, int iat, GradType& grad_iat, ComplexType& spingrad) override final;
106 
107   void mw_ratioGrad(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
108                     const RefVectorWithLeader<ParticleSet>& p_list,
109                     int iat,
110                     std::vector<PsiValueType>& ratios,
111                     std::vector<GradType>& grad_new) const override;
112 
113   GradType evalGrad(ParticleSet& P, int iat) override;
114 
115   GradType evalGradWithSpin(ParticleSet& P, int iat, ComplexType& spingrad) override final;
116 
117   GradType evalGradSource(ParticleSet& P, ParticleSet& source, int iat) override;
118 
119   GradType evalGradSource(ParticleSet& P,
120                           ParticleSet& source,
121                           int iat,
122                           TinyVector<ParticleSet::ParticleGradient_t, OHMMS_DIM>& grad_grad,
123                           TinyVector<ParticleSet::ParticleLaplacian_t, OHMMS_DIM>& lapl_grad) override;
124 
125   /** move was accepted, update the real container
126    */
127   void acceptMove(ParticleSet& P, int iat, bool safe_to_delay = false) override;
128 
129   void mw_accept_rejectMove(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
130                             const RefVectorWithLeader<ParticleSet>& p_list,
131                             int iat,
132                             const std::vector<bool>& isAccepted,
133                             bool safe_to_delay = false) const override
134   {
135     for (int iw = 0; iw < wfc_list.size(); iw++)
136       if (isAccepted[iw])
137         wfc_list[iw].acceptMove(p_list[iw], iat, safe_to_delay);
138       else
139         wfc_list[iw].restore(iat);
140   }
141 
142   void completeUpdates() override;
143 
mw_completeUpdates(const RefVectorWithLeader<WaveFunctionComponent> & wfc_list)144   void mw_completeUpdates(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list) const override
145   {
146     for (int iw = 0; iw < wfc_list.size(); iw++)
147       wfc_list[iw].completeUpdates();
148   }
149 
150   /** move was rejected. copy the real container to the temporary to move on
151    */
152   void restore(int iat) override;
153 
154   ///evaluate log of a determinant for a particle set
155   LogValueType evaluateLog(const ParticleSet& P,
156                            ParticleSet::ParticleGradient_t& G,
157                            ParticleSet::ParticleLaplacian_t& L) override;
158 
159   //Ye: TODO, good performance needs batched SPO evaluation.
160   //void mw_evaluateLog(const std::vector<WaveFunctionComponent*>& wfc_list,
161   //                    const std::vector<ParticleSet*>& p_list,
162   //                    const std::vector<ParticleSet::ParticleGradient_t*>& G_list,
163   //                    const std::vector<ParticleSet::ParticleLaplacian_t*>& L_list) override;
164 
165   void recompute(const ParticleSet& P) override;
166 
167   LogValueType evaluateGL(const ParticleSet& P,
168                           ParticleSet::ParticleGradient_t& G,
169                           ParticleSet::ParticleLaplacian_t& L,
170                           bool fromscratch) override;
171 
172   void evaluateHessian(ParticleSet& P, HessVector_t& grad_grad_psi) override;
173 
174   void createResource(ResourceCollection& collection) const override;
175   void acquireResource(ResourceCollection& collection) override;
176   void releaseResource(ResourceCollection& collection) override;
177 
178   /** cloning function
179    * @param tqp target particleset
180    * @param spo spo set
181    *
182    * This interface is exposed only to SlaterDet and its derived classes
183    * can overwrite to clone itself correctly.
184    */
185   DiracDeterminant* makeCopy(std::shared_ptr<SPOSet>&& spo) const override;
186 
187   void evaluateRatiosAlltoOne(ParticleSet& P, std::vector<ValueType>& ratios) override;
188 
189 #ifndef NDEBUG
190   /// return  for testing
getPsiMinv()191   ValueMatrix_t& getPsiMinv() override { return psiM; }
192 #else
getPsiMinv()193   ValueMatrix_t& getPsiMinv() { return psiM; }
194 #endif
195 
196   /// psiM(j,i) \f$= \psi_j({\bf r}_i)\f$
197   ValueMatrix_t psiM_temp;
198 
199   /// inverse transpose of psiM(j,i) \f$= \psi_j({\bf r}_i)\f$
200   ValueMatrix_t psiM;
201 
202   /// temporary container for testing
203   ValueMatrix_t psiMinv;
204 
205   /// dpsiM(i,j) \f$= \nabla_i \psi_j({\bf r}_i)\f$
206   GradMatrix_t dpsiM;
207 
208   /// d2psiM(i,j) \f$= \nabla_i^2 \psi_j({\bf r}_i)\f$
209   ValueMatrix_t d2psiM;
210 
211   /// Used for force computations
212   GradMatrix_t grad_source_psiM, grad_lapl_source_psiM;
213   HessMatrix_t grad_grad_source_psiM;
214 
215   GradMatrix_t phi_alpha_Minv, grad_phi_Minv;
216   ValueMatrix_t lapl_phi_Minv;
217   HessMatrix_t grad_phi_alpha_Minv;
218 
219   /// value of single-particle orbital for particle-by-particle update
220   ValueVector_t psiV;
221   ValueVector_t dspin_psiV;
222   GradVector_t dpsiV;
223   ValueVector_t d2psiV;
224 
225   /// delayed update engine
226   DU_TYPE updateEng;
227 
228   /// the row of up-to-date inverse matrix
229   ValueVector_t invRow;
230 
231   /** row id correspond to the up-to-date invRow. [0 norb), invRow is ready; -1, invRow is not valid.
232    *  This id is set after calling getInvRow indicating invRow has been prepared for the invRow_id row
233    *  ratioGrad checks if invRow_id is consistent. If not, invRow needs to be recomputed.
234    *  acceptMove and completeUpdates mark invRow invalid by setting invRow_id to -1
235    */
236   int invRow_id;
237 
238   PsiValueType curRatio;
239   ValueType* FirstAddressOfdV;
240   ValueType* LastAddressOfdV;
241 
242 private:
243   /// invert psiM or its copies
244   void invertPsiM(const ValueMatrix_t& logdetT, ValueMatrix_t& invMat);
245 
246   /// Resize all temporary arrays required for force computation.
247   void resizeScratchObjectsForIonDerivs();
248 
249   /// internal function computing ratio and gradients after computing the SPOs, used by ratioGrad.
250   PsiValueType ratioGrad_compute(int iat, GradType& grad_iat);
251 };
252 
253 extern template class DiracDeterminant<>;
254 #if defined(ENABLE_CUDA)
255 extern template class DiracDeterminant<DelayedUpdateCUDA<QMCTraits::ValueType, QMCTraits::QTFull::ValueType>>;
256 #endif
257 
258 } // namespace qmcplusplus
259 #endif
260