From 8b6e5c9b3d76ea5fa2839e3b8a4a5d5ae114a1c0 Mon Sep 17 00:00:00 2001 From: j-wags Date: Mon, 15 Jun 2020 17:49:28 -0700 Subject: [PATCH] added ability to handle 'None' partial charges on OFFMols --- .../generators/template_generators.py | 5 +++- .../tests/test_template_generators.py | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/openmmforcefields/generators/template_generators.py b/openmmforcefields/generators/template_generators.py index 4d1772bc..4253d7a6 100644 --- a/openmmforcefields/generators/template_generators.py +++ b/openmmforcefields/generators/template_generators.py @@ -220,7 +220,10 @@ def _molecule_has_user_charges(self, molecule): import numpy as np from simtk import unit zeros = np.zeros([molecule.n_particles]) - charges_are_zero = np.allclose(molecule.partial_charges / unit.elementary_charge, zeros) + if (molecule.partial_charges is None) or (np.allclose(molecule.partial_charges / unit.elementary_charge, zeros)): + charges_are_zero = True + else: + charges_are_zero = False return not charges_are_zero def _generate_unique_atom_names(self, molecule): diff --git a/openmmforcefields/tests/test_template_generators.py b/openmmforcefields/tests/test_template_generators.py index 9bef23d6..1b91685c 100644 --- a/openmmforcefields/tests/test_template_generators.py +++ b/openmmforcefields/tests/test_template_generators.py @@ -740,6 +740,30 @@ def test_energies(self): # Compare energies again self.compare_energies(molecule, openmm_system, smirnoff_system) + + def test_partial_charges_are_none(self): + """Test parameterizing a small molecule with `partial_charges=None` instead + of zeros (happens frequently in OFFTK>=0.7.0)""" + from openforcefield.topology import Molecule + molecule = Molecule.from_smiles('C=O') + molecule.generate_conformers(n_conformers=1) + molecule._partial_charges = None + # Test all supported SMIRNOFF force fields + for small_molecule_forcefield in SMIRNOFFTemplateGenerator.INSTALLED_FORCEFIELDS: + print(f'Testing energies for {small_molecule_forcefield}...') + # Create a generator that knows about a few molecules + # TODO: Should the generator also load the appropriate force field files into the ForceField object? + generator = SMIRNOFFTemplateGenerator(molecules=[molecule], forcefield=small_molecule_forcefield) + # Create a ForceField + import simtk + openmm_forcefield = simtk.openmm.app.ForceField() + # Register the template generator + openmm_forcefield.registerTemplateGenerator(generator.generator) + # Create OpenMM System using OpenMM app + from simtk.openmm.app import NoCutoff + openmm_system = openmm_forcefield.createSystem(molecule.to_topology().to_openmm(), removeCMMotion=False, onbondedMethod=NoCutoff) + smirnoff_system = generator.get_openmm_system(molecule) + def test_version(self): """Test version""" for forcefield in SMIRNOFFTemplateGenerator.INSTALLED_FORCEFIELDS: