diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index c89572f..bdf6b1e 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -3,10 +3,10 @@ name: CI-Linux on: push: branches: - - main + - scenario_management pull_request: branches: - - main + - scenario_management schedule: - cron: "0 5 * * TUE" @@ -72,20 +72,47 @@ jobs: - name: Move test config run: | cd ../pypsa-earth - cp pypsa-kz-data/test/config_kz_test.yaml ./test/config.custom.yaml + cp pypsa-kz-data/test/config_kz_default_test.yaml ./test/config.landlock.yaml - name: Create test configs run: | cd ../pypsa-earth snakemake --cores all build_test_configs - - name: Test pypsa-kz-data workflow + - name: Clean scenarios folder run: | cd ../pypsa-earth - cp ./test/tmp/config.custom_tmp.yaml ./config.yaml - snakemake -j1 retrieve_databundle_light # we first retrieve data + rm -r pypsa-kz-data/scenarios/* + + - name: Move test configs to scenario folder + run: | + cd ../pypsa-earth + cp pypsa-kz-data/test/config_kz_test1.yaml pypsa-kz-data/scenarios/config.kz_2013.yaml + cp ./test/tmp/config.landlock_tmp.yaml pypsa-kz-data/config.kz_default.yaml + + - name : Change Snakefile lines + run: | + cd ../pypsa-earth + sed -i 's\os.system("snakemake -j all solve_all_networks --rerun-incomplete")\os.system(f"snakemake -j1 networks/{wildcards.scenario_name}/base.nc")\g' Snakefile + sed -i 's,os.system("snakemake -j1 make_statistics --force"),os.system("cp pypsa-kz-data/data/custom_powerplants.csv data/custom_powerplants.csv")\n\tos.system("snakemake -j1 solve_all_networks --rerun-incomplete"),g' Snakefile + cat Snakefile + + - name: Replace Default config + run: | + cd ../pypsa-earth + cp pypsa-kz-data/config.kz_default.yaml config.default.yaml + cp config.default.yaml config.yaml + + - name: Prepare KZ-scenarios + run: | + cd ../pypsa-earth + snakemake -j1 prepare_kz_scenarios cp -r pypsa-kz-data/test/gadm ./data/gadm find data -type f - cp pypsa-kz-data/data/custom_powerplants.csv ./data/custom_powerplants.csv # overwrite powerplantdata - snakemake -j1 solve_all_networks - \ No newline at end of file + cat configs/scenarios/config.kz_2013.yaml + + - name: Run all scenarios + run: | + cd ../pypsa-earth + snakemake -j1 run_all_scenarios + diff --git a/README.md b/README.md index 5097652..17280e8 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ Monthly electricity demand data with monthly aggregation provided by Kazakhstan # Model Execution +## Setting up the general repositories + The provided workflow builds on [PyPSA-Earth](https://github.com/pypsa-meets-earth/pypsa-earth). Therefore, first, the PyPSA-Earth repository must be forked and the fork should then be cloned. A fork can be created by navigating to the [PyPSA-Earth](https://github.com/pypsa-meets-earth/pypsa-earth) website. By clicking on the fork-symbol in the upper right corner, a fork is created and linked to the specific user. Next, we also need to fork the [pypsa-kz-data](https://github.com/pypsa-meets-earth/pypsa-kz-data) repository. A fork can be created by navigating to the [pypsa-kz-data](https://github.com/pypsa-meets-earth/pypsa-kz-data) website and clicking the fork symbol in the upper right corner. @@ -63,35 +65,49 @@ After installing the environment, activate it using ```bash conda activate pypsa-earth ``` -Before the whole workflow can be executed, the databundle must be retrieved. This can be done via: + +## Modeling adaptations for KZ study + +To adapt the overall workflow for kz, only two further changes are necessary. + +Firstly, open the Snakefile (in `pypsa-earth/`) and navigate to line [1057-1058](https://github.com/pypsa-meets-earth/pypsa-earth/blob/main/Snakefile#L1057-L1058), which should read ```bash -snakemake -j 1 retrieve_databundle_light +os.system("snakemake -j all solve_all_networks --rerun-incomplete") +os.system("snakemake -j1 make_statistics --force") ``` -This step can optionally be skipped if the `data/` folder with all relevant subfolders already exists. - -To adapt the overall workflow for kz, only three further changes are necessary: -1. replace the `pypsa-earth/data/custom_powerplants.csv` with the provided `pypsa-kz-data/data/custom_powerplants.csv`. This can be done using the command: +and replace these two lines with ```bash -cp pypsa-kz-data/data/custom_powerplants.csv data/custom_powerplants.csv +os.system(f"snakemake -j1 networks/{wildcards.scenario_name}/base.nc") +os.system("cp pypsa-kz-data/data/custom_powerplants.csv data/custom_powerplants.csv") +os.system("snakemake -j1 solve_everything --rerun-incomplete") ``` -2. Open the Snakefile (in `pypsa-earth/`) and navigate to line 25, which should read `configfile: "config.yaml"`. Replace this line with `configfile: "pypsa-kz-data/config_kz_default.yaml"`. To run the default scenario for different weather years (2011, 2013, 2018), add a new line below (line 26) with `configfile: "pypsa-kz-data/config_kz_.yaml"`, where `` represents an existing weather year (2011, 2013, 2018). - -The whole workflow can be reproduced by executing +Secondly, copy the default configuration file to the pypsa-earth folder using: +```bash +cp pypsa-kz-data/config.kz_default.yaml config.default.yaml +``` +In case you already have a custom config file, make sure to replace it as well, using ```bash -snakemake -j 1 solve_everything +cp pypsa-kz-data/config.kz_default.yaml config.yaml ``` -3. Only for scenarios: To run a certain scenario, make sure to update the *2nd* config file, i.e. navigate to line 26 in the Snakefile, which now should read: `configfile: "pypsa-kz-data/config_kz_.yaml"` and replace this with the scenario you want to execute: `configfile: "pypsa-kz-data/config_kz__discount

.yaml"`. `` and `

` must be replaced with existing years (2011, 2013, 2018) and discount rates (10 for optimistic scenario, 15 for BAU and 20 for pessimistic scenario). To run the coal exit scenario, the corresponding config file also must be referred in line 26 of the `Snakemake`. For this setting, the line must read `configfile: "pypsa-kz-data/config_kz__discount

_coalexit.yaml"`, where `` and `

` are the weather year (2011, 2013, 2018) and discount rates (10, 15, and 20). +You are now all set to run all scenarios! -Again, the whole workflow can be reproduced by executing the same command as above: +## Running KZ scenarios + +To prepare running all scenarios, execute +```bash +snakemake -j1 prepare_kz_scenarios +``` +Optionally, to save time for future runs, you can now set `enable: retrieve_databundle: True` in the `config.yaml` to `False`. If you already have build all cutouts for 2011, 2013 and 2018, you can also set `enable: build_cutout: True` to `False`. +Finally, to run all scenarios, execute ```bash -snakemake -j 1 solve_everything +snakemake -j1 run_all_scenarios ``` -Results are generated and locally saved in `pypsa-earth/results//networks/`. +After all scenarios have executed successfully, all results are generated and locally saved in `pypsa-earth/results//networks/`. -## Potential errors: +# Potential errors - A rule is killed. In this case, open the `Snakefile` in `pypsa-earth` or open `kz.smk` in `pypsa-kz-data` (depending on the rule which is killed), navigate to the rule that is being killed in the workflow and increase the memory assignment (for example, add a 0 at the end). - The workflow runs into an error during the `build_powerplants` rule. In this case, try to repeat step 1. of the workflow using the command @@ -99,9 +115,22 @@ Results are generated and locally saved in `pypsa-earth/results/.yaml'` are tabs instead of four spaces. +- Unusual error arising from either Snakemake or the `Snakefile` and proving to be challenging to comprehend: Inspect all indentation. Ensure there is no tab spacing; employ only spaces, i.e., ` `. It is probable that the indentations before +```bash +os.system(f"snakemake -j1 networks/{wildcards.scenario_name}/base.nc") +os.system("cp pypsa-kz-data/data/custom_powerplants.csv data/custom_powerplants.csv") +os.system("snakemake -j1 solve_everything --rerun-incomplete") +``` +are tabs instead of four spaces. + +- Missing `data/` folder or some relevant subfolders. This should normally be executed automatically when executing the rule `prepare_kz_scenarios`, however might be missing due to incorrect execution. The databundle can be also retrieved manually via: +```bash +snakemake -j 1 retrieve_databundle_light +``` + +- The rule `retrieve_databundle_light` always executes with an error. To avoid this, try setting `enable: build_cutout: False` to `True`. -## Comes in handy: +# Comes in handy After all cutouts were generated (i.e. the three files `asia--era5.nc` exist in the folder `pypsa-earth/cutouts/`, where `` is 2011, 2013, and 2018, navigate to `pypsa-earth/pypsa-kz-data`, open the default config file, navigate to line 36, which should read `build_cutout: True`, and set it to `build_cutout: false`. This will save you a lot of time when (re-)runnig scenarios. But remember to set it back to `true` in case one of the cutouts was deleted! ## Acknowledgement diff --git a/config_kz_default.yaml b/config.kz_default.yaml similarity index 96% rename from config_kz_default.yaml rename to config.kz_default.yaml index 66a75fe..e507c66 100644 --- a/config_kz_default.yaml +++ b/config.kz_default.yaml @@ -18,7 +18,7 @@ scenario: simpl: [''] ll: ['v1.0'] clusters: [14] - opts: [RES0.2-1H, RES0.25-1H, RES0.3-1H, RES0.35-1H, RES0.4-1H] + opts: [BAU-RES0.2-1H, BAU-RES0.25-1H, BAU-RES0.3-1H, BAU-RES0.35-1H, BAU-RES0.4-1H] countries: ["KZ"] # Can be replaced by country ["NG", "BJ"], continent ["Africa"] or user-specific region, see more at https://pypsa-earth.readthedocs.io/en/latest/configuration.html#top-level-configuration @@ -128,6 +128,13 @@ electricity: co2base: 3.17e+8 # Kazakhstan default for 1990 agg_p_nom_limits: data/agg_p_nom_minmax.csv hvdc_as_lines: false # should HVDC lines be modeled as `Line` or as `Link` component? + BAU_maxcapacities: + solar: 1e9 # essentially no limit + onwind: 1e9 # essentially no limit + offwind-ac: 1e9 # essentially no limit + offwind-dc: 1e9 # essentially no limit + coal: 1e9 # essentially no limit (only relevant for coal exit scenarios) + ror: 2.133e3 # limit in MW (2030 projection taken from https://kea.kz/storage/app/media/NPA%20NTD/ministra-energetiki-respubliki-kazakhstan-ot-24-marta-2022-goda-104-ob-utverzhdenii-energeticheskogo-balansa-respubliki-ka.pdf) operational_reserve: # like https://genxproject.github.io/GenX/dev/core/#Reserves activate: false diff --git a/kz.smk b/kz.smk index 592e065..89e537b 100644 --- a/kz.smk +++ b/kz.smk @@ -94,3 +94,12 @@ rule solve_everything: ["results/" + RDIR + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_dle.nc"], **config["scenario"] ), + + +rule prepare_kz_scenarios: + run: + import os + os.system("rm configs/scenarios/config.NG.yaml") + os.system("cp -r pypsa-kz-data/scenarios/ configs/") + os.system("snakemake -j1 retrieve_databundle_light") + diff --git a/config_kz_2011.yaml b/scenarios/config.kz_2011.yaml similarity index 100% rename from config_kz_2011.yaml rename to scenarios/config.kz_2011.yaml diff --git a/config_kz_2011_discount10.yaml b/scenarios/config.kz_2011_discount10.yaml similarity index 91% rename from config_kz_2011_discount10.yaml rename to scenarios/config.kz_2011_discount10.yaml index 04622aa..80d9860 100644 --- a/config_kz_2011_discount10.yaml +++ b/scenarios/config.kz_2011_discount10.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2011 # Load scenarios available with different weather year (different renewable potentials) + scale_kz: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2011_discount10_coalexit.yaml b/scenarios/config.kz_2011_discount10_coalexit.yaml similarity index 88% rename from config_kz_2011_discount10_coalexit.yaml rename to scenarios/config.kz_2011_discount10_coalexit.yaml index 0ba1177..d75a61e 100644 --- a/config_kz_2011_discount10_coalexit.yaml +++ b/scenarios/config.kz_2011_discount10_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2011-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2011 # Load scenarios available with different weather year (different renewable potentials) + scale_kz: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2011_discount15.yaml b/scenarios/config.kz_2011_discount15.yaml similarity index 91% rename from config_kz_2011_discount15.yaml rename to scenarios/config.kz_2011_discount15.yaml index 78c55c5..7abd04f 100644 --- a/config_kz_2011_discount15.yaml +++ b/scenarios/config.kz_2011_discount15.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2011 # Load scenarios available with different weather year (different renewable potentials) + scale_kz: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2011_discount15_coalexit.yaml b/scenarios/config.kz_2011_discount15_coalexit.yaml similarity index 88% rename from config_kz_2011_discount15_coalexit.yaml rename to scenarios/config.kz_2011_discount15_coalexit.yaml index cdede4a..318eaf4 100644 --- a/config_kz_2011_discount15_coalexit.yaml +++ b/scenarios/config.kz_2011_discount15_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2011-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2011 # Load scenarios available with different weather year (different renewable potentials) + scale_kz: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2011_discount20.yaml b/scenarios/config.kz_2011_discount20.yaml similarity index 91% rename from config_kz_2011_discount20.yaml rename to scenarios/config.kz_2011_discount20.yaml index 37353a2..47cc119 100644 --- a/config_kz_2011_discount20.yaml +++ b/scenarios/config.kz_2011_discount20.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2011 # Load scenarios available with different weather year (different renewable potentials) + scale_kz: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2011_discount20_coalexit.yaml b/scenarios/config.kz_2011_discount20_coalexit.yaml similarity index 88% rename from config_kz_2011_discount20_coalexit.yaml rename to scenarios/config.kz_2011_discount20_coalexit.yaml index 172ef7a..ede3a02 100644 --- a/config_kz_2011_discount20_coalexit.yaml +++ b/scenarios/config.kz_2011_discount20_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2011-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2011 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013.yaml b/scenarios/config.kz_2013.yaml similarity index 100% rename from config_kz_2013.yaml rename to scenarios/config.kz_2013.yaml diff --git a/config_kz_2013_discount10.yaml b/scenarios/config.kz_2013_discount10.yaml similarity index 91% rename from config_kz_2013_discount10.yaml rename to scenarios/config.kz_2013_discount10.yaml index c7e6296..a499d99 100644 --- a/config_kz_2013_discount10.yaml +++ b/scenarios/config.kz_2013_discount10.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount10_coalexit.yaml b/scenarios/config.kz_2013_discount10_coalexit.yaml similarity index 88% rename from config_kz_2013_discount10_coalexit.yaml rename to scenarios/config.kz_2013_discount10_coalexit.yaml index 5fb1f45..8838cb2 100644 --- a/config_kz_2013_discount10_coalexit.yaml +++ b/scenarios/config.kz_2013_discount10_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2013-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount15.yaml b/scenarios/config.kz_2013_discount15.yaml similarity index 91% rename from config_kz_2013_discount15.yaml rename to scenarios/config.kz_2013_discount15.yaml index 673982e..9568357 100644 --- a/config_kz_2013_discount15.yaml +++ b/scenarios/config.kz_2013_discount15.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount15_coalexit.yaml b/scenarios/config.kz_2013_discount15_coalexit.yaml similarity index 88% rename from config_kz_2013_discount15_coalexit.yaml rename to scenarios/config.kz_2013_discount15_coalexit.yaml index b8a57fd..8b5ec81 100644 --- a/config_kz_2013_discount15_coalexit.yaml +++ b/scenarios/config.kz_2013_discount15_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2013-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount15_coalexit_newline.yaml b/scenarios/config.kz_2013_discount15_coalexit_newline.yaml similarity index 90% rename from config_kz_2013_discount15_coalexit_newline.yaml rename to scenarios/config.kz_2013_discount15_coalexit_newline.yaml index bb138a8..313967b 100644 --- a/config_kz_2013_discount15_coalexit_newline.yaml +++ b/scenarios/config.kz_2013_discount15_coalexit_newline.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H] + opts: [BAU-1H] snapshots: start: "2013-01-01" @@ -19,10 +19,11 @@ lines: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount15_newline.yaml b/scenarios/config.kz_2013_discount15_newline.yaml similarity index 92% rename from config_kz_2013_discount15_newline.yaml rename to scenarios/config.kz_2013_discount15_newline.yaml index f44c961..50e6245 100644 --- a/config_kz_2013_discount15_newline.yaml +++ b/scenarios/config.kz_2013_discount15_newline.yaml @@ -15,10 +15,11 @@ lines: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount20.yaml b/scenarios/config.kz_2013_discount20.yaml similarity index 91% rename from config_kz_2013_discount20.yaml rename to scenarios/config.kz_2013_discount20.yaml index 7e7285a..e1d09a4 100644 --- a/config_kz_2013_discount20.yaml +++ b/scenarios/config.kz_2013_discount20.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2013_discount20_coalexit.yaml b/scenarios/config.kz_2013_discount20_coalexit.yaml similarity index 88% rename from config_kz_2013_discount20_coalexit.yaml rename to scenarios/config.kz_2013_discount20_coalexit.yaml index 1c0e64b..649275f 100644 --- a/config_kz_2013_discount20_coalexit.yaml +++ b/scenarios/config.kz_2013_discount20_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2013-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2013 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2018.yaml b/scenarios/config.kz_2018.yaml similarity index 100% rename from config_kz_2018.yaml rename to scenarios/config.kz_2018.yaml diff --git a/config_kz_2018_discount10.yaml b/scenarios/config.kz_2018_discount10.yaml similarity index 91% rename from config_kz_2018_discount10.yaml rename to scenarios/config.kz_2018_discount10.yaml index e751b08..3a1cc53 100644 --- a/config_kz_2018_discount10.yaml +++ b/scenarios/config.kz_2018_discount10.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2018 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2018_discount10_coalexit.yaml b/scenarios/config.kz_2018_discount10_coalexit.yaml similarity index 88% rename from config_kz_2018_discount10_coalexit.yaml rename to scenarios/config.kz_2018_discount10_coalexit.yaml index 6f2babc..e6ccb22 100644 --- a/config_kz_2018_discount10_coalexit.yaml +++ b/scenarios/config.kz_2018_discount10_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2018-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2018 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2018_discount15.yaml b/scenarios/config.kz_2018_discount15.yaml similarity index 91% rename from config_kz_2018_discount15.yaml rename to scenarios/config.kz_2018_discount15.yaml index c6b3a4e..4170ea0 100644 --- a/config_kz_2018_discount15.yaml +++ b/scenarios/config.kz_2018_discount15.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2018 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2018_discount15_coalexit.yaml b/scenarios/config.kz_2018_discount15_coalexit.yaml similarity index 88% rename from config_kz_2018_discount15_coalexit.yaml rename to scenarios/config.kz_2018_discount15_coalexit.yaml index 3b34d9b..897bf38 100644 --- a/config_kz_2018_discount15_coalexit.yaml +++ b/scenarios/config.kz_2018_discount15_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2018-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2018 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2018_discount20.yaml b/scenarios/config.kz_2018_discount20.yaml similarity index 91% rename from config_kz_2018_discount20.yaml rename to scenarios/config.kz_2018_discount20.yaml index 930918d..4f79568 100644 --- a/config_kz_2018_discount20.yaml +++ b/scenarios/config.kz_2018_discount20.yaml @@ -11,10 +11,11 @@ snapshots: load_options: weather_year: 2018 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc] + Generator: [solar, onwind, offwind-ac, offwind-dc, ror] Store: [battery, H2] atlite: diff --git a/config_kz_2018_discount20_coalexit.yaml b/scenarios/config.kz_2018_discount20_coalexit.yaml similarity index 88% rename from config_kz_2018_discount20_coalexit.yaml rename to scenarios/config.kz_2018_discount20_coalexit.yaml index 6a543d1..3c87107 100644 --- a/config_kz_2018_discount20_coalexit.yaml +++ b/scenarios/config.kz_2018_discount20_coalexit.yaml @@ -7,7 +7,7 @@ run: scenario: ll: ['v1.0','copt'] - opts: [1H, RES0.4-1H] + opts: [BAU-1H, BAU-RES0.4-1H] snapshots: start: "2018-01-01" @@ -15,10 +15,11 @@ snapshots: load_options: weather_year: 2018 # Load scenarios available with different weather year (different renewable potentials) + scale: 1.3705 electricity: extendable_carriers: - Generator: [solar, onwind, offwind-ac, offwind-dc, coal] + Generator: [solar, onwind, offwind-ac, offwind-dc, coal, ror] Store: [battery, H2] atlite: diff --git a/scripts/modify_demand.py b/scripts/modify_demand.py index e29435e..679552f 100644 --- a/scripts/modify_demand.py +++ b/scripts/modify_demand.py @@ -41,15 +41,21 @@ def rescale_load(n, gadm_demand, scale): logger.info(f"Rescaling GADM demand profile based on national report") official_demand = pd.read_csv(gadm_demand, index_col=0) - + official_demand = official_demand["Consumption (GWh)"] * 1e3 + + # regional scaling to official demand is not adjusted to global scaling factor + n.loads_t.p_set /= snakemake.config["load_options"]["scale"] pypsa_demand = n.loads_t.p_set.sum(axis=0) - scale_factor = (official_demand["Consumption (GWh)"] * 1e3) / pypsa_demand *scale + scale_factor = official_demand / pypsa_demand * scale n.loads_t.p_set.loc[:,official_demand.index] = ( n.loads_t.p_set.loc[:,official_demand.index] * scale_factor.loc[official_demand.index] ) + # regional scaling to official demand is not adjusted to global scaling factor + n.loads_t.p_set *= snakemake.config["load_options"]["scale"] + if True in n.generators.query("carrier=='coal'").p_nom_extendable.unique(): n.generators.loc[n.generators.carrier=="coal","p_nom_max"] = ( n.generators.loc[n.generators.carrier=="coal","p_nom"] @@ -71,9 +77,9 @@ def rescale_load(n, gadm_demand, scale): # Snakemake imports: gadm_demand = snakemake.input["gadm_demand_data"] start_date = datetime.strptime(snakemake.config["snapshots"]["start"], "%Y-%m-%d") - end_date =datetime.strptime( snakemake.config["snapshots"]["end"], "%Y-%m-%d") - scale = snakemake.config["load_options"]["scale"] *(end_date-start_date).days/365 - rescale_load(n, gadm_demand,scale) + end_date = datetime.strptime( snakemake.config["snapshots"]["end"], "%Y-%m-%d") + scale = (end_date-start_date).days/365 + rescale_load(n, gadm_demand, scale) # Snakemake output n.export_to_netcdf(snakemake.output.network) diff --git a/scripts/modify_lines.py b/scripts/modify_lines.py index 4ff3ab1..57b077c 100644 --- a/scripts/modify_lines.py +++ b/scripts/modify_lines.py @@ -65,6 +65,11 @@ def add_line(n): configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) + + if "ror" in snakemake.config["electricity"]["extendable_carriers"]["Generator"]: + ror_i = n.generators.query("carrier == 'ror'").index + n.generators.loc[ror_i, "p_nom_extendable"] = True + n.generators.loc[ror_i, "p_nom_min"] = n.generators.loc[ror_i, "p_nom"] boi = snakemake.config["lines"]["modify_lines"]["bus_of_interest"] max_limit = snakemake.config["lines"]["modify_lines"]["max_limit"] diff --git a/test/config_kz_test.yaml b/test/config_kz_default_test.yaml similarity index 96% rename from test/config_kz_test.yaml rename to test/config_kz_default_test.yaml index 4d33fdb..6c1560d 100644 --- a/test/config_kz_test.yaml +++ b/test/config_kz_default_test.yaml @@ -6,18 +6,19 @@ tutorial: false run: - name: "kz_test" # use this to keep track of runs with different settings + name: "kz_2013_default" # use this to keep track of runs with different settings shared_cutouts: true # set to true to share the default cutout(s) across runs # Note: value false requires build_cutout to be enabled scenario: ll: ['v1.0'] clusters: [5] - opts: [RES0.2-6H] + opts: [BAU-RES0.2-6H] countries: ["KZ"] + snapshots: start: "2013-01-01" end: "2013-01-02" @@ -46,6 +47,7 @@ build_shape_options: nchunks: 3 # number of data chuncks for build_shapes. If not specified or smaller than nprocesses, specified as nprocesses gadm_layer_id: 0 # set gadm level to 0 to simplify the case + load_options: rescale_demand: true external_loads: true # true - adds external load buses based on data/custom_data/electricity_exp-imp.csv diff --git a/test/config_kz_test1.yaml b/test/config_kz_test1.yaml new file mode 100644 index 0000000..e54aea7 --- /dev/null +++ b/test/config_kz_test1.yaml @@ -0,0 +1,117 @@ +# SPDX-FileCopyrightText: pypsa-kz-data authors +# +# SPDX-License-Identifier: CC0-1.0 + + +tutorial: false + +run: + name: "kz_2013" # use this to keep track of runs with different settings + shared_cutouts: true # set to true to share the default cutout(s) across runs + # Note: value false requires build_cutout to be enabled + +scenario: + ll: ['v1.0'] + clusters: [5] + opts: [6H] + + +countries: ["KZ"] + +snapshots: + start: "2013-01-01" + end: "2013-01-02" + + +enable: + build_natura_raster: false # If True, than an exclusion raster will be build + + +retrieve_databundle: # required to be "false" for nice CI test output + show_progress: true #false # show (true) or do not show (false) the progress bar in retrieve_databundle while downloading data + + +custom_rules: ["pypsa-kz-data/kz.smk"] + + +cluster_options: + simplify_network: + p_threshold_drop_isolated: 10 # [MW] isolated buses are being discarded if bus mean power is below the specified threshold + + alternative_clustering: false # "False" use Voronoi shapes, "True" use GADM shapes + + +build_shape_options: + nprocesses: 1 # number of processes to be used in build_shapes + nchunks: 3 # number of data chuncks for build_shapes. If not specified or smaller than nprocesses, specified as nprocesses + gadm_layer_id: 0 + +load_options: + rescale_demand: true + external_loads: true # true - adds external load buses based on data/custom_data/electricity_exp-imp.csv + +electricity: + base_voltage: 500. + voltages: [110., 220., 500.] + co2limit: 7.75e+11 # European default, 0.05 * 3.1e9*0.5, needs to be adjusted for Africa + co2base: 3.17e+8 # Kazakhstan default for 1990 + + + extendable_carriers: + Generator: [] + + + custom_powerplants: replace #merge #replace # "false" - no custom powerplants, "merge" use both open source and custom powerplants, "replace" use only custom powerplants + + + estimate_renewable_capacities: + stats: False #'irena' # False, = greenfield expansion, 'irena' uses IRENA stats to add expansion limits + + +lines: + types: + 220.: "490-AL1/64-ST1A 220.0" #"Al/St 240/40 2-bundle 220.0" + 110.: "243-AL1/39-ST1A 110.0" #"Al/St 240/40 3-bundle 300.0" + 500.: "Al/St 240/40 4-bundle 380.0" #"Al/St 560/50 4-bundle 750.0" # + + modify_lines: + limit_line_capacities: true # limiting line capacities + bus_of_interest: ["KZ.1_1_AC", "KZ.9_1_AC"] # buses of interest whose lines are limited + max_limit: 700.0 # maximum limit for s_nom + + +atlite: + nprocesses: 4 + cutouts: + # geographical bounds automatically determined from countries input + cutout-2013-era5-tutorial: + module: era5 + dx: 0.3 # cutout resolution + dy: 0.3 # cutout resolution + + +renewable: + onwind: + cutout: cutout-2013-era5-tutorial + + offwind-ac: + cutout: cutout-2013-era5-tutorial + + offwind-dc: + cutout: cutout-2013-era5-tutorial + + solar: + cutout: cutout-2013-era5-tutorial + + hydro: + cutout: cutout-2013-era5-tutorial + extendable: true + normalization: + method: eia #hydro_capacities # 'hydro_capacities' to rescale country hydro production by using hydro_capacities, 'eia' to rescale by eia data, false for no rescaling + year: 2013 # (optional) year of statistics used to rescale the runoff time series. When not provided, the weather year of the snapshots is used + + +costs: + year: 2020 + fill_values: + discount rate: 0.15