abinit
FreeGenerate and manage ABINIT DFT calculations. Use when the user requests ABINIT, or needs DFPT phonons, GW calculations, or BSE optical spectra.
The English summary is being prepared. Showing the original description.
Generate ORCA input files for TD-DFT UV-Vis calculations and parse/plot the resulting absorption spectrum. Use when the user asks about UV-Vis spectra, absorption spectra, TD-DFT calculations, excited state calculations in ORCA, or wants to plot results from an ORCA TD-DFT output file. Also trigger when the user mentions oscillator strengths, electronic transitions, or simulated UV-Vis.
The English summary is being prepared. Showing the original description.
Run score Not tested
See how to installReview the instructions the agent will receive before you install.
This skill covers two stages: generating an ORCA input file for a TD-DFT calculation, and post-processing the output to plot a Gaussian-broadened UV-Vis absorption spectrum.
Scope: Input generation, local post-processing, and (optionally) HPC submission via the CatGo workflow engine. The "Submitting to HPC" section below covers the proven Expanse flow. If the user is running on their own non-CatGo infrastructure, just generate the input file from the template in Stage 1 and skip the submission section.
Target version: ORCA 6.x. Output block layout in ORCA 5 is close but not identical; the parser below is written against the ORCA 6 format used by CatGo's own parser (server/catgo/utils/orca_output.py::OrcaUvVisOutput).
Before generating the input file, ask the user for:
orca-opt first)0 1 if not specified)Generate an ORCA input file with these fixed settings:
CAM-B3LYPDEF2-TZVPTemplate:
!CAM-B3LYP DEF2-TZVP CPCM(HEXANE)
%TDDFT
NROOTS 30
END
%output jsongbwfile True jsonpropfile True end
*XYZFILE 0 1 geometry.xyz
Substitute the user's solvent, charge, multiplicity, and XYZ path. If the user provides inline coordinates instead of a file, use * XYZ <charge> <mult> followed by the coordinates and close with *.
The %output ... end line makes ORCA emit the JSON files OPI's Output.parse() consumes during post-processing (Stage 2). Keep it.
%tddft block with OPIOPI's BlockTddft exposes every TD-DFT knob (nroots, iroot, irootmult, maxdim, maxiter, etol, rtol, tda, lrcpcm, cpcmeq, donto, saveunrnatorb, spinflip, soc, socgrad, triplets, ...) as a typed Pydantic field. Bad keys raise at construction.
The catgo backend builds the route line, %pal, %maxcore, charge/multiplicity, and geometry from node params — it does not emit a %TDDFT block of its own. So OPI only contributes the %tddft and %output blocks here, which we paste into extra_blocks as text. Do not use Calculator.write_input() — that writes a full input file and would duplicate the route line / pal / geometry the backend already emits.
from opi.input.blocks import BlockTddft, BlockOutput
tddft_block = BlockTddft(nroots=30, tda=False, triplets=False, donto=True)
output_block = BlockOutput(jsongbwfile=True, jsonpropfile=True)
extra_blocks_text = tddft_block.format_orca() + "\n" + output_block.format_orca()
# Pass extra_blocks_text into the node's `extra_blocks` param.
format_orca() emits exactly one %...end block per call. The result for the snippet above is:
%tddft
nroots 30
tda False
donto True
triplets False
end
%output
jsonpropfile True
jsongbwfile True
end
TD-DFT with 30 roots at def2-TZVP is expensive — tell the user this is a heavy calculation and that they should expect to run it on a cluster or at least overnight on a workstation, not on a laptop.
Use this when the user wants the CatGo workflow engine to run the TD-DFT job on Expanse. Skip if they only want the input file.
Use
catgo_workflow(graph-based), NOTcatgo_workflow_engine(task-based). The graph-based tool auto-captures the viewer structure oncreate. Task-basedadd_taskdoesn't, so jobs fail with "No input structure provided". Param keys differ: graph-based usesmethod/basis, task-based usesorca_method/orca_basis.
catgo_view(action: "get_state")
curl -s http://localhost:8000/api/hpc/connections
Copy the session_id for host: login.expanse.sdsc.edu.
catgo_workflow(action: "create", name: "UV-Vis CAM-B3LYP TD-DFT")
Use the orca_uvvis node type, which has dedicated TD-DFT params (nroots, triplets, tda, donto, solvation, solvent, calc_type, aux_basis) plus the standard dispersion field. Do NOT use extra_keywords or extra_blocks — they are NOT read by the engine and are silently dropped.
catgo_workflow(action: "batch", workflow_id: "<wf_id>", operations: [
{"op": "add_node", "node_type": "orca_uvvis", "label": "tddft",
"params": {
"software": "orca",
"method": "CAM-B3LYP",
"basis": "def2-TZVP",
"calc_type": "tddft",
"nroots": 30,
"tda": false,
"triplets": false,
"donto": true,
"solvation": "CPCM",
"solvent": "hexane",
"dispersion": "D4",
"charge": 0,
"multiplicity": 1,
"num_cores": 16,
"max_core_mb": 4000
}},
{"op": "connect", "from_id": "<structure_input_id>", "to_id": "tddft",
"from_handle": "structure", "to_handle": "structure"}
])
| Parameter | Default | Description |
|---|---|---|
method | CAM-B3LYP | Functional |
basis | def2-TZVP | Basis set |
dispersion | (none) | D4 | D3BJ | D3 |
calc_type | tddft | tddft or steom (STEOM-DLPNO-CCSD) |
nroots | 10 | Number of excited states |
tda | true | Tamm-Dancoff approximation; pass false for full TD-DFT |
triplets | false | Compute triplet states |
donto | false | Natural transition orbitals |
solvation | none | CPCM | none |
solvent | water | Any ORCA-recognised solvent name |
aux_basis | def2-TZVP/C | Aux basis (used by STEOM path) |
num_cores / max_core_mb | 4 / 4000 |
TD-DFT with 30 roots at def2-TZVP is heavy — bump walltime and use shared
or compute (debug caps at 30 min). Read server/templates/orca_generic.sh
and pass its contents as default_template.
catgo_workflow(action: "run", workflow_id: "<wf_id>", run_config: {
"execution_mode": "hpc",
"default_session_id": "<expanse_session_id>",
"base_work_dir": "/expanse/lustre/projects/sdp126/jyang25/ORCA/catgo",
"default_job_params": {
"nodes": 1, "ntasks": 16, "cpus_per_task": 1,
"walltime": "12:00:00", "partition": "shared"
},
"cluster_configs": {
"<expanse_session_id>": {
"account": "sdp126",
"partition": "shared",
"module_loads": "module load cpu/0.17.3b\nmodule load gcc/10.2.0/npcyll4\nexport PATH=$HOME/openmpi-4.1.8/bin:$PATH\nexport LD_LIBRARY_PATH=$HOME/openmpi-4.1.8/lib:$LD_LIBRARY_PATH",
"orca_dir": "/home/jyang25/orca_6_1_1_RRP8",
"default_template": "<contents of server/templates/orca_generic.sh>",
"default_job_params": {
"nodes": 1, "ntasks": 16, "cpus_per_task": 1,
"walltime": "12:00:00", "partition": "shared"
}
}
}
})
The local-scratch template stages I/O to $TMPDIR/orca_$SLURM_JOB_ID and copies
results back. Required on Expanse — Lustre kills ORCA's many-small-file I/O during
the 30-root TD-DFT response solver.
catgo_workflow(action: "status", workflow_id: "<wf_id>")
When status is COMPLETED, pull ORCA.out plus the JSON files OPI parses,
then run the parser/plotter from Stage 2 below against the local copy:
mkdir -p ./local_run
for f in ORCA.out ORCA.property.json ORCA.json; do
curl -s -X POST http://localhost:8000/api/hpc/files/read-content \
-H 'Content-Type: application/json' \
-d "{\"session_id\":\"<expanse_session_id>\",\"file_path\":\"<work_dir>/$f\"}" \
> ./local_run/$f
done
catgo_workflow_engine.add_task doesn't auto-attach the viewer structure → "No input structure provided".partition=workq (Shaheen default) is invalid on Expanse → use debug/shared/compute.partition=debug capped at 30 min — TD-DFT/30-roots almost always needs more.account=sdp126 → "Invalid account or account/partition combination".module_loads + orca_dir → orca not on PATH; the response solver silently produces nothing./api/hpc/connections and update both default_session_id and the cluster_configs key.OPI surfaces the absorption spectrum as output.results_properties.geometries[-1].absorption_spectrum — a list[Spectrum] keyed by representation ("Length" / "Velocity") and pointgroup. This replaces the regex parser entirely:
rfind-vs-find STEOM-DLPNO-CCSD workaround is unnecessary; the model returns one entry per (representation, pointgroup) and you pick the one you want.Spectrum shape.geometries[-1].ecd_spectrum.Spectrum.excitationenergies is a list of rows; columns are unnamed in the model but the order for ORCA 6.1.1 is fixed at [energy_eV, energy_cm, wavelength_nm, fosc, |mu|^2]. The shared helper exposes this as UVVIS_COLS.
import sys
sys.path.insert(0, ".claude/skills") # for the _shared helper
import numpy as np
import matplotlib.pyplot as plt
from _shared.orca_opi import parse_local, UVVIS_COLS
def parse_orca_tddft(work_dir="./local_run"):
out = parse_local(work_dir)
spectra = out.results_properties.geometries[-1].absorption_spectrum
if not spectra:
raise ValueError("No absorption_spectrum block found — check ORCA.property.json")
# Prefer length representation; fall back to whatever's first.
target = next((s for s in spectra if s.representation == "Length"), spectra[0])
wl_col = UVVIS_COLS["wavelength_nm"]
f_col = UVVIS_COLS["fosc"]
wavelengths = np.array([row[wl_col] for row in target.excitationenergies])
fosc = np.array([row[f_col] for row in target.excitationenergies])
return wavelengths, fosc
def gaussian(x, center, height, sigma=15):
return height * np.exp(-0.5 * ((x - center) / sigma) ** 2)
def plot_uv_vis(wavelengths, fosc, output_png="uv_vis_spectrum.png"):
x = np.linspace(200, 800, 2000)
spectrum = sum(gaussian(x, w, f) for w, f in zip(wavelengths, fosc))
peak = spectrum.max()
if peak > 0:
spectrum = spectrum / peak
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, spectrum, color="#2563eb", linewidth=1.5, label="Broadened")
f_peak = fosc.max() if fosc.size and fosc.max() > 0 else 1.0
ax.vlines(wavelengths, 0, fosc / f_peak, color="#ef4444", alpha=0.7, label="Transitions")
ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("Normalized Absorbance")
ax.set_xlim(200, 800)
ax.set_ylim(0, 1.05)
ax.legend(loc="upper right", frameon=False)
fig.tight_layout()
fig.savefig(output_png, dpi=150)
print(f"Spectrum saved to {output_png}")
if __name__ == "__main__":
work_dir = sys.argv[1] if len(sys.argv) > 1 else "./local_run"
png_name = sys.argv[2] if len(sys.argv) > 2 else "uv_vis_spectrum.png"
wl, f = parse_orca_tddft(work_dir)
plot_uv_vis(wl, f, png_name)
After plot_uv_vis(...) writes the PNG, surface it inline with the shared helper:
from _shared.orca_opi import show_png
show_png("uv_vis_spectrum.png", "UV-Vis spectrum")
# prints ``
Then reply to the user with that markdown link so Claude Code renders the figure inline in chat.
#2563eb (blue), sticks #ef4444 (red) — matches CatGo's red-TS / blue-accent conventionsIf the user asks for eV instead of nm, convert via E_eV = 1240 / wavelength_nm and rebuild the x-grid from (e.g.) 1.5–6.5 eV. Broadening σ of ~0.3 eV is a sensible default in eV space.
No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
Generate and manage ABINIT DFT calculations. Use when the user requests ABINIT, or needs DFPT phonons, GW calculations, or BSE optical spectra.
The English summary is being prepared. Showing the original description.
Use when the user asks to place an adsorbate molecule on a surface, find adsorption sites, or set up a surface+adsorbate model for DFT.
The English summary is being prepared. Showing the original description.
Use when the user asks for adsorption energy, binding energy, or wants to compare how strongly a molecule binds to a surface.
The English summary is being prepared. Showing the original description.
Use when the user asks to analyze computational results: Gibbs free energy, OER/HER/CO2RR overpotentials, adsorption energy, convergence tests, DOS/d-band analysis, or Bader charge analysis.
The English summary is being prepared. Showing the original description.
Use AmberTools antechamber for molecular force field parameterization. Generates GAFF/GAFF2 parameters and AM1-BCC or RESP charges for use in AMBER or LAMMPS classical MD simulations.
The English summary is being prepared. Showing the original description.
One-shot recipes for adding, deleting, moving, and replacing individual atoms in the active CatGo viewer structure. Use whenever the user asks to "add an atom", "delete atoms", "remove this atom", "move atom N", "replace H with Li", or any single-atom edit — including "add a hydrogen on top of atom 12" / "delete atoms 5–9" / "swap the oxygen at site 3 for fluorine". Skips the discovery loop (no need to list structure tools or check adsorption sites first); goes straight to the matching `catgo_structure` action. Triggers in Chinese on 加原子, 删原子, 减原子, 移动原子, 替换原子, 增加氢, 删除氧, 把 ... 换成 ....
The English summary is being prepared. Showing the original description.