HEFFSO Build And Usage#

HEFFSO builds and diagonalizes the spin-orbit effective Hamiltonian after DIAGPT. The current implementation is HDF5-first: previous-stage determinants, effective Hamiltonian matrices, orbital metadata, and spin-orbit integrals are read from an explicit shared HDF5 dump and one DIAGPT HEFFSO handoff file.

Runtime Model#

The recommended route is the unified cipsixx workflow, which validates all inputs, generates the runtime namelist, and checkpoints completion. For a manual run, provide:

  • An HDF5 dump from pyscf2mppt; it must contain orbital metadata and intso. Select it with MPPT_HDF5_FILE=/path/to/calculation.h5. The historical fallback name is pyscf_dump.h5.

  • The fixed <prefix>heffso.1.h5 handoff from DIAGPT, for example Pr_heffso.1.h5. The .1 suffix is retained for file compatibility.

  • A HEFFSO input file with &sofil, a title line, &sort, and &ic.

The legacy previous-stage scalar integral and determinant files are not used by the current HEFFSO route.

Minimal input:

&sofil prefix='Pr_', &end
Pr
&sort
  nvectw=228, primme_guess_space=-1,
  primme_max_basis=0, primme_max_block=0, primme_max_matvecs=0,
  primme_eps=1.d-6, primme_initial_vector_tolerance=1.d-7,
  primme_print_level=1, primme_progress_interval_seconds=60,
  primme_allow_constrained_basis=.false.,
  primme_preconditioner=.true., primme_direct_sparse=.true.,
&end
&ic iorder=2, &end

iorder=2 reads the h2 matrix from the HDF5 handoff. Use iorder=1 for h1.

Bare Projected Effective Operators#

Set effective_operators=.true. in &sort, or set mppt.heffso.effective_operators: true in the unified YAML input, to write the bare projected effective-operator artifact. This route requires full-space intdip and intang datasets in the PySCF HDF5 file. It does not require scalar root vectors or energies in the DIAGPT handoff.

For each Cartesian one-body operator Q in L, S, J, and the length-gauge dipole r, HEFFSO stores V^dagger Q V in the HEFFSO eigenstate basis, where the columns of V are the computed HEFFSO eigenvectors in the finite determinant catalog. The total angular-momentum matrices satisfy J = L + S component by component. Before projection, HEFFSO converts the legacy excitation-record phases of those eigenvectors to the canonical alpha-then-beta occupation convention used by the catalog operator kernel.

The determinant catalog is also the model-space projector: an operator-generated daughter determinant contributes only when that daughter is present in the finite catalog. External daughters outside the catalog are omitted. The stored matrices are therefore bare model-space operators. They do not include wave-operator dressing or an external-space correction, and they do not provide exact Casimir values, multiplet or parentage assignments, certification, or exact E1 spectroscopy claims.

The run writes <prefix>heffso_effective_operators.h5 with schema mppt_heffso_effective_operators_v1. For n HEFFSO states, its required attributes are:

Attribute

Value or meaning

schema, schema_version

mppt_heffso_effective_operators_v1, 1

index_base, state_count, write_complete

one-based state IDs, n, completion marker 1

energy_unit, energy_reference

hartree, absolute_electronic

vacuum_energy_hartree

vacuum energy added to the HEFFSO eigenvalues

cartesian_components, matrix_axis_order

x,y,z, component,bra_state,ket_state

operator_semantics, state_basis, projection

bare_projected_model_space, heffso_eigenvectors, V_dagger_Q_V

dipole_operator, dipole_origin_bohr

r and its three-component origin in bohr

Required datasets are:

Dataset

Shape

Meaning

state_id

(n,)

contiguous one-based state IDs

state_energy_hartree

(n,)

absolute electronic energies in Hartree

l_matrix_real, l_matrix_imag

(3,n,n)

split-complex Cartesian L matrices

s_matrix_real, s_matrix_imag

(3,n,n)

split-complex Cartesian S matrices

j_matrix_real, j_matrix_imag

(3,n,n)

split-complex Cartesian J = L + S matrices

dipole_matrix_real, dipole_matrix_imag

(3,n,n)

split-complex Cartesian bare dipole matrices

An effective-operators-disabled run removes any existing artifact with that prefix before continuing, so a stale enabled-run file is not exposed as current output. MPPT_HDF5_FILE must not name or alias that prefix-owned artifact; native HEFFSO checks file identity before cleanup and rejects the run instead of deleting its input.

Caspy provides a typed eager reader:

from caspy import read_heffso_effective_operators

result = read_heffso_effective_operators(
    "Pr_heffso_effective_operators.h5"
)
print(result.state_energy_hartree)
print(result.j_matrix.shape)  # (3, n, n)

The returned arrays own their data and are read-only; the source HDF5 handle is closed before the reader returns. The reader validates the v1 metadata, shapes, finiteness, Hermiticity, and J = L + S relation.

Human Report#

The bounded console report is independent of the effective-operator switch. It contains only:

  • SPIN-ORBIT STATES, with state, absolute Eh, dE / eV, and dE / cm-1;

  • ACTIVE-ORBITAL OCCUPATIONS;

  • DOMINANT CONFIGURATION WEIGHTS.

Operator matrices are HDF5-only. Caspy’s text parser reads these bounded energy, occupation, and configuration sections; use read_heffso_effective_operators for L, S, J, and dipole matrices.

Runtime Controls#

Raw &sort controls and defaults are:

Setting

Default

Role

primme_guess_space

-1

p-space size; negative selects min(n, max(512, 2*nev))

primme_max_basis

0

search basis; zero selects min(n, max(nev+64, 4*nev))

primme_max_block

0

block size; zero selects min(nev, 8, OpenMP threads)

primme_max_matvecs

0

matrix-vector budget; zero selects max(10000, 400*nev)

primme_eps

1.0e-6

relative residual convergence tolerance

primme_initial_vector_tolerance

1.0e-7

minimum norm accepted for an initial vector

primme_print_level

1

compact progress reporting

primme_progress_interval_seconds

60

maximum progress interval at outer-iteration boundaries

primme_allow_constrained_basis

.false.

permit an explicit basis smaller than 2*nev

primme_preconditioner

.true.

diagonal preconditioner policy

primme_direct_sparse

.true.

direct complex sparse callback policy

configuration_weight_percent

10.0

strict `

configuration_top_n

3

minimum configurations per state

PRIMME tolerances are finite and positive. Explicit PRIMME limits are rejected instead of clamped. A basis below 2*nev requires primme_allow_constrained_basis=.true., and any basis below the recommended 4*nev emits a performance warning. Before allocating solver storage, HEFFSO reports the complex n * max_basis basis lower bound and the returned n * nev vectors in GiB. PRIMME working memory is higher than this portable lower bound. configuration_weight_percent must be finite and in [0,100]; configuration_top_n must be positive.

HEFFSO always uses the repository-pinned PRIMME 3.2.3 eigensolver. CMake fetches and builds this mandatory dependency; configuration or compilation fails rather than producing a binary with a different eigensolver.

Plain BLAS/LAPACK Build#

This path is useful for portability checks and systems without oneMKL. It is not the preferred performance path.

MPPT_PREFIX="$CONDA_PREFIX"
cmake -S . -B build_heffso_blas \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_PREFIX_PATH="$MPPT_PREFIX" \
  -DHDF5_ROOT="$MPPT_PREFIX" \
  -DOpenMP_gomp_LIBRARY="$MPPT_PREFIX/lib/libgomp.so.1" \
  -DWITH_MKL=OFF \
  -DWITH_MKL_SPARSE=OFF \
  -DWITH_CUDA_SPARSE=OFF
cmake --build build_heffso_blas --target heffso

To force system BLAS/LAPACK instead of whatever CMake finds first:

cmake -S . -B build_heffso_blas \
  -DBLAS_LIBRARIES=/usr/lib/x86_64-linux-gnu/libblas.so.3 \
  -DLAPACK_LIBRARIES=/usr/lib/x86_64-linux-gnu/liblapack.so.3 \
  ...

With no sparse backend compiled, PRIMME falls back to the split real/imaginary Fortran/OpenMP HMAT callback.

Optional CUDA Build#

CUDA/cuSPARSE is an experimental acceleration backend for the PRIMME sparse matrix products. It is not selected implicitly at runtime.

Build CUDA together with MKL:

MPPT_PREFIX="$CONDA_PREFIX"
cmake -S . -B build_heffso_cuda \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_PREFIX_PATH="$MPPT_PREFIX" \
  -DHDF5_ROOT="$MPPT_PREFIX" \
  -DOpenMP_gomp_LIBRARY="$MPPT_PREFIX/lib/libgomp.so.1" \
  -DWITH_MKL=ON \
  -DWITH_MKL_SPARSE=ON \
  -DWITH_CUDA_SPARSE=ON \
  -DCUDAToolkit_ROOT="$CUDA_HOME" \
  -DCMAKE_CUDA_COMPILER="$CUDA_HOME/bin/nvcc" \
  -DCMAKE_CUDA_ARCHITECTURES=86
cmake --build build_heffso_cuda --target heffso

Runtime:

export HEFFSO_SPMM=cuda

build_heffso_cuda/bin/heffso < Pr_heffso.inp > heffso.log 2> heffso.stderr

CUDA controls:

  • HEFFSO_CUDA_SPMM_ALG=csr_alg3 is the tuned default.

  • HEFFSO_CUDA_SPMM_ALG=csr_alg1, csr_alg2, or default can be used for comparisons.

  • HEFFSO_CUDA_TIMING=1 prints aggregate CUDA setup, transfer, and SpMM times.

The Python workflow requires direct_sparse: true for the CUDA backend and includes both CUDA controls in HEFFSO checkpoint identity.

Use CUDA only after the MKL path is working and validated on the same input.

Validation#

For every build profile:

cmake --build <build_dir> --target heffso mppt_heffso_unit_tests \
  mppt_heffso_effective_operators_writer_probe
ctest --test-dir <build_dir> -L HEFFSO --output-on-failure

Smoke-test the Python/MPPT path:

conda run -n mppt ctest --test-dir <build_dir> -R '^hf_based_mppt_H2O_no_symm$' \
  --output-on-failure

For CUDA builds add HEFFSO_SPMM=cuda to the smoke-test environment.

mppt.heffso.print_level and raw primme_print_level use these levels:

  • 0: final completion or failure summary only.

  • 1: compact progress after another 5% of roots converge or after 60 seconds.

  • 2: PRIMME per-root convergence output.

  • 3 and above: increasingly detailed iteration diagnostics.

The compact lines start with HEFFSO PRIMME, so the Python workflow mirrors only those lines live while retaining the complete output in .mppt-workflow/logs/heffso.log. Raw &sort input accepts the complete primme_* contract listed above. Workflow runs remove historical HEFFSO_PRIMME_* and HEFFSO_GUESS_SPACE variables so ambient shell settings cannot override fingerprinted YAML controls.

With PRIMME hard locking, compact progress counts locked roots, matching PRIMME’s monotonic completed-root contract. An exact zero Hamiltonian is also a valid converged case when both its scaled residual limit and residual are zero. Debug builds suspend IEEE exception halting only while inside zprimme and restore the caller’s modes before HEFFSO post-processing.

The repository test-light target injects exact paths to the current CMake targets. See the installation guide for the supported test command.

Outputs#

HEFFSO writes:

  • HEFF.TMP

  • HMAT

  • <prefix>sovec (for YAML prefix Pr, this is Pr_sovec)

  • <prefix>heffso_effective_operators.h5 when effective_operators=.true.

  • the console table headed state Eh dE / eV dE / cm-1

Successful logs end with:

fin heffso

Performance Notes#

  • MKL Sparse BLAS is the default performance target on CPU.

  • Bare operator projection traverses the finite determinant catalog and skips every generated daughter that is not in that catalog. Cost scales with the catalog, operator connectivity, and requested state count; no external determinant image map is built.

  • CUDA can improve large sparse PRIMME matvecs on the local RTX 3090, but profiling shows the remaining wall time is mostly CPU-side PRIMME and projected-vector work, not host-device transfer.

  • Automatic guess space uses min(n, max(512, 2*nev)). Set guess_space explicitly only for a controlled comparison or memory-constrained run.