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 
16 #ifndef QMCPLUSPLUS_BACKFLOW_EE_KSPACE_H
17 #define QMCPLUSPLUS_BACKFLOW_EE_KSPACE_H
18 #include "QMCWaveFunctions/OrbitalSetTraits.h"
19 #include "QMCWaveFunctions/Fermion/BackflowFunctionBase.h"
20 #include "LongRange/StructFact.h"
21 #include "Message/Communicate.h"
22 #include <cmath>
23 
24 namespace qmcplusplus
25 {
26 class Backflow_ee_kSpace : public BackflowFunctionBase
27 {
28   typedef QMCTraits::ComplexType ComplexType;
29   ///typedef for real values
30   //typedef optimize::VariableSet::real_type real_type;
31   ///typedef for variableset: this is going to be replaced
32   typedef optimize::VariableSet opt_variables_type;
33   ///typedef for name-value lists
34   typedef optimize::VariableSet::variable_map_type variable_map_type;
35 
36 public:
37   //number of groups of the target particleset
38   bool Optimize;
39   int numParams;
40   std::vector<RealType> Fk;
41   std::vector<int> offsetPrms;
42   int NumGroups;
43   int NumKShells; // number of k shells included in bf function
44   int NumKVecs;   // number of k vectors included in bf function
45 
46   Vector<ComplexType> Rhok;
47 
48   Matrix<int> PairID;
49   ///set of variables to be optimized
50   opt_variables_type myVars;
51 
Backflow_ee_kSpace(ParticleSet & ions,ParticleSet & els)52   Backflow_ee_kSpace(ParticleSet& ions, ParticleSet& els) : BackflowFunctionBase(ions, els)
53   {
54     Optimize  = false;
55     numParams = 0;
56     resize(NumTargets);
57     NumGroups = els.groups();
58     PairID.resize(NumTargets, NumTargets);
59     for (int i = 0; i < NumTargets; ++i)
60       for (int j = 0; j < NumTargets; ++j)
61         PairID(i, j) = els.GroupID[i] * NumGroups + els.GroupID[j];
62     offsetPrms.resize(NumGroups * NumGroups, 0);
63   }
64 
initialize(ParticleSet & P,std::vector<RealType> & yk)65   void initialize(ParticleSet& P, std::vector<RealType>& yk)
66   {
67     NumKShells = yk.size();
68     Fk         = yk;
69     NumKVecs   = P.SK->KLists.kshell[NumKShells + 1];
70     Rhok.resize(NumKVecs);
71     if (Optimize)
72       numParams = NumKShells;
73   }
74 
resize(int NT)75   void resize(int NT) { NumTargets = NT; }
76 
~Backflow_ee_kSpace()77   ~Backflow_ee_kSpace(){};
78 
makeClone(ParticleSet & tqp)79   BackflowFunctionBase* makeClone(ParticleSet& tqp) const
80   {
81     Backflow_ee_kSpace* clone = new Backflow_ee_kSpace(CenterSys, tqp);
82     clone->resize(NumTargets);
83     //       clone->uniqueRadFun.resize(uniqueRadFun.size());
84     //       clone->RadFun.resize(RadFun.size());
85     /*
86     for(int i=0; i<uniqueRadFun.size(); i++)
87       clone->uniqueRadFun[i] = new FT(*(uniqueRadFun[i]));
88     for(int i=0; i<RadFun.size(); i++)
89     {
90       bool done=false;
91       for(int k=0; k<uniqueRadFun.size(); k++)
92         if(RadFun[i] == uniqueRadFun[k]) {
93           done=true;
94           clone->RadFun[i] = clone->uniqueRadFun[k];
95           break;
96         }
97       if(!done) {
98         APP_ABORT("Error cloning Backflow_ee_kSpace object. \n");
99       }
100     }
101     */
102     return clone;
103   }
104 
addFunc(int ia,int ib)105   void addFunc(int ia, int ib)
106   {
107     /*
108           uniqueRadFun.push_back(rf);
109           if(first) {
110             // initialize all with rf the first time
111             for(int i=0; i<RadFun.size(); i++)
112               RadFun[i]=rf;
113             first=false;
114           } else {
115             RadFun[ia*NumGroups+ib] = rf;
116             RadFun[ib*NumGroups+ia] = rf;
117           }
118     */
119   }
120 
registerData(WFBufferType & buf)121   void registerData(WFBufferType& buf)
122   {
123     /*
124           FirstOfU = &(UIJ(0,0)[0]);
125           LastOfU = FirstOfU + OHMMS_DIM*NumTargets*NumTargets;
126           FirstOfA = &(AIJ(0,0)[0]);
127           LastOfA = FirstOfA + OHMMS_DIM*OHMMS_DIM*NumTargets*NumTargets;
128           FirstOfB = &(BIJ(0,0)[0]);
129           LastOfB = FirstOfB + OHMMS_DIM*NumTargets*NumTargets;
130           buf.add(FirstOfU,LastOfU);
131           buf.add(FirstOfA,LastOfA);
132           buf.add(FirstOfB,LastOfB);
133     */
134   }
135 
reportStatus(std::ostream & os)136   void reportStatus(std::ostream& os) { myVars.print(os); }
137 
resetParameters(const opt_variables_type & active)138   void resetParameters(const opt_variables_type& active)
139   {
140     if (Optimize)
141     {
142       for (int i = 0; i < Fk.size(); ++i)
143       {
144         int loc = myVars.where(i);
145         if (loc >= 0) {
146           myVars[i] = active[loc];
147           Fk[i] = std::real(myVars[i]);
148           //Fk[i] = myVars[i] = active[loc];
149         }
150       }
151     }
152   }
153 
checkInVariables(opt_variables_type & active)154   void checkInVariables(opt_variables_type& active)
155   {
156     if (Optimize)
157       active.insertFrom(myVars);
158   }
159 
checkOutVariables(const opt_variables_type & active)160   void checkOutVariables(const opt_variables_type& active)
161   {
162     if (Optimize)
163       myVars.getIndex(active);
164   }
165 
isOptimizable()166   inline bool isOptimizable() { return Optimize; }
167 
indexOffset()168   inline int indexOffset()
169   {
170     if (Optimize)
171       return myVars.where(0);
172     else
173       return 0;
174   }
175 
acceptMove(int iat,int UpdateMode)176   inline void acceptMove(int iat, int UpdateMode)
177   {
178     int num;
179     switch (UpdateMode)
180     {
181     case ORB_PBYP_RATIO:
182       num = UIJ.rows();
183       for (int i = 0; i < num; i++)
184       {
185         //            UIJ(iat,i) = UIJ_temp(i);
186         //            UIJ(i,iat) = -1.0*UIJ_temp(i);
187       }
188       break;
189     case ORB_PBYP_PARTIAL:
190       num = UIJ.rows();
191       for (int i = 0; i < num; i++)
192       {
193         //            UIJ(iat,i) = UIJ_temp(i);
194         //            UIJ(i,iat) = -1.0*UIJ_temp(i);
195       }
196       num = AIJ.rows();
197       for (int i = 0; i < num; i++)
198       {
199         //            AIJ(iat,i) = AIJ_temp(i);
200         //            AIJ(i,iat) = AIJ_temp(i);
201       }
202       break;
203     case ORB_PBYP_ALL:
204       num = UIJ.rows();
205       for (int i = 0; i < num; i++)
206       {
207         //            UIJ(iat,i) = UIJ_temp(i);
208         //            UIJ(i,iat) = -1.0*UIJ_temp(i);
209       }
210       num = AIJ.rows();
211       for (int i = 0; i < num; i++)
212       {
213         //            AIJ(iat,i) = AIJ_temp(i);
214         //            AIJ(i,iat) = AIJ_temp(i);
215       }
216       num = BIJ.rows();
217       for (int i = 0; i < num; i++)
218       {
219         //            BIJ(iat,i) = BIJ_temp(i);
220         //            BIJ(i,iat) = -1.0*BIJ_temp(i);
221       }
222       break;
223     default:
224       num = UIJ.rows();
225       for (int i = 0; i < num; i++)
226       {
227         //            UIJ(iat,i) = UIJ_temp(i);
228         //            UIJ(i,iat) = -1.0*UIJ_temp(i);
229       }
230       num = AIJ.rows();
231       for (int i = 0; i < num; i++)
232       {
233         //            AIJ(iat,i) = AIJ_temp(i);
234         //            AIJ(i,iat) = AIJ_temp(i);
235       }
236       num = BIJ.rows();
237       for (int i = 0; i < num; i++)
238       {
239         //            BIJ(iat,i) = BIJ_temp(i);
240         //            BIJ(i,iat) = -1.0*BIJ_temp(i);
241       }
242       break;
243     }
244     //      UIJ_temp=0.0;
245     //      AIJ_temp=0.0;
246     //      BIJ_temp=0.0;
247   }
248 
restore(int iat,int UpdateType)249   inline void restore(int iat, int UpdateType)
250   {
251     //      UIJ_temp=0.0;
252     //      AIJ_temp=0.0;
253     //      BIJ_temp=0.0;
254   }
255 
256   /** calculate quasi-particle coordinates only
257    */
evaluate(const ParticleSet & P,ParticleSet & QP)258   inline void evaluate(const ParticleSet& P, ParticleSet& QP)
259   {
260 #if defined(USE_REAL_STRUCT_FACTOR)
261     APP_ABORT("Backflow_ee_kSpace::evaluate");
262 #else
263     //memcopy if necessary but this is not so critcal
264     copy(P.SK->rhok[0], P.SK->rhok[0] + NumKVecs, Rhok.data());
265     for (int spec1 = 1; spec1 < NumGroups; spec1++)
266       accumulate_elements(P.SK->rhok[spec1], P.SK->rhok[spec1] + NumKVecs, Rhok.data());
267     const KContainer::VContainer_t& Kcart(P.SK->KLists.kpts_cart);
268     std::vector<int>& kshell(P.SK->KLists.kshell);
269     for (int iel = 0; iel < NumTargets; iel++)
270     {
271       const ComplexType* restrict eikr_ptr(P.SK->eikr[iel]);
272       const ComplexType* restrict rhok_ptr(Rhok.data());
273       int ki = 0;
274       for (int ks = 0; ks < NumKShells; ks++)
275       {
276         // don't understand factor of 2, ask Markus!!!
277         RealType pre = 2.0 * Fk[ks];
278         for (; ki < kshell[ks + 1]; ki++, eikr_ptr++, rhok_ptr++)
279         {
280           RealType ii = ((*eikr_ptr).real() * (*rhok_ptr).imag() - (*eikr_ptr).imag() * (*rhok_ptr).real());
281           QP.R[iel] -= pre * Kcart[ki] * ii;
282         }
283       }
284     }
285 #endif
286   }
287 
evaluate(const ParticleSet & P,ParticleSet & QP,GradVector_t & Bmat,HessMatrix_t & Amat)288   inline void evaluate(const ParticleSet& P, ParticleSet& QP, GradVector_t& Bmat, HessMatrix_t& Amat)
289   {
290     APP_ABORT("This shouldn't be called: Backflow_ee_kSpace::evaluate(Bmat)");
291   }
292 
293 
294   /** calculate quasi-particle coordinates, Bmat and Amat
295    */
evaluate(const ParticleSet & P,ParticleSet & QP,GradMatrix_t & Bmat_full,HessMatrix_t & Amat)296   inline void evaluate(const ParticleSet& P, ParticleSet& QP, GradMatrix_t& Bmat_full, HessMatrix_t& Amat)
297   {
298 #if defined(USE_REAL_STRUCT_FACTOR)
299     APP_ABORT("Backflow_ee_kSpace::evaluate");
300 #else
301     //memcopy if necessary but this is not so critcal
302     copy(P.SK->rhok[0], P.SK->rhok[0] + NumKVecs, Rhok.data());
303     for (int spec1 = 1; spec1 < NumGroups; spec1++)
304       accumulate_elements(P.SK->rhok[spec1], P.SK->rhok[spec1] + NumKVecs, Rhok.data());
305     const KContainer::VContainer_t& Kcart(P.SK->KLists.kpts_cart);
306     std::vector<int>& kshell(P.SK->KLists.kshell);
307     GradType fact;
308     HessType kakb;
309     for (int iel = 0; iel < NumTargets; iel++)
310     {
311       const ComplexType* restrict eikr_ptr(P.SK->eikr[iel]);
312       const ComplexType* restrict rhok_ptr(Rhok.data());
313       const RealType* restrict ksq_ptr(P.SK->KLists.ksq.data());
314       int ki = 0;
315       for (int ks = 0; ks < NumKShells; ks++, ksq_ptr++)
316       {
317         // don't understand factor of 2, ask Markus!!!
318         RealType pre = 2.0 * Fk[ks];
319         RealType k2  = *ksq_ptr;
320         for (; ki < kshell[ks + 1]; ki++, eikr_ptr++, rhok_ptr++)
321         {
322           RealType rr = ((*eikr_ptr).real() * (*rhok_ptr).real() + (*eikr_ptr).imag() * (*rhok_ptr).imag());
323           RealType ii = ((*eikr_ptr).real() * (*rhok_ptr).imag() - (*eikr_ptr).imag() * (*rhok_ptr).real());
324           // quasiparticle
325           QP.R[iel] -= pre * Kcart[ki] * ii;
326           // B matrix
327           convert(k2 * pre * Kcart[ki], fact);
328           convert(pre * outerProduct(Kcart[ki], Kcart[ki]), kakb);
329           Bmat_full(iel, iel) += fact * (ii - 1.0);
330           // I can use symmetry to do only i<j, and then symmetrize
331           // A matrix
332           Amat(iel, iel) += kakb * (rr - 1.0);
333           // I can use symmetry to do only i<j, and then symmetrize
334           for (int j = 0; j < iel; j++)
335           {
336             ComplexType& eikrj = P.SK->eikr[j][ki];
337             Bmat_full(iel, j) += fact * ((*eikr_ptr).real() * (eikrj).imag() - (*eikr_ptr).imag() * (eikrj).real());
338             Amat(iel, j) -= kakb * ((*eikr_ptr).real() * (eikrj).real() + (*eikr_ptr).imag() * (eikrj).imag());
339           }
340           for (int j = iel + 1; j < NumTargets; j++)
341           {
342             ComplexType& eikrj = P.SK->eikr[j][ki];
343             Bmat_full(iel, j) += fact * ((*eikr_ptr).real() * (eikrj).imag() - (*eikr_ptr).imag() * (eikrj).real());
344             Amat(iel, j) -= kakb * ((*eikr_ptr).real() * (eikrj).real() + (*eikr_ptr).imag() * (eikrj).imag());
345           }
346         }
347       }
348     }
349 #endif
350   }
351 
352   /** calculate quasi-particle coordinates after pbyp move
353    */
evaluatePbyP(const ParticleSet & P,ParticleSet::ParticlePos_t & newQP,const std::vector<int> & index)354   inline void evaluatePbyP(const ParticleSet& P, ParticleSet::ParticlePos_t& newQP, const std::vector<int>& index) {}
355 
356   /** calculate quasi-particle coordinates after pbyp move
357    */
evaluatePbyP(const ParticleSet & P,int iat,ParticleSet::ParticlePos_t & newQP)358   inline void evaluatePbyP(const ParticleSet& P, int iat, ParticleSet::ParticlePos_t& newQP) {}
359 
360   /** calculate quasi-particle coordinates and Amat after pbyp move
361    */
evaluatePbyP(const ParticleSet & P,ParticleSet::ParticlePos_t & newQP,const std::vector<int> & index,HessMatrix_t & Amat)362   inline void evaluatePbyP(const ParticleSet& P,
363                            ParticleSet::ParticlePos_t& newQP,
364                            const std::vector<int>& index,
365                            HessMatrix_t& Amat)
366   {}
367 
368   /** calculate quasi-particle coordinates and Amat after pbyp move
369    */
evaluatePbyP(const ParticleSet & P,int iat,ParticleSet::ParticlePos_t & newQP,HessMatrix_t & Amat)370   inline void evaluatePbyP(const ParticleSet& P, int iat, ParticleSet::ParticlePos_t& newQP, HessMatrix_t& Amat) {}
371 
372   /** calculate quasi-particle coordinates and Amat after pbyp move
373    */
evaluatePbyP(const ParticleSet & P,ParticleSet::ParticlePos_t & newQP,const std::vector<int> & index,GradMatrix_t & Bmat,HessMatrix_t & Amat)374   inline void evaluatePbyP(const ParticleSet& P,
375                            ParticleSet::ParticlePos_t& newQP,
376                            const std::vector<int>& index,
377                            GradMatrix_t& Bmat,
378                            HessMatrix_t& Amat)
379   {}
380 
381   /** calculate quasi-particle coordinates and Amat after pbyp move
382    */
evaluatePbyP(const ParticleSet & P,int iat,ParticleSet::ParticlePos_t & newQP,GradMatrix_t & Bmat,HessMatrix_t & Amat)383   inline void evaluatePbyP(const ParticleSet& P,
384                            int iat,
385                            ParticleSet::ParticlePos_t& newQP,
386                            GradMatrix_t& Bmat,
387                            HessMatrix_t& Amat)
388   {}
389 
390   /** calculate only Bmat
391    *  This is used in pbyp moves, in updateBuffer()
392    */
evaluateBmatOnly(const ParticleSet & P,GradMatrix_t & Bmat_full)393   inline void evaluateBmatOnly(const ParticleSet& P, GradMatrix_t& Bmat_full) {}
394 
395   /** calculate quasi-particle coordinates, Bmat and Amat
396    *  calculate derivatives wrt to variational parameters
397    */
evaluateWithDerivatives(const ParticleSet & P,ParticleSet & QP,GradMatrix_t & Bmat_full,HessMatrix_t & Amat,GradMatrix_t & Cmat,GradMatrix_t & Ymat,HessArray_t & Xmat)398   inline void evaluateWithDerivatives(const ParticleSet& P,
399                                       ParticleSet& QP,
400                                       GradMatrix_t& Bmat_full,
401                                       HessMatrix_t& Amat,
402                                       GradMatrix_t& Cmat,
403                                       GradMatrix_t& Ymat,
404                                       HessArray_t& Xmat)
405   {}
406 };
407 
408 } // namespace qmcplusplus
409 
410 #endif
411