Date: 2026-05-09. Source: web research via WebSearch + WebFetch (see Sources section at the end). Goal — align field names, enum values, and required/optional status of TM-Spec v0.2 with mature domain standards (2025-2026) so that downstream NOMAD upload / OPTIMADE query / QCSchema interop work without ad-hoc mapping.
Notation:
[FACT] — verified from first-party spec.[CLAIM] — stated in paper/wiki, not verified in source code.[NOT_VERIFIED] — WebFetch could not retrieve access; manual check needed later.runschema plugin.Run → Method → DFT → XCFunctional confirmed
via architectural descriptions in FAIRmat tutorial, but exact field names of the plugin
could not be retrieved from the GitHub UI via WebFetch.EntryArchive.section_run.section_method.section_XC_functional
(legacy) → Run.method.dft.xc_functional (current plugin) [CLAIM].GGA_X_PBE, GGA_C_PBE,
HYB_GGA_XC_HSE06, MGGA_X_SCAN. One functional = split into _X (exchange)
_C (correlation) + optional _XC.Run.program.name — string (“VASP”, “QuantumESPRESSO”, “CP2K”) [CLAIM].Run.program.version — string (“7.3.1”) [CLAIM].Run.method.electronic_structure_method — enum: DFT, DFT+U, G0W0,
MP2, CCSD(T), tight_binding, MM, ML [CLAIM].Run.method.dft.xc_functional — list of LibXC IDs.Run.method.basis_set — enum: plane_waves, gaussians, numeric_AOs,
mixed.Run.method.k_mesh.grid — [Nx, Ny, Nz].Run.method.k_mesh.offset — [fx, fy, fz].Run.method.smearing.kind — enum: gaussian, fermi, methfessel-paxton,
marzari-vanderbilt, tetrahedra.Run.method.smearing.width — float, units Joule (NOMAD SI internal).GGA_X_PBE + GGA_C_PBE for PBE,
HYB_GGA_XC_HSE06 for HSE06, MGGA_X_SCAN + MGGA_C_SCAN for SCAN.Method.vdw_method: D2, D3,
D3-BJ, TS, MBD, XDM [CLAIM].Dudarev (single Ueff) or Liechtenstein (U+J).| TM-Spec field | NOMAD recommends | Decision |
|—|—|—|
| level.xc: PBE+D3(BJ) | split into: xc_functional: ["GGA_X_PBE", "GGA_C_PBE"] + vdw_method: D3-BJ | adopt hybrid: keep xc: PBE+D3(BJ) for human-readable, add xc_libxc: [GGA_X_PBE, GGA_C_PBE] + vdw: D3-BJ for machine mapping |
| level.smearing.kind: Marzari-Vanderbilt | marzari-vanderbilt (lowercase, hyphen) | adopt lowercase enum |
| level.smearing.width_Ry | width in Joule | keep eV/Ry for human; add width_J when exporting to NOMAD |
| level.basis.kind: PW | plane_waves | adopt plane_waves as primary, PW as alias |
| code.name: QuantumESPRESSO | Run.program.name | adopt field path, value match |
| hubbard.Fe-3d.formulation: Dudarev | Method.dft.dft_plus_u.formulation: Dudarev | adopt capitalisation (Dudarev/Liechtenstein) |
MUST, SHOULD, MAY (via
x-optimade-requirements in JSON).id — string [MUST].type: "structures" — string [MUST].elements — list of element symbols, alphabetical [SHOULD].nelements — int [SHOULD].elements_ratios — list of floats, sum=1 [SHOULD].chemical_formula_descriptive — human-readable string [SHOULD].chemical_formula_reduced — strict alphabetical reduced [MUST in v1.3].chemical_formula_anonymous — A1B2 notation [SHOULD].chemical_formula_hill — C-first then H, then alphabetical [MAY].lattice_vectors — [[ax,ay,az],[bx,by,bz],[cx,cy,cz]] Å [SHOULD,
REQUIRED if response_fields not specified].cartesian_site_positions — list [[x,y,z], ...] Å [REQUIRED if no fields].nsites — int [REQUIRED if no fields].species_at_sites — list of strings (species names) [REQUIRED].species — list of objects with name, chemical_symbols, concentration,
optional mass, attached, nattached.dimension_types — [0|1, 0|1, 0|1] [OPTIONAL].nperiodic_dimensions — int 0..3 [OPTIONAL].last_modified — ISO timestamp [SHOULD].structure_features — enum list (see below).structure_features: disorder, implicit_atoms, site_attachments,
assemblies. Empty list [] means “ordered, fully described”.species.chemical_symbols — periodic table symbols + "X" (unknown) +
"vacancy".dimension_types — each of the 3 elements is 0 (non-periodic) or 1 (periodic).| TM-Spec field | OPTIMADE | Decision |
|—|—|—|
| structure.formula: Fe16S16 | chemical_formula_descriptive: "Fe16S16" + chemical_formula_reduced: "FeS" + chemical_formula_anonymous: "AB" | adopt — add three formula fields on export |
| structure.cell.a / .c / .gamma | lattice_vectors: [[a,0,0],[0,a,0],...] Cartesian Å | keep human-readable a/b/c/α/β/γ; add computed lattice_vectors |
| structure.pbc: [true,true,true] | dimension_types: [1,1,1] + nperiodic_dimensions: 3 | adopt both forms (boolean primary, ints for OPTIMADE export) |
| structure.wyckoff: {Fe@2a: [0,0,0]} | cartesian_site_positions + species_at_sites (no explicit Wyckoff) | keep Wyckoff for human; expand into species/positions on export |
| kind: NEBCalculation | OPTIMADE has only structures/references/files/calculations/trajectories (draft) | note: TM-Spec NEB is not covered by OPTIMADE 1.3; requires trajectories extension v1.4+ |
qcschema/data/v2/).qcelemental.schema_name: qcschema_molecule):
symbols — list of element symbols (Title case).geometry — flat list [x1,y1,z1,x2,...] in Bohr (a0) [FACT — units].atomic_numbers, mass_numbers, masses, atom_labels.molecular_charge (default 0.0), molecular_multiplicity (default 1).connectivity — list of [atom_i, atom_j, bond_order].fragments, fragment_charges, fragment_multiplicities.fix_com, fix_orientation, fix_symmetry.provenance — object (creator, version, routine).extras — free-form dict.schema_name: qcschema_input):
model: { method: "PBE", basis: "def2-svp" } — XC and basis in one object.driver — enum.keywords — code-specific dict.molecule — Molecule object.schema_name: qcschema_output):
properties: AtomicResultProperties (energies, dipole, etc.).return_result — driver-dependent (scalar / array / object).success: bool, error: ComputeError | None.wavefunction: WavefunctionProperties | None.final_molecule — Molecule.trajectory — list of AtomicResult (per step).energies — list of floats.driver: energy, gradient, hessian, properties.schema_version: 1 or 2.schema_name: qcschema_molecule, qcschema_input, qcschema_output,
qcschema_optimization_input, qcschema_optimization_output.| TM-Spec field | QCSchema | Decision |
|—|—|—|
| level.xc: PBE+D3(BJ) | model.method: "PBE-D3BJ" (single string) | note: QCSchema is not strict about vdW; multiple encodings exist (PBE-D3, PBE+D3BJ). Adopt model.method as human string; separate model.dispersion: D3BJ in extras |
| level.basis: { kind: PW, cutoff_Ry: 80 } | model.basis: "PW" (string) — no PW deep specs | mismatch: QCSchema is biased toward Gaussian basis sets. Keep TM-Spec rich basis block; on export → model.basis: "PW-80Ry" string |
| structure.cell (Å) | Molecule.geometry in Bohr | note: unit conversion required on export (1 Å = 1.8897 a0) |
| kind: NEBCalculation | no equivalent — QCSchema has only OptimizationResult / TorsionDriveResult | mismatch: TM-Spec NEB requires a custom QCSchema-like extension |
| results.Ea_forward_eV | properties.return_energy in Hartree | note: unit conversion (1 eV = 0.0367 Ha) |
_atom_site_moment.label — string, refers to _atom_site.label._atom_site_moment.crystalaxis_x / _y / _z — float, μ_B units,
components along unit cell axes._atom_site_moment.Cartn — moment in orthogonal Cartesian (x‖a, z‖c*)._atom_site_moment.magnitude — |
m | in μ_B. |
_atom_site_moment.symmform — symmetry constraint form._space_group_magn.name_BNS / _OG — Belov-Neronova-Smirnova (BNS) or
Opechowski-Guccione (OG) magnetic space group notation._space_group_magn.number_BNS — int (e.g., 62.448)._parent_space_group.name_H-M_alt — parent crystallographic SG._parent_space_group.transform_Pp_abc — parent → magnetic transformation._parent_propagation_vector.kxkykz — [1/2, 1/2, 0] or string format._atom_site_moment_modulation.* — for incommensurate modulated structures.BNS (recommended) or OG.commensurate or incommensurate._space_group_magn.name_BNS: "P_b 4'/n m m'" (mackinawite-like).| TM-Spec field | magCIF | Decision |
|—|—|—|
| magnetic.state: AFM-G | no such enum. Described via BNS group + magmoms | keep TM-Spec abbreviation (AFM-G/A/C, FM, ferri, NM) — convenient shortcut. ADD optional magnetic.bns_group: "..." for magCIF export |
| magnetic.collinear: true | implicit — moment vectors have only 1 non-zero component | keep boolean; verify collinearity on export |
| magnetic.propagation_vector: [0,0,0] | _parent_propagation_vector.kxkykz: "0 0 0" | adopt — our format is already close |
| magnetic.magmoms_uB.Fe[top]: +3.5 | _atom_site_moment.crystalaxis_z: 3.5 (per-atom) | expand on export: one moment entry per Fe in the asymmetric unit, with label |
| magnetic.surrogate_warning | no equivalent in magCIF | keep — this is our original semantics for the PBE PM/itinerant proxy |
+683 prototypes → 1783 total,
standardized label protocol.Format: <stoichiometry>_<Pearson>_<SGnum>_<Wyckoff_per_element>[-<index>]
Components:
_.-NNN suffix — index if multiple structures share the same label.Examples decoded (verified):
A_cF4_225_a-001 = Cu (FCC, SG 225 Fm-3m, single Wyckoff 4a).AB_cF8_225_a_b-001 = NaCl.AB_tP4_129_a_c = mackinawite-like (tetragonal P4/nmm).AB2C4D_oP32_34_ab_abc_4c_c-001 = K2AgSbS4.a (triclinic), m (monoclinic), o (orthorhombic),
t (tetragonal), h (hexagonal/trigonal/rhombohedral), c (cubic).P (primitive), I (body-centered), F (face-centered),
R (rhombohedral), A/B/C (single-face-centered).| TM-Spec field | AFLOW | Decision |
|—|—|—|
| structure.prototype: AB_tP4_129_a_c | format match | adopt fully — our draft is already correct |
| structure.space_group: { number: 129, symbol: P4/nmm } | redundant with prototype | keep SG for human readability, prototype for machine matching |
| Wyckoff Fe@2a: [0,0,0] | AFLOW does not include coordinates in the label, only letters | keep our expanded Wyckoff format (coordinates + letter) |
Node:
uuid — UUID4 string.pk — int (primary key in local DB).node_type — string class path.process_type — string (for ProcessNodes).label — short human label.description — long description.ctime / mtime — created/modified timestamps.attributes — dict[str, Any] (typed attributes).extras — dict (mutable user metadata).repository_metadata / repository_content — file repository (base64).ProcessNode adds:
process_state — enum: created, running, waiting, finished, excepted, killed.exit_status — int |
None. |
exit_message — string |
None. |
CalcJobNode adds:
state (CALC_JOB_STATE_KEY).remote_workdir.retrieve_list.StructureData (Data subclass):
cell — 3×3 list.pbc — [bool, bool, bool].kinds — list of Kind (name, symbols, weights, mass).sites — list of Site (kind_name, position).[FACT] AiiDA aiida.common.links.LinkType:
INPUT_CALC — Data → CalculationNode.INPUT_WORK — Data → WorkflowNode.CREATE — CalculationNode → Data (output of a calc).RETURN — WorkflowNode → Data (output of a workflow).CALL_CALC — WorkflowNode → CalculationNode (workflow called calc).CALL_WORK — WorkflowNode → WorkflowNode (sub-workflow).| TM-Spec field | AiiDA | Decision |
|—|—|—|
| provenance.parents: [tm.mack.vfe.hint.smoke@2026-05-03] | edges via INPUT_CALC/INPUT_WORK + uuid links | keep human-readable parent IDs (our deliberate design choice); export mapping parent_id → uuid via aiida lookup |
| provenance.author: igor@exopoiesis.space | Node.user.email | adopt field path |
| provenance.compute.cost_usd / walltime_h | no native fields — stored in attributes or extras | keep our fields; export → extras.tm_compute |
| provenance.hash.inputs/outputs sha256 | AiiDA hashes inputs automatically in attributes._aiida_hash | additionally adopt on export |
| id: tm.<system>.<setup>.<method>.<date> | Node.label (string) + UUID | keep — id → label, UUID generated on export |
| TM-Spec links by human-readable parent IDs | LinkType enum | adopt enum on serialization: kind: NEBCalculation parent type → INPUT_WORK or CALL_CALC |
[name]: reactants -> products; rate_law.J0: A -> B; k1*A - k2*B or J0: A <-> B; ....J: 2A + B -> C; k*A^2*B.k1 = 0.1; (after reactions).A = 1.0;.compartment cell = 1.0;.model name() ... end.:= expr; rate rules: '.k*A (mass action), Vm*S/(Km+S) (MM), Vmax*S^n/(Km^n + S^n) (Hill).| TM-Spec field | Antimony | Decision |
|—|—|—|
| reactions[].rule: "H_aq^+ + Fe_Fe^× → (H–Fe)_Fe^×" | R1: H_aq + Fe_Fe -> H_Fe; k1*H_aq*Fe_free (no Unicode arrows, no Kröger-Vink superscripts) | mismatch: Antimony — ASCII identifiers only. Hybrid: keep human-readable Unicode + Kröger-Vink in TM-Spec; on export → ASCII aliases (e.g. H_aq → H_aq, (H-Fe)_Fe^× → H_Fe_x) |
| reactions[].rate: "k1 * [H+] * θ_Fe_free" | k1*H_aq*theta_Fe_free | adopt rate-law string; mapping [X] → X, θ → theta_ |
| reactions[].params.k1: { value: 1e-4, units: M^-1·s^-1 } | k1 = 1e-4; (units in comment) | keep our rich format; on export → comment // units: M^-1 s^-1 |
| reactions[].id: R1 | R1: reaction label | adopt |
| reactions[].Ea_eV: 0.043 | absent — Antimony rate-law does not expect activation energy | keep for scientific value; derive k via Arrhenius on compilation |
temp (or temperature, -t) — °C.pressure (or press, -pr) — atm.pH — float, optionally charge (charge balance flag).pe — float (negative log of activity of e-).redox — couple, e.g. O(-2)/O(0) or S(6)/S(-2).units — concentration unit (see enums).density (or dens, -d) — kg/L, may be calculate.-isotope — isotope ratios.-water — kg of water.<element> [valence] <conc> [units] [as formula | gfw value] [redox_couple] [charge|phase_name].units allowed values:
mol/L, mmol/L, umol/L, g/L, mg/L, ug/L.mol/kgs, mmol/kgs, ppm, ppb, ppt, g/kgs, mg/kgs.mol/kgw, mmol/kgw (default), umol/kgw, g/kgw, mg/kgw.charge flag — applied to one ion for charge balance.phase_name — for saturation-driven concentration (e.g. Calcite SI 0.0).| TM-Spec field | PHREEQC | Decision |
|—|—|—|
| environment.composition_molal: { Fe(2): 1e-3, S(-2): 5e-4 } | Fe(2) 1.0e-3 mol/kgw | adopt PHREEQC element(valence) notation verbatim — our format is already close |
| environment.T: 363.15 K | temp 90 (°C) | mismatch: PHREEQC uses °C. Decision: keep K as primary, add computed temp_C on export |
| environment.pH: 6.0 | match | adopt |
| environment.redox.Eh: -0.40 V_SHE | pe (dimensionless) — no direct Eh | note: convert Eh→pe = Eh/(0.05916·T_factor). Keep Eh; auto-derive pe. |
| environment.database: phreeqc/llnl.dat | DATABASE phreeqc.dat keyword | adopt path → DATABASE keyword |
| environment.saturation_targets: {mackinawite: equilibrium} | EQUILIBRIUM_PHASES block | keep our short dict; expand into EQUILIBRIUM_PHASES on export |
builder_meta — software versions (emmet-core, pymatgen).nsites, elements, nelements, composition, composition_reduced,
formula_pretty, formula_anonymous, chemsys, volume, density,
density_atomic (StructureMetadata mixin).symmetry — SymmetryDoc (crystal_system, symbol, number, point_group, …).tags — list of strings.dir_name — calculation directory.state — completion status.calcs_reversed — list of CalculationDoc (per step).structure — final pymatgen Structure (serialized).task_type — string (“Structure Optimization”, “NEB”, “Static”).task_id, task_label.run_type — XC functional category (PBE, PBESol, SCAN, R2SCAN, HSE06).calc_type — combined f"{run_type} {task_type}".orig_inputs — original user inputs.input — InputDoc: structure, parameters (INCAR), pseudo_potentials,
potcar_spec, xc_override, is_lasph, is_hubbard, magnetic_moments.output — OutputDoc: structure, energy, energy_per_atom, forces, stress,
bandgap, density.custodian — corrections applied.run_stats — runtime/memory.run_type: PBE, PBESol, SCAN, R2SCAN, HSE06, PBE+U, PBESol+U, …
(VASP-biased — mostly via pseudopotential + INCAR introspection).task_type: “Structure Optimization”, “Static”, “NEB”, “Phonon”, “GW”,
“Frequency Dependent Dielectric”, …state: “successful”, “unsuccessful”, “error”.| TM-Spec field | emmet-core | Decision |
|—|—|—|
| results.Ea_forward_eV: { value: 0.043, ci95: [...] } | no native CI — output.energy is a plain float | keep our rich format; on export → output.energy: 0.043 + extras.ci95: [...] |
| results.status: PASS / PRELIMINARY / FAIL / RETRACTED | state: successful/unsuccessful/error | partial mapping: PASS→successful, FAIL→unsuccessful, RETRACTED→error, PRELIMINARY→no equivalent. Keep our enum. |
| results.paper_quotable: bool | no equivalent | keep — our original semantics |
| results.validated_by: [chemist@opus, physicist@opus] | no equivalent | keep — our original semantics (optionally → extras.validators) |
| calculation.code.name: QuantumESPRESSO | builder_meta.pymatgen_version + parser-implicit | mismatch: emmet/atomate2 is VASP-only. Note: TM-Spec extension to non-VASP codes adds code.* on top of the emmet schema. |
| task_type: NEB | match for NEB | adopt when mapping kind: NEBCalculation → task_type: NEB |
structure, site, multiplicity, oxi_state,
equivalent_sites, symprec, angle_tolerance, user_charges.defect.structure — host pymatgen Structure.defect.site — PeriodicSite (fractional coords).defect.multiplicity — site multiplicity.defect.oxi_state — float |
str | None. |
defect.user_charges — list of int (for charge state generation).defect.name — string (auto-generated: "v_Na", "Al_Si", "Li_i").DefectEntry.charge_state — int.DefectEntry.sc_entry — pymatgen ComputedStructureEntry (defect supercell).DefectEntry.bulk_entry — bulk reference.DefectEntry.corrections — dict of energy corrections.DefectEntry.sc_defect_frac_coords — tuple (3 floats).degeneracy_factors, conventional_structure,
conv_cell_frac_coords, wyckoff (label string), defect_supercell,
bulk_supercell.v_<element> (e.g. v_Fe).<sub>_<host> (e.g. Cu_Zn).<element>_i (e.g. H_i).<host_a>_<host_b> (same as substitution).| TM-Spec field | pymatgen/doped | Decision |
|—|—|—|
| defects.reactions[]: "Fe_Fe^× → V_Fe'' + Fe(removed)" | Kröger-Vink not native. Defect represented as Vacancy(structure=..., site=...) object | keep Kröger-Vink (more scientific) + add parsed defects.objects[].name: "v_Fe" for machine handling |
| defects.population.V_Fe: { count: 1, conc: 1/144 } | Defect has no concentration field — that lives in DefectEntry context | keep; export → DefectEntry list per supercell |
| H_i^• notation (charged interstitial) | doped: H_i + separate charge_state: +1 | adopt: separate notation into name: H_i + charge: +1 on export |
| defects.population.H_int.site: tetrahedral_cavity | doped: wyckoff label or conv_cell_frac_coords | keep human description; add wyckoff label on export |
small, medium, large — original 2024 variants.medium-mpa-0 (default since v0.3.10) — re-trained on Materials Project A dataset.large-mpa-0 — extended.mace_mp(model="medium", device="cuda").v0.3.0 — current default pretrained checkpoint.v0.2.0 — legacy.CHGNet.load() (default v0.3.0) or CHGNet.from_file(...).TM-Spec extension for kind: MLIPBenchmark (v0.2):
calculation:
method: MLIP
level:
backend: MACE # MACE | CHGNet | M3GNet | NequIP | ...
model: mace-mp-0
variant: medium-mpa-0 # see foundation_models.py
version: 0.3.13 # mace package version
device: cuda
fine_tuned: false
fine_tune_dataset: null # if fine_tuned=true: ref to dataset
| TM-Spec field | Current draft | Standard recommends | Source | Decision |
|---|---|---|---|---|
calculation.level.xc |
PBE+D3(BJ) |
xc_libxc: [GGA_X_PBE, GGA_C_PBE] + vdw: D3-BJ |
NOMAD/LibXC | hybrid: keep human + add LibXC alias |
calculation.level.smearing.kind |
Marzari-Vanderbilt |
marzari-vanderbilt lowercase |
NOMAD | adopt lowercase enum |
calculation.level.basis.kind |
PW |
plane_waves |
NOMAD | adopt primary plane_waves, alias PW |
calculation.code.name |
QuantumESPRESSO |
match (NOMAD Run.program.name) |
NOMAD | adopt field path, no value change |
calculation.hubbard.formulation |
Dudarev |
Dudarev capitalised |
NOMAD | adopt as-is |
structure.formula |
Fe16S16 |
chemical_formula_descriptive + _reduced + _anonymous |
OPTIMADE | adopt: add three formula fields on export |
structure.cell.{a,c,gamma} |
human a/b/c/α/β/γ | lattice_vectors: [[ax,ay,az],...] Å |
OPTIMADE | keep human, add computed lattice_vectors |
structure.pbc |
[true,true,true] |
dimension_types: [1,1,1] |
OPTIMADE | keep boolean primary, add ints for export |
structure.prototype |
AB_tP4_129_a_c |
match | AFLOW | adopt verbatim |
defects.reactions[] |
Kröger-Vink string | Vacancy(name="v_Fe") + charge_state: -2 |
pymatgen-defects + doped | keep Kröger-Vink + add machine defects.objects[] |
defects.population[].site |
tetrahedral_cavity |
wyckoff label |
doped | adopt — add wyckoff |
magnetic.state |
AFM-G shortcut |
BNS magnetic space group symbol | magCIF | keep shortcut + add opt bns_group |
magnetic.magmoms_uB |
Fe[top]: +3.5 |
_atom_site_moment.crystalaxis_z: 3.5 per atom |
magCIF | keep dict; expand on export |
environment.composition_molal |
Fe(2): 1.0e-3 |
match (PHREEQC element-valence + mol/kgw default) | PHREEQC | adopt verbatim — our format is already correct |
environment.T |
363.15 K |
temp 90 °C |
PHREEQC | keep K, computed temp_C on export |
environment.redox.Eh |
-0.40 V_SHE |
pe dimensionless |
PHREEQC | keep Eh, auto-derive pe |
reactions[].rule |
Unicode arrows + Kröger-Vink | ASCII identifiers H_Fe + ... |
Antimony | keep Unicode primary + add ASCII alias on export |
reactions[].rate |
k1 * [H+] * θ_Fe_free |
k1*H_aq*theta_Fe_free |
Antimony | adopt ASCII on export, [X]→X, θ→theta_ |
workflow.kind: NEB |
match | task_type: NEB |
atomate2/emmet | adopt mapping to task_type on export |
workflow.endpoints |
{A,B} extxyz refs |
atomate2 NEB Maker — images list |
atomate2 | keep {A,B,images}; map on export |
results.status |
PASS/PRELIMINARY/FAIL/RETRACTED |
successful/unsuccessful/error |
emmet | keep our richer enum, partial mapping on export |
results.paper_quotable |
bool | no equivalent | — | keep — original TM-Spec semantics |
provenance.parents[] |
human IDs | UUIDs + LinkType edges | AiiDA | keep human IDs, lookup map on export |
provenance.compute.cost_usd |
float | extras.tm_compute |
AiiDA | keep primary, AiiDA extras on export |
xc_libxc[], vdw,
temp_C, pe_derived, lattice_vectors_A. Primary fields remain human-readable.magnetic.bns_group — optional field for magCIF export.Marzari-Vanderbilt →
marzari-vanderbilt in draft (breaking change, before schema publication).basis.kind — plane_waves primary, PW alias.defects.objects[].name (auto-generated:
v_Fe, H_i) + charge_state separate from ^•/'' notation.tm-spec → antimony function in
tools/tm_spec_export.py with auto-aliasing Unicode → ASCII identifiers.task_type mapping table — NEBCalculation → "NEB",
USCalculation → "Umbrella Sampling" (TM-Spec extension to emmet enum).MLIPBenchmark) — backend, model,
variant, version, fine_tuned. Use MACE/CHGNet variant names.Added 2026-06-01 for the v0.3 additive bump. Both additions were checked against the standards already surveyed above; neither imports a single scalar field, so both export rather than import.
endpoint.geometry_originThere is no single scalar field in the surveyed standards that records “how
this geometry was obtained” as a (method × relaxation) shortcut. The
closest constructs are combinations or structural conventions, so
geometry_origin is a human shortcut (in the spirit of magnetic.state)
with an export alias onto emmet / NOMAD.
| TM-Spec value | emmet run_type × task_type |
NOMAD / QCSchema | Decision |
|---|---|---|---|
dft_relaxed |
"<XC> Structure Optimization" (CalcType = f"{run_type} {task_type}") [FACT] |
electronic_structure_method = DFT [CLAIM] |
export alias to emmet CalcType |
dft_static |
"<XC> Static" [FACT] |
electronic_structure_method = DFT [CLAIM] |
export alias to emmet CalcType |
mlip_relaxed |
emmet is VASP/DFT-only — no MLIP task_type [FACT] | NOMAD electronic_structure_method enum includes ML [CLAIM] |
export to NOMAD method=ML; no emmet target |
experimental / as_built / unknown |
no equivalent | no equivalent | keep — original TM-Spec semantics |
Notes:
RunType / TaskType / CalcType are VASP/DFT-only;
CalcType = f"{run_type} {task_type}" [FACT, emmet.core.vasp.calc_types.enums].
There is no MLIP TaskType, so mlip_relaxed has no emmet target.OptimizationResult.final_molecule (driver = energy/gradient/…),
not as a label [FACT]; its provenance{creator,version,routine} describes
the software, not the geometry.provenance block already means
record authorship (date / author / parents / compute — the
QCSchema / AiiDA sense). The per-endpoint field is therefore not
named provenance; it is geometry_origin. The corresponding gate is
G09_geometry_origin (see gate-registry.md).Decision: keep a human-shortcut enum geometry_origin; provide an
export alias onto emmet run_type × task_type and NOMAD
electronic_structure_method. Energy comparisons across endpoints are valid
only for dft_relaxed.
Update 2026-06-02 (additive, still 0.3):
geometry_originis now also available onstructure($defs.structure.properties.geometry_origin, same enum). Rationale: a NEB doc has one geometry per endpoint (endpoint-level is preferred there), but a single-structure doc —SinglePointCalculation/RelaxCalculation, e.g. a NOMAD import — has noendpointblock, so its origin belongs onstructure.geometry_origin. The NOMAD importer now writesstructure.geometry_origindirectly (previously it could only record the origin in theG09_geometry_originsanity gate, a workaround). The G09 gate is still emitted because it carries the gate-vocabulary verdict the prodromos planner reads. Same enum, sameG09_geometry_origingate, no version bump.
preflightpreflight is a predictive pre-flight assessment produced BEFORE the
expensive calculation. No surveyed standard has an equivalent: they are all
retrospective or descriptive.
| Standard | What it offers | Why it does not cover preflight |
|---|---|---|
| W3C PROV-O | provenance of things that happened | retrospective by design; a plan for a future run is out of scope [FACT] |
| P-Plan (PROV extension) | models a workflow template (steps, variables) | describes a plan’s structure, not a probabilistic GO / NO-GO verdict [CLAIM] |
| RO-Crate | packages inputs/outputs/metadata | packs results, does not predict them [FACT] |
| emmet / NOMAD / QCSchema / AiiDA | post-hoc status (state, success, exit_status, process_state) |
only report what already ran; no pre-run probability or strategy tree [FACT] |
Notes:
preflight is the forward-looking twin of the post-hoc sanity array
and is kept original, alongside paper_quotable and validated_by.engine{name, version, routine}
maps onto QCSchema provenance{creator, version, routine}
(name → creator, version → version, routine → routine) [FACT].sanity[] and preflight.gates[] draw from
the same ^G\d{2}_* vocabulary in gate-registry.md — is an original
TM-Spec contribution (one ID = one check, evaluated before or after).Decision: keep preflight original; align only engine onto QCSchema
provenance; treat the shared gate-ID registry as a TM-Spec contribution.