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: 8 // 9 // File created by: Jeongnim Kim, jeongnim.kim@intel.com, Intel Corp. 10 ////////////////////////////////////////////////////////////////////////////////////// 11 12 13 /** @file SoaLocalizedBasisSet.h 14 * @brief A derived class from BasisSetBase 15 * 16 * This is intended as a replacement for MolecularWaveFunctionComponent and 17 * any other localized basis set. 18 */ 19 #ifndef QMCPLUSPLUS_SOA_LOCALIZEDBASISSET_H 20 #define QMCPLUSPLUS_SOA_LOCALIZEDBASISSET_H 21 22 #include "QMCWaveFunctions/BasisSetBase.h" 23 #include "Particle/DistanceTableData.h" 24 25 namespace qmcplusplus 26 { 27 /** A localized basis set derived from SoaBasisSetBase<ORBT> 28 * 29 * This class performs the evaluation of the basis functions and their 30 * derivatives for each of the N-particles in a configuration. 31 * The template parameter COT denotes Centered-Orbital-Type which provides 32 * a set of localized orbitals associated with a center. 33 * The template parameter ORBT denotes the orbital value return type 34 */ 35 template<class COT, typename ORBT> 36 struct SoaLocalizedBasisSet : public SoaBasisSetBase<ORBT> 37 { 38 typedef typename COT::RealType RealType; 39 typedef SoaBasisSetBase<ORBT> BaseType; 40 typedef typename BaseType::vgl_type vgl_type; 41 typedef typename BaseType::vgh_type vgh_type; 42 typedef typename BaseType::vghgh_type vghgh_type; 43 typedef typename ParticleSet::PosType PosType; 44 45 using BaseType::BasisSetSize; 46 47 ///number of centers, e.g., ions 48 size_t NumCenters; 49 ///number of quantum particles 50 size_t NumTargets; 51 ///ion particle set 52 const ParticleSet& ions_; 53 ///number of quantum particles 54 const int myTableIndex; 55 ///Global Coordinate of Supertwist read from HDF5 56 PosType SuperTwist; 57 58 59 /** container to store the offsets of the basis functions 60 * 61 * the number of basis states for center J is BasisOffset[J+1]-Basis[J] 62 */ 63 aligned_vector<size_t> BasisOffset; 64 65 /** container of the unique pointers to the Atomic Orbitals 66 * 67 * size of LOBasisSet = number of unique centers 68 */ 69 aligned_vector<COT*> LOBasisSet; 70 71 /** constructor 72 * @param ions ionic system 73 * @param els electronic system 74 */ SoaLocalizedBasisSetSoaLocalizedBasisSet75 SoaLocalizedBasisSet(ParticleSet& ions, ParticleSet& els) 76 : ions_(ions), myTableIndex(els.addTable(ions, true)), SuperTwist(0.0) 77 { 78 NumCenters = ions.getTotalNum(); 79 NumTargets = els.getTotalNum(); 80 LOBasisSet.resize(ions.getSpeciesSet().getTotalNum(), 0); 81 BasisOffset.resize(NumCenters + 1); 82 BasisSetSize = 0; 83 } 84 85 /** copy constructor */ 86 SoaLocalizedBasisSet(const SoaLocalizedBasisSet& a) = default; 87 88 /** makeClone */ 89 //SoaLocalizedBasisSet<COT>* makeClone() const makeCloneSoaLocalizedBasisSet90 BaseType* makeClone() const 91 { 92 SoaLocalizedBasisSet<COT, ORBT>* myclone = new SoaLocalizedBasisSet<COT, ORBT>(*this); 93 for (int i = 0; i < LOBasisSet.size(); ++i) 94 myclone->LOBasisSet[i] = LOBasisSet[i]->makeClone(); 95 return myclone; 96 } 97 /** set Number of periodic Images to evaluate the orbitals. 98 Set to 0 for non-PBC, and set manually in the input. 99 Passes the pre-computed phase factor for evaluation of complex wavefunction. If WF is real Phase_factor is real and equals 1 if gamma or -1 if non-Gamma. 100 */ setPBCParamsSoaLocalizedBasisSet101 void setPBCParams(const TinyVector<int, 3>& PBCImages, 102 const TinyVector<double, 3> Sup_Twist, 103 const std::vector<QMCTraits::ValueType>& phase_factor) 104 { 105 for (int i = 0; i < LOBasisSet.size(); ++i) 106 LOBasisSet[i]->setPBCParams(PBCImages, Sup_Twist, phase_factor); 107 108 SuperTwist = Sup_Twist; 109 } 110 /** set BasisSetSize and allocate mVGL container 111 */ setBasisSetSizeSoaLocalizedBasisSet112 void setBasisSetSize(int nbs) 113 { 114 const auto& IonID(ions_.GroupID); 115 if (BasisSetSize > 0 && nbs == BasisSetSize) 116 return; 117 118 //evaluate the total basis dimension and offset for each center 119 BasisOffset[0] = 0; 120 for (int c = 0; c < NumCenters; c++) 121 { 122 BasisOffset[c + 1] = BasisOffset[c] + LOBasisSet[IonID[c]]->getBasisSetSize(); 123 } 124 BasisSetSize = BasisOffset[NumCenters]; 125 } 126 127 /** Determine which orbitals are S-type. Used by cusp correction. 128 */ queryOrbitalsForSTypeSoaLocalizedBasisSet129 void queryOrbitalsForSType(const std::vector<bool>& corrCenter, std::vector<bool>& is_s_orbital) const 130 { 131 const auto& IonID(ions_.GroupID); 132 int idx = 0; 133 for (int c = 0; c < NumCenters; c++) 134 { 135 int bss = LOBasisSet[IonID[c]]->BasisSetSize; 136 std::vector<bool> local_is_s_orbital(bss); 137 LOBasisSet[IonID[c]]->queryOrbitalsForSType(local_is_s_orbital); 138 for (int k = 0; k < bss; k++) 139 { 140 if (corrCenter[c]) 141 { 142 is_s_orbital[idx++] = local_is_s_orbital[k]; 143 } 144 else 145 { 146 is_s_orbital[idx++] = false; 147 } 148 } 149 } 150 } 151 152 /** compute VGL 153 * @param P quantum particleset 154 * @param iat active particle 155 * @param vgl Matrix(5,BasisSetSize) 156 * @param trialMove if true, use getTempDists()/getTempDispls() 157 */ evaluateVGLSoaLocalizedBasisSet158 inline void evaluateVGL(const ParticleSet& P, int iat, vgl_type& vgl) 159 { 160 const auto& IonID(ions_.GroupID); 161 const auto& coordR = P.activeR(iat); 162 const auto& d_table = P.getDistTable(myTableIndex); 163 const auto& dist = (P.activePtcl == iat) ? d_table.getTempDists() : d_table.getDistRow(iat); 164 const auto& displ = (P.activePtcl == iat) ? d_table.getTempDispls() : d_table.getDisplRow(iat); 165 166 PosType Tv; 167 for (int c = 0; c < NumCenters; c++) 168 { 169 Tv[0] = (ions_.R[c][0] - coordR[0]) - displ[c][0]; 170 Tv[1] = (ions_.R[c][1] - coordR[1]) - displ[c][1]; 171 Tv[2] = (ions_.R[c][2] - coordR[2]) - displ[c][2]; 172 LOBasisSet[IonID[c]]->evaluateVGL(P.Lattice, dist[c], displ[c], BasisOffset[c], vgl, Tv); 173 } 174 } 175 176 177 /** compute VGH 178 * @param P quantum particleset 179 * @param iat active particle 180 * @param vgl Matrix(10,BasisSetSize) 181 * @param trialMove if true, use getTempDists()/getTempDispls() 182 */ evaluateVGHSoaLocalizedBasisSet183 inline void evaluateVGH(const ParticleSet& P, int iat, vgh_type& vgh) 184 { 185 const auto& IonID(ions_.GroupID); 186 const auto& d_table = P.getDistTable(myTableIndex); 187 const auto& dist = (P.activePtcl == iat) ? d_table.getTempDists() : d_table.getDistRow(iat); 188 const auto& displ = (P.activePtcl == iat) ? d_table.getTempDispls() : d_table.getDisplRow(iat); 189 for (int c = 0; c < NumCenters; c++) 190 { 191 LOBasisSet[IonID[c]]->evaluateVGH(P.Lattice, dist[c], displ[c], BasisOffset[c], vgh); 192 } 193 } 194 195 /** compute VGHGH 196 * @param P quantum particleset 197 * @param iat active particle 198 * @param vghgh Matrix(20,BasisSetSize) 199 * @param trialMove if true, use getTempDists()/getTempDispls() 200 */ evaluateVGHGHSoaLocalizedBasisSet201 inline void evaluateVGHGH(const ParticleSet& P, int iat, vghgh_type& vghgh) 202 { 203 // APP_ABORT("SoaLocalizedBasisSet::evaluateVGH() not implemented\n"); 204 205 const auto& IonID(ions_.GroupID); 206 const auto& d_table = P.getDistTable(myTableIndex); 207 const auto& dist = (P.activePtcl == iat) ? d_table.getTempDists() : d_table.getDistRow(iat); 208 const auto& displ = (P.activePtcl == iat) ? d_table.getTempDispls() : d_table.getDisplRow(iat); 209 for (int c = 0; c < NumCenters; c++) 210 { 211 LOBasisSet[IonID[c]]->evaluateVGHGH(P.Lattice, dist[c], displ[c], BasisOffset[c], vghgh); 212 } 213 } 214 215 /** compute values for the iat-paricle move 216 * 217 * Always uses getTempDists() and getTempDispls() 218 * Tv is a translation vector; In PBC, in order to reduce the number 219 * of images that need to be summed over when generating the AO the 220 * nearest image displacement, dr, is used. Tv corresponds to the 221 * translation that takes the 'general displacement' (displacement 222 * between ion position and electron position) to the nearest image 223 * displacement. We need to keep track of Tv because it must be add 224 * as a phase factor, i.e., exp(i*k*Tv). 225 */ evaluateVSoaLocalizedBasisSet226 inline void evaluateV(const ParticleSet& P, int iat, ORBT* restrict vals) 227 { 228 const auto& IonID(ions_.GroupID); 229 const auto& coordR = P.activeR(iat); 230 const auto& d_table = P.getDistTable(myTableIndex); 231 const auto& dist = (P.activePtcl == iat) ? d_table.getTempDists() : d_table.getDistRow(iat); 232 const auto& displ = (P.activePtcl == iat) ? d_table.getTempDispls() : d_table.getDisplRow(iat); 233 234 PosType Tv; 235 for (int c = 0; c < NumCenters; c++) 236 { 237 Tv[0] = (ions_.R[c][0] - coordR[0]) - displ[c][0]; 238 Tv[1] = (ions_.R[c][1] - coordR[1]) - displ[c][1]; 239 Tv[2] = (ions_.R[c][2] - coordR[2]) - displ[c][2]; 240 LOBasisSet[IonID[c]]->evaluateV(P.Lattice, dist[c], displ[c], vals + BasisOffset[c], Tv); 241 } 242 } 243 evaluateGradSourceVSoaLocalizedBasisSet244 inline void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vgl_type& vgl) 245 { 246 //We need to zero out the temporary array vgl. 247 auto* restrict gx = vgl.data(1); 248 auto* restrict gy = vgl.data(2); 249 auto* restrict gz = vgl.data(3); 250 251 for (int ib = 0; ib < BasisSetSize; ib++) 252 { 253 gx[ib] = 0; 254 gy[ib] = 0; 255 gz[ib] = 0; 256 } 257 258 const auto& IonID(ions_.GroupID); 259 const auto& d_table = P.getDistTable(myTableIndex); 260 const auto& dist = (P.activePtcl == iat) ? d_table.getTempDists() : d_table.getDistRow(iat); 261 const auto& displ = (P.activePtcl == iat) ? d_table.getTempDispls() : d_table.getDisplRow(iat); 262 263 264 PosType Tv; 265 Tv[0] = Tv[1] = Tv[2] = 0; 266 //Since LCAO's are written only in terms of (r-R), ionic derivatives only exist for the atomic center 267 //that we wish to take derivatives of. Moreover, we can obtain an ion derivative by multiplying an electron 268 //derivative by -1.0. Handling this sign is left to LCAOrbitalSet. For now, just note this is the electron VGL function. 269 LOBasisSet[IonID[jion]]->evaluateVGL(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vgl, Tv); 270 } 271 evaluateGradSourceVGLSoaLocalizedBasisSet272 inline void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) 273 { 274 //We need to zero out the temporary array vghgh. 275 auto* restrict gx = vghgh.data(1); 276 auto* restrict gy = vghgh.data(2); 277 auto* restrict gz = vghgh.data(3); 278 279 auto* restrict hxx = vghgh.data(4); 280 auto* restrict hxy = vghgh.data(5); 281 auto* restrict hxz = vghgh.data(6); 282 auto* restrict hyy = vghgh.data(7); 283 auto* restrict hyz = vghgh.data(8); 284 auto* restrict hzz = vghgh.data(9); 285 286 auto* restrict gxxx = vghgh.data(10); 287 auto* restrict gxxy = vghgh.data(11); 288 auto* restrict gxxz = vghgh.data(12); 289 auto* restrict gxyy = vghgh.data(13); 290 auto* restrict gxyz = vghgh.data(14); 291 auto* restrict gxzz = vghgh.data(15); 292 auto* restrict gyyy = vghgh.data(16); 293 auto* restrict gyyz = vghgh.data(17); 294 auto* restrict gyzz = vghgh.data(18); 295 auto* restrict gzzz = vghgh.data(19); 296 297 298 for (int ib = 0; ib < BasisSetSize; ib++) 299 { 300 gx[ib] = 0; 301 gy[ib] = 0; 302 gz[ib] = 0; 303 304 hxx[ib] = 0; 305 hxy[ib] = 0; 306 hxz[ib] = 0; 307 hyy[ib] = 0; 308 hyz[ib] = 0; 309 hzz[ib] = 0; 310 311 gxxx[ib] = 0; 312 gxxy[ib] = 0; 313 gxxz[ib] = 0; 314 gxyy[ib] = 0; 315 gxyz[ib] = 0; 316 gxzz[ib] = 0; 317 gyyy[ib] = 0; 318 gyyz[ib] = 0; 319 gyzz[ib] = 0; 320 gzzz[ib] = 0; 321 } 322 323 // Since jion is indexed on the source ions not the ions_ the distinction between 324 // ions_ and ions is extremely important. 325 const auto& IonID(ions.GroupID); 326 const auto& d_table = P.getDistTable(myTableIndex); 327 const auto& dist = (P.activePtcl == iat) ? d_table.getTempDists() : d_table.getDistRow(iat); 328 const auto& displ = (P.activePtcl == iat) ? d_table.getTempDispls() : d_table.getDisplRow(iat); 329 330 //Since LCAO's are written only in terms of (r-R), ionic derivatives only exist for the atomic center 331 //that we wish to take derivatives of. Moreover, we can obtain an ion derivative by multiplying an electron 332 //derivative by -1.0. Handling this sign is left to LCAOrbitalSet. For now, just note this is the electron VGL function. 333 334 LOBasisSet[IonID[jion]]->evaluateVGHGH(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vghgh); 335 } 336 /** add a new set of Centered Atomic Orbitals 337 * @param icenter the index of the center 338 * @param aos a set of Centered Atomic Orbitals 339 */ addSoaLocalizedBasisSet340 void add(int icenter, COT* aos) { LOBasisSet[icenter] = aos; } 341 }; 342 } // namespace qmcplusplus 343 #endif 344