@@ -857,13 +857,14 @@ def test_ring_opening_and_size_change(ligands, mapping):
857857)
858858def test_ring_breaking_intrascale ():
859859 """
860- Regression test for mergeIntrascale with ring-breaking perturbations.
861-
862- Before the fix, CLJNBPairs pairs that were excluded/1-4 in one end state
863- but fully interacting (1,1) in the other were incorrectly left at the
864- non-(1,1) value in the merged intrascale. For cyclopentane->cyclohexane
865- this produced only 6 changed OpenMM exceptions instead of the correct 18,
866- causing simulation instabilities due to missing non-bonded interactions.
860+ Test that ring-breaking merges produce correct intrascale matrices for a
861+ standard force field (GAFF2) with no non-default per-pair scale factors.
862+
863+ The intrascale matrices are built from per-state connectivity, which
864+ correctly captures bonded distances across the ring-closure bond in the
865+ merged atom space. Since GAFF2 has no non-default per-pair scale factors,
866+ patchIntrascale is a no-op — verified by checking that apply_scale_factors=False
867+ gives the same changed bond and exception counts as the default path.
867868 """
868869 # Parameterise both molecules with GAFF2.
869870 cyclopentane = BSS .Parameters .gaff2 ("C1CCCC1" ).getMolecule ()
@@ -928,6 +929,22 @@ def test_ring_breaking_intrascale():
928929 assert len (omm_rev .changed_bonds ()) == len (ref_bonds )
929930 assert len (omm_rev .changed_exceptions ()) == len (ref_exceptions )
930931
932+ # Verify patchIntrascale is a no-op for GAFF2: skipping it with
933+ # apply_scale_factors=False must give identical results.
934+ merged_nopatch = BSS .Align .merge (
935+ cyclopentane_aligned ,
936+ cyclohexane ,
937+ mapping ,
938+ allow_ring_size_change = True ,
939+ allow_ring_breaking = True ,
940+ apply_scale_factors = False ,
941+ )
942+ omm_nopatch = merged_nopatch ._sire_object .perturbation ().to_openmm (
943+ map = {"coordinates" : "coordinates0" }
944+ )
945+ assert len (omm_nopatch .changed_bonds ()) == len (ref_bonds )
946+ assert len (omm_nopatch .changed_exceptions ()) == len (ref_exceptions )
947+
931948
932949@pytest .mark .skipif (
933950 not has_antechamber or not has_tleap ,
@@ -937,24 +954,20 @@ def test_ring_breaking_intrascale():
937954 not has_openff ,
938955 reason = "Requires OpenFF to be installed." ,
939956)
940- def test_ring_breaking_intrascale_connectivity ():
957+ def test_ring_breaking_intrascale_m338 ():
941958 """
942- Regression test for mergeIntrascale using a real-world ring-breaking
943- perturbation (int1 -> m338).
944-
945- Validates that the merged intrascale matrices produced by mergeIntrascale
946- (which builds CLJNBPairs from per-state connectivity and overrides with
947- per-pair values) exactly match those produced directly from
948- CLJNBPairs(conn0/conn1, sf14). For ring-breaking perturbations the two
949- approaches must agree: discrepancies indicate that bonded distances in the
950- merged topology are not being correctly captured, which causes missing or
951- spurious OpenMM exceptions and simulation instabilities.
959+ Test that ring-breaking merges produce correct intrascale matrices for a
960+ real-world perturbation (int1 -> m338) with a standard force field (OpenFF).
961+
962+ Since OpenFF has no non-default per-pair scale factors, patchIntrascale is
963+ a no-op and the merged intrascale matrices must exactly match those built
964+ directly from CLJNBPairs(conn0/conn1, sf14).
952965 """
953966 from sire .legacy import CAS as _SireCAS
954967 from sire .legacy import MM as _SireMM
955968 from sire .legacy import Mol as _SireMol
956969
957- # Atom mapping: {int1_idx: m338_idx}, read from m338_int1_MCS.txt.
970+ # Atom mapping: {int1_idx: m338_idx}
958971 mapping = {
959972 21 : 0 ,
960973 0 : 1 ,
@@ -1013,11 +1026,11 @@ def test_ring_breaking_intrascale_connectivity():
10131026
10141027 sire_mol = merged ._sire_object
10151028
1016- # Extract the intrascale matrices produced by mergeIntrascale.
10171029 intra0 = sire_mol .property ("intrascale0" )
10181030 intra1 = sire_mol .property ("intrascale1" )
10191031
1020- # Build the reference intrascale matrices from per-state connectivity,
1032+ # Build reference matrices directly from per-state connectivity. For OpenFF
1033+ # these must be identical to the merge output since patchIntrascale is a no-op.
10211034 ff = mol0 ._sire_object .property ("forcefield" )
10221035 sf14 = _SireMM .CLJScaleFactor (
10231036 ff .electrostatic14_scale_factor (), ff .vdw14_scale_factor ()
0 commit comments