Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1rdm with spinor support #4807

Merged
merged 31 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
da41925
initial implementation
camelto2 May 15, 2023
86737a8
forgot switch in generateSamples
camelto2 May 16, 2023
9531313
add break
camelto2 May 16, 2023
4427709
forgot to resize array in composite SPOSet
camelto2 May 17, 2023
edf4c8b
fix generateSampleRatios for spinor moves
camelto2 May 22, 2023
a7103f3
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 May 22, 2023
28482c4
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Jun 27, 2023
7498a3b
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Oct 2, 2023
22a03c6
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Oct 2, 2023
c1c8478
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Oct 18, 2023
89976db
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Oct 30, 2023
05f2dd6
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 2, 2023
608009e
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 9, 2023
2fbd83c
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 9, 2023
c7bb140
Merge branch 'QMCPACK:develop' into 1rdm_spinor
camelto2 Nov 9, 2023
e8bc465
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 15, 2023
2534c73
Merge remote-tracking branch 'origin/1rdm_spinor' into 1rdm_spinor
camelto2 Nov 15, 2023
b765edb
initial unit test, making sure 1RDM actually does something with spins
camelto2 Nov 16, 2023
0b8aa2f
guard spinor wave functions for complex
camelto2 Nov 16, 2023
0ed8cec
fix const and address CI failure
camelto2 Nov 17, 2023
f1fb128
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 17, 2023
1542176
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 21, 2023
11e13a3
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 21, 2023
c537300
Merge remote-tracking branch 'origin/1rdm_spinor' into 1rdm_spinor
camelto2 Nov 21, 2023
362a42c
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 21, 2023
cc4dd10
address comments
camelto2 Nov 21, 2023
7f06e6f
fix issue in compositeSPOSet
camelto2 Nov 21, 2023
29db6c8
Merge remote-tracking branch 'upstream/develop' into 1rdm_spinor
camelto2 Nov 21, 2023
24d32d9
remove unnecessary intermediate variable
camelto2 Nov 22, 2023
b46d81e
Merge branch 'develop' into 1rdm_spinor
camelto2 Dec 5, 2023
55483da
Merge branch 'develop' into 1rdm_spinor
prckent Dec 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 189 additions & 9 deletions src/Estimators/OneBodyDensityMatrices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
lattice_(lattice),
species_(species),
basis_functions_("OneBodyDensityMatrices::basis"),
is_spinor_(pset_target.isSpinor()),
timers_("OneBodyDensityMatrix")
{
my_name_ = "OneBodyDensityMatrices";
Expand Down Expand Up @@ -81,6 +82,8 @@
break;
}
rsamples_.resize(samples_);
if (is_spinor_)
ssamples_.resize(samples_);

// get the sposets that form the basis
auto& sposets = input_.get_basis_sets();
Expand Down Expand Up @@ -122,7 +125,6 @@
for (int i = 0; i < basis_size_; ++i)
basis_norms_[i] = bn_standard;

rsamples_.resize(samples_);
samples_weights_.resize(samples_);
psi_ratios_.resize(nparticles);

Expand All @@ -147,6 +149,8 @@
{
basis_gradients_.resize(basis_size_);
basis_laplacians_.resize(basis_size_);
if (is_spinor_)
basis_spin_gradients_.resize(basis_size_);
}

// so if the input is not normalized, normalize it.
Expand Down Expand Up @@ -220,9 +224,12 @@
case Integrator::UNIFORM:
generateUniformSamples(rng);
break;
case Integrator::DENSITY: {
generateDensitySamples(save, steps, rng, pset_target);
}
case Integrator::DENSITY:
if (is_spinor_)
generateDensitySamplesWithSpin(save, steps, rng, pset_target);
else
generateDensitySamples(save, steps, rng, pset_target);
break;
}

if (save)
Expand Down Expand Up @@ -354,6 +361,78 @@
rhocur_ = rho;
}

inline void OneBodyDensityMatrices::generateDensitySamplesWithSpin(bool save,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateDensitySamples has a unit test this can as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

int steps,
RandomBase<FullPrecReal>& rng,
ParticleSet& pset_target)
{
const auto timestep = input_.get_timestep();
Real sqt = std::sqrt(timestep);
Real ot = 1.0 / timestep;
Position r = rpcur_; //current position
Position d = dpcur_; //current drift
Real rho = rhocur_; //current density
for (int s = 0; s < steps; ++s)
{
nmoves_++;
Position rp; // trial pos
Position dp; // trial drift
Position ds; // drift sum
Real rhop; // trial density
Real ratio; // dens ratio
Real Pacc; // acc prob
Position diff = diffuse(sqt, rng); // get diffusion

//now do spin variables
Real spinp; // trial spin
Real dspinp; // trial spindrifty
Real spin_ds; // spin drift sum
Real sdiff = diffuseSpin(sqt, rng); //spin diffusion
if (input_.get_use_drift())
{
rp = r + diff + d; //update trial position
spinp = spcur_ + sdiff + dspcur_; //update trial spin
calcDensityDriftWithSpin(rp, spinp, rhop, dp, dspinp, pset_target); //get trial drift and density
ratio = rhop / rho; //density ratio
ds = dp + d; //drift sum
spin_ds = dspinp + dspcur_; //spin drift sum
Pacc = ratio * std::exp(-ot * (dot(diff, ds) + .5 * dot(ds, ds))) *
std::exp(-ot * (sdiff * spin_ds) + 0.5 * spin_ds * spin_ds); //acceptance probability
}
else
{
rp = r + diff; //update trial position
spinp = spcur_ + sdiff; //update trial spin
calcDensityWithSpin(rp, spinp, rhop, pset_target); //get trial density
ratio = rhop / rho; //density ratio
Pacc = ratio; //acceptance probability

Check warning on line 408 in src/Estimators/OneBodyDensityMatrices.cpp

View check run for this annotation

Codecov / codecov/patch

src/Estimators/OneBodyDensityMatrices.cpp#L404-L408

Added lines #L404 - L408 were not covered by tests
}
if (rng() < Pacc)
{ //accept move
r = rp;
d = dp;
spcur_ = spinp;
dspcur_ = dspinp;
rho = rhop;
naccepted_++;
}
if (save)
{
rsamples_[s] = r;
samples_weights_[s] = 1.0 / rho;
ssamples_[s] = spcur_;
}
}
acceptance_ratio_ = Real(naccepted_) / nmoves_;

if (input_.get_write_acceptance_ratio() && omp_get_thread_num() == 0)
app_log() << "dm1b acceptance_ratio = " << acceptance_ratio_ << std::endl;

Check warning on line 429 in src/Estimators/OneBodyDensityMatrices.cpp

View check run for this annotation

Codecov / codecov/patch

src/Estimators/OneBodyDensityMatrices.cpp#L429

Added line #L429 was not covered by tests

rpcur_ = r;
dpcur_ = d;
rhocur_ = rho;
}

OneBodyDensityMatrices::Position OneBodyDensityMatrices::diffuse(const Real sqt, RandomBase<FullPrecReal>& rng)
{
Position diff;
Expand All @@ -362,6 +441,13 @@
return diff;
}

OneBodyDensityMatrices::Real OneBodyDensityMatrices::diffuseSpin(const Real sqt, RandomBase<FullPrecReal>& rng)
{
Real diff;
assignGaussRand(&diff, 1, rng);
diff *= sqt;
return diff;
}

inline void OneBodyDensityMatrices::calcDensity(const Position& r, Real& dens, ParticleSet& pset_target)
{
Expand All @@ -375,6 +461,20 @@
dens /= basis_size_;
}

inline void OneBodyDensityMatrices::calcDensityWithSpin(const Position& r,
const Real& s,
Real& dens,
ParticleSet& pset_target)
{
updateBasisWithSpin(r, s, pset_target);
dens = 0.0;
for (int i = 0; i < basis_size_; ++i)
{
Value b = basis_values_[i];
dens += std::abs(qmcplusplus::conj(b) * b);
}
dens /= basis_size_;
}

void OneBodyDensityMatrices::calcDensityDrift(const Position& r, Real& dens, Position& drift, ParticleSet& pset_target)
{
Expand All @@ -394,6 +494,33 @@
dens /= basis_size_;
}

void OneBodyDensityMatrices::calcDensityDriftWithSpin(const Position& r,
const Real& s,
Real& dens,
Position& drift,
Real& sdrift,
ParticleSet& pset_target)
{
updateBasisD012WithSpin(r, s, pset_target);
dens = 0.0;
drift = 0.0;
sdrift = 0.0;
for (int i = 0; i < basis_size_; ++i)
{
const Grad& bg = basis_gradients_[i];
const Value& bsg = basis_spin_gradients_[i];
Value b = basis_values_[i];
Value bc = qmcplusplus::conj(b);
dens += std::abs(bc * b);
for (int d = 0; d < OHMMS_DIM; ++d)
drift[d] += std::real(bc * bg[d]);
sdrift += std::real(bc * bsg);
}
drift *= input_.get_timestep() / dens;
sdrift *= input_.get_timestep() / dens;
dens /= basis_size_;
}

void OneBodyDensityMatrices::accumulate(const RefVector<MCPWalker>& walkers,
const RefVector<ParticleSet>& psets,
const RefVector<TrialWaveFunction>& wfns,
Expand Down Expand Up @@ -479,7 +606,10 @@
Matrix<Value>& P_nb = phi_nb[s];
for (int n = 0; n < species_sizes_[s]; ++n, ++p)
{
updateBasis(pset_target.R[p], pset_target);
if (is_spinor_)
updateBasisWithSpin(pset_target.R[p], pset_target.spins[p], pset_target);
else
updateBasis(pset_target.R[p], pset_target);
for (int b = 0; b < basis_size_; ++b, ++nb)
P_nb(nb) = qmcplusplus::conj(basis_values_[b]);
}
Expand All @@ -494,7 +624,10 @@
int mb = 0;
for (int m = 0; m < samples_; ++m)
{
updateBasis(rsamples_[m], pset_target);
if (is_spinor_)
updateBasisWithSpin(rsamples_[m], ssamples_[m], pset_target);
else
updateBasis(rsamples_[m], pset_target);
for (int b = 0; b < basis_size_; ++b, ++mb)
Phi_mb(mb) = basis_values_[b];
}
Expand All @@ -508,8 +641,25 @@
for (int m = 0; m < samples_; ++m)
{
// get N ratios for the current sample point
pset_target.makeVirtualMoves(rsamples_[m]);
psi_target.evaluateRatiosAlltoOne(pset_target, psi_ratios_);
if (!is_spinor_)
{
pset_target.makeVirtualMoves(rsamples_[m]);
psi_target.evaluateRatiosAlltoOne(pset_target, psi_ratios_);
}
else
{
//note: makeVirtualMoves updates distance tables
//There is not a corresponding "distance table" for the spins, so we need to brute force this by moving each electron and using makeMoveWithSpin, calcRatio, and rejectMove, and resetPhaseDiff, similar to how NonLocalECP works for evaluating quadrature points without virtual particles
int p = 0;
for (int s = 0; s < species_.size(); ++s)
for (int n = 0; n < species_sizes_[s]; ++n, ++p)
{
pset_target.makeMoveWithSpin(p, rsamples_[m] - pset_target.R[p], ssamples_[m] - pset_target.spins[p]);
psi_ratios_[p] = psi_target.calcRatio(pset_target, p);
pset_target.rejectMove(p);
psi_target.resetPhaseDiff();

Check warning on line 660 in src/Estimators/OneBodyDensityMatrices.cpp

View check run for this annotation

Codecov / codecov/patch

src/Estimators/OneBodyDensityMatrices.cpp#L660

Added line #L660 was not covered by tests
}
}

// collect ratios into per-species matrices
int p = 0;
Expand All @@ -534,6 +684,15 @@
basis_values_[i] *= basis_norms_[i];
}

inline void OneBodyDensityMatrices::updateBasisWithSpin(const Position& r, const Real& s, ParticleSet& pset_target)
{
// This is ridiculous in the case of splines, still necessary for hybrid/LCAO
pset_target.makeMoveWithSpin(0, r - pset_target.R[0], s - pset_target.spins[0]);
basis_functions_.evaluateValue(pset_target, 0, basis_values_);
pset_target.rejectMove(0);
for (int i = 0; i < basis_size_; ++i)
basis_values_[i] *= basis_norms_[i];
}

inline void OneBodyDensityMatrices::updateBasisD012(const Position& r, ParticleSet& pset_target)
{
Expand All @@ -548,6 +707,21 @@
basis_laplacians_[i] *= basis_norms_[i];
}

inline void OneBodyDensityMatrices::updateBasisD012WithSpin(const Position& r, const Real& s, ParticleSet& pset_target)
{
pset_target.makeMoveWithSpin(0, r - pset_target.R[0], s - pset_target.spins[0]);
basis_functions_.evaluateVGL_spin(pset_target, 0, basis_values_, basis_gradients_, basis_laplacians_,
basis_spin_gradients_);
pset_target.rejectMove(0);
for (int i = 0; i < basis_size_; ++i)
{
basis_values_[i] *= basis_norms_[i];
basis_gradients_[i] *= basis_norms_[i];
basis_laplacians_[i] *= basis_norms_[i];
basis_spin_gradients_[i] *= basis_norms_[i];
}
}

void OneBodyDensityMatrices::warmupSampling(ParticleSet& pset_target, RandomBase<FullPrecReal>& rng)
{
if (sampling_ == Sampling::METROPOLIS)
Expand All @@ -556,7 +730,13 @@
{
rpcur_ = diffuse(std::sqrt(input_.get_timestep()), rng);
rpcur_ += center_;
calcDensityDrift(rpcur_, rhocur_, dpcur_, pset_target);
if (!is_spinor_)
calcDensityDrift(rpcur_, rhocur_, dpcur_, pset_target);
else
{
spcur_ = diffuseSpin(std::sqrt(input_.get_timestep()), rng);
calcDensityDriftWithSpin(rpcur_, spcur_, rhocur_, dpcur_, dspcur_, pset_target);

Check warning on line 738 in src/Estimators/OneBodyDensityMatrices.cpp

View check run for this annotation

Codecov / codecov/patch

src/Estimators/OneBodyDensityMatrices.cpp#L737-L738

Added lines #L737 - L738 were not covered by tests
}
}
generateSamples(1.0, pset_target, rng, input_.get_warmup_samples());
warmed_up_ = true;
Expand Down
30 changes: 29 additions & 1 deletion src/Estimators/OneBodyDensityMatrices.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ class OneBodyDensityMatrices : public OperatorEstBase
Vector<Value> basis_norms_;
Vector<Grad> basis_gradients_;
Vector<Value> basis_laplacians_;
Vector<Value> basis_spin_gradients_;
std::vector<Position> rsamples_;
std::vector<Real> ssamples_;
Vector<Real> samples_weights_;
int basis_size_;
std::vector<int> species_sizes_;
Expand Down Expand Up @@ -145,6 +147,11 @@ class OneBodyDensityMatrices : public OperatorEstBase
/// current density
Real rhocur_ = 0.0;

///spin related variables
Real spcur_;
Real dspcur_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI. The above two uninitialized variables caused failure https://github.com/QMCPACK/qmcpack/actions/runs/8022503383/job/21922019273?pr=4928
Fixed by 1aa5148
Unfortunately compilers didn't warn us in this case.

const bool is_spinor_;

public:
/** Standard Constructor
* Call this to make a new OBDM this is what you should be calling
Expand Down Expand Up @@ -234,11 +241,19 @@ class OneBodyDensityMatrices : public OperatorEstBase
* *
*/
void generateDensitySamples(bool save, int steps, RandomBase<FullPrecReal>& rng, ParticleSet& pset_target);

/// same as above, but with spin variables included
void generateDensitySamplesWithSpin(bool save, int steps, RandomBase<FullPrecReal>& rng, ParticleSet& pset_target);

void generateSampleRatios(ParticleSet& pset_target,
TrialWaveFunction& psi_target,
std::vector<Matrix<Value>>& Psi_nm);
/// produce a position difference vector from timestep
Position diffuse(const Real sqt, RandomBase<FullPrecReal>& rng);

/// spin diffusion
Real diffuseSpin(const Real sqt, RandomBase<FullPrecReal>& rng);

/** calculate density based on r
* \param[in] r position
* \param[out] dens density
Expand All @@ -249,6 +264,8 @@ class OneBodyDensityMatrices : public OperatorEstBase
* * updateBasis is called
*/
void calcDensity(const Position& r, Real& dens, ParticleSet& pset_target);
/// same as above, but with spin move
void calcDensityWithSpin(const Position& r, const Real& s, Real& dens, ParticleSet& pset_target);
/** calculate density and drift bashed on r
* \param[in] r position
* \param[out] dens density
Expand All @@ -261,6 +278,13 @@ class OneBodyDensityMatrices : public OperatorEstBase
* * updateBasisD012 is called
*/
void calcDensityDrift(const Position& r, Real& dens, Position& drift, ParticleSet& pset_target);
/// same as above, but with spin move
void calcDensityDriftWithSpin(const Position& r,
const Real& s,
Real& dens,
Position& drift,
Real& sdrift,
ParticleSet& pset_target);
// basis & wavefunction ratio matrix construction

/** set Phi_mp to basis vaules per sample
Expand All @@ -274,14 +298,18 @@ class OneBodyDensityMatrices : public OperatorEstBase
*/
void generateParticleBasis(ParticleSet& pset_target, std::vector<Matrix<Value>>& phi_nb);

// basis set updates
/// basis set updates
void updateBasis(const Position& r, ParticleSet& pset_target);
/// basis set updates with spin
void updateBasisWithSpin(const Position& r, const Real& s, ParticleSet& pset_target);
/** evaluates vgl on basis_functions_ for r
* sideeffects:
* * sets basis_values_, basis_gradients_, basis_laplacians_
* all are normalized by basis norms_
*/
void updateBasisD012(const Position& r, ParticleSet& pset_target);
/// same as above, but includes spin gradients
void updateBasisD012WithSpin(const Position& r, const Real& s, ParticleSet& pset_target);
/** does some warmup sampling i.e. samples but throws away the results
* Only when integrator_ = Integrator::DENSITY
* sets rpcur_ initial rpcur + one diffusion step
Expand Down
2 changes: 2 additions & 0 deletions src/Estimators/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ set(SRC_DIR estimators)
set(UTEST_EXE test_${SRC_DIR})
set(UTEST_NAME deterministic-unit_test_${SRC_DIR})
set(UTEST_HDF_INPUT ${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp/pwscf.pwscf.h5)
set(UTEST_HDF_INPUT_SPINOR ${qmcpack_SOURCE_DIR}/tests/solids/monoO_noncollinear_1x1x1_pp/o2_45deg_spins.pwscf.h5)
set(UTEST_DIR ${CMAKE_CURRENT_BINARY_DIR})
maybe_symlink(${UTEST_HDF_INPUT} ${UTEST_DIR}/diamondC_1x1x1.pwscf.h5)
maybe_symlink(${UTEST_HDF_INPUT_SPINOR} ${UTEST_DIR}/o2_45deg_spins.pwscf.h5)

set(SRCS
test_accumulator.cpp
Expand Down
Loading