From 1cbbc04435cd6106665e603e52245c9c9c992faa Mon Sep 17 00:00:00 2001 From: timlichtenberg Date: Fri, 11 Sep 2026 21:53:33 +0200 Subject: [PATCH 1/2] Narrow the mushy_zone_factor no-effect warning to the PALEOS family The config validator warned that mushy_zone_factor has no effect for every mantle EOS that does not start with the literal PALEOS: prefix. The factor is consumed across the whole PALEOS family (PALEOS, PALEOS-2phase, PALEOS-API, PALEOS-API-2phase): it scales the derived solidus as T_sol = T_liq * mushy_zone_factor. A PALEOS-2phase run with mushy_zone_factor below 1.0 therefore received a false no-effect warning while the run applied the factor. Match the warning condition to the four EOS families that consume the factor, correct the warning text, and update the field docstring to describe the real scope and the exempt families. WolfBower2018 and RTPress100TPa use explicit melting curve files; Seager2007 and Analytic have no derived solidus. Add unit tests covering the four PALEOS strings staying silent, the file-curve EOS still warning, and the warning tracking the factor value rather than only the EOS name. --- src/proteus/config/_struct.py | 18 ++++++------- tests/config/test_struct.py | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/proteus/config/_struct.py b/src/proteus/config/_struct.py index 7a0bfe455..fc0a5a14a 100644 --- a/src/proteus/config/_struct.py +++ b/src/proteus/config/_struct.py @@ -50,12 +50,13 @@ def valid_zalmoxis(instance, attribute, value): import logging as _logging _log = _logging.getLogger('fwl.' + __name__) - # mushy_zone_factor only applies to PALEOS unified tables + # mushy_zone_factor scales the derived solidus only for the PALEOS EOS family + _MZF_EOS_PREFIXES = ('PALEOS:', 'PALEOS-2phase:', 'PALEOS-API:', 'PALEOS-API-2phase:') mzf = getattr(instance.zalmoxis, 'mushy_zone_factor', 0.8) - if mzf < 1.0 and not mantle_eos.startswith('PALEOS:'): + if mzf < 1.0 and not mantle_eos.startswith(_MZF_EOS_PREFIXES): _log.warning( 'mushy_zone_factor=%.2f has no effect with mantle EOS %s. ' - 'The mushy zone factor only applies to PALEOS unified tables. ' + 'The mushy zone factor applies only to the PALEOS EOS family. ' 'For WolfBower2018/RTPress100TPa, the mushy zone is defined by ' 'the solidus/liquidus melting curve files.', mzf, @@ -102,16 +103,15 @@ class Zalmoxis: Tabulated: "PALEOS:H2O", "Seager2007:H2O". Analytic: "Analytic:H2O". mushy_zone_factor: float Cryoscopic depression factor controlling the width of the mushy - zone (partially molten region) in the PALEOS unified EOS. + zone (partially molten region) in the PALEOS EOS family. Defines the solidus as T_sol = T_liq * mushy_zone_factor. 1.0 = sharp phase boundary (no mushy zone). 0.8 = solidus at 80% of the liquidus temperature, roughly matching the Stixrude+2014 cryoscopic depression for MgSiO3. - Must be in [0.7, 1.0]. Only applies to PALEOS unified EOS; - ignored for WolfBower2018 and RTPress100TPa (which use explicit - melting curve files). This factor is applied consistently across - Zalmoxis (density interpolation), SPIDER (phase boundaries), - and the VolatileProfile phi-blending. + Must be in [0.7, 1.0]. Applies to the PALEOS EOS family (PALEOS, + PALEOS-2phase, PALEOS-API, PALEOS-API-2phase); ignored for + WolfBower2018 and RTPress100TPa (which use explicit melting curve + files) and for Seager2007/Analytic (no derived solidus). mantle_mass_fraction: float Fraction of the planet's interior mass corresponding to the mantle. Required for 3-layer models (with ice layer) and for T-dependent diff --git a/tests/config/test_struct.py b/tests/config/test_struct.py index 69e714c03..a8bd30de7 100644 --- a/tests/config/test_struct.py +++ b/tests/config/test_struct.py @@ -13,6 +13,8 @@ from __future__ import annotations +import logging + import pytest from proteus.config._struct import Struct, Zalmoxis @@ -160,3 +162,52 @@ def test_spider_module_skips_the_gate(self): # absent. with pytest.raises(ValueError, match='core_eos'): Struct(module='zalmoxis', zalmoxis=Zalmoxis(core_eos='no_colon')) + + +class TestZalmoxisMushyZoneWarning: + """The mushy_zone_factor no-effect warning must fire only for the EOS + families that actually ignore the factor. + + mushy_zone_factor scales the derived solidus ``T_sol = T_liq * mzf`` for + the PALEOS family (unified, 2-phase, and the API variants) through + ``load_zalmoxis_solidus_liquidus_functions``. For WolfBower2018 and + RTPress100TPa the melting curves come from file and the factor is inert, + so there the warning is correct and must still fire. + """ + + @staticmethod + def _warns(caplog, mantle_eos, mzf=0.8): + """Construct a zalmoxis Struct and report whether the no-effect + warning fired for ``mantle_eos`` at the given factor.""" + caplog.clear() + with caplog.at_level(logging.WARNING, logger='fwl.proteus.config._struct'): + Struct( + module='zalmoxis', + zalmoxis=Zalmoxis(mantle_eos=mantle_eos, mushy_zone_factor=mzf), + ) + return any('has no effect' in r.getMessage() for r in caplog.records) + + def test_warning_silent_for_the_paleos_family(self, caplog): + """Each PALEOS-family EOS feeds the factor into the derived solidus, so + the no-effect warning must stay silent for all four.""" + for eos in ( + 'PALEOS:MgSiO3', + 'PALEOS-2phase:MgSiO3', + 'PALEOS-API:MgSiO3', + 'PALEOS-API-2phase:MgSiO3', + ): + assert not self._warns(caplog, eos), eos + + def test_warning_fires_for_file_curve_eos(self, caplog): + """WolfBower2018 and RTPress100TPa read melting curves from file, so the + factor has no effect and the warning must fire.""" + for eos in ('WolfBower2018:MgSiO3', 'RTPress100TPa:MgSiO3'): + assert self._warns(caplog, eos), eos + + def test_warning_tracks_the_factor_not_only_the_eos(self, caplog): + """The warning depends on mushy_zone_factor < 1: at the sharp-boundary + value 1.0 an ignored setting is not misreported.""" + assert not self._warns(caplog, 'WolfBower2018:MgSiO3', mzf=1.0) + # Paired positive: the same EOS at 0.8 fires, so silence at 1.0 is the + # factor guard rather than the EOS being exempt. + assert self._warns(caplog, 'WolfBower2018:MgSiO3', mzf=0.8) From 0b2db1f7176cf90c9f42dfce14dabd67ded85a45 Mon Sep 17 00:00:00 2001 From: timlichtenberg Date: Sat, 12 Sep 2026 05:49:27 +0200 Subject: [PATCH 2/2] Regenerate interior.md for the mushy_zone_factor docstring reword The mushy_zone_factor docstring change went in without a docs regeneration, so the committed reference page carried the old PALEOS-only wording while the source described the four-member family. Ran tools/generate_config_reference.py; only interior.md and its JSON sidecar change, both by the one field description. --- docs/Reference/config/config_schema.json | 2 +- docs/Reference/config/interior.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Reference/config/config_schema.json b/docs/Reference/config/config_schema.json index 696ff76b1..a112b09ec 100644 --- a/docs/Reference/config/config_schema.json +++ b/docs/Reference/config/config_schema.json @@ -2838,7 +2838,7 @@ "value": 1.0 } ], - "description": "Cryoscopic depression factor controlling the width of the mushy zone (partially molten region) in the PALEOS unified EOS. Defines the solidus as T_sol = T_liq * mushy_zone_factor. 1.0 = sharp phase boundary (no mushy zone). 0.8 = solidus at 80% of the liquidus temperature, roughly matching the Stixrude+2014 cryoscopic depression for MgSiO3. Must be in [0.7, 1.0]. Only applies to PALEOS unified EOS; ignored for WolfBower2018 and RTPress100TPa (which use explicit melting curve files). This factor is applied consistently across Zalmoxis (density interpolation), SPIDER (phase boundaries), and the VolatileProfile phi-blending.", + "description": "Cryoscopic depression factor controlling the width of the mushy zone (partially molten region) in the PALEOS EOS family. Defines the solidus as T_sol = T_liq * mushy_zone_factor. 1.0 = sharp phase boundary (no mushy zone). 0.8 = solidus at 80% of the liquidus temperature, roughly matching the Stixrude+2014 cryoscopic depression for MgSiO3. Must be in [0.7, 1.0]. Applies to the PALEOS EOS family (PALEOS, PALEOS-2phase, PALEOS-API, PALEOS-API-2phase); ignored for WolfBower2018 and RTPress100TPa (which use explicit melting curve files) and for Seager2007/Analytic (no derived solidus).", "doc_source": "attributes", "group_order": 0, "group_position": 3, diff --git a/docs/Reference/config/interior.md b/docs/Reference/config/interior.md index 5e14b4fc3..cf364f4a0 100644 --- a/docs/Reference/config/interior.md +++ b/docs/Reference/config/interior.md @@ -49,7 +49,7 @@ belong to the experimental binodal-aware mode. | `core_eos` | str | `"PALEOS:iron"` | EOS for the core layer. Format: ":". Tabulated: "PALEOS:iron" (default), "Seager2007:iron". Analytic: "Analytic:iron", "Analytic:MgFeSiO3", etc. | | `mantle_eos` | str | `"PALEOS:MgSiO3"` | EOS for the mantle layer. Format: ":". Tabulated: "PALEOS:MgSiO3" (default), "PALEOS-2phase:MgSiO3", "Seager2007:MgSiO3", "WolfBower2018:MgSiO3". Analytic: "Analytic:MgSiO3", "Analytic:MgFeSiO3", etc. | | `ice_layer_eos` | str or none | `none` | EOS for the ice/water layer (3-layer model). 'none' for 2-layer model (core + mantle only). Tabulated: "PALEOS:H2O", "Seager2007:H2O". Analytic: "Analytic:H2O". | -| `mushy_zone_factor` | float | `0.8` | Cryoscopic depression factor controlling the width of the mushy zone (partially molten region) in the PALEOS unified EOS. Defines the solidus as T_sol = T_liq * mushy_zone_factor. 1.0 = sharp phase boundary (no mushy zone). 0.8 = solidus at 80% of the liquidus temperature, roughly matching the Stixrude+2014 cryoscopic depression for MgSiO3. Must be in \[0.7, 1.0\]. Only applies to PALEOS unified EOS; ignored for WolfBower2018 and RTPress100TPa (which use explicit melting curve files). This factor is applied consistently across Zalmoxis (density interpolation), SPIDER (phase boundaries), and the VolatileProfile phi-blending. Must be >= 0.7 and <= 1.0. | +| `mushy_zone_factor` | float | `0.8` | Cryoscopic depression factor controlling the width of the mushy zone (partially molten region) in the PALEOS EOS family. Defines the solidus as T_sol = T_liq * mushy_zone_factor. 1.0 = sharp phase boundary (no mushy zone). 0.8 = solidus at 80% of the liquidus temperature, roughly matching the Stixrude+2014 cryoscopic depression for MgSiO3. Must be in \[0.7, 1.0\]. Applies to the PALEOS EOS family (PALEOS, PALEOS-2phase, PALEOS-API, PALEOS-API-2phase); ignored for WolfBower2018 and RTPress100TPa (which use explicit melting curve files) and for Seager2007/Analytic (no derived solidus). Must be >= 0.7 and <= 1.0. | | `mantle_mass_fraction` | float | `0` | Fraction of the planet's interior mass corresponding to the mantle. Required for 3-layer models (with ice layer) and for T-dependent 2-layer models (WolfBower2018, RTPress100TPa) where it partitions mass between core and mantle layers. Must be >= 0 and < 1. | | `dry_mantle` | bool | `true` | Structure EOS assumes a dry mantle. Set False for melt-fraction-aware dissolved-volatile mixing in the mantle density (per-shell volatile profile); the dissolved mass then stays inside the interior mass target. |