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