Skip to content

Commit

Permalink
Merge pull request cmelab#96 from cmelab/surface-wetting
Browse files Browse the repository at this point in the history
Add surface wetting module
  • Loading branch information
marjanalbooyeh authored Nov 28, 2023
2 parents 531cd82 + c8105bc commit 6e2c173
Show file tree
Hide file tree
Showing 25 changed files with 1,566 additions and 51 deletions.
1 change: 1 addition & 0 deletions docs/source/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ Modules
:maxdepth: 1

welding
surface_wetting
23 changes: 23 additions & 0 deletions docs/source/surface_wetting.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Surface Wetting
---------------

.. py:currentmodule:flowermd.modules
.. rubric:: Details

.. automodule:: flowermd.modules.surface_wetting
:no-members:

.. autoclass:: DropletSimulation()
:members:
:no-index:

.. autoclass:: InterfaceBuilder()
:members:
:no-index:
:show-inheritance:

.. autoclass:: WettingSimulation()
:members:
:no-index:
:show-inheritance:
18 changes: 15 additions & 3 deletions flowermd/base/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Molecule:
Number of molecules to generate.
force_field : flowermd.ForceField or a list of
`hoomd.md.force.Force` objects, default=None
The force field to be applied to the molecule for parameterization.
The forcefield to be applied to the molecule for parameterization.
Note that setting `force_field` does not actually apply the
forcefield to the molecule. The forcefield in this step is mainly
used for validation purposes.
Expand Down Expand Up @@ -430,8 +430,12 @@ class Polymer(Molecule):
The smiles string of the monomer to generate.
file : str, default None
The file path to the monomer to generate.
force_field : str, default None
The force field to apply to the molecule.
force_field : flowermd.ForceField or a list of
`hoomd.md.force.Force` objects, default=None
The forcefield to be applied to the molecule for parameterization.
Note that setting `force_field` does not actually apply the
forcefield to the molecule. The forcefield in this step is mainly
used for validation purposes.
bond_indices: list, default None
The indices of the atoms to bond.
bond_length: float, default None
Expand Down Expand Up @@ -502,13 +506,21 @@ class CoPolymer(Molecule):
Class of the B-type monomer
length : int, required
The total number of monomers in the molecule
num_mols : int, required
Number of chains to generate.
sequence : str, default None
Manually define the sequence of 'A' and 'B' monomers.
Leave as None if generating random sequences.
Example: sequence = "AABAABAAB"
AB_ratio : float, default 0.50
The relative weight of A to B monomer types.
Used when generating random sequences.
force_field : flowermd.ForceField or a list of
`hoomd.md.force.Force` objects, default=None
The forcefield to be applied to the molecule for parameterization.
Note that setting `force_field` does not actually apply the
forcefield to the molecule. The forcefield in this step is mainly
used for validation purposes.
seed : int, default 24
Set the seed used when generating random sequences
Expand Down
2 changes: 1 addition & 1 deletion flowermd/base/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ def run_update_volume(
Number of steps to run during volume update.
period : int, required
The number of steps ran between each box update iteration.
kT : int or hoomd.variant.Ramp, required
kT : float or hoomd.variant.Ramp, required
The temperature to use during volume update.
tau_kt : float, required
Thermostat coupling period (in simulation time units).
Expand Down
32 changes: 19 additions & 13 deletions flowermd/base/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,21 +586,27 @@ def apply_forcefield(
if scale_charges and not remove_charges:
self._scale_charges()

epsilons = [
s.atom_type.parameters["epsilon"] for s in self.gmso_system.sites
]
sigmas = [
s.atom_type.parameters["sigma"] for s in self.gmso_system.sites
]
masses = [s.mass for s in self.gmso_system.sites]
if not self._reference_values:
epsilons = [
s.atom_type.parameters["epsilon"]
for s in self.gmso_system.sites
]
sigmas = [
s.atom_type.parameters["sigma"] for s in self.gmso_system.sites
]
masses = [s.mass for s in self.gmso_system.sites]

energy_scale = np.max(epsilons) if self.auto_scale else 1.0
length_scale = np.max(sigmas) if self.auto_scale else 1.0
mass_scale = np.max(masses) if self.auto_scale else 1.0
energy_scale = np.max(epsilons) if self.auto_scale else 1.0
length_scale = np.max(sigmas) if self.auto_scale else 1.0
mass_scale = np.max(masses) if self.auto_scale else 1.0

self._reference_values["energy"] = energy_scale * epsilons[0].unit_array
self._reference_values["length"] = length_scale * sigmas[0].unit_array
self._reference_values["mass"] = mass_scale * masses[0].unit_array
self._reference_values["energy"] = (
energy_scale * epsilons[0].unit_array
)
self._reference_values["length"] = (
length_scale * sigmas[0].unit_array
)
self._reference_values["mass"] = mass_scale * masses[0].unit_array

if remove_hydrogens:
self.remove_hydrogens()
Expand Down
69 changes: 62 additions & 7 deletions flowermd/library/surfaces.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Recipes to generate surfaces using mBuild."""

import mbuild as mb
from mbuild.compound import Compound
from mbuild.lattice import Lattice

from flowermd.base import Molecule, System

class Graphene(Compound):

class Graphene(System):
"""Create a rectangular graphene layer or multiple layers.
Parameters
Expand All @@ -15,10 +18,43 @@ class Graphene(Compound):
Number of times to repeat graphene lattice in the y-direciton.
n_layers: int, optional, default 1
Number of times to repeat the complete layer in the normal direction.
force_field: force_field : flowermd.ForceField
The force field to be applied to the surface for paramaterizaiton.
Note that setting `force_field` does not actually apply the forcefield
to the molecule. The forcefield in this step is mainly used for
validation purposes.
reference_values : dict, required
A dictionary of reference values for the surface. The keys of the
dictionary are "length", "energy", and "mass". The values of the
dictionary are unyt quantities.
r_cut : float, required
The cutoff radius for the Lennard-Jones interactions.
periodicity : tuple of bools, length=3, optional, default=(True, True, False) # noqa: E501
Whether the Compound is periodic in the x, y, and z directions.
If None is provided, the periodicity is set to `(False, False, False)`
which is non-periodic in all directions.
auto_scale : bool, default=False
Set to true to use reduced simulation units.
distance, mass, and energy are scaled by the largest value
present in the system for each.
scale_charges : bool, default False
Set to true to scale charges to net zero.
remove_charges : bool, default False
Set to true to remove charges from the system.
remove_hydrogens : bool, default False
Set to true to remove hydrogen atoms from the system.
The masses and charges of the hydrogens are absorbed into
the heavy atoms they were bonded to.
pppm_resolution : tuple, default=(8, 8, 8)
The resolution used in
`hoomd.md.long_range.pppm.make_pppm_coulomb_force` representing
number of grid points in the x, y, and z directions.
ppmp_order : int, default=4
The order used in
`hoomd.md.long_range.pppm.make_pppm_coulomb_force` representing
number of grid points in each direction to assign charges to.
nlist_buffer : float, default=0.4
Neighborlist buffer for simulation cell.
Notes
-----
Expand All @@ -28,19 +64,38 @@ class Graphene(Compound):
"""

def __init__(
self, x_repeat, y_repeat, n_layers, periodicity=(True, True, False)
self,
x_repeat,
y_repeat,
n_layers,
base_units=dict(),
periodicity=(True, True, False),
):
super(Graphene, self).__init__(periodicity=periodicity)
surface = mb.Compound(periodicity=periodicity)
spacings = [0.425, 0.246, 0.35]
points = [[1 / 6, 0, 0], [1 / 2, 0, 0], [0, 0.5, 0], [2 / 3, 1 / 2, 0]]
points = [
[1 / 6, 0, 0],
[1 / 2, 0, 0],
[0, 1 / 2, 0],
[2 / 3, 1 / 2, 0],
]
lattice = Lattice(
lattice_spacing=spacings,
angles=[90, 90, 90],
lattice_points={"A": points},
)
carbon = Compound(name="C")
carbon = Compound(name="C", element="C")
layers = lattice.populate(
compound_dict={"A": carbon}, x=x_repeat, y=y_repeat, z=n_layers
)
self.add(layers)
self.freud_generate_bonds("C", "C", dmin=0.14, dmax=0.145)
surface.add(layers)
surface.freud_generate_bonds("C", "C", dmin=0.14, dmax=0.145)
surface_mol = Molecule(num_mols=1, compound=surface)
super(Graphene, self).__init__(
molecules=[surface_mol],
density=1.0,
base_units=base_units,
)

def _build_system(self):
return self.all_molecules[0]
6 changes: 6 additions & 0 deletions flowermd/modules/surface_wetting/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Surface wetting module for FlowerMD."""
from .surface_wetting import (
DropletSimulation,
InterfaceBuilder,
WettingSimulation,
)
Loading

0 comments on commit 6e2c173

Please sign in to comment.