Skip to content

Commit 6c1be0b

Browse files
authored
Merge pull request QMCPACK#5649 from PDoakORNL/eden_agreement_hamiltonian_changes
collect missing particle elements for energy density
2 parents b6d3074 + 0eb14d0 commit 6c1be0b

7 files changed

Lines changed: 255 additions & 135 deletions

File tree

src/QMCHamiltonians/CoulombPBCAA.cpp

Lines changed: 109 additions & 99 deletions
Large diffs are not rendered by default.

src/QMCHamiltonians/CoulombPBCAA.h

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// This file is distributed under the University of Illinois/NCSA Open Source License.
33
// See LICENSE file in top directory for details.
44
//
5-
// Copyright (c) 2022 QMCPACK developers.
5+
// Copyright (c) 2025 QMCPACK developers.
66
//
77
// File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
88
// Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
@@ -32,8 +32,6 @@ class OneDimCubicSplineLinearGrid;
3232
/** @ingroup hamiltonian
3333
*\brief Calculates the AA Coulomb potential using PBCs
3434
*
35-
* Functionally identical to CoulombPBCAA but uses a templated version of
36-
* LRHandler.
3735
*/
3836
struct CoulombPBCAA : public OperatorBase, public ForceBase
3937
{
@@ -44,7 +42,7 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase
4442
using OffloadSpline = OneDimCubicSplineLinearGrid<LRCoulombSingleton::pRealType>;
4543

4644
/// energy-optimized long range handle. Should be const LRHandlerType eventually
47-
std::shared_ptr<LRHandlerType> AA;
45+
std::shared_ptr<LRHandlerType> lr_aa_;
4846
/// energy-optimized short range pair potential
4947
std::shared_ptr<const RadFunctorType> rVs;
5048
/// the same as rVs but can be used inside OpenMP offload regions
@@ -85,10 +83,31 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase
8583
Array<TraceReal, 1>* V_sample;
8684
Array<TraceReal, 1> V_const;
8785
#endif
88-
ParticleSet& Ps;
8986

87+
/** Needs to be a mutable reference and not a copy since ParticleSet
88+
* copy misses important state which causes later access
89+
* violations.
90+
* This is a bad bad smell.
91+
*/
92+
ParticleSet& Ps;
9093

91-
/** constructor */
94+
/** constructor
95+
* Sadly there is significant conditional behavior here
96+
* the constructor does the operator calculation for the static
97+
* and only for active==true are most of the methods other than
98+
* nops.
99+
*
100+
* Consistent side effects
101+
* * local copies of most of of pset refs basic properties
102+
* input psets will not be checked for consistency later!
103+
* *
104+
* Conditional side effects include
105+
* When ComputeForces == true
106+
* * turnOnPerParticleSK for ref
107+
* * updateSource(ref)
108+
* When is_activate == false
109+
*
110+
*/
92111
CoulombPBCAA(ParticleSet& ref, bool active, bool computeForces, bool use_offload);
93112

94113
~CoulombPBCAA() override;
@@ -97,6 +116,13 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase
97116

98117
void resetTargetParticleSet(ParticleSet& P) override;
99118

119+
/** evaluate just one walker
120+
*
121+
* This is still called for batch AA IonIon
122+
* we later need to make sure for Ions that we assign from value_
123+
* to the v_samples in multi walker reference.
124+
* AA IonIon evaluation.
125+
*/
100126
Return_t evaluate(ParticleSet& P) override;
101127

102128
void mw_evaluate(const RefVectorWithLeader<OperatorBase>& o_list,
@@ -124,6 +150,11 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase
124150
TrialWaveFunction& psi,
125151
ParticleSet::ParticlePos& hf_terms,
126152
ParticleSet::ParticlePos& pulay_terms) override;
153+
154+
/**
155+
* calls eval(LR|SR){withForces} and updates eS and eL updates new_value_
156+
* new_value_ doesn't seem to ever be used anywhere
157+
*/
127158
void updateSource(ParticleSet& s) override;
128159

129160
/** Do nothing */
@@ -209,7 +240,13 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase
209240

210241
/** constructor code factored out
211242
*/
212-
void initBreakup(ParticleSet& P);
243+
void initBreakup(ParticleSet& ref_pset);
244+
245+
/** initialize everything for a static particle set
246+
* for static particle set hamiltonians no significant calculation
247+
* is done after this.
248+
*/
249+
void inactiveInitialization(ParticleSet& ref);
213250

214251
/** Compute the const part of the per particle coulomb self interaction potential.
215252
* \param[out] pp_consts constant values for the particles self interaction

src/QMCHamiltonians/Listener.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ namespace qmcplusplus
1717
template<typename T>
1818
void combinePerParticleEnergies(const CrowdEnergyValues<T>& cev_in, std::vector<Vector<T>>& values_out)
1919
{
20+
if (cev_in.begin() == cev_in.end())
21+
return;
2022
const auto num_walkers = cev_in.begin()->second.size();
2123
const auto num_particles = cev_in.begin()->second[0].size();
2224

@@ -50,5 +52,5 @@ template void combinePerParticleEnergies<std::complex<double>>(const CrowdEnergy
5052
template void combinePerParticleEnergies<std::complex<float>>(const CrowdEnergyValues<std::complex<float>>& cev_in,
5153
std::vector<Vector<std::complex<float>>>& values_out);
5254

53-
55+
5456
} // namespace qmcplusplus

src/QMCHamiltonians/NonLocalECPotential.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,8 @@ void NonLocalECPotential::mw_evaluateImpl(const RefVectorWithLeader<OperatorBase
414414
auto& vi_samples = O_leader.mw_res_handle_.getResource().vi_samples;
415415
// CAUTION! This may not be so simple in the future
416416
int iw = j;
417-
ve_samples(iw, batch_list[j].get().electron_id) += pairpots[j];
418-
vi_samples(iw, batch_list[j].get().ion_id) += pairpots[j];
417+
ve_samples(iw, batch_list[j].get().electron_id) += 0.5 * pairpots[j];
418+
vi_samples(iw, batch_list[j].get().ion_id) += 0.5 * pairpots[j];
419419
}
420420

421421
#ifdef DEBUG_NLPP_BATCHED
@@ -453,7 +453,7 @@ void NonLocalECPotential::mw_evaluateImpl(const RefVectorWithLeader<OperatorBase
453453
listener.report(iw, O_leader.getName(), ve_sample);
454454

455455
for (const ListenerVector<Real>& listener : listeners->ion_values)
456-
listener.report(iw, O_leader.getName(), vi_sample);
456+
listener.report(iw, ion_listener_operator_name, vi_sample);
457457
}
458458
ve_samples = 0.0;
459459
vi_samples = 0.0;

src/QMCHamiltonians/tests/MinimalHamiltonianPool.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,6 @@
1313
namespace qmcplusplus
1414
{
1515

16-
// See src/QMCHamiltonians/tests/test_hamiltonian_factory for parsing tests
17-
static constexpr const char* const hamiltonian_xml = R"(
18-
<hamiltonian name="h0" type="generic" target="e">
19-
<pairpot type="coulomb" name="ElecElec" source="e" target="e"/>
20-
</hamiltonian>
21-
)";
22-
23-
static constexpr const char* const hamiltonian_eeei_xml = R"(
24-
<hamiltonian name="h0" type="generic" target="e">
25-
<pairpot type="coulomb" name="ElecElec" source="e" target="e"/>
26-
<pairpot type="coulomb" name="ElecIon" source="ion" target="e"/>
27-
</hamiltonian>
28-
)";
29-
3016
HamiltonianPool MinimalHamiltonianPool::make_hamWithEE(Communicate* comm,
3117
ParticleSetPool& particle_pool,
3218
WaveFunctionPool& wavefunction_pool)
@@ -55,5 +41,33 @@ HamiltonianPool MinimalHamiltonianPool::makeHamWithEEEI(Communicate* comm,
5541
return hpool;
5642
}
5743

44+
HamiltonianPool MinimalHamiltonianPool::makeHamWithEEEIII(Communicate* comm,
45+
ParticleSetPool& particle_pool,
46+
WaveFunctionPool& wavefunction_pool)
47+
{
48+
HamiltonianPool hpool(particle_pool, wavefunction_pool, comm);
49+
Libxml2Document doc;
50+
doc.parseFromString(hamiltonian_eeeiii_xml);
51+
52+
xmlNodePtr root = doc.getRoot();
53+
hpool.put(root);
54+
55+
return hpool;
56+
}
57+
58+
HamiltonianPool MinimalHamiltonianPool::makeHamWithEEEIPS(Communicate* comm,
59+
ParticleSetPool& particle_pool,
60+
WaveFunctionPool& wavefunction_pool)
61+
{
62+
HamiltonianPool hpool(particle_pool, wavefunction_pool, comm);
63+
Libxml2Document doc;
64+
doc.parseFromString(hamiltonian_eeeips_xml);
65+
66+
xmlNodePtr root = doc.getRoot();
67+
hpool.put(root);
68+
69+
return hpool;
70+
}
71+
5872

5973
} // namespace qmcplusplus

src/QMCHamiltonians/tests/MinimalHamiltonianPool.h

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// This file is distributed under the University of Illinois/NCSA Open Source License.
33
// See LICENSE file in top directory for details.
44
//
5-
// Copyright (c) 2019 QMCPACK developers.
5+
// Copyright (c) 2025 QMCPACK developers.
66
//
77
// File developed by: Peter Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
88
//
@@ -21,13 +21,62 @@ namespace qmcplusplus
2121
{
2222
class MinimalHamiltonianPool
2323
{
24+
// See src/QMCHamiltonians/tests/test_hamiltonian_factory for parsing tests
25+
static constexpr const char* const hamiltonian_xml = R"(
26+
<hamiltonian name="h0" type="generic" target="e">
27+
<pairpot type="coulomb" name="ElecElec" source="e" target="e"/>
28+
</hamiltonian>
29+
)";
30+
31+
static constexpr const char* const hamiltonian_eeei_xml = R"(
32+
<hamiltonian name="h0" type="generic" target="e">
33+
<pairpot type="coulomb" name="ElecElec" source="e" target="e"/>
34+
<pairpot type="coulomb" name="ElecIon" source="ion" target="e"/>
35+
</hamiltonian>
36+
)";
37+
38+
static constexpr const char* const hamiltonian_eeeiii_xml = R"(
39+
<hamiltonian name="h0" type="generic" target="e">
40+
<pairpot type="coulomb" name="ElecElec" source="e" target="e"/>
41+
<pairpot type="coulomb" name="ElecIon" source="ion" target="e"/>
42+
<pairpot type="coulomb" name="IonIon" source="ion" target="ion"/>
43+
</hamiltonian>
44+
)";
45+
46+
static constexpr const char* const hamiltonian_eeeips_xml = R"(
47+
<hamiltonian name="h0" type="generic" target="e">
48+
<pairpot type="coulomb" name="ElecElec" source="e" target="e"/>
49+
<pairpot type="coulomb" name="ElecIon" source="ion" target="e"/>
50+
<pairpot type="pseudo" name="PseudoPot" source="ion0" wavefunction="psi0" format="xml">
51+
<pseudo elementType="C" href="C.BFD.xml"/>
52+
</pairpot>
53+
</hamiltonian>
54+
)";
55+
2456
public:
57+
/// make a HamitonianPool with a primary hamiltonian with Coulombic electron electron interaction
2558
static HamiltonianPool make_hamWithEE(Communicate* comm,
2659
ParticleSetPool& particle_pool,
2760
WaveFunctionPool& wavefunction_pool);
61+
/** make a HamitonianPool with a primary hamiltonian with Coulombic electron
62+
* electron interaction and electron ion interaction
63+
*/
2864
static HamiltonianPool makeHamWithEEEI(Communicate* comm,
2965
ParticleSetPool& particle_pool,
3066
WaveFunctionPool& wavefunction_pool);
67+
/** make a HamitonianPool with a primary hamiltonian with Coulombic electron
68+
* electron interaction and electron ion interaction and ion ion interaction.
69+
*/
70+
static HamiltonianPool makeHamWithEEEIII(Communicate* comm,
71+
ParticleSetPool& particle_pool,
72+
WaveFunctionPool& wavefunction_pool);
73+
74+
/** make a HamitonianPool with a primary hamiltonian with Coulombic electron
75+
* electron interaction and electron ion interaction and a pseudo potential component
76+
*/
77+
static HamiltonianPool makeHamWithEEEIPS(Communicate* comm,
78+
ParticleSetPool& particle_pool,
79+
WaveFunctionPool& wavefunction_pool);
3180
};
3281

3382
} // namespace qmcplusplus

src/QMCHamiltonians/tests/test_NonLocalECPotential.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,12 @@ TEST_CASE("NonLocalECPotential", "[hamiltonian]")
190190
testing::TestNonLocalECPotential::evaluateImpl(nl_ecp, elec, false, true);
191191
const auto value = nl_ecp.getValue();
192192

193-
CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(value));
194-
CHECK(std::accumulate(local_pots2.begin(), local_pots2.begin() + local_pots2.cols(), 0.0) == Approx(value));
195-
CHECK(std::accumulate(ion_pots.begin(), ion_pots.begin() + ion_pots.cols(), 0.0) == Approx(-2.1047365665));
196-
CHECK(std::accumulate(ion_pots2.begin(), ion_pots2.begin() + ion_pots2.cols(), 0.0) == Approx(-2.1047365665));
193+
double total_localpots = std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0);
194+
total_localpots += std::accumulate(ion_pots.begin(), ion_pots.begin() + ion_pots.cols(), 0.0);
195+
CHECK(total_localpots == Approx(value));
196+
double total_localpots2 = std::accumulate(local_pots[1], local_pots[1] + local_pots.cols(), 0.0);
197+
total_localpots2 += std::accumulate(ion_pots[1], ion_pots[1] + ion_pots.cols(), 0.0);
198+
CHECK(total_localpots2 == Approx(value));
197199

198200
CHECK(!testing::TestNonLocalECPotential::didGridChange(nl_ecp));
199201

@@ -203,16 +205,22 @@ TEST_CASE("NonLocalECPotential", "[hamiltonian]")
203205
testing::TestNonLocalECPotential::mw_evaluateImpl(nl_ecp, o_list, twf_list, p_list, false, listener_opt, true);
204206

205207
CHECK(!testing::TestNonLocalECPotential::didGridChange(nl_ecp));
206-
auto value2 = o_list[0].evaluateDeterministic(elec);
208+
auto value_moved = o_list[0].evaluateDeterministic(elec);
207209

208-
CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(value2));
210+
total_localpots = std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0);
211+
total_localpots += std::accumulate(ion_pots.begin(), ion_pots.begin() + ion_pots.cols(), 0.0);
212+
CHECK(total_localpots == Approx(value_moved));
209213
// check the second walker which will be unchanged.
210-
CHECK(std::accumulate(local_pots2[1], local_pots2[1] + local_pots2.cols(), 0.0) == Approx(value));
214+
total_localpots2 = std::accumulate(local_pots[1], local_pots[1] + local_pots.cols(), 0.0);
215+
total_localpots2 += std::accumulate(ion_pots[1], ion_pots[1] + ion_pots.cols(), 0.0);
216+
CHECK(total_localpots2 == Approx(value));
211217

212-
// Randomizing grid does nothing for Na pp
213218
testing::TestNonLocalECPotential::mw_evaluateImpl(nl_ecp, o_list, twf_list, p_list, false, listener_opt, false);
214-
auto value3 = o_list[0].evaluateDeterministic(p_list[0]);
215-
CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(value3));
219+
auto value3 = o_list[0].evaluateDeterministic(p_list[0]);
220+
total_localpots = std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0);
221+
total_localpots += std::accumulate(ion_pots.begin(), ion_pots.begin() + ion_pots.cols(), 0.0);
222+
223+
CHECK(total_localpots == Approx(value3));
216224
}
217225

218226
} // namespace qmcplusplus

0 commit comments

Comments
 (0)