diff --git a/.gitignore b/.gitignore index 6b68b80ca..2f9419925 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.json +!ml_peg/calcs/bulk_crystal/qha_lattice_constants/data/*.json *.html *.dat *.lock diff --git a/docs/source/user_guide/benchmarks/bulk_crystal.rst b/docs/source/user_guide/benchmarks/bulk_crystal.rst index 575bbcc11..9bada2846 100644 --- a/docs/source/user_guide/benchmarks/bulk_crystal.rst +++ b/docs/source/user_guide/benchmarks/bulk_crystal.rst @@ -115,3 +115,95 @@ Reference data: * Same as input data * PBE + + +Quasiharmonic Approximation +=========================== + +Summary +------- + +Performance in evaluating temperature-dependent thermodynamic properties using the +quasiharmonic approximation (QHA). Each data point is a (structure, temperature, pressure) +triple with experimental reference values. + +The QHA extends the harmonic approximation by accounting for volume-dependent phonon +frequencies, enabling prediction of thermal expansion and bulk properties at temperature. + + +Metrics +------- + +(1) Lattice constant MAE (Experimental) + +Mean absolute error of equilibrium lattice constants at target temperature and pressure +conditions. + +(2) Volume per atom MAE (Experimental) + +Mean absolute error of equilibrium volume per atom at target (structure, T, P) conditions. + +(3) Thermal expansion MAE (Experimental) + +Mean absolute error of thermal expansion coefficient (in 10⁻⁶ K⁻¹) at target conditions. + +(4) Bulk modulus MAE (Experimental) + +Mean absolute error of isothermal bulk modulus (in GPa) at target temperature and pressure. + +(5) Heat capacity MAE (Experimental) + +Mean absolute error of heat capacity at constant pressure (in J/mol·K) at target conditions. + + +Methodology +----------- + +The benchmark uses atomate2's ``ForceFieldQhaMaker`` workflow, which performs: + +1. **Initial relaxation**: The input structure is fully relaxed (cell + positions) using + the MLIP. We use an fmax of 0.0005 eV/Å. + +2. **Equation of state (EOS) sampling**: Multiple strained structures are generated around + the equilibrium volume (default: ±5% strain, 10 volumes). + +3. **Phonon calculations**: For each strained volume, phonon frequencies are computed using + the finite displacement method with a supercell approach using the default strategy in atomate2. + +4. **Free energy fitting**: The Helmholtz free energy F(V,T) is computed at each volume and + temperature using phonopy by combining: + + - Electronic energy E(V) from the EOS + - Vibrational free energy F_vib(V,T) from phonon calculations + +5. **QHA analysis**: Temperature-dependent equilibrium properties are extracted by minimizing + F(V,T) at each temperature: + + - V(T): equilibrium volume vs temperature + - α(T): thermal expansion coefficient + - B(T): isothermal bulk modulus + - C_p(T): heat capacity at constant pressure + +The workflow uses the Vinet equation of state for fitting and supports pressure-dependent +calculations. + + +Computational cost +------------------ + +High: Each QHA calculation requires multiple phonon calculations (one per volume point). +The cost depends strongly on the size and symmetry of the structure. As a rough guide, Silicon +in the diamond structure takes around a minute on gpu. + + +Data availability +----------------- + +Input structures: + +* CIF files for bulk crystals (e.g., Si in diamond structure) + +Reference data: + +* Experimental thermophysical properties from TPRC Data Series (Thermophysical properties + of matter, Vol. 12-13) diff --git a/ml_peg/analysis/bulk_crystal/quasiharmonic/analyse_quasiharmonic.py b/ml_peg/analysis/bulk_crystal/quasiharmonic/analyse_quasiharmonic.py new file mode 100644 index 000000000..715a3d64a --- /dev/null +++ b/ml_peg/analysis/bulk_crystal/quasiharmonic/analyse_quasiharmonic.py @@ -0,0 +1,431 @@ +"""Analyse quasiharmonic benchmark results.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any + +import pandas as pd +import pytest + +from ml_peg.analysis.utils.decorators import build_table, plot_parity +from ml_peg.analysis.utils.utils import load_metrics_config, mae +from ml_peg.app import APP_ROOT +from ml_peg.calcs import CALCS_ROOT +from ml_peg.models.get_models import get_model_names +from ml_peg.models.models import current_models + +MODELS = get_model_names(current_models) +CALC_PATH = CALCS_ROOT / "bulk_crystal" / "quasiharmonic" / "outputs" +OUT_PATH = APP_ROOT / "data" / "bulk_crystal" / "quasiharmonic" + +METRICS_CONFIG_PATH = Path(__file__).with_name("metrics.yml") +DEFAULT_THRESHOLDS, DEFAULT_TOOLTIPS, DEFAULT_WEIGHTS = load_metrics_config( + METRICS_CONFIG_PATH +) + + +def _make_hoverdata() -> dict[str, list]: + """ + Create empty hoverdata dictionary for QHA plots. + + Returns + ------- + dict[str, list] + Empty hoverdata with Material, Temperature, and Pressure keys. + """ + return { + "Material": [], + "Temperature (K)": [], + "Pressure (GPa)": [], + } + + +# Hover data for interactive plots (populated during fixture execution) +HOVERDATA_LATTICE = _make_hoverdata() +HOVERDATA_VOLUME = _make_hoverdata() +HOVERDATA_THERMAL_EXPANSION = _make_hoverdata() +HOVERDATA_BULK_MODULUS = _make_hoverdata() +HOVERDATA_HEAT_CAPACITY = _make_hoverdata() + + +def _load_results(model_name: str) -> pd.DataFrame: + """ + Load results for a given model. + + Parameters + ---------- + model_name + Name of the model. + + Returns + ------- + pd.DataFrame + Results dataframe or empty dataframe if missing. + """ + path = CALC_PATH / model_name / "results.csv" + if not path.exists(): + return pd.DataFrame() + df = pd.read_csv(path) + # Filter to only successful calculations + if "status" in df.columns: + df = df[df["status"] == "success"] + return df.sort_values(["material", "temperature_K", "pressure_GPa"]).reset_index( + drop=True + ) + + +def _gather_parity_data( + ref_col: str, + pred_col: str, + hoverdata: dict[str, list], +) -> dict[str, list]: + """ + Gather reference and predicted values for parity plotting. + + Parameters + ---------- + ref_col + Column name for reference values. + pred_col + Column name for predicted values. + hoverdata + Hoverdata dictionary to populate (mutated in place). + + Returns + ------- + dict[str, list] + Dictionary of reference and predicted values per model. + """ + OUT_PATH.mkdir(parents=True, exist_ok=True) + + results: dict[str, list] = {"ref": []} | {mlip: [] for mlip in MODELS} + ref_stored = False + + for model_name in MODELS: + df = _load_results(model_name) + if df.empty: + continue + + if ref_col not in df.columns or pred_col not in df.columns: + continue + + valid_df = df.dropna(subset=[pred_col, ref_col]) + results[model_name] = valid_df[pred_col].tolist() + + if not ref_stored and not valid_df.empty: + results["ref"] = valid_df[ref_col].tolist() + hoverdata["Material"] = valid_df["material"].tolist() + hoverdata["Temperature (K)"] = valid_df["temperature_K"].tolist() + hoverdata["Pressure (GPa)"] = valid_df["pressure_GPa"].tolist() + ref_stored = True + + return results + + +def _calculate_mae(parity_data: dict[str, list]) -> dict[str, float | None]: + """ + Calculate MAE for each model from parity data. + + Parameters + ---------- + parity_data + Dictionary with 'ref' key and model name keys containing lists. + + Returns + ------- + dict[str, float | None] + MAE values for each model, None if data is missing or mismatched. + """ + results: dict[str, float | None] = {} + ref = parity_data.get("ref", []) + for model_name in MODELS: + pred = parity_data.get(model_name, []) + if not ref or not pred or len(ref) != len(pred): + results[model_name] = None + else: + results[model_name] = mae(ref, pred) + return results + + +@pytest.fixture +@plot_parity( + filename=OUT_PATH / "figure_qha_lattice_constants.json", + title="QHA Lattice Constants", + x_label="Predicted lattice constant / \u00c5", + y_label="Reference lattice constant / \u00c5", + hoverdata=HOVERDATA_LATTICE, +) +def qha_lattice_constants() -> dict[str, list]: + """ + Gather reference and predicted lattice constants for parity plotting. + + Returns + ------- + dict[str, list] + Dictionary of reference and predicted values per model. + """ + return _gather_parity_data("ref_lattice_a", "pred_lattice_a", HOVERDATA_LATTICE) + + +@pytest.fixture +@plot_parity( + filename=OUT_PATH / "figure_qha_volume_per_atom.json", + title="QHA Volume per Atom", + x_label="Predicted volume per atom / ų/atom", + y_label="Reference volume per atom / ų/atom", + hoverdata=HOVERDATA_VOLUME, +) +def qha_volume_per_atom() -> dict[str, list]: + """ + Gather reference and predicted equilibrium volume per atom. + + Returns + ------- + dict[str, list] + Dictionary of reference and predicted values per model. + """ + return _gather_parity_data( + "ref_volume_per_atom", "pred_volume_per_atom", HOVERDATA_VOLUME + ) + + +@pytest.fixture +@plot_parity( + filename=OUT_PATH / "figure_qha_thermal_expansion.json", + title="QHA Thermal Expansion", + x_label="Predicted thermal expansion / 10\u207b\u2076 K\u207b\u00b9", + y_label="Reference thermal expansion / 10\u207b\u2076 K\u207b\u00b9", + hoverdata=HOVERDATA_THERMAL_EXPANSION, +) +def qha_thermal_expansion() -> dict[str, list]: + """ + Gather reference and predicted thermal expansion coefficients. + + Returns + ------- + dict[str, list] + Dictionary of reference and predicted values per model. + """ + return _gather_parity_data( + "ref_thermal_expansion_1e6_K", + "pred_thermal_expansion_1e6_K", + HOVERDATA_THERMAL_EXPANSION, + ) + + +@pytest.fixture +@plot_parity( + filename=OUT_PATH / "figure_qha_bulk_modulus.json", + title="QHA Bulk Modulus", + x_label="Predicted bulk modulus / GPa", + y_label="Reference bulk modulus / GPa", + hoverdata=HOVERDATA_BULK_MODULUS, +) +def qha_bulk_modulus() -> dict[str, list]: + """ + Gather reference and predicted bulk modulus values. + + Returns + ------- + dict[str, list] + Dictionary of reference and predicted values per model. + """ + return _gather_parity_data( + "ref_bulk_modulus_GPa", "pred_bulk_modulus_GPa", HOVERDATA_BULK_MODULUS + ) + + +@pytest.fixture +@plot_parity( + filename=OUT_PATH / "figure_qha_heat_capacity.json", + title="QHA Heat Capacity", + x_label="Predicted heat capacity / J/(mol·K)", + y_label="Reference heat capacity / J/(mol·K)", + hoverdata=HOVERDATA_HEAT_CAPACITY, +) +def qha_heat_capacity() -> dict[str, list]: + """ + Gather reference and predicted heat capacity values. + + Returns + ------- + dict[str, list] + Dictionary of reference and predicted values per model. + """ + return _gather_parity_data( + "ref_heat_capacity_J_mol_K", + "pred_heat_capacity_J_mol_K", + HOVERDATA_HEAT_CAPACITY, + ) + + +@pytest.fixture +def lattice_constant_mae( + qha_lattice_constants: dict[str, list], +) -> dict[str, float | None]: + """ + Mean absolute error for lattice constants. + + Parameters + ---------- + qha_lattice_constants + Reference and predicted lattice constants. + + Returns + ------- + dict[str, float | None] + MAE values for each model. + """ + return _calculate_mae(qha_lattice_constants) + + +@pytest.fixture +def volume_per_atom_mae( + qha_volume_per_atom: dict[str, list], +) -> dict[str, float | None]: + """ + Mean absolute error for equilibrium volume per atom. + + Parameters + ---------- + qha_volume_per_atom + Reference and predicted volumes per atom. + + Returns + ------- + dict[str, float | None] + MAE values for each model. + """ + return _calculate_mae(qha_volume_per_atom) + + +@pytest.fixture +def thermal_expansion_mae( + qha_thermal_expansion: dict[str, list], +) -> dict[str, float | None]: + """ + Mean absolute error for thermal expansion coefficient. + + Parameters + ---------- + qha_thermal_expansion + Reference and predicted thermal expansion. + + Returns + ------- + dict[str, float | None] + MAE values for each model. + """ + return _calculate_mae(qha_thermal_expansion) + + +@pytest.fixture +def bulk_modulus_mae(qha_bulk_modulus: dict[str, list]) -> dict[str, float | None]: + """ + Mean absolute error for bulk modulus. + + Parameters + ---------- + qha_bulk_modulus + Reference and predicted bulk modulus. + + Returns + ------- + dict[str, float | None] + MAE values for each model. + """ + return _calculate_mae(qha_bulk_modulus) + + +@pytest.fixture +def heat_capacity_mae(qha_heat_capacity: dict[str, list]) -> dict[str, float | None]: + """ + Mean absolute error for heat capacity at constant pressure. + + Parameters + ---------- + qha_heat_capacity + Reference and predicted heat capacity. + + Returns + ------- + dict[str, float | None] + MAE values for each model. + """ + return _calculate_mae(qha_heat_capacity) + + +@pytest.fixture +@build_table( + filename=OUT_PATH / "quasiharmonic_metrics_table.json", + metric_tooltips=DEFAULT_TOOLTIPS, + thresholds=DEFAULT_THRESHOLDS, + weights=DEFAULT_WEIGHTS, +) +def metrics( + lattice_constant_mae: dict[str, float | None], + volume_per_atom_mae: dict[str, float | None], + thermal_expansion_mae: dict[str, float | None], + bulk_modulus_mae: dict[str, float | None], + heat_capacity_mae: dict[str, float | None], +) -> dict[str, dict[str, float | None]]: + """ + Build metrics dictionary for quasiharmonic benchmark. + + Each metric is computed over (structure, temperature, pressure) data points. + + Parameters + ---------- + lattice_constant_mae + Lattice constant MAE per model. + volume_per_atom_mae + Volume per atom MAE per model. + thermal_expansion_mae + Thermal expansion MAE per model. + bulk_modulus_mae + Bulk modulus MAE per model. + heat_capacity_mae + Heat capacity MAE per model. + + Returns + ------- + dict[str, dict[str, float | None]] + Metrics dictionary. + """ + return { + "Lattice constant MAE": lattice_constant_mae, + "Volume per atom MAE": volume_per_atom_mae, + "Thermal expansion MAE": thermal_expansion_mae, + "Bulk modulus MAE": bulk_modulus_mae, + "Heat capacity MAE": heat_capacity_mae, + } + + +def test_quasiharmonic( + metrics: dict[str, dict[str, Any]], + qha_lattice_constants: dict[str, list], + qha_volume_per_atom: dict[str, list], + qha_thermal_expansion: dict[str, list], + qha_bulk_modulus: dict[str, list], + qha_heat_capacity: dict[str, list], +) -> None: + """ + Run quasiharmonic analysis test. + + Parameters + ---------- + metrics + Metrics dictionary. + qha_lattice_constants + Lattice constants parity data. + qha_volume_per_atom + Volume per atom parity data. + qha_thermal_expansion + Thermal expansion parity data. + qha_bulk_modulus + Bulk modulus parity data. + qha_heat_capacity + Heat capacity parity data. + """ + return diff --git a/ml_peg/analysis/bulk_crystal/quasiharmonic/metrics.yml b/ml_peg/analysis/bulk_crystal/quasiharmonic/metrics.yml new file mode 100644 index 000000000..09cd01c85 --- /dev/null +++ b/ml_peg/analysis/bulk_crystal/quasiharmonic/metrics.yml @@ -0,0 +1,40 @@ +metrics: + Lattice constant MAE: + good: 0.02 + bad: 0.1 + unit: "\u00c5" + tooltip: "Mean Absolute Error of lattice constants at target (structure, T, P) conditions from QHA" + level_of_theory: Experimental + weight: 2.0 + + Volume per atom MAE: + good: 0.02 + bad: 0.1 + unit: "ų/atom" + tooltip: "Mean Absolute Error of equilibrium volume per atom at target (structure, T, P) conditions" + level_of_theory: Experimental + weight: 1.5 + + Thermal expansion MAE: + good: 0.0 + bad: 2.0 + unit: "10\u207b\u2076 K\u207b\u00b9" + tooltip: "Mean Absolute Error of thermal expansion coefficient at target (structure, T, P) conditions" + level_of_theory: Experimental + weight: 1.0 + + Bulk modulus MAE: + good: 0.0 + bad: 10.0 + unit: GPa + tooltip: "Mean Absolute Error of bulk modulus at target (structure, T, P) conditions" + level_of_theory: Experimental + weight: 1.0 + + Heat capacity MAE: + good: 0.0 + bad: 5.0 + unit: "J/(mol\u00b7K)" + tooltip: "Mean Absolute Error of heat capacity at constant pressure at target (structure, T, P) conditions" + level_of_theory: Experimental + weight: 1.0 diff --git a/ml_peg/app/bulk_crystal/quasiharmonic/app_quasiharmonic.py b/ml_peg/app/bulk_crystal/quasiharmonic/app_quasiharmonic.py new file mode 100644 index 000000000..e4376eb7a --- /dev/null +++ b/ml_peg/app/bulk_crystal/quasiharmonic/app_quasiharmonic.py @@ -0,0 +1,84 @@ +"""Quasiharmonic benchmark app layout and callbacks.""" + +from __future__ import annotations + +from dash import Dash +from dash.html import Div + +from ml_peg.app import APP_ROOT +from ml_peg.app.base_app import BaseApp +from ml_peg.app.utils.build_callbacks import plot_from_table_column +from ml_peg.app.utils.load import read_plot + +BENCHMARK_NAME = "Quasiharmonic" +DOCS_URL = ( + "https://ddmms.github.io/ml-peg/user_guide/benchmarks/bulk_crystal.html" + "#quasiharmonic" +) +DATA_PATH = APP_ROOT / "data" / "bulk_crystal" / "quasiharmonic" + + +class QuasiharmonicApp(BaseApp): + """Quasiharmonic benchmark app layout and callbacks.""" + + def register_callbacks(self) -> None: + """Register callbacks to app.""" + # Define plot paths and their metric mappings + plot_configs = [ + ("figure_qha_lattice_constants.json", "Lattice constant MAE", "lattice"), + ("figure_qha_volume_per_atom.json", "Volume per atom MAE", "volume"), + ("figure_qha_thermal_expansion.json", "Thermal expansion MAE", "thermal"), + ("figure_qha_bulk_modulus.json", "Bulk modulus MAE", "bulk-modulus"), + ("figure_qha_heat_capacity.json", "Heat capacity MAE", "heat-capacity"), + ] + + # Build column-to-plot mapping + column_to_plot = {} + for filename, metric_name, plot_id_suffix in plot_configs: + plot_path = DATA_PATH / filename + if plot_path.exists(): + scatter = read_plot( + plot_path, + id=f"{BENCHMARK_NAME}-figure-{plot_id_suffix}", + ) + column_to_plot[metric_name] = scatter + + if column_to_plot: + plot_from_table_column( + table_id=self.table_id, + plot_id=f"{BENCHMARK_NAME}-figure-placeholder", + column_to_plot=column_to_plot, + ) + + +def get_app() -> QuasiharmonicApp: + """ + Get quasiharmonic benchmark app. + + Returns + ------- + QuasiharmonicApp + Benchmark layout and callback registration. + """ + return QuasiharmonicApp( + name=BENCHMARK_NAME, + description=( + "Temperature-dependent thermodynamic properties using the " + "quasiharmonic approximation (QHA). Evaluates MLIP predictions of " + "lattice constants, volume, thermal expansion, bulk modulus, " + "and heat capacity as a function of temperature and pressure." + ), + docs_url=DOCS_URL, + table_path=DATA_PATH / "quasiharmonic_metrics_table.json", + extra_components=[ + Div(id=f"{BENCHMARK_NAME}-figure-placeholder"), + ], + ) + + +if __name__ == "__main__": + full_app = Dash(__name__, assets_folder=DATA_PATH.parent.parent) + qha_app = get_app() + full_app.layout = qha_app.layout + qha_app.register_callbacks() + full_app.run(port=8063, debug=True) diff --git a/ml_peg/calcs/bulk_crystal/quasiharmonic/calc_quasiharmonic.py b/ml_peg/calcs/bulk_crystal/quasiharmonic/calc_quasiharmonic.py new file mode 100644 index 000000000..98a9cb40d --- /dev/null +++ b/ml_peg/calcs/bulk_crystal/quasiharmonic/calc_quasiharmonic.py @@ -0,0 +1,549 @@ +""" +Run calculations for quasiharmonic benchmark using atomate2. + +This module implements a quasiharmonic approximation (QHA) workflow using +atomate2's ForceFieldQhaMaker. It supports all force fields in ml-peg through +atomate2's ASE calculator integration. + +The workflow computes temperature-dependent thermodynamic properties including: +- Equilibrium volume vs temperature +- Lattice constants vs temperature +- Thermal expansion coefficient +- Heat capacity and free energy +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import TYPE_CHECKING, Any +import uuid + +from jobflow import JobStore, run_locally +from maggma.stores import MemoryStore +import pandas as pd +from pymatgen.io.ase import AseAtomsAdaptor +import pytest + +from ml_peg.models.get_models import get_model_names, load_model_configs +from ml_peg.models.models import current_models + +if TYPE_CHECKING: + from pymatgen.core import Structure + +MODELS = get_model_names(current_models) + +DATA_PATH = Path(__file__).parent / "data" +OUT_PATH = Path(__file__).parent / "outputs" + +# Load reference data +REFERENCE_FILE = DATA_PATH / "quasiharmonic_reference.json" + + +def get_atomate2_config(model_name: str) -> dict[str, Any]: + """ + Get atomate2-compatible configuration for a ml-peg model. + + Parameters + ---------- + model_name + Name of the model in ml-peg's models.yml. + + Returns + ------- + dict[str, Any] + Configuration dict with 'force_field_name' and 'calculator_kwargs'. + + Raises + ------ + ValueError + If the model is not supported by atomate2. + """ + from atomate2.forcefields import MLFF + + configs, _ = load_model_configs((model_name,)) + cfg = configs.get(model_name, {}) + if not cfg: + raise ValueError(f"Model '{model_name}' not found in models.yml") + class_name = cfg.get("class_name", "") + kwargs = cfg.get("kwargs", {}) + + # Map ml-peg models to atomate2 MLFF and calculator_kwargs + if class_name == "mace_mp": + model_id = kwargs.get("model", "medium") + + # Map to atomate2 MLFF names + if model_id == "medium": + return { + "force_field_name": MLFF.MACE_MP_0, + "calculator_kwargs": {"model": "medium"}, + } + if model_id == "medium-0b3": + return { + "force_field_name": MLFF.MACE_MP_0B3, + "calculator_kwargs": {}, + } + if model_id in ("medium-mpa-0", "mpa-0"): + return { + "force_field_name": MLFF.MACE_MPA_0, + "calculator_kwargs": {}, + } + if model_id in ("medium-omat-0", "omat-0"): + # Use MACE generic with specific model + return { + "force_field_name": MLFF.MACE, + "calculator_kwargs": {"model": model_id}, + } + if "matpes" in model_id.lower() or "r2scan" in model_id.lower(): + return { + "force_field_name": MLFF.MATPES_R2SCAN, + "calculator_kwargs": kwargs, + } + return { + "force_field_name": MLFF.MACE, + "calculator_kwargs": {"model": model_id}, + } + + if class_name == "OrbCalc": + # Orb models - use monty dict format for external calculator + orb_name = kwargs.get("name", "orb_v3_conservative_inf_omat") + return { + "force_field_name": { + "@module": "orb_models.forcefield.calculator", + "@callable": "ORBCalculator", + }, + "calculator_kwargs": { + "model_name": orb_name, + "device": cfg.get("device", "cpu"), + }, + } + + if class_name == "PETMADCalculator": + # PET-MAD - use monty dict format + return { + "force_field_name": { + "@module": "pet_mad.calculator", + "@callable": "PETMADCalculator", + }, + "calculator_kwargs": kwargs, + } + + if class_name == "FAIRChemCalculator": + # FAIRChem/UMA calculators + return { + "force_field_name": { + "@module": "fairchem.core", + "@callable": "FAIRChemCalculator", + }, + "calculator_kwargs": { + "model_name": kwargs.get("model_name"), + "task_name": kwargs.get("task_name", "omat"), + }, + } + + if class_name == "CHGNetCalculator": + return { + "force_field_name": MLFF.CHGNet, + "calculator_kwargs": kwargs, + } + + if class_name == "M3GNetCalculator": + return { + "force_field_name": MLFF.M3GNet, + "calculator_kwargs": kwargs, + } + + # Try generic ASE calculator via monty dict + module = cfg.get("module", "") + if not module: + raise ValueError( + f"Model '{model_name}' with class '{class_name}' " + "is not supported by atomate2" + ) + return { + "force_field_name": { + "@module": module, + "@callable": class_name, + }, + "calculator_kwargs": kwargs, + } + + +def load_reference_data() -> dict[str, Any]: + """ + Load reference data for the quasiharmonic benchmark. + + Returns + ------- + dict[str, Any] + Reference data containing materials, conditions, and settings. + """ + with REFERENCE_FILE.open(encoding="utf-8") as f: + return json.load(f) + + +def load_structure(material: dict[str, Any]) -> Structure: + """ + Load a structure from the data directory. + + Parameters + ---------- + material + Material metadata with 'cif_file' or bulk parameters. + + Returns + ------- + Structure + Pymatgen Structure object. + """ + from pymatgen.core import Structure + + if "cif_file" in material: + cif_path = DATA_PATH / material["cif_file"] + if cif_path.exists(): + return Structure.from_file(str(cif_path)) + + # Build from bulk parameters using ASE and convert + from ase.build import bulk + + atoms = bulk( + material["symbols"], + material["lattice_type"], + a=material["a0"], + ) + return AseAtomsAdaptor.get_structure(atoms) + + +def run_qha_workflow( + structure: Structure, + model_name: str, + settings: dict[str, Any], + pressure_gpa: float = 0.0, + work_dir: Path | None = None, +) -> dict[str, Any]: + """ + Run atomate2 QHA workflow for a given structure and model. + + Parameters + ---------- + structure + Pymatgen Structure to run QHA on. + model_name + Name of the ml-peg model to use. + settings + QHA workflow settings. + pressure_gpa + External pressure in GPa. + work_dir + Working directory for the workflow. If None, uses current directory. + + Returns + ------- + dict[str, Any] + QHA workflow results. + """ + from atomate2.forcefields.flows.phonons import PhononMaker + from atomate2.forcefields.flows.qha import ForceFieldQhaMaker + from atomate2.forcefields.jobs import ForceFieldRelaxMaker, ForceFieldStaticMaker + + # Get atomate2 configuration for this model + atomate2_cfg = get_atomate2_config(model_name) + force_field_name = atomate2_cfg["force_field_name"] + calculator_kwargs = atomate2_cfg["calculator_kwargs"] + + # Extract settings + volume_scale = settings.get("volume_scale_range", [-0.05, 0.05]) + n_volumes = settings.get("n_volumes", 10) + eos_type = settings.get("eos_type", "vinet") + fmax = settings.get("relax_fmax", 0.001) + temp_range = settings.get("temperature_range", [0, 500]) + temp_step = settings.get("temperature_step", 50) + min_length = settings.get("min_length", 10.0) + + # Create makers with the force field configuration + initial_relax_maker = ForceFieldRelaxMaker( + force_field_name=force_field_name, + relax_cell=True, + relax_kwargs={"fmax": fmax}, + calculator_kwargs=calculator_kwargs, + ) + + eos_relax_maker = ForceFieldRelaxMaker( + force_field_name=force_field_name, + relax_cell=False, # Fixed cell for EOS + relax_kwargs={"fmax": fmax}, + calculator_kwargs=calculator_kwargs, + ) + + phonon_static_maker = ForceFieldStaticMaker( + force_field_name=force_field_name, + calculator_kwargs=calculator_kwargs, + ) + phonon_static_maker.name = f"{model_name} phonon static" + + phonon_maker = PhononMaker( + generate_frequencies_eigenvectors_kwargs={ + "tmin": temp_range[0], + "tmax": temp_range[1], + "tstep": temp_step, + }, + bulk_relax_maker=None, # Already relaxed + born_maker=None, # Skip Born charges for ML potentials + static_energy_maker=phonon_static_maker, + phonon_displacement_maker=phonon_static_maker, + min_length=min_length, + ) + + # Create QHA flow + qha_maker = ForceFieldQhaMaker( + initial_relax_maker=initial_relax_maker, + eos_relax_maker=eos_relax_maker, + phonon_maker=phonon_maker, + linear_strain=tuple(volume_scale), + number_of_frames=n_volumes, + pressure=pressure_gpa if pressure_gpa != 0.0 else None, + t_max=temp_range[1], + ignore_imaginary_modes=False, + skip_analysis=False, + eos_type=eos_type, + min_length=min_length, + ) + + # Create flow + flow = qha_maker.make(structure=structure) + + # Set up job store + job_store = JobStore( + MemoryStore(), + additional_stores={"data": MemoryStore()}, + ) + + # Run locally with specified working directory + run_kwargs = {"ensure_success": True} + if work_dir is not None: + run_kwargs["root_dir"] = str(work_dir) + + responses = run_locally(flow, store=job_store, **run_kwargs) + + # Extract the PhononQHADoc from the last job's output + # The last job is the analyze_free_energy job that returns the QHA document + last_uuid = list(responses.keys())[-1] + last_response = responses[last_uuid] + # The response is a list, index 1 contains the output + qha_doc = last_response[1].output + + return {"qha_doc": qha_doc} + + +def _interpolate_at_temperature( + temps: list[float], + values: list[float] | None, + target_temp: float, +) -> float | None: + """ + Get value at target temperature using nearest neighbor interpolation. + + Parameters + ---------- + temps + Temperature values. + values + Property values (can be None). + target_temp + Target temperature. + + Returns + ------- + float | None + Interpolated value or None if no data. + """ + if not temps or not values: + return None + idx = min(range(len(temps)), key=lambda i: abs(temps[i] - target_temp)) + return values[idx] + + +def extract_qha_properties( + qha_doc: Any, + temperature: float, + n_atoms_conventional: int = 8, +) -> dict[str, float | None]: + """ + Extract QHA properties at a specific temperature from PhononQHADoc. + + Parameters + ---------- + qha_doc + PhononQHADoc from atomate2 workflow. + temperature + Target temperature in K. + n_atoms_conventional + Number of atoms in the conventional cell (for volume conversion). + Default is 8 for diamond structure. + + Returns + ------- + dict[str, float | None] + Extracted properties at target temperature. + """ + properties: dict[str, float | None] = { + "volume_per_atom": None, + "lattice_a": None, + "thermal_expansion": None, + "bulk_modulus": None, + "heat_capacity": None, + } + + if qha_doc is None: + return properties + + temps = getattr(qha_doc, "temperatures", None) or [] + if not temps: + return properties + + # Volume per atom (atomate2 outputs volume per atom directly) + vol_t = getattr(qha_doc, "volume_temperature", None) + vol_per_atom = _interpolate_at_temperature(temps, vol_t, temperature) + if vol_per_atom is not None: + properties["volume_per_atom"] = vol_per_atom + # Lattice constant from conventional cell volume + properties["lattice_a"] = (vol_per_atom * n_atoms_conventional) ** (1 / 3) + + # Thermal expansion (K^-1, convert to 10^-6 K^-1) + te = getattr(qha_doc, "thermal_expansion", None) + te_value = _interpolate_at_temperature(temps, te, temperature) + if te_value is not None: + properties["thermal_expansion"] = te_value * 1e6 + + # Bulk modulus (GPa) + bm = getattr(qha_doc, "bulk_modulus_temperature", None) + bm_value = _interpolate_at_temperature(temps, bm, temperature) + if bm_value is not None: + properties["bulk_modulus"] = bm_value + + # Heat capacity (J/mol·K) + cp = getattr(qha_doc, "heat_capacity_p_numerical", None) + cp_value = _interpolate_at_temperature(temps, cp, temperature) + if cp_value is not None: + properties["heat_capacity"] = cp_value + + return properties + + +@pytest.mark.slow +@pytest.mark.parametrize("model_name", MODELS) +def test_quasiharmonic(model_name: str) -> None: + """ + Run quasiharmonic benchmark for a given MLIP using atomate2. + + Parameters + ---------- + model_name + Name of the model from ml-peg models registry. + """ + # Check if model is supported + try: + get_atomate2_config(model_name) + except ValueError as err: + pytest.skip(str(err)) + + # Load reference data + ref_data = load_reference_data() + materials = {mat["name"]: mat for mat in ref_data["materials"]} + conditions = ref_data["conditions"] + settings = ref_data["qha_settings"] + + # Create output directory + model_out_dir = OUT_PATH / model_name + model_out_dir.mkdir(parents=True, exist_ok=True) + + # Create temporary directory for intermediate workflow files + temp_base_dir = model_out_dir / "tmp" + temp_base_dir.mkdir(parents=True, exist_ok=True) + + results_list = [] + + for condition in conditions: + material_name = condition["material"] + material = materials[material_name] + temperature = condition["temperature_K"] + pressure = condition["pressure_GPa"] + + # Load structure + structure = load_structure(material) + + # Create unique temporary directory for this calculation + calc_id = f"{material_name}_T{temperature}_P{pressure}_{uuid.uuid4().hex[:8]}" + calc_work_dir = temp_base_dir / calc_id + calc_work_dir.mkdir(parents=True, exist_ok=True) + + # Run workflow + try: + workflow_result = run_qha_workflow( + structure, + model_name, + settings, + pressure_gpa=pressure, + work_dir=calc_work_dir, + ) + + # Extract predictions at target temperature + qha_doc = workflow_result.get("qha_doc") + properties = extract_qha_properties(qha_doc, temperature) + + results_list.append( + { + "material": material_name, + "temperature_K": temperature, + "pressure_GPa": pressure, + "ref_lattice_a": condition["ref_lattice_a"], + "pred_lattice_a": properties["lattice_a"], + "ref_volume_per_atom": condition.get("ref_volume_per_atom"), + "pred_volume_per_atom": properties["volume_per_atom"], + "ref_thermal_expansion_1e6_K": condition.get( + "ref_thermal_expansion_1e6_K" + ), + "pred_thermal_expansion_1e6_K": properties["thermal_expansion"], + "ref_bulk_modulus_GPa": condition.get("ref_bulk_modulus_GPa"), + "pred_bulk_modulus_GPa": properties["bulk_modulus"], + "ref_heat_capacity_J_mol_K": condition.get( + "ref_heat_capacity_J_mol_K" + ), + "pred_heat_capacity_J_mol_K": properties["heat_capacity"], + "status": "success", + } + ) + + # Save full workflow results + results_file = ( + model_out_dir / f"{material_name}_T{temperature}_P{pressure}_qha.json" + ) + with results_file.open("w") as f: + # Convert to JSON-serializable format + json.dump( + {"properties": properties, "condition": condition}, + f, + indent=2, + default=str, + ) + + except Exception as e: + results_list.append( + { + "material": material_name, + "temperature_K": temperature, + "pressure_GPa": pressure, + "ref_lattice_a": condition["ref_lattice_a"], + "pred_lattice_a": None, + "status": "failed", + "error": str(e), + } + ) + + # Save results summary + df = pd.DataFrame(results_list) + df.to_csv(model_out_dir / "results.csv", index=False) + + # Also save as JSON for more detailed data + with (model_out_dir / "results.json").open("w") as f: + json.dump(results_list, f, indent=2) diff --git a/pyproject.toml b/pyproject.toml index 64a36ff30..52bd60519 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ dependencies = [ "kaleido>=1.0.0", "mlipx<0.2,>=0.1.5", "scikit-learn>=1.7.1", - "typer<1.0.0,>=0.19.1", + "typer>=0.19.1,<1.0.0", "matcalc", "matminer", "MDAnalysis", @@ -64,6 +64,10 @@ orb = [ pet-mad = [ "pet-mad == 1.4.4; sys_platform != 'win32'" ] +qha = [ + "atomate2>=0.0.19", + "jobflow>=0.1.18", +] uma = [ "fairchem-core == 2.10.0", ] diff --git a/uv.lock b/uv.lock index f828ab629..255775523 100644 --- a/uv.lock +++ b/uv.lock @@ -572,23 +572,44 @@ name = "atomate2" version = "0.0.21" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version < '3.11' and sys_platform == 'win32'", - "python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux'", - "python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32'", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version < '3.11' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", ] dependencies = [ - { name = "click", marker = "python_full_version < '3.11'" }, - { name = "custodian", marker = "python_full_version < '3.11'" }, - { name = "emmet-core", version = "0.85.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "jobflow", marker = "python_full_version < '3.11'" }, - { name = "monty", marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "pydantic", marker = "python_full_version < '3.11'" }, - { name = "pydantic-settings", marker = "python_full_version < '3.11'" }, - { name = "pymatgen", marker = "python_full_version < '3.11'" }, - { name = "pymongo", marker = "python_full_version < '3.11'" }, - { name = "pyyaml", marker = "python_full_version < '3.11'" }, + { name = "click", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "custodian", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "emmet-core", version = "0.85.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "jobflow", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "monty", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "numpy", version = "1.26.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and extra == 'extra-6-ml-peg-grace') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and extra != 'extra-6-ml-peg-grace') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pydantic", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pydantic-settings", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pymatgen", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pymongo", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pyyaml", marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/36/a6/0e972ce70e0f17471c527f0645038dbc579f0026f4da549079de2d3f7c66/atomate2-0.0.21.tar.gz", hash = "sha256:3f94e85460cb5a08fe3f49507a98d0a97343ff665fce6c1bd82381afbdf7d313", size = 367588, upload-time = "2025-06-05T16:42:32.296Z" } wheels = [ @@ -600,35 +621,116 @@ name = "atomate2" version = "0.0.23" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "python_full_version >= '3.14' and sys_platform == 'win32'", - "python_full_version == '3.13.*' and sys_platform == 'win32'", - "python_full_version == '3.12.*' and sys_platform == 'win32'", - "python_full_version == '3.11.*' and sys_platform == 'win32'", - "python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux'", - "python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32'", - "python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32'", - "python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32'", - "python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux'", - "python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32'", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra == 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra == 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.12.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma'", + "(python_full_version >= '3.14' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version >= '3.14' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.13.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.13.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.12.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", + "(python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma') or (python_full_version == '3.11.*' and sys_platform != 'linux' and sys_platform != 'win32' and extra != 'extra-6-ml-peg-grace' and extra != 'extra-6-ml-peg-mace' and extra != 'extra-6-ml-peg-mattersim' and extra != 'extra-6-ml-peg-uma')", ] dependencies = [ - { name = "click", marker = "python_full_version >= '3.11'" }, - { name = "custodian", marker = "python_full_version >= '3.11'" }, - { name = "emmet-core", version = "0.86.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "jobflow", marker = "python_full_version >= '3.11'" }, - { name = "monty", marker = "python_full_version >= '3.11'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, - { name = "pydantic-settings", marker = "python_full_version >= '3.11'" }, - { name = "pymatgen", marker = "python_full_version >= '3.11'" }, - { name = "pymongo", marker = "python_full_version >= '3.11'" }, - { name = "pyyaml", marker = "python_full_version >= '3.11'" }, + { name = "click", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "custodian", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "emmet-core", version = "0.86.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "jobflow", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "monty", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "numpy", version = "1.26.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-6-ml-peg-grace') or (python_full_version < '3.11' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (python_full_version < '3.11' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (python_full_version < '3.11' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (python_full_version < '3.11' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma') or (python_full_version >= '3.13' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (python_full_version >= '3.13' and extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (python_full_version >= '3.13' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (python_full_version >= '3.13' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma') or (extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra != 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' or (python_full_version >= '3.11' and extra != 'extra-6-ml-peg-grace') or (python_full_version < '3.11' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (python_full_version < '3.11' and extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pydantic", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pydantic-settings", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pymatgen", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pymongo", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "pyyaml", marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/8a/41/de55c6f2840e125b62903cc7a010ca303becd9a8ca446bb66d4c574e099d/atomate2-0.0.23.tar.gz", hash = "sha256:473294553fa5c9373a32cb536a18df72a6b6725d151c3851119fbf2e0543c2cf", size = 390240, upload-time = "2025-12-03T22:40:13.229Z" } wheels = [ @@ -2603,6 +2705,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/35/a8/365059bbcd4572cbc41de17fd5b682be5868b218c3c5479071865cab9078/entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f", size = 5294, upload-time = "2022-02-02T21:30:26.024Z" }, ] +[[package]] +name = "et-xmlfile" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234, upload-time = "2024-10-25T17:25:40.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, +] + [[package]] name = "eventlet" version = "0.40.4" @@ -4071,8 +4182,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "maggma" }, { name = "monty" }, - { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, - { name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, { name = "pydantic" }, { name = "pydantic-settings" }, { name = "pydash" }, @@ -4763,7 +4874,8 @@ dependencies = [ { name = "mongomock" }, { name = "monty" }, { name = "msgpack" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy", version = "1.26.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.13' and extra == 'extra-6-ml-peg-grace') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' or extra != 'extra-6-ml-peg-grace' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma')" }, { name = "orjson" }, { name = "pandas" }, { name = "pydantic" }, @@ -5998,6 +6110,7 @@ dependencies = [ { name = "mdanalysis", version = "2.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, { name = "mdanalysis", version = "2.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, { name = "mlipx" }, + { name = "openpyxl" }, { name = "scikit-learn", version = "1.7.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, { name = "scikit-learn", version = "1.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, { name = "tqdm" }, @@ -6029,6 +6142,11 @@ orb = [ pet-mad = [ { name = "pet-mad", marker = "sys_platform != 'win32' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, ] +qha = [ + { name = "atomate2", version = "0.0.21", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "atomate2", version = "0.0.23", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, + { name = "jobflow" }, +] uma = [ { name = "fairchem-core" }, ] @@ -6065,12 +6183,14 @@ prod = [ [package.metadata] requires-dist = [ + { name = "atomate2", marker = "extra == 'qha'", specifier = ">=0.0.19" }, { name = "boto3", specifier = ">=1.40.49,<2" }, { name = "chgnet", marker = "extra == 'chgnet'", specifier = "==0.4.0" }, { name = "dash", specifier = ">=3.1.1" }, { name = "deepmd-kit", marker = "extra == 'dpa3'", specifier = "==3.1.0" }, { name = "fairchem-core", marker = "extra == 'uma'", specifier = "==2.10.0" }, { name = "janus-core", specifier = ">=0.8.2,<1.0.0" }, + { name = "jobflow", marker = "extra == 'qha'", specifier = ">=0.1.18" }, { name = "kaleido", specifier = ">=1.0.0" }, { name = "mace-torch", marker = "extra == 'mace'", specifier = "==0.3.14" }, { name = "matcalc" }, @@ -6078,6 +6198,7 @@ requires-dist = [ { name = "mattersim", marker = "extra == 'mattersim'", specifier = "==1.2.0" }, { name = "mdanalysis" }, { name = "mlipx", specifier = ">=0.1.5,<0.2" }, + { name = "openpyxl" }, { name = "orb-models", marker = "python_full_version < '3.13' and sys_platform != 'win32' and extra == 'orb'", specifier = "==0.5.5" }, { name = "pet-mad", marker = "sys_platform != 'win32' and extra == 'pet-mad'", specifier = "==1.4.4" }, { name = "scikit-learn", specifier = ">=1.7.1" }, @@ -6086,7 +6207,7 @@ requires-dist = [ { name = "tqdm" }, { name = "typer", specifier = ">=0.19.1,<1.0.0" }, ] -provides-extras = ["chgnet", "d3", "dpa3", "grace", "mace", "mattersim", "orb", "pet-mad", "uma"] +provides-extras = ["chgnet", "d3", "dpa3", "grace", "mace", "mattersim", "orb", "pet-mad", "qha", "uma"] [package.metadata.requires-dev] dev = [ @@ -7337,6 +7458,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e3/94/1843518e420fa3ed6919835845df698c7e27e183cb997394e4a670973a65/omegaconf-2.3.0-py3-none-any.whl", hash = "sha256:7b4df175cdb08ba400f45cae3bdcae7ba8365db4d165fc65fd04b050ab63b46b", size = 79500, upload-time = "2022-12-08T20:59:19.686Z" }, ] +[[package]] +name = "openpyxl" +version = "3.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "et-xmlfile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464, upload-time = "2024-06-28T14:03:44.161Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910, upload-time = "2024-06-28T14:03:41.161Z" }, +] + [[package]] name = "opt-einsum" version = "3.4.0" @@ -9170,7 +9303,7 @@ name = "pynacl" version = "1.6.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, + { name = "cffi", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-grace' and extra == 'extra-6-ml-peg-uma') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-mattersim') or (extra == 'extra-6-ml-peg-mace' and extra == 'extra-6-ml-peg-uma')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d9/9a/4019b524b03a13438637b11538c82781a5eda427394380381af8f04f467a/pynacl-1.6.2.tar.gz", hash = "sha256:018494d6d696ae03c7e656e5e74cdfd8ea1326962cc401bcf018f1ed8436811c", size = 3511692, upload-time = "2026-01-01T17:48:10.851Z" } wheels = [