# Checkpoints: state, accessors, save & load

The **checkpoint** is the central object of qc-rs — every calculation is a checkpoint you build, extend, run,
and query. [Core concepts](../00-intro/concepts.md) introduced the model; this page is the reference for what
a checkpoint holds and the API to read and persist it.

## What a checkpoint holds

A checkpoint bundles:

- the **molecular input** — geometry, basis (`ao`), `charge`, `spin`, `ao_rep`, and the resolved `iop` map;
- the **current electronic state** — `current_mo` (row-MO coefficients) + `current_density`, updated by the
  guess, SCF, and CASSCF;
- **materialized results** — the SCF/LCT/opt/property records;
- **workflow metadata** — the pending graph, trace/restart metadata, and cache metadata.

The current MO/density is a *single* current set (guess, SCF, and CASSCF update it in place, not per-stage
copies). Coordinates are stored in **bohr**.

## Building and inspecting

```python
import qc
m = qc.chk.new(atom="O 0 0 0.117; H 0 0.757 -0.469; H 0 -0.757 -0.469",
               ao="cc-pvdz", unit="angstrom")

# molecular accessors (some are properties, some methods — note the ())
m.natom                 # 3            (property)
m.symbols               # ['O','H','H']
m.charge, m.spin        # (0, 1)
m.nelectron()           # 10           (method)
m.coordinates()         # (natom, 3) array, bohr
m.nuclear_energy()      # scalar, hartree
m.dummy_atoms(), m.translation_vectors()   # special atoms
```

## Adding steps: functional and method forms

Every workflow verb exists both ways — identical behavior:

```python
qc.scf(m, ref="r")      # functional
m.scf(ref="r")          # method-chain — the same pending step
```

The verbs: `guess`, `ints`, `scf`, `casscf`, `fci`, `dmrg`, `lct`, `td`, `.opt()`, plus `qc.grad`. Adding a
step does **no** heavy computation — it returns a new checkpoint with a pending node. **`.run()`** materializes
the results.

## Reading results

After `.run()`, the step accessors expose the materialized records:

```python
m = m.scf(ref="r").run()
m.scf.energy            # -76.026794
m.scf.converged         # True
m.scf.ncycle            # 9
m.scf.energy_components # {'core':..., 'coulomb':..., 'exchange':...}
m.scf.gradient          # forces (after a gradient/opt)

m.lct.energy, m.lct.e_corr        # after lct(method="mp2")
m.opt.converged, m.opt.energy     # after .opt()
m.prop.chrg.hirshfeld()           # properties (the qc.prop namespace)
```

Before `.run()`, `m.scf` is a *pending* node; after, it is the *result* accessor.

## Logging and display

```python
m.run(log="stdout")   # stream the live transcript
m.log(format="text")  # replay the stored transcript ("text"/"markdown"/"jsonl")
m.show("result")      # rendered state/result snapshot
m.run_events()        # raw event stream: list of JSON strings
```

See the [logging chapter](../20-guide/logging-output.md).

## Save and load

A checkpoint persists to an **HDF5 `.qch5`** file and reloads into a queryable/extendable checkpoint:

```python
m.save("water.qch5")            # persist state + results + pending metadata + transcript
r = qc.chk.load("water.qch5")   # restore

r.scf.energy                    # -76.026794   results survive the round-trip
r.scf(xc="b3lyp").run()         # add more steps to the loaded checkpoint
```

`save`/`load` is how you **stop and resume**: run an expensive step once, save, and later load to compute
properties, optimize, or restart — no recomputation. (Session-sticky parallelism from `run(nthread=/nmpi=)`
is **not** saved.)

## Importing orbitals: `guess("read")`

`guess("read", source="other.qch5", irreps=...)` imports and projects the MOs from another checkpoint into
the current basis — for restart or cheap-basis → big-basis stepping ([initial-guess chapter](../20-guide/initial-guess.md)).
`irreps` is `"auto"` (preserve labels only when symmetry matches), `"preserve"` (mismatch is an error), or
`"ignore"` (drop labels). `qc.chk.load(path)` already restores the *whole* checkpoint, so
`qc.chk.load(path).guess("read")` is usually redundant.

## Reference: common accessors

| accessor | form | returns |
|---|---|---|
| `natom`, `charge`, `spin` | property | int |
| `symbols` | property | list of element symbols |
| `nelectron()`, `nuclear_energy()` | method | int / float |
| `coordinates()` | method | `(natom,3)` array, bohr |
| `density`, `density_alpha`, `density_beta` | property | `(nao,nao)` array (after a state exists) |
| `overlap`, `kinetic`, `nuclear_attraction` | property | one-electron matrices (after `ints`) |
| `orbitals`, `mo` | property | orbital table / MO coefficients |
| `scf.*`, `lct.*`, `opt.*` | step accessor | the materialized result fields |
