diff --git a/src/QMCWaveFunctions/tests/CMakeLists.txt b/src/QMCWaveFunctions/tests/CMakeLists.txt index 5c9484da4c0..b414f0158b4 100644 --- a/src/QMCWaveFunctions/tests/CMakeLists.txt +++ b/src/QMCWaveFunctions/tests/CMakeLists.txt @@ -111,6 +111,7 @@ set(SPOSET_SRC test_hybridrep.cpp test_pw.cpp test_ConstantSPOSet.cpp + test_ConstantSPOSetT.cpp ${MO_SRCS}) if(NiO_a16_H5_FOUND) set(SPOSET_SRC ${SPOSET_SRC} test_einset_NiO_a16.cpp) @@ -139,7 +140,7 @@ set(DETERMINANT_SRC test_ci_configuration.cpp test_multi_slater_determinant.cpp) -add_library(sposets_for_testing FakeSPOT.cpp FakeSPO.cpp ConstantSPOSet.cpp) +add_library(sposets_for_testing FakeSPOT.cpp FakeSPO.cpp ConstantSPOSet.cpp ConstantSPOSetT.cpp) target_include_directories(sposets_for_testing PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_link_libraries(sposets_for_testing PUBLIC qmcwfs) diff --git a/src/QMCWaveFunctions/tests/ConstantSPOSetT.cpp b/src/QMCWaveFunctions/tests/ConstantSPOSetT.cpp new file mode 100644 index 00000000000..49e50702419 --- /dev/null +++ b/src/QMCWaveFunctions/tests/ConstantSPOSetT.cpp @@ -0,0 +1,124 @@ +////////////////////////////////////////////////////////////////////////////////////// +// This file is distributed under the University of Illinois/NCSA Open Source License. +// See LICENSE file in top directory for details. +// +// Copyright (c) 2023 Raymond Clay and QMCPACK developers. +// +// File developed by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories +// +// File created by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories +////////////////////////////////////////////////////////////////////////////////////// + +#include "ConstantSPOSetT.h" + +namespace qmcplusplus +{ + +template +ConstantSPOSetT::ConstantSPOSetT(const std::string& my_name, const int nparticles, const int norbitals) + : SPOSetT(my_name), numparticles_(nparticles) +{ + this->OrbitalSetSize = norbitals; + ref_psi_.resize(numparticles_, this->OrbitalSetSize); + ref_egrad_.resize(numparticles_, this->OrbitalSetSize); + ref_elapl_.resize(numparticles_, this->OrbitalSetSize); + + ref_psi_ = 0.0; + ref_egrad_ = 0.0; + ref_elapl_ = 0.0; +} + +template +std::unique_ptr> ConstantSPOSetT::makeClone() const +{ + auto myclone = std::make_unique>(this->my_name_, numparticles_, this->OrbitalSetSize); + myclone->setRefVals(ref_psi_); + myclone->setRefEGrads(ref_egrad_); + myclone->setRefELapls(ref_elapl_); + return myclone; +} + +template +void ConstantSPOSetT::checkOutVariables(const opt_variables_type& active) +{ + APP_ABORT("ConstantSPOSet should not call checkOutVariables"); +}; + +template +void ConstantSPOSetT::setOrbitalSetSize(int norbs) +{ + APP_ABORT("ConstantSPOSet should not call setOrbitalSetSize()"); +} + +template +void ConstantSPOSetT::setRefVals(const ValueMatrix& vals) +{ + assert(vals.cols() == this->OrbitalSetSize); + assert(vals.rows() == numparticles_); + ref_psi_ = vals; +} + +template +void ConstantSPOSetT::setRefEGrads(const GradMatrix& grads) +{ + assert(grads.cols() == this->OrbitalSetSize); + assert(grads.rows() == numparticles_); + ref_egrad_ = grads; +} + +template +void ConstantSPOSetT::setRefELapls(const ValueMatrix& lapls) +{ + assert(lapls.cols() == this->OrbitalSetSize); + assert(lapls.rows() == numparticles_); + ref_elapl_ = lapls; +} + +template +void ConstantSPOSetT::evaluateValue(const ParticleSet& P, int iat, ValueVector& psi) +{ + const auto* vp = dynamic_cast(&P); + int ptcl = vp ? vp->refPtcl : iat; + assert(psi.size() == this->OrbitalSetSize); + for (int iorb = 0; iorb < this->OrbitalSetSize; iorb++) + psi[iorb] = ref_psi_(ptcl, iorb); +} + +template +void ConstantSPOSetT::evaluateVGL(const ParticleSet& P, + int iat, + ValueVector& psi, + GradVector& dpsi, + ValueVector& d2psi) +{ + for (int iorb = 0; iorb < this->OrbitalSetSize; iorb++) + { + psi[iorb] = ref_psi_(iat, iorb); + dpsi[iorb] = ref_egrad_(iat, iorb); + d2psi[iorb] = ref_elapl_(iat, iorb); + } +} + +template +void ConstantSPOSetT::evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + ValueMatrix& d2logdet) +{ + for (int iat = first, i = 0; iat < last; ++iat, ++i) + { + ValueVector v(logdet[i], logdet.cols()); + GradVector g(dlogdet[i], dlogdet.cols()); + ValueVector l(d2logdet[i], d2logdet.cols()); + evaluateVGL(P, iat, v, g, l); + } +} + +template class ConstantSPOSetT; +template class ConstantSPOSetT; +template class ConstantSPOSetT>; +template class ConstantSPOSetT>; + +} //namespace qmcplusplus diff --git a/src/QMCWaveFunctions/tests/ConstantSPOSetT.h b/src/QMCWaveFunctions/tests/ConstantSPOSetT.h new file mode 100644 index 00000000000..a6e16f8e3d9 --- /dev/null +++ b/src/QMCWaveFunctions/tests/ConstantSPOSetT.h @@ -0,0 +1,93 @@ +////////////////////////////////////////////////////////////////////////////////////// +// This file is distributed under the University of Illinois/NCSA Open Source License. +// See LICENSE file in top directory for details. +// +// Copyright (c) 2023 Raymond Clay and QMCPACK developers. +// +// File developed by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories +// +// File created by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories +////////////////////////////////////////////////////////////////////////////////////// + + +#ifndef QMCPLUSPLUS_CONSTANTSPOSET_H +#define QMCPLUSPLUS_CONSTANTSPOSET_H + +#include "QMCWaveFunctions/SPOSetT.h" + +namespace qmcplusplus +{ +/** Constant SPOSet for testing purposes. Fixed N_elec x N_orb matrices storing value, gradients, and laplacians, etc., + * These values are accessed through standard SPOSet calls like evaluateValue, evaluateVGL, etc. + * Exists to provide deterministic and known output to objects requiring SPOSet evaluations. + * + */ +template +class ConstantSPOSetT : public SPOSetT +{ +public: + using ValueMatrix = typename SPOSetT::ValueMatrix; + using GradMatrix = typename SPOSetT::GradMatrix; + using ValueVector = typename SPOSetT::ValueVector; + using GradVector = typename SPOSetT::GradVector; + + ConstantSPOSetT(const std::string& my_name) = delete; + + //Constructor needs number of particles and number of orbitals. This is the minimum + //amount of information needed to sanely construct all data members and perform size + //checks later. + ConstantSPOSetT(const std::string& my_name, const int nparticles, const int norbitals); + + std::unique_ptr> makeClone() const final; + + std::string getClassName() const final { return "ConstantSPOSet"; }; + + void checkOutVariables(const opt_variables_type& active) final; + + void setOrbitalSetSize(int norbs) final; + + /** + * @brief Setter method to set \phi_j(r_i). Stores input matrix in ref_psi_. + * @param Nelec x Nion ValueType matrix of \phi_j(r_i) + * @return void + */ + void setRefVals(const ValueMatrix& vals); + /** + * @brief Setter method to set \nabla_i \phi_j(r_i). Stores input matrix in ref_egrad_. + * @param Nelec x Nion GradType matrix of \grad_i \phi_j(r_i) + * @return void + */ + void setRefEGrads(const GradMatrix& grads); + /** + * @brief Setter method to set \nabla^2_i \phi_j(r_i). Stores input matrix in ref_elapl_. + * @param Nelec x Nion GradType matrix of \grad^2_i \phi_j(r_i) + * @return void + */ + void setRefELapls(const ValueMatrix& lapls); + + void evaluateValue(const ParticleSet& P, int iat, ValueVector& psi) final; + + void evaluateVGL(const ParticleSet& P, int iat, ValueVector& psi, GradVector& dpsi, ValueVector& d2psi) final; + + void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix& logdet, + GradMatrix& dlogdet, + ValueMatrix& d2logdet) final; + +private: + const int numparticles_; /// evaluate_notranspose arrays are nparticle x norb matrices. + /// To ensure consistent array sizing and enforcement, + /// we agree at construction how large these matrices will be. + /// norb is stored in SPOSet::OrbitalSetSize. + + //Value, electron gradient, and electron laplacian at "reference configuration". + //i.e. before any attempted moves. + + ValueMatrix ref_psi_; + GradMatrix ref_egrad_; + ValueMatrix ref_elapl_; +}; +} // namespace qmcplusplus +#endif diff --git a/src/QMCWaveFunctions/tests/test_ConstantSPOSetT.cpp b/src/QMCWaveFunctions/tests/test_ConstantSPOSetT.cpp new file mode 100644 index 00000000000..87425bbb91a --- /dev/null +++ b/src/QMCWaveFunctions/tests/test_ConstantSPOSetT.cpp @@ -0,0 +1,136 @@ +////////////////////////////////////////////////////////////////////////////////////// +// This file is distributed under the University of Illinois/NCSA Open Source License. +// See LICENSE file in top directory for details. +// +// Copyright (c) 2023 QMCPACK developers. +// +// File developed by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories +// +// File created by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories +////////////////////////////////////////////////////////////////////////////////////// + + +#include "catch.hpp" +#include "Configuration.h" +#include "QMCWaveFunctions/WaveFunctionTypes.hpp" +#include "QMCWaveFunctions/tests/ConstantSPOSetT.h" +#include "Utilities/for_testing/checkMatrix.hpp" +namespace qmcplusplus +{ +//Ray: Figure out how to template me on value type. +TEST_CASE("ConstantSPOSetT", "[wavefunction]") +{ + //For now, do a small square case. + const int nelec = 2; + const int norb = 2; + using WF = WaveFunctionTypes; + using Real = WF::Real; + using Value = WF::Value; + using Grad = WF::Grad; + using ValueVector = Vector; + using GradVector = Vector; + using ValueMatrix = Matrix; + using GradMatrix = Matrix; + + ValueVector row0{Value(0.92387953), Value(0.92387953)}; + ValueVector row1{Value(0.29131988), Value(0.81078057)}; + + GradVector grow0{Grad({-2.22222, -1.11111, 0.33333}), Grad({8.795388, -0.816057, -0.9238793})}; + GradVector grow1{Grad({2.22222, 1.11111, -0.33333}), Grad({-8.795388, 0.816057, 0.9238793})}; + + ValueVector lrow0{Value(-0.2234545), Value(0.72340234)}; + ValueVector lrow1{Value(-12.291810), Value(6.879057)}; + + + ValueMatrix spomat; + GradMatrix gradspomat; + ValueMatrix laplspomat; + + spomat.resize(nelec, norb); + gradspomat.resize(nelec, norb); + laplspomat.resize(nelec, norb); + + for (int iorb = 0; iorb < norb; iorb++) + { + spomat(0, iorb) = row0[iorb]; + spomat(1, iorb) = row1[iorb]; + + gradspomat(0, iorb) = grow0[iorb]; + gradspomat(1, iorb) = grow1[iorb]; + + laplspomat(0, iorb) = lrow0[iorb]; + laplspomat(1, iorb) = lrow1[iorb]; + } + + + const SimulationCell simulation_cell; + ParticleSet elec(simulation_cell); + + elec.create({nelec}); + + ValueVector psiV = {0.0, 0.0}; + ValueVector psiL = {0.0, 0.0}; + GradVector psiG; + psiG.resize(norb); + + //Test of value only constructor. + auto sposet = std::make_unique>("constant_spo", nelec, norb); + sposet->setRefVals(spomat); + sposet->setRefEGrads(gradspomat); + sposet->setRefELapls(laplspomat); + + sposet->evaluateValue(elec, 0, psiV); + + CHECK(psiV[0] == row0[0]); + CHECK(psiV[1] == row0[1]); + + + psiV = 0.0; + + sposet->evaluateValue(elec, 1, psiV); + CHECK(psiV[0] == row1[0]); + CHECK(psiV[1] == row1[1]); + + psiV = 0.0; + + sposet->evaluateVGL(elec, 1, psiV, psiG, psiL); + + for (int iorb = 0; iorb < norb; iorb++) + { + CHECK(psiV[iorb] == row1[iorb]); + CHECK(psiL[iorb] == lrow1[iorb]); + + for (int idim = 0; idim < OHMMS_DIM; idim++) + CHECK(psiG[iorb][idim] == grow1[iorb][idim]); + } + //Test of evaluate_notranspose. + ValueMatrix phimat, lphimat; + GradMatrix gphimat; + phimat.resize(nelec, norb); + gphimat.resize(nelec, norb); + lphimat.resize(nelec, norb); + + const int first_index = 0; //Only 2 electrons in this case. + const int last_index = 2; + sposet->evaluate_notranspose(elec, first_index, last_index, phimat, gphimat, lphimat); + + checkMatrix(phimat, spomat); + checkMatrix(lphimat, laplspomat); + + //Test of makeClone() + auto sposet_vgl2 = sposet->makeClone(); + phimat = 0.0; + gphimat = 0.0; + lphimat = 0.0; + + sposet_vgl2->evaluate_notranspose(elec, first_index, last_index, phimat, gphimat, lphimat); + + checkMatrix(phimat, spomat); + checkMatrix(lphimat, laplspomat); + + //Lastly, check if name is correct. + std::string myname = sposet_vgl2->getClassName(); + std::string targetstring("ConstantSPOSet"); + CHECK(myname == targetstring); +} +} // namespace qmcplusplus