Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Contributing and the Rust API

CONTRIBUTING.md owns branch naming, lint policy, and verification commands. See development environments for setup.

The workspace keeps CLI parsing and presentation in the root package and scientific configuration and calculations in rustiq-chem-core. The core’s calculation module orchestrates work in molecules, basis, eri, hf, and mp2.

Rustdoc remains the canonical public API reference. Generate and open it with MathJax support:

tools/generate-rustdoc.sh --open

On Windows:

.\tools\generate-rustdoc.ps1 -Open

The generated entry point is target/doc/rustiq_core/index.html. MathJax equations require browser access to the CDN. The initial Pages site publishes the manual; rustdoc is generated separately.

Runnable API examples and public API tests provide executable workflows and verification. Link to these sources instead of duplicating item-level documentation in the book.

Architecture and calculation lifecycle

The root CLI package owns terminal reports, application directories, and src/runfile/, which resolves TOML/Nickel through the embedded Nickel schema. The library owns scientific configuration and calculations without a Nickel dependency. This boundary lets a different frontend supply scientific options without embedding its input syntax or terminal behavior into numerical code.

Within the core, molecules owns geometry, units, charge and electron counts; basis constructs Gaussian functions; eri computes and stores electron repulsion integrals; hf solves RHF/UHF; and mp2 consumes HF orbitals. Rust makes ownership and mutation explicit for matrices, integral storage, and shared results. Enums model choices such as the HF method, while Cargo brings dependency locking, feature selection, and tests into one workflow. These engineering tools help make assumptions inspectable; they do not establish numerical correctness or a performance advantage over other languages.

Typed errors distinguish invalid input from numerical failures. Optional source locations let the CLI attach diagnostics to input text without making the library own that text or its presentation.

CalculationBuilder accepts geometry, basis data, and scientific options. prepare() validates the state, converts coordinates to Bohr, constructs the basis, and resolves RHF/UHF. A prepared calculation can execute repeatedly. run_hf() distinguishes converged and unconverged outcomes; only the converged solution exposes mp2(). This type boundary prevents accidental MP2 execution on unconverged orbitals. Cloned solutions share immutable scientific data; execution errors retain completed HF outcomes when available.

The normalized CalculationRequest records scientific input without geometry paths or frontend source spans. Canonical TOML/XYZ rendering belongs to CLI adapters. Core consumers supply explicit paths to BasisStore::new; application storage environment variables are CLI policy. The core has no default features; its optional online feature enables online basis support. See the runnable examples and public API tests above for complete construction and error handling.

Data preparation, execution, and reuse

The lifecycle is:

CLI TOML/Nickel adapter or another frontend
    -> geometry + basis data + scientific options
    -> CalculationBuilder::prepare()
       molecule in Bohr, Gaussian basis, resolved HF method and random seeds
    -> PreparedCalculation::run_hf()
       one-electron integrals, overlap orthogonalization, AO ERI acquisition
       -> iterative SCF and final canonicalization
       -> HfOutcome::Converged or HfOutcome::Unconverged
    -> converged HfSolution::mp2()
       blocked AO-to-MO transformation and correlation energy

prepare() constructs reusable input data; it does not compute integrals or solve HF. Each normal run_hf() call builds a new HF execution state, including one-electron integrals and the orthogonalizer. Without an explicit reuse source, AO ERIs are recomputed too. Repeated execution of a prepared calculation does not itself memoize these numerical arrays. Random seeds resolved at preparation are retained for repeated executions.

An optional EriCache can load compatible AO ERIs from a directory or store newly computed ones. It is disposable local storage. A supplied CompactEri through run_hf_with_eri() bypasses AO ERI computation and cache lookup, but the raw tensor API checks its expected element count rather than proving its scientific provenance. The caller must supply ERIs for the prepared geometry, AO ordering, and screening policy. Use the persistence APIs’ compatibility checks when reusing an archive. HF solutions retain their AO ERIs, and cloned solutions share immutable result data; these retained results are distinct from the prepared input data.

Portable .rustiq bundles can be read and written through the core persistence APIs and through the CLI’s run --reuse, run --artifact, and artifact inspect commands. CLI reuse starts from the supplied runfile and resolves its geometry and basis as usual, then uses bundle compatibility to select AO ERIs; the bundle is not an input-file substitute. The Rust API can also reconstruct a calculation from the archived scientific snapshots. Neither workflow turns a local cache directory into a portable artifact. See the portable bundle guide, the persistence contract, and the runnable API examples for details.

This distinction matters for performance: compact AO ERI storage still grows as the fourth power of basis dimension, and the MP2 workspace budget covers additional transformation buffers rather than the full HF data or process memory. See MP2 memory policy.

Build profiles and performance investigation

Cargo’s default development and test builds favor development speed. Release builds optimize execution using thin link-time optimization and one codegen unit, and strip symbols. The custom profiling profile retains release optimizations with debug information and symbols:

cargo build --locked --release
cargo build --locked --profile profiling

The profiling executable is under target/profiling/. For optimization specific to the build machine’s CPU, use RUSTFLAGS="-C target-cpu=native" cargo build --locked --release; that binary may require instructions absent on another CPU. In PowerShell, set $env:RUSTFLAGS = "-C target-cpu=native", build, then remove it with Remove-Item Env:RUSTFLAGS. There is no separate native Cargo profile.

The eri_timings and mp2_timings benchmarks use Criterion and require bench-support:

cargo bench --bench mp2_timings --features bench-support
cargo bench --bench eri_timings --features bench-support

The MP2 benchmark compares dense and memory-blocked kernels on deterministic synthetic inputs. It validates that both paths produce matching energies before timing them; input and ERI construction remain outside the measured iterations. RUSTIQ_MP2_MEMORY, RUSTIQ_MP2_SIZES (comma-separated AO dimensions), and RAYON_NUM_THREADS select the memory budget, AO dimensions, and thread count. The ERI benchmark times repeated integral construction for the checked-in molecular cases. By default it skips the larger ethanol and cholesterol cases; set RUSTIQ_BENCH_HEAVY=1 to include them. RUSTIQ_BENCH_FILTER selects cases by name or geometry path, and RUSTIQ_BENCH_BASIS_STORE selects a basis store. It reports compact ERI storage elements processed per second. This count is the size of the compact representation; Schwarz screening may skip evaluations or leave stored elements zero, so it is not a count of integrals evaluated per second.

The standard cases use 30 samples, a 2-second warm-up, and a 5-second measurement target. Heavy ERI cases and MP2 cases with 48 or more AOs use Criterion’s minimum of 10 samples, a 1-second warm-up, and a 2-second target. These are targets: Criterion may take longer to collect the requested samples, especially when each calculation is expensive. Heavy ERI cases remain disabled unless RUSTIQ_BENCH_HEAVY=1 is set. Measurements are saved under target/criterion.

Criterion baselines can be compared only between revisions that both use Criterion. The first Criterion-enabled revision establishes the starting point; legacy timing results cannot be compared directly with Criterion measurements. MP2 input construction is excluded from measured iterations. Keep CPU architecture, Rayon thread count, build flags, enabled features, MP2 memory budget, power settings, and benchmark environment variables consistent. Save a baseline on the first Criterion revision, then compare from the revision under test:

cargo bench --bench mp2_timings --features bench-support -- --save-baseline before
cargo bench --bench mp2_timings --features bench-support -- --baseline before

See the MP2 benchmark source and ERI benchmark source. Benchmarks provide performance measurements, not scientific validation.