diff --git a/docs/source/config-sectors.md b/docs/source/config-sectors.md index cfd32458..9591ebe8 100644 --- a/docs/source/config-sectors.md +++ b/docs/source/config-sectors.md @@ -6,6 +6,9 @@ the following configuration options are exposed to the user. ```{note} Only single-period studies are currently supported when running sector studies. +Set `renewable_weather_years: [2018]` for sector-coupled runs (`G` or `E-G`): +residential and commercial demand profiles use 2018 weather data. +Other weather years are rejected when the workflow loads the configuration. ``` ## Carbon Limits diff --git a/tests/static/test_config_schema.py b/tests/static/test_config_schema.py index d07f5e77..9c8d36f9 100644 --- a/tests/static/test_config_schema.py +++ b/tests/static/test_config_schema.py @@ -129,3 +129,34 @@ def test_godeeep_requires_renewable_land_access_key(schema): cfg.pop("renewable_land_access") with pytest.raises(jsonschema.ValidationError): jsonschema.validate(cfg, schema) + + +@pytest.mark.fast +@pytest.mark.parametrize("sector", ["G", "E-G"]) +@pytest.mark.parametrize("weather_years", [[2019], [2018, 2019], []]) +def test_sector_weather_year_must_be_2018(sector, weather_years, schema): + cfg = _merged("config.default.yaml") + cfg["scenario"]["sector"] = sector + cfg["renewable_weather_years"] = weather_years + with pytest.raises(jsonschema.ValidationError) as exc_info: + jsonschema.validate(cfg, schema) + assert list(exc_info.value.path) == ["renewable_weather_years"] + + +@pytest.mark.fast +@pytest.mark.parametrize("sector", ["G", "E-G"]) +def test_sector_weather_year_2018_is_supported(sector, schema): + cfg = _merged("config.default.yaml") + cfg["scenario"]["sector"] = sector + cfg["renewable_weather_years"] = [2018] + jsonschema.validate(cfg, schema) + + +@pytest.mark.fast +@pytest.mark.parametrize("sector", ["", "E"]) +@pytest.mark.parametrize("weather_years", [[2019], [2018, 2019]]) +def test_electricity_weather_years_remain_supported(sector, weather_years, schema): + cfg = _merged("config.default.yaml") + cfg["scenario"]["sector"] = sector + cfg["renewable_weather_years"] = weather_years + jsonschema.validate(cfg, schema) diff --git a/tests/static/test_dag_dryrun.py b/tests/static/test_dag_dryrun.py index 1666a7cd..62323df3 100644 --- a/tests/static/test_dag_dryrun.py +++ b/tests/static/test_dag_dryrun.py @@ -75,6 +75,27 @@ def test_snakemake_dryrun_resolves(configfile, target, overrides): ) +@pytest.mark.fast +@pytest.mark.parametrize("sector", ["G", "E-G"]) +def test_sector_weather_year_is_checked_at_workflow_start(tmp_path, sector): + configfile = tmp_path / "sector.yaml" + configfile.write_text(f"scenario:\n sector: {sector}\nrenewable_weather_years: [2019]\n") + result = subprocess.run( + ["snakemake", "--list", "--configfile", str(configfile)], + cwd=WORKFLOW_DIR, + capture_output=True, + text=True, + timeout=60, + ) + assert result.returncode != 0 + output = result.stdout + result.stderr + assert "Error validating config file" in output + assert "renewable_weather_years" in output + assert "Sector-coupled runs require" in output + assert "[2018]" in output + assert "[2019]" in output + + def _solve_network_inputs(overrides): """Return the ``solve_network`` input paths snakemake resolves in a dry run.""" cmd = [ diff --git a/workflow/schemas/config.schema.yaml b/workflow/schemas/config.schema.yaml index 746dc40b..555a237f 100644 --- a/workflow/schemas/config.schema.yaml +++ b/workflow/schemas/config.schema.yaml @@ -506,6 +506,22 @@ properties: eia: {type: ["string", "null"]} allOf: +# Residential and commercial sector demand profiles use 2018 weather data. +- if: + properties: + scenario: + properties: + sector: {pattern: "(^|-)G(-|$)"} + required: [sector] + required: [scenario] + then: + properties: + renewable_weather_years: + description: >- + Sector-coupled runs require renewable_weather_years: [2018]. + Residential and commercial demand profiles use 2018 weather data. + const: [2018] + # The selected solver's options block must exist in solver_options. - if: properties: