You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Re-mix GGA(+U)/r2SCAN entries without fuzzy matching, as for MP's pre-built phase diagrams - #1141
When MP has no pre-built phase diagram for a chemical system, get_entries_in_chemsys re-mixes the GGA(+U) and
r2SCAN entries locally with MaterialsProjectDFTMixingScheme(), which uses pymatgen's default fuzzy_matching=True.
That matches O2, H2, Cl2, F2, N2, I, Br and H2O across functionals by formula, space group and number of sites only
(no structure matching). MP builds its phase diagrams with fuzzy_matching=False, as recorded in the cls of the served
entries' mixing adjustments. So for any chemical system with one of these elements, the local re-mix (which happens if requesting a non pre-built PD) differs from MP's diagram (and the website).
This PR sets fuzzy_matching=False in the re-mix. Re-mixing the unmixed entries of systems that do have a pre-built diagram then reproduces MP's diagrams exactly.
Noting that get_stability keeps the default (fuzzy_matching=True): it re-mixes the user's own entries with MP's, and without fuzzy matching a user's r2SCAN entry at a new composition in a system with O/F/Cl/Br/I is dropped by the mixing scheme (as the system is then GGA(+U)-anchored), after which get_e_above_hull raises. E.g. an r2SCAN NaLu(SiO3)2 entry in Lu-Na-O-Si gets 0.000 eV/atom with fuzzy matching, and ValueError: No valid decomposition found without.
test_get_entries_in_chemsys_remix_matches_served added, which artificially forces the re-mix for the O system and compares it with the served diagram.
Note: Should MP building use strict/fuzzy matching?
Fuzzy matching was written for these cases where strict matching (based on structure matching) fails: pymatgen's docstring: different-functional relaxations of these elements "frequently fail to structure match ... even though they come from the same original material". It is pymatgen's default, and what MP's docs describer for re-mixing locally (phase diagrams page), and MP's builder seems to have used it before: the mixed-thermo MP entries in pymatgen's entries_thermo_type_GGA_GGA_U_R2SCAN.json test file (added in Feb 2023) record fuzzy_matching: true -- but doesn't currently.
Without fuzzy matching, the Cl2, F2, Br and I ground states (mp-22848, mp-1525632, mp-23154, mp-23153)
don't structure-match their own r2SCAN calculations (r2SCAN contracts these molecular crystals by 16-21% in volume),
and the O2 ground state mp-12957 has no r2SCAN calculation (fuzzy matching pairs it with the r2SCAN-only mp-1524462, which looks like the same alpha-O2 structure with a slightly different cell/packing). So all of MP's diagrams with O, F, Cl, Br or I are GGA(+U)-anchored, while the fuzzy re-mix anchors some of them to r2SCAN instead (energy above hull differences up to 0.25 eV/atom, e.g. Lu-Na-O-Si), and places the gas-phase entries differently in the others (up to 0.16 eV/atom in Be-Ge-Nd-O and Ca-La-Mg-O-Ta). Systems with N or H differ too, even though N2 and H2 do structure-match: fuzzy matching collapses all gas-phase polymorphs with the same space group and number of sites into one entry per
functional, dropping the rest.
With strict matching, none of MP's 39,254 phase diagrams with O, F, Cl, Br or I is r2SCAN-anchored (vs 35% of the 71,636 without these elements, and 56% of those with only N/H), and r2SCAN-only materials at new compositions are dropped from them: e.g. only 124 of the 19,184 GNoMe materials in these systems appear in any mixed diagram. With fuzzy matching, 8,942 of the 39,254 systems (23%) with O, F, Cl, Br or I would become r2SCAN-anchored (and GNoMe materials would go from 124 to 6,392 appearances in mixed hulls, 33%). The mixing scheme paper's remedy for such matching failures is r2SCAN single-point calculations of the GGA(+U) ground-state structures (Kingsbury et al., npj Comput. Mater. 8, 195 (2022)), which would let these few ground states (mp-12957, mp-1525632, mp-22848, mp-23154, mp-23153) match strictly.
Just raising this point, as I'm not sure what the preferred approach in general of the MP would be.
Either way, the strict/fuzzy-matching choice of MP building should ideally match that of mp-api's local re-mixing!
Checklist
Google format doc strings added. Check with ruff.
Type annotations included. Check with mypy.
Tests added for new features/fixes.
If applicable, new classes/functions/modules have duecredit@due.dcite decorators to reference relevant papers by DOI (example)
This PR also bumps the pymatgen requirement, so that it uses the fixed MaterialsProjectDFTMixingScheme from materialsproject/pymatgen#4704 (released in 2026.9.23) – e.g. it keeps rutile TiO2 (mp-2657) as both its GGA and r2SCAN entries.
Note:
Separately from this mixing fix: get_pourbaix_entries can also silently use the wrong O2/H2O reference energies with current pymatgen releases (not fixed by the other PRs I just created).
This is fixed in materialsproject/pymatgen#4754 (flagged in materialsproject/pymatgen#4747), which merged after v2026.10.24, so no release includes it yet. Once the next pymatgen release is out, it might be worth mp-api raising its pymatgen floor to that release, on top of the >=2026.9.23 here, so this bug is avoided? Just to flag and track here.
Explanation of the issue from Claude:
In pymatgen ≤ v2026.10.24, MaterialsProjectAqueousCompatibility is a monty @cached_class, so constructing it with the same arguments returns the same instance while anything still references it. process_entries stores the O2/H2O energies it infers on that instance, and only infers them while they're unset. get_pourbaix_entries builds MaterialsProjectAqueousCompatibility(solid_compat=MaterialsProject2020Compatibility()), and _private_copy starts from that instance's __dict__. So if the caller holds an equal instance that has already processed other entries, the Pourbaix entries are corrected with that instance's energies, with no warning.
E.g. after processing MP's default Fe-O-H entries with such an instance (inferred H2O energy −5.125 eV/atom, vs −5.193 from get_pourbaix_entries("Fe")'s own GGA/GGA+U entries), FeOOH replaces Fe2O3 at 395 of 1,189 (pH, V) points of the Fe Pourbaix diagram.
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When MP has no pre-built phase diagram for a chemical system,
get_entries_in_chemsysre-mixes the GGA(+U) andr2SCAN entries locally with
MaterialsProjectDFTMixingScheme(), which usespymatgen's defaultfuzzy_matching=True.That matches O2, H2, Cl2, F2, N2, I, Br and H2O across functionals by formula, space group and number of sites only
(no structure matching). MP builds its phase diagrams with
fuzzy_matching=False, as recorded in theclsof the servedentries' mixing adjustments. So for any chemical system with one of these elements, the local re-mix (which happens if requesting a non pre-built PD) differs from MP's diagram (and the website).
This PR sets
fuzzy_matching=Falsein the re-mix. Re-mixing the unmixed entries of systems that do have a pre-built diagram then reproduces MP's diagrams exactly.Noting that
get_stabilitykeeps the default (fuzzy_matching=True): it re-mixes the user's own entries with MP's, and without fuzzy matching a user's r2SCAN entry at a new composition in a system with O/F/Cl/Br/I is dropped by the mixing scheme (as the system is then GGA(+U)-anchored), after whichget_e_above_hullraises. E.g. an r2SCAN NaLu(SiO3)2 entry in Lu-Na-O-Si gets 0.000 eV/atom with fuzzy matching, andValueError: No valid decomposition foundwithout.test_get_entries_in_chemsys_remix_matches_servedadded, which artificially forces the re-mix for the O system and compares it with the served diagram.Note: Should MP building use strict/fuzzy matching?
Fuzzy matching was written for these cases where strict matching (based on structure matching) fails:
pymatgen's docstring: different-functional relaxations of these elements "frequently fail to structure match ... even though they come from the same original material". It is pymatgen's default, and what MP's docs describer for re-mixing locally (phase diagrams page), and MP's builder seems to have used it before: the mixed-thermo MP entries in pymatgen'sentries_thermo_type_GGA_GGA_U_R2SCAN.jsontest file (added in Feb 2023) recordfuzzy_matching: true-- but doesn't currently.Without fuzzy matching, the Cl2, F2, Br and I ground states (
mp-22848,mp-1525632,mp-23154,mp-23153)don't structure-match their own r2SCAN calculations (r2SCAN contracts these molecular crystals by 16-21% in volume),
and the O2 ground state
mp-12957has no r2SCAN calculation (fuzzy matching pairs it with the r2SCAN-onlymp-1524462, which looks like the same alpha-O2 structure with a slightly different cell/packing). So all of MP's diagrams with O, F, Cl, Br or I are GGA(+U)-anchored, while the fuzzy re-mix anchors some of them to r2SCAN instead (energy above hull differences up to 0.25 eV/atom, e.g. Lu-Na-O-Si), and places the gas-phase entries differently in the others (up to 0.16 eV/atom in Be-Ge-Nd-O and Ca-La-Mg-O-Ta). Systems with N or H differ too, even though N2 and H2 do structure-match: fuzzy matching collapses all gas-phase polymorphs with the same space group and number of sites into one entry perfunctional, dropping the rest.
With strict matching, none of MP's 39,254 phase diagrams with O, F, Cl, Br or I is r2SCAN-anchored (vs 35% of the 71,636 without these elements, and 56% of those with only N/H), and r2SCAN-only materials at new compositions are dropped from them: e.g. only 124 of the 19,184 GNoMe materials in these systems appear in any mixed diagram. With fuzzy matching, 8,942 of the 39,254 systems (23%) with O, F, Cl, Br or I would become r2SCAN-anchored (and GNoMe materials would go from 124 to 6,392 appearances in mixed hulls, 33%). The mixing scheme paper's remedy for such matching failures is r2SCAN single-point calculations of the GGA(+U) ground-state structures (Kingsbury et al., npj Comput. Mater. 8, 195 (2022)), which would let these few ground states (mp-12957, mp-1525632, mp-22848, mp-23154, mp-23153) match strictly.
Just raising this point, as I'm not sure what the preferred approach in general of the MP would be.
Either way, the strict/fuzzy-matching choice of MP building should ideally match that of
mp-api's local re-mixing!Checklist
ruff.mypy.duecredit@due.dcitedecorators to reference relevant papers by DOI (example)