|
156 | 156 | xml_toolkitam1bcc_ff = ''' |
157 | 157 | <SMIRNOFF version="0.3" aromaticity_model="OEAroModel_MDL"> |
158 | 158 | <ToolkitAM1BCC version="0.3"/> |
159 | | -</SMIRNOFF>''' |
| 159 | +</SMIRNOFF> |
| 160 | +''' |
160 | 161 |
|
| 162 | +xml_tip3p_library_charges_ff = ''' |
| 163 | +<SMIRNOFF version="0.3" aromaticity_model="OEAroModel_MDL"> |
| 164 | + <LibraryCharges version="0.3"> |
| 165 | + <!-- TIP3P water oxygen with charge override --> |
| 166 | + <LibraryCharge name="TIP3P" smirks="[#1:1]-[#8X2H2+0:2]-[#1:3]" charge1="+0.417*elementary_charge" charge2="-0.834*elementary_charge" charge3="+0.417*elementary_charge"/> |
| 167 | + </LibraryCharges> |
| 168 | +</SMIRNOFF> |
| 169 | +''' |
161 | 170 | #====================================================================== |
162 | 171 | # TEST UTILITY FUNCTIONS |
163 | 172 | #====================================================================== |
@@ -806,6 +815,70 @@ def test_parameterize_ethanol_to_parmed(self): |
806 | 815 |
|
807 | 816 | parmed_system = forcefield.create_parmed_structure(topology, positions=pdbfile.getPositions()) |
808 | 817 |
|
| 818 | + |
| 819 | + |
| 820 | + |
| 821 | + @pytest.mark.parametrize("toolkit_registry,registry_description", toolkit_registries) |
| 822 | + def test_pass_invalid_kwarg_to_create_openmm_system(self, toolkit_registry, registry_description): |
| 823 | + """Test to ensure an exception is raised when an unrecognized kwarg is passed """ |
| 824 | + from simtk.openmm import app |
| 825 | + |
| 826 | + file_path = get_data_file_path('test_forcefields/smirnoff99Frosst.offxml') |
| 827 | + forcefield = ForceField(file_path) |
| 828 | + pdbfile = app.PDBFile(get_data_file_path('systems/test_systems/1_ethanol.pdb')) |
| 829 | + molecules = [] |
| 830 | + molecules.append(Molecule.from_smiles('CCO')) |
| 831 | + topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules) |
| 832 | + |
| 833 | + with pytest.raises(ValueError, match=".* not used by any registered force Handler: {'invalid_kwarg'}.*") as e: |
| 834 | + omm_system = forcefield.create_openmm_system(topology, invalid_kwarg='aaa', toolkit_registry=toolkit_registry) |
| 835 | + |
| 836 | + |
| 837 | + @pytest.mark.parametrize("inputs", nonbonded_resolution_matrix) |
| 838 | + def test_nonbonded_method_resolution(self, |
| 839 | + inputs |
| 840 | + ): |
| 841 | + """Test predefined permutations of input options to ensure nonbonded handling is correctly resolved""" |
| 842 | + from simtk.openmm import app |
| 843 | + |
| 844 | + vdw_method = inputs['vdw_method'] |
| 845 | + electrostatics_method = inputs['electrostatics_method'] |
| 846 | + has_periodic_box = inputs['has_periodic_box'] |
| 847 | + omm_force = inputs['omm_force'] |
| 848 | + exception = inputs['exception'] |
| 849 | + exception_match= inputs['exception_match'] |
| 850 | + |
| 851 | + molecules = [create_ethanol()] |
| 852 | + forcefield = ForceField('test_forcefields/smirnoff99Frosst.offxml') |
| 853 | + |
| 854 | + pdbfile = app.PDBFile(get_data_file_path('systems/test_systems/1_ethanol.pdb')) |
| 855 | + topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules) |
| 856 | + |
| 857 | + if not(has_periodic_box): |
| 858 | + topology.box_vectors = None |
| 859 | + |
| 860 | + if exception is None: |
| 861 | + # The method is validated and may raise an exception if it's not supported. |
| 862 | + forcefield.get_parameter_handler('vdW', {}).method = vdw_method |
| 863 | + forcefield.get_parameter_handler('Electrostatics', {}).method = electrostatics_method |
| 864 | + omm_system = forcefield.create_openmm_system(topology) |
| 865 | + nonbond_method_matched = False |
| 866 | + for f_idx in range(omm_system.getNumForces()): |
| 867 | + force = omm_system.getForce(f_idx) |
| 868 | + if isinstance(force, openmm.NonbondedForce): |
| 869 | + if force.getNonbondedMethod() == omm_force: |
| 870 | + nonbond_method_matched = True |
| 871 | + assert nonbond_method_matched |
| 872 | + else: |
| 873 | + with pytest.raises(exception, match=exception_match) as excinfo: |
| 874 | + # The method is validated and may raise an exception if it's not supported. |
| 875 | + forcefield.get_parameter_handler('vdW', {}).method = vdw_method |
| 876 | + forcefield.get_parameter_handler('Electrostatics', {}).method = electrostatics_method |
| 877 | + omm_system = forcefield.create_openmm_system(topology) |
| 878 | + |
| 879 | + |
| 880 | + |
| 881 | +class TestForceFieldChargeAssignment: |
809 | 882 | @pytest.mark.parametrize("toolkit_registry,registry_description", toolkit_registries) |
810 | 883 | def test_charges_from_molecule(self, toolkit_registry, registry_description): |
811 | 884 | """Test skipping charge generation and instead getting charges from the original Molecule""" |
@@ -878,65 +951,49 @@ def test_some_charges_from_molecule(self, toolkit_registry, registry_description |
878 | 951 | q, sigma, epsilon = nonbondedForce.getParticleParameters(particle_index) |
879 | 952 | assert q != (0. * unit.elementary_charge) |
880 | 953 |
|
| 954 | + def test_library_charges_to_single_water(self): |
| 955 | + """Test assigning charges to one water molecule using library charges""" |
| 956 | + from simtk.openmm import NonbondedForce |
881 | 957 |
|
| 958 | + ff = ForceField(simple_xml_ff, xml_tip3p_library_charges_ff) |
| 959 | + mol = Molecule.from_smiles('O') |
| 960 | + omm_system = ff.create_openmm_system(mol.to_topology()) |
| 961 | + nonbondedForce = [f for f in omm_system.getForces() if type(f) == NonbondedForce][0] |
| 962 | + expected_charges = [-0.834, 0.417, 0.417] * unit.elementary_charge |
| 963 | + for particle_index, expected_charge in expected_charges: |
| 964 | + q, sigma, epsilon = nonbondedForce.getParticleParameters(particle_index) |
| 965 | + assert q == expected_charge |
882 | 966 |
|
883 | | - @pytest.mark.parametrize("toolkit_registry,registry_description", toolkit_registries) |
884 | | - def test_pass_invalid_kwarg_to_create_openmm_system(self, toolkit_registry, registry_description): |
885 | | - """Test to ensure an exception is raised when an unrecognized kwarg is passed """ |
886 | | - from simtk.openmm import app |
| 967 | + def test_library_charges_to_two_waters(self): |
| 968 | + """Test assigning charges to two water molecules using library charges""" |
| 969 | + pass |
887 | 970 |
|
888 | | - file_path = get_data_file_path('test_forcefields/smirnoff99Frosst.offxml') |
889 | | - forcefield = ForceField(file_path) |
890 | | - pdbfile = app.PDBFile(get_data_file_path('systems/test_systems/1_ethanol.pdb')) |
891 | | - molecules = [] |
892 | | - molecules.append(Molecule.from_smiles('CCO')) |
893 | | - topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules) |
| 971 | + def test_library_charges_to_two_ethanols_different_atom_ordering(self): |
| 972 | + """Test assigning charges to two ethanols with different atom orderings""" |
| 973 | + pass |
894 | 974 |
|
895 | | - with pytest.raises(ValueError, match=".* not used by any registered force Handler: {'invalid_kwarg'}.*") as e: |
896 | | - omm_system = forcefield.create_openmm_system(topology, invalid_kwarg='aaa', toolkit_registry=toolkit_registry) |
| 975 | + def test_library_charges_to_only_some_molecules(self): |
| 976 | + """Test assigning charges to a topology in which some molecules are covered by library charges |
| 977 | + but other aren't""" |
| 978 | + pass |
897 | 979 |
|
| 980 | + def test_assign_charges_to_molecule_in_parts_using_multiple_library_charges(self): |
| 981 | + """Test assigning charges to parts of a molecule using two library charge lines""" |
| 982 | + pass |
898 | 983 |
|
899 | | - @pytest.mark.parametrize("inputs", nonbonded_resolution_matrix) |
900 | | - def test_nonbonded_method_resolution(self, |
901 | | - inputs |
902 | | - ): |
903 | | - """Test predefined permutations of input options to ensure nonbonded handling is correctly resolved""" |
904 | | - from simtk.openmm import app |
| 984 | + def test_assign_charges_using_library_charges_by_single_atoms(self): |
| 985 | + """Test assigning charges to parts of a molecule using per-atom library charges""" |
| 986 | + pass |
905 | 987 |
|
906 | | - vdw_method = inputs['vdw_method'] |
907 | | - electrostatics_method = inputs['electrostatics_method'] |
908 | | - has_periodic_box = inputs['has_periodic_box'] |
909 | | - omm_force = inputs['omm_force'] |
910 | | - exception = inputs['exception'] |
911 | | - exception_match= inputs['exception_match'] |
| 988 | + def test_library_charges_dont_parameterize_molecule_because_of_incomplete_coverage(self): |
| 989 | + """Fail to assign charges to a molecule becau\se not all atoms can be assigned""" |
| 990 | + pass |
912 | 991 |
|
913 | | - molecules = [create_ethanol()] |
914 | | - forcefield = ForceField('test_forcefields/smirnoff99Frosst.offxml') |
| 992 | + def library_charges_overridden_by_charge_from_molecules(self): |
| 993 | + """Skip assigning charges to a molecule because it has already had charges assigned |
| 994 | + using charge_from_molecules""" |
| 995 | + pass |
915 | 996 |
|
916 | | - pdbfile = app.PDBFile(get_data_file_path('systems/test_systems/1_ethanol.pdb')) |
917 | | - topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules) |
918 | | - |
919 | | - if not(has_periodic_box): |
920 | | - topology.box_vectors = None |
921 | | - |
922 | | - if exception is None: |
923 | | - # The method is validated and may raise an exception if it's not supported. |
924 | | - forcefield.get_parameter_handler('vdW', {}).method = vdw_method |
925 | | - forcefield.get_parameter_handler('Electrostatics', {}).method = electrostatics_method |
926 | | - omm_system = forcefield.create_openmm_system(topology) |
927 | | - nonbond_method_matched = False |
928 | | - for f_idx in range(omm_system.getNumForces()): |
929 | | - force = omm_system.getForce(f_idx) |
930 | | - if isinstance(force, openmm.NonbondedForce): |
931 | | - if force.getNonbondedMethod() == omm_force: |
932 | | - nonbond_method_matched = True |
933 | | - assert nonbond_method_matched |
934 | | - else: |
935 | | - with pytest.raises(exception, match=exception_match) as excinfo: |
936 | | - # The method is validated and may raise an exception if it's not supported. |
937 | | - forcefield.get_parameter_handler('vdW', {}).method = vdw_method |
938 | | - forcefield.get_parameter_handler('Electrostatics', {}).method = electrostatics_method |
939 | | - omm_system = forcefield.create_openmm_system(topology) |
940 | 997 |
|
941 | 998 | #====================================================================== |
942 | 999 | # TEST CONSTRAINTS |
|
0 commit comments