|
36 | 36 | setup_dummy_interactions_from_ff,
|
37 | 37 | )
|
38 | 38 | from timemachine.fe.system import minimize_scipy, simulate_system
|
| 39 | +from timemachine.fe.topology import BaseTopology |
39 | 40 | from timemachine.fe.utils import get_mol_name, get_romol_conf, read_sdf, read_sdf_mols_by_name, set_mol_name
|
40 | 41 | from timemachine.ff import Forcefield
|
41 | 42 | from timemachine.md import minimizer
|
@@ -1743,3 +1744,48 @@ def test_hif2a_end_state_symmetry_nightly_test():
|
1743 | 1744 | print("testing", mol_a.GetProp("_Name"), "->", mol_b.GetProp("_Name"))
|
1744 | 1745 | core = atom_mapping.get_cores(mol_a, mol_b, **DEFAULT_ATOM_MAPPING_KWARGS)[0]
|
1745 | 1746 | assert_symmetric_interpolation(mol_a, mol_b, core)
|
| 1747 | + |
| 1748 | + |
| 1749 | +def test_empty_core(): |
| 1750 | + # test that an empty core results in an end-state with identical energies and forces to independent molecules |
| 1751 | + with path_to_internal_file("timemachine.testsystems.data", "ligands_40.sdf") as path_to_ligand: |
| 1752 | + mols = read_sdf(path_to_ligand) |
| 1753 | + |
| 1754 | + mol_a = mols[0] |
| 1755 | + mol_b = mols[1] |
| 1756 | + |
| 1757 | + x_a = get_romol_conf(mol_a) |
| 1758 | + x_b = get_romol_conf(mol_b) |
| 1759 | + core = np.zeros((0, 2)) |
| 1760 | + |
| 1761 | + ff = Forcefield.load_default() |
| 1762 | + st = SingleTopology(mol_a, mol_b, core, ff) |
| 1763 | + lhs = st.setup_intermediate_state(0.0) |
| 1764 | + rhs = st.setup_intermediate_state(1.0) |
| 1765 | + |
| 1766 | + x_0 = st.combine_confs(x_a, x_b, 0.0) |
| 1767 | + x_1 = st.combine_confs(x_a, x_b, 1.0) |
| 1768 | + |
| 1769 | + np.testing.assert_array_equal(x_0, x_1) |
| 1770 | + |
| 1771 | + # lhs and rhs do not have identical total energies since dummy molecule is in a softened state |
| 1772 | + lhs_U_fn = lhs.get_U_fn() |
| 1773 | + rhs_U_fn = rhs.get_U_fn() |
| 1774 | + |
| 1775 | + assert lhs_U_fn(x_0) != rhs_U_fn(x_0) |
| 1776 | + |
| 1777 | + # however, the bond, angle, improper energies should be bitwise identical |
| 1778 | + assert lhs.bond(x_0, None) == rhs.bond(x_0, None) |
| 1779 | + assert lhs.angle(x_0, None) == rhs.angle(x_0, None) |
| 1780 | + assert lhs.improper(x_0, None) == rhs.improper(x_0, None) |
| 1781 | + |
| 1782 | + # we should also be consistent with vanilla base topologies |
| 1783 | + bt_a = BaseTopology(mol_a, ff) |
| 1784 | + bt_b = BaseTopology(mol_b, ff) |
| 1785 | + |
| 1786 | + ref_a = bt_a.setup_end_state() |
| 1787 | + ref_b = bt_b.setup_end_state() |
| 1788 | + |
| 1789 | + np.testing.assert_almost_equal(lhs.bond(x_0, None), ref_a.bond(x_a, None) + ref_b.bond(x_b, None)) |
| 1790 | + np.testing.assert_almost_equal(lhs.angle(x_0, None), ref_a.angle(x_a, None) + ref_b.angle(x_b, None)) |
| 1791 | + np.testing.assert_almost_equal(lhs.improper(x_0, None), ref_a.improper(x_a, None) + ref_b.improper(x_b, None)) |
0 commit comments