Interoperability between workflows
Quantas treats interoperability as an explicit scientific transformation, not as accidental compatibility between file formats. A downstream module must receive the physical quantities, units, tensor convention, thermodynamic condition, masks, and provenance that it requires. Moving arrays manually may appear simple, but it can silently lose exactly the information that makes a cross-module result reproducible.
The currently supported public path is:
QHA input or result
|
v
validated QHA--elasticity context
|
v
thermoelastic calibration Cij(V)
|
v
one reconstructed state Cij(P,T), rho(P,T)
| |
v v
Elasticity SEISMIC
Two public transformations in quantas.api.interop implement the
non-trivial parts of this path:
quantas.api.interop.qha_to_thermoelastic_context()validates and couples QHA data with a static elastic-volume series;quantas.api.interop.thermoelastic_to_seismic()reconstructs one thermoelastic state and returns a validated SEISMIC input.
The CLI represents the same boundaries with native HDF5 files and a shared Elasticity/SEISMIC text input. The Python API may keep the same typed contracts in memory and only persist the artifacts that the user wants to retain.
Important
Interoperability does not make two scientifically incompatible calculations compatible. It verifies the contracts that Quantas can inspect, reports extrapolation and missing fields, and refuses invalid transformations. The user remains responsible for phase stability, electronic-structure quality, phonon convergence, and the scientific suitability of the selected approximation.
Supported transformations
The current public interoperability surface is intentionally small.
Source |
Transformation |
Destination |
Public interface |
|---|---|---|---|
QHA input, result object, or native HDF5 |
Validate volume coverage, atomic normalization, units, and required QHA fields |
||
Thermoelastic calibration result or native HDF5 |
Reconstruct one P–T state, select \(C^T\) or \(C^S\), and attach QHA-consistent density |
||
Thermoelastic point analysis |
Write the selected stiffness tensor and density using the shared text contract |
Elasticity and SEISMIC CLI input |
|
There is no generic workflow graph engine and no automatic chaining based on file names. Unsupported or future transformations are not inferred from similar-looking arrays.
Why the CLI and API look different
The CLI communicates between independent processes. Persistent files are therefore the natural boundary:
qha run
-> QHA HDF5
-> thermoelasticity run
-> thermoelastic fit HDF5
-> thermoelasticity analysis point
-> shared text input
-> elasticity run / seismic run
This design provides several advantages:
every expensive stage can be resumed independently;
intermediate results can be inspected before they are consumed;
the exact source archive remains available for provenance;
downstream calculations do not repeat QHA or thermoelastic calibration;
shell scripts and batch systems can schedule each stage separately.
The Python API can pass ResultData and passive
input contracts directly:
QHA ResultData
-> Thermoelastic Context
-> thermoelastic ResultData
-> Seismic Input
-> seismic ResultData
This avoids temporary files while preserving the same numerical path. Writing HDF5 remains recommended at scientific checkpoints, even in an in-memory workflow.
General interoperability rules
Use typed transformations
Prefer quantas.api.interop or a documented module export function to
manual array copying. The transformation should own:
unit conversion;
shape validation;
tensor-condition selection;
density propagation;
coverage and extrapolation checks;
metadata and source provenance;
clear failure messages.
Freeze expensive upstream results
For exploratory notebooks, passing a QHA result object directly is convenient. For publication calculations, a native QHA HDF5 is normally the better source:
it fixes the exact QHA options and versioned result;
it avoids an accidental recalculation with changed defaults;
it can be inspected independently;
it makes the downstream calibration reproducible without the original Python process.
The same principle applies to the reusable thermoelastic fit archive.
Do not infer units from array magnitude
The QHA result envelope records the volume unit. The interoperability layer converts equilibrium volumes to the angstrom-based convention used by the thermoelastic elastic-volume series. Users should not reproduce this logic by assuming that a numerical range “looks like” cubic angstroms.
Preserve tensor condition
Thermoelastic results may contain both isothermal and adiabatic stiffness coefficients. The selected condition is part of the downstream input, not a plotting preference.
Elasticity may analyze either condition if it is named and interpreted correctly.
SEISMIC normally uses the adiabatic tensor because elastic-wave propagation is adiabatic on the relevant timescale.
Requesting
adiabaticis valid only when the upstream result contains the data needed for the conversion.
Treat extrapolation as a source property
The transformation distinguishes two limitations:
QHA coordinate extrapolation outside the stored P–T grid;
elastic-volume extrapolation outside the calibrated static \(C_{ij}(V)\) range.
A downstream result must not erase these distinctions. The point
transformation accepts fail, warn, or allow so the policy is an
explicit user decision.
QHA to Thermoelasticity
Scientific purpose
The QHA result supplies the thermodynamic path:
while the static elastic series supplies the cold response:
The coupling context verifies that these datasets can be used together before any finite-strain calibration is attempted. The quasi-static approximation is explained in Thermoelasticity: implementation and workflow and its thermodynamic basis in Thermoelasticity.
Accepted QHA sources
quantas.api.interop.load_qha_result() accepts:
an existing QHA
ResultData;a native QHA HDF5 path;
a QHA or phonon input object;
a YAML path that must first be calculated.
When a calculation is required, quantas.api.qha.Options must describe
the desired P–T domain and numerical strategy. Options are ignored when the
source is already a completed QHA result.
Context checks
The public transformation performs the following checks and normalizations:
normalize the thermoelastic elastic-volume input;
load or calculate a valid QHA result envelope;
require
equilibrium_volumewith shape(nT, nP);convert the QHA volume unit to angstroms;
compare every equilibrium volume with the sampled elastic-volume interval;
list QHA fields that are absent;
compare primitive atomic numbers and ordering when the QHA input stores them;
record source mode, volume bounds, and the number of extrapolated states.
The returned context exposes:
input_dataNormalized thermoelastic input.
qha_result_dataComplete QHA result envelope.
qhaTyped QHA payload.
extrapolation_maskBoolean
(nT, nP)mask for QHA equilibrium volumes outside the elastic calibration interval.missing_qha_fieldsNames of optional or required downstream fields absent from the QHA result.
metadataElastic and QHA volume bounds, point counts, and source mode.
Missing fields do not all have the same consequence. Equilibrium volume is mandatory for the QSA. Heat capacity and the Cartesian thermal-expansion tensor are additionally required when the adiabatic correction is requested. Structural fields may be absent without preventing an isothermal tensor calibration.
CLI: explicit two-stage calculation
The most reproducible CLI path first freezes QHA:
quantas qha run examples/qha/crystal-phonons/dol_pbe0.yaml \
--scheme freq \
--minimization poly \
--thermal-expansion mixed_derivative \
--temperature 300 1800 100 \
--pressure 0 10 2 \
--energy-degree 3 \
--frequency-degree 3 \
--output dolomite_qha.hdf5 \
--report dolomite_qha.log \
--no-progress \
--force
The native result is then consumed by the thermoelastic calibration:
quantas thermoelasticity run \
examples/thermoelasticity/dol_pbe0_thermoelastic.yaml \
dolomite_qha.hdf5 \
--reference-eos BM3 \
--finite-strain-order 3 \
--adiabatic auto \
--validation standard \
--output dolomite_fit.hdf5 \
--report dolomite_fit.log \
--no-progress \
--force
The second command reads the QHA archive. It does not rerun QHA.
CLI: direct YAML source
thermoelasticity run may also receive a QHA YAML input directly:
quantas thermoelasticity run \
examples/thermoelasticity/dol_pbe0_thermoelastic.yaml \
examples/qha/crystal-phonons/dol_pbe0.yaml \
--qha-temperature 300 1800 100 \
--qha-pressure 0 10 2 \
--qha-scheme freq \
--qha-minimization poly \
--qha-degree 3 \
--reference-eos BM3 \
--finite-strain-order 3 \
--output dolomite_fit.hdf5 \
--no-progress \
--force
This is convenient for a compact calculation, but the intermediate QHA result is less visible as an independent scientific checkpoint. Use the explicit two-stage path when the QHA result must be reviewed, reused, or cited separately.
API: inspect the coupling before fitting
The API makes the prevalidated context directly available:
from quantas.api import interop, qha, thermoelasticity
qha_result = qha.run(
"examples/qha/crystal-phonons/dol_pbe0.yaml",
options=qha.Options(
temperature_min=300.0,
temperature_max=1800.0,
temperature_step=100.0,
pressure_min=0.0,
pressure_max=10.0,
pressure_step=2.0,
scheme="freq",
minimization="poly",
thermal_expansion_method="mixed_derivative",
),
)
context = interop.qha_to_thermoelastic_context(
"examples/thermoelasticity/dol_pbe0_thermoelastic.yaml",
qha_result,
)
print(context.metadata)
print(context.missing_qha_fields)
print(context.extrapolation_mask.sum())
fit_result = thermoelasticity.run_context(
context,
options=thermoelasticity.Options(
reference_eos="BM3",
finite_strain_order=3,
adiabatic_mode="auto",
),
)
The convenience function quantas.api.thermoelasticity.run() performs the
context preparation and calibration in one call. Use the explicit context
when coverage or completeness must be inspected before fitting.
Thermoelasticity to one material state
A thermoelastic fit archive stores a reusable model. A downstream Elasticity or SEISMIC calculation requires one concrete state:
The state transformation therefore needs:
pressure in GPa;
temperature in K;
isothermaloradiabaticstiffness condition;an extrapolation policy.
It reconstructs a one-point grid through the same post-fit engine used by the thermoelastic CLI, selects the requested tensor, validates density, and creates a descriptive job name containing P, T, and tensor condition.
State to Elasticity
CLI
The shared state file can be analyzed directly:
quantas elasticity run dolomite_5GPa_800K.dat \
--output dolomite_state_elasticity.hdf5 \
--report dolomite_state_elasticity.log \
--no-progress \
--force
Elasticity uses the stiffness tensor. Density is retained in the input file for compatibility with SEISMIC but is not needed for static directional elastic properties.
API
A dedicated thermoelastic_to_elasticity helper is not required because the
Elasticity public input contains only a title and a stiffness tensor. The same
state returned for SEISMIC can be adapted without unit conversion or private
imports:
import numpy as np
from quantas.api import elasticity, interop
state = interop.thermoelastic_to_seismic(
"dolomite_fit.hdf5",
pressure=5.0,
temperature=800.0,
tensor_condition="adiabatic",
extrapolation_policy="fail",
)
elastic_input = elasticity.Input(
jobname=state.jobname,
stiffness=np.asarray(state.stiffness, dtype=np.float64),
source=state.source,
)
elastic_result = elasticity.run(elastic_input)
Alternatively, write the shared state input with
quantas.api.thermoelasticity.write_state_input() and pass its path to
quantas.api.elasticity.run(). The file-mediated route is useful when the
state itself is an artifact that must be retained.
State to SEISMIC
CLI
quantas seismic run dolomite_5GPa_800K.dat \
--level phase \
--ntheta 31 \
--nphi 61 \
--output dolomite_state_seismic.hdf5 \
--report dolomite_state_seismic.log \
--no-progress \
--force
The reduced phase-only grid above is suitable for an interoperability check. A final acoustic study should choose sampling and property level according to Seismic-wave analysis: implementation and workflow and Seismic-wave analysis.
API
The direct API path returns a validated quantas.api.seismic.Input:
from quantas.api import interop, seismic
seismic_input = interop.thermoelastic_to_seismic(
"dolomite_fit.hdf5",
pressure=5.0,
temperature=800.0,
tensor_condition="adiabatic",
extrapolation_policy="fail",
)
seismic_result = seismic.run(
seismic_input,
options=seismic.Options(
ntheta=31,
nphi=61,
hemisphere="upper",
level="phase",
),
)
The transformation centralizes reconstruction, condition selection, density,
and provenance. Do not extract stiffness_adiabatic[0, 0] and density by
hand unless reproducing the same validation logic is an explicit research
requirement.
Complete CLI example
The complete shell workflow is distributed as:
Run it from the project root:
bash examples/interoperability/workflow_cli.sh interoperability_cli
It writes:
interoperability_cli/
|-- dolomite_qha.hdf5
|-- dolomite_qha.log
|-- dolomite_fit.hdf5
|-- dolomite_fit.log
|-- dolomite_5GPa_800K.dat
|-- dolomite_state_elasticity.hdf5
|-- dolomite_state_elasticity.log
|-- dolomite_state_seismic.hdf5
`-- dolomite_state_seismic.log
Complete Python API example
The equivalent public-API workflow is available as:
Run it from the project root:
python examples/interoperability/workflow_api.py \
--output-dir interoperability_api
The script demonstrates both styles:
in-memory typed transformations for the numerical chain;
native HDF5 and shared text artifacts at reusable checkpoints.
For the distributed dolomite example at 5 GPa and 800 K, the verified output is:
Context extrapolated states: 0
State density / kg m^-3: 2908.736749
State C11_S / GPa: 230.296285
Hill bulk modulus / GPa: 109.557211
Sampled V_P range / km s^-1: 6.600439 9.171102
The VP range belongs to the deliberately coarse 31 x 61 phase
sampling used by the example. It is a reproducibility checkpoint, not a
converged directional study.
CLI/API equivalence
The two frontends use the same public numerical operations but expose different artifact boundaries.
Stage |
CLI |
Python API |
|---|---|---|
QHA |
|
|
Coupling |
|
|
Calibration |
|
|
State reconstruction |
|
|
Elasticity input |
shared |
|
SEISMIC input |
shared |
Numerical equivalence should be checked at the boundary quantities before comparing derived reports or sampled extrema:
pressure and temperature;
selected tensor condition;
density;
all 21 independent entries of the symmetric stiffness matrix;
downstream options such as sphere sampling.
The QHA and thermoelastic HDF5 paths preserve native arrays and can be compared exactly when options are identical. The portable state text file is a formatted export; compare downstream results with a tolerance consistent with its six-decimal stiffness representation rather than demanding bitwise equality. For the distributed example, the resulting phase speeds differ by less than \(2 imes10^{-8}\) km s-1 between the in-memory API path and the file-mediated CLI path.
Provenance and persistence
QHA result
The QHA HDF5 stores normalized input, resolved options, equilibrium properties, fit diagnostics, warnings, and numerical precision metadata.
Thermoelastic context
The context is an in-memory validation object. Its diagnostics become part of the calibration result and report; it is not a separate native file format.
Thermoelastic fit archive
The fit HDF5 is the reusable source for all later Point, Grid, and Profile analyses. It stores the reference EOS, component fits, covariance, classification, QHA source fields, and calibration metadata.
Downstream HDF5 files
Elasticity and SEISMIC each write their own native result envelopes. Their metadata identify the downstream workflow, while the input title and source retain the state origin where available.
Failure modes and diagnostics
Different primitive atomic normalization
When the QHA input stores atomic numbers, their sequence must match the thermoelastic reference structure. A mismatch may represent a different primitive cell, atom ordering, composition, or phase and is rejected.
Missing equilibrium volume
Thermoelastic QSA cannot proceed without equilibrium_volume. A harmonic
result or incomplete QHA payload is not a substitute.
Incomplete adiabatic inputs
An isothermal calibration may be valid even when QHA heat capacity or Cartesian thermal expansion is absent. Requesting an adiabatic state then fails or is reported according to the selected thermoelastic adiabatic mode. Quantas does not silently label \(C^T\) as \(C^S\).
QHA volume outside elastic support
The coupling context counts these states before fitting. A point
transformation with extrapolation_policy="fail" refuses them. warn or
allow should be used only with a documented scientific justification.
Requested P or T outside the stored QHA grid
This is coordinate extrapolation and is distinct from elastic-volume extrapolation. A state can trigger either mask, both, or neither.
Invalid density
SEISMIC requires finite positive density. The direct transformation rejects a state whose QHA-consistent density cannot be reconstructed.
Unstable stiffness
The transformation can construct the state, but SEISMIC rejects a stiffness matrix that is not positive definite. Elasticity may report instability and skip directional properties according to its own workflow contract.
Wrong tensor condition
A state exported as isothermal remains isothermal. Downstream file compatibility does not imply that the tensor condition is appropriate for the intended experiment or wave-propagation calculation.
Repeated upstream calculation
Passing a YAML source to load_qha_result or thermoelasticity run may
calculate QHA. Passing a QHA ResultData or HDF5 reads the completed result.
Use a frozen HDF5 when recomputation would be undesirable.
Performance and reuse
Interoperability itself is inexpensive. The dominant costs are the upstream and downstream scientific calculations:
QHA over the selected P–T grid;
thermoelastic component calibration;
Elasticity 2D/3D fields when requested;
SEISMIC spherical sampling, especially group and enhancement levels.
A productive workflow is therefore:
calculate and inspect QHA once;
calibrate and inspect the thermoelastic fit once;
reconstruct many inexpensive Point states from the fit archive;
run coarse downstream checks;
increase Elasticity or SEISMIC sampling only for selected states.
Do not rerun QHA for every seismic state. Do not recalibrate \(C_{IJ}(V)\) for every point on a profile. The reusable fit archive exists precisely to separate those costs.
Decision guide
Situation |
Recommended path |
Reason |
|---|---|---|
One exploratory notebook |
Pass |
Minimal temporary I/O while retaining typed contracts |
Publication or shared calculation |
Freeze QHA and thermoelastic HDF5 checkpoints |
Reproducibility and independent inspection |
Need to review coverage before fitting |
Build an explicit interoperability context |
Exposes missing fields and extrapolation mask |
One reusable P–T state |
Write the shared text input |
Portable boundary for both downstream CLIs |
Direct Python SEISMIC calculation |
Use |
Centralized density, tensor condition, and validation |
Direct Python Elasticity calculation |
Construct |
Elasticity requires no density-specific transformation |
Many states along a profile |
Analyze the profile once and select states deliberately |
Avoid repeated calibration and hidden gridding |
State outside support |
Keep |
Prevents silent use of unsupported tensors |
Boundaries of the current implementation
The current interoperability layer does not:
perform phase-equilibrium selection;
transform between different chemical compositions;
reconcile different primitive cells or atom orderings automatically;
derive QHA q-point weights;
add explicit phonon-strain elastic terms absent from the QSA;
infer whether isothermal or adiabatic coefficients are appropriate;
build multiphase aggregate properties;
chain EOS fitting into QHA or thermoelasticity implicitly;
create a general-purpose workflow scheduler.
New transformations should be added only when the scientific contract is well-defined and testable. The development procedure is described in Adding a new scientific module, Maintaining the public API, and Common change recipes.