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

Union Potentials in HPMC #1725

Merged
merged 43 commits into from Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9d885d7
Refactor r_cut framework to allow parent potentials.
joaander Jan 25, 2024
063a682
Restore simulation performance.
joaander Jan 25, 2024
609b95c
Export setParent.
joaander Jan 25, 2024
af38cc8
Include only necessary files.
joaander Jan 25, 2024
cc28003
Make r_cut accurate in intermediate pair potentials.
joaander Feb 9, 2024
0d956de
Document that the caller should evaluate r_cut.
joaander Feb 9, 2024
e111799
Add PairPotentialUnion C++ code.
joaander Feb 9, 2024
2fabcb1
python code skeleton for union hpmc union potentials
tommy-waltmann Feb 16, 2024
79f8581
update CMakeLists fiels
tommy-waltmann Feb 16, 2024
6724fdc
started work on unit testing
tommy-waltmann Feb 19, 2024
39b8e37
write more tests
tommy-waltmann Feb 19, 2024
92620d6
Set constituent potential parent.
joaander Feb 21, 2024
fce6f3f
Set null parent on detach.
joaander Feb 21, 2024
57c9a60
Run pre-commit.
joaander Feb 21, 2024
fd16a15
Remove unused definition.
joaander Feb 21, 2024
bf9f04d
Refactor attach/detach hooks
joaander Feb 21, 2024
3ff55f6
Misc clean up.
joaander Feb 21, 2024
6ac82bf
Separate extent from OBB calculation.
joaander Feb 21, 2024
8d79c5d
Add all N*M patch energy evaluation.
joaander Feb 21, 2024
b416172
Fix r_cut handling.
joaander Feb 21, 2024
032266c
Validate dict key by key.
joaander Feb 21, 2024
22ff5e7
Always inline internal energy methods.
joaander Feb 21, 2024
3b1f2da
Improve performance.
joaander Feb 21, 2024
98173a0
added test for getting/setting the rest of the properties
tommy-waltmann Feb 26, 2024
c9d1f46
fix failing MPI test
tommy-waltmann Feb 26, 2024
863d25b
Merge branch 'trunk-minor' into hpmc-union-potential
tommy-waltmann Feb 26, 2024
e3f0147
linting
tommy-waltmann Feb 26, 2024
b169291
Type parameter dicts must be dicts, not None.
joaander Feb 27, 2024
bb71f90
Use appropriate r_cut for systems with more than 1 particle type.
joaander Feb 27, 2024
c2c2fe2
Document Union.
joaander Feb 27, 2024
3f0c4fe
Revert "Type parameter dicts must be dicts, not None."
joaander Feb 27, 2024
7dcb086
Make body[type] = None functional.
joaander Feb 27, 2024
30d946e
Run pre-commit.
joaander Feb 27, 2024
fb996a4
Fix failing unit test.
joaander Feb 27, 2024
fc09421
Apply suggestions from code review
joaander Feb 29, 2024
2e2967a
Remove unneeded std::move.
joaander Feb 29, 2024
db5d5a5
Fix errors.
joaander Feb 29, 2024
770ec98
Add _make_cpp_obj method.
joaander Feb 29, 2024
3e4cbe3
Some updates for consistency.
joaander Mar 1, 2024
c7ba866
Run pre-commit.
joaander Mar 1, 2024
e43d648
Use range-based for loop for extent.
joaander Mar 1, 2024
68cc934
Apply suggestions from code review
joaander Mar 4, 2024
652b70f
Run pre-commit.
joaander Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions hoomd/hpmc/CMakeLists.txt
Expand Up @@ -39,6 +39,7 @@ set(_hpmc_sources module.cc
ExternalFieldWall.cc
PairPotential.cc
PairPotentialLennardJones.cc
PairPotentialUnion.cc
ShapeUtils.cc
UpdaterBoxMC.cc
UpdaterQuickCompress.cc
Expand Down Expand Up @@ -78,6 +79,7 @@ set(_hpmc_headers
OBBTree.h
PairPotential.h
PairPotentialLennardJones.h
PairPotentialUnion.h
ShapeConvexPolygon.h
ShapeConvexPolyhedron.h
ShapeEllipsoid.h
Expand Down
3 changes: 2 additions & 1 deletion hoomd/hpmc/PairPotential.cc
Expand Up @@ -11,7 +11,8 @@ namespace hoomd::hpmc::detail
void exportPairPotential(pybind11::module& m)
{
pybind11::class_<hpmc::PairPotential, std::shared_ptr<hpmc::PairPotential>>(m, "PairPotential")
.def(pybind11::init<std::shared_ptr<SystemDefinition>>());
.def(pybind11::init<std::shared_ptr<SystemDefinition>>())
.def("setParent", &hpmc::PairPotential::setParent);

pybind11::bind_vector<std::vector<std::shared_ptr<PairPotential>>>(m, "PairPotentialList");
}
Expand Down
105 changes: 70 additions & 35 deletions hoomd/hpmc/PairPotential.h
Expand Up @@ -33,8 +33,19 @@ namespace hpmc

Of the two, the additive r_cut provides better performance when particle types have different
sizes. The non-additive r_cut allows more freedom to implement models. Subclasses can use
one of the two or both at the same time. r_cut_additive and r_cut_non_additive default to all
0's - subclasses must call setRCutNonAdditive and/or setRCutAdditive to update the arrays.
one of the two or both at the same time.

A PairPotential may be compose another PairPotential (e.g. angular patches modulating a square
joaander marked this conversation as resolved.
Show resolved Hide resolved
well). Each PairPotential maintains a weak pointer to its parent. Only the r_cut of the top most
parent is considered by IntegratorHPMC when computing interactions. Each PairPotential subclass
should override the default computeRCutNonAdditive and computeRCutAdditive methods as needed
to compute the various r_cut values as a function of parameters and child potentials. The base
implementations return 0.

The top level potential maintains cached values of the total and maximum r_cut values.
Subclasses must call notifyRCutChanged whenever they would change the value of their computed
r_cut values. The cached values ensure that we can use non-virtual inlined calls in the
inner loops where the total r_cut values are checked.
*/
class PairPotential
{
Expand Down Expand Up @@ -67,16 +78,31 @@ class PairPotential
}

/// Returns the maximum non-additive r_cut beteween any two types.
inline LongReal getMaxRCutNonAdditive()
inline LongReal getMaxRCutNonAdditive() const
{
return m_max_r_cut_non_additive;
}

/// Set the parent potential
void setParent(std::shared_ptr<PairPotential> parent)
{
m_parent = parent;

if (auto parent = m_parent.lock())
{
parent->notifyRCutChanged();
}
}

/*** Evaluate the energy of the pair interaction

energy is given a pre-computed r_squared as many potentials use this parameter and the
caller has already computed it.

To avoid repeated evaluations of r_square < r_cut_squared, the *caller* must perform the
joaander marked this conversation as resolved.
Show resolved Hide resolved
check before calling energy. Implementations of energy are free to compute non-zero values
beyond r_cut when convenient.

@param r_squared Pre-computed dot(r_ij, r_ij).
@param r_ij Vector pointing from particle i to j.
@param type_i Integer type index of particle i.
Expand All @@ -99,32 +125,34 @@ class PairPotential
return 0;
}

/// Compute the non-additive cuttoff radius
virtual LongReal computeRCutNonAdditive(unsigned int type_i, unsigned int type_j) const
{
return 0;
}

/// Returns the additive part of the cutoff distance for a given type.
virtual LongReal computeRCutAdditive(unsigned int type) const
{
return m_r_cut_additive[type];
}

protected:
/// The system definition.
std::shared_ptr<SystemDefinition> m_sysdef;

/// Indexer to access arrays by pairs of type parameters
Index2D m_type_param_index;

/// Set the non-additive cutoff radius for both i,j and j,i pairs.
void setRCutNonAdditive(unsigned int type_i, unsigned int type_j, LongReal r)
/// Notify all parents that r_cut has changed.
void notifyRCutChanged()
{
m_r_cut_non_additive[m_type_param_index(type_i, type_j)] = r;
m_r_cut_non_additive[m_type_param_index(type_j, type_i)] = r;

updateRCutTotal(type_i, type_j);
updateMaxRCutNonAdditive();
}

/// Set the additive part of the cutoff distance for a given type.
void setRCutAdditive(unsigned int type, LongReal r)
{
m_r_cut_additive[type] = r;

for (unsigned int type_j = 0; type_j < m_sysdef->getParticleData()->getNTypes(); type_j++)
if (auto parent = m_parent.lock())
{
updateRCutTotal(type, type_j);
parent->notifyRCutChanged();
}

updateRCutCache();
}

private:
Expand All @@ -140,31 +168,38 @@ class PairPotential
/// Pre-computed maximum additive r_cut.
LongReal m_max_r_cut_non_additive = 0;

/// Update the pre-computed r_cut_total value.
void updateRCutTotal(unsigned int type_i, unsigned int type_j)
/// Parent potential
std::weak_ptr<PairPotential> m_parent;

/// Update r_cut cache
void updateRCutCache()
{
unsigned int type_pair = m_type_param_index(type_i, type_j);
LongReal r_cut = m_r_cut_non_additive[type_pair]
+ LongReal(0.5) * (m_r_cut_additive[type_i] + m_r_cut_additive[type_j]);
m_r_cut_squared_total[type_pair] = r_cut * r_cut;
const unsigned int n_types = m_sysdef->getParticleData()->getNTypes();

type_pair = m_type_param_index(type_j, type_i);
m_r_cut_squared_total[type_pair] = r_cut * r_cut;
}
for (unsigned int type = 0; type < n_types; type++)
{
m_r_cut_additive[type] = computeRCutAdditive(type);
}

/// Update the pre-computed m_max_r_cut_non_additive value.
void updateMaxRCutNonAdditive()
{
m_max_r_cut_non_additive = 0;
const unsigned int n_types = m_sysdef->getParticleData()->getNTypes();

for (unsigned int type_i = 0; type_i < n_types; type_i++)
{
for (unsigned int type_j = type_i; type_j < n_types; type_j++)
{
unsigned int type_pair = m_type_param_index(type_i, type_j);
LongReal r_cut_non_additive = m_r_cut_non_additive[type_pair];
m_max_r_cut_non_additive = std::max(m_max_r_cut_non_additive, r_cut_non_additive);
LongReal r_cut_ij = computeRCutNonAdditive(type_i, type_j);
m_max_r_cut_non_additive = std::max(m_max_r_cut_non_additive, r_cut_ij);

unsigned int param_index_1 = m_type_param_index(type_i, type_j);
unsigned int param_index_2 = m_type_param_index(type_j, type_i);
m_r_cut_non_additive[param_index_1] = r_cut_ij;
m_r_cut_non_additive[param_index_2] = r_cut_ij;

LongReal r_cut
= m_r_cut_non_additive[param_index_1]
+ LongReal(0.5) * (m_r_cut_additive[type_i] + m_r_cut_additive[type_j]);
m_r_cut_squared_total[param_index_1] = r_cut * r_cut;
m_r_cut_squared_total[param_index_2] = r_cut * r_cut;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion hoomd/hpmc/PairPotentialLennardJones.cc
Expand Up @@ -65,7 +65,7 @@ void PairPotentialLennardJones::setParamsPython(pybind11::tuple typ, pybind11::d
unsigned int param_index_2 = m_type_param_index(type_j, type_i);
m_params[param_index_2] = ParamType(params);

setRCutNonAdditive(type_i, type_j, params["r_cut"].cast<LongReal>());
notifyRCutChanged();
}

pybind11::dict PairPotentialLennardJones::getParamsPython(pybind11::tuple typ)
Expand Down
9 changes: 8 additions & 1 deletion hoomd/hpmc/PairPotentialLennardJones.h
Expand Up @@ -3,7 +3,7 @@

#pragma once

#include "hoomd/hpmc/IntegratorHPMC.h"
#include "PairPotential.h"

namespace hoomd
{
Expand All @@ -29,6 +29,13 @@ class PairPotentialLennardJones : public hpmc::PairPotential
const quat<LongReal>& q_j,
const LongReal charge_j) const;

/// Compute the non-additive cuttoff radius
virtual LongReal computeRCutNonAdditive(unsigned int type_i, unsigned int type_j) const
{
unsigned int param_index = m_type_param_index(type_i, type_j);
return slow::sqrt(m_params[param_index].r_cut_squared);
}

/// Set type pair dependent parameters to the potential.
void setParamsPython(pybind11::tuple typ, pybind11::dict params);

Expand Down