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
Available on this machine: 24.0 GB. Proceeding.
iter energy (Ha) dE ||[F,DS]|| DIIS
...
The headline figure already carries a 20 % safety headroom over the
sum of the per-category numbers (configurable via
MemoryEstimate.headroom_factor).
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 4-index ERI tensor: \(n^4 \cdot 8\) bytes |
64 GB at n=300 |
RKS / UKS |
RHF baseline + DFT grid + χ matrices |
\(\sim\) \(n_\text{pts} \cdot n \cdot 8\) for χ |
MP2 |
OVOV MO-basis tensor |
\(n_\text{occ}^2 \cdot n_\text{vir}^2 \cdot 8\) |
UMP2 |
Three spin-channel OVOV tensors |
\(\alpha\alpha + \beta\beta + \alpha\beta\) |
Periodic and post-HF methods beyond MP2 are currently not covered by the estimator; they ship estimators with the corresponding drivers (v0.8+).
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.