diff --git a/CHANGELOG.md b/CHANGELOG.md index e8993779c..052997abf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### changed -- +- **scripts** peatland rewetting now automatically considered in `extra/runSEALSallocation.R` ### added - diff --git a/config/default.cfg b/config/default.cfg index 8b5941ac4..50d4a57f0 100644 --- a/config/default.cfg +++ b/config/default.cfg @@ -25,7 +25,7 @@ cfg$model <- "main.gms" #def = "main.gms" cfg$input <- c(regional = "rev4.116_h12_magpie.tgz", cellular = "rev4.116_h12_fd712c0b_cellularmagpie_c200_MRI-ESM2-0-ssp370_lpjml-8e6c5eb1.tgz", validation = "rev4.116_h12_validation.tgz", - additional = "additional_data_rev4.59.tgz", + additional = "additional_data_rev4.60.tgz", calibration = "calibration_H12_27Sep24.tgz") # NOTE: It is recommended to recalibrate the model when changing cellular input data @@ -612,7 +612,7 @@ cfg$gms$s21_trade_tariff_startyear <- 2025 # * end year of fadeout if s21_trade_tariff_fadeout = 1 # def = 2050 cfg$gms$s21_trade_tariff_targetyear <- 2050 -# * Minimum trade margin for forestry products (USD17MER per tDM) +# * Minimum trade margin for forestry products (USD17MER per tDM) # * (inflated from default originally in USD05 using USD05 --> USD17 inflation rate:1.23) cfg$gms$s21_min_trade_margin_forestry <- 62 # def = 50 * 1.23 @@ -760,8 +760,8 @@ cfg$gms$s29_treecover_scenario_start <- 2025 # def = 2025 cfg$gms$s29_treecover_scenario_target <- 2050 # def = 2050 # * Penalty for violation of treecover target before scenario start (USD17MER per ha) # * (inflated from default originally in USD05 using USD05 --> USD17 inflation rate:1.23) -cfg$gms$s29_treecover_penalty_before <- 0 # def = 0 -# * Penalty for violation of treecover target after scenario start (USD17MER per ha) +cfg$gms$s29_treecover_penalty_before <- 0 # def = 0 +# * Penalty for violation of treecover target after scenario start (USD17MER per ha) # * (inflated from default originally in USD05 using USD05 --> USD17 inflation rate: 1.23) cfg$gms$s29_treecover_penalty <- 6150 # def = 5000 * 1.23 # * Tree cover establishment cost (USD17MER per ha) @@ -1733,13 +1733,13 @@ cfg$gms$policy_countries58 <- all_iso_countries cfg$gms$s58_rewetting_exo <- 0 # def = 0 # * Switch for exogenous peatland rewetting for all other countries (0=off, 1=on) cfg$gms$s58_rewetting_exo_noselect <- 0 # def = 0 -# * The following default values for exogenous peatland rewetting are based on the +# * The following default values for exogenous peatland rewetting are based on the # * Nature Restoration Law (NRL): 30 % by 2030, 40% by 2040, 50% by 2050 # * Start year for exogenous peatland rewetting cfg$gms$s58_rewet_exo_start_year <- 2030 # def = 2030 # * Target year for exogenous peatland rewetting cfg$gms$s58_rewet_exo_target_year <- 2050 # def = 2050 -# * Start value for exogenous peatland rewetting as share of drained peatland in reference period +# * Start value for exogenous peatland rewetting as share of drained peatland in reference period cfg$gms$s58_rewet_exo_start_value <- 0.3 # def = 0.3 # * Target value for exogenous peatland rewetting as share of drained peatland in reference period cfg$gms$s58_rewet_exo_target_value <- 0.5 # def = 0.5 @@ -1907,9 +1907,9 @@ cfg$gms$c60_biodem_level <- 1 # def = 1 cfg$gms$s60_2ndgen_bioenergy_dem_min <- 1 # def = 1 # * t DM-based first generation bioenergy subsidy (USD17MER per ton) -# * The subsidy can simulate a perfectly elastic demand for bioenergy from the energy sector and should be used as a -# * default floor price that avoids the wastage of ethanal or oils in case that the demand for byproducts -# * (oilcake and brewers grains) exceeds the demand for these secondary products. As such, it also avoids unrealistic +# * The subsidy can simulate a perfectly elastic demand for bioenergy from the energy sector and should be used as a +# * default floor price that avoids the wastage of ethanal or oils in case that the demand for byproducts +# * (oilcake and brewers grains) exceeds the demand for these secondary products. As such, it also avoids unrealistic # * price fluctuations connected to the inelastic demand for couple products. # * (1stgen_priced_dec18): c60_bioenergy_subsidy is applied constant over historic and model horizon, c60_bioenergy_subsidy_fix_SSP2 has no effect # * (1st2ndgen_priced_feb24): c60_bioenergy_subsidy_fix_SSP2 is applied constant to historic time steps (up until sm_fix_SSP2). diff --git a/scripts/output/extra/runSEALSallocation.R b/scripts/output/extra/runSEALSallocation.R index 26b8fcfdf..cbf692ae8 100644 --- a/scripts/output/extra/runSEALSallocation.R +++ b/scripts/output/extra/runSEALSallocation.R @@ -10,11 +10,12 @@ # comparison script: FALSE # --------------------------------------------------------------- -# Version 1.00 - Patrick v. Jeetze, Pascal Sauer -# 1.00: first working version +# Version 1.1.0 - Patrick v. Jeetze, Pascal Sauer +# 1.0.0: first working version +# 1.1.0: SEALS coefficients are modified based on scenario settings library(gms) -library(gdx) +library(gdx2) library(magpie4) library(filelock) @@ -63,9 +64,10 @@ if (length(cfg$seals_years) != 0) { } # Restructure data to conform to SEALS +sealsInput <- paste0("cell.land_0.5_SEALS_", title, ".nc") reportLandUseForSEALS( magCellLand = "cell.land_0.5_share.mz", - outFile = paste0("cell.land_0.5_SEALS_", title, ".nc"), + outFile = sealsInput, dir = outputdir, selectyears = rep_years ) @@ -108,11 +110,13 @@ Sys.chmod(iniLock, mode = "0664") # Prepare SEALS start script # -------------------------------- -.setupSEALSrun <- function(title, dir, dirProject, dirSEALS, dirBaseFiles) { +.setupSEALSrun <- function(cfg, sealsInput, dir, dirProject, dirSEALS, dirBaseFiles) { if (!dir.exists(file.path(dirProject, "scripts"))) { dir.create(file.path(dirProject, "scripts"), recursive = TRUE) } + title <- cfg$title + file.copy( from = list.files(file.path(dirSEALS, "seals"), full.names = TRUE), to = file.path(dirProject, "scripts"), @@ -124,11 +128,89 @@ Sys.chmod(iniLock, mode = "0664") dir.create(file.path(dirProject, "inputs"), recursive = TRUE) } - file.copy( - from = file.path(dir, paste0("seals_scenario_config_", title, ".csv")), - to = file.path(dirProject, "inputs", paste0("seals_scenario_config_", title, ".csv")), - overwrite = TRUE - ) + rcp <- unlist(strsplit(cfg$input["cellular"], "_"))[6] + rcp <- paste0("rcp", substr(rcp, nchar(rcp) - 1, nchar(rcp))) + + ssp <- tolower(cfg$gms$c09_pop_scenario) + + if (length(cfg$seals_years) != 0) { + sealsYears <- cfg$seals_years[cfg$seals_years > 2020] + sealsYears <- paste(sealsYears, collapse = " ") + } else { + sealsYears <- "2050" + } + + scenarioType <- ifelse(grepl("default|bau|ssp\\d-ref", tolower(title)), "bau", "policy") + + if (cfg$gms$c22_protect_scenario == "none") { + consv <- cfg$gms$c22_base_protect + } else { + consv <- cfg$gms$c22_protect_scenario + } + + ### Modify SEALS model coefficients based on scenario settings + + message("Updating SEALS model coefficients based on scenario settings") + + sealsCoeff <- paste0(c("./", "../", "../../"), "input/seals_global_coefficients.csv") + sealsCoeff <- Find(file.exists, sealsCoeff) + + if (!is.null(sealsCoeff)) { + sealsCoeff <- read.csv(sealsCoeff) + consvRow <- which(sealsCoeff[, "spatial_regressor_name"] == "land_conservation") + sealsCoeff[consvRow, "data_location"] <- sub( + "WDPA", consv, sealsCoeff[consvRow, "data_location"] + ) + + peatArea <- PeatlandArea(file.path(dir, "fulldata.gdx"))[, as.numeric(sealsYears), ] + rewetSwitch <- dimSums(peatArea[, , "rewet"], dim = 1) / dimSums(peatArea, dim = c(1, 3)) > 0.01 + if (any(c(rewetSwitch))) { + peatRow <- which(sealsCoeff[, "spatial_regressor_name"] == "peatland_rewetting") + # SEALS rewetting coefficient + rewetCoeff <- 10000 + # disincentivise agricultural expansion + sealsCoeff[peatRow, c("cropland", "grassland")] <- rewetCoeff + # peatland rewetting incentive + sealsCoeff[peatRow, c("forest", "othernat")] <- -rewetCoeff + } + + sealsCoeffPath <- file.path( + dirProject, "inputs", + paste0("seals_global_coefficients_", title, ".csv") + ) + + write.csv(sealsCoeff, sealsCoeffPath, + row.names = FALSE, na = "", quote = FALSE # quote = FALSE is critical here! + ) + } else { + stop("Could not find seals_global_coefficients.csv file") + } + + + ### Create SEALS scenario definitions CSV + + message("Creating SEALS scenario definitions CSV") + + sealsConfig <- paste0(c("./", "../", "../../"), "input/seals_scenario_config.csv") + sealsConfig <- Find(file.exists, sealsConfig) + + if (!is.null(sealsConfig)) { + sealsConfig <- read.csv(sealsConfig) + sealsConfig[nrow(sealsConfig), "scenario_label"] <- title + sealsConfig[nrow(sealsConfig), "scenario_type"] <- scenarioType + sealsConfig[nrow(sealsConfig), "exogenous_label"] <- ssp + sealsConfig[nrow(sealsConfig), "climate_label"] <- rcp + sealsConfig[nrow(sealsConfig), "counterfactual_label"] <- title + sealsConfig[nrow(sealsConfig), "comparison_counterfactual_labels"] <- ifelse(scenarioType == "bau", "", "bau") + sealsConfig[, "coarse_projections_input_path"] <- normalizePath(file.path(dir, sealsInput)) + sealsConfig[nrow(sealsConfig), "years"] <- sealsYears + sealsConfig[nrow(sealsConfig), "calibration_parameters_source"] <- normalizePath(sealsCoeffPath) + write.csv(sealsConfig, file.path(dirProject, "inputs", paste0("seals_scenario_config_", title, ".csv")), + row.names = FALSE, na = "", quote = FALSE # quote = FALSE is critical here! + ) + } else { + stop("Could not find seals_scenario_config.csv file template") + } main <- readLines(file.path(dirProject, "scripts", "run_test_standard.py")) @@ -200,19 +282,21 @@ Sys.chmod(iniLock, mode = "0664") if (!is.null(lockOn)) { sealsLock <- file.path(dirProject, "seals.lock") + .setupSEALSrun( + cfg = cfg, + sealsInput = sealsInput, + dir = outputdir, + dirProject = dirProject, + dirSEALS = dirSEALS, + dirBaseFiles = dirBaseFiles + ) + if (!file.exists(sealsLock) || file.size(sealsLock) == 0) { message(paste( "Starting SEALS allocation with input data creation.\n", "Stitched SEALS allocation outputs will be written to", "'./output/seals/intermediate/stitched_lulc_simplified_scenarios'" )) - .setupSEALSrun( - title = title, - dir = outputdir, - dirProject = dirProject, - dirSEALS = dirSEALS, - dirBaseFiles = dirBaseFiles - ) id <- .submitSEALS( title = title, @@ -225,22 +309,14 @@ if (!is.null(lockOn)) { writeLines(id, sealsLock) } else { + id <- readLines(sealsLock) + message(paste( "Starting SEALS allocation using existing input data.\n", "Stitched SEALS allocation outputs will be written to", "'./output/seals/intermediate/stitched_lulc_simplified_scenarios'" )) - id <- readLines(sealsLock) - - .setupSEALSrun( - title = title, - dir = outputdir, - dirProject = dirProject, - dirSEALS = dirSEALS, - dirBaseFiles = dirBaseFiles - ) - .submitSEALS( title = title, dirProject = dirProject,