Skip to content

Add support for writing rigid bodies when converting to HOOMD formats. #850

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 50 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3a27d99
add rigid_body field to atom, populate in from_mbuild
chrisjonesBSU Sep 17, 2024
bbb65c3
move rigid_id property to abstract_site from atom, write out rigid_id…
chrisjonesBSU Sep 17, 2024
92534db
add rigid types and typeids
chrisjonesBSU Sep 17, 2024
62edfeb
Merge branch 'fix/molecule' into rigid-bodies
chrisjonesBSU Sep 18, 2024
ab00493
add test for rigid_id assignment
chrisjonesBSU Sep 18, 2024
3d28187
Merge branch 'main' of github.com:mosdef-hub/gmso into rigid-bodies
chrisjonesBSU Sep 19, 2024
f6480bc
write out rigid xyz, com, tags
chrisjonesBSU Sep 23, 2024
ad603fa
add if statement before writing rigid tags
chrisjonesBSU Sep 23, 2024
fdba315
add basic rigid body snapshot test
chrisjonesBSU Sep 23, 2024
3a06f24
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 23, 2024
60e3538
Merge branch 'main' of github.com:mosdef-hub/gmso into rigid-bodies
chrisjonesBSU Sep 24, 2024
8842973
remove rigid id from convert mbuild, remove rigid id prop from abstra…
chrisjonesBSU Sep 25, 2024
6a383c6
parse rigid sites from site.molecule, update test
chrisjonesBSU Sep 26, 2024
7c65624
remove un-needed var
chrisjonesBSU Sep 30, 2024
a732661
Merge branch 'main' into rigid-bodies
chrisjonesBSU Oct 14, 2024
8da6fe5
update tests
chrisjonesBSU Oct 16, 2024
e9de935
Merge branch 'main' of github.com:mosdef-hub/gmso into rigid-bodies
chrisjonesBSU Oct 16, 2024
75289bb
fix charge array in np.concatenate call
chrisjonesBSU Oct 17, 2024
0d6e7d2
adjust snapshot groups by num rigid bodies
chrisjonesBSU Oct 17, 2024
a72d898
update tests
chrisjonesBSU Oct 17, 2024
5e8635f
fix _parse_pairs
chrisjonesBSU Oct 17, 2024
b96a83c
use unyt_arrays for charges and mass instead of lists
chrisjonesBSU Oct 18, 2024
937f913
Merge branch 'main' into rigid-bodies
chrisjonesBSU Oct 22, 2024
ffe639c
handle mix of rigid and non rigid
chrisjonesBSU Oct 30, 2024
4eaf697
remove if statement to filter -1 ids
chrisjonesBSU Oct 30, 2024
fb161b1
merge and fix conflicts. Pin hoomd<5
chrisjonesBSU Jan 21, 2025
c712555
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 21, 2025
91642f0
Merge branch 'main' of github.com:mosdef-hub/gmso into rigid-bodies
chrisjonesBSU Jan 23, 2025
da69c18
Merge branch 'main' of github.com:mosdef-hub/gmso into rigid-bodies
chrisjonesBSU Jan 28, 2025
24537d1
Merge branch 'main' into rigid-bodies
chrisjonesBSU Mar 5, 2025
8546680
add moit util, fill in more snapshot info
chrisjonesBSU Mar 5, 2025
1e388b0
Merge branch 'main' into rigid-bodies
chrisjonesBSU Mar 18, 2025
c2738e7
bump molecule numbres, return rigid body info dict
chrisjonesBSU Mar 18, 2025
e23bb51
refactor to work with multiple kinds of rigid mols
chrisjonesBSU Mar 18, 2025
e81ddb6
add more code comments
chrisjonesBSU Mar 19, 2025
14c4deb
remove unused variable
chrisjonesBSU Mar 19, 2025
fc73e46
fix existing tests
chrisjonesBSU Mar 20, 2025
104b2de
Merge branch 'rigid-bodies' of github.com:chrisjonesBSU/gmso into rig…
chrisjonesBSU Mar 20, 2025
91a3ffb
clean things up a bit
chrisjonesBSU Mar 20, 2025
f4d0dd6
add test with 2 kinds of rigid mols
chrisjonesBSU Mar 20, 2025
ff6512f
remove snapshot.validate() for hoomd snapshot
chrisjonesBSU Mar 20, 2025
c8b66d2
simplify tests
chrisjonesBSU Mar 20, 2025
d24b36b
Merge branch 'main' of github.com:mosdef-hub/gmso into rigid-bodies
chrisjonesBSU Mar 25, 2025
86c1684
add conditional return, update doc strings
chrisjonesBSU Mar 25, 2025
3ea4599
minor doc string fixes
chrisjonesBSU Mar 25, 2025
e69e1df
add test for moit function
chrisjonesBSU Mar 25, 2025
078cc18
quick doc string change
chrisjonesBSU Mar 25, 2025
67ebc62
merge and fix conflicts
chrisjonesBSU Mar 26, 2025
3dc1ce2
Merge branch 'main' into rigid-bodies
chrisjonesBSU Apr 2, 2025
1e39411
Merge branch 'main' into rigid-bodies
chrisjonesBSU Apr 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions gmso/abc/abstract_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ def __repr__(self):
alias="position",
)

rigid_id_: Optional[int] = Field(
None,
description="Rigid body ID used to assign rigid body contraints in HOOMD-Blue topologies.",
alias="rigid_id",
)

model_config = ConfigDict(
alias_to_fields={
"name": "name_",
Expand Down Expand Up @@ -261,6 +267,11 @@ def residue(self):
"""Return the residue assigned to the site."""
return self.__dict__.get("residue_")

@property
def rigid_id(self):
"""Return the rigid body ID for this atom."""
return self.__dict__.get("rigid_id_")

@field_serializer("position_")
def serialize_position(self, position_: PositionType):
return unyt_to_dict(position_)
Expand Down
46 changes: 38 additions & 8 deletions gmso/external/convert_hoomd.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,6 @@ def _parse_particle_information(
site.name if site.atom_type is None else site.atom_type.name
for site in top.sites
]
unique_types = sorted(list(set(types)))
typeids = np.array([unique_types.index(t) for t in types])
masses = list()
charges = list()
for site in top.sites:
Expand All @@ -295,6 +293,39 @@ def _parse_particle_information(
else 1 * base_units["mass"]
)
charges.append(site.charge if site.charge else 0 * u.elementary_charge)
# Check for rigid IDs
rigid_ids = [site.rigid_id for site in top.sites]
rigid_ids_set = set(rigid_ids)
if all(rigid_ids): # Need to create rigid bodies
n_rigid = len(rigid_ids_set)
write_rigid = True
else:
write_rigid = False
n_rigid = 0
unique_types = sorted(list(set(types)))
typeids = np.array([unique_types.index(t) for t in types])
if write_rigid:
rigid_masses = np.zeros(n_rigid)
rigid_xyz = np.zeros(n_rigid)
# Rigid particle type defaults to "R"; add to front of list
# TODO: Can we always use "R" here? What if an atom_type is "R"?
unique_types = ["R"] + unique_types
# Rigid particles get type ID 0, move all others up by 1
typeids = np.concatenate(([0] * n_rigid), typeids + 1)
# Update mass list and position list of Frame
for idx, _id in enumerate(rigid_ids_set):
group_indices = np.where(rigid_ids == _id)[0]
group_positions = xyz[group_indices]
group_masses = masses[group_indices]
com_xyz = np.sum(group_positions.T * group_masses, axis=1) / sum(
group_masses
)
rigid_masses[idx] = sum(group_masses)
rigid_xyz[idx] = com_xyz
# Append rigid center mass and xyz to front
masses = np.concatenate(rigid_masses, masses)
xyz = np.concatenate(rigid_xyz, xyz)
rigid_id_tags = np.concatenate(np.arange(n_rigid), np.array(rigid_ids))

"""
Permittivity of free space = 2.39725e-4 e^2/((kcal/mol)(angstrom)),
Expand All @@ -309,24 +340,23 @@ def _parse_particle_information(
) ** 0.5

if isinstance(snapshot, hoomd.Snapshot):
snapshot.particles.N = top.n_sites
snapshot.particles.N = top.n_sites + n_rigid
snapshot.particles.types = unique_types
snapshot.particles.position[0:] = xyz
snapshot.particles.typeid[0:] = typeids
snapshot.particles.mass[0:] = masses
snapshot.particles.charge[0:] = charges / charge_factor
if write_rigid:
snapshot.particles.body[0:] = rigid_id_tags
elif isinstance(snapshot, gsd.hoomd.Frame):
snapshot.particles.N = top.n_sites
snapshot.particles.types = unique_types
snapshot.particles.position = xyz
snapshot.particles.typeid = typeids
snapshot.particles.mass = masses
snapshot.particles.charge = charges / charge_factor
if rigid_bodies:
warnings.warn(
"Rigid bodies detected, but not yet implemented for GSD",
NotYetImplementedWarning,
)
if write_rigid:
snapshot.particles.body = rigid_id_tags


def _parse_pairs_information(
Expand Down
2 changes: 2 additions & 0 deletions gmso/external/convert_mbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ def _parse_particle(particle_map, site):
charge=charge,
mass=mass,
)
particle.rigid_id = site.rigid_id
particle_map[site] = particle
return particle

Expand All @@ -272,6 +273,7 @@ def _parse_site(site_map, particle, search_method, infer_element=False):
element=ele,
charge=charge,
mass=mass,
rigid_id=particle.rigid_id,
molecule=site_map[particle]["molecule"],
residue=site_map[particle]["residue"],
group=site_map[particle]["group"],
Expand Down
11 changes: 11 additions & 0 deletions gmso/tests/test_convert_mbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,14 @@ def test_nontop_level_compound(self, mb_ethane):
cpd.add(mb_ethane)
with pytest.raises(AssertionError):
from_mbuild(mb_ethane)

def test_rigid_ids(self, mb_ethane):
box = mb.fill_box(mb_ethane, n_compounds=3, box=[2, 2, 2])
for i, child in enumerate(box.children):
for p in child.particles():
p.rigid_id = i

top = from_mbuild(box)
assert set([site.rigid_id for site in top.sites]) == {0, 1, 2}
for particle, site in zip(box.particles(), top.sites):
assert particle.rigid_id == site.rigid_id
Loading