Memory budget¶
Every run_job calculation runs through a pre-flight memory check
that (a) reports the estimated peak memory in the text output and (b)
aborts with an explanation if that estimate exceeds the machine’s
available RAM. This is a guardrail against the most common
catastrophic failure mode of a QC code, calculations that silently
thrash to disk and freeze the host.
What you’ll see in the .out file¶
Job: RKS / PBE basis=cc-pvdz
Atoms (bohr)
------------------------------------------------------
1 Z= 8 0.00000000 0.00000000 0.00000000
2 Z= 1 0.00000000 1.43000000 -0.98000000
3 Z= 1 0.00000000 -1.43000000 -0.98000000
charge=0 multiplicity=1 n_electrons=10
vibe-qc estimates this calculation will require ~0.13 GB of memory:
ERI tensor 0.00 GB
Fock + density + 1e 0.00 GB
DIIS history 0.00 GB
MO workspace 0.00 GB
DFT grid + chi 0.10 GB
Python runtime + NumPy overhead 0.10 GB
Available on this machine: 24.0 GB. Proceeding.
iter energy (Ha) dE ||[F,DS]|| DIIS
...
The headline figure already carries a 1.5x default safety headroom
over the sum of the per-category numbers. Set
VIBEQC_MEMORY_HEADROOM=2.0 (or another value >= 1.0) to tune the
factor for a site or scheduler wrapper.
When the estimate exceeds available RAM¶
vibe-qc estimates this calculation will require ~218.4 GB of memory:
ERI tensor 186.0 GB
...
Available on this machine: 7.2 GB. ABORTING.
InsufficientMemoryError: Set `options.memory_override = True` (or pass
`memory_override=True` to `run_job`) to proceed anyway. Consider a
smaller basis or, once shipped in v0.6+, density fitting / on-disk
scratch.
Overriding the check¶
Pass memory_override=True to run_job:
from vibeqc import Molecule, run_job
mol = Molecule.from_xyz("large.xyz")
run_job(
mol, basis="def2-tzvp", method="rhf",
output="huge",
memory_override=True, # accept the risk of swap / freeze
)
The output then reads Proceeding (override) instead of Proceeding
so anyone reading the log later knows what happened.
Estimators covered¶
Method |
Dominant cost |
Notes |
|---|---|---|
RHF / UHF |
Dense ERI tensor or direct-SCF shell-pair scratch |
Direct SCF charges about 1 KB per shell pair |
RKS / UKS |
HF baseline + DFT grid, weights, coordinates, libxc scratch |
meta-GGA adds tau buffers |
MP2 / UMP2 |
OVOV tensor or DF auxiliary integrals and OV workspace |
spin-channel storage for UMP2 |
CCSD / CCSD(T) |
T1/T2 amplitudes, D1/D2 intermediates, triples workspace |
DF auxiliary integrals are charged separately |
DLPNO-MP2 / DLPNO-CCSD(T) |
PAO/PNO domains, pair lists, auxiliary pair workspaces, triples domains |
conservative local-domain estimate |
CAS/CI/FCI |
CI or determinant vectors, RDMs, MO integral transforms |
exponential methods report their vector storage |
Periodic GDF / GPW / GAPW |
GDF Lpq factor cache or FFT-grid collocation/cache arrays |
wired through |
NEB uses a separate per-image-worker model and is intentionally not folded into the single-point estimator.
Reading the probe yourself¶
The cross-platform “how much memory is available right now” probe is exposed for scripting:
>>> import vibeqc
>>> vibeqc.available_memory_bytes() / 1024**3
24.3...
It tries psutil.virtual_memory().available
first (install with pip install psutil to get the highest-quality
number), then falls back to /proc/meminfo on Linux and os.sysconf
on macOS. Returns 0 if all probes fail, check_memory treats that
as “unknown” and silently proceeds rather than false-aborting on an
unsupported platform.
Writing your own estimator¶
If you call the low-level SCF drivers (run_rhf, run_rks, …)
directly instead of through run_job, you can invoke the estimator
yourself:
from vibeqc import estimate_memory, check_memory
est = estimate_memory(mol, basis, method="rhf", options=rhf_options)
print(est) # human-readable block
check_memory(est) # raises InsufficientMemoryError if over budget
# ... your own driver call ...
The estimator returns a
MemoryEstimate dataclass with a
by_category dict, so you can inspect exactly where the memory goes.