Repository navigation
output.yml schema 1.3: export levels, provenance, atom maps, IRC mapping and correction switches - #1059
Open
calvinp0 wants to merge 8 commits into
Open
output.yml schema 1.3: export levels, provenance, atom maps, IRC mapping and correction switches#1059calvinp0 wants to merge 8 commits into
calvinp0 wants to merge 8 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1059 +/- ##
==========================================
+ Coverage 67.09% 68.05% +0.96%
==========================================
Files 123 123
Lines 43663 44981 +1318
Branches 11152 11399 +247
==========================================
+ Hits 29295 30613 +1318
+ Misses 11220 11186 -34
- Partials 3148 3182 +34
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
September 29, 2026 12:14
1977e53 to
6979e16
Compare
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
3 times, most recently
from
October 1, 2026 05:49
7fcbdcd to
bc731fb
Compare
calvinp0
added a commit
that referenced
this pull request
Oct 1, 2026
…fcbdcd..bc731fb) Applies the delta between the old and the force-pushed head of PR #1059 onto arcbench; the earlier commits of that PR are already integrated here. The delta contains: per-record levels and the header levels of the adaptive, scan, IRC, conformer and TS-guess jobs with their provenance (software, versions, routes, isotopes); reaction atom maps and the IRC participant mapping; parsed properties (T1 diagnostic, dipole moment, polarizability); thermo and kinetics atom and bond correction switches and the energy-correction components; the RMG database and AEC identity; the arkane follow-ups (dispersion and solvation key matching, synthetic-key tests); scheduler, species, conformer, vector, reaction, level, TS-check, xtb_gsm, pipe and Gaussian changes the export relies on; and the schema, docs and golden files for schema 1.3. Conflicts with arcbench-only code were resolved by keeping both sides: the cost-metrics completed_job_records argument beside adaptive_levels in main.py and output.py, the cost-metrics tests beside the new tests, and the NMD undetermined-bonds test beside the new frequency test.
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 06:16
bc731fb to
bbff27f
Compare
calvinp0
added a commit
that referenced
this pull request
Oct 1, 2026
…sary lambdas, unclosed descriptor) Mirrors the test changes folded into PR #1059 at bbff27f: the raise inside route_logger_to_arc_log's block moves into a local function passed to assertRaises, job_factory is patched with functools.partial instead of a lambda, and the mocked mkstemp returns the descriptor of a real mkstemp call, which the code under test closes.
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 10:10
bbff27f to
ebc88ec
Compare
calvinp0
added a commit
that referenced
this pull request
Oct 1, 2026
…ff27f..ebc88ec) Adds reactant_species_labels and product_species_labels to exported reactions, the TS-only nmd_forced flag, ARCSpecies.conformer_logs with the exported conformer_ess_software and conformer_ess_version, the 101325 Pa standard-state pressure fallback in arkane.py, the ts_atom_map condensed-graph-of-reaction isomorphism in checks/ts.py with its constants and helpers in checks/common.py, the schema and docs changes, and the _get_exported_xyz helper in output.py.
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 15:37
ebc88ec to
bbd3861
Compare
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 17:23
bbd3861 to
be7da53
Compare
calvinp0
added a commit
that referenced
this pull request
Oct 1, 2026
…c88ec..be7da53) Applies the PR delta: the TS atom map redesign (IRC start and endpoint congruence, endpoint graphs from the verdict's fragments), composite step routes and neb_succeeded, nullable species labels, isotopes read only from logs, the rigid rotor kind from the point group, fail-closed correction rows, the AEC.yml digest stamped with each E0, T1 from the sp log, the NMD mode index, and parse_irc_start_geometry. On arcbench, compute_rxn_e0 and check_ts also reset, copy and carry e0_aec_yml_sha256 alongside the E0 correction stamps, the condensed-graph fallback of the IRC check is kept, and the helper that only served the superseded atom order comparison is dropped.
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 17:41
be7da53 to
7d31795
Compare
output.yml states the level of theory of the job behind each exported log, and that level has to survive a restart.yml round trip and a YAML dump. A Level object cannot be stored as is, and a shallow as_dict() shares its mutable values (args) with the level and can emit YAML anchors. arc/level.py gains level_as_plain_dict, a deep-copied dictionary of plain types in which the nested solvation_scheme_level is converted recursively, or dropped, and any other keys can be stripped at every depth. adaptive_levels_as_list converts the processed adaptive levels into the list form written to restart.yml; the output commit switches the main driver to it. set_recorded_level, set_recorded_irc_level and set_recorded_irc_log_level keep the per-species levels dictionary and the irc_levels list in step with the logs ARC stores. The solvation scheme's own level is not recorded, since the energies of the scheme's extra jobs are not the exported ones. Forward and reverse IRC logs are exported together under one key, so the first log records its level and a second log at a different level removes the record: the level of the pair is then undeterminable, and stating either level would be wrong. Levels are compared without the fields output.yml does not state for a job (repr, compatible_ess, software, solvation_scheme_level).
…ticipant records
Several things a consumer of output.yml needs were held nowhere, or held in a
form that hid where they came from. This commit gives the species and
reaction objects the attributes, and keeps them through restart.
Conformers. conformer_energies mixed units without saying so: a force-field
energy is kcal/mol and a parsed electronic energy is kJ/mol. ARCSpecies now
keeps conformer_levels (the level of the optimization job that produced each
geometry) and conformer_energy_sources ({kind, level, force_field}) in
lockstep with conformers, padded with None for an older restart or a
conformer added without a record. conformers.py records which force field
and backend actually produced the energies of a generation, and in which
unit, through a context variable, so the name is only stated when exactly one
force field, backend and unit did. RDKit's MMFF to UFF fallback is reported
as UFF, and the UFF energy path no longer asks for MMFF properties it does
not use.
Reaction atom map. ARCReaction records where its atom map came from:
'inferred' when map_reaction computed it (with the algorithm and family),
'declared' when the reaction dict carries an atom_map_source: declared
entry, and None when it is unknown. The setter records no
origin, and the state is saved to and restored from the reaction dict. The
docstring now states the atom order the map counts in: the species of
get_reactants_and_products, once per occurrence.
Arkane and TS records. ARCSpecies keeps e0_atom_corrections_applied,
e0_bond_corrections_applied and arkane_rotor_modes next to e0, and
copy_e0_from takes the switches together with an E0 from another species, so
a borrowed E0 is never paired with switches from a different Arkane run. The
NMD check records the 0-based position of the mode it analysed in the
frequencies it parsed (nmd_record['mode_index']), and the IRC check's
participant mapping is stored on the TS species.
Conformer log provenance. ARCSpecies keeps conformer_logs, the path of the
conformer optimization log that produced each conformer geometry, in
lockstep with conformer_levels and conformer_energy_sources: padded with
None for an older restart, extended with None for force-field and user-
supplied conformers, reset with the rest of the provenance, and saved to and
restored from the species dict. record_conformer_geometry_level takes the
log path beside the level.
TS atom map. A TS species keeps ts_atom_map (the TS atom of every reactant
and product atom of its reaction) and ts_atom_map_unavailable_reason (why it
holds none), saved, restored and cleared with the other IRC check records.
A queue TS-guess job whose log yields no usable geometry now records a
failed, coordinate-less orca_neb guess, as the in-core job does, so that a
failed NEB reads the same on both paths.
…stage xtb_gsm The IRC check decided by graph isomorphism but discarded which fragment of each endpoint geometry was which species. _assign_fragments_to_species replaces the boolean _match_fragments_to_species: it returns the matching (for each fragment, the index of the expected species it matched, or None when there is no one-to-one matching), and the check uses it to build ts_species.irc_participant_mapping: for the reactant and product side, the endpoint it matched and, per participant (repeated species included, one entry per occurrence), the 0-based atom indices into the endpoint geometry. The mapping also states whether the reactants and products are graph- isomorphic to each other (when they are, which endpoint is called the reactants is a convention) and whether the IRC geometries follow from the TS geometry (see below), which is what makes atom i of an endpoint atom i of the TS. A failure to build it is logged and leaves the verdict untouched. A check that is forced to pass is marked by the forced flag of nmd_record, and the record is cleared with the rest of the TS checks. xtb_gsm staged its ograd script with a hard-coded --chrg 0 and no spin, so a charged or open-shell reaction was searched as a neutral closed-shell one. The script is now a template with @charge@ and @UHF@ placeholders (and an explicit --gfn 2) that the adapter fills with the reaction charge and multiplicity minus one, and it refuses to stage when either is unknown. The script is executable, and the staged copy is made executable too. The Gaussian adapter rewrote self.level.basis and self.level.method in place (def2- to def2, cbs-qb3-paraskevas to cbs-qb3), so the level ARC recorded for a job no longer matched the level requested. It now applies the same rewrites only to the values written to the input file and leaves the Level alone. The linear TS adapter uses the reaction's atom map state accessors, so that restoring a snapshot also restores the map's source and method. The IRC check also states which TS atom each atom of the reaction is, as ts_species.ts_atom_map. No ARC TS method guarantees that the TS lists its atoms in reactant order, so the map comes from a label-preserving isomorphism of two condensed graphs of reaction (a constitutional, 2D correspondence): one over the concatenated reactant atoms, with an edge for every bond of the reactants or the products, labelled by which of the two it is in, and one over the TS atoms, whose bonds are the connectivity of the two IRC endpoints taken from the molecule fragments the IRC verdict itself perceived (element and connectivity only, and refused unless each fragment atom carries the coordinates of the endpoint geometry exactly). The identity is preferred when it is a solution, otherwise the first match found is taken, so symmetry-equivalent atoms follow a deterministic convention that is not canonical across networkx versions; the endpoint roles are swapped when the reactants and products are isomorphic. Taking endpoint atom i as TS atom i is verified from the logs, not assumed. The first geometry of every IRC log must be the TS geometry atom for atom (Gaussian's first input orientation, read by the new parse_irc_start_geometry; no other program's IRC log is read): the same elements in order and, with no permutation of atoms, the same coordinates after a proper rotation and translation (kabsch, after giving the parsed geometry the isotopes of the reference), within a root-summed-squared deviation of 1e-3 Angstrom that covers print precision (IRC_START_GEOMETRY_TOLERANCE in arc/checks/common.py). The chain continues to the endpoints: the optimization log of endpoint k starts from a geometry congruent with the last geometry of IRC log k (the endpoint species is made from that geometry), and the endpoint geometry the check receives is exactly the final geometry of that optimization log, which the scheduler now passes by path. Both endpoints must also have the element sequence of the TS. What remains rests on the ESS keeping its input atom order within a log and on ARC's parsing and writing keeping it. No distance limits are applied. The fragments of the IRC verdict are tied to the endpoint atoms by exact coordinate equality, so a perception that reorders their atoms still maps. Each way of not stating a map has its own reason, including an unreadable or differing IRC start geometry (irc_start_geometry_unavailable and irc_start_geometry_differs) and a differing endpoint chain (irc_endpoint_geometry_differs), and a failure is logged and leaves the verdict, the participant mapping and the reaction's atom map untouched.
A piped job left no trace of the level it ran at: conf_opt and conf_sp ingestion overwrote the conformer geometry and energy and stated neither level nor energy kind, and the freq and IRC ingestion recorded paths only. The ingest functions now build a Level from the task spec and record it the way the local scheduler does, through the helpers in arc/level.py: the conformer geometry level, the conformer energy source (electronic, in kJ/mol, with the task's level), the freq level, and the IRC level together with the level and direction of each IRC log, kept in lockstep with the IRC paths. A conf_opt task whose optimized geometry parses but whose energy does not now sets the energy to None with no recorded kind, instead of keeping the force-field energy that was there, which would otherwise be reported as belonging to the optimized geometry. Ingesting a conf_opt task also records its output log, the conformer optimization log that produced the geometry, beside the level.
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 21:34
7d31795 to
d31ab7a
Compare
calvinp0
added a commit
that referenced
this pull request
Oct 1, 2026
A static method on Scheduler reached through the pipe coordinator test's real-method stub was bound with the stub as an extra argument, so piped freq finalization raised TypeError there. The helper does not use the Scheduler, so it now lives at module level, as in PR #1059.
…ge for TS search jobs output.yml states the level of theory of the job whose log it exports, so the Scheduler now records it where it stores the log path, in output[label]['levels'] (opt, freq, sp, composite, irc) and, for IRC, paths['irc_levels'] in lockstep with paths['irc']. The record is an independent plain dict that round-trips through restart.yml, and an older restart without the keys gets them created. The level comes from the job that ran, not from the run-level setting, since those differ under adaptive levels and after troubleshooting. A composite job's frequencies are at the composite method's own geometry level, which the job's level does not name, so the freq level of a composite log is left unknown. opt_level of a species is likewise taken from the job. The sp record is restored after a solvation scheme's extra sp jobs, together with the original path, the T1 diagnostic and the electronic energy. Conformer jobs record the conformer geometry level and the electronic energy source, and a conformer whose optimization returned no geometry no longer overwrites the stored one or its energy. IRC endpoint species record the direction of the IRC job they came from and the check is passed the endpoint labels. switch_ts now clears the TS's E0, together with its correction switches and Arkane rotor modes. Before this, compute_rxn_e0 skipped a TS whose e0 was already set, so the E0 check of the next guess reused the E0 of the abandoned guess. Resetting a species' E0 also resets the correction switches and Arkane rotor modes recorded with it, and resetting its conformers resets their provenance. TS search jobs are not spawned for a reaction whose charge is unknown, as they already were not for an unknown multiplicity, since xtb_gsm now states both in its input. Conformer jobs also record the conformer optimization log that produced the stored geometry, beside its level. The IRC check receives the paths of the two IRC logs, so that it can verify they start from the TS geometry.
…spersion and solvation Record on each species' thermo the atom- and bond-correction switches ARC actually rendered into the Arkane input, and the level the atom energies were taken from. Without them a consumer cannot tell a formation enthalpy from the raw electronic energy Arkane reports when no atom energies exist for the level, because a missing atom_energy correction record proves nothing. thermo.atom_corrections_applied and bond_corrections_applied are the switches of the Arkane run that produced the thermo, and are None when unknown (thermo loaded from an Arkane YAML, not produced by this run, or an older output). True means the switch was on, not that H298 is a formation enthalpy. thermo.atom_corrections_level is the level the atom energies came from, in the sp_level shape, so it can be compared with the species' energy level; it differs when arkane_level_of_theory is a stand-in, as in the BDE example. The same switches are stamped on the species' and the TS's E0 and on the fitted kinetics, since they decide what the E0 means, and a species or reaction declared by an Arkane YAML is stamped None because Arkane loads it as is. ARC now also renders the species' bonds into the Arkane species file, records which rotor modes (HinderedRotor, FreeRotor, HinderedRotor2D, HinderedRotorClassicalND, and Mode, which is how Arkane writes a multi-dimensional rotor) the conformer block of the Arkane output holds, and derives from them the statmech treatment Arkane applied. get_qm_corrections.py reports the quantum_corrections/data.py path Arkane loaded. The adapter records the SHA-256 of ARC's data/AEC.yml (aec_yml_sha256s) at the moment it renders atomEnergies from it into an Arkane input, and process_arc_project returns the distinct digests of its adapters, so a consumer can identify the correction tables behind a number without a level being matched again at output time. Match Arkane correction keys (AEC, PBAC, MBAC) and data/AEC.yml on a level's dispersion and solvation_method as well as its method string, basis, software and year. A canonical dispersion is folded into the method, so a dispersion field behaves exactly like the same dispersion written in the method string. A dispersion added to a separately parametrized "-D" functional (B97, wB97X, wB97M) matches none of that functional's variants. A solvated level matches nothing, since Arkane has only gas-phase correction sets; such levels follow ARC's existing no-correction path, and the startup error names the remedies, which docs/source/advanced.rst now describes. Frequency-key matching is unchanged: a missing frequency key drops the whole Arkane model chemistry, and with it the corrections of a correct gas-phase sp level. BREAKING: a level with a solvation_method, or with a separate dispersion field for which Arkane has no dispersion-corrected entry, now gets no Arkane corrections. With compute_thermo on (the default), ARC stops at startup for such a level, which includes restarting an existing project that used one. The error names the remedies: set compute_thermo to False, or set an arkane_level_of_theory that Arkane has corrections for. No existing match changes (checked against the previous matcher on every Arkane key with software, year and spelling variants); b2plyp with a gd3 suffix or field now matches Arkane's b2plypd3 entry. Thermo that is read from the Arkane output.py because no thermo.yaml is available records a standard-state pressure of 101325 Pa (1 atm), the constant RMG's translational partition function applies. A thermo that no Arkane run produced still records none. parse_species_thermo reports whether it parsed a thermo block.
…properties (schema 1.3) Bump the output.yml schema to 1.3. The schema is closed and every key a consumer relies on is required but nullable, so a consumer can tell "ARC does not know" (null) from "not applicable" without probing for absent keys. ARC states only what it observed or what the run recorded, and never rebuilds a value from a level or from job.args. Levels and programs. Each species and TS record carries levels, the level of the job behind each exported log (opt, freq, sp, composite, irc), as recorded by the Scheduler, and the header carries adaptive_levels plus the requested scan, IRC, conformer opt, conformer sp, TS guess and GSM levels, each null unless a job of that type could have run at it. The GSM level and program are read from the archived xtb outputs, and ess_software and ess_version are identified from the logs themselves, now for composite, IRC and scan jobs as well. Conformers export their geometry levels, the energy kind (force field kcal/mol or electronic kJ/mol), the level of an electronic energy and the force field, and conformer energies are absolute. Atom maps and IRC. A reaction exports its atom map with the order of the species it counts in, its source (declared or inferred) and method; the map must be a permutation that conserves the elements, and the exported geometry of every participant must follow the atom order of its mol, or it is null. TS records export the IRC participant mapping (which atoms of each endpoint belong to which participant, whether the sides are distinguishable, whether the atom order follows the TS), IRC log routes, directions and levels, and IRC endpoint species state the TS they belong to and their direction. TS frequencies are exported in ESS order with the index of the reaction coordinate mode, which is the position the NMD check recorded for the mode it analysed, given only when the number of modes the check indexed equals the number of exported frequencies and the log it parsed is the exported frequency log, and the NMD record states whether a check was forced. Corrections. Thermo states whether atom and bond corrections were applied and at which level, E0 and the kinetics state the same switches, and an atom_energy or bond_additivity record is kept only for a switch recorded as on: a switch that was off or is unknown states no row. The identity of the tables Arkane loaded (git commit or package version, and the SHA-256 of the file; a mismatch with ARC's RMG_DB_PATH is logged) is exported, and so is the digest of ARC's own AEC.yml that an Arkane adapter recorded when it rendered atom energies from it, collected from the final processing and from the E0 of every exported species and TS (the TS check's E0 carries the digest of its own adapter), which is null unless exactly one distinct digest was recorded in the run. Petersson components list the bonds Arkane skipped, and the Arkane treatment and rotor count are stated. A rotor's treatment is read from the mode Arkane holds and is null when that is not known. Properties and routes. The rigid rotor kind is read from the exported point group alone (cubic groups are spherical tops, groups with a proper C_n axis of n >= 3 are symmetric tops, and so are D2d and S_n with even n >= 4, since an improper rotation acts on the inertia tensor as the proper rotation by the angle plus pi, the low-symmetry groups are asymmetric tops, C-infinity-v and D-infinity-h are linear), with no moment of inertia and no tolerance, and is null without a point group or for an isotopically labelled species. Isotope lists are exported only from logs that state the masses (the log of the exported geometry, and each conformer's own log) and are null otherwise; ARC's own geometry dicts are never read for them. The effective route keywords of each job are read from the log in preference to the input deck, and the T1 diagnostic the exported sp log prints for its correlated method, the Gaussian dipole moment with its density, and the Gaussian polarizability (read by fixed-width field) are exported. Kinetics carry Arkane's comment and a ts_validation marker for a rate from a TS that failed its IRC check, and reactions state their reversibility from the arrow. The main driver warns at startup when arkane_level_of_theory differs from the energy level (composite method or sp level, and any adaptive sp/composite level), comparing method and basis with Arkane's own normalisation and with dispersion folded into the method, whether it is written in the method string or in the separate dispersion field. A gas-phase Arkane level set for solvated energy levels is warned about too. The driver also passes the requested levels to the writer, and reports an NEB level only when the run has a TS or a reaction and the orca_neb adapter is among those the scheduler uses. The schema file, the docs, the parser evidence version and its golden files follow. Reactions state their species once per occurrence in reactant_species_labels and product_species_labels, since reactant_labels is sorted and de- duplicated, and TS records state nmd_forced, whether a check was forced to pass. Species with conformers state the program and the version banner of each conformer's own optimization log in conformer_ess_software and conformer_ess_version. A null conformer energy means the conformer has no energy, and the energy kind, level and force field describe only the other entries. A reaction exports ts_atom_map, the TS atom of each reactant and product atom, a constitutional (2D) correspondence from an isomorphism of condensed graphs of reaction (method irc_endpoint_cgr_isomorphism) whose TS-side bonds come from the fragments the IRC verdict perceived, or the reason it cannot. It is stated only after the first geometry of every IRC log is verified to be the TS geometry atom for atom, each endpoint is verified to follow from its IRC log through its optimization log, and the record is checked against the reaction, the TS elements and the atom order of each participant's exported geometry. That last check is ARC's are_coords_compliant_with_graph: the geometry has the element of the molecule's atom in every position and every bond of the molecule is no longer than 1.2 times the single-bond length of its two elements, so it can only turn a map into null. The reason species_atom_order_mismatch appears only when the TS has a geometry, its IRC check passed and it recorded a TS map; otherwise the reason is no_ts, irc_not_passed or the one the IRC check recorded. The reasons irc_start_geometry_unavailable, irc_start_geometry_differs and irc_endpoint_geometry_differs state the geometry checks. The irc_participant_mapping flag atom_order_matches_ts is true only when those checks pass and both endpoints have the element sequence of the TS, false when one is contradicted, and null when unknown. Applied bond corrections, in the thermo block or in the E0 of a species or TS, require a bac_type in the schema, and thermo read from output.py states its standard-state pressure. Composite steps and NEB. A Gaussian composite job (CBS-QB3, G4) exports composite_step_routes, the route of each Link1 step in the order the log echoes them, read by the same reader as composite_route, which stays the first entry; nothing more is stated or deduced from it. A TS exports neb_succeeded: true when the log recorded for an orca_neb guess (its own or a merged source) prints THE NEB OPTIMIZATION HAS CONVERGED, false when orca_neb guesses were recorded with readable logs and none prints it, null otherwise (a guess with no recorded log states nothing), and never inferred from a geometry, neb_level, a success flag or the configured adapters. reactant_species_labels and product_species_labels are null, not an empty array, for a reaction that holds no species objects.
tckdb_arc logs to its own "tckdb_arc" logger and, as a library, attaches no handler. ARC never routed that logger, so during the post-run upload its INFO records were dropped and its warnings reached only stderr through Python's last-resort handler. A run whose TCKDB server was unreachable ended arc.log at "Uploading ARC results to TCKDB ..." with no word that the upload failed or of the tckdb-arc-upload command that recovers it. arc/common.py gains route_logger_to_arc_log(name, level=INFO), a context manager that hands a named logger's records to the ARC logger's handlers (console and arc.log) for one block, stops it propagating for that block so nothing is written twice, and restores its handlers, level and propagation on exit, including on error. run_tckdb_upload wraps the config parsing, adapter construction and sweep in it. Each ARC handler's own level still applies, so a quiet run keeps INFO out of both outputs. The sweep returns None and prints its per-kind summary to stdout, so ARC has no outcome to summarise into arc.log beyond what is now routed.
calvinp0
force-pushed
the
feature_export_atom_corrections_applied
branch
from
October 1, 2026 22:36
d31ab7a to
e1c2126
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
output.ymlleft a consumer to infer things ARC knew, or could have recorded, and in several places the inference was wrong.Formation enthalpies. When Arkane has no atom-energy corrections (AEC) for the level of theory and
data/AEC.ymlhas no entry either, ARC renders the Arkane input withuseAtomCorrections = False(arc/statmech/arkane.py,render_arkane_input_template). RMG-Py then sets the atom correction to zero (arkane/statmech.py), so the species'h298_kj_mol, NASAa6/b6and tabulated H/G are raw electronic energies, about −10⁵ kJ/mol per heavy atom, not formation enthalpies.output.ymlgave a consumer no reliable way to tell. Anatom_energyrecord inenergy_correctionslooks like proof that AEC was applied, but its absence proves nothing:data/AEC.ymlpath applies AEC without writing a record.arkane_level_of_theory, regardless of whether Arkane actually ran with corrections. With spwb97xd/def2tzvp, a frequency level Arkane has no entry for andfreq_scale_factor=None,get_arkane_model_chemistryreturnsNoneand Arkane runs uncorrected, yetoutput.ymlstill reportedatom_energyandbond_additivitycorrections as applied.A downstream consumer (the TCKDB adapter) must label an enthalpy
formation_298konly when it really is one, so it needs ARC to say so.Everything else a consumer needs. The same gap exists elsewhere in the document:
adaptive_levels, a reaction-wide override or troubleshooting it differs from the run-level setting, and a consumer had only that setting.conformer_energiesmixed units without saying so: a force-field energy is kcal/mol and a parsed electronic energy is kJ/mol. The docs also called them relative to the lowest conformer, which they are not.reactant_labelsandproduct_labelsare sorted and de-duplicated, soHO2 + HO2 <=> H2O2 + O2exportedreactant_labels: [HO2]and a consumer could not balance the reaction.output.pystated no standard-state pressure.xtb_gsmstaged itsogradscript with a hard-coded--chrg 0and no spin, so a charged or open-shell reaction was searched as a neutral closed-shell one.self.level.basisandself.level.methodin place, so the level ARC recorded for a job no longer matched the level requested.The change
OUTPUT_SCHEMA_VERSIONgoes from 1.1 to 1.3. The schema is closed and every key a consumer relies on is required but nullable, so a consumer can tell "ARC does not know" (null) from "not applicable" without probing for absent keys. ARC states only what it observed or what the run recorded, and never rebuilds a value from a level or fromjob.args. The new keys are required in records that disallow extra properties, so 1.1 and 1.2 validators reject 1.3 output.docs/output_yml_schema.mdandarc/schemas/output_yml_schema.jsondescribe every key.Correction switches (the 1.2 keys). Each species'
thermogains three required keys:render_arkane_input_templateand stored asuse_aec/use_bac. The same values feed the Arkane template and the record, so they cannot disagree.parse_arkane_thermo_outputstamps them only on species whose thermo this Arkane run wrote.nullmeans unknown, never guessed. This covers thermo loaded from an Arkane YAML (StatMechJob.loadreturns before any correction step), thermo not produced by this run, and older output.truemeans only that the switch was on, not that H298 is a formation enthalpy.atom_corrections_levelis the level the atom energies came from, so a consumer can compare it with the species' energy level. They differ whenarkane_level_of_theoryis a stand-in, as inexamples/Stationary/bde/input.yml:bmk/cbsb7corrections onapfd/def2svpenergies.atom_energy/bond_additivityrecords are dropped for a species whose switch was off. They are left unchanged when the switch is unknown.statmech.e0_atom_corrections_applied,e0_bond_corrections_applied) and on the fitted kinetics (kinetics.atom_corrections_applied), since they decide what the E0 means. A species or reaction declared by an Arkane YAML is stampednull.arkane_level_of_theorydiffers from the energy level: the composite method or sp level, and any adaptive sp/composite level. The comparison normalises method and basis with Arkane's own name handling, and folds dispersion into the method whether it is written in the method string (b3lyp-d3bj) or in the separatedispersionfield (gd3bj,EmpiricalDispersion=GD3BJ). ARC also warns when solvated energy levels are paired with a gas-phasearkane_level_of_theory: gas-phase atom energies are then subtracted from solvated energies, so the results are not formation enthalpies.The JSON schema enforces the couplings with
if/thenrules:truerequires a level;falserequires bondfalseand a null level;nullrequires both others to be null.docs/output_yml_schema.mdstates how a consumer should compare the two levels, and when a match still does not establish a formation enthalpy:dispersionfield;Kinetics are unaffected in the numbers: the same AEC decision applies to reactants, TS and products in one run, so AEC cancels in barriers, and kinetics never uses BAC.
Levels and programs. Each species and TS record carries
levels(opt, freq, sp, composite, irc), the level of the job behind each exported log, as recorded by the Scheduler. The header carriesadaptive_levelsplus the requested scan, IRC, conformer opt, conformer sp, TS guess and GSM levels, eachnullunless a job of that type could have run at it.ess_softwareandess_versionare identified from the logs themselves, now for composite, IRC and scan jobs as well.Conformers. Records export
conformer_levels,conformer_energy_kind(force field kcal/mol or electronic kJ/mol),conformer_energy_levelandconformer_force_field, andconformer_ess_software/conformer_ess_version, read from the optimization log that produced each conformer geometry (nullfor a force-field conformer). Conformer energies are absolute. Anullenergy means the conformer has no energy, and the energy kind, level and force field describe only the other entries.Atom maps and IRC. A reaction exports
atom_mapwithatom_map_reactant_labelsandatom_map_product_labels(the order of the species it counts in),atom_map_source(declared or inferred) andatom_map_method; the map must be a permutation that conserves the elements or it isnull. TS records exportirc_participant_mapping(which atoms of each endpoint belong to which participant, whether the sides are distinguishable, andatom_order_matches_ts),irc_log_routes,irc_log_directions,irc_log_levels, and IRC endpoint species stateirc_endpoint_ofandirc_endpoint_direction.atom_order_matches_tsistrueonly when the chain and element order below are verified,falsewhen one is contradicted, andnullwhen unknown. TS frequencies are exported in ESS order asfreq_frequencies_cm1_ess_order, andnmd_forcedstates whether the normal mode check was forced to pass. Reactions state their species once per occurrence, inget_reactants_and_productsorder, asreactant_species_labelsandproduct_species_labels; both arenull, not[], for a reaction that holds no species objects.Reaction coordinate mode.
reaction_coordinate_mode_indexis the 1-based position, infreq_frequencies_cm1_ess_order, of the mode the normal mode check validated. It comes from the NMD record'smode_index, and is stated only when the record'sn_modesequals the number of exported frequencies, the log the check parsed is the exported frequency log, and the check genuinely passed. A forced check leaves itnull.TS atom map. A reaction exports
ts_atom_map, the TS atom of every reactant and product atom (methodirc_endpoint_cgr_isomorphism), orts_atom_map_unavailable_reason. ARC does not assume an order: it takes a label-preserving isomorphism between two condensed graphs of reaction, one over the reactant atoms with every bond of the reactants or products (labelled by which side it is on) and one over the TS atoms with the bonds of the two IRC endpoints. The isomorphism fixes the atoms whose bonds form or break and leaves only graph automorphisms free, so the reactant and product legs agree withatom_mapby construction. The endpoint graphs come from the IRC verdict's own perceived fragments, tied to the endpoint geometry by exact coordinates; no distance limit is applied. The map is a constitutional (2D) correspondence: symmetry-equivalent atoms, diastereotopic ones included, follow a deterministic convention that prefers the identity.ts_atom_order_follows_reactantsstates whether the identity is a solution.Taking endpoint atom i as TS atom i is verified from the logs, not assumed:
parse_irc_start_geometry) must be congruent with the TS geometry, atom for atom.converter.kabschwith an RSSD of at most 1e-3 Å (print precision), proper rotations only, after the parsed geometry takes the isotopes of the reference. A mirror image is refused.What remains rests on the ESS keeping its input atom order within a log and on ARC's parsing and writing keeping it. The map is also
nullwhen a participant's exported geometry is not in the atom order of its molecule (same elements in each position and every bond within ARC'sare_coords_compliant_with_graphlimit), a check that can only turn a map intonull. When no map is stated, the reason is one of:no_ts,irc_not_passed,irc_fallback_path,no_atom_map,endpoint_perception_mismatch,atom_map_contradicts_ts,species_atom_order_mismatch,irc_start_geometry_unavailable,irc_start_geometry_differs,irc_endpoint_geometry_differs,computation_failedornot_recorded.Parsed properties and routes. The effective route keywords of each job are read from the log in preference to the input deck. A Gaussian composite job (CBS-QB3, G4) exports
composite_step_routes, the route of each Link1 step in the log's order;composite_routestays the first entry. A TS exportsneb_succeeded:truewhen the log of a recordedorca_nebguess printsTHE NEB OPTIMIZATION HAS CONVERGED,falsewhen such guesses were recorded with readable logs and none prints it,nullotherwise, and never inferred from a geometry,neb_levelor a success flag.sp_t1_diagnosticis the T1 thatparse_t1reads from the exported sp log, with no gate on the method name. The Gaussian dipole moment with its density and the Gaussian polarizability (read by fixed-width field) are exported.rigid_rotor_kind. It is read from the exported point group alone, with no moment of inertia and no tolerance. Cubic groups are spherical tops. Groups with a proper C_n axis of n >= 3 are symmetric tops, and so are D2d and S_n with even n >= 4: an improper rotation S_n(θ) is the inversion times the proper rotation C(θ+π), and the inversion acts trivially on the inertia tensor, so S_n acts as a rotation of order 3 or more and forces two moments equal (allene is a prolate symmetric top). C1, Cs, Ci, C2, C2v, C2h, D2 and D2h are asymmetric tops, and C∞v and D∞h are linear. It isnullwithout a point group, and with non-default isotopes, since the point group is that of the unlabelled geometry.Isotopes. Isotope lists accompany a geometry only when the log of that geometry prints its masses (Gaussian thermochemistry jobs, including each conformer's own log); otherwise they are
null. ARC's own geometry dicts are never read for them.Kinetics and reactions. Kinetics carry Arkane's
commentand ats_validationmarker for a rate from a TS that failed its IRC check. Reactions statereversiblefrom the arrow; ARC writes every reaction with<=>, so it is alwaystrue.Arkane identity and treatment. The header exports the identity of the tables Arkane loaded (
rmg_database:path_kind,git_commit,version,quantum_corrections_sha256; a mismatch with the file under ARC'sRMG_DB_PATHis logged, not exported).arc_aec_yml_sha256is the SHA-256 of ARC'sdata/AEC.yml, recorded when an Arkane adapter renders atom energies from it, and carried with each E0 ase0_aec_yml_sha256, so the E0 computed by the TS check is covered. It is exported when exactly one distinct digest exists, and isnullotherwise. Petersson components list the bonds Arkane skipped (skipped_components), andstatmechstatesarkane_rotors_appliedandarkane_treatment. A rotor'streatmentis read from the mode Arkane holds and isnullwhen that is not known. Thermo read from Arkane'soutput.pystates a standard-state pressure of 101325 Pa (1 atm). Applied bond corrections require abac_typein the schema.Correction records. An
atom_energyorbond_additivityrecord is kept only when its switch istrue; a switch that is off or unknown states no row.Removed keys.
rmg_database.quantum_corrections_path,rmg_database.matches_arc_rmg_db_pathandirc_participant_mapping.<side>.endpointare not exported.Commits
6337df90level: record the level of a job as a plain dict.arc/level.pygainslevel_as_plain_dict, a deep-copied dictionary of plain types (the nested solvation scheme level is converted recursively, or dropped), so a recorded level survives arestart.ymlround trip and a YAML dump.adaptive_levels_as_listconverts the processed adaptive levels into the restart list form.set_recorded_level,set_recorded_irc_levelandset_recorded_irc_log_levelkeep the per-specieslevelsdictionary and theirc_levelslist in step with the logs ARC stores; forward and reverse IRC logs are exported together, so a second log at a different level removes the record instead of stating either level.10917979species: track conformer provenance, atom map origin, NMD and IRC participant records.ARCSpecieskeepsconformer_levels,conformer_energy_sources({kind, level, force_field}) andconformer_logsin lockstep withconformers, padded withNonefor an older restart.conformers.pyrecords which force field and backend produced the energies of a generation, and in which unit, so the name is stated only when exactly one force field, backend and unit did; RDKit's MMFF to UFF fallback is reported as UFF, and the UFF energy path no longer asks for MMFF properties.ARCReactionrecords the origin of its atom map (inferredwith algorithm and family,declared, orNone).ARCSpecieskeepse0_atom_corrections_applied,e0_bond_corrections_appliedandarkane_rotor_modesnext toe0, andcopy_e0_fromtakes the switches with the E0. The NMD check records the position of the mode it analysed (mode_index), and a TS keepsts_atom_mapand its unavailable reason. A queue TS-guess job whose log yields no usable geometry records a failed, coordinate-lessorca_nebguess, as the in-core job does.09e2b03ats: state IRC participants, endpoint atom order and the TS atom map, stage xtb_gsm._assign_fragments_to_speciesreplaces the boolean_match_fragments_to_speciesand returns the matching, which the IRC check uses to buildirc_participant_mapping. The IRC check also buildsts_atom_mapas described above and verifies the IRC start geometry and the endpoint chain;parse_irc_start_geometryis the new Gaussian parser, and the tolerance isIRC_START_GEOMETRY_TOLERANCEinarc/checks/common.py. A failure to build a record is logged and leaves the verdict, the participant mapping and the reaction's atom map untouched. Thextb_gsmogradscript becomes a template with@CHARGE@and@UHF@placeholders and an explicit--gfn 2, and the adapter refuses to stage when the charge or multiplicity is unknown. The Gaussian adapter applies its basis and method rewrites only to the values written to the input file and leaves theLevelalone. The linear TS adapter uses the reaction's atom map state accessors.fb697a92pipe: record the level of ingested tasks and the IRC direction. The ingest functions build aLevelfrom the task spec and record it the way the local scheduler does: the conformer geometry level and its log, the conformer energy source (electronic, kJ/mol), the freq level, and the IRC level and direction of each IRC log. Aconf_opttask whose geometry parses but whose energy does not sets the energy toNoneinstead of keeping the force-field energy.30dd1320scheduler: record the level behind each job's log, and require a charge for TS search jobs. The Scheduler records the level of the job whose log it stores inoutput[label]['levels']and, for IRC,paths['irc_levels'], as an independent plain dict that round-trips throughrestart.yml. The level comes from the job that ran, not the run-level setting. A composite job's freq level is left unknown, and the sp record is restored after a solvation scheme's extra sp jobs. IRC endpoint species record the direction of their IRC job, and the IRC check receives the IRC logs (irc_log_paths) and the endpoint opt logs (endpoint_log_paths).switch_tsclears the TS's E0 together with its correction switches and Arkane rotor modes. A conformer whose optimization returned no geometry no longer overwrites the stored one or its energy. TS search jobs are not spawned for a reaction whose charge is unknown.842a96d9arkane: record whether corrections were applied, and match them on dispersion and solvation. Records the atom- and bond-correction switches ARC rendered into the Arkane input, and the level the atom energies came from, on each species' thermo, E0 and kinetics. ARC now writes the species'bondsinto the Arkane species file, records which rotor modes the conformer block of the Arkane output holds, and derives the statmech treatment from them.get_qm_corrections.pyreports thequantum_corrections/data.pypath Arkane loaded. The adapter records the SHA-256 ofdata/AEC.ymlwhen it renders atom energies from it, andprocess_arc_projectreturns the distinct digests. Correction keys (AEC, PBAC, MBAC) anddata/AEC.ymlare matched on a level'sdispersionandsolvation_methodas well as method, basis, software and year (BREAKING, see below). Thermo read fromoutput.pyrecords the 1 atm standard state.82aeb4aboutput: export levels, provenance, atom maps, IRC mapping and parsed properties (schema 1.3). Bumps the schema and exports everything listed under "The change". The main driver passes the requested levels to the writer, reports an NEB level only when the run has a TS or a reaction andorca_nebis among the adapters the scheduler uses, and emits the startup level warnings. The schema file, the docs, the parser evidence version and its golden files follow.e1c2126eARC.py: write the tckdb_arc upload's log records to arc.log. See the section below.Correction matching: dispersion and solvation (BREAKING)
ARC's Arkane energy-correction matching (AEC, PBAC, MBAC and
data/AEC.yml) now reads a level'sdispersionandsolvation_method. No existing match changes; this was checked against the previous matcher on every key in Arkane's database, with software, year and spelling variants. Two forms that matched nothing now match Arkane's B2PLYP-D3 entry: the Gaussian-styleb2plyp-gd3andb2plypwithdispersion: gd3.A dispersion correction added to a separately parametrized "-D" functional (B97, ωB97X, ωB97M) matches none of that functional's variants. That holds whether it is given as a separate field or in Gaussian's g-prefixed spelling (
b97-gd3). The functionals' own names (b97-d3,wb97x-d3,wb97xd) match as before.BREAKING: some levels now get no Arkane energy corrections. Previously they silently got the gas-phase, non-dispersion ones. This covers:
solvation_method;dispersionfield for which Arkane has no dispersion-corrected entry, e.g.m062xwithgd3.Arkane's
b3lyp2023/def2tzvpset was fitted on B3LYP-D3(BJ) (Wu et al., J. Phys. Chem. A 2024, 128, 4335) but is keyed as plain B3LYP. With the current RMG-database, plainb3lypmatches it andb3lyp+gd3bjgets no corrections; RMG-database #747 relabels itb3lypd3bj2023, after which the two swap. The dispersion-matching tests use a synthetic corrections file, so they pass with either database.What happens next depends on the run:
compute_thermoon (the default): ARC stops at startup. This includes restarting an existing project that used such a level. The message names the remedies:compute_thermo: false, or an explicit gas-phase / non-dispersionarkane_level_of_theory, which ARC then warns mixes levels.docs/source/advanced.rstdescribes them.compute_thermo: false, e.g. rates only: Arkane runs with atom corrections off. That cancels in rate coefficients, andoutput.ymlcarries no correction records for those levels.Frequency-key matching is unchanged. A missing frequency key drops the whole Arkane model chemistry, and with it the corrections of a correct gas-phase sp level.
arc.logrecords the TCKDB uploadtckdb_arclogs to its owntckdb_arclogger and attaches no handler, so during the post-run upload its INFO records were dropped and its warnings reached only stderr. A run whose TCKDB server was unreachable therefore endedarc.logat "Uploading ARC results to TCKDB …" without saying the upload failed or giving thetckdb-arc-uploadcommand that recovers it.arc/common.pygainsroute_logger_to_arc_log(name, level=INFO), a context manager that passes a named logger's records to ARC's console andarc.loghandlers for one block. It turns off that logger's propagation for the block so nothing is written twice, and restores the logger's handlers, level and propagation on exit, including on error. Each ARC handler's own level still applies, so a quiet run keeps INFO out of both outputs.run_tckdb_uploadwraps the config parsing, adapter and sweep in it.Behaviour changes outside
output.ymldef2-todef2andcbs-qb3-paraskevastocbs-qb3rewrites apply only to the values written to the input file, so theLevelARC records for a job is the one requested.xtb_gsmis staged with charge and spin, and refuses without them. The script passes--gfn 2,--chrgwith the reaction charge and--uhfwith multiplicity minus one. Before, every search ran as neutral and closed-shell.xtb_gsmthat refuses.switch_tsclears the TS E0, with its correction switches and Arkane rotor modes. Before,compute_rxn_e0skipped a TS whosee0was set, so the E0 check of the next guess reused the E0 of the abandoned guess. Resetting a species' E0 also resets the switches and rotor modes recorded with it, and resetting its conformers resets their provenance.conf_optenergy isNonewhen it is not parsed, instead of keeping the force-field energy that was there.parse_conformer. A finishedconf_optjob with no parseable geometry keeps the stored geometry and the force-field energy. Onmainit set both toNone.bonds = {...}into it, so Arkane's BAC and the exported Petersson components use one bond dictionary.orca_neb. A queue-pathorca_nebjob whose log gives no usable geometry is recorded as a failed TS guess without coordinates, as the in-core job does. Before, nothing was recorded.irc_log_paths) and the endpoint opt logs (endpoint_log_paths), andparse_irc_start_geometryis added to the parsers.Tests
Results (serial, at
e1c2126e):arc/output_schema_test.pydrives the real writer over realARCSpeciesandARCReactionobjects and validates the document againstarc/schemas/output_yml_schema.json; its negative cases assert that the schema rejects a missing key and each inconsistent combination.Consumers
The TCKDB adapter (
tckdb-arc; its 0.9.x branches) reads schema 1.3. It must treat anullspecies-label key (reactant_species_labels,product_species_labels) as "not stated", and readneb_succeeded. The adapter turnsts_atom_mapinto TCKDB's per-participantatom_to_tsby slicing it with the participants' atom counts inatom_map_reactant_labels/atom_map_product_labelsorder; TCKDB'svalidate_reaction_atom_mapaccepts the result for H-abstraction, A + A and degenerate reactions.🤖 Generated with Claude Code