Introduction
RustiQ is an experimental Rust quantum chemistry application and reusable
rustiq-chem-core library. This manual serves scientific users, Rust contributors,
and theoretical chemists.
Do not use RustiQ results for research conclusions without independent validation against established quantum chemistry packages.
Choose TOML for a single calculation or optional Nickel for parameterized studies. Both formats share the same defaults and validation; see calculation inputs and execution for how an input becomes a result.
Where should I start?
- Scientific users: Installation → First H₂ calculation → Interpreting output. These explain how to run the software without writing Rust. Read scientific limitations before using the results.
- Rust developers and architects: Development environments
→ Contributing, architecture, and the Rust API
→ Documentation checks. Start with the
calculation lifecycle to see how input, scientific code, and reporting fit together.
User-guide commands use the installed
rustiqexecutable; a source checkout can install it with the instructions on the installation page or run it through Cargo. - Theoretical chemists: First calculation → Reference comparisons → Scientific limitations. These identify tested evidence and current assumptions without requiring development tools. The release binary is sufficient for calculations; reproducing the reference suite additionally requires a source checkout and its documented test environment.
The glossary explains unfamiliar scientific and software terms. Existing workflow notes preserve useful operational guidance alongside the user guides and CLI reference.
Implemented capabilities include RHF, UHF, MP2, XYZ geometries, Gaussian basis sets, TOML and native Nickel input, sequential studies, and versioned JSON. The practical user guides now cover these capabilities, including HF/MP2 calculations, Nickel studies, JSON output, and portable calculation bundles. The command-line reference describes the shipped commands and options.
Portable .rustiq bundles can be written, reused, and inspected from the CLI
as well as through Rust APIs. Start with the
portable bundle guide for a runnable CLI
workflow, then see the persistence specification
for the archive contract.
The authoritative references page links to the roadmap
for plans and to the files that define existing contracts.
Installation
After a release promotion completes, RustiQ is distributed through a prebuilt archive on GitHub Releases, the Cargo registry, and the Nix flake. The three publications run independently, so use the channel where the release is listed. They are all built from the same release tag.
| Method | Choose it when | Platforms and manual |
|---|---|---|
| GitHub Releases archive | You want a runnable executable without installing Rust or Nix. | The six target platforms listed below; includes the offline manual. |
| Cargo | You already use Rust and Cargo, or want Cargo to build RustiQ locally. | Native Cargo-supported platforms; uses the online manual. |
| Nix | You already use Nix or want declarative installation and a pinned package environment. | Linux x86_64/ARM64 and Apple Silicon macOS; includes the offline manual. |
Install a prebuilt release binary
Download the archive for your operating system and CPU from the
GitHub Releases page.
Archives are named rustiq-chem-<target>.tar.gz on Unix and
rustiq-chem-<target>.zip on Windows. Supported targets are
x86_64-unknown-linux-gnu (Linux Intel/AMD),
aarch64-unknown-linux-gnu (Linux ARM64), x86_64-apple-darwin (Intel
macOS), aarch64-apple-darwin (Apple Silicon),
x86_64-pc-windows-msvc (Windows Intel/AMD), and
aarch64-pc-windows-msvc (Windows ARM64). Linux GNU archives require a
compatible glibc runtime.
RustiQ-authored code is MIT OR Apache-2.0. Executables include LGPL libraries, third-party notices and a matching corresponding-source archive on the same release page. See licenses and redistribution for source access, rebuilding and package redistribution requirements.
Verify and run the executable
Download the release’s sha256.sum beside the archive chosen for your platform.
You do not need the archives for other platforms. Copy only the matching line
from sha256.sum into a new text file named selected.sha256, preserving both
the hash and filename. On Linux or macOS, verify it before extracting:
sha256sum --check selected.sha256 # Linux
shasum -a 256 --check selected.sha256 # macOS
On Windows, use PowerShell to compare the downloaded archive’s computed hash
with its matching entry in sha256.sum:
$archive = "rustiq-chem-x86_64-pc-windows-msvc.zip"
$entries = @(Select-String -Path .\sha256.sum -SimpleMatch $archive)
if ($entries.Count -ne 1) { throw "Expected one checksum entry for $archive" }
$expected = ($entries[0].Line -split '\s+')[0]
$actual = (Get-FileHash ".\$archive" -Algorithm SHA256).Hash
if ($actual -ine $expected) { throw "SHA-256 mismatch for $archive" }
Write-Host "SHA-256 verified: $archive"
The release guide has the full
platform-specific verification instructions. For Windows ARM64, replace the
archive filename with rustiq-chem-aarch64-pc-windows-msvc.zip. Extract the
archive only after the checksum comparison succeeds. From the directory holding
the download, extract it with one of the following commands:
tar -xzf rustiq-chem-<target>.tar.gz # Linux or macOS
Expand-Archive rustiq-chem-<target>.zip -DestinationPath .\rustiq-chem
Open a terminal in the extracted directory and run ./rustiq --help on Linux
or macOS, or .\rustiq.exe --help in PowerShell. This works without changing
PATH. To run rustiq from any directory, add the directory containing
rustiq or rustiq.exe to PATH and open a new terminal.
The Cargo package is named rustiq-chem; the executable is named rustiq (or
rustiq.exe on Windows).
Install with Cargo
Install the released Cargo package from crates.io from any directory. No source checkout is needed. This builds RustiQ from source and requires Rust and Cargo, a C/C++ toolchain, and CMake; see manual setup for platform prerequisites, but do not follow that page’s checkout commands unless you intend to contribute.
cargo install --locked rustiq-chem --version '=0.1.0-beta.1'
rustiq --help
Ensure Cargo’s binary directory is on PATH. Cargo-only installations use the
online manual, as described below.
Install with Nix
See installing with Nix for the supported platforms,
profile and declarative installation, and CPU-specific builds. That page uses
the repository’s default branch, main, which contains released versions only.
Consult the manual
Release archives contain an offline HTML manual in manual/html/ beside the
executable. Keep that directory with the executable when moving the extracted
installation. The Nix package installs the same offline manual under
share/doc/rustiq/manual/html. Navigation, styling, equations, and diagrams use local
resources; external reference links require network access.
rustiq docs
rustiq docs --web
rustiq docs --print-path
rustiq docs opens the installed manual in the default browser using a browser-specific
launcher, independently of HTML file associations. --web forces
the online manual for the compiled release version; development builds use
the development manual. The choice is
made from the Cargo package version without a network lookup. Versions with a
complete dev prerelease identifier, such as 0.1.0-alpha.1.dev, select /dev/.
Other versions, including alpha and beta releases, select /vVERSION/.
This applies equally to Cargo, Nix, and release archives, without packaging flags.
A release-version source build selects its versioned manual even before publication.
--print-path prints the
absolute local index path without starting a browser; combine it with --web
to print the online URL instead. On headless machines, copy the manual tree to
another machine and open its index.html, or use the printed URL in a browser
with network access.
Cargo-only installations have no bundled manual: rustiq docs opens the online
manual and --print-path prints its URL. RustiQ does not download the manual.
An existing manual directory with a missing index produces an error; restore
the complete installation or use --web. If the whole manual directory has
been removed, RustiQ cannot distinguish the installation from a Cargo install
and uses the online manual.
If browser launching fails, the diagnostic includes the target and the
--print-path route. RustiQ uses the operating system’s default browser opener.
PDF export is future work and --pdf is not supported.
After installation: obtain a basis and run a calculation
Run rustiq --version to confirm the installation. Installed release packages
do not include sample inputs or basis data. With network access, download a
basis using rustiq basis download sto-3g. This command is available in online
builds and requires network access. To work offline, import a local Basis Set
Exchange JSON file with rustiq basis import /path/to/basis.json; import does
not access the network. The first calculation works
with an archive, Cargo, or Nix installation. See the
basis-set guide for basis-data details.
Build and install from source
Contributors and users building from a checkout need Git, Rust through rustup, a C/C++ build toolchain, and CMake. Clone from a parent directory, then run Cargo commands from the checkout root. For complete prerequisite and platform details, see the manual setup.
git clone --branch develop --single-branch https://github.com/mveril/RustiQ.git
cd RustiQ
cargo build --locked
The default branch, main, is reserved for released versions. Use develop
for an active development checkout; a checkout intended to reproduce a release
should instead use its release tag.
For example, to reproduce the 0.1.0-beta.1 release source, clone its tag:
git clone --branch v0.1.0-beta.1 --single-branch https://github.com/mveril/RustiQ.git
cargo build does not add the executable to PATH. To run without installing,
prefix commands with cargo run --locked --, for example
cargo run --locked -- --help. To install the package executable into Cargo’s
binary directory:
cargo install --locked --path .
rustiq --help
See the development environments page for Nix, Docker, and other supported contributor setups.
Installing with Nix
Nix is one of the three release installation channels, alongside a GitHub Releases archive and the Cargo package. This page covers the Nix-specific choices.
Install Nix and enable the nix-command and
flakes experimental features. The flake supports x86-64 Linux, ARM64 Linux,
and Apple Silicon macOS. On Windows, use Nix inside WSL2 to run the Linux
package. See Nix setup for enabling
flakes and platform prerequisites. The first install needs network access and
may compile dependencies. Install the standard package from any directory with:
nix profile install github:mveril/RustiQ
rustiq --version
The unqualified github:mveril/RustiQ reference follows GitHub’s default
branch, main. That branch contains released versions only. To keep a fixed
version, use a release tag (for example,
github:mveril/RustiQ/v0.1.0-beta.1) or a commit revision instead.
An unqualified reference is captured only when a consuming configuration’s
flake.lock is updated; a tag makes the selected release explicit.
Home Manager without a configuration flake
If your Home Manager configuration uses home.nix directly, create a
rustiq.nix file beside it:
{ pkgs, ... }:
let
rustiq = builtins.getFlake "github:mveril/RustiQ";
in
{
home.packages = [
rustiq.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
Add the module to the imports in home.nix, keeping any existing imports:
imports = [ ./rustiq.nix ];
Apply the configuration using your usual command. For Home Manager integrated
as a NixOS module, run sudo nixos-rebuild switch --impure; for standalone Home
Manager, run home-manager switch --impure. The unlocked GitHub reference
requires impure evaluation. Check rustiq --version afterward. The reference tracks
the release-only default branch, main, and is not pinned by a configuration
flake.lock; use a revision in the URL
for a fixed version. The standard package is portable across machines of the
same supported platform.
Home Manager and NixOS
The following snippets extend an existing flake-based configuration. Add
RustiQ as an input to your configuration’s flake.nix:
inputs.rustiq.url = "github:mveril/RustiQ";
The configuration’s flake.lock pins that input. To update it later, run
nix flake update rustiq in the configuration directory, then apply the
configuration again. Keep your existing inputs, modules, and state version.
If the configuration is a Git flake, add any newly created module files to Git
before applying it so that Nix can see them.
Home Manager
In the existing outputs function, bind the inputs as inputs@{ ... }, and
pass them to your existing home-manager.lib.homeManagerConfiguration:
extraSpecialArgs = { inherit inputs; };
Merge this with any existing extraSpecialArgs. In your home.nix, add
inputs to the module arguments and add RustiQ to home.packages:
{ pkgs, inputs, ... }:
{
home.packages = [
inputs.rustiq.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
Merge the list with your existing packages. From your configuration directory,
apply it with home-manager switch --flake .#YOUR_USER and check
rustiq --version. Replace YOUR_USER with your Home Manager configuration
name. See the Home Manager flake guide.
For Home Manager as a NixOS module, pass the inputs through
home-manager.extraSpecialArgs instead.
NixOS configuration.nix
In the existing outputs function, bind the inputs as inputs@{ ... }, and
pass them to your existing nixpkgs.lib.nixosSystem:
specialArgs = { inherit inputs; };
Merge this with any existing specialArgs. Create rustiq.nix beside your
configuration.nix. This complete NixOS module installs the standard portable
RustiQ package:
# NixOS module: provide the RustiQ flake through specialArgs.inputs.
{ pkgs, inputs, ... }:
{
environment.systemPackages = [
inputs.rustiq.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
Then import it in the existing configuration.nix, preserving any other imports:
{ ... }:
{
imports = [ ./rustiq.nix ];
}
Alternatively, add ./rustiq.nix to the modules list in nixosSystem.
From the configuration directory, apply it with
sudo nixos-rebuild switch --flake .#YOUR_HOST and check rustiq --version.
Replace YOUR_HOST with your NixOS configuration name. See the
NixOS package management guide.
Optional CPU-specific build
The examples above use the portable standard package. For NixOS or Home Manager, replace that package expression with this one only when a build tied to the build machine’s CPU is appropriate:
(inputs.rustiq.legacyPackages.${pkgs.stdenv.hostPlatform.system}.cpuTarget "native")
For a profile installation from any directory, use one command instead:
nix profile install --impure --expr '(builtins.getFlake "github:mveril/RustiQ").legacyPackages.${builtins.currentSystem}.cpuTarget "native"'
List compiler CPU names with rustc --print target-cpus (for example inside
nix develop github:mveril/RustiQ#rust). native selects the build machine’s CPU, which may differ from the machine
running RustiQ when using remote builders. Its detected CPU is not recorded in
the Nix build identity: cached results may have been built for a different CPU.
For reproducible builds or deployment across machines, replace native with a
compatible explicit CPU name such as znver3. A binary may fail on machines
with fewer processor features. This setting applies to Rust-compiled code and
does not promise optimization of every native dependency. The --impure flag
allows the command-line expression to obtain the current system and resolve the
unlocked GitHub reference.
Build from a checkout
From the root of a RustiQ checkout, build the default package and run it without adding it to your profile:
nix build
./result/bin/rustiq --version
For development, clone develop explicitly because the default branch is
release-only:
git clone --branch develop --single-branch https://github.com/mveril/RustiQ.git
cd RustiQ
nix develop
The package includes the offline manual and shell completions. Run rustiq docs
after installing, or ./result/bin/rustiq docs from the checkout. See the
manual instructions and the
Nix package guide.
The package enables online basis downloads but does not bundle sample inputs or basis sets. Download or import a basis before running a calculation; see obtaining a basis after installation and the first calculation. For development shells, see Nix setup.
First H₂ calculation
Using an installed release
The following commands work after installing a release from a GitHub archive,
Cargo, or Nix. Copy the following geometry into a file named h2.xyz in your
working directory. It is the same geometry used by the checked-in sample:
2
Hydrogen molecule
H 0.0 0.0 -0.37
H 0.0 0.0 0.37
The explicit download is needed because run does not fetch missing bases
unless --auto-download or RUSTIQ_AUTO_DOWNLOAD enables downloading.
Use --no-auto-download to explicitly prevent it. The release archive contains
neither sample inputs nor basis files. To use an existing local basis file without
network access, import it with rustiq basis import /path/to/basis.json.
Create an input, download STO-3G, and run the calculation:
rustiq init h2.xyz -o calculation.toml
rustiq basis download sto-3g
rustiq run calculation.toml
Tip
With an online-enabled build and network access, you can replace the separate download and run commands with
rustiq run calculation.toml --auto-downloadto fetch a missing basis.
Reproducing the sample configuration without a checkout
The checked-in configuration is included directly:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf.guess]
type = "CoreHamiltonian"
You can also copy this configuration without a checkout: save the geometry
shown above as molecule.xyz in a new working directory, create an inputs
directory with mkdir inputs, and save the TOML as inputs/h2.toml. After
obtaining STO-3G as described above, run rustiq run inputs/h2.toml. The
../molecule.xyz path resolves relative to the runfile directory. This is an
alternative to the init workflow; keep using calculation.toml from that
workflow in subsequent guides.
Using the checked-in sample
From a source checkout, run these commands from the repository root to import the checked-in fixture and run the example without installing RustiQ:
cargo run --locked -- basis import tests/data/sto-3g.json
cargo run --locked -- run samples/h2/sto-3g/calculation.toml
CLI tests import the same fixture into an isolated store.
Verifying the calculation
Default input units are Angstrom; resolved coordinates are Bohr. The neutral
singlet defaults resolve HF Auto to RHF. The core-Hamiltonian guess makes
this example deterministic.
The following verification commands are for users working from a source checkout; they are optional when using only the release binary. The existing CLI regression test checks this input, RHF resolution, units, two SCF iterations, and these selected output lines. Its reproducible command is below; the test source is linked for readers who want to inspect its assertions.
SCF converged after 2 iterations.
Total Energy (including nuclear repulsion): -1.116759 Hartree
Run that verification with:
cargo test --locked --test cli_samples test_cli_h2_sample_converges_and_prints_reference_energy
For independent numerical verification, the h2-sto-3g-rhf case compares full
precision JSON energies against PySCF with a 2e-10 Hartree energy tolerance.
The rounded terminal value above is not that tolerance. See the book’s
scientific scope and reference comparisons
for the coverage boundary. The comparison implementation and full reference
instructions are linked below.
Reference test instructions on GitHub
Reproducing this comparison requires the cloned repository and its Nix
development environment (or the documented uv/PySCF setup); the binary
archive alone does not include the reference harness.
nix run .#pyscf-check -- -k 'h2-sto-3g-rhf and not mp2'
These checks validate this case, not arbitrary chemistry. Results remain experimental and require independent validation before research use. Continue with output interpretation. To save and reuse the calculation’s AO ERIs, continue with the portable bundle guide.
Explore more calculations and workflows in the examples index.
Interpreting output
The standard run report has three visible parts:
-
Requested options: a canonical TOML representation of the requested calculation and a canonical XYZ representation of its input geometry. These show the options after parsing and normalization; they do not reproduce the original source text or comments.
-
Resolved settings: a concise summary of the scientific setup used for the calculation, including atom count, charge, multiplicity, coordinate units, resolved HF method, and basis name and size.
-
Numerical results: SCF convergence information, energy values, overlap rank, energy components, and timings. The H₂ sample’s total HF energy is reported as
-1.116759Hartree. The first sample resolves to neutral singlet H₂, RHF, STO-3G, and two basis functions. Input coordinates are Angstrom; resolved coordinates are Bohr. Energies are in Hartree. -
Electronic energy: electronic kinetic energy, electron–nuclear attraction, and electron–electron interaction at the HF level.
-
Nuclear repulsion energy: repulsion between the fixed nuclei.
-
Total HF energy: electronic energy plus nuclear repulsion.
-
SCF convergence: the iterative solution met its configured criterion. This does not establish basis completeness or accuracy against experiment.
With colors enabled, section titles are cyan, successful SCF convergence is
green, and displayed energy values are yellow. The same energy-value styling is
used for HF iteration values, energy components, and MP2 energies; residuals
and other diagnostics remain uncolored. The Calculation heading follows the
same title styling. TOML and XYZ use syntax highlighting.
The original TOML and XYZ source text, along with full canonical views of the resolved configuration and geometry, are retained as internal representations; the standard CLI report does not display them.
Portable bundles can retain the scientific input snapshots and AO ERIs for later inspection and compatible reuse. They do not save the energies or the HF wavefunction; see portable calculation bundles.
Convergence and overlap diagnostics
Both RHF and UHF require delta_energy and residual_norm to be below
method.hf.convergence_threshold (default 1e-8). delta_energy is the
absolute change in electronic energy between successive iterations, in Hartree.
residual_norm is the Frobenius norm of the AO matrix residual
\(FPS - SPF\), where \(F\), \(P\), and \(S\) are the Fock, density, and
overlap matrices. UHF combines the alpha and beta norms as
\(\sqrt{r_\alpha^2 + r_\beta^2}\). The same numerical threshold is applied
to both diagnostics; it is not an error bound on the final energy.
Final canonicalization also checks that orbitals obtained from the final Fock matrix reproduce the occupied density within that threshold. Further density updates consume the remaining SCF iteration budget; failure to obtain consistent orbitals is a numerical error. RHF additionally requires an unmixed orbital density before accepting convergence.
Overlap effective rank is the number of retained independent basis directions.
With method.hf.orthogonalization.linear_dependency_threshold = t, eigenvectors
of the overlap matrix are retained only when their eigenvalue exceeds
\(t\lambda_{\max}\). The default is 1e-8. A report of 9/10 means one
direction was discarded, reducing the orbital space used by HF and MP2.
Increasing this threshold can change energies. Setting it to zero retains all
directions only if the overlap matrix is strictly positive definite.
Inspect both convergence diagnostics and the retained rank when comparing calculations. See the Nickel schema for input defaults and the scientific limitations for the interpretation of a converged solution.
The first-calculation test checks the rounded total
energy of -1.116759 Hartree. The independent comparison uses full precision.
MP2 adds a correlation energy to a converged HF reference. This first sample does not request MP2. The checked-in MP2 sample is included here so the manual shows the exact runnable input:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf]
method = "Rhf"
[method.hf.guess]
type = "CoreHamiltonian"
[method.mp2]
frozen_orbitals = 0
Its h2-sto-3g-rhf-mp2 PySCF comparison provides executable evidence for the
MP2 guide; see the book’s
reference comparison coverage.
A successful small-basis H₂ test does not validate every molecule, basis, open-shell state, or chemical prediction. Review the book’s scientific limitations. The full reference-test instructions remain available on GitHub.
Examples
This curated selection introduces introductory and representative workflows; it is not an exhaustive catalog. See the repository’s samples directory for additional molecules and advanced configurations. Those files require a source checkout and are not bundled with release archives.
These guides use the installed rustiq executable. Basis sets are not distributed
with RustiQ: download them explicitly, or import independently obtained JSON files
with rustiq basis import /path/to/basis.json when offline. Automatic downloads
must be enabled explicitly with --auto-download or
RUSTIQ_AUTO_DOWNLOAD; --no-auto-download prevents them. See
basis availability for offline and online builds.
| Example and objective | Basis | Guide and prerequisites |
|---|---|---|
| H₂ / RHF: first calculation | STO-3G | First calculation; create the XYZ file and obtain the basis. |
| OH / UHF: open-shell calculation | STO-3G | Hartree–Fock; create the OH geometry and obtain the basis. |
| H₂ / RHF-MP2: electron correlation | STO-3G | MP2; first create H₂ as in the first calculation. |
| OH / UHF-MP2: open-shell correlation | STO-3G | Open-shell MP2; create OH as in the HF guide. |
| Inspect and transform XYZ geometry | None | Geometry; create an XYZ file. |
| Parameterized and batch studies | STO-3G and 6-31G | Nickel studies; obtain both bases. No separate Nickel executable is needed. |
| Create, inspect, verify and rerun bundles; reuse AO ERIs | STO-3G | Portable bundles; first prepare the H₂ input and basis. |
Calculation inputs and execution
RustiQ offers two complementary input formats. TOML is the simple choice for one calculation: a small, readable file is enough, and users do not need to learn Nickel.
Nickel is optional for calculation studies. Its imports, functions, and list operations can generate related configurations—for example, varying basis sets or numerical settings without duplicating full input files. Nickel can also describe one calculation.
Both formats pass through the same embedded Nickel contracts for defaults, validation, and normalization. The normalized configurations then enter the same Rust scientific core, which has no dependency on TOML or Nickel. Users do not need to install the Nickel executable: RustiQ embeds the configuration evaluator.
---
config:
flowchart:
htmlLabels: false
---
flowchart TD
TOML["`TOML (.toml)
One calculation`"]
NICKEL["`Nickel (.ncl)
One or more calculations`"]
CONTRACTS["`Shared Nickel contracts
Defaults, validation, normalization`"]
INPUTS["Resolved scientific configurations"]
CORE["`rustiq-chem-core
Runs scientific calculations`"]
RESULTS["Single result or ordered batch results"]
TOML --> CONTRACTS
NICKEL --> CONTRACTS
CONTRACTS --> INPUTS
INPUTS --> CORE
CORE --> RESULTS
Choose the TOML calculation guide for one calculation or Nickel studies for a parameterized campaign. Studies execute sequentially, not as a parallel job scheduler.
Geometry files
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create local inputs and obtain a basis.
RustiQ reads molecular coordinates from XYZ files. Each file starts with the number of atoms, then a comment line, then one line per atom containing an element symbol or atomic number and three Cartesian coordinates. See the checked-in H₂ example:
2
Hydrogen molecule
H 0.0 0.0 -0.37
H 0.0 0.0 0.37
Tip
Element symbols and atomic numbers are interchangeable. Each atom line may use either an element symbol, such as
H, or its atomic number, such as1. Both forms identify hydrogen; this book uses symbols consistently for readability.
The atom count must not exceed the number of atom lines present in the file. RustiQ reports a geometry parse error when the count and available lines do not match, including when the count is too large to represent the supplied geometry.
RustiQ treats the coordinates as Angstrom by default; TOML can specify Bohr. The coordinates in XYZ do not specify molecular charge, spin multiplicity, or units. Those are calculation settings. A charge changes the electron count; multiplicity specifies the intended spin state. RustiQ checks that the electron count and multiplicity have compatible parity, but this check does not identify the physical ground state. See the configuration guide.
Calculations convert between Bohr and Angstrom using the
2018 CODATA Bohr radius published by NIST:
5.29177210903e-11 m, multiplied by 1e10 to obtain Angstrom per Bohr.
RustiQ keeps this edition to preserve existing numerical results. The conversion
regression can be run with
cargo test -p rustiq-chem-core conversion_preserves_the_2018_codata_factor;
it checks the exact floating-point result for one Bohr.
geometry info reports atom and center information, including a nuclear
repulsion value.
The calculation returns an error if any two atoms have exactly identical
coordinates, because their nuclear repulsion is undefined.
Warning
Nuclear repulsion: beware of XYZ coordinate units.
geometry infodoes not convert coordinates from Angstrom to Bohr. XYZ files have no unit metadata, so this command evaluates nuclear repulsion directly from the supplied numbers, effectively treating them as Bohr. For an XYZ file written in Angstrom (including the H₂ sample below), its reported nuclear-repulsion value is not a physically meaningful energy in Hartree. Do not interpret or compare it with energies from a molecular calculation.Unlike
geometry info,rustiq runconverts input coordinates using[molecule].units(default:"Angstrom") before computing energies. This setting does not apply to the standalone geometry command.
With only the release binary, save this geometry as h2.xyz as shown in the
first-calculation guide. After
reading the units warning above, inspect or transform the local file with:
rustiq geometry info h2.xyz
rustiq geometry translate h2.xyz --dz 1 -o h2-shifted.xyz
From the repository root, inspect a geometry with:
rustiq geometry info samples/h2/molecule.xyz
The geometry tools can rotate, translate, center, or orient XYZ coordinates. For example, transformations read and write XYZ and can use standard input/output:
rustiq geometry translate samples/h2/molecule.xyz --dz 1
These are coordinate transformations. They do not change coordinates to
minimize molecular energy and are not geometry optimization. Standalone XYZ
tools do not convert coordinate units; they have no unit metadata.
Transformations change coordinate values, and written XYZ coordinates are
rounded to six decimal places. Use the runfile’s units setting to tell a
calculation how to interpret its coordinates.
Mass centering and principal-axis orientation use atomic weights from
mendeleev:
interval-valued weights use the conventional value, uncertain weights use the
central value, and elements without a standard weight use the mass number of
the most stable isotope. Consequently, these transformations can produce
slightly different coordinates than versions that used a different periodic
table dataset. In the Rust core API, Atom stores mendeleev::Element by
value. The core crate re-exports this type as rustiq_core::Element, so a
downstream crate can construct hydrogen atoms with
rustiq_core::Element::H without declaring its own direct
mendeleev dependency. The same element type supplies atomic numbers for
electronic-structure calculations and atomic weights for geometry operations.
The core methods for mass centering, inertia tensors, and principal-axis
orientation return their values directly without an atomic-weight error.
For a TOML calculation, the geometry path is relative to the TOML file’s
directory. init can create a TOML file that refers to an XYZ file without
copying it:
rustiq init samples/h2/molecule.xyz -o calculation.toml
Run commands from the repository root. The relevant executable checks are in
tests/cli_samples.rs
and tests/init_cli.rs.
Geometry parsing and the transformations themselves are implemented in
crates/rustiq-core/src/molecules/geometry.rs
and src/cli/commands/geometry_command/.
The core Geometry::nucl_repulsion API returns a dedicated
NuclearRepulsionError::CoincidentAtoms for coincident nuclei. It traverses
atom pairs without allocating an intermediate collection.
Continue with basis sets, then configuration.
Gaussian basis sets
A basis set is a finite collection of functions used to represent molecular orbitals. RustiQ’s Gaussian basis functions are built from Gaussian functions centered on atoms. The chosen basis affects the size of the orbital space and the numerical result. A small basis such as STO-3G is useful for examples but does not guarantee accurate energies or properties.
Import or download a basis
basis import reads a Basis Set Exchange JSON file from the path you provide.
It works with the release binary and does not require Cargo or a source
checkout. For example, if sto-3g.json is in the current directory:
rustiq basis import sto-3g.json
rustiq basis list
The import itself is local and needs no network access; you must obtain the
JSON file separately. On a connected computer, choose a basis and JSON format
from the Basis Set Exchange, download the
file, and transfer it to the calculation computer if needed. Then import it
with the executable command above. In a source checkout, the checked-in STO-3G fixture is
available at tests/data/sto-3g.json, and the sample calculation is at
samples/h2/sto-3g/calculation.toml:
rustiq basis import tests/data/sto-3g.json
rustiq run samples/h2/sto-3g/calculation.toml
The test suite exercises the fixture using an isolated store in
tests/cli_samples.rs
and basis import/storage behavior in
crates/rustiq-core/src/basis/basis_store.rs.
List, import, or remove locally stored bases with:
rustiq basis list
rustiq basis import /path/to/basis.json
rustiq basis remove sto-3g
The default store is in the platform’s application data directory. Set
RUSTIQ_DATA_BASIS to choose its exact path, or RUSTIQ_DATA_HOME to choose
the data root. The CLI guide in
existing workflows
lists platform paths and migration notes.
Online workflow
The default CLI build enables the online feature. Use it to list or download
bases:
rustiq basis list --online
rustiq basis download sto-3g
Online commands require network access. A normal run uses the local basis
store; automatic downloading can be enabled with --auto-download, disabled
with --no-auto-download, or set using RUSTIQ_AUTO_DOWNLOAD. Builds without
the online feature can import, list local files, and remove bases but cannot
download or query online listings. The commands reflect the CLI tests in
tests/cli_samples.rs.
Supported input features
Basis files are imported in the Basis Set Exchange JSON form. A shell groups
functions with the same center and angular momentum: \(l=0,1,2\) denote
s, p, and d functions. Cartesian and spherical describe two function forms
that differ in how angular dependence is represented. For elements used by a
molecule, the current loader accepts Gaussian-type and Cartesian Gaussian
shells through angular momentum \(l=15\), and spherical Gaussian shells
through \(l=2\). It rejects Slater-type shells and effective core
potentials (ECPs). Higher angular momentum or other basis-file features should
not be assumed to work just because a basis is downloadable. This describes
loader support, not numerical validation of all those cases. The checks are in
basis.rs.
During basis construction, RustiQ normalizes each Cartesian primitive using its three angular momentum components, then normalizes the contraction for its shell. Spherical functions are formed from normalized Cartesian components. The imported contraction coefficients therefore set the relative primitive weights; their overall scale does not set the resulting function norm. A coefficient group that cancels to the zero function, or whose computed norm is not finite and positive, is rejected with a shell and coefficient-group diagnostic. Contractions that cannot be normalized reliably and unrepresentable normalized primitive coefficients are also rejected. The contraction norm is checked again after normalization; an absolute deviation from unity of \(10^{-6}\) or greater causes rejection. These safeguards do not establish support for arbitrary extreme exponents throughout the integral engine.
Basis choice is one part of a calculation’s accuracy. Convergence, independent agreement, basis quality, and physical validity are distinct checks; see scientific scope. See the glossary for shared basis vocabulary.
Next: TOML configuration.
TOML calculation configuration
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create equivalent local inputs and obtain a basis.
A TOML input describes one calculation. TOML is the simplest choice: you do not
need to learn Nickel or install its executable. RustiQ embeds Nickel internally
to supply the same defaults and validation as optional Nickel studies.
For a standalone input, reuse calculation.toml generated by rustiq init
in the first-calculation guide,
keep its geometry and downloaded or imported STO-3G basis available, and run
rustiq run calculation.toml.
The checked-in neutral H₂ example below is for a source checkout:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf.guess]
type = "CoreHamiltonian"
From the repository root, import the basis if needed and run the input:
rustiq basis import tests/data/sto-3g.json
rustiq run samples/h2/sto-3g/calculation.toml
The [molecule] section points to an XYZ geometry and can set charge,
multiplicity, and coordinate units. [basis] names a locally available
basis. [method.hf] controls Hartree–Fock, and [method.mp2] requests a
correlation calculation after HF. See the HF and
MP2 guides for interpreting those methods.
For example, the existing MP2 sample adds an MP2 section:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf]
method = "Rhf"
[method.hf.guess]
type = "CoreHamiltonian"
[method.mp2]
frozen_orbitals = 0
Defaults such as neutral charge, Angstrom coordinates, automatic HF selection, 100 SCF iterations, and a \(10^{-8}\) convergence threshold are filled by the embedded Nickel contracts. The same contracts reject unknown fields and validate values; TOML parsing alone does not describe the full input rules. See calculation inputs and execution for how TOML and Nickel inputs pass through the shared contracts. See the authoritative Nickel input contracts.
Important HF numerical controls include convergence_threshold,
max_iterations, diis.enabled, diis.max_history, and
orthogonalization.linear_dependency_threshold. MP2 has frozen_orbitals
and memory_limit; the latter is a workspace budget, not a process memory
limit. The defaults and detailed validation rules belong to the Nickel source,
not a second specification in this guide.
Optional local AO ERI cache
The directory-backed AO ERI cache is local, disposable storage. It is disabled
by default; enable it in the runfile to allow reuse across runs. The checked-in
cache sample below is a complete calculation input; its geometry path is
relative to the sample file and points to samples/h2/molecule.xyz:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf.guess]
type = "CoreHamiltonian"
[cache]
enabled = true
With only the release binary, follow the first-calculation workflow to create
calculation.toml, then add this section to that file and rerun it:
[cache]
enabled = true
The short block is a fragment to append to the existing input, not a complete runfile. Then run the local input and inspect its cache entries with:
rustiq run calculation.toml --cache-dir ./rustiq-cache
rustiq cache list --cache-dir ./rustiq-cache
--cache-dir DIR selects the directory for this run but does not enable the
cache. The cache can be used as a fallback when a portable bundle has no
compatible AO ERI; it is not itself a portable .rustiq bundle. See the
portable bundle guide for that reuse order.
The geometry path is resolved relative to the TOML file. If the input is read from standard input, its geometry path is resolved from the current working directory. Geometry file structure and coordinate units are explained in the geometry guide.
The CLI reports diagnostics for malformed TOML, unknown or invalid fields,
unavailable bases, and invalid molecular states. Tests cover valid examples
and grouped diagnostics in
tests/cli_samples.rs
and tests/nickel_cli.rs.
Successful validation means the requested input is internally acceptable; it
does not validate the scientific choice of state or method.
See the glossary for shared configuration and scientific
terms.
Hartree–Fock calculations
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create local inputs and obtain a basis.
Hartree–Fock (HF) is RustiQ’s reference method for its calculations. It approximates each electron as moving in an average field from the others. The result is found iteratively by updating the electron density and solving the effective one-electron equations until the density and energy are consistent.
RHF (restricted HF) uses shared spatial orbitals for paired alpha- and beta-spin electrons. It is appropriate for a closed-shell state. UHF (unrestricted HF) allows alpha and beta electrons to use different spatial orbitals, which supports open-shell states. UHF is more flexible but its wavefunction need not have a pure total spin.
Select a method and starting guess
With method = "Auto", RustiQ selects RHF for an even electron count and
singlet multiplicity, and UHF otherwise. In Nickel/TOML values these methods
are spelled "Rhf" and "Uhf". Explicit RHF requires an even-electron
singlet; explicit UHF can also describe a singlet. This rule uses the requested charge
and multiplicity; it is not a ground-state search. The user remains responsible
for choosing the molecular state. Explicit Rhf or Uhf can also be requested
when compatible with the electron count.
This open-shell OH example uses neutral charge and doublet
multiplicity, so Auto resolves to UHF:
[basis]
name = "sto-3g"
[molecule]
geometry = "../oh.xyz"
charge = 0
multiplicity = 2
[method.hf]
method = "Auto"
convergence_threshold = 1e-5
[method.hf.guess]
type = "CoreHamiltonian"
[method.hf.diis]
enabled = true
max_history = 6
To run this same example with only the release binary, save the following
geometry as oh.xyz in your working directory. Create an inputs directory
with mkdir inputs if it does not already exist, and save the TOML above as inputs/oh.toml. Its
../oh.xyz path then resolves without editing the sample. Download STO-3G
and run (offline, instead import an independently obtained STO-3G JSON file
with rustiq basis import /path/to/sto-3g.json):
2
Hydroxyl radical
O 0.0 0.0 0.000
H 0.0 0.0 0.970
rustiq basis download sto-3g
rustiq run inputs/oh.toml
Tip
With an online-enabled build and network access,
rustiq run inputs/oh.toml --auto-downloaddownloads STO-3G if it is missing, then runs the calculation. You can use this instead of the separate download and run commands above.
For a source checkout, run it after importing STO-3G:
rustiq basis import tests/data/sto-3g.json
rustiq run samples/oh/sto-3g/calculation.toml
The converged total HF energy is approximately -74.362669 Hartree.
The open-shell CLI test and PySCF comparison are linked in
scientific scope.
The checked-in H₂ input uses a core-Hamiltonian guess and resolves to RHF:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf.guess]
type = "CoreHamiltonian"
An initial density guess starts the self-consistent iterations. Available choices include core-Hamiltonian, one-electron, random, and zero guesses; the default is core-Hamiltonian. A guess affects the starting path, not the definition of the converged equations. Different guesses can lead to different solutions in difficult cases.
Iterations and convergence
SCF means self-consistent field, the repeated process of building a Fock matrix (the effective one-electron operator) from the current density matrix, solving for orbitals, then rebuilding the density. The atomic-orbital (AO) basis consists of functions centered on atoms; molecular orbitals are combinations of these functions. DIIS (direct inversion in the iterative subspace) can extrapolate Fock matrices from previous iterations to accelerate convergence. It is disabled by default; it changes the numerical route, not the HF model. The DIIS method is associated with Pulay’s extrapolation approach (Pulay, 1982).
The default maximum is 100 iterations. The default convergence_threshold is
\(10^{-8}\). Both the absolute change in electronic energy between iterations
and the Frobenius norm of the AO commutator residual must fall below this
threshold. The energy change is in Hartree; the residual is \(FPS-SPF\). For
UHF, alpha and beta residual norms combine as
\(\sqrt{r_\alpha^2+r_\beta^2}\). This threshold is not a bound on final
energy error.
If SCF reaches its iteration limit, inspect the energy and residual history, then try enabling DIIS or a different initial guess. First confirm geometry units, charge, multiplicity, and basis. Treat numerical errors separately from iteration-limit outcomes, and do not interpret an unconverged result as a valid solution.
Enabling DIIS also enables an energy safeguard in RHF and UHF. Once the
density has the required electron populations, a step that raises the
electronic energy beyond a roundoff allowance clears the DIIS history and
triggers optimal damping. This includes ordinary SCF steps when DIIS has too
little usable history to extrapolate: diagonalizing the physical Fock matrix
minimizes a linearized energy, and can still raise the full HF energy.
For a rejected DIIS extrapolation, the candidate is first recomputed from the
physical Fock operator. An ordinary step already supplies that candidate.
The Zero guess is a startup sentinel without the required electrons, so its
first step is not damped; occupied orbitals establish the electron populations.
Optimal damping minimizes the HF energy along a density segment. For spin channel \(\sigma\), let \(P_\sigma^{(0)}\) be the density before the step and \(P_\sigma^{(1)}\) the density obtained by diagonalizing the physical Fock operator. The damped density is
\[ P_\sigma(t) = (1-t)P_\sigma^{(0)} + tP_\sigma^{(1)}, \qquad 0 \le t \le 1. \]
Because each Hartree-Fock Fock matrix is affine in the densities, the energy along this segment is quadratic:
\[ E(t) - E(0) = \mathrm{slope}\, t + \mathrm{curvature}\, t^2. \]
\[ \mathrm{slope} = \sum_\sigma \operatorname{Tr} [\Delta P_\sigma F_\sigma^{(0)}], \qquad \mathrm{curvature} = \frac{1}{2}\sum_\sigma \operatorname{Tr} [\Delta P_\sigma \Delta F_\sigma], \]
Here \(F_\sigma^{(k)}\) is the physical Fock operator built from the endpoint densities; each UHF Fock operator depends on both spin channels. Also, \(\Delta P_\sigma=P_\sigma^{(1)}-P_\sigma^{(0)}\) and \(\Delta F_\sigma=F_\sigma^{(1)}-F_\sigma^{(0)}\). For RHF, the sum has one spin-summed density and its Fock matrix; for UHF, it runs over \(\sigma\in\{\alpha,\beta\}\). The UHF terms use one shared \(t\), so \(\mathrm{curvature}\) includes the Coulomb coupling between the spin channels. The implementation chooses \(t\) that minimizes \(E(t)\) on this common segment, \([0,1]\), rather than varying the two spin fractions independently. Electron populations in the AO basis are \(N_\sigma=\operatorname{Tr}(P_\sigma S)\), or \(N=\operatorname{Tr}(PS)\) for the RHF spin-summed density. When both endpoint densities have the required electron populations, their mixture preserves those populations, though it need not represent a single determinant. Convergence and determinant spin diagnostics require the stored density to be represented by the current orbitals. An interior mixture generally does not represent the candidate determinant. If damping retains the previous endpoint (\(t=0\)), its density also need not match the newly computed orbitals; spin diagnostics are omitted in that case too. The undamped candidate (\(t=1\)) retains its orbital representation. These safeguards do not guarantee the global HF minimum or stability against spin symmetry breaking. For background on UHF damping, see Yamamoto and Mochizuki (2014).
The AO basis functions overlap. RustiQ diagonalizes their overlap matrix and discards directions whose eigenvalues are at or below the configured relative cutoff (default \(10^{-8}\) times the largest eigenvalue). The retained rank reports the effective dimension used by HF. Rank reduction can change results; inspect it when comparing calculations.
Read the result carefully
The electronic HF energy includes electronic kinetic, electron–nuclear, and electron–electron terms. Total HF energy adds nuclear repulsion. Energies are in Hartree; input Angstrom coordinates are converted to Bohr internally. Terminal energies are rounded for display. The H₂/STO-3G example is checked against a PySCF 2.15.0 reference in the project comparison suite with an absolute energy tolerance of \(2\times10^{-10}\) Hartree; the CLI test checks the rounded value. See reference comparison coverage and the output guide.
When determinant spin diagnostics are available, UHF output includes \(\langle S^2\rangle\) and its deviation from the requested spin state’s ideal value. A nonzero deviation is called spin contamination. For a requested spin \(S=(M-1)/2\), where \(M\) is multiplicity, the ideal expectation is \(S(S+1)\) in units of \(\hbar^2\). For a doublet this is 0.75. Contamination is a diagnostic, not a correction and not proof that UHF found the right state. A converged SCF solution can still be a poor physical model or a local solution. HF uses one Slater determinant and omits electron correlation beyond exchange; small bases and strongly correlated systems need particular care. Read the scientific limitations before interpreting results. See the glossary for shared terms.
The SCF criteria, overlap rank, and spin diagnostics are implemented in
scf.rs,
orthogonalization.rs,
and uhf.rs.
The checked-in H₂ and OH CLI/reference cases provide reproducible examples.
Next: MP2.
MP2 calculations
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create local inputs and obtain a basis.
Commands using rustiq assume the executable is installed or available on
PATH. From a source checkout without installation, use the
cargo run --locked -- prefix described in the
CLI reference.
Second-order Møller–Plesset perturbation theory (MP2) estimates an electron correlation correction using molecular orbitals from a converged HF reference. It does not replace HF: RustiQ first solves HF, then evaluates MP2. MP2 is available with both RHF and UHF references. An unconverged HF result cannot be used as an MP2 reference.
The checked-in H₂ input requests RHF-MP2 with no frozen orbitals:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf]
method = "Rhf"
[method.hf.guess]
type = "CoreHamiltonian"
[method.mp2]
frozen_orbitals = 0
With only the release binary, follow the first-calculation guide to create
h2.xyz. STO-3G must be available: run rustiq basis download sto-3g
with network access, or import an independently obtained local file with
rustiq basis import /path/to/sto-3g.json when offline. If you already ran
that first calculation, its imported or downloaded basis is still available.
Generate and run an MP2 input with:
rustiq init h2.xyz --mp2 -o h2-mp2.toml
rustiq run h2-mp2.toml
Tip
With an online-enabled build and network access, use
rustiq run h2-mp2.toml --auto-downloadto fetch STO-3G if it is missing instead of downloading it separately.
For a source checkout, run the checked-in sample from the repository root after importing STO-3G:
cargo run --locked -- basis import tests/data/sto-3g.json
cargo run --locked -- run samples/h2/sto-3g/mp2_calculation.toml
On successful completion, H₂ reports an MP2 correlation energy of approximately
-0.013138 Hartree, in addition to its converged HF energy and total MP2
energy. This is rounded output for the STO-3G case, not a general accuracy
claim; the reference tolerances are given below.
The MP2 correlation energy is the correction added to HF electronic energy. Total MP2 energy is HF electronic energy plus MP2 correlation energy plus nuclear repulsion. For the implemented canonical RHF/UHF references with occupied orbitals below virtual orbitals and finite denominators, the second-order correction is nonpositive. A positive value should prompt investigation of orbital ordering, the reference, or numerical inputs.
Open-shell UHF-MP2 example
OH is an open-shell doublet (multiplicity 2). For this input, Auto selects
UHF, and MP2 uses the converged UHF reference. The existing OH/STO-3G input is:
[basis]
name = "sto-3g"
[molecule]
geometry = "../oh.xyz"
charge = 0
multiplicity = 2
[method.hf]
method = "Auto"
convergence_threshold = 1e-10
[method.hf.guess]
type = "CoreHamiltonian"
[method.mp2]
frozen_orbitals = 0
[method.hf.diis]
enabled = true
max_history = 6
With only the release binary, save the following geometry as oh.xyz in
your working directory:
2
Hydroxyl radical
O 0.0 0.0 0.000
H 0.0 0.0 0.970
Create an inputs directory with mkdir inputs if it does not already exist.
Save the TOML above as inputs/oh-mp2.toml; its ../oh.xyz path resolves to
that geometry. Preserve the threshold and DIIS settings. STO-3G must be
available before running: download it as below, or, when offline, replace the
download command with rustiq basis import /path/to/sto-3g.json using an
independently obtained local file.
rustiq basis download sto-3g
rustiq run inputs/oh-mp2.toml
Tip
With an online-enabled build and network access,
rustiq run inputs/oh-mp2.toml --auto-downloadfetches STO-3G if it is missing, then runs the calculation. Use this instead of the separate download and run commands above.
Run it from the repository root after making STO-3G available, as described in the basis-set guide:
cargo run --locked -- run samples/oh/sto-3g/mp2_calculation.toml
The calculation reports a UHF-MP2 correlation energy. Existing PySCF comparisons cover this specific example within the tolerances documented below; they do not establish general chemical accuracy.
Frozen occupied orbitals
Occupied orbitals contain electrons in the HF reference; virtual orbitals are
unoccupied orbitals available as excitation destinations. The
frozen_orbitals setting excludes the lowest occupied orbitals from the MP2
correlation treatment. Its default is zero, so all occupied orbitals are
included. RHF requires at least one occupied orbital to remain correlated and
at least one virtual orbital; the frozen count must be smaller than the
occupied count. For UHF, the count
cannot exceed either spin’s occupied-orbital count, though one spin sector may
be fully frozen.
For RHF, the count refers to spatial orbitals; freezing one excludes one doubly occupied orbital. For UHF, the same count is applied separately to the alpha and beta occupied spaces. The excluded orbitals can have different spatial shapes. The setting does not choose chemically defined core orbitals automatically. Select it explicitly when comparing calculations.
Memory use
MP2 transforms integrals from the atomic-orbital basis into molecular-orbital
blocks. RustiQ processes these blocks to avoid storing the full transformed
four-index tensor at once. memory_limit configures the estimated additional
workspace used for these transformations. "auto" selects a budget based on
available memory; explicit byte sizes such as "500 MB" can also be set.
This workspace budget is not a limit on total process memory. It excludes
already resident HF data and atomic-orbital integrals, allocator overhead, and
other numerical-library scratch space. If one required block cannot fit within
the budget, the calculation returns an error; it does not exceed the budget to
allocate that block. See the source for
Mp2MemoryPlan
and the authoritative Nickel defaults in the
input contract.
For example, the existing Nickel default is auto. To set an explicit byte-size
budget, add this field inside [method.mp2] if that table already exists:
memory_limit = "500 MB"
If the table does not exist, create it with the field:
[method.mp2]
memory_limit = "500 MB"
These are configuration fragments, not complete runfiles. Do not add a second
[method.mp2] table or redefine an existing memory_limit key.
If the budget is below the minimum workspace needed for one occupied block, that sector cannot be transformed and the MP2 calculation errors. Automatic budget resolution follows the shared resource policy.
The H₂/STO-3G RHF-MP2 comparison checks the HF energy within \(2\times10^{-10}\)
Hartree and MP2 correlation energy within \(10^{-10}\) Hartree against PySCF
2.15.0. The OH/STO-3G UHF-MP2 case checks HF energy within \(5\times10^{-8}\),
correlation energy within \(5\times10^{-9}\) Hartree, and spin expectation
within \(2\times10^{-5}\). These are agreement tolerances for those inputs,
not a measure of general chemical accuracy. See the
reference coverage and the
reference test source.
Reproduce both selected cases from a cloned repository with Nix, or use the
documented uv/PySCF setup. These reference commands are optional and are not
included in the release binary:
nix run .#pyscf-check -- -k 'h2-sto-3g-rhf-mp2 or oh-sto-3g-uhf-mp2'
Small energy denominators can make MP2 corrections unreliable, especially in strongly correlated or near-degenerate systems. Numerical safeguards and agreement on a few examples do not establish physical validity. The method’s perturbative basis is described in Møller and Plesset (1934); see also this discussion of problematic MP2 denominators (Lee and Head-Gordon, 2018).
Nickel studies
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create local inputs and obtain a basis.
For a single calculation, TOML is sufficient. Nickel is an optional interface for parameterized studies that vary basis sets or numerical settings without duplicating input files. You do not need Nickel to run TOML calculations.
Nickel is a configuration language that RustiQ embeds. A .ncl file can
import other Nickel files and compute a list of related calculation records.
The checked-in single-calculation .ncl input is a small starting point:
{
molecule.geometry = "../molecule.xyz",
basis.name = "sto-3g",
method.hf = {},
}
For the release binary, copy the H₂ geometry from the study section below to
molecule.xyz in your working directory. Create an inputs directory with
mkdir inputs and save this input as inputs/calculation.ncl. Its
../molecule.xyz path resolves without editing. Download STO-3G with
rustiq basis download sto-3g, or import an independently obtained local
JSON file with rustiq basis import /path/to/sto-3g.json when offline. Then
run rustiq run inputs/calculation.ncl.
Tip
With an online-enabled build and network access,
rustiq run inputs/calculation.ncl --auto-downloadfetches STO-3G if it is missing before running the calculation.
For a source checkout, make sure STO-3G is in the local basis store, then run this checked-in input:
rustiq basis import tests/data/sto-3g.json
rustiq run samples/h2/sto-3g/calculation.ncl
The checked-in H₂ study maps over two basis names to produce two inputs:
let bases = ["sto-3g", "6-31g"] in
std.array.map
(fun basis_name => {
molecule.geometry = "molecule.xyz",
basis.name = basis_name,
method.hf.diis = { enabled = true, max_history = 2 },
})
bases
To run this study with only the release binary, save the H₂ geometry below as
molecule.xyz and save the study above as study.ncl in the same working
directory. The study’s molecule.geometry = "molecule.xyz" path is relative
to that file. Both STO-3G and 6-31G must be available. Download them as shown
below, or import independently obtained local files when offline with
rustiq basis import /path/to/sto-3g.json /path/to/6-31g.json.
2
Hydrogen molecule
H 0.0 0.0 -0.37
H 0.0 0.0 0.37
rustiq basis download sto-3g
rustiq basis download 6-31g
rustiq run study.ncl
Tip
With an online-enabled build and network access,
rustiq run study.ncl --auto-downloadfetches any missing bases required by the study instead of downloading them separately.
This study is sequential. For a source checkout, run it from the repository root after making both bases available:
rustiq basis import tests/data/sto-3g.json
rustiq basis import tests/data/reference/RustiQ/basis_sets/6-31g.json
rustiq run samples/h2/study.ncl
When both calculations succeed, selected output excerpts are:
Calculation 1/2
Calculation 2/2
2 succeeded, 0 non-converged, 0 failed
The example runs two calculations sequentially, using STO-3G and 6-31G. Both must succeed for this success summary to appear. These are selected lines, not the complete terminal output.
The Nickel file uses molecule.geometry, basis.name, and an HF DIIS setting
to create one calculation for each list item. Geometry paths resolve relative
to the top-level .ncl file; Nickel imports resolve relative to the file that
imports them. No external Nickel executable is needed.
TOML inputs describe one calculation. A .ncl file with one calculation
behaves as a single calculation; an array with multiple entries produces a
batch. This is useful for studies that vary inputs while keeping the remaining
settings shared. Nickel is validated using the same authoritative input
contracts as TOML; it does not define a second scientific configuration
schema. See calculation inputs and execution for the
shared input flow. The project integration test constructs a native import
fixture and checks resolution from a different working directory; see
tests/nickel_cli.rs.
See configuration and the
Nickel contract source.
RustiQ validates all study entries before it starts running them. Calculations
then run in source order. A calculation that has a recoverable runtime error
or does not converge is recorded for that entry, and later entries are still
attempted. Fatal infrastructure errors stop the batch.
The batch returns an unsuccessful process status if any entry fails or does
not converge, while retaining per-calculation results: 4 for partial success,
3 when every entry stops because HF did not converge, or 1 when no entry
succeeds and at least one has another error. Fatal infrastructure errors return
1 regardless of earlier successes. A configuration error prevents execution
of the batch and returns 1. See the CLI exit-code contract.
The integration coverage is in
tests/nickel_cli.rs
and tests/json_output_cli.rs.
For structured outcomes, see JSON output.
To save a study’s calculation entries and reusable AO ERIs in one portable
bundle, see portable calculation bundles.
See the glossary for Nickel and calculation terminology.
JSON output
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create local inputs and obtain a basis.
Use JSON when another program needs calculation results. run writes only
the machine-readable result to standard output. After following the release-
binary path in the first-calculation guide,
use the locally created input:
This writes a JSON file without terminal color:
rustiq run calculation.toml --format json --color never > result.json
For a source checkout, run commands from the repository root and make the named basis available first. To save machine-readable output, redirect standard output and disable color explicitly:
rustiq run samples/h2/sto-3g/calculation.toml --format json
rustiq run samples/h2/sto-3g/calculation.toml --format json --color never > result.json
For readable terminal inspection, add --pretty:
rustiq run samples/h2/sto-3g/calculation.toml --format json --pretty
--pretty requires --format json. Compact JSON is unstyled; when saving
pretty output for another tool, use --color never to disable syntax colors.
A TOML input produces one calculation result. A one-entry Nickel array also
uses the single-result schema. A multi-entry Nickel study produces a batch
document with one outcome per input, in source order. Each entry can be
success, non_converged, or error. Later calculations continue after a
recoverable per-calculation error, but fatal infrastructure errors stop the
batch. A valid JSON document can accompany a nonzero exit code. A single
HF-only calculation that does not converge still produces the single result
with converged: false; its energy and diagnostics describe the final iterate,
and the command returns 3. If MP2 was requested, non-converged HF prevents
MP2 execution and the run reports a diagnostic with code 3 instead of a
single-result JSON document. Other input, preparation, or runtime errors for a
single calculation return 1 without result JSON.
A completed batch returns 0 when all entries succeed, 4 when some succeed
and others do not, 3 when none succeed and all stop because HF did not converge,
and 1 when none succeed and any entry has another error. Fatal infrastructure
errors always return 1. See the CLI exit-code contract
and Nickel studies guide for details.
Results include schema_version, which lets consuming software select the
matching contract. The single-calculation contract is
calculation-output-v1.schema.json;
batch output uses
batch-output-v1.schema.json.
These versioned schemas are authoritative; this guide does not repeat their
field definitions. See also the reference index.
When run uses --reuse or --artifact, calculation results add an optional
artifacts field describing AO ERI selection and its origin. For example, a
bundle hit appears as:
{
"artifacts": [
{ "name": "ao_eri", "decision": "reused", "origin": "archive", "source_index": 0 }
]
}
decision describes whether the archive supplied a compatible AO ERI;
origin identifies the archive, enabled local cache, or fresh computation
that supplied the ERIs actually used. A bundle hit also includes its
zero-based source_index. The field is omitted when neither option is used,
and batch results report it on each calculation entry. See the
portable bundle guide for the full workflow and the
CLI reference for details.
Nickel batch JSON
The checked-in Nickel study runs two calculations. Follow that guide’s basis-set setup first, especially when running offline, then produce pretty JSON with colors disabled:
rustiq run samples/h2/study.ncl --format json --pretty --color never
For the release-binary path, save the local study as described in the Nickel
guide and use its filename instead, for example
rustiq run study.ncl --format json --pretty --color never.
The output follows the versioned batch schema. Each successful calculation
contains a result following the single-calculation schema linked above. Inspect
the status of every calculation; a batch can include non-converged or failed
entries even when it produces valid JSON. --color never prevents ANSI escape
sequences in redirected output.
Energies are in Hartree. JSON preserves full floating-point values for
comparison and downstream processing, while terminal tables round energies
for readability. Do not compare a rounded terminal value against a tight
numerical tolerance. Existing JSON CLI tests validate both schemas and
full-precision H₂ output in
tests/json_output_cli.rs.
The checked-in reference tests compare JSON values against PySCF 2.15.0 for
selected systems; see scientific scope.
For terminology used in result fields, see the glossary.
Portable calculation bundles
Examples in this chapter that use samples/ or tests/data/ require a cloned
repository and should be run from its root. Release binaries do not include
those files; the first-calculation guide
shows how to create local inputs and obtain a basis.
Commands using rustiq assume the executable is installed or available on
PATH. From a source checkout without installation, use the
cargo run --locked -- prefix described in the
CLI reference.
A .rustiq bundle is a portable snapshot of RustiQ calculation inputs and
optional reusable atomic-orbital electron-repulsion integrals (AO ERIs). It
lets users rerun saved calculations or reuse compatible AO ERIs in new ones
without carrying a machine-local cache. The bundle does not save a
Hartree–Fock wavefunction or skip a new SCF run.
Create and inspect a bundle
Release binary
First follow the local-input workflow in the
first-calculation guide. Use the
calculation.toml generated by rustiq init and its downloaded or imported
STO-3G basis; no additional basis setup is needed.
Choose a destination that does not already exist.
rustiq run calculation.toml --artifact h2.rustiq
rustiq artifact inspect h2.rustiq
rustiq artifact verify h2.rustiq
rustiq run h2.rustiq
Tip
With an online-enabled build and network access,
rustiq run calculation.toml --artifact h2.rustiq --auto-downloadfetches STO-3G if it is missing during bundle creation. Direct reruns of an existing bundle need no basis download.
Source checkout
Alternatively, from a cloned repository, make the checked-in STO-3G basis available, then run the H₂ sample and write a bundle to the current directory:
The runfile used here is the checked-in H₂ sample. Run these commands from the repository root:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf.guess]
type = "CoreHamiltonian"
cargo run --locked -- basis import tests/data/sto-3g.json
cargo run --locked -- run samples/h2/sto-3g/calculation.toml --artifact h2.rustiq
--artifact writes the current calculation collection as a new bundle,
independently of text or JSON result output. For a Nickel study, the bundle
contains one entry for each requested calculation.
Inspect a bundle without the original runfile, geometry file, or basis store:
rustiq artifact inspect h2.rustiq
rustiq artifact inspect h2.rustiq --format json
Inspection displays canonical requested and resolved calculation snapshots,
producer information, artifact representations, and captured source names and
sizes. Requested values may differ from resolved values: for example, an
Auto HF method can resolve to RHF, and requested Angstrom coordinates appear
as resolved Bohr coordinates. Text output syntax-highlights the canonical TOML
and XYZ when color is enabled by --color or RUSTIQ_COLOR; use
--color never for plain text. The optional JSON payloads_verified field is
false: inspection validates the archive index, provenance, scientific
snapshots and declared artifact sizes, but does not hash or decode numerical
payloads. Use artifact verify to check supported payloads eagerly; otherwise,
execution checks a payload when its scientific stage selects and reads it.
Inspection is structural, not a calculation or an independent scientific
validation.
Use artifact verify to eagerly read and validate every supported numerical
payload in the bundle:
rustiq artifact verify h2.rustiq
The command checks compact AO ERI payload hashes, NPY encoding, array dimensions, and consistency with the declared AO basis. It reports the number of verified payloads and calculations on standard output, and exits unsuccessfully if a payload is invalid or has an unsupported representation. A bundle with no numerical payloads can successfully report zero verified payloads. Verification does not execute the calculation or establish that the scientific method or result is valid. For the H₂ bundle created above, the output is:
Verified 1 payload(s) across 1 calculation(s).
Rerun a saved calculation
Run a .rustiq bundle directly to reconstruct and execute its archived
calculation settings, without the original runfile, geometry file, or basis
store:
rustiq run h2.rustiq
rustiq run h2.rustiq --format json --pretty --color never
For a multi-calculation bundle, RustiQ reruns every entry in manifest order and reports a batch, like a multi-entry Nickel study. This is a fresh calculation: RustiQ restores the resolved scientific inputs and reuses compatible AO ERIs when present; otherwise it recomputes them. A corrupt compatible AO ERI payload causes an execution error. It then runs HF again and MP2 again when requested. It does not restore orbitals, density matrices, DIIS history, or prior results, so this command does not resume an SCF trajectory. A saved random seed is restored as an input; it does not guarantee bitwise-identical results across software versions or platforms.
To use different settings, supply a TOML or Nickel input and use --reuse
instead. A direct archive rerun cannot be combined with --reuse, --artifact,
--cache-dir, --auto-download, or --no-auto-download.
With --format json, the rerun uses the normal single-calculation or batch
result schema and omits the artifacts reuse-decision array because the bundle
is the implicit artifact source. The source bundle remains unchanged; direct
reruns do not use the local AO ERI cache or download basis sets.
Reuse AO ERIs in a new calculation
This workflow needs a TOML or Nickel input, its geometry, and an available
basis. --reuse does not run the calculation saved in the bundle or restore its
captured source files. Instead, RustiQ prepares the supplied input, checks the
bundle for compatible AO ERIs, and runs HF again; it also runs MP2 again if the
new input requests MP2. The archive itself supplies reusable artifacts and
remains read-only.
For the release-binary workflow, use the local calculation.toml created in
the first-calculation guide. Keep its downloaded basis available for this new
run; its geometry path resolves beside calculation.toml:
rustiq run calculation.toml --reuse h2.rustiq --format json --pretty --color never
From a source checkout, the equivalent command uses the checked-in sample:
cargo run --locked -- run samples/h2/sto-3g/calculation.toml --reuse h2.rustiq --format json --pretty --color never
When a runfile is executed with --reuse or --artifact, its JSON result
includes an artifacts entry. A reused AO ERI is reported like this:
{
"artifacts": [
{
"name": "ao_eri",
"decision": "reused",
"origin": "archive",
"source_index": 0
}
]
}
decision says whether the bundle supplied a compatible artifact; the CLI
reports reused, missing, or incompatible. origin says where the ERIs
actually came from: archive, an enabled local cache, or fresh computation.
For example, decision: incompatible with origin: cache means no bundle entry
matched but an enabled local cache supplied the ERIs. When an archive entry is
selected, source_index is its zero-based position in that bundle. In a batch,
each result reports its own selection.
The reuse order is:
- First compatible AO ERI in the archive’s manifest order.
- Matching entry in the enabled local AO ERI cache.
- Recompute the AO ERIs.
The local-cache step is used only when [cache].enabled = true in the runfile.
--cache-dir selects the cache location but does not enable caching; see the
configuration guide for the
input setting.
The archive remains read-only during reuse. To publish a new snapshot from the calculation, provide a new destination. For the release-binary workflow:
rustiq run calculation.toml --reuse h2.rustiq --artifact h2-updated.rustiq
For a source checkout, use the sample path:
cargo run --locked -- run samples/h2/sto-3g/calculation.toml --reuse h2.rustiq --artifact h2-updated.rustiq
What can be reused?
AO ERIs are reusable when the effective integral inputs match. RustiQ checks the ordered atomic numbers and nuclear coordinates in Bohr, effective AO basis functions, Schwarz screening setting, and integral representation and computation versions. A matching basis-set label or atom count alone is not enough. HF method and convergence settings, and whether MP2 is requested, do not change AO ERI compatibility. The persistence specification defines the complete identity.
| Change to the new input | AO ERI compatibility |
|---|---|
| HF method, initial guess, or SCF convergence limit | Can remain compatible; HF runs again with the new settings. |
| Add or change MP2 settings | Can remain compatible; MP2 runs again from the new HF result. |
| Geometry, effective AO basis, or Schwarz screening | Incompatible; RustiQ checks the local cache, then recomputes if needed. |
The bundle stores scientific input snapshots and optional AO ERIs. It does not store HF energies, convergence status, orbitals, density matrices, DIIS history, or MP2 results. Save the result JSON separately when those outputs matter. Captured input and geometry bytes are provenance for inspection; they do not affect compatibility, and Nickel imports are not captured recursively. The same reconstruction is available to Rust callers; see the Rust API examples in the persistence specification.
Publication and failures
--artifact publishes the current requested collection; it does not append to
the source bundle. A new destination must not exist. An existing destination is
accepted only when it resolves to the explicit --reuse source, in which case
RustiQ replaces that bundle after producing a complete validated snapshot.
Other existing destinations are left untouched.
| Run outcome | Bundle behavior |
|---|---|
| Every requested calculation produces a result | Publish the current collection. |
| A preparation or execution error occurs | Do not publish; preserve any prior destination. |
| HF-only run reaches its iteration limit | Its result can still publish the AO ERIs. A single HF run returns exit code 3; a batch with non-converged results and no execution errors publishes, then returns 3 if none converged or 4 if some succeeded. See the CLI exit-code contract. |
| MP2 was requested but HF did not converge | MP2 execution fails, so the collection is not published. |
JSON for a completed calculation or batch may already have been written when a later publication error is reported. See the CLI reference for exact exit and publication behavior and the persistence V1 specification for the archive contract and the EZFIO comparison.
Scientific scope and limitations
RustiQ is experimental software for molecular electronic energies at a fixed geometry. The implemented model uses the nonrelativistic, clamped point-nucleus electronic Hamiltonian: nuclei do not move, and relativistic corrections are not included. A successful run or reference comparison does not establish research-grade correctness. Independently validate the method, basis, molecular state, convergence, and quantities relevant to your research against established packages before drawing chemical conclusions.
Implemented scope
Hartree–Fock (HF) is available as restricted HF (RHF) for closed shells and unrestricted HF (UHF) with separate alpha and beta orbitals for open shells. Automatic selection resolves the method from the molecular state. DIIS accelerates the iterative SCF solution; core-Hamiltonian and randomized density guesses are available. MP2 adds a correlation correction to converged RHF or UHF orbitals, with optional frozen occupied orbitals and a blocked transformation governed by a workspace budget.
Calculations use XYZ geometries with Angstrom or Bohr input, charge and spin
multiplicity, Gaussian basis functions, one-electron integrals, and compact
stored electron-repulsion integrals (ERIs). Schwarz screening can skip small
ERIs, and overlap orthogonalization removes near-dependent directions according
to a configured threshold. These thresholds can affect energies and convergence;
convergence alone does not establish their suitability for a particular system.
Increasing integrals.schwarz_threshold skips more small integrals at a
potential accuracy cost; setting it to zero disables Schwarz screening.
The authoritative default is in the Nickel schema.
Gaussian Cartesian and spherical functions are implemented, including spherical d functions. Spherical angular momentum above d and effective core potentials (ECPs) are rejected by the current basis loader. The relevant implementation is linked below for inspection.
Basis loader source on GitHub Downloading a basis file does not guarantee that its contents are supported or numerically validated. Geometry inspection and coordinate transformations are available; these operations do not optimize the geometry’s energy. See the glossary for terminology and the workflow notes for preserved usage guidance.
Reference comparisons
The book’s first H₂ calculation
provides a reproducible entry point to independent PySCF comparisons with
explicit tolerances. The comparison instructions and case definitions are
linked below. The release binary user can inspect these checked-in comparisons
and their tolerances, but reproducing them requires a source checkout plus the
Nix development shell or the documented uv/PySCF setup. They cover
H₂ and water in STO-3G, 6-31G, and cc-pVDZ, open-shell H₂⁺ and OH, and selected
RHF/UHF MP2 cases. The expanded independent energy matrix adds LiH/6-31G
RHF, CO/STO-3G RHF and RHF-MP2, H₂O/cc-pVDZ RHF-MP2 with spherical d
functions, and OH/6-31G UHF and UHF-MP2. Geometry provenance and reuse notes
are in Molecular and basis-set data sources.
The new cases independently interpret the checked-in raw BSE coefficients;
primary MP2 references correlate all occupied orbitals. New HF tolerances are
1e-11–2e-11 Hartree and MP2 correlation tolerances 1e-11–2e-11 Hartree,
with measured errors and per-case justifications in the reference instructions.
OH/6-31G uses an explicit seeded random guess to reach the lower-energy pi-hole
solution: a core-Hamiltonian guess can converge to a distinct sigma-hole state.
The comparisons check HF spin diagnostics as well as energy, without claiming
global HF stability. The report records available SCF iteration counts,
provenance hashes, and derived total MP2 energies. Additional cases exercise frozen occupied orbitals and
small versus larger MP2 workspace budgets. For OH/STO-3G, the UHF-only sample
uses a numerical SCF threshold of 1e-5 in both RustiQ and PySCF, while the
UHF-MP2 sample uses 1e-10 in both. Matching the numerical thresholds does
not make the two codes’ SCF stopping criteria identical: RustiQ checks an
energy change and an AO commutator residual, while PySCF uses its own
convergence tests. Compare converged energies and spin diagnostics rather than
assuming equivalent accuracy from a matching input number. The
first H₂ calculation identifies its
CLI test and full-precision independent comparison.
This is a useful, limited reference suite. Its tolerances are case-specific; the H₂/STO-3G tolerance is not a universal accuracy guarantee. It does not systematically span elements, contraction conventions, angular momenta, charges, spin states, difficult SCF solutions, or large systems. Agreement in selected energies can leave errors in untested quantities or shared assumptions undetected. It also does not prove basis completeness, adequacy of HF/MP2 for a chemical problem, or agreement with experiment. UHF spin contamination is an additional physical concern even for converged solutions.
Physical limits of HF and MP2
HF represents the state with a single Slater determinant and omits electron correlation beyond exchange. Convergence establishes a self-consistent solution within the selected orbital space; it does not establish that the solution is the lowest-energy HF state. Different initial guesses can find different solutions. UHF can lower its energy by breaking spin symmetry, so inspect \(\langle S^2\rangle\) and spin contamination as well as the energy.
Bond stretching, dissociation, and near-degenerate states can require several important electronic configurations. A converged single-determinant reference can then be physically inadequate. MP2 is a perturbative correction to that reference, not a general remedy for strong correlation. Its energy terms contain denominators \(\epsilon_i + \epsilon_j - \epsilon_a - \epsilon_b\), with occupied indices \(i,j\) and virtual indices \(a,b\). Small denominators can produce excessively large corrections. Lee and Head-Gordon discuss these denominator problems and bond-breaking examples in their study of regularized MP2.
RustiQ rejects non-finite denominators and absolute denominator values at or
below 1e-12 Hartree. This numerical guard is not a physical suitability test:
passing it does not establish that the perturbation expansion is reliable.
Agreement with another HF/MP2 implementation tests numerical consistency under
matched conventions; judging a chemical prediction also requires an appropriate
method, basis, and molecular state.
Major limitations
The current calculation methods do not provide DFT, analytic gradients, geometry optimization, vibrational frequencies, or post-HF methods beyond MP2. The molecular input workflow uses XYZ rather than a broad set of chemistry formats. General research use needs broader independent numerical validation, scientific convention documentation, and performance evidence.
Memory management and screening already exist, but compact ERI storage can still grow rapidly with basis size. The MP2 workspace budget is not a bound on total process memory. Larger checked-in molecules are examples, not evidence of robust or competitive performance at scale.
The authoritative references page links to the roadmap and issues, which own future plans. Detailed method derivations and broader validation methodology belong to later scientific documentation; this page describes current boundaries.
Reference comparison instructions on GitHub
Reference case definitions on GitHub
Glossary
This short glossary connects the scientific and software vocabulary used in this manual. It is an orientation aid; method definitions and API contracts remain in their authoritative references.
| Term | Meaning in this manual |
|---|---|
| AO / MO | Atomic orbital / molecular orbital. Basis functions centered on atoms represent the molecular orbitals used by HF and MP2. |
| Basis set | A finite collection of functions used to represent electronic orbitals. STO-3G is a small basis suitable for the first example, not a general accuracy guarantee. |
| Bohr / Angstrom | Length units. Bohr is the atomic unit of length; Angstrom is commonly used for molecular coordinates. RustiQ converts input coordinates to Bohr for calculations. |
| Hartree | The atomic unit of energy used in RustiQ’s reported energies. |
| HF / RHF / UHF | Hartree–Fock / restricted HF / unrestricted HF. RHF pairs electrons in shared spatial orbitals; UHF permits different spatial orbitals for alpha and beta spins. |
| SCF | Self-consistent field: the iterative procedure for solving the HF equations. Meeting its convergence criterion does not prove chemical accuracy. |
| DIIS | Direct inversion in the iterative subspace: an acceleration technique for SCF iterations. |
| MP2 | Second-order Møller–Plesset perturbation theory: a correlation correction built from an HF reference. |
| Multiplicity | 2S + 1 for spin quantum number S. Singlet and doublet mean multiplicities one and two. Charge and multiplicity specify the intended molecular state. |
| Spin contamination | Deviation of UHF’s spin expectation value from the value for the intended pure spin state. |
| ERI | Electron-repulsion integral: a contribution describing the Coulomb interaction between electrons in the chosen basis. |
| AO ERI | Atomic-orbital electron-repulsion integral. RustiQ’s optional local cache stores these deterministic integrals, not HF or MP2 results. |
| Orthogonalization | Construction of an orthonormal orbital space from overlapping basis functions. Near-dependent directions may be removed. |
| Frozen orbitals | Occupied orbitals excluded from the MP2 correlation calculation. |
| ECP | Effective core potential: a model replacing core electrons and their nuclear interaction; currently unsupported by RustiQ’s basis loader. |
| Rust / Cargo | Rust is the implementation language; Cargo builds Rust packages and runs their tests and examples. Users can run an installed CLI without writing Rust. |
| Crate / workspace | A Rust package’s library or executable unit / a group of packages built together. RustiQ separates its CLI and scientific library. |
| CLI / API | Command-line interface for terminal users / application programming interface for code using the library. |
| rustdoc / mdBook | Rust’s API documentation generator / the tool that builds this user and developer manual. |
| TOML / Nickel | Calculation input languages. TOML provides declarative settings; Nickel also supports imports and computed studies and owns input defaults and validation. |
| JSON / schema | A structured data format / the contract describing valid data. Existing versioned schemas define RustiQ’s machine-readable results. |
| Nix / flake | A tool for reproducible packages and environments / this repository’s project definition, with dependencies locked by flake.lock. Nix does not require NixOS. |
| Dev Container | A prepared Linux development environment running through Docker, with editor integration. |
| Cache / portable artifact | Disposable local data used to avoid repeated work / an intentional scientific snapshot. .rustiq bundles can be written, reused, and inspected through the CLI or Rust APIs. |
| Validation / tolerance | Comparison against independent evidence / the allowed difference in a particular numerical check. Passing selected checks does not validate every calculation. |
| Contracted Gaussian | A basis function formed by a weighted sum of primitive Gaussian functions that share a center and angular momentum. |
| Primitive Gaussian | A Gaussian function used as a component of a contracted basis function. |
| Occupied / virtual orbital | An orbital assigned electrons in the reference determinant / an unoccupied orbital available as an excitation destination. |
| Fock matrix | The effective one-electron matrix built from the current electron density in Hartree–Fock. |
| Density matrix | A matrix encoding which molecular orbitals are occupied and their contributions in the atomic-orbital basis. |
| Overlap matrix | The matrix of pairwise integrals between basis functions; its off-diagonal values reflect that these functions need not be orthogonal. |
| Cartesian / spherical Gaussian | Two ways to represent the angular part of Gaussian basis functions. Their function counts differ for d and higher angular momentum. |
| Correlation energy | The energy correction beyond the chosen HF reference; RustiQ reports MP2 correlation separately from the HF and total energies. |
| Linear dependence | Near-redundancy among basis functions, which can make the overlap matrix numerically singular. RustiQ may discard the affected directions. |
Command-line reference
Run these commands from any working directory with the installed rustiq
binary. In a source checkout without an installed executable, replace the
rustiq command prefix with cargo run --locked --.
rustiq --help and rustiq <command> --help show the
options supported by the installed build.
Manual
rustiq docs opens the offline HTML manual bundled with a release archive or
Nix package. Cargo-only installations open the online manual. Use --web to
force the online version, or --print-path to print the local index path or
online URL without launching a browser. See
installation for
relocation, headless use, browser selection, and incomplete-installation errors.
PDF export is not implemented.
Binary version and build details
rustiq --version (or rustiq -V) prints the package version on one line.
Use rustiq --version --verbose (or rustiq -V -v) for grouped build details;
the two flags can also appear in reverse order. These requests return exit code
zero and write plain text to standard output. The top-level --verbose flag
requires --version; basis list --verbose retains its existing meaning.
The detailed output groups source, compiler, CPU target, and build
configuration metadata.
It includes the full Git commit and status, compilation
target, Rust compiler and LLVM versions, Cargo optimization level, exact
profile when supplied by the build, declared debug-information, LTO,
codegen-unit, debug-assertion, and integer overflow-check settings, target
architecture and explicitly requested target CPU
when available, enabled target features, and enabled Cargo features. The
architecture is displayed whenever Cargo provides it, independently of
whether a target CPU was explicitly requested. No named ISA classification
is inferred from the features.
Cargo’s synthetic default feature marker is omitted. Values that Cargo or
the build system cannot establish are generally omitted from text output.
The integer overflow-check row explicitly shows unknown when unavailable;
without a declared value, debug assertions are read from the CLI’s compiled
cfg(debug_assertions). Cargo’s
PROFILE variable does not identify custom profiles reliably, so the profile
is shown only when the build supplies its exact name. Release artifacts built
by cargo-dist declare dist in their workflow; Nix package builds declare
release.
Configuration declared in the selected package profile in Cargo.toml is
labeled as declared. Profile inheritance is followed. Cargo does not expose
effective LTO, codegen-unit, overflow-check, debug-assertion, or
debug-information settings to build scripts. Declared values are reported when
the selected profile declares them; debug assertions otherwise use the
compiled cfg value and integer overflow checks show unknown. Cargo’s optimization value is supplied to
build scripts; a separate compiler flag can override it. Target CPU is
populated only from an explicit RustiQ build override or a recognized
target-cpu option in Cargo’s encoded rustflags or RUSTFLAGS. The target
feature list comes from Cargo’s target cfg for the final target; it does not
describe runtime CPU support. Observed rustflags are not a complete record of
compiler arguments or Cargo configuration.
LTO and codegen units are labeled as declared because Cargo does not expose their effective compiler values to build scripts. Target features describe compile-time target settings, not instructions supported by the machine at runtime. The architecture and globally enabled features come from Cargo’s final compilation target, including during cross-compilation. The display does not hard-code CPU families, instruction sets, ISA levels, or reference feature lists. This allows the same code to report targets supported by different compiler toolchains without assuming their naming conventions. Rust’s target cfg does not establish the minimum compatible processor for the entire linked executable, particularly if native dependencies or specialized kernels use additional instructions. RustiQ does not guess the concrete build-host CPU.
For example, the grouped output has this shape (unknown optional fields are omitted and the values depend on the build):
rustiq 0.1.0-beta.1
SOURCE
Git commit <full commit hash>
Status dirty
COMPILER
Rust <compiler version>
Channel <stable, beta, nightly, or dev>
Rust commit <full hash, only for nightly when available>
LLVM <LLVM version>
Target <target triple>
CPU TARGET
Architecture <target architecture, when available>
Target CPU <explicit CPU request, when available>
Target features <features enabled for the compilation target, when available>
BUILD CONFIGURATION
Profile <exact profile, if supplied>
Optimization <Cargo value>
Debug information <profile value, if declared>
LTO <profile value (declared)>
Codegen units <profile value (declared)>
Debug assertions <profile value (declared), or compiled cfg value>
Integer overflow checks <profile value (declared), or unknown>
Cargo features <enabled features, excluding the default marker>
NUMERICAL LIBRARIES
Linear algebra nalgebra <version>
Parallelism rayon <version>
Special functions special <version>
CHEMICAL DATA
Periodic table mendeleev <version>
Bohr radius CODATA 2018
The numerical libraries section identifies nalgebra for linear algebra,
Rayon for parallelism, and special for special functions used by the Boys
function implementation. Their versions are read at build time from Cargo.lock
when it contains a single distinct version of each crate; otherwise the
corresponding version is shown as version unknown. When terminal hyperlinks
are enabled, each backend name and version links to that exact version on
crates.io. Unknown versions have no link. The parallelism row does not report
the active thread count.
The chemical data section identifies the mendeleev crate used for
chemical element properties; its resolved version is read from Cargo.lock
during the build, using the same fallback and crates.io hyperlink behavior
as the numerical libraries. The Bohr-to-ångström conversion factor in the
core uses the CODATA 2018 Bohr radius from NIST. Its revision and NIST
reference URL are defined alongside the conversion constant in
rustiq-core, not duplicated in the CLI. With terminal hyperlinks enabled,
the revision links to the NIST CODATA 2018 table.
This does not claim that all chemical constants, atomic masses, or basis
sets use CODATA 2018. Basis sets and their own revisions are specific to
individual calculations and are not reported in this binary-version output.
Integer overflow checks concern integer arithmetic, not floating-point NaN, infinity, or SCF convergence.
Text calculation banners show a 12-character commit abbreviation and its
source state. When Git provenance is unknown, they show Build: unknown.
OSC 8 links, when enabled, target the complete commit hash. JSON calculation
output remains free of banners and retains its existing schema.
All fields are embedded during compilation and remain available when the
executable is copied elsewhere, without Git or Rust installed. The source
state is clean or dirty according to changes to tracked files at build
time; untracked files do not affect this Git dirty flag. The Status row
displays clean, dirty, or unknown; a missing commit is displayed as
unknown, as can happen when compiling an unpacked source archive without Git
metadata. When stdout is a terminal that supports hyperlinks, the Git commit
hash links to that commit in the RustiQ repository.
The target feature list links to the Rust Reference’s explanation and tables
of processor features.
Redirected output stays plain text unless FORCE_HYPERLINK explicitly enables
links.
These fields describe build provenance, not a cryptographic identity of the
executable or proof that two builds are identical. The compiler commit is shown
only for nightly toolchains, when available; stable, beta, and dev builds still
show their compiler channel.
Packagers may set RUSTIQ_BUILD_GIT_COMMIT to a full Git hash (or unknown)
and RUSTIQ_BUILD_GIT_STATE to clean, dirty, or unknown at compilation
time to override Git discovery. An injected commit without an injected state
uses state unknown. RUSTIQ_BUILD_PROFILE, RUSTIQ_BUILD_SYSTEM, and
RUSTIQ_BUILD_TARGET_CPU can supply exact build-system metadata when known;
the profile, system name, and CPU values are validated before embedding. Nix
supplies its profile, build-system name, and flake revision, while the
cargo-dist release workflow supplies its profile and build-system name. The
Nix source revision is the Git revision passed by the flake, not a Nix store
path. Setting these variables when running an already built binary has no
effect.
Commands
Manual pages and shell completions
Cargo builds enable the independent manpages and completions features by
default. They provide these commands:
rustiq manpages ./manpages
rustiq completions > current-shell-completion
rustiq completions bash > rustiq.bash
rustiq completions zsh > _rustiq
rustiq completions fish > rustiq.fish
rustiq completions elvish > rustiq.elv
rustiq completions powershell > rustiq.ps1
rustiq completions nushell > rustiq.nu
manpages creates its destination directory and replaces existing generated
pages. When switching between standalone and packaging modes in the same
directory, obsolete rustiq-manpages.1 and rustiq-completions.1 pages are
removed. Use a fresh directory for a completely clean generated set if other
commands have changed between RustiQ versions. It writes rustiq.1 and pages
for the subcommands, including nested
commands such as rustiq-artifact-inspect.1. Each page includes the
online manual in its SEE ALSO section.
completions writes only the script to standard output; generation errors go
to standard error and return a failing exit status. Its shell argument is
optional: RustiQ recognizes the calling process’s shell first, then falls back
to the SHELL environment variable. This includes nu for Nushell and pwsh
or powershell for PowerShell. If neither identifies a supported shell, the
command asks you to provide one explicitly. Supply the argument when running
through a launcher that obscures the calling shell.
Both generators reflect the commands and options enabled in the current
build. For example, offline builds omit online-only basis commands. By
default, generated files also include manpages and completions when those
features are enabled. Set
RUSTIQ_PACKAGING=true (or 1) to omit manpages and completions from
both manuals and shell completion scripts; false, 0, or an unset variable
keeps them. Other packagers can use this setting when installing generated
files alongside a binary built without the generator features. Values other
than true, false, 1, and 0 produce an error.
Load the generated file in the matching shell: source ./rustiq.bash in Bash,
source ./rustiq.fish in Fish, or source ./rustiq.elv in Elvish. For Zsh,
place _rustiq in a directory on $fpath before running autoload -Uz compinit; compinit. In PowerShell, dot-source the script with . ./rustiq.ps1; it
registers native argument completion without adding a command wrapper or
Get-Help integration. In Nushell, load it with use ./rustiq.nu *.
Add the appropriate loading command to your shell configuration to retain it
in future sessions.
To select features explicitly from a checkout, use, for example:
cargo run --locked --no-default-features --features manpages -- manpages ./manpages
cargo run --locked --no-default-features --features completions -- completions nushell
These examples omit online; add it to the feature list if needed. A build
without a generator’s feature omits that command and its dependency. The
Nix package
installs the generated assets but disables both generators in its executable.
Application commands
| Command | Purpose |
|---|---|
rustiq init <XYZ> | Create a TOML calculation input that refers to an XYZ geometry. |
rustiq run [INPUT] | Run TOML or Nickel input, or rerun calculations from a .rustiq bundle. With no path, read TOML from standard input. Multi-entry inputs run as batches. |
rustiq basis import <PATH>... | Import basis JSON files into the local basis store. |
rustiq basis list [--online] [--verbose] | List locally stored bases; online listing is available in builds with the online feature. |
rustiq basis download <NAME> | Download a basis in builds with the online feature. |
rustiq basis remove <NAME>... / --all | Remove selected bases or the local basis store contents. |
rustiq cache list [--cache-dir DIR] | Inspect AO ERI cache entries and their validation status. |
rustiq cache remove <NAME-OR-FINGERPRINT> [--cache-dir DIR] / --all | Remove selected or all AO ERI cache entries. |
rustiq artifact inspect <PATH> [--format FORMAT] | Inspect portable .rustiq calculation snapshots and artifact metadata. |
rustiq artifact verify <PATH> | Check hashes and decode supported numerical payloads in a portable .rustiq bundle. |
rustiq geometry info [XYZ] | Print basic geometry information; read XYZ from standard input when no path is given. |
rustiq geometry rotate, translate, center, oriente, isometry | Transform a geometry and write the result; each subcommand has its own help. |
The geometry tools and basis storage are utilities around a calculation; they
do not create a .rustiq portable artifact. See the
geometry guide and existing workflows
for examples of geometry, init, and basis management commands.
init options include --output (calculation.toml by default), --force,
--basis (sto-3g), --charge (zero), --multiplicity, --units
(angstrom by default, or bohr), --hf (auto, rhf, or uhf), and
--mp2. Without an explicit multiplicity, it selects singlet for an even
electron count and doublet for an odd count. This is a starting convention;
choose the physical state appropriate to the molecule. The existing
workflows documents path and overwrite behavior.
run options and input selection
The input filename extension selects TOML, Nickel (.ncl), or a portable
.rustiq bundle. TOML describes a single calculation. Nickel can describe one
calculation or an ordered array; an array of one uses the single-calculation
output contract, while a larger array uses the batch contract. A .rustiq
input reconstructs and reruns its archived resolved calculation(s); multi-entry
bundles use the batch contract. Nickel imports resolve relative to the importing
file. Geometry paths resolve relative to the top-level input file; for TOML
read from standard input, they resolve from the current working directory.
Direct archive reruns cannot be combined with --reuse, --artifact,
--cache-dir, --auto-download, or --no-auto-download; the source bundle is
read-only and provides its resolved basis and inputs. Archive reruns do not use
the local ERI cache or basis-download settings. Text output shows SCF progress;
JSON output suppresses progress and writes only the result document.
Important options:
| Option | Behavior |
|---|---|
--format FORMAT (text or json) | Select text output (default) or versioned JSON. JSON result data is written to standard output. |
--pretty | Pretty-print single-calculation or batch JSON, optionally with syntax highlighting. Requires --format json. |
--color MODE (auto, always, or never) | Control ANSI colors globally; also accepts RUSTIQ_COLOR. Use --color never when redirecting pretty JSON. |
--auto-download / --no-auto-download | In online builds, allow or disable fetching a missing basis for this run. These override RUSTIQ_AUTO_DOWNLOAD; without either flag, 1 or true (case-insensitive) enables it and other or missing values disable it. Offline builds always use local bases. |
--cache-dir DIR | Choose the AO ERI cache root for this run. The input must also set [cache].enabled = true; this option does not enable caching. |
--reuse PATH | Read a portable .rustiq bundle and reuse the first compatible AO ERI for each calculation. |
--artifact PATH | Write the current calculation or batch as a portable .rustiq bundle, independently of text or JSON output. |
Output presentation is selected exclusively by the CLI --format text|json option.
The TOML and Nickel calculation contracts do not accept an output section.
Scientific execution emits a completion event after all requested stages complete.
An HF-only result can be unconverged and still be a completed execution.
The CLI consumes it to retain a lightweight summary, then selects text or JSON
presentation after execution. JSON retains its single versioned result document
(including the existing batch envelope), without streaming intermediate events.
The campaign runner returns ordered outcomes directly; recoverable failures remain
in that result and fatal orchestration failures stop the campaign before rendering.
The cache directory path is resolved from the caller’s current working
directory. Pass the same --cache-dir to cache list or cache remove to
manage entries from a run that used a custom cache root.
The CLI reports input, basis, preparation, and calculation errors as diagnostics. Exit codes follow the Unix convention: zero means complete success; any nonzero code means the command did not fully succeed. Codes 3 and 4 are RustiQ-specific.
| Code | Meaning |
|---|---|
0 | All requested calculations succeeded. Help and version requests also return zero. |
1 | General error, a batch with no successful calculations and at least one error unrelated to HF non-convergence, or a fatal infrastructure error. |
2 | Invalid command-line arguments. |
3 | No requested calculation succeeded, and every unsuccessful calculation stopped because HF did not converge. |
4 | A completed batch contains both successful and unsuccessful calculations, including non-convergence or recoverable errors. |
These codes apply to TOML, Nickel, and .rustiq inputs, with text or JSON output.
A calculation succeeds only when the complete requested method succeeds: converged
HF followed by an MP2 error is not a successful calculation. MP2 blocked by HF
non-convergence counts as non-convergence, so a single such run returns 3.
Input validation before execution returns 1; CLI argument validation returns 2.
Fatal infrastructure errors during execution or output writing return 1 and can
prevent result JSON from being produced. Artifact publication happens after
successful scientific execution. If publication then fails, the CLI still writes
the completed calculation or campaign JSON before returning 1; this behavior is
covered by publication_error_keeps_complete_calculation_and_batch_json.
A single HF-only calculation that reaches its iteration limit still returns its
final-iteration result, with converged: false in JSON, but exits with 3.
MP2 requires converged HF; a single MP2 run blocked by non-convergence reports a
diagnostic without result JSON. Recoverable per-entry errors in a batch do not
prevent later entries from running. The batch JSON records each outcome, and a
valid JSON document can accompany a nonzero exit code. Output fields remain
defined by the versioned schemas.
Convergence alone does not establish the physical validity of a result.
From the repository root, capture the status even when the calculation fails
(the conditional also works in shells using set -e):
status=0
cargo run -- run samples/h2/sto-3g/calculation.toml --format json > result.json || status=$?
printf 'Exit code: %s\n' "$status"
When using the installed binary, replace cargo run -- with rustiq. In scripts,
inspect the exit code and, when available, individual JSON outcomes; see the
JSON guide.
Feature availability
| Capability | Available behavior |
|---|---|
| TOML | One calculation per input; see the checked-in H₂ input. |
| Nickel | One calculation or an ordered study/batch; see the checked-in study example. |
| JSON | Versioned single-calculation and batch results, selected with run --format json; schemas are linked below. |
| AO ERI cache | Optional local reuse through [cache].enabled and --cache-dir; entries can be listed or removed. AO ERI means atomic-orbital electron-repulsion integral. |
Portable .rustiq bundle | Create with run --artifact, rerun with run FILE.rustiq, reuse artifacts with run INPUT --reuse FILE.rustiq, inspect with artifact inspect, and validate stored AO ERIs with artifact verify. Reruns start a fresh HF calculation. See the portable bundle guide. |
| Scientific status | Experimental; selected checks do not establish research-grade correctness. See scientific scope and limitations. |
Basis downloads and online basis listing require a build with the online
feature. The standard CLI enables it; offline builds provide import, local
listing, and removal. Geometry transformations are CLI utilities, not
calculation input transformations unless their output file is then used as an
input.
These examples use files shipped in the repository and must be run from its
root after checkout. The release archive contains neither fixtures nor sample
inputs. With only the binary, use rustiq basis import /path/to/basis.json
for a separately obtained basis file, or rustiq basis download sto-3g in an
online build; provide your own input file to rustiq run.
From the repository root, import the checked-in STO-3G and 6-31G basis fixtures before running these examples:
rustiq basis import tests/data/sto-3g.json tests/data/reference/RustiQ/basis_sets/6-31g.json
rustiq run samples/h2/sto-3g/calculation.toml
rustiq run samples/h2/study.ncl --format json --pretty --color never
rustiq run samples/h2/sto-3g/calculation-cache.toml --cache-dir ./rustiq-cache
rustiq cache list --cache-dir ./rustiq-cache
The Nickel study uses both STO-3G and 6-31G; importing only STO-3G is
insufficient unless basis auto-download is enabled in an online build.
The TOML and cache examples require only STO-3G. See the
Nickel studies guide for the individual
import commands. The relative ./rustiq-cache directory is resolved from
the caller’s working directory on Windows, Linux, and macOS.
The H₂ TOML and Nickel examples are exercised by
tests/cli_samples.rs,
tests/nickel_cli.rs,
and tests/json_output_cli.rs.
The JSON tests also check pretty-printing of Nickel batches. The
cache-enabled input is samples/h2/sto-3g/calculation-cache.toml; its
store-then-hit behavior is covered by
test_cli_h2_sample_uses_eri_cache_when_enabled_in_runfile in
tests/cli_samples.rs,
in addition to the Rust core persistence tests.
Calculation input contracts
TOML and Nickel inputs use the same calculation settings. The embedded Nickel contracts are authoritative for defaults, allowed fields, types, and validation; the CLI does not define a separate TOML-only set of defaults. Consult the TOML guide for sections and checked-in examples, then the geometry, Hartree–Fock, and MP2 guides for the corresponding scientific settings. The Nickel contracts and their validation are linked from the reference index.
The following settings are accepted by both TOML and Nickel. This is a navigation aid, not a second schema: exact defaults, value constraints, and cross-field validation remain defined by the linked Nickel contract.
| Section | Supported settings |
|---|---|
[molecule] | geometry, charge, multiplicity, units (Angstrom or Bohr) |
[basis] | name |
[method.hf] | method (Auto, Rhf, Uhf), max_iterations, convergence_threshold, guess, diis.enabled, diis.max_history, orthogonalization.linear_dependency_threshold |
[method.mp2] | frozen_orbitals, memory_limit |
[integrals] | schwarz_threshold for integral screening |
[cache] | enabled for the disposable local AO ERI cache |
The accepted density guesses and their fields are defined in the Nickel contract; see the HF guide for their use. The cache stores AO ERI data only; it does not store Hartree–Fock or MP2 results, and a cache hit does not guarantee that every calculation will run faster.
Cache and portable bundles
The local AO ERI cache (atomic-orbital electron-repulsion integrals) is a
disposable optimization for deterministic two-electron integrals. It is
disabled by default in the calculation input;
--cache-dir only selects where enabled cache entries are stored. Use
cache list and cache remove to inspect or remove entries. Missing, invalid,
or incompatible entries are recomputed. The local cache is not a deliverable
or a portable calculation file.
Portable .rustiq bundles use the V1 ZIP/ZIP64 format described by the
authoritative persistence specification.
The format is conceptually inspired by EZFIO
in Quantum Package 2 (qp2), but uses
an independent archive structure and APIs; see the
comparison.
For a guided create, inspect, and reuse workflow, see the
portable bundle guide.
Bundles are separate from the disposable local AO ERI cache. Reuse opens its source
read-only. For each requested calculation, RustiQ selects the first compatible,
supported AO ERI in bundle order; when none is available, an enabled local cache
is checked before recomputation. A corrupt selected payload is an error. A
source entry can supply data to multiple calculations in a Nickel batch.
rustiq run samples/h2/sto-3g/calculation.toml --artifact h2.rustiq
rustiq run samples/h2/sto-3g/calculation.toml --reuse h2.rustiq --artifact next.rustiq --format json
rustiq artifact inspect h2.rustiq --format json
rustiq artifact verify h2.rustiq
rustiq run h2.rustiq
# Replace the source bundle after all requested calculations produce results:
rustiq run samples/h2/sto-3g/calculation.toml --reuse h2.rustiq --artifact h2.rustiq
Publication captures the current requested calculation collection and its
compatible known artifacts. It does not append history. An existing destination
is accepted only when it resolves to the explicit --reuse source; otherwise
the command fails without replacing it. Publication happens after every requested
calculation produces a result. Preparation or execution errors prevent
publication of the collection and leave the destination unchanged. An HF-only
non-converged result can contribute its AO ERI. A Nickel batch containing only
non-converged HF-only results can publish its bundle even though the command
exits unsuccessfully. If MP2 was requested but HF does not converge, execution
fails and the bundle is not published. HF orbitals, SCF restart state, DIIS
history, and MP2 results are not persisted.
When --reuse or --artifact is used, JSON calculation results include an
optional artifacts array. decision reports archive selection (reused,
missing, or incompatible); origin reports the ERI actually used
(archive, cache, or computation). A reused item includes its zero-based
source_index. Without these options the existing JSON result shape is retained.
run FILE.rustiq --format json uses the regular single-calculation or batch
result schema but does not include this reuse-decision array: the bundle is the
implicit artifact source for that mode.
Publication failures are reported on stderr and return a failing exit status.
Since publication follows scientific execution, JSON for the completed calculation
or campaign is written before that publication error is returned.
artifact inspect PATH displays requested and resolved scientific snapshots,
producer details, artifact representations, and captured source names and sizes.
In text mode, canonical TOML and XYZ are syntax-highlighted when color is
enabled by --color or RUSTIQ_COLOR; JSON output remains structured JSON.
It validates the archive index, provenance, snapshots, and declared artifact
sizes, but does not hash or decode numeric payloads. Use artifact verify to
check supported payloads eagerly; otherwise, execution checks a payload when
its scientific stage selects and reads it. Inspection does not execute
calculations or establish scientific validity. JSON output follows the
artifact inspection V1 schema.
artifact verify PATH eagerly reads and validates supported numerical
payloads. It currently checks compact AO ERI payload hashes, NPY encoding,
array dimensions, and consistency with the declared AO basis. It reports an
error for an invalid payload or unsupported representation. Verification does
not run a calculation or establish scientific validity.
The archive captures exact bytes of the main input and geometry files as shared
provenance; it does not capture Nickel’s full import graph. See the
persistence specification
for the archive contract and API details.
Output contracts
run --format json selects one of two versioned contracts: the single
calculation schema or the batch schema. schema_version identifies the
contract; schemas, rather than this manual, define the complete field sets.
The JSON guide describes output selection,
standard output behavior, failure cases, and the existing automated checks.
Existing calculation workflows
For a concise catalog of shipped commands, input settings, JSON behavior, and feature availability, see the command-line reference. This page keeps the longer workflow examples.
This page preserves operational details from the former README. For the
progressive workflows, start with the geometry,
basis set,
configuration,
Nickel,
MP2, and
JSON guides. Commands below use checked-in
sample files and run from the repository root after cloning. The Cargo package
is rustiq-chem, and the installed executable is rustiq. Users with only
the release binary can run equivalent commands with their own geometry, input,
and basis JSON files; see the first calculation
and basis-set guide.
Commands below use an installed rustiq; when working from the checkout
without installing it, prepend cargo run --locked -- to the command
arguments, for example cargo run --locked -- run samples/h2/sto-3g/calculation.toml.
See the glossary for scientific and development terms.
Create input from an XYZ geometry
rustiq init samples/h2/molecule.xyz -o calculation.toml
rustiq init samples/h2/molecule.xyz --hf uhf --multiplicity 3 --mp2 -o triplet.toml
init references the geometry; it does not copy it. The output defaults to
calculation.toml in the current directory. Its parent directory must exist.
Use --force to replace an existing regular file; the source geometry,
directories, and symbolic links are protected from replacement.
Defaults are STO-3G, neutral charge, Angstrom coordinates, and automatic HF
selection. Without --multiplicity, the electron count (including charge)
selects a singlet for an even count and a doublet for an odd count. This is a
starting convention, not a prediction of the ground state. Specify the
physical state yourself. --hf accepts auto, rhf, or uhf; --units
accepts angstrom or bohr. Incompatible molecular states are rejected.
--basis and --charge select another basis and charge. --mp2 adds MP2 with
no frozen orbitals. Default-valued settings are omitted from generated TOML
and restored by the authoritative Nickel configuration.
Initialization needs neither a cached basis nor network access. Running the calculation checks basis availability and numerical requirements. tests/init_cli.rs checks that generated HF and MP2 inputs run; unit tests in init_command.rs check options, paths, defaults, and overwrite protection.
Geometry paths resolve from the top-level calculation file’s directory,
including geometry values supplied by Nickel imports. Nickel imports themselves
resolve from the importing file. With no input filename, run reads TOML from
standard input and resolves geometry from the caller’s current directory.
CLI paths such as --cache-dir also resolve from the caller’s directory.
Basis management and storage
A basis set supplies the functions used to represent electronic orbitals. Import the checked-in fixture for the first calculation, or manage the local store with:
rustiq basis list
rustiq basis import tests/data/sto-3g.json
rustiq basis list --online
rustiq basis download sto-3g
basis import reads a local file and works offline. Online listing and
basis download require the online Cargo feature, enabled by default for the
CLI, and network access. Offline builds retain local listing and removal.
run --auto-download permits downloading a missing basis;
--no-auto-download disables it. These flags override RUSTIQ_AUTO_DOWNLOAD,
which enables downloading for 1 or true (case-insensitive); otherwise it is
disabled. Import and store behavior are tested in
basis_store.rs.
The CLI uses the platform’s local application data directory, then appends
basis_sets:
| Platform | Default basis directory |
|---|---|
| Linux | ~/.local/share/rustiq/basis_sets |
| Windows | %LOCALAPPDATA%\rustiq\data\basis_sets |
| macOS | ~/Library/Application Support/rustiq/basis_sets |
An absolute XDG_DATA_HOME replaces ~/.local/share on Linux.
RUSTIQ_DATA_BASIS overrides the entire basis directory and takes precedence
over RUSTIQ_DATA_HOME, which selects <root>/rustiq/basis_sets.
Prefer absolute paths for these overrides. If the platform directory cannot be
determined, the fallback is <system temporary directory>/rustiq/basis_sets;
the operating system may remove its contents.
Older alpha installations used ~/.local/share/RustiQ/basis_sets on Linux,
%LOCALAPPDATA%\RustiQ\basis_sets on Windows, and
~/Library/Application Support/RustiQ/basis_sets on macOS. There is no
automatic migration or lookup there. Copy existing bases to the current
location or set RUSTIQ_DATA_BASIS to the old directory. The policy and
override tests live in
directories.rs.
The basis store is separate from the disposable integral cache and portable
scientific bundles described under authoritative references.
JSON results and Nickel studies
rustiq run samples/h2/sto-3g/calculation.toml --format json
rustiq run samples/h2/sto-3g/calculation.ncl
rustiq run samples/h2/study.ncl --format json
The study runs STO-3G and 6-31G calculations sequentially. Import both fixtures
from tests/data/reference/RustiQ/basis_sets/, or permit automatic download.
The input extension selects TOML or Nickel; no external Nickel executable is
needed. TOML and init describe single calculations.
JSON is suitable for automated analysis because energies retain floating-point
precision rather than terminal display rounding. Use the existing
single and batch schemas as the field contracts; check
schema_version. UHF results include spin expectation and contamination
relative to the requested spin state; RHF results omit that spin object.
Unconverged results describe the final iteration, not a converged wavefunction.
One calculation, including an array of length one, produces the single-result
contract. Larger arrays produce the batch contract in source order, with
success, non_converged, or error outcomes. Configuration is validated
before execution. Recoverable runtime failures allow later entries to run; fatal
execution or output errors can stop the campaign before a complete document is
rendered. Completed campaign JSON records ordered per-entry outcomes, and a
nonzero exit code can accompany that document. Artifact publication occurs after
successful execution, so a publication failure preserves the completed JSON but
still makes the command fail. Empty arrays are rejected.
Compact JSON has no ANSI styling even with forced color. --pretty requires
--format json and can add syntax highlighting when colors are enabled;
use --color never when saving pretty JSON for another program.
JSON tests
and Nickel tests
verify these contracts and study execution.
MP2 and its memory budget
MP2 estimates a correlation correction using converged HF orbitals; RustiQ supports both RHF and UHF references. It refuses MP2 on unconverged HF. The existing H₂ input is:
[basis]
name = "sto-3g"
[molecule]
geometry = "../molecule.xyz"
[method.hf]
method = "Rhf"
[method.hf.guess]
type = "CoreHamiltonian"
[method.mp2]
frozen_orbitals = 0
After importing STO-3G, run:
rustiq run samples/h2/sto-3g/mp2_calculation.toml
frozen_orbitals excludes the lowest occupied orbitals from correlation;
zero correlates all occupied orbitals. For RHF, it counts spatial orbitals:
frozen_orbitals = 1 freezes one doubly occupied orbital (two electrons).
For UHF, the same count applies separately to the alpha and beta occupied
spaces: 1 freezes the lowest occupied alpha orbital and the lowest occupied
beta orbital, also excluding two electrons. These spin orbitals can have
different spatial shapes. This configuration setting does not specify separate spin counts
or arbitrary orbital indices.
RHF requires the count to be smaller than the occupied-orbital count. UHF requires it not to exceed either spin’s occupied count; a spin channel may have no active occupied orbitals left. Choose the frozen space explicitly when comparing packages. Defaults and input validation belong to Nickel; the core also checks the reference-specific orbital partition during MP2. The PySCF comparisons include RHF/UHF MP2, frozen orbitals, and different workspace budgets.
memory_limit = "auto" resolves once before MP2 to half the available memory.
On Linux, the process’s cgroup free-memory limit caps the host value when
available. If memory information is unavailable, the fallback is 512 MiB.
Explicit sizes such as "500 MB" (decimal units) and "1.5 GiB" (binary units)
are accepted. The budget covers additional matrix payloads for the blocked
transformation from atomic to molecular orbitals, including panels and
coefficient copies. The transformation stages the left virtual coefficient
transpose once per spin sector and borrows contiguous right occupied and virtual
coefficient columns across occupied blocks. Each AO panel is expanded using its
first-pair symmetry, and the transformed panel is reused for the swapped
second AO pair. Panels are still expanded again for each occupied block. The
workspace estimate remains a conservative bound on these temporary payloads.
HF data and compact atomic-orbital integrals are separate.
It does not cap total process memory, allocator overhead, or matrix-kernel
scratch storage. A budget too small for one occupied block fails before the
transformation buffers are allocated. The text report shows block size and
workspace estimates. See the tested
resource policy
and blocked implementation.
Terminal colors
--color and RUSTIQ_COLOR accept auto, always, and never, in order of
precedence: CLI flag, environment setting, automatic detection. In automatic
mode, NO_COLOR disables styling; otherwise terminal detection is independent
for standard output (reports) and standard error (diagnostics and progress).
Explicit always or never overrides NO_COLOR.
rustiq --color never run samples/h2/sto-3g/calculation.toml
Windows output uses adaptive terminal support, including legacy consoles. The implementation and focused checks are in color.rs and the JSON integration tests. See the JSON section above for pretty output.
Authoritative references
These documents remain the sources of truth:
-
Molecular and basis-set data sources: provenance and reuse notes for molecular geometries and locally stored basis datasets.
-
Command-line reference: shipped commands, principal options, output behavior, and availability boundaries.
-
TOML calculation configuration and Nickel studies: runnable inputs linked to the authoritative Nickel defaults and validation below.
-
Persistence V1 specification: the portable ZIP/ZIP64
.rustiqcontract. -
Embedded Nickel schema: input defaults and validation.
-
Rustdoc: public Rust API reference.
-
CONTRIBUTING.md: contribution requirements.
-
CITATION.cff: project citation metadata.
-
ROADMAP.md and issues: future work.
The directory-backed local AO ERI cache is disposable, machine-local storage.
A portable .rustiq bundle is a deliberate scientific snapshot accessed by
the CLI and Rust APIs. A cache directory is not a portable bundle.
Molecular and basis-set data sources
The repository-root DATA_SOURCES.md is the authoritative record. Its contents
are included below so the source notes are available in the published manual
as well.
Molecular and basis-set data sources
This file records the provenance of molecular geometries and basis-set data currently checked into RustiQ. Coordinates in the XYZ files are in ångströms. For geometries without an external citation, no external provenance is recorded in the repository; do not cite them as experimental or independently optimized reference data.
Molecular geometries
| Molecule | Repository files | Provenance and reuse notes |
|---|---|---|
| Hydrogen, H₂ | samples/h2/molecule.xyz; crates/rustiq-core/tests/data/samples/h2/molecule.xyz | Project sample/test geometry, with atoms 0.74 Å apart. No external geometry source is recorded. The core fixture duplicates the sample. |
| Water, H₂O | samples/h2o/h2o.xyz; crates/rustiq-core/tests/data/samples/h2o/h2o.xyz | Project sample/test geometry. No external geometry source is recorded. The core fixture duplicates the sample. |
| Hydroxyl radical, OH | samples/oh/oh.xyz; crates/rustiq-core/tests/data/samples/oh/oh.xyz | Project sample/test geometry, with an O–H distance of 0.970 Å. No external geometry source is recorded. The core fixture duplicates the sample. |
| Lithium hydride, LiH | samples/lih/lih.xyz | Project-authored, fixed test geometry: Li at the origin and H at z = 1.60 Å. Chosen as a rounded equilibrium-like distance, consistent with the 1.5957 Å spectroscopic distance discussed in Gottlieb and Weishäupl, Comput. Theor. Chem. 1007, 82–89 (2013), author manuscript. It is not an experimental coordinate file or an optimization result. Neutral singlet; reused by the 6-31G RHF reference. |
| Carbon monoxide, CO | samples/co/co.xyz | Project-authored, fixed test geometry: C at the origin and O at z = 1.13 Å. A deliberately rounded equilibrium-like test distance; not an experimental coordinate file or an optimization result. Neutral singlet; the STO-3G RHF and RHF-MP2 references use this identical file. |
| Ethanol | samples/ethanol/ethanol.xyz | The file describes this as an approximate gas-phase geometry. No external source or calculation provenance is recorded; treat it as an illustrative project geometry, not as a sourced equilibrium structure. |
| Benzene | samples/benzene/benzene.xyz | 3D conformer identified by the file as PubChem CID 241 and retrieved through PubChem PUG REST. PubChem record; PUG REST documentation. PubChem’s policy states that PubChem-generated information and participant-provided information are made available without cost and restriction, while warning that some contributed information may be copyrighted. The record labels this as a PubChem 3D conformer. |
| Cholesterol | samples/cholesterol/cholesterol.xyz | 3D conformer identified by the file as PubChem CID 5997. PubChem record. PubChem’s policy states that PubChem-generated information and participant-provided information are made available without cost and restriction, while warning that some contributed information may be copyrighted. The record labels this as a PubChem 3D conformer. |
| Anthracene | samples/anthracene/anthracene.xyz | PubChem 3D conformer for CID 8418, obtained as an SDF record through the PubChem PUG REST 3D SDF endpoint; PubChem compound record. The XYZ stores the 24 atom coordinates from that conformer in ångströms. PubChem policy says PubChem-generated and participant-provided information is made available without cost and restriction, but warns that some contributed information may be copyrighted; verify provenance-specific notices when present. |
PubChem’s data submission policy also places responsibility on users to respect restrictions that apply to third-party contributed content. The PubChem attribution here describes the geometry provenance recorded by the files; it is not a blanket clearance for every item associated with a PubChem record.
Geometry reuse review for the HF/MP2 extension
Reviewed on 2026-10-21. The new XYZ files are constructed by the project; no third-party coordinate file, database table, spectrum, image, or article text is redistributed. LiH uses a rounded test distance with literature attribution; CO uses a project-selected rounded test distance. Existing water and OH geometries are reused byte-for-byte, with their original unsourced status preserved above. A new reference calculation does not establish external provenance for an old geometry.
The U.S. Copyright Office distinguishes facts from protected expression. This is not a blanket license for database compilations or a determination of rights in every jurisdiction. In particular, the NIST SRD policy reserves compilation copyright under the Standard Reference Data Act, and the NIST Chemistry WebBook is SRD 69. Its government origin must not be treated as automatic public-domain status. The WebBook was consulted to check physical plausibility; its coordinate exports and tables are not imported. The test geometries above intentionally use project-selected rounded distances instead of copied database records. No NIST license is claimed or granted by this repository.
Locally stored basis sets
These are the basis-set datasets present in the repository’s versioned reference store. No other basis-set dataset is listed here. The reference store README identifies them as unmodified files downloaded from the Basis Set Exchange (BSE) using RustiQ. Their embedded revision metadata is reproduced below.
| Basis set | Local source file | Embedded BSE revision metadata | Foundational reference |
|---|---|---|---|
| STO-3G | tests/data/reference/RustiQ/basis_sets/sto-3g.json | Data from Gaussian09, revision date 2018-06-19, version 1 | Hehre, Stewart, and Pople, “Self-consistent molecular-orbital methods. I. Use of Gaussian expansions of Slater-type atomic orbitals,” J. Chem. Phys. 51, 2657 (1969), DOI 10.1063/1.1672392. |
| 6-31G | tests/data/reference/RustiQ/basis_sets/6-31g.json | Data from Gaussian 09/GAMESS, revision date 2018-06-19, version 1 | Hehre, Ditchfield, and Pople, “Self-Consistent Molecular Orbital Methods. XII. Further Extensions of Gaussian-Type Basis Sets for Use in Molecular Orbital Studies of Organic Molecules,” J. Chem. Phys. 56, 2257 (1972), DOI 10.1063/1.1677527. |
| cc-pVDZ | tests/data/reference/RustiQ/basis_sets/cc-pvdz.json | Data from ccRepo/Grant Hill, revision date 2018-10-03, version 1 | Dunning, “Gaussian basis sets for use in correlated molecular calculations. I. The atoms boron through neon and hydrogen,” J. Chem. Phys. 90, 1007 (1989), DOI 10.1063/1.456153. |
The BSE recommends citing its database papers when publishing work that uses the exchange: Pritchard et al., “A New Basis Set Exchange: An Open, Up-to-date Resource for the Molecular Sciences Community” (2019), and, for the earlier database, Schuchardt et al., “Basis Set Exchange: A Community Database for Computational Sciences” (2007). The BSE documentation identifies the software code as BSD-3-Clause; that statement alone does not establish a license for all contributed basis data. The local JSON records do not state a separate data license. Retain their attribution and review the applicable source terms before republishing these datasets beyond the repository.
The HF/MP2 extension reuses the existing 6-31G lithium (elements["3"])
and STO-3G carbon (elements["6"]) records. No BSE data was added,
modified, or downloaded for this extension. The reference environment copies
the existing versioned files into an isolated store. PySCF independently
normalizes their raw coefficients for the new cases. The upstream
BSE software license
was checked on 2026-10-21; its BSD redistribution conditions concern software
and do not resolve separate contributed-data rights. The attribution and
existing data-license limitation above continue to apply.
The repository also contains byte-identical copies of STO-3G at
tests/data/sto-3g.json and crates/rustiq-core/tests/data/sto-3g.json. Their
SHA-256 is db3478afbe34866ed9ee8720e1bf8513d4de16dea22e568e7c1e838fd1231e40.
They are project fixtures, distinct from the BSE snapshot above (SHA-256
6e9edeb7ae5ee1c4155dbc84b8bad9b74f07077f8136c7531f86d7f0d358b638); they
have no separate provenance metadata and are not described as a BSE download.
The project uses NIST’s Computational Chemistry Comparison and Benchmark Database (CCCBDB, SRD 101) as a possible reference resource only when its terms permit. It is not the provenance of any geometry listed above, and no CCCBDB geometry is bundled here. NIST identifies CCCBDB as SRD 101; consult the NIST license and terms before any reuse.
Development environments
Choose an environment according to the operating system on which you want RustiQ to run, the tools you want prepared, and your compute site’s policies. Docker is an optional development convenience; it is not a universal recommendation for scientific calculations.
| Setup | Where Rust and RustiQ run | Advantages | Limitations |
|---|---|---|---|
| Docker / Dev Container | Linux inside a container on every host | Prepared workspace and VS Code integration | Linux target only; Desktop uses a VM; resource and file-sharing settings need attention |
| Nix | Native Linux or Apple Silicon macOS; Linux in WSL2 on Windows | Pinned tools without requiring Docker | Limited flake platforms; store and installation requirements; WSL2 uses a VM |
| Manual / Cargo | Native Linux, macOS, or Windows | Direct host execution and control over installed tools | Native dependencies and optional scientific tools must be installed separately |
For native execution on Windows or Intel macOS, choose manual installation. On Linux or Apple Silicon macOS, Nix prepares tools while retaining native execution. Choose Docker when a shared Linux development workspace is useful and its host integration suits your needs.
For HPC workloads, consider the compute node’s operating system, available memory and CPUs, filesystem, and scheduler policies. A native setup avoids adding a VM on Windows or macOS; Docker Engine directly on Linux shares the host kernel. These distinctions do not establish a performance ranking: measure representative calculations with release builds on the intended execution environment. The Docker page explains resource limits and platform boundaries in more detail.
Each setup page contains its prerequisites, commands, advantages, and limits. See known supported platforms for compatibility evidence and Nix packages and shells for the pinned tool inventory.
Terms used in the setup guides
A host is the machine running your environment. A container isolates processes and their installed tools while using a Linux kernel. A virtual machine (VM) runs a guest operating system with its own kernel. WSL2 runs Linux in a VM on Windows. A terminal lets you type commands; a shell interprets them. A Nix development shell makes selected tools available in that session. Cargo builds Rust programs, and rustup installs Rust toolchains.
Docker and VS Code Dev Container
Visual Studio Code (usually called VS Code) is a free application for editing and managing software projects. You can think of it as a text editor with a project file browser, a built-in terminal, and optional extensions that add features such as Rust error highlighting, debugging, or Nickel support. For this project, it gives you one place to edit files, run commands, and see errors.
A Dev Container is a prepared Linux environment for the project. VS Code shows the files and editor on your computer, while Rust, Nix, and the other development tools run inside the container. This avoids installing and configuring those tools individually on your computer. The repository includes the container configuration, so contributors can use the same setup.
Choose this setup when you want a prepared Linux workspace with VS Code integration. Compare it with native Nix and manual installation before choosing a calculation environment.
Advantages and limitations for scientific computing
- Advantages: the repository supplies a consistent Linux workspace, pinned tools through Nix, and editor integration. Development dependencies stay in the container; the host needs Docker, Git, and VS Code.
- Platform: Rust, Cargo, and RustiQ run under Linux regardless of the host operating system. The resulting executable targets the container’s Linux architecture; it is not a native Windows or macOS executable.
- Virtualization: Docker Engine directly on Linux shares the host kernel and does not require a virtual machine. Docker Desktop runs Linux containers in a Linux VM, including on Linux hosts. On Windows, its Linux backend uses WSL2 or Hyper-V. See the official Docker Desktop VM documentation.
- Resources and files: the VM’s CPU and memory allocation can restrict a calculation independently of the physical machine’s capacity. Host file sharing can also affect I/O. Review Desktop resource settings and any container resource limits before large calculations. Images and the persistent Nix store consume disk space, and initial setup needs downloads.
- HPC use: this is a development workspace. Cluster policy may prohibit Docker or require another runtime; the supplied Dev Container does not configure a batch scheduler. Check the site’s supported environment before choosing it for compute nodes.
There is no measured universal performance penalty documented for this setup. For performance comparisons, use release builds and record the actual CPU, available memory, architecture, filesystem, and any VM or container limits. Matching the container architecture to the processor avoids introducing cross-architecture emulation into the comparison.
Prepare your computer
- Install Visual Studio Code.
- Install and start Docker Desktop, or Docker Engine on Linux. Follow its instructions for your operating system. On Windows, its WSL2 backend requires WSL2; the official setup guide explains that requirement. Docker must be configured to run Linux containers.
- In VS Code, open the Extensions view from the left sidebar, search for Dev Containers, and install the extension published by Microsoft.
- Install Git to download the project.
Open RustiQ in its prepared environment
Open a terminal on your computer and download the project:
git clone --branch develop --single-branch https://github.com/mveril/RustiQ.git
cd RustiQ
In VS Code, choose File > Open Folder and select the downloaded RustiQ
folder. Open View > Command Palette, search for
Dev Containers: Reopen in Container, and select it. The command palette
lets you find VS Code actions by name. The
first creation can take several minutes while Docker builds the image and Nix
downloads the toolchain pinned by flake.lock. Subsequent starts reuse the
Docker image and Nix store.
The container is based on Debian Bookworm and installs only Nix and direnv at
the system level. The FlakeEnv extension loads devShells.default directly and
propagates its environment to terminals, tasks, debuggers, and language
servers. Rust, Nix, TOML, Nickel, dependency, Python, Jupyter, and LLDB support
is installed as a small explicit extension list rather than through extension
packs with overlapping behavior.
The Rust toolchain, rust-analyzer, nixd, nixfmt, Nickel, its language server, Ruff, scientific Python stack, and development utilities are provided by the Nix shell. The Dev Container also installs these VS Code extensions:
- FlakeEnv loads the flake environment into editor processes.
- rust-analyzer provides Rust language support; CodeLLDB provides debugging.
- Nix IDE and Nickel provide Nix and Nickel language support.
- Even Better TOML supports TOML, while Prettier formats JSON, YAML, and Markdown.
- Dependi helps inspect dependencies; Python, Jupyter, and Ruff support the Python reference tools.
- NPY Viewer provides tables, heatmaps, and statistics for
.npyfiles, including the integral fixtures incrates/rustiq-core/tests/data/integrals/. Python is optional. Use the reference tools for numerical verification.
The first activation can take several minutes; later starts reuse the persistent Nix store.
Because .envrc execution requires explicit trust, run direnv allow once in
the container if FlakeEnv reports that it is blocked, then run FlakeEnv:
Reload Environment.
When the workspace is ready, choose Terminal > New Terminal in VS Code. Commands in this terminal run inside the prepared Linux environment. Verify that the tools are available:
cargo --version
rustc --version
rust-analyzer --version
cargo test
After changing .devcontainer/devcontainer.json, rebuild the container. After
changing flake.nix or flake.lock, run FlakeEnv: Reload Environment; a
container rebuild is only needed when the Dev Container configuration changes.
Dev Container Troubleshooting On Windows
- If Docker reports that
dockerDesktopLinuxEnginecannot be found, start Docker Desktop and wait untildocker infosucceeds before reopening the repository. - If container creation fails while mounting a path such as
\\wsl.localhost\<distribution>\mnt\wslg\runtime-dir\wayland-0, disable Dev Containers: Mount Wayland Socket in the VS Code user settings. The equivalent JSON setting is"dev.containers.mountWaylandSocket": false. This only disables Linux GUI forwarding; it does not affect Docker, Rust, Nix, or terminal access. - Nix inside the container is installed by the Dev Container feature. It is independent of any Nix or NixOS installation in WSL.
- If a flake change is not visible in the editor, run FlakeEnv: Reload Environment and restart the affected language server if necessary.
Nix setup
Nix supplies the project’s pinned toolchain without requiring Docker or VS Code. A development shell makes tools available to processes on the current operating system; it is not a virtual machine. See Nix packages and shells for the individual tools provided by the flake.
Advantages and limitations
- Advantages:
flake.lockpins the environment dependencies. Linux and Apple Silicon macOS users compile and run RustiQ natively with prepared Rust and optional PySCF tools. Any editor or terminal can be used. - Platforms: this flake supports Linux x86_64 and AArch64 and Apple Silicon macOS. It does not declare native Windows or Intel macOS support.
- Windows: WSL2 adds a Linux VM and produces Linux executables. Nix inside WSL2 does not remove that virtualization layer.
- Maintenance: Nix installation, flakes, and the store introduce concepts
to learn. Initial downloads or local dependency builds can take time; the
store requires disk space.
direnvis optional. - HPC use: native Nix avoids a container runtime on supported hosts, but
installation and access to
/nix/storedepend on cluster policy. Build on a suitable build node and follow the site’s scheduler and resource rules. Copying a Nix executable alone does not carry its store dependencies to another machine.
If Nix is new to you, start with the official introduction to Nix and learning resources. Nix is a package manager and development-environment tool; NixOS is a complete Linux distribution built around it. You do not need to replace your operating system with NixOS to use this repository’s flake.
Useful references include the official Nix flakes guide,
nix develop reference,
NixOS-WSL documentation,
direnv installation guide, and
nix-direnv. For tools used outside
the flake, see Rustup and the uv documentation.
The flake supports the following platforms:
- Linux on x86_64 and AArch64;
- macOS on Apple Silicon.
The pinned nixpkgs revision no longer supports Intel macOS (x86_64-darwin).
Use the native Cargo workflow on that platform.
On Windows, use the Linux flake through WSL2, with either NixOS-WSL or another Linux distribution with Nix installed. This builds and runs Linux executables. For a native Windows executable, use manual installation.
Getting Nix
Choose the case that matches your machine:
-
On NixOS, including NixOS-WSL: Nix is already installed as part of the operating system. NixOS-WSL installation instructions are available for users who want to run NixOS directly under WSL2. Make sure the modern Nix command and flakes are enabled in your NixOS configuration:
nix.settings.experimental-features = [ "nix-command" "flakes" ];Apply the configuration with
sudo nixos-rebuild switch, then continue withnix developor the direnv workflow below. -
On another Linux distribution, macOS, or a non-NixOS WSL2 distribution: install Nix separately as an additional package manager. It works alongside tools such as
apt,dnf,pacman, or Homebrew and does not replace them. Follow the official Nix download and installation instructions for your platform, restart the shell if requested, and verify the installation withnix --version. The official page recommends a multi-user installation when the platform supports it. To enable the commands used here, add the following line to your user configuration file,~/.config/nix/nix.conf(create the directory and file if needed):experimental-features = nix-command flakesMerge these features with any existing
experimental-featuressetting.
In either case, Nix reads flake.nix and flake.lock from this repository to
create the same project-specific toolchain without installing those development
tools globally. The first invocation may take some time because Nix must
download the pinned dependencies; later invocations reuse its local store.
Nix Without direnv
Install Nix with flakes enabled, clone the repository, and enter the development shell manually:
git clone --branch develop --single-branch https://github.com/mveril/RustiQ.git
cd RustiQ
nix develop
The default full shell provides the Rust toolchain selected by
rust-toolchain.toml, the development utilities, and a Python environment
built from the checked-in uv.lock. PySCF and the scientific Python
dependencies are available on every platform declared by the flake. Nix places
that environment directly on PATH, so no virtual environment needs to be
created or activated:
python -c "import pyscf; print(pyscf.__version__)"
Platform-specific profiling and debugging tools are included where available. Run the usual Cargo commands inside the shell:
cargo build
cargo test
cargo run --locked -- basis import tests/data/sto-3g.json
cargo run --locked -- run samples/h2/sto-3g/calculation.toml
Four shells are available so that contributors only load the tools needed for their current task:
| Shell | Contents | Command |
|---|---|---|
mini-rust | Rust toolchain and native build dependencies | nix develop .#mini-rust |
rust | Complete Rust development, debugging, and profiling tools without Python | nix develop .#rust |
mini-pyscf | Minimal Rust build environment plus Python and PySCF | nix develop .#mini-pyscf |
full | Complete Rust and scientific Python environment | nix develop .#full |
Running nix develop without a shell name selects full.
Leave the environment with exit or Ctrl-D. You can also build the default Nix
package without entering the development shell:
nix build
Nix With direnv
Install both Nix and direnv, enable the direnv hook for your shell, then run:
git clone --branch develop --single-branch https://github.com/mveril/RustiQ.git
cd RustiQ
direnv allow
The tracked .envrc loads the full shell automatically whenever you enter
the repository and unloads it when you leave. To select a lighter shell for one
checkout, create an ignored .envrc.local, then allow the updated environment:
printf '%s\n' 'export RUSTIQ_DEV_SHELL=rust' > .envrc.local
direnv allow
Valid values are mini-rust, rust, mini-pyscf, and full. The tracked
.envrc rejects other values before passing the selection to Nix. direnv allow is deliberately required the first time, and again after either envrc
file changes, so that shell code is not executed without review. Use direnv deny to revoke permission.
Inside the Dev Container, FlakeEnv performs this integration for VS Code. The
tracked .envrc remains useful for developers who use direnv in another editor
or terminal.
If use flake is unknown, install or configure
nix-direnv, or use nix develop
directly. Some direnv/Nix installations already provide this integration.
Manual setup with Rust and Cargo
Advantages and limitations
- Advantages: builds and calculations run directly on Linux, macOS, or Windows. No container or VM is required. This is suitable when native host execution, local profiling, or existing cluster build tools matter.
- Maintenance: you install native build dependencies and optional tools
yourself. The repository selects Rust through
rust-toolchain.tomland Cargo dependencies throughCargo.lock, but does not pin the entire host environment. - Platforms: native Cargo supports the platforms in the compatibility table, including Windows and Intel macOS. Python development tools run natively on Windows; PySCF comparisons also run on Windows x86-64.
- HPC use: this route can use the site’s existing compiler environment without Docker or Nix. Build and run according to cluster policy, using the scheduler’s assigned resources. A locally built binary still needs a compatible target OS, architecture, and runtime dependencies.
Install and build
Install a C/C++ build toolchain and CMake for native dependencies. On Linux, use your distribution’s development packages; on macOS, install the Xcode Command Line Tools and CMake. On Windows, install Visual Studio C++ Build Tools with the Windows SDK, CMake, and the Rust MSVC toolchain.
Install Git and Rust through rustup, then use Cargo
directly on Linux, macOS, or Windows:
git clone --branch develop --single-branch https://github.com/mveril/RustiQ.git
cd RustiQ
rustup show
cargo build --locked
cargo test
cargo run --locked -- basis import tests/data/sto-3g.json
cargo run --locked -- run samples/h2/sto-3g/calculation.toml
rustup show causes rustup to notice rust-toolchain.toml and install the
requested stable toolchain and components if necessary. This route is enough to
build and run RustiQ, but the extra tools and the PySCF reference environment
from the Nix development shell must be installed separately if you need them.
The repository uses uv for that environment on
Linux, macOS, WSL2, and native Windows:
uv sync --locked
uv run --locked ruff --version
uv run --locked pytest tools/test_book_links.py tools/test_release_smoke.py tools/benchmarks
The project supports Python 3.12 through 3.14. The default groups install JupyterLab, ipykernel, Matplotlib, SciPy, NumPy, pytest, and Ruff. The lock also includes PySCF 2.15.0 on Linux, macOS, and Windows x86-64. Windows ARM64 remains excluded. Binary wheels are required; source builds remain disabled. Run the reference suite with:
uv run --locked pytest tools/reference
On Windows x86-64, the same command runs PySCF calculations, AO integral comparisons, helper tests, and persistence interoperability tests. Use WSL2 for PySCF on Windows ARM64. These Python tools support development and validation; building the RustiQ executable still requires the Rust toolchain and the Cargo commands above.
Build for calculations and install the executable
From the repository root, use an optimized build for substantial calculations or timing comparisons:
cargo build --release --locked
cargo run --locked -- basis import tests/data/sto-3g.json
cargo run --release --locked -- run samples/h2/sto-3g/calculation.toml
To install into Cargo’s binary directory:
cargo install --locked --path .
rustiq --help
The executable is named rustiq (or rustiq.exe on Windows); use lowercase on case-sensitive systems. Ensure Cargo’s binary
directory is on PATH. Keep the checkout for the tutorial’s sample files.
Nix packages and shells
The flake also exposes legacyPackages.<system>.cpuTarget, a function accepting
an LLVM CPU name and returning a CPU-specific RustiQ package. See the
Nix installation guide for
commands and portability considerations. The default package remains portable.
The packages below are declared in flake.nix. All four
shells share Rust build essentials. rust adds Rust development tools;
mini-pyscf adds the Python reference-test environment to the minimal Rust
shell; full combines both extensions. nix develop selects full by default.
Use nix develop .#<shell> to enter a named shell. The direnv setup can
select the same names with RUSTIQ_DEV_SHELL; see Development
environments.
Rust build essentials
| Package | Purpose | Shells |
|---|---|---|
Rust toolchain from rust-toolchain.toml | rustc, Cargo, Clippy, rustfmt, and Rust source components pinned to the project toolchain | All |
cmake | Builds native dependencies that use CMake | All |
pkg-config | Helps native builds find installed libraries | All |
libiconv (macOS only) | Provides character conversion support needed by native builds on macOS | All on macOS |
Rust development tools
The flake pins a NixOS 26.05 nixpkgs revision and uses its development tools
directly, without local package overrides.
Its cargo-dist package is version 0.31.0; before regenerating release workflows,
install the version required by dist-workspace.toml as described in
Releasing.
| Package | Purpose | Shells |
|---|---|---|
rust-analyzer | Rust language server for editor completion, diagnostics, and navigation | rust, full |
cargo-nextest | Runs Rust tests with improved reporting and test isolation | rust, full |
cargo-deny | Checks dependency licenses, advisories, sources, and duplicate crates | rust, full |
cargo-about | Generates the third-party license notices used in distributions | rust, full |
cargo-llvm-cov | Measures Rust test code coverage using LLVM instrumentation | rust, full |
cargo-criterion | Runs Criterion benchmarks through Cargo | rust, full |
cargo-expand | Displays macro-expanded Rust code | rust, full |
cargo-edit | Adds, removes, and upgrades dependencies from the command line | rust, full |
cargo-dist (dist) | Builds release archives, installers, and checksums | rust, full |
cargo-info (cargo info) | Displays crate metadata from registries | rust, full |
bacon | Watches files and reruns selected Cargo checks | rust, full |
cargo-watch | Runs Cargo commands when files change | rust, full |
git | Source control commands | rust, full |
hyperfine | Repeats and compares command-line benchmarks | rust, full |
jq | Reads and transforms JSON from the command line | rust, full |
mdbook | Builds and previews this manual | rust, full |
mdbook-mermaid | Preprocesses Mermaid diagrams in the manual | rust, full |
nixd | Nix language server for editor support | rust, full |
nixfmt | Formats Nix expressions | rust, full |
nickel | Parses and evaluates Nickel configuration files | rust, full |
nls | Nickel language server for editor diagnostics and completion | rust, full |
ripgrep (rg) | Fast recursive text search | rust, full |
time | Reports elapsed time and resource usage for commands | rust, full |
clang (Linux only) | C/C++ compiler used by profiling and native development tools | rust, full on Linux |
cargo-flamegraph (Linux only) | Profiles Rust programs and creates flamegraphs | rust, full on Linux |
gdb (Linux only) | Command-line debugger | rust, full on Linux |
inferno (Linux only) | Converts profiler output into flamegraphs | rust, full on Linux |
perf (Linux only) | Linux performance-counter profiler | rust, full on Linux |
samply (macOS only) | Sampling profiler for macOS | rust, full on macOS |
Python and scientific packages
Python dependencies are described by pyproject.toml and pinned in uv.lock.
Nix builds the Python environments from those files. Python is 3.14 in this
flake.
| Package or group | Purpose | Shells |
|---|---|---|
uv | Python project and dependency manager for workflows outside the prebuilt shell environment | full |
pyscf | Independent quantum-chemistry implementation used for reference calculations | mini-pyscf, full |
numpy | Array and numerical operations used in tests and scientific Python tools | mini-pyscf, full |
pytest | Runs the PySCF reference test suite | mini-pyscf, full |
scipy | Scientific algorithms used by optional analysis and development tools | full |
matplotlib | Creates plots for scientific analysis | full |
ipykernel | Connects Python environments to Jupyter kernels | full |
jupyterlab | Interactive notebook environment | full |
ruff | Lints and formats Python code | full |
mini-pyscf uses the Python test dependency group; full includes the
default group, which combines dev, test, and linting. The helper
nix run .#pyscf-check -- ... runs the reference tests against the packaged
RustiQ binary. For example:
nix run .#pyscf-check -- -q
Other flake outputs
The flake also exposes nix build .#book to build this manual,
nix build .#cargo-artifacts for cached Cargo dependency artifacts, and
nix build .#pyscf-environment for the base PySCF environment. These are build
outputs rather than development shells. The default package is the RustiQ CLI
binary, available through nix build or explicitly through nix build .#default.
Install a tagged version with nix profile install github:mveril/RustiQ/vVERSION,
replacing vVERSION with a published tag. Both development and release revisions
use this default package. Its online manual follows the Cargo
version: a dev prerelease identifier selects development documentation;
other versions select the matching versioned manual. No release flag is needed.
See releasing.
Installed manual and completions
The default package includes manual pages for man rustiq and its
subcommands, such as man rustiq-artifact-inspect. Every page links to the
online book. The package also includes the complete offline HTML manual under
share/doc/rustiq/manual/html, including local equation and diagram resources. From the
repository root:
nix build
./result/bin/rustiq docs
./result/bin/rustiq docs --print-path
Use --web to open the online manual. Cargo-only installations use the online
manual by default; see installation.
The package also installs Bash, Zsh, and Fish completions in the standard Nix locations. Shell discovery depends on your Nix profile and shell setup.
Nushell also loads the completion automatically at interactive startup when
the profile exposes share/nushell/vendor/autoload through its data directories.
On NixOS, enabling programs.nushell exposes share/nushell from the system
profile. Other profiles may need their share directory in XDG_DATA_DIRS.
Nushell, PowerShell, and Elvish scripts are also provided under
share/rustiq/completions/ for manual loading. From the repository root, build
the package with nix build, then load the script in the matching shell:
use ./result/share/rustiq/completions/rustiq.nu *
. ./result/share/rustiq/completions/rustiq.ps1
source ./result/share/rustiq/completions/rustiq.elv
For persistent configuration, use the corresponding installed profile path
instead of a checkout’s result link. PowerShell support registers native
argument completion only.
Nix generates the files with a separate build tool and sets
RUSTIQ_PACKAGING=true so both generators omit themselves from manuals and
completions. The installed executable retains online but disables the Cargo
features manpages and completions, so it does not offer generation commands
or link their dependencies. Other packagers can set the same variable when
generating assets for a binary built without those features.
Nix checks build and test all features separately; package installation checks
verify the installed assets and the absence of generator commands.
Useful references
- Nix flakes and
nix develop. - Rustup toolchain file and Cargo commands.
- PySCF documentation, uv documentation, and JupyterLab documentation.
Known supported platforms
RustiQ is written almost entirely in Rust, which makes it portable across a
wide range of operating systems and processor architectures. The CLI and the
rustiq-chem-core library are known to work on the platforms below. Automated build
and test checks help maintain that compatibility as the project evolves.
| Operating system | Processor architecture | Available setup |
|---|---|---|
| Linux | x86_64 | Cargo, Nix, or the Dev Container |
| Linux | AArch64 (ARM64) | Cargo, Nix, or the Dev Container |
| Windows | x86_64 | Native Cargo, or a Linux environment through WSL2 or the Dev Container |
| Windows | AArch64 (ARM64) | Native Cargo, or a Linux environment through WSL2 or the Dev Container |
| macOS | Apple Silicon (AArch64) | Cargo, Nix, or the Dev Container |
| macOS | Intel (x86_64) | Cargo or the Dev Container |
Other Rust targets may also work. This table describes known compatibility; it is not an exhaustive list of every platform on which RustiQ could run. Native dependencies and optional tools can impose additional requirements.
Choosing an environment
The Cargo workflow builds RustiQ directly on your operating system. It is available on all the platforms listed above. The Nix flake provides a prepared Rust and scientific Python environment for these systems:
x86_64-linux;aarch64-linux;aarch64-darwin(Apple Silicon).
The pinned nixpkgs revision no longer supports Intel macOS, so use native Cargo or the Linux Dev Container on that platform. Native Windows users can also use Cargo; Nix requires a Linux environment such as WSL2.
The optional VS Code Dev Container provides a Linux environment through
Docker. It is an option on all the host platforms in the table, including
Linux and Windows ARM64, provided Docker can run Linux containers on the host.
Inside the container, Nix uses x86_64-linux or aarch64-linux according to
the container architecture, even when the host runs Windows or macOS. See
Development environments for installation instructions,
Windows troubleshooting, and the configured VS Code extensions.
The optional scientific Python tools have their own platform requirements.
The project configures uv for Linux, macOS, and native Windows. The locked
PySCF 2.15.0 release includes native Windows x86-64 wheels; Windows ARM64
remains excluded. The Nix environment provides PySCF on every declared Nix
system. For PySCF comparisons on Windows ARM64, use WSL2 or the Linux Dev Container.
How compatibility is checked
The regular CI workflow provides ongoing evidence for this support:
- Native Cargo checks cover Linux x86_64, Windows x86_64 and ARM64, and macOS Apple Silicon and Intel. They run formatting, Clippy, workspace tests with and without the online feature, and standalone core checks.
- Nix checks cover Linux x86_64 and AArch64 and macOS Apple Silicon. They build RustiQ, exercise the development shells, and compare reference energies against PySCF.
- The Dev Container is built and tested on Linux x86_64, including Cargo tests and PySCF comparisons. Separate Windows and macOS host integrations are not exercised by these checks.
- The standalone
uvenvironment is checked on Linux and Windows x86_64 with Python 3.12 and 3.14. A native PySCF job runs the reference suite on Linux x86-64 and ARM64, macOS Intel and Apple Silicon, and Windows x86-64. Windows also checks Rust/NumPy persistence interoperability with Python 3.12.
The scheduled full Nix workflow also runs all native flake checks on the three declared Nix systems. These checks validate known configurations; they do not limit the possible platforms for the Rust application.
Releasing RustiQ
RustiQ uses dist to build and
publish binary archives to GitHub Releases. crates.io publication runs in a
separate workflow. Registry lookup or dry-run failures block promotion; once
promoted, a registry publishing failure does not block the binary workflow.
Neither workflow creates a release from a GitHub Release event; both are
explicitly dispatched by promotion after a merge into main, and crates.io publication can also be
started manually for an existing tag.
Binary releases
The repository-root dist-workspace.toml pins dist 0.34.0, selects only the
rustiq-chem CLI package, and lists the six supported targets. Pull requests
run dist plan; this checks the release plan without building or publishing
artifacts. The generated workflow also runs on non-main pull requests because
dist 0.34.0 does not expose a pull-request base-branch filter. A pull request
cannot enter the publishing jobs.
All six target builds use native GitHub-hosted runners: Linux x64 on
ubuntu-22.04, Linux ARM64 on ubuntu-24.04-arm, macOS Intel on
macos-15-intel, Apple Silicon on macos-latest, Windows x64 on windows-2025,
and Windows ARM64 on windows-11-arm. The configuration explicitly selects
the ARM runners and preserves the native Windows runners.
The
rustiq-chem-core library remains a build dependency and is not packaged as an
application. The generated workflow is .github/workflows/release.yml. It pins
actions/upload-artifact to an exact version. Because cargo-dist emits a major
version reference for that action, dist-workspace.toml sets
allow-dirty = ["ci"] so dist plan does not reject the exact pin as an
out-of-date generated workflow. Keep the pin synchronized with the intended
upload-artifact release when updating the workflow or cargo-dist. Preserve the
custom build-manual job, the local-build dependency on it, and the download
into manual/html/ when regenerating the release workflow; generated defaults do
not contain this offline-manual integration. Preserve the static local-build job
name, Build platform artifacts, so pull requests that skip artifact builds
display a readable name before the target matrix is expanded.
Release rehearsal
The Release artifact smoke test workflow runs automatically on pull requests
targeting main, testing the prospective merge commit. To rehearse another
revision, run Actions → Release artifact smoke test → Run workflow and select
the commit, branch, or tag. New runs cancel older rehearsals for the same pull
request or selected workflow ref. The workflow builds the configured target archive with the pinned dist version on each target’s native
GitHub-hosted runner. It extracts that archive, verifies its dist-generated
SHA-256 checksum, starts the packaged rustiq executable, checks --help,
and runs the checked-in H2/STO-3G regression with a copied local basis fixture
and JSON output. Per-target results appear in the job summary; archives, dist
manifests, and command logs are uploaded as workflow artifacts. Successful targets also
publish a separate rustiq-packages-<target> artifact containing the distributable
archive and checksums. Follow the download link in the run summary, then unzip
the GitHub Actions artifact to obtain the original release archive. Downloads
require a GitHub login and remain available until the workflow artifacts expire.
After all six native builds pass, a global job runs dist build --artifacts=global,
just as publication does. This builds the corresponding source archive and combined
checksums. Download rustiq-release-packages from its summary link to obtain
all native archives and global assets together. Only after this upload do the
six native smoke jobs download that same artifact and test their target archive
against its combined sha256.sum. Thus the downloadable final packages are
the packages exercised by the smoke tests. The source archive requires a
clean committed checkout; commit local changes before rehearsing them in CI.
The Apple Silicon smoke job uses the native macos-latest runner.
This checks archive integrity and basic executable operation for the six
configured targets. The H2 energy comparison reuses the regression reference
and is a packaging smoke test, not broad scientific validation, independent
platform validation, or proof of compatibility with every supported operating
system. The runs use GitHub-hosted runners, which are not pristine operating
system installations. The rehearsal requires the combined sha256.sum generated by the global
dist build and verifies each tested archive against it. A checksum made during a rehearsal does not independently validate
a published release.
The rehearsal has read-only repository permissions and supports pull_request
events targeting main and manual workflow_dispatch runs. It does not run dist’s host command, upload
release assets, create a GitHub Release, create tags, or publish crates. It
complements .github/workflows/release.yml, whose dispatched release path builds
and publishes the release assets. Pull requests targeting develop continue
to use the generated plan-only check without the six-target rehearsal.
Each executable archive includes rustiq (named rustiq.exe on Windows),
the README, LICENSE-MIT, LICENSE-APACHE, COPYING, DISTRIBUTION.md, and
THIRD-PARTY-NOTICES.txt, and the complete offline manual in manual/html/.
The release workflow builds the validated Nix book once and downloads that
artifact into every native archive build. Archive rehearsals check the manual
after relocating the extracted tree. See documentation checks
for local archive preparation and the offline build process. RustiQ-authored source retains MIT OR Apache-2.0;
Malachite and ansi_colours retain their LGPL terms. COPYING supplies the GPLv3
text referenced by LGPLv3, rather than imposing GPLv3 on all RustiQ code. Unix archives use .tar.gz
and Windows archives use .zip. Dist adds a .sha256 file for each archive
and a sha256.sum manifest. Installers are disabled. Archives do not include
calculation samples or basis data.
Each release also includes rustiq-corresponding-source.tar.gz, generated by
the dist extra-artifact command python3 tools/distribution.py source before
publication. This supplies the committed repository tree and all locked
dependency sources. The generated Cargo configuration allows registry-free
rebuilding. Dist’s repository-only source tarball is disabled because it would
omit the dependency sources.
Dist treats this file as an extra artifact; it does not emit a separate
checksum for it in the release plan. Before publishing, verify that the source
archive is actually present in the release assets and corresponds to the tagged
commit. Its checksum can be calculated separately when verifying distribution
integrity.
See licenses and redistribution for rebuild instructions and
the requirements for package maintainers. The Nix package installs the same
notice documents into share/doc/rustiq/manual/html; its metadata describes RustiQ’s
MIT/Apache terms and the bundled LGPL/MPL components.
To verify the assets listed in sha256.sum on Linux, download it and all listed
assets into one directory, then run:
sha256sum --check sha256.sum
On macOS, use the built-in shasum command:
shasum -a 256 --check sha256.sum
On Windows PowerShell, use the explicit manifest comparison in the installation guide, replacing its example archive filename with the archive for your target.
The archive target identifies the operating system and CPU architecture; it does not guarantee compatibility with every Linux distribution or older system library. The Linux GNU archives require a compatible glibc runtime.
Maintaining the changelog
Maintain the repository-root CHANGELOG.md by hand using Keep a Changelog categories and concise, user-facing entries.
- Add notable implemented changes under
Unreleasedduring development. - Review and edit the entries before each release, checking capabilities and limitations against the current code, tests, and documentation.
- During release preparation, move the relevant entries into a versioned
section, such as
## [0.1.0-beta.1] - YYYY-MM-DD. - Replace
YYYY-MM-DDwith the actual release date and update the changelog’s version and comparison links. - Leave an empty
## [Unreleased]section for future changes, omitting empty categories. - After updating package versions as described below, run
dist plan --tag v0.1.0-beta.1 --output-format=json(substitute the intended tag). Check thatannouncement_github_bodycontains the intended version’s changelog entries and limitations, rather than only artifact download notes. - Finalize and commit the changelog with the release preparation changes before creating the release tag.
The first public beta should document the capabilities available at launch. For subsequent beta releases, describe incremental changes instead of repeating the complete feature inventory.
Before the first release, preserve the existing Unreleased link to the develop
branch’s commit history: no beta release tag exists yet. When preparing
v0.1.0-beta.1, finalize the entries under a dated version heading and leave
Unreleased ready for future changes:
## [Unreleased]
## [0.1.0-beta.1] - YYYY-MM-DD
Replace YYYY-MM-DD with the actual publication date. As part of that release
preparation, set the reference links to the following convention, which applies
after the first release:
[Unreleased]: https://github.com/mveril/RustiQ/compare/v0.1.0-beta.1...HEAD
[0.1.0-beta.1]: https://github.com/mveril/RustiQ/releases/tag/v0.1.0-beta.1
For each subsequent release, add its version link and update the Unreleased
comparison to start from the latest published version. Until release preparation
begins, do not finalize the beta section or add links to an unpublished release.
Dist 0.34.0 has built-in changelog support.
It discovers the root changelog and selects the matching version section for
release notes. It can also use Unreleased for prereleases, but release
preparation should still finalize a dated version section. The existing
workflow passes dist’s announcement_github_body to gh release create;
no separate release-note generator or workflow change is needed.
Preparing a release
Start from develop on a task branch:
git switch -c chore/prepare-version develop
From the repository root, update the version in both package manifests and
update the CLI’s rustiq-chem-core dependency requirement to that same
version:
Cargo.toml(rustiq-chem)crates/rustiq-core/Cargo.toml(rustiq-chem-core)Cargo.toml’srustiq-coredependency
After editing the manifests, regenerate Cargo.lock and the corresponding
notices. The distribution script needs Python with tarfile extraction filters:
Python 3.12 or later, or the backported filters in Python 3.10.12+/3.11.4+.
This is independent of the optional PySCF environment. Enter the Nix rust or
full shell for the pinned notice generator, or install cargo-about 0.9.2
outside Nix, then run:
cargo check --workspace
cargo install cargo-about --version 0.9.2 --locked
python3 tools/distribution.py notices
python3 tools/distribution.py check
cargo deny --locked --workspace --all-features check
git add CHANGELOG.md Cargo.toml crates/rustiq-core/Cargo.toml Cargo.lock THIRD-PARTY-NOTICES.txt THIRD-PARTY-NOTICES.sha256
git commit -m "Prepare release X.Y.Z"
The publishing workflow checks both package versions and the CLI dependency requirement against the tag using Cargo metadata. After committing the version change, build the workspace:
cargo check --workspace --locked
Promotion requires registry availability and a successful workspace publication dry run.
There is currently no local Nickel patch or corresponding crates.io
publication block. Before publishing crates, review the acknowledged
upstream advisories described in crates.io publication
and run cargo publish --dry-run --workspace --locked.
Regenerate and commit notices after changing dependencies, license configuration, the notice template or generator. Review supplemental upstream notices when updating crates whose published packages omit their licenses. CI checks their package inventory, input hashes and generated-file integrity. This catches stale or accidentally edited output; it does not independently verify every license clause or certify legal compliance. Review generated notices and supplemental attribution when changing dependencies. To rehearse the complete source delivery from a clean committed checkout:
python3 tools/distribution.py source
The command rejects source changes and untracked files, except the dist workflow’s generated JSON manifests. It verifies offline Cargo resolution from the archive staging tree. Before a release, also extract the source artifact and run the reconstruction command documented in licensing.
Review the dist release plan and regenerate the workflow after changing the
dist configuration or updating dist. The allow-dirty = ["ci"] setting means
the generator does not check whether the checked-in release workflow matches
its current template. Preserve the exact upload-artifact pin if you regenerate
the workflow:
dist plan
dist generate --mode ci
dist generate --mode ci --check
The Rust development shell includes the Nixpkgs cargo-dist package. The
generated workflow installs the exact dist version recorded in
dist-workspace.toml. Before regenerating locally, install that same version
if the Nixpkgs package differs:
cargo install cargo-dist --version 0.34.0 --locked
Development takes place on the develop branch. Use a version ending
in .dev, keeping both crate versions and the internal dependency synchronized.
Prepare a release on a chore/* task branch from develop: remove the development
identifier, finalize the dated changelog, and update Cargo.lock.
Push the task branch and open a pull request targeting main:
git push -u origin chore/prepare-version
gh pr create --base main --head chore/prepare-version
The required Release eligibility check rejects development versions, mismatched package versions, and versions already present as a tag, GitHub Release, crates.io package, or published manual. Lookup failures block release eligibility. The check also runs:
cargo publish --workspace --locked --dry-run
Cargo packages and compiles both crates, including the unpublished core dependency.
Keep package verification enabled. A failure blocks the merge. Update the branch
with main before merging so checks apply to the prospective merged result.
Every merge into main, including documentation changes, requires a fresh version.
Alpha and beta versions are allowed; a complete dev prerelease identifier is not.
After merging, Promote release repeats validation and the publication dry run,
creates vVERSION at the merged commit, and explicitly dispatches the binary,
crates.io, and documentation workflows at that tag. Do not create or push tags
manually. Tag creation with the Actions token does not itself start push workflows.
The three publications run independently; inspect each workflow for completion.
The registry publication still requires CARGO_REGISTRY_TOKEN.
Resume development with the next intended version ending in .dev on develop.
No release/* branches are used. Check the matching /RustiQ/vVERSION/ manual
and versions.json after publication. Versioned manuals remain immutable.
The documentation homepage opens the latest stable version, otherwise the latest
prerelease, otherwise /dev/. Pushes to develop update only /dev/.
crates.io publication
Nickel 0.19’s published dependency graph currently includes
imbl-sized-chunks 0.1.3, affected by the unfixed security advisory
RUSTSEC-2026-0292, and the unmaintained bitmaps 3.2.1
(RUSTSEC-2026-0247). RustiQ intentionally uses Nickel’s published releases:
it does not fork Nickel or backport its transitive dependencies.
deny.toml records explicit exceptions for these advisories. Passing
cargo deny check does not indicate that the vulnerability is fixed.
Review these exceptions and upstream fixes before each release; see
dependency review.
The crates.io workflow is not blocked by these exceptions. A merge into main
can trigger publication of both crates while the upstream vulnerability remains
present. Decide whether to publish that version with the documented risk or
hold the release pull request until Nickel publishes a compatible fix.
.github/workflows/publish-crates.yml publishes both workspace crates when a
release is promoted from main. Cargo publishes workspace members in dependency
order, so
rustiq-chem-core is available before rustiq-chem. Before publishing, the
workflow uses the crates.io API to exclude package versions that already
exist. If a run publishes the core crate and then fails while publishing the
CLI, rerunning the same tag skips the existing core version and retries the
CLI. For a retry, open Actions → Publish crates.io packages → Run
workflow, enter the existing v… tag, and start the workflow.
This workflow remains separate from the dist binary release workflow and can
also be run manually for an existing tag.
The workflow currently authenticates with the Actions secret
CARGO_REGISTRY_TOKEN. Create it from a crates.io API token with only package
publishing permissions, then add it under the repository’s Actions secrets
before the first release. Keep the token out of repository files and do not
grant permissions to yank crates.
Crates.io Trusted Publishing uses GitHub OIDC and avoids a long-lived token,
but crates.io requires each crate to have an initial token-authenticated
publication before a Trusted Publisher can be configured. For RustiQ’s first
publication, use CARGO_REGISTRY_TOKEN to publish both packages through the
tag workflow or its manual execution for an existing tag. After both crates
exist, configure a Trusted Publisher for each crate in crates.io to trust this
repository and the publishing workflow. A follow-up change can then replace
the token authentication with OIDC; the binary release workflow does not use
or depend on the crates.io token.
Cargo may time out while waiting for a published version to appear in the registry index even when the upload succeeded. Check the version on crates.io before retrying; the workflow’s existence check will skip a version already published.
All package formats derive their online documentation channel from the Cargo
version. Build a tagged release with nix build github:mveril/RustiQ/vX.Y.Z;
no package selector or release flag is required.
If tag creation succeeds but a dispatch fails, run the missing publication workflow manually at that existing tag. Do not rerun promotion to create the tag again. Rerun failed publication jobs for the same tag; never move the tag. Cargo skips already published crates, and the documentation publisher checks immutable content. For binaries, inspect an existing GitHub Release and its assets before retrying.
Resume development through a task pull request to develop. Port any release-only
fixes or changelog changes, then synchronize both crate versions, the internal
dependency, and Cargo.lock with the next version ending in .dev. Do not merge
release versions back without restoring the development suffix.
For an existing release tag, explicitly select that tag when retrying:
gh workflow run release.yml --ref vVERSION
gh workflow run docs-publish.yml --ref vVERSION
gh workflow run publish-crates.yml --ref vVERSION -f tag=vVERSION
Dispatch only the missing publication. A default-branch dispatch does not select the release revision. Rerun failed jobs in the original binary workflow when some assets already exist; do not create a competing GitHub Release.
RustiQ distribution terms and source access
RustiQ-authored source files are available under MIT OR Apache-2.0. Third-party files keep their upstream licenses and copyrights. The package manifests describe the RustiQ-authored source; they do not relicense dependencies.
The executable uses Malachite under LGPL-3.0-only through Nickel and
ansi_colours under LGPL-3.0-or-later through bat. These libraries and their
use are covered by the LGPL. RustiQ’s own code remains MIT OR Apache-2.0;
the libraries are not relicensed. The GPLv3 text in COPYING accompanies the
LGPL terms, which supplement GPLv3; it does not declare RustiQ as a whole GPL.
THIRD-PARTY-NOTICES.txt supplies the LGPL, MPL, data-license and other texts
and upstream notices. The BSD alternative is selected for bounded-vec-deque.
This policy also applies to binaries built without the online feature.
Sources for a distributed executable
Each tagged GitHub release supplies rustiq-corresponding-source.tar.gz
alongside its binary archives, at no additional charge. The version-specific
download URL is recorded at the top of THIRD-PARTY-NOTICES.txt. Obtain the
source artifact from the same release as the binary. It contains the
repository sources, Cargo.lock, build scripts, assets, vendored dependencies,
and Cargo configuration for using them without accessing a registry.
Vendored dependencies are the bundled third-party source code in vendor.
GitHub’s automatic repository source downloads do not contain the vendor tree.
Extract and enter the archive using tar on Unix or recent Windows systems:
tar -xzf rustiq-corresponding-source.tar.gz
cd rustiq-source
Install Rust, a native C/C++ toolchain and CMake as described in the manual’s Cargo setup guide. Build the executable using:
cargo build --offline --locked --profile dist --bin rustiq
The result is target/dist/rustiq (target/dist/rustiq.exe on Windows).
This rebuild enables the default online feature. An offline application build
adds --no-default-features; the build itself stays offline in both cases.
This is a reconstruction procedure, not a guarantee of byte-identical binaries.
SOURCE-INFO.txt identifies the repository commit and lockfile.
To replace an LGPL component, copy its directory from vendor to an editable
directory. For example, copy vendor/malachite-base-0.9.2 to
modified/malachite-base and make your changes there. Create a
[patch.crates-io] section in the extracted source archive’s root
Cargo.toml (or add an entry to that section if it already exists):
[patch.crates-io]
malachite-base = { path = "modified/malachite-base" }
Then rebuild with cargo build --offline --profile dist --bin rustiq.
Omit --locked because Cargo may need to update the lockfile for the local
replacement. The replacement must satisfy the required package version and
API, or you must adjust its dependents too. Keep the upstream license and
document your modifications. Vendored files have integrity checks, so use
a path patch rather than editing them in place. This changes only the local
reconstruction: RustiQ does not modify or fork Nickel upstream.
Redistributing or packaging RustiQ
Include COPYING, LICENSE-MIT, LICENSE-APACHE, DISTRIBUTION.md and
THIRD-PARTY-NOTICES.txt with each executable archive or installed package.
Preserve the upstream notices, including bundled native code and assets.
Package metadata may describe RustiQ-authored code as MIT OR Apache-2.0.
It must also preserve the notices and terms for the bundled LGPL, MPL and other
components; the application license does not replace those terms.
When serving binaries for download, give recipients equally convenient, no-charge access to the exact corresponding sources on the same download page. If the sources are on another server, put clear directions next to the binary and keep that source access available for as long as needed to meet LGPLv3 section 4(d)(0), which refers to GPLv3 section 6. Preserve the source link in the installed documentation. If you rebuild or patch the application, supply corresponding sources for your own build, including packaging scripts and modifications. Media, devices and other distribution methods require the applicable GPLv3 section 6 arrangements, including installation information when required.
The upstream LGPL and MPL sources and any modifications must remain available under their applicable licenses. Do not add terms that prevent modification, replacement of LGPL components, or reverse engineering to debug those modifications. Normal command execution does not require a credits banner; the accompanying documents carry the notices.
Dependency review
cargo-deny restricts additional license approvals to reviewed crate versions.
cargo-about generates license texts; tools/distribution.py adds separate
upstream notices and records the lockfile and input hashes. Identical upstream
texts are included once and referenced by each package that supplies them.
cargo vendor gathers dependency sources; git archive supplies the committed
project tree; cargo-dist publishes the resulting archive.
CI checks the package inventory and generated-file integrity, not every license
clause. Supplemental upstream notices and their provenance
are retained in licenses/extra-notices.txt, including notices missing from
published crate archives. Review these when updating the affected crates.
cargo-about and cargo-deny only cover the Cargo dependency graph; review
the license terms and attribution of checked-in scientific data, fixtures,
assets, and other third-party content separately before redistribution.
RustiQ retains transitive dependencies with informational maintenance
advisories for bincode, unsafe-libyaml and yaml-rust. Their specific advisory
IDs and reasons are recorded in deny.toml. Rustls has been updated to its
fixed patch release.
Nickel 0.19 depends on imbl-sized-chunks 0.1.3, affected by
RUSTSEC-2026-0292:
a memory-safety vulnerability involving double free / use-after-free if an
element’s destructor panics during certain removal operations. The fix is in
imbl-sized-chunks 0.2.0 or later, but RustiQ deliberately keeps Nickel’s
published dependency graph rather than carrying a local backport or forking
Nickel. deny.toml explicitly acknowledges this unfixed security advisory;
a passing cargo deny check does not mean this risk has been mitigated.
The same dependency graph includes the unmaintained bitmaps 3.2.1 crate
(RUSTSEC-2026-0247),
which is a maintenance advisory, not the same vulnerability. Reassess both
exceptions before releases and adopt a compatible upstream Nickel update
when one becomes available. There is no automatic crates.io publication
block associated with these acknowledged advisories; the publishing workflow
still runs on version tags.
Authoritative terms: GPLv3, LGPLv3, MPL 2.0, and CDLA-Permissive-2.0.
For build prerequisites, see Manual / Cargo setup. For release maintenance commands, see Releasing RustiQ.
Contributing and the Rust API
CONTRIBUTING.md owns branch naming, lint policy, and verification commands. See development environments for setup.
Run cargo deny check from the workspace root to check dependency advisories,
licenses, duplicate versions, and dependency sources. The same check runs in a
dedicated GitHub Actions job; its policy is defined in deny.toml.
The distribution script requires Python with tarfile extraction filters
(Python 3.12+, or patched 3.10.12+/3.11.4+). The rust and full Nix shells
provide cargo-about. Outside Nix, install cargo-about 0.9.2. After dependency
or notice-generation changes, run python3 tools/distribution.py notices, then
python3 tools/distribution.py check. Commit the generated notice text and its
checksum with the change. See licenses and redistribution for
the distribution policy and Nickel’s dependency advisories.
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 Pages site publishes the manual; rustdoc is generated separately.
For book equations, use MathJax delimiters \\( ... \\) inline and
\\[ ... \\] for display math. Markdown consumes one backslash, so
write TeX commands with doubled backslashes as well. Avoid starting a
continuation line with Markdown syntax such as +, which can split an
equation into a list. Build the book and inspect the generated HTML and a
browser-rendered equation, including multiline equations. MathJax requires
JavaScript in the browser.
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.
Public API imports
Use rustiq_core::prelude::* for direct calculations. It includes
CalculationExecution, the trait providing execute() and
execute_with_events() for builders and prepared calculations. With explicit
imports, bring rustiq_core::calculation::CalculationExecution into scope to
call those methods. The builder supports mutable setters such as hf(...),
accessors such as get_hf(), and consuming with_hf(...) variants.
Explicit imports use molecules for molecular inputs, config for options,
random distributions and validated scalars, basis for basis data, and
calculation for execution and results. Located<T> remains available from
config and the prelude for optional frontend source positions.
Extensible option structs, including HF, DIIS, orthogonalization, molecular,
integral, MP2, random-guess, and guess-perturbation configurations, are
#[non_exhaustive]. Create them with Default::default() and then assign the
public fields you want to customize. External Rust callers cannot use struct
literals or ..Default::default() to construct these types. See the core
config module’s Rustdoc for executable examples.
RandomConfig is also non-exhaustive, but has no Default implementation
because no distribution is appropriate for every calculation. Start with
RandomConfig::new(distribution) and assign seed when reproducible sampling
is required. An absent seed continues to initialize sampling from system
randomness.
New options must have defaults that preserve the previous behavior when the
option is omitted. Maintain this contract in both the core’s Default
implementations and the input frontend’s defaults. Non-exhaustiveness protects
Rust source compatibility when fields are added; preserving default behavior
also requires checking the existing calculation and input regression tests.
The core produces ScfResult, ScfIteration, SCF timings,
HfCalculationResult, and Mp2MemoryPlan; these are non-exhaustive inspection
records, not extension points for constructing scientific output. Public
fields remain readable, while new diagnostics can be added without requiring
downstream struct literals to change. Mp2Result remains constructible because
the public Mp2Calculation trait lets downstream implementations return the
same result type.
Enums are non-exhaustive when callers select among evolving configurations or
consume results that may gain another variant, such as HfMethod,
ResolvedHfMethod, density guesses, random distributions, and MP2 sectors.
HfOutcome remains exhaustive because a completed HF run has exactly two
convergence states; setup and calculation failures are returned as errors.
RestrictedMethod and UnrestrictedMethod also remain exhaustive and name
only the currently implemented method for each reference. Adding a supported
method is an explicit API change, rather than an open-ended configuration
choice.
For portable archives and raw AO ERIs, import RustiQData, RustiQBundle, and CompactEri explicitly from
rustiq_core::persistence. Import ArtifactReuseDecision and
ArtifactReuseEvent from rustiq_core::calculation; these advanced types
require explicit imports. The portable examples linked above demonstrate the
persistence imports, and the
portable prelude test
shows how to combine them with the calculation prelude.
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.
UHF builds the alpha and beta Fock matrices in one pass over AO pairs. Each
pair shares the Coulomb contribution from the total density and the integral
loads, while retaining a separate exchange contribution for each spin density.
The independent scalar contraction regression covers unequal spin densities,
equal spin densities, and an empty beta density across different Rayon pools:
cargo test -p rustiq-chem-core spin_fock_matrices_match_independent_contractions.
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 core emits CalculationCompleted once after all requested stages complete.
An HF-only run emits it even when the returned HF outcome is unconverged; execution
completion and convergence are separate facts. A failing requested MP2 stage leaves
the earlier HF notification available but emits no calculation completion. Callbacks
borrow results synchronously; retaining them requires copying.
The CLI copies only numerical summaries and artifact reports for batch presentation,
so collecting a campaign does not retain orbital matrices or AO integrals.
Campaign execution returns one ordered CampaignResult directly, including
recoverable errors. Fatal errors stop execution before presentation. The CLI then
derives the campaign summary, publishes artifacts when allowed, and renders the
complete text or versioned JSON document. Publication failure after successful
scientific execution still leaves the completed JSON on stdout while returning a
failing process status. Portable bundle reruns use the same result presentation.
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; final canonicalization if converged
-> HfOutcome::Converged or HfOutcome::Unconverged
-> extract the typed converged RHF/UHF solution
-> Mp2Calculation::mp2()
blocked AO-to-MO integral transformation and MP2 correlation-energy evaluation
HfOutcome records whether HF converged and contains an
AnyHfSolution<State> whose Restricted or Unrestricted variant retains the
reference-specific solution. HfSolution<R, State> carries both the reference
and convergence state in its type; the RhfSolution and UhfSolution aliases
name the common profiles. AnyHfSolution does not expose MP2. For HF followed
by MP2, call prepared.run_hf()?.into_converged()?, match the runtime variant,
then call mp2(config) on the resulting typed RHF or UHF solution. Both typed
solutions implement the Mp2Calculation capability trait, exported in the
prelude; unconverged and generic runtime solutions do not. The conversion
returns an execution error retaining the unconverged outcome, recoverable with
into_hf(). Typed/runtime conversions preserve state and return a typed
HfReferenceMismatch error that retains the original solution when the requested
reference does not match.
The owned-output implementation lives in
crates/rustiq-core/src/calculation/solution/, with separate modules for generic
results, HF adaptation, runtime dispatch, outcomes and execution errors. The
calculation/solution.rs facade preserves the existing public exports through
rustiq_core::calculation and the prelude. Convergence markers stay together,
and private shared storage stays with the result that owns it.
HfSolution<R, State> wraps ScfSolution<HfMethodDescriptor<R>, State>.
The following conversions preserve the physical method, reference, convergence
state and shared scientific allocation:
| Source | Target | Conversion |
|---|---|---|
HfSolution<R, State> | ScfSolution<HfMethodDescriptor<R>, State> | From / Into, or into_scf() |
ScfSolution<HfMethodDescriptor<R>, State> | HfSolution<R, State> | From / Into, or from_scf() |
&HfSolution<R, State> | &ScfSolution<HfMethodDescriptor<R>, State> | AsRef, or as_scf() |
| Restricted or unrestricted generic HF output | AnyHfSolution<State> | From / Into |
AnyHfSolution<State> | Restricted or unrestricted generic HF output | TryFrom / TryInto |
The checked runtime extraction returns HfReferenceMismatch<State> on a
reference mismatch. It reports the expected and actual HF references and retains
the original AnyHfSolution<State>, recoverable with into_solution(). These
conversions transfer or borrow existing ownership; they do not clone scientific
data or allocate another result. The named methods delegate to the standard
traits. The HF wrapper keeps its explicit interface, including
occupied_orbitals(); existing HF callers need no migration.
ScfSolution<M, State> owns scientific output; ScfResult contains numerical
metrics. The public ScfMethod trait associates independent coefficient,
energy, occupation, summary and RetainedData types. It describes output rather
than an executable SCF algorithm. The implementing descriptor type identifies
the physical method separately from those representations. The generic occupations() accessor
borrows method-specific occupations, which need not be integer orbital counts.
retained_data() borrows scientific artifacts retained after execution; the
generic contract requires neither an HF summary nor AO ERIs.
Implementing this trait does not provide an SCF engine or a public solution
constructor: the library establishes the method-specific convergence state.
For HF, HfMethodDescriptor<R> identifies the compatible method, with an
HfCalculationResult summary and retained AO ERIs. Its ScfSolution
specialization exposes scf_result() to borrow metrics from the summary.
Only compatible converged HF wrappers implement Mp2Calculation; generic HF
output can be restored through Into or from_scf(). AnyHfSolution itself
does not imply that MP2 is available for every contained or future HF reference.
Supported converged HF implementations also guarantee final canonicalization;
this is an HF guarantee, rather than a universal requirement on every SCF
method.
The sealed HfReference contract associates a compatible HF method, coefficient
representation, orbital energies, and occupations. Generic code converts the
associated method into ResolvedHfMethod; conversion into the input selector
HfMethod is not required by the trait. RHF has one shared
coefficient matrix and energy vector with one doubly occupied spatial-orbital
count. UHF has separate alpha and beta coefficients, energies, and electron
counts, represented by Spin<T>. Read-only accessors expose these values;
energies are in Hartree, and each occupation count selects a prefix of its
coefficient columns. Cloning a solution shares retained scientific data. An
unconverged solution keeps diagnostic orbitals, while final canonical orbitals
are guaranteed only after convergence.
Initial guesses use the same reference markers through DensityGuess<R> and
OrbitalGuess<R>. Reference-specific Fock-like inputs contain one matrix for
Restricted and a Spin pair for Unrestricted, using the same HfReference
component contract as HfSolution. The zero startup sentinel is available for
both. Unperturbed guesses retain one core matrix for RHF or duplicate it for
UHF. Random and perturbed guesses generate one matrix for RHF or two ordered
alpha/beta matrices for UHF without constructing a discarded beta matrix;
the seeded alpha sequence is preserved across references.
Only converged solutions expose MP2. Method dispatch is exhaustive, so each
supported reference has an explicit correlation implementation. An MP2 error
retains the completed HF result for inspection or retry. See the
hf_solution example
and API tests
for executable workflows.
The complete offline example in crates/rustiq-core/examples/hf_solution.rs
is also included directly in the HfOutcome API documentation. Run it from the
repository root:
cargo run -p rustiq-chem-core --example hf_solution --no-default-features
It embeds the checked-in STO-3G basis and the H2 singlet and OH doublet geometries, with coordinates interpreted in Angstrom. It prints reference-specific occupied counts, total HF energies and MP2 correlation energies in Hartree. A deliberately invalid frozen-orbital count demonstrates error recovery: the example drops the original HF handle, extracts the retained output from the error using the standard conversion traits, and retries MP2 without rerunning HF. Unexpected failures propagate as errors. The example illustrates API ownership and error handling; the independent scientific comparisons remain separate verification procedures.
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, artifact inspect,
and artifact verify commands. run INPUT --reuse BUNDLE resolves the supplied
runfile’s geometry and basis as usual, then uses bundle compatibility to select
AO ERIs. run BUNDLE.rustiq reconstructs the archived resolved calculations
without the original inputs or local basis store. The Rust API can also reconstruct
a calculation from those scientific snapshots. These workflows start fresh HF
executions; HF solutions and SCF restart state are not persisted. 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.
Portable NPY ERI payloads stream directly into the final shared compact storage
through an exact-size iterator, avoiding a temporary full-size Vec<f64>.
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.
Coulomb integrals cache Boys function values by order. When the requested
maximum order is nonzero, positive arguments up to 20 use a positive-term series
to seed the highest order, followed by downward recurrence; larger arguments
retain the gamma-function seed. An order-zero cache uses the error-function
expression. This changes numerical evaluation rather than the integral
definition or screening policy. The unit tests in
boys.rs
compare the cache against independent quadrature, including the series boundary.
Run cargo test -p rustiq-chem-core math_utils::boys and the affected
PySCF comparisons after changing this path.
The eri_timings and mp2_timings benchmarks use Criterion and require
bench:
cargo bench --bench mp2_timings --features bench
cargo bench --bench eri_timings --features bench
cargo bench --bench eri_storage_allocation --features bench
cargo bench --bench eri_storage_memory --features bench
The MP2 benchmark compares the dense AO-to-MO transformation and correlation
energy evaluation with the production memory-blocked path on deterministic
synthetic RHF inputs. Each blocked case is constrained to process occupied
orbitals in at least two blocks, even when the requested memory budget could fit
one block. RUSTIQ_MP2_MEMORY sets an upper cap; each case may use a smaller
budget to force multiple blocks. AO dimensions must be at least 6. It checks that
both paths produce matching energies before timing
them, and records the selected block size, block count, workspace budget, and
estimated temporary workspace. Input and ERI construction remain outside the
measured iterations. These synthetic inputs benchmark the contraction code;
they are not molecular calculations or scientific accuracy validation.
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 eri_storage_allocation benchmark compares Vec-then-Arc construction with
the exact-size-iterator Arc initialization path for identical compact tensor
sizes. It measures storage allocation and initialization only, not ERI
evaluation. Compare the same Criterion benchmark and compiler settings on both
revisions. The Miri
workflow targets a sequential unit test for the shared in-place initialization
helper, checking its initialization safety independently of Rayon scheduling.
Run the same check locally with nightly Rust:
rustup +nightly component add miri rust-src
cargo +nightly miri setup
cargo +nightly miri test -p rustiq-chem-core --lib test_in_place_storage_initialization_miri
The eri_storage_memory benchmark uses a counting global allocator in a
separate executable to report peak live heap bytes attributable to each
construction. It includes requested allocation sizes, not allocator overhead
or process RSS. It compares the same Vec-then-Arc and in-place storage paths.
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 and the same benchmark workload. The multiblock MP2 workload has a
new Criterion identifier, so its first run establishes a new starting point;
do not compare it with the previous single-block mp2/blocked measurements.
Legacy timing results also 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 reference revision with the same workload, then compare from
the revision under test:
cargo bench --bench mp2_timings --features bench -- --save-baseline before
cargo bench --bench mp2_timings --features bench -- --baseline before
See the MP2 benchmark source and ERI benchmark source. Benchmarks provide performance measurements, not scientific validation.
Generate reproducible reports
From the repository root, the scientific report reuses the canonical PySCF reference cases and their absolute tolerances:
uv run --locked python tools/reference/report.py --output-dir target/scientific-report
It writes full precision results to validation.json and readable tables to
validation.md. In addition to the cases run by pytest tools/reference, it
includes the frozen-core MP2 variants exercised by those tests at 32 KiB and
512 MiB workspace budgets. Total HF energies and MP2 correlation energies are
reported separately. A case fails if either implementation does not converge,
an energy comparison exceeds its existing tolerance, or the UHF spin expectation
value misses its tolerance. Failed cases remain in the report, and the command
returns a nonzero status. The report records software versions, commit and
platform metadata so results can be compared across revisions.
Generate Criterion measurements and their report with:
cargo bench --features bench --bench eri_timings
cargo bench --features bench --bench mp2_timings
uv run --locked python tools/benchmarks/report.py
The report is written to target/performance-report/benchmarks.json and
benchmarks.md. To produce both reports on GitHub, open Actions → Scientific
and performance report → Run workflow on the selected branch or commit. The
workflow uploads rustiq-scientific-performance-reports; download that artifact
from the completed workflow run to inspect the Markdown and JSON files.
Criterion stores structured estimates in target/criterion; the benchmark
executables also write the case dimensions and configuration used by the report
generator there. The default runs include the small ERI cases and MP2 AO sizes
12, 24, and 48. To select a smaller local run or opt into the expensive ERI
cases, set RUSTIQ_BENCH_FILTER, RUSTIQ_MP2_SIZES, RUSTIQ_MP2_MEMORY, and
RUSTIQ_BENCH_HEAVY as described above. The report includes Criterion means
and confidence intervals. Its configured MP2 workspace is not measured peak
RSS, and synthetic MP2 cases do not model complete molecular calculations.
Results are machine-dependent; the on-demand GitHub Actions workflow starts
with one small ERI case and AO sizes 12 and 24. To run heavy ERI cases, select
Include the heavy ERI cases and choose an ERI filter that matches those cases.
The checkbox enables RUSTIQ_BENCH_HEAVY=1; it is disabled by default.
These reports provide numerical regression checks for selected cases. They do not establish general chemical accuracy; see the scientific scope for the limits of HF, MP2, and numerical agreement. Equal numeric convergence thresholds do not mean that RustiQ and PySCF use identical convergence tests.
Independent AO integral validation
The parameterized Cargo tests
integral_reference_tests::export_integral_validation::case_N compare
production overlap (S), kinetic (T), nuclear attraction (V), and
Hcore = T + V matrices with versioned PySCF 2.14.0 fixtures. It compares every
matrix entry and every unique unscreened electron-repulsion integral (ERI),
in chemists’ notation. No Python installation is needed for Cargo tests.
The cases are H2/STO-3G (2 AOs), H2O/STO-3G (7), H2O/6-31G (13), and
H2O/cc-pVDZ with spherical 5D (24) and Cartesian 6D (25) functions. The
Cartesian cc-pVDZ water case is also rotated by 0.37 radians around the
normalized (1, 2, 3) axis with RustiQ’s Geometry::rotate; its independently
generated PySCF reference uses the same Rodrigues rotation. This checks the
Cartesian integrals with coordinates spanning all three Cartesian axes.
All families use an absolute tolerance of 1e-10 in each family’s units, with no relative acceptance criterion. Measured maxima on these cases are below 9e-14; the threshold leaves margin for floating-point accumulation and platform differences in contracted Hermite/Boys evaluation while remaining below the 1e-8 scale that would require investigation. Relative errors are diagnostic only and are reported for reference magnitudes at least 1e-8. Reports include dimensions, counts, RMS and maximum absolute error, exceedance counts, and the five largest discrepancies with zero-based AO indices and full precision values. For S the units are dimensionless; T, V, Hcore, and ERIs are in atomic units of energy.
The fixtures are generated independently by PySCF/libcint from the same raw checked-in Basis Set Exchange (BSE) JSON exponents and contraction coefficients, not from RustiQ’s normalized primitives. PySCF interprets and normalizes those coefficients independently. This avoids differences in rounded packaged basis sets. Geometry is converted from the checked-in Angstrom XYZ files to Bohr using 0.529177210903 Angstrom/Bohr (CODATA 2018), then supplied explicitly in Bohr. The JSON metadata records source hashes, PySCF version, AO permutation, units, layout, and each numerical array hash. Cargo rejects changed source inputs or array contents; pytest also regenerates every reference array and checks it within 1e-13 absolute units. Regeneration never reads RustiQ integral values.
RustiQ retains atom, BSE shell, and contraction order; PySCF stably sorts shells by angular momentum. Within each p shell RustiQ uses z,y,x versus PySCF x,y,z. The real spherical d order and phases agree: xy, yz, (2zz−xx−yy), xz, (xx−yy), with normalized polynomial combinations. Cartesian order is reversed: RustiQ zz,yz,yy,xz,xy,xx versus PySCF xx,xy,xz,yy,yz,zz. The mapping is constructed from these conventions, never fitted to integral values. PySCF’s Cartesian d functions have radial normalization: multiply its xx,yy,zz functions by sqrt(5/(4π)) and xy,xz,yz by sqrt(15/(4π)) to obtain unit-normalized monomials. These factors follow from angular integrals of squared monomials, 4π/5 and 4π/15, respectively. The reference generator checks the resulting unit overlap diagonals. A separate analytic coefficient test compares the spherical d polynomials with PySCF’s Cartesian-to-spherical transformation, checking phases that the planar water geometry alone cannot distinguish. This positive diagonal scaling has condition number sqrt(3); there is no fitted rotation or phase adjustment. The Cartesian extension changes only the in-memory shell representation, preserving every source exponent and coefficient and leaving fixtures and production defaults unchanged. See the authoritative PySCF basis construction source and integral interface.
Reproduce the independent comparisons and verify the fixtures:
cargo test -p rustiq-chem-core --lib integral_reference_tests
nix develop .#mini-pyscf --command pytest tools/reference
# Equivalent non-Nix workflow:
uv run --locked pytest tools/reference
# Intentionally regenerate versioned NumPy arrays and provenance:
uv run --locked python tools/reference/integrals.py --regenerate
# Write the detailed integral-only machine-readable report:
uv run --locked python tools/reference/integrals.py --report target/integrals.json
NumPy writes individual .npy fixtures; Rust reads them directly
through the existing persistence readers backed by npyz. Matrices have
two-dimensional shapes and Fortran (column-major) storage. ERIs use lower triangular AO pairs i≥j, followed by lower
triangular pairs of pairs p≥q, with pair index i(i+1)/2+j. No full four-index
tensor is allocated. The scientific report above includes an independent AO
integral section and full precision JSON diagnostics. Harness failures are
reported as failures, not omitted.
Three forms of evidence remain distinct: independent integral comparisons
check agreement with libcint; internal eightfold compact reconstruction checks
validate storage symmetry; end-to-end HF/MP2 comparisons validate selected
calculations. The compact reconstruction check is algebraic and does not
independently recompute eight permutations. Existing Schwarz screening tests
remain separate; this accuracy test passes None to the production threshold
interface and does not change default screening. Successful checks establish
agreement only for these geometries, contractions, s/p functions, and spherical
and Cartesian d functions. They do not establish correctness for higher angular
momenta, extreme exponents, arbitrary geometries, or basis completeness.
Documentation checks
The manual uses mdBook, MathJax for equations, and
mdbook-mermaid for diagrams.
Nix is optional. Run the commands below from the repository root.
Build the offline manual
The complete documentation build and checks are:
nix build .#book
Open result/index.html. The derivation builds the book, bundles pinned
MathJax resources and Mermaid assets, tests supported Rust snippets, and checks
local links and HTML fragments. Its build runs without networking once Nix has
fetched its declared inputs.
Without Nix, install mdbook and mdbook-mermaid using Cargo or equivalent
packages, and provide Python 3.12 or later with pytest installed (see the
Python tooling setup):
cargo install mdbook --version 0.5.2 --locked
cargo install mdbook-mermaid --version 0.17.1 --locked
python tools/build-manual.py
mdbook test docs
pytest tools/test_book_links.py tools/test_release_smoke.py
python tools/check-book-links.py docs/book --config docs/book.toml --offline
git diff --check
Open docs/book/index.html. The builder downloads the pinned MathJax 2.7.9
npm archive, verifies its SHA-256 digest, installs Mermaid resources, and builds
the HTML. It replaces mdBook’s CDN loader with relative local MathJax paths,
using SVG equations so reading local files does not require web fonts.
MathJax’s license is preserved in mathjax/LICENSE in the output.
Use mdbook-mermaid 0.17.1 with mdBook 0.5: it fixes the theme button
identifiers used by the diagram initializer. The browser check also exercises
light and dark theme changes with networking disabled.
The local installation follows MathJax’s installation guidance.
To build with networking disabled, supply the already downloaded, matching MathJax 2.7.9 npm archive; the documentation tools must also be installed:
python tools/build-manual.py --mathjax-archive /path/to/mathjax-2.7.9.tgz
Both routes produce the same relocatable manual. Readers need a browser, but
no checkout, Python, Rust, mdBook, or network connection. External reference
links, repository links, and edit links still require networking.
Generated docs/book/, docs/mermaid.min.js, and docs/mermaid-init.js are
ignored by Git and must not be committed.
Preview while editing
The Nix rust and full shells include mdBook and mdbook-mermaid. For a live
preview, enter nix develop .#rust if using Nix, then run:
mdbook-mermaid install docs
mdbook serve docs --open
This direct mdBook preview uses its CDN MathJax loader. To inspect the offline
result, stop the server, rerun the offline builder above, and open the generated
index.html. Running mdbook build or mdbook serve directly regenerates the
unmodified CDN loader; it does not produce the distributable offline manual.
Release integration and coverage
The release and six-target rehearsal workflows build the Nix book once and
supply it as manual/html/ to every archive build. For a local dist build, first
prepare that directory:
nix build .#book
mkdir -p manual/html
cp -R result/. manual/html/
dist build --artifacts=local --target x86_64-unknown-linux-gnu
Use the target for the native operating system and architecture. The generated
manual/html/ directory is ignored by Git. The Nix package installs the same book
under share/doc/rustiq/manual/html and checks rustiq docs --print-path against its
installed index. Cargo builds and published crates do not bundle the book.
Verification coverage is explicit:
- The book build checks chapter structure, sample includes, and Mermaid assets.
- The link checker validates local links, assets, and HTML fragments. Its
--offlinemode also rejects remote HTML runtime resources; external reference links remain allowed. It does not execute JavaScript or fetch URLs. - Documentation CI also runs
tools/check-manual-browser.pyagainst the built book in Chromium with networking disabled, checking file navigation, styles, rendered SVG equations, and Mermaid diagrams. To reproduce, installplaywright==1.64.1and its Chromium browser in a separate Python environment, then runpython tools/check-manual-browser.py docs/book(orresult). mdbook testvalidates supported Rust blocks; this edition has no Rust snippets. It does not execute shell, TOML, XYZ, or Nickel examples.- CLI integration tests exercise relocated archive and Nix layouts, an incomplete manual, browser failures, explicit web selection, and Cargo’s online-only behavior. Archive rehearsals verify the packaged manual path and required MathJax/Mermaid assets after relocation.
- Main CI validates CLI samples, configuration, batches, and PySCF comparisons. Documentation CI does not repeat that scientific suite. The first-calculation chapter identifies its numerical reference, tolerance, and reproduction command.
The Documentation workflow validates pull requests and supports manual runs.
Publish documentation runs on pushes to develop and explicit release dispatches and deploys the validated book
to GitHub Pages. Set the repository’s Pages source to GitHub Actions.
PR builds have no Pages write permission.
Published versions
Pushes to develop publish the current book at /RustiQ/dev/. Release workflow dispatches at version tags
publish immutable snapshots at /RustiQ/vX.Y.Z/, for example
/RustiQ/v0.1.0-beta.1/; a retry fails if the stored
commit or generated content differs. The gh-pages branch stores the complete
assembled site, including earlier snapshots. GitHub Pages must remain configured
to deploy using GitHub Actions, not from that branch. Publication is
serialized, and pull requests only validate the book.
/RustiQ/beta/ points to the highest published beta and
/RustiQ/stable/ to the highest stable release; the stable alias appears only
when a stable release exists. The root redirects to the highest stable release, otherwise the highest prerelease, otherwise development. Release tags
must match the package version and point to an ancestor of main; publication
fetches main and rejects tags outside its history.
The root 404.html uses the same release preference as the homepage, with an
absolute site path independent of the missing URL’s nesting depth. Versioned 404 pages
retain their version-specific asset base. These changes apply only to the
published website; the offline manual remains relocatable.
Initial migration
Before enabling the first publication, choose one of these procedures. Keep
Pages configured for GitHub Actions in both cases. In the repository’s Actions tab, select Publish documentation and disable
the workflow using its menu; wait for any active run to finish before preparing
the branch so a run cannot migrate an incomplete seed. Re-enable it after
seeding. Re-enabling alone does not publish: the next push to develop or a valid
release dispatch triggers publication.
Existing populated gh-pages branch: inspect its root tree and confirm that
it contains the old published HTML paths, including pages removed from the
current book. If it does, leave those files in place and enable publication.
The first run inventories their HTML paths, replaces them with redirects to
the corresponding dev/ paths, removes old root assets, and records
"legacy_source": "existing-root" in versions.json. A removed development
page ultimately reaches the site-wide 404 fallback.
Fresh or empty gh-pages branch: previous Actions deployments do not
automatically populate this branch. To preserve their paths, obtain the complete
HTML tree from the last successful deployment’s retained Pages artifact or an
archived copy before migration. Extract the artifact so index.html and the
chapter directories are directly in a local directory, for example
/tmp/previous-manual. If the downloaded artifact is a ZIP containing
artifact.tar, unpack both layers:
mkdir -p /tmp/previous-pages-artifact /tmp/previous-manual
unzip /path/to/github-pages.zip -d /tmp/previous-pages-artifact
tar -xf /tmp/previous-pages-artifact/artifact.tar -C /tmp/previous-manual
test -f /tmp/previous-manual/index.html
Inspect the extracted paths and contents before proceeding. In a separate clone, seed the branch as follows:
git clone https://github.com/mveril/RustiQ.git /tmp/rustiq-pages-seed
cd /tmp/rustiq-pages-seed
git switch --orphan gh-pages
git rm -rf --ignore-unmatch .
cp -R /tmp/previous-manual/. .
git add -A
git commit -m "Seed previously published manual for migration"
git push origin gh-pages
Use this orphan procedure only when the remote branch does not exist. If an empty branch already exists, use the following in the separate clone instead of the orphan sequence:
git switch --track origin/gh-pages
cp -R /tmp/previous-manual/. .
git add -A
git commit -m "Seed previously published manual for migration"
git push origin gh-pages
Inspect the seeded tree before enabling publication; then follow
the populated-branch procedure above. Do not replace an already versioned site
or delete its versions.json or snapshots.
If no archive is available, publication can start from the fresh branch, but
only paths in the current book receive legacy redirects. The script emits a
warning and records "legacy_source": "current-book-only"; it cannot recover
removed historical paths. No live website is downloaded or scraped. The
legacy_redirects flag records completion of redirect generation, not proof
that all historical paths were available.
Migration runs once. Subsequent runs retain its provenance and legacy redirects, refresh the root 404 fallback, and leave existing release snapshots immutable. Identical release retries succeed; conflicting content or source commits fail before modifying the site.
/RustiQ/versions.json lists releases in descending SemVer order, their URLs,
channels and source commit IDs, along with the latest aliases and development URL. URLs in the index are relative to the site root.
The index is static and does not require an API. The offline book remains separate.
For a local assembly test, run python tools/publish-docs.py result SITE COMMIT --development, or replace --development with --version v0.1.0-beta.1.
COMMIT is the full source commit ID and SITE is a writable directory. For
example, the index contains entries of this form (the commit is abbreviated
here for readability):
{
"legacy_redirects": true,
"legacy_source": "existing-root",
"development": "dev/",
"latest_beta": "v0.1.0-beta.1",
"latest_stable": null,
"versions": [{"version": "v0.1.0-beta.1", "url": "v0.1.0-beta.1/", "channel": "beta", "commit": "..."}]
}
Repository rename
The current public Pages base remains https://mveril.github.io/RustiQ/.
After renaming the repository to mveril/rustiq, configure Pages to deploy via
GitHub Actions, update the documentation base URL and the site-specific 404
base, then publish and verify the new site and release links. GitHub repository
redirects do not guarantee redirects for the old Pages URL: arrange and verify
a separate redirect for the old Pages site before relying on existing links.
Previously published binary URLs cannot be changed.