Skip to content

Brute-force directed scans optimize freely at every point (Scheduler.run_job passes constraints=None) — flat V(φ) #986

Description

@alongd

Summary

A brute-force directed scan (directed_rotors: {brute_force_opt: [...]}) optimizes freely at every dihedral point instead of holding the scanned dihedral, so every point relaxes to the same minimum and the resulting V(φ) is flat (≈ zero barrier). This is silent — no error, just a wrong potential — and it is not software-specific: it reproduces on the Gaussian adapter as well as on the ASE adapter.

Root cause

Scheduler.run_job() always passes constraints=None, and no adapter derives a constraint from the torsions + dihedrals it is handed instead. So the per-point optimization that a directed scan spawns has nothing pinning the scanned dihedral, and each point optimizes to the nearest minimum.

Signature of the bug: for a directed scan, the relaxed energies across all points span ≈ 0 (a flat V(φ)), because every point collapsed to the same geometry.

Evidence

Found while running UMA (fairchem) hindered-rotor scans through the generic ASEAdapter on a cluster. With the ASE adapter made to translate torsions+dihedrals into a FixInternals constraint, the same DMH N–N torsion that had given a flat V(φ) instead held each point's dihedral to 0.000° and produced an 8.5 kJ/mol barrier. Tracing it showed the missing constraint originates upstream of any adapter, in run_job() — hence it affects Gaussian brute-force directed scans too.

Scope / workaround

PR #985 (queue-executed ASE/UMA jobs) works around this inside the ASE adapter only — it derives the constraint locally so UMA rotor scans are correct. The general fix — deriving the constraint in Scheduler.run_job() (or having each adapter honor torsions+dihedrals) so all brute-force directed scans are constrained — is out of scope for that PR and is what this issue tracks.

Suggested fix

In Scheduler.run_job() / the directed-scan spawn path, translate the job's torsions + dihedrals into the constraints argument (1-indexed atom tuples + target value) before dispatch, so every adapter receives a real constraint. Add a regression check that a brute-force directed scan on a floppy rotor produces a non-flat V(φ).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions