Skip to content

Fix ORCA hessian decode failing on missing CARTESIAN GRADIENT block - #47

Merged
coltonbh merged 5 commits into
atomsforhumanity:masterfrom
TroyNSmith:master
Aug 29, 2026
Merged

Fix ORCA hessian decode failing on missing CARTESIAN GRADIENT block#47
coltonbh merged 5 commits into
atomsforhumanity:masterfrom
TroyNSmith:master

Conversation

@TroyNSmith

Copy link
Copy Markdown
Contributor

Analytic Hessian jobs don't print CARTESIAN GRADIENT block in ORCA stdout. Split gradient parsing into non-required parse_gradient_hessian for Hessian calctype to prevent decode() raising when the gradient block is missing:

@register(
    filetype=OrcaFileType.STDOUT,
    calctypes=[CalcType.hessian],
    target="gradient",
    required=False,
)
def parse_gradient_hessian(contents: str) -> list[list[float]]:
    """Parse the gradient from Orca stdout for a hessian calculation.

    Analytic Hessian jobs don't print CARTESIAN GRADIENT block.
    """
    return parse_gradient(contents)

Original error:

Timings for individual modules:

Sum of individual times          ...        0.237 sec (=   0.004 min)
XTB module                       ...        0.237 sec (=   0.004 min) 100.0 %
                             ****ORCA TERMINATED NORMALLY****
TOTAL RUN TIME: 0 days 0 hours 0 minutes 0 seconds 314 msec
'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/foo/coding/autodev/autoengine/notebooks/conformer_search.py", line 43, in <module>
    hess = frequency(db, opt.geometry, model=orca_xtb, prov=InputProvenance())
  File "/home/foo/coding/autodev/autoengine/src/autoengine/run.py", line 246, in frequency
    program_output: ProgramOutput = run_program(db, calc, model, program_input)
                                    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/foo/coding/autodev/autoengine/src/autoengine/utils.py", line 124, in run_program
    return qccompute.compute(model.program, program_input)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/foo/coding/autodev/autoengine/.pixi/envs/dev/lib/python3.13/site-packages/qccompute/main.py", line 78, in compute
    return adapter.compute(
           ~~~~~~~~~~~~~~~^
        input_data,
        ^^^^^^^^^^^
    ...<10 lines>...
        **adapter_kwargs,
        ^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/foo/coding/autodev/autoengine/.pixi/envs/dev/lib/python3.13/site-packages/qccompute/adapters/base.py", line 233, in compute
    raise exc
  File "/home/foo/coding/autodev/autoengine/.pixi/envs/dev/lib/python3.13/site-packages/qccompute/adapters/base.py", line 165, in compute
    data, logs = self.compute_data(
                 ~~~~~~~~~~~~~~~~~^
        input_data,
        ^^^^^^^^^^^
    ...<3 lines>...
        **adapter_kwargs,
        ^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/foo/coding/autodev/autoengine/.pixi/envs/dev/lib/python3.13/site-packages/qccompute/adapters/orca.py", line 96, in compute_data
    raise ExternalProgramError(
    ...<4 lines>...
    ) from e
qccompute.exceptions.ExternalProgramError: Failed to parse Orca output.

@coltonbh, @avcopan may be out of town so would not be able to review. Your call on whether to review yourself--no rush either way.

Analytic Hessian jobs don't print CARTESIAN GRADIENT block in ORCA
stdout. Split gradient parsing into non-required parse_gradient_hessian
for Hessian calctype to prevent decode() raising when the gradient block
is missing.
_trj.xyz doesn't carry charge/multiplicity info, so Structure.open_multi
was silently defaulting to (0, 1) regardless of electronic state.
@TroyNSmith

Copy link
Copy Markdown
Contributor Author

Found a second bug with optimizations always returning Structure(..., charge=0, multiplicity=1) regardless of input charge/multiplicity that I've solved and added to this PR.

@coltonbh

Copy link
Copy Markdown
Collaborator

@TroyNSmith Will take a look at this Sunday/Monday :)

Thank you for this!

Also, good news--I won the grant for Atoms for Humanity so starting September I'll be working on this full time to really take these packages to the next level :)

@TroyNSmith

Copy link
Copy Markdown
Contributor Author

@coltonbh Thanks!

That's so exciting, congratulations on the award! I can't wait to see how these packages evolve over the next year!

@coltonbh

Copy link
Copy Markdown
Collaborator

@TroyNSmith apologies! Will look at this tomorrow/Wednesday! Conference is taking all my time! Thanks :)

@coltonbh coltonbh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Troy! This looks really good. Thanks for the test coverage :)

Let's just update the test to assert the correctness of the Hessian parsing too and not just the presence of the value, as that adds some robustness to our test suite.

Then I'll merge and release a new version!

Comment thread tests/test_codec.py Outdated
computed_props = decode("orca", "hessian", stdout=stdout, directory=orca_dir)

assert computed_props.gradient is None
assert computed_props.hessian is not None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update this to check for correctness too and not just that the value exists :)

Fix minor issue with parsing ORCA Hessians where only a single column
exists in the row
@TroyNSmith

Copy link
Copy Markdown
Contributor Author

@coltonbh I apologize for the delay in addressing your comment... finally settling down after 2 long months of travel 🥲

Fixed assert computed_props.hessian.tolist() == hessians.water_b3lyp

On another note:

I don't remember applying this fix, but apparently there was an issue with parsing ORCA hessians in the case where the final row of the Hessian only contains one column... that fix is now packaged into this PR. It seems like it was a regex issue (aka one-line fix). I added a test case to test_orca_parsers with appropriate data files / answers. The test files were written by hand, so the formatting may seem odd... it works, though!

On another another note:

I ran uv run ruff format before committing. It reformatted 12 files, and I'm pretty sure I didn't touch 12 files... If the format changes are an issue, tag me and I'll fix them! I'll be able to respond much quicker this time (at least for the time being--ain't no rest for the wicked 😉).

On another another another note:

I looked at CONTRIBUTING.md for guidance on your pre-commit workflow (linting, formatting, testing, ...), but I didn't see any. If this exists, then I apologize for missing them--if not, would you consider adding a section (## Pre-commit workflow)? If you feel up to implementing a hooks manager like lefthook, that would be even better! 😄

@coltonbh

Copy link
Copy Markdown
Collaborator

@TroyNSmith Thanks for the thoughts on updating CONTRIBUTING.md. Yes--this all needs to happen! AFH will kickoff full time Sept 8 and I'll be bringing all of these packages into a much nicer state for community contributions. Please continue to make requests that will facilitate your workflow and I'll get them incorporated :)

For now, let's get this fix shipped!

@coltonbh
coltonbh merged commit 73e7dd2 into atomsforhumanity:master Aug 29, 2026
9 checks passed
@coltonbh

Copy link
Copy Markdown
Collaborator

@TroyNSmith Released in v0.11.2 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants