Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions arc/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1132,9 +1132,10 @@ def is_equal_family_product_dicts(dicts1: list[dict],
"""
Compare two lists of family‐product dictionaries for equality.
Returns True if they have the same length and, for each corresponding entry:
- 'family', 'group_labels', 'own_reverse', 'discovered_in_reverse' are equal
- 'products' lists contain Molecules with the same SMILES in the same order
- 'r_label_map' and 'p_label_map' dicts are equal

- ``family``, ``group_labels``, ``own_reverse``, and ``discovered_in_reverse`` are equal.
- ``products`` lists contain Molecules with the same SMILES in the same order.
- ``r_label_map`` and ``p_label_map`` dicts are equal.

Args:
dicts1: First list of product‐dicts from determine_possible_reaction_products_from_family.
Expand Down Expand Up @@ -1533,8 +1534,9 @@ def signed_angular_diff(phi_1: float, phi_2: float) -> float:

This returns the value of (phi1 - phi2), wrapped into the interval (-180, 180],
so that the result represents the smallest signed rotation from phi_2 to phi_1:
- A positive value means phi1 is ahead of phi2 in the counter-clockwise (CCW) direction.
- A negative value means phi1 trails phi2 (i.e., clockwise rotation).

- A positive value means phi1 is ahead of phi2 in the counter-clockwise (CCW) direction.
- A negative value means phi1 trails phi2 (i.e., clockwise rotation).

Args:
phi_1 (float): First angle in degrees.
Expand Down
2 changes: 1 addition & 1 deletion arc/job/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def check_job_status(job_id: int) -> str:
14428 debug xq1371m2 user_name R 50-04:04:46 1 node06
PBS (taken from zeldo.dow.com)::
Req'd Req'd Elap
Job ID Username Queue Jobname SessID NDS TSK Memory Time S Time
----------------------- ----------- -------- --------------- ------ ----- ------ --------- --------- - ---------
2016614.zeldo.local u780444 workq scan.pbs 75380 1 10 -- 730:00:00 R 00:00:20
Expand Down
17 changes: 8 additions & 9 deletions arc/job/trsh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1942,19 +1942,18 @@ def trsh_keyword_opt_maxcycles(job_status, ess_trsh_methods, trsh_keyword, could
def trsh_keyword_inaccurate_quadrature(job_status, ess_trsh_methods, trsh_keyword, couldnt_trsh) -> tuple[list, list, bool]:
"""
Check if the job requires change of inaccurate quadrature

Explanation

The integral not enough, under DFT calculations with some basis sets.
Explanation:
The integral is not accurate enough under DFT calculations with some basis sets.

Fixing
Fixing:
Check the input file for a missing basis set or unreasonable structure. If not, use one of the following keywords:

Check the input file, whether there was some miss in basis set or unreasonable structure. If not, use one of following keywords:
1. ``int=ultrafine`` (default in Gaussian 16), or ``int=grid=300590``.
2. ``SCF=novaracc``.
3. ``guess=INDO``.

1. int=ultrafine (default in Gaussian 16), or int=grid=300590.
2. SCF=novaracc.
3. guess=INDO.
If not work, use (1)~(3) at same time.
If that does not work, use (1)~(3) at the same time.

"""
if 'InaccurateQuadrature' in job_status['keywords'] and 'int=grid=300590' not in ess_trsh_methods:
Expand Down
3 changes: 3 additions & 0 deletions arc/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
A module for plotting and saving output files such as RMG libraries.
"""

from __future__ import annotations

import matplotlib
# Force matplotlib to not use any Xwindows backend.
# This must be called before pylab, matplotlib.pyplot, or matplotlib.backends is imported.
Expand Down Expand Up @@ -1398,6 +1400,7 @@ def plot_2d_scan_bond_dihedral(results: dict,
results (dict):
The results dictionary, dihedrals are assumed to be in degrees (not radians).
This dictionary has the following structure::

{'directed_scan_type': <str, used for the fig name>,
'scans': <list, entries are lists of torsion indices>,
'directed_scan': <dict>, keys are tuples of '{0:.2f}' formatted dihedrals,
Expand Down
2 changes: 2 additions & 0 deletions arc/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Includes spawning, terminating, checking, and troubleshooting various jobs
"""

from __future__ import annotations

import datetime
import itertools
import os
Expand Down
2 changes: 2 additions & 0 deletions arc/species/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
A module for performing various species-related format conversions.
"""

from __future__ import annotations

import math
import numpy as np
import os
Expand Down
7 changes: 3 additions & 4 deletions arc/species/species.py
Original file line number Diff line number Diff line change
Expand Up @@ -2184,7 +2184,8 @@ def kabsch(self, other: ARCSpecies, map_: list) -> float:
Args:
other (ARCSpecies): The other species to compare to.
map_ (list): A list of atom indices mapping atoms from this species to the other species. (i.e., if
this species has atoms [A, B, C] and the other species has atoms [C, A, B], then map_ would be [1, 2, 0]
this species has atoms [A, B, C] and the other species has atoms [C, A, B],
then ``map_`` would be [1, 2, 0])
Returns:
float: The Kabsch RMSD value.
"""
Expand Down Expand Up @@ -2223,8 +2224,6 @@ class TSGuess(object):
project_directory (str, optional): The path to the project directory.

Attributes:
initial_xyz (dict): The 3D coordinates guess.
opt_xyz (dict): The 3D coordinates after optimization at the ts_guesses level.
method (str): The method/source used for the xyz guess.
method_sources (list[str]): All methods/sources that produced an equivalent xyz guess.
method_index (int): A subindex, used for cases where a single method generates several guesses.
Expand Down Expand Up @@ -2258,7 +2257,7 @@ def __init__(self,
success: bool | None = None,
family: str | None = None,
xyz: dict | str | None = None,
arc_reaction: Optional = None,
arc_reaction: 'ARCReaction | None' = None,
ts_dict: dict | None = None,
energy: float | None = None,
cluster: list[int] | None = None,
Expand Down
97 changes: 96 additions & 1 deletion docs/source/TS_search.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,101 @@ Transition State Search
ARC can automatically search for and validate transition states (TSs) for selected reaction types.
This section describes currently supported TS-search workflows and how to use them through ARC input files.

Heuristics adapter
^^^^^^^^^^^^^^^^^^

ARC includes an internal TS-guess adapter named ``heuristics``. The implementation
lives in ``arc/job/adapters/ts/heuristics.py`` and runs incore; it generates
candidate TS geometries directly from the mapped reactant and product wells
rather than submitting a separate external TS-search program.

The current heuristic adapter supports:

- ``H_Abstraction`` reactions
- ``carbonyl_based_hydrolysis`` reactions
- ``ether_hydrolysis`` reactions
- ``nitrile_hydrolysis`` reactions

Use it by listing ``heuristics`` under ``ts_adapters``:

.. code-block:: yaml

ts_adapters:
- heuristics

.. graphviz::
:caption: How the heuristic TS adapter fits into an ARC run.

digraph heuristic_ts {
graph [rankdir=LR, bgcolor="transparent"];
node [shape=box, style="rounded,filled", fillcolor="#f5f7fa", color="#9fb3c8", fontname="Helvetica"];
edge [color="#5b6676", fontname="Helvetica"];

rxn [label="ARCReaction\nmapped wells"];
family [label="Reaction family"];
heuristics [label="heuristics.py"];
guesses [label="TSGuess objects\nXYZ geometries"];
opt [label="TS optimization"];
validate [label="frequency / IRC\nvalidation"];

rxn -> family -> heuristics -> guesses -> opt -> validate;
}

Hydrogen abstraction heuristic TS search
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For RMG ``H_Abstraction`` reactions, the heuristic adapter constructs TS guesses
for reactions of the form:

.. code-block:: text

R1-H + R2 <=> R1 + R2-H

The algorithm identifies the transferred hydrogen and the two reacting centers
from the mapped reaction, combines reactant/product geometries, stretches the
forming and breaking H bonds, and samples relevant dihedral angles. Duplicate
and colliding geometries are filtered before ARC stores the remaining guesses as
``TSGuess(method='Heuristics')`` entries.

At minimum, the reaction must have:

- A recognized ``H_Abstraction`` family assignment.
- 3D coordinates for all reactant and product wells.
- Atom mapping between reactants and products, including the transferred H.
- ``heuristics`` enabled in ``ts_adapters``.

Example input pattern:

.. code-block:: yaml

project: h_abstraction_example

ts_adapters:
- heuristics

species:
- label: methane
smiles: C
- label: OH
smiles: "[OH]"
- label: methyl
smiles: "[CH3]"
- label: water
smiles: O

reactions:
- label: methane + OH <=> methyl + water
reactants:
- methane
- OH
products:
- methyl
- water

ARC then uses the heuristic guesses as normal TS candidates: it optimizes them,
checks for a single meaningful imaginary frequency, optionally runs IRCs, and
uses the successful TS in kinetics processing.

Neutral hydrolysis TS search
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -40,7 +135,7 @@ For neutral hydrolysis reactions, ARC performs the following general steps:

1. Identify the relevant reactive atoms based on the reaction family definition.
2. Generate one or more chemically reasonable TS guesses for the hydrolysis transformation.
3. Optimize the TS candidates that passes internal filtration.
3. Optimize the TS candidates that pass internal filtration.
4. Validate the TS using vibrational frequency and IRC calculations.

Outputs and validation
Expand Down
121 changes: 121 additions & 0 deletions docs/source/_static/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* ARC documentation polish on top of sphinx_rtd_theme. */

:root {
--arc-ink: #18212f;
--arc-muted: #5b6676;
--arc-blue: #1f6feb;
--arc-teal: #0f766e;
--arc-border: #d9e2ec;
--arc-code-bg: #f5f7fa;
}

body {
color: var(--arc-ink);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.wy-side-nav-search {
background: linear-gradient(135deg, #12355b 0%, #0f766e 100%);
}

.wy-side-nav-search > a,
.wy-side-nav-search .wy-dropdown > a {
color: #fff;
font-weight: 700;
letter-spacing: 0;
}

.wy-nav-side {
background: #142033;
}

.wy-menu-vertical a {
color: #dbe6f3;
}

.wy-menu-vertical a:hover {
background: #20314b;
}

.wy-menu-vertical li.current > a,
.wy-menu-vertical li.on > a {
border-right: 4px solid #14b8a6;
}

.wy-nav-content {
max-width: 1040px;
}

.rst-content h1,
.rst-content h2,
.rst-content h3 {
color: var(--arc-ink);
font-weight: 750;
letter-spacing: 0;
}

.rst-content h1 {
border-bottom: 1px solid var(--arc-border);
padding-bottom: 0.35em;
}

.rst-content p,
.rst-content li {
line-height: 1.65;
}

.rst-content a {
color: var(--arc-blue);
}

.rst-content code.literal,
.rst-content tt.literal {
color: #0f4c81;
background: var(--arc-code-bg);
border: 1px solid #e4e9f0;
border-radius: 4px;
padding: 0.1rem 0.28rem;
}

.rst-content div[class^="highlight"] {
border: 1px solid var(--arc-border);
border-radius: 8px;
background: #f8fafc;
box-shadow: none;
}

.rst-content pre {
font-size: 0.9rem;
line-height: 1.5;
}

.rst-content .toctree-wrapper {
border-top: 1px solid var(--arc-border);
margin-top: 1.75rem;
padding-top: 1rem;
}

.rst-content .admonition,
.rst-content .note,
.rst-content .warning {
border-radius: 8px;
border: 1px solid var(--arc-border);
box-shadow: none;
}

.rst-content .admonition-title {
border-radius: 7px 7px 0 0;
}

.rst-content table.docutils {
border: 1px solid var(--arc-border);
}

.rst-content table.docutils td,
.rst-content table.docutils th {
border-color: var(--arc-border);
}

footer {
color: var(--arc-muted);
}
Loading