Skip to content

Add WiSE electrolyte benchmark (density, X-ray S(q), Li-O RDF) - #445

Open
LucaBrugnoli wants to merge 13 commits into
ddmms:mainfrom
LucaBrugnoli:wise-electrolytes-benchmark
Open

Add WiSE electrolyte benchmark (density, X-ray S(q), Li-O RDF)#445
LucaBrugnoli wants to merge 13 commits into
ddmms:mainfrom
LucaBrugnoli:wise-electrolytes-benchmark

Conversation

@LucaBrugnoli

@LucaBrugnoli LucaBrugnoli commented Apr 3, 2026

Copy link
Copy Markdown

Pre-review checklist for PR author

Summary

New benchmark for 21 molal LiTFSI/H₂O water-in-salt electrolyte (WiSE), evaluating MLIP foundation models on three
experimental observables:

  1. Density — NPT equilibrium density vs Gilbert et al., JCED 62, 2056
    (2017)
  2. X-ray S(q) — Structure factor R-factor vs SAXS data, Zhang et al., JPCB 125, 4501
    (2021)
    . Computed via dynasor.
  3. Li-O RDF — Coordination numbers (Li-O_water, Li-O_TFSI) vs Watanabe et al., JPCB 125, 7477
    (2021)

Further details on the simulation protocol and MLIP assessment for this system: L. Brugnoli, arXiv:2603.22099
(2026)
.

Linked issue

Resolves #304

Progress

  • Calculations
  • Analysis
  • Application
  • Documentation

Note: Trajectory data (~500 MB, extxyz) needs to be uploaded to the ml-peg S3 bucket. Data files are available on
request.

Testing

Tested on 6 models: matpes-r2scan, mace-mpa-0-medium, mace-omat-0-medium, mace-mp-0b3, mace-mh-1-omat,
mace-mh-1-omol.

Requirement: ASE < 3.28 (3.28.0 has a bug in ase.io.extxyz.ixyzchunks). Tests run with --noconftest.

New decorators/callbacks

No new callbacks required. The RDF app uses existing plot_from_table_column from ml-peg utils.

@LucaBrugnoli

Copy link
Copy Markdown
Author

@joehart2001 The code and analysis are complete. The remaining step I think is uploading the trajectory data to
the S3 bucket. Could you let me know how to proceed with the upload, please?

@joehart2001

Copy link
Copy Markdown
Collaborator

@joehart2001 The code and analysis are complete. The remaining step I think is uploading the trajectory data to the S3 bucket. Could you let me know how to proceed with the upload, please?

Hi @LucaBrugnoli thanks for the PR! The easiest way is to attach a zip file containing your data to this PR and I can upload it. Hopefully that works

@LucaBrugnoli

Copy link
Copy Markdown
Author

Here are the 6 data files, one per model.
Each zip contains:

  • nvt_trajectory.extxyz — 501-frame NVT trajectory (50 ps, p64_w170 cell, 1534 atoms), used for both the X-ray S(q) and
    RDF benchmarks
  • density.json — NPT equilibrium density data (p16_w42 cell, 50 ps), used for the density benchmark

The expected directory structure on S3 is:
wise_electrolytes/xray_sf/{model}/nvt_trajectory.extxyz
wise_electrolytes/density/{model}/density.json

Let me know if anything looks off or if you need the data in a different format

mace-mh-1-omat.zip
mace-mh-1-omol.zip
mace-mp-0b3.zip
mace-mpa-0-medium.zip
mace-omat-0-medium.zip
matpes-r2scan.zip

@ElliottKasoar ElliottKasoar added the new benchmark Proposals and suggestions for new benchmarks label Apr 9, 2026
@LucaBrugnoli
LucaBrugnoli force-pushed the wise-electrolytes-benchmark branch from dba4e00 to ef5aecc Compare April 16, 2026 17:40
return results


def normalize_metric(value: float, good: float, bad: float) -> float:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will be taken care of when you build the table using the decorator. you could define your own function if you dont want to use our defualt, see the docs

APP_ROOT = Path(__file__).resolve().parents[3] / "app"
OUT_PATH = APP_ROOT / "data" / "wise_electrolytes" / "density"

MODELS = [

@joehart2001 joehart2001 Apr 21, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usually we import this to get all the models. this is better for in the future when we have more models than now.

from ml_peg.models.get_models import load_models
from ml_peg.models.models import current_models

# --- Metrics table -----------------------------------------------------------


def build_metrics_table(data: dict[str, dict]) -> dict:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have decorators to build this automatically, see the tutorial

@joehart2001

Copy link
Copy Markdown
Collaborator

Hi @LucaBrugnoli thanks for the PR! From what i understand, you've provided us with NVT trajectories for each model and then your calc script takes these trajectories to calculate e.g. the rdf etc. Thank you for providing these trajectories! However, to make this test not rely on you computing these for each new model that is added in the future (as im sure you would prefer us running them for you!), I think we need to do some reshuffling.

The ideal workflow would be:
calc:

  • this is where your reproducable NVT script would go, and you can look at examples such as PR Aqueous Iron Chloride Oxidation States #360 (direct link to line) for an easy way to do this with e.g. Janus (used for many of our MD benchmarks).
  • To keep things modular and separated, we like to keep anything that could be considered analysis in the anlysis scripts only. The PR linked computes the rdf as part of the calc, so you could do this too, or separate it out into the analysis script. This format will mean you will only have one directory for your benchmark instead of three.

analysis

  • ive left some comments about using our helpers and decorators to help be consistent and also keep up with future changes to table builidng etc.

app

  • overall looks good, just need to add the docs link later. do you think structure visualisation would be useful in this benchmark? if so we could help add that

LucaBrugnoli pushed a commit to LucaBrugnoli/ml-peg that referenced this pull request Apr 26, 2026
- Merge density / rdf / xray_sf into a single litfsi_h2o_21m benchmark
  under ml_peg/{calcs,analysis,app}/wise_electrolytes/litfsi_h2o_21m/.
- Adopt the standard ml-peg patterns in the analysis and calc scripts:
  load_models(current_models) for model discovery, @build_table for
  the metrics table, and metrics.yml for thresholds/tooltips/weights.
- Add a Janus recast of the LAMMPS+symmetrix Adastra production protocol
  in ml_peg/calcs/wise_electrolytes/md_reference/calc_md_reference.py
  (pytest-skipped reference; documents the exact MD parameters).
- Add the docs page docs/source/user_guide/benchmarks/wise_electrolytes.rst
  (and toctree entry) and wire the app docs_url to it.
- Update the parent wise_electrolytes.yml to a single benchmark weight.
Comment thread ml_peg/calcs/wise_electrolytes/md_reference/calc_md_reference.py Outdated
LucaBrugnoli pushed a commit to LucaBrugnoli/ml-peg that referenced this pull request Apr 28, 2026
- Switch NPT (Melchionna) -> NPT_MTK (Martyna-Tobias-Klein) so the
  janus reference matches the LAMMPS fix npt formulation used in
  production. Pass thermostat_chain=3 and barostat_chain=3 explicitly,
  matching the LAMMPS default chain length.
- Replace pytest.mark.skip with pytest.mark.very_slow per Joseph's
  review on PR ddmms#445: the reference protocol is now opt-in via
  --run-very-slow rather than unconditionally skipped, so it can be
  exercised when validating new models.
@joehart2001

Copy link
Copy Markdown
Collaborator

Thanks for the code updates! I think this test could also be well suited in the molecular dynamics category instead of its own one as its quite specific, opinions @ElliottKasoar?

@LucaBrugnoli

LucaBrugnoli commented Apr 28, 2026

Copy link
Copy Markdown
Author

Thanks for both messages, I'll let you and @ElliottKasoar decide on the location; happy with whichever directory you prefer.
On the LAMMPS/ASE reproducibility question: I'm currently running the protocol on a cluster with GPUs MI250X, with mace-mp-0b3 and mace-matpes-r2scan to validate it empirically.
I've tried to match the integrator formulations exactly, NVT_NH for LAMMPS fix nvt (Nosé–Hoover chain, length 3) and NPT_MTK for fix npt iso (Martyna–Tobias–Klein chain, length 3), with the same TDAMP=50 fs / PDAMP=500 fs and dt=0.5 fs.
Even so, I don't expect bit-for-bit trajectory agreement: the LAMMPS production used the SymmetriX/Kokkos MACE kernels, while ASE/janus uses the reference PyTorch path; combined with different RNG-seeded initial velocities, chaotic divergence is unavoidable. What should agree, within sampling uncertainty, are the statistical observables, i.e the equilibrium density, RDFs, coordination numbers, and S(q).
I'll update the PR as soon as the runs are done with the LAMMPS/ASE comparison and the wallclock cost per ns of MD on a single MI250X GCD, so we have a realistic estimate for running the marker across the registry.

LucaBrugnoli added a commit to LucaBrugnoli/ml-peg that referenced this pull request May 13, 2026
- Merge density / rdf / xray_sf into a single litfsi_h2o_21m benchmark
  under ml_peg/{calcs,analysis,app}/wise_electrolytes/litfsi_h2o_21m/.
- Adopt the standard ml-peg patterns in the analysis and calc scripts:
  load_models(current_models) for model discovery, @build_table for
  the metrics table, and metrics.yml for thresholds/tooltips/weights.
- Add a Janus recast of the LAMMPS+symmetrix Adastra production protocol
  in ml_peg/calcs/wise_electrolytes/md_reference/calc_md_reference.py
  (pytest-skipped reference; documents the exact MD parameters).
- Add the docs page docs/source/user_guide/benchmarks/wise_electrolytes.rst
  (and toctree entry) and wire the app docs_url to it.
- Update the parent wise_electrolytes.yml to a single benchmark weight.
LucaBrugnoli added a commit to LucaBrugnoli/ml-peg that referenced this pull request May 13, 2026
- Switch NPT (Melchionna) -> NPT_MTK (Martyna-Tobias-Klein) so the
  janus reference matches the LAMMPS fix npt formulation used in
  production. Pass thermostat_chain=3 and barostat_chain=3 explicitly,
  matching the LAMMPS default chain length.
- Replace pytest.mark.skip with pytest.mark.very_slow per Joseph's
  review on PR ddmms#445: the reference protocol is now opt-in via
  --run-very-slow rather than unconditionally skipped, so it can be
  exercised when validating new models.
@LucaBrugnoli
LucaBrugnoli force-pushed the wise-electrolytes-benchmark branch from f3f66f7 to b3816eb Compare May 13, 2026 10:17
Three sub-benchmarks for 21 m LiTFSI/H2O with 6 MLIP models
(matpes-r2scan, mace-mpa-0-medium, mace-omat-0-medium, mace-mp-0b3,
mace-mh-1-omat, mace-mh-1-omol):
- NPT density vs Gilbert et al. JCED 2017
- X-ray structure factor S(q) vs SAXS experiment
- Li-O RDF coordination numbers vs Watanabe et al. JPCB 2021
- Merge density / rdf / xray_sf into a single litfsi_h2o_21m benchmark
  under ml_peg/{calcs,analysis,app}/wise_electrolytes/litfsi_h2o_21m/.
- Adopt the standard ml-peg patterns in the analysis and calc scripts:
  load_models(current_models) for model discovery, @build_table for
  the metrics table, and metrics.yml for thresholds/tooltips/weights.
- Add a Janus recast of the LAMMPS+symmetrix Adastra production protocol
  in ml_peg/calcs/wise_electrolytes/md_reference/calc_md_reference.py
  (pytest-skipped reference; documents the exact MD parameters).
- Add the docs page docs/source/user_guide/benchmarks/wise_electrolytes.rst
  (and toctree entry) and wire the app docs_url to it.
- Update the parent wise_electrolytes.yml to a single benchmark weight.
- Switch NPT (Melchionna) -> NPT_MTK (Martyna-Tobias-Klein) so the
  janus reference matches the LAMMPS fix npt formulation used in
  production. Pass thermostat_chain=3 and barostat_chain=3 explicitly,
  matching the LAMMPS default chain length.
- Replace pytest.mark.skip with pytest.mark.very_slow per Joseph's
  review on PR ddmms#445: the reference protocol is now opt-in via
  --run-very-slow rather than unconditionally skipped, so it can be
  exercised when validating new models.
- SAVGOL_WINDOW: 27 → 5 in calc_litfsi_h2o_21m.py (physical width 0.54
  Å⁻¹ → 0.10 Å⁻¹), matching TRAVIS smoothing for dynasor/TRAVIS agreement
- Add mace-mh-1-omat and mace-mh-1-omol to models.yml
- Reset cubic cell to diagonal form after FIRE minimisation in md_reference
@LucaBrugnoli
LucaBrugnoli force-pushed the wise-electrolytes-benchmark branch from b3816eb to e198469 Compare May 19, 2026 14:52
@LucaBrugnoli
LucaBrugnoli marked this pull request as ready for review May 21, 2026 01:12
Comment thread docs/source/user_guide/benchmarks/index.rst
Comment thread ml_peg/models/models.yml

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert these changes? We will test these models, but we make the changes locally (or would do this change as a separate PR, now that MACE has released these properly)

Comment on lines +143 to +144
model.default_dtype = "float64"
calc = model.get_calculator()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
model.default_dtype = "float64"
calc = model.get_calculator()
calc = model.get_calculator(precision="high")

This is effectively the same, but more future-proof.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be combined with calc_litfsi_h2o_21m.py? Generally the idea is to have ml_peg/calcs/[category]/[benchmark]/calc_[benchmark].py,, but this isn't really its own benchmark?

We have similar examples e..g oxidation_states where there's a slow part that we may well run separately, and a faster part.

As long as the slow part is defined first, I think it's fine since they can be run either together or independently thanks to the very slow marker.

Comment on lines +229 to +246
if __name__ == "__main__":
import argparse

parser = argparse.ArgumentParser(
description="Run the WiSE reference MD protocol for one registered model."
)
parser.add_argument("model", help=f"one of: {sorted(MODELS)}")
parser.add_argument(
"--continuation",
action="store_true",
help="append the optional 50 ps NVT continuation after NPT.",
)
args = parser.parse_args()

if args.model not in MODELS:
parser.error(f"unknown model '{args.model}'. Registered: {sorted(MODELS)}")

run_reference_md(args.model, MODELS[args.model], run_continuation=args.continuation)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of questions/suggestions:

  • What's the context of continuation - when would we/wouldn't we want to use it? Generally, I think it's good to define a single protocol for all the models
  • It's preferable to integrate with the ml_peg calc CLI, which also allows us to add custom inputs if you wanted to add an new conftest.py (see the water and liquid densities in the MD category for examples). That already has built in things for choosing the model(s) etc.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks you both for the detailed review, and apologies for the delayed response. Here's a summary of what I've changed, plus two open questions I can't settle on my own.

  1. models.yml
    Reverted to the upstream state, as requested. This undoes the model additions that went in with e198469; ok for the MH-1 heads to be enabled on your side or in a separate PR now that MACE has released them properly.
    My results for those two models don't depend on the registry flag, so nothing is lost by leaving them commented.

  2. Reference MD protocol
    Your question about continuation prompted me to re-check the script against the protocol that actually produced the published trajectories, and I found two discrepancies. The script was running minimization → 50 ps NVT → 200 ps NPT on p64_w170, with an optional NVT continuation, and it never used p16_w42. This differs from the production workflow in two important ways: it included an NPT stage that was not used in production, and, because the density data were obtained from the smaller p16_w42 cell, it could not have regenerated density.json.

This is what production actually did, and what the script now does:

  • p64_w170 (S(q) and RDF): Min → NVT 50 ps equilibration → NVT 50 ps production, held at the experimental volume (L =27.49 Å) throughout. No NPT: the box is fixed at the experimental density, so that S(q) and the coordination numbers are compared at the reference density rather than at each model's own.
  • p16_w42 (density): Min → NVT 50 ps → NPT 200 ps, with the density averaged over the last 150 ps. NPT is used only here, on the smaller cell, because it's cheaper to converge.

One consequence worth flagging: the mace-mp-0b3 density I sent in April came from a 50 ps NPT run, so it no longer matched the protocol above. I've rerun it at 200 ps like the other three. The density was practically unchanged (from 1.5632 to 1.5623 g/cm³), but the set is now homogeneous. The updated zip is attached below.

  1. Continuation
    This option was a consequence of the protocol mismatch described above. The second 50 ps NVT block is not an optional continuation after NPT, but the production stage that follows equilibration directly, with no intervening NPT stage. Once the protocol was corrected, the flag no longer served a purpose, so I removed it. All models now follow the same single protocol.
    When a test is rerun, it instead detects and skips any stages that have already reached their final step, allowing interrupted runs to resume without repeating the entire workflow.

  2. Scripts combined
    I merged the two scripts into a single calc_litfsi_h2o_21m.py, following the structure used in oxidation_states.
    The very_slow MD test is defined first and generates the trajectories. The extraction tests then read those trajectories and, when the required data are unavailable, skip with a reference to the MD test that produces them. The MD and analysis stages can therefore be run either together or independently. The separate md_reference/ directory has been removed, leaving the benchmark contained in a single directory as intended.

  3. Precision
    Applied as suggested. I also removed the model.default_dtype = "float64" assignment immediately above it.

About the earlier review comments
@joehart2001, the three comments from April are now addressed in the consolidated analyse_litfsi_h2o_21m.py. It uses the build_table decorator for table generation and scoring, and loads the registry through load_models(current_models) rather than using a hard-coded model list.
analyse_density.py has been removed, so I believe those three threads can now be resolved.

Category change
I agree that the electrolytes category introduced in PR (#394) is the most appropriate location for this benchmark. Since that PR has not yet been completed, would you prefer me to restructure the benchmark against it now, or leave the current location unchanged and move it once PR (#394) is merged?

Additional data upload

The April upload contained only the generated outputs, not the initial structures. I have attached the missing inputs here, together with the updated mace-mp-0b3 results:

litfsi_h2o_21m_initial_structures.zip: contains p64_w170_initial.xyz (1,534 atoms) and p16_w42_initial.xyz (382 atoms), both at the experimental density.
mace-mp-0b3.zip: replaces the archive uploaded in April. It contains the same NVT trajectory, together with the updated density.json from the 200 ps rerun.

mace-mp-0b3.zip
litfsi_h2o_21m_initial_structures.zip

The MH-1 heads were enabled here to run them through this benchmark, but
models.yml is shared by every benchmark in the repo, so activating them
is not this PR's call to make.
The reference MD did not match the protocol that produced the published
data. It ran NPT 200 ps on p64_w170 and never ran p16_w42 at all, so it
sampled S(q) and the RDF at each model's own density rather than at the
experimental one, and could not have regenerated the density data.

The production protocol, and what this now does:

  p64_w170  Min -> NVT 50 ps eq -> NVT 50 ps prod at the experimental
            volume. No NPT. Gives nvt_trajectory.extxyz.
  p16_w42   Min -> NVT 50 ps -> NPT 200 ps, density averaged over the
            last 150 ps. Gives density.json.

The continuation flag was an artefact of the same mis-transcription: the
second NVT block is the production stage, not an optional addition after
NPT. With the protocol corrected there is nothing left for it to select,
so it is gone and the protocol is identical for every model. Re-running
the test now skips whichever stages already reached their final step.

Minimization passes filter_class=None so that only the atoms relax:
janus-core defaults to FrechetCellFilter, which would have relaxed the
cell away from the experimental volume the protocol depends on.

Both halves live in calc_litfsi_h2o_21m.py, as in calc_oxidation_states.py:
the very_slow MD test is defined first and writes the data, the extraction
tests read it back and skip with a pointer to the MD test if it is absent.

Also switch to get_calculator(precision="high") and drop the preceding
model.default_dtype assignment, which took precedence over the argument
and would have made the change a no-op.
current_models moved to ml_peg/models/__init__.py in ddmms#560, so importing it
from ml_peg.models.models raised ImportError and every test in this
benchmark errored at collection. All other calcs use `from ml_peg.models
import current_models`; do the same.
The Savitzky-Golay window is 5, not 27: at dq = 0.02 A^-1 that is the
0.10 A^-1 physical width the calc applies. The 27 referred to an earlier,
finer q grid.

Also describe the protocol per cell, and point at the reference MD in its
new home now that md_reference/ is gone.
figure_density_timeseries was loaded but never mapped to a table column, so
it was never displayed, and ruff rejects the dead assignment.
CI runs the full pre-commit suite, which this benchmark had never been
through: ruff-format wanted to reformat both files, and numpydoc rejected
two parameter descriptions that opened with a lowercase "janus-core".

The reformatting is cosmetic only; the protocol constants, Cromer-Mann
form factors and composition are unchanged.
@LucaBrugnoli

LucaBrugnoli commented Jul 17, 2026

Copy link
Copy Markdown
Author

Reposting here because my earlier reply ended up in a review thread on md_reference/calc_md_reference.py. Since that file has now been removed, GitHub marks the thread as outdated and hides the comment by default.

Thank you both for the detailed review, and apologies for the delayed response. Here's a summary of what I've changed, plus two open questions I can't settle on my own.

  1. models.yml
    Reverted to the upstream state, as requested. This undoes the model additions that went in with e198469; I am happy for the MH-1 heads to be enabled on your side or in a separate PR now that MACE has released them properly.
    My results for those two models don't depend on the registry flag, so nothing is lost by leaving them commented.

  2. Reference MD protocol
    Your question about continuation prompted me to re-check the script against the protocol that actually produced the published trajectories, and I found two discrepancies. The script was running minimization → 50 ps NVT → 200 ps NPT on p64_w170, with an optional NVT continuation, and it never used p16_w42. This differed from the production workflow in two important ways: it included an NPT stage that was not used in production, and, because the density data were obtained from the smaller p16_w42 cell, it could not have regenerated density.json.

This is what production actually did, and what the script now does:

  • p64_w170 (S(q) and RDF): minimization → NVT 50 ps equilibration → NVT 50 ps production, held at the experimental volume (L = 27.49 Å) throughout. No NPT: the box is fixed at the experimental density, so that S(q) and the coordination numbers are compared at the reference density rather than at each model's own.
  • p16_w42 (density): minimization → NVT 50 ps → NPT 200 ps, with the density averaged over the last 150 ps. NPT is used only here, on the smaller cell, because it is less computationally expensive to run for the required duration.

One consequence worth flagging: the mace-mp-0b3 density I sent in April came from a 50 ps NPT run, so it did not match the protocol above. I've rerun it for 200 ps, as for the other three models. The density was practically unchanged (from 1.5632 to 1.5623 g/cm³), but the dataset is now consistent. The updated zip is attached below.

  1. Continuation
    This option was a consequence of the protocol mismatch described above. The second 50 ps NVT block is not an optional continuation after NPT, but the production stage that follows equilibration directly, with no intervening NPT stage. Once the protocol was corrected, the flag no longer served a purpose, so I removed it. All models now follow the same protocol for each observable.
    When a test is rerun, it instead detects and skips any stages that have already reached their final step, allowing interrupted runs to resume without repeating the entire workflow.

  2. Scripts combined
    I merged the two scripts into a single calc_litfsi_h2o_21m.py, following the structure used in oxidation_states.
    The very_slow MD test is defined first and generates the trajectories. The extraction tests then read those trajectories and, when the required data are unavailable, skip with a reference to the MD test that produces them. The MD and analysis stages can therefore be run either together or independently. The separate md_reference/ directory has been removed, leaving the benchmark contained in a single directory as intended.

  3. Precision
    Applied as suggested. I also removed the model.default_dtype = "float64" assignment immediately above it. That assignment took precedence over the precision argument passed to get_calculator, so changing the argument alone would not have changed the dtype.

About the earlier review comments
@joehart2001, the three comments from April are now addressed in the consolidated analyse_litfsi_h2o_21m.py. It uses the build_table decorator for table generation and scoring, and loads the registry through load_models(current_models) rather than using a hard-coded model list.
analyse_density.py has been removed, so I believe those three threads can now be resolved.

Category change
I agree that the electrolytes category introduced in (#394) is the most appropriate location for this benchmark, and I have now moved it there. I also renamed the documentation page to electrolytes.rst. I kept its entry in index.rst in the same position used in (#394).

Additional data upload

The April upload contained only the generated outputs, not the initial structures, so the MD test cannot currently be run without the local input files. I have attached the missing inputs here, together with the updated mace-mp-0b3 results:

litfsi_h2o_21m_initial_structures.zip: contains p64_w170_initial.xyz (1,534 atoms) and p16_w42_initial.xyz (382 atoms), both at the experimental density.
mace-mp-0b3.zip: replaces the archive uploaded in April. It contains the same NVT trajectory, together with the updated density.json from the 200 ps rerun.

litfsi_h2o_21m_initial_structures.zip
mace-mp-0b3.zip

The calculation still reads its inputs from a local directory rather than through download_s3_data, which is the last remaining change I am aware of. What would be the best way to handle this from here?

The pre-commit failure shown for 6a972ba was fixed in 4cd1ff2, including the ruff-format changes and two NumPy-style docstring fixes. The CI run for the latest commit is currently waiting for approval.

Relocate calcs, analysis, app and docs from wise_electrolytes/ to
electrolytes/, following the category introduced in ddmms#394.
Replace the experimental per-species CN references (2.0/2.0, Watanabe
et al. 2021, measured at ~18.5 m) with theory-anchored values at the
benchmark composition: 2.4 (water), 1.9 (TFSI) and 4.3 (total), from
r2SCAN AIMD and two independent MACE potentials trained on the same
r2SCAN dataset (converged over >2 ns). The experimental total (4.21)
is kept as a consistency check; the experimental water/TFSI split is
dropped, as it is at a different concentration and disagrees
systematically with all MD-based partitionings.

Add a total-CN metric and rebalance weights (0.25/0.25/0.5) so the CN
family carries the same total weight as density and S(q); good
thresholds now equal the reference uncertainties (0.15/0.05/0.10).
Models trained on molecular data refuse to evaluate a structure whose
info dict lacks these keys: orb-v3-consv-omol raises
"atoms.info must contain both 'charge' and 'spin'", and the same applies
to the other OMol-headed models in models.yml. Both cells are neutral and
closed shell, so the defaults used by the other calculation scripts
(charge 0, spin 1) are the right ones here too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new benchmark Proposals and suggestions for new benchmarks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Water-in-salt electrolytes

3 participants