Skip to content

Commit

Permalink
Merge pull request #282 from marrink-lab/fix/top-dih
Browse files Browse the repository at this point in the history
Fix/top dih
  • Loading branch information
fgrunewald authored Nov 4, 2022
2 parents 15515e4 + 0b042ce commit 56b0b40
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 15 deletions.
2 changes: 1 addition & 1 deletion polyply/src/top_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def _type_params(self, line, lineno=0):
atoms, params = self._split_atoms_and_parameters(line.split(),
self.atom_idxs[section_name])

self.topology.types[inter_type][tuple(atoms)] = (params, self.current_meta)
self.topology.types[inter_type][tuple(atoms)].append((params, self.current_meta))


@SectionLineParser.section_parser('implicit_genborn_params')
Expand Down
69 changes: 56 additions & 13 deletions polyply/src/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from vermouth.forcefield import ForceField
from vermouth.gmx.gro import read_gro
from vermouth.pdb import read_pdb
from vermouth.molecule import Interaction
from .top_parser import read_topology
from .linalg_functions import center_of_geometry

Expand Down Expand Up @@ -221,7 +222,7 @@ def __init__(self, force_field, name=None):
self.defines = {}
self.description = []
self.atom_types = {}
self.types = defaultdict(dict)
self.types = defaultdict(lambda: defaultdict(list))
self.nonbond_params = {}
self.mol_idx_by_name = defaultdict(list)
self.persistences = []
Expand Down Expand Up @@ -288,19 +289,38 @@ def gen_pairs(self):

def gen_bonded_interactions(self):
"""
Check for each interaction if there is
no parameter for an interaction if that
parameter is defined in the bonded directive
of the topology.
Check for each interaction, if the parameter list is empty. If it is
check if the parameters are defined in the bonded types directive
of the topology. This essentially does part of the step done by
grompp.
Updates
-------
self.molecules.interactions
self.blocks.interactions
Raises
------
OSError
no match for an interaction in the bonded types provided
"""
for block in self.force_field.blocks.values():
# We loop over blocks not molecules, because there is only
# one unique block per molecule, whereas there cab be a large number of
# duplicate molecules in the topology.molecules list. As the interactions
# in those molecules are still references to the blocks updating them here
# will propagate into the molecules. This works except for one case where
# a single dihedral directive is expanded into multiple ones. Updating the
# block dict will not propagate into the molecules.
for mol_name, block in self.force_field.blocks.items():
additional_interactions = defaultdict(list)
for inter_type, interactions in block.interactions.items():
# these interactions have no types associated
if inter_type in ["pairs", "exclusions", "virtual_sitesn",
"virtual_sites2", "virtual_sites3", "virtual_sites4"]:
continue

for interaction in interactions:
if len(interaction.parameters) == 1:

# Some force-fields - in GMX library only OPLS - use bond-type
# definitions. Each atomtype matches one bond-type, which
# in turn matches an expression in the bondedtypes section
Expand All @@ -312,14 +332,17 @@ def gen_bonded_interactions(self):
else:
atoms = tuple(block.nodes[node]["atype"] for node in interaction.atoms)

# now we match the atom or bondtypes to the types defined in the topology
if atoms in self.types[inter_type]:
new_params, meta = self.types[inter_type][atoms]
new_params = self.types[inter_type][atoms]
elif atoms[::-1] in self.types[inter_type]:
new_params, meta = self.types[inter_type][atoms[::-1]]
new_params = self.types[inter_type][atoms[::-1]]
# dihedrals are more complicated because they are treated as symmetric and
# can have wild-cards
elif inter_type in "dihedrals":
match = match_dihedral_interaction_types(atoms, self.types[inter_type])
if match:
new_params, meta = self.types[inter_type][match]
new_params = self.types[inter_type][match]
else:
msg = ("In section dihedrals interaction of atoms {} has no "
"corresponding bonded type.")
Expand All @@ -332,9 +355,29 @@ def gen_bonded_interactions(self):
atoms = " ".join(list(map(lambda x: str(x), interaction.atoms)))
raise OSError(msg.format(inter_type, atoms))

interaction.parameters[:] = new_params[:]
if meta:
interaction.meta.update(meta)
for idx, (new_param, meta) in enumerate(new_params):
if not meta:
meta = {}
# there is always at least one interaction in molecule, which
# needs to get the typed parameters
if idx == 0:
interaction.parameters[:] = new_param[:]
interaction.meta.update(meta)
# however, sometimes a single interaction term needs to be
# expanded (i.e. a single statment spwans multiple interactions)
# In that case we update the parameters of the first term and
# need to add the other interactions additionally
else:
new_interaction = Interaction(atoms=tuple(interaction.atoms),
parameters=new_param,
meta=meta)
additional_interactions[inter_type].append(new_interaction)


# here we add the expanded interactions into the molecules
for mol_idx in self.mol_idx_by_name[mol_name]:
for inter_type, new_inters in additional_interactions.items():
self.molecules[mol_idx].molecule.interactions[inter_type] += new_inters

def convert_nonbond_to_sig_eps(self):
"""
Expand Down
14 changes: 13 additions & 1 deletion polyply/tests/test_top_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,20 @@ class TestTopParsing:
OM O 1 1.9670816e-03 8.5679450e-07
""",
"types",
{"bonds": {("OM", "O"): (["1", "1.9670816e-03", "8.5679450e-07"], None)}}
{"bonds": {("OM", "O"): [(["1", "1.9670816e-03", "8.5679450e-07"], None)]}}
),
("""
[ dihedraltypes ]
CEL1 CEL1 CTL2 CTL2 9 1.800000e+02 3.807440e+00 1
CEL1 CEL1 CTL2 CTL2 9 1.800000e+02 7.531200e-01 2
CEL1 CEL1 CTL2 CTL2 9 1.800000e+02 7.112800e-01 3
""",
"types",
{"dihedrals": {("CEL1", "CEL1", "CTL2", "CTL2"): [(["9", "1.800000e+02", "3.807440e+00", "1"], None),
(["9", "1.800000e+02", "7.531200e-01", "2"], None),
(["9", "1.800000e+02", "7.112800e-01", "3"], None)]}}
),
("""
[ system ]
some multiline
Expand Down
43 changes: 43 additions & 0 deletions polyply/tests/test_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,49 @@ def test_convert_nonbond_to_sig_eps():
"virtual_sites2": [Interaction(atoms=(3, 0, 8), parameters=["1", "0.5000"], meta={})],
"virtual_sites3": [Interaction(atoms=(4, 3, 7, 0), parameters=["1", "0.200", "0.200"], meta={}),
Interaction(atoms=(5, 3, 8, 1), parameters=["1", "0.200", "0.200"], meta={})]}
),
# test multiple dihedrals are assigned
(
"""
[ defaults ]
1.0 1.0 yes 2.0 1.0
[ atomtypes ]
CTL2 6 12.0110 -0.100 A 3.58141284692e-01 2.343040e-01
CEL1 6 12.0110 -0.150 A 3.72395664183e-01 2.845120e-01
[ bondtypes ]
CEL1 CEL1 1 1.340000e-01 3.681920e+05
CEL1 CTL2 1 1.502000e-01 3.054320e+05
CTL2 CTL2 1 1.538000e-01 1.861880e+05
[ dihedraltypes ]
CEL1 CEL1 CTL2 CTL2 9 1.800000e+02 3.807440e+00 1
CEL1 CEL1 CTL2 CTL2 9 1.800000e+02 7.531200e-01 2
CEL1 CEL1 CTL2 CTL2 9 1.800000e+02 7.112800e-01 3
[ moleculetype ]
test 3
[ atoms ]
; CEL1 CEL1 CTL2 CTL2
1 CEL1 1 POPC C12 2 0.000000 12.0110 ; qtot -0.700
2 CEL1 1 POPC C12 2 0.000000 12.0110 ; qtot -0.700
3 CTL2 1 POPC C12 2 0.000000 12.0110 ; qtot -0.700
4 CTL2 1 POPC C12 2 0.000000 12.0110 ; qtot -0.700
[ bonds ]
1 2 1
2 3 1
3 4 1
[ dihedrals ]
1 2 3 4 9
[ system ]
some title
[ molecules ]
test 1
""",
{"bonds": [Interaction(atoms=(0, 1), parameters=["1", "1.340000e-01", "3.681920e+05"], meta={}),
Interaction(atoms=(1, 2), parameters=["1", "1.502000e-01", "3.054320e+05"], meta={}),
Interaction(atoms=(2, 3), parameters=["1", "1.538000e-01", "1.861880e+05"], meta={}),],
"dihedrals": [Interaction(atoms=(0, 1, 2, 3), parameters=["9", "1.800000e+02", "3.807440e+00", "1"], meta={}),
Interaction(atoms=(0, 1, 2, 3), parameters=["9", "1.800000e+02", "7.531200e-01", "2"], meta={}),
Interaction(atoms=(0, 1, 2, 3), parameters=["9", "1.800000e+02", "7.112800e-01", "3"], meta={}),]}
)
))
def test_replace_types(lines, outcome):
Expand Down

0 comments on commit 56b0b40

Please sign in to comment.