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..89f83ddb4 --- /dev/null +++ b/ml_peg/analysis/bulk_crystal/quasiharmonic/analyse_quasiharmonic.py @@ -0,0 +1,233 @@ +"""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_VOLUME = _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_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 +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 +@build_table( + filename=OUT_PATH / "quasiharmonic_metrics_table.json", + metric_tooltips=DEFAULT_TOOLTIPS, + thresholds=DEFAULT_THRESHOLDS, + weights=DEFAULT_WEIGHTS, +) +def metrics( + volume_per_atom_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 + ---------- + volume_per_atom_mae + Volume per atom MAE per model. + + Returns + ------- + dict[str, dict[str, float | None]] + Metrics dictionary. + """ + return { + "Volume per atom MAE": volume_per_atom_mae, + } + + +def test_quasiharmonic( + metrics: dict[str, dict[str, Any]], + qha_volume_per_atom: dict[str, list], +) -> None: + """ + Run quasiharmonic analysis test. + + Parameters + ---------- + metrics + Metrics dictionary. + qha_volume_per_atom + Volume per atom 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..82901fa1d --- /dev/null +++ b/ml_peg/analysis/bulk_crystal/quasiharmonic/metrics.yml @@ -0,0 +1,8 @@ +metrics: + 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.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..f482b386d --- /dev/null +++ b/ml_peg/app/bulk_crystal/quasiharmonic/app_quasiharmonic.py @@ -0,0 +1,79 @@ +"""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_volume_per_atom.json", "Volume per atom MAE", "volume"), + ] + + # 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 lattice constants and volume per atom using the " + "quasiharmonic approximation (QHA). Evaluates MLIP predictions against " + "experimental reference data at target temperature and pressure conditions." + ), + 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..11e1a93dc --- /dev/null +++ b/ml_peg/calcs/bulk_crystal/quasiharmonic/calc_quasiharmonic.py @@ -0,0 +1,475 @@ +""" +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.core import Structure +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 == "UPETCalculator": + # UPET - use monty dict format + return { + "force_field_name": { + "@module": "upet.calculator", + "@callable": "UPETCalculator", + }, + "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 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, +) -> 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. + + Returns + ------- + dict[str, float | None] + Extracted properties at target temperature. + """ + properties: dict[str, float | None] = { + "volume_per_atom": 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 + + 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 = Structure.from_file(DATA_PATH / material["cif_file"]) + + # 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_volume_per_atom": condition["ref_volume_per_atom"], + "pred_volume_per_atom": properties["volume_per_atom"], + "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, + "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/ml_peg/calcs/bulk_crystal/quasiharmonic/data/Si.cif b/ml_peg/calcs/bulk_crystal/quasiharmonic/data/Si.cif new file mode 100644 index 000000000..bd5a8c4cf --- /dev/null +++ b/ml_peg/calcs/bulk_crystal/quasiharmonic/data/Si.cif @@ -0,0 +1,218 @@ +# generated using pymatgen +data_Si +_symmetry_space_group_name_H-M Fd-3m +_cell_length_a 5.46872800 +_cell_length_b 5.46872800 +_cell_length_c 5.46872800 +_cell_angle_alpha 90.00000000 +_cell_angle_beta 90.00000000 +_cell_angle_gamma 90.00000000 +_symmetry_Int_Tables_number 227 +_chemical_formula_structural Si +_chemical_formula_sum Si8 +_cell_volume 163.55317139 +_cell_formula_units_Z 8 +loop_ + _symmetry_equiv_pos_site_id + _symmetry_equiv_pos_as_xyz + 1 'x, y, z' + 2 '-y+1/4, x+3/4, z+3/4' + 3 '-x, -y, z' + 4 'y+1/4, -x+3/4, z+3/4' + 5 'x, -y, -z' + 6 '-y+1/4, -x+3/4, -z+3/4' + 7 '-x, y, -z' + 8 'y+1/4, x+3/4, -z+3/4' + 9 'z, x, y' + 10 'z+1/4, -y+3/4, x+3/4' + 11 'z, -x, -y' + 12 'z+1/4, y+3/4, -x+3/4' + 13 '-z, x, -y' + 14 '-z+1/4, -y+3/4, -x+3/4' + 15 '-z, -x, y' + 16 '-z+1/4, y+3/4, x+3/4' + 17 'y, z, x' + 18 'x+1/4, z+3/4, -y+3/4' + 19 '-y, z, -x' + 20 '-x+1/4, z+3/4, y+3/4' + 21 '-y, -z, x' + 22 '-x+1/4, -z+3/4, -y+3/4' + 23 'y, -z, -x' + 24 'x+1/4, -z+3/4, y+3/4' + 25 '-x+1/4, -y+3/4, -z+3/4' + 26 'y, -x, -z' + 27 'x+1/4, y+3/4, -z+3/4' + 28 '-y, x, -z' + 29 '-x+1/4, y+3/4, z+3/4' + 30 'y, x, z' + 31 'x+1/4, -y+3/4, z+3/4' + 32 '-y, -x, z' + 33 '-z+1/4, -x+3/4, -y+3/4' + 34 '-z, y, -x' + 35 '-z+1/4, x+3/4, y+3/4' + 36 '-z, -y, x' + 37 'z+1/4, -x+3/4, y+3/4' + 38 'z, y, x' + 39 'z+1/4, x+3/4, -y+3/4' + 40 'z, -y, -x' + 41 '-y+1/4, -z+3/4, -x+3/4' + 42 '-x, -z, y' + 43 'y+1/4, -z+3/4, x+3/4' + 44 'x, -z, -y' + 45 'y+1/4, z+3/4, -x+3/4' + 46 'x, z, y' + 47 '-y+1/4, z+3/4, x+3/4' + 48 '-x, z, -y' + 49 'x+1/2, y+1/2, z' + 50 '-y+3/4, x+1/4, z+3/4' + 51 '-x+1/2, -y+1/2, z' + 52 'y+3/4, -x+1/4, z+3/4' + 53 'x+1/2, -y+1/2, -z' + 54 '-y+3/4, -x+1/4, -z+3/4' + 55 '-x+1/2, y+1/2, -z' + 56 'y+3/4, x+1/4, -z+3/4' + 57 'z+1/2, x+1/2, y' + 58 'z+3/4, -y+1/4, x+3/4' + 59 'z+1/2, -x+1/2, -y' + 60 'z+3/4, y+1/4, -x+3/4' + 61 '-z+1/2, x+1/2, -y' + 62 '-z+3/4, -y+1/4, -x+3/4' + 63 '-z+1/2, -x+1/2, y' + 64 '-z+3/4, y+1/4, x+3/4' + 65 'y+1/2, z+1/2, x' + 66 'x+3/4, z+1/4, -y+3/4' + 67 '-y+1/2, z+1/2, -x' + 68 '-x+3/4, z+1/4, y+3/4' + 69 '-y+1/2, -z+1/2, x' + 70 '-x+3/4, -z+1/4, -y+3/4' + 71 'y+1/2, -z+1/2, -x' + 72 'x+3/4, -z+1/4, y+3/4' + 73 '-x+3/4, -y+1/4, -z+3/4' + 74 'y+1/2, -x+1/2, -z' + 75 'x+3/4, y+1/4, -z+3/4' + 76 '-y+1/2, x+1/2, -z' + 77 '-x+3/4, y+1/4, z+3/4' + 78 'y+1/2, x+1/2, z' + 79 'x+3/4, -y+1/4, z+3/4' + 80 '-y+1/2, -x+1/2, z' + 81 '-z+3/4, -x+1/4, -y+3/4' + 82 '-z+1/2, y+1/2, -x' + 83 '-z+3/4, x+1/4, y+3/4' + 84 '-z+1/2, -y+1/2, x' + 85 'z+3/4, -x+1/4, y+3/4' + 86 'z+1/2, y+1/2, x' + 87 'z+3/4, x+1/4, -y+3/4' + 88 'z+1/2, -y+1/2, -x' + 89 '-y+3/4, -z+1/4, -x+3/4' + 90 '-x+1/2, -z+1/2, y' + 91 'y+3/4, -z+1/4, x+3/4' + 92 'x+1/2, -z+1/2, -y' + 93 'y+3/4, z+1/4, -x+3/4' + 94 'x+1/2, z+1/2, y' + 95 '-y+3/4, z+1/4, x+3/4' + 96 '-x+1/2, z+1/2, -y' + 97 'x+1/2, y, z+1/2' + 98 '-y+3/4, x+3/4, z+1/4' + 99 '-x+1/2, -y, z+1/2' + 100 'y+3/4, -x+3/4, z+1/4' + 101 'x+1/2, -y, -z+1/2' + 102 '-y+3/4, -x+3/4, -z+1/4' + 103 '-x+1/2, y, -z+1/2' + 104 'y+3/4, x+3/4, -z+1/4' + 105 'z+1/2, x, y+1/2' + 106 'z+3/4, -y+3/4, x+1/4' + 107 'z+1/2, -x, -y+1/2' + 108 'z+3/4, y+3/4, -x+1/4' + 109 '-z+1/2, x, -y+1/2' + 110 '-z+3/4, -y+3/4, -x+1/4' + 111 '-z+1/2, -x, y+1/2' + 112 '-z+3/4, y+3/4, x+1/4' + 113 'y+1/2, z, x+1/2' + 114 'x+3/4, z+3/4, -y+1/4' + 115 '-y+1/2, z, -x+1/2' + 116 '-x+3/4, z+3/4, y+1/4' + 117 '-y+1/2, -z, x+1/2' + 118 '-x+3/4, -z+3/4, -y+1/4' + 119 'y+1/2, -z, -x+1/2' + 120 'x+3/4, -z+3/4, y+1/4' + 121 '-x+3/4, -y+3/4, -z+1/4' + 122 'y+1/2, -x, -z+1/2' + 123 'x+3/4, y+3/4, -z+1/4' + 124 '-y+1/2, x, -z+1/2' + 125 '-x+3/4, y+3/4, z+1/4' + 126 'y+1/2, x, z+1/2' + 127 'x+3/4, -y+3/4, z+1/4' + 128 '-y+1/2, -x, z+1/2' + 129 '-z+3/4, -x+3/4, -y+1/4' + 130 '-z+1/2, y, -x+1/2' + 131 '-z+3/4, x+3/4, y+1/4' + 132 '-z+1/2, -y, x+1/2' + 133 'z+3/4, -x+3/4, y+1/4' + 134 'z+1/2, y, x+1/2' + 135 'z+3/4, x+3/4, -y+1/4' + 136 'z+1/2, -y, -x+1/2' + 137 '-y+3/4, -z+3/4, -x+1/4' + 138 '-x+1/2, -z, y+1/2' + 139 'y+3/4, -z+3/4, x+1/4' + 140 'x+1/2, -z, -y+1/2' + 141 'y+3/4, z+3/4, -x+1/4' + 142 'x+1/2, z, y+1/2' + 143 '-y+3/4, z+3/4, x+1/4' + 144 '-x+1/2, z, -y+1/2' + 145 'x, y+1/2, z+1/2' + 146 '-y+1/4, x+1/4, z+1/4' + 147 '-x, -y+1/2, z+1/2' + 148 'y+1/4, -x+1/4, z+1/4' + 149 'x, -y+1/2, -z+1/2' + 150 '-y+1/4, -x+1/4, -z+1/4' + 151 '-x, y+1/2, -z+1/2' + 152 'y+1/4, x+1/4, -z+1/4' + 153 'z, x+1/2, y+1/2' + 154 'z+1/4, -y+1/4, x+1/4' + 155 'z, -x+1/2, -y+1/2' + 156 'z+1/4, y+1/4, -x+1/4' + 157 '-z, x+1/2, -y+1/2' + 158 '-z+1/4, -y+1/4, -x+1/4' + 159 '-z, -x+1/2, y+1/2' + 160 '-z+1/4, y+1/4, x+1/4' + 161 'y, z+1/2, x+1/2' + 162 'x+1/4, z+1/4, -y+1/4' + 163 '-y, z+1/2, -x+1/2' + 164 '-x+1/4, z+1/4, y+1/4' + 165 '-y, -z+1/2, x+1/2' + 166 '-x+1/4, -z+1/4, -y+1/4' + 167 'y, -z+1/2, -x+1/2' + 168 'x+1/4, -z+1/4, y+1/4' + 169 '-x+1/4, -y+1/4, -z+1/4' + 170 'y, -x+1/2, -z+1/2' + 171 'x+1/4, y+1/4, -z+1/4' + 172 '-y, x+1/2, -z+1/2' + 173 '-x+1/4, y+1/4, z+1/4' + 174 'y, x+1/2, z+1/2' + 175 'x+1/4, -y+1/4, z+1/4' + 176 '-y, -x+1/2, z+1/2' + 177 '-z+1/4, -x+1/4, -y+1/4' + 178 '-z, y+1/2, -x+1/2' + 179 '-z+1/4, x+1/4, y+1/4' + 180 '-z, -y+1/2, x+1/2' + 181 'z+1/4, -x+1/4, y+1/4' + 182 'z, y+1/2, x+1/2' + 183 'z+1/4, x+1/4, -y+1/4' + 184 'z, -y+1/2, -x+1/2' + 185 '-y+1/4, -z+1/4, -x+1/4' + 186 '-x, -z+1/2, y+1/2' + 187 'y+1/4, -z+1/4, x+1/4' + 188 'x, -z+1/2, -y+1/2' + 189 'y+1/4, z+1/4, -x+1/4' + 190 'x, z+1/2, y+1/2' + 191 '-y+1/4, z+1/4, x+1/4' + 192 '-x, z+1/2, -y+1/2' +loop_ + _atom_site_type_symbol + _atom_site_label + _atom_site_symmetry_multiplicity + _atom_site_fract_x + _atom_site_fract_y + _atom_site_fract_z + _atom_site_occupancy + Si Si0 8 0.00000000 0.00000000 0.50000000 1 diff --git a/ml_peg/calcs/bulk_crystal/quasiharmonic/data/quasiharmonic_reference.json b/ml_peg/calcs/bulk_crystal/quasiharmonic/data/quasiharmonic_reference.json new file mode 100644 index 000000000..ab8524fb2 --- /dev/null +++ b/ml_peg/calcs/bulk_crystal/quasiharmonic/data/quasiharmonic_reference.json @@ -0,0 +1,40 @@ +{ + "materials": [ + { + "name": "Si", + "cif_file": "Si.cif", + "description": "Silicon - diamond cubic structure" + } + ], + "conditions": [ + { + "material": "Si", + "temperature_K": 300, + "pressure_GPa": 0.0, + "ref_volume_per_atom": 20.0225, + "level_of_theory": "Experimental", + "reference": "Thermophysical properties of matter, Vol. 12-13, TPRC Data Series" + } + ], + "qha_settings": { + "temperature_range": [290, 320], + "temperature_step": 10, + "volume_scale_range": [-0.05, 0.05], + "n_volumes": 10, + "eos_type": "vinet", + "supercell_matrix": [5, 5, 5], + "phonon_displacement": 0.01, + "phonon_mesh": [10, 10, 10], + "relax_fmax": 0.0005, + "relax_steps": 500, + "min_length": 10.0 + }, + "metadata": { + "benchmark_name": "Quasiharmonic Approximation", + "description": "Benchmark for evaluating MLIP predictions of temperature-dependent thermodynamic properties using the quasiharmonic approximation (QHA). Each data point is a (structure, temperature, pressure) triple with experimental reference values.", + "version": "1.0.0", + "properties_computed": [ + "equilibrium_volume" + ] + } +} diff --git a/ml_peg/models/get_models.py b/ml_peg/models/get_models.py index 523fa7aaf..7cb56e399 100644 --- a/ml_peg/models/get_models.py +++ b/ml_peg/models/get_models.py @@ -137,7 +137,7 @@ def load_models(models: None | str | Iterable = None) -> dict[str, Any]: trained_on_d3=cfg.get("trained_on_d3", False), d3_kwargs=cfg.get("d3_kwargs", {}), ) - elif cfg["class_name"] == "PETMADCalculator": + elif cfg["class_name"] == "UPETCalculator": loaded_models[name] = PetMadCalc( module=cfg["module"], class_name=cfg["class_name"], diff --git a/ml_peg/models/models.py b/ml_peg/models/models.py index 002f0959d..287fc2ac1 100644 --- a/ml_peg/models/models.py +++ b/ml_peg/models/models.py @@ -96,7 +96,7 @@ def get_calculator(self, **kwargs) -> Calculator: @dataclasses.dataclass(kw_only=True) class PetMadCalc(GenericASECalc): - """Dataclass for PET-MAD calculator.""" + """Dataclass for UPET calculator.""" def get_calculator(self, **kwargs) -> Calculator: """ @@ -112,12 +112,13 @@ def get_calculator(self, **kwargs) -> Calculator: Calculator Loaded ASE Calculator. """ - if self.default_dtype is not None: - kwargs["dtype"] = self.default_dtype - else: - kwargs["dtype"] = self.default_dtype + from upet.calculator import UPETCalculator - return MlipxGenericASECalc.get_calculator(self, **kwargs) + calc_kwargs = {**self.kwargs} + if self.device: + calc_kwargs.setdefault("device", str(self.device)) + calc = UPETCalculator(**calc_kwargs) + return self.add_d3_calculator(calc) # https://github.com/orbital-materials/orb-models diff --git a/ml_peg/models/models.yml b/ml_peg/models/models.yml index 77e54a16b..3279724bf 100644 --- a/ml_peg/models/models.yml +++ b/ml_peg/models/models.yml @@ -160,13 +160,13 @@ orb-v3-consv-inf-omat: # task_name: "omol" pet-mad: - module: pet_mad.calculator - class_name: PETMADCalculator + module: upet.calculator + class_name: UPETCalculator device: "cpu" default_dtype: float32 trained_on_d3: false level_of_theory: PBEsol kwargs: - version: "v1.0.2" + model: "pet-mad-s" d3_kwargs: xc: pbesol 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 = [