External PySCF#

Use the external-reference API when your Python program, notebook, or another package already owns the PySCF SCF/CASCI/CASSCF calculation. The API exports the completed orbitals and final Hamiltonian to the same HDF5 contract as the full pyscf2mppt YAML route. The downstream workflow can then run without rebuilding the molecule or rerunning PySCF.

your PySCF code
    -> completed SCF/CASCI/CASSCF object
    -> ReferenceData
    -> MPPT HDF5
    -> CIPSIXX -> DIAGPT -> HEFFSO

This page covers both supported ways to continue after export:

  • run a workflow-only YAML with pyscf2mppt --from-hdf5;

  • call run_workflow_from_hdf5() from the same Python program.

Runnable Repository Cases#

The maintained examples live in test_suite/workflows/external_reference/:

Case

Run from its directory

Coverage

h2_scf

python run.py

RHF export, Python continuation, full-space FCI comparison

h2_casscf

python run.py

CASSCF export, CLI continuation and restart checks

ce_ypo4_grpp

bash test.sh

PySCF + LIBGRPP, including full Ce GRPP, embedding and spin-orbit integrals, through all downstream stages

h4_dmrg_casscf

python run.py

Optional Block DMRG-CASSCF and complete downstream workflow

Each case owns workflow.yaml, a README and test.sh. Use --dump-only to stop after export, then run pyscf2mppt ../../workflow.yaml --from-hdf5 reference.h5 from the generated output directory (runs/default/ for H2, runs/compact-150/ for a direct YPO4 run). Keep the HDF5 and workflow outputs together. The YPO4 default is a small integration model space, not a converged excitation-spectrum calculation.

The Ce:YPO4 example shows how an ordinary PySCF program uses native LIBGRPP through libgrpppy.libgrpp4pyscf.GRPPMole, then hands its completed reference to MPPT. LIBGRPP evaluates Ce’s full scalar GRPP, including outer-core terms, the embedding ECPs, point-charge attraction and the spin-orbit operator exported for HEFFSO. PySCF provides SCF and the remaining ordinary AO integrals.

The model has 150 spherical AO, all-electron oxygen and 40 selected MOs, including 20 occupied and 20 virtual MOs above HOMO. bash test.sh runs SCF, export, CIPSIXX, DIAGPT and HEFFSO, then checks the HDF5 contract and final artifacts. Its README gives the complete launch instructions; validation.json records the verification status. The log identifies the native LIBGRPP library.

Install MPPT with WITH_LIBGRPP=ON and INSTALL_PYSCF2MPPT=ON (both enabled by default), using the bundled third-party package as supplied.

See Block DMRG-CASSCF References for optional installation, the solver substitution and the boundary between a Block MPS and CIPSIXX.

What Each Layer Owns#

The boundary is deliberately explicit:

  1. Your Python code builds the molecule, installs any external potentials, converges SCF/CASCI/CASSCF, and chooses the final orbitals.

  2. reference_from_scf() or reference_from_casscf() takes a validated snapshot of those results. It does not run or converge PySCF.

  3. dump_reference() applies configured orbital generation, performs the AO-to-MO transformation and publishes one HDF5 artifact atomically.

  4. The workflow runs enabled downstream stages in dependency order: CIPSIXX, DIAGPT, then HEFFSO. It does not call PySCF again.

The exported integral and reference datasets are the stable physical input. The HDF5 file itself is not read-only: selection adds determinants and model-space data, and stages that reach checkpointing add restart records. Disabled stages and some preflight failures create no stage record. DIAGPT and HEFFSO also write prefix-qualified numerical outputs beside the workflow logs.

Before The First Run#

Install the Python package and build cipsixx_select, diagpt, and heffso as described in the installation guide. Make the executables available on PATH:

export PATH="$MPPT_ROOT/build/bin:$PATH"
command -v cipsixx_select diagpt heffso

Alternatively, pass explicit executable paths to the CLI or Python API. Only executables for enabled stages are required.

For a large transformation, put PySCF scratch on a filesystem with enough space before starting Python:

export PYSCF_TMPDIR=/path/to/large/scratch

First Complete CASSCF Export#

This complete water example exports optimized CASSCF orbitals to water-reference.h5. It uses CAS(2,2), a 6-31G working basis and the selected route with MOs 1–9. spin_orbit=False is intentional: the continuation below stops after scalar DIAGPT.

from pathlib import Path

from pyscf import gto, mcscf, scf

from pyscf2mppt import ExportConfig, dump_reference, reference_from_casscf


mol = gto.M(
    atom="O 0 0 0; H 0 -0.757 0.587; H 0 0.757 0.587",
    basis="6-31g",
    unit="angstrom",
    charge=0,
    spin=0,
    symmetry=False,
)
mf = scf.RHF(mol)
mf.kernel()
if not mf.converged:
    raise RuntimeError("SCF did not converge")

mc = mcscf.CASSCF(mf, ncas=2, nelecas=2)
mc.kernel()
if not mc.converged:
    raise RuntimeError("CASSCF did not converge")

# Use this same selection definition when starting the downstream workflow.
selection = {
    "enabled": True,
    "initial_space": "cas",
    "core_orbitals": [1, 2, 3, 4],
    "cas_orbitals": [5, 6],
    "cas_electrons": 2,
    "max_selected": 100,
}

dump_path = dump_reference(
    reference_from_casscf(mc),
    ExportConfig(
        output_path=Path("water-reference.h5"),
        prefix="water",
        spin_orbit=False,
        n_start=1,
        n_select=9,
        cipsixx=selection,
    ),
)

print(f"MPPT reference: {dump_path}")

Run it as an ordinary Python program:

python external_casscf.py

dump_reference() returns an absolute Path. Keep and pass that returned path instead of reconstructing a relative path in later Python code.

For an SCF-only reference, import and use reference_from_scf(mf) instead. Choose the downstream selection settings for that reference explicitly.

The adapter calls mc.get_hcore() exactly once and mc.energy_nuc() exactly once when explicit values are not supplied. The exporter uses the captured matrix and scalar; it does not reconstruct the one-electron Hamiltonian from individual PySCF integrals and does not call get_hcore() again.

The adapter also borrows the completed object’s own native with_df without building it. Both YAML and Python inherit exact/DF from the selected reference. integral_mode="exact" or "df" checks that choice and rejects a mismatch. An exact CASSCF object remains exact even if its parent SCF used DF.

The Same CASSCF Export With Orbital Generation#

This is the same calculation with occupied and virtual generation enabled directly in ExportConfig. The inactive MOs 1–4 are projected first; virtual generation starts at MO 7, preserving the CAS MOs 5–6. Each stage uses its own reference AO basis. The working 6-31G basis remains the integral basis.

Save as external_casscf_projected.py and run python external_casscf_projected.py:

from pathlib import Path

from pyscf import gto, mcscf, scf

from pyscf2mppt import ExportConfig, dump_reference, reference_from_casscf


mol = gto.M(
    atom="O 0 0 0; H 0 -0.757 0.587; H 0 0.757 0.587",
    basis="6-31g",
    unit="angstrom",
    charge=0,
    spin=0,
    symmetry=False,
)
mf = scf.RHF(mol)
mf.kernel()
if not mf.converged:
    raise RuntimeError("SCF did not converge")

mc = mcscf.CASSCF(mf, ncas=2, nelecas=2)
mc.kernel()
if not mc.converged:
    raise RuntimeError("CASSCF did not converge")

selection = {
    "enabled": True,
    "initial_space": "cas",
    "core_orbitals": [1, 2, 3, 4],
    "cas_orbitals": [5, 6],
    "cas_electrons": 2,
    "max_selected": 100,
}

dump_path = dump_reference(
    reference_from_casscf(mc),
    ExportConfig(
        output_path=Path("water-projected-reference.h5"),
        prefix="water",
        spin_orbit=False,
        n_start=1,
        n_select=9,
        cipsixx=selection,
        generate_projected_occupieds=True,
        generate_occupieds_from=1,
        generate_occupieds_to=4,
        avas_labels_occupied=("O 2s",),
        avas_basis_occupied={"O": ("library", "sto-3g")},
        occupied_orbital_map={"O 2s": 4},
        generate_projected_virtuals=True,
        generate_virtuals_from=7,
        avas_labels_virtual=("O 2p",),
        avas_basis_virtual={"O": ("library", "sto-3g")},
    ),
)

print(f"MPPT reference: {dump_path}")

Generation uses the same numerical routines as YAML. It leaves the supplied mc and reference arrays intact and recomputes populations in the final basis from the full correlated one-particle density, including its off-diagonal terms. It does not rerun CASSCF or transform its CI coefficients into a downstream wavefunction. CASSCF generation requires density information; old checkpoints without it can still export already-prepared orbitals.

YAML saves the prepared orbitals at its existing orbital checkpoint. Resuming export or inspecting that checkpoint uses the saved coefficients and populations without running either generator again. Reported source orbital energies remain source metadata; the generators do not recanonicalize the final orbitals.

Shared Preparation Controls#

Use the same keyword names under YAML mppt: or in Python ExportConfig:

Setting

Meaning

generate_projected_occupieds / generate_projected_virtuals

Enable the corresponding generator; both default to False.

avas_labels_occupied / avas_labels_virtual

Ordered AO projectors; labels are required when their generator is enabled.

avas_basis_occupied / avas_basis_virtual

Independent atom-label reference bases; None uses the working basis.

generate_occupieds_from / generate_occupieds_to

Inclusive one-based occupied interval; defaults to 1 through the occupied SCF count.

occupied_orbital_map

Place high-weight projected orbitals at absolute one-based positions within that interval.

generate_virtuals_from

First rotated MO; all preceding columns are preserved.

The automatic virtual boundary preserves the occupied SCF count plus the active orbital count for CASSCF, matching existing YAML behavior. To preserve exactly the inactive and active CASSCF blocks, set generate_occupieds_to=mc.ncore and generate_virtuals_from=mc.ncore + mc.ncas + 1; disable occupied generation when mc.ncore is zero. Explicit occupied endpoints cannot exceed the SCF occupied count. The example uses explicit boundaries for clarity.

File reference bases resolve against the Python process directory, or the YAML calculation work directory. Historical YAML spellings, including avas_labels_analyzis, remain accepted; conflicting aliases fail. Python also accepts N_start, N_select and output_hdf5; model_dump(by_alias=True) emits the established YAML names. max_mem_bytes accepts integer bytes or strings such as "2GB" at either boundary.

Default Changes For Existing Python Callers#

integral_mode now defaults to None (inherit the reference), and write_property_integrals defaults to True, matching YAML export. To export an exact reference, supply an exact source/provider; an explicit mode cannot silently replace its approximation. Set write_property_integrals=False when property datasets are intentionally unnecessary.

External export still requires overwrite=True to replace an existing file. The YAML runner retains its replacement default; an explicit mppt.overwrite overrides it. YAML molecule.so remains the fallback for spin_orbit.

Run From A Workflow YAML#

Create a workflow-only YAML. It needs only the mppt section; molecule, basis, SCF, and CASSCF sections are neither needed nor rerun.

mppt:
  prefix: water

  cipsixx:
    enabled: true
    initial_space: cas
    core_orbitals: [1, 2, 3, 4]
    cas_orbitals: [5, 6]
    cas_electrons: 2
    max_selected: 100

  diagpt:
    enabled: true
    integral_space: auto

  heffso:
    enabled: false

Run the enabled stages against the exported file:

# Continue from the saved reference; SCF and integral export are already complete.
pyscf2mppt workflow.yaml --from-hdf5 water-reference.h5

For executables that are not on PATH, use explicit paths:

pyscf2mppt workflow.yaml \
  --from-hdf5 water-reference.h5 \
  --selection-executable "$MPPT_ROOT/build/bin/cipsixx_select" \
  --diagpt-executable "$MPPT_ROOT/build/bin/diagpt"

The CLI creates runs/workflow/ by default; use --output-dir for another location. Generated inputs are in input/generated/, raw stage logs in logs/, native binary outputs in data/, and analysis tables in reports/heffso/. run.log contains the complete pipeline stream. mppt.prefix is a filename prefix, not a path. The explicit --from-hdf5 path is authoritative and writable: mppt.output_hdf5 does not override it, and the source is updated in place. No implicit HDF5 copy is made; an explicit archive includes a verified copy.

Matching completed stages are reused automatically. Use --force-workflow only when the enabled stages must run again despite valid fingerprints:

pyscf2mppt workflow.yaml \
  --from-hdf5 water-reference.h5 \
  --resume --force-workflow

--from-hdf5 cannot be combined with --stop-after. Downstream stage fingerprints live in the HDF5 file, while DIAGPT and HEFFSO reuse also depends on their prefix-qualified outputs. With a relative prefix, those outputs live under data/ and reports/heffso/ in the run directory. HEFFSO reuse additionally requires logs/heffso.log.

Run From The PySCF Program#

The same workflow can start directly after dump_reference() in the Python program. This low-level API writes raw stage logs and forwards complete native output to the caller’s stdout; the host program owns its top-level log. Add this after either CASSCF export example:

from pyscf2mppt.workflow import run_workflow_from_hdf5


# Reuse the selection settings used for export and enable the desired stages.
workflow = {
    "mppt": {
        "prefix": "water",
        "cipsixx": selection,
        "diagpt": {"enabled": True, "integral_space": "auto"},
        "heffso": {"enabled": False},
    }
}

# Launch the enabled MPPT stages from the absolute HDF5 path returned by export.
run_workflow_from_hdf5(
    workflow,
    dump_path,
    workdir=Path("water-workflow"),
)

config_input may be any of the following:

  • a YAML-like mapping, as above;

  • a path to a full or workflow-only YAML file;

  • a WorkflowConfig returned by build_workflow_config().

Explicit executable paths are available as selection_executable=, diagpt_executable=, and heffso_executable=. The Python force=True argument is equivalent to CLI --force-workflow.

The Python API creates workdir while resolving the HEFFSO stage even when all stages are disabled. Disabled HEFFSO also removes stale prefix-owned sovec, analysis-log, and properties outputs so they cannot be mistaken for current results. An all-disabled call therefore performs cleanup; it is not a read-only no-op. A relative hdf5_path is resolved under workdir, while a relative YAML config_input path is resolved under the caller’s current directory. Passing the absolute path returned by dump_reference() avoids the common HDF5-path mistake.

Export CASSCF Or CASCI#

Use reference_from_casscf() after kernel() has completed. The adapter uses mc.mo_coeff. PySCF commonly leaves mc.mo_occ unset, so the adapter computes populations from the final-basis spin-summed CASSCF/CASCI one-particle density. State-averaged references use their actual solver weights and spin sectors. An explicitly supplied mc.mo_occ remains authoritative for unmodified export; generation derives the final populations from the correlated density.

CASCI objects use the same adapter. The adapter does not infer a downstream CIPSIXX initial space from mc.ncas or mc.nelecas. Configure initial_space, active orbitals, and active electron counts explicitly in both the exported cipsixx metadata and the workflow configuration. Reusing one Python selection mapping, as above, keeps the two definitions synchronized.

Workflow orbital lists are human-facing, 1-based indices in the orbital space written for CIPSIXX. If n_select > 0, they index the selected space, not the original full PySCF MO list. See the selection guide for the HF, CAS, and determinant initial-space contracts.

External Potentials And Final Operators#

Patched get_hcore() implementations are supported. For example, PySCF QM/MM, point-charge, electric-field, embedding, and custom mean-field objects can provide the final AO Hamiltonian through their normal public method. The adapter captures that result once.

Pass hcore_ao explicitly when another layer already owns or caches the final matrix:

# Supply the complete cached operator and scalar, including all external terms.
reference = reference_from_scf(
    mf,
    hcore_ao=final_hcore_ao,
    constant_energy=final_constant,
)

Providing hcore_ao causes zero get_hcore() calls. It must be the complete final AO one-electron Hamiltonian, including the base Hamiltonian and every external contribution exactly once. Do not pass a correction-only matrix, and do not add a potential again if get_hcore() already includes it.

constant_energy has the same rule: it is the complete additive scalar for the exported Hamiltonian. The default is one call to energy_nuc(). Supply an explicit value when the external model has a scalar term that energy_nuc() does not include, or when the patched provider already uses a different energy partition. Do not include a scalar both in hcore_ao and constant_energy.

For CASSCF/CASCI, reference_from_casscf() calls the public mc.get_hcore(). This preserves an override installed directly on mc and PySCF’s normal delegation to mc._scf.get_hcore().

The LIBGRPP example wraps mf.get_hcore with functools.cache before SCF. This is particularly useful if the same mean-field object is used for CASSCF: its macro-iteration code repeatedly requests the core Hamiltonian. At fixed geometry, basis, GRPP parameters and external potentials, the AO operator does not depend on density or orbital rotations, so repeated calls can reuse it. The Fock matrix and MO-basis transformations still change during optimization. Call mf.get_hcore.cache_clear() or create a new mean-field object when modifying the molecule or potentials in place.

Spin-Orbit And Property Integrals#

ExportConfig.spin_orbit defaults to True. Set it to False only when HEFFSO will not run; this deliberately writes a zero spin-orbit tensor and leaves no physical coupling for a later HEFFSO calculation. The current exporter still evaluates the AO ECPso provider in both modes; False replaces its result with zeros rather than avoiding that call. Setting spin_orbit=True retains and transforms the evaluated operator, but cannot guarantee that the chosen molecule, ECP/GRPP, and basis produce the intended nonzero data. Verify that scientific input explicitly.

When a separate molecule supplies spin-orbit integrals, pass it through the adapter:

# Keep the SCF reference, but obtain SO integrals from an AO-compatible provider.
reference = reference_from_scf(mf, mol_for_so=spin_orbit_mol)

mol_for_so must preserve the AO count, labels, order, and overlap of mf.mol. An equal matrix size alone is insufficient.

heffso.properties defaults to true. For an external reference, export the required full-space property integrals before running HEFFSO with properties:

# Attach final AO property operators to the completed reference.
reference = reference_from_scf(
    mf,
    one_body_operators_ao={
        "dipole": dipole_ao,
        "angular_momentum": angular_momentum_ao,
    },
)

# Include the property and physical SO datasets required by HEFFSO.
dump_path = dump_reference(
    reference,
    ExportConfig(
        output_path=Path("reference.h5"),
        spin_orbit=True,
        write_property_integrals=True,
    ),
)

Explicit property tensors have shape (3, nao, nao). dipole components must be symmetric and angular_momentum components skew-symmetric. Either name may be supplied independently. Omitted property tensors are computed from mol when write_property_integrals=True. Supplying a tensor while leaving write_property_integrals=False is rejected instead of silently ignoring it. Set heffso.properties: false in the downstream workflow only when the four-column energy report without <prefix>heffso_properties.h5 is intended.

Explicit tensors must also follow the conventions recorded in HDF5. dipole is the bare position operator r, not -r, at the fixed origin (0, 0, 0) Bohr. angular_momentum contains the real skew coefficients from -int1e_cg_irxp; the physical complex Hermitian orbital-angular-momentum operator is 1j * angular_momentum. Shape and symmetry checks cannot detect a wrong sign, origin, or operator convention.

Choose The Export Route#

Export inherits exact Coulomb integrals or the DF-expanded approximation from the selected source. Memory and scratch settings do not switch the approximation.

ExportConfig.avas_basis_occupied and avas_basis_virtual select independent reference AO bases for the corresponding diagnostic labels. Python values are atom-label dictionaries with ("library", name) or ("file", path) tuples; unspecified atoms inherit the working basis. These settings drive diagnostics and the enabled generators in both YAML and Python. Labels alone do not rotate orbitals: set the corresponding generate_projected_* flag. Final orbital analysis preserves the per-label reference-basis specifications.

The most important ExportConfig controls are:

Setting

Meaning

output_path

Destination Path; defaults to pyscf_dump.h5.

prefix

Prefix embedded for downstream MPPT artifacts. Keep it consistent with mppt.prefix.

integral_mode=None

Inherit the source’s own exact/DF provider. An explicit "exact" or "df" must match it.

delete_from=0

Keep every supplied reference MO; no automatic virtual-tail truncation.

n_select=0

Export the full-ERI route, including int2e_full. This can be very large in either approximation.

n_select>0

Export compact downstream families for exactly this many consecutive MOs, starting at n_start. The entire window must fit inside the retained full MO space.

n_start=1

Exact positive one-based first selected MO. The window must contain a downstream occupied orbital. For example, n_start=1, n_select=25 selects MO 1–25.

downstream_nocc

Override the occupied-orbital count used by downstream selected-space tools when the default physical count is not the intended quasi-restricted vacuum.

max_mem_bytes=None

Automatic workspace from reference.mol.max_memory; a positive integer adds a temporary-buffer cap, not a process-wide hard limit.

exact_half_block_size=None

Keep the monolithic exact selected half-transform; a positive integer optionally bounds its first MO side. Requires n_select>0 and is incompatible with DF.

force_transform_outcore

Force disk-backed AO-to-MO transformation only on the exact full route. It has no effect on selected export or DF MO-factor storage.

overwrite

Atomically replace an existing artifact; defaults to False.

To retain all reference MOs with a selected window, use delete_from=0 and n_select>0. The window is inside the full space, not added to it; n_select=0 requests full-ERI materialization rather than preserving extra orbitals. Both routes retain the complete final Hamiltonian and requested SO/property operators described above, with their established HDF5 meanings and indexing.

If delete_from exceeds the number of supplied MO columns, export logs a [WARN] before orbital analysis and ignores the cutoff, exactly as with delete_from=0. This includes MO count plus one and applies to both exact and DF export. The comparison uses the MO count, not the AO basis size. A cutoff equal to the MO count removes the last MO; negative values and 1 remain errors. Selected-window settings still apply when the cutoff is ignored.

The default full route can require large temporary and final two-electron integral storage. For a scientifically appropriate compact selected route, review its required datasets, indexing rules and consumer limits in Selected Route. Export success alone does not establish that a downstream calculation fits. Set PYSCF_TMPDIR before importing the package to suitable scratch even when max_mem_bytes is bounded.

overwrite=True replaces the entire HDF5 artifact. It therefore removes any downstream results and workflow checkpoints stored in the old file. It is an export operation, not a workflow restart option.

Shared Export Memory#

Set reference.mol.max_memory to a realistic total hint and normally leave ExportConfig.max_mem_bytes=None. Numeric molecule memory is decimal PySCF MB: 50000 means 50,000,000,000 bytes, not MiB. Automatic planning also applies to dump_reference(reference) with no export config, on both routes; no hidden 2-GiB cap or separate J/K user budget is needed.

An explicit positive integer such as max_mem_bytes=16 * 1024**2 keeps its temporary-buffer meaning within the remaining total workspace. It is a valid API value, but runtime admission can reject it if even one unit of work cannot fit. Python expects integer bytes, not YAML unit strings. Neither the molecule hint nor the cap enforces process RSS or limits final dataset size. Caller-owned SCF/DF caches continue to consume RAM and are not deleted by export.

On the exact full route, automatic transform/reorder selection uses the checked remaining workspace, intersected with an explicit cap and the conservative array budget. A small cap can select disk-backed work without an infeasible process total or force flags. Native/packing buffer floors still apply, so the cap is not a strict per-allocation ceiling.

If export reports Integral workspace does not fit, an exact J/K projector failure or DF phase workspace does not fit, compare the reported total, current usage and cap. Removing a restrictive cap with None helps only when the total has room; raise the molecule total only when additional RAM is genuinely available within the host/worker limits. Current admission can reject a nominal 1-MB total already exceeded by the resident process. See the shared memory units and failure guidance for both modes/routes.

For an exact reference export with a valid five-orbital selected window, the optional control fragment is ExportConfig(delete_from=0, n_select=5, exact_half_block_size=4). The slab size must be a strict positive integer, not a boolean or fraction; None keeps the monolithic strategy. Full-route and DF requests with a non-null slab size are rejected. The low-level dump_integrals API accepts the same keyword-only control.

Smaller exact slabs reduce only the half-transform scratch, not all peak disk or RAM usage. Dense CV-CV staging, other ERI arrays, J/K and final datasets remain; repeated AO passes can make the dump slower. The width is not automatically resized. Retained MOs, integral values, packed output and atomic publication are unchanged. Preflight scratch and destination capacity separately.

DF instead chooses RAM or HDF5 MO-factor storage automatically, without a public force flag. Full DF still materializes large native pair and packed/reorder arrays; force_transform_outcore=True does not remove them. Both modes write ordinary consumer integrals, not factor-only artifacts.

For a separate export of a completed reference, choose a new destination and an explicit ExportConfig. CLI --resume validates saved input and resources; it is not a way to change the approximation or repeat a completed export. Use a new --output-dir for changed scientific inputs. --from-hdf5 only runs downstream stages, not a new transformation.

Exact Export Internals contains the exact formulas, lifetimes, screening assumptions, coverage maps and full-route routing limits. DF Export Internals covers its separate phase model and assembly checks. Small tests do not certify large-Ce accuracy, peak memory or performance; matched-DF controls do not measure DF-versus-exact error.

Every completed artifact records the reference schema version and JSON provenance under /mppt/reference.

What Gets Reused#

Each enabled stage fingerprints its normalized configuration, executable, and consumed HDF5 inputs. DIAGPT and HEFFSO also validate their prefix-qualified sidecar outputs. HEFFSO additionally validates its captured primary log. With the recommended relative prefix, all of these files are in the same workdir. On a later call:

  • a matching complete stage with valid outputs is skipped;

  • a changed stage configuration reruns that stage;

  • changed upstream selection invalidates DIAGPT and HEFFSO;

  • force=True or --force-workflow reruns all enabled stages.

Workflow-only changes do not rerun PySCF or repeat the AO-to-MO export. They can, however, replace downstream groups and outputs. With a relative prefix, moving only a post-workflow HDF5 file to a different workdir preserves the physical inputs but normally does not preserve DIAGPT/HEFFSO reuse because sidecar outputs and the HEFFSO primary log are left behind.

With a relative prefix, treat one HDF5 file plus its workflow directory as one restart unit. An absolute prefix adds its external output paths to that unit. Do not launch concurrent workflows that write the same artifact. For independent parameter studies whose results must coexist, copy the freshly exported reference before the first downstream run and use one copy and one working directory per study. For example, run these commands from the project directory:

mkdir -p runs/config-a runs/config-b
cp reference.h5 runs/config-a/reference.h5
cp reference.h5 runs/config-b/reference.h5
(cd runs/config-a && pyscf2mppt ../../config-a.yaml --from-hdf5 reference.h5)
(cd runs/config-b && pyscf2mppt ../../config-b.yaml --from-hdf5 reference.h5)

Inspect a completed artifact read-only and only while no workflow is writing it:

from pathlib import Path

import h5py


with h5py.File(Path("h2-reference.h5"), "r") as h5file:
    print("reference schema:", h5file["/mppt/reference"].attrs["schema_version"])
    print("workflow stages:", list(h5file.get("/mppt/workflow/stages", {})))

Reference provenance is stored as JSON under /mppt/reference. Stage status is stored under /mppt/workflow/stages; selection also writes /cipsixx/selected_determinants and the quasi-restricted model-space handoff. See Outputs And Checkpoints for the complete file and log layout.

Validation And Current Limits#

ReferenceData detaches its arrays from PySCF and validates the export boundary:

  • mo_coeff must be finite, real, AO-by-MO, and orthonormal in the AO overlap metric;

  • mo_occ and optional mo_energy must match the MO count;

  • hcore_ao must be a finite real Hermitian (nao, nao) matrix;

  • constant_energy must be finite;

  • provenance must be JSON-compatible.

The current contract supports C1 calculations with real restricted spatial orbitals and one-electron spin-orbit integrals. Complex orbitals and unrestricted alpha/beta coefficient pairs are rejected rather than coerced. The exporter does not preserve a non-C1 symmetry-block contract.

ReferenceData validates the completed arrays but does not decide whether an SCF or CASSCF solution is scientifically converged. Check mf.converged or mc.converged before adapting the object, as in the examples.

ExportConfig is strict. Use Path for output_path and correctly typed values for all controls. The destination is published only after a complete temporary artifact has been written beside it. Existing destinations are rejected unless overwrite=True; a failed overwrite leaves the previous artifact unchanged.

Common Problems#

Symptom

Cause and fix

calculation must provide completed mo_coeff

kernel() was not run or did not produce a completed object. Run PySCF first and check convergence.

Unexpected external-potential energy

Verify that hcore_ao is the complete matrix exactly once and that constant_energy contains only the complete scalar term.

FileExistsError during export

The destination already exists. Reuse it for workflow restart, choose a new path, or deliberately set overwrite=True to replace everything.

No downstream computation starts

All three downstream enabled flags default to false. Enable at least one stage. The disabled HEFFSO stage can still remove stale prefix-owned HEFFSO outputs.

cipsixx_select or another executable is not found

Put the built executables on PATH, set the documented environment variables, or pass explicit executable paths.

CAS orbitals are rejected or select the wrong space

Lists are 1-based and refer to the exported CIPSIXX orbital space. With n_select>0, renumber them in the selected space.

DIAGPT starts without model-space data

A fresh export needs CIPSIXX selection first. Enable cipsixx, or provide an HDF5 file that already contains a valid model space.

HEFFSO gives zero or unexpected spin-orbit splitting

Export with spin_orbit=True, then verify that the chosen ECP/GRPP and integral provider produce the intended nonzero SO operator; shape validation alone cannot certify it.

HEFFSO reports missing property inputs

heffso.properties is true by default. Export with write_property_integrals=True, or deliberately set properties: false for an energy-only report.

Relative HDF5 path works in CLI but not Python

The Python API resolves a relative HDF5 path under workdir. Pass the absolute dump_path returned by the exporter.

Export rejects its memory budget or buffer cap

Use the reported byte counts and shared memory guidance. None removes only the optional cap, not the total/availability checks.

Full-route export runs out of memory or scratch

Check the molecule total hint and scratch capacity. force_transform_outcore=True selects disk-backed AO-to-MO work only for exact full export; it has no effect on selected export or DF factor storage, and does not remove full DF’s materialized arrays. Choose n_select>0 only when that different integral contract is intended.

Workflow-only parsing currently ignores unknown top-level keys and unknown keys directly under mppt; nested cipsixx, diagpt, and heffso sections are strict. Check spelling because a typo such as mppt.prefx silently selects the default prefix.

For production settings, continue with the unified workflow guide and the exact YAML input reference. Selection targets, active spaces, root counts, and state weights are scientific inputs; do not copy the small H2 demonstration values to another system.