Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 54 additions & 0 deletions gmso/core/forcefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,33 @@ def _get_bond_type(self, atom_types, return_match_order=False, warn=False):
if reverse in self.bond_types:
match = self.bond_types[reverse], (1, 0)

if match:
if return_match_order:
return match
else:
return match[0]

for i in range(1, 3):
forward_patterns = mask_with(atom_types, i)
reverse_patterns = mask_with(reversed(atom_types), i)

for forward_pattern, reverse_pattern in zip(
forward_patterns, reverse_patterns
):
forward_match_key = FF_TOKENS_SEPARATOR.join(forward_pattern)
reverse_match_key = FF_TOKENS_SEPARATOR.join(reverse_pattern)

if forward_match_key in self.bond_types:
match = self.bond_types[forward_match_key], (0, 1)
break

if reverse_match_key in self.bond_types:
match = self.bond_types[reverse_match_key], (1, 0)
break

if match:
break

msg = (
f"BondType between atoms {atom_types[0]} and {atom_types[1]} "
f"is missing from the ForceField"
Expand Down Expand Up @@ -382,6 +409,33 @@ def _get_angle_type(self, atom_types, return_match_order=False, warn=False):
if reverse in self.angle_types:
match = self.angle_types[reverse], (2, 1, 0)

if match:
if return_match_order:
return match
else:
return match[0]

for i in range(1, 4):
forward_patterns = mask_with(atom_types, i)
reverse_patterns = mask_with(reversed(atom_types), i)

for forward_pattern, reverse_pattern in zip(
forward_patterns, reverse_patterns
):
forward_match_key = FF_TOKENS_SEPARATOR.join(forward_pattern)
reverse_match_key = FF_TOKENS_SEPARATOR.join(reverse_pattern)

if forward_match_key in self.angle_types:
match = self.angle_types[forward_match_key], (0, 1, 2)
break

if reverse_match_key in self.angle_types:
match = self.angle_types[reverse_match_key], (2, 1, 0)
break

if match:
break

msg = (
f"AngleType between atoms {atom_types[0]}, {atom_types[1]} "
f"and {atom_types[2]} is missing from the ForceField"
Expand Down
54 changes: 19 additions & 35 deletions gmso/tests/files/alkanes_wildcards.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,32 @@
<BondTypes expression="0.5*k*(r - r_eq)**2">
<ParametersUnitDef parameter="k" unit="kJ/(mol*nm**2)"/>
<ParametersUnitDef parameter="r_eq" unit="nm"/>
<BondType name="BondType-Harmonic-1" type1="CT" type2="HC">
<BondType name="BondType-Harmonic-wildcard" type1="*" type2="*">
<Parameters>
<Parameter name="k" value="284512.0"/>
<Parameter name="r_eq" value="0.109"/>
<Parameter name="k" value="1"/>
<Parameter name="r_eq" value="1"/>
</Parameters>
</BondType>
<BondType name="BondType-Harmonic-2" type1="CT" type2="CT">
<BondType name="BondType-Harmonic-135" type1="*" type2="opls_135">
<Parameters>
<Parameter name="k" value="224262.4"/>
<Parameter name="r_eq" value="0.1529"/>
<Parameter name="k" value="2"/>
<Parameter name="r_eq" value="1"/>
</Parameters>
</BondType>
</BondTypes>
<AngleTypes expression="0.5*k*(theta - theta_eq)**2">
<ParametersUnitDef parameter="k" unit="kJ/(mol*rad**2)"/>
<ParametersUnitDef parameter="theta_eq" unit="rad"/>
<AngleType name="AngleType-Harmonic-1" type1="HC" type2="CT" type3="HC">
<AngleType name="AngleType-Harmonic-wildcard" type1="*" type2="*" type3="*">
<Parameters>
<Parameter name="k" value="276.144"/>
<Parameter name="theta_eq" value="1.88146493365"/>
<Parameter name="k" value="1"/>
<Parameter name="theta_eq" value="1"/>
</Parameters>
</AngleType>
<AngleType name="AngleType-Harmonic-2" type1="CT" type2="CT" type3="HC">
<AngleType name="AngleType-Harmonic-opls_135" type1="*" type2="*" type3="opls_135">
<Parameters>
<Parameter name="k" value="313.8"/>
<Parameter name="theta_eq" value="1.93207948196"/>
</Parameters>
</AngleType>
<AngleType name="AngleType-Harmonic-3" type1="CT" type2="CT" type3="CT">
<Parameters>
<Parameter name="k" value="488.273"/>
<Parameter name="theta_eq" value="1.966986067"/>
<Parameter name="k" value="1"/>
<Parameter name="theta_eq" value="1"/>
</Parameters>
</AngleType>
</AngleTypes>
Expand All @@ -88,24 +82,14 @@
<ParametersUnitDef parameter="c3" unit="kJ/mol"/>
<ParametersUnitDef parameter="c4" unit="kJ/mol"/>
<ParametersUnitDef parameter="c5" unit="kJ/mol"/>
<DihedralType name="RyckaertBellemansTorsionPotential-1" type1="HC" type2="CT" type3="CT" type4="">
<Parameters>
<Parameter name="c0" value="0.6276"/>
<Parameter name="c1" value="1.8828"/>
<Parameter name="c2" value="0.0"/>
<Parameter name="c3" value="-2.5104"/>
<Parameter name="c4" value="0.0"/>
<Parameter name="c5" value="0.0"/>
</Parameters>
</DihedralType>
<DihedralType name="RyckaertBellemansTorsionPotential-3" type1="CT" type2="CT" type3="CT" type4="CT">
<DihedralType name="RyckaertBellemansTorsionPotential-1" type1="*" type2="*" type3="*" type4="">
<Parameters>
<Parameter name="c0" value="2.9288"/>
<Parameter name="c1" value="-1.4644"/>
<Parameter name="c2" value="0.2092"/>
<Parameter name="c3" value="-1.6736"/>
<Parameter name="c4" value="0.0"/>
<Parameter name="c5" value="0.0"/>
<Parameter name="c0" value="1"/>
<Parameter name="c1" value="1"/>
<Parameter name="c2" value="1"/>
<Parameter name="c3" value="1"/>
<Parameter name="c4" value="1"/>
<Parameter name="c5" value="0"/>
</Parameters>
</DihedralType>
</DihedralTypes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import parmed as pmd
import pytest

from gmso import ForceField
from gmso.external.convert_parmed import from_parmed
from gmso.parameterization.parameterize import apply
from gmso.tests.parameterization.parameterization_base_test import (
ParameterizationBaseTest,
)
from gmso.tests.utils import get_path


def get_foyer_opls_test_dirs():
Expand Down Expand Up @@ -56,3 +58,25 @@ def test_foyer_oplsaa_files(
assert_same_connection_params(gmso_top, gmso_top_from_pmd)
assert_same_connection_params(gmso_top, gmso_top_from_pmd, "angles")
assert_same_connection_params(gmso_top, gmso_top_from_pmd, "dihedrals")


class TestGeneralParameterizations(ParameterizationBaseTest):
def test_wildcards(self, ethane_methane_top):
from gmso.core.views import PotentialFilters

ff = ForceField(get_path("alkanes_wildcards.xml"))
ptop = apply(ethane_methane_top, ff, identify_connections=True)
assert ptop.is_fully_typed()
assert len(ptop.bond_types) == 11
assert len(ptop.bond_types(PotentialFilters.UNIQUE_NAME_CLASS)) == 2
assert ptop.bonds[0].bond_type.member_types == ("*", "opls_135") # ethane
assert ptop.bonds[8].bond_type.member_types == ("*", "*") # methane

assert len(ptop.angle_types) == 12 + 6 # ethane + methane
assert len(ptop.angle_types(PotentialFilters.UNIQUE_NAME_CLASS)) == 2
assert ptop.angles[0].angle_type.member_types == ("*", "*", "*")
assert ptop.angles[2].angle_type.member_types == ("*", "*", "opls_135")

assert len(ptop.dihedral_types) == 9
assert len(ptop.dihedral_types(PotentialFilters.UNIQUE_NAME_CLASS)) == 1
assert ptop.dihedrals[0].dihedral_type.member_types == ("*", "*", "*", "*")