From 246f27e339707c808ef7db8130817d7192e763df Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 10 Mar 2025 16:23:57 -0400 Subject: [PATCH 01/58] update MeshBonds --- hoomd/MeshGroupData.cc | 185 +++++++++++++---------------------------- 1 file changed, 59 insertions(+), 126 deletions(-) diff --git a/hoomd/MeshGroupData.cc b/hoomd/MeshGroupData.cc index 706ffb012b..8cc99df1bc 100644 --- a/hoomd/MeshGroupData.cc +++ b/hoomd/MeshGroupData.cc @@ -123,131 +123,64 @@ void MeshGroupData::initializeFromTriangleSnapsho std::vector all_types; - if (group_size == 4) - { - for (unsigned group_idx = 0; group_idx < snapshot.groups.size(); group_idx++) - { - std::vector triag_tag(3); - std::vector::members_t> bonds( - 3); - triag_tag[0] = snapshot.groups[group_idx].tag[0]; - triag_tag[1] = snapshot.groups[group_idx].tag[1]; - triag_tag[2] = snapshot.groups[group_idx].tag[2]; - - bonds[0].tag[0] = triag_tag[0]; - bonds[0].tag[1] = triag_tag[1]; - bonds[0].tag[2] = triag_tag[2]; - bonds[0].tag[3] = triag_tag[2]; - - bonds[1].tag[0] = triag_tag[1]; - bonds[1].tag[1] = triag_tag[2]; - bonds[1].tag[2] = triag_tag[0]; - bonds[1].tag[3] = triag_tag[0]; - - bonds[2].tag[0] = triag_tag[2]; - bonds[2].tag[1] = triag_tag[0]; - bonds[2].tag[2] = triag_tag[1]; - bonds[2].tag[3] = triag_tag[1]; - - for (unsigned int j = 0; j < bonds.size(); ++j) - { - if (bonds[j].tag[0] > bonds[j].tag[1]) - { - unsigned int bonds0 = bonds[j].tag[0]; - unsigned int bonds1 = bonds[j].tag[1]; - - bonds[j].tag[0] = bonds1; - bonds[j].tag[1] = bonds0; - } - } - - // Remove any duplicate bonds. - for (unsigned int i = 0; i < all_helper.size(); ++i) - { - for (unsigned int j = 0; j < bonds.size(); ++j) - { - if (bonds[j].tag[0] == all_helper[i].tag[0] - && bonds[j].tag[1] == all_helper[i].tag[1]) - { - // all_helper[i].tag[3] = group_idx; - all_helper[i].tag[3] = bonds[j].tag[2]; - bonds.erase(bonds.begin() + j); - break; - } - } - } - for (unsigned int i = 0; i < bonds.size(); ++i) - { - all_helper.push_back(bonds[i]); - all_types.push_back(snapshot.type_id[group_idx]); - } - } - all_groups = all_helper; - } - else // this part will be important later for dynamical bonding - { - all_groups.resize(snapshot.groups.size()); - all_types.resize(snapshot.groups.size()); - for (unsigned group_idx = 0; group_idx < snapshot.groups.size(); group_idx++) - { - typename BondedGroupData::members_t triag; - std::vector::members_t> bonds( - 3); - unsigned int bonds0, bonds1; - std::vector bond_id; - triag.tag[0] = snapshot.groups[group_idx].tag[0]; - triag.tag[1] = snapshot.groups[group_idx].tag[1]; - triag.tag[2] = snapshot.groups[group_idx].tag[2]; - - bonds[0].tag[0] = triag.tag[0]; - bonds[0].tag[1] = triag.tag[1]; - bonds[0].tag[2] = triag.tag[2]; - bonds[1].tag[0] = triag.tag[1]; - bonds[1].tag[1] = triag.tag[2]; - bonds[1].tag[2] = triag.tag[0]; - bonds[2].tag[0] = triag.tag[2]; - bonds[2].tag[1] = triag.tag[0]; - bonds[2].tag[2] = triag.tag[1]; - - for (unsigned int i = 0; i < all_helper.size(); ++i) - { - for (unsigned int j = 0; j < bonds.size(); ++j) - { - if (bonds[j].tag[0] > bonds[j].tag[1]) - { - bonds0 = bonds[j].tag[0]; - bonds1 = bonds[j].tag[1]; - - bonds[j].tag[0] = bonds1; - bonds[j].tag[1] = bonds0; - } - if (bonds[j].tag[0] == all_helper[i].tag[0] - && bonds[j].tag[1] == all_helper[i].tag[1]) - { - // bond_id.push_back(i); - bond_id.push_back(all_helper[i].tag[2]); - bonds.erase(bonds.begin() + j); - break; - } - } - } - unsigned int j = 0; - for (j = 0; j < bond_id.size(); ++j) - { - triag.tag[3 + j] = bond_id[j]; - } - - for (unsigned int i = 0; i < bonds.size(); ++i) - { - // triag.tag[3 + j] = static_cast(all_helper.size()); - triag.tag[3 + j] = bonds[i].tag[2]; - all_helper.push_back(bonds[i]); - j++; - } - all_groups[group_idx] = triag; - all_types[group_idx] = snapshot.type_id[group_idx]; - } - } + for (unsigned group_idx = 0; group_idx < snapshot.groups.size(); group_idx++) + { + std::vector triag_tag(3); + std::vector::members_t> bonds( + 3); + triag_tag[0] = snapshot.groups[group_idx].tag[0]; + triag_tag[1] = snapshot.groups[group_idx].tag[1]; + triag_tag[2] = snapshot.groups[group_idx].tag[2]; + + bonds[0].tag[0] = triag_tag[0]; + bonds[0].tag[1] = triag_tag[1]; + bonds[0].tag[2] = triag_tag[2]; + bonds[0].tag[3] = triag_tag[2]; + + bonds[1].tag[0] = triag_tag[1]; + bonds[1].tag[1] = triag_tag[2]; + bonds[1].tag[2] = triag_tag[0]; + bonds[1].tag[3] = triag_tag[0]; + + bonds[2].tag[0] = triag_tag[2]; + bonds[2].tag[1] = triag_tag[0]; + bonds[2].tag[2] = triag_tag[1]; + bonds[2].tag[3] = triag_tag[1]; + + for (unsigned int j = 0; j < bonds.size(); ++j) + { + if (bonds[j].tag[0] > bonds[j].tag[1]) + { + unsigned int bonds0 = bonds[j].tag[0]; + unsigned int bonds1 = bonds[j].tag[1]; + + bonds[j].tag[0] = bonds1; + bonds[j].tag[1] = bonds0; + } + } + + // Remove any duplicate bonds. + for (unsigned int i = 0; i < all_helper.size(); ++i) + { + for (unsigned int j = 0; j < bonds.size(); ++j) + { + if (bonds[j].tag[0] == all_helper[i].tag[0] + && bonds[j].tag[1] == all_helper[i].tag[1]) + { + // all_helper[i].tag[3] = group_idx; + all_helper[i].tag[3] = bonds[j].tag[2]; + bonds.erase(bonds.begin() + j); + break; + } + } + } + for (unsigned int i = 0; i < bonds.size(); ++i) + { + all_helper.push_back(bonds[i]); + all_types.push_back(snapshot.type_id[group_idx]); + } + } + all_groups = all_helper; #ifdef ENABLE_MPI if (this->m_pdata->getDomainDecomposition()) @@ -302,7 +235,7 @@ unsigned int MeshGroupData::addBondedGroup(Group unsigned int group_size_half = group_size / 2; // validate user input - for (unsigned int i = 0; i < group_size_half; ++i) + for (unsigned int i = 0; i < group_size; ++i) { if (members_tags.tag[i] > max_tag) { From d5304be154dd1cf27925f25bfe7d3dcf91ba8b50 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 11 Mar 2025 17:20:04 -0400 Subject: [PATCH 02/58] remove group_size_half --- hoomd/MeshGroupData.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hoomd/MeshGroupData.cc b/hoomd/MeshGroupData.cc index 8cc99df1bc..b055be9915 100644 --- a/hoomd/MeshGroupData.cc +++ b/hoomd/MeshGroupData.cc @@ -233,7 +233,6 @@ unsigned int MeshGroupData::addBondedGroup(Group unsigned int max_tag = this->m_pdata->getMaximumTag(); - unsigned int group_size_half = group_size / 2; // validate user input for (unsigned int i = 0; i < group_size; ++i) { @@ -247,7 +246,7 @@ unsigned int MeshGroupData::addBondedGroup(Group throw runtime_error(oss.str()); } - for (unsigned int j = 0; j < group_size_half; ++j) + for (unsigned int j = 0; j < 2; ++j) { if (i != j && members_tags.tag[i] == members_tags.tag[j]) { @@ -364,8 +363,6 @@ MeshGroupData::takeSnapshot(snap& snapshot) const // map to lookup snapshot index by tag std::map index; - unsigned int group_size_half = group_size / 2; - std::map rtag_map; for (unsigned int group_idx = 0; group_idx < this->getN(); group_idx++) @@ -454,7 +451,7 @@ MeshGroupData::takeSnapshot(snap& snapshot) const unsigned int idx = rank_idx.second; snapshot.type_id[snap_id] = typevals_proc[rank][idx].type; - for (unsigned int i = 0; i < group_size_half; i++) + for (unsigned int i = 0; i < 2; i++) { snapshot.groups[snap_id].tag[i] = members_proc[rank][idx].tag[i]; } @@ -493,7 +490,7 @@ MeshGroupData::takeSnapshot(snap& snapshot) const unsigned int group_idx = rtag_it->second; typename BondedGroupData::members_t member = this->m_groups[group_idx]; - for (unsigned int i = 0; i < group_size_half; i++) + for (unsigned int i = 0; i < 2; i++) { snapshot.groups[snap_id].tag[i] = member.tag[i]; } From 306cb3f5197a77ea273056148f4652ced4e9e92d Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 12 Mar 2025 16:37:10 -0400 Subject: [PATCH 03/58] creat neighbor lists --- hoomd/MeshDefinition.cc | 93 +++++++++++++++++++++++++++++++++++++++++ hoomd/MeshDefinition.h | 15 +++++++ hoomd/MeshGroupData.cc | 2 - 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/hoomd/MeshDefinition.cc b/hoomd/MeshDefinition.cc index fafd44bfa5..ae169416d7 100644 --- a/hoomd/MeshDefinition.cc +++ b/hoomd/MeshDefinition.cc @@ -131,6 +131,16 @@ void MeshDefinition::setTriangulationData(pybind11::dict triangulation) m_meshbond_data = std::shared_ptr( new MeshBondData(m_sysdef->getParticleData(), triangle_data)); + GPUArray neigh_to_triag(len_triang, m_sysdef->getParticleData()->getExecConf()); + m_neigh_to_triag.swap(neigh_to_triag); + + unsigned int len_bond = m_meshbond_data->getNGlobal(); + GPUArray neigh_to_bond(len_bond, m_sysdef->getParticleData()->getExecConf()); + m_neigh_to_bond.swap(neigh_to_bond); + + createMeshNeighborhood(); + + #ifdef ENABLE_MPI if (m_sysdef->isDomainDecomposed()) { @@ -144,6 +154,89 @@ void MeshDefinition::setTriangulationData(pybind11::dict triangulation) #endif } +void MeshDefinition::createMeshNeighborhood() + { + ArrayHandle h_neigh_to_bond(m_neigh_to_bond, access_location::host, access_mode::overwrite); + + ArrayHandle h_neigh_to_triag(m_neigh_to_triag, access_location::host, access_mode::overwrite); + + ArrayHandle h_bonds( + m_meshbond_data->getMembersArray(), + access_location::host, + access_mode::read); + + ArrayHandle h_triangles( + m_meshtriangle_data->getMembersArray(), + access_location::host, + access_mode::read); + + std::vector bonds(3); + + unsigned int bond_length = m_meshbond_data->getNGlobal(); + + for (unsigned int j = 0; j < bond_length; ++j) + { + h_neigh_to_bond.data[j] = make_uint2(bond_length,bond_length); + } + + for (unsigned int i = 0; i < m_meshtriangle_data->getNGlobal(); i++) + { + const typename Angle::members_t& triangle = h_triangles.data[i]; + + if(triangle.tag[0] < triangle.tag[1]) + bonds[0] = make_uint2(triangle.tag[0],triangle.tag[1]); + else + bonds[0] = make_uint2(triangle.tag[1],triangle.tag[0]); + + if(triangle.tag[1] < triangle.tag[2]) + bonds[1] = make_uint2(triangle.tag[1],triangle.tag[2]); + else + bonds[1] = make_uint2(triangle.tag[2],triangle.tag[1]); + + if(triangle.tag[0] < triangle.tag[2]) + bonds[2] = make_uint2(triangle.tag[0],triangle.tag[2]); + else + bonds[2] = make_uint2(triangle.tag[2],triangle.tag[0]); + + unsigned int counter = 0; + std::vector t_idx; + std::vector b_done(bond_length); + + for (unsigned int j = 0; j < bond_length; ++j) + b_done[j]=false; + + for (unsigned int j = 0; j < bond_length; ++j) + { + if( b_done[j]) + continue; + + const typename MeshBond::members_t& meshbond = h_bonds.data[j]; + for (unsigned int k = 0; k < bonds.size(); ++k) + { + if (bonds[k].x == meshbond.tag[0] + && bonds[k].y == meshbond.tag[1]) + { + t_idx.push_back(j); + h_neigh_to_bond.data[j].y = i; + if(h_neigh_to_bond.data[j].x != bond_length) + b_done[j] = true; + else + h_neigh_to_bond.data[j].x = i; + counter++; + break; + } + } + if( counter == 3) + { + h_neigh_to_triag.data[i].x = t_idx[0]; + h_neigh_to_triag.data[i].y = t_idx[1]; + h_neigh_to_triag.data[i].z = t_idx[2]; + break; + } + } + } + } + namespace detail { void export_MeshDefinition(pybind11::module& m) diff --git a/hoomd/MeshDefinition.h b/hoomd/MeshDefinition.h index b76ffa3f21..c455f3be2a 100644 --- a/hoomd/MeshDefinition.h +++ b/hoomd/MeshDefinition.h @@ -90,6 +90,16 @@ class PYBIND11_EXPORT MeshDefinition return m_globalN; } + const GPUArray& getNeighToBond() const + { + return m_neigh_to_bond; + } + + const GPUArray& getNeighToTriag() const + { + return m_neigh_to_triag; + } + void setTypes(pybind11::list types); BondData::Snapshot getBondData(); @@ -100,12 +110,17 @@ class PYBIND11_EXPORT MeshDefinition void setTriangulationData(pybind11::dict triangulation); + void createMeshNeighborhood(); + private: GPUArray m_globalN; std::shared_ptr m_sysdef; //!< System definition later needed for dynamic bonding std::shared_ptr m_meshbond_data; //!< Bond data for the mesh std::shared_ptr m_meshtriangle_data; //!< Triangle data for the mesh + // + GPUArray m_neigh_to_bond; //!< triangle ids corresponding to bond + GPUArray m_neigh_to_triag; //!< bond ids corresponding to triangle }; namespace detail diff --git a/hoomd/MeshGroupData.cc b/hoomd/MeshGroupData.cc index b055be9915..4b123a5605 100644 --- a/hoomd/MeshGroupData.cc +++ b/hoomd/MeshGroupData.cc @@ -14,7 +14,6 @@ #ifdef ENABLE_HIP #include "CachedAllocator.h" -// #include "MeshGroupData.cuh" #endif using namespace std; @@ -167,7 +166,6 @@ void MeshGroupData::initializeFromTriangleSnapsho if (bonds[j].tag[0] == all_helper[i].tag[0] && bonds[j].tag[1] == all_helper[i].tag[1]) { - // all_helper[i].tag[3] = group_idx; all_helper[i].tag[3] = bonds[j].tag[2]; bonds.erase(bonds.begin() + j); break; From c5be9bdc5d29dbb0fbb7cbbea9fab769099efcbb Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 12 Mar 2025 17:01:53 -0400 Subject: [PATCH 04/58] first backbone of MeshUpdater --- hoomd/md/MeshDynamicBondUpdater.cc | 460 +++++++++++++++++++++++++++++ hoomd/md/MeshDynamicBondUpdater.h | 84 ++++++ 2 files changed, 544 insertions(+) create mode 100644 hoomd/md/MeshDynamicBondUpdater.cc create mode 100644 hoomd/md/MeshDynamicBondUpdater.h diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc new file mode 100644 index 0000000000..36a5ce2b6d --- /dev/null +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -0,0 +1,460 @@ +// Copyright (c) 2009-2022 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +/*! \file MeshDynamicBondUpdater.cc + \brief Defines the MeshDynamicBondUpdater class +*/ + +#include "MeshDynamicBondUpdater.h" +#include "hoomd/RNGIdentifiers.h" +#include "hoomd/RandomNumbers.h" + +#include + +using namespace std; + +namespace hoomd + { +namespace md + { +/*! \param sysdef System definition + * \param rotational_diffusion The diffusion across time + * \param group the particles to diffusion rotation on + */ + +MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr sysdef, + std::shared_ptr trigger, + std::shared_ptr integrator, + std::shared_ptr mesh, + Scalar T) + : Updater(sysdef, trigger), m_integrator(integrator), m_mesh(mesh), m_inv_T(1.0 / T) + { + GlobalVector tmp_allowSwitch(m_pdata->getNTypes(), m_exec_conf); + + m_allowSwitch.swap(tmp_allowSwitch); + TAG_ALLOCATION(m_allowSwitch); + + ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::overwrite); + + for (unsigned int i = 0; i < m_allowSwitch.size(); i++) + h_allowSwitch.data[i] = true; + + assert(m_pdata); + assert(m_integrator); + assert(m_mesh); + m_exec_conf->msg->notice(5) << "Constructing MeshDynamicBondUpdater" << endl; + } + +MeshDynamicBondUpdater::~MeshDynamicBondUpdater() + { + m_exec_conf->msg->notice(5) << "Destroying MeshDynamicBondUpdater" << endl; + } + +void MeshDynamicBondUpdater::setAllowSwitch(const std::string& type_name, pybind11::bool_ v) + { + unsigned int typ = this->m_pdata->getTypeByName(type_name); + + // check for user errors + if (typ >= m_pdata->getNTypes()) + { + throw std::invalid_argument("Type does not exist"); + } + + bool allowSwitch = pybind11::cast(v); + + ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::readwrite); + h_allowSwitch.data[typ] = allowSwitch; + } + +pybind11::bool_ MeshDynamicBondUpdater::getAllowSwitch(const std::string& type_name) + { + unsigned int typ = this->m_pdata->getTypeByName(type_name); + + ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::read); + + bool allowSwitch = h_allowSwitch.data[typ]; + return pybind11::bool_(allowSwitch); + } + +/** Perform the needed calculations to update particle orientations + \param timestep Current time step of the simulation +*/ +void MeshDynamicBondUpdater::update(uint64_t timestep) + { + std::vector> forces = m_integrator->getForces(); + + uint16_t seed = m_sysdef->getSeed(); + + for (auto& force : forces) + { + force->precomputeParameter(); + } + + ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), + access_location::host, + access_mode::readwrite); + ArrayHandle h_triangles( + m_mesh->getMeshTriangleData()->getMembersArray(), + access_location::host, + access_mode::readwrite); + + ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); + + ArrayHandle h_typeval(m_mesh->getMeshBondData()->getTypeValArray(), + access_location::host, + access_mode::read); + + ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::read); + + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + + // for each of the angles + const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); + + bool changeDetected = false; + + std::vector changed; + + for (unsigned int i = 0; i < size; i++) + { + const typename MeshBond::members_t& bond = h_bonds.data[i]; + assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); + assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); + + // transform a and b into indices into the particle data arrays + // (MEM TRANSFER: 4 integers) + unsigned int tag_a = bond.tag[0]; + unsigned int tag_b = bond.tag[1]; + + unsigned int idx_a = h_rtag.data[tag_a]; + unsigned int idx_b = h_rtag.data[tag_b]; + + unsigned int type_a = __scalar_as_int(h_pos.data[idx_a].w); + unsigned int type_b = __scalar_as_int(h_pos.data[idx_b].w); + + bool allow_a = h_allowSwitch.data[type_a]; + bool allow_b = h_allowSwitch.data[type_b]; + + if (!allow_a && !allow_b) + continue; + + bool already_used = false; + for (unsigned int j = 0; j < changed.size(); j++) + { + if (tag_a == changed[j] || tag_b == changed[j]) + { + already_used = true; + break; + } + } + + if (already_used) + continue; + + unsigned int tr_idx1 = bond.tag[2]; + unsigned int tr_idx2 = bond.tag[3]; + + if (tr_idx1 == tr_idx2) + continue; + + const typename MeshTriangle::members_t& triangle1 = h_triangles.data[tr_idx1]; + const typename MeshTriangle::members_t& triangle2 = h_triangles.data[tr_idx2]; + + unsigned int iterator = 0; + + bool a_before_b = true; + + while (idx_b == h_rtag.data[triangle1.tag[iterator]]) + iterator++; + + iterator = (iterator + 1) % 3; + + if (idx_a == h_rtag.data[triangle1.tag[iterator]]) + a_before_b = false; + + unsigned int tag_c = triangle1.tag[0]; + unsigned int idx_c = h_rtag.data[tag_c]; + + iterator = 0; + while (idx_a == idx_c || idx_b == idx_c) + { + iterator++; + tag_c = triangle1.tag[iterator]; + idx_c = h_rtag.data[tag_c]; + } + + unsigned int tag_d = triangle2.tag[0]; + unsigned int idx_d = h_rtag.data[tag_d]; + + iterator = 0; + while (idx_a == idx_d || idx_b == idx_d) + { + iterator++; + tag_d = triangle2.tag[iterator]; + idx_d = h_rtag.data[tag_d]; + } + + for (unsigned int j = 0; j < changed.size(); j++) + { + if (tag_c == changed[j] || tag_d == changed[j]) + { + already_used = true; + break; + } + } + + if (already_used) + continue; + + unsigned int type_id = h_typeval.data[i].type; + + Scalar energyDifference = 0; + + unsigned int idx_cc = idx_d; + unsigned int idx_dd = idx_c; + + if (a_before_b) + { + idx_cc = idx_c; + idx_dd = idx_d; + } + + bool have_to_check_surrounding = false; + for (auto& force : forces) + { + energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); + + if(force->checkSurrounding()) + have_to_check_surrounding = true; + } + + if(have_to_check_surrounding) + { + unsigned int idx_1, idx_2, idx_3, idx_4, idx_5; + for( int bo_i = 3; bo_i < 6; bo_i++) + { + unsigned int new_bo = triangle1.tag[bo_i]; + if( new_bo == i) continue; + const typename MeshBond::members_t& bond1 = h_bonds.data[new_bo]; + + idx_1 = h_rtag.data[bond1.tag[0]]; + idx_2 = h_rtag.data[bond1.tag[1]]; + + for( int tr_i = 2; tr_i < 4; tr_i++) + { + if(bond1.tag[tr_i] == tr_idx1) continue; + + const typename MeshTriangle::members_t& triangle1 = h_triangles.data[bond1.tag[tr_i]]; + for( int idx_i = 0; idx_i < 3; idx_i++) + { + if( triangle1.tag[idx_i] != bond1.tag[0] && triangle1.tag[idx_i] != bond1.tag[1] ) + { + idx_3 = h_rtag.data[triangle1.tag[idx_i]]; + break; + } + } + break; + } + + idx_4 = idx_a; + if(idx_1 == idx_4 || idx_2 == idx_4) idx_4 = idx_b; + idx_5 = idx_d; + + for (auto& force : forces) + energyDifference += force->energyDiffSurrounding(idx_1, idx_2, idx_3, idx_4, idx_5, type_id); + + } + + for( int bo_i = 3; bo_i < 6; bo_i++) + { + unsigned int new_bo = triangle2.tag[bo_i]; + if( new_bo == i) continue; + const typename MeshBond::members_t& bond1 = h_bonds.data[new_bo]; + + idx_1 = h_rtag.data[bond1.tag[0]]; + idx_2 = h_rtag.data[bond1.tag[1]]; + + for( int tr_i = 2; tr_i < 4; tr_i++) + { + if(bond1.tag[tr_i] == tr_idx2) continue; + + const typename MeshTriangle::members_t& triangle2 = h_triangles.data[bond1.tag[tr_i]]; + for( int idx_i = 0; idx_i < 3; idx_i++) + { + if( triangle2.tag[idx_i] != bond1.tag[0] && triangle2.tag[idx_i] != bond1.tag[1] ) + { + idx_3 = h_rtag.data[triangle2.tag[idx_i]]; + break; + } + } + break; + } + + idx_4 = idx_a; + if(idx_1 == idx_4 || idx_2 == idx_4) idx_4 = idx_b; + idx_5 = idx_c; + + for (auto& force : forces) + energyDifference += force->energyDiffSurrounding(idx_1, idx_2, idx_3, idx_4, idx_5, type_id); + + } + } + + // Initialize the RNG + RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), + hoomd::Counter(i)); + + // compute the random force + UniformDistribution uniform(0, Scalar(1)); + + if (exp(-m_inv_T * energyDifference) > uniform(rng)) + { + changeDetected = true; + + changed.push_back(tag_a); + changed.push_back(tag_b); + changed.push_back(tag_c); + changed.push_back(tag_d); + + typename MeshBond::members_t bond_n; + typename MeshTriangle::members_t triangle1_n; + typename MeshTriangle::members_t triangle2_n; + + bond_n.tag[0] = tag_c; + bond_n.tag[1] = tag_d; + bond_n.tag[2] = tr_idx1; + bond_n.tag[3] = tr_idx2; + + h_bonds.data[i] = bond_n; + + bool needs_flipping = true; + + if (iterator < 2) + { + if (triangle2.tag[iterator + 1] == tag_a) + needs_flipping = false; + } + else + { + if (triangle2.tag[0] == tag_a) + needs_flipping = false; + } + + triangle1_n.tag[0] = tag_a; + triangle2_n.tag[0] = tag_b; + + if (needs_flipping) + { + triangle1_n.tag[2] = tag_c; + triangle1_n.tag[1] = tag_d; + triangle2_n.tag[2] = tag_d; + triangle2_n.tag[1] = tag_c; + } + else + { + triangle1_n.tag[1] = tag_c; + triangle1_n.tag[2] = tag_d; + triangle2_n.tag[1] = tag_d; + triangle2_n.tag[2] = tag_c; + } + + for (int j = 3; j < 6; j++) + { + int k = triangle1.tag[j]; + if (k != i) + { + typename MeshBond::members_t& bond_s = h_bonds.data[k]; + + unsigned int tr_idx; + if (bond_s.tag[0] == tag_a || bond_s.tag[1] == tag_a) + { + tr_idx = tr_idx1; + triangle1_n.tag[3] = k; + } + else + { + tr_idx = tr_idx2; + triangle2_n.tag[3] = k; + } + + if (bond_s.tag[2] == tr_idx1 || bond_s.tag[2] == tr_idx2) + bond_s.tag[2] = tr_idx; + else + bond_s.tag[3] = tr_idx; + h_bonds.data[k] = bond_s; + } + k = triangle2.tag[j]; + if (k != i) + { + typename MeshBond::members_t& bond_s = h_bonds.data[k]; + + unsigned int tr_idx; + if (bond_s.tag[0] == tag_a || bond_s.tag[1] == tag_a) + { + tr_idx = tr_idx1; + triangle1_n.tag[4] = k; + } + else + { + tr_idx = tr_idx2; + triangle2_n.tag[4] = k; + } + + if (bond_s.tag[2] == tr_idx1 || bond_s.tag[2] == tr_idx2) + bond_s.tag[2] = tr_idx; + else + bond_s.tag[3] = tr_idx; + h_bonds.data[k] = bond_s; + } + } + + triangle1_n.tag[5] = i; + triangle2_n.tag[5] = i; + + h_triangles.data[tr_idx1] = triangle1_n; + h_triangles.data[tr_idx2] = triangle2_n; + + if (a_before_b) + { + for (auto& force : forces) + { + force->postcompute(idx_a, idx_b, idx_c, idx_d); + } + } + else + { + for (auto& force : forces) + { + force->postcompute(idx_a, idx_b, idx_d, idx_c); + } + } + } + } + + if (changeDetected) + { + m_mesh->getMeshBondData()->meshChanged(); + m_mesh->getMeshTriangleData()->meshChanged(); + } + } + +namespace detail + { +void export_MeshDynamicBondUpdater(pybind11::module& m) + { + pybind11::class_>( + m, + "MeshDynamicBondUpdater") + .def(pybind11::init, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + Scalar>()) + .def("setAllowSwitch", &MeshDynamicBondUpdater::setAllowSwitch) + .def("getAllowSwitch", &MeshDynamicBondUpdater::getAllowSwitch) + .def_property("kT", &MeshDynamicBondUpdater::getT, &MeshDynamicBondUpdater::setT); + } + + } // end namespace detail + } // end namespace md + } // end namespace hoomd diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h new file mode 100644 index 0000000000..5c6e7b0f3b --- /dev/null +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -0,0 +1,84 @@ +// Copyright (c) 2009-2022 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +/*! \file ActiveRotationalDiffusionUpdater.h + \brief Declares an updater that actively diffuses particle orientations +*/ + +#ifdef __HIPCC__ +#error This header cannot be compiled by nvcc +#endif + +#include "hoomd/ForceCompute.h" +#include "hoomd/Integrator.h" +#include "hoomd/MeshDefinition.h" +#include "hoomd/Updater.h" +#include "hoomd/Variant.h" + +#include +#include + +#pragma once + +namespace hoomd + { +namespace md + { +/// Updates particle's orientations based on a given diffusion constant. +/** The updater accepts a variant rotational diffusion and updates the particle orientations of the + * associated ActiveForceCompute's group (by calling m_active_force.rotationalDiffusion). + * + * Note: This was originally part of the ActiveForceCompute, and is separated to obey the idea that + * force computes do not update the system directly, but updaters do. See GitHub issue (898). The + * updater is just a shell that calls through to m_active_force due to the complexities of the logic + * with the introduction of manifolds. + * + * If anyone has the time to do so, the implementation would be cleaner if moved to this updater. + */ +class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater + { + public: + /// Constructor + MeshDynamicBondUpdater(std::shared_ptr sysdef, + std::shared_ptr trigger, + std::shared_ptr integrator, + std::shared_ptr mesh, + Scalar T); + + /// Destructor + virtual ~MeshDynamicBondUpdater(); + + void setAllowSwitch(const std::string& type_name, pybind11::bool_ v); + + /// Gets active torque vector for a given particle type + pybind11::bool_ getAllowSwitch(const std::string& type_name); + + /// Update box interpolation based on provided timestep + virtual void update(uint64_t timestep); + + Scalar getT() + { + return 1.0 / m_inv_T; + }; + + void setT(Scalar T) + { + m_inv_T = 1.0 / T; + }; + + private: + std::shared_ptr m_integrator; //!< Integrator that advances time in this System + std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on + Scalar m_inv_T; + GlobalVector m_allowSwitch; //! check if bond wich features two particles of certain + //! particle types is allow to switch + }; + +namespace detail + { +/// Export the ActiveRotationalDiffusionUpdater to python +void export_MeshDynamicBondUpdater(pybind11::module& m); + + } // end namespace detail + } // end namespace md + } // end namespace hoomd From f6968b1a7e3a94d4c15b68dde8850a9468c7ffbe Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 13 Mar 2025 12:49:58 -0400 Subject: [PATCH 05/58] update parts of the mesh updater --- hoomd/MeshDefinition.h | 3 +- hoomd/md/MeshDynamicBondUpdater.cc | 210 +++++++---------------------- hoomd/md/MeshDynamicBondUpdater.h | 7 - 3 files changed, 48 insertions(+), 172 deletions(-) diff --git a/hoomd/MeshDefinition.h b/hoomd/MeshDefinition.h index c455f3be2a..08a8c33601 100644 --- a/hoomd/MeshDefinition.h +++ b/hoomd/MeshDefinition.h @@ -114,8 +114,7 @@ class PYBIND11_EXPORT MeshDefinition private: GPUArray m_globalN; - std::shared_ptr - m_sysdef; //!< System definition later needed for dynamic bonding + std::shared_ptr m_sysdef; //!< System definition std::shared_ptr m_meshbond_data; //!< Bond data for the mesh std::shared_ptr m_meshtriangle_data; //!< Triangle data for the mesh // diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 36a5ce2b6d..3bc0086fe7 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -29,16 +29,6 @@ MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr Scalar T) : Updater(sysdef, trigger), m_integrator(integrator), m_mesh(mesh), m_inv_T(1.0 / T) { - GlobalVector tmp_allowSwitch(m_pdata->getNTypes(), m_exec_conf); - - m_allowSwitch.swap(tmp_allowSwitch); - TAG_ALLOCATION(m_allowSwitch); - - ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::overwrite); - - for (unsigned int i = 0; i < m_allowSwitch.size(); i++) - h_allowSwitch.data[i] = true; - assert(m_pdata); assert(m_integrator); assert(m_mesh); @@ -50,31 +40,6 @@ MeshDynamicBondUpdater::~MeshDynamicBondUpdater() m_exec_conf->msg->notice(5) << "Destroying MeshDynamicBondUpdater" << endl; } -void MeshDynamicBondUpdater::setAllowSwitch(const std::string& type_name, pybind11::bool_ v) - { - unsigned int typ = this->m_pdata->getTypeByName(type_name); - - // check for user errors - if (typ >= m_pdata->getNTypes()) - { - throw std::invalid_argument("Type does not exist"); - } - - bool allowSwitch = pybind11::cast(v); - - ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::readwrite); - h_allowSwitch.data[typ] = allowSwitch; - } - -pybind11::bool_ MeshDynamicBondUpdater::getAllowSwitch(const std::string& type_name) - { - unsigned int typ = this->m_pdata->getTypeByName(type_name); - - ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::read); - - bool allowSwitch = h_allowSwitch.data[typ]; - return pybind11::bool_(allowSwitch); - } /** Perform the needed calculations to update particle orientations \param timestep Current time step of the simulation @@ -93,6 +58,11 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), access_location::host, access_mode::readwrite); + + ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond()->getMembersArray(), + access_location::host, + access_mode::readwrite); + ArrayHandle h_triangles( m_mesh->getMeshTriangleData()->getMembersArray(), access_location::host, @@ -104,8 +74,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) access_location::host, access_mode::read); - ArrayHandle h_allowSwitch(m_allowSwitch, access_location::host, access_mode::read); - ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); // for each of the angles @@ -132,79 +100,43 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int type_a = __scalar_as_int(h_pos.data[idx_a].w); unsigned int type_b = __scalar_as_int(h_pos.data[idx_b].w); - bool allow_a = h_allowSwitch.data[type_a]; - bool allow_b = h_allowSwitch.data[type_b]; + //bool already_used = false; + //for (unsigned int j = 0; j < changed.size(); j++) + // { + // if (tag_a == changed[j] || tag_b == changed[j]) + // { + // already_used = true; + // break; + // } + // } - if (!allow_a && !allow_b) - continue; + //if (already_used) + // continue; - bool already_used = false; - for (unsigned int j = 0; j < changed.size(); j++) - { - if (tag_a == changed[j] || tag_b == changed[j]) - { - already_used = true; - break; - } - } + unsigned int tag_c = bond.tag[2]; + unsigned int tag_d = bond.tag[3]; - if (already_used) + if (tag_c == tag_d) continue; - unsigned int tr_idx1 = bond.tag[2]; - unsigned int tr_idx2 = bond.tag[3]; + unsigned int idx_c = h_rtag.data[tag_c]; + unsigned int idx_d = h_rtag.data[tag_d]; - if (tr_idx1 == tr_idx2) - continue; + unsigned int tr_idx1 = h_neigh_bonds.data[i].tag[0]; const typename MeshTriangle::members_t& triangle1 = h_triangles.data[tr_idx1]; - const typename MeshTriangle::members_t& triangle2 = h_triangles.data[tr_idx2]; unsigned int iterator = 0; - bool a_before_b = true; + bool a_before_b = false; - while (idx_b == h_rtag.data[triangle1.tag[iterator]]) + while (tag_a != triangle1.tag[iterator]) iterator++; iterator = (iterator + 1) % 3; - if (idx_a == h_rtag.data[triangle1.tag[iterator]]) - a_before_b = false; - - unsigned int tag_c = triangle1.tag[0]; - unsigned int idx_c = h_rtag.data[tag_c]; - - iterator = 0; - while (idx_a == idx_c || idx_b == idx_c) - { - iterator++; - tag_c = triangle1.tag[iterator]; - idx_c = h_rtag.data[tag_c]; - } - - unsigned int tag_d = triangle2.tag[0]; - unsigned int idx_d = h_rtag.data[tag_d]; - - iterator = 0; - while (idx_a == idx_d || idx_b == idx_d) - { - iterator++; - tag_d = triangle2.tag[iterator]; - idx_d = h_rtag.data[tag_d]; - } - - for (unsigned int j = 0; j < changed.size(); j++) - { - if (tag_c == changed[j] || tag_d == changed[j]) - { - already_used = true; - break; - } - } - - if (already_used) - continue; + if (tag_b == triangle1.tag[iterator]) + a_before_b = true; unsigned int type_id = h_typeval.data[i].type; @@ -230,74 +162,28 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if(have_to_check_surrounding) { - unsigned int idx_1, idx_2, idx_3, idx_4, idx_5; - for( int bo_i = 3; bo_i < 6; bo_i++) - { - unsigned int new_bo = triangle1.tag[bo_i]; - if( new_bo == i) continue; - const typename MeshBond::members_t& bond1 = h_bonds.data[new_bo]; - - idx_1 = h_rtag.data[bond1.tag[0]]; - idx_2 = h_rtag.data[bond1.tag[1]]; - - for( int tr_i = 2; tr_i < 4; tr_i++) - { - if(bond1.tag[tr_i] == tr_idx1) continue; - - const typename MeshTriangle::members_t& triangle1 = h_triangles.data[bond1.tag[tr_i]]; - for( int idx_i = 0; idx_i < 3; idx_i++) - { - if( triangle1.tag[idx_i] != bond1.tag[0] && triangle1.tag[idx_i] != bond1.tag[1] ) - { - idx_3 = h_rtag.data[triangle1.tag[idx_i]]; - break; - } - } - break; - } - - idx_4 = idx_a; - if(idx_1 == idx_4 || idx_2 == idx_4) idx_4 = idx_b; - idx_5 = idx_d; - - for (auto& force : forces) - energyDifference += force->energyDiffSurrounding(idx_1, idx_2, idx_3, idx_4, idx_5, type_id); - - } - - for( int bo_i = 3; bo_i < 6; bo_i++) - { - unsigned int new_bo = triangle2.tag[bo_i]; - if( new_bo == i) continue; - const typename MeshBond::members_t& bond1 = h_bonds.data[new_bo]; - - idx_1 = h_rtag.data[bond1.tag[0]]; - idx_2 = h_rtag.data[bond1.tag[1]]; - - for( int tr_i = 2; tr_i < 4; tr_i++) - { - if(bond1.tag[tr_i] == tr_idx2) continue; - - const typename MeshTriangle::members_t& triangle2 = h_triangles.data[bond1.tag[tr_i]]; - for( int idx_i = 0; idx_i < 3; idx_i++) - { - if( triangle2.tag[idx_i] != bond1.tag[0] && triangle2.tag[idx_i] != bond1.tag[1] ) - { - idx_3 = h_rtag.data[triangle2.tag[idx_i]]; - break; - } - } - break; - } - - idx_4 = idx_a; - if(idx_1 == idx_4 || idx_2 == idx_4) idx_4 = idx_b; - idx_5 = idx_c; - - for (auto& force : forces) - energyDifference += force->energyDiffSurrounding(idx_1, idx_2, idx_3, idx_4, idx_5, type_id); + std::vector tr_idx(6); + counter = 2; + tr_idx[0] = tr_idx1; + tr_idx[1] = h_neigh_bonds.data[i].tag[1]; + + + for(unsigned int j = 0; j < 2; ++j) + { + for(unsigned int k = 0; k < 3; ++k) + { + unsigned int tr_idx_candidate = h_neigh_triags.data[tr_idx[j]].tag[k]; + if(tr_idx_candidate != i) + { + tr_idx[counter] = tr_idx_candidate; + counter++; + } + } + } + + for (auto& force : forces) + energyDifference += force->energyDiffSurrounding(tr_idx, type_id); - } } // Initialize the RNG @@ -450,8 +336,6 @@ void export_MeshDynamicBondUpdater(pybind11::module& m) std::shared_ptr, std::shared_ptr, Scalar>()) - .def("setAllowSwitch", &MeshDynamicBondUpdater::setAllowSwitch) - .def("getAllowSwitch", &MeshDynamicBondUpdater::getAllowSwitch) .def_property("kT", &MeshDynamicBondUpdater::getT, &MeshDynamicBondUpdater::setT); } diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index 5c6e7b0f3b..4da1299b69 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -48,11 +48,6 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater /// Destructor virtual ~MeshDynamicBondUpdater(); - void setAllowSwitch(const std::string& type_name, pybind11::bool_ v); - - /// Gets active torque vector for a given particle type - pybind11::bool_ getAllowSwitch(const std::string& type_name); - /// Update box interpolation based on provided timestep virtual void update(uint64_t timestep); @@ -70,8 +65,6 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater std::shared_ptr m_integrator; //!< Integrator that advances time in this System std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on Scalar m_inv_T; - GlobalVector m_allowSwitch; //! check if bond wich features two particles of certain - //! particle types is allow to switch }; namespace detail From e2c90bb153edd55ed7bd910ea4039c2eff97af07 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Fri, 14 Mar 2025 17:06:09 -0400 Subject: [PATCH 06/58] conseptualize edge flip --- hoomd/md/MeshDynamicBondUpdater.cc | 35 ++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 3bc0086fe7..e7647c8334 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -123,12 +123,14 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_d = h_rtag.data[tag_d]; unsigned int tr_idx1 = h_neigh_bonds.data[i].tag[0]; + unsigned int tr_idx2 = h_neigh_bonds.data[i].tag[1]; const typename MeshTriangle::members_t& triangle1 = h_triangles.data[tr_idx1]; unsigned int iterator = 0; bool a_before_b = false; + bool tr1_with_c = false; while (tag_a != triangle1.tag[iterator]) iterator++; @@ -136,7 +138,13 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) iterator = (iterator + 1) % 3; if (tag_b == triangle1.tag[iterator]) + { a_before_b = true; + iterator = (iterator + 1) % 3; + } + + if(tag_c == triangle1.tag[iterator]) + tr1_with_c = true; unsigned int type_id = h_typeval.data[i].type; @@ -165,8 +173,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector tr_idx(6); counter = 2; tr_idx[0] = tr_idx1; - tr_idx[1] = h_neigh_bonds.data[i].tag[1]; - + tr_idx[1] = tr_idx2; for(unsigned int j = 0; j < 2; ++j) { @@ -197,6 +204,30 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { changeDetected = true; + h_bonds.data[i]; // bond a,b to c,d + + h_triangles[tr_idx1]; // triangle a,b,c/d to a,c,d + h_triangles[tr_id2]; // triangle a,b,c/d to b,c,d + + h_bonds.data[b_idx1]; // bond a,c,b,x to a,c,d,x + h_bonds.data[b_idx2]; // bond a,d,b,x to a,d,c,x + + h_bonds.data[b_idx3]; // bond b,c,b,x to b,c,d,x + h_bonds.data[b_idx4]; // bond b,d,b,x to b,d,c,x + // + h_neight_bonds.data[b_idx1]; // nbond tr1/2,trx,try to tr1,trx,try + h_neight_bonds.data[b_idx2]; // nbond tr1/2,trx,try to tr1,trx,try + + h_neight_bonds.data[b_idx3]; // nbond tr1/2,trx,try to tr2,trx,try + h_neight_bonds.data[b_idx4]; // nbond tr1/2,trx,try to tr2,trx,try + // + h_neight_triags.data[tr_idx1]; // nbond i,b_idx1/2,b_idx3/4 to i,b_idx1,b_idx2 + h_neight_triags.data[tr_idx2]; // nbond i,b_idx2/1,b_idx4/3 to i,b_idx3,b_idx4 + + + + + changed.push_back(tag_a); changed.push_back(tag_b); changed.push_back(tag_c); From 5da031a90e955d479553c33c55249dc722527bd8 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 14:51:32 -0400 Subject: [PATCH 07/58] first version of MeshUpdater --- hoomd/MeshDefinition.cc | 2 + hoomd/md/MeshDynamicBondUpdater.cc | 295 ++++++++++++++--------------- 2 files changed, 139 insertions(+), 158 deletions(-) diff --git a/hoomd/MeshDefinition.cc b/hoomd/MeshDefinition.cc index ae169416d7..3af6ea63bc 100644 --- a/hoomd/MeshDefinition.cc +++ b/hoomd/MeshDefinition.cc @@ -246,6 +246,8 @@ void export_MeshDefinition(pybind11::module& m) .def(pybind11::init, unsigned int>()) .def("getMeshTriangleData", &MeshDefinition::getMeshTriangleData) .def("getMeshBondData", &MeshDefinition::getMeshBondData) + .def("getNeighToTriag", &MeshDefinition::getNeighToTriag) + .def("getNeighToBond", &MeshDefinition::getNeighToBond) .def("getBondData", &MeshDefinition::getBondData) .def("setTypes", &MeshDefinition::setTypes) .def("getSize", &MeshDefinition::getSize) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index e7647c8334..551a1b0704 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -59,7 +59,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) access_location::host, access_mode::readwrite); - ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond()->getMembersArray(), + ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond()->getMembersArray(), access_location::host, access_mode::readwrite); @@ -68,6 +68,10 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) access_location::host, access_mode::readwrite); + ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag()->getMembersArray(), + access_location::host, + access_mode::readwrite); + ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); ArrayHandle h_typeval(m_mesh->getMeshBondData()->getTypeValArray(), @@ -122,8 +126,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_c = h_rtag.data[tag_c]; unsigned int idx_d = h_rtag.data[tag_d]; - unsigned int tr_idx1 = h_neigh_bonds.data[i].tag[0]; - unsigned int tr_idx2 = h_neigh_bonds.data[i].tag[1]; + unsigned int tr_idx1 = h_neigh_bonds.data[i].x; + unsigned int tr_idx2 = h_neigh_bonds.data[i].y; const typename MeshTriangle::members_t& triangle1 = h_triangles.data[tr_idx1]; @@ -168,191 +172,166 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) have_to_check_surrounding = true; } - if(have_to_check_surrounding) + // Initialize the RNG + RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), + hoomd::Counter(i)); + + // compute the random force + UniformDistribution uniform(0, Scalar(1)); + + Scalar rand_number = uniform(rng); + Scalar part_func = exp(-m_inv_T * energyDifference); + + std::vector tr_idx(6); + std::vector b_idx(4); + std::vector v_idx(8); + + if (have_to_check_surrounding || part_func > random_number ) { - std::vector tr_idx(6); - counter = 2; - tr_idx[0] = tr_idx1; - tr_idx[1] = tr_idx2; + tr_idx[1] = tr_idx1; + tr_idx[0] = tr_idx2; + if(a_before_b) + { + tr_idx[0] = tr_idx1; + tr_idx[1] = tr_idx2; + } + + v_idx[0]=idx_a; + v_idx[1]=idx_b; + v_idx[2]=idx_cc; + v_idx[3]=idx_dd; + counter = 4; for(unsigned int j = 0; j < 2; ++j) { - for(unsigned int k = 0; k < 3; ++k) - { - unsigned int tr_idx_candidate = h_neigh_triags.data[tr_idx[j]].tag[k]; - if(tr_idx_candidate != i) + unsigned int bic = h_neigh_triags.data[tr_idx[j]].x; + unsigned int bic2 = h_neigh_triags.data[tr_idx[j]].y; + if(bic == i) + { + bic = bic2; + bic2 = h_neigh_triags.data[tr_idx[j]].z; + } + else + { + if(bic2 == i) + bic2 = h_neigh_triags.data[tr_idx[j]].z; + } + if( h_bonds.data[bic].tag[0] == idx_a || h_bonds.data[bic].tag[1] == idx_a) + { + b_idx[2*j] = bic; + b_idx[2*j+1] = bic2; + } + else + { + b_idx[2*j+1] = bic; + b_idx[2*j] = bic2; + } + for(unsigned int k = 0; k < 2; ++j) + { + unsigned int tic = h_neigh_bonds.data[b_idx[2*j+k]].x; + if(tic == tr_idx[j]) + tic = h_neigh_bonds.data[bic_idx[2*j+k]].y; + unsigned int zaehler = 1; + unsigned int nv_idx = h_triangles.data[tic].tag[0]; + while(nv_idx == v_idx[k] || nv_idx == v_idx[2+j]) { - tr_idx[counter] = tr_idx_candidate; - counter++; - } - } + nv_idx = h_triangles.data[tic].tag[zaehler]; + zaehler++; + } + v_idx[counter] = nv_idx; + tr_idx[counter-2] = = tic; + counter++; + } } - for (auto& force : forces) - energyDifference += force->energyDiffSurrounding(tr_idx, type_id); - + if (have_to_check_surrounding) + { + for (auto& force : forces) + energyDifference += force->energyDiffSurrounding(v_idx[0],v_idx[1],v_idx[2],v_idx[3],v_idx[4],v_idx[5],v_idx[6],v_idx[7], type_id); + part_func = exp(-m_inv_T * energyDifference); + } } - // Initialize the RNG - RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), - hoomd::Counter(i)); - - // compute the random force - UniformDistribution uniform(0, Scalar(1)); - - if (exp(-m_inv_T * energyDifference) > uniform(rng)) + if (part_func > random_number) { - changeDetected = true; + bond.tag[0] = v_idx[2]; + bond.tag[1] = v_idx[3]; + if(v_idx[2] < v_idx[3]) + { + bond.tag[1] = v_idx[2]; + bond.tag[0] = v_idx[3]; + } - h_bonds.data[i]; // bond a,b to c,d + bond.tag[2] = v_idx[0]; + bond.tag[3] = v_idx[1]; - h_triangles[tr_idx1]; // triangle a,b,c/d to a,c,d - h_triangles[tr_id2]; // triangle a,b,c/d to b,c,d - - h_bonds.data[b_idx1]; // bond a,c,b,x to a,c,d,x - h_bonds.data[b_idx2]; // bond a,d,b,x to a,d,c,x - - h_bonds.data[b_idx3]; // bond b,c,b,x to b,c,d,x - h_bonds.data[b_idx4]; // bond b,d,b,x to b,d,c,x - // - h_neight_bonds.data[b_idx1]; // nbond tr1/2,trx,try to tr1,trx,try - h_neight_bonds.data[b_idx2]; // nbond tr1/2,trx,try to tr1,trx,try - - h_neight_bonds.data[b_idx3]; // nbond tr1/2,trx,try to tr2,trx,try - h_neight_bonds.data[b_idx4]; // nbond tr1/2,trx,try to tr2,trx,try - // - h_neight_triags.data[tr_idx1]; // nbond i,b_idx1/2,b_idx3/4 to i,b_idx1,b_idx2 - h_neight_triags.data[tr_idx2]; // nbond i,b_idx2/1,b_idx4/3 to i,b_idx3,b_idx4 - - + h_bonds.data[i] = bond; + triangle1.tag[0] = v_idx[0]; + triangle1.tag[1] = v_idx[3]; + triangle1.tag[2] = v_idx[2]; + h_triangles[tr_idx[0]] = triangle1; // triangle a,b,c to a,d,c + triangle1.tag[0] = v_idx[1]; + triangle1.tag[1] = v_idx[2]; + triangle1.tag[2] = v_idx[3]; + h_triangles[tr_idx[1]] = triangle2; // triangle b,a,d to b,c,d - changed.push_back(tag_a); - changed.push_back(tag_b); - changed.push_back(tag_c); - changed.push_back(tag_d); + bond = h_bonds.data[b_idx[0]]; + bond.tag[2] = v_idx[3]; + bond.tag[3] = v_idx[4]; + h_bonds.data[b_idx[0]] = bond; // bond a,c,b,x to a,c,d,x - typename MeshBond::members_t bond_n; - typename MeshTriangle::members_t triangle1_n; - typename MeshTriangle::members_t triangle2_n; + bond = h_bonds.data[b_idx[1]]; + bond.tag[2] = v_idx[3]; + bond.tag[3] = v_idx[5]; + h_bonds.data[b_idx[1]] = bond; // bond b,c,a,x to b,c,d,x - bond_n.tag[0] = tag_c; - bond_n.tag[1] = tag_d; - bond_n.tag[2] = tr_idx1; - bond_n.tag[3] = tr_idx2; + bond = h_bonds.data[b_idx[2]]; + bond.tag[2] = v_idx[2]; + bond.tag[3] = v_idx[6]; + h_bonds.data[b_idx[2]] = bond; // bond a,d,b,x to a,d,c,x - h_bonds.data[i] = bond_n; + bond = h_bonds.data[b_idx[3]]; + bond.tag[2] = v_idx[2]; + bond.tag[3] = v_idx[7]; + h_bonds.data[b_idx[3]] = bond; // bond b,d,a,x to b,d,c,x - bool needs_flipping = true; + uint2 tris; + uint3 bs; - if (iterator < 2) - { - if (triangle2.tag[iterator + 1] == tag_a) - needs_flipping = false; - } - else - { - if (triangle2.tag[0] == tag_a) - needs_flipping = false; - } + tris.x = tr_idx[0]; + tris.y = tr_idx[2]; + h_neight_bonds.data[b_idx[0]] = tris; - triangle1_n.tag[0] = tag_a; - triangle2_n.tag[0] = tag_b; + tris.y = tr_idx[4]; + h_neight_bonds.data[b_idx[2]] = tris; - if (needs_flipping) - { - triangle1_n.tag[2] = tag_c; - triangle1_n.tag[1] = tag_d; - triangle2_n.tag[2] = tag_d; - triangle2_n.tag[1] = tag_c; - } - else - { - triangle1_n.tag[1] = tag_c; - triangle1_n.tag[2] = tag_d; - triangle2_n.tag[1] = tag_d; - triangle2_n.tag[2] = tag_c; - } + tris.x = tr_idx[1]; + tris.y = tr_idx[3]; + h_neight_bonds.data[b_idx[1]] = tris; - for (int j = 3; j < 6; j++) - { - int k = triangle1.tag[j]; - if (k != i) - { - typename MeshBond::members_t& bond_s = h_bonds.data[k]; - - unsigned int tr_idx; - if (bond_s.tag[0] == tag_a || bond_s.tag[1] == tag_a) - { - tr_idx = tr_idx1; - triangle1_n.tag[3] = k; - } - else - { - tr_idx = tr_idx2; - triangle2_n.tag[3] = k; - } - - if (bond_s.tag[2] == tr_idx1 || bond_s.tag[2] == tr_idx2) - bond_s.tag[2] = tr_idx; - else - bond_s.tag[3] = tr_idx; - h_bonds.data[k] = bond_s; - } - k = triangle2.tag[j]; - if (k != i) - { - typename MeshBond::members_t& bond_s = h_bonds.data[k]; - - unsigned int tr_idx; - if (bond_s.tag[0] == tag_a || bond_s.tag[1] == tag_a) - { - tr_idx = tr_idx1; - triangle1_n.tag[4] = k; - } - else - { - tr_idx = tr_idx2; - triangle2_n.tag[4] = k; - } - - if (bond_s.tag[2] == tr_idx1 || bond_s.tag[2] == tr_idx2) - bond_s.tag[2] = tr_idx; - else - bond_s.tag[3] = tr_idx; - h_bonds.data[k] = bond_s; - } - } + tris.y = tr_idx[5]; + h_neight_bonds.data[b_idx[3]] = tris; - triangle1_n.tag[5] = i; - triangle2_n.tag[5] = i; + bs.x = i; + bs.y = b_idx[0]; + bs.z = b_idx[2]; + h_neight_triags.data[tr_idx[0]] = bs; - h_triangles.data[tr_idx1] = triangle1_n; - h_triangles.data[tr_idx2] = triangle2_n; + bs.x = i; + bs.y = b_idx[1]; + bs.z = b_idx[3]; + h_neight_triags.data[tr_idx[1]] = bs; - if (a_before_b) + for (auto& force : forces) { - for (auto& force : forces) - { - force->postcompute(idx_a, idx_b, idx_c, idx_d); - } - } - else - { - for (auto& force : forces) - { - force->postcompute(idx_a, idx_b, idx_d, idx_c); - } + force->postcompute(idx_a, idx_b, idx_cc, idx_dd); } + m_mesh->getMeshBondData()->meshChanged(); + m_mesh->getMeshTriangleData()->meshChanged(); } } - - if (changeDetected) - { - m_mesh->getMeshBondData()->meshChanged(); - m_mesh->getMeshTriangleData()->meshChanged(); - } } namespace detail From 0fbaf1c8381edba27a4225258b690b9b634caeef Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 15:52:12 -0400 Subject: [PATCH 08/58] creat MeshForceCompute class --- hoomd/md/CMakeLists.txt | 26 +++++++++-------- hoomd/md/MeshForceCompute.cc | 38 +++++++++++++++++++++++++ hoomd/md/MeshForceCompute.h | 54 ++++++++++++++++++++++++++++++++++++ hoomd/md/module-md.cc | 2 ++ 4 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 hoomd/md/MeshForceCompute.cc create mode 100644 hoomd/md/MeshForceCompute.h diff --git a/hoomd/md/CMakeLists.txt b/hoomd/md/CMakeLists.txt index 1ef7afd842..445edd461d 100644 --- a/hoomd/md/CMakeLists.txt +++ b/hoomd/md/CMakeLists.txt @@ -36,6 +36,7 @@ set(_md_sources module-md.cc ManifoldXYPlane.cc ManifoldPrimitive.cc ManifoldSphere.cc + MeshForceCompute.cc MolecularForceCompute.cc MuellerPlatheFlow.cc NeighborListBinned.cc @@ -56,7 +57,7 @@ set(_md_sources module-md.cc Thermostat.cc TwoStepNVTAlchemy.cc WallData.cc - VolumeConservationMeshForceCompute.cc + VolumeConservationMeshForceCompute.cc ZeroMomentumUpdater.cc ) @@ -99,7 +100,7 @@ set(_md_headers ActiveForceComputeGPU.h EvaluatorSpecialPairLJ.h EvaluatorSpecialPairCoulomb.h EvaluatorExternalElectricField.h - EvaluatorExternalMagneticField.h + EvaluatorExternalMagneticField.h EvaluatorExternalPeriodic.h EvaluatorPairALJ.h EvaluatorPairBuckingham.h @@ -143,8 +144,8 @@ set(_md_headers ActiveForceComputeGPU.h HarmonicDihedralForceCompute.h HarmonicImproperForceComputeGPU.h HarmonicImproperForceCompute.h - HelfrichMeshForceComputeGPU.h - HelfrichMeshForceCompute.h + HelfrichMeshForceComputeGPU.h + HelfrichMeshForceCompute.h IntegrationMethodTwoStep.h IntegratorTwoStep.h ManifoldZCylinder.h @@ -154,6 +155,7 @@ set(_md_headers ActiveForceComputeGPU.h ManifoldXYPlane.h ManifoldPrimitive.h ManifoldSphere.h + MeshForceCompute.h MolecularForceCompute.cuh MolecularForceCompute.h MuellerPlatheFlowEnum.h @@ -220,9 +222,9 @@ set(_md_headers ActiveForceComputeGPU.h TwoStepConstantPressure.h AlchemostatTwoStep.h TwoStepNVTAlchemy.h - VolumeConservationMeshParameters.h - VolumeConservationMeshForceCompute.h - VolumeConservationMeshForceComputeGPU.h + VolumeConservationMeshParameters.h + VolumeConservationMeshForceCompute.h + VolumeConservationMeshForceComputeGPU.h AlchemostatTwoStep.h WallData.h ZeroMomentumUpdater.h @@ -247,7 +249,7 @@ list(APPEND _md_sources ActiveForceComputeGPU.cc HarmonicAngleForceComputeGPU.cc HarmonicDihedralForceComputeGPU.cc HarmonicImproperForceComputeGPU.cc - HelfrichMeshForceComputeGPU.cc + HelfrichMeshForceComputeGPU.cc MolecularForceCompute.cu NeighborListGPU.cc NeighborListGPUBinned.cc @@ -261,7 +263,7 @@ list(APPEND _md_sources ActiveForceComputeGPU.cc TriangleAreaConservationMeshForceComputeGPU.cc TwoStepBDGPU.cc TwoStepLangevinGPU.cc - VolumeConservationMeshForceComputeGPU.cc + VolumeConservationMeshForceComputeGPU.cc TwoStepConstantVolumeGPU.cc TwoStepConstantPressureGPU.cc MuellerPlatheFlowGPU.cc @@ -275,7 +277,7 @@ set(_md_cu_sources ActiveForceComputeGPU.cu AnisoPotentialPairALJ3GPUKernel.cu AnisoPotentialPairDipoleGPUKernel.cu AnisoPotentialPairGBGPUKernel.cu - BendingRigidityMeshForceComputeGPU.cu + BendingRigidityMeshForceComputeGPU.cu ComputeThermoGPU.cu ComputeThermoHMAGPU.cu ConstantForceComputeGPU.cu @@ -287,7 +289,7 @@ set(_md_cu_sources ActiveForceComputeGPU.cu HarmonicAngleForceGPU.cu HarmonicDihedralForceGPU.cu HarmonicImproperForceGPU.cu - HelfrichMeshForceComputeGPU.cu + HelfrichMeshForceComputeGPU.cu MolecularForceCompute.cu NeighborListGPUBinned.cu NeighborListGPU.cu @@ -306,7 +308,7 @@ set(_md_cu_sources ActiveForceComputeGPU.cu TwoStepConstantVolumeGPU.cu TwoStepNVEGPU.cu TwoStepRATTLENVEGPU.cu - VolumeConservationMeshForceComputeGPU.cu + VolumeConservationMeshForceComputeGPU.cu MuellerPlatheFlowGPU.cu CosineSqAngleForceGPU.cu ) diff --git a/hoomd/md/MeshForceCompute.cc b/hoomd/md/MeshForceCompute.cc new file mode 100644 index 0000000000..1f7abca97c --- /dev/null +++ b/hoomd/md/MeshForceCompute.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2009-2025 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +#include "MeshForceCompute.h" + +#include + +using namespace std; + +/*! \file MeshForceCompute.cc + \brief Contains code for the MeshForceCompute class +*/ + +namespace hoomd + { +namespace md + { +/*! \param sysdef System to compute forces on + \param meshdef Mesh triangulation + \post Memory is allocated, and forces are zeroed. +*/ +MeshForceCompute::MeshForceCompute(std::shared_ptr sysdef, + std::shared_ptr meshdef) + : ForceCompute(sysdef), m_mesh_data(meshdef){} + +namespace detail + { +void export_MeshForceCompute(pybind11::module& m) + { + pybind11::class_>(m, "MeshForceCompute") + .def(pybind11::init, std::shared_ptr>()); + } + + } // end namespace detail + } // end namespace md + } // end namespace hoomd diff --git a/hoomd/md/MeshForceCompute.h b/hoomd/md/MeshForceCompute.h new file mode 100644 index 0000000000..7373794ddb --- /dev/null +++ b/hoomd/md/MeshForceCompute.h @@ -0,0 +1,54 @@ +// Copyright (c) 2009-2025 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +#include "hoomd/ForceCompute.h" +#include "hoomd/MeshDefinition.h" + +#include + +/*! \file MeshForceCompute.h + \brief Declares the MeshForceCompute class +*/ + +#ifdef __HIPCC__ +#error This header cannot be compiled by nvcc +#endif + +#include + +#ifndef __MeshFORCECOMPUTE_H__ +#define __MeshFORCECOMPUTE_H__ + +namespace hoomd + { +namespace md + { +//! Structure for passing the meshforce arrays around + +class PYBIND11_EXPORT MeshForceCompute : public ForceCompute + { + public: + //! Constructs the compute + MeshForceCompute(std::shared_ptr sysdef, + std::shared_ptr meshdef); + + //! compute areas + virtual void precomputeParameter(){ }; + + protected: + std::shared_ptr m_mesh_data; //!< Mesh data to use in computing helfich energy + }; + +namespace detail + { + +//! Exports the MeshForceCompute class to python +#ifndef __HIPCC__ +void export_MeshForceCompute(pybind11::module& m); +#endif + + } // end namespace detail + } // end namespace md + } // end namespace hoomd + +#endif // __MESHFORCECOMPUTE_H__ diff --git a/hoomd/md/module-md.cc b/hoomd/md/module-md.cc index 13dc32c0ad..9e23b3fb69 100644 --- a/hoomd/md/module-md.cc +++ b/hoomd/md/module-md.cc @@ -36,6 +36,7 @@ void export_NeighborList(pybind11::module& m); void export_NeighborListBinned(pybind11::module& m); void export_NeighborListStencil(pybind11::module& m); void export_NeighborListTree(pybind11::module& m); +void export_MeshForceCompute(pybind11::module& m); void export_MolecularForceCompute(pybind11::module& m); void export_ForceDistanceConstraint(pybind11::module& m); void export_ForceComposite(pybind11::module& m); @@ -414,6 +415,7 @@ PYBIND11_MODULE(_md, m) export_NeighborListBinned(m); export_NeighborListStencil(m); export_NeighborListTree(m); + export_MeshForceCompute(m); export_MolecularForceCompute(m); export_ForceDistanceConstraint(m); export_ForceComposite(m); From ac7defb254486a52c0501cbdb84feb3d53eed52a Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 16:15:26 -0400 Subject: [PATCH 09/58] reverse MeshForceCmpute --- hoomd/md/CMakeLists.txt | 2 -- hoomd/md/MeshForceCompute.cc | 38 ------------------------- hoomd/md/MeshForceCompute.h | 54 ------------------------------------ hoomd/md/module-md.cc | 2 -- 4 files changed, 96 deletions(-) delete mode 100644 hoomd/md/MeshForceCompute.cc delete mode 100644 hoomd/md/MeshForceCompute.h diff --git a/hoomd/md/CMakeLists.txt b/hoomd/md/CMakeLists.txt index 445edd461d..ea74bc3949 100644 --- a/hoomd/md/CMakeLists.txt +++ b/hoomd/md/CMakeLists.txt @@ -36,7 +36,6 @@ set(_md_sources module-md.cc ManifoldXYPlane.cc ManifoldPrimitive.cc ManifoldSphere.cc - MeshForceCompute.cc MolecularForceCompute.cc MuellerPlatheFlow.cc NeighborListBinned.cc @@ -155,7 +154,6 @@ set(_md_headers ActiveForceComputeGPU.h ManifoldXYPlane.h ManifoldPrimitive.h ManifoldSphere.h - MeshForceCompute.h MolecularForceCompute.cuh MolecularForceCompute.h MuellerPlatheFlowEnum.h diff --git a/hoomd/md/MeshForceCompute.cc b/hoomd/md/MeshForceCompute.cc deleted file mode 100644 index 1f7abca97c..0000000000 --- a/hoomd/md/MeshForceCompute.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2009-2025 The Regents of the University of Michigan. -// Part of HOOMD-blue, released under the BSD 3-Clause License. - -#include "MeshForceCompute.h" - -#include - -using namespace std; - -/*! \file MeshForceCompute.cc - \brief Contains code for the MeshForceCompute class -*/ - -namespace hoomd - { -namespace md - { -/*! \param sysdef System to compute forces on - \param meshdef Mesh triangulation - \post Memory is allocated, and forces are zeroed. -*/ -MeshForceCompute::MeshForceCompute(std::shared_ptr sysdef, - std::shared_ptr meshdef) - : ForceCompute(sysdef), m_mesh_data(meshdef){} - -namespace detail - { -void export_MeshForceCompute(pybind11::module& m) - { - pybind11::class_>(m, "MeshForceCompute") - .def(pybind11::init, std::shared_ptr>()); - } - - } // end namespace detail - } // end namespace md - } // end namespace hoomd diff --git a/hoomd/md/MeshForceCompute.h b/hoomd/md/MeshForceCompute.h deleted file mode 100644 index 7373794ddb..0000000000 --- a/hoomd/md/MeshForceCompute.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2009-2025 The Regents of the University of Michigan. -// Part of HOOMD-blue, released under the BSD 3-Clause License. - -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" - -#include - -/*! \file MeshForceCompute.h - \brief Declares the MeshForceCompute class -*/ - -#ifdef __HIPCC__ -#error This header cannot be compiled by nvcc -#endif - -#include - -#ifndef __MeshFORCECOMPUTE_H__ -#define __MeshFORCECOMPUTE_H__ - -namespace hoomd - { -namespace md - { -//! Structure for passing the meshforce arrays around - -class PYBIND11_EXPORT MeshForceCompute : public ForceCompute - { - public: - //! Constructs the compute - MeshForceCompute(std::shared_ptr sysdef, - std::shared_ptr meshdef); - - //! compute areas - virtual void precomputeParameter(){ }; - - protected: - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing helfich energy - }; - -namespace detail - { - -//! Exports the MeshForceCompute class to python -#ifndef __HIPCC__ -void export_MeshForceCompute(pybind11::module& m); -#endif - - } // end namespace detail - } // end namespace md - } // end namespace hoomd - -#endif // __MESHFORCECOMPUTE_H__ diff --git a/hoomd/md/module-md.cc b/hoomd/md/module-md.cc index 9e23b3fb69..13dc32c0ad 100644 --- a/hoomd/md/module-md.cc +++ b/hoomd/md/module-md.cc @@ -36,7 +36,6 @@ void export_NeighborList(pybind11::module& m); void export_NeighborListBinned(pybind11::module& m); void export_NeighborListStencil(pybind11::module& m); void export_NeighborListTree(pybind11::module& m); -void export_MeshForceCompute(pybind11::module& m); void export_MolecularForceCompute(pybind11::module& m); void export_ForceDistanceConstraint(pybind11::module& m); void export_ForceComposite(pybind11::module& m); @@ -415,7 +414,6 @@ PYBIND11_MODULE(_md, m) export_NeighborListBinned(m); export_NeighborListStencil(m); export_NeighborListTree(m); - export_MeshForceCompute(m); export_MolecularForceCompute(m); export_ForceDistanceConstraint(m); export_ForceComposite(m); From 855b9cb22f340298f7a6ba6799904bfa956f7904 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 16:33:42 -0400 Subject: [PATCH 10/58] rename precomputeParameters --- hoomd/md/HelfrichMeshForceCompute.cc | 4 ++-- hoomd/md/HelfrichMeshForceCompute.h | 2 +- hoomd/md/HelfrichMeshForceComputeGPU.cc | 4 ++-- hoomd/md/HelfrichMeshForceComputeGPU.h | 2 +- hoomd/md/VolumeConservationMeshForceCompute.cc | 4 ++-- hoomd/md/VolumeConservationMeshForceCompute.h | 2 +- hoomd/md/VolumeConservationMeshForceComputeGPU.cc | 4 ++-- hoomd/md/VolumeConservationMeshForceComputeGPU.h | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 58fccedd84..0d96f1c14b 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -91,7 +91,7 @@ pybind11::dict HelfrichMeshForceCompute::getParams(std::string type) */ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) { - computeSigma(); // precompute sigmas + precomputeParameter(); assert(m_pdata); // access the particle data arrays @@ -386,7 +386,7 @@ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) } } -void HelfrichMeshForceCompute::computeSigma() +void HelfrichMeshForceCompute::precomputeParameter() { ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index e032951a17..33d4b5fc55 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -74,7 +74,7 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute virtual void computeForces(uint64_t timestep); //! compute sigmas - virtual void computeSigma(); + virtual void precomputeParameter(); }; namespace detail diff --git a/hoomd/md/HelfrichMeshForceComputeGPU.cc b/hoomd/md/HelfrichMeshForceComputeGPU.cc index 3f71f8d2a9..7c657bc924 100644 --- a/hoomd/md/HelfrichMeshForceComputeGPU.cc +++ b/hoomd/md/HelfrichMeshForceComputeGPU.cc @@ -72,7 +72,7 @@ HelfrichMeshForceComputeGPU::HelfrichMeshForceComputeGPU(std::shared_ptr d_pos(m_pdata->getPositions(), access_location::device, access_mode::read); @@ -133,7 +133,7 @@ void HelfrichMeshForceComputeGPU::computeForces(uint64_t timestep) /*! Actually perform the force computation \param timestep Current time step */ -void HelfrichMeshForceComputeGPU::computeSigma() +void HelfrichMeshForceComputeGPU::precomputeParameter() { const GPUArray& gpu_meshbond_list = this->m_mesh_data->getMeshBondData()->getGPUTable(); diff --git a/hoomd/md/HelfrichMeshForceComputeGPU.h b/hoomd/md/HelfrichMeshForceComputeGPU.h index 21af1548e7..2f29836d68 100644 --- a/hoomd/md/HelfrichMeshForceComputeGPU.h +++ b/hoomd/md/HelfrichMeshForceComputeGPU.h @@ -43,7 +43,7 @@ class PYBIND11_EXPORT HelfrichMeshForceComputeGPU : public HelfrichMeshForceComp virtual void computeForces(uint64_t timestep); //! compute sigmas - virtual void computeSigma(); + virtual void precomputeParameter(); }; namespace detail diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index 7c6f436a10..b2b037460e 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -95,7 +95,7 @@ void VolumeConservationMeshForceCompute::computeForces(uint64_t timestep) { unsigned int triN = m_mesh_data->getSize(); - computeVolume(); // precompute volume + precomputeParameter(); assert(m_pdata); ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); @@ -262,7 +262,7 @@ void VolumeConservationMeshForceCompute::computeForces(uint64_t timestep) } } -void VolumeConservationMeshForceCompute::computeVolume() +void VolumeConservationMeshForceCompute::precomputeParameter() { ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index 6f551c591c..b211936cc2 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -84,7 +84,7 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public ForceCompute virtual void computeForces(uint64_t timestep); //! compute volumes - virtual void computeVolume(); + virtual void precomputeParameter(); }; namespace detail diff --git a/hoomd/md/VolumeConservationMeshForceComputeGPU.cc b/hoomd/md/VolumeConservationMeshForceComputeGPU.cc index 7649871e6d..b6cce42147 100644 --- a/hoomd/md/VolumeConservationMeshForceComputeGPU.cc +++ b/hoomd/md/VolumeConservationMeshForceComputeGPU.cc @@ -61,7 +61,7 @@ void VolumeConservationMeshForceComputeGPU::computeForces(uint64_t timestep) { unsigned int triN = m_mesh_data->getSize(); - computeVolume(); + precomputeParameter(); // access the particle data arrays ArrayHandle d_pos(m_pdata->getPositions(), access_location::device, access_mode::read); @@ -125,7 +125,7 @@ void VolumeConservationMeshForceComputeGPU::computeForces(uint64_t timestep) /*! Actually perform the force computation \param timestep Current time step */ -void VolumeConservationMeshForceComputeGPU::computeVolume() +void VolumeConservationMeshForceComputeGPU::precomputeParameter() { // access the particle data arrays ArrayHandle d_pos(m_pdata->getPositions(), access_location::device, access_mode::read); diff --git a/hoomd/md/VolumeConservationMeshForceComputeGPU.h b/hoomd/md/VolumeConservationMeshForceComputeGPU.h index c479012f39..e3be3cc325 100644 --- a/hoomd/md/VolumeConservationMeshForceComputeGPU.h +++ b/hoomd/md/VolumeConservationMeshForceComputeGPU.h @@ -50,7 +50,7 @@ class PYBIND11_EXPORT VolumeConservationMeshForceComputeGPU virtual void computeForces(uint64_t timestep); //! compute volumes - virtual void computeVolume(); + virtual void precomputeParameter(); }; namespace detail From 8b062cb5f5bcdc94dd26c0bd71849b1607115a43 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 16:42:17 -0400 Subject: [PATCH 11/58] add precomputeParameter to ForceCompute --- hoomd/ForceCompute.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index b94cfdd8c2..ec72bd4b76 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -75,6 +75,9 @@ class PYBIND11_EXPORT ForceCompute : public Compute //! Computes the forces virtual void compute(uint64_t timestep); + //! Computes the parameters for meshes + virtual void precomputeParameter(){}; + //! Total the potential energy Scalar calcEnergySum(); From 80883acb60f335369a52b1a6701f0c45d1f31152 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 22:13:52 -0400 Subject: [PATCH 12/58] add all necesarry functions to Helfrich --- hoomd/ForceCompute.h | 22 ++ hoomd/md/HelfrichMeshForceCompute.cc | 304 ++++++++++++++++++++++++++- hoomd/md/HelfrichMeshForceCompute.h | 21 ++ 3 files changed, 341 insertions(+), 6 deletions(-) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index ec72bd4b76..f683e35246 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -78,6 +78,28 @@ class PYBIND11_EXPORT ForceCompute : public Compute //! Computes the parameters for meshes virtual void precomputeParameter(){}; + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id){return 0;}; + + virtual Scalar energyDiffSurrounding(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int idx_e, + unsigned int idx_f, + unsigned int idx_g, + unsigned int idx_h){ return 0;}; + + virtual void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d){}; + + virtual bool checkSurrounding(){ return false;} + //! Total the potential energy Scalar calcEnergySum(); diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 0d96f1c14b..36a33062ba 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -184,17 +184,11 @@ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; - Scalar3 dcd; - dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; - dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; - dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; - dab = box.minImage(dab); dac = box.minImage(dac); dad = box.minImage(dad); dbc = box.minImage(dbc); dbd = box.minImage(dbd); - dcd = box.minImage(dcd); Scalar rsqab = dab.x * dab.x + dab.y * dab.y + dab.z * dab.z; Scalar rab = sqrt(rsqab); @@ -548,6 +542,304 @@ void HelfrichMeshForceCompute::precomputeParameter() } } +Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + + ArrayHandle h_sigma(m_sigma, access_location::host, access_mode::read); + ArrayHandle h_sigma_dash(m_sigma_dash, access_location::host, access_mode::read); + + ArrayHandle h_params(m_params, access_location::host, access_mode::read); + + const BoxDim& box = m_pdata->getGlobalBox(); + + // calculate d\vec{r} + Scalar3 dab; + dab.x = h_pos.data[idx_a].x - h_pos.data[idx_b].x; + dab.y = h_pos.data[idx_a].y - h_pos.data[idx_b].y; + dab.z = h_pos.data[idx_a].z - h_pos.data[idx_b].z; + + Scalar3 dac; + dac.x = h_pos.data[idx_a].x - h_pos.data[idx_c].x; + dac.y = h_pos.data[idx_a].y - h_pos.data[idx_c].y; + dac.z = h_pos.data[idx_a].z - h_pos.data[idx_c].z; + + Scalar3 dad; + dad.x = h_pos.data[idx_a].x - h_pos.data[idx_d].x; + dad.y = h_pos.data[idx_a].y - h_pos.data[idx_d].y; + dad.z = h_pos.data[idx_a].z - h_pos.data[idx_d].z; + + Scalar3 dbc; + dbc.x = h_pos.data[idx_b].x - h_pos.data[idx_c].x; + dbc.y = h_pos.data[idx_b].y - h_pos.data[idx_c].y; + dbc.z = h_pos.data[idx_b].z - h_pos.data[idx_c].z; + + Scalar3 dbd; + dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; + dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; + dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + + Scalar3 dcd; + dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; + dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; + dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; + + // apply minimum image conventions to all 3 vectors + dab = box.minImage(dab); + dac = box.minImage(dac); + dad = box.minImage(dad); + dbc = box.minImage(dbc); + dbd = box.minImage(dbd); + dcd = box.minImage(dcd); + + Scalar rsqab = dab.x * dab.x + dab.y * dab.y + dab.z * dab.z; + Scalar rab = sqrt(rsqab); + Scalar rsqac = dac.x * dac.x + dac.y * dac.y + dac.z * dac.z; + Scalar rac = sqrt(rsqac); + Scalar rsqad = dad.x * dad.x + dad.y * dad.y + dad.z * dad.z; + Scalar rad = sqrt(rsqad); + + Scalar rsqbc = dbc.x * dbc.x + dbc.y * dbc.y + dbc.z * dbc.z; + Scalar rbc = sqrt(rsqbc); + Scalar rsqbd = dbd.x * dbd.x + dbd.y * dbd.y + dbd.z * dbd.z; + Scalar rbd = sqrt(rsqbd); + Scalar rsqcd = dcd.x * dcd.x + dcd.y * dcd.y + dcd.z * dcd.z; + Scalar rcd = sqrt(rsqcd); + + Scalar3 nab, nac, nad, nbc, nbd, ncd; + nab = dab / rab; + nac = dac / rac; + nad = dad / rad; + nbc = dbc / rbc; + nbd = dbd / rbd; + ncd = dcd / rcd; + + Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; + if (c_accb > 1.0) + c_accb = 1.0; + if (c_accb < -1.0) + c_accb = -1.0; + + Scalar inv_s_accb = sqrt(1.0 - c_accb * c_accb); + if (inv_s_accb < SMALL) + inv_s_accb = SMALL; + inv_s_accb = 1.0 / inv_s_accb; + + Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; + if (c_addb > 1.0) + c_addb = 1.0; + if (c_addb < -1.0) + c_addb = -1.0; + + Scalar inv_s_addb = sqrt(1.0 - c_addb * c_addb); + if (inv_s_addb < SMALL) + inv_s_addb = SMALL; + inv_s_addb = 1.0 / inv_s_addb; + + Scalar c_abbc = -(nab.x * nbc.x + nab.y * nbc.y + nab.z * nbc.z); + if (c_abbc > 1.0) + c_abbc = 1.0; + if (c_abbc < -1.0) + c_abbc = -1.0; + + Scalar inv_s_abbc = sqrt(1.0 - c_abbc * c_abbc); + if (inv_s_abbc < SMALL) + inv_s_abbc = SMALL; + inv_s_abbc = 1.0 / inv_s_abbc; + + Scalar c_abbd = -(nab.x * nbd.x + nab.y * nbd.y + nab.z * nbd.z); + if (c_abbd > 1.0) + c_abbd = 1.0; + if (c_abbd < -1.0) + c_abbd = -1.0; + + Scalar inv_s_abbd = sqrt(1.0 - c_abbd * c_abbd); + if (inv_s_abbd < SMALL) + inv_s_abbd = SMALL; + inv_s_abbd = 1.0 / inv_s_abbd; + + Scalar c_baac = nab.x * nac.x + nab.y * nac.y + nab.z * nac.z; + if (c_baac > 1.0) + c_baac = 1.0; + if (c_baac < -1.0) + c_baac = -1.0; + + Scalar inv_s_baac = sqrt(1.0 - c_baac * c_baac); + if (inv_s_baac < SMALL) + inv_s_baac = SMALL; + inv_s_baac = 1.0 / inv_s_baac; + + Scalar c_baad = nab.x * nad.x + nab.y * nad.y + nab.z * nad.z; + if (c_baad > 1.0) + c_baad = 1.0; + if (c_baad < -1.0) + c_baad = -1.0; + + Scalar inv_s_baad = sqrt(1.0 - c_baad * c_baad); + if (inv_s_baad < SMALL) + inv_s_baad = SMALL; + inv_s_baad = 1.0 / inv_s_baad; + + + + + + Scalar c_caad = nac.x * nad.x + nac.y * nad.y + nac.z * nad.z; + if (c_caad > 1.0) + c_caad = 1.0; + if (c_caad < -1.0) + c_caad = -1.0; + + Scalar inv_s_caad = sqrt(1.0 - c_caad * c_caad); + if (inv_s_caad < SMALL) + inv_s_caad = SMALL; + inv_s_caad = 1.0 / inv_s_caad; + + Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; + if (c_cbbd > 1.0) + c_cbbd = 1.0; + if (c_cbbd < -1.0) + c_cbbd = -1.0; + + Scalar inv_s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); + if (inv_s_cbbd < SMALL) + inv_s_cbbd = SMALL; + inv_s_cbbd = 1.0 / inv_s_cbbd; + + Scalar c_accd = -(nac.x * ncd.x + nac.y * ncd.y + nac.z * ncd.z); + if (c_accd > 1.0) + c_accd = 1.0; + if (c_accd < -1.0) + c_accd = -1.0; + + Scalar inv_s_accd = sqrt(1.0 - c_accd * c_accd); + if (inv_s_accd < SMALL) + inv_s_accd = SMALL; + inv_s_accd = 1.0 / inv_s_accd; + + Scalar c_addc = nad.x * ncd.x + nad.y * ncd.y + nad.z * ncd.z; + if (c_addc > 1.0) + c_addc = 1.0; + if (c_addc < -1.0) + c_addc = -1.0; + + Scalar inv_s_addc = sqrt(1.0 - c_addc * c_addc); + if (inv_s_addc < SMALL) + inv_s_addc = SMALL; + inv_s_addc = 1.0 / inv_s_addc; + + Scalar c_bccd = -(nbc.x * ncd.x + nbc.y * ncd.y + nbc.z * ncd.z); + if (c_bccd > 1.0) + c_bccd = 1.0; + if (c_bccd < -1.0) + c_bccd = -1.0; + + Scalar inv_s_bccd = sqrt(1.0 - c_bccd * c_bccd); + if (inv_s_bccd < SMALL) + inv_s_bccd = SMALL; + inv_s_bccd = 1.0 / inv_s_bccd; + + Scalar c_bddc = nbd.x * ncd.x + nbd.y * ncd.y + nbd.z * ncd.z; + if (c_bddc > 1.0) + c_bddc = 1.0; + if (c_bddc < -1.0) + c_bddc = -1.0; + + Scalar inv_s_bddc = sqrt(1.0 - c_bddc * c_bddc); + if (inv_s_bddc < SMALL) + inv_s_bddc = SMALL; + inv_s_bddc = 1.0 / inv_s_bddc; + + Scalar cot_accb = c_accb * inv_s_accb; + Scalar cot_addb = c_addb * inv_s_addb; + Scalar cot_baac = c_baac * inv_s_baac; + Scalar cot_baad = c_baad * inv_s_baad; + Scalar cot_abbc = c_abbc * inv_s_abbc; + Scalar cot_abbd = c_abbd * inv_s_abbd; + + Scalar cot_caad = c_caad * inv_s_caad; + Scalar cot_cbbd = c_cbbd * inv_s_cbbd; + Scalar cot_accd = c_accd * inv_s_accd; + Scalar cot_addc = c_addc * inv_s_addc; + Scalar cot_bccd = c_bccd * inv_s_bccd; + Scalar cot_bddc = c_bddc * inv_s_bddc; + + Scalar sigma_hat_ab = -(cot_accb + cot_addb) * 0.5; + Scalar sigma_hat_cd = (cot_caad + cot_cbbd) * 0.5; + Scalar sigma_hat_ac = (cot_addc - cot_abbc) * 0.5; + Scalar sigma_hat_ad = (cot_accd - cot_abbd) * 0.5; + Scalar sigma_hat_bc = (cot_bddc - cot_baac) * 0.5; + Scalar sigma_hat_bd = (cot_bccd - cot_baad) * 0.5; + + Scalar sigma_a = h_sigma.data[idx_a]; // precomputed + Scalar sigma_b = h_sigma.data[idx_b]; // precomputed + Scalar sigma_c = h_sigma.data[idx_c]; // precomputed + Scalar sigma_d = h_sigma.data[idx_d]; // precomputed + + m_sigma_diff_a = (sigma_hat_ab * rsqab + sigma_hat_ac * rsqac + sigma_hat_ad * rsqad) * 0.25; + m_sigma_diff_b = (sigma_hat_ab * rsqab + sigma_hat_bc * rsqbc + sigma_hat_bd * rsqbd) * 0.25; + m_sigma_diff_c = (sigma_hat_ac * rsqac + sigma_hat_bc * rsqbc + sigma_hat_cd * rsqcd) * 0.25; + m_sigma_diff_d = (sigma_hat_ad * rsqad + sigma_hat_bd * rsqbd + sigma_hat_cd * rsqcd) * 0.25; + + Scalar sigma_a_n = sigma_a + m_sigma_diff_a; + Scalar sigma_b_n = sigma_b + m_sigma_diff_b; + Scalar sigma_c_n = sigma_c + m_sigma_diff_c; + Scalar sigma_d_n = sigma_d + m_sigma_diff_d; + + Scalar3 sigma_dash_a = h_sigma_dash.data[idx_a]; // precomputed + Scalar3 sigma_dash_b = h_sigma_dash.data[idx_b]; // precomputed + Scalar3 sigma_dash_c = h_sigma_dash.data[idx_c]; // precomputed + Scalar3 sigma_dash_d = h_sigma_dash.data[idx_d]; // precomputed + + m_sigma_dash_diff_a = sigma_hat_ab * dab + sigma_hat_ac * dac + sigma_hat_ad * dad; + m_sigma_dash_diff_b = -sigma_hat_ab * dab + sigma_hat_bc * dbc + sigma_hat_bd * dbd; + m_sigma_dash_diff_c = -sigma_hat_ac * dac - sigma_hat_bc * dbc + sigma_hat_cd * dcd; + m_sigma_dash_diff_d = -sigma_hat_ad * dad - sigma_hat_bd * dbd - sigma_hat_cd * dcd; + + Scalar3 sigma_dash_a_n = sigma_dash_a + m_sigma_dash_diff_a; + Scalar3 sigma_dash_b_n = sigma_dash_b + m_sigma_dash_diff_b; + Scalar3 sigma_dash_c_n = sigma_dash_c + m_sigma_dash_diff_c; + Scalar3 sigma_dash_d_n = sigma_dash_d + m_sigma_dash_diff_d; + + Scalar energy_old = dot(sigma_dash_a, sigma_dash_a) / sigma_a; + energy_old += (dot(sigma_dash_b, sigma_dash_b) / sigma_b); + energy_old += (dot(sigma_dash_c, sigma_dash_c) / sigma_c); + energy_old += (dot(sigma_dash_d, sigma_dash_d) / sigma_d); + + Scalar energy_new = dot(sigma_dash_a_n, sigma_dash_a_n) / sigma_a_n; + energy_new += (dot(sigma_dash_b_n, sigma_dash_b_n) / sigma_b_n); + energy_new += (dot(sigma_dash_c_n, sigma_dash_c_n) / sigma_c_n); + energy_new += (dot(sigma_dash_d_n, sigma_dash_d_n) / sigma_d_n); + + if (energy_new < 0) + return DBL_MAX; + + return h_params.data[type_id] * 0.5 * (energy_new - energy_old); + } + +void HelfrichMeshForceCompute::postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d) + { + ArrayHandle h_sigma(m_sigma, access_location::host, access_mode::readwrite); + ArrayHandle h_sigma_dash(m_sigma_dash, access_location::host, access_mode::readwrite); + + h_sigma.data[idx_a] += m_sigma_diff_a; + h_sigma.data[idx_b] += m_sigma_diff_b; + h_sigma.data[idx_c] += m_sigma_diff_c; + h_sigma.data[idx_d] += m_sigma_diff_d; + + h_sigma_dash.data[idx_a] += m_sigma_dash_diff_a; + h_sigma_dash.data[idx_b] += m_sigma_dash_diff_b; + h_sigma_dash.data[idx_c] += m_sigma_dash_diff_c; + h_sigma_dash.data[idx_d] += m_sigma_dash_diff_d; + } + namespace detail { void export_HelfrichMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index 33d4b5fc55..501838081c 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -70,11 +70,32 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute GPUArray m_sigma; //! sum of the vectors weighted by the bending angle over all neighbors + Scalar m_sigma_diff_a; + Scalar m_sigma_diff_b; + Scalar m_sigma_diff_c; + Scalar m_sigma_diff_d; + + Scalar3 m_sigma_dash_diff_a; + Scalar3 m_sigma_dash_diff_b; + Scalar3 m_sigma_dash_diff_c; + Scalar3 m_sigma_dash_diff_d; + //! Actually compute the forces virtual void computeForces(uint64_t timestep); + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); + //! compute sigmas virtual void precomputeParameter(); + + virtual void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d); }; namespace detail From fc1fb5b027446ef8ac0e55ba5cac5a22957d8d2a Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 25 Mar 2025 22:42:45 -0400 Subject: [PATCH 13/58] prepare TriangleArea --- ...riangleAreaConservationMeshForceCompute.cc | 91 +++++++++++++++++++ ...TriangleAreaConservationMeshForceCompute.h | 6 ++ 2 files changed, 97 insertions(+) diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc index 60f8175a3d..4641c824ba 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc @@ -296,6 +296,97 @@ void TriangleAreaConservationMeshForceCompute::computeForces(uint64_t timestep) h_area.data[i] = global_area[i]; } +Scalar TriangleAreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + + ArrayHandle h_params(m_params, + access_location::host, + access_mode::read); + + const BoxDim& box = m_pdata->getGlobalBox(); + + // calculate d\vec{r} + Scalar3 dac; + dac.x = h_pos.data[idx_a].x - h_pos.data[idx_c].x; + dac.y = h_pos.data[idx_a].y - h_pos.data[idx_c].y; + dac.z = h_pos.data[idx_a].z - h_pos.data[idx_c].z; + + Scalar3 dad; + dad.x = h_pos.data[idx_a].x - h_pos.data[idx_d].x; + dad.y = h_pos.data[idx_a].y - h_pos.data[idx_d].y; + dad.z = h_pos.data[idx_a].z - h_pos.data[idx_d].z; + + Scalar3 dbc; + dbc.x = h_pos.data[idx_b].x - h_pos.data[idx_c].x; + dbc.y = h_pos.data[idx_b].y - h_pos.data[idx_c].y; + dbc.z = h_pos.data[idx_b].z - h_pos.data[idx_c].z; + + Scalar3 dbd; + dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; + dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; + dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + + // apply minimum image conventions to all 3 vectors + dac = box.minImage(dac); + dad = box.minImage(dad); + dbc = box.minImage(dbc); + dbd = box.minImage(dbd); + + Scalar rac = sqrt(dac.x * dac.x + dac.y * dac.y + dac.z * dac.z); + Scalar rad = sqrt(dad.x * dad.x + dad.y * dad.y + dad.z * dad.z); + Scalar rbc = sqrt(dbc.x * dbc.x + dbc.y * dbc.y + dbc.z * dbc.z); + Scalar rbd = sqrt(dbd.x * dbd.x + dbd.y * dbd.y + dbd.z * dbd.z); + + Scalar3 nac = dac / rac; + Scalar3 nad = dad / rad; + Scalar3 nbc = dbc / rbc; + Scalar3 nbd = dbd / rbd; + + Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; + if (c_accb > 1.0) + c_accb = 1.0; + if (c_accb < -1.0) + c_accb = -1.0; + + Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; + if (c_addb > 1.0) + c_addb = 1.0; + if (c_addb < -1.0) + c_addb = -1.0; + + Scalar c_caad = nac.x * nad.x + nac.y * nad.y + nac.z * nad.z; + if (c_caad > 1.0) + c_caad = 1.0; + if (c_caad < -1.0) + c_caad = -1.0; + + Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; + if (c_cbbd > 1.0) + c_cbbd = 1.0; + if (c_cbbd < -1.0) + c_cbbd = -1.0; + + Scalar s_accb = sqrt(1.0 - c_accb * c_accb); + Scalar s_addb = sqrt(1.0 - c_addb * c_addb); + Scalar s_caad = sqrt(1.0 - c_caad * c_caad); + Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); + + Scalar energy_old1 = rac * rbc * s_accb / 2.0 - h_params.data[type_id].A0; + Scalar energy_old2 = rad * rbd * s_addb / 2.0 - h_params.data[type_id].A0; + + Scalar energy_new1 = rac * rad * s_caad / 2.0 - h_params.data[type_id].A0; + Scalar energy_new2 = rbc * rbd * s_cbbd / 2.0 - h_params.data[type_id].A0; + + return h_params.data[type_id].k / (2.0 * h_params.data[type_id].A0) + * (energy_new1 * energy_new1 + energy_new2 * energy_new2 - energy_old1 * energy_old1 + - energy_old2 * energy_old2); + } + namespace detail { void export_TriangleAreaConservationMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.h b/hoomd/md/TriangleAreaConservationMeshForceCompute.h index 42cd160311..3f698a5194 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.h +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.h @@ -75,6 +75,12 @@ class PYBIND11_EXPORT TriangleAreaConservationMeshForceCompute : public ForceCom //! Actually compute the forces virtual void computeForces(uint64_t timestep); + + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); }; namespace detail From b0865750405819bd7ed12e6d7d9fff2a97319191 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 26 Mar 2025 10:27:19 -0400 Subject: [PATCH 14/58] prepare AreaConservationMeshForceCompute --- hoomd/md/AreaConservationMeshForceCompute.cc | 97 ++++++++++++++++++++ hoomd/md/AreaConservationMeshForceCompute.h | 19 +++- hoomd/md/HelfrichMeshForceCompute.cc | 3 +- hoomd/md/HelfrichMeshForceCompute.h | 3 +- hoomd/md/MeshDynamicBondUpdater.cc | 2 +- 5 files changed, 120 insertions(+), 4 deletions(-) diff --git a/hoomd/md/AreaConservationMeshForceCompute.cc b/hoomd/md/AreaConservationMeshForceCompute.cc index a3deb385f9..9f9ddffb6c 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.cc +++ b/hoomd/md/AreaConservationMeshForceCompute.cc @@ -388,6 +388,103 @@ void AreaConservationMeshForceCompute::precomputeParameter() h_area.data[i] = global_area[i]; } +Scalar AreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + + ArrayHandle h_params(m_params, + access_location::host, + access_mode::read); + + ArrayHandle h_area(m_area, access_location::host, access_mode::read); + + const BoxDim& box = m_pdata->getGlobalBox(); + + // calculate d\vec{r} + Scalar3 dac; + dac.x = h_pos.data[idx_a].x - h_pos.data[idx_c].x; + dac.y = h_pos.data[idx_a].y - h_pos.data[idx_c].y; + dac.z = h_pos.data[idx_a].z - h_pos.data[idx_c].z; + + Scalar3 dad; + dad.x = h_pos.data[idx_a].x - h_pos.data[idx_d].x; + dad.y = h_pos.data[idx_a].y - h_pos.data[idx_d].y; + dad.z = h_pos.data[idx_a].z - h_pos.data[idx_d].z; + + Scalar3 dbc; + dbc.x = h_pos.data[idx_b].x - h_pos.data[idx_c].x; + dbc.y = h_pos.data[idx_b].y - h_pos.data[idx_c].y; + dbc.z = h_pos.data[idx_b].z - h_pos.data[idx_c].z; + + Scalar3 dbd; + dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; + dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; + dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + + // apply minimum image conventions to all 3 vectors + dac = box.minImage(dac); + dad = box.minImage(dad); + dbc = box.minImage(dbc); + dbd = box.minImage(dbd); + + Scalar rac = sqrt(dac.x * dac.x + dac.y * dac.y + dac.z * dac.z); + Scalar rad = sqrt(dad.x * dad.x + dad.y * dad.y + dad.z * dad.z); + Scalar rbc = sqrt(dbc.x * dbc.x + dbc.y * dbc.y + dbc.z * dbc.z); + Scalar rbd = sqrt(dbd.x * dbd.x + dbd.y * dbd.y + dbd.z * dbd.z); + + Scalar3 nac = dac / rac; + Scalar3 nad = dad / rad; + Scalar3 nbc = dbc / rbc; + Scalar3 nbd = dbd / rbd; + + Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; + if (c_accb > 1.0) + c_accb = 1.0; + if (c_accb < -1.0) + c_accb = -1.0; + + Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; + if (c_addb > 1.0) + c_addb = 1.0; + if (c_addb < -1.0) + c_addb = -1.0; + + Scalar c_caad = nac.x * nad.x + nac.y * nad.y + nac.z * nad.z; + if (c_caad > 1.0) + c_caad = 1.0; + if (c_caad < -1.0) + c_caad = -1.0; + + Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; + if (c_cbbd > 1.0) + c_cbbd = 1.0; + if (c_cbbd < -1.0) + c_cbbd = -1.0; + + Scalar s_accb = sqrt(1.0 - c_accb * c_accb); + Scalar s_addb = sqrt(1.0 - c_addb * c_addb); + Scalar s_caad = sqrt(1.0 - c_caad * c_caad); + Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); + + m_area_diff = rac * rad * s_caad + rbc * rbd * s_cbbd; + m_area_diff -= (rac * rbc * s_accb + rad * rbd * s_addb); + + m_area_diff /= 2.0; + + Scalar AreaDiff = h_area.data[type_id] - h_params.data[type_id].A0; + + Scalar energy_old = AreaDiff * AreaDiff; + + Scalar energy_new = (AreaDiff + m_area_diff) * (AreaDiff + m_area_diff); + + return h_params.data[type_id].k * (energy_new - energy_old) + / (2 * h_params.data[type_id].A0); + } + namespace detail { void export_AreaConservationMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/AreaConservationMeshForceCompute.h b/hoomd/md/AreaConservationMeshForceCompute.h index e81ab797bd..86b0dd6998 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.h +++ b/hoomd/md/AreaConservationMeshForceCompute.h @@ -73,7 +73,7 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public ForceCompute protected: GPUArray m_params; //!< Parameters GPUArray m_area; //!< memory space for area - // + Scalar m_area_diff; std::shared_ptr m_mesh_data; //!< Mesh data to use in computing energy bool m_ignore_type; //! ignore type to calculate global area if true @@ -82,6 +82,23 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public ForceCompute //! compute areas virtual void precomputeParameter(); + + virtual void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_area(m_area, access_location::host, access_mode::readwrite); + h_area.data[type_id] += m_area_diff; + }; + + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); + }; namespace detail diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 36a33062ba..8226a10fba 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -824,7 +824,8 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, void HelfrichMeshForceCompute::postcomputeParameter(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, - unsigned int idx_d) + unsigned int idx_d, + unsigned int type_id) { ArrayHandle h_sigma(m_sigma, access_location::host, access_mode::readwrite); ArrayHandle h_sigma_dash(m_sigma_dash, access_location::host, access_mode::readwrite); diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index 501838081c..bc4e059a02 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -95,7 +95,8 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute virtual void postcomputeParameter(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, - unsigned int idx_d); + unsigned int idx_d, + unsigned int type_id); }; namespace detail diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 551a1b0704..bd6d96bda4 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -326,7 +326,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) for (auto& force : forces) { - force->postcompute(idx_a, idx_b, idx_cc, idx_dd); + force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); } m_mesh->getMeshBondData()->meshChanged(); m_mesh->getMeshTriangleData()->meshChanged(); From 85d2e831dc71ae03e757adadada5a00d7fb8af9d Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 26 Mar 2025 10:29:12 -0400 Subject: [PATCH 15/58] update ForceCompute --- hoomd/ForceCompute.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index f683e35246..9f835e9f93 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -96,7 +96,8 @@ class PYBIND11_EXPORT ForceCompute : public Compute virtual void postcomputeParameter(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, - unsigned int idx_d){}; + unsigned int idx_d, + unsigned int type_id){}; virtual bool checkSurrounding(){ return false;} From fbdebfda59525ffa9c5200333f6ba9fc8717130d Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 26 Mar 2025 11:56:12 -0400 Subject: [PATCH 16/58] update BendingRigidity --- hoomd/md/BendingRigidityMeshForceCompute.cc | 87 +++++++++++++++++++ hoomd/md/BendingRigidityMeshForceCompute.h | 25 ++++++ .../md/VolumeConservationMeshForceCompute.cc | 44 ++++++++++ hoomd/md/VolumeConservationMeshForceCompute.h | 20 +++++ 4 files changed, 176 insertions(+) diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index ee0d85afec..870ef5b149 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -296,6 +296,93 @@ void BendingRigidityMeshForceCompute::computeForces(uint64_t timestep) } } +Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + + ArrayHandle h_params(m_params, access_location::host, access_mode::read); + + const BoxDim& box = m_pdata->getGlobalBox(); + Scalar3 dab; + dab.x = h_pos.data[idx_a].x - h_pos.data[idx_b].x; + dab.y = h_pos.data[idx_a].y - h_pos.data[idx_b].y; + dab.z = h_pos.data[idx_a].z - h_pos.data[idx_b].z; + + Scalar3 dac; + dac.x = h_pos.data[idx_a].x - h_pos.data[idx_c].x; + dac.y = h_pos.data[idx_a].y - h_pos.data[idx_c].y; + dac.z = h_pos.data[idx_a].z - h_pos.data[idx_c].z; + + Scalar3 dbd; + dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; + dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; + dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + + // apply minimum image conventions to all 3 vectors + dab = box.minImage(dab); + dac = box.minImage(dac); + dbd = box.minImage(dbd); + + Scalar3 z1; + z1.x = dab.y * dac.z - dab.z * dac.y; + z1.y = dab.z * dac.x - dab.x * dac.z; + z1.z = dab.x * dac.y - dab.y * dac.x; + + Scalar3 z2; + z2.x = -dbd.y * dab.z + dbd.z * dab.y; + z2.y = -dbd.z * dab.x + dbd.x * dab.z; + z2.z = -dbd.x * dab.y + dbd.y * dab.x; + + Scalar n1 = fast::rsqrt(z1.x * z1.x + z1.y * z1.y + z1.z * z1.z); + Scalar n2 = fast::rsqrt(z2.x * z2.x + z2.y * z2.y + z2.z * z2.z); + Scalar z1z2 = z1.x * z2.x + z1.y * z2.y + z1.z * z2.z; + + Scalar cosinus = z1z2 * n1 * n2; + + return h_params.data[type_id] * 0.5 * (1-cosinus); + } + +Scalar BendingRigidityMeshForceCompute::energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + Scalar energy_old = calcEnergy(idx_a,idx_b,idx_c,idx_d,type_id); + Scalar energy_new = calcEnergy(idx_c,idx_d,idx_b,idx_a,type_id); + + return energy_new-energy_old; + } + +Scalar BendingRigidityMeshForceCompute::energyDiffSurrounding(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int idx_e, + unsigned int idx_f, + unsigned int idx_g, + unsigned int idx_h, + unsigned int type_id) + { + Scalar energy = calcEnergy(idx_a,idx_c,idx_e,idx_d,type_id); + energy += calcEnergy(idx_c,idx_b,idx_f,idx_d,type_id); + energy += calcEnergy(idx_a,idx_d,idx_c,idx_g,type_id); + energy += calcEnergy(idx_d,idx_b,idx_c,idx_h,type_id); + + energy -= calcEnergy(idx_a,idx_c,idx_e,idx_b,type_id); + energy -= calcEnergy(idx_c,idx_b,idx_f,idx_a,type_id); + energy -= calcEnergy(idx_a,idx_d,idx_b,idx_g,type_id); + energy -= calcEnergy(idx_d,idx_b,idx_a,idx_h,type_id); + + return energy; + } + + + namespace detail { void export_BendingRigidityMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/BendingRigidityMeshForceCompute.h b/hoomd/md/BendingRigidityMeshForceCompute.h index 720f0c5c6b..1d81868968 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.h +++ b/hoomd/md/BendingRigidityMeshForceCompute.h @@ -89,6 +89,31 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public ForceCompute //! Actually compute the forces virtual void computeForces(uint64_t timestep); + + virtual Scalar calcEnergy(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); + + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); + + virtual Scalar energyDiffSurrounding(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int idx_e, + unsigned int idx_f, + unsigned int idx_g, + unsigned int idx_h, + unsigned int type_id); + + virtual bool checkSurrounding(){return true;} + }; namespace detail diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index b2b037460e..b5c5024bed 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -354,6 +354,50 @@ void VolumeConservationMeshForceCompute::precomputeParameter() h_volume.data[i] = global_volume[i]; } +Scalar VolumeConservationMeshForceCompute::energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + ArrayHandle h_image(m_pdata->getImages(), access_location::host, access_mode::read); + + ArrayHandle h_params(m_params, + access_location::host, + access_mode::read); + + ArrayHandle h_volume(m_volume, access_location::host, access_mode::read); + + const BoxDim& box = m_pdata->getGlobalBox(); + + vec3 pos_a(h_pos.data[idx_a].x, h_pos.data[idx_a].y, h_pos.data[idx_a].z); + vec3 pos_b(h_pos.data[idx_b].x, h_pos.data[idx_b].y, h_pos.data[idx_b].z); + vec3 pos_c(h_pos.data[idx_c].x, h_pos.data[idx_c].y, h_pos.data[idx_c].z); + vec3 pos_d(h_pos.data[idx_d].x, h_pos.data[idx_d].y, h_pos.data[idx_d].z); + + pos_a = box.shift(pos_a, h_image.data[idx_a]); + pos_b = box.shift(pos_b, h_image.data[idx_b]); + pos_c = box.shift(pos_c, h_image.data[idx_c]); + pos_d = box.shift(pos_d, h_image.data[idx_d]); + + Scalar volume_old = dot(cross(pos_c, pos_b), pos_a) + dot(cross(pos_d, pos_a), pos_b); + + Scalar volume_new = dot(cross(pos_a, pos_c), pos_d) + dot(cross(pos_b, pos_d), pos_c); + + m_volume_diff = (volume_new-volume_old)/6.0; + + Scalar energy_old = h_volume.data[type_id] - h_params.data[type_id].V0; + + Scalar energy_new = energy_old + m_volume_diff; + + energy_old = energy_old * energy_old; + + energy_new = energy_new * energy_new; + + return h_params.data[type_id].k / (2.0 * h_params.data[type_id].V0) * (energy_new - energy_old); + } + namespace detail { void export_VolumeConservationMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index b211936cc2..e12f0a4528 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -78,6 +78,8 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public ForceCompute GPUArray m_volume; //!< memory space for volume + Scalar m_volume_diff; + bool m_ignore_type; //! do we ignore type to calculate global area //! Actually compute the forces @@ -85,6 +87,24 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public ForceCompute //! compute volumes virtual void precomputeParameter(); + + virtual void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_volume(m_volume, access_location::host, access_mode::readwrite); + h_volume.data[type_id] += m_volume_diff; + }; + + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); + + }; namespace detail From d8b348884e51592ce1d55a433fc57a88fd861be6 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 26 Mar 2025 19:03:03 -0400 Subject: [PATCH 17/58] compiling version --- hoomd/ForceCompute.h | 3 +- hoomd/MeshDefinition.cc | 16 ++++--- hoomd/RNGIdentifiers.h | 1 + hoomd/md/CMakeLists.txt | 2 + hoomd/md/MeshDynamicBondUpdater.cc | 68 +++++++++++++----------------- hoomd/md/MeshDynamicBondUpdater.h | 10 ++++- hoomd/md/PotentialBond.h | 51 ++++++++++++++++++++++ hoomd/md/module-md.cc | 3 ++ hoomd/md/update.py | 56 ++++++++++++++++++++++++ 9 files changed, 161 insertions(+), 49 deletions(-) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index 9f835e9f93..09651471b9 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -91,7 +91,8 @@ class PYBIND11_EXPORT ForceCompute : public Compute unsigned int idx_e, unsigned int idx_f, unsigned int idx_g, - unsigned int idx_h){ return 0;}; + unsigned int idx_h, + unsigned int type_id){ return 0;}; virtual void postcomputeParameter(unsigned int idx_a, unsigned int idx_b, diff --git a/hoomd/MeshDefinition.cc b/hoomd/MeshDefinition.cc index 3af6ea63bc..045331e4be 100644 --- a/hoomd/MeshDefinition.cc +++ b/hoomd/MeshDefinition.cc @@ -131,13 +131,6 @@ void MeshDefinition::setTriangulationData(pybind11::dict triangulation) m_meshbond_data = std::shared_ptr( new MeshBondData(m_sysdef->getParticleData(), triangle_data)); - GPUArray neigh_to_triag(len_triang, m_sysdef->getParticleData()->getExecConf()); - m_neigh_to_triag.swap(neigh_to_triag); - - unsigned int len_bond = m_meshbond_data->getNGlobal(); - GPUArray neigh_to_bond(len_bond, m_sysdef->getParticleData()->getExecConf()); - m_neigh_to_bond.swap(neigh_to_bond); - createMeshNeighborhood(); @@ -156,6 +149,15 @@ void MeshDefinition::setTriangulationData(pybind11::dict triangulation) void MeshDefinition::createMeshNeighborhood() { + + unsigned int len_triang = m_meshtriangle_data->getNGlobal(); + GPUArray neigh_to_triag(len_triang, m_sysdef->getParticleData()->getExecConf()); + m_neigh_to_triag.swap(neigh_to_triag); + + unsigned int len_bond = m_meshbond_data->getNGlobal(); + GPUArray neigh_to_bond(len_bond, m_sysdef->getParticleData()->getExecConf()); + m_neigh_to_bond.swap(neigh_to_bond); + ArrayHandle h_neigh_to_bond(m_neigh_to_bond, access_location::host, access_mode::overwrite); ArrayHandle h_neigh_to_triag(m_neigh_to_triag, access_location::host, access_mode::overwrite); diff --git a/hoomd/RNGIdentifiers.h b/hoomd/RNGIdentifiers.h index dd1bef91fc..1f1cfcf3cd 100644 --- a/hoomd/RNGIdentifiers.h +++ b/hoomd/RNGIdentifiers.h @@ -70,6 +70,7 @@ struct RNGIdentifier static const uint8_t BussiThermostat = 45; static const uint8_t ConstantPressure = 46; static const uint8_t MPCDCellList = 47; + static const uint8_t MeshDynamicBondUpdater = 48; }; } // namespace hoomd diff --git a/hoomd/md/CMakeLists.txt b/hoomd/md/CMakeLists.txt index ea74bc3949..395305d97e 100644 --- a/hoomd/md/CMakeLists.txt +++ b/hoomd/md/CMakeLists.txt @@ -36,6 +36,7 @@ set(_md_sources module-md.cc ManifoldXYPlane.cc ManifoldPrimitive.cc ManifoldSphere.cc + MeshDynamicBondUpdater.cc MolecularForceCompute.cc MuellerPlatheFlow.cc NeighborListBinned.cc @@ -154,6 +155,7 @@ set(_md_headers ActiveForceComputeGPU.h ManifoldXYPlane.h ManifoldPrimitive.h ManifoldSphere.h + MeshDynamicBondUpdater.h MolecularForceCompute.cuh MolecularForceCompute.h MuellerPlatheFlowEnum.h diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index bd6d96bda4..e7200a1779 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -24,14 +24,15 @@ namespace md MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr sysdef, std::shared_ptr trigger, - std::shared_ptr integrator, std::shared_ptr mesh, Scalar T) - : Updater(sysdef, trigger), m_integrator(integrator), m_mesh(mesh), m_inv_T(1.0 / T) + : Updater(sysdef, trigger), m_mesh(mesh), m_inv_T(1.0 / T) { assert(m_pdata); - assert(m_integrator); assert(m_mesh); + + m_mesh->createMeshNeighborhood(); + m_exec_conf->msg->notice(5) << "Constructing MeshDynamicBondUpdater" << endl; } @@ -46,11 +47,9 @@ MeshDynamicBondUpdater::~MeshDynamicBondUpdater() */ void MeshDynamicBondUpdater::update(uint64_t timestep) { - std::vector> forces = m_integrator->getForces(); - uint16_t seed = m_sysdef->getSeed(); - for (auto& force : forces) + for (auto& force : m_forces) { force->precomputeParameter(); } @@ -59,16 +58,16 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) access_location::host, access_mode::readwrite); - ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond()->getMembersArray(), + ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond(), access_location::host, access_mode::readwrite); - ArrayHandle h_triangles( + ArrayHandle h_triangles( m_mesh->getMeshTriangleData()->getMembersArray(), access_location::host, access_mode::readwrite); - ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag()->getMembersArray(), + ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag(), access_location::host, access_mode::readwrite); @@ -83,13 +82,11 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) // for each of the angles const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); - bool changeDetected = false; - std::vector changed; for (unsigned int i = 0; i < size; i++) { - const typename MeshBond::members_t& bond = h_bonds.data[i]; + typename MeshBond::members_t& bond = h_bonds.data[i]; assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); @@ -101,9 +98,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_a = h_rtag.data[tag_a]; unsigned int idx_b = h_rtag.data[tag_b]; - unsigned int type_a = __scalar_as_int(h_pos.data[idx_a].w); - unsigned int type_b = __scalar_as_int(h_pos.data[idx_b].w); - //bool already_used = false; //for (unsigned int j = 0; j < changed.size(); j++) // { @@ -129,12 +123,11 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int tr_idx1 = h_neigh_bonds.data[i].x; unsigned int tr_idx2 = h_neigh_bonds.data[i].y; - const typename MeshTriangle::members_t& triangle1 = h_triangles.data[tr_idx1]; + typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; unsigned int iterator = 0; bool a_before_b = false; - bool tr1_with_c = false; while (tag_a != triangle1.tag[iterator]) iterator++; @@ -147,9 +140,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) iterator = (iterator + 1) % 3; } - if(tag_c == triangle1.tag[iterator]) - tr1_with_c = true; - unsigned int type_id = h_typeval.data[i].type; Scalar energyDifference = 0; @@ -164,7 +154,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } bool have_to_check_surrounding = false; - for (auto& force : forces) + for (auto& force : m_forces) { energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); @@ -186,7 +176,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector b_idx(4); std::vector v_idx(8); - if (have_to_check_surrounding || part_func > random_number ) + if (have_to_check_surrounding || part_func > rand_number ) { tr_idx[1] = tr_idx1; tr_idx[0] = tr_idx2; @@ -200,7 +190,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) v_idx[1]=idx_b; v_idx[2]=idx_cc; v_idx[3]=idx_dd; - counter = 4; + unsigned int counter = 4; for(unsigned int j = 0; j < 2; ++j) { @@ -230,7 +220,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { unsigned int tic = h_neigh_bonds.data[b_idx[2*j+k]].x; if(tic == tr_idx[j]) - tic = h_neigh_bonds.data[bic_idx[2*j+k]].y; + tic = h_neigh_bonds.data[b_idx[2*j+k]].y; unsigned int zaehler = 1; unsigned int nv_idx = h_triangles.data[tic].tag[0]; while(nv_idx == v_idx[k] || nv_idx == v_idx[2+j]) @@ -239,20 +229,20 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) zaehler++; } v_idx[counter] = nv_idx; - tr_idx[counter-2] = = tic; + tr_idx[counter-2] = tic; counter++; } } if (have_to_check_surrounding) { - for (auto& force : forces) + for (auto& force : m_forces) energyDifference += force->energyDiffSurrounding(v_idx[0],v_idx[1],v_idx[2],v_idx[3],v_idx[4],v_idx[5],v_idx[6],v_idx[7], type_id); part_func = exp(-m_inv_T * energyDifference); } } - if (part_func > random_number) + if (part_func > rand_number) { bond.tag[0] = v_idx[2]; bond.tag[1] = v_idx[3]; @@ -270,12 +260,12 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) triangle1.tag[0] = v_idx[0]; triangle1.tag[1] = v_idx[3]; triangle1.tag[2] = v_idx[2]; - h_triangles[tr_idx[0]] = triangle1; // triangle a,b,c to a,d,c + h_triangles.data[tr_idx[0]] = triangle1; // triangle a,b,c to a,d,c triangle1.tag[0] = v_idx[1]; triangle1.tag[1] = v_idx[2]; triangle1.tag[2] = v_idx[3]; - h_triangles[tr_idx[1]] = triangle2; // triangle b,a,d to b,c,d + h_triangles.data[tr_idx[1]] = triangle1; // triangle b,a,d to b,c,d bond = h_bonds.data[b_idx[0]]; bond.tag[2] = v_idx[3]; @@ -302,34 +292,34 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) tris.x = tr_idx[0]; tris.y = tr_idx[2]; - h_neight_bonds.data[b_idx[0]] = tris; + h_neigh_bonds.data[b_idx[0]] = tris; tris.y = tr_idx[4]; - h_neight_bonds.data[b_idx[2]] = tris; + h_neigh_bonds.data[b_idx[2]] = tris; tris.x = tr_idx[1]; tris.y = tr_idx[3]; - h_neight_bonds.data[b_idx[1]] = tris; + h_neigh_bonds.data[b_idx[1]] = tris; tris.y = tr_idx[5]; - h_neight_bonds.data[b_idx[3]] = tris; + h_neigh_bonds.data[b_idx[3]] = tris; bs.x = i; bs.y = b_idx[0]; bs.z = b_idx[2]; - h_neight_triags.data[tr_idx[0]] = bs; + h_neigh_triags.data[tr_idx[0]] = bs; bs.x = i; bs.y = b_idx[1]; bs.z = b_idx[3]; - h_neight_triags.data[tr_idx[1]] = bs; + h_neigh_triags.data[tr_idx[1]] = bs; - for (auto& force : forces) + for (auto& force : m_forces) { force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); } - m_mesh->getMeshBondData()->meshChanged(); - m_mesh->getMeshTriangleData()->meshChanged(); + //m_mesh->getMeshBondData()->meshChanged(); + //m_mesh->getMeshTriangleData()->meshChanged(); } } } @@ -343,9 +333,9 @@ void export_MeshDynamicBondUpdater(pybind11::module& m) "MeshDynamicBondUpdater") .def(pybind11::init, std::shared_ptr, - std::shared_ptr, std::shared_ptr, Scalar>()) + .def_property_readonly("forces", &MeshDynamicBondUpdater::getForces) .def_property("kT", &MeshDynamicBondUpdater::getT, &MeshDynamicBondUpdater::setT); } diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index 4da1299b69..b090e40133 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -41,7 +41,6 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater /// Constructor MeshDynamicBondUpdater(std::shared_ptr sysdef, std::shared_ptr trigger, - std::shared_ptr integrator, std::shared_ptr mesh, Scalar T); @@ -51,6 +50,12 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater /// Update box interpolation based on provided timestep virtual void update(uint64_t timestep); + /// Get the list of force computes + std::vector>& getForces() + { + return m_forces; + } + Scalar getT() { return 1.0 / m_inv_T; @@ -62,7 +67,8 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater }; private: - std::shared_ptr m_integrator; //!< Integrator that advances time in this System + /// List of all the force computes + std::vector> m_forces; std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on Scalar m_inv_T; }; diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index 6d6939aeb1..a59968cd7d 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -66,6 +66,12 @@ template class PotentialBond : public ForceCompute //! Actually compute the forces virtual void computeForces(uint64_t timestep); + + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); }; template @@ -314,6 +320,51 @@ void PotentialBond::computeForces(uint64_t timestep) } } +template +Scalar PotentialBond::energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + // access the parameters + ArrayHandle h_params(m_params, access_location::host, access_mode::read); + + const BoxDim& box = m_pdata->getGlobalBox(); + + Scalar3 posa = make_scalar3(h_pos.data[idx_a].x, h_pos.data[idx_a].y, h_pos.data[idx_a].z); + Scalar3 posb = make_scalar3(h_pos.data[idx_b].x, h_pos.data[idx_b].y, h_pos.data[idx_b].z); + Scalar3 posc = make_scalar3(h_pos.data[idx_c].x, h_pos.data[idx_c].y, h_pos.data[idx_c].z); + Scalar3 posd = make_scalar3(h_pos.data[idx_d].x, h_pos.data[idx_d].y, h_pos.data[idx_d].z); + + Scalar3 xab = posb - posa; + + Scalar3 xcd = posd - posc; + + xab = box.minImage(xab); + xcd = box.minImage(xcd); + + // calculate r_ab squared + Scalar rsqab = dot(xab, xab); + Scalar rsqcd = dot(xcd, xcd); + + // compute the force and potential energy + Scalar force_divr = Scalar(0.0); + Scalar bond_eng1 = Scalar(0.0); + Scalar bond_eng2 = Scalar(0.0); + evaluator eval1(rsqab, h_params.data[type_id]); + evaluator eval2(rsqcd, h_params.data[type_id]); + + eval1.evalForceAndEnergy(force_divr, bond_eng1); + bool evaluated = eval2.evalForceAndEnergy(force_divr, bond_eng2); + + if (evaluated) + return (bond_eng2 - bond_eng1); + else + return DBL_MAX; + } + #ifdef ENABLE_MPI /*! \param timestep Current time step */ diff --git a/hoomd/md/module-md.cc b/hoomd/md/module-md.cc index 13dc32c0ad..01f16fe21c 100644 --- a/hoomd/md/module-md.cc +++ b/hoomd/md/module-md.cc @@ -117,6 +117,8 @@ void export_PotentialExternalWallMorse(pybind11::module& m); void export_PotentialPairDPDThermoDPD(pybind11::module& m); void export_PotentialPairDPDThermoLJ(pybind11::module& m); +void export_MeshDynamicBondUpdater(pybind11::module& m); + void export_IntegratorTwoStep(pybind11::module& m); void export_IntegrationMethodTwoStep(pybind11::module& m); void export_ZeroMomentumUpdater(pybind11::module& m); @@ -544,6 +546,7 @@ PYBIND11_MODULE(_md, m) export_MTTKThermostat(m); export_BussiThermostat(m); export_BerendsenThermostat(m); + export_MeshDynamicBondUpdater(m); export_IntegratorTwoStep(m); export_IntegrationMethodTwoStep(m); diff --git a/hoomd/md/update.py b/hoomd/md/update.py index d96debc783..f4297d730f 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -7,9 +7,11 @@ import hoomd from hoomd.error import SimulationDefinitionError from hoomd.operation import Updater +from hoomd.data import syncedlist from hoomd.data.parameterdicts import ParameterDict from hoomd.data.typeconverter import OnlyTypes from hoomd.logging import log +from hoomd.md.mesh.potential import MeshPotential class ZeroMomentum(Updater): @@ -349,9 +351,63 @@ def _setattr_param(self, attr, value): raise ValueError("active_force is not settable after construction.") super()._setattr_param(attr, value) +#class MeshDynamicalBonding(Updater): +# """Dynamical bonding of the applies mesh that allows edge flips according to a +# Metropolic Monte Carlo algorithm. +# +# Args: +# trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond +# flip attempt. +# +# mesh (hoomd.mesh.Mesh): Mesh data structure. +# +# kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. +# +# forces (Sequence[hoomd.md.force.Force]): Sequence of forces applied to +# the updater. The default value of ``None`` initializes +# an empty list. +# +# Examples:: +# +# mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(100), +# mesh, kT = 1, forces=[]) +# +# """ +# +# def __init__(self, trigger, mesh, kT, forces=[]): +# # initialize base class +# super().__init__(trigger) +# +# self._forces = syncedlist.SyncedList( +# MeshPotential, syncedlist._PartialGetAttr("_cpp_obj"), iterable=forces +# ) +# +# param_dict = ParameterDict(kT=float(kT)) +# +# self._param_dict.update(param_dict) +# +# allow_switch = TypeParameter("allow_switch", +# type_kind="particle_types", +# param_dict=TypeParameterDict(True, +# len_keys=1)) +# +# self._extend_typeparam([allow_switch]) +# +# self._mesh = mesh +# +# def _attach_hook(self): +# # create the c++ mirror class +# +# self._cpp_obj = _md.MeshDynamicBondUpdater( +# self._simulation.state._cpp_sys_def, self.trigger, +# self._mesh._cpp_obj, self.kT) +# +# self._forces._sync(self._simulation, self._cpp_obj.forces) + __all__ = [ "ActiveRotationalDiffusion", "ReversePerturbationFlow", "ZeroMomentum", + #"MeshDynamicalBonding", ] From 5a13772d34c6b1f620e83bea71c051c52ec774d1 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 26 Mar 2025 19:03:50 -0400 Subject: [PATCH 18/58] write python updater object --- hoomd/md/update.py | 106 ++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/hoomd/md/update.py b/hoomd/md/update.py index f4297d730f..2d260f32a3 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -351,63 +351,63 @@ def _setattr_param(self, attr, value): raise ValueError("active_force is not settable after construction.") super()._setattr_param(attr, value) -#class MeshDynamicalBonding(Updater): -# """Dynamical bonding of the applies mesh that allows edge flips according to a -# Metropolic Monte Carlo algorithm. -# -# Args: -# trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond -# flip attempt. -# -# mesh (hoomd.mesh.Mesh): Mesh data structure. -# -# kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. -# -# forces (Sequence[hoomd.md.force.Force]): Sequence of forces applied to -# the updater. The default value of ``None`` initializes -# an empty list. -# -# Examples:: -# -# mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(100), -# mesh, kT = 1, forces=[]) -# -# """ -# -# def __init__(self, trigger, mesh, kT, forces=[]): -# # initialize base class -# super().__init__(trigger) -# -# self._forces = syncedlist.SyncedList( -# MeshPotential, syncedlist._PartialGetAttr("_cpp_obj"), iterable=forces -# ) -# -# param_dict = ParameterDict(kT=float(kT)) -# -# self._param_dict.update(param_dict) -# -# allow_switch = TypeParameter("allow_switch", -# type_kind="particle_types", -# param_dict=TypeParameterDict(True, -# len_keys=1)) -# -# self._extend_typeparam([allow_switch]) -# -# self._mesh = mesh -# -# def _attach_hook(self): -# # create the c++ mirror class -# -# self._cpp_obj = _md.MeshDynamicBondUpdater( -# self._simulation.state._cpp_sys_def, self.trigger, -# self._mesh._cpp_obj, self.kT) -# -# self._forces._sync(self._simulation, self._cpp_obj.forces) +class MeshDynamicalBonding(Updater): + """Dynamical bonding of the applies mesh that allows edge flips according to a + Metropolic Monte Carlo algorithm. + + Args: + trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond + flip attempt. + + mesh (hoomd.mesh.Mesh): Mesh data structure. + + kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. + + forces (Sequence[hoomd.md.force.Force]): Sequence of forces applied to + the updater. The default value of ``None`` initializes + an empty list. + + Examples:: + + mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(100), + mesh, kT = 1, forces=[]) + + """ + + def __init__(self, trigger, mesh, kT, forces=[]): + # initialize base class + super().__init__(trigger) + + self._forces = syncedlist.SyncedList( + MeshPotential, syncedlist._PartialGetAttr("_cpp_obj"), iterable=forces + ) + + param_dict = ParameterDict(kT=float(kT)) + + self._param_dict.update(param_dict) + + allow_switch = TypeParameter("allow_switch", + type_kind="particle_types", + param_dict=TypeParameterDict(True, + len_keys=1)) + + self._extend_typeparam([allow_switch]) + + self._mesh = mesh + + def _attach_hook(self): + # create the c++ mirror class + + self._cpp_obj = _md.MeshDynamicBondUpdater( + self._simulation.state._cpp_sys_def, self.trigger, + self._mesh._cpp_obj, self.kT) + + self._forces._sync(self._simulation, self._cpp_obj.forces) __all__ = [ "ActiveRotationalDiffusion", "ReversePerturbationFlow", "ZeroMomentum", - #"MeshDynamicalBonding", + "MeshDynamicalBonding", ] From 0edc574c59b5e3a5e72f392d0c38c29d47510c37 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Fri, 28 Mar 2025 11:55:43 -0400 Subject: [PATCH 19/58] working Updater without forces list --- hoomd/MeshDefinition.cc | 75 +++++++++--------- hoomd/md/MeshDynamicBondUpdater.cc | 119 +++++++++++++---------------- hoomd/md/update.py | 15 ++-- 3 files changed, 96 insertions(+), 113 deletions(-) diff --git a/hoomd/MeshDefinition.cc b/hoomd/MeshDefinition.cc index 045331e4be..6040df1baa 100644 --- a/hoomd/MeshDefinition.cc +++ b/hoomd/MeshDefinition.cc @@ -131,9 +131,6 @@ void MeshDefinition::setTriangulationData(pybind11::dict triangulation) m_meshbond_data = std::shared_ptr( new MeshBondData(m_sysdef->getParticleData(), triangle_data)); - createMeshNeighborhood(); - - #ifdef ENABLE_MPI if (m_sysdef->isDomainDecomposed()) { @@ -176,9 +173,9 @@ void MeshDefinition::createMeshNeighborhood() unsigned int bond_length = m_meshbond_data->getNGlobal(); - for (unsigned int j = 0; j < bond_length; ++j) + for (unsigned int i = 0; i < bond_length; ++i) { - h_neigh_to_bond.data[j] = make_uint2(bond_length,bond_length); + h_neigh_to_bond.data[i] = make_uint2(bond_length,bond_length); } for (unsigned int i = 0; i < m_meshtriangle_data->getNGlobal(); i++) @@ -186,56 +183,54 @@ void MeshDefinition::createMeshNeighborhood() const typename Angle::members_t& triangle = h_triangles.data[i]; if(triangle.tag[0] < triangle.tag[1]) - bonds[0] = make_uint2(triangle.tag[0],triangle.tag[1]); + bonds[0] = make_uint2(triangle.tag[0],triangle.tag[1]); else - bonds[0] = make_uint2(triangle.tag[1],triangle.tag[0]); + bonds[0] = make_uint2(triangle.tag[1],triangle.tag[0]); if(triangle.tag[1] < triangle.tag[2]) - bonds[1] = make_uint2(triangle.tag[1],triangle.tag[2]); + bonds[1] = make_uint2(triangle.tag[1],triangle.tag[2]); else - bonds[1] = make_uint2(triangle.tag[2],triangle.tag[1]); + bonds[1] = make_uint2(triangle.tag[2],triangle.tag[1]); if(triangle.tag[0] < triangle.tag[2]) - bonds[2] = make_uint2(triangle.tag[0],triangle.tag[2]); + bonds[2] = make_uint2(triangle.tag[0],triangle.tag[2]); else - bonds[2] = make_uint2(triangle.tag[2],triangle.tag[0]); + bonds[2] = make_uint2(triangle.tag[2],triangle.tag[0]); unsigned int counter = 0; std::vector t_idx; - std::vector b_done(bond_length); + std::vector b_done(bond_length); for (unsigned int j = 0; j < bond_length; ++j) - b_done[j]=false; + b_done[j]=false; for (unsigned int j = 0; j < bond_length; ++j) - { - if( b_done[j]) - continue; - - const typename MeshBond::members_t& meshbond = h_bonds.data[j]; - for (unsigned int k = 0; k < bonds.size(); ++k) - { - if (bonds[k].x == meshbond.tag[0] - && bonds[k].y == meshbond.tag[1]) - { - t_idx.push_back(j); - h_neigh_to_bond.data[j].y = i; - if(h_neigh_to_bond.data[j].x != bond_length) - b_done[j] = true; - else - h_neigh_to_bond.data[j].x = i; - counter++; - break; - } - } - if( counter == 3) - { - h_neigh_to_triag.data[i].x = t_idx[0]; - h_neigh_to_triag.data[i].y = t_idx[1]; - h_neigh_to_triag.data[i].z = t_idx[2]; - break; - } + { + if( b_done[j]) + continue; + const typename MeshBond::members_t& meshbond = h_bonds.data[j]; + for (unsigned int k = 0; k < 3; ++k) + { + if (bonds[k].x == meshbond.tag[0] && bonds[k].y == meshbond.tag[1]) + { + t_idx.push_back(j); + h_neigh_to_bond.data[j].y = i; + if(h_neigh_to_bond.data[j].x != bond_length) + b_done[j] = true; + else + h_neigh_to_bond.data[j].x = i; + counter++; + break; + } + } + if( counter == 3) + { + h_neigh_to_triag.data[i].x = t_idx[0]; + h_neigh_to_triag.data[i].y = t_idx[1]; + h_neigh_to_triag.data[i].z = t_idx[2]; + break; } + } } } diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index e7200a1779..b13c087a9e 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -54,6 +54,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) force->precomputeParameter(); } + ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), access_location::host, access_mode::readwrite); @@ -84,6 +85,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector changed; + for (unsigned int i = 0; i < size; i++) { typename MeshBond::members_t& bond = h_bonds.data[i]; @@ -114,11 +116,12 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int tag_c = bond.tag[2]; unsigned int tag_d = bond.tag[3]; + unsigned int idx_c = h_rtag.data[tag_c]; + unsigned int idx_d = h_rtag.data[tag_d]; + if (tag_c == tag_d) continue; - unsigned int idx_c = h_rtag.data[tag_c]; - unsigned int idx_d = h_rtag.data[tag_d]; unsigned int tr_idx1 = h_neigh_bonds.data[i].x; unsigned int tr_idx2 = h_neigh_bonds.data[i].y; @@ -162,6 +165,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) have_to_check_surrounding = true; } + // Initialize the RNG RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), hoomd::Counter(i)); @@ -180,16 +184,19 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { tr_idx[1] = tr_idx1; tr_idx[0] = tr_idx2; + + v_idx[0]=tag_a; + v_idx[1]=tag_b; + v_idx[2]=tag_d; + v_idx[3]=tag_c; + if(a_before_b) { tr_idx[0] = tr_idx1; tr_idx[1] = tr_idx2; + v_idx[2]=tag_c; + v_idx[3]=tag_d; } - - v_idx[0]=idx_a; - v_idx[1]=idx_b; - v_idx[2]=idx_cc; - v_idx[3]=idx_dd; unsigned int counter = 4; for(unsigned int j = 0; j < 2; ++j) @@ -206,7 +213,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if(bic2 == i) bic2 = h_neigh_triags.data[tr_idx[j]].z; } - if( h_bonds.data[bic].tag[0] == idx_a || h_bonds.data[bic].tag[1] == idx_a) + if( h_bonds.data[bic].tag[0] == tag_a || h_bonds.data[bic].tag[1] == tag_a) { b_idx[2*j] = bic; b_idx[2*j+1] = bic2; @@ -216,7 +223,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) b_idx[2*j+1] = bic; b_idx[2*j] = bic2; } - for(unsigned int k = 0; k < 2; ++j) + for(unsigned int k = 0; k < 2; ++k) { unsigned int tic = h_neigh_bonds.data[b_idx[2*j+k]].x; if(tic == tr_idx[j]) @@ -233,86 +240,66 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) counter++; } } - if (have_to_check_surrounding) { for (auto& force : m_forces) - energyDifference += force->energyDiffSurrounding(v_idx[0],v_idx[1],v_idx[2],v_idx[3],v_idx[4],v_idx[5],v_idx[6],v_idx[7], type_id); + energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]],h_rtag.data[v_idx[1]],h_rtag.data[v_idx[2]],h_rtag.data[v_idx[3]],h_rtag.data[v_idx[4]],h_rtag.data[v_idx[5]],h_rtag.data[v_idx[6]],h_rtag.data[v_idx[7]], type_id); part_func = exp(-m_inv_T * energyDifference); } } if (part_func > rand_number) { - bond.tag[0] = v_idx[2]; - bond.tag[1] = v_idx[3]; - if(v_idx[2] < v_idx[3]) + h_bonds.data[i].tag[0] = v_idx[2]; + h_bonds.data[i].tag[1] = v_idx[3]; + if(v_idx[2] > v_idx[3]) { - bond.tag[1] = v_idx[2]; - bond.tag[0] = v_idx[3]; + h_bonds.data[i].tag[1] = v_idx[2]; + h_bonds.data[i].tag[0] = v_idx[3]; } - bond.tag[2] = v_idx[0]; - bond.tag[3] = v_idx[1]; - - h_bonds.data[i] = bond; - - triangle1.tag[0] = v_idx[0]; - triangle1.tag[1] = v_idx[3]; - triangle1.tag[2] = v_idx[2]; - h_triangles.data[tr_idx[0]] = triangle1; // triangle a,b,c to a,d,c - - triangle1.tag[0] = v_idx[1]; - triangle1.tag[1] = v_idx[2]; - triangle1.tag[2] = v_idx[3]; - h_triangles.data[tr_idx[1]] = triangle1; // triangle b,a,d to b,c,d + h_bonds.data[i].tag[2] = v_idx[0]; + h_bonds.data[i].tag[3] = v_idx[1]; - bond = h_bonds.data[b_idx[0]]; - bond.tag[2] = v_idx[3]; - bond.tag[3] = v_idx[4]; - h_bonds.data[b_idx[0]] = bond; // bond a,c,b,x to a,c,d,x + h_triangles.data[tr_idx[0]].tag[0] = v_idx[0]; + h_triangles.data[tr_idx[0]].tag[1] = v_idx[3]; + h_triangles.data[tr_idx[0]].tag[2] = v_idx[2]; + + h_triangles.data[tr_idx[1]].tag[0] = v_idx[1]; + h_triangles.data[tr_idx[1]].tag[1] = v_idx[2]; + h_triangles.data[tr_idx[1]].tag[2] = v_idx[3]; - bond = h_bonds.data[b_idx[1]]; - bond.tag[2] = v_idx[3]; - bond.tag[3] = v_idx[5]; - h_bonds.data[b_idx[1]] = bond; // bond b,c,a,x to b,c,d,x + h_bonds.data[b_idx[0]].tag[2] = v_idx[3]; + h_bonds.data[b_idx[0]].tag[3] = v_idx[4]; - bond = h_bonds.data[b_idx[2]]; - bond.tag[2] = v_idx[2]; - bond.tag[3] = v_idx[6]; - h_bonds.data[b_idx[2]] = bond; // bond a,d,b,x to a,d,c,x + h_bonds.data[b_idx[1]].tag[2] = v_idx[3]; + h_bonds.data[b_idx[1]].tag[3] = v_idx[5]; - bond = h_bonds.data[b_idx[3]]; - bond.tag[2] = v_idx[2]; - bond.tag[3] = v_idx[7]; - h_bonds.data[b_idx[3]] = bond; // bond b,d,a,x to b,d,c,x + h_bonds.data[b_idx[2]].tag[2] = v_idx[2]; + h_bonds.data[b_idx[2]].tag[3] = v_idx[6]; - uint2 tris; - uint3 bs; + h_bonds.data[b_idx[3]].tag[2] = v_idx[2]; + h_bonds.data[b_idx[3]].tag[3] = v_idx[7]; - tris.x = tr_idx[0]; - tris.y = tr_idx[2]; - h_neigh_bonds.data[b_idx[0]] = tris; + h_neigh_bonds.data[b_idx[0]].x = tr_idx[0]; + h_neigh_bonds.data[b_idx[0]].y = tr_idx[2]; - tris.y = tr_idx[4]; - h_neigh_bonds.data[b_idx[2]] = tris; + h_neigh_bonds.data[b_idx[2]].x = tr_idx[0]; + h_neigh_bonds.data[b_idx[2]].y = tr_idx[4]; - tris.x = tr_idx[1]; - tris.y = tr_idx[3]; - h_neigh_bonds.data[b_idx[1]] = tris; + h_neigh_bonds.data[b_idx[1]].x = tr_idx[1]; + h_neigh_bonds.data[b_idx[1]].y = tr_idx[3]; - tris.y = tr_idx[5]; - h_neigh_bonds.data[b_idx[3]] = tris; + h_neigh_bonds.data[b_idx[3]].x = tr_idx[1]; + h_neigh_bonds.data[b_idx[3]].y = tr_idx[5]; - bs.x = i; - bs.y = b_idx[0]; - bs.z = b_idx[2]; - h_neigh_triags.data[tr_idx[0]] = bs; + h_neigh_triags.data[tr_idx[0]].x = i; + h_neigh_triags.data[tr_idx[0]].y = b_idx[0]; + h_neigh_triags.data[tr_idx[0]].z = b_idx[2]; - bs.x = i; - bs.y = b_idx[1]; - bs.z = b_idx[3]; - h_neigh_triags.data[tr_idx[1]] = bs; + h_neigh_triags.data[tr_idx[1]].x = i; + h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; + h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; for (auto& force : m_forces) { diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 2d260f32a3..3b5f17c8dc 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -386,13 +386,6 @@ def __init__(self, trigger, mesh, kT, forces=[]): self._param_dict.update(param_dict) - allow_switch = TypeParameter("allow_switch", - type_kind="particle_types", - param_dict=TypeParameterDict(True, - len_keys=1)) - - self._extend_typeparam([allow_switch]) - self._mesh = mesh def _attach_hook(self): @@ -404,6 +397,14 @@ def _attach_hook(self): self._forces._sync(self._simulation, self._cpp_obj.forces) + @property + def forces(self): + return self._forces + + @forces.setter + def forces(self, value): + self._forces.clear() + self._forces.extend(value) __all__ = [ "ActiveRotationalDiffusion", From 8028ce4ce15c8fd06aa82eaab5a01a40e192fd7c Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Sun, 30 Mar 2025 16:42:44 -0400 Subject: [PATCH 20/58] working with force though integrator --- hoomd/md/MeshDynamicBondUpdater.cc | 28 +++++++++++++++------------- hoomd/md/MeshDynamicBondUpdater.h | 2 ++ hoomd/md/update.py | 1 + 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index b13c087a9e..74d1c8deb5 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -24,9 +24,10 @@ namespace md MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr sysdef, std::shared_ptr trigger, + std::shared_ptr integrator, std::shared_ptr mesh, Scalar T) - : Updater(sysdef, trigger), m_mesh(mesh), m_inv_T(1.0 / T) + : Updater(sysdef, trigger), m_integrator(integrator), m_mesh(mesh), m_inv_T(1.0 / T) { assert(m_pdata); assert(m_mesh); @@ -49,12 +50,14 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { uint16_t seed = m_sysdef->getSeed(); - for (auto& force : m_forces) + std::vector> forces = m_integrator->getForces(); + + //for (auto& force : m_forces) + for (auto& force : forces) { force->precomputeParameter(); } - ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), access_location::host, access_mode::readwrite); @@ -78,14 +81,11 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) access_location::host, access_mode::read); - ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); - // for each of the angles const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); std::vector changed; - for (unsigned int i = 0; i < size; i++) { typename MeshBond::members_t& bond = h_bonds.data[i]; @@ -122,7 +122,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if (tag_c == tag_d) continue; - unsigned int tr_idx1 = h_neigh_bonds.data[i].x; unsigned int tr_idx2 = h_neigh_bonds.data[i].y; @@ -157,7 +156,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } bool have_to_check_surrounding = false; - for (auto& force : m_forces) + //for (auto& force : m_forces) + for (auto& force : forces) { energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); @@ -165,7 +165,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) have_to_check_surrounding = true; } - // Initialize the RNG RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), hoomd::Counter(i)); @@ -242,7 +241,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } if (have_to_check_surrounding) { - for (auto& force : m_forces) + //for (auto& force : m_forces) + for (auto& force : forces) energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]],h_rtag.data[v_idx[1]],h_rtag.data[v_idx[2]],h_rtag.data[v_idx[3]],h_rtag.data[v_idx[4]],h_rtag.data[v_idx[5]],h_rtag.data[v_idx[6]],h_rtag.data[v_idx[7]], type_id); part_func = exp(-m_inv_T * energyDifference); } @@ -301,12 +301,13 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; - for (auto& force : m_forces) + //for (auto& force : m_forces) + for (auto& force : forces) { force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); } - //m_mesh->getMeshBondData()->meshChanged(); - //m_mesh->getMeshTriangleData()->meshChanged(); + m_mesh->getMeshBondData()->notifyGroupReorder(); + m_mesh->getMeshTriangleData()->notifyGroupReorder(); } } } @@ -320,6 +321,7 @@ void export_MeshDynamicBondUpdater(pybind11::module& m) "MeshDynamicBondUpdater") .def(pybind11::init, std::shared_ptr, + std::shared_ptr, std::shared_ptr, Scalar>()) .def_property_readonly("forces", &MeshDynamicBondUpdater::getForces) diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index b090e40133..82596d7f86 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -41,6 +41,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater /// Constructor MeshDynamicBondUpdater(std::shared_ptr sysdef, std::shared_ptr trigger, + std::shared_ptr integrator, std::shared_ptr mesh, Scalar T); @@ -68,6 +69,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater private: /// List of all the force computes + std::shared_ptr m_integrator; std::vector> m_forces; std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on Scalar m_inv_T; diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 3b5f17c8dc..935f87a209 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -393,6 +393,7 @@ def _attach_hook(self): self._cpp_obj = _md.MeshDynamicBondUpdater( self._simulation.state._cpp_sys_def, self.trigger, + self._simulation.operations.integrator._cpp_obj, self._mesh._cpp_obj, self.kT) self._forces._sync(self._simulation, self._cpp_obj.forces) From ac36c124340e4b5f029417d23b1ed53150b31e2f Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Sun, 30 Mar 2025 20:03:56 -0400 Subject: [PATCH 21/58] add reorder group --- hoomd/BondedGroupData.cc | 9 +++------ hoomd/BondedGroupData.h | 6 ++++++ hoomd/MeshGroupData.cc | 6 ++++-- hoomd/md/MeshDynamicBondUpdater.cc | 12 ++++++++++-- hoomd/md/VolumeConservationMeshForceCompute.cc | 15 +++++++++++++++ 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/hoomd/BondedGroupData.cc b/hoomd/BondedGroupData.cc index eec06c4d85..21d1d49f7a 100644 --- a/hoomd/BondedGroupData.cc +++ b/hoomd/BondedGroupData.cc @@ -438,8 +438,7 @@ unsigned int BondedGroupData::addBond m_nglobal++; // notify observers - m_group_num_change_signal.emit(); - notifyGroupReorder(); + groupReorder(); return tag; } @@ -669,8 +668,7 @@ void BondedGroupData::removeBondedGro m_nglobal--; // notify observers - m_group_num_change_signal.emit(); - notifyGroupReorder(); + groupReorder(); } /*! \param name Type name @@ -1301,8 +1299,7 @@ void BondedGroupData::moveParticleGro } // notify observers - m_group_num_change_signal.emit(); - notifyGroupReorder(); + groupReorder(); } #endif diff --git a/hoomd/BondedGroupData.h b/hoomd/BondedGroupData.h index da5680e710..c4d54bb6e9 100644 --- a/hoomd/BondedGroupData.h +++ b/hoomd/BondedGroupData.h @@ -627,6 +627,12 @@ class BondedGroupData m_groups_dirty = true; } + virtual void groupReorder() + { + m_group_num_change_signal.emit(); + notifyGroupReorder(); + } + #ifdef ENABLE_MPI //! Helper function to transfer bonded groups connected to a single particle /*! \param tag Tag of particle that moves between domains diff --git a/hoomd/MeshGroupData.cc b/hoomd/MeshGroupData.cc index 4b123a5605..f5a63e26aa 100644 --- a/hoomd/MeshGroupData.cc +++ b/hoomd/MeshGroupData.cc @@ -343,8 +343,7 @@ unsigned int MeshGroupData::addBondedGroup(Group this->m_nglobal++; // notify observers - this->m_group_num_change_signal.emit(); - this->notifyGroupReorder(); + this->groupReorder(); return tag; } @@ -502,6 +501,9 @@ MeshGroupData::takeSnapshot(snap& snapshot) const return index; } + + + namespace detail { template diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 74d1c8deb5..58a481fd3c 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -159,12 +159,16 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) //for (auto& force : m_forces) for (auto& force : forces) { + std::cout << tag_a << " " << tag_b << " " << tag_c << " " << tag_d << ": "<< energyDifference << std::endl; energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); + std::cout << tag_a << " " << tag_b << " " << tag_c << " " << tag_d << ": "<< energyDifference << std::endl; if(force->checkSurrounding()) have_to_check_surrounding = true; } + + // Initialize the RNG RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), hoomd::Counter(i)); @@ -175,6 +179,10 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) Scalar rand_number = uniform(rng); Scalar part_func = exp(-m_inv_T * energyDifference); + std::cout << part_func << " > " << rand_number << std::endl; + + exit(0); + std::vector tr_idx(6); std::vector b_idx(4); std::vector v_idx(8); @@ -306,8 +314,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); } - m_mesh->getMeshBondData()->notifyGroupReorder(); - m_mesh->getMeshTriangleData()->notifyGroupReorder(); + m_mesh->getMeshBondData()->groupReorder(); + m_mesh->getMeshTriangleData()->groupReorder(); } } } diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index b5c5024bed..6f57c26146 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -381,20 +381,35 @@ Scalar VolumeConservationMeshForceCompute::energyDiff(unsigned int idx_a, pos_c = box.shift(pos_c, h_image.data[idx_c]); pos_d = box.shift(pos_d, h_image.data[idx_d]); + std::cout << pos_a.x << " " << pos_a.y << " " << pos_a.z << std::endl; + std::cout << pos_b.x << " " << pos_b.y << " " << pos_b.z << std::endl; + std::cout << pos_c.x << " " << pos_c.y << " " << pos_c.z << std::endl; + std::cout << pos_d.x << " " << pos_d.y << " " << pos_d.z << std::endl; + + Scalar test = dot(cross(pos_b, pos_d),pos_c)/6; + + std::cout << test << std::endl; + Scalar volume_old = dot(cross(pos_c, pos_b), pos_a) + dot(cross(pos_d, pos_a), pos_b); Scalar volume_new = dot(cross(pos_a, pos_c), pos_d) + dot(cross(pos_b, pos_d), pos_c); m_volume_diff = (volume_new-volume_old)/6.0; + std::cout << m_volume_diff << std::endl; + Scalar energy_old = h_volume.data[type_id] - h_params.data[type_id].V0; Scalar energy_new = energy_old + m_volume_diff; + std::cout << energy_old << " " << energy_new << std::endl; + energy_old = energy_old * energy_old; energy_new = energy_new * energy_new; + std::cout << energy_old << " " << energy_new << std::endl; + return h_params.data[type_id].k / (2.0 * h_params.data[type_id].V0) * (energy_new - energy_old); } From 51f616f7e4862896fc63774bf02d07b9537a9e17 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 31 Mar 2025 10:36:12 -0400 Subject: [PATCH 22/58] no write out --- hoomd/md/MeshDynamicBondUpdater.cc | 7 ------- hoomd/md/VolumeConservationMeshForceCompute.cc | 18 ------------------ 2 files changed, 25 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 58a481fd3c..7147e63169 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -159,10 +159,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) //for (auto& force : m_forces) for (auto& force : forces) { - std::cout << tag_a << " " << tag_b << " " << tag_c << " " << tag_d << ": "<< energyDifference << std::endl; energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); - std::cout << tag_a << " " << tag_b << " " << tag_c << " " << tag_d << ": "<< energyDifference << std::endl; - if(force->checkSurrounding()) have_to_check_surrounding = true; } @@ -179,10 +176,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) Scalar rand_number = uniform(rng); Scalar part_func = exp(-m_inv_T * energyDifference); - std::cout << part_func << " > " << rand_number << std::endl; - - exit(0); - std::vector tr_idx(6); std::vector b_idx(4); std::vector v_idx(8); diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index 6f57c26146..d23ecc3e38 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -381,35 +381,17 @@ Scalar VolumeConservationMeshForceCompute::energyDiff(unsigned int idx_a, pos_c = box.shift(pos_c, h_image.data[idx_c]); pos_d = box.shift(pos_d, h_image.data[idx_d]); - std::cout << pos_a.x << " " << pos_a.y << " " << pos_a.z << std::endl; - std::cout << pos_b.x << " " << pos_b.y << " " << pos_b.z << std::endl; - std::cout << pos_c.x << " " << pos_c.y << " " << pos_c.z << std::endl; - std::cout << pos_d.x << " " << pos_d.y << " " << pos_d.z << std::endl; - - Scalar test = dot(cross(pos_b, pos_d),pos_c)/6; - - std::cout << test << std::endl; - Scalar volume_old = dot(cross(pos_c, pos_b), pos_a) + dot(cross(pos_d, pos_a), pos_b); - Scalar volume_new = dot(cross(pos_a, pos_c), pos_d) + dot(cross(pos_b, pos_d), pos_c); m_volume_diff = (volume_new-volume_old)/6.0; - std::cout << m_volume_diff << std::endl; - Scalar energy_old = h_volume.data[type_id] - h_params.data[type_id].V0; - Scalar energy_new = energy_old + m_volume_diff; - std::cout << energy_old << " " << energy_new << std::endl; - energy_old = energy_old * energy_old; - energy_new = energy_new * energy_new; - std::cout << energy_old << " " << energy_new << std::endl; - return h_params.data[type_id].k / (2.0 * h_params.data[type_id].V0) * (energy_new - energy_old); } From 55df2db12cc33de453d6e2f71f34364f2e7ff751 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 16 Apr 2025 17:16:46 -0400 Subject: [PATCH 23/58] fix dublicating edges when fliping --- hoomd/md/BendingRigidityMeshForceCompute.cc | 24 +++--- hoomd/md/HelfrichMeshForceCompute.cc | 3 +- hoomd/md/MeshDynamicBondUpdater.cc | 76 ++++++++++++++++++- ...angleAreaConservationMeshForceComputeGPU.h | 2 - 4 files changed, 86 insertions(+), 19 deletions(-) diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index 870ef5b149..e7daa8f10b 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -333,9 +333,9 @@ Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, z1.z = dab.x * dac.y - dab.y * dac.x; Scalar3 z2; - z2.x = -dbd.y * dab.z + dbd.z * dab.y; - z2.y = -dbd.z * dab.x + dbd.x * dab.z; - z2.z = -dbd.x * dab.y + dbd.y * dab.x; + z2.x = dbd.y * dab.z - dbd.z * dab.y; + z2.y = dbd.z * dab.x - dbd.x * dab.z; + z2.z = dbd.x * dab.y - dbd.y * dab.x; Scalar n1 = fast::rsqrt(z1.x * z1.x + z1.y * z1.y + z1.z * z1.z); Scalar n2 = fast::rsqrt(z2.x * z2.x + z2.y * z2.y + z2.z * z2.z); @@ -368,17 +368,17 @@ Scalar BendingRigidityMeshForceCompute::energyDiffSurrounding(unsigned int idx_a unsigned int idx_h, unsigned int type_id) { - Scalar energy = calcEnergy(idx_a,idx_c,idx_e,idx_d,type_id); - energy += calcEnergy(idx_c,idx_b,idx_f,idx_d,type_id); - energy += calcEnergy(idx_a,idx_d,idx_c,idx_g,type_id); - energy += calcEnergy(idx_d,idx_b,idx_c,idx_h,type_id); + Scalar energy_new = calcEnergy(idx_a,idx_c,idx_e,idx_d,type_id); + energy_new += calcEnergy(idx_c,idx_b,idx_f,idx_d,type_id); + energy_new += calcEnergy(idx_a,idx_d,idx_c,idx_g,type_id); + energy_new += calcEnergy(idx_d,idx_b,idx_c,idx_h,type_id); - energy -= calcEnergy(idx_a,idx_c,idx_e,idx_b,type_id); - energy -= calcEnergy(idx_c,idx_b,idx_f,idx_a,type_id); - energy -= calcEnergy(idx_a,idx_d,idx_b,idx_g,type_id); - energy -= calcEnergy(idx_d,idx_b,idx_a,idx_h,type_id); + Scalar energy_old = calcEnergy(idx_a,idx_c,idx_e,idx_b,type_id); + energy_old += calcEnergy(idx_c,idx_b,idx_f,idx_a,type_id); + energy_old += calcEnergy(idx_a,idx_d,idx_b,idx_g,type_id); + energy_old += calcEnergy(idx_d,idx_b,idx_a,idx_h,type_id); - return energy; + return energy_new - energy_old; } diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 8226a10fba..542330eb1f 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -498,7 +498,7 @@ void HelfrichMeshForceCompute::precomputeParameter() Scalar inv_nbad = 1.0 / sqrt(dot(nbad, nbad)); - if (dot(nbac, nbad) * inv_nbad * inv_nbac > 0.9) + /*if (dot(nbac, nbad) * inv_nbad * inv_nbac > 0.9) { this->m_exec_conf->msg->error() << "helfrich calculations : triangles (" << idx_a << "," << idx_b << "," << idx_c @@ -506,6 +506,7 @@ void HelfrichMeshForceCompute::precomputeParameter() << std::endl; throw std::runtime_error("Error in bending energy calculation"); } + */ Scalar inv_s_accb = sqrt(1.0 - c_accb * c_accb); if (inv_s_accb < SMALL) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 7147e63169..585dd08674 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -58,6 +58,23 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) force->precomputeParameter(); } + const Index2D& table_indexer = m_mesh->getMeshBondData()->getGPUTableIndexer(); + + ArrayHandle h_meshbondlist(m_mesh->getMeshBondData()->getGPUTable(), + access_location::host, + access_mode::read); + + ArrayHandle h_n_meshbond( + m_mesh->getMeshBondData()->getNGroupsArray(), + access_location::host, + access_mode::read); + + ArrayHandle h_meshbond_pos_list( + m_mesh->getMeshBondData()->getGPUPosTable(), + access_location::host, + access_mode::read); + + ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), access_location::host, access_mode::readwrite); @@ -84,7 +101,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) // for each of the angles const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); - std::vector changed; + std::vector changed; + for (unsigned int i = 0; i < size; i++) { @@ -100,6 +118,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_a = h_rtag.data[tag_a]; unsigned int idx_b = h_rtag.data[tag_b]; + + //bool already_used = false; //for (unsigned int j = 0; j < changed.size(); j++) // { @@ -116,12 +136,47 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int tag_c = bond.tag[2]; unsigned int tag_d = bond.tag[3]; - unsigned int idx_c = h_rtag.data[tag_c]; - unsigned int idx_d = h_rtag.data[tag_d]; + std::cout << "Tags " << tag_a << " " << tag_b << " " << tag_c << " " << tag_d << std::endl; if (tag_c == tag_d) continue; + bool already_changed = false; + for( unsigned int ii = 0; ii < changed.size(); ii++) + { + if( (changed[ii].x == tag_c && changed[ii].y == tag_d) || (changed[ii].x == tag_d && changed[ii].y == tag_c) ) + { + already_changed = true; + break; + } + } + if(already_changed) + continue; + + unsigned int idx_c = h_rtag.data[tag_c]; + unsigned int idx_d = h_rtag.data[tag_d]; + + std::cout << "Idx " << idx_a << " " << idx_b << " " << idx_c << " " << idx_d << std::endl; + + std::cout << "Numbers " << h_n_meshbond.data[idx_c] << std::endl; + + unsigned int test_idx = idx_c; + + for( unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) + { + if( h_meshbond_pos_list.data[table_indexer(idx_c,ii)] > 1 ) + continue; + test_idx = h_meshbondlist.data[table_indexer(idx_c,ii)].idx[0]; + if(test_idx == idx_d) + break; + } + + if(test_idx == idx_d) + { + std::cout << "FOUND!" << std::endl; + continue; + } + unsigned int tr_idx1 = h_neigh_bonds.data[i].x; unsigned int tr_idx2 = h_neigh_bonds.data[i].y; @@ -165,7 +220,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } - // Initialize the RNG RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), hoomd::Counter(i)); @@ -176,6 +230,9 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) Scalar rand_number = uniform(rng); Scalar part_func = exp(-m_inv_T * energyDifference); + std::cout << "Energy Difference " << energyDifference << " " << part_func << " " << std::endl; + + std::vector tr_idx(6); std::vector b_idx(4); std::vector v_idx(8); @@ -197,6 +254,12 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) v_idx[2]=tag_c; v_idx[3]=tag_d; } + + uint2 bb; + bb.x = v_idx[2]; + bb.y = v_idx[3]; + changed.push_back(bb); + unsigned int counter = 4; for(unsigned int j = 0; j < 2; ++j) @@ -240,6 +303,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) counter++; } } + if (have_to_check_surrounding) { //for (auto& force : m_forces) @@ -247,10 +311,14 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]],h_rtag.data[v_idx[1]],h_rtag.data[v_idx[2]],h_rtag.data[v_idx[3]],h_rtag.data[v_idx[4]],h_rtag.data[v_idx[5]],h_rtag.data[v_idx[6]],h_rtag.data[v_idx[7]], type_id); part_func = exp(-m_inv_T * energyDifference); } + } if (part_func > rand_number) { + std::cout << part_func << " " << rand_number << std::endl; + //exit(0); + h_bonds.data[i].tag[0] = v_idx[2]; h_bonds.data[i].tag[1] = v_idx[3]; if(v_idx[2] > v_idx[3]) diff --git a/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h b/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h index 154483cff5..9cf591ac21 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h +++ b/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h @@ -1,8 +1,6 @@ // Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. -// Part of HOOMD-blue, released under the BSD 3-Clause License. - #include "AreaConservationMeshForceComputeGPU.cuh" #include "TriangleAreaConservationMeshForceCompute.h" #include "TriangleAreaConservationMeshForceComputeGPU.cuh" From b50b713ec5057386478dde4bca913afd07bfdfa1 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 21 Apr 2025 15:52:10 -0400 Subject: [PATCH 24/58] working mesh dynamic updater with write out --- hoomd/ForceCompute.h | 3 + hoomd/md/HelfrichMeshForceCompute.cc | 30 ++++- hoomd/md/HelfrichMeshForceCompute.h | 2 + hoomd/md/MeshDynamicBondUpdater.cc | 164 +++++++++++++++++++++------ 4 files changed, 164 insertions(+), 35 deletions(-) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index 09651471b9..217e015e66 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -78,6 +78,8 @@ class PYBIND11_EXPORT ForceCompute : public Compute //! Computes the parameters for meshes virtual void precomputeParameter(){}; + virtual void writeParameter(){}; + virtual Scalar energyDiff(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, @@ -100,6 +102,7 @@ class PYBIND11_EXPORT ForceCompute : public Compute unsigned int idx_d, unsigned int type_id){}; + virtual bool checkSurrounding(){ return false;} //! Total the potential energy diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 542330eb1f..d850965206 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -93,6 +93,8 @@ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) { precomputeParameter(); + std::cout << " Calc force " << timestep << std::endl; + assert(m_pdata); // access the particle data arrays ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); @@ -488,7 +490,11 @@ void HelfrichMeshForceCompute::precomputeParameter() if (c_addb < -1.0) c_addb = -1.0; - vec3 nbac + + std::cout << "Precompute " << btag_a << " " << btag_b << " " << btag_c << " " << btag_d << ": " << dac.x << " " << dac.y << " " << dac.z << " " << dbc.x << " " << dbc.y << " " << dbc.z << std::endl; + + /* + vec3 nbac = cross(vec3(nab.x, nab.y, nab.z), vec3(nac.x, nac.y, nac.z)); Scalar inv_nbac = 1.0 / sqrt(dot(nbac, nbac)); @@ -498,7 +504,7 @@ void HelfrichMeshForceCompute::precomputeParameter() Scalar inv_nbad = 1.0 / sqrt(dot(nbad, nbad)); - /*if (dot(nbac, nbad) * inv_nbad * inv_nbac > 0.9) + if (dot(nbac, nbad) * inv_nbad * inv_nbac > 0.9) { this->m_exec_conf->msg->error() << "helfrich calculations : triangles (" << idx_a << "," << idx_b << "," << idx_c @@ -842,6 +848,26 @@ void HelfrichMeshForceCompute::postcomputeParameter(unsigned int idx_a, h_sigma_dash.data[idx_d] += m_sigma_dash_diff_d; } +void HelfrichMeshForceCompute::writeParameter() + { + + ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); + + ArrayHandle h_sigma(m_sigma, access_location::host, access_mode::read); + ArrayHandle h_sigma_dash(m_sigma_dash, access_location::host, access_mode::read); + + const unsigned int size = m_pdata->getN(); + for (unsigned int i = 0; i < size; i++) + { + unsigned int idx = h_rtag.data[i]; + Scalar3 sigma_dash = h_sigma_dash.data[idx]; // precomputed + Scalar sigma = h_sigma.data[idx]; // precomputed + // + std::cout << "Sigmas " << i << ": " << sigma << " " << sigma_dash.x << " " << sigma_dash.y << " " << sigma_dash.z << std::endl; + } + std::cout << std::endl; + } + namespace detail { void export_HelfrichMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index bc4e059a02..757b72a10b 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -92,6 +92,8 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute //! compute sigmas virtual void precomputeParameter(); + virtual void writeParameter(); + virtual void postcomputeParameter(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 585dd08674..71dae16c17 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -50,14 +50,19 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { uint16_t seed = m_sysdef->getSeed(); + std::cout << "Update " << timestep << std::endl; + std::vector> forces = m_integrator->getForces(); //for (auto& force : m_forces) for (auto& force : forces) { force->precomputeParameter(); + force->writeParameter(); } + { + const Index2D& table_indexer = m_mesh->getMeshBondData()->getGPUTableIndexer(); ArrayHandle h_meshbondlist(m_mesh->getMeshBondData()->getGPUTable(), @@ -103,6 +108,27 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector changed; + std::cout << "Pre bonds" << std::endl; + for (unsigned int i = 0; i < size; i++) + { + std::cout << i << ": "; + for(unsigned int ii = 0; ii < 4; ii++) + std::cout << h_bonds.data[i].tag[ii] << " "; + std::cout << " | "; + std::cout << h_neigh_bonds.data[i].x << " " << h_neigh_bonds.data[i].y << std::endl; + } + + std::cout << "Pre tris" << std::endl; + for (unsigned int i = 0; i < m_mesh->getMeshTriangleData()->getN(); i++) + { + std::cout << i << " "; + for(unsigned int ii = 0; ii < 3; ii++) + std::cout << h_triangles.data[i].tag[ii] << " "; + std::cout << " | "; + std::cout << h_neigh_triags.data[i].x << " " << h_neigh_triags.data[i].y << " " << h_neigh_triags.data[i].z << std::endl; + } + + for (unsigned int i = 0; i < size; i++) { @@ -118,21 +144,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_a = h_rtag.data[tag_a]; unsigned int idx_b = h_rtag.data[tag_b]; - - - //bool already_used = false; - //for (unsigned int j = 0; j < changed.size(); j++) - // { - // if (tag_a == changed[j] || tag_b == changed[j]) - // { - // already_used = true; - // break; - // } - // } - - //if (already_used) - // continue; - unsigned int tag_c = bond.tag[2]; unsigned int tag_d = bond.tag[3]; @@ -156,10 +167,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_c = h_rtag.data[tag_c]; unsigned int idx_d = h_rtag.data[tag_d]; - std::cout << "Idx " << idx_a << " " << idx_b << " " << idx_c << " " << idx_d << std::endl; - - std::cout << "Numbers " << h_n_meshbond.data[idx_c] << std::endl; - unsigned int test_idx = idx_c; for( unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) @@ -172,16 +179,26 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } if(test_idx == idx_d) - { - std::cout << "FOUND!" << std::endl; continue; - } unsigned int tr_idx1 = h_neigh_bonds.data[i].x; unsigned int tr_idx2 = h_neigh_bonds.data[i].y; typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; + for( unsigned int j = 0; j<3; j++) + { + if(triangle1.tag[j] == tag_d) + { + tr_idx1 = h_neigh_bonds.data[i].y; + tr_idx2 = h_neigh_bonds.data[i].x; + triangle1 = h_triangles.data[tr_idx1]; + break; + } + } + + std::cout << "TrIdx " << tr_idx1 << " " << tr_idx2 << std::endl; + unsigned int iterator = 0; bool a_before_b = false; @@ -196,7 +213,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) a_before_b = true; iterator = (iterator + 1) % 3; } - + unsigned int type_id = h_typeval.data[i].type; Scalar energyDifference = 0; @@ -230,8 +247,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) Scalar rand_number = uniform(rng); Scalar part_func = exp(-m_inv_T * energyDifference); - std::cout << "Energy Difference " << energyDifference << " " << part_func << " " << std::endl; - + //std::cout << "Energy Difference " << energyDifference << " " << part_func << " " << std::endl; std::vector tr_idx(6); std::vector b_idx(4); @@ -316,20 +332,64 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if (part_func > rand_number) { - std::cout << part_func << " " << rand_number << std::endl; - //exit(0); + std::cout << part_func << " " << rand_number << " "; + + for(int ii = 0; ii< 8; ii++) + std::cout << v_idx[ii] << " "; + std::cout << std::endl; + + for(int ii = 0; ii< 6; ii++) + std::cout << tr_idx[ii] << " "; + std::cout << std::endl; + + for(int ii = 0; ii< 4; ii++) + std::cout << b_idx[ii] << " "; + std::cout << std::endl; + + std::cout << "Fliped bond before " << i << ": "; + for( int ii=0; ii<4; ii++) + std::cout << h_bonds.data[i].tag[ii] << " "; + std::cout << std::endl; + - h_bonds.data[i].tag[0] = v_idx[2]; - h_bonds.data[i].tag[1] = v_idx[3]; + for ( int jj=0; jj<4; jj++) + { + std::cout << "Neigboring bond before " << b_idx[jj] << ": "; + for( int ii=0; ii<4; ii++) + std::cout << h_bonds.data[b_idx[jj]].tag[ii] << " "; + std::cout << std::endl; + } + + for ( int jj=0; jj<4; jj++) + std::cout << "Neigboring list bond before " << b_idx[jj] << ": " << h_neigh_bonds.data[b_idx[jj]].x << " " << h_neigh_bonds.data[b_idx[jj]].y << std::endl; + + for ( int jj=0; jj<2; jj++) + { + std::cout << "Neigboring triags " << tr_idx[jj] << ": "; + for( int ii=0; ii<3; ii++) + std::cout << h_triangles.data[tr_idx[jj]].tag[ii] << " "; + std::cout << std::endl; + } + + for ( int jj=0; jj<2; jj++) + std::cout << "Neigboring list triags before " << tr_idx[jj] << ": " << h_neigh_triags.data[tr_idx[jj]].x << " " << h_neigh_triags.data[tr_idx[jj]].y << " " << h_neigh_triags.data[tr_idx[jj]].z << std::endl; + std::cout << std::endl; + + //Flip bond if(v_idx[2] > v_idx[3]) { h_bonds.data[i].tag[1] = v_idx[2]; h_bonds.data[i].tag[0] = v_idx[3]; } - + else + { + h_bonds.data[i].tag[0] = v_idx[2]; + h_bonds.data[i].tag[1] = v_idx[3]; + } h_bonds.data[i].tag[2] = v_idx[0]; h_bonds.data[i].tag[3] = v_idx[1]; + //Update triagles asociated with the bond h_triangles.data[tr_idx[0]].tag[0] = v_idx[0]; h_triangles.data[tr_idx[0]].tag[1] = v_idx[3]; h_triangles.data[tr_idx[0]].tag[2] = v_idx[2]; @@ -350,26 +410,56 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) h_bonds.data[b_idx[3]].tag[2] = v_idx[2]; h_bonds.data[b_idx[3]].tag[3] = v_idx[7]; + //Update triangle neighbors list for the surrounding bonds h_neigh_bonds.data[b_idx[0]].x = tr_idx[0]; h_neigh_bonds.data[b_idx[0]].y = tr_idx[2]; h_neigh_bonds.data[b_idx[2]].x = tr_idx[0]; h_neigh_bonds.data[b_idx[2]].y = tr_idx[4]; - + h_neigh_bonds.data[b_idx[1]].x = tr_idx[1]; h_neigh_bonds.data[b_idx[1]].y = tr_idx[3]; h_neigh_bonds.data[b_idx[3]].x = tr_idx[1]; h_neigh_bonds.data[b_idx[3]].y = tr_idx[5]; - h_neigh_triags.data[tr_idx[0]].x = i; + //Update bond neighbors list for the two triangles + h_neigh_triags.data[tr_idx[0]].x = i; h_neigh_triags.data[tr_idx[0]].y = b_idx[0]; h_neigh_triags.data[tr_idx[0]].z = b_idx[2]; - + h_neigh_triags.data[tr_idx[1]].x = i; h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; + std::cout << "Fliped bond " << i << ": "; + for( int ii=0; ii<4; ii++) + std::cout << h_bonds.data[i].tag[ii] << " "; + std::cout << std::endl; + + + for ( int jj=0; jj<4; jj++) + { + std::cout << "Neigboring bond " << b_idx[jj] << ": "; + for( int ii=0; ii<4; ii++) + std::cout << h_bonds.data[b_idx[jj]].tag[ii] << " "; + std::cout << std::endl; + } + + for ( int jj=0; jj<4; jj++) + std::cout << "Neigboring list bond " << b_idx[jj] << ": " << h_neigh_bonds.data[b_idx[jj]].x << " " << h_neigh_bonds.data[b_idx[jj]].y << std::endl; + + for ( int jj=0; jj<2; jj++) + { + std::cout << "Neigboring triags " << tr_idx[jj] << ": "; + for( int ii=0; ii<3; ii++) + std::cout << h_triangles.data[tr_idx[jj]].tag[ii] << " "; + std::cout << std::endl; + } + + for ( int jj=0; jj<2; jj++) + std::cout << "Neigboring list triags " << tr_idx[jj] << ": " << h_neigh_triags.data[tr_idx[jj]].x << " " << h_neigh_triags.data[tr_idx[jj]].y << " " << h_neigh_triags.data[tr_idx[jj]].z << std::endl; + //for (auto& force : m_forces) for (auto& force : forces) { @@ -379,6 +469,14 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) m_mesh->getMeshTriangleData()->groupReorder(); } } + + } + for (auto& force : forces) + { + force->writeParameter(); + force->precomputeParameter(); + force->writeParameter(); + } } namespace detail From ed7b4c1f1c65fbd47aafb2cc41af639d80b599c9 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 21 Apr 2025 18:24:50 -0400 Subject: [PATCH 25/58] fix another bug in mesh updater with write outs --- hoomd/md/HelfrichMeshForceCompute.cc | 4 ++-- hoomd/md/MeshDynamicBondUpdater.cc | 29 +++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index d850965206..81a0608329 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -93,7 +93,7 @@ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) { precomputeParameter(); - std::cout << " Calc force " << timestep << std::endl; + //std::cout << " Calc force " << timestep << std::endl; assert(m_pdata); // access the particle data arrays @@ -491,7 +491,7 @@ void HelfrichMeshForceCompute::precomputeParameter() c_addb = -1.0; - std::cout << "Precompute " << btag_a << " " << btag_b << " " << btag_c << " " << btag_d << ": " << dac.x << " " << dac.y << " " << dac.z << " " << dbc.x << " " << dbc.y << " " << dbc.z << std::endl; + //std::cout << "Precompute " << btag_a << " " << btag_b << " " << btag_c << " " << btag_d << ": " << dac.x << " " << dac.y << " " << dac.z << " " << dbc.x << " " << dbc.y << " " << dbc.z << std::endl; /* vec3 nbac diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 71dae16c17..966e1ce585 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -128,8 +128,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::cout << h_neigh_triags.data[i].x << " " << h_neigh_triags.data[i].y << " " << h_neigh_triags.data[i].z << std::endl; } - - for (unsigned int i = 0; i < size; i++) { typename MeshBond::members_t& bond = h_bonds.data[i]; @@ -184,20 +182,21 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int tr_idx1 = h_neigh_bonds.data[i].x; unsigned int tr_idx2 = h_neigh_bonds.data[i].y; - typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; + typename Angle::members_t& triangleT = h_triangles.data[tr_idx1]; for( unsigned int j = 0; j<3; j++) { - if(triangle1.tag[j] == tag_d) + if(triangleT.tag[j] == tag_d) { tr_idx1 = h_neigh_bonds.data[i].y; tr_idx2 = h_neigh_bonds.data[i].x; - triangle1 = h_triangles.data[tr_idx1]; break; } } std::cout << "TrIdx " << tr_idx1 << " " << tr_idx2 << std::endl; + + typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; unsigned int iterator = 0; @@ -468,6 +467,26 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) m_mesh->getMeshBondData()->groupReorder(); m_mesh->getMeshTriangleData()->groupReorder(); } + + std::cout << "Post bonds" << std::endl; + for (unsigned int ii = 0; ii < size; ii++) + { + std::cout << ii << ": "; + for(unsigned int iii = 0; iii < 4; iii++) + std::cout << h_bonds.data[ii].tag[iii] << " "; + std::cout << " | "; + std::cout << h_neigh_bonds.data[ii].x << " " << h_neigh_bonds.data[ii].y << std::endl; + } + + std::cout << "Post tris" << std::endl; + for (unsigned int ii = 0; ii < m_mesh->getMeshTriangleData()->getN(); ii++) + { + std::cout << ii << " "; + for(unsigned int iii = 0; iii < 3; iii++) + std::cout << h_triangles.data[ii].tag[iii] << " "; + std::cout << " | "; + std::cout << h_neigh_triags.data[ii].x << " " << h_neigh_triags.data[ii].y << " " << h_neigh_triags.data[ii].z << std::endl; + } } } From 60901ba27a53875d6b861851280a212d18c076eb Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 19 Jun 2025 15:44:05 -0400 Subject: [PATCH 26/58] remove writers --- hoomd/md/HelfrichMeshForceCompute.cc | 56 +++++++---- hoomd/md/MeshDynamicBondUpdater.cc | 135 ++------------------------- hoomd/md/PotentialBond.h | 87 +++++++++++++++++ 3 files changed, 131 insertions(+), 147 deletions(-) diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 81a0608329..8ef61691c2 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -93,8 +93,6 @@ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) { precomputeParameter(); - //std::cout << " Calc force " << timestep << std::endl; - assert(m_pdata); // access the particle data arrays ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); @@ -345,7 +343,6 @@ void HelfrichMeshForceCompute::computeForces(uint64_t timestep) unsigned int meshbond_type = m_mesh_data->getMeshBondData()->getTypeByIndex(i); Fa *= h_params.data[meshbond_type]; - if (compute_virial) { helfrich_virial[0] = Scalar(1. / 2.) * dab.x * Fa.x; // xx @@ -491,9 +488,6 @@ void HelfrichMeshForceCompute::precomputeParameter() c_addb = -1.0; - //std::cout << "Precompute " << btag_a << " " << btag_b << " " << btag_c << " " << btag_d << ": " << dac.x << " " << dac.y << " " << dac.z << " " << dbc.x << " " << dbc.y << " " << dbc.z << std::endl; - - /* vec3 nbac = cross(vec3(nab.x, nab.y, nab.z), vec3(nac.x, nac.y, nac.z)); @@ -512,7 +506,6 @@ void HelfrichMeshForceCompute::precomputeParameter() << std::endl; throw std::runtime_error("Error in bending energy calculation"); } - */ Scalar inv_s_accb = sqrt(1.0 - c_accb * c_accb); if (inv_s_accb < SMALL) @@ -691,10 +684,6 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, inv_s_baad = SMALL; inv_s_baad = 1.0 / inv_s_baad; - - - - Scalar c_caad = nac.x * nad.x + nac.y * nad.y + nac.z * nad.z; if (c_caad > 1.0) c_caad = 1.0; @@ -851,21 +840,48 @@ void HelfrichMeshForceCompute::postcomputeParameter(unsigned int idx_a, void HelfrichMeshForceCompute::writeParameter() { - ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); + /*ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); + + ArrayHandle h_params(m_params, access_location::host, access_mode::read); + + ArrayHandle h_bonds( + m_mesh_data->getMeshBondData()->getMembersArray(), + access_location::host, + access_mode::read); ArrayHandle h_sigma(m_sigma, access_location::host, access_mode::read); ArrayHandle h_sigma_dash(m_sigma_dash, access_location::host, access_mode::read); - const unsigned int size = m_pdata->getN(); + assert(h_bonds.data); + assert(h_sigma.data); + assert(h_sigma_dash.data); + + const unsigned int size = (unsigned int)m_mesh_data->getMeshBondData()->getN(); for (unsigned int i = 0; i < size; i++) { - unsigned int idx = h_rtag.data[i]; - Scalar3 sigma_dash = h_sigma_dash.data[idx]; // precomputed - Scalar sigma = h_sigma.data[idx]; // precomputed - // - std::cout << "Sigmas " << i << ": " << sigma << " " << sigma_dash.x << " " << sigma_dash.y << " " << sigma_dash.z << std::endl; - } - std::cout << std::endl; + const typename MeshBond::members_t& bond = h_bonds.data[i]; + unsigned int meshbond_type = m_mesh_data->getMeshBondData()->getTypeByIndex(i); + + unsigned int btag_a = bond.tag[0]; + assert(btag_a < m_pdata->getMaximumTag() + 1); + unsigned int btag_b = bond.tag[1]; + assert(btag_b < m_pdata->getMaximumTag() + 1); + + unsigned int idx_a = h_rtag.data[btag_a]; + unsigned int idx_b = h_rtag.data[btag_b]; + + assert(idx_a < m_pdata->getN() + m_pdata->getNGhosts()); + assert(idx_b < m_pdata->getN() + m_pdata->getNGhosts()); + + Scalar3 sigma_dash_a = h_sigma_dash.data[idx_a]; // precomputed + Scalar3 sigma_dash_b = h_sigma_dash.data[idx_b]; // precomputed + + Scalar sigma_a = h_sigma.data[idx_a]; // precomputed + Scalar sigma_b = h_sigma.data[idx_b]; // precomputed + + Scalar energy_a = h_params.data[meshbond_type] * 0.5* dot(sigma_dash_a, sigma_dash_a) / sigma_a; + Scalar energy_b = h_params.data[meshbond_type] * 0.5* dot(sigma_dash_b, sigma_dash_b) / sigma_b; + }*/ } namespace detail diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 966e1ce585..9ed69c5524 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -50,15 +50,13 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { uint16_t seed = m_sysdef->getSeed(); - std::cout << "Update " << timestep << std::endl; - std::vector> forces = m_integrator->getForces(); //for (auto& force : m_forces) for (auto& force : forces) { force->precomputeParameter(); - force->writeParameter(); + //force->writeParameter(); } { @@ -108,26 +106,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector changed; - std::cout << "Pre bonds" << std::endl; - for (unsigned int i = 0; i < size; i++) - { - std::cout << i << ": "; - for(unsigned int ii = 0; ii < 4; ii++) - std::cout << h_bonds.data[i].tag[ii] << " "; - std::cout << " | "; - std::cout << h_neigh_bonds.data[i].x << " " << h_neigh_bonds.data[i].y << std::endl; - } - - std::cout << "Pre tris" << std::endl; - for (unsigned int i = 0; i < m_mesh->getMeshTriangleData()->getN(); i++) - { - std::cout << i << " "; - for(unsigned int ii = 0; ii < 3; ii++) - std::cout << h_triangles.data[i].tag[ii] << " "; - std::cout << " | "; - std::cout << h_neigh_triags.data[i].x << " " << h_neigh_triags.data[i].y << " " << h_neigh_triags.data[i].z << std::endl; - } - for (unsigned int i = 0; i < size; i++) { typename MeshBond::members_t& bond = h_bonds.data[i]; @@ -145,8 +123,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int tag_c = bond.tag[2]; unsigned int tag_d = bond.tag[3]; - std::cout << "Tags " << tag_a << " " << tag_b << " " << tag_c << " " << tag_d << std::endl; - if (tag_c == tag_d) continue; @@ -194,8 +170,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } } - std::cout << "TrIdx " << tr_idx1 << " " << tr_idx2 << std::endl; - typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; unsigned int iterator = 0; @@ -246,8 +220,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) Scalar rand_number = uniform(rng); Scalar part_func = exp(-m_inv_T * energyDifference); - //std::cout << "Energy Difference " << energyDifference << " " << part_func << " " << std::endl; - std::vector tr_idx(6); std::vector b_idx(4); std::vector v_idx(8); @@ -270,11 +242,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) v_idx[3]=tag_d; } - uint2 bb; - bb.x = v_idx[2]; - bb.y = v_idx[3]; - changed.push_back(bb); - unsigned int counter = 4; for(unsigned int j = 0; j < 2; ++j) @@ -319,6 +286,11 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } } + uint2 bb; + bb.x = v_idx[2]; + bb.y = v_idx[3]; + changed.push_back(bb); + if (have_to_check_surrounding) { //for (auto& force : m_forces) @@ -331,49 +303,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if (part_func > rand_number) { - std::cout << part_func << " " << rand_number << " "; - - for(int ii = 0; ii< 8; ii++) - std::cout << v_idx[ii] << " "; - std::cout << std::endl; - - for(int ii = 0; ii< 6; ii++) - std::cout << tr_idx[ii] << " "; - std::cout << std::endl; - - for(int ii = 0; ii< 4; ii++) - std::cout << b_idx[ii] << " "; - std::cout << std::endl; - - std::cout << "Fliped bond before " << i << ": "; - for( int ii=0; ii<4; ii++) - std::cout << h_bonds.data[i].tag[ii] << " "; - std::cout << std::endl; - - - for ( int jj=0; jj<4; jj++) - { - std::cout << "Neigboring bond before " << b_idx[jj] << ": "; - for( int ii=0; ii<4; ii++) - std::cout << h_bonds.data[b_idx[jj]].tag[ii] << " "; - std::cout << std::endl; - } - - for ( int jj=0; jj<4; jj++) - std::cout << "Neigboring list bond before " << b_idx[jj] << ": " << h_neigh_bonds.data[b_idx[jj]].x << " " << h_neigh_bonds.data[b_idx[jj]].y << std::endl; - - for ( int jj=0; jj<2; jj++) - { - std::cout << "Neigboring triags " << tr_idx[jj] << ": "; - for( int ii=0; ii<3; ii++) - std::cout << h_triangles.data[tr_idx[jj]].tag[ii] << " "; - std::cout << std::endl; - } - - for ( int jj=0; jj<2; jj++) - std::cout << "Neigboring list triags before " << tr_idx[jj] << ": " << h_neigh_triags.data[tr_idx[jj]].x << " " << h_neigh_triags.data[tr_idx[jj]].y << " " << h_neigh_triags.data[tr_idx[jj]].z << std::endl; - std::cout << std::endl; - //Flip bond if(v_idx[2] > v_idx[3]) { @@ -431,34 +360,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; - std::cout << "Fliped bond " << i << ": "; - for( int ii=0; ii<4; ii++) - std::cout << h_bonds.data[i].tag[ii] << " "; - std::cout << std::endl; - - - for ( int jj=0; jj<4; jj++) - { - std::cout << "Neigboring bond " << b_idx[jj] << ": "; - for( int ii=0; ii<4; ii++) - std::cout << h_bonds.data[b_idx[jj]].tag[ii] << " "; - std::cout << std::endl; - } - - for ( int jj=0; jj<4; jj++) - std::cout << "Neigboring list bond " << b_idx[jj] << ": " << h_neigh_bonds.data[b_idx[jj]].x << " " << h_neigh_bonds.data[b_idx[jj]].y << std::endl; - - for ( int jj=0; jj<2; jj++) - { - std::cout << "Neigboring triags " << tr_idx[jj] << ": "; - for( int ii=0; ii<3; ii++) - std::cout << h_triangles.data[tr_idx[jj]].tag[ii] << " "; - std::cout << std::endl; - } - - for ( int jj=0; jj<2; jj++) - std::cout << "Neigboring list triags " << tr_idx[jj] << ": " << h_neigh_triags.data[tr_idx[jj]].x << " " << h_neigh_triags.data[tr_idx[jj]].y << " " << h_neigh_triags.data[tr_idx[jj]].z << std::endl; - //for (auto& force : m_forces) for (auto& force : forces) { @@ -467,34 +368,14 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) m_mesh->getMeshBondData()->groupReorder(); m_mesh->getMeshTriangleData()->groupReorder(); } - - std::cout << "Post bonds" << std::endl; - for (unsigned int ii = 0; ii < size; ii++) - { - std::cout << ii << ": "; - for(unsigned int iii = 0; iii < 4; iii++) - std::cout << h_bonds.data[ii].tag[iii] << " "; - std::cout << " | "; - std::cout << h_neigh_bonds.data[ii].x << " " << h_neigh_bonds.data[ii].y << std::endl; - } - - std::cout << "Post tris" << std::endl; - for (unsigned int ii = 0; ii < m_mesh->getMeshTriangleData()->getN(); ii++) - { - std::cout << ii << " "; - for(unsigned int iii = 0; iii < 3; iii++) - std::cout << h_triangles.data[ii].tag[iii] << " "; - std::cout << " | "; - std::cout << h_neigh_triags.data[ii].x << " " << h_neigh_triags.data[ii].y << " " << h_neigh_triags.data[ii].z << std::endl; - } } } for (auto& force : forces) { - force->writeParameter(); + //force->writeParameter(); force->precomputeParameter(); - force->writeParameter(); + //force->writeParameter(); } } diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index a59968cd7d..e888701cb2 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -66,6 +66,8 @@ template class PotentialBond : public ForceCompute //! Actually compute the forces virtual void computeForces(uint64_t timestep); + + virtual void writeParameter(); virtual Scalar energyDiff(unsigned int idx_a, unsigned int idx_b, @@ -365,6 +367,91 @@ Scalar PotentialBond::energyDiff(unsigned int idx_a, return DBL_MAX; } +template +void PotentialBond::writeParameter() + { + /*ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); + ArrayHandle h_charge(m_pdata->getCharges(), access_location::host, access_mode::read); + + // access the parameters + ArrayHandle h_params(m_params, access_location::host, access_mode::read); + + // there are enough other checks on the input data: but it doesn't hurt to be safe + assert(h_pos.data); + assert(h_charge.data); + + const BoxDim box = m_pdata->getGlobalBox(); + + PDataFlags flags = this->m_pdata->getFlags(); + + ArrayHandle h_bonds(m_bond_data->getMembersArray(), + access_location::host, + access_mode::read); + ArrayHandle h_typeval(m_bond_data->getTypeValArray(), + access_location::host, + access_mode::read); + + unsigned int max_local = m_pdata->getN() + m_pdata->getNGhosts(); + + // for each of the bonds + const unsigned int size = (unsigned int)m_bond_data->getN(); + + for (unsigned int i = 0; i < size; i++) + { + // lookup the tag of each of the particles participating in the bond + const typename Bonds::members_t& bond = h_bonds.data[i]; + assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); + assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); + + // transform a and b into indices into the particle data arrays + // (MEM TRANSFER: 4 integers) + unsigned int idx_a = h_rtag.data[bond.tag[0]]; + unsigned int idx_b = h_rtag.data[bond.tag[1]]; + + // throw an error if this bond is incomplete + if (idx_a >= max_local || idx_b >= max_local) + { + std::ostringstream stream; + stream << "Error: bond " << bond.tag[0] << " " << bond.tag[1] << " is incomplete."; + throw std::runtime_error(stream.str()); + } + + // calculate d\vec{r} + // (MEM TRANSFER: 6 Scalars / FLOPS: 3) + Scalar3 posa = make_scalar3(h_pos.data[idx_a].x, h_pos.data[idx_a].y, h_pos.data[idx_a].z); + Scalar3 posb = make_scalar3(h_pos.data[idx_b].x, h_pos.data[idx_b].y, h_pos.data[idx_b].z); + + Scalar3 dx = posb - posa; + + // access charge (if needed) + Scalar charge_a = Scalar(0.0); + Scalar charge_b = Scalar(0.0); + if (evaluator::needsCharge()) + { + charge_a = h_charge.data[idx_a]; + charge_b = h_charge.data[idx_b]; + } + + // if the vector crosses the box, pull it back + dx = box.minImage(dx); + + // calculate r_ab squared + Scalar rsq = dot(dx, dx); + + // compute the force and potential energy + Scalar force_divr = Scalar(0.0); + Scalar bond_eng = Scalar(0.0); + evaluator eval(rsq, h_params.data[h_typeval.data[i].type]); + if (evaluator::needsCharge()) + eval.setCharge(charge_a, charge_b); + + bool evaluated = eval.evalForceAndEnergy(force_divr, bond_eng); + + std::cout << bond.tag[0] << " " << bond.tag[1] << ":: " << bond_eng << " " << fast::sqrt(rsq) << std::endl; + }*/ + } + #ifdef ENABLE_MPI /*! \param timestep Current time step */ From 5410ab299c8fe7c635a74b54c727ff18ea762600 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 24 Jun 2025 13:19:53 -0400 Subject: [PATCH 27/58] force list in Meshupdater works --- hoomd/md/HelfrichMeshForceCompute.cc | 20 -------------------- hoomd/md/MeshDynamicBondUpdater.cc | 26 ++++++++++++-------------- hoomd/md/update.py | 8 ++++++-- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 8ef61691c2..dd5a191860 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -487,26 +487,6 @@ void HelfrichMeshForceCompute::precomputeParameter() if (c_addb < -1.0) c_addb = -1.0; - - vec3 nbac - = cross(vec3(nab.x, nab.y, nab.z), vec3(nac.x, nac.y, nac.z)); - - Scalar inv_nbac = 1.0 / sqrt(dot(nbac, nbac)); - - vec3 nbad - = cross(vec3(nab.x, nab.y, nab.z), vec3(nad.x, nad.y, nad.z)); - - Scalar inv_nbad = 1.0 / sqrt(dot(nbad, nbad)); - - if (dot(nbac, nbad) * inv_nbad * inv_nbac > 0.9) - { - this->m_exec_conf->msg->error() - << "helfrich calculations : triangles (" << idx_a << "," << idx_b << "," << idx_c - << ") and (" << idx_a << "," << idx_b << "," << idx_d << ") overlap." << std::endl - << std::endl; - throw std::runtime_error("Error in bending energy calculation"); - } - Scalar inv_s_accb = sqrt(1.0 - c_accb * c_accb); if (inv_s_accb < SMALL) inv_s_accb = SMALL; diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 9ed69c5524..683be57320 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -11,6 +11,9 @@ #include +#include +PYBIND11_MAKE_OPAQUE(std::vector>); + using namespace std; namespace hoomd @@ -50,10 +53,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) { uint16_t seed = m_sysdef->getSeed(); - std::vector> forces = m_integrator->getForces(); - - //for (auto& force : m_forces) - for (auto& force : forces) + for (auto& force : m_forces) { force->precomputeParameter(); //force->writeParameter(); @@ -201,8 +201,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } bool have_to_check_surrounding = false; - //for (auto& force : m_forces) - for (auto& force : forces) + for (auto& force : m_forces) { energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); if(force->checkSurrounding()) @@ -293,8 +292,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if (have_to_check_surrounding) { - //for (auto& force : m_forces) - for (auto& force : forces) + for (auto& force : m_forces) energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]],h_rtag.data[v_idx[1]],h_rtag.data[v_idx[2]],h_rtag.data[v_idx[3]],h_rtag.data[v_idx[4]],h_rtag.data[v_idx[5]],h_rtag.data[v_idx[6]],h_rtag.data[v_idx[7]], type_id); part_func = exp(-m_inv_T * energyDifference); } @@ -360,8 +358,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; - //for (auto& force : m_forces) - for (auto& force : forces) + for (auto& force : m_forces) { force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); } @@ -371,18 +368,19 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } } - for (auto& force : forces) - { + //for (auto& force : forces) + // { //force->writeParameter(); - force->precomputeParameter(); + // force->precomputeParameter(); //force->writeParameter(); - } + // } } namespace detail { void export_MeshDynamicBondUpdater(pybind11::module& m) { + pybind11::bind_vector>>(m, "ForceComputeList"); pybind11::class_>( m, "MeshDynamicBondUpdater") diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 935f87a209..c30f0d5f54 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -398,14 +398,18 @@ def _attach_hook(self): self._forces._sync(self._simulation, self._cpp_obj.forces) + super()._attach_hook() + + def _detach_hook(self): + self._forces._unsync() + @property def forces(self): return self._forces @forces.setter def forces(self, value): - self._forces.clear() - self._forces.extend(value) + _set_synced_list(self._forces, value) __all__ = [ "ActiveRotationalDiffusion", From 79030a5176bfbdb4aea682bc262cd5f5e1161154 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 25 Jun 2025 11:55:14 -0400 Subject: [PATCH 28/58] random order --- hoomd/RNGIdentifiers.h | 3 ++- hoomd/md/MeshDynamicBondUpdater.cc | 21 +++++++++++++++++++-- hoomd/md/MeshDynamicBondUpdater.h | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/hoomd/RNGIdentifiers.h b/hoomd/RNGIdentifiers.h index 1f1cfcf3cd..bdcab2fa07 100644 --- a/hoomd/RNGIdentifiers.h +++ b/hoomd/RNGIdentifiers.h @@ -70,7 +70,8 @@ struct RNGIdentifier static const uint8_t BussiThermostat = 45; static const uint8_t ConstantPressure = 46; static const uint8_t MPCDCellList = 47; - static const uint8_t MeshDynamicBondUpdater = 48; + static const uint8_t MeshDynamicBondUpdateOrder = 48; + static const uint8_t MeshDynamicBondUpdater = 49; }; } // namespace hoomd diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 683be57320..59d32d3d7b 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -37,6 +37,9 @@ MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr m_mesh->createMeshNeighborhood(); + m_update_order.resize(m_mesh->getMeshBondData()->getN()); + + m_exec_conf->msg->notice(5) << "Constructing MeshDynamicBondUpdater" << endl; } @@ -104,10 +107,25 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) // for each of the angles const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); - std::vector changed; + hoomd::RandomGenerator rng( + hoomd::Seed(hoomd::RNGIdentifier::MeshDynamicBondUpdateOrder, timestep, seed), + hoomd::Counter(m_exec_conf->getRank())); +// maybe too slow for (unsigned int i = 0; i < size; i++) + m_update_order[i] = i; + + for (unsigned int i = size-1; i>0; i--) + { + unsigned int j = hoomd::UniformIntDistribution(i)(rng); + std::swap(m_update_order[i], m_update_order[j]); + } + + std::vector changed; + + for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) { + unsigned int i = m_update_order[cur_bond]; typename MeshBond::members_t& bond = h_bonds.data[i]; assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); @@ -296,7 +314,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]],h_rtag.data[v_idx[1]],h_rtag.data[v_idx[2]],h_rtag.data[v_idx[3]],h_rtag.data[v_idx[4]],h_rtag.data[v_idx[5]],h_rtag.data[v_idx[6]],h_rtag.data[v_idx[7]], type_id); part_func = exp(-m_inv_T * energyDifference); } - } if (part_func > rand_number) diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index 82596d7f86..d1f6d1614f 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -72,6 +72,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater std::shared_ptr m_integrator; std::vector> m_forces; std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on + std::vector m_update_order; Scalar m_inv_T; }; From b332b143c1d8eab55ae14f618119ac2fef42c652 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 25 Jun 2025 11:56:33 -0400 Subject: [PATCH 29/58] allow to attach mesh forces to intefrator and meshupdater --- hoomd/data/syncedlist.py | 5 ++++- hoomd/md/force.py | 1 + hoomd/md/mesh/potential.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hoomd/data/syncedlist.py b/hoomd/data/syncedlist.py index 538900a42f..293e0b6998 100644 --- a/hoomd/data/syncedlist.py +++ b/hoomd/data/syncedlist.py @@ -192,7 +192,10 @@ def _register_item(self, value): return else: if value._attached: - raise RuntimeError(f"Cannot place {value} into two simulations.") + if not value._two_attach: + raise RuntimeError(f"Cannot place {value} into two simulations.") + else: + value._two_attach = False def _unregister_item(self, value): """Detaches and/or removes value to simulation if attached. diff --git a/hoomd/md/force.py b/hoomd/md/force.py index 11544d7ff8..3c7c5d527e 100644 --- a/hoomd/md/force.py +++ b/hoomd/md/force.py @@ -136,6 +136,7 @@ class Force(Compute): def __init__(self): self._in_context_manager = False + self._two_attach = False @log(requires_run=True) def energy(self): diff --git a/hoomd/md/mesh/potential.py b/hoomd/md/mesh/potential.py index b4ecedb90a..282852e849 100644 --- a/hoomd/md/mesh/potential.py +++ b/hoomd/md/mesh/potential.py @@ -48,6 +48,7 @@ class MeshPotential(Force): def __init__(self, mesh): self._mesh = validate_mesh(mesh) + self._two_attach = True def _attach_hook(self): """Create the c++ mirror class.""" From a23c7278a076fcecc10a4f61ff401472358f8698 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 25 Jun 2025 15:05:25 -0400 Subject: [PATCH 30/58] only one time in list for all syced lists except for mesh updater --- hoomd/hpmc/compute.py | 2 ++ hoomd/md/force.py | 2 +- hoomd/md/integrate.py | 1 + hoomd/md/mesh/potential.py | 1 + hoomd/md/nlist.py | 2 ++ hoomd/operation.py | 3 +++ 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hoomd/hpmc/compute.py b/hoomd/hpmc/compute.py index bc7e4bc4c2..84d7add9f9 100644 --- a/hoomd/hpmc/compute.py +++ b/hoomd/hpmc/compute.py @@ -110,6 +110,7 @@ def __init__(self, test_particle_type, num_samples): dict(test_particle_type=test_particle_type, num_samples=num_samples) ) self._param_dict.update(param_dict) + super().__init__() def _attach_hook(self): integrator = self._simulation.operations.integrator @@ -341,6 +342,7 @@ def __init__(self, xmax, dx): dx=float(dx), ) self._param_dict.update(param_dict) + super().__init__() def _attach_hook(self): integrator = self._simulation.operations.integrator diff --git a/hoomd/md/force.py b/hoomd/md/force.py index 3c7c5d527e..563bfc54f1 100644 --- a/hoomd/md/force.py +++ b/hoomd/md/force.py @@ -136,7 +136,7 @@ class Force(Compute): def __init__(self): self._in_context_manager = False - self._two_attach = False + super().__init__() @log(requires_run=True) def energy(self): diff --git a/hoomd/md/integrate.py b/hoomd/md/integrate.py index 387033a749..de78c03394 100644 --- a/hoomd/md/integrate.py +++ b/hoomd/md/integrate.py @@ -43,6 +43,7 @@ def __init__(self, forces, constraints, methods, rigid): raise ValueError("Rigid object can only belong to one integrator.") param_dict["rigid"] = rigid self._param_dict.update(param_dict) + super().__init__() def _attach_hook(self): self._forces._sync(self._simulation, self._cpp_obj.forces) diff --git a/hoomd/md/mesh/potential.py b/hoomd/md/mesh/potential.py index 282852e849..c1d2356254 100644 --- a/hoomd/md/mesh/potential.py +++ b/hoomd/md/mesh/potential.py @@ -47,6 +47,7 @@ class MeshPotential(Force): ) def __init__(self, mesh): + super().__init__() self._mesh = validate_mesh(mesh) self._two_attach = True diff --git a/hoomd/md/nlist.py b/hoomd/md/nlist.py index 037d4c3ec0..85bf380f8b 100644 --- a/hoomd/md/nlist.py +++ b/hoomd/md/nlist.py @@ -230,6 +230,8 @@ def __init__( self._in_context_manager = False + super().__init__() + def _attach_hook(self): if self._mesh is not None: self._cpp_obj.addMesh(self._mesh._cpp_obj) diff --git a/hoomd/operation.py b/hoomd/operation.py index 43c6acb1e4..583266fb34 100644 --- a/hoomd/operation.py +++ b/hoomd/operation.py @@ -546,6 +546,8 @@ class see its documentation. __doc__ += AutotunedObject._doc_inherited + def __init__(self): + self._two_attach = False class TriggeredOperation(Operation): """Operations that execute on timesteps determined by a trigger. @@ -591,6 +593,7 @@ def __init__(self, trigger): trigger_param = ParameterDict(trigger=hoomd.trigger.Trigger) self._param_dict.update(trigger_param) self.trigger = trigger + super().__init__() class Updater(TriggeredOperation): From 3d22521341ec0e616acb1f8d1a131de9db16ed5f Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Sat, 28 Jun 2025 15:16:54 -0400 Subject: [PATCH 31/58] do not change if triangle area = 0 --- hoomd/md/AreaConservationMeshForceCompute.cc | 47 +++++++++++++------ ...riangleAreaConservationMeshForceCompute.cc | 30 ++++++------ 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/hoomd/md/AreaConservationMeshForceCompute.cc b/hoomd/md/AreaConservationMeshForceCompute.cc index 49c9647bf7..7bdda6c178 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.cc +++ b/hoomd/md/AreaConservationMeshForceCompute.cc @@ -425,6 +425,23 @@ Scalar AreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + Scalar3 dcd; + dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; + dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; + dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; + + int3 acImage = box.getImage(dac); + int3 adImage = box.getImage(dad); + int3 bcImage = box.getImage(dbc); + int3 bdImage = box.getImage(dbd); + int3 cdImage = box.getImage(dcd); + + int3 Image1 = acImage+adImage+cdImage; + int3 Image2 = bcImage+bdImage+cdImage; + + if( Image1.x % 2 != 0 || Image1.y % 2 != 0 || Image1.z % 2 != 0 || Image2.x % 2 != 0 || Image2.y % 2 != 0 || Image2.z % 2 != 0) + return DBL_MAX; + // apply minimum image conventions to all 3 vectors dac = box.minImage(dac); dad = box.minImage(dad); @@ -441,34 +458,36 @@ Scalar AreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, Scalar3 nbc = dbc / rbc; Scalar3 nbd = dbd / rbd; - Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; - if (c_accb > 1.0) - c_accb = 1.0; - if (c_accb < -1.0) - c_accb = -1.0; - - Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; - if (c_addb > 1.0) - c_addb = 1.0; - if (c_addb < -1.0) - c_addb = -1.0; - Scalar c_caad = nac.x * nad.x + nac.y * nad.y + nac.z * nad.z; if (c_caad > 1.0) c_caad = 1.0; if (c_caad < -1.0) c_caad = -1.0; + Scalar s_caad = sqrt(1.0 - c_caad * c_caad); Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; if (c_cbbd > 1.0) c_cbbd = 1.0; if (c_cbbd < -1.0) c_cbbd = -1.0; + Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); + if( s_caad == 0 || s_cbbd == 0) + return DBL_MAX; + + Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; + if (c_accb > 1.0) + c_accb = 1.0; + if (c_accb < -1.0) + c_accb = -1.0; Scalar s_accb = sqrt(1.0 - c_accb * c_accb); + + Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; + if (c_addb > 1.0) + c_addb = 1.0; + if (c_addb < -1.0) + c_addb = -1.0; Scalar s_addb = sqrt(1.0 - c_addb * c_addb); - Scalar s_caad = sqrt(1.0 - c_caad * c_caad); - Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); m_area_diff = rac * rad * s_caad + rbc * rbd * s_cbbd; m_area_diff -= (rac * rbc * s_accb + rad * rbd * s_addb); diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc index 4824ae15fc..edfe6adddb 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc @@ -364,34 +364,36 @@ Scalar TriangleAreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, Scalar3 nbc = dbc / rbc; Scalar3 nbd = dbd / rbd; - Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; - if (c_accb > 1.0) - c_accb = 1.0; - if (c_accb < -1.0) - c_accb = -1.0; - - Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; - if (c_addb > 1.0) - c_addb = 1.0; - if (c_addb < -1.0) - c_addb = -1.0; - Scalar c_caad = nac.x * nad.x + nac.y * nad.y + nac.z * nad.z; if (c_caad > 1.0) c_caad = 1.0; if (c_caad < -1.0) c_caad = -1.0; + Scalar s_caad = sqrt(1.0 - c_caad * c_caad); Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; if (c_cbbd > 1.0) c_cbbd = 1.0; if (c_cbbd < -1.0) c_cbbd = -1.0; + Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); + if( s_caad == 0 || s_cbbd == 0) + return DBL_MAX; + + Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; + if (c_accb > 1.0) + c_accb = 1.0; + if (c_accb < -1.0) + c_accb = -1.0; Scalar s_accb = sqrt(1.0 - c_accb * c_accb); + + Scalar c_addb = nad.x * nbd.x + nad.y * nbd.y + nad.z * nbd.z; + if (c_addb > 1.0) + c_addb = 1.0; + if (c_addb < -1.0) + c_addb = -1.0; Scalar s_addb = sqrt(1.0 - c_addb * c_addb); - Scalar s_caad = sqrt(1.0 - c_caad * c_caad); - Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); Scalar energy_old1 = rac * rbc * s_accb / 2.0 - h_params.data[type_id].A0; Scalar energy_old2 = rad * rbd * s_addb / 2.0 - h_params.data[type_id].A0; From 43d3294dfd5d889991b458482796b41f8bdea967 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 1 Jul 2025 10:47:18 -0400 Subject: [PATCH 32/58] add pytest --- hoomd/md/HelfrichMeshForceCompute.cc | 13 +- hoomd/md/MeshDynamicBondUpdater.cc | 2 + hoomd/md/pytest/test_meshpotential.py | 8 - hoomd/md/pytest/test_meshupdater.py | 277 ++++++++++++++++++++++++++ 4 files changed, 286 insertions(+), 14 deletions(-) create mode 100644 hoomd/md/pytest/test_meshupdater.py diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index fb04663770..4de515deec 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -672,7 +672,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_caad = sqrt(1.0 - c_caad * c_caad); if (inv_s_caad < SMALL) - inv_s_caad = SMALL; + inv_s_caad = SMALL; inv_s_caad = 1.0 / inv_s_caad; Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; @@ -683,7 +683,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); if (inv_s_cbbd < SMALL) - inv_s_cbbd = SMALL; + inv_s_cbbd = SMALL; inv_s_cbbd = 1.0 / inv_s_cbbd; Scalar c_accd = -(nac.x * ncd.x + nac.y * ncd.y + nac.z * ncd.z); @@ -694,7 +694,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_accd = sqrt(1.0 - c_accd * c_accd); if (inv_s_accd < SMALL) - inv_s_accd = SMALL; + inv_s_accd = SMALL; inv_s_accd = 1.0 / inv_s_accd; Scalar c_addc = nad.x * ncd.x + nad.y * ncd.y + nad.z * ncd.z; @@ -705,7 +705,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_addc = sqrt(1.0 - c_addc * c_addc); if (inv_s_addc < SMALL) - inv_s_addc = SMALL; + inv_s_addc = SMALL; inv_s_addc = 1.0 / inv_s_addc; Scalar c_bccd = -(nbc.x * ncd.x + nbc.y * ncd.y + nbc.z * ncd.z); @@ -716,7 +716,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_bccd = sqrt(1.0 - c_bccd * c_bccd); if (inv_s_bccd < SMALL) - inv_s_bccd = SMALL; + inv_s_bccd = SMALL; inv_s_bccd = 1.0 / inv_s_bccd; Scalar c_bddc = nbd.x * ncd.x + nbd.y * ncd.y + nbd.z * ncd.z; @@ -727,9 +727,10 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_bddc = sqrt(1.0 - c_bddc * c_bddc); if (inv_s_bddc < SMALL) - inv_s_bddc = SMALL; + inv_s_bddc = SMALL; inv_s_bddc = 1.0 / inv_s_bddc; + Scalar cot_accb = c_accb * inv_s_accb; Scalar cot_addb = c_addb * inv_s_addb; Scalar cot_baac = c_baac * inv_s_baac; diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 59d32d3d7b..f6a5e66e3f 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -123,6 +123,8 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector changed; + unsigned int zahl = 0; + for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) { unsigned int i = m_update_order[cur_bond]; diff --git a/hoomd/md/pytest/test_meshpotential.py b/hoomd/md/pytest/test_meshpotential.py index 401ecdeffd..996f9df9d6 100644 --- a/hoomd/md/pytest/test_meshpotential.py +++ b/hoomd/md/pytest/test_meshpotential.py @@ -70,14 +70,6 @@ for val in zip(*_TriangleAreaConservation_args.values()) ] -_Helfrich_args = { - "k": [1.0, 20.0, 100.0], -} -_Helfrich_arg_list = [ - (hoomd.md.mesh.bending.Helfrich, dict(zip(_Helfrich_args, val))) - for val in zip(*_Helfrich_args.values()) -] - _Volume_args = {"k": [20.0, 50.0, 100.0], "V0": [0.107227, 1, 0.01]} _Volume_arg_list = [ (hoomd.md.mesh.conservation.Volume, dict(zip(_Volume_args, val))) diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py new file mode 100644 index 0000000000..71d922a02f --- /dev/null +++ b/hoomd/md/pytest/test_meshupdater.py @@ -0,0 +1,277 @@ +# Copyright (c) 2009-2025 The Regents of the University of Michigan. +# Part of HOOMD-blue, released under the BSD 3-Clause License. + +import hoomd +import pytest +import numpy as np + +def test_before_attaching(): + mesh = hoomd.mesh.Mesh() + mesh_potential1 = hoomd.md.mesh.bond.Harmonic(mesh) + mesh_potential1.params.default = dict(k=100,r0=1) + + mesh_potential2 = hoomd.md.mesh.conservation.TriangleArea(mesh) + mesh_potential2.params.default = dict(k=100,A0=1) + + mdb = hoomd.md.update.MeshDynamicalBonding(10,mesh, 1, forces=[mesh_potential1]) + + assert mdb.trigger == hoomd.trigger.Periodic(10) + assert mdb.kT == 1 + assert mdb.mesh == mesh + assert mdb.forces == [mesh_potential1] + + mdb.trigger = hoomd.trigger.Periodic(100) + mdb.kT = 0.5 + mdb.forces.append(mesh_potential2) + + tree = hoomd.md.nlist.Cell(buffer=0.5) + + lj = hoomd.md.pair.LJ(tree, default_r_cut=2) + lj.params.default = dict(epsilon=1, sigma=1) + + with pytest.raises(ValueError): + mdb.forces.append(lj) + + assert mdb.trigger == hoomd.trigger.Periodic(100) + assert mdb.kT == 0.5 + assert mdb.forces == [mesh_potential1,mesh_potential2] + +@pytest.fixture(scope="session") +def local_snapshot_factory(device): + def make_snapshot(d=0.0, particle_types=["A"], L=20): + s = hoomd.Snapshot(device.communicator) + N = 16 + if s.communicator.rank == 0: + box = [4, 2*np.sqrt(3), L, 0, 0, 0] + s.configuration.box = box + s.particles.N = N + + base_positions = np.array( + [ + [-2.0,-1.73205081,0.0], + [-1.0,-1.73205081,0.0], + [0.0,-1.73205081,0.0], + [1.0,-1.73205081,0.0], + [-1.5,-0.8660254,0.0], + [-0.5,-0.8660254,d], + [0.5,-0.8660254,d], + [1.5,-0.8660254,0.0], + [-2.0,0.,0.0], + [-1.0,0.,0.0], + [0.0,0.,0.0], + [1.0,0.,0.0], + [-1.5,0.8660254,0.0], + [-0.5,0.8660254,0.0], + [0.5,0.8660254,0.0], + [1.5,0.8660254,0.0] + ] + ) + # move particles slightly in direction of MPI decomposition which + # varies by simulation dimension + s.particles.position[:] = base_positions + s.particles.types = particle_types + return s + + return make_snapshot + + +def test_after_attaching(local_snapshot_factory, simulation_factory): + snap = local_snapshot_factory(d=1, L=20) + sim = simulation_factory(snap) + + mesh = hoomd.mesh.Mesh() + + mesh_potential1 = hoomd.md.mesh.bond.Harmonic(mesh) + mesh_potential1.params.default = dict(k=100,r0=1) + + mesh_potential2 = hoomd.md.mesh.conservation.TriangleArea(mesh) + mesh_potential2.params.default = dict(k=100,A0=1) + + mdb = hoomd.md.update.MeshDynamicalBonding(10,mesh, 1, forces=[mesh_potential1]) + sim.operations.updaters.append(mdb) + + sim.operations.integrator = hoomd.md.Integrator(dt=0.005) + + sim.run(0) + + assert mdb.trigger == hoomd.trigger.Periodic(10) + assert mdb.kT == 1 + assert mdb.mesh == mesh + assert mdb.forces == [mesh_potential1] + + mdb.trigger = hoomd.trigger.Periodic(100) + mdb.kT = 0.5 + mdb.forces.append(mesh_potential2) + + with pytest.raises(hoomd.error.MutabilityError): + mdb.mesh = hoomd.mesh.Mesh() + + assert mdb.trigger == hoomd.trigger.Periodic(100) + assert mdb.kT == 0.5 + assert mdb.forces == [mesh_potential1,mesh_potential2] + +mesh_triangle_start=[ + [ 0, 1, 4], + [ 0, 12, 1], + [ 1, 2, 5], + [ 1, 13, 2], + [ 2, 3, 6], + [ 2, 14, 3], + [ 3, 0, 7], + [ 3, 15, 0], + [ 4, 5, 9], + [ 4, 1, 5], + [ 5, 2, 10], + [ 6, 10, 2], + [ 6, 7, 11], + [ 6, 3, 7], + [ 7, 4, 8], + [ 7, 0, 4], + [ 8, 9, 12], + [ 8, 4, 9], + [ 9, 10, 13], + [ 9, 5, 10], + [10, 11, 14], + [10, 6, 11], + [11, 8, 15], + [11, 7, 8], + [12, 13, 1], + [12, 9, 13], + [13, 14, 2], + [13, 10, 14], + [14, 15, 3], + [14, 11, 15], + [15, 12, 0], + [15, 8, 12] + ] + +mesh_triangle_end=[ + [ 0, 1, 4], + [ 0, 12, 1], + [ 1, 2, 5], + [ 1, 13, 2], + [ 2, 3, 6], + [ 2, 14, 3], + [ 3, 0, 7], + [ 3, 15, 0], + [ 4, 5, 9], + [ 4, 1, 5], + [ 2, 6, 5], + [10, 5, 6], + [ 6, 7, 11], + [ 6, 3, 7], + [ 7, 4, 8], + [ 7, 0, 4], + [ 8, 9, 12], + [ 8, 4, 9], + [ 9, 10, 13], + [ 9, 5, 10], + [10, 11, 14], + [10, 6, 11], + [11, 8, 15], + [11, 7, 8], + [12, 13, 1], + [12, 9, 13], + [13, 14, 2], + [13, 10, 14], + [14, 15, 3], + [14, 11, 15], + [15, 12, 0], + [15, 8, 12] + ] + + +def test_updating(local_snapshot_factory, simulation_factory): + snap = local_snapshot_factory(d=0.0, L=20) + sim = simulation_factory(snap) + + mesh = hoomd.mesh.Mesh() + mesh.types = ["mesh"] + mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle_start), triangles=mesh_triangle_start) + + mesh_potential = hoomd.md.mesh.bond.Harmonic(mesh) + mesh_potential.params.default = dict(k=1,r0=1) + + integrator = hoomd.md.Integrator(dt=0.01) + integrator.forces.append(mesh_potential) + sim.operations.integrator = integrator + + sim.run(0) + + assert not np.isclose(mesh_potential.energy, 0) + + mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(1),mesh, kT = 0.001, forces=[mesh_potential]) + + sim.operations += mdb + + sim.run(1) + + assert np.isclose(mesh_potential.energy, 0) + + assert np.array_equal(mesh.triangles, mesh_triangle_end) + +_harmonic_arg_list = [ + (hoomd.md.mesh.bond.Harmonic, dict(k=30.0,r0=1.0)) +] +_FENE_arg_list = [ + (hoomd.md.mesh.bond.FENEWCA, dict(k=30.0,r0=2.0,epsilon=1.0,sigma=1.0,delta=0.0)) +] +_Tether_arg_list = [ + (hoomd.md.mesh.bond.Tether, dict(k_b=10,l_min=0.5,l_c1=0.9,l_c0=1.1,l_max=2.0)) +] +_BendingRigidity_arg_list = [ + (hoomd.md.mesh.bending.BendingRigidity, dict(k=300.0)) +] +_Helfrich_arg_list = [ + (hoomd.md.mesh.bending.Helfrich, dict(k=100.0)) +] +_AreaConservation_arg_list = [ + (hoomd.md.mesh.conservation.Area, dict(k=100.0,A0=8*np.sqrt(3))) +] +_TriangleAreaConservation_arg_list = [ + ( + hoomd.md.mesh.conservation.TriangleArea, + dict(k=100.0,A0=np.sqrt(3) /4) + ) +] + +def get_mesh_potential_and_args(): + return ( + _harmonic_arg_list + + _FENE_arg_list + + _Tether_arg_list + + _AreaConservation_arg_list + + _TriangleAreaConservation_arg_list + + _BendingRigidity_arg_list + + _Helfrich_arg_list + ) + +@pytest.mark.parametrize( + "mesh_potential_cls, potential_kwargs", get_mesh_potential_and_args() +) +def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential_cls, potential_kwargs): + snap = local_snapshot_factory(d=0.5, L=20) + sim = simulation_factory(snap) + + mesh = hoomd.mesh.Mesh() + mesh.types = ["mesh"] + mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle_start), triangles=mesh_triangle_start) + + mesh_potential = mesh_potential_cls(mesh) + mesh_potential.params["mesh"] = potential_kwargs + + integrator = hoomd.md.Integrator(dt=0.01) + integrator.forces.append(mesh_potential) + sim.operations.integrator = integrator + + sim.run(0) + + energy = mesh_potential.energy + + mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(1),mesh, kT = 0.001, forces=[mesh_potential]) + + sim.operations += mdb + + sim.run(1) + + assert mesh_potential.energy <= energy From 8b07e742abcf751716019dcc0615b5be2f492f04 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 1 Jul 2025 11:50:58 -0400 Subject: [PATCH 33/58] fix BendingRigidity --- hoomd/md/BendingRigidityMeshForceCompute.cc | 27 ++++++++++++--------- hoomd/md/MeshDynamicBondUpdater.cc | 2 -- hoomd/md/pytest/test_meshupdater.py | 2 ++ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index d0ea34c23d..379d910eb8 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -317,15 +317,15 @@ Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, dac.y = h_pos.data[idx_a].y - h_pos.data[idx_c].y; dac.z = h_pos.data[idx_a].z - h_pos.data[idx_c].z; - Scalar3 dbd; - dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; - dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; - dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + Scalar3 dad; + dad.x = h_pos.data[idx_a].x - h_pos.data[idx_d].x; + dad.y = h_pos.data[idx_a].y - h_pos.data[idx_d].y; + dad.z = h_pos.data[idx_a].z - h_pos.data[idx_d].z; // apply minimum image conventions to all 3 vectors dab = box.minImage(dab); dac = box.minImage(dac); - dbd = box.minImage(dbd); + dad = box.minImage(dad); Scalar3 z1; z1.x = dab.y * dac.z - dab.z * dac.y; @@ -333,15 +333,18 @@ Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, z1.z = dab.x * dac.y - dab.y * dac.x; Scalar3 z2; - z2.x = dbd.y * dab.z - dbd.z * dab.y; - z2.y = dbd.z * dab.x - dbd.x * dab.z; - z2.z = dbd.x * dab.y - dbd.y * dab.x; + z2.x = dad.y * dab.z - dad.z * dab.y; + z2.y = dad.z * dab.x - dad.x * dab.z; + z2.z = dad.x * dab.y - dad.y * dab.x; + + Scalar n1 = z1.x * z1.x + z1.y * z1.y + z1.z * z1.z; + Scalar n2 = z2.x * z2.x + z2.y * z2.y + z2.z * z2.z; - Scalar n1 = fast::rsqrt(z1.x * z1.x + z1.y * z1.y + z1.z * z1.z); - Scalar n2 = fast::rsqrt(z2.x * z2.x + z2.y * z2.y + z2.z * z2.z); - Scalar z1z2 = z1.x * z2.x + z1.y * z2.y + z1.z * z2.z; + if( n1 == 0 || n2 == 0) + return DBL_MAX; - Scalar cosinus = z1z2 * n1 * n2; + Scalar z1z2 = z1.x * z2.x + z1.y * z2.y + z1.z * z2.z; + Scalar cosinus = z1z2 * fast::rsqrt( n1 * n2); return h_params.data[type_id] * 0.5 * (1-cosinus); } diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index f6a5e66e3f..59d32d3d7b 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -123,8 +123,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::vector changed; - unsigned int zahl = 0; - for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) { unsigned int i = m_update_order[cur_bond]; diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 71d922a02f..6744e1b7d0 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -266,6 +266,8 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential sim.run(0) + print(sim.seed) + energy = mesh_potential.energy mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(1),mesh, kT = 0.001, forces=[mesh_potential]) From aff4a40846a9f8b0e31ec3fbcf16a305a4f88296 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 1 Jul 2025 11:51:39 -0400 Subject: [PATCH 34/58] fix pytest --- hoomd/md/pytest/test_meshupdater.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 6744e1b7d0..71d922a02f 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -266,8 +266,6 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential sim.run(0) - print(sim.seed) - energy = mesh_potential.energy mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(1),mesh, kT = 0.001, forces=[mesh_potential]) From 4557b239a00e41c13a0c9a57ab061e03bffa430b Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 1 Jul 2025 14:20:04 -0400 Subject: [PATCH 35/58] fix BendingRigidity for small systems --- hoomd/md/BendingRigidityMeshForceCompute.cc | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index 379d910eb8..515a036cbe 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -322,6 +322,28 @@ Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, dad.y = h_pos.data[idx_a].y - h_pos.data[idx_d].y; dad.z = h_pos.data[idx_a].z - h_pos.data[idx_d].z; + Scalar3 dbc; + dbc.x = h_pos.data[idx_b].x - h_pos.data[idx_c].x; + dbc.y = h_pos.data[idx_b].y - h_pos.data[idx_c].y; + dbc.z = h_pos.data[idx_b].z - h_pos.data[idx_c].z; + + Scalar3 dbd; + dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; + dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; + dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; + + int3 acImage = box.getImage(dac); + int3 adImage = box.getImage(dad); + int3 bcImage = box.getImage(dbc); + int3 bdImage = box.getImage(dbd); + int3 abImage = box.getImage(dab); + + int3 Image1 = acImage+adImage+abImage; + int3 Image2 = bcImage+bdImage+abImage; + + if( Image1.x % 2 != 0 || Image1.y % 2 != 0 || Image1.z % 2 != 0 || Image2.x % 2 != 0 || Image2.y % 2 != 0 || Image2.z % 2 != 0) + return DBL_MAX; + // apply minimum image conventions to all 3 vectors dab = box.minImage(dab); dac = box.minImage(dac); From 8b3ef93492174111bdbcff2c4ac1bad3dd1454b1 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 2 Jul 2025 16:46:51 -0400 Subject: [PATCH 36/58] don't allow to flip to long edges --- hoomd/ForceCompute.h | 2 - hoomd/md/AreaConservationMeshForceCompute.cc | 17 ---- hoomd/md/BendingRigidityMeshForceCompute.cc | 22 ----- hoomd/md/HelfrichMeshForceCompute.cc | 47 ---------- hoomd/md/HelfrichMeshForceCompute.h | 2 - hoomd/md/MeshDynamicBondUpdater.cc | 41 +++++---- hoomd/md/PotentialBond.h | 87 ------------------- ...riangleAreaConservationMeshForceCompute.cc | 17 ---- 8 files changed, 24 insertions(+), 211 deletions(-) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index 3ddf6da136..1e3bf6a5a7 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -78,8 +78,6 @@ class PYBIND11_EXPORT ForceCompute : public Compute //! Computes the parameters for meshes virtual void precomputeParameter(){}; - virtual void writeParameter(){}; - virtual Scalar energyDiff(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, diff --git a/hoomd/md/AreaConservationMeshForceCompute.cc b/hoomd/md/AreaConservationMeshForceCompute.cc index 7bdda6c178..76e0f482a4 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.cc +++ b/hoomd/md/AreaConservationMeshForceCompute.cc @@ -425,23 +425,6 @@ Scalar AreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; - Scalar3 dcd; - dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; - dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; - dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; - - int3 acImage = box.getImage(dac); - int3 adImage = box.getImage(dad); - int3 bcImage = box.getImage(dbc); - int3 bdImage = box.getImage(dbd); - int3 cdImage = box.getImage(dcd); - - int3 Image1 = acImage+adImage+cdImage; - int3 Image2 = bcImage+bdImage+cdImage; - - if( Image1.x % 2 != 0 || Image1.y % 2 != 0 || Image1.z % 2 != 0 || Image2.x % 2 != 0 || Image2.y % 2 != 0 || Image2.z % 2 != 0) - return DBL_MAX; - // apply minimum image conventions to all 3 vectors dac = box.minImage(dac); dad = box.minImage(dad); diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index 515a036cbe..379d910eb8 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -322,28 +322,6 @@ Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, dad.y = h_pos.data[idx_a].y - h_pos.data[idx_d].y; dad.z = h_pos.data[idx_a].z - h_pos.data[idx_d].z; - Scalar3 dbc; - dbc.x = h_pos.data[idx_b].x - h_pos.data[idx_c].x; - dbc.y = h_pos.data[idx_b].y - h_pos.data[idx_c].y; - dbc.z = h_pos.data[idx_b].z - h_pos.data[idx_c].z; - - Scalar3 dbd; - dbd.x = h_pos.data[idx_b].x - h_pos.data[idx_d].x; - dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; - dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; - - int3 acImage = box.getImage(dac); - int3 adImage = box.getImage(dad); - int3 bcImage = box.getImage(dbc); - int3 bdImage = box.getImage(dbd); - int3 abImage = box.getImage(dab); - - int3 Image1 = acImage+adImage+abImage; - int3 Image2 = bcImage+bdImage+abImage; - - if( Image1.x % 2 != 0 || Image1.y % 2 != 0 || Image1.z % 2 != 0 || Image2.x % 2 != 0 || Image2.y % 2 != 0 || Image2.z % 2 != 0) - return DBL_MAX; - // apply minimum image conventions to all 3 vectors dab = box.minImage(dab); dac = box.minImage(dac); diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 4de515deec..da6f369494 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -818,53 +818,6 @@ void HelfrichMeshForceCompute::postcomputeParameter(unsigned int idx_a, h_sigma_dash.data[idx_d] += m_sigma_dash_diff_d; } -void HelfrichMeshForceCompute::writeParameter() - { - - /*ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); - - ArrayHandle h_params(m_params, access_location::host, access_mode::read); - - ArrayHandle h_bonds( - m_mesh_data->getMeshBondData()->getMembersArray(), - access_location::host, - access_mode::read); - - ArrayHandle h_sigma(m_sigma, access_location::host, access_mode::read); - ArrayHandle h_sigma_dash(m_sigma_dash, access_location::host, access_mode::read); - - assert(h_bonds.data); - assert(h_sigma.data); - assert(h_sigma_dash.data); - - const unsigned int size = (unsigned int)m_mesh_data->getMeshBondData()->getN(); - for (unsigned int i = 0; i < size; i++) - { - const typename MeshBond::members_t& bond = h_bonds.data[i]; - unsigned int meshbond_type = m_mesh_data->getMeshBondData()->getTypeByIndex(i); - - unsigned int btag_a = bond.tag[0]; - assert(btag_a < m_pdata->getMaximumTag() + 1); - unsigned int btag_b = bond.tag[1]; - assert(btag_b < m_pdata->getMaximumTag() + 1); - - unsigned int idx_a = h_rtag.data[btag_a]; - unsigned int idx_b = h_rtag.data[btag_b]; - - assert(idx_a < m_pdata->getN() + m_pdata->getNGhosts()); - assert(idx_b < m_pdata->getN() + m_pdata->getNGhosts()); - - Scalar3 sigma_dash_a = h_sigma_dash.data[idx_a]; // precomputed - Scalar3 sigma_dash_b = h_sigma_dash.data[idx_b]; // precomputed - - Scalar sigma_a = h_sigma.data[idx_a]; // precomputed - Scalar sigma_b = h_sigma.data[idx_b]; // precomputed - - Scalar energy_a = h_params.data[meshbond_type] * 0.5* dot(sigma_dash_a, sigma_dash_a) / sigma_a; - Scalar energy_b = h_params.data[meshbond_type] * 0.5* dot(sigma_dash_b, sigma_dash_b) / sigma_b; - }*/ - } - namespace detail { void export_HelfrichMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index 757b72a10b..bc4e059a02 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -92,8 +92,6 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute //! compute sigmas virtual void precomputeParameter(); - virtual void writeParameter(); - virtual void postcomputeParameter(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 59d32d3d7b..945ff6cee9 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -57,10 +57,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) uint16_t seed = m_sysdef->getSeed(); for (auto& force : m_forces) - { force->precomputeParameter(); - //force->writeParameter(); - } { @@ -130,14 +127,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); - // transform a and b into indices into the particle data arrays - // (MEM TRANSFER: 4 integers) - unsigned int tag_a = bond.tag[0]; - unsigned int tag_b = bond.tag[1]; - - unsigned int idx_a = h_rtag.data[tag_a]; - unsigned int idx_b = h_rtag.data[tag_b]; - unsigned int tag_c = bond.tag[2]; unsigned int tag_d = bond.tag[3]; @@ -159,6 +148,30 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) unsigned int idx_c = h_rtag.data[tag_c]; unsigned int idx_d = h_rtag.data[tag_d]; + { + ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + Scalar3 boxL = m_pdata->getGlobalBox().getL()/4; + + Scalar3 dcd; + dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; + if( dcd.x > boxL.x || dcd.x < -boxL.x) + continue; + dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; + if( dcd.y > boxL.y || dcd.y < -boxL.y) + continue; + dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; + if( dcd.y > boxL.y || dcd.y < -boxL.y) + continue; + } + + + unsigned int tag_a = bond.tag[0]; + unsigned int tag_b = bond.tag[1]; + + unsigned int idx_a = h_rtag.data[tag_a]; + unsigned int idx_b = h_rtag.data[tag_b]; + + unsigned int test_idx = idx_c; for( unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) @@ -385,12 +398,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } } - //for (auto& force : forces) - // { - //force->writeParameter(); - // force->precomputeParameter(); - //force->writeParameter(); - // } } namespace detail diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index ff55811e9f..4938303385 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -66,8 +66,6 @@ template class PotentialBond : public ForceCompute //! Actually compute the forces virtual void computeForces(uint64_t timestep); - - virtual void writeParameter(); virtual Scalar energyDiff(unsigned int idx_a, unsigned int idx_b, @@ -367,91 +365,6 @@ Scalar PotentialBond::energyDiff(unsigned int idx_a, return DBL_MAX; } -template -void PotentialBond::writeParameter() - { - /*ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); - ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); - ArrayHandle h_charge(m_pdata->getCharges(), access_location::host, access_mode::read); - - // access the parameters - ArrayHandle h_params(m_params, access_location::host, access_mode::read); - - // there are enough other checks on the input data: but it doesn't hurt to be safe - assert(h_pos.data); - assert(h_charge.data); - - const BoxDim box = m_pdata->getGlobalBox(); - - PDataFlags flags = this->m_pdata->getFlags(); - - ArrayHandle h_bonds(m_bond_data->getMembersArray(), - access_location::host, - access_mode::read); - ArrayHandle h_typeval(m_bond_data->getTypeValArray(), - access_location::host, - access_mode::read); - - unsigned int max_local = m_pdata->getN() + m_pdata->getNGhosts(); - - // for each of the bonds - const unsigned int size = (unsigned int)m_bond_data->getN(); - - for (unsigned int i = 0; i < size; i++) - { - // lookup the tag of each of the particles participating in the bond - const typename Bonds::members_t& bond = h_bonds.data[i]; - assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); - assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); - - // transform a and b into indices into the particle data arrays - // (MEM TRANSFER: 4 integers) - unsigned int idx_a = h_rtag.data[bond.tag[0]]; - unsigned int idx_b = h_rtag.data[bond.tag[1]]; - - // throw an error if this bond is incomplete - if (idx_a >= max_local || idx_b >= max_local) - { - std::ostringstream stream; - stream << "Error: bond " << bond.tag[0] << " " << bond.tag[1] << " is incomplete."; - throw std::runtime_error(stream.str()); - } - - // calculate d\vec{r} - // (MEM TRANSFER: 6 Scalars / FLOPS: 3) - Scalar3 posa = make_scalar3(h_pos.data[idx_a].x, h_pos.data[idx_a].y, h_pos.data[idx_a].z); - Scalar3 posb = make_scalar3(h_pos.data[idx_b].x, h_pos.data[idx_b].y, h_pos.data[idx_b].z); - - Scalar3 dx = posb - posa; - - // access charge (if needed) - Scalar charge_a = Scalar(0.0); - Scalar charge_b = Scalar(0.0); - if (evaluator::needsCharge()) - { - charge_a = h_charge.data[idx_a]; - charge_b = h_charge.data[idx_b]; - } - - // if the vector crosses the box, pull it back - dx = box.minImage(dx); - - // calculate r_ab squared - Scalar rsq = dot(dx, dx); - - // compute the force and potential energy - Scalar force_divr = Scalar(0.0); - Scalar bond_eng = Scalar(0.0); - evaluator eval(rsq, h_params.data[h_typeval.data[i].type]); - if (evaluator::needsCharge()) - eval.setCharge(charge_a, charge_b); - - bool evaluated = eval.evalForceAndEnergy(force_divr, bond_eng); - - std::cout << bond.tag[0] << " " << bond.tag[1] << ":: " << bond_eng << " " << fast::sqrt(rsq) << std::endl; - }*/ - } - #ifdef ENABLE_MPI /*! \param timestep Current time step */ diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc index edfe6adddb..ec6c9e990e 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc @@ -331,23 +331,6 @@ Scalar TriangleAreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, dbd.y = h_pos.data[idx_b].y - h_pos.data[idx_d].y; dbd.z = h_pos.data[idx_b].z - h_pos.data[idx_d].z; - Scalar3 dcd; - dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; - dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; - dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; - - int3 acImage = box.getImage(dac); - int3 adImage = box.getImage(dad); - int3 bcImage = box.getImage(dbc); - int3 bdImage = box.getImage(dbd); - int3 cdImage = box.getImage(dcd); - - int3 Image1 = acImage+adImage+cdImage; - int3 Image2 = bcImage+bdImage+cdImage; - - if( Image1.x % 2 != 0 || Image1.y % 2 != 0 || Image1.z % 2 != 0 || Image2.x % 2 != 0 || Image2.y % 2 != 0 || Image2.z % 2 != 0) - return DBL_MAX; - // apply minimum image conventions to all 3 vectors dac = box.minImage(dac); dad = box.minImage(dad); From c91d6f83147d2228c3a1c9ee8cbf8a5877aa8c20 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 2 Jul 2025 16:49:53 -0400 Subject: [PATCH 37/58] add MeshUpdater to docs --- sphinx-doc/hoomd/md/module-update.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sphinx-doc/hoomd/md/module-update.rst b/sphinx-doc/hoomd/md/module-update.rst index ab56868038..a26253067b 100644 --- a/sphinx-doc/hoomd/md/module-update.rst +++ b/sphinx-doc/hoomd/md/module-update.rst @@ -3,7 +3,7 @@ update .. automodule:: hoomd.md.update :members: - :exclude-members: ActiveRotationalDiffusion,ReversePerturbationFlow,ZeroMomentum + :exclude-members: ActiveRotationalDiffusion,MeshDynamicalBonding,ReversePerturbationFlow,ZeroMomentum .. rubric:: Classes @@ -11,5 +11,6 @@ update :maxdepth: 1 update/activerotationaldiffusion + update/meshdynamicalbonding update/reverseperturbationflow update/zeromomentum From deccd5debcfc042f0eed289c47b5e62480984a0a Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 2 Jul 2025 17:22:00 -0400 Subject: [PATCH 38/58] improve pytests --- hoomd/md/pytest/test_meshupdater.py | 155 +++++++++++----------------- 1 file changed, 58 insertions(+), 97 deletions(-) diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 71d922a02f..9b4bc61465 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -40,32 +40,27 @@ def test_before_attaching(): def local_snapshot_factory(device): def make_snapshot(d=0.0, particle_types=["A"], L=20): s = hoomd.Snapshot(device.communicator) - N = 16 + N = 64 if s.communicator.rank == 0: - box = [4, 2*np.sqrt(3), L, 0, 0, 0] + Lx = 8 + Ly = 4*np.sqrt(3) + box = [Lx, Ly, L, 0, 0, 0] s.configuration.box = box s.particles.N = N - base_positions = np.array( - [ - [-2.0,-1.73205081,0.0], - [-1.0,-1.73205081,0.0], - [0.0,-1.73205081,0.0], - [1.0,-1.73205081,0.0], - [-1.5,-0.8660254,0.0], - [-0.5,-0.8660254,d], - [0.5,-0.8660254,d], - [1.5,-0.8660254,0.0], - [-2.0,0.,0.0], - [-1.0,0.,0.0], - [0.0,0.,0.0], - [1.0,0.,0.0], - [-1.5,0.8660254,0.0], - [-0.5,0.8660254,0.0], - [0.5,0.8660254,0.0], - [1.5,0.8660254,0.0] - ] - ) + x = np.arange(-Lx / 2, Lx / 2, Lx / 8) + y = np.arange(-Ly / 2, Ly / 2, Ly / 8) + X, Y = np.meshgrid(x, y) + + # Offset every second row to create a triangular pattern + X[1::2, :] += 0.5 + + # Combine X and Y coordinates to define vertex positions + base_positions = np.column_stack([X.flatten(), Y.flatten(), np.zeros(N)]) + + base_positions[12,2] = d + base_positions[13,2] = d + # move particles slightly in direction of MPI decomposition which # varies by simulation dimension s.particles.position[:] = base_positions @@ -74,9 +69,40 @@ def make_snapshot(d=0.0, particle_types=["A"], L=20): return make_snapshot +def make_mesh(flip=True): + row = 8 + N = row**2 + + v_index = np.arange(N) + vr_index = v_index + 1 + vr_index[row - 1 :: row] -= row + + e_index = np.repeat(v_index, 2).reshape(-1, 2) + e_index[:, 0] += row + e_index[:, 1] -= row + e_index = e_index.reshape(row, -1, 2) + e_index[1::2] += 1 + e_index[1::2, -1] -= row + e_index = e_index.reshape(-1) % N + + v_index = np.repeat(v_index, 2) + vr_index = np.repeat(vr_index, 2) + vr_index[1::2] = e_index[1::2] + e_index[1::2] = vr_index[0::2] + + triangles = np.column_stack([v_index, vr_index, e_index]) + + if flip: + triangles[24] = [12,5,21] + triangles[25] = [13,21,5] + else: + triangles[24] = [5,13,12] + triangles[25] = [21,12,13] + + return triangles def test_after_attaching(local_snapshot_factory, simulation_factory): - snap = local_snapshot_factory(d=1, L=20) + snap = local_snapshot_factory(d=0, L=20) sim = simulation_factory(snap) mesh = hoomd.mesh.Mesh() @@ -110,84 +136,15 @@ def test_after_attaching(local_snapshot_factory, simulation_factory): assert mdb.kT == 0.5 assert mdb.forces == [mesh_potential1,mesh_potential2] -mesh_triangle_start=[ - [ 0, 1, 4], - [ 0, 12, 1], - [ 1, 2, 5], - [ 1, 13, 2], - [ 2, 3, 6], - [ 2, 14, 3], - [ 3, 0, 7], - [ 3, 15, 0], - [ 4, 5, 9], - [ 4, 1, 5], - [ 5, 2, 10], - [ 6, 10, 2], - [ 6, 7, 11], - [ 6, 3, 7], - [ 7, 4, 8], - [ 7, 0, 4], - [ 8, 9, 12], - [ 8, 4, 9], - [ 9, 10, 13], - [ 9, 5, 10], - [10, 11, 14], - [10, 6, 11], - [11, 8, 15], - [11, 7, 8], - [12, 13, 1], - [12, 9, 13], - [13, 14, 2], - [13, 10, 14], - [14, 15, 3], - [14, 11, 15], - [15, 12, 0], - [15, 8, 12] - ] - -mesh_triangle_end=[ - [ 0, 1, 4], - [ 0, 12, 1], - [ 1, 2, 5], - [ 1, 13, 2], - [ 2, 3, 6], - [ 2, 14, 3], - [ 3, 0, 7], - [ 3, 15, 0], - [ 4, 5, 9], - [ 4, 1, 5], - [ 2, 6, 5], - [10, 5, 6], - [ 6, 7, 11], - [ 6, 3, 7], - [ 7, 4, 8], - [ 7, 0, 4], - [ 8, 9, 12], - [ 8, 4, 9], - [ 9, 10, 13], - [ 9, 5, 10], - [10, 11, 14], - [10, 6, 11], - [11, 8, 15], - [11, 7, 8], - [12, 13, 1], - [12, 9, 13], - [13, 14, 2], - [13, 10, 14], - [14, 15, 3], - [14, 11, 15], - [15, 12, 0], - [15, 8, 12] - ] - - def test_updating(local_snapshot_factory, simulation_factory): snap = local_snapshot_factory(d=0.0, L=20) sim = simulation_factory(snap) + mesh_triangle = make_mesh() + mesh = hoomd.mesh.Mesh() mesh.types = ["mesh"] - mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle_start), triangles=mesh_triangle_start) + mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle), triangles=mesh_triangle) mesh_potential = hoomd.md.mesh.bond.Harmonic(mesh) mesh_potential.params.default = dict(k=1,r0=1) @@ -206,9 +163,11 @@ def test_updating(local_snapshot_factory, simulation_factory): sim.run(1) + mesh_triangle = make_mesh(False) + assert np.isclose(mesh_potential.energy, 0) - assert np.array_equal(mesh.triangles, mesh_triangle_end) + assert np.array_equal(mesh.triangles, make_mesh(False)) _harmonic_arg_list = [ (hoomd.md.mesh.bond.Harmonic, dict(k=30.0,r0=1.0)) @@ -253,9 +212,11 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential snap = local_snapshot_factory(d=0.5, L=20) sim = simulation_factory(snap) + mesh_triangle = make_mesh() + mesh = hoomd.mesh.Mesh() mesh.types = ["mesh"] - mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle_start), triangles=mesh_triangle_start) + mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle), triangles=mesh_triangle) mesh_potential = mesh_potential_cls(mesh) mesh_potential.params["mesh"] = potential_kwargs From 551e5f91b77f8513578e37f74242c579789b97fe Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 14:44:55 -0400 Subject: [PATCH 39/58] update documentation and tests --- hoomd/md/MeshDynamicBondUpdater.cc | 4 +--- hoomd/md/MeshDynamicBondUpdater.h | 2 -- hoomd/md/pytest/test_meshupdater.py | 12 +++++++++++ hoomd/md/update.py | 32 ++++++++++++++++++++++------- hoomd/mesh.py | 21 +++++++++++++++++++ 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 945ff6cee9..024a1eeea7 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -27,10 +27,9 @@ namespace md MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr sysdef, std::shared_ptr trigger, - std::shared_ptr integrator, std::shared_ptr mesh, Scalar T) - : Updater(sysdef, trigger), m_integrator(integrator), m_mesh(mesh), m_inv_T(1.0 / T) + : Updater(sysdef, trigger), m_mesh(mesh), m_inv_T(1.0 / T) { assert(m_pdata); assert(m_mesh); @@ -410,7 +409,6 @@ void export_MeshDynamicBondUpdater(pybind11::module& m) "MeshDynamicBondUpdater") .def(pybind11::init, std::shared_ptr, - std::shared_ptr, std::shared_ptr, Scalar>()) .def_property_readonly("forces", &MeshDynamicBondUpdater::getForces) diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index d1f6d1614f..3be1f75eb1 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -41,7 +41,6 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater /// Constructor MeshDynamicBondUpdater(std::shared_ptr sysdef, std::shared_ptr trigger, - std::shared_ptr integrator, std::shared_ptr mesh, Scalar T); @@ -69,7 +68,6 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater private: /// List of all the force computes - std::shared_ptr m_integrator; std::vector> m_forces; std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on std::vector m_update_order; diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 9b4bc61465..99170c0397 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -236,3 +236,15 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential sim.run(1) assert mesh_potential.energy <= energy + +def test_pickling(local_snapshot_factory, simulation_factory): + # don't add the rd_updater since operation_pickling_check will deal with + # that. + snap = local_snapshot_factory(d=0, L=20) + sim = simulation_factory(snap) + mesh = hoomd.mesh.Mesh() + + mdb = hoomd.md.update.MeshDynamicalBonding(1,mesh, kT = 0.001) + + hoomd.conftest.operation_pickling_check(mdb, sim) + diff --git a/hoomd/md/update.py b/hoomd/md/update.py index aa5eee5ee9..2735ab398f 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -360,8 +360,8 @@ def _setattr_param(self, attr, value): super()._setattr_param(attr, value) class MeshDynamicalBonding(Updater): - """Dynamical bonding of the applies mesh that allows edge flips according to a - Metropolic Monte Carlo algorithm. + r"""Dynamical bonding of the applied mesh that allows edge flips according to + a Metropolic Monte Carlo algorithm. Args: trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond @@ -371,14 +371,33 @@ class MeshDynamicalBonding(Updater): kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. - forces (Sequence[hoomd.md.force.Force]): Sequence of forces applied to - the updater. The default value of ``None`` initializes - an empty list. + forces (Sequence[hoomd.md.force.MeshPotential]): Sequence of mesh + potentials applied to the updater. The default value of ``None`` + initializes an empty list. + + `MeshDynamicalBonding` works directly with `hoomd.mesh.Mesh` to apply edge + flips between neighboring triangles in the mesh. At each step, the updater + attempts to flip each edge within the mesh in random order. The probability + of fliping an edge :math:`ij` between the common vertices :math:`i` and + :math:`j` of triangles :math:`ijk` and :math:`jil` to an edge :math:`kl` + between :math:`k` and :math:`l` is: + + .. math:: + + p_\mathrm{accept} = + \begin{cases} + \exp(-\beta (U(kl)-U(ij))) & U(kl) > U(ij) \\ + 1 & \Delta U(kl) \le U(ij).\\ + \end{cases} + + To obtain energies :math:`U(ij)` and :math:`U(kl)` for the corresponding edge + configurations, only the mesh potentials attached to the updater are + considered. Examples:: mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(100), - mesh, kT = 1, forces=[]) + mesh, kT = 1, forces=[mesh_ponetial]) """ @@ -414,7 +433,6 @@ def _attach_hook(self): self._cpp_obj = _md.MeshDynamicBondUpdater( self._simulation.state._cpp_sys_def, self.trigger, - self._simulation.operations.integrator._cpp_obj, self.mesh._cpp_obj, self.kT) self._forces._sync(self._simulation, self._cpp_obj.forces) diff --git a/hoomd/mesh.py b/hoomd/mesh.py index 7aab6ac880..38f3a801a7 100644 --- a/hoomd/mesh.py +++ b/hoomd/mesh.py @@ -153,5 +153,26 @@ def size(self): return 0 return len(self.triangulation["triangles"]) + def create_dynamical_bonding_updater(self, trigger, kT, forces = []): + """Create a dynamical bonding updater for this mesh. + + Args: + trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond + flip attempt. + + kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. + + forces (Sequence[hoomd.md.force.MeshPotential]): Sequence of mesh + potentials applied to the updater. The default value of ``None`` + initializes an empty list. + + Returns: + hoomd.md.update.MeshDynamicalBonding: + The dynamical bonding updater. + """ + return hoomd.md.update.MeshDynamicalBonding( + trigger, self, kT, forces + ) + __all__ = ["Mesh"] From cc4012f7455c3ccc08166320fdf278da4fbc8f24 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 14:51:10 -0400 Subject: [PATCH 40/58] add create_dynamical_bonding_updater --- hoomd/md/update.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 2735ab398f..1929e3e6ce 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -390,9 +390,15 @@ class MeshDynamicalBonding(Updater): 1 & \Delta U(kl) \le U(ij).\\ \end{cases} - To obtain energies :math:`U(ij)` and :math:`U(kl)` for the corresponding edge - configurations, only the mesh potentials attached to the updater are - considered. + To obtain energies :math:`U(ij)` and :math:`U(kl)` for the corresponding edge + configurations, only the mesh potentials attached to the updater are + considered. + + Tip: + Use `hoomd.mesh.Mesh.create_dynamical_bonding_updater` to construct a + `MeshDynamicalBonding` instance. + + {inherited} Examples:: From 578bd548cae3c35f84877036b7f0c9791880a29c Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 15:27:09 -0400 Subject: [PATCH 41/58] fix docs --- hoomd/md/update.py | 4 ++-- hoomd/mesh.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 1929e3e6ce..3d0bd447bb 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -369,9 +369,9 @@ class MeshDynamicalBonding(Updater): mesh (hoomd.mesh.Mesh): Mesh data structure. - kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. + kT (float): Temperature of the simulation :math:`[\mathrm{energy}]`. - forces (Sequence[hoomd.md.force.MeshPotential]): Sequence of mesh + forces (Sequence[hoomd.md.mesh.MeshPotential]): Sequence of mesh potentials applied to the updater. The default value of ``None`` initializes an empty list. diff --git a/hoomd/mesh.py b/hoomd/mesh.py index 38f3a801a7..f2e50eff84 100644 --- a/hoomd/mesh.py +++ b/hoomd/mesh.py @@ -160,9 +160,9 @@ def create_dynamical_bonding_updater(self, trigger, kT, forces = []): trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond flip attempt. - kT (Scalar): Temperature of the simulation :math:`[\mathrm{energy}]`. + kT (float): Temperature of the simulation :math:`[\mathrm{energy}]`. - forces (Sequence[hoomd.md.force.MeshPotential]): Sequence of mesh + forces (Sequence[hoomd.md.mesh.MeshPotential]): Sequence of mesh potentials applied to the updater. The default value of ``None`` initializes an empty list. From 930307e6bc835490b09644560973e4004046f885 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 15:27:38 -0400 Subject: [PATCH 42/58] add meshdynamicalbonding.rst --- sphinx-doc/hoomd/md/update/meshdynamicalbonding.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 sphinx-doc/hoomd/md/update/meshdynamicalbonding.rst diff --git a/sphinx-doc/hoomd/md/update/meshdynamicalbonding.rst b/sphinx-doc/hoomd/md/update/meshdynamicalbonding.rst new file mode 100644 index 0000000000..e37367c76d --- /dev/null +++ b/sphinx-doc/hoomd/md/update/meshdynamicalbonding.rst @@ -0,0 +1,8 @@ +MeshDynamicalBonding +==================== + +.. py:currentmodule:: hoomd.md.update + +.. autoclass:: MeshDynamicalBonding + :members: + :show-inheritance: From 873dedf8199ff7e2ff485da5d15911af2e68c7cd Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 16:00:44 -0400 Subject: [PATCH 43/58] pre-commit --- hoomd/BondedGroupData.h | 2 +- hoomd/ForceCompute.h | 46 +- hoomd/MeshDefinition.cc | 123 ++-- hoomd/MeshDefinition.h | 6 +- hoomd/MeshGroupData.cc | 112 ++-- hoomd/md/AreaConservationMeshForceCompute.cc | 11 +- hoomd/md/AreaConservationMeshForceCompute.h | 13 +- hoomd/md/BendingRigidityMeshForceCompute.cc | 36 +- hoomd/md/BendingRigidityMeshForceCompute.h | 6 +- hoomd/md/HelfrichMeshForceCompute.cc | 13 +- hoomd/md/HelfrichMeshForceCompute.h | 16 +- hoomd/md/MeshDynamicBondUpdater.cc | 633 +++++++++--------- hoomd/md/MeshDynamicBondUpdater.h | 4 +- ...riangleAreaConservationMeshForceCompute.cc | 4 +- .../md/VolumeConservationMeshForceCompute.cc | 2 +- hoomd/md/VolumeConservationMeshForceCompute.h | 10 +- hoomd/md/pytest/test_meshupdater.py | 90 +-- hoomd/md/update.py | 45 +- hoomd/mesh.py | 14 +- hoomd/operation.py | 1 + 20 files changed, 604 insertions(+), 583 deletions(-) diff --git a/hoomd/BondedGroupData.h b/hoomd/BondedGroupData.h index c4d54bb6e9..611eade6ff 100644 --- a/hoomd/BondedGroupData.h +++ b/hoomd/BondedGroupData.h @@ -631,7 +631,7 @@ class BondedGroupData { m_group_num_change_signal.emit(); notifyGroupReorder(); - } + } #ifdef ENABLE_MPI //! Helper function to transfer bonded groups connected to a single particle diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index 1e3bf6a5a7..acb805af28 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -76,32 +76,40 @@ class PYBIND11_EXPORT ForceCompute : public Compute virtual void compute(uint64_t timestep); //! Computes the parameters for meshes - virtual void precomputeParameter(){}; + virtual void precomputeParameter() { }; virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id){return 0;}; + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + return 0; + }; virtual Scalar energyDiffSurrounding(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int idx_e, - unsigned int idx_f, - unsigned int idx_g, - unsigned int idx_h, - unsigned int type_id){ return 0;}; + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int idx_e, + unsigned int idx_f, + unsigned int idx_g, + unsigned int idx_h, + unsigned int type_id) + { + return 0; + }; virtual void postcomputeParameter(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id){}; - + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) { }; - virtual bool checkSurrounding(){ return false;} + virtual bool checkSurrounding() + { + return false; + } //! Total the potential energy Scalar calcEnergySum(); diff --git a/hoomd/MeshDefinition.cc b/hoomd/MeshDefinition.cc index 6040df1baa..449a3bec3d 100644 --- a/hoomd/MeshDefinition.cc +++ b/hoomd/MeshDefinition.cc @@ -146,92 +146,93 @@ void MeshDefinition::setTriangulationData(pybind11::dict triangulation) void MeshDefinition::createMeshNeighborhood() { - - unsigned int len_triang = m_meshtriangle_data->getNGlobal(); + unsigned int len_triang = m_meshtriangle_data->getNGlobal(); GPUArray neigh_to_triag(len_triang, m_sysdef->getParticleData()->getExecConf()); m_neigh_to_triag.swap(neigh_to_triag); - unsigned int len_bond = m_meshbond_data->getNGlobal(); + unsigned int len_bond = m_meshbond_data->getNGlobal(); GPUArray neigh_to_bond(len_bond, m_sysdef->getParticleData()->getExecConf()); m_neigh_to_bond.swap(neigh_to_bond); - ArrayHandle h_neigh_to_bond(m_neigh_to_bond, access_location::host, access_mode::overwrite); + ArrayHandle h_neigh_to_bond(m_neigh_to_bond, + access_location::host, + access_mode::overwrite); - ArrayHandle h_neigh_to_triag(m_neigh_to_triag, access_location::host, access_mode::overwrite); + ArrayHandle h_neigh_to_triag(m_neigh_to_triag, + access_location::host, + access_mode::overwrite); - ArrayHandle h_bonds( - m_meshbond_data->getMembersArray(), - access_location::host, - access_mode::read); + ArrayHandle h_bonds(m_meshbond_data->getMembersArray(), + access_location::host, + access_mode::read); - ArrayHandle h_triangles( - m_meshtriangle_data->getMembersArray(), - access_location::host, - access_mode::read); + ArrayHandle h_triangles(m_meshtriangle_data->getMembersArray(), + access_location::host, + access_mode::read); std::vector bonds(3); unsigned int bond_length = m_meshbond_data->getNGlobal(); for (unsigned int i = 0; i < bond_length; ++i) - { - h_neigh_to_bond.data[i] = make_uint2(bond_length,bond_length); - } + { + h_neigh_to_bond.data[i] = make_uint2(bond_length, bond_length); + } for (unsigned int i = 0; i < m_meshtriangle_data->getNGlobal(); i++) - { + { const typename Angle::members_t& triangle = h_triangles.data[i]; - if(triangle.tag[0] < triangle.tag[1]) - bonds[0] = make_uint2(triangle.tag[0],triangle.tag[1]); - else - bonds[0] = make_uint2(triangle.tag[1],triangle.tag[0]); + if (triangle.tag[0] < triangle.tag[1]) + bonds[0] = make_uint2(triangle.tag[0], triangle.tag[1]); + else + bonds[0] = make_uint2(triangle.tag[1], triangle.tag[0]); - if(triangle.tag[1] < triangle.tag[2]) - bonds[1] = make_uint2(triangle.tag[1],triangle.tag[2]); - else - bonds[1] = make_uint2(triangle.tag[2],triangle.tag[1]); + if (triangle.tag[1] < triangle.tag[2]) + bonds[1] = make_uint2(triangle.tag[1], triangle.tag[2]); + else + bonds[1] = make_uint2(triangle.tag[2], triangle.tag[1]); - if(triangle.tag[0] < triangle.tag[2]) - bonds[2] = make_uint2(triangle.tag[0],triangle.tag[2]); - else - bonds[2] = make_uint2(triangle.tag[2],triangle.tag[0]); + if (triangle.tag[0] < triangle.tag[2]) + bonds[2] = make_uint2(triangle.tag[0], triangle.tag[2]); + else + bonds[2] = make_uint2(triangle.tag[2], triangle.tag[0]); - unsigned int counter = 0; - std::vector t_idx; - std::vector b_done(bond_length); + unsigned int counter = 0; + std::vector t_idx; + std::vector b_done(bond_length); - for (unsigned int j = 0; j < bond_length; ++j) - b_done[j]=false; + for (unsigned int j = 0; j < bond_length; ++j) + b_done[j] = false; - for (unsigned int j = 0; j < bond_length; ++j) - { - if( b_done[j]) - continue; + for (unsigned int j = 0; j < bond_length; ++j) + { + if (b_done[j]) + continue; const typename MeshBond::members_t& meshbond = h_bonds.data[j]; - for (unsigned int k = 0; k < 3; ++k) - { - if (bonds[k].x == meshbond.tag[0] && bonds[k].y == meshbond.tag[1]) - { - t_idx.push_back(j); - h_neigh_to_bond.data[j].y = i; - if(h_neigh_to_bond.data[j].x != bond_length) - b_done[j] = true; - else - h_neigh_to_bond.data[j].x = i; - counter++; - break; - } - } - if( counter == 3) - { - h_neigh_to_triag.data[i].x = t_idx[0]; - h_neigh_to_triag.data[i].y = t_idx[1]; - h_neigh_to_triag.data[i].z = t_idx[2]; - break; - } - } - } + for (unsigned int k = 0; k < 3; ++k) + { + if (bonds[k].x == meshbond.tag[0] && bonds[k].y == meshbond.tag[1]) + { + t_idx.push_back(j); + h_neigh_to_bond.data[j].y = i; + if (h_neigh_to_bond.data[j].x != bond_length) + b_done[j] = true; + else + h_neigh_to_bond.data[j].x = i; + counter++; + break; + } + } + if (counter == 3) + { + h_neigh_to_triag.data[i].x = t_idx[0]; + h_neigh_to_triag.data[i].y = t_idx[1]; + h_neigh_to_triag.data[i].z = t_idx[2]; + break; + } + } + } } namespace detail diff --git a/hoomd/MeshDefinition.h b/hoomd/MeshDefinition.h index 08a8c33601..6f57871ff4 100644 --- a/hoomd/MeshDefinition.h +++ b/hoomd/MeshDefinition.h @@ -117,9 +117,9 @@ class PYBIND11_EXPORT MeshDefinition std::shared_ptr m_sysdef; //!< System definition std::shared_ptr m_meshbond_data; //!< Bond data for the mesh std::shared_ptr m_meshtriangle_data; //!< Triangle data for the mesh - // - GPUArray m_neigh_to_bond; //!< triangle ids corresponding to bond - GPUArray m_neigh_to_triag; //!< bond ids corresponding to triangle + // + GPUArray m_neigh_to_bond; //!< triangle ids corresponding to bond + GPUArray m_neigh_to_triag; //!< bond ids corresponding to triangle }; namespace detail diff --git a/hoomd/MeshGroupData.cc b/hoomd/MeshGroupData.cc index f5a63e26aa..474bbda689 100644 --- a/hoomd/MeshGroupData.cc +++ b/hoomd/MeshGroupData.cc @@ -123,61 +123,60 @@ void MeshGroupData::initializeFromTriangleSnapsho std::vector all_types; for (unsigned group_idx = 0; group_idx < snapshot.groups.size(); group_idx++) - { - std::vector triag_tag(3); - std::vector::members_t> bonds( - 3); - triag_tag[0] = snapshot.groups[group_idx].tag[0]; - triag_tag[1] = snapshot.groups[group_idx].tag[1]; - triag_tag[2] = snapshot.groups[group_idx].tag[2]; - - bonds[0].tag[0] = triag_tag[0]; - bonds[0].tag[1] = triag_tag[1]; - bonds[0].tag[2] = triag_tag[2]; - bonds[0].tag[3] = triag_tag[2]; - - bonds[1].tag[0] = triag_tag[1]; - bonds[1].tag[1] = triag_tag[2]; - bonds[1].tag[2] = triag_tag[0]; - bonds[1].tag[3] = triag_tag[0]; - - bonds[2].tag[0] = triag_tag[2]; - bonds[2].tag[1] = triag_tag[0]; - bonds[2].tag[2] = triag_tag[1]; - bonds[2].tag[3] = triag_tag[1]; - - for (unsigned int j = 0; j < bonds.size(); ++j) - { - if (bonds[j].tag[0] > bonds[j].tag[1]) - { - unsigned int bonds0 = bonds[j].tag[0]; - unsigned int bonds1 = bonds[j].tag[1]; - - bonds[j].tag[0] = bonds1; - bonds[j].tag[1] = bonds0; - } - } - - // Remove any duplicate bonds. - for (unsigned int i = 0; i < all_helper.size(); ++i) - { - for (unsigned int j = 0; j < bonds.size(); ++j) - { - if (bonds[j].tag[0] == all_helper[i].tag[0] - && bonds[j].tag[1] == all_helper[i].tag[1]) - { - all_helper[i].tag[3] = bonds[j].tag[2]; - bonds.erase(bonds.begin() + j); - break; - } - } - } - for (unsigned int i = 0; i < bonds.size(); ++i) - { - all_helper.push_back(bonds[i]); - all_types.push_back(snapshot.type_id[group_idx]); - } - } + { + std::vector triag_tag(3); + std::vector::members_t> bonds(3); + triag_tag[0] = snapshot.groups[group_idx].tag[0]; + triag_tag[1] = snapshot.groups[group_idx].tag[1]; + triag_tag[2] = snapshot.groups[group_idx].tag[2]; + + bonds[0].tag[0] = triag_tag[0]; + bonds[0].tag[1] = triag_tag[1]; + bonds[0].tag[2] = triag_tag[2]; + bonds[0].tag[3] = triag_tag[2]; + + bonds[1].tag[0] = triag_tag[1]; + bonds[1].tag[1] = triag_tag[2]; + bonds[1].tag[2] = triag_tag[0]; + bonds[1].tag[3] = triag_tag[0]; + + bonds[2].tag[0] = triag_tag[2]; + bonds[2].tag[1] = triag_tag[0]; + bonds[2].tag[2] = triag_tag[1]; + bonds[2].tag[3] = triag_tag[1]; + + for (unsigned int j = 0; j < bonds.size(); ++j) + { + if (bonds[j].tag[0] > bonds[j].tag[1]) + { + unsigned int bonds0 = bonds[j].tag[0]; + unsigned int bonds1 = bonds[j].tag[1]; + + bonds[j].tag[0] = bonds1; + bonds[j].tag[1] = bonds0; + } + } + + // Remove any duplicate bonds. + for (unsigned int i = 0; i < all_helper.size(); ++i) + { + for (unsigned int j = 0; j < bonds.size(); ++j) + { + if (bonds[j].tag[0] == all_helper[i].tag[0] + && bonds[j].tag[1] == all_helper[i].tag[1]) + { + all_helper[i].tag[3] = bonds[j].tag[2]; + bonds.erase(bonds.begin() + j); + break; + } + } + } + for (unsigned int i = 0; i < bonds.size(); ++i) + { + all_helper.push_back(bonds[i]); + all_types.push_back(snapshot.type_id[group_idx]); + } + } all_groups = all_helper; #ifdef ENABLE_MPI @@ -501,9 +500,6 @@ MeshGroupData::takeSnapshot(snap& snapshot) const return index; } - - - namespace detail { template diff --git a/hoomd/md/AreaConservationMeshForceCompute.cc b/hoomd/md/AreaConservationMeshForceCompute.cc index 76e0f482a4..ae24bf9220 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.cc +++ b/hoomd/md/AreaConservationMeshForceCompute.cc @@ -455,8 +455,8 @@ Scalar AreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, c_cbbd = -1.0; Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); - if( s_caad == 0 || s_cbbd == 0) - return DBL_MAX; + if (s_caad == 0 || s_cbbd == 0) + return DBL_MAX; Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; if (c_accb > 1.0) @@ -479,12 +479,11 @@ Scalar AreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, Scalar AreaDiff = h_area.data[type_id] - h_params.data[type_id].A0; - Scalar energy_old = AreaDiff * AreaDiff; + Scalar energy_old = AreaDiff * AreaDiff; - Scalar energy_new = (AreaDiff + m_area_diff) * (AreaDiff + m_area_diff); + Scalar energy_new = (AreaDiff + m_area_diff) * (AreaDiff + m_area_diff); - return h_params.data[type_id].k * (energy_new - energy_old) - / (2 * h_params.data[type_id].A0); + return h_params.data[type_id].k * (energy_new - energy_old) / (2 * h_params.data[type_id].A0); } namespace detail diff --git a/hoomd/md/AreaConservationMeshForceCompute.h b/hoomd/md/AreaConservationMeshForceCompute.h index 86b0dd6998..e33ddf4e61 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.h +++ b/hoomd/md/AreaConservationMeshForceCompute.h @@ -74,8 +74,8 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public ForceCompute GPUArray m_params; //!< Parameters GPUArray m_area; //!< memory space for area Scalar m_area_diff; - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing energy - bool m_ignore_type; //! ignore type to calculate global area if true + std::shared_ptr m_mesh_data; //!< Mesh data to use in computing energy + bool m_ignore_type; //! ignore type to calculate global area if true //! Actually compute the forces virtual void computeForces(uint64_t timestep); @@ -88,17 +88,16 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public ForceCompute unsigned int idx_c, unsigned int idx_d, unsigned int type_id) - { - ArrayHandle h_area(m_area, access_location::host, access_mode::readwrite); - h_area.data[type_id] += m_area_diff; - }; + { + ArrayHandle h_area(m_area, access_location::host, access_mode::readwrite); + h_area.data[type_id] += m_area_diff; + }; virtual Scalar energyDiff(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, unsigned int idx_d, unsigned int type_id); - }; namespace detail diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index 379d910eb8..24b321639b 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -336,17 +336,17 @@ Scalar BendingRigidityMeshForceCompute::calcEnergy(unsigned int idx_a, z2.x = dad.y * dab.z - dad.z * dab.y; z2.y = dad.z * dab.x - dad.x * dab.z; z2.z = dad.x * dab.y - dad.y * dab.x; - + Scalar n1 = z1.x * z1.x + z1.y * z1.y + z1.z * z1.z; Scalar n2 = z2.x * z2.x + z2.y * z2.y + z2.z * z2.z; - if( n1 == 0 || n2 == 0) - return DBL_MAX; + if (n1 == 0 || n2 == 0) + return DBL_MAX; Scalar z1z2 = z1.x * z2.x + z1.y * z2.y + z1.z * z2.z; - Scalar cosinus = z1z2 * fast::rsqrt( n1 * n2); + Scalar cosinus = z1z2 * fast::rsqrt(n1 * n2); - return h_params.data[type_id] * 0.5 * (1-cosinus); + return h_params.data[type_id] * 0.5 * (1 - cosinus); } Scalar BendingRigidityMeshForceCompute::energyDiff(unsigned int idx_a, @@ -355,10 +355,10 @@ Scalar BendingRigidityMeshForceCompute::energyDiff(unsigned int idx_a, unsigned int idx_d, unsigned int type_id) { - Scalar energy_old = calcEnergy(idx_a,idx_b,idx_c,idx_d,type_id); - Scalar energy_new = calcEnergy(idx_c,idx_d,idx_b,idx_a,type_id); + Scalar energy_old = calcEnergy(idx_a, idx_b, idx_c, idx_d, type_id); + Scalar energy_new = calcEnergy(idx_c, idx_d, idx_b, idx_a, type_id); - return energy_new-energy_old; + return energy_new - energy_old; } Scalar BendingRigidityMeshForceCompute::energyDiffSurrounding(unsigned int idx_a, @@ -371,21 +371,19 @@ Scalar BendingRigidityMeshForceCompute::energyDiffSurrounding(unsigned int idx_a unsigned int idx_h, unsigned int type_id) { - Scalar energy_new = calcEnergy(idx_a,idx_c,idx_e,idx_d,type_id); - energy_new += calcEnergy(idx_c,idx_b,idx_f,idx_d,type_id); - energy_new += calcEnergy(idx_a,idx_d,idx_c,idx_g,type_id); - energy_new += calcEnergy(idx_d,idx_b,idx_c,idx_h,type_id); + Scalar energy_new = calcEnergy(idx_a, idx_c, idx_e, idx_d, type_id); + energy_new += calcEnergy(idx_c, idx_b, idx_f, idx_d, type_id); + energy_new += calcEnergy(idx_a, idx_d, idx_c, idx_g, type_id); + energy_new += calcEnergy(idx_d, idx_b, idx_c, idx_h, type_id); - Scalar energy_old = calcEnergy(idx_a,idx_c,idx_e,idx_b,type_id); - energy_old += calcEnergy(idx_c,idx_b,idx_f,idx_a,type_id); - energy_old += calcEnergy(idx_a,idx_d,idx_b,idx_g,type_id); - energy_old += calcEnergy(idx_d,idx_b,idx_a,idx_h,type_id); + Scalar energy_old = calcEnergy(idx_a, idx_c, idx_e, idx_b, type_id); + energy_old += calcEnergy(idx_c, idx_b, idx_f, idx_a, type_id); + energy_old += calcEnergy(idx_a, idx_d, idx_b, idx_g, type_id); + energy_old += calcEnergy(idx_d, idx_b, idx_a, idx_h, type_id); - return energy_new - energy_old; + return energy_new - energy_old; } - - namespace detail { void export_BendingRigidityMeshForceCompute(pybind11::module& m) diff --git a/hoomd/md/BendingRigidityMeshForceCompute.h b/hoomd/md/BendingRigidityMeshForceCompute.h index 1d81868968..a14f148af1 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.h +++ b/hoomd/md/BendingRigidityMeshForceCompute.h @@ -112,8 +112,10 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public ForceCompute unsigned int idx_h, unsigned int type_id); - virtual bool checkSurrounding(){return true;} - + virtual bool checkSurrounding() + { + return true; + } }; namespace detail diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index da6f369494..6bf0ea9040 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -672,7 +672,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_caad = sqrt(1.0 - c_caad * c_caad); if (inv_s_caad < SMALL) - inv_s_caad = SMALL; + inv_s_caad = SMALL; inv_s_caad = 1.0 / inv_s_caad; Scalar c_cbbd = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; @@ -683,7 +683,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); if (inv_s_cbbd < SMALL) - inv_s_cbbd = SMALL; + inv_s_cbbd = SMALL; inv_s_cbbd = 1.0 / inv_s_cbbd; Scalar c_accd = -(nac.x * ncd.x + nac.y * ncd.y + nac.z * ncd.z); @@ -694,7 +694,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_accd = sqrt(1.0 - c_accd * c_accd); if (inv_s_accd < SMALL) - inv_s_accd = SMALL; + inv_s_accd = SMALL; inv_s_accd = 1.0 / inv_s_accd; Scalar c_addc = nad.x * ncd.x + nad.y * ncd.y + nad.z * ncd.z; @@ -705,7 +705,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_addc = sqrt(1.0 - c_addc * c_addc); if (inv_s_addc < SMALL) - inv_s_addc = SMALL; + inv_s_addc = SMALL; inv_s_addc = 1.0 / inv_s_addc; Scalar c_bccd = -(nbc.x * ncd.x + nbc.y * ncd.y + nbc.z * ncd.z); @@ -716,7 +716,7 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_bccd = sqrt(1.0 - c_bccd * c_bccd); if (inv_s_bccd < SMALL) - inv_s_bccd = SMALL; + inv_s_bccd = SMALL; inv_s_bccd = 1.0 / inv_s_bccd; Scalar c_bddc = nbd.x * ncd.x + nbd.y * ncd.y + nbd.z * ncd.z; @@ -727,10 +727,9 @@ Scalar HelfrichMeshForceCompute::energyDiff(unsigned int idx_a, Scalar inv_s_bddc = sqrt(1.0 - c_bddc * c_bddc); if (inv_s_bddc < SMALL) - inv_s_bddc = SMALL; + inv_s_bddc = SMALL; inv_s_bddc = 1.0 / inv_s_bddc; - Scalar cot_accb = c_accb * inv_s_accb; Scalar cot_addb = c_addb * inv_s_addb; Scalar cot_baac = c_baac * inv_s_baac; diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index bc4e059a02..f950ff56de 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -84,19 +84,19 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute virtual void computeForces(uint64_t timestep); virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); //! compute sigmas virtual void precomputeParameter(); virtual void postcomputeParameter(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id); }; namespace detail diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 024a1eeea7..0ad4b3217e 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2022 The Regents of the University of Michigan. +// Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. /*! \file MeshDynamicBondUpdater.cc @@ -38,7 +38,6 @@ MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr m_update_order.resize(m_mesh->getMeshBondData()->getN()); - m_exec_conf->msg->notice(5) << "Constructing MeshDynamicBondUpdater" << endl; } @@ -47,7 +46,6 @@ MeshDynamicBondUpdater::~MeshDynamicBondUpdater() m_exec_conf->msg->notice(5) << "Destroying MeshDynamicBondUpdater" << endl; } - /** Perform the needed calculations to update particle orientations \param timestep Current time step of the simulation */ @@ -58,345 +56,352 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) for (auto& force : m_forces) force->precomputeParameter(); - { + { + const Index2D& table_indexer = m_mesh->getMeshBondData()->getGPUTableIndexer(); - const Index2D& table_indexer = m_mesh->getMeshBondData()->getGPUTableIndexer(); + ArrayHandle h_meshbondlist( + m_mesh->getMeshBondData()->getGPUTable(), + access_location::host, + access_mode::read); - ArrayHandle h_meshbondlist(m_mesh->getMeshBondData()->getGPUTable(), - access_location::host, - access_mode::read); + ArrayHandle h_n_meshbond(m_mesh->getMeshBondData()->getNGroupsArray(), + access_location::host, + access_mode::read); - ArrayHandle h_n_meshbond( - m_mesh->getMeshBondData()->getNGroupsArray(), - access_location::host, - access_mode::read); + ArrayHandle h_meshbond_pos_list(m_mesh->getMeshBondData()->getGPUPosTable(), + access_location::host, + access_mode::read); - ArrayHandle h_meshbond_pos_list( - m_mesh->getMeshBondData()->getGPUPosTable(), - access_location::host, - access_mode::read); + ArrayHandle h_bonds( + m_mesh->getMeshBondData()->getMembersArray(), + access_location::host, + access_mode::readwrite); + ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond(), + access_location::host, + access_mode::readwrite); - ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_triangles( + m_mesh->getMeshTriangleData()->getMembersArray(), + access_location::host, + access_mode::readwrite); - ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag(), + access_location::host, + access_mode::readwrite); - ArrayHandle h_triangles( - m_mesh->getMeshTriangleData()->getMembersArray(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_rtag(m_pdata->getRTags(), + access_location::host, + access_mode::read); - ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_typeval(m_mesh->getMeshBondData()->getTypeValArray(), + access_location::host, + access_mode::read); - ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); + // for each of the angles + const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); - ArrayHandle h_typeval(m_mesh->getMeshBondData()->getTypeValArray(), - access_location::host, - access_mode::read); + hoomd::RandomGenerator rng( + hoomd::Seed(hoomd::RNGIdentifier::MeshDynamicBondUpdateOrder, timestep, seed), + hoomd::Counter(m_exec_conf->getRank())); - // for each of the angles - const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); + // maybe too slow + for (unsigned int i = 0; i < size; i++) + m_update_order[i] = i; - hoomd::RandomGenerator rng( - hoomd::Seed(hoomd::RNGIdentifier::MeshDynamicBondUpdateOrder, timestep, seed), - hoomd::Counter(m_exec_conf->getRank())); + for (unsigned int i = size - 1; i > 0; i--) + { + unsigned int j = hoomd::UniformIntDistribution(i)(rng); + std::swap(m_update_order[i], m_update_order[j]); + } -// maybe too slow - for (unsigned int i = 0; i < size; i++) - m_update_order[i] = i; + std::vector changed; - for (unsigned int i = size-1; i>0; i--) - { - unsigned int j = hoomd::UniformIntDistribution(i)(rng); - std::swap(m_update_order[i], m_update_order[j]); - } + for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) + { + unsigned int i = m_update_order[cur_bond]; + typename MeshBond::members_t& bond = h_bonds.data[i]; + assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); + assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); - std::vector changed; + unsigned int tag_c = bond.tag[2]; + unsigned int tag_d = bond.tag[3]; + + if (tag_c == tag_d) + continue; + + bool already_changed = false; + for (unsigned int ii = 0; ii < changed.size(); ii++) + { + if ((changed[ii].x == tag_c && changed[ii].y == tag_d) + || (changed[ii].x == tag_d && changed[ii].y == tag_c)) + { + already_changed = true; + break; + } + } + if (already_changed) + continue; + + unsigned int idx_c = h_rtag.data[tag_c]; + unsigned int idx_d = h_rtag.data[tag_d]; + + { + ArrayHandle h_pos(m_pdata->getPositions(), + access_location::host, + access_mode::read); + Scalar3 boxL = m_pdata->getGlobalBox().getL() / 4; + + Scalar3 dcd; + dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; + if (dcd.x > boxL.x || dcd.x < -boxL.x) + continue; + dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; + if (dcd.y > boxL.y || dcd.y < -boxL.y) + continue; + dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; + if (dcd.y > boxL.y || dcd.y < -boxL.y) + continue; + } + + unsigned int tag_a = bond.tag[0]; + unsigned int tag_b = bond.tag[1]; + + unsigned int idx_a = h_rtag.data[tag_a]; + unsigned int idx_b = h_rtag.data[tag_b]; + + unsigned int test_idx = idx_c; + + for (unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) + { + if (h_meshbond_pos_list.data[table_indexer(idx_c, ii)] > 1) + continue; + test_idx = h_meshbondlist.data[table_indexer(idx_c, ii)].idx[0]; + if (test_idx == idx_d) + break; + } + + if (test_idx == idx_d) + continue; + + unsigned int tr_idx1 = h_neigh_bonds.data[i].x; + unsigned int tr_idx2 = h_neigh_bonds.data[i].y; + + typename Angle::members_t& triangleT = h_triangles.data[tr_idx1]; + + for (unsigned int j = 0; j < 3; j++) + { + if (triangleT.tag[j] == tag_d) + { + tr_idx1 = h_neigh_bonds.data[i].y; + tr_idx2 = h_neigh_bonds.data[i].x; + break; + } + } + + typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; + + unsigned int iterator = 0; + + bool a_before_b = false; + + while (tag_a != triangle1.tag[iterator]) + iterator++; - for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) - { - unsigned int i = m_update_order[cur_bond]; - typename MeshBond::members_t& bond = h_bonds.data[i]; - assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); - assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); - - unsigned int tag_c = bond.tag[2]; - unsigned int tag_d = bond.tag[3]; - - if (tag_c == tag_d) - continue; - - bool already_changed = false; - for( unsigned int ii = 0; ii < changed.size(); ii++) - { - if( (changed[ii].x == tag_c && changed[ii].y == tag_d) || (changed[ii].x == tag_d && changed[ii].y == tag_c) ) - { - already_changed = true; - break; - } - } - if(already_changed) - continue; - - unsigned int idx_c = h_rtag.data[tag_c]; - unsigned int idx_d = h_rtag.data[tag_d]; - - { - ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); - Scalar3 boxL = m_pdata->getGlobalBox().getL()/4; - - Scalar3 dcd; - dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; - if( dcd.x > boxL.x || dcd.x < -boxL.x) - continue; - dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; - if( dcd.y > boxL.y || dcd.y < -boxL.y) - continue; - dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; - if( dcd.y > boxL.y || dcd.y < -boxL.y) - continue; - } - - - unsigned int tag_a = bond.tag[0]; - unsigned int tag_b = bond.tag[1]; - - unsigned int idx_a = h_rtag.data[tag_a]; - unsigned int idx_b = h_rtag.data[tag_b]; - - - unsigned int test_idx = idx_c; - - for( unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) - { - if( h_meshbond_pos_list.data[table_indexer(idx_c,ii)] > 1 ) - continue; - test_idx = h_meshbondlist.data[table_indexer(idx_c,ii)].idx[0]; - if(test_idx == idx_d) - break; - } - - if(test_idx == idx_d) - continue; - - unsigned int tr_idx1 = h_neigh_bonds.data[i].x; - unsigned int tr_idx2 = h_neigh_bonds.data[i].y; - - typename Angle::members_t& triangleT = h_triangles.data[tr_idx1]; - - for( unsigned int j = 0; j<3; j++) - { - if(triangleT.tag[j] == tag_d) - { - tr_idx1 = h_neigh_bonds.data[i].y; - tr_idx2 = h_neigh_bonds.data[i].x; - break; - } - } - - typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; - - unsigned int iterator = 0; - - bool a_before_b = false; - - while (tag_a != triangle1.tag[iterator]) - iterator++; - - iterator = (iterator + 1) % 3; - - if (tag_b == triangle1.tag[iterator]) - { - a_before_b = true; iterator = (iterator + 1) % 3; - } - unsigned int type_id = h_typeval.data[i].type; + if (tag_b == triangle1.tag[iterator]) + { + a_before_b = true; + iterator = (iterator + 1) % 3; + } - Scalar energyDifference = 0; + unsigned int type_id = h_typeval.data[i].type; - unsigned int idx_cc = idx_d; - unsigned int idx_dd = idx_c; + Scalar energyDifference = 0; - if (a_before_b) - { - idx_cc = idx_c; - idx_dd = idx_d; - } - - bool have_to_check_surrounding = false; - for (auto& force : m_forces) - { - energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); - if(force->checkSurrounding()) - have_to_check_surrounding = true; - } - - - // Initialize the RNG - RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), - hoomd::Counter(i)); - - // compute the random force - UniformDistribution uniform(0, Scalar(1)); - - Scalar rand_number = uniform(rng); - Scalar part_func = exp(-m_inv_T * energyDifference); - - std::vector tr_idx(6); - std::vector b_idx(4); - std::vector v_idx(8); - - if (have_to_check_surrounding || part_func > rand_number ) - { - tr_idx[1] = tr_idx1; - tr_idx[0] = tr_idx2; - - v_idx[0]=tag_a; - v_idx[1]=tag_b; - v_idx[2]=tag_d; - v_idx[3]=tag_c; - - if(a_before_b) - { - tr_idx[0] = tr_idx1; - tr_idx[1] = tr_idx2; - v_idx[2]=tag_c; - v_idx[3]=tag_d; - } - - unsigned int counter = 4; - - for(unsigned int j = 0; j < 2; ++j) - { - unsigned int bic = h_neigh_triags.data[tr_idx[j]].x; - unsigned int bic2 = h_neigh_triags.data[tr_idx[j]].y; - if(bic == i) - { - bic = bic2; - bic2 = h_neigh_triags.data[tr_idx[j]].z; - } - else - { - if(bic2 == i) - bic2 = h_neigh_triags.data[tr_idx[j]].z; - } - if( h_bonds.data[bic].tag[0] == tag_a || h_bonds.data[bic].tag[1] == tag_a) - { - b_idx[2*j] = bic; - b_idx[2*j+1] = bic2; - } - else - { - b_idx[2*j+1] = bic; - b_idx[2*j] = bic2; - } - for(unsigned int k = 0; k < 2; ++k) - { - unsigned int tic = h_neigh_bonds.data[b_idx[2*j+k]].x; - if(tic == tr_idx[j]) - tic = h_neigh_bonds.data[b_idx[2*j+k]].y; - unsigned int zaehler = 1; - unsigned int nv_idx = h_triangles.data[tic].tag[0]; - while(nv_idx == v_idx[k] || nv_idx == v_idx[2+j]) - { - nv_idx = h_triangles.data[tic].tag[zaehler]; - zaehler++; - } - v_idx[counter] = nv_idx; - tr_idx[counter-2] = tic; - counter++; - } - } - - uint2 bb; - bb.x = v_idx[2]; - bb.y = v_idx[3]; - changed.push_back(bb); - - if (have_to_check_surrounding) - { - for (auto& force : m_forces) - energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]],h_rtag.data[v_idx[1]],h_rtag.data[v_idx[2]],h_rtag.data[v_idx[3]],h_rtag.data[v_idx[4]],h_rtag.data[v_idx[5]],h_rtag.data[v_idx[6]],h_rtag.data[v_idx[7]], type_id); - part_func = exp(-m_inv_T * energyDifference); - } - } - - if (part_func > rand_number) - { - //Flip bond - if(v_idx[2] > v_idx[3]) - { - h_bonds.data[i].tag[1] = v_idx[2]; - h_bonds.data[i].tag[0] = v_idx[3]; - } - else - { - h_bonds.data[i].tag[0] = v_idx[2]; - h_bonds.data[i].tag[1] = v_idx[3]; - } - h_bonds.data[i].tag[2] = v_idx[0]; - h_bonds.data[i].tag[3] = v_idx[1]; - - //Update triagles asociated with the bond - h_triangles.data[tr_idx[0]].tag[0] = v_idx[0]; - h_triangles.data[tr_idx[0]].tag[1] = v_idx[3]; - h_triangles.data[tr_idx[0]].tag[2] = v_idx[2]; - - h_triangles.data[tr_idx[1]].tag[0] = v_idx[1]; - h_triangles.data[tr_idx[1]].tag[1] = v_idx[2]; - h_triangles.data[tr_idx[1]].tag[2] = v_idx[3]; - - h_bonds.data[b_idx[0]].tag[2] = v_idx[3]; - h_bonds.data[b_idx[0]].tag[3] = v_idx[4]; - - h_bonds.data[b_idx[1]].tag[2] = v_idx[3]; - h_bonds.data[b_idx[1]].tag[3] = v_idx[5]; - - h_bonds.data[b_idx[2]].tag[2] = v_idx[2]; - h_bonds.data[b_idx[2]].tag[3] = v_idx[6]; - - h_bonds.data[b_idx[3]].tag[2] = v_idx[2]; - h_bonds.data[b_idx[3]].tag[3] = v_idx[7]; - - //Update triangle neighbors list for the surrounding bonds - h_neigh_bonds.data[b_idx[0]].x = tr_idx[0]; - h_neigh_bonds.data[b_idx[0]].y = tr_idx[2]; - - h_neigh_bonds.data[b_idx[2]].x = tr_idx[0]; - h_neigh_bonds.data[b_idx[2]].y = tr_idx[4]; - - h_neigh_bonds.data[b_idx[1]].x = tr_idx[1]; - h_neigh_bonds.data[b_idx[1]].y = tr_idx[3]; - - h_neigh_bonds.data[b_idx[3]].x = tr_idx[1]; - h_neigh_bonds.data[b_idx[3]].y = tr_idx[5]; - - //Update bond neighbors list for the two triangles - h_neigh_triags.data[tr_idx[0]].x = i; - h_neigh_triags.data[tr_idx[0]].y = b_idx[0]; - h_neigh_triags.data[tr_idx[0]].z = b_idx[2]; - - h_neigh_triags.data[tr_idx[1]].x = i; - h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; - h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; + unsigned int idx_cc = idx_d; + unsigned int idx_dd = idx_c; + if (a_before_b) + { + idx_cc = idx_c; + idx_dd = idx_d; + } + + bool have_to_check_surrounding = false; for (auto& force : m_forces) { - force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); + energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); + if (force->checkSurrounding()) + have_to_check_surrounding = true; + } + + // Initialize the RNG + RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), + hoomd::Counter(i)); + + // compute the random force + UniformDistribution uniform(0, Scalar(1)); + + Scalar rand_number = uniform(rng); + Scalar part_func = exp(-m_inv_T * energyDifference); + + std::vector tr_idx(6); + std::vector b_idx(4); + std::vector v_idx(8); + + if (have_to_check_surrounding || part_func > rand_number) + { + tr_idx[1] = tr_idx1; + tr_idx[0] = tr_idx2; + + v_idx[0] = tag_a; + v_idx[1] = tag_b; + v_idx[2] = tag_d; + v_idx[3] = tag_c; + + if (a_before_b) + { + tr_idx[0] = tr_idx1; + tr_idx[1] = tr_idx2; + v_idx[2] = tag_c; + v_idx[3] = tag_d; + } + + unsigned int counter = 4; + + for (unsigned int j = 0; j < 2; ++j) + { + unsigned int bic = h_neigh_triags.data[tr_idx[j]].x; + unsigned int bic2 = h_neigh_triags.data[tr_idx[j]].y; + if (bic == i) + { + bic = bic2; + bic2 = h_neigh_triags.data[tr_idx[j]].z; + } + else + { + if (bic2 == i) + bic2 = h_neigh_triags.data[tr_idx[j]].z; + } + if (h_bonds.data[bic].tag[0] == tag_a || h_bonds.data[bic].tag[1] == tag_a) + { + b_idx[2 * j] = bic; + b_idx[2 * j + 1] = bic2; + } + else + { + b_idx[2 * j + 1] = bic; + b_idx[2 * j] = bic2; + } + for (unsigned int k = 0; k < 2; ++k) + { + unsigned int tic = h_neigh_bonds.data[b_idx[2 * j + k]].x; + if (tic == tr_idx[j]) + tic = h_neigh_bonds.data[b_idx[2 * j + k]].y; + unsigned int zaehler = 1; + unsigned int nv_idx = h_triangles.data[tic].tag[0]; + while (nv_idx == v_idx[k] || nv_idx == v_idx[2 + j]) + { + nv_idx = h_triangles.data[tic].tag[zaehler]; + zaehler++; + } + v_idx[counter] = nv_idx; + tr_idx[counter - 2] = tic; + counter++; + } + } + + uint2 bb; + bb.x = v_idx[2]; + bb.y = v_idx[3]; + changed.push_back(bb); + + if (have_to_check_surrounding) + { + for (auto& force : m_forces) + energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]], + h_rtag.data[v_idx[1]], + h_rtag.data[v_idx[2]], + h_rtag.data[v_idx[3]], + h_rtag.data[v_idx[4]], + h_rtag.data[v_idx[5]], + h_rtag.data[v_idx[6]], + h_rtag.data[v_idx[7]], + type_id); + part_func = exp(-m_inv_T * energyDifference); + } + } + + if (part_func > rand_number) + { + // Flip bond + if (v_idx[2] > v_idx[3]) + { + h_bonds.data[i].tag[1] = v_idx[2]; + h_bonds.data[i].tag[0] = v_idx[3]; + } + else + { + h_bonds.data[i].tag[0] = v_idx[2]; + h_bonds.data[i].tag[1] = v_idx[3]; + } + h_bonds.data[i].tag[2] = v_idx[0]; + h_bonds.data[i].tag[3] = v_idx[1]; + + // Update triagles asociated with the bond + h_triangles.data[tr_idx[0]].tag[0] = v_idx[0]; + h_triangles.data[tr_idx[0]].tag[1] = v_idx[3]; + h_triangles.data[tr_idx[0]].tag[2] = v_idx[2]; + + h_triangles.data[tr_idx[1]].tag[0] = v_idx[1]; + h_triangles.data[tr_idx[1]].tag[1] = v_idx[2]; + h_triangles.data[tr_idx[1]].tag[2] = v_idx[3]; + + h_bonds.data[b_idx[0]].tag[2] = v_idx[3]; + h_bonds.data[b_idx[0]].tag[3] = v_idx[4]; + + h_bonds.data[b_idx[1]].tag[2] = v_idx[3]; + h_bonds.data[b_idx[1]].tag[3] = v_idx[5]; + + h_bonds.data[b_idx[2]].tag[2] = v_idx[2]; + h_bonds.data[b_idx[2]].tag[3] = v_idx[6]; + + h_bonds.data[b_idx[3]].tag[2] = v_idx[2]; + h_bonds.data[b_idx[3]].tag[3] = v_idx[7]; + + // Update triangle neighbors list for the surrounding bonds + h_neigh_bonds.data[b_idx[0]].x = tr_idx[0]; + h_neigh_bonds.data[b_idx[0]].y = tr_idx[2]; + + h_neigh_bonds.data[b_idx[2]].x = tr_idx[0]; + h_neigh_bonds.data[b_idx[2]].y = tr_idx[4]; + + h_neigh_bonds.data[b_idx[1]].x = tr_idx[1]; + h_neigh_bonds.data[b_idx[1]].y = tr_idx[3]; + + h_neigh_bonds.data[b_idx[3]].x = tr_idx[1]; + h_neigh_bonds.data[b_idx[3]].y = tr_idx[5]; + + // Update bond neighbors list for the two triangles + h_neigh_triags.data[tr_idx[0]].x = i; + h_neigh_triags.data[tr_idx[0]].y = b_idx[0]; + h_neigh_triags.data[tr_idx[0]].z = b_idx[2]; + + h_neigh_triags.data[tr_idx[1]].x = i; + h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; + h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; + + for (auto& force : m_forces) + { + force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); + } + m_mesh->getMeshBondData()->groupReorder(); + m_mesh->getMeshTriangleData()->groupReorder(); } - m_mesh->getMeshBondData()->groupReorder(); - m_mesh->getMeshTriangleData()->groupReorder(); } } - - } } namespace detail diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index 3be1f75eb1..4aa535b961 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2022 The Regents of the University of Michigan. +// Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. /*! \file ActiveRotationalDiffusionUpdater.h @@ -69,7 +69,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater private: /// List of all the force computes std::vector> m_forces; - std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on + std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on std::vector m_update_order; Scalar m_inv_T; }; diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc index ec6c9e990e..4233d3dd92 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc @@ -361,8 +361,8 @@ Scalar TriangleAreaConservationMeshForceCompute::energyDiff(unsigned int idx_a, c_cbbd = -1.0; Scalar s_cbbd = sqrt(1.0 - c_cbbd * c_cbbd); - if( s_caad == 0 || s_cbbd == 0) - return DBL_MAX; + if (s_caad == 0 || s_cbbd == 0) + return DBL_MAX; Scalar c_accb = nac.x * nbc.x + nac.y * nbc.y + nac.z * nbc.z; if (c_accb > 1.0) diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index e343335540..7e9eb1d5d7 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -384,7 +384,7 @@ Scalar VolumeConservationMeshForceCompute::energyDiff(unsigned int idx_a, Scalar volume_old = dot(cross(pos_c, pos_b), pos_a) + dot(cross(pos_d, pos_a), pos_b); Scalar volume_new = dot(cross(pos_a, pos_c), pos_d) + dot(cross(pos_b, pos_d), pos_c); - m_volume_diff = (volume_new-volume_old)/6.0; + m_volume_diff = (volume_new - volume_old) / 6.0; Scalar energy_old = h_volume.data[type_id] - h_params.data[type_id].V0; Scalar energy_new = energy_old + m_volume_diff; diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index e12f0a4528..539a460bb8 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -93,18 +93,16 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public ForceCompute unsigned int idx_c, unsigned int idx_d, unsigned int type_id) - { - ArrayHandle h_volume(m_volume, access_location::host, access_mode::readwrite); - h_volume.data[type_id] += m_volume_diff; - }; + { + ArrayHandle h_volume(m_volume, access_location::host, access_mode::readwrite); + h_volume.data[type_id] += m_volume_diff; + }; virtual Scalar energyDiff(unsigned int idx_a, unsigned int idx_b, unsigned int idx_c, unsigned int idx_d, unsigned int type_id); - - }; namespace detail diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 99170c0397..fc1a38a6c3 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -5,15 +5,16 @@ import pytest import numpy as np + def test_before_attaching(): mesh = hoomd.mesh.Mesh() mesh_potential1 = hoomd.md.mesh.bond.Harmonic(mesh) - mesh_potential1.params.default = dict(k=100,r0=1) + mesh_potential1.params.default = dict(k=100, r0=1) mesh_potential2 = hoomd.md.mesh.conservation.TriangleArea(mesh) - mesh_potential2.params.default = dict(k=100,A0=1) + mesh_potential2.params.default = dict(k=100, A0=1) - mdb = hoomd.md.update.MeshDynamicalBonding(10,mesh, 1, forces=[mesh_potential1]) + mdb = hoomd.md.update.MeshDynamicalBonding(10, mesh, 1, forces=[mesh_potential1]) assert mdb.trigger == hoomd.trigger.Periodic(10) assert mdb.kT == 1 @@ -34,7 +35,8 @@ def test_before_attaching(): assert mdb.trigger == hoomd.trigger.Periodic(100) assert mdb.kT == 0.5 - assert mdb.forces == [mesh_potential1,mesh_potential2] + assert mdb.forces == [mesh_potential1, mesh_potential2] + @pytest.fixture(scope="session") def local_snapshot_factory(device): @@ -43,7 +45,7 @@ def make_snapshot(d=0.0, particle_types=["A"], L=20): N = 64 if s.communicator.rank == 0: Lx = 8 - Ly = 4*np.sqrt(3) + Ly = 4 * np.sqrt(3) box = [Lx, Ly, L, 0, 0, 0] s.configuration.box = box s.particles.N = N @@ -58,8 +60,8 @@ def make_snapshot(d=0.0, particle_types=["A"], L=20): # Combine X and Y coordinates to define vertex positions base_positions = np.column_stack([X.flatten(), Y.flatten(), np.zeros(N)]) - base_positions[12,2] = d - base_positions[13,2] = d + base_positions[12, 2] = d + base_positions[13, 2] = d # move particles slightly in direction of MPI decomposition which # varies by simulation dimension @@ -69,6 +71,7 @@ def make_snapshot(d=0.0, particle_types=["A"], L=20): return make_snapshot + def make_mesh(flip=True): row = 8 N = row**2 @@ -93,14 +96,15 @@ def make_mesh(flip=True): triangles = np.column_stack([v_index, vr_index, e_index]) if flip: - triangles[24] = [12,5,21] - triangles[25] = [13,21,5] + triangles[24] = [12, 5, 21] + triangles[25] = [13, 21, 5] else: - triangles[24] = [5,13,12] - triangles[25] = [21,12,13] + triangles[24] = [5, 13, 12] + triangles[25] = [21, 12, 13] return triangles + def test_after_attaching(local_snapshot_factory, simulation_factory): snap = local_snapshot_factory(d=0, L=20) sim = simulation_factory(snap) @@ -108,12 +112,12 @@ def test_after_attaching(local_snapshot_factory, simulation_factory): mesh = hoomd.mesh.Mesh() mesh_potential1 = hoomd.md.mesh.bond.Harmonic(mesh) - mesh_potential1.params.default = dict(k=100,r0=1) + mesh_potential1.params.default = dict(k=100, r0=1) mesh_potential2 = hoomd.md.mesh.conservation.TriangleArea(mesh) - mesh_potential2.params.default = dict(k=100,A0=1) + mesh_potential2.params.default = dict(k=100, A0=1) - mdb = hoomd.md.update.MeshDynamicalBonding(10,mesh, 1, forces=[mesh_potential1]) + mdb = hoomd.md.update.MeshDynamicalBonding(10, mesh, 1, forces=[mesh_potential1]) sim.operations.updaters.append(mdb) sim.operations.integrator = hoomd.md.Integrator(dt=0.005) @@ -134,7 +138,8 @@ def test_after_attaching(local_snapshot_factory, simulation_factory): assert mdb.trigger == hoomd.trigger.Periodic(100) assert mdb.kT == 0.5 - assert mdb.forces == [mesh_potential1,mesh_potential2] + assert mdb.forces == [mesh_potential1, mesh_potential2] + def test_updating(local_snapshot_factory, simulation_factory): snap = local_snapshot_factory(d=0.0, L=20) @@ -144,10 +149,12 @@ def test_updating(local_snapshot_factory, simulation_factory): mesh = hoomd.mesh.Mesh() mesh.types = ["mesh"] - mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle), triangles=mesh_triangle) + mesh.triangulation = dict( + type_ids=[0] * len(mesh_triangle), triangles=mesh_triangle + ) mesh_potential = hoomd.md.mesh.bond.Harmonic(mesh) - mesh_potential.params.default = dict(k=1,r0=1) + mesh_potential.params.default = dict(k=1, r0=1) integrator = hoomd.md.Integrator(dt=0.01) integrator.forces.append(mesh_potential) @@ -157,7 +164,9 @@ def test_updating(local_snapshot_factory, simulation_factory): assert not np.isclose(mesh_potential.energy, 0) - mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(1),mesh, kT = 0.001, forces=[mesh_potential]) + mdb = hoomd.md.update.MeshDynamicalBonding( + hoomd.trigger.Periodic(1), mesh, kT=0.001, forces=[mesh_potential] + ) sim.operations += mdb @@ -169,31 +178,27 @@ def test_updating(local_snapshot_factory, simulation_factory): assert np.array_equal(mesh.triangles, make_mesh(False)) -_harmonic_arg_list = [ - (hoomd.md.mesh.bond.Harmonic, dict(k=30.0,r0=1.0)) -] + +_harmonic_arg_list = [(hoomd.md.mesh.bond.Harmonic, dict(k=30.0, r0=1.0))] _FENE_arg_list = [ - (hoomd.md.mesh.bond.FENEWCA, dict(k=30.0,r0=2.0,epsilon=1.0,sigma=1.0,delta=0.0)) + ( + hoomd.md.mesh.bond.FENEWCA, + dict(k=30.0, r0=2.0, epsilon=1.0, sigma=1.0, delta=0.0), + ) ] _Tether_arg_list = [ - (hoomd.md.mesh.bond.Tether, dict(k_b=10,l_min=0.5,l_c1=0.9,l_c0=1.1,l_max=2.0)) -] -_BendingRigidity_arg_list = [ - (hoomd.md.mesh.bending.BendingRigidity, dict(k=300.0)) -] -_Helfrich_arg_list = [ - (hoomd.md.mesh.bending.Helfrich, dict(k=100.0)) + (hoomd.md.mesh.bond.Tether, dict(k_b=10, l_min=0.5, l_c1=0.9, l_c0=1.1, l_max=2.0)) ] +_BendingRigidity_arg_list = [(hoomd.md.mesh.bending.BendingRigidity, dict(k=300.0))] +_Helfrich_arg_list = [(hoomd.md.mesh.bending.Helfrich, dict(k=100.0))] _AreaConservation_arg_list = [ - (hoomd.md.mesh.conservation.Area, dict(k=100.0,A0=8*np.sqrt(3))) + (hoomd.md.mesh.conservation.Area, dict(k=100.0, A0=8 * np.sqrt(3))) ] _TriangleAreaConservation_arg_list = [ - ( - hoomd.md.mesh.conservation.TriangleArea, - dict(k=100.0,A0=np.sqrt(3) /4) - ) + (hoomd.md.mesh.conservation.TriangleArea, dict(k=100.0, A0=np.sqrt(3) / 4)) ] + def get_mesh_potential_and_args(): return ( _harmonic_arg_list @@ -205,10 +210,13 @@ def get_mesh_potential_and_args(): + _Helfrich_arg_list ) + @pytest.mark.parametrize( "mesh_potential_cls, potential_kwargs", get_mesh_potential_and_args() ) -def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential_cls, potential_kwargs): +def test_reduce_energy( + local_snapshot_factory, simulation_factory, mesh_potential_cls, potential_kwargs +): snap = local_snapshot_factory(d=0.5, L=20) sim = simulation_factory(snap) @@ -216,7 +224,9 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential mesh = hoomd.mesh.Mesh() mesh.types = ["mesh"] - mesh.triangulation = dict(type_ids=[0] * len(mesh_triangle), triangles=mesh_triangle) + mesh.triangulation = dict( + type_ids=[0] * len(mesh_triangle), triangles=mesh_triangle + ) mesh_potential = mesh_potential_cls(mesh) mesh_potential.params["mesh"] = potential_kwargs @@ -229,7 +239,9 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential energy = mesh_potential.energy - mdb = hoomd.md.update.MeshDynamicalBonding(hoomd.trigger.Periodic(1),mesh, kT = 0.001, forces=[mesh_potential]) + mdb = hoomd.md.update.MeshDynamicalBonding( + hoomd.trigger.Periodic(1), mesh, kT=0.001, forces=[mesh_potential] + ) sim.operations += mdb @@ -237,6 +249,7 @@ def test_reduce_energy(local_snapshot_factory, simulation_factory,mesh_potential assert mesh_potential.energy <= energy + def test_pickling(local_snapshot_factory, simulation_factory): # don't add the rd_updater since operation_pickling_check will deal with # that. @@ -244,7 +257,6 @@ def test_pickling(local_snapshot_factory, simulation_factory): sim = simulation_factory(snap) mesh = hoomd.mesh.Mesh() - mdb = hoomd.md.update.MeshDynamicalBonding(1,mesh, kT = 0.001) + mdb = hoomd.md.update.MeshDynamicalBonding(1, mesh, kT=0.001) hoomd.conftest.operation_pickling_check(mdb, sim) - diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 3d0bd447bb..28bed684ed 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -14,6 +14,7 @@ from hoomd.mesh import Mesh from hoomd.md.mesh.potential import MeshPotential import inspect +import warnings class ZeroMomentum(Updater): @@ -359,27 +360,25 @@ def _setattr_param(self, attr, value): raise ValueError("active_force is not settable after construction.") super()._setattr_param(attr, value) + class MeshDynamicalBonding(Updater): - r"""Dynamical bonding of the applied mesh that allows edge flips according to + r"""Dynamical bonding of the applied mesh that allows edge flips according to a Metropolic Monte Carlo algorithm. Args: trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond flip attempt. - mesh (hoomd.mesh.Mesh): Mesh data structure. - kT (float): Temperature of the simulation :math:`[\mathrm{energy}]`. - - forces (Sequence[hoomd.md.mesh.MeshPotential]): Sequence of mesh - potentials applied to the updater. The default value of ``None`` - initializes an empty list. + forces (Sequence[hoomd.md.mesh.MeshPotential]): Sequence of mesh + potentials applied to the updater. The default value of ``None`` + initializes an empty list. `MeshDynamicalBonding` works directly with `hoomd.mesh.Mesh` to apply edge flips between neighboring triangles in the mesh. At each step, the updater - attempts to flip each edge within the mesh in random order. The probability - of fliping an edge :math:`ij` between the common vertices :math:`i` and - :math:`j` of triangles :math:`ijk` and :math:`jil` to an edge :math:`kl` + attempts to flip each edge within the mesh in random order. The probability + of fliping an edge :math:`ij` between the common vertices :math:`i` and + :math:`j` of triangles :math:`ijk` and :math:`jil` to an edge :math:`kl` between :math:`k` and :math:`l` is: .. math:: @@ -389,13 +388,13 @@ class MeshDynamicalBonding(Updater): \exp(-\beta (U(kl)-U(ij))) & U(kl) > U(ij) \\ 1 & \Delta U(kl) \le U(ij).\\ \end{cases} - + To obtain energies :math:`U(ij)` and :math:`U(kl)` for the corresponding edge - configurations, only the mesh potentials attached to the updater are + configurations, only the mesh potentials attached to the updater are considered. Tip: - Use `hoomd.mesh.Mesh.create_dynamical_bonding_updater` to construct a + Use `hoomd.mesh.Mesh.create_dynamical_bonding_updater` to construct a `MeshDynamicalBonding` instance. {inherited} @@ -418,9 +417,9 @@ def __init__(self, trigger, mesh, kT, forces=[]): validate_mesh = OnlyTypes(Mesh, allow_none=True) param_dict = ParameterDict( - kT=float(kT), - mesh=validate_mesh, - ) + kT=float(kT), + mesh=validate_mesh, + ) param_dict["mesh"] = mesh self._param_dict.update(param_dict) @@ -438,8 +437,11 @@ def _attach_hook(self): self.mesh._attach(self._simulation) self._cpp_obj = _md.MeshDynamicBondUpdater( - self._simulation.state._cpp_sys_def, self.trigger, - self.mesh._cpp_obj, self.kT) + self._simulation.state._cpp_sys_def, + self.trigger, + self.mesh._cpp_obj, + self.kT, + ) self._forces._sync(self._simulation, self._cpp_obj.forces) @@ -451,15 +453,18 @@ def _detach_hook(self): @property def forces(self): + """Returns the applied mesh potentials.""" return self._forces @forces.setter def forces(self, value): - _set_synced_list(self._forces, value) + self._forces.clear() + self._forces.extend(value) + __all__ = [ "ActiveRotationalDiffusion", + "MeshDynamicalBonding", "ReversePerturbationFlow", "ZeroMomentum", - "MeshDynamicalBonding", ] diff --git a/hoomd/mesh.py b/hoomd/mesh.py index f2e50eff84..d96db14859 100644 --- a/hoomd/mesh.py +++ b/hoomd/mesh.py @@ -153,8 +153,8 @@ def size(self): return 0 return len(self.triangulation["triangles"]) - def create_dynamical_bonding_updater(self, trigger, kT, forces = []): - """Create a dynamical bonding updater for this mesh. + def create_dynamical_bonding_updater(self, trigger, kT, forces=[]): + r"""Create a dynamical bonding updater for this mesh. Args: trigger (hoomd.trigger.trigger_like): Select the timesteps to triger bond @@ -162,17 +162,15 @@ def create_dynamical_bonding_updater(self, trigger, kT, forces = []): kT (float): Temperature of the simulation :math:`[\mathrm{energy}]`. - forces (Sequence[hoomd.md.mesh.MeshPotential]): Sequence of mesh - potentials applied to the updater. The default value of ``None`` - initializes an empty list. + forces (Sequence[hoomd.md.mesh.MeshPotential]): Sequence of mesh + potentials applied to the updater. The default value of ``None`` + initializes an empty list. Returns: hoomd.md.update.MeshDynamicalBonding: The dynamical bonding updater. """ - return hoomd.md.update.MeshDynamicalBonding( - trigger, self, kT, forces - ) + return hoomd.md.update.MeshDynamicalBonding(trigger, self, kT, forces) __all__ = ["Mesh"] diff --git a/hoomd/operation.py b/hoomd/operation.py index b9d1863b93..3b9d38c9fc 100644 --- a/hoomd/operation.py +++ b/hoomd/operation.py @@ -550,6 +550,7 @@ class see its documentation. def __init__(self): self._two_attach = False + class TriggeredOperation(Operation): """Operations that execute on timesteps determined by a trigger. From 59970977f55ab8562fa22b6a0c2c2ad4632025ac Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 16:18:11 -0400 Subject: [PATCH 44/58] fix for loop --- hoomd/md/MeshDynamicBondUpdater.cc | 527 ++++++++++++++--------------- 1 file changed, 261 insertions(+), 266 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 0ad4b3217e..821eaab9c5 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -56,350 +56,345 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) for (auto& force : m_forces) force->precomputeParameter(); - { - const Index2D& table_indexer = m_mesh->getMeshBondData()->getGPUTableIndexer(); + const Index2D& table_indexer = m_mesh->getMeshBondData()->getGPUTableIndexer(); + + ArrayHandle h_meshbondlist( + m_mesh->getMeshBondData()->getGPUTable(), + access_location::host, + access_mode::read); - ArrayHandle h_meshbondlist( - m_mesh->getMeshBondData()->getGPUTable(), - access_location::host, - access_mode::read); + ArrayHandle h_n_meshbond(m_mesh->getMeshBondData()->getNGroupsArray(), + access_location::host, + access_mode::read); - ArrayHandle h_n_meshbond(m_mesh->getMeshBondData()->getNGroupsArray(), - access_location::host, - access_mode::read); + ArrayHandle h_meshbond_pos_list(m_mesh->getMeshBondData()->getGPUPosTable(), + access_location::host, + access_mode::read); - ArrayHandle h_meshbond_pos_list(m_mesh->getMeshBondData()->getGPUPosTable(), + ArrayHandle h_bonds(m_mesh->getMeshBondData()->getMembersArray(), access_location::host, - access_mode::read); - - ArrayHandle h_bonds( - m_mesh->getMeshBondData()->getMembersArray(), - access_location::host, - access_mode::readwrite); + access_mode::readwrite); - ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_neigh_bonds(m_mesh->getNeighToBond(), + access_location::host, + access_mode::readwrite); - ArrayHandle h_triangles( - m_mesh->getMeshTriangleData()->getMembersArray(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_triangles( + m_mesh->getMeshTriangleData()->getMembersArray(), + access_location::host, + access_mode::readwrite); - ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag(), - access_location::host, - access_mode::readwrite); + ArrayHandle h_neigh_triags(m_mesh->getNeighToTriag(), + access_location::host, + access_mode::readwrite); - ArrayHandle h_rtag(m_pdata->getRTags(), - access_location::host, - access_mode::read); + ArrayHandle h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read); - ArrayHandle h_typeval(m_mesh->getMeshBondData()->getTypeValArray(), - access_location::host, - access_mode::read); + ArrayHandle h_typeval(m_mesh->getMeshBondData()->getTypeValArray(), + access_location::host, + access_mode::read); - // for each of the angles - const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); + // for each of the angles + const unsigned int size = (unsigned int)m_mesh->getMeshBondData()->getN(); - hoomd::RandomGenerator rng( - hoomd::Seed(hoomd::RNGIdentifier::MeshDynamicBondUpdateOrder, timestep, seed), - hoomd::Counter(m_exec_conf->getRank())); + hoomd::RandomGenerator rng( + hoomd::Seed(hoomd::RNGIdentifier::MeshDynamicBondUpdateOrder, timestep, seed), + hoomd::Counter(m_exec_conf->getRank())); - // maybe too slow - for (unsigned int i = 0; i < size; i++) - m_update_order[i] = i; + // maybe too slow + for (unsigned int i = 0; i < size; i++) + m_update_order[i] = i; - for (unsigned int i = size - 1; i > 0; i--) - { - unsigned int j = hoomd::UniformIntDistribution(i)(rng); - std::swap(m_update_order[i], m_update_order[j]); - } + for (unsigned int i = size - 1; i > 0; i--) + { + unsigned int j = hoomd::UniformIntDistribution(i)(rng); + std::swap(m_update_order[i], m_update_order[j]); + } - std::vector changed; + std::vector changed; - for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) - { - unsigned int i = m_update_order[cur_bond]; - typename MeshBond::members_t& bond = h_bonds.data[i]; - assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); - assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); + for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) + { + unsigned int i = m_update_order[cur_bond]; + typename MeshBond::members_t& bond = h_bonds.data[i]; + assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); + assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); - unsigned int tag_c = bond.tag[2]; - unsigned int tag_d = bond.tag[3]; + unsigned int tag_c = bond.tag[2]; + unsigned int tag_d = bond.tag[3]; - if (tag_c == tag_d) - continue; + if (tag_c == tag_d) + continue; - bool already_changed = false; - for (unsigned int ii = 0; ii < changed.size(); ii++) + bool already_changed = false; + for (unsigned int ii = 0; ii < changed.size(); ii++) + { + if ((changed[ii].x == tag_c && changed[ii].y == tag_d) + || (changed[ii].x == tag_d && changed[ii].y == tag_c)) { - if ((changed[ii].x == tag_c && changed[ii].y == tag_d) - || (changed[ii].x == tag_d && changed[ii].y == tag_c)) - { - already_changed = true; - break; - } + already_changed = true; + break; } - if (already_changed) - continue; - - unsigned int idx_c = h_rtag.data[tag_c]; - unsigned int idx_d = h_rtag.data[tag_d]; + } + if (already_changed) + continue; - { - ArrayHandle h_pos(m_pdata->getPositions(), - access_location::host, - access_mode::read); - Scalar3 boxL = m_pdata->getGlobalBox().getL() / 4; - - Scalar3 dcd; - dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; - if (dcd.x > boxL.x || dcd.x < -boxL.x) - continue; - dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; - if (dcd.y > boxL.y || dcd.y < -boxL.y) - continue; - dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; - if (dcd.y > boxL.y || dcd.y < -boxL.y) - continue; - } + unsigned int idx_c = h_rtag.data[tag_c]; + unsigned int idx_d = h_rtag.data[tag_d]; - unsigned int tag_a = bond.tag[0]; - unsigned int tag_b = bond.tag[1]; + { + ArrayHandle h_pos(m_pdata->getPositions(), + access_location::host, + access_mode::read); + Scalar3 boxL = m_pdata->getGlobalBox().getL() / 4; + + Scalar3 dcd; + dcd.x = h_pos.data[idx_c].x - h_pos.data[idx_d].x; + if (dcd.x > boxL.x || dcd.x < -boxL.x) + continue; + dcd.y = h_pos.data[idx_c].y - h_pos.data[idx_d].y; + if (dcd.y > boxL.y || dcd.y < -boxL.y) + continue; + dcd.z = h_pos.data[idx_c].z - h_pos.data[idx_d].z; + if (dcd.y > boxL.y || dcd.y < -boxL.y) + continue; + } - unsigned int idx_a = h_rtag.data[tag_a]; - unsigned int idx_b = h_rtag.data[tag_b]; + unsigned int tag_a = bond.tag[0]; + unsigned int tag_b = bond.tag[1]; - unsigned int test_idx = idx_c; + unsigned int idx_a = h_rtag.data[tag_a]; + unsigned int idx_b = h_rtag.data[tag_b]; - for (unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) - { - if (h_meshbond_pos_list.data[table_indexer(idx_c, ii)] > 1) - continue; - test_idx = h_meshbondlist.data[table_indexer(idx_c, ii)].idx[0]; - if (test_idx == idx_d) - break; - } + unsigned int test_idx = idx_c; - if (test_idx == idx_d) + for (unsigned int ii = 0; ii < h_n_meshbond.data[idx_c]; ii++) + { + if (h_meshbond_pos_list.data[table_indexer(idx_c, ii)] > 1) continue; + test_idx = h_meshbondlist.data[table_indexer(idx_c, ii)].idx[0]; + if (test_idx == idx_d) + break; + } - unsigned int tr_idx1 = h_neigh_bonds.data[i].x; - unsigned int tr_idx2 = h_neigh_bonds.data[i].y; + if (test_idx == idx_d) + continue; - typename Angle::members_t& triangleT = h_triangles.data[tr_idx1]; + unsigned int tr_idx1 = h_neigh_bonds.data[i].x; + unsigned int tr_idx2 = h_neigh_bonds.data[i].y; - for (unsigned int j = 0; j < 3; j++) + typename Angle::members_t& triangleT = h_triangles.data[tr_idx1]; + + for (unsigned int j = 0; j < 3; j++) + { + if (triangleT.tag[j] == tag_d) { - if (triangleT.tag[j] == tag_d) - { - tr_idx1 = h_neigh_bonds.data[i].y; - tr_idx2 = h_neigh_bonds.data[i].x; - break; - } + tr_idx1 = h_neigh_bonds.data[i].y; + tr_idx2 = h_neigh_bonds.data[i].x; + break; } + } + + typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; - typename Angle::members_t& triangle1 = h_triangles.data[tr_idx1]; + unsigned int iterator = 0; - unsigned int iterator = 0; + bool a_before_b = false; - bool a_before_b = false; + while (tag_a != triangle1.tag[iterator]) + iterator++; - while (tag_a != triangle1.tag[iterator]) - iterator++; + iterator = (iterator + 1) % 3; + if (tag_b == triangle1.tag[iterator]) + { + a_before_b = true; iterator = (iterator + 1) % 3; + } - if (tag_b == triangle1.tag[iterator]) - { - a_before_b = true; - iterator = (iterator + 1) % 3; - } + unsigned int type_id = h_typeval.data[i].type; - unsigned int type_id = h_typeval.data[i].type; + Scalar energyDifference = 0; - Scalar energyDifference = 0; + unsigned int idx_cc = idx_d; + unsigned int idx_dd = idx_c; - unsigned int idx_cc = idx_d; - unsigned int idx_dd = idx_c; + if (a_before_b) + { + idx_cc = idx_c; + idx_dd = idx_d; + } - if (a_before_b) - { - idx_cc = idx_c; - idx_dd = idx_d; - } + bool have_to_check_surrounding = false; + for (auto& force : m_forces) + { + energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); + if (force->checkSurrounding()) + have_to_check_surrounding = true; + } - bool have_to_check_surrounding = false; - for (auto& force : m_forces) - { - energyDifference += force->energyDiff(idx_a, idx_b, idx_cc, idx_dd, type_id); - if (force->checkSurrounding()) - have_to_check_surrounding = true; - } + // Initialize the RNG + RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), + hoomd::Counter(i)); + + // compute the random force + UniformDistribution uniform(0, Scalar(1)); - // Initialize the RNG - RandomGenerator rng(hoomd::Seed(RNGIdentifier::MeshDynamicBondUpdater, timestep, seed), - hoomd::Counter(i)); + Scalar rand_number = uniform(rng); + Scalar part_func = exp(-m_inv_T * energyDifference); - // compute the random force - UniformDistribution uniform(0, Scalar(1)); + std::vector tr_idx(6); + std::vector b_idx(4); + std::vector v_idx(8); - Scalar rand_number = uniform(rng); - Scalar part_func = exp(-m_inv_T * energyDifference); + if (have_to_check_surrounding || part_func > rand_number) + { + tr_idx[1] = tr_idx1; + tr_idx[0] = tr_idx2; - std::vector tr_idx(6); - std::vector b_idx(4); - std::vector v_idx(8); + v_idx[0] = tag_a; + v_idx[1] = tag_b; + v_idx[2] = tag_d; + v_idx[3] = tag_c; - if (have_to_check_surrounding || part_func > rand_number) + if (a_before_b) { - tr_idx[1] = tr_idx1; - tr_idx[0] = tr_idx2; + tr_idx[0] = tr_idx1; + tr_idx[1] = tr_idx2; + v_idx[2] = tag_c; + v_idx[3] = tag_d; + } - v_idx[0] = tag_a; - v_idx[1] = tag_b; - v_idx[2] = tag_d; - v_idx[3] = tag_c; + unsigned int counter = 4; - if (a_before_b) + for (unsigned int j = 0; j < 2; ++j) + { + unsigned int bic = h_neigh_triags.data[tr_idx[j]].x; + unsigned int bic2 = h_neigh_triags.data[tr_idx[j]].y; + if (bic == i) { - tr_idx[0] = tr_idx1; - tr_idx[1] = tr_idx2; - v_idx[2] = tag_c; - v_idx[3] = tag_d; + bic = bic2; + bic2 = h_neigh_triags.data[tr_idx[j]].z; } - - unsigned int counter = 4; - - for (unsigned int j = 0; j < 2; ++j) + else { - unsigned int bic = h_neigh_triags.data[tr_idx[j]].x; - unsigned int bic2 = h_neigh_triags.data[tr_idx[j]].y; - if (bic == i) - { - bic = bic2; + if (bic2 == i) bic2 = h_neigh_triags.data[tr_idx[j]].z; - } - else - { - if (bic2 == i) - bic2 = h_neigh_triags.data[tr_idx[j]].z; - } - if (h_bonds.data[bic].tag[0] == tag_a || h_bonds.data[bic].tag[1] == tag_a) - { - b_idx[2 * j] = bic; - b_idx[2 * j + 1] = bic2; - } - else - { - b_idx[2 * j + 1] = bic; - b_idx[2 * j] = bic2; - } - for (unsigned int k = 0; k < 2; ++k) + } + if (h_bonds.data[bic].tag[0] == tag_a || h_bonds.data[bic].tag[1] == tag_a) + { + b_idx[2 * j] = bic; + b_idx[2 * j + 1] = bic2; + } + else + { + b_idx[2 * j + 1] = bic; + b_idx[2 * j] = bic2; + } + for (unsigned int k = 0; k < 2; ++k) + { + unsigned int tic = h_neigh_bonds.data[b_idx[2 * j + k]].x; + if (tic == tr_idx[j]) + tic = h_neigh_bonds.data[b_idx[2 * j + k]].y; + unsigned int zaehler = 1; + unsigned int nv_idx = h_triangles.data[tic].tag[0]; + while (nv_idx == v_idx[k] || nv_idx == v_idx[2 + j]) { - unsigned int tic = h_neigh_bonds.data[b_idx[2 * j + k]].x; - if (tic == tr_idx[j]) - tic = h_neigh_bonds.data[b_idx[2 * j + k]].y; - unsigned int zaehler = 1; - unsigned int nv_idx = h_triangles.data[tic].tag[0]; - while (nv_idx == v_idx[k] || nv_idx == v_idx[2 + j]) - { - nv_idx = h_triangles.data[tic].tag[zaehler]; - zaehler++; - } - v_idx[counter] = nv_idx; - tr_idx[counter - 2] = tic; - counter++; + nv_idx = h_triangles.data[tic].tag[zaehler]; + zaehler++; } + v_idx[counter] = nv_idx; + tr_idx[counter - 2] = tic; + counter++; } + } - uint2 bb; - bb.x = v_idx[2]; - bb.y = v_idx[3]; - changed.push_back(bb); + uint2 bb; + bb.x = v_idx[2]; + bb.y = v_idx[3]; + changed.push_back(bb); - if (have_to_check_surrounding) - { - for (auto& force : m_forces) - energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]], - h_rtag.data[v_idx[1]], - h_rtag.data[v_idx[2]], - h_rtag.data[v_idx[3]], - h_rtag.data[v_idx[4]], - h_rtag.data[v_idx[5]], - h_rtag.data[v_idx[6]], - h_rtag.data[v_idx[7]], - type_id); - part_func = exp(-m_inv_T * energyDifference); - } + if (have_to_check_surrounding) + { + for (auto& force : m_forces) + energyDifference += force->energyDiffSurrounding(h_rtag.data[v_idx[0]], + h_rtag.data[v_idx[1]], + h_rtag.data[v_idx[2]], + h_rtag.data[v_idx[3]], + h_rtag.data[v_idx[4]], + h_rtag.data[v_idx[5]], + h_rtag.data[v_idx[6]], + h_rtag.data[v_idx[7]], + type_id); + part_func = exp(-m_inv_T * energyDifference); } + } - if (part_func > rand_number) + if (part_func > rand_number) + { + // Flip bond + if (v_idx[2] > v_idx[3]) { - // Flip bond - if (v_idx[2] > v_idx[3]) - { - h_bonds.data[i].tag[1] = v_idx[2]; - h_bonds.data[i].tag[0] = v_idx[3]; - } - else - { - h_bonds.data[i].tag[0] = v_idx[2]; - h_bonds.data[i].tag[1] = v_idx[3]; - } - h_bonds.data[i].tag[2] = v_idx[0]; - h_bonds.data[i].tag[3] = v_idx[1]; + h_bonds.data[i].tag[1] = v_idx[2]; + h_bonds.data[i].tag[0] = v_idx[3]; + } + else + { + h_bonds.data[i].tag[0] = v_idx[2]; + h_bonds.data[i].tag[1] = v_idx[3]; + } + h_bonds.data[i].tag[2] = v_idx[0]; + h_bonds.data[i].tag[3] = v_idx[1]; - // Update triagles asociated with the bond - h_triangles.data[tr_idx[0]].tag[0] = v_idx[0]; - h_triangles.data[tr_idx[0]].tag[1] = v_idx[3]; - h_triangles.data[tr_idx[0]].tag[2] = v_idx[2]; + // Update triagles asociated with the bond + h_triangles.data[tr_idx[0]].tag[0] = v_idx[0]; + h_triangles.data[tr_idx[0]].tag[1] = v_idx[3]; + h_triangles.data[tr_idx[0]].tag[2] = v_idx[2]; - h_triangles.data[tr_idx[1]].tag[0] = v_idx[1]; - h_triangles.data[tr_idx[1]].tag[1] = v_idx[2]; - h_triangles.data[tr_idx[1]].tag[2] = v_idx[3]; + h_triangles.data[tr_idx[1]].tag[0] = v_idx[1]; + h_triangles.data[tr_idx[1]].tag[1] = v_idx[2]; + h_triangles.data[tr_idx[1]].tag[2] = v_idx[3]; - h_bonds.data[b_idx[0]].tag[2] = v_idx[3]; - h_bonds.data[b_idx[0]].tag[3] = v_idx[4]; + h_bonds.data[b_idx[0]].tag[2] = v_idx[3]; + h_bonds.data[b_idx[0]].tag[3] = v_idx[4]; - h_bonds.data[b_idx[1]].tag[2] = v_idx[3]; - h_bonds.data[b_idx[1]].tag[3] = v_idx[5]; + h_bonds.data[b_idx[1]].tag[2] = v_idx[3]; + h_bonds.data[b_idx[1]].tag[3] = v_idx[5]; - h_bonds.data[b_idx[2]].tag[2] = v_idx[2]; - h_bonds.data[b_idx[2]].tag[3] = v_idx[6]; + h_bonds.data[b_idx[2]].tag[2] = v_idx[2]; + h_bonds.data[b_idx[2]].tag[3] = v_idx[6]; - h_bonds.data[b_idx[3]].tag[2] = v_idx[2]; - h_bonds.data[b_idx[3]].tag[3] = v_idx[7]; + h_bonds.data[b_idx[3]].tag[2] = v_idx[2]; + h_bonds.data[b_idx[3]].tag[3] = v_idx[7]; - // Update triangle neighbors list for the surrounding bonds - h_neigh_bonds.data[b_idx[0]].x = tr_idx[0]; - h_neigh_bonds.data[b_idx[0]].y = tr_idx[2]; + // Update triangle neighbors list for the surrounding bonds + h_neigh_bonds.data[b_idx[0]].x = tr_idx[0]; + h_neigh_bonds.data[b_idx[0]].y = tr_idx[2]; - h_neigh_bonds.data[b_idx[2]].x = tr_idx[0]; - h_neigh_bonds.data[b_idx[2]].y = tr_idx[4]; + h_neigh_bonds.data[b_idx[2]].x = tr_idx[0]; + h_neigh_bonds.data[b_idx[2]].y = tr_idx[4]; - h_neigh_bonds.data[b_idx[1]].x = tr_idx[1]; - h_neigh_bonds.data[b_idx[1]].y = tr_idx[3]; + h_neigh_bonds.data[b_idx[1]].x = tr_idx[1]; + h_neigh_bonds.data[b_idx[1]].y = tr_idx[3]; - h_neigh_bonds.data[b_idx[3]].x = tr_idx[1]; - h_neigh_bonds.data[b_idx[3]].y = tr_idx[5]; + h_neigh_bonds.data[b_idx[3]].x = tr_idx[1]; + h_neigh_bonds.data[b_idx[3]].y = tr_idx[5]; - // Update bond neighbors list for the two triangles - h_neigh_triags.data[tr_idx[0]].x = i; - h_neigh_triags.data[tr_idx[0]].y = b_idx[0]; - h_neigh_triags.data[tr_idx[0]].z = b_idx[2]; + // Update bond neighbors list for the two triangles + h_neigh_triags.data[tr_idx[0]].x = i; + h_neigh_triags.data[tr_idx[0]].y = b_idx[0]; + h_neigh_triags.data[tr_idx[0]].z = b_idx[2]; - h_neigh_triags.data[tr_idx[1]].x = i; - h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; - h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; + h_neigh_triags.data[tr_idx[1]].x = i; + h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; + h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; - for (auto& force : m_forces) - { - force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); - } - m_mesh->getMeshBondData()->groupReorder(); - m_mesh->getMeshTriangleData()->groupReorder(); + for (auto& force : m_forces) + { + force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); } + m_mesh->getMeshBondData()->groupReorder(); + m_mesh->getMeshTriangleData()->groupReorder(); } } } From 8e80bf59f3f46a9a09612bc7cf47cfd4092d1fcc Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 3 Jul 2025 16:35:00 -0400 Subject: [PATCH 45/58] turn off mesh updater pytests for mpi --- hoomd/md/pytest/test_meshupdater.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index fc1a38a6c3..968bb0980e 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -145,6 +145,9 @@ def test_updating(local_snapshot_factory, simulation_factory): snap = local_snapshot_factory(d=0.0, L=20) sim = simulation_factory(snap) + if sim.device.communicator.num_ranks > 1: + pytest.skip("Cannot run MeshDynamicalBonding with MPI") + mesh_triangle = make_mesh() mesh = hoomd.mesh.Mesh() @@ -220,6 +223,9 @@ def test_reduce_energy( snap = local_snapshot_factory(d=0.5, L=20) sim = simulation_factory(snap) + if sim.device.communicator.num_ranks > 1: + pytest.skip("Cannot run MeshDynamicalBonding with MPI") + mesh_triangle = make_mesh() mesh = hoomd.mesh.Mesh() From 522aa76701ca23aa99911165e154ba3b1bb25998 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 7 Jul 2025 14:07:34 -0400 Subject: [PATCH 46/58] no MPI for mesh updater --- hoomd/md/pytest/test_meshupdater.py | 30 +++++++++++--------- hoomd/md/update.py | 43 +++++++++++++++++------------ 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 968bb0980e..9753453895 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -122,23 +122,27 @@ def test_after_attaching(local_snapshot_factory, simulation_factory): sim.operations.integrator = hoomd.md.Integrator(dt=0.005) - sim.run(0) + if sim.device.communicator.num_ranks > 1: + with pytest.raises(NotImplementedError): + sim.run(0) + else: + sim.run(0) - assert mdb.trigger == hoomd.trigger.Periodic(10) - assert mdb.kT == 1 - assert mdb.mesh == mesh - assert mdb.forces == [mesh_potential1] + assert mdb.trigger == hoomd.trigger.Periodic(10) + assert mdb.kT == 1 + assert mdb.mesh == mesh + assert mdb.forces == [mesh_potential1] - mdb.trigger = hoomd.trigger.Periodic(100) - mdb.kT = 0.5 - mdb.forces.append(mesh_potential2) + mdb.trigger = hoomd.trigger.Periodic(100) + mdb.kT = 0.5 + mdb.forces.append(mesh_potential2) - with pytest.raises(hoomd.error.MutabilityError): - mdb.mesh = hoomd.mesh.Mesh() + with pytest.raises(hoomd.error.MutabilityError): + mdb.mesh = hoomd.mesh.Mesh() - assert mdb.trigger == hoomd.trigger.Periodic(100) - assert mdb.kT == 0.5 - assert mdb.forces == [mesh_potential1, mesh_potential2] + assert mdb.trigger == hoomd.trigger.Periodic(100) + assert mdb.kT == 0.5 + assert mdb.forces == [mesh_potential1, mesh_potential2] def test_updating(local_snapshot_factory, simulation_factory): diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 28bed684ed..3dbc4fa075 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -5,7 +5,7 @@ from hoomd.md import _md import hoomd -from hoomd.error import SimulationDefinitionError +from hoomd.error import SimulationDefinitionError, MPINotAvailableError from hoomd.operation import Updater from hoomd.data import syncedlist from hoomd.data.parameterdicts import ParameterDict @@ -397,6 +397,10 @@ class MeshDynamicalBonding(Updater): Use `hoomd.mesh.Mesh.create_dynamical_bonding_updater` to construct a `MeshDynamicalBonding` instance. + Attention: + `MeshDynamicalBonding` is NOT implemented for MPI parallel execution! + + {inherited} Examples:: @@ -427,25 +431,30 @@ def __init__(self, trigger, mesh, kT, forces=[]): def _attach_hook(self): # create the c++ mirror class - if self.mesh._attached and self._simulation != self.mesh._simulation: - warnings.warn( - f"{self} object is creating a new equivalent mesh structure." - f" This is happending since the force is moving to a new " - f"simulation. To suppress the warning explicitly set new mesh.", - RuntimeWarning, + if self._simulation.device.communicator.num_ranks == 1: + if self.mesh._attached and self._simulation != self.mesh._simulation: + warnings.warn( + f"{self} object is creating a new equivalent mesh structure." + f" This is happending since the force is moving to a new " + f"simulation. To suppress the warning explicitly set new mesh.", + RuntimeWarning, + ) + self.mesh._attach(self._simulation) + + self._cpp_obj = _md.MeshDynamicBondUpdater( + self._simulation.state._cpp_sys_def, + self.trigger, + self.mesh._cpp_obj, + self.kT, ) - self.mesh._attach(self._simulation) - - self._cpp_obj = _md.MeshDynamicBondUpdater( - self._simulation.state._cpp_sys_def, - self.trigger, - self.mesh._cpp_obj, - self.kT, - ) - self._forces._sync(self._simulation, self._cpp_obj.forces) + self._forces._sync(self._simulation, self._cpp_obj.forces) - super()._attach_hook() + super()._attach_hook() + else: + raise MPINotAvailableError( + "MeshDynamicalBonding is not implemented for MPI" + ) def _detach_hook(self): self._forces._unsync() From 6c5c8257571bf83415dc1129512948fa59d44f0d Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 7 Jul 2025 15:03:07 -0400 Subject: [PATCH 47/58] improve already changed --- hoomd/md/MeshDynamicBondUpdater.cc | 31 +++++++++++------------------- hoomd/md/MeshDynamicBondUpdater.h | 1 + 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index 821eaab9c5..ed9954e480 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -38,6 +38,8 @@ MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr m_update_order.resize(m_mesh->getMeshBondData()->getN()); + m_already_updated.resize(m_mesh->getMeshBondData()->getN()); + m_exec_conf->msg->notice(5) << "Constructing MeshDynamicBondUpdater" << endl; } @@ -103,7 +105,10 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) // maybe too slow for (unsigned int i = 0; i < size; i++) + { m_update_order[i] = i; + m_already_updated[i] = false; + } for (unsigned int i = size - 1; i > 0; i--) { @@ -111,11 +116,12 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) std::swap(m_update_order[i], m_update_order[j]); } - std::vector changed; - for (unsigned int cur_bond = 0; cur_bond < size; cur_bond++) { unsigned int i = m_update_order[cur_bond]; + if (m_already_updated[i]) + continue; + typename MeshBond::members_t& bond = h_bonds.data[i]; assert(bond.tag[0] < m_pdata->getMaximumTag() + 1); assert(bond.tag[1] < m_pdata->getMaximumTag() + 1); @@ -126,19 +132,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) if (tag_c == tag_d) continue; - bool already_changed = false; - for (unsigned int ii = 0; ii < changed.size(); ii++) - { - if ((changed[ii].x == tag_c && changed[ii].y == tag_d) - || (changed[ii].x == tag_d && changed[ii].y == tag_c)) - { - already_changed = true; - break; - } - } - if (already_changed) - continue; - unsigned int idx_c = h_rtag.data[tag_c]; unsigned int idx_d = h_rtag.data[tag_d]; @@ -309,11 +302,6 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) } } - uint2 bb; - bb.x = v_idx[2]; - bb.y = v_idx[3]; - changed.push_back(bb); - if (have_to_check_surrounding) { for (auto& force : m_forces) @@ -389,6 +377,9 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) h_neigh_triags.data[tr_idx[1]].y = b_idx[1]; h_neigh_triags.data[tr_idx[1]].z = b_idx[3]; + for (unsigned int j = 0; j < 4; j++) + m_already_updated[b_idx[j]] = true; + for (auto& force : m_forces) { force->postcomputeParameter(idx_a, idx_b, idx_cc, idx_dd, type_id); diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index 4aa535b961..e861e04760 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -71,6 +71,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater std::vector> m_forces; std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on std::vector m_update_order; + std::vector m_already_updated; Scalar m_inv_T; }; From 9479b0546ca0bddd4bc53971325414741697865b Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 7 Jul 2025 15:05:46 -0400 Subject: [PATCH 48/58] fix pickling test --- hoomd/md/pytest/test_meshupdater.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hoomd/md/pytest/test_meshupdater.py b/hoomd/md/pytest/test_meshupdater.py index 9753453895..b3df95dbbe 100644 --- a/hoomd/md/pytest/test_meshupdater.py +++ b/hoomd/md/pytest/test_meshupdater.py @@ -265,6 +265,10 @@ def test_pickling(local_snapshot_factory, simulation_factory): # that. snap = local_snapshot_factory(d=0, L=20) sim = simulation_factory(snap) + + if sim.device.communicator.num_ranks > 1: + pytest.skip("Cannot run MeshDynamicalBonding with MPI") + mesh = hoomd.mesh.Mesh() mdb = hoomd.md.update.MeshDynamicalBonding(1, mesh, kT=0.001) From e8b2185243c6b1bedbff0e81a9278b4f540f5a07 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Mon, 25 Aug 2025 17:57:11 -0400 Subject: [PATCH 49/58] establish MeshForceCompute class --- hoomd/md/CMakeLists.txt | 2 + hoomd/md/MeshForceCompute.cc | 39 +++++++++++++++++ hoomd/md/MeshForceCompute.h | 82 ++++++++++++++++++++++++++++++++++++ hoomd/md/module-md.cc | 2 + 4 files changed, 125 insertions(+) create mode 100644 hoomd/md/MeshForceCompute.cc create mode 100644 hoomd/md/MeshForceCompute.h diff --git a/hoomd/md/CMakeLists.txt b/hoomd/md/CMakeLists.txt index d1a120e180..c22524bb19 100644 --- a/hoomd/md/CMakeLists.txt +++ b/hoomd/md/CMakeLists.txt @@ -38,6 +38,7 @@ set(_md_sources module-md.cc ManifoldPrimitive.cc ManifoldSphere.cc MeshDynamicBondUpdater.cc + MeshForceCompute.cc MolecularForceCompute.cc MuellerPlatheFlow.cc NeighborListBinned.cc @@ -168,6 +169,7 @@ set(_md_headers ActiveForceComputeGPU.h ManifoldPrimitive.h ManifoldSphere.h MeshDynamicBondUpdater.h + MeshForceCompute.h MolecularForceCompute.cuh MolecularForceCompute.h MuellerPlatheFlowEnum.h diff --git a/hoomd/md/MeshForceCompute.cc b/hoomd/md/MeshForceCompute.cc new file mode 100644 index 0000000000..0c451dfa3e --- /dev/null +++ b/hoomd/md/MeshForceCompute.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2009-2025 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +/*! \file MeshForceCompute.cc + \brief Defines the MeshForceCompute class +*/ + +#include "MeshForceCompute.h" + +#include +using namespace std; + +#include + +#include + +namespace hoomd + { +namespace md + { +/*! \param sysdef System to compute forces on + \param meshdef Mesh triangulation +*/ +MeshForceCompute::MeshForceCompute(std::shared_ptr sysdef, + std::shared_ptr meshdef) + : ForceCompute(sysdef), m_mesh_data(meshdef) + { + } + +namespace detail + { +void export_MeshForceCompute(pybind11::module& m) + { + pybind11::class_>(m, "MeshForceCompute") + .def(pybind11::init, std::shared_ptr>()); + } + } // end namespace detail + } // end namespace md + } // end namespace hoomd diff --git a/hoomd/md/MeshForceCompute.h b/hoomd/md/MeshForceCompute.h new file mode 100644 index 0000000000..bb07d53489 --- /dev/null +++ b/hoomd/md/MeshForceCompute.h @@ -0,0 +1,82 @@ +// Copyright (c) 2009-2025 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +#include "hoomd/ForceCompute.h" +#include "hoomd/MeshDefinition.h" + +#include + +/*! \file MeshForceCompute.h + \brief Declares the ForceCompute class +*/ + +#ifdef __HIPCC__ +#error This header cannot be compiled by nvcc +#endif + +#include + +#ifndef __MESHFORCECOMPUTE_H__ +#define __MESHFORCECOMPUTE_H__ + +namespace hoomd + { +namespace md + { +//! Structure for handeling mesh forces + +class PYBIND11_EXPORT MeshForceCompute : public ForceCompute + { + public: + //! Constructs the compute + MeshForceCompute(std::shared_ptr sysdef, + std::shared_ptr meshdef); + + //! Computes the parameters for meshes + virtual void precomputeParameter() { }; + + virtual Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) + { + return 0; + }; + + virtual Scalar energyDiffSurrounding(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int idx_e, + unsigned int idx_f, + unsigned int idx_g, + unsigned int idx_h, + unsigned int type_id) + { + return 0; + }; + + virtual void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) { }; + + protected: + + std::shared_ptr m_mesh_data; //!< Mesh data to use in computing helfich energy + }; + +namespace detail + { +//! Exports the MeshForceCompute class to python +#ifndef __HIPCC__ +void export_MeshForceCompute(pybind11::module& m); +#endif + + } // end namespace detail + } // end namespace md + } // end namespace hoomd + +#endif // __MESHFORCECOMPUTE_H__ diff --git a/hoomd/md/module-md.cc b/hoomd/md/module-md.cc index e8e2318cd5..eb407847f9 100644 --- a/hoomd/md/module-md.cc +++ b/hoomd/md/module-md.cc @@ -92,6 +92,7 @@ void export_PotentialMeshBondHarmonic(pybind11::module& m); void export_PotentialMeshBondFENE(pybind11::module& m); void export_PotentialMeshBondTether(pybind11::module& m); +void export_MeshForceCompute(pybind11::module& m); void export_BendingRigidityMeshForceCompute(pybind11::module& m); void export_HelfrichMeshForceCompute(pybind11::module& m); void export_VolumeConservationMeshForceCompute(pybind11::module& m); @@ -408,6 +409,7 @@ PYBIND11_MODULE(_md, m) export_PotentialMeshBondFENE(m); export_PotentialMeshBondTether(m); + export_MeshForceCompute(m); export_BendingRigidityMeshForceCompute(m); export_HelfrichMeshForceCompute(m); export_VolumeConservationMeshForceCompute(m); From dfe5361f0c85370da137ebaa4b37c2434d752a77 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 09:41:23 -0400 Subject: [PATCH 50/58] change to MeshForceCompute --- hoomd/md/AreaConservationMeshForceCompute.cc | 4 ++-- hoomd/md/AreaConservationMeshForceCompute.h | 6 ++---- hoomd/md/BendingRigidityMeshForceCompute.cc | 4 ++-- hoomd/md/BendingRigidityMeshForceCompute.h | 8 +++----- hoomd/md/HelfrichMeshForceCompute.cc | 4 ++-- hoomd/md/HelfrichMeshForceCompute.h | 6 ++---- hoomd/md/TriangleAreaConservationMeshForceCompute.cc | 4 ++-- hoomd/md/TriangleAreaConservationMeshForceCompute.h | 8 ++------ hoomd/md/VolumeConservationMeshForceCompute.cc | 4 ++-- hoomd/md/VolumeConservationMeshForceCompute.h | 7 ++----- 10 files changed, 21 insertions(+), 34 deletions(-) diff --git a/hoomd/md/AreaConservationMeshForceCompute.cc b/hoomd/md/AreaConservationMeshForceCompute.cc index ae24bf9220..c5756636fd 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.cc +++ b/hoomd/md/AreaConservationMeshForceCompute.cc @@ -25,7 +25,7 @@ AreaConservationMeshForceCompute::AreaConservationMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef, bool ignore_type) - : ForceCompute(sysdef), m_mesh_data(meshdef), m_ignore_type(ignore_type) + : MeshForceCompute(sysdef,meshdef), m_ignore_type(ignore_type) { m_exec_conf->msg->notice(5) << "Constructing AreaConservationMeshForceCompute" << endl; @@ -491,7 +491,7 @@ namespace detail void export_AreaConservationMeshForceCompute(pybind11::module& m) { pybind11::class_>( m, "AreaConservationMeshForceCompute") diff --git a/hoomd/md/AreaConservationMeshForceCompute.h b/hoomd/md/AreaConservationMeshForceCompute.h index e33ddf4e61..0d4294e1d4 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.h +++ b/hoomd/md/AreaConservationMeshForceCompute.h @@ -2,8 +2,7 @@ // Part of HOOMD-blue, released under the BSD 3-Clause License. #include "AreaConservationMeshParameters.h" -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" +#include "MeshForceCompute.h" #include @@ -29,7 +28,7 @@ namespace md \ingroup computes */ -class PYBIND11_EXPORT AreaConservationMeshForceCompute : public ForceCompute +class PYBIND11_EXPORT AreaConservationMeshForceCompute : public MeshForceCompute { public: //! Constructs the compute @@ -74,7 +73,6 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public ForceCompute GPUArray m_params; //!< Parameters GPUArray m_area; //!< memory space for area Scalar m_area_diff; - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing energy bool m_ignore_type; //! ignore type to calculate global area if true //! Actually compute the forces diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index 24b321639b..eef4f3475f 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -23,7 +23,7 @@ namespace md BendingRigidityMeshForceCompute::BendingRigidityMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef) - : ForceCompute(sysdef), m_mesh_data(meshdef) + : MeshForceCompute(sysdef,meshdef) { m_exec_conf->msg->notice(5) << "Constructing BendingRigidityMeshForceCompute" << endl; @@ -389,7 +389,7 @@ namespace detail void export_BendingRigidityMeshForceCompute(pybind11::module& m) { pybind11::class_>( m, "BendingRigidityMeshForceCompute") diff --git a/hoomd/md/BendingRigidityMeshForceCompute.h b/hoomd/md/BendingRigidityMeshForceCompute.h index a14f148af1..a55f138451 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.h +++ b/hoomd/md/BendingRigidityMeshForceCompute.h @@ -1,8 +1,8 @@ // Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" +#include "MeshForceCompute.h" + #include @@ -51,7 +51,7 @@ struct bending_params \ingroup computes */ -class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public ForceCompute +class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public MeshForceCompute { public: //! Constructs the compute @@ -84,8 +84,6 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public ForceCompute protected: GPUArray m_params; //!< Parameters - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing - // the bending energy //! Actually compute the forces virtual void computeForces(uint64_t timestep); diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 6bf0ea9040..2b07d04766 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -26,7 +26,7 @@ namespace md */ HelfrichMeshForceCompute::HelfrichMeshForceCompute(std::shared_ptr sysdef, std::shared_ptr meshdef) - : ForceCompute(sysdef), m_mesh_data(meshdef) + : MeshForceCompute(sysdef,meshdef) { m_exec_conf->msg->notice(5) << "Constructing HelfrichMeshForceCompute" << endl; @@ -822,7 +822,7 @@ namespace detail void export_HelfrichMeshForceCompute(pybind11::module& m) { pybind11::class_>(m, "HelfrichMeshForceCompute") .def(pybind11::init, std::shared_ptr>()) .def("setParams", &HelfrichMeshForceCompute::setParamsPython) diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index f950ff56de..246c458670 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -1,8 +1,7 @@ // Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" +#include "MeshForceCompute.h" #include @@ -29,7 +28,7 @@ namespace md \ingroup computes */ -class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute +class PYBIND11_EXPORT HelfrichMeshForceCompute : public MeshForceCompute { public: //! Constructs the compute @@ -62,7 +61,6 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public ForceCompute protected: GPUArray m_params; //!< Parameters - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing helfich energy GPUArray m_sigma_dash; //! sum of the distances weighted by the bending angle over all neighbors diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc index 4233d3dd92..e9f411e05d 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc @@ -24,7 +24,7 @@ namespace md TriangleAreaConservationMeshForceCompute::TriangleAreaConservationMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef) - : ForceCompute(sysdef), m_mesh_data(meshdef) + : MeshForceCompute(sysdef,meshdef) { m_exec_conf->msg->notice(5) << "Constructing TriangleAreaConservationhMeshForceCompute" << endl; @@ -394,7 +394,7 @@ namespace detail void export_TriangleAreaConservationMeshForceCompute(pybind11::module& m) { pybind11::class_>( m, "TriangleAreaConservationMeshForceCompute") diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.h b/hoomd/md/TriangleAreaConservationMeshForceCompute.h index 3f698a5194..1ddc0d881c 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.h +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.h @@ -2,8 +2,7 @@ // Part of HOOMD-blue, released under the BSD 3-Clause License. #include "TriangleAreaConservationMeshParameters.h" -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" +#include "MeshForceCompute.h" #include @@ -29,7 +28,7 @@ namespace md /*! Triangle Area Conservation forces are computed on every triangle in a mesh. \ingroup computes */ -class PYBIND11_EXPORT TriangleAreaConservationMeshForceCompute : public ForceCompute +class PYBIND11_EXPORT TriangleAreaConservationMeshForceCompute : public MeshForceCompute { public: //! Constructs the compute @@ -70,9 +69,6 @@ class PYBIND11_EXPORT TriangleAreaConservationMeshForceCompute : public ForceCom GPUArray m_params; //!< Parameters GPUArray m_area; //!< memory space for area - std::shared_ptr - m_mesh_data; //!< Mesh data to use in computing area conservation energy - //! Actually compute the forces virtual void computeForces(uint64_t timestep); diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index 7e9eb1d5d7..97ff63472e 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -25,7 +25,7 @@ VolumeConservationMeshForceCompute::VolumeConservationMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef, bool ignore_type) - : ForceCompute(sysdef), m_mesh_data(meshdef), m_ignore_type(ignore_type) + : MeshForceCompute(sysdef,meshdef), m_ignore_type(ignore_type) { m_exec_conf->msg->notice(5) << "Constructing VolumeConservationMeshForceCompute" << endl; @@ -400,7 +400,7 @@ namespace detail void export_VolumeConservationMeshForceCompute(pybind11::module& m) { pybind11::class_>( m, "VolumeConservationMeshForceCompute") diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index 539a460bb8..3ddba90a55 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -2,8 +2,7 @@ // Part of HOOMD-blue, released under the BSD 3-Clause License. #include "VolumeConservationMeshParameters.h" -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" +#include "MeshForceCompute.h" #include @@ -30,7 +29,7 @@ namespace md \ingroup computes */ -class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public ForceCompute +class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public MeshForceCompute { public: //! Constructs the compute @@ -74,8 +73,6 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public ForceCompute protected: GPUArray m_params; //!< Parameters - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing volume energy - GPUArray m_volume; //!< memory space for volume Scalar m_volume_diff; From bd162208bbc0c07ccec94e3940d7c07aa7096c07 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 10:14:08 -0400 Subject: [PATCH 51/58] change PotentialBond to MeshForceCompute --- hoomd/md/PotentialBond.h | 17 ++++++++--------- hoomd/md/module-md.cc | 6 ++++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index 4938303385..25416f9007 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -1,9 +1,8 @@ // Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. -#include "hoomd/ForceCompute.h" +#include "MeshForceCompute.h" #include "hoomd/GPUArray.h" -#include "hoomd/MeshDefinition.h" #include #include @@ -29,7 +28,7 @@ namespace md \ingroup computes */ -template class PotentialBond : public ForceCompute +template class PotentialBond : public MeshForceCompute { public: //! Param type from evaluator @@ -76,7 +75,7 @@ template class PotentialBond : public ForceCompute template PotentialBond::PotentialBond(std::shared_ptr sysdef) - : ForceCompute(sysdef) + : MeshForceCompute(sysdef,NULL) { m_exec_conf->msg->notice(5) << "Constructing PotentialBond<" << evaluator::getName() << ">" << std::endl; @@ -93,14 +92,14 @@ PotentialBond::PotentialBond(std::shared_ptr template PotentialBond::PotentialBond(std::shared_ptr sysdef, std::shared_ptr meshdef) - : ForceCompute(sysdef) + : MeshForceCompute(sysdef,meshdef) { m_exec_conf->msg->notice(5) << "Constructing PotentialMeshBond<" << evaluator::getName() << ">" << std::endl; assert(m_pdata); // access the bond data for later use - m_bond_data = meshdef->getMeshBondData(); + m_bond_data = m_mesh_data->getMeshBondData(); // allocate the parameters GPUArray params(m_bond_data->getNTypes(), m_exec_conf); @@ -378,7 +377,7 @@ CommFlags PotentialBond::getRequestedCommFlags(uint64_t timest if (evaluator::needsCharge()) flags[comm_flag::charge] = 1; - flags |= ForceCompute::getRequestedCommFlags(timestep); + flags |= MeshForceCompute::getRequestedCommFlags(timestep); return flags; } @@ -393,7 +392,7 @@ namespace detail template void export_PotentialBond(pybind11::module& m, const std::string& name) { pybind11::class_, - ForceCompute, + MeshForceCompute, std::shared_ptr>>(m, name.c_str()) .def(pybind11::init>()) .def("setParams", &PotentialBond::setParamsPython) @@ -407,7 +406,7 @@ template void export_PotentialBond(pybind11::module& m, const std::stri template void export_PotentialMeshBond(pybind11::module& m, const std::string& name) { pybind11::class_, - ForceCompute, + MeshForceCompute, std::shared_ptr>>(m, name.c_str()) .def(pybind11::init, std::shared_ptr>()) .def("setParams", &PotentialBond::setParamsPython) diff --git a/hoomd/md/module-md.cc b/hoomd/md/module-md.cc index eb407847f9..db2f64fe7b 100644 --- a/hoomd/md/module-md.cc +++ b/hoomd/md/module-md.cc @@ -84,6 +84,8 @@ void export_AnisoPotentialPairPatchyMie(pybind11::module& m); void export_AnisoPotentialPairPatchyYukawa(pybind11::module& m); void export_AnisoPotentialPairPatchyTable(pybind11::module& m); +void export_MeshForceCompute(pybind11::module& m); + void export_PotentialBondHarmonic(pybind11::module& m); void export_PotentialBondFENE(pybind11::module& m); void export_PotentialBondTether(pybind11::module& m); @@ -92,7 +94,6 @@ void export_PotentialMeshBondHarmonic(pybind11::module& m); void export_PotentialMeshBondFENE(pybind11::module& m); void export_PotentialMeshBondTether(pybind11::module& m); -void export_MeshForceCompute(pybind11::module& m); void export_BendingRigidityMeshForceCompute(pybind11::module& m); void export_HelfrichMeshForceCompute(pybind11::module& m); void export_VolumeConservationMeshForceCompute(pybind11::module& m); @@ -401,6 +402,8 @@ PYBIND11_MODULE(_md, m) export_PotentialPairDPDThermoDPD(m); export_PotentialPairDPDThermoLJ(m); + export_MeshForceCompute(m); + export_PotentialBondHarmonic(m); export_PotentialBondFENE(m); export_PotentialBondTether(m); @@ -409,7 +412,6 @@ PYBIND11_MODULE(_md, m) export_PotentialMeshBondFENE(m); export_PotentialMeshBondTether(m); - export_MeshForceCompute(m); export_BendingRigidityMeshForceCompute(m); export_HelfrichMeshForceCompute(m); export_VolumeConservationMeshForceCompute(m); From 347b0d2ca48e4a5dc1197a08bffb4450e43fa97f Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 10:42:09 -0400 Subject: [PATCH 52/58] run pre-commit --- hoomd/ForceCompute.h | 31 ------------------- hoomd/md/AreaConservationMeshForceCompute.cc | 2 +- hoomd/md/AreaConservationMeshForceCompute.h | 2 +- hoomd/md/BendingRigidityMeshForceCompute.cc | 2 +- hoomd/md/BendingRigidityMeshForceCompute.h | 3 +- hoomd/md/HelfrichMeshForceCompute.cc | 2 +- hoomd/md/HelfrichMeshForceCompute.h | 2 +- hoomd/md/MeshDynamicBondUpdater.cc | 5 +-- hoomd/md/MeshDynamicBondUpdater.h | 7 ++--- hoomd/md/MeshForceCompute.cc | 4 ++- hoomd/md/MeshForceCompute.h | 1 - hoomd/md/PotentialBond.h | 4 +-- ...riangleAreaConservationMeshForceCompute.cc | 2 +- ...TriangleAreaConservationMeshForceCompute.h | 2 +- .../md/VolumeConservationMeshForceCompute.cc | 2 +- hoomd/md/VolumeConservationMeshForceCompute.h | 2 +- 16 files changed, 21 insertions(+), 52 deletions(-) diff --git a/hoomd/ForceCompute.h b/hoomd/ForceCompute.h index acb805af28..fbf5e5ba1c 100644 --- a/hoomd/ForceCompute.h +++ b/hoomd/ForceCompute.h @@ -75,37 +75,6 @@ class PYBIND11_EXPORT ForceCompute : public Compute //! Computes the forces virtual void compute(uint64_t timestep); - //! Computes the parameters for meshes - virtual void precomputeParameter() { }; - - virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id) - { - return 0; - }; - - virtual Scalar energyDiffSurrounding(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int idx_e, - unsigned int idx_f, - unsigned int idx_g, - unsigned int idx_h, - unsigned int type_id) - { - return 0; - }; - - virtual void postcomputeParameter(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id) { }; - virtual bool checkSurrounding() { return false; diff --git a/hoomd/md/AreaConservationMeshForceCompute.cc b/hoomd/md/AreaConservationMeshForceCompute.cc index c5756636fd..425eb0cd79 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.cc +++ b/hoomd/md/AreaConservationMeshForceCompute.cc @@ -25,7 +25,7 @@ AreaConservationMeshForceCompute::AreaConservationMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef, bool ignore_type) - : MeshForceCompute(sysdef,meshdef), m_ignore_type(ignore_type) + : MeshForceCompute(sysdef, meshdef), m_ignore_type(ignore_type) { m_exec_conf->msg->notice(5) << "Constructing AreaConservationMeshForceCompute" << endl; diff --git a/hoomd/md/AreaConservationMeshForceCompute.h b/hoomd/md/AreaConservationMeshForceCompute.h index 0d4294e1d4..4b1b3b0f91 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.h +++ b/hoomd/md/AreaConservationMeshForceCompute.h @@ -73,7 +73,7 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public MeshForceCompute GPUArray m_params; //!< Parameters GPUArray m_area; //!< memory space for area Scalar m_area_diff; - bool m_ignore_type; //! ignore type to calculate global area if true + bool m_ignore_type; //! ignore type to calculate global area if true //! Actually compute the forces virtual void computeForces(uint64_t timestep); diff --git a/hoomd/md/BendingRigidityMeshForceCompute.cc b/hoomd/md/BendingRigidityMeshForceCompute.cc index eef4f3475f..b5b4c42ecb 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.cc +++ b/hoomd/md/BendingRigidityMeshForceCompute.cc @@ -23,7 +23,7 @@ namespace md BendingRigidityMeshForceCompute::BendingRigidityMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef) - : MeshForceCompute(sysdef,meshdef) + : MeshForceCompute(sysdef, meshdef) { m_exec_conf->msg->notice(5) << "Constructing BendingRigidityMeshForceCompute" << endl; diff --git a/hoomd/md/BendingRigidityMeshForceCompute.h b/hoomd/md/BendingRigidityMeshForceCompute.h index a55f138451..2254823b22 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.h +++ b/hoomd/md/BendingRigidityMeshForceCompute.h @@ -3,7 +3,6 @@ #include "MeshForceCompute.h" - #include /*! \file BendingRigidityMeshForceCompute.h @@ -83,7 +82,7 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public MeshForceCompute #endif protected: - GPUArray m_params; //!< Parameters + GPUArray m_params; //!< Parameters //! Actually compute the forces virtual void computeForces(uint64_t timestep); diff --git a/hoomd/md/HelfrichMeshForceCompute.cc b/hoomd/md/HelfrichMeshForceCompute.cc index 2b07d04766..e9fd1db68f 100644 --- a/hoomd/md/HelfrichMeshForceCompute.cc +++ b/hoomd/md/HelfrichMeshForceCompute.cc @@ -26,7 +26,7 @@ namespace md */ HelfrichMeshForceCompute::HelfrichMeshForceCompute(std::shared_ptr sysdef, std::shared_ptr meshdef) - : MeshForceCompute(sysdef,meshdef) + : MeshForceCompute(sysdef, meshdef) { m_exec_conf->msg->notice(5) << "Constructing HelfrichMeshForceCompute" << endl; diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index 246c458670..36b3b86b67 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -60,7 +60,7 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public MeshForceCompute #endif protected: - GPUArray m_params; //!< Parameters + GPUArray m_params; //!< Parameters GPUArray m_sigma_dash; //! sum of the distances weighted by the bending angle over all neighbors diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index ed9954e480..a2ea0deb60 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -12,7 +12,7 @@ #include #include -PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); using namespace std; @@ -394,7 +394,8 @@ namespace detail { void export_MeshDynamicBondUpdater(pybind11::module& m) { - pybind11::bind_vector>>(m, "ForceComputeList"); + pybind11::bind_vector>>(m, + "MeshForceComputeList"); pybind11::class_>( m, "MeshDynamicBondUpdater") diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index e861e04760..1dadb7df25 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -9,9 +9,8 @@ #error This header cannot be compiled by nvcc #endif -#include "hoomd/ForceCompute.h" +#include "MeshForceCompute.h" #include "hoomd/Integrator.h" -#include "hoomd/MeshDefinition.h" #include "hoomd/Updater.h" #include "hoomd/Variant.h" @@ -51,7 +50,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater virtual void update(uint64_t timestep); /// Get the list of force computes - std::vector>& getForces() + std::vector>& getForces() { return m_forces; } @@ -68,7 +67,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater private: /// List of all the force computes - std::vector> m_forces; + std::vector> m_forces; std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on std::vector m_update_order; std::vector m_already_updated; diff --git a/hoomd/md/MeshForceCompute.cc b/hoomd/md/MeshForceCompute.cc index 0c451dfa3e..120021cc70 100644 --- a/hoomd/md/MeshForceCompute.cc +++ b/hoomd/md/MeshForceCompute.cc @@ -31,7 +31,9 @@ namespace detail { void export_MeshForceCompute(pybind11::module& m) { - pybind11::class_>(m, "MeshForceCompute") + pybind11::class_>( + m, + "MeshForceCompute") .def(pybind11::init, std::shared_ptr>()); } } // end namespace detail diff --git a/hoomd/md/MeshForceCompute.h b/hoomd/md/MeshForceCompute.h index bb07d53489..fb9d858007 100644 --- a/hoomd/md/MeshForceCompute.h +++ b/hoomd/md/MeshForceCompute.h @@ -64,7 +64,6 @@ class PYBIND11_EXPORT MeshForceCompute : public ForceCompute unsigned int type_id) { }; protected: - std::shared_ptr m_mesh_data; //!< Mesh data to use in computing helfich energy }; diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index 25416f9007..dd3deef286 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -75,7 +75,7 @@ template class PotentialBond : public MeshForceCom template PotentialBond::PotentialBond(std::shared_ptr sysdef) - : MeshForceCompute(sysdef,NULL) + : MeshForceCompute(sysdef, NULL) { m_exec_conf->msg->notice(5) << "Constructing PotentialBond<" << evaluator::getName() << ">" << std::endl; @@ -92,7 +92,7 @@ PotentialBond::PotentialBond(std::shared_ptr template PotentialBond::PotentialBond(std::shared_ptr sysdef, std::shared_ptr meshdef) - : MeshForceCompute(sysdef,meshdef) + : MeshForceCompute(sysdef, meshdef) { m_exec_conf->msg->notice(5) << "Constructing PotentialMeshBond<" << evaluator::getName() << ">" << std::endl; diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc index e9f411e05d..37f547adbd 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.cc +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.cc @@ -24,7 +24,7 @@ namespace md TriangleAreaConservationMeshForceCompute::TriangleAreaConservationMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef) - : MeshForceCompute(sysdef,meshdef) + : MeshForceCompute(sysdef, meshdef) { m_exec_conf->msg->notice(5) << "Constructing TriangleAreaConservationhMeshForceCompute" << endl; diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.h b/hoomd/md/TriangleAreaConservationMeshForceCompute.h index 1ddc0d881c..27653fdcbd 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.h +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.h @@ -1,8 +1,8 @@ // Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. -#include "TriangleAreaConservationMeshParameters.h" #include "MeshForceCompute.h" +#include "TriangleAreaConservationMeshParameters.h" #include diff --git a/hoomd/md/VolumeConservationMeshForceCompute.cc b/hoomd/md/VolumeConservationMeshForceCompute.cc index 97ff63472e..b440980990 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.cc +++ b/hoomd/md/VolumeConservationMeshForceCompute.cc @@ -25,7 +25,7 @@ VolumeConservationMeshForceCompute::VolumeConservationMeshForceCompute( std::shared_ptr sysdef, std::shared_ptr meshdef, bool ignore_type) - : MeshForceCompute(sysdef,meshdef), m_ignore_type(ignore_type) + : MeshForceCompute(sysdef, meshdef), m_ignore_type(ignore_type) { m_exec_conf->msg->notice(5) << "Constructing VolumeConservationMeshForceCompute" << endl; diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index 3ddba90a55..77788d97bd 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -1,8 +1,8 @@ // Copyright (c) 2009-2025 The Regents of the University of Michigan. // Part of HOOMD-blue, released under the BSD 3-Clause License. -#include "VolumeConservationMeshParameters.h" #include "MeshForceCompute.h" +#include "VolumeConservationMeshParameters.h" #include From 7fb65c0eade60e3b781152b1c1a39da0dc59b877 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 11:17:26 -0400 Subject: [PATCH 53/58] change all virtuals to override --- hoomd/md/AreaConservationMeshForceCompute.h | 24 ++++++------- .../md/AreaConservationMeshForceComputeGPU.h | 4 +-- hoomd/md/BendingRigidityMeshForceCompute.h | 36 +++++++++---------- hoomd/md/BendingRigidityMeshForceComputeGPU.h | 2 +- hoomd/md/HelfrichMeshForceCompute.h | 26 +++++++------- hoomd/md/HelfrichMeshForceComputeGPU.h | 4 +-- hoomd/md/MeshDynamicBondUpdater.h | 2 +- hoomd/md/PotentialBond.h | 12 +++---- ...TriangleAreaConservationMeshForceCompute.h | 12 +++---- ...angleAreaConservationMeshForceComputeGPU.h | 4 +-- hoomd/md/VolumeConservationMeshForceCompute.h | 16 ++++----- .../VolumeConservationMeshForceComputeGPU.h | 4 +-- 12 files changed, 73 insertions(+), 73 deletions(-) diff --git a/hoomd/md/AreaConservationMeshForceCompute.h b/hoomd/md/AreaConservationMeshForceCompute.h index 4b1b3b0f91..23da068546 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.h +++ b/hoomd/md/AreaConservationMeshForceCompute.h @@ -76,26 +76,26 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public MeshForceCompute bool m_ignore_type; //! ignore type to calculate global area if true //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; //! compute areas - virtual void precomputeParameter(); + void precomputeParameter() override; - virtual void postcomputeParameter(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id) + void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override { ArrayHandle h_area(m_area, access_location::host, access_mode::readwrite); h_area.data[type_id] += m_area_diff; }; - virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override; }; namespace detail diff --git a/hoomd/md/AreaConservationMeshForceComputeGPU.h b/hoomd/md/AreaConservationMeshForceComputeGPU.h index d025b8ff6e..605d4865db 100644 --- a/hoomd/md/AreaConservationMeshForceComputeGPU.h +++ b/hoomd/md/AreaConservationMeshForceComputeGPU.h @@ -46,10 +46,10 @@ class PYBIND11_EXPORT AreaConservationMeshForceComputeGPU : public AreaConservat GPUArray m_sum; //!< memory space for sum over area //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; //! compute areas - virtual void precomputeParameter(); + void precomputeParameter() override; }; namespace detail diff --git a/hoomd/md/BendingRigidityMeshForceCompute.h b/hoomd/md/BendingRigidityMeshForceCompute.h index 2254823b22..65762062d6 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.h +++ b/hoomd/md/BendingRigidityMeshForceCompute.h @@ -85,7 +85,7 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public MeshForceCompute GPUArray m_params; //!< Parameters //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; virtual Scalar calcEnergy(unsigned int idx_a, unsigned int idx_b, @@ -93,23 +93,23 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public MeshForceCompute unsigned int idx_d, unsigned int type_id); - virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); - - virtual Scalar energyDiffSurrounding(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int idx_e, - unsigned int idx_f, - unsigned int idx_g, - unsigned int idx_h, - unsigned int type_id); - - virtual bool checkSurrounding() + Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override; + + Scalar energyDiffSurrounding(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int idx_e, + unsigned int idx_f, + unsigned int idx_g, + unsigned int idx_h, + unsigned int type_id) override; + + bool checkSurrounding() override { return true; } diff --git a/hoomd/md/BendingRigidityMeshForceComputeGPU.h b/hoomd/md/BendingRigidityMeshForceComputeGPU.h index f12a8135a1..5f81961206 100644 --- a/hoomd/md/BendingRigidityMeshForceComputeGPU.h +++ b/hoomd/md/BendingRigidityMeshForceComputeGPU.h @@ -41,7 +41,7 @@ class PYBIND11_EXPORT BendingRigidityMeshForceComputeGPU : public BendingRigidit std::shared_ptr> m_tuner; //!< Autotuner //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; }; namespace detail diff --git a/hoomd/md/HelfrichMeshForceCompute.h b/hoomd/md/HelfrichMeshForceCompute.h index 36b3b86b67..3fd1c61667 100644 --- a/hoomd/md/HelfrichMeshForceCompute.h +++ b/hoomd/md/HelfrichMeshForceCompute.h @@ -50,7 +50,7 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public MeshForceCompute //! Get ghost particle fields requested by this pair potential /*! \param timestep Current time step */ - virtual CommFlags getRequestedCommFlags(uint64_t timestep) + CommFlags getRequestedCommFlags(uint64_t timestep) override { CommFlags flags = CommFlags(0); flags[comm_flag::tag] = 1; @@ -79,22 +79,22 @@ class PYBIND11_EXPORT HelfrichMeshForceCompute : public MeshForceCompute Scalar3 m_sigma_dash_diff_d; //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; - virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override; //! compute sigmas - virtual void precomputeParameter(); + void precomputeParameter() override; - virtual void postcomputeParameter(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override; }; namespace detail diff --git a/hoomd/md/HelfrichMeshForceComputeGPU.h b/hoomd/md/HelfrichMeshForceComputeGPU.h index 2f29836d68..9dd1c5fec5 100644 --- a/hoomd/md/HelfrichMeshForceComputeGPU.h +++ b/hoomd/md/HelfrichMeshForceComputeGPU.h @@ -40,10 +40,10 @@ class PYBIND11_EXPORT HelfrichMeshForceComputeGPU : public HelfrichMeshForceComp std::shared_ptr> m_tuner_sigma; //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; //! compute sigmas - virtual void precomputeParameter(); + void precomputeParameter() override; }; namespace detail diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index 1dadb7df25..d1b95b4bef 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -47,7 +47,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater virtual ~MeshDynamicBondUpdater(); /// Update box interpolation based on provided timestep - virtual void update(uint64_t timestep); + void update(uint64_t timestep) override; /// Get the list of force computes std::vector>& getForces() diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index dd3deef286..d838f92297 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -64,13 +64,13 @@ template class PotentialBond : public MeshForceCom std::shared_ptr m_bond_data; //!< Bond data to use in computing bonds //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; - virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override; }; template diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.h b/hoomd/md/TriangleAreaConservationMeshForceCompute.h index 27653fdcbd..0e46a80bdb 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.h +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.h @@ -70,13 +70,13 @@ class PYBIND11_EXPORT TriangleAreaConservationMeshForceCompute : public MeshForc GPUArray m_area; //!< memory space for area //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; - virtual Scalar energyDiff(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id); + Scalar energyDiff(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override; }; namespace detail diff --git a/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h b/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h index 9cf591ac21..ca62f1162e 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h +++ b/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h @@ -56,9 +56,9 @@ class PYBIND11_EXPORT TriangleAreaConservationMeshForceComputeGPU GPUArray m_sum; //!< memory space for sum over area //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; - virtual void computeArea(); + void computeArea() override; }; namespace detail diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index 77788d97bd..6a2935c5fe 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -80,16 +80,16 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public MeshForceCompu bool m_ignore_type; //! do we ignore type to calculate global area //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; //! compute volumes - virtual void precomputeParameter(); + void precomputeParameter() override; - virtual void postcomputeParameter(unsigned int idx_a, - unsigned int idx_b, - unsigned int idx_c, - unsigned int idx_d, - unsigned int type_id) + void postcomputeParameter(unsigned int idx_a, + unsigned int idx_b, + unsigned int idx_c, + unsigned int idx_d, + unsigned int type_id) override { ArrayHandle h_volume(m_volume, access_location::host, access_mode::readwrite); h_volume.data[type_id] += m_volume_diff; @@ -99,7 +99,7 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public MeshForceCompu unsigned int idx_b, unsigned int idx_c, unsigned int idx_d, - unsigned int type_id); + unsigned int type_id) override; }; namespace detail diff --git a/hoomd/md/VolumeConservationMeshForceComputeGPU.h b/hoomd/md/VolumeConservationMeshForceComputeGPU.h index e3be3cc325..dc837de226 100644 --- a/hoomd/md/VolumeConservationMeshForceComputeGPU.h +++ b/hoomd/md/VolumeConservationMeshForceComputeGPU.h @@ -47,10 +47,10 @@ class PYBIND11_EXPORT VolumeConservationMeshForceComputeGPU GPUArray m_sum; //!< memory space for sum over volume //! Actually compute the forces - virtual void computeForces(uint64_t timestep); + void computeForces(uint64_t timestep) override; //! compute volumes - virtual void precomputeParameter(); + void precomputeParameter() override; }; namespace detail From 9495dbd54c2e9f96b31a7e3f20610668f1c6a0c6 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 11:22:43 -0400 Subject: [PATCH 54/58] change m_inv_T to m_inv_kT to make it more obvious that it is the temperature --- hoomd/md/MeshDynamicBondUpdater.cc | 8 ++++---- hoomd/md/MeshDynamicBondUpdater.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hoomd/md/MeshDynamicBondUpdater.cc b/hoomd/md/MeshDynamicBondUpdater.cc index a2ea0deb60..10d13e38f3 100644 --- a/hoomd/md/MeshDynamicBondUpdater.cc +++ b/hoomd/md/MeshDynamicBondUpdater.cc @@ -29,7 +29,7 @@ MeshDynamicBondUpdater::MeshDynamicBondUpdater(std::shared_ptr std::shared_ptr trigger, std::shared_ptr mesh, Scalar T) - : Updater(sysdef, trigger), m_mesh(mesh), m_inv_T(1.0 / T) + : Updater(sysdef, trigger), m_mesh(mesh), m_inv_kT(1.0 / T) { assert(m_pdata); assert(m_mesh); @@ -234,7 +234,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) UniformDistribution uniform(0, Scalar(1)); Scalar rand_number = uniform(rng); - Scalar part_func = exp(-m_inv_T * energyDifference); + Scalar part_func = exp(-m_inv_kT * energyDifference); std::vector tr_idx(6); std::vector b_idx(4); @@ -314,7 +314,7 @@ void MeshDynamicBondUpdater::update(uint64_t timestep) h_rtag.data[v_idx[6]], h_rtag.data[v_idx[7]], type_id); - part_func = exp(-m_inv_T * energyDifference); + part_func = exp(-m_inv_kT * energyDifference); } } @@ -404,7 +404,7 @@ void export_MeshDynamicBondUpdater(pybind11::module& m) std::shared_ptr, Scalar>()) .def_property_readonly("forces", &MeshDynamicBondUpdater::getForces) - .def_property("kT", &MeshDynamicBondUpdater::getT, &MeshDynamicBondUpdater::setT); + .def_property("kT", &MeshDynamicBondUpdater::getkT, &MeshDynamicBondUpdater::setkT); } } // end namespace detail diff --git a/hoomd/md/MeshDynamicBondUpdater.h b/hoomd/md/MeshDynamicBondUpdater.h index d1b95b4bef..290ae3ceb2 100644 --- a/hoomd/md/MeshDynamicBondUpdater.h +++ b/hoomd/md/MeshDynamicBondUpdater.h @@ -55,14 +55,14 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater return m_forces; } - Scalar getT() + Scalar getkT() { - return 1.0 / m_inv_T; + return 1.0 / m_inv_kT; }; - void setT(Scalar T) + void setkT(Scalar T) { - m_inv_T = 1.0 / T; + m_inv_kT = 1.0 / T; }; private: @@ -71,7 +71,7 @@ class PYBIND11_EXPORT MeshDynamicBondUpdater : public Updater std::shared_ptr m_mesh; //!< Active force to call rotationalDiffusion on std::vector m_update_order; std::vector m_already_updated; - Scalar m_inv_T; + Scalar m_inv_kT; }; namespace detail From cae3cd4f7d7c8f9e8c4bcdf094132333767b4652 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 13:28:29 -0400 Subject: [PATCH 55/58] fix virtaul vs override --- hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h b/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h index ca62f1162e..daec254bf2 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h +++ b/hoomd/md/TriangleAreaConservationMeshForceComputeGPU.h @@ -58,7 +58,7 @@ class PYBIND11_EXPORT TriangleAreaConservationMeshForceComputeGPU //! Actually compute the forces void computeForces(uint64_t timestep) override; - void computeArea() override; + virtual void computeArea(); }; namespace detail From b7b80bc5381eba6d2ed04526637017d603a221c2 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 15:12:54 -0400 Subject: [PATCH 56/58] rephrase attach exception for force list in updater --- hoomd/data/syncedlist.py | 6 +++--- hoomd/md/mesh/potential.py | 1 - hoomd/md/update.py | 3 +++ hoomd/operation.py | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/hoomd/data/syncedlist.py b/hoomd/data/syncedlist.py index 92487b060d..d3472a8d36 100644 --- a/hoomd/data/syncedlist.py +++ b/hoomd/data/syncedlist.py @@ -192,10 +192,10 @@ def _register_item(self, value): return else: if value._attached: - if not value._two_attach: - raise RuntimeError(f"Cannot place {value} into two simulations.") + if not value._allow_if_updater: + raise RuntimeError(f"Cannot place {value} into list twice.") else: - value._two_attach = False + value._allow_if_updater = False def _unregister_item(self, value): """Detaches and/or removes value to simulation if attached. diff --git a/hoomd/md/mesh/potential.py b/hoomd/md/mesh/potential.py index 98193cc07a..07ced7e824 100644 --- a/hoomd/md/mesh/potential.py +++ b/hoomd/md/mesh/potential.py @@ -52,7 +52,6 @@ class MeshPotential(Force): def __init__(self, mesh): super().__init__() self._mesh = validate_mesh(mesh) - self._two_attach = True def _attach_hook(self): """Create the c++ mirror class.""" diff --git a/hoomd/md/update.py b/hoomd/md/update.py index 3dbc4fa075..ca49b7e116 100644 --- a/hoomd/md/update.py +++ b/hoomd/md/update.py @@ -414,6 +414,9 @@ def __init__(self, trigger, mesh, kT, forces=[]): # initialize base class super().__init__(trigger) + for force in forces: + force._allow_if_updater = True + self._forces = syncedlist.SyncedList( MeshPotential, syncedlist._PartialGetAttr("_cpp_obj"), iterable=forces ) diff --git a/hoomd/operation.py b/hoomd/operation.py index 3b9d38c9fc..4df2b0721c 100644 --- a/hoomd/operation.py +++ b/hoomd/operation.py @@ -548,7 +548,7 @@ class see its documentation. ) def __init__(self): - self._two_attach = False + self._allow_if_updater = False class TriggeredOperation(Operation): From e86f5c50b0b76ce782b4303baea4e3d7929db4b9 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 15:33:19 -0400 Subject: [PATCH 57/58] override getRequestedCommFlags --- hoomd/md/AreaConservationMeshForceCompute.h | 2 +- hoomd/md/BendingRigidityMeshForceCompute.h | 2 +- hoomd/md/PotentialBond.h | 2 +- hoomd/md/SurfaceTensionMeshForceCompute.h | 113 ++++++++++++++++++ ...TriangleAreaConservationMeshForceCompute.h | 2 +- hoomd/md/VolumeConservationMeshForceCompute.h | 2 +- 6 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 hoomd/md/SurfaceTensionMeshForceCompute.h diff --git a/hoomd/md/AreaConservationMeshForceCompute.h b/hoomd/md/AreaConservationMeshForceCompute.h index 23da068546..47c0aed10a 100644 --- a/hoomd/md/AreaConservationMeshForceCompute.h +++ b/hoomd/md/AreaConservationMeshForceCompute.h @@ -60,7 +60,7 @@ class PYBIND11_EXPORT AreaConservationMeshForceCompute : public MeshForceCompute //! Get ghost particle fields requested by this pair potential /*! \param timestep Current time step */ - virtual CommFlags getRequestedCommFlags(uint64_t timestep) + CommFlags getRequestedCommFlags(uint64_t timestep) override { CommFlags flags = CommFlags(0); flags[comm_flag::tag] = 1; diff --git a/hoomd/md/BendingRigidityMeshForceCompute.h b/hoomd/md/BendingRigidityMeshForceCompute.h index 65762062d6..e75ea35c8e 100644 --- a/hoomd/md/BendingRigidityMeshForceCompute.h +++ b/hoomd/md/BendingRigidityMeshForceCompute.h @@ -72,7 +72,7 @@ class PYBIND11_EXPORT BendingRigidityMeshForceCompute : public MeshForceCompute //! Get ghost particle fields requested by this pair potential /*! \param timestep Current time step */ - virtual CommFlags getRequestedCommFlags(uint64_t timestep) + CommFlags getRequestedCommFlags(uint64_t timestep) override { CommFlags flags = CommFlags(0); flags[comm_flag::tag] = 1; diff --git a/hoomd/md/PotentialBond.h b/hoomd/md/PotentialBond.h index d838f92297..16249cde8c 100644 --- a/hoomd/md/PotentialBond.h +++ b/hoomd/md/PotentialBond.h @@ -56,7 +56,7 @@ template class PotentialBond : public MeshForceCom #ifdef ENABLE_MPI //! Get ghost particle fields requested by this pair potential - virtual CommFlags getRequestedCommFlags(uint64_t timestep); + CommFlags getRequestedCommFlags(uint64_t timestep) override; #endif protected: diff --git a/hoomd/md/SurfaceTensionMeshForceCompute.h b/hoomd/md/SurfaceTensionMeshForceCompute.h new file mode 100644 index 0000000000..527e314f50 --- /dev/null +++ b/hoomd/md/SurfaceTensionMeshForceCompute.h @@ -0,0 +1,113 @@ +// Copyright (c) 2009-2025 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +#include "hoomd/ForceCompute.h" +#include "hoomd/MeshDefinition.h" + +#include + +/*! \file SurfaceTensionForceCompute.h + \brief Declares a class for computing surface tension forces +*/ + +#ifdef __HIPCC__ +#error This header cannot be compiled by nvcc +#endif + +#include + +#ifndef __SURFACETENSIONMESHFORCECOMPUTE_H__ +#define __SURFACETENSIONMESHFORCECOMPUTE_H__ + +namespace hoomd + { +namespace md + { +struct surface_tension_params + { + Scalar k; + +#ifndef __HIPCC__ + surface_tension_params() : k(0){ } + + surface_tension_params(pybind11::dict params) + : sigma(params["k"].cast()) + { + } + + pybind11::dict asDict() + { + pybind11::dict v; + v["k"] = k; + return v; + } +#endif + } +#ifdef SINGLE_PRECISION + __attribute__((aligned(8))); +#else + __attribute__((aligned(16))); +#endif + +//! Computes surface tension forces on the mesh +/*! Surface tension forces are computed on every triangle in a mesh. + \ingroup computes +*/ +class PYBIND11_EXPORT SurfaceTensionMeshForceCompute : public ForceCompute + { + public: + //! Constructs the compute + SurfaceTensionMeshForceCompute(std::shared_ptr sysdef, + std::shared_ptr meshdef); + + //! Destructor + virtual ~SurfaceTensionMeshForceCompute(); + + //! Set the parameters + virtual void setParams(unsigned int type, Scalar sigma); + + virtual void setParamsPython(std::string type, pybind11::dict params); + + /// Get the parameters for a type + pybind11::dict getParams(std::string type); + + virtual pybind11::array_t getArea() + { + ArrayHandle h_area(m_area, access_location::host, access_mode::read); + return pybind11::array(m_mesh_data->getMeshTriangleData()->getNTypes(), h_area.data); + }; + +#ifdef ENABLE_MPI + //! Get ghost particle fields requested by this pair potential + /*! \param timestep Current time step + */ + virtual CommFlags getRequestedCommFlags(uint64_t timestep) + { + CommFlags flags = CommFlags(0); + flags[comm_flag::tag] = 1; + flags |= ForceCompute::getRequestedCommFlags(timestep); + return flags; + } +#endif + + protected: + GPUArray m_params; //!< Parameters + GPUArray m_area; //!< memory space for area + + std::shared_ptr + m_mesh_data; //!< Mesh data to use in computing area conservation energy + + //! Actually compute the forces + virtual void computeForces(uint64_t timestep); + }; + +namespace detail + { +//! Exports the SurfaceTensionMeshForceCompute class to python +void export_SurfaceTensionMeshForceCompute(pybind11::module& m); + + } // end namespace detail + } // end namespace md + } // end namespace hoomd + +#endif diff --git a/hoomd/md/TriangleAreaConservationMeshForceCompute.h b/hoomd/md/TriangleAreaConservationMeshForceCompute.h index 0e46a80bdb..1e9fe2c1e8 100644 --- a/hoomd/md/TriangleAreaConservationMeshForceCompute.h +++ b/hoomd/md/TriangleAreaConservationMeshForceCompute.h @@ -56,7 +56,7 @@ class PYBIND11_EXPORT TriangleAreaConservationMeshForceCompute : public MeshForc //! Get ghost particle fields requested by this pair potential /*! \param timestep Current time step */ - virtual CommFlags getRequestedCommFlags(uint64_t timestep) + CommFlags getRequestedCommFlags(uint64_t timestep) override { CommFlags flags = CommFlags(0); flags[comm_flag::tag] = 1; diff --git a/hoomd/md/VolumeConservationMeshForceCompute.h b/hoomd/md/VolumeConservationMeshForceCompute.h index 6a2935c5fe..9f0315e733 100644 --- a/hoomd/md/VolumeConservationMeshForceCompute.h +++ b/hoomd/md/VolumeConservationMeshForceCompute.h @@ -61,7 +61,7 @@ class PYBIND11_EXPORT VolumeConservationMeshForceCompute : public MeshForceCompu //! Get ghost particle fields requested by this pair potential /*! \param timestep Current time step */ - virtual CommFlags getRequestedCommFlags(uint64_t timestep) + CommFlags getRequestedCommFlags(uint64_t timestep) override { CommFlags flags = CommFlags(0); flags[comm_flag::tag] = 1; From 5a1595eb069d2910fadac446cf91bb76c351d86b Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 26 Aug 2025 15:37:57 -0400 Subject: [PATCH 58/58] remove wrong file --- hoomd/md/SurfaceTensionMeshForceCompute.h | 113 ---------------------- 1 file changed, 113 deletions(-) delete mode 100644 hoomd/md/SurfaceTensionMeshForceCompute.h diff --git a/hoomd/md/SurfaceTensionMeshForceCompute.h b/hoomd/md/SurfaceTensionMeshForceCompute.h deleted file mode 100644 index 527e314f50..0000000000 --- a/hoomd/md/SurfaceTensionMeshForceCompute.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2009-2025 The Regents of the University of Michigan. -// Part of HOOMD-blue, released under the BSD 3-Clause License. - -#include "hoomd/ForceCompute.h" -#include "hoomd/MeshDefinition.h" - -#include - -/*! \file SurfaceTensionForceCompute.h - \brief Declares a class for computing surface tension forces -*/ - -#ifdef __HIPCC__ -#error This header cannot be compiled by nvcc -#endif - -#include - -#ifndef __SURFACETENSIONMESHFORCECOMPUTE_H__ -#define __SURFACETENSIONMESHFORCECOMPUTE_H__ - -namespace hoomd - { -namespace md - { -struct surface_tension_params - { - Scalar k; - -#ifndef __HIPCC__ - surface_tension_params() : k(0){ } - - surface_tension_params(pybind11::dict params) - : sigma(params["k"].cast()) - { - } - - pybind11::dict asDict() - { - pybind11::dict v; - v["k"] = k; - return v; - } -#endif - } -#ifdef SINGLE_PRECISION - __attribute__((aligned(8))); -#else - __attribute__((aligned(16))); -#endif - -//! Computes surface tension forces on the mesh -/*! Surface tension forces are computed on every triangle in a mesh. - \ingroup computes -*/ -class PYBIND11_EXPORT SurfaceTensionMeshForceCompute : public ForceCompute - { - public: - //! Constructs the compute - SurfaceTensionMeshForceCompute(std::shared_ptr sysdef, - std::shared_ptr meshdef); - - //! Destructor - virtual ~SurfaceTensionMeshForceCompute(); - - //! Set the parameters - virtual void setParams(unsigned int type, Scalar sigma); - - virtual void setParamsPython(std::string type, pybind11::dict params); - - /// Get the parameters for a type - pybind11::dict getParams(std::string type); - - virtual pybind11::array_t getArea() - { - ArrayHandle h_area(m_area, access_location::host, access_mode::read); - return pybind11::array(m_mesh_data->getMeshTriangleData()->getNTypes(), h_area.data); - }; - -#ifdef ENABLE_MPI - //! Get ghost particle fields requested by this pair potential - /*! \param timestep Current time step - */ - virtual CommFlags getRequestedCommFlags(uint64_t timestep) - { - CommFlags flags = CommFlags(0); - flags[comm_flag::tag] = 1; - flags |= ForceCompute::getRequestedCommFlags(timestep); - return flags; - } -#endif - - protected: - GPUArray m_params; //!< Parameters - GPUArray m_area; //!< memory space for area - - std::shared_ptr - m_mesh_data; //!< Mesh data to use in computing area conservation energy - - //! Actually compute the forces - virtual void computeForces(uint64_t timestep); - }; - -namespace detail - { -//! Exports the SurfaceTensionMeshForceCompute class to python -void export_SurfaceTensionMeshForceCompute(pybind11::module& m); - - } // end namespace detail - } // end namespace md - } // end namespace hoomd - -#endif