ReactionMechanismGenerator / ReactionMechanismGenerator/ARC

deduce_method_type() substring-matches 'am' inside 'cam-b3lyp': every CAM functional types as semi-empirical

Open
#1,049 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
51
Forks
25
Avg merge
4d 5h
Merged PRs (30d)
15

Description

Level.deduce_method_type() matches its markers as raw substrings, so a short marker fires inside an unrelated method name. 'am' sits inside every Coulomb-attenuated functional, and every one of them is typed as semi-empirical:

cam-b3lyp / camb3lyp / camh-b3lyp / cam-qtp00 / lc-camb3lyp  ->  semiempirical
am05                                                          ->  semiempirical
amber                                                         ->  semiempirical   (not force_field)
ghemical                                                      ->  wavefunction    ('ic' inside 'ghemICAl')

cam-b3lyp (gaussian) and camb3lyp (terachem) are both registered in data/ess_methods.yml, so this is reachable from an ordinary input file.

Why it matters

method_type gates behaviour in several places, and every consequence points the same way — a CAM functional silently gets treated as a method it is not.

1. A radical runs restricted. is_species_restricted() (arc/job/adapters/common.py) early-returns True for semiempirical before it ever reads the multiplicity.

2. A TS optimization stops searching for a saddle point. arc/job/adapters/gaussian.py gates the optimization keyword list on method_type in ['dft', 'composite', 'wavefunction'] and otherwise emits a bare opt, dropping ts, calcfc and noeigentest. The job then optimizes the TS guess down to a minimum.

3. fine is silently dropped — the integral=(grid=ultrafine) / scf=(tight,direct) block is also gated on method_type in ['dft', 'composite'].

Generated Gaussian route lines, b3lyp vs cam-b3lyp, same species and same settings (a doublet OH with fine=True, then a TS with fine=True):

b3lyp      #P opt=(calcfc,maxcycle=100,maxstep=5,tight)  guess=mix ub3lyp/def2tzvp  integral=(grid=ultrafine, Acc2E=12) ... scf=(direct,tight)
cam-b3lyp  #P opt  guess=mix cam-b3lyp/def2tzvp

b3lyp      #P opt=(calcfc,maxcycle=100,maxstep=5,noeigentest,tight,ts)  guess=mix b3lyp/def2tzvp  integral=(grid=ultrafine, Acc2E=12) ... scf=(direct,tight)   <- TS
cam-b3lyp  #P opt  guess=mix cam-b3lyp/def2tzvp                                                                                                              <- TS

Note the missing u prefix on the doublet and the missing ts on the TS.

4. Dispersion is rejected. Level(method='cam-b3lyp', basis='def2-TZVP', dispersion='gd3bj') raises ValueError: Dispersion is only allowed for DFT (or composite) methods, got gd3bj for cam-b3lyp which is a semiempirical.

5. Orca gets the wrong block. arc/job/adapters/orca.py sets method_class = 'KS' and the DFT grid only for method_type == 'dft'.

6. ESS preference is wrong. Level.deduce_software() picks a different preferred_ess_order per method type.

The shape of the fix

Two independent problems:

  • 'am' and 'pm' are abbreviations of am1 / pm3 / pm6 / pm7, so spelling them out in full removes the false positives without losing anything.
  • The wave-function markers are the shortest and most promiscuous (cc, ci, ri, ic, mr, bd, cp), and they are currently matched first. Matching them last lets the longer, more specific force-field and semi-empirical names win.

Matching on token boundaries instead is tempting and wrong: BCCD, QCISD, FCI, LCCSD, LT-DF-LCC2 and torchani all carry their marker mid-token, and a token-start rule re-types all six. That variant was tried and rejected against the full registered-method sweep below.

The verifier for any fix should be the exhaustive one: type all 180 methods in data/ess_methods.yml before and after, and confirm the only changes are the intended ones. For the fix in the linked PR that diff is exactly:

amber      semiempirical  -> force_field
cam-b3lyp  semiempirical  -> dft
camb3lyp   semiempirical  -> dft
ghemical   wavefunction   -> force_field

Found while reviewing #1014, where the same typing feeds the broken-symmetry adoption gate — a CAM functional currently reaches it as REFERENCE_AGNOSTIC, so it is denied a broken-symmetry reference it should be offered. That direction is conservative and is not a defect in #1014.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at Level.deduce_method_type() and the registered names in data/ess_methods.yml; compare marker ordering against the full 180-method type sweep. Check affected behavior in arc/job/adapters/common.py, gaussian.py, and orca.py, then verify that only amber, cam-b3lyp, camb3lyp, and ghemical change classifications as listed.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.