Skip to content

Commit f04b5c2

Browse files
authored
Fix TS multiplicity from YAML input (#882)
## Issue A TS species defined in input.yml with only is_ts: true and xyz (no smiles/adjlist) could be assigned the wrong multiplicity, causing Gaussian to reject the input with GL301. For example, a closed-shell TS with 24 electrons was written as 0 2 (mult=2), which is electronically impossible. ## Root cause ARCSpecies.from_dict (the path taken when main.py loads species from YAML via ARCSpecies(species_dict=spc)) called mol_from_xyz to perceive a 2D graph from the TS geometry, then blindly assigned self.multiplicity = self.mol.multiplicity. RMG's perception of TS-like geometries (partial bonds, near-radical atoms) routinely returns spurious biradical structures — for the failing case it returned O=[C][H][OH] with mult=2. Direct construction (ARCSpecies(label=..., is_ts=True, xyz=...)) was unaffected because __init__ routes through determine_multiplicity, which skips the descriptor path for TSs and uses electron parity from xyz. ## Fix In from_dict, when is_ts=True and xyz is available, fall back to determine_multiplicity_from_xyz (electron-parity) instead of trusting the perceived mol.multiplicity. Non-TS behavior is unchanged; TSs without xyz still fall through to mol.multiplicity since there's no parity signal. ## Test Added a dict-construction assertion to test_determine_multiplicity for the failing TS xyz — this is the path the bug actually went through. The pre-existing direct-construction assertion was insufficient because it bypassed from_dict entirely.
2 parents 5f2138a + 55edf36 commit f04b5c2

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

arc/species/species.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,12 @@ def from_dict(self, species_dict):
932932
if self.bond_corrections:
933933
self.long_thermo_description += f'Bond corrections: {self.bond_corrections}\n'
934934
if self.multiplicity is None:
935-
self.multiplicity = self.mol.multiplicity
935+
if self.is_ts and self.get_xyz(generate=False):
936+
self.determine_multiplicity_from_xyz()
937+
logger.debug(f'TS species {self.label}: using xyz-based multiplicity '
938+
f'{self.multiplicity} (ignored mol.multiplicity)')
939+
else:
940+
self.multiplicity = self.mol.multiplicity
936941
if self.charge is None:
937942
self.charge = self.mol.get_net_charge()
938943
if 'conformers' in species_dict:

arc/species/species_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,6 +2188,29 @@ def test_determine_multiplicity(self):
21882188
ch_ts = ARCSpecies(label='C--H-TS', xyz='C 0 0 0\nH 1 2 5', is_ts=True)
21892189
self.assertEqual(ch_ts.multiplicity, 2)
21902190

2191+
ts_1_xyz = """H -2.99394700 1.00970200 0.09451400
2192+
O -4.10192200 0.13578500 -0.05953100
2193+
H -4.43761000 -0.35213100 0.70859500
2194+
C -2.22272000 0.16048700 -0.01004900
2195+
O -1.59892700 -0.79618100 0.08758500"""
2196+
ts_1_spc = ARCSpecies(label='TS1', is_ts=True, xyz=ts_1_xyz)
2197+
self.assertEqual(ts_1_spc.multiplicity, 1)
2198+
2199+
ts_1_spc_from_dict = ARCSpecies(species_dict={'label': 'TS1', 'is_ts': True, 'xyz': ts_1_xyz})
2200+
self.assertEqual(ts_1_spc_from_dict.multiplicity, 1)
2201+
2202+
# Test a known doublet TS from a Gaussian output file (NH3 + H = NH2 + H2).
2203+
# Verify that xyz-based electron counting (11 electrons → mult 2) wins over mol.multiplicity.
2204+
ts_doublet_path = os.path.join(ARC_TESTING_PATH, 'freq', 'TS_NH3+H=NH2+H2.out')
2205+
ts_doublet = ARCSpecies(label='TS_NH3+H', is_ts=True, xyz=ts_doublet_path)
2206+
self.assertIsNotNone(ts_doublet.mol)
2207+
self.assertEqual(ts_doublet.multiplicity, 2)
2208+
# Simulate a mol that incorrectly perceives multiplicity as 1, and verify xyz detection still gives 2.
2209+
ts_doublet.multiplicity = None
2210+
ts_doublet.mol.multiplicity = 1
2211+
ts_doublet.determine_multiplicity_from_xyz()
2212+
self.assertEqual(ts_doublet.multiplicity, 2)
2213+
21912214
def test_cluster_tsgs(self):
21922215
"""Test the cluster_tsgs() method."""
21932216
xyz_1 = """N 0.9177905887 0.5194617797 0.0000000000

0 commit comments

Comments
 (0)