bmd-check is a small, deterministic observation and diagnostic layer for the Burton Materials Discovery Lab at Tel Aviv University. It helps researchers understand VASP calculations without replacing the software and knowledge sources that produced them.
bmd-check observes and diagnoses calculations. It can inspect:
- VASP inputs and results;
- SLURM state, accounting, resource use, and out-of-memory evidence;
- Custodian interventions;
- bmd-compute workflow and Git provenance;
- compact convergence trajectories; and
- applicable contextual knowledge supplied by bmd-store.
The default output is a concise student-facing diagnosis. Detailed evidence remains available for advanced users and reproducibility.
bmd-check requires Python 3.12 or newer. From a fresh clone:
git clone https://github.com/bmd-lab/bmd-check.git
cd bmd-check
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .On Windows PowerShell, activate the environment with:
.\.venv\Scripts\Activate.ps1For development, install the declared test dependency and run the suite:
python -m pip install -e ".[dev]"
python -m pytestNo bmd-compute checkout, bmd-store checkout, SSH connection, PowerSLURM access, or VASP installation is required to run the unit tests.
The tracked example configuration documents the supported resource fields. Copy it to a deployment-local location and edit the copy. The example is never used automatically for real execution.
The normal Linux location is:
~/.config/bmd-agent/resources.toml
On Windows, the normal location is:
%APPDATA%\bmd-agent\resources.toml
Set BMD_AGENT_RESOURCES to use a different file:
export BMD_AGENT_RESOURCES=/secure/local/path/resources.tomlDeployment configuration identifies resources; it does not define scientific workflow policy. The main fields are:
repositories: trusted bmd-compute and bmd-store checkout paths;capability_python: the Python executable for each checkout's own environment;ssh_host: a configured SSH alias for the observational cluster identity;allowed_remote_roots: absolute POSIX roots authorized for remote reads;deployment_profile: an optional shipped infrastructure reference profile;- timeout values for SSH, fixed remote commands, and scheduler accounting; and
access,protected, andlivedeclarations describing bmd-check policy.
Keep resources.toml local. Do not commit credentials, private keys, or
deployment-local configuration. SSH credentials belong in the user's SSH
configuration or agent, not in this repository or resources.toml.
The normal interface is deliberately simple:
bmd-check
bmd-check JOB_ID
bmd-check PATH- No target analyzes the current working directory.
- A bare positive decimal integer inspects that SLURM job and resolves its BMD bmd-compute run when producer evidence permits.
- Any other existing filesystem path analyzes that calculation or workflow.
bmd-check is the canonical command. The bmd-agent command remains a fully
supported compatibility alias for the same program. The Python distribution
name remains bmd-agent, and the import package remains bmd_agent.
Examples:
cd /path/to/calculation
bmd-check
bmd-check 21853598
bmd-check ./copied-calculationThe reported status is an evidence claim about the whole calculation:
COMPLETED: every declared workflow stage has positive convergence evidence (electronic, plus ionic for relaxations) and VASP normal termination or a successful scheduler exit. SLURMCOMPLETED 0:0alone is never enough.INCOMPLETE: execution ended, but a required stage is missing, did not terminate normally, or did not meet its convergence criteria.FAILED: the scheduler reports an unsuccessful state or a nonzero exit.UNKNOWN: the available evidence cannot establish completion. Missing evidence, or the absence of reported errors, is not treated as convergence.PENDING,RUNNING, andPRE_RUNdescribe queue and execution state.
The same workflow-level status is reported whether bmd-check is run from the workflow root or from any stage directory.
Use --verbose for detailed evidence, provenance, parser limitations, and
scheduler accounting. On job inspection, use --profile for
developer-oriented acquisition and performance telemetry. Additional
expert/debug subcommands remain available for compatibility and testing, but
are not required for normal use.
bmd-check remains independently callable on a cluster with these same commands. Its Python interfaces may also be called by bmd-compute in the future, but this repository does not implement that integration.
bmd-check assess electronic-character RUN_ROOT [--stage-index N] [--format json]This read-only assessment reports whether one completed VASP stage supports
classifying the calculated system as metallic or nonmetallic; otherwise it
reports uncertain. A workflow with several declared stages requires
--stage-index. It reads only that stage's vasprun.xml and the same local
completion evidence used by assess completion; it contacts no scheduler and
writes nothing.
The method (electronic_character, method version 1.0.0-c2) counts
electrons per spin channel and examines band dispersion relative to the Fermi
level:
- a clearly fractionally filled channel with a band clearly crossing the Fermi level, or a clearly integer-filled channel whose valence and conduction bands overlap across it, is metallic; one such channel in a collinear spin-polarized calculation is enough (a half-metal is metallic);
- every channel clearly integer-filled, with no band edge passing the Fermi
level by more than 0.01 eV and a gap of at least 0.1 eV that is also at least
four times
SIGMAfor smearing methods, is nonmetallic; - evidence between these criteria (near-integer filling, shallow Fermi-level
crossings, small band overlaps) is
uncertain; - noncollinear and spin-orbit calculations are treated as one spinor channel.
Sampling density is accepted only from a k-point mesh that VASP generated and
recorded in vasprun.xml (Gamma, Monkhorst-Pack or Auto), and only when
every weighted k-point lies on that mesh and the weights are integer symmetry
multiplicities of it. Explicit k-point lists never establish a mesh. Every
numerical input is validated; NaN, infinite or malformed values give
uncertain with INVALID_NUMERICAL_EVIDENCE. A recorded NELECT that is not
an integer (beyond 1e-6) is a deliberately fractional electron count and gives
uncertain; occupations must reproduce NELECT within 0.005 electrons.
NBANDS must be recorded and must equal the number of bands present in every
spin channel, otherwise the result is uncertain.
Published band edges, gaps and gap types all come from one named evidence set
(band_edge_evidence), which includes zero-weight k-points when present. Band
extrema within 1 meV are treated as degenerate and counted; the gap is direct
when one k-point holds both extrema, indirect when the smallest same-k gap
is at least 10 meV larger, and undetermined in between. Two k-points are the
same when their reduced coordinates differ by at most 1e-4 on every axis after
removing reciprocal-lattice vectors. A chain of such matches that joins points
further apart than that is ambiguous and sets kpoint_equivalence_ambiguous.
If it could set the smallest direct gap, min_direct_gap_ev is withheld
(null) and only min_direct_gap_lower_bound_ev is reported; direct then
requires an unambiguous k-point, indirect requires the lower bound to clear
10 meV, and anything else is undetermined.
Fractional occupations caused by smearing never establish metallicity, and a
small gap never establishes nonmetallicity. Unconverged or unfinished stages,
truncated or missing vasprun.xml, a missing Fermi level, a single k-point,
meshes coarser than 0.5 1/Angstrom, unverified meshes, band paths,
non-self-consistent runs without a verified mesh, too few bands,
contradictory occupations, fixed-occupation runs and many-body methods all
give uncertain. Every threshold is listed in the JSON output under
thresholds; they are provisional tolerances, not validated physical
boundaries.
The JSON contract (bmd_check.electronic_character_assessment, schema version
- contains the classification, assessment status, structured reason codes,
per-channel band-edge evidence, k-point and spin information, provenance and
limitations. It contains no eigenvalue arrays, POTCAR data or absolute paths.
bmd-check does not choose
ISMEAR,SIGMAor any other VASP setting; any mapping from this classification to methodology belongs to bmd-compute.
A producer that holds one completed stage in a directory of its own can call
bmd_agent.resources.electronic_character.assess_stage_directory(directory, stage_index=..., stage_type=..., theory=...). It reads only that directory
(vasprun.xml, and OUTCAR and OSZICAR for completion and convergence),
never discovers workflow records in parent directories, and returns the same
C1/C2 verdict with scope stage_directory. Unusable evidence gives uncertain;
only an invalid stage_index raises.
For bmd-compute runs, bmd-check reads two bmd-compute-owned records: the Prepare-time
submission specification submission.json (bmd_compute.submission) and the
run-resolution record job_<JOB_ID>.json (bmd_compute.job_record).
bmd-compute defines both contracts. bmd-check reads version 1 strictly, reads older
records without a schema as legacy unversioned records and says so, reports
an unsupported future version as unsupported rather than guessing, and reports
malformed records as invalid. Records written before 2026-08-11 lack
flow_spec.workflow_spec and are reported as unsupported legacy records;
stages are not inferred from older fields. Status fields in these records are
never used for execution state: SLURM accounting and VASP artifacts decide
that.
bmd-check does not intentionally modify calculations, submit or cancel jobs, restart calculations, alter scientific inputs, delete calculation files, or extract Custodian error archives. It does not read POTCAR contents.
In particular, bmd-check does not provide commands to edit INCAR, KPOINTS, or
POSCAR, and it does not expose arbitrary user-controlled remote shell
execution. Remote scheduler and file operations are fixed-purpose observation
interfaces.
Safe deployment relies on all three of the following:
- bmd-check's read-only, action-free implementation;
- correctly configured
allowed_remote_roots; and - appropriately restricted OS/SSH credentials and filesystem permissions.
SSH observation runs with BatchMode=yes, so missing keys or unknown hosts
fail immediately instead of prompting. When bmd-check runs on the POSIX cluster it
observes, ssh_host = "local" selects the local transport: the same typed
observational operations, path authorization and size limits apply, but they
run as argument vectors under the invoking user's identity without SSH. That
user's filesystem permissions are then the operating-system boundary,
including for symlinks beneath allowed roots. Local mode is not available on
Windows.
Remote path authorization is lexical. It rejects paths outside configured
roots after POSIX normalization, but it is not a filesystem sandbox and does
not resolve every remote symlink before access. A symlink beneath an allowed
root may point outside that root if the SSH identity can follow it. Likewise,
access = "read_only" is a bmd-check policy declaration; it does not remove write
permission from the operating-system account. Deploy bmd-check with a
least-privileged observational identity and suitable server-side permissions.
bmd-check invokes only fixed producer modules from explicitly configured bmd-compute and bmd-store checkouts, using each checkout's configured Python executable. Those checkouts are trusted code dependencies: their module code executes with the bmd-check caller's OS privileges. Do not configure arbitrary third-party checkouts as producers.
See SECURITY.md for the complete security model.
src/bmd_agent/deployment_profiles/power.toml
is a versioned record of expected and observed POWER infrastructure facts. It
supports reproducibility and compatibility checks; its paths do not grant
access.
Deployment-local resources.toml remains authoritative for the SSH alias,
allowed roots, operational timeouts, and access policy. The current VM-to-POWER
SSH route is a supported deployment, not a promise about the final production
architecture.
bmd-check reads bmd-compute's versioned records; it does not recompute them.
runtime_environment.json(bmd_compute.runtime_environmentv1), when a run'ssubmission.jsondeclares one: detailed output reports bmd-compute's own verdict (Runtime parity: PASSEDorFAILEDwith bmd-compute's reasons), the prepared and runtime versions of the parity-critical packages, supporting packages and the effective atomate2 settings. Runs prepared before this record existed showRuntime parity: not recordedand keep the runner-log evidence. A declared record that cannot be read is reported as unavailable, never as a pass.provenance.execution.automatic_treatments: for BMD-managed Desired Output workflows, which automatic treatments bmd-compute applied (including the frozen automatic DFT+U record). bmd-check never infers automatic treatments from stage modifiers; bmd-compute does not separately record Custom workflows.- The capability payload's
stage_modifier_supportis shown bybmd-check computeexactly as bmd-compute declares it.
Unsupported major versions of these records (and of the submission
provenance block) are reported as unsupported rather than read under v1
assumptions.
bmd-check preserves the responsibilities of independently version-controlled BMD projects:
- bmd-compute owns what its VASP workflows execute.
- bmd-store owns curated supporting scientific data and contextual evidence.
- bmd-help owns human-oriented tutorials and explanations.
- bmd-check connects evidence so researchers can understand and diagnose a calculation.
Implementation is not scientific validation, a completed job is not methodology adoption, and bmd-check observations do not automatically become BMD standards. Human scientific review and governance remain separate.
The architecture is described in ARCHITECTURE.md. Graduate students can contribute using the lightweight process in CONTRIBUTING.md.
The package reserves an offline, versioned corpus of preserved VASP Wiki pages
in src/bmd_agent/reference_corpus/vasp_wiki/. bmd-check never fetches the
VASP Wiki at runtime, so a change to the live wiki cannot change an installed
release. Corpus updates are explicit maintainer operations with
tools/vasp_reference/fetch_corpus.py,
reviewed through normal pull requests.
Release 1.0.0 holds the complete public VASP Wiki documentation as of 2026-10-20: 1,047 main-namespace pages (one further page is excluded under the archival character policy), with revision pinning, SHA-256 verification and recorded GFDL 1.2 licensing. Preserved pages are third-party material; see THIRD_PARTY_NOTICES.md.
When bmd-check (or bmd-check PATH) finds a significant problem in a
calculation that has stopped, it consults the frozen corpus and adds a short
"VASP manual guidance" section:
VASP manual guidance
--------------------
Observed: The calculation: the final completed electronic cycle did not
reach EDIFF = 1e-06 after using all NELM = 8 electronic iterations.
VASP Wiki (Troubleshooting electronic convergence): "There can be many
reasons why convergence to the electronic ground state fails. ..."
Next step: Read the cited guidance on electronic convergence; BMD Check has
not established the cause.
- Observed is BMD Check's own finding, restated from its existing assessments (electronic and ionic convergence progress, memory evidence, VASP log messages, workflow stage completion and, for completed calculations, the electronic-character assessment). The manual never changes those findings or any C1/C2 verdict.
- VASP Wiki is a verbatim excerpt (markup simplified) of the
best-matching passage, retrieved from all 1,047 pages with a query built
from the evidence: the settings and criteria the finding involves, method
settings such as
LHFCALC,LDAU,ISPINorMETAGGA, and distinctive tokens of error messages. In a multistage workflow each finding is read with the executed INCAR of its own stage only; settings are never taken from another stage, and are omitted when that stage's INCAR is not available. Passages whose own text is about a method that stage does not use (hybrid functionals, DFT+U, GW, machine-learned force fields, phonons, magnetism, ...) are excluded, in both the concise and the verbose output; general guidance that only mentions such a method in passing is kept. - Next step never prescribes a value. A setting is named only when it is set in this calculation and named in the cited passage.
--verbose lists every finding with up to three citations: page title,
section, pinned revision, permanent URL, corpus version and the quoted
passage. If the corpus is missing or fails its integrity checks, the report
says that references are unavailable and is otherwise unchanged. Successful
calculations, running jobs and jobs inspected by SLURM job ID are unaffected.
bmd-check's repository-owned source and documentation are released under the MIT License. This license does not grant rights to VASP, POTCAR/PAW datasets, preserved third-party reference material, or third-party dependencies; those remain subject to their own licenses and access terms (see THIRD_PARTY_NOTICES.md).