ReactionMechanismGenerator / ReactionMechanismGenerator/ARC
Reaction multiplicity silently resolves to 1 when species are attached after first access
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 51
- Forks
- 25
- Avg merge
- 4d 5h
- Merged PRs (30d)
- 15
Description
Describe the bug
ARCReaction.multiplicity returns 1 for any reaction whose species are attached after the property is first read, and the wrong value is then cached for the life of the object. Attaching the species afterwards does not correct it.
The derivation itself is fine. get_rxn_multiplicity() opens with
reactants, products = self.get_reactants_and_products()
multiplicity = None
ordered_r_mult_list, ordered_p_mult_list = list(), list()
if len(reactants):
if len(reactants) == 1:
return reactants[0].multiplicity
so a unimolecular reaction returns its reactant's multiplicity, which is right. But when reactants is empty the guarded block is skipped and both ordered lists stay empty, and the first test in the loop below is
if all(m == 1 for m in list_1) and multiplicity is None:
multiplicity = 1 # S + S = S or T
all() over an empty list is vacuously true, so the function returns 1 rather than None. Because the caller caches into self._multiplicity and only recomputes when it is None, a doublet reaction is permanently a singlet.
How to reproduce
r = ARCSpecies(label='R', smiles='[CH2]C(C)CC') # multiplicity 2
p = ARCSpecies(label='P', smiles='CC(C)[CH]C') # multiplicity 2
# species present when the property is first read -> correct
rxn1 = ARCReaction(r_species=[r], p_species=[p])
rxn1.multiplicity # 2
# species attached later -> wrong, and it sticks
rxn2 = ARCReaction(label='R <=> P', reactants=['R'], products=['P'])
rxn2.multiplicity # 1
rxn2.r_species = [r]; rxn2.p_species = [p]
rxn2.multiplicity # still 1
The second form is what an input file produces when a reaction names its species by label:
species:
- {label: R, smiles: '[CH2]C(C)CC'}
- {label: P, smiles: 'CC(C)[CH]C'}
reactions:
- label: R <=> P
reactants: [R]
products: [P]
What it costs
The species themselves are perceived correctly — the log shows multiplicity=2 for both — while the reaction is set to 1, so the TS inherits 1 and Gaussian is handed an impossible specification:
Setting multiplicity of reaction R <=> P to 1
...
The combination of multiplicity 1 and 41 electrons is impossible.
Error termination via Lnk1e in .../l301.exe
ARC does notice, but too late and in the wrong place. The Linear TS adapter raises
Impossible multiplicity for species TS0: the species has 41 electrons, which requires an even
multiplicity, but a multiplicity of 1 was requested. The nearest valid multiplicities are [2].
and that exception is caught, so the run continues, submits the impossible job, exhausts its troubleshooting on it (int=(Acc2E=14), all_attempted) and reports the TS as unconverged. I lost ten transition-state searches this way before opening a Gaussian log; nothing upstream of that log says "multiplicity".
Expected behavior
get_rxn_multiplicity()should returnNonewhen it has no species to reason about, so the property recomputes later instead of caching a guess. Guarding the empty case explicitly would do it — the vacuousall([])is the only reason 1 is reached.- The parity check that already exists (
check_multiplicity_parity) is the right test; it should be applied to the reaction when its multiplicity is set, not only when an adapter happens to build a species. An electron count and a multiplicity of opposite parity is knowable before any job is written.
Installation information
- ARC
main@4d67ad4c - Python 3.14, Linux, PBS, Gaussian 16
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at ARCReaction.multiplicity and get_rxn_multiplicity(), using the reproduction in the issue to observe caching before and after species attachment. Then inspect check_multiplicity_parity and the Linear TS adapter path. Done means an empty species set does not cache 1, later attachment recomputes the reaction multiplicity, and parity is checked when the reaction multiplicity is set.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100