Give each test class its own scratch directory instead of writing into arc/testing - #1008
Closed
calvinp0 wants to merge 7 commits into
Closed
Give each test class its own scratch directory instead of writing into arc/testing#1008calvinp0 wants to merge 7 commits into
calvinp0 wants to merge 7 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1008 +/- ##
==========================================
- Coverage 64.60% 64.57% -0.04%
==========================================
Files 119 119
Lines 39785 39785
Branches 10307 10307
==========================================
- Hits 25703 25690 -13
- Misses 11105 11114 +9
- Partials 2977 2981 +4
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
added a commit
that referenced
this pull request
Aug 22, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. ONLY THE STABILITY JOB READS A GUESS. Uploading a previous job's orbitals to every ORCA job would change the SCF starting point of the whole workflow, including jobs at a different level or basis, which is a larger change than this one and is not needed by anything here: the stability analysis is the only job whose result depends on converging to a particular one of several solutions. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 22, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 22, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 22, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 22, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 23, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 23, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 23, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
ARC_TESTING_PATH holds read-only fixture inputs. Passing a subdirectory of it as a project_directory made every test class in these modules write into one shared, fixed path, and tearing that path down with shutil.rmtree at the end of the class. Under pytest-xdist a single TestCase class is split across workers, so every worker runs tearDownClass. One worker therefore deletes the shared directory while another is still writing input files into it, which surfaces as FileExistsError / FileNotFoundError on an unrelated test. A crashed run also leaves the directory behind inside the repository. Each class now allocates its scratch with tempfile.mkdtemp() in setUpClass and releases it with addClassCleanup. mkdtemp is unique per setUpClass invocation, so concurrent workers never share a path and nothing is ever written under arc/testing. Read-only fixture reads (the PBS time-limit err.txt in adapter_test) still come from ARC_TESTING_PATH and are unchanged.
Same change as for the ESS job adapters: the TS search adapter tests wrote their project directories into ARC_TESTING_PATH and removed them from tearDownClass or from ad-hoc per-test cleanup helpers. Scratch now comes from tempfile.mkdtemp() and is released with addClassCleanup / addCleanup. The KinBot helper that removed a single test's subdirectory and then attempted to rmdir the shared parent existed only to make the shared parent safe under xdist; with a per-class temporary root the whole tree is released at once and the helper is dropped. gcn_test.py also drops the `from arc.job.adapters.ts.gcn_ts import GCNAdapter` line, which duplicated the `import arc.job.adapters.ts.gcn_ts as ts_gcn` already present; kinbot_test.py imports unittest.mock as mock rather than `from unittest import mock` alongside `import unittest`.
These modules built their project directories under ARC_TESTING_PATH and removed them in tearDownClass, which is not safe when xdist splits the class across workers. Both UMA test classes now allocate their own mkdtemp root, so the env-independent and model-dependent classes can no longer reach into each other's tree either.
Four tests treated a fixture directory as writable scratch: - common_test.test_globalize_paths wrote restart_paths_globalized.yml into arc/testing/restart/4_globalized_paths, which needed a self-healing cleanup helper called from both setUpClass and tearDownClass to keep the artifact from leaking into the repo. The fixture is now copied into a temporary directory and globalized there, and the two assertions that hard-coded the arc/testing path now assert against the temporary project directory. - common_test.test_safe_copy_file copied its destination file next to the source fixture. - processor_test.test_compare_rates wrote rate plots into arc/testing/process_kinetics. - reaction_test.test_load_ts_xyz_user_guess_from_files passed the fixture directory itself as an ARC project_directory, so a Scheduler run created arc.log, output/ and log_and_restart_archive/ inside arc/testing/reactions/methanoate_hydrolysis. The fixture is now copied to a temporary directory first; the TS guess filenames in input_1.yml and input_2.yml resolve relative to project_directory, so the copy keeps them working. - arkane_test.TestArkaneAdapter released its mkdtemp from tearDownClass rather than addClassCleanup, and wrote generate_arkane_input output into arc/testing.
The TestNMD and TestTSChecks classes built their job project directories under ARC's shared Projects folder and deleted them in tearDownClass. pytest-xdist may split a single TestCase class across workers, so each worker runs setUpClass and tearDownClass independently and one worker's teardown removes a directory another worker is still using. Allocate the scratch with tempfile.mkdtemp() in setUpClass and release it with addClassCleanup instead.
…irectories TestARC instantiated ARC without a project directory, so every instance created a directory named after its project under ARC's shared Projects folder, several of which were never deleted. TestPlotter additionally wrote its multi-species logs, its BDE report and its IRC animation into the read-only arc/testing fixture tree, where one test asserted the absence of files another test had created. Give each of them a tempfile.mkdtemp() scratch directory released through addCleanup or addClassCleanup, and drop the tearDownClass removals of shared paths. The gcn_tst cleanup entry in species_test is dropped as well; nothing creates that directory any more.
The restart tests derived their project directories from a per-xdist-worker project name, which does not help when pytest-xdist splits the class across workers. Allocate each project directory with tempfile.mkdtemp() and release it with addCleanup.
calvinp0
force-pushed
the
fix_test_scratch_isolation
branch
from
August 23, 2026 12:40
54c0848 to
a63e083
Compare
alongd
pushed a commit
that referenced
this pull request
Aug 23, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict.
calvinp0
added a commit
that referenced
this pull request
Aug 23, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict. AN EMPTY ORBITALS FILE IS NOT READ AS A GUESS. reads_orbital_guess tests the size of the checkfile as well as its presence: the server-side copy of a .gbw an ORCA job died before writing is silent, and a failed download leaves a zero-byte file behind, so the file can be present and empty at the moment the input is composed. The adapter's fallback to an orbitals file sitting in its own job directory goes through readable_checkfile, which applies the same test, and is refused outright while the species carries an adopted wavefunction-stability verdict and holds no checkfile, in which state the route to the lower solution is BrokenSym rather than a guess.
calvinp0
added a commit
that referenced
this pull request
Aug 23, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict. AN EMPTY ORBITALS FILE IS NOT READ AS A GUESS. reads_orbital_guess tests the size of the checkfile as well as its presence: the server-side copy of a .gbw an ORCA job died before writing is silent, and a failed download leaves a zero-byte file behind, so the file can be present and empty at the moment the input is composed. The adapter's fallback to an orbitals file sitting in its own job directory goes through readable_checkfile, which applies the same test, and is refused outright while the species carries an adopted wavefunction-stability verdict and holds no checkfile, in which state the route to the lower solution is BrokenSym rather than a guess.
calvinp0
added a commit
that referenced
this pull request
Aug 24, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict. AN EMPTY ORBITALS FILE IS NOT READ AS A GUESS. reads_orbital_guess tests the size of the checkfile as well as its presence: the server-side copy of a .gbw an ORCA job died before writing is silent, and a failed download leaves a zero-byte file behind, so the file can be present and empty at the moment the input is composed. The adapter's fallback to an orbitals file sitting in its own job directory goes through readable_checkfile, which applies the same test, and is refused outright while the species carries an adopted wavefunction-stability verdict and holds no checkfile, in which state the route to the lower solution is BrokenSym rather than a guess.
calvinp0
added a commit
that referenced
this pull request
Aug 25, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict. AN EMPTY ORBITALS FILE IS NOT READ AS A GUESS. reads_orbital_guess tests the size of the checkfile as well as its presence: the server-side copy of a .gbw an ORCA job died before writing is silent, and a failed download leaves a zero-byte file behind, so the file can be present and empty at the moment the input is composed. The adapter's fallback to an orbitals file sitting in its own job directory goes through readable_checkfile, which applies the same test, and is refused outright while the species carries an adopted wavefunction-stability verdict and holds no checkfile, in which state the route to the lower solution is BrokenSym rather than a guess.
calvinp0
added a commit
that referenced
this pull request
Aug 26, 2026
Adds the ORCA side of the 'stability' job type: a single point at the frequency level and on the frequency geometry that adds STABPerform and STABRestartUHFifUnstable to the existing %scf block, reading the orbitals of the job under test. THE INSTABILITY IS ALWAYS FOLLOWED, and that is not a preference. With STABRestartUHFifUnstable false, ORCA 6.0.0 prints the verdict and the stability-matrix roots and then dies in LEANSCF with a BLAS incompatible-matrices error and mpirun exit code 62. Measured at eight processes and at one, and at six roots and at three, so it is not an MPI artifact; LeanSCF false does not help, failing earlier, in the SCF, before any verdict is printed. The three stable jobs run to a normal termination on the same settings, so it is the re-entry into LeanSCF after an instability that breaks. ORCA therefore has no equivalent of Gaussian's NoOpt, which reports an instability without following it. With the key true the job terminates normally and the log holds two analyses; the parser reads the verdict of the first, which is the wavefunction under test. A crashed job would additionally be misread by determine_ess_status, whose orca branch matches 'error termination in SCF' and not 'in LEANSCF', so the job would be an unrecognised error and the verdict never read. THE ORBITALS UNDER TEST ARE HANDED OVER, because ORCA's analysis is an SCF post-step: it converges an SCF first, and from its own initial guess that need not be the solution the frequency job reached. This is the hazard Gaussian's checkfile requirement exists to prevent, and ARC's scheduler already refuses to spawn the job unless the species still holds the checkfile its frequency job used. ORCA names its own orbitals after the input file, so it cannot read and write one file the way Gaussian reuses a single checkfile: the previous orbitals are uploaded as guess.gbw and read with !MORead and %moinp, while the job's own input.gbw is downloaded and becomes the next job's guess. The adapter adopts a checkfile on construction the way the Gaussian adapter does. INPUT.GBW IS DOWNLOADED ONLY WHERE SOMETHING READS IT. A def2-TZVP .gbw runs to tens of MB and the job type is off by default, so downloading one from every ORCA job would cost every run bandwidth and disk for a file nothing opens. It is fetched for the job types the guess chain actually reads from -- the opt, optfreq and composite jobs Scheduler.end_job adopts a checkfile from -- plus the stability job, whose own orbitals are the relaxed solution. A job array takes the data.hdf5 branch and fetches no orbitals at all, since its members share one remote path; the docstring now says so rather than leaving it to be inferred. EVERY ORCA JOB THAT RUNS AN SCF READS THE GUESS, as every Gaussian job carrying a checkfile gets guess=read. OrcaAdapter.reads_orbital_guess is the single predicate behind both halves of it, the !MORead and %moinp keywords and the guess.gbw upload, so the file is uploaded for exactly the jobs that read it; emitting the keywords without the file aborts the job on a missing guess. ORBITALS_GUESS_JOB_TYPES holds the job types this adapter writes an SCF on one starting structure for: opt, conf_opt, optfreq and scan, whose first SCF the guess seeds and whose later points ORCA propagates orbitals through itself, and freq, sp, conf_sp and stability, each a single SCF. The rest are the job types write_input_file emits no keyword for, so ORCA is handed no calculation for a guess to seed -- composite, for which ORCA offers no composite method; irc and orbitals; and directed_scan, for which this adapter writes neither the scan block nor the constraints such a job needs -- plus gen_confs, tsg and onedmin, which belong to other adapters. A job array is excluded because it writes no input file and its members share one remote path, where one uploaded guess would stand in for every member, and a monatomic species because ARC spawns it neither an optimization nor a frequency job. WHAT THE CHAIN BUYS IS MEASURED. On a C5H10 TS at UKS B3LYP/def2-TZVP, same geometry and same input but for the guess, a fresh guess collapsed to the closed-shell solution (E = -196.344572 Eh, <S**2> = 0.000000) while !MORead held the broken-symmetry solution (E = -196.364789 Eh, <S**2> = 0.864739), reproducing the followed solution to 1e-9 Eh -- 12.7 kcal/mol apart. Without the chain the freq job converges from ORCA's own initial guess while the stability job reads the optimization's orbitals, and those are two different SCF solutions in exactly the cases the analysis exists to find. NO LEVEL OR BASIS IS TRACKED, because ORCA projects a guess written in another basis onto the basis of the job reading it. A def2-SVP job reading a def2-TZVP .gbw logs 'Atom 0: N(Shells)= 6 and 11 - projection required' and terminates normally at a sane def2-SVP energy, so the chain crosses the basis change ARC makes between the optimization and the single point on its own. The predicate is whether a checkfile this ESS wrote exists, and no new state is stored on the species, in the restart dict or in output.yml. The single point runs on defgrid3, the grid a frequency job uses, rather than the defgrid2 an sp would take, so the SCF under test integrates on the grid the Hessian was built on. The input template gains two placeholders that render empty for every other job type, so every existing ORCA input is emitted byte for byte as before. The test module's project directory moves from a shared path under arc/testing to a private tempfile.mkdtemp(), which is what the project requires of writable test scratch. It adopts the exact form open PR #1008 uses for the same file -- cls.scratch_dir = tempfile.mkdtemp(prefix='arc_test_orca_') with project_directory=os.path.join(cls.scratch_dir, 'test_OrcaAdapter') -- so the two PRs' overlapping lines are textually identical and merge without conflict. AN EMPTY ORBITALS FILE IS NOT READ AS A GUESS. reads_orbital_guess tests the size of the checkfile as well as its presence: the server-side copy of a .gbw an ORCA job died before writing is silent, and a failed download leaves a zero-byte file behind, so the file can be present and empty at the moment the input is composed. The adapter's fallback to an orbitals file sitting in its own job directory goes through readable_checkfile, which applies the same test, and is refused outright while the species carries an adopted wavefunction-stability verdict and holds no checkfile, in which state the route to the lower solution is BrokenSym rather than a guess.
Member
Author
|
Superseded by #1028, which rebases this onto current Closing in favour of #1028 rather than rebasing this one separately, since the two overlap in intent and |
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.
Test classes were writing scratch into
ARC_TESTING_PATH, which holds read-only fixture inputs. Nineteen files did it, and eight of themrmtree'd a subdirectory of it in a teardown — so one module's cleanup deleted a directory another module was still writing into.The result is a suite that is broadly unstable under xdist. Measured on
main, each module run solo under-n 4 --dist worksteal, three runs each:mainorca_testxtb_testadapter_testmolpro_testobabel_testmockter_testcfour_testarkane_testPaired (7 job-adapter modules together, 5 runs):
5 failed, 58 passed× 5 →63 passed× 5.Solo failure is the important column.
--dist workstealcan split a singleTestCaseclass across workers, so each worker independently runssetUpClassandtearDownClass— a class does not own its directory merely because only that class uses it. A per-worker path suffix does not fix this;tempfile.mkdtemp()does, because it is unique persetUpClassinvocation.What changed
Every converted class allocates scratch with
tempfile.mkdtemp()insetUpClass/setUpand releases it viaaddClassCleanup/addCleanup. AlltearDownClassrmtrees ofARC_TESTING_PATHsubdirectories are gone. Read-only fixture reads are untouched — those are shared safely, because nobody writes to them.Eight of the nineteen were not findable by grepping for
rmtree(os.path.join(ARC_TESTING_PATH,…))because they build the path through a variable:pyscf_test,ase_test,uma_test,ts/orca_neb_test,ts/kinbot_test,ts/gcn_test,processor_test,common_test,reaction_test.Cases needing more than a mechanical rewrite
common_test.test_globalize_pathsasserted on a literal repo path. The fixture is nowcopytree'd into a tmpdir and both assertions rebuilt fromproject_directory— same semantics, and it allowed deleting_clean_globalized_restart_artifact(), a self-healing helper that existed only because the test wroterestart_paths_globalized.ymlback into the repo on every run.reaction_test.test_load_ts_xyz_user_guess_from_filespassed a fixture directory as an ARCproject_directory, so a Scheduler run createdarc.log,output/andlog_and_restart_archive/insidearc/testing/reactions/methanoate_hydrolysis. Itsts_xyz_guessentries resolve relative toproject_directory, so the fixture is copied and the run happens in the copy.kinbot_testhad a hand-rolled_remove_test_dirwritten specifically to survive xdist; a per-class tmp root makes it dead code.Not touched
arc/job/adapters/gaussian_test.pyandarc/job/adapters/common_test.pyare #1001's files and are converted there. They remain the one genuinely cross-module shared directory onmain, and Group C measurements confirm that pair still races here — unchanged, as expected.Verification
Full suite, serial:
main5 failed, 2803 passed, 36 skipped (386 s) → branch 5 failed, 2803 passed, 36 skipped (413 s). Identical counts; the 5 are the knowntorch_ani_testenvironmental failures.git status --porcelainclean after both runs — noarc/testing/debris left behind.Mutation-verified: reverting
orca_testtomain's version brings the failures straight back (1F+15P+4E,2F+18P,1F+19P), restoring it gives20 passed× 3; same forxtb_test. Restored files md5-matched their snapshots.Four commits, no file in more than one. Two pre-existing
py/import-and-import-fromviolations fixed in files already being touched (gcn_test,kinbot_test).🤖 Generated with Claude Code