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

Implement new HPMC pair potential framework #1676

Merged
merged 45 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
245a344
First pass at working LJ patch potential.
joaander Dec 11, 2023
54161f1
Run pre-commit.
joaander Dec 12, 2023
4f14cb2
Add framework for multiple PairEnergy evaluators in HPMC.
joaander Dec 12, 2023
bdbd372
Rename to pair potentials.
joaander Dec 12, 2023
192d0ce
Add Python interface to set pair_potentials.
joaander Dec 12, 2023
64f3db8
Rename PatchEnergyLJ to PairEnergyLennardJones and add documentation.
joaander Dec 13, 2023
f7141e3
Run pre-commit.
joaander Dec 13, 2023
5719084
Add unit tests.
joaander Dec 13, 2023
7b4312d
Implement and test XPLOR smoothing.
joaander Dec 13, 2023
94cf3ac
Compute potential energy due to individual pairs.
joaander Dec 13, 2023
2bbaf56
Fix failing build.
joaander Dec 13, 2023
04adbf9
Test on the CPU only.
joaander Dec 13, 2023
de3edcd
Add helper function to compute one pair energy.
joaander Dec 13, 2023
49e5938
Run clang-format.
joaander Dec 13, 2023
15ad2b5
Fix one more use of getPatchEnergy.
joaander Dec 13, 2023
3772fe0
Support pair potentials in UpdaterMuVT.
joaander Dec 13, 2023
0340b8c
Update ComputeSDF.
joaander Dec 13, 2023
15cab6a
Fix r_cut determination for m_patch.
joaander Dec 13, 2023
6707cc0
Fix performance bug.
joaander Dec 14, 2023
bca5c32
Switch to LongReal API for PairPotential.
joaander Dec 14, 2023
9ba71ca
First pass at increasing performance.
joaander Dec 15, 2023
95fdd65
Microoptimization - compute r_squared only once.
joaander Dec 18, 2023
2285be8
Expose additive and non-additive r_cut API to PairPotential subclasses.
joaander Dec 18, 2023
1660342
Run clang-format.
joaander Dec 18, 2023
059370e
Micro optimizations to AABB tree.
joaander Dec 18, 2023
bc83eba
Merge branch 'trunk-minor' into hpmc-pair-lj
joaander Dec 21, 2023
36db294
Fix r_cut evaluation when computing the energy of a specific pair.
joaander Dec 21, 2023
1f3a39b
Update documentation.
joaander Dec 22, 2023
2a004e7
Use appropriate stacklevel options in warnings.warn.
joaander Dec 22, 2023
c47e807
Fix r_on >= r_cut consistency with MD.
joaander Jan 9, 2024
aea402e
Revise documentation.
joaander Jan 10, 2024
fc7a4af
Merge branch 'trunk-minor' into hpmc-pair-lj
joaander Jan 12, 2024
81e8aa7
Apply suggestions from code review
joaander Jan 15, 2024
2f9f9a0
Run pre-commit.
joaander Jan 15, 2024
e9afb58
One class per file.
joaander Jan 15, 2024
fe8293a
Run pre-commit.
joaander Jan 15, 2024
6614b84
Add getMaxRCutNonAdditive to PairPotential.
joaander Jan 16, 2024
971c9a2
Move evaluation of max r_cut and min core diameters outside the main …
joaander Jan 16, 2024
75ae669
Run pre-commit.
joaander Jan 16, 2024
0a11a75
Move mode to a class level attribute.
joaander Jan 16, 2024
43345b6
Remove unneeded assert.
joaander Jan 17, 2024
86565a2
Apply suggestions from code review
joaander Jan 22, 2024
9bfe8d9
Fix flake8 error.
joaander Jan 22, 2024
565d133
Log to correct namespace.
joaander Jan 22, 2024
bc2be18
Run pre-commit.
joaander Jan 22, 2024
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
122 changes: 54 additions & 68 deletions hoomd/AABBTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@ class PYBIND11_EXPORT AABBTree
unsigned int m_root; //!< Index to the root node of the tree
std::vector<unsigned int> m_mapping; //!< Reverse mapping to find node given a particle index

/// Temporary index list used to build the AABB tree.
std::vector<unsigned int> m_idx;

/// Temporary index list used when partitioning nodes.
std::vector<unsigned int> m_idx_right;

/// Temporary index list used when partitioning nodes.
std::vector<AABB> m_aabb_right;

//! Initialize the tree to hold N particles
inline void init(unsigned int N);

Expand Down Expand Up @@ -385,11 +394,12 @@ inline void AABBTree::buildTree(AABB* aabbs, unsigned int N)
{
init(N);

std::vector<unsigned int> idx;
m_idx.clear();
m_idx.reserve(N);
for (unsigned int i = 0; i < N; i++)
idx.push_back(i);
m_idx.push_back(i);

m_root = buildNode(aabbs, idx, 0, N, INVALID_NODE);
m_root = buildNode(aabbs, m_idx, 0, N, INVALID_NODE);
updateSkip(m_root);
}

Expand Down Expand Up @@ -447,8 +457,9 @@ inline unsigned int AABBTree::buildNode(AABB* aabbs,
unsigned int my_idx = allocateNode();

// need to split the list of aabbs into two sets for left and right
unsigned int start_left = 0;
unsigned int start_right = len;
unsigned int left_insert_point = 0;
m_idx_right.clear();
m_aabb_right.clear();

// if there are only 2 aabbs, put one on each side
if (len == 2)
Expand All @@ -457,81 +468,57 @@ inline unsigned int AABBTree::buildNode(AABB* aabbs,
}
else
{
// otherwise, we need to split them based on a heuristic. split the longest dimension in
// half
if (my_radius.x > my_radius.y && my_radius.x > my_radius.z)
// Otherwise, we need to split them based on a heuristic. Split the longest dimension in
// half. Use a stable partition to keep particles in index order.

for (unsigned int i = 0; i < len; i++)
{
// split on x direction
for (unsigned int i = 0; i < start_right; i++)
bool on_left = false;
if (my_radius.x > my_radius.y && my_radius.x > my_radius.z)
{
if (aabbs[start + i].getPosition().x < my_aabb.getPosition().x)
{
// if on the left side, everything is happy, just continue on
}
else
{
// if on the right side, need to swap the current aabb with the one at
// start_right-1, subtract one off of start_right to indicate the addition of
// one to the right side and subtract 1 from i to look at the current index (new
// aabb). This is quick and easy to write, but will randomize indices - might
// need to look into a stable partitioning algorithm!
std::swap(aabbs[start + i], aabbs[start + start_right - 1]);
std::swap(idx[start + i], idx[start + start_right - 1]);
start_right--;
i--;
}
// split on x direction
on_left = aabbs[start + i].getPosition().x < my_aabb.getPosition().x;
}
}
else if (my_radius.y > my_radius.z)
{
// split on y direction
for (unsigned int i = 0; i < start_right; i++)
else if (my_radius.y > my_radius.z)
{
if (aabbs[start + i].getPosition().y < my_aabb.getPosition().y)
{
// if on the left side, everything is happy, just continue on
}
else
{
// if on the right side, need to swap the current aabb with the one at
// start_right-1, subtract one off of start_right to indicate the addition of
// one to the right side and subtract 1 from i to look at the current index (new
// aabb). This is quick and easy to write, but will randomize indices - might
// need to look into a stable partitioning algorithm!
std::swap(aabbs[start + i], aabbs[start + start_right - 1]);
std::swap(idx[start + i], idx[start + start_right - 1]);
start_right--;
i--;
}
// split on y direction
on_left = aabbs[start + i].getPosition().y < my_aabb.getPosition().y;
}
}
else
{
// split on z direction
for (unsigned int i = 0; i < start_right; i++)
else
{
if (aabbs[start + i].getPosition().z < my_aabb.getPosition().z)
{
// if on the left side, everything is happy, just continue on
}
else
// split on z direction
on_left = aabbs[start + i].getPosition().z < my_aabb.getPosition().z;
}

if (on_left)
{
if (left_insert_point != i)
{
// if on the right side, need to swap the current aabb with the one at
// start_right-1, subtract one off of start_right to indicate the addition of
// one to the right side and subtract 1 from i to look at the current index (new
// aabb). This is quick and easy to write, but will randomize indices - might
// need to look into a stable partitioning algorithm!
std::swap(aabbs[start + i], aabbs[start + start_right - 1]);
std::swap(idx[start + i], idx[start + start_right - 1]);
start_right--;
i--;
// Set the AABB and index at the insert point.
aabbs[start + left_insert_point] = aabbs[start + i];
idx[start + left_insert_point] = idx[start + i];
}
left_insert_point++;
}
else
{
// Add the right side AABBs to a temporary list.
m_aabb_right.push_back(aabbs[start + i]);
m_idx_right.push_back(idx[start + i]);
}
}

assert(m_aabb_right.size() == m_idx_right.size());
assert(left_insert_point + m_aabb_right.size() == len);

// Copy the right AABBs back into the list.
std::copy(m_aabb_right.begin(), m_aabb_right.end(), aabbs + start + left_insert_point);
std::copy(m_idx_right.begin(), m_idx_right.end(), idx.begin() + start + left_insert_point);
}

// sanity check. The left or right tree may have ended up empty. If so, just borrow one particle
// from it
unsigned int start_right = left_insert_point;
if (start_right == len)
start_right = len - 1;
if (start_right == 0)
Expand All @@ -540,8 +527,7 @@ inline unsigned int AABBTree::buildNode(AABB* aabbs,
// note: calling buildNode has side effects, the m_nodes array may be reallocated. So we need to
// determine the left and right children, then build our node (can't say m_nodes[my_idx].left =
// buildNode(...))
unsigned int new_left
= buildNode(aabbs, idx, start + start_left, start_right - start_left, my_idx);
unsigned int new_left = buildNode(aabbs, idx, start, start_right, my_idx);
unsigned int new_right = buildNode(aabbs, idx, start + start_right, len - start_right, my_idx);

// now, create the children and connect them up
Expand Down
4 changes: 4 additions & 0 deletions hoomd/hpmc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ set(_hpmc_sources module.cc
module_convex_polyhedron.cc
module_convex_spheropolyhedron.cc
ExternalFieldWall.cc
PairPotential.cc
PairPotentialLennardJones.cc
ShapeUtils.cc
UpdaterBoxMC.cc
UpdaterQuickCompress.cc
Expand Down Expand Up @@ -74,6 +76,8 @@ set(_hpmc_headers
Moves.h
OBB.h
OBBTree.h
PairPotential.h
PairPotentialLennardJones.h
ShapeConvexPolygon.h
ShapeConvexPolyhedron.h
ShapeEllipsoid.h
Expand Down
Loading