diff --git a/src/QMCWaveFunctions/CMakeLists.txt b/src/QMCWaveFunctions/CMakeLists.txt index 8a0611a6f5..11da0d4cf9 100644 --- a/src/QMCWaveFunctions/CMakeLists.txt +++ b/src/QMCWaveFunctions/CMakeLists.txt @@ -32,6 +32,7 @@ set(WFBASE_SRCS SPOSetInfo.cpp SPOSetInputInfo.cpp SPOSet.cpp + SPOSetT.cpp CompositeSPOSet.cpp HarmonicOscillator/SHOSet.cpp HarmonicOscillator/SHOSetBuilder.cpp diff --git a/src/QMCWaveFunctions/SPOSetT.cpp b/src/QMCWaveFunctions/SPOSetT.cpp new file mode 100644 index 0000000000..6d488d4bea --- /dev/null +++ b/src/QMCWaveFunctions/SPOSetT.cpp @@ -0,0 +1,399 @@ +////////////////////////////////////////////////////////////////////////////////////// +// This file is distributed under the University of Illinois/NCSA Open Source License. +// See LICENSE file in top directory for details. +// +// Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. +// +// File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign +// Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory +// Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory +// Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign +// Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory +// Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign +// Ying Wai Li, yingwaili@ornl.gov, Oak Ridge National Laboratory +// Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory +// William F. Godoy, godoywf@ornl.gov, Oak Ridge National Laboratory +// +// File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign +////////////////////////////////////////////////////////////////////////////////////// + +#include "SPOSetT.h" + +#include "CPU/SIMD/simd.hpp" // simd::dot + +namespace qmcplusplus +{ + +template +SPOSetT::SPOSetT(const std::string& my_name) : my_name_(my_name), OrbitalSetSize(0) +{} + +template +void SPOSetT::extractOptimizableObjectRefs(UniqueOptObjRefs&) +{ + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::extractOptimizableObjectRefs " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::checkOutVariables(const opt_variables_type& active) +{ + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::checkOutVariables " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::evaluateDetRatios(const VirtualParticleSet& VP, + ValueVector& psi, + const ValueVector& psiinv, + std::vector& ratios) +{ + assert(psi.size() == psiinv.size()); + for (int iat = 0; iat < VP.getTotalNum(); ++iat) + { + evaluateValue(VP, iat, psi); + ratios[iat] = simd::dot(psi.data(), psiinv.data(), psi.size()); + } +} + + +template +void SPOSetT::mw_evaluateDetRatios(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& vp_list, + const RefVector& psi_list, + const std::vector& invRow_ptr_list, + std::vector>& ratios_list) const +{ + assert(this == &spo_list.getLeader()); + for (int iw = 0; iw < spo_list.size(); iw++) + { + Vector invRow(const_cast(invRow_ptr_list[iw]), psi_list[iw].get().size()); + spo_list[iw].evaluateDetRatios(vp_list[iw], psi_list[iw], invRow, ratios_list[iw]); + } +} + +template +void SPOSetT::evaluateVGL_spin(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + ValueVector& d2psi, + ValueVector& dspin) +{ + throw std::runtime_error("Need specialization of SPOSet::evaluateVGL_spin"); +} + +template +void SPOSetT::mw_evaluateVGL(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const RefVector& psi_v_list, + const RefVector& dpsi_v_list, + const RefVector& d2psi_v_list) const +{ + assert(this == &spo_list.getLeader()); + for (int iw = 0; iw < spo_list.size(); iw++) + spo_list[iw].evaluateVGL(P_list[iw], iat, psi_v_list[iw], dpsi_v_list[iw], d2psi_v_list[iw]); +} + +template +void SPOSetT::mw_evaluateValue(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const RefVector& psi_v_list) const +{ + assert(this == &spo_list.getLeader()); + for (int iw = 0; iw < spo_list.size(); iw++) + spo_list[iw].evaluateValue(P_list[iw], iat, psi_v_list[iw]); +} + +template +void SPOSetT::mw_evaluateVGLWithSpin(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const RefVector& psi_v_list, + const RefVector& dpsi_v_list, + const RefVector& d2psi_v_list, + OffloadMatrix& mw_dspin) const +{ + throw std::runtime_error(getClassName() + "::mw_evaluateVGLWithSpin() is not supported. \n"); +} + + +template +void SPOSetT::mw_evaluateVGLandDetRatioGrads(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const std::vector& invRow_ptr_list, + OffloadMWVGLArray& phi_vgl_v, + std::vector& ratios, + std::vector& grads) const +{ + assert(this == &spo_list.getLeader()); + assert(phi_vgl_v.size(0) == DIM_VGL); + assert(phi_vgl_v.size(1) == spo_list.size()); + const size_t nw = spo_list.size(); + const size_t norb_requested = phi_vgl_v.size(2); + GradVector dphi_v(norb_requested); + for (int iw = 0; iw < nw; iw++) + { + ValueVector phi_v(phi_vgl_v.data_at(0, iw, 0), norb_requested); + ValueVector d2phi_v(phi_vgl_v.data_at(4, iw, 0), norb_requested); + spo_list[iw].evaluateVGL(P_list[iw], iat, phi_v, dphi_v, d2phi_v); + + ratios[iw] = simd::dot(invRow_ptr_list[iw], phi_v.data(), norb_requested); + grads[iw] = simd::dot(invRow_ptr_list[iw], dphi_v.data(), norb_requested) / ratios[iw]; + + // transpose the array of gradients to SoA in phi_vgl_v + for (size_t idim = 0; idim < DIM; idim++) + { + T* phi_g = phi_vgl_v.data_at(idim + 1, iw, 0); + for (size_t iorb = 0; iorb < norb_requested; iorb++) + phi_g[iorb] = dphi_v[iorb][idim]; + } + } + phi_vgl_v.updateTo(); +} + +template +void SPOSetT::mw_evaluateVGLandDetRatioGradsWithSpin(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const std::vector& invRow_ptr_list, + OffloadMWVGLArray& phi_vgl_v, + std::vector& ratios, + std::vector& grads, + std::vector& spingrads) const +{ + throw std::runtime_error("Need specialization of " + getClassName() + + "::mw_evaluateVGLandDetRatioGradsWithSpin(). \n"); +} + +template +void SPOSetT::evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix& grad_grad_grad_logdet) +{ + throw std::runtime_error("Need specialization of SPOSet::evaluateThirdDeriv(). \n"); +} + +template +void SPOSetT::evaluate_notranspose_spin(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + ValueMatrix& d2logdet, + ValueMatrix& dspinlogdet) +{ + throw std::runtime_error("Need specialization of " + getClassName() + + "::evaluate_notranspose_spin(P,iat,psi,dpsi,d2logdet, dspin_logdet) (vector quantities)\n"); +} + +template +void SPOSetT::mw_evaluate_notranspose(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int first, + int last, + const RefVector& logdet_list, + const RefVector& dlogdet_list, + const RefVector& d2logdet_list) const +{ + assert(this == &spo_list.getLeader()); + for (int iw = 0; iw < spo_list.size(); iw++) + spo_list[iw].evaluate_notranspose(P_list[iw], first, last, logdet_list[iw], dlogdet_list[iw], d2logdet_list[iw]); +} + +template +std::unique_ptr> SPOSetT::makeClone() const +{ + throw std::runtime_error("Missing SPOSet::makeClone for " + getClassName()); +} + +template +void SPOSetT::basic_report(const std::string& pad) const +{ + app_log() << pad << "size = " << size() << std::endl; + app_log() << pad << "state info:" << std::endl; + //states.report(pad+" "); + app_log().flush(); +} + +template +void SPOSetT::evaluateVGH(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + HessVector& grad_grad_psi) +{ + throw std::runtime_error("Need specialization of " + getClassName() + + "::evaluate(P,iat,psi,dpsi,dhpsi) (vector quantities)\n"); +} + +template +void SPOSetT::evaluateVGHGH(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + HessVector& grad_grad_psi, + GGGVector& grad_grad_grad_psi) +{ + throw std::runtime_error("Need specialization of " + getClassName() + + "::evaluate(P,iat,psi,dpsi,dhpsi,dghpsi) (vector quantities)\n"); +} + +template +void SPOSetT::applyRotation(const ValueMatrix& rot_mat, bool use_stored_copy) +{ + if (isRotationSupported()) + throw std::logic_error("Bug!! " + getClassName() + + "::applyRotation " + "must be overloaded when the SPOSet supports rotation."); +} + +template +void SPOSetT::evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + Vector& dhpsioverpsi, + const int& FirstIndex, + const int& LastIndex) +{ + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateDerivatives " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::evaluateDerivativesWF(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + int FirstIndex, + int LastIndex) +{ + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateDerivativesWF " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::evaluateDerivRatios(const VirtualParticleSet& VP, + const opt_variables_type& optvars, + ValueVector& psi, + const ValueVector& psiinv, + std::vector& ratios, + Matrix& dratios, + int FirstIndex, + int LastIndex) +{ + // Match the fallback in WaveFunctionComponent that evaluates just the ratios + evaluateDetRatios(VP, psi, psiinv, ratios); + + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateDerivRatios " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + Vector& dhpsioverpsi, + const T& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector& detValues_up, + const ValueVector& detValues_dn, + const GradMatrix& grads_up, + const GradMatrix& grads_dn, + const ValueMatrix& lapls_up, + const ValueMatrix& lapls_dn, + const ValueMatrix& M_up, + const ValueMatrix& M_dn, + const ValueMatrix& Minv_up, + const ValueMatrix& Minv_dn, + const GradMatrix& B_grad, + const ValueMatrix& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl) +{ + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateDerivatives " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::evaluateDerivativesWF(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + const T& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector& detValues_up, + const ValueVector& detValues_dn, + const ValueMatrix& M_up, + const ValueMatrix& M_dn, + const ValueMatrix& Minv_up, + const ValueMatrix& Minv_dn, + const std::vector& detData_up, + const std::vector>& lookup_tbl) +{ + if (isOptimizable()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateDerivativesWF " + "must be overloaded when the SPOSet is optimizable."); +} + +template +void SPOSetT::evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix& gradphi) +{ + if (hasIonDerivs()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateGradSource " + "must be overloaded when the SPOSet has ion derivatives."); +} + +template +void SPOSetT::evaluateGradSourceRow(const ParticleSet& P, + int iel, + const ParticleSet& source, + int iat_src, + GradVector& gradphi) +{ + if (hasIonDerivs()) + throw std::logic_error("Bug!! " + getClassName() + + "::evaluateGradSourceRow " + "must be overloaded when the SPOSet has ion derivatives."); +} + +template +void SPOSetT::evaluate_spin(const ParticleSet& P, int iat, ValueVector& psi, ValueVector& dpsi) +{ + throw std::runtime_error("Need specialization of " + getClassName() + + "::evaluate_spin(P,iat,psi,dpsi) (vector quantities)\n"); +} + +// Class concrete types from ValueType +template class SPOSetT; +template class SPOSetT; +template class SPOSetT>; +template class SPOSetT>; + +} // namespace qmcplusplus \ No newline at end of file diff --git a/src/QMCWaveFunctions/SPOSetT.h b/src/QMCWaveFunctions/SPOSetT.h new file mode 100644 index 0000000000..1959422ca7 --- /dev/null +++ b/src/QMCWaveFunctions/SPOSetT.h @@ -0,0 +1,567 @@ +////////////////////////////////////////////////////////////////////////////////////// +// This file is distributed under the University of Illinois/NCSA Open Source License. +// See LICENSE file in top directory for details. +// +// Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. +// +// File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign +// Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory +// Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory +// Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign +// Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory +// Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign +// Ying Wai Li, yingwaili@ornl.gov, Oak Ridge National Laboratory +// Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory +// William F. Godoy, godoywf@ornl.gov, Oak Ridge National Laboratory +// +// File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign +////////////////////////////////////////////////////////////////////////////////////// + + +#ifndef QMCPLUSPLUS_SPOSETT_H +#define QMCPLUSPLUS_SPOSETT_H + +#include "OhmmsPETE/OhmmsArray.h" +#include "Particle/ParticleSet.h" +#include "Particle/VirtualParticleSet.h" +#include "QMCWaveFunctions/OrbitalSetTraits.h" +#include "OptimizableObject.h" +#include "OMPTarget/OffloadAlignedAllocators.hpp" +#include "DualAllocatorAliases.hpp" + +namespace qmcplusplus +{ +class ResourceCollection; + +class SPOSet; +namespace testing +{ +opt_variables_type& getMyVars(SPOSet& spo); +} + + +/** base class for Single-particle orbital sets + * + * SPOSet stands for S(ingle)P(article)O(rbital)Set which contains + * a number of single-particle orbitals with capabilities of evaluating \f$ \psi_j({\bf r}_i)\f$ + */ +template +class SPOSetT : public QMCTraits +{ +public: + using ValueVector = typename OrbitalSetTraits::ValueVector; + using ValueMatrix = typename OrbitalSetTraits::ValueMatrix; + using GradVector = typename OrbitalSetTraits::GradVector; + using GradMatrix = typename OrbitalSetTraits::GradMatrix; + using GradType = TinyVector; + using HessVector = typename OrbitalSetTraits::HessVector; + using HessMatrix = typename OrbitalSetTraits::HessMatrix; + using GGGVector = typename OrbitalSetTraits::GradHessVector; + using GGGMatrix = typename OrbitalSetTraits::GradHessMatrix; + using SPOMap = std::map>>; + using OffloadMWVGLArray = Array>; // [VGL, walker, Orbs] + using OffloadMWVArray = Array>; // [walker, Orbs] + template + using OffloadMatrix = Matrix>; + + /** constructor */ + SPOSetT(const std::string& my_name); + + /** destructor + * + * Derived class destructor needs to pay extra attention to freeing memory shared among clones of SPOSet. + */ + virtual ~SPOSetT() = default; + + /** return the size of the orbital set + * Ye: this needs to be replaced by getOrbitalSetSize(); + */ + inline int size() const { return OrbitalSetSize; } + + /** print basic SPOSet information + */ + void basic_report(const std::string& pad = "") const; + + /** print SPOSet information + */ + virtual void report(const std::string& pad = "") const { basic_report(pad); } + + + /** return the size of the orbitals + */ + inline int getOrbitalSetSize() const { return OrbitalSetSize; } + + /// Query if this SPOSet is optimizable + virtual bool isOptimizable() const { return false; } + + /** extract underlying OptimizableObject references + * @param opt_obj_refs aggregated list of optimizable object references + */ + virtual void extractOptimizableObjectRefs(UniqueOptObjRefs& opt_obj_refs); + + /** check out variational optimizable variables + * @param active a super set of optimizable variables + */ + virtual void checkOutVariables(const opt_variables_type& active); + + /// Query if this SPOSet uses OpenMP offload + virtual bool isOMPoffload() const { return false; } + + /** Query if this SPOSet has an explicit ion dependence. returns true if it does. + */ + virtual bool hasIonDerivs() const { return false; } + + /// check a few key parameters before putting the SPO into a determinant + virtual void checkObject() const {} + + /// return true if this SPOSet can be wrappered by RotatedSPO + virtual bool isRotationSupported() const { return false; } + /// store parameters before getting destroyed by rotation. + virtual void storeParamsBeforeRotation() {} + /// apply rotation to all the orbitals + virtual void applyRotation(const ValueMatrix& rot_mat, bool use_stored_copy = false); + + /// Parameter derivatives of the wavefunction and the Laplacian of the wavefunction + virtual void evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + Vector& dhpsioverpsi, + const int& FirstIndex, + const int& LastIndex); + + /// Parameter derivatives of the wavefunction + virtual void evaluateDerivativesWF(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + int FirstIndex, + int LastIndex); + + /** Evaluate the derivative of the optimized orbitals with respect to the parameters + * this is used only for MSD, to be refined for better serving both single and multi SD + */ + virtual void evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + Vector& dhpsioverpsi, + const T& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector& detValues_up, + const ValueVector& detValues_dn, + const GradMatrix& grads_up, + const GradMatrix& grads_dn, + const ValueMatrix& lapls_up, + const ValueMatrix& lapls_dn, + const ValueMatrix& M_up, + const ValueMatrix& M_dn, + const ValueMatrix& Minv_up, + const ValueMatrix& Minv_dn, + const GradMatrix& B_grad, + const ValueMatrix& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl); + + /** Evaluate the derivative of the optimized orbitals with respect to the parameters + * this is used only for MSD, to be refined for better serving both single and multi SD + */ + virtual void evaluateDerivativesWF(ParticleSet& P, + const opt_variables_type& optvars, + Vector& dlogpsi, + const T& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector& detValues_up, + const ValueVector& detValues_dn, + const ValueMatrix& M_up, + const ValueMatrix& M_dn, + const ValueMatrix& Minv_up, + const ValueMatrix& Minv_dn, + const std::vector& detData_up, + const std::vector>& lookup_tbl); + + /** set the OrbitalSetSize + * @param norbs number of single-particle orbitals + * Ye: I prefer to remove this interface in the future. SPOSet builders need to handle the size correctly. + * It doesn't make sense allowing to set the value at any place in the code. + */ + virtual void setOrbitalSetSize(int norbs) = 0; + + /** evaluate the values of this single-particle orbital set + * @param P current ParticleSet + * @param iat active particle + * @param psi values of the SPO + */ + virtual void evaluateValue(const ParticleSet& P, int iat, ValueVector& psi) = 0; + + /** evaluate determinant ratios for virtual moves, e.g., sphere move for nonlocalPP + * @param VP virtual particle set + * @param psi values of the SPO, used as a scratch space if needed + * @param psiinv the row of inverse slater matrix corresponding to the particle moved virtually + * @param ratios return determinant ratios + */ + virtual void evaluateDetRatios(const VirtualParticleSet& VP, + ValueVector& psi, + const ValueVector& psiinv, + std::vector& ratios); + + + /// Determinant ratios and parameter derivatives of the wavefunction for virtual moves + virtual void evaluateDerivRatios(const VirtualParticleSet& VP, + const opt_variables_type& optvars, + ValueVector& psi, + const ValueVector& psiinv, + std::vector& ratios, + Matrix& dratios, + int FirstIndex, + int LastIndex); + + + /** evaluate determinant ratios for virtual moves, e.g., sphere move for nonlocalPP, of multiple walkers + * @param spo_list the list of SPOSet pointers in a walker batch + * @param vp_list a list of virtual particle sets in a walker batch + * @param psi_list a list of values of the SPO, used as a scratch space if needed + * @param invRow_ptr_list a list of pointers to the rows of inverse slater matrix corresponding to the particles moved virtually + * @param ratios_list a list of returning determinant ratios + */ + virtual void mw_evaluateDetRatios(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& vp_list, + const RefVector& psi_list, + const std::vector& invRow_ptr_list, + std::vector>& ratios_list) const; + + /** evaluate the values, gradients and laplacians of this single-particle orbital set + * @param P current ParticleSet + * @param iat active particle + * @param psi values of the SPO + * @param dpsi gradients of the SPO + * @param d2psi laplacians of the SPO + */ + virtual void evaluateVGL(const ParticleSet& P, int iat, ValueVector& psi, GradVector& dpsi, ValueVector& d2psi) = 0; + + /** evaluate the values, gradients and laplacians and spin gradient of this single-particle orbital set + * @param P current ParticleSet + * @param iat active particle + * @param psi values of the SPO + * @param dpsi gradients of the SPO + * @param d2psi laplacians of the SPO + * @param dspin spin gradients of the SPO + */ + virtual void evaluateVGL_spin(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + ValueVector& d2psi, + ValueVector& dspin); + + /** evaluate the values this single-particle orbital sets of multiple walkers + * @param spo_list the list of SPOSet pointers in a walker batch + * @param P_list the list of ParticleSet pointers in a walker batch + * @param iat active particle + * @param psi_v_list the list of value vector pointers in a walker batch + */ + virtual void mw_evaluateValue(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const RefVector& psi_v_list) const; + + /** evaluate the values, gradients and laplacians of this single-particle orbital sets of multiple walkers + * @param spo_list the list of SPOSet pointers in a walker batch + * @param P_list the list of ParticleSet pointers in a walker batch + * @param iat active particle + * @param psi_v_list the list of value vector pointers in a walker batch + * @param dpsi_v_list the list of gradient vector pointers in a walker batch + * @param d2psi_v_list the list of laplacian vector pointers in a walker batch + */ + virtual void mw_evaluateVGL(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const RefVector& psi_v_list, + const RefVector& dpsi_v_list, + const RefVector& d2psi_v_list) const; + + /** evaluate the values, gradients and laplacians and spin gradient of this single-particle orbital sets of multiple walkers + * @param spo_list the list of SPOSet pointers in a walker batch + * @param P_list the list of ParticleSet pointers in a walker batch + * @param iat active particle + * @param psi_v_list the list of value vector pointers in a walker batch + * @param dpsi_v_list the list of gradient vector pointers in a walker batch + * @param d2psi_v_list the list of laplacian vector pointers in a walker batch + * @param mw_dspin is a dual matrix of spin gradients [nw][norb] + * Note that the device side of mw_dspin is up to date + */ + virtual void mw_evaluateVGLWithSpin(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const RefVector& psi_v_list, + const RefVector& dpsi_v_list, + const RefVector& d2psi_v_list, + OffloadMatrix& mw_dspin) const; + + /** evaluate the values, gradients and laplacians of this single-particle orbital sets and determinant ratio + * and grads of multiple walkers. Device data of phi_vgl_v must be up-to-date upon return + * @param spo_list the list of SPOSet pointers in a walker batch + * @param P_list the list of ParticleSet pointers in a walker batch + * @param iat active particle + * @param phi_vgl_v orbital values, gradients and laplacians of all the walkers + * @param psi_ratio_grads_v determinant ratio and grads of all the walkers + */ + virtual void mw_evaluateVGLandDetRatioGrads(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const std::vector& invRow_ptr_list, + OffloadMWVGLArray& phi_vgl_v, + std::vector& ratios, + std::vector& grads) const; + + /** evaluate the values, gradients and laplacians of this single-particle orbital sets and determinant ratio + * and grads of multiple walkers. Device data of phi_vgl_v must be up-to-date upon return. + * Includes spin gradients + * @param spo_list the list of SPOSet pointers in a walker batch + * @param P_list the list of ParticleSet pointers in a walker batch + * @param iat active particle + * @param phi_vgl_v orbital values, gradients and laplacians of all the walkers + * @param ratios, ratios of all walkers + * @param grads, spatial gradients of all walkers + * @param spingrads, spin gradients of all walkers + */ + virtual void mw_evaluateVGLandDetRatioGradsWithSpin(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int iat, + const std::vector& invRow_ptr_list, + OffloadMWVGLArray& phi_vgl_v, + std::vector& ratios, + std::vector& grads, + std::vector& spingrads) const; + + /** evaluate the values, gradients and hessians of this single-particle orbital set + * @param P current ParticleSet + * @param iat active particle + * @param psi values of the SPO + * @param dpsi gradients of the SPO + * @param grad_grad_psi hessians of the SPO + */ + virtual void evaluateVGH(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + HessVector& grad_grad_psi); + + /** evaluate the values, gradients, hessians, and grad hessians of this single-particle orbital set + * @param P current ParticleSet + * @param iat active particle + * @param psi values of the SPO + * @param dpsi gradients of the SPO + * @param grad_grad_psi hessians of the SPO + * @param grad_grad_grad_psi grad hessians of the SPO + */ + virtual void evaluateVGHGH(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + HessVector& grad_grad_psi, + GGGVector& grad_grad_grad_psi); + + /** evaluate the values of this single-particle orbital set + * @param P current ParticleSet + * @param iat active particle + * @param psi values of the SPO + */ + virtual void evaluate_spin(const ParticleSet& P, int iat, ValueVector& psi, ValueVector& dpsi); + + /** evaluate the third derivatives of this single-particle orbital set + * @param P current ParticleSet + * @param first first particle + * @param last last particle + * @param grad_grad_grad_logdet third derivatives of the SPO + */ + virtual void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix& grad_grad_grad_logdet); + + /** evaluate the values, gradients and laplacians of this single-particle orbital for [first,last) particles + * @param[in] P current ParticleSet + * @param[in] first starting index of the particles + * @param[in] last ending index of the particles + * @param[out] logdet determinant matrix to be inverted + * @param[out] dlogdet gradients + * @param[out] d2logdet laplacians + * + */ + virtual void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + ValueMatrix& d2logdet) = 0; + + /** evaluate the values, gradients and laplacians of this single-particle orbital for [first,last) particles, including the spin gradient + * @param P current ParticleSet + * @param first starting index of the particles + * @param last ending index of the particles + * @param logdet determinant matrix to be inverted + * @param dlogdet gradients + * @param d2logdet laplacians + * @param dspinlogdet, spin gradients + * + * default implementation will abort for all SPOSets except SpinorSet + * + */ + virtual void evaluate_notranspose_spin(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + ValueMatrix& d2logdet, + ValueMatrix& dspinlogdet); + + virtual void mw_evaluate_notranspose(const RefVectorWithLeader>& spo_list, + const RefVectorWithLeader& P_list, + int first, + int last, + const RefVector& logdet_list, + const RefVector& dlogdet_list, + const RefVector& d2logdet_list) const; + + /** evaluate the values, gradients and hessians of this single-particle orbital for [first,last) particles + * @param P current ParticleSet + * @param first starting index of the particles + * @param last ending index of the particles + * @param logdet determinant matrix to be inverted + * @param dlogdet gradients + * @param grad_grad_logdet hessians + * + */ + virtual void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + HessMatrix& grad_grad_logdet); + + /** evaluate the values, gradients, hessians and third derivatives of this single-particle orbital for [first,last) particles + * @param P current ParticleSet + * @param first starting index of the particles + * @param last ending index of the particles + * @param logdet determinant matrix to be inverted + * @param dlogdet gradients + * @param grad_grad_logdet hessians + * @param grad_grad_grad_logdet third derivatives + * + */ + virtual void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + HessMatrix& grad_grad_logdet, + GGGMatrix& grad_grad_grad_logdet); + + /** evaluate the gradients of this single-particle orbital + * for [first,last) target particles with respect to the given source particle + * @param P current ParticleSet + * @param first starting index of the particles + * @param last ending index of the particles + * @param iat_src source particle index + * @param gradphi gradients + * + */ + virtual void evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix& gradphi); + + /** evaluate the gradients of values, gradients, laplacians of this single-particle orbital + * for [first,last) target particles with respect to the given source particle + * @param P current ParticleSet + * @param first starting index of the particles + * @param last ending index of the particles + * @param iat_src source particle index + * @param gradphi gradients of values + * @param grad_grad_phi gradients of gradients + * @param grad_lapl_phi gradients of laplacians + * + */ + virtual void evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix& grad_phi, + HessMatrix& grad_grad_phi, + GradMatrix& grad_lapl_phi); + + /** @brief Returns a row of d/dR_iat phi_j(r) evaluated at position r. + * + * @param[in] P particle set. + * @param[in] iel The electron at which to evaluate phi(r_iel) + * @param[in] source ion particle set. + * @param[in] iat_src ion ID w.r.t. which to take derivative. + * @param[in,out] gradphi Vector of d/dR_iat phi_j(r). + * @return Void + */ + virtual void evaluateGradSourceRow(const ParticleSet& P, + int iel, + const ParticleSet& source, + int iat_src, + GradVector& gradphi); + + /** access the k point related to the given orbital */ + virtual PosType get_k(int orb) { return PosType(); } + + /** initialize a shared resource and hand it to collection + */ + virtual void createResource(ResourceCollection& collection) const {} + + /** acquire a shared resource from collection + */ + virtual void acquireResource(ResourceCollection& collection, const RefVectorWithLeader& spo_list) const {} + + /** return a shared resource to collection + */ + virtual void releaseResource(ResourceCollection& collection, const RefVectorWithLeader& spo_list) const {} + + /** make a clone of itself + * every derived class must implement this to have threading working correctly. + */ + [[noreturn]] virtual std::unique_ptr> makeClone() const; + + /** Used only by cusp correction in AOS LCAO. + * Ye: the SoA LCAO moves all this responsibility to the builder. + * This interface should be removed with AoS. + */ + virtual bool transformSPOSet() { return true; } + + /** finalize the construction of SPOSet + * + * for example, classes serving accelerators may need to transfer data from host to device + * after the host side objects are built. + */ + virtual void finalizeConstruction() {} + + /// return object name + const std::string& getName() const { return my_name_; } + + /// return class name + virtual std::string getClassName() const = 0; + +protected: + /// name of the object, unique identifier + const std::string my_name_; + ///number of Single-particle orbitals + IndexType OrbitalSetSize; + /// Optimizable variables + opt_variables_type myVars; + + friend opt_variables_type& testing::getMyVars(SPOSetT& spo); +}; + +using SPOSetPtr = SPOSet*; + +} // namespace qmcplusplus +#endif