Skip to content

Commit

Permalink
Merge branch 'main' into ml-forces
Browse files Browse the repository at this point in the history
  • Loading branch information
marjanalbooyeh authored Feb 17, 2025
2 parents 7342483 + 5bc8a03 commit 6971732
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 191 deletions.
21 changes: 9 additions & 12 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
fail-fast: false
matrix:
os: [macos-14, ubuntu-24.04]
python-version: ['3.10', '3.11']
python-version: ['3.10', '3.11', '3.12']

runs-on: ${{ matrix.os }}

Expand All @@ -39,13 +39,11 @@ jobs:
uses: actions/checkout@v4

- name: Build environment
uses: conda-incubator/setup-miniconda@v3
uses: mamba-org/setup-micromamba@v2
with:
environment-file: environment-dev.yml
python-version: ${{ matrix.python-version }}
miniforge-variant: Mambaforge
#miniforge-version: 24.11.0
use-mamba: true
create-args: >-
python=${{ matrix.python-version }}
- name: Install package
shell: bash -l {0}
Expand All @@ -56,7 +54,7 @@ jobs:
run: python -m pytest -rs -v --cov=./ --cov-report=xml

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
Expand Down Expand Up @@ -99,17 +97,16 @@ jobs:
uses: actions/checkout@v4

- name: Build environment
uses: conda-incubator/setup-miniconda@v3
uses: mamba-org/setup-micromamba@v2
with:
environment-file: environment-dev.yml
miniforge-variant: Mambaforge
#miniforge-version: 24.11.0
use-mamba: true
create-args: >-
python=3.12
- name: Install package
shell: bash -l {0}
run: pip install .

- name: Run pytest on tutorials
shell: bash -l {0}
run: python -m pytest -rs -v --nbmake tutorials/
run: python -m pytest -rs -v --nbmake tutorials/
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ ci:
submodules: false
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4 # Ruff version
rev: v0.9.6 # Ruff version
hooks:
- id: ruff
args: [--fix, --extend-ignore=E203]
Expand All @@ -23,7 +23,7 @@ repos:
- id: trailing-whitespace
exclude: 'flowermd/tests/assets/.* | flowermd/assets/.*'
- repo: https://github.com/pycqa/isort
rev: 5.13.2
rev: 6.0.0
hooks:
- id: isort
name: isort (python)
Expand Down
2 changes: 1 addition & 1 deletion environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ dependencies:
- pytest
- pytest-cov
- nbmake
- python >=3.10, <3.12
- python >=3.10, <3.13
- fresnel >=0.13.5
- cmeutils >=1.3
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ dependencies:
- openbabel >=3
- pip
- py3Dmol
- python >=3.10, <3.12
- python >=3.10, <3.13
- fresnel >=0.13.5
- cmeutils >=1.3
1 change: 1 addition & 0 deletions flowermd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
System,
)
from .internal.units import Units

3 changes: 0 additions & 3 deletions flowermd/__version__.py

This file was deleted.

3 changes: 1 addition & 2 deletions flowermd/base/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,7 @@ def _build(self, length):
self.periodic_bond_axis, str
) or self.periodic_bond_axis.lower() not in ["x", "y", "z"]:
raise ValueError(
"Valid choices for a `periodic_bond_axis` are "
"'x', 'y', 'z'"
"Valid choices for a `periodic_bond_axis` are 'x', 'y', 'z'"
)
add_hydrogens = False
else:
Expand Down
3 changes: 1 addition & 2 deletions flowermd/base/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ def __init__(
):
if not isinstance(forcefield, Iterable) or isinstance(forcefield, str):
raise ValueError(
"forcefield must be a sequence of "
"hoomd.md.force.Force objects."
"forcefield must be a sequence of hoomd.md.force.Force objects."
)
else:
for obj in forcefield:
Expand Down
94 changes: 48 additions & 46 deletions flowermd/base/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pickle
import warnings
from abc import ABC, abstractmethod
from typing import List, Union
from typing import List

import gsd
import mbuild as mb
Expand All @@ -14,7 +14,7 @@

from flowermd.base.forcefield import BaseHOOMDForcefield, BaseXMLForcefield
from flowermd.base.molecule import Molecule
from flowermd.internal import Units, check_return_iterable, validate_unit
from flowermd.internal import check_return_iterable, validate_ref_value
from flowermd.internal.exceptions import ForceFieldError, MoleculeLoadError
from flowermd.utils import (
get_target_box_mass_density,
Expand Down Expand Up @@ -48,6 +48,8 @@ class System(ABC):
Dictionary of base units to use for scaling.
Dictionary keys are "length", "mass", and "energy". Values should be an
unyt array of the desired base unit.
kwargs
See classes that inherit from System for kwargs
Warnings
--------
Expand All @@ -68,6 +70,7 @@ def __init__(
self,
molecules,
base_units=dict(),
**kwargs,
):
self._molecules = check_return_iterable(molecules)
self.all_molecules = []
Expand Down Expand Up @@ -123,7 +126,7 @@ def __init__(
self.n_mol_types += 1

# Create mBuild system
self.system = self._build_system()
self.system = self._build_system(**kwargs)
# Create GMSO topology
self.gmso_system = self._convert_to_gmso()

Expand Down Expand Up @@ -208,10 +211,12 @@ def reference_length(self, length):
Parameters
----------
length : reference length * `flowermd.Units`, required
length : string or unyt.unyt_quantity, required
The reference length of the system.
It can be provided in the following form of:
value * `flowermd.Units`, for example 1 * `flowermd.Units.angstrom`.
It can be provided in the following forms:
1) A string with the format of "value unit", for example "1 nm".
2) A unyt.unyt_quantity object with the correct dimension. For
example, unyt.unyt_quantity(1, "nm").
"""
if self.auto_scale:
Expand All @@ -220,7 +225,7 @@ def reference_length(self, length):
"Setting reference length manually disables auto "
"scaling."
)
validated_length = validate_unit(length, u.dimensions.length)
validated_length = validate_ref_value(length, u.dimensions.length)
self._reference_values["length"] = validated_length

@reference_energy.setter
Expand All @@ -229,10 +234,12 @@ def reference_energy(self, energy):
Parameters
----------
energy : reference energy * `flowermd.Units`, required
energy : string or unyt.unyt_quantity, required
The reference energy of the system.
It can be provided in the following form of:
value * `flowermd.Units`, for example 1 * `flowermd.Units.kcal/mol`.
It can be provided in the following forms:
1) A string with the format of "value unit", for example "1 kJ/mol".
2) A unyt.unyt_quantity object with the correct dimension. For
example, unyt.unyt_quantity(1, "kJ/mol").
"""
if self.auto_scale:
Expand All @@ -241,7 +248,7 @@ def reference_energy(self, energy):
"Setting reference energy manually disables auto "
"scaling."
)
validated_energy = validate_unit(energy, u.dimensions.energy)
validated_energy = validate_ref_value(energy, u.dimensions.energy)
self._reference_values["energy"] = validated_energy

@reference_mass.setter
Expand All @@ -250,18 +257,21 @@ def reference_mass(self, mass):
Parameters
----------
mass : reference mass * `flowermd.Units`, required
mass : string or unyt.unyt_quantity, required
The reference mass of the system.
It can be provided in the following form of:
value * `flowermd.Units`, for example 1 * `flowermd.Units.amu`.
It can be provided in the following forms:
1) A string with the format of "value unit", for example "1 amu".
2) A unyt.unyt_quantity object with the correct dimension. For
example, unyt.unyt_quantity(1, "amu").
"""
if self.auto_scale:
warnings.warn(
"`auto_scale` was set to True for this system. "
"Setting reference mass manually disables auto "
"scaling."
)
validated_mass = validate_unit(mass, u.dimensions.mass)
validated_mass = validate_ref_value(mass, u.dimensions.mass)
self._reference_values["mass"] = validated_mass

@reference_values.setter
Expand Down Expand Up @@ -397,23 +407,6 @@ def to_gsd(self, file_name):
with gsd.hoomd.open(file_name, "w") as traj:
traj.append(self.hoomd_snapshot)

def save_reference_values(self, file_path="reference_values.pickle"):
"""Save the reference values of the system to a pickle file.
Parameters
----------
file_path : str, default "reference_values.pickle"
The path to save the pickle file to.
"""
if not self.reference_values:
raise ValueError(
"Reference values have not been set. "
"See System.reference_values"
)
f = open(file_path, "wb")
pickle.dump(self.reference_values, f)

def _convert_to_gmso(self):
"""Convert the mbuild system to a gmso system."""
topology = from_mbuild(self.system)
Expand Down Expand Up @@ -625,18 +618,21 @@ class Pack(System):
Parameters
----------
density : float or unyt_quantity or flowermd.internal.Units, required
The desired density of the system. Used to set the
density : float, required
The desired density of the system (g/cm^3). Used to set the
target_box attribute. Can be useful when initializing
systems at low density and running a shrink simulation
to achieve a target density. If no unit is provided, assuming the
density is in g/cm**3.
to achieve a target density.
packing_expand_factor : int, default 5
The factor by which to expand the box for packing.
edge : float, default 0.2
The space (nm) between the edge of the box and the molecules.
overlap : float, default 0.2
Minimum separation (nm) between particles of different molecules.
seed : int, default 12345
Change seed to be passed to PACKMOL for different starting positions
kwargs
Arguments to be passed into mbuild.packing.fill_box
.. warning::
Expand All @@ -661,30 +657,34 @@ class Pack(System):
def __init__(
self,
molecules,
density: Union[int, float, u.unyt_quantity, u.unyt_array, Units],
density: float,
base_units=dict(),
packing_expand_factor=5,
edge=0.2,
overlap=0.2,
seed=12345,
fix_orientation=False,
**kwargs,
):
if isinstance(density, (int, float)):
if not isinstance(density, u.array.unyt_quantity):
self.density = density * u.Unit("g") / u.Unit("cm**3")
warnings.warn(
"Units for density were not given, assuming "
"units of g/cm**3."
"Units for density were not given, assuming units of g/cm**3."
)
self.density = density * Units.g_cm3
else:
self.density = density
self.packing_expand_factor = packing_expand_factor
self.edge = edge
self.overlap = overlap
self.seed = seed
self.fix_orientation = fix_orientation
super(Pack, self).__init__(molecules=molecules, base_units=base_units)
super(Pack, self).__init__(
molecules=molecules, base_units=base_units, **kwargs
)

def _build_system(self):
mass_density = Units.kg_m3
number_density = Units.n_m3
def _build_system(self, **kwargs):
mass_density = u.Unit("kg") / u.Unit("m**3")
number_density = u.Unit("m**-3")
if self.density.units.dimensions == mass_density.dimensions:
target_box = get_target_box_mass_density(
density=self.density, mass=self.mass
Expand All @@ -706,8 +706,10 @@ def _build_system(self):
n_compounds=[1 for i in self.all_molecules],
box=list(target_box * self.packing_expand_factor),
overlap=self.overlap,
seed=self.seed,
edge=self.edge,
fix_orientation=self.fix_orientation,
**kwargs,
)
return system

Expand Down Expand Up @@ -794,4 +796,4 @@ def _build_system(self):
system.translate_to(
(system.box.Lx / 2, system.box.Ly / 2, system.box.Lz / 2)
)
return system
return system
3 changes: 1 addition & 2 deletions flowermd/modules/surface_wetting/surface_wetting.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ def run_droplet(
final_density, (u.array.unyt_quantity, u.unyt_quantity, Units)
):
warnings.warn(
"Units for density were not given, assuming "
"units of g/cm**3."
"Units for density were not given, assuming units of g/cm**3."
)
target_box_shrink = get_target_box_mass_density(
density=shrink_density * Units.g_cm3,
Expand Down
12 changes: 6 additions & 6 deletions flowermd/tests/base/test_molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ def test_polymer_different_chain_lengths(self, dimethylether_smiles):
bond_orientation=[None, None],
)
assert polymer.n_particles == 53
assert len(polymer.molecules[0].children) == 3
assert len(polymer.molecules[1].children) == 4
assert len(polymer.molecules[0].labels["all-monomers"]) == 3
assert len(polymer.molecules[1].labels["all-monomers"]) == 4

def test_polymer_different_num_mol(self, dimethylether_smiles):
polymer = Polymer(
Expand All @@ -220,9 +220,9 @@ def test_polymer_different_num_mol(self, dimethylether_smiles):
bond_orientation=[None, None],
)
assert polymer.n_particles == 55
assert len(polymer.molecules[0].children) == 3
assert len(polymer.molecules[1].children) == 2
assert len(polymer.molecules[2].children) == 2
assert len(polymer.molecules[0].labels["all-monomers"]) == 3
assert len(polymer.molecules[1].labels["all-monomers"]) == 2
assert len(polymer.molecules[2].labels["all-monomers"]) == 2

def test_polymer_unequal_num_mol_length(self, dimethylether_smiles):
with pytest.raises(ValueError):
Expand Down Expand Up @@ -324,4 +324,4 @@ def test_periodic_bond_bad_axis(self, polyethylene):
with pytest.raises(ValueError):
polyethylene(num_mols=1, lengths=20, periodic_bond_axis=1)
with pytest.raises(ValueError):
polyethylene(num_mols=1, lengths=20, periodic_bond_axis="a")
polyethylene(num_mols=1, lengths=20, periodic_bond_axis="a")
Loading

0 comments on commit 6971732

Please sign in to comment.