pyscf2mppt YAML Input Format#

pyscf2mppt reads a YAML file, runs the PySCF calculation directly, and optionally writes an HDF5 integral dump for the downstream MPPT tools. The default path remains pyscf_dump.h5. The old path that printed a generated calculation.py file and executed it has been removed. The CLI accepts only .yaml and .yml input files.

General notes:

  • Keys are case-sensitive.

  • Booleans must be YAML booleans (true/false), not quoted strings.

  • Use YAML numbers rather than quoted numeric strings. Strict numeric fields reject coercion; several cipsixx/DIAGPT threshold and weight fields currently use coercive floats, but portable inputs should not rely on that exception.

  • Strict floating-point fields such as SCF/CASSCF max_memory and HEFFSO tolerances require floating-point YAML values (8000.0, not 8000).

  • molecule.atoms and basis are required; other sections are optional and defaulted.

  • Section examples are illustrative and mix defaults with nondefault values. Do not infer a default from an example unless the surrounding text identifies it explicitly.

  • Full-calculation YAML rejects unknown top-level and nested keys. Workflow-only parsing with --from-hdf5 is an exception: top-level keys other than mppt and unknown keys directly under mppt are currently ignored; unknown keys inside cipsixx, diagpt, and heffso are rejected.

  • One parser-level exception is a mapping-form casscf.states_to_average item: it requires spin and nroots but currently discards additional keys.

  • Only C1/no symmetry is supported. Use molecule.symmetry: false, omit the key, or use molecule.symmetry: C1, which is normalized to false internally.


Minimal example#

molecule:
  symmetry: false
  charge: 0
  units: bohr
  so: true
  atoms:
    - [O, 0.0, 0.0, 0.11779]
    - [H, 0.0, 0.75545, -0.47116]
    - [H, 0.0, -0.75545, -0.47116]

basis:
  H: [library, sto-3g]
  O: [library, sto-3g]

scf:
  spin: singlet
  type: rhf

mppt:
  prefix: h2o

Section: molecule#

molecule:
  symmetry: false   # only false or C1 allowed; defaults to false
  charge: 0
  units: bohr       # or angstrom / A
  so: true          # dump spin-orbit integrals when supported by the setup
  max_memory: 32000 # MB; can also be "32GB"
  atoms:
    - [H, 0.0, 0.0, 0.0]
    - [H, 0.0, 0.0, 0.74]
  • symmetry: must be false or C1. Other symmetries are rejected.

  • units: use A/angstrom or B/bohr. The current normalizer also accepts strings beginning with a or b; counterintuitively, a.u. maps to Angstrom. Avoid ambiguous spellings and write bohr explicitly for atomic units.

  • so: include spin-orbit integrals in the dump when supported by the setup. This does not run a spin-orbit electronic-structure calculation in PySCF. The schema default is true; set it explicitly for reproducible inputs.

  • max_memory: global memory cap (MB). Accepts numeric MB or strings like "32GB".

  • atoms: list of [Element, x, y, z].

  • charge: total molecular charge.


Section: point_charges (optional)#

point_charges:
  - [1.0, 0.0, 0.0, -0.5]
  - [-1.0, 0.0, 0.0, 0.5]

Each entry is [x, y, z, charge]. Coordinates use the same units as molecule.units.


Section: basis#

basis:
  H: [library, sto-3g]
  Ce: [file, ./Ce_expt.dat]
  • Each element maps to [library, name] or [file, path]. Only the case-insensitive token file selects file loading. Any other first token, including a misspelling of library, is currently treated as a library specification, so use the exact documented tokens.


Section: ecp (optional)#

ecp:
  Ce: [library, stuttgart]
  Pr: [file, ./Pr_ecp.dat]

Section: grpp (optional)#

Note: libgrpp library must be pointed at the execution time.

grpp:
  Pr: ./Pr_grpp.dat

Section: scf (optional)#

scf:
  spin: singlet   # or integer multiplicity, not N_alpha - N_beta
  type: rhf
  conv: 1.0e-10
  max_cycle: 100
  max_memory: 8000.0
  density_fit: false
  auxbasis: null
  omp_num_threads: 8
  verbose: 3

Notes:

  • spin accepts names (singlet, doublet, triplet, …) or a positive integer multiplicity.

  • type currently accepts rhf and rohf.

  • omp_num_threads controls PySCF/OpenMP thread setup for the SCF stage. It is applied before the first PySCF import in the normal runtime path.

  • density_fit: true enables PySCF density fitting. auxbasis selects an auxiliary basis when the PySCF default is not appropriate.

  • Aliases are accepted:

    • conv -> conv_tol

    • threads, omp, omp_threads, num_threads, cores, num_cores -> omp_num_threads

    • maxiter, iter, num_iter, numiter -> max_cycle

    • memory, mem, maxmem, max_mem -> max_memory

    • df, density_fitting, with_df -> density_fit

    • aux_basis, auxiliary_basis, df_auxbasis -> auxbasis


Section: casscf (optional)#

casscf:
  active_orbitals: 8
  n_active_electrons: 10
  conv_tol: 1.0e-7
  conv_tol_grad: 1.0e-4
  max_cycle_micro: 5
  max_cycle_macro: 100
  ah_max_cycle: 30
  ah_start_tol: 2.5
  ah_lindep: 1.0e-14
  ah_conv_tol: 1.0e-12
  ah_level_shift: 1.0e-8
  omp_num_threads: 8
  max_memory: 8000.0
  density_fit: false
  auxbasis: null
  charge: 0
  spin: triplet
  verbose: 6
  avas_labels: ["Pr 4f", ["O 2p", "Pr 5d"]]
  states_to_average:
    - [singlet, 2]
    - {spin: triplet, nroots: 1}

Notes:

  • The runtime schedules CASSCF only when active_orbitals is supplied. Convergence, memory, density-fitting, charge, or spin settings alone do not add a CASSCF stage. Supplying n_active_electrons, avas_labels, or states_to_average without active_orbitals is treated as an incomplete active-space request and raises an error. A requested stage requires positive active_orbitals and n_active_electrons.

  • states_to_average entries can be [spin, nroots] or {spin: <spin>, nroots: <nroots>}. All requested roots receive uniform weights; there is no CASSCF state-weight input. Every multiplicity and root count must be positive.

  • conv_tol_grad defaults to sqrt(conv_tol) when omitted.

  • density_fit and auxbasis control density fitting for the CASSCF setup. Completed SCF arrays are still required before AVAS or active-space work.

  • AVAS failure is reported as a warning and falls back to SCF orbitals.

  • charge or spin overrides rebuild the molecule and create a new ROHF reference object, but do not run a new SCF kernel for that overridden reference before CASSCF.

  • Aliases accepted:

    • n_active_orbitals -> active_orbitals

    • avas_label -> avas_labels

    • state_averaged -> states_to_average

    • threads, omp, omp_threads, num_threads, cores, num_cores -> omp_num_threads

    • memory, mem, maxmem, max_mem -> max_memory

    • df, density_fitting, with_df -> density_fit

    • aux_basis, auxiliary_basis, df_auxbasis -> auxbasis


Section: mppt (optional)#

mppt:
  orbitals: auto         # auto | scf | casscf
  prefix: pyscf
  output_hdf5: pyscf_dump.h5
  so_source: auto        # auto | scalar | relativistic
  no_dump: false
  N_select: 0
  N_start: 0
  delete_from: 0
  avas_labels_analyzis: ["Pr 4f"]   # labels for projection-analysis tables only
  generate_virtuals_count: null      # accepted compatibility key; currently unused
  max_mem_bytes: "2GB"
  downstream_nocc: null              # optional downstream occupied-prefix override

Notes:

  • orbitals chooses the orbital coefficients used for projection and dump: auto uses CASSCF orbitals when CASSCF ran and SCF orbitals otherwise; scf always uses SCF orbitals; casscf requires a CASSCF stage.

  • output_hdf5 chooses the integral-dump path. Relative paths are resolved from the process working directory; parent directories are created.

  • prefix and output_hdf5 must remain nonempty after surrounding whitespace is removed when the downstream workflow configuration is built.

  • so_source accepts auto, scalar, or relativistic. auto constructs the GRPP molecule when a nonempty grpp section exists; scalar suppresses that construction even when GRPP paths are present; relativistic requires a nonempty grpp section. This is separate from molecule.so: setting molecule.so: false still writes intso, but fills it with zeros.

  • no_dump: true runs through calculation/orbital preparation but skips final pyscf_dump.h5 generation. Because automatic downstream continuation occurs only after dump, it also prevents enabled cipsixx, DIAGPT, and HEFFSO stages from running in that command.

  • N_select writes one contiguous window of energy-sorted orbitals around the HOMO. 0 keeps the full orbital space. The schema currently also accepts negative values; runtime treats every N_select <= 0 as the full route, so use nonnegative values.

  • N_start is an optional one-based lower bound for that window and cannot start above the HOMO. The parser does not reject negative values; runtime treats N_start <= 0 as automatic placement.

  • delete_from is a one-based inclusive trim point applied before integral transformation. For example, delete_from: 320 keeps orbitals 1 through 319. 0 disables trimming. Negative values and 1 are rejected. A value equal to the current orbital count plus one is accepted as a no-op; larger values are rejected.

  • max_mem_bytes can be an integer byte count or a string with units (GB, MB, KB).

  • avas_labels_analyzis controls which AO labels are shown in projection-analysis tables.

  • downstream_nocc overrides the closed-shell occupied-orbital prefix used by downstream compatibility metadata. When omitted, the producer uses the larger of the occupied-MO count above 0.1 and ceil(nelec/2). An explicit value must be between zero and the post-trim orbital count.

  • generate_virtuals_count is accepted and checkpointed but currently has no runtime consumer and does not limit projected virtual generation. Do not rely on it as an active control.

The four memory settings have distinct roles but are not operationally independent. molecule.max_memory is the global PySCF cap and the basis for the dump’s automatic RAM budget. scf.max_memory and casscf.max_memory override their stages and otherwise fall back to the molecule/global value. mppt.max_mem_bytes requests AO-to-MO transformation buffering but is clamped to the molecule-derived budget. None of them limits the final integral dataset size.

Accepted MPPT aliases are normalized before strict schema validation:

  • so_from, so_provider, so -> so_source;

  • ao2mo_max_mem_bytes, ao2mo_max_memory_bytes -> max_mem_bytes;

  • generate_projected_occupied, generate_occupieds, project_occupieds -> generate_projected_occupieds;

  • generate_occupied_from, occupied_from, occupied_start -> generate_occupieds_from;

  • generate_occupied_to, occupied_to, occupied_end -> generate_occupieds_to;

  • occupied_map, occupied_mapping, orbital_map_occupied -> occupied_orbital_map.

Do not provide an alias together with its canonical key. Alias/canonical collision precedence differs between older compatibility paths; canonical-only inputs are deterministic and recommended.

Removed options are rejected explicitly rather than ignored: scf.frac_occ, scf.frac_occ_find, mppt.avas_labels, mppt.avas_label, mppt.analyze_avas_labels, mppt.analyze_avas_label, and mppt.analysis_avas_labels. Use the three purpose-specific avas_labels_analyzis, avas_labels_virtual, and avas_labels_occupied keys.

Optional cipsixx initialization and selection metadata:

mppt:
  cipsixx:
    enabled: true
    initial_space: cas       # hf | cas | determinants
    selection_method: mp2_coefficient
    max_selected: 4000
    batch_size: 250
    max_iterations: 20
    max_candidates: null
    denominator_tolerance: 1.0e-12
    n_roots: 8
    selected_root: 0
    multi_state: true
    selection_growth: topk   # topk | threshold
    selection_metric: coefficient
    state_weighting: uniform # uniform | legacy-taum | inverse-participation | custom
    root_weights: null        # required only for custom weighting
    spin_adaptation_closure: spin-projection # spin-projection | spin-complement | none
    final_diagonalization: always            # always | never
    adaptive_threshold: false
    threshold_multiplier: 0.75
    threshold_floor: 1.0e-7
    min_new_determinants: 100
    min_abs_coefficient: 1.0e-5
    min_abs_energy: 0.0
    cas_orbitals: [14, 15, 16, 17]  # human-facing 1-based labels
    core_orbitals: [1, 2, 3, 4]
    frozen_orbitals: []
    cas_alpha_electrons: 1
    cas_beta_electrons: 0
    cas_electrons: null
    determinants_group: /cipsixx/initial_determinants
    omp_num_threads: 8
    iteration_report: cipsixx_iterations.csv
    root_energy_report: cipsixx_root_energies.csv

Positive integer settings such as batch_size, max_iterations, n_roots, and min_new_determinants must be greater than zero. Orbital lists are human-facing, one-based, positive, and duplicate-free; core_orbitals and cas_orbitals cannot overlap. CAS initialization requires cas_orbitals plus either cas_electrons or both spin-resolved electron counts. When all three counts are provided, total electrons must equal alpha plus beta.

selected_root is zero-based and must be smaller than n_roots. state_weighting values other than uniform require multi_state: true. state_weighting: custom requires exactly n_roots nonnegative root_weights, with at least one positive value; all other weighting modes reject root_weights. determinants_group must be a nonempty absolute HDF5 path. Report paths, when not null, must be nonempty. selection_method currently accepts only mp2_coefficient; selection growth can use topk or threshold, and its metric can be coefficient or energy. final_diagonalization: never is a deliberate handoff/performance mode rather than the default authoritative variational result.

The example above is not a defaults listing. Important cipsixx defaults are enabled: false, initial_space: hf, max_selected: null, batch_size: 250, max_iterations: 12, max_candidates: null, n_roots: 1, multi_state: false, state_weighting: uniform, adaptive_threshold: false, and omp_num_threads: -1. Optional selection and candidate counts must be positive. Coefficient, energy, denominator, and floor thresholds are nonnegative; threshold_multiplier is in (0, 1].

The dump normalizes cipsixx orbital indices to zero-based values. With N_select > 0, /cipsixx/integrals uses the selected orbital space and carries orbital_space="selected". With N_select <= 0, it uses the complete post-trim orbital space and carries orbital_space="full". The existing MPPT root datasets remain part of the current HDF5 contract, including the packed full-space ERIs in their required C1 destination ordering.

Optional restartable DIAGPT and HEFFSO stages:

mppt:
  prefix: Pr
  diagpt:
    enabled: true
    title: Pr scalar states
    thrpri: 0.25
    wmupa: 1.0
    gap: 0.05
    zshift: false
    write_h0: true
    state_weights: null
    integral_space: auto     # auto | full | selected
    omp_num_threads: 8
  heffso:
    enabled: true
    title: Pr spin-orbit states
    effective_operators: true
    nvectw: 8
    iorder: 2
    guess_space: null
    max_basis: null
    max_block: null
    max_matvecs: null
    residual_tolerance: 1.0e-6
    initial_vector_tolerance: 1.0e-7
    print_level: 1
    progress_interval_seconds: 60
    allow_constrained_basis: false
    preconditioner: true
    direct_sparse: true
    sparse_backend: auto     # auto | fortran | cuda
    omp_num_threads: 8
    report:
      configuration_weight_percent: 10.0
      configuration_top_n: 3

DIAGPT title, when set, must be nonempty and single-line. thrpri and gap are nonnegative, wmupa is in [0, 1], and state_weights must be nonnegative with at least one positive value. At execution, an explicit weight list must contain exactly one value per model-space state. When omitted, the generated DIAGPT input contains one 1.0 weight per state. DIAGPT always uses the mandatory repository-pinned PRIMME eigensolver. The former solver field under mppt.diagpt is not accepted.

The downstream workflow supports one C1 scalar handoff. DIAGPT and HEFFSO use the fixed compatibility filename <prefix>_heffso.1.h5; there is no pass number setting.

Null PRIMME sizes are adaptive. guess_space becomes min(n, max(512, 2*nvectw)), max_basis becomes min(n, max(nvectw+64, 4*nvectw)), max_block uses at most eight OpenMP threads, and max_matvecs becomes max(10000, 400*nvectw). The workflow removes historical HEFFSO_PRIMME_* environment overrides before launch. With inherited OpenMP threads, an explicit basis too small for the worst-case eight-vector adaptive block must also set max_block; this prevents a YAML configuration from becoming valid or invalid only because the caller’s thread environment changed. Explicit max_block cannot exceed nvectw, max_matvecs cannot be smaller than nvectw, and max_basis must hold nvectw + max_block. sparse_backend: cuda requires direct_sparse: true. HEFFSO title, when set, must be nonempty and single-line. nvectw is in [1, 1000], iorder is 1 or 2, print_level is in [0, 5], guess_space is nonnegative, and progress_interval_seconds is positive. Residual and initial-vector tolerances must be finite and positive.

effective_operators: true writes full-space intdip and intang property tensors during the PySCF dump, enables the HEFFSO namelist setting effective_operators, and requires <prefix>heffso_effective_operators.h5 after prefix normalization. The artifact uses mppt_heffso_effective_operators_v1 and stores bare V^dagger Q V matrices for Cartesian L, S, J = L + S, and dipole operators. Generated daughter determinants outside the finite catalog are omitted by the model-space projector. There is no wave-operator dressing, exact Casimir or multiplet analysis, parentage or certification, or exact E1 spectroscopy contract.

The switch does not add sections to the human report. That report contains only state energies, active-orbital occupations, and dominant configuration weights. configuration_weight_percent is in [0, 100]; the strict threshold is supplemented by at least the positive configuration_top_n row count.

All downstream stages are opt-in and default to disabled. The complete configuration, HDF5 group ownership, and checkpoint rules are documented in the unified cipsixx workflow.

Thread-count semantics differ by layer. For direct SCF/CASSCF, omp_num_threads: -1 selects all detected cores, 0 becomes one thread, and a positive value is capped at the detected core count. For cipsixx, DIAGPT, and HEFFSO, -1 inherits the caller’s environment, 0 is rejected, and a positive value sets OMP_NUM_THREADS, MKL_NUM_THREADS, and OPENBLAS_NUM_THREADS. Selection and DIAGPT fingerprints do not include inherited ambient thread variables; the HEFFSO fingerprint includes its solver-relevant inherited OpenMP, MKL, OpenBLAS, and CUDA variables.

Current model-space preflight rejects excitation rank above eight, DIAGPT ncf > 46340, metat > 1000, or metat > ncf. When HEFFSO is enabled it also rejects ncf > 35000 and a packed excitation-slot count above 280001. DIAGPT additionally requires 2*norb + 1 and its packed excitation-slot count to fit signed 32-bit integers.

Optional occupied-orbital projection:

mppt:
  generate_projected_occupieds: true
  avas_labels_occupied: ["Pr 4f"]
  generate_occupieds_from: 1        # 1-based, inclusive; default 1
  generate_occupieds_to: 10         # 1-based, inclusive; default nocc
  occupied_orbital_map:
    "Pr 4f": [4, 5, 6]

Optional virtual-orbital projection:

mppt:
  generate_projected_virtuals: true
  avas_labels_virtual: ["Pr 5d"]
  generate_virtuals_from: 26        # optional 1-based start index

Projection notes:

  • avas_labels_occupied is required when generate_projected_occupieds: true.

  • Explicit generate_occupieds_from and generate_occupieds_to values must be at least one, and the upper bound cannot be smaller than the lower bound. These checks run even when occupied projection is disabled.

  • generate_projected_virtuals: true requires avas_labels_virtual.

  • generate_virtuals_from is optional; when omitted, virtual projection starts after the occupied space and after the active space for CASSCF orbitals.

  • occupied_orbital_map supports either a dict ({"Ce 4p": [10, 11, 12]}) or an explicit list of pairs ([["Ce 4p", 10], ["Ce 4p", 11]]) for repeated labels.

  • When occupied/virtual projection is enabled, pyscf2mppt prints one pre-projection orbital snapshot using the merged label set from analyze/occupied/virtual inputs.


CLI Runtime And Checkpoints#

Run a YAML input directly:

pyscf2mppt input.yaml > input.out

Checkpoint and resume long calculations:

pyscf2mppt input.yaml --checkpoint-dir ckpt --stop-after scf > scf.out
pyscf2mppt input.yaml --resume-from ckpt --checkpoint-dir ckpt > resumed.out

Inspect a checkpoint without running the full integral dump:

pyscf2mppt --inspect-checkpoint ckpt > inspect.out

Run only enabled downstream stages from any existing compatible HDF5 dump:

pyscf2mppt workflow.yaml --from-hdf5 checkpoints/calculation.h5

Matching completed stages are reused from /mppt/workflow/stages. Use --force-workflow to rerun enabled stages. Executable paths may be supplied with --selection-executable, --diagpt-executable, and --heffso-executable.

The explicit --from-hdf5 path is authoritative; mppt.output_hdf5 in a workflow-only file does not select the input. Top-level keys other than mppt and unknown keys directly under mppt are currently ignored in this mode. Nested downstream sections remain strict. With every downstream stage disabled, the command is a successful no-op and may not validate that the HDF5 exists.

--from-hdf5 is intentionally independent from the PySCF checkpoint options and cannot be combined with --checkpoint-dir, --resume-from, or --stop-after.

Supported --stop-after stages are:

  • input_normalized

  • scf

  • casscf

  • orbitals

  • dump

The supplied YAML must still exist and pass full parsing before resume loads the checkpoint. Resume restores the saved normalized input and work directory for direct PySCF stages, so edits do not change those stages. Automatic downstream execution instead uses the current YAML’s mppt section. Direct checkpoints do not fingerprint external basis/ECP/GRPP file contents, package/runtime versions, executables, or environment, and do not own the final HDF5 dump. A checkpoint recorded through dump can return PySCF completion without checking that the dump still exists; enabled downstream stages can then fail when they open the current YAML’s path. The complete flag, inspection, executable-resolution, managed-run identity, and restart semantics are in the CLI reference.

For a fresh direct CLI run, the default runtime work directory is the process current directory: relative basis/ECP/GRPP files, cipsixx reports, HDF5 output, and prefix-derived files resolve there, not beside the YAML. Resume splits these bases. Relative resources and workflow sidecars use the work directory restored from the checkpoint, while the current YAML’s relative output_hdf5 is resolved from the current process directory. The Python run_from_yaml(workdir=...) API exposes the same distinction on a fresh run: resources and sidecars use the supplied workdir, while the writer creates a relative output_hdf5 below the process current directory. The direct writer does not expand ~, while downstream HDF5 resolution does; avoid ~ and use an absolute path or an ordinary relative path. Managed runs intentionally differ: they resolve file resources relative to the source YAML, copy them into resources/, and rewrite the effective input.


Occupied projections (Python API)#

Projected occupied-orbital construction is available through Python API:

from pyscf2mppt.orbitals import construct_occupied_via_projections

mol_orb = construct_occupied_via_projections(
    mol=mol,
    mo_coeff=mol_orb,
    labels=["Ce 4p"],                  # AO labels in working basis
    start_orbital=10,                  # 1-based, inclusive
    end_orbital=18,                    # 1-based, inclusive
    mo_energy=mf.mo_energy,
    mo_occ=mf.mo_occ,
    orbital_map={"Ce 4p": [12, 13, 14]},  # same label -> multiple targets
    scf_obj=mf,                        # enables HF total-energy before/after printout
)

Behavior:

  • Uses AVAS-like AO projections in the current working basis (no MINAO basis).

  • Reconstructs/project-rotates only the selected occupied window.

  • Builds Fock in the new occupied subspace, diagonalizes it, and places orbitals by energy.

  • Optionally applies label-to-target mapping after canonical placement.

Mapping input supports:

  • {"Label": 12}

  • {"Label": [12, 13, 14]}

  • [("Label", 12), ("Label", 13)]

Note:

  • YAML keys for projected virtuals and occupieds are documented above.

Integral dump from an existing PySCF object#

The library API remains independent of the YAML runner. Existing SCF or CASSCF objects can be dumped directly to any destination:

from pyscf2mppt import dump_casscf, dump_scf

selection = {
    "initial_space": "cas",
    "cas_orbitals": [14, 15, 16, 17],
    "cas_electrons": 1,
}
dump_scf(
    mf,
    cipsixx_config=selection,
    output_path="checkpoints/scf_integrals.h5",
)
dump_casscf(
    mc,
    cipsixx_config=selection,
    output_path="checkpoints/casscf_integrals.h5",
)

Omitting output_path preserves the historical pyscf_dump.h5 behavior.