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: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign 8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign 9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign 10 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory 11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory 12 // 13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign 14 ////////////////////////////////////////////////////////////////////////////////////// 15 16 17 /**@file QMCHamiltonian.h 18 *@brief Declaration of QMCHamiltonian 19 */ 20 #ifndef QMCPLUSPLUS_HAMILTONIAN_H 21 #define QMCPLUSPLUS_HAMILTONIAN_H 22 #include "QMCHamiltonians/NonLocalECPotential.h" 23 #include "QMCHamiltonians/L2Potential.h" 24 #include "Configuration.h" 25 #include "QMCDrivers/WalkerProperties.h" 26 #include "QMCHamiltonians/OperatorBase.h" 27 #if !defined(REMOVE_TRACEMANAGER) 28 #include "Estimators/TraceManager.h" 29 #endif 30 #include "QMCWaveFunctions/OrbitalSetTraits.h" 31 32 namespace qmcplusplus 33 { 34 class MCWalkerConfiguration; 35 class HamiltonianFactory; 36 class NonLocalECPotential; 37 38 /** Collection of Local Energy Operators 39 * 40 * Note that QMCHamiltonian is not derived from QMCHmailtonianBase. 41 */ 42 class QMCHamiltonian 43 { 44 friend class HamiltonianFactory; 45 46 public: 47 typedef OperatorBase::Return_t Return_t; 48 typedef OperatorBase::PosType PosType; 49 typedef OperatorBase::TensorType TensorType; 50 typedef OperatorBase::RealType RealType; 51 typedef OperatorBase::ValueType ValueType; 52 using FullPrecRealType = QMCTraits::FullPrecRealType; 53 typedef OperatorBase::PropertySetType PropertySetType; 54 typedef OperatorBase::BufferType BufferType; 55 typedef OperatorBase::Walker_t Walker_t; 56 using WP = WalkerProperties::Indexes; 57 enum 58 { 59 DIM = OHMMS_DIM 60 }; 61 62 ///constructor 63 QMCHamiltonian(const std::string& aname = "psi0"); 64 65 ///destructor 66 ~QMCHamiltonian(); 67 68 ///add an operator 69 void addOperator(OperatorBase* h, const std::string& aname, bool physical = true); 70 71 ///record the name-type pair of an operator 72 void addOperatorType(const std::string& name, const std::string& type); 73 74 ///return type of named H element or fail 75 const std::string& getOperatorType(const std::string& name); 76 77 ///return the number of Hamiltonians size()78 inline int size() const { return H.size(); } 79 80 ///return the total number of Hamiltonians (physical + aux) total_size()81 inline int total_size() const { return H.size() + auxH.size(); } 82 83 /** return OperatorBase with the name aname 84 * @param aname name of a OperatorBase 85 * @return 0 if aname is not found. 86 */ 87 OperatorBase* getHamiltonian(const std::string& aname); 88 89 /** return i-th OperatorBase 90 * @param i index of the OperatorBase 91 * @return H[i] 92 */ getHamiltonian(int i)93 OperatorBase* getHamiltonian(int i) { return H[i]; } 94 95 #if !defined(REMOVE_TRACEMANAGER) 96 ///initialize trace data 97 void initialize_traces(TraceManager& tm, ParticleSet& P); 98 99 // ///collect scalar trace data 100 //void collect_scalar_traces(); 101 102 ///collect walker trace data 103 void collect_walker_traces(Walker_t& walker, int step); 104 105 ///finalize trace data 106 void finalize_traces(); 107 #endif 108 109 /** 110 * \defgroup Functions to get/put observables 111 */ 112 /**@{*/ 113 /** add each term to the PropertyList for averages 114 * @param plist a set of properties to which this Hamiltonian add the observables 115 */ 116 //void addObservables(PropertySetType& plist); 117 118 /** add each term to P.PropertyList and P.mcObservables 119 * @param P particle set to which observables are added 120 * @return the number of observables 121 */ 122 int addObservables(ParticleSet& P); 123 124 /** register obsevables so that their averages can be dumped to hdf5 125 * @param h5desc has observable_helper* for each h5 group 126 * @param gid h5 group id to which the observable groups are added. 127 */ 128 void registerObservables(std::vector<observable_helper*>& h5desc, hid_t gid) const; 129 /** register collectables so that their averages can be dumped to hdf5 130 * @param h5desc has observable_helper* for each h5 group 131 * @param gid h5 group id to which the observable groups are added. 132 * 133 * Add observable_helper information for the data stored in ParticleSet::mcObservables. 134 */ 135 void registerCollectables(std::vector<observable_helper*>& h5desc, hid_t gid) const; 136 ///retrun the starting index startIndex()137 inline int startIndex() const { return myIndex; } 138 ///return the size of observables sizeOfObservables()139 inline int sizeOfObservables() const { return Observables.size(); } 140 ///return the size of collectables sizeOfCollectables()141 inline int sizeOfCollectables() const { return numCollectables; } 142 ///return the value of the i-th observable getObservable(int i)143 inline RealType getObservable(int i) const { return Observables.Values[i]; } 144 ///return the value of the observable with a set name if it exists getObservable(std::string Oname)145 inline int getObservable(std::string Oname) const 146 { 147 int rtval(-1); 148 for (int io = 0; io < Observables.size(); io++) 149 { 150 if (Observables.Names[io] == Oname) 151 return io; 152 } 153 return rtval; 154 } 155 ///return the name of the i-th observable getObservableName(int i)156 inline std::string getObservableName(int i) const { return Observables.Names[i]; } 157 158 /** save the values of Hamiltonian elements to the Properties 159 * 160 * This creates a hard dependence on Walker using WalkerProperties to index its Properties. 161 * It also assumes no one else is sticking things into Walker's Properties and that 162 * It can access into it as if it were a raw FullPrecRealType array. 163 * 164 */ 165 template<class IT, typename = std::enable_if_t<std::is_same<std::add_pointer<FullPrecRealType>::type, IT>::value>> saveProperty(IT first)166 inline void saveProperty(IT first) 167 { 168 first[WP::LOCALPOTENTIAL] = LocalEnergy - KineticEnergy; 169 copy(Observables.begin(), Observables.end(), first + myIndex); 170 } 171 /**@}*/ 172 173 template<class IT, typename = std::enable_if_t<std::is_same<std::add_pointer<FullPrecRealType>::type, IT>::value>> setProperty(IT first)174 inline void setProperty(IT first) 175 { 176 // LocalEnergy=first[WP::LOCALENERGY]; 177 // KineticEnergy=LocalEnergy-first[LOCALPOTENTIAL]; 178 copy(first + myIndex, first + myIndex + Observables.size(), Observables.begin()); 179 } 180 181 void update_source(ParticleSet& s); 182 183 ////return the LocalEnergy \f$=\sum_i H^{qmc}_{i}\f$ getLocalEnergy()184 inline FullPrecRealType getLocalEnergy() { return LocalEnergy; } 185 ////return the LocalPotential \f$=\sum_i H^{qmc}_{i} - KE\f$ getLocalPotential()186 inline FullPrecRealType getLocalPotential() { return LocalEnergy - KineticEnergy; } getKineticEnergy()187 inline FullPrecRealType getKineticEnergy() { return KineticEnergy; } 188 void auxHevaluate(ParticleSet& P); 189 void auxHevaluate(ParticleSet& P, Walker_t& ThisWalker); 190 void auxHevaluate(ParticleSet& P, Walker_t& ThisWalker, bool do_properties, bool do_collectables); 191 void rejectedMove(ParticleSet& P, Walker_t& ThisWalker); 192 ///** set Tau for each Hamiltonian 193 // */ 194 //inline void setTau(RealType tau) 195 //{ 196 // for(int i=0; i< H.size();i++)H[i]->setTau(tau); 197 //} 198 199 /** set PRIMARY bit of all the components 200 */ setPrimary(bool primary)201 inline void setPrimary(bool primary) 202 { 203 for (int i = 0; i < H.size(); i++) 204 H[i]->UpdateMode.set(OperatorBase::PRIMARY, primary); 205 } 206 207 /////Set Tau inside each of the Hamiltonian elements 208 //void setTau(Return_t tau) 209 //{ 210 // for(int i=0; i<H.size(); i++) H[i]->setTau(tau); 211 // for(int i=0; i<auxH.size(); i++) auxH[i]->setTau(tau); 212 //} 213 214 ///** return if WaveFunction Ratio needs to be evaluated 215 // * 216 // * This is added to handle orbital-dependent OperatorBase during 217 // * orbital optimizations. 218 // */ 219 //inline bool needRatio() { 220 // bool dependOnOrbital=false; 221 // for(int i=0; i< H.size();i++) 222 // if(H[i]->UpdateMode[OperatorBase::RATIOUPDATE]) dependOnOrbital=true; 223 // return dependOnOrbital; 224 //} 225 226 /** evaluate Local Energy 227 * @param P ParticleSet 228 * @return the local energy 229 * 230 * P.R, P.G and P.L are used to evaluate the LocalEnergy. 231 */ 232 FullPrecRealType evaluate(ParticleSet& P); 233 234 /** evaluate Local Energy deterministically. Defaults to evaluate(P) for operators 235 * without a stochastic component. For the nonlocal PP, the quadrature grid is not rerandomized. 236 * @param P ParticleSet 237 * @return Local energy. 238 */ 239 FullPrecRealType evaluateDeterministic(ParticleSet& P); 240 /** batched version of evaluate for LocalEnergy 241 * 242 * Encapsulation is ignored for ham_list hamiltonians method uses its status as QMCHamiltonian to break encapsulation. 243 * ParticleSet is also updated. 244 * Bugs could easily be created by accessing this scope. 245 * This should be set to static and fixed. 246 */ 247 static std::vector<QMCHamiltonian::FullPrecRealType> mw_evaluate(const RefVectorWithLeader<QMCHamiltonian>& ham_list, 248 const RefVectorWithLeader<ParticleSet>& p_list); 249 250 /** evaluate Local energy with Toperators updated. 251 * @param P ParticleSEt 252 * @return Local energy 253 */ 254 FullPrecRealType evaluateWithToperator(ParticleSet& P); 255 256 /** batched version of evaluate Local energy with Toperators updated. 257 */ 258 static std::vector<QMCHamiltonian::FullPrecRealType> mw_evaluateWithToperator( 259 const RefVectorWithLeader<QMCHamiltonian>& ham_list, 260 const RefVectorWithLeader<ParticleSet>& p_list); 261 262 263 /** evaluate energy and derivatives wrt to the variables 264 * @param P ParticleSet 265 * @param optvars current optimiable variables 266 * @param dlogpsi \f$\partial \ln \Psi({\bf R})/\partial \alpha \f$ 267 * @param dhpsioverpsi \f$\partial(\hat{h}\Psi({\bf R})/\Psi({\bf R})) /\partial \alpha \f$ 268 * @param compute_deriv if true, compute dhpsioverpsi of the non-local potential component 269 */ 270 FullPrecRealType evaluateValueAndDerivatives(ParticleSet& P, 271 const opt_variables_type& optvars, 272 std::vector<ValueType>& dlogpsi, 273 std::vector<ValueType>& dhpsioverpsi, 274 bool compute_deriv); 275 276 static std::vector<QMCHamiltonian::FullPrecRealType> mw_evaluateValueAndDerivatives( 277 const RefVectorWithLeader<QMCHamiltonian>& ham_list, 278 const RefVectorWithLeader<ParticleSet>& p_list, 279 const opt_variables_type& optvars, 280 RecordArray<ValueType>& dlogpsi, 281 RecordArray<ValueType>& dhpsioverpsi, 282 bool compute_deriv); 283 284 static std::vector<QMCHamiltonian::FullPrecRealType> mw_evaluateValueAndDerivativesInner( 285 const RefVectorWithLeader<QMCHamiltonian>& ham_list, 286 const RefVectorWithLeader<ParticleSet>& p_list, 287 const opt_variables_type& optvars, 288 RecordArray<ValueType>& dlogpsi, 289 RecordArray<ValueType>& dhpsioverpsi); 290 291 292 /** Evaluate the electron gradient of the local energy. 293 * @param psi Trial Wave Function 294 * @param P electron particle set 295 * @param EGrad an Nelec x 3 real array which corresponds to d/d[r_i]_j E_L 296 * @param A finite difference step size if applicable. Default is to use finite diff with delta=1e-5. 297 * @return EGrad. Function itself returns nothing. 298 */ 299 void evaluateElecGrad(ParticleSet& P, 300 TrialWaveFunction& psi, 301 ParticleSet::ParticlePos_t& EGrad, 302 RealType delta = 1e-5); 303 304 /** evaluate local energy and derivatives w.r.t ionic coordinates. 305 * @param P target particle set (electrons) 306 * @param ions source particle set (ions) 307 * @param psi Trial wave function 308 * @param hf_terms Re [(dH)Psi]/Psi 309 * @param pulay_terms Re [(H-E_L)dPsi]/Psi 310 * @param wf_grad Re (dPsi/Psi) 311 * @return Local Energy. 312 */ 313 FullPrecRealType evaluateIonDerivs(ParticleSet& P, 314 ParticleSet& ions, 315 TrialWaveFunction& psi, 316 ParticleSet::ParticlePos_t& hf_terms, 317 ParticleSet::ParticlePos_t& pulay_terms, 318 ParticleSet::ParticlePos_t& wf_grad); 319 /** set non local moves options 320 * @param cur the xml input 321 */ 322 void setNonLocalMoves(xmlNodePtr cur); 323 324 void setNonLocalMoves(const std::string& non_local_move_option, 325 const double tau, 326 const double alpha, 327 const double gamma); 328 329 /** make non local moves 330 * @param P particle set 331 * @return the number of accepted moves 332 */ 333 int makeNonLocalMoves(ParticleSet& P); 334 335 /** determine if L2 potential is present 336 */ has_L2()337 bool has_L2() { return l2_ptr != nullptr; } 338 339 /** compute D matrix and K vector for L2 potential propagator 340 * @param r single particle coordinate 341 * @param D diffusion matrix (outputted) 342 * @param K drift modification vector (outputted) 343 */ computeL2DK(ParticleSet & P,int iel,TensorType & D,PosType & K)344 void computeL2DK(ParticleSet& P, int iel, TensorType& D, PosType& K) 345 { 346 if (l2_ptr != nullptr) 347 l2_ptr->evaluateDK(P, iel, D, K); 348 } 349 350 /** compute D matrix for L2 potential propagator 351 * @param r single particle coordinate 352 * @param D diffusion matrix (outputted) 353 */ computeL2D(ParticleSet & P,int iel,TensorType & D)354 void computeL2D(ParticleSet& P, int iel, TensorType& D) 355 { 356 if (l2_ptr != nullptr) 357 l2_ptr->evaluateD(P, iel, D); 358 } 359 360 static std::vector<int> mw_makeNonLocalMoves(const RefVectorWithLeader<QMCHamiltonian>& ham_list, 361 const RefVectorWithLeader<ParticleSet>& p_list); 362 /** evaluate energy 363 * @param P quantum particleset 364 * @param free_nlpp if true, non-local PP is a variable 365 * @return KE + NonLocal potential 366 */ 367 FullPrecRealType evaluateVariableEnergy(ParticleSet& P, bool free_nlpp); 368 369 /** return an average value of the LocalEnergy 370 * 371 * Introduced to get a collective value 372 */ 373 FullPrecRealType getEnsembleAverage(); 374 375 void resetTargetParticleSet(ParticleSet& P); 376 getName()377 const std::string& getName() const { return myName; } 378 379 bool get(std::ostream& os) const; 380 get_LocalEnergy()381 RealType get_LocalEnergy() const { return LocalEnergy; } 382 383 void setRandomGenerator(RandomGenerator_t* rng); 384 385 static void updateNonKinetic(OperatorBase& op, QMCHamiltonian& ham, ParticleSet& pset); 386 static void updateKinetic(OperatorBase& op, QMCHamiltonian& ham, ParticleSet& pset); 387 388 389 /// initialize a shared resource and hand it to a collection 390 void createResource(ResourceCollection& collection) const; 391 /** acquire external resource 392 * Note: use RAII ResourceCollectionLock whenever possible 393 */ 394 void acquireResource(ResourceCollection& collection); 395 /** release external resource 396 * Note: use RAII ResourceCollectionLock whenever possible 397 */ 398 void releaseResource(ResourceCollection& collection); 399 400 /** return a clone */ 401 QMCHamiltonian* makeClone(ParticleSet& qp, TrialWaveFunction& psi); 402 403 #ifdef QMC_CUDA 404 //////////////////////////////////////////// 405 // Vectorized evaluation routines for GPU // 406 //////////////////////////////////////////// 407 void evaluate(MCWalkerConfiguration& W, std::vector<RealType>& LocalEnergy); 408 void evaluate(MCWalkerConfiguration& W, 409 std::vector<RealType>& energyVector, 410 std::vector<std::vector<NonLocalData>>& Txy); 411 412 private: 413 ///////////////////// 414 // Vectorized data // 415 ///////////////////// 416 std::vector<QMCHamiltonian::FullPrecRealType> LocalEnergyVector, KineticEnergyVector, AuxEnergyVector; 417 #endif 418 419 private: 420 ///starting index 421 int myIndex; 422 ///starting index 423 int numCollectables; 424 ///Current Local Energy 425 FullPrecRealType LocalEnergy; 426 ///Current Kinetic Energy 427 FullPrecRealType KineticEnergy; 428 ///Current Local Energy for the proposed move 429 FullPrecRealType NewLocalEnergy; 430 ///getName is in the way 431 const std::string myName; 432 ///vector of Hamiltonians 433 std::vector<OperatorBase*> H; 434 ///pointer to NonLocalECP 435 NonLocalECPotential* nlpp_ptr; 436 ///pointer to L2Potential 437 L2Potential* l2_ptr; 438 ///vector of Hamiltonians 439 std::vector<OperatorBase*> auxH; 440 /// Total timer for H evaluation 441 NewTimer& ham_timer_; 442 /// timers for H components 443 TimerList_t my_timers_; 444 ///types of component operators 445 std::map<std::string, std::string> operator_types; 446 ///data 447 PropertySetType Observables; 448 /** reset Observables and counters 449 * @param start starting index within PropertyList 450 * @param ncollects number of collectables 451 */ 452 void resetObservables(int start, int ncollects); 453 454 // helper function for extracting a list of Hamiltonian components from a list of QMCHamiltonian::H. 455 static RefVectorWithLeader<OperatorBase> extract_HC_list(const RefVectorWithLeader<QMCHamiltonian>& ham_list, int id); 456 457 #if !defined(REMOVE_TRACEMANAGER) 458 ///traces variables 459 TraceRequest request; 460 bool streaming_position; 461 Array<TraceInt, 1>* id_sample; 462 Array<TraceInt, 1>* pid_sample; 463 Array<TraceInt, 1>* step_sample; 464 Array<TraceInt, 1>* gen_sample; 465 Array<TraceInt, 1>* age_sample; 466 Array<TraceInt, 1>* mult_sample; 467 Array<TraceReal, 1>* weight_sample; 468 Array<TraceReal, 2>* position_sample; 469 #endif 470 }; 471 } // namespace qmcplusplus 472 #endif 473