Several Files, One Calculation

A calculation does not always arrive as one file. An HPC job that outlives its walltime is resubmitted, and the run continues in a second output. A four-file NWChem chain has its geometry optimisation in file 1 and one numerical Hessian restarted across files 2, 3 and 4, with only the last holding the finished modes. Orbitron reads such a set as one study.

The same mechanism covers the other shape: unrelated runs looked at together — an Fe calculation beside a ligand calculation, or an NWChem run beside a Molpro one. Composition is simply the case where no task continues another, so there is one concept rather than two.

What a study shows

One member is displayed and the task list spans all of them, naming which file each task came from. Three tasks in one file and three tasks in three files read the same except for that name.

Nothing merges the structures. Two members of a restart chain hold the same molecule at different points, and averaging or concatenating them would produce a geometry that never existed.

Opening one

File → Open Several as One Calculation…, then select the files in the order they were run. The Analysis → Tasks pane gains a header naming the files; clicking one shows that file’s structure.

orbitron inspect cm2mba3h2_s_1.out cm2mba3h2_s_2.out \
                 cm2mba3h2_s_3.out cm2mba3h2_s_4.out
== Study of 4 sources
  [1] cm2mba3h2_s_1.out  NWChem  2026-01-05T20:38:38
  [2] cm2mba3h2_s_2.out  NWChem  2026-01-06T18:30:52
  [3] cm2mba3h2_s_3.out  NWChem  2026-01-07T12:34:22
  [4] cm2mba3h2_s_4.out  NWChem  2026-01-08T15:48:36

== Canonical task overview, across every source
  [1] NWChem · Optimization · B3LYP
      ...
      From: cm2mba3h2_s_1.out
  [2] NWChem · Frequency · DFT
      Modes: 165
      From: cm2mba3h2_s_4.out
orbitron view jobA.out jobB.out --tui
import orbitron

study = orbitron.open_study(["jobA.out", "jobB.out"])
for task in study.tasks:
    print(task["label"], task["outcome"], "from", study.members[task["source"]]["path"])

study.show(0)          # display the first member instead
scene = study.scene()  # its structure

Every source is gated for memory the same way load_scene gates one, and a study of one gives the scene load_scene gives.

Packing one up

A study travels as a single .orbpack, which is also the only way one reaches the web viewer:

orbitron canonical export jobA.out jobB.out -o chain.orbpack

Opening that bundle gives the study back — every member, the one it was left showing, and the warnings it was packed with. Warnings are carried rather than recomputed, because they are conclusions about the sources as they were read and the bundle may end up on a machine that never had those files.

A single source produces a bundle of one member, which is the ordinary export and behaves exactly as it did.

Bundles written before schema 3.0 no longer open

manifest.json holds a list of members now, and a bundle that held one document cannot express a calculation made of several sources. Re-export the run to read it; nothing else is needed.

The order matters, and is yours

Members are read in the order you give them. Filesystem timestamps cannot supply it: copying results off a cluster with scp rewrites every one, and that copy is the workflow this exists for.

The runs record their own start time inside the file, which survives copying, so Orbitron uses it to check your order rather than to derive one. A disagreement is reported rather than silently corrected:

! the members are not in the order their own runs record
  (2026-01-08T15:48:36 before 2026-01-05T20:38:38); check the sequence

Members that name different calculations are reported the same way, and their tasks are never joined. Three formats state such a name — NWChem’s .db prefix, Gaussian’s %chk, QMCPACK’s <project id> — and a disagreement between two of them settles the question: neither run continues the other, however well their tasks line up. Silence does not, because most formats name nothing and a chain would then never join.

That a set names different calculations is not an error: viewing an Fe run beside a ligand run is a legitimate composition. It catches the stray file picked up by accident, which would otherwise merge into a chain in silence.

What continues, and what does not

A task continues an earlier one when it is the same program and the same kind, the two members do not name different calculations, and the earlier one did not finish. That is the only thing separating a restart from a re-run: the same deck submitted twice produces two identical task lists, and neither file says which happened.

A task whose outcome is unknown is left alone rather than guessed at. The formats that state nothing per task are also the ones whose files are most often unrelated runs, and merging two single points that merely look alike would be a guess with a scientific answer attached.

How the instances of a continued task combine depends on the kind:

Task kind Joined by
Optimization, MD concatenating the step history — the instances are successive parts of one walk
Frequency taking the instance that completed; a numerical Hessian’s earlier attempts hold no result of their own
everything else taking the last; a single point recomputed after a restart supersedes the earlier attempt

The walk itself

The table above joins a task’s account — its energy, outcome and step count. The frames are a separate, explicit request, because concatenating everything a study holds would produce a walk no run took:

walk = study.joined_trajectory(0)   # by position in `study.tasks`
print(len(walk), "steps")

Only a concatenating kind will do it; asking a frequency is refused by name rather than silently returning its displacement geometries as a trajectory.

A restart re-reports the geometry it resumed from, and that repeated step is dropped. A split water optimisation measured in NWChem 7.2.3 has three steps in part 1 and two in part 2, and the joined walk is four: part 2’s step 0 is part 1’s step 2, to all eight printed decimals. The two energies differ by 3e-9 Ha because part 2 re-converged the SCF there, which is why the repeat is found on coordinates rather than on energy — exact equality, with no tolerance to get wrong.

A restart that prints no geometry

An NWChem restart job without an echo prints no coordinates at all — the geometry came from the .db. Such a file cannot be read on its own, and Orbitron says so:

Error: failed to parse 'jobB.out': Unable to determine NWChem structure snapshot

Inside a study it reads: the member inherits its predecessor’s geometry, and the document records that it did, so nothing downstream can mistake it for a geometry the file stated. A restart cannot be the first member — there is nothing to inherit from — and the error names the file rather than the set.