mirror of https://github.com/QMCPACK/qmcpack.git
Merge pull request #4918 from camelto2/mw_spin_slaterdet
Add mw_ WithSpin APIs to SlaterDet
This commit is contained in:
commit
6f44c14419
|
@ -82,6 +82,29 @@ void SlaterDet::mw_ratioGrad(const RefVectorWithLeader<WaveFunctionComponent>& w
|
|||
Dets[det_id]->mw_ratioGrad(extract_DetRef_list(wfc_list, det_id), p_list, iat, ratios, grad_now);
|
||||
}
|
||||
|
||||
void SlaterDet::mw_ratioGradWithSpin(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
int iat,
|
||||
std::vector<PsiValue>& ratios,
|
||||
std::vector<GradType>& grad_now,
|
||||
std::vector<ComplexType>& spingrad_now) const
|
||||
{
|
||||
const int det_id = getDetID(iat);
|
||||
Dets[det_id]->mw_ratioGradWithSpin(extract_DetRef_list(wfc_list, det_id), p_list, iat, ratios, grad_now,
|
||||
spingrad_now);
|
||||
}
|
||||
|
||||
|
||||
void SlaterDet::mw_evalGradWithSpin(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
int iat,
|
||||
std::vector<GradType>& grad_now,
|
||||
std::vector<ComplexType>& spingrad_now) const
|
||||
{
|
||||
const int det_id = getDetID(iat);
|
||||
Dets[det_id]->mw_evalGradWithSpin(extract_DetRef_list(wfc_list, det_id), p_list, iat, grad_now, spingrad_now);
|
||||
}
|
||||
|
||||
void SlaterDet::evaluateRatiosAlltoOne(ParticleSet& P, std::vector<ValueType>& ratios)
|
||||
{
|
||||
for (int i = 0; i < Dets.size(); ++i)
|
||||
|
|
|
@ -136,6 +136,13 @@ public:
|
|||
std::vector<PsiValue>& ratios,
|
||||
std::vector<GradType>& grad_now) const override;
|
||||
|
||||
void mw_ratioGradWithSpin(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
int iat,
|
||||
std::vector<PsiValue>& ratios,
|
||||
std::vector<GradType>& grad_now,
|
||||
std::vector<ComplexType>& spingrad_now) const override;
|
||||
|
||||
GradType evalGrad(ParticleSet& P, int iat) override { return Dets[getDetID(iat)]->evalGrad(P, iat); }
|
||||
|
||||
GradType evalGradWithSpin(ParticleSet& P, int iat, ComplexType& spingrad) override
|
||||
|
@ -152,6 +159,12 @@ public:
|
|||
Dets[det_id]->mw_evalGrad(extract_DetRef_list(wfc_list, det_id), p_list, iat, grad_now);
|
||||
}
|
||||
|
||||
void mw_evalGradWithSpin(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
int iat,
|
||||
std::vector<GradType>& grad_now,
|
||||
std::vector<ComplexType>& spingrad_now) const override;
|
||||
|
||||
GradType evalGradSource(ParticleSet& P, ParticleSet& src, int iat) override
|
||||
{
|
||||
GradType G = GradType();
|
||||
|
|
|
@ -527,7 +527,6 @@ public:
|
|||
std::vector<ValueType>& ratios,
|
||||
Matrix<ValueType>& dratios);
|
||||
|
||||
private:
|
||||
/** compute the current gradients and spin gradients for the iat-th particle of multiple walkers
|
||||
* @param wfc_list the list of WaveFunctionComponent pointers of the same component in a walker batch
|
||||
* @param p_list the list of ParticleSet pointers in a walker batch
|
||||
|
|
|
@ -144,7 +144,8 @@ set(DETERMINANT_SRC
|
|||
test_multi_dirac_determinant.cpp
|
||||
test_DiracMatrix.cpp
|
||||
test_ci_configuration.cpp
|
||||
test_multi_slater_determinant.cpp)
|
||||
test_multi_slater_determinant.cpp
|
||||
test_SlaterDet.cpp)
|
||||
|
||||
add_library(sposets_for_testing FakeSPO.cpp ConstantSPOSet.cpp)
|
||||
target_include_directories(sposets_for_testing PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
|
|
@ -0,0 +1,288 @@
|
|||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// This file is distributed under the University of Illinois/NCSA Open Source License.
|
||||
// See LICENSE file in top directory for details.
|
||||
//
|
||||
// Copyright (c) 2024 QMCPACK developers.
|
||||
//
|
||||
// File developed by: Cody A. Melton, cmelton@sandia.gov, Sandia National Laboratories
|
||||
//
|
||||
// File created by: Cody A. Melton, cmelton@sandia.gov, Sandia National Laboratories
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "QMCWaveFunctions/Fermion/DiracDeterminantBase.h"
|
||||
#include "QMCWaveFunctions/Fermion/SlaterDet.h"
|
||||
#include "QMCWaveFunctions/tests/ConstantSPOSet.h"
|
||||
#include "Particle/tests/MinimalParticlePool.h"
|
||||
#include <ResourceCollection.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace qmcplusplus
|
||||
{
|
||||
|
||||
class DummyDiracDetWithoutMW : public DiracDeterminantBase
|
||||
{
|
||||
public:
|
||||
DummyDiracDetWithoutMW(const std::string& class_name, std::unique_ptr<SPOSet>&& spos, int first, int last)
|
||||
: DiracDeterminantBase(getClassName(), std::move(spos), first, last)
|
||||
{}
|
||||
std::string getClassName() const override { return "DummyDiracDetWithoutMW"; }
|
||||
LogValue evaluateLog(const ParticleSet& P,
|
||||
ParticleSet::ParticleGradient& G,
|
||||
ParticleSet::ParticleLaplacian& L) override
|
||||
{
|
||||
G = 0.0;
|
||||
L = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
void acceptMove(ParticleSet& P, int iat, bool safe_to_delay = false) override {}
|
||||
void restore(int iat) override {}
|
||||
PsiValue ratio(ParticleSet& P, int iat) override { return 1.0; }
|
||||
GradType evalGrad(ParticleSet& P, int iat) override
|
||||
{
|
||||
GradType grad;
|
||||
grad[0] = 123.;
|
||||
grad[1] = 456.;
|
||||
grad[2] = 789.;
|
||||
return grad;
|
||||
}
|
||||
GradType evalGradWithSpin(ParticleSet& P, int iat, ComplexType& spingrad) override
|
||||
{
|
||||
GradType grad;
|
||||
grad[0] = 0.123;
|
||||
grad[1] = 0.456;
|
||||
grad[2] = 0.789;
|
||||
spingrad = ComplexType(0.1, 0.2);
|
||||
return grad;
|
||||
}
|
||||
PsiValue ratioGrad(ParticleSet& P, int iat, GradType& grad_iat) override
|
||||
{
|
||||
grad_iat[0] = 123.;
|
||||
grad_iat[1] = 456.;
|
||||
grad_iat[2] = 789.;
|
||||
return 1;
|
||||
}
|
||||
PsiValue ratioGradWithSpin(ParticleSet& P, int iat, GradType& grad_iat, ComplexType& spingrad_iat) override
|
||||
{
|
||||
grad_iat[0] = 0.123;
|
||||
grad_iat[1] = 0.456;
|
||||
grad_iat[2] = 0.789;
|
||||
spingrad_iat = ComplexType(0.1, 0.2);
|
||||
return 1;
|
||||
}
|
||||
void registerData(ParticleSet& P, WFBufferType& buf) override {}
|
||||
LogValue updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch = false) override { return 0.0; }
|
||||
void copyFromBuffer(ParticleSet& P, WFBufferType& buf) override {}
|
||||
void evaluateDerivatives(ParticleSet& P,
|
||||
const opt_variables_type& optvars,
|
||||
Vector<ValueType>& dlogpsi,
|
||||
Vector<ValueType>& dhpsioverpsi) override
|
||||
{}
|
||||
std::unique_ptr<DiracDeterminantBase> makeCopy(std::unique_ptr<SPOSet>&& spo) const override
|
||||
{
|
||||
return std::make_unique<DummyDiracDetWithoutMW>(getClassName(), std::move(spo), FirstIndex, LastIndex);
|
||||
}
|
||||
};
|
||||
|
||||
class DummyDiracDetWithMW : public DummyDiracDetWithoutMW
|
||||
{
|
||||
public:
|
||||
DummyDiracDetWithMW(const std::string& class_name, std::unique_ptr<SPOSet>&& spos, int first, int last)
|
||||
: DummyDiracDetWithoutMW(getClassName(), std::move(spos), first, last)
|
||||
{}
|
||||
|
||||
void mw_evalGrad(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
const int iat,
|
||||
std::vector<GradType>& grad_now) const override
|
||||
{
|
||||
for (auto& grad : grad_now)
|
||||
{
|
||||
grad[0] = 321.;
|
||||
grad[1] = 654.;
|
||||
grad[2] = 987.;
|
||||
}
|
||||
}
|
||||
void mw_evalGradWithSpin(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
const int iat,
|
||||
std::vector<GradType>& grad_now,
|
||||
std::vector<ComplexType>& spingrad_now) const override
|
||||
{
|
||||
for (auto& grad : grad_now)
|
||||
{
|
||||
grad[0] = 0.321;
|
||||
grad[1] = 0.654;
|
||||
grad[2] = 0.987;
|
||||
}
|
||||
for (auto& spingrad : spingrad_now)
|
||||
spingrad = ComplexType(0.2, 0.1);
|
||||
}
|
||||
void mw_ratioGrad(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
int iat,
|
||||
std::vector<PsiValue>& ratios,
|
||||
std::vector<GradType>& grad_new) const override
|
||||
{
|
||||
for (auto& grad : grad_new)
|
||||
{
|
||||
grad[0] = 321.;
|
||||
grad[1] = 654.;
|
||||
grad[2] = 987.;
|
||||
}
|
||||
}
|
||||
void mw_ratioGradWithSpin(const RefVectorWithLeader<WaveFunctionComponent>& wfc_list,
|
||||
const RefVectorWithLeader<ParticleSet>& p_list,
|
||||
int iat,
|
||||
std::vector<PsiValue>& ratios,
|
||||
std::vector<GradType>& grad_new,
|
||||
std::vector<ComplexType>& spingrad_new) const override
|
||||
{
|
||||
for (auto& grad : grad_new)
|
||||
{
|
||||
grad[0] = 0.321;
|
||||
grad[1] = 0.654;
|
||||
grad[2] = 0.987;
|
||||
}
|
||||
for (auto& spingrad : spingrad_new)
|
||||
spingrad = ComplexType(0.2, 0.1);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("SlaterDet mw_ APIs", "[wavefunction]")
|
||||
{
|
||||
Communicate* comm = OHMMS::Controller;
|
||||
|
||||
auto particle_pool = MinimalParticlePool::make_O2_spinor(comm);
|
||||
auto& elec0 = *(particle_pool).getParticleSet("e");
|
||||
auto& elec1 = *(particle_pool).getParticleSet("e");
|
||||
RefVectorWithLeader<ParticleSet> p_list(elec0, {elec0, elec1});
|
||||
|
||||
std::unique_ptr<ConstantSPOSet> spo_ptr0 = std::make_unique<ConstantSPOSet>("dummySPO", 3, 3);
|
||||
std::unique_ptr<ConstantSPOSet> spo_ptr1 = std::make_unique<ConstantSPOSet>("dummySPO", 3, 3);
|
||||
//Right now, DiracDeterminantBatched has mw_ WithSpin APIs but DiracDeterminant does not.
|
||||
//We want to add a test to make sure Slater determinant chooses the mw_ implementation if it has it.
|
||||
|
||||
// First, do without mw_ APIs
|
||||
{
|
||||
std::unique_ptr<DiracDeterminantBase> det_ptr0 =
|
||||
std::make_unique<DummyDiracDetWithoutMW>("dummy", std::move(spo_ptr0), 0, 12);
|
||||
std::unique_ptr<DiracDeterminantBase> det_ptr1 =
|
||||
std::make_unique<DummyDiracDetWithoutMW>("dummy", std::move(spo_ptr1), 0, 12);
|
||||
|
||||
std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets0;
|
||||
dirac_dets0.push_back(std::move(det_ptr0));
|
||||
std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets1;
|
||||
dirac_dets1.push_back(std::move(det_ptr1));
|
||||
|
||||
SlaterDet slaterdet0(elec0, std::move(dirac_dets0));
|
||||
SlaterDet slaterdet1(elec0, std::move(dirac_dets1));
|
||||
|
||||
RefVectorWithLeader<WaveFunctionComponent> sd_list(slaterdet0, {slaterdet0, slaterdet1});
|
||||
ResourceCollection sd_res("test_sd_res");
|
||||
slaterdet0.createResource(sd_res);
|
||||
ResourceCollectionTeamLock<WaveFunctionComponent> mw_sd_lock(sd_res, sd_list);
|
||||
|
||||
std::vector<SPOSet::GradType> grads(2);
|
||||
std::vector<WaveFunctionComponent::PsiValue> ratios(2);
|
||||
std::vector<SPOSet::ComplexType> spingrads(2);
|
||||
slaterdet0.mw_evalGrad(sd_list, p_list, 0, grads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(123.));
|
||||
CHECK(grad[1] == ValueApprox(456.));
|
||||
CHECK(grad[2] == ValueApprox(789.));
|
||||
}
|
||||
|
||||
slaterdet0.mw_evalGradWithSpin(sd_list, p_list, 0, grads, spingrads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(0.123));
|
||||
CHECK(grad[1] == ValueApprox(0.456));
|
||||
CHECK(grad[2] == ValueApprox(0.789));
|
||||
}
|
||||
for (auto sgrad : spingrads)
|
||||
CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.1, 0.2)));
|
||||
|
||||
slaterdet0.mw_ratioGrad(sd_list, p_list, 0, ratios, grads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(123.));
|
||||
CHECK(grad[1] == ValueApprox(456.));
|
||||
CHECK(grad[2] == ValueApprox(789.));
|
||||
}
|
||||
|
||||
slaterdet0.mw_ratioGradWithSpin(sd_list, p_list, 0, ratios, grads, spingrads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(0.123));
|
||||
CHECK(grad[1] == ValueApprox(0.456));
|
||||
CHECK(grad[2] == ValueApprox(0.789));
|
||||
}
|
||||
for (auto sgrad : spingrads)
|
||||
CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.1, 0.2)));
|
||||
}
|
||||
//Now do with MW
|
||||
{
|
||||
std::unique_ptr<DiracDeterminantBase> det_ptr0 =
|
||||
std::make_unique<DummyDiracDetWithMW>("dummy", std::move(spo_ptr0), 0, 12);
|
||||
std::unique_ptr<DiracDeterminantBase> det_ptr1 =
|
||||
std::make_unique<DummyDiracDetWithMW>("dummy", std::move(spo_ptr1), 0, 12);
|
||||
|
||||
std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets0;
|
||||
dirac_dets0.push_back(std::move(det_ptr0));
|
||||
std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets1;
|
||||
dirac_dets1.push_back(std::move(det_ptr1));
|
||||
|
||||
SlaterDet slaterdet0(elec0, std::move(dirac_dets0));
|
||||
SlaterDet slaterdet1(elec1, std::move(dirac_dets1));
|
||||
|
||||
RefVectorWithLeader<WaveFunctionComponent> sd_list(slaterdet0, {slaterdet0, slaterdet1});
|
||||
|
||||
ResourceCollection sd_res("test_sd_res");
|
||||
slaterdet0.createResource(sd_res);
|
||||
ResourceCollectionTeamLock<WaveFunctionComponent> mw_sd_lock(sd_res, sd_list);
|
||||
|
||||
std::vector<SPOSet::GradType> grads(2);
|
||||
std::vector<WaveFunctionComponent::PsiValue> ratios(2);
|
||||
std::vector<SPOSet::ComplexType> spingrads(2);
|
||||
slaterdet0.mw_evalGrad(sd_list, p_list, 0, grads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(321.));
|
||||
CHECK(grad[1] == ValueApprox(654.));
|
||||
CHECK(grad[2] == ValueApprox(987.));
|
||||
}
|
||||
|
||||
slaterdet0.mw_evalGradWithSpin(sd_list, p_list, 0, grads, spingrads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(0.321));
|
||||
CHECK(grad[1] == ValueApprox(0.654));
|
||||
CHECK(grad[2] == ValueApprox(0.987));
|
||||
}
|
||||
for (auto sgrad : spingrads)
|
||||
CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.2, 0.1)));
|
||||
|
||||
slaterdet0.mw_ratioGrad(sd_list, p_list, 0, ratios, grads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(321.));
|
||||
CHECK(grad[1] == ValueApprox(654.));
|
||||
CHECK(grad[2] == ValueApprox(987.));
|
||||
}
|
||||
|
||||
slaterdet0.mw_ratioGradWithSpin(sd_list, p_list, 0, ratios, grads, spingrads);
|
||||
for (auto grad : grads)
|
||||
{
|
||||
CHECK(grad[0] == ValueApprox(0.321));
|
||||
CHECK(grad[1] == ValueApprox(0.654));
|
||||
CHECK(grad[2] == ValueApprox(0.987));
|
||||
}
|
||||
for (auto sgrad : spingrads)
|
||||
CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.2, 0.1)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace qmcplusplus
|
|
@ -371,7 +371,7 @@ TEST_CASE("TrialWaveFunction_diamondC_1x1x1", "[wavefunction]")
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef QMC_COMPLEX
|
||||
#if defined(QMC_COMPLEX) && !defined(ENABLE_CUDA)
|
||||
/** This test is intended to catch a bug that was found in the batched code
|
||||
* when using spinors and jastrows. The issue came about because WFCs that don't
|
||||
* contribute to the spin gradient end up going back to the normal mw_evalGrad
|
||||
|
|
Loading…
Reference in New Issue