Skip to content
Snippets Groups Projects
start_bundle_coupled.R 17.3 KiB
Newer Older
Lavinia Baumstark's avatar
Lavinia Baumstark committed
# |  (C) 2006-2019 Potsdam Institute for Climate Impact Research (PIK)
# |  authors, and contributors see CITATION.cff file. This file is part
# |  of REMIND and licensed under AGPL-3.0-or-later. Under Section 7 of
# |  AGPL-3.0, you are granted additional permissions described in the
# |  REMIND License Exception, version 1.0 (see LICENSE file).
# |  Contact: remind@pik-potsdam.de
########################################################################################################
#################################  U S E R   S E T T I N G S ###########################################
########################################################################################################

# Please provide all files and paths relative to the folder where start_coupled is executed
path_remind <- paste0(getwd(),"/")   # provide path to REMIND. Default: the actual path which the script is started from
path_magpie <- "/p/projects/piam/runs/coupled-magpie/"

# If there are existing runs you would like to take the gdxes (REMIND) or reportings (REMIND or MAgPIE) from provide the path and name prefix here. 
# Note: the sceanrio names have to be identical to the runs that are to be started. If they differ please provide the names of the old scenarios in the 
# file that you read in below to path_settings_coupled
path_remind_oldruns <- paste0(path_remind,"output-20200129/")
path_magpie_oldruns <- paste0(path_magpie,"output-20200129/")
Lavinia Baumstark's avatar
Lavinia Baumstark committed

# The scripts automatically adds a prefix (name of your remind path) to the scenario names. This is useful because it enables 
# using the same MAgPIE and REMIND output folders to store results of coupled runs from multiple REMIND revisions (prevents double names)
# If you want the script to find gdxs or reports of older runs as starting point for new runs please 
# provide the prefix of the old run names so the script can find them.
prefix_oldruns <-  "C_" # "REMIND_" # "coupled-remind_" # 
Lavinia Baumstark's avatar
Lavinia Baumstark committed

# Paths to the files where scenarios are defined
# path_settings_remind contains the detailed configuration of the REMIND scenarios
# path_settings_coupled defines which runs will be started, coupling infos, and optinal gdx and report inforamtion that overrides path_settings_remind
path_settings_coupled <- paste0(path_remind,"config/scenario_config_coupled_SSPSDP.csv")
path_settings_remind  <- paste0(path_remind,"config/scenario_config_SSPSDP.csv")

# number of coupling iterations
max_iterations <- 5

# Number of coupling iterations (before final iteration) in which MAgPIE uses higher n600 resolution.
# Until "max_iteration - n600_iterations" iteration MAgPIE runs with n200 resolution.
# Afterwards REMIND runs for "n600_iterations" iterations with results from higher resolution.
n600_iterations <- 0 # max_iterations

########################################################################################################
########################################################################################################
########################################################################################################

require(magclass)
require(lucode)
require(remind)
require(gtools) # required for mixedsort()

####################################################
############## F U N C T I O N S ###################
####################################################
.setgdxcopy <- function(needle,stack,new){
  # delete entries in stack that contain needle and append new
  matches <- grepl(needle,stack)
  out <- c(stack[!matches],new)
  return(out)
}

####################################################
##############  READ FROM COMMAND LINE #############
####################################################
readArgs("test")

####################################################
##############  READ SCENARIO FILES ################
####################################################
# Read-in the switches table, use first column as row names

scenarios_coupled <- read.csv2(path_settings_coupled, stringsAsFactors = FALSE, row.names=1, na.strings="")

# Read in

settings_remind <- read.csv2(path_settings_remind, stringsAsFactors = FALSE, row.names=1, na.strings="")

# Choose which scenarios to start: select rows according to "subset" and columns according to "select" (not used in the moment)
scenarios_coupled  <- subset(scenarios_coupled, subset=(start == "1"))
if (length(grep("\\.",rownames(scenarios_coupled))) > 0) stop("One or more titles contain dots - GAMS would not tolerate this, and quit working at a point where you least expect it. Stopping now. ")

missing <- setdiff(rownames(scenarios_coupled),rownames(settings_remind))
if (!identical(missing, character(0))) {
  cat(paste0("The following scenarios are given in '",path_settings_coupled,"' but could not be found in '",path_settings_remind,"'\n"))
  cat(missing,sep="\n")
}

common <- intersect(rownames(settings_remind),rownames(scenarios_coupled))
if (!identical(common,character(0))) {
  cat("The following ",length(common)," scenarios will be started:\n")
  cat(common,sep="\n")
}

####################################################
######## PREPARE AND START COUPLED RUNS ############
####################################################
for(scen in common){
  cat(paste0("\n################################\nPreparing run ",scen,"\n"))
  
  prefix_runname <- "C" #strsplit(path_remind,"/")[[1]][length(strsplit(path_remind,"/")[[1]])]
Lavinia Baumstark's avatar
Lavinia Baumstark committed
  prefix_runname <- paste0(prefix_runname,"_")
  
  runname      <- paste0(prefix_runname,scen)            # name of the run that is used for the folder names
  path_report  <- NULL                                   # sets the path to the report REMIND is started with in the first loop
  LU_pricing   <- scenarios_coupled[scen, "LU_pricing"]  # indicates whether GHG prices should be used by MAgPIE or not
  
  start_iter <- 1 # iteration to start the coupling with
  
  # look whether there is already a REMIND run (check for old name if provided)
  if (!is.na(scenarios_coupled[scen, "oldrun"])) {
    needle <- scenarios_coupled[scen, "oldrun"]
  } else {
    needle <- scen
  }
	
  # Check for existing REMIND and MAgPIE runs and whether iteration can be continued from those (at least one REMIND iteration has to exist!)
  suche <- paste0(path_remind_oldruns,prefix_oldruns,needle,"-rem-*/fulldata.gdx")
  already_rem <- Sys.glob(suche)
  if(identical(already_rem,character(0))) cat("Nothing found for",suche,"\n")

  if (!identical(already_rem, character(0))) {
    # if there is an existing REMIND run use it's gdx for the run to be started
	  already_rem <- mixedsort(already_rem)[1]
	  settings_remind[scen, "path_gdx"] <- normalizePath(already_rem)
    cat(paste0("\nFound gdx here: ",normalizePath(already_rem),"\n"))
    iter_rem <- 0
    # is there a coupling iteration that could be continued?
    if(identical(paste0(path_remind,"output/"),path_remind_oldruns) && identical(prefix_runname,prefix_oldruns) && is.na(scenarios_coupled[scen, "oldrun"])) {
      # continue counting only if remind is started in the same directoy the gdxes are taken from
      iter_rem <- as.integer(sub(".*rem-(\\d.*)/.*","\\1",already_rem))
    }
      
    # is there already a MAgPIE run with this name?
    suche <- paste0(path_magpie_oldruns,prefix_oldruns,needle,"-mag-*/report.mif")
    already_mag <- Sys.glob(suche)
    if(identical(already_mag,character(0))) cat("Nothing found for",suche,"\n")
    iter_mag <- 0
    if (!identical(already_mag, character(0))) {
      already_mag <- mixedsort(already_mag)[1]
      path_report <- normalizePath(already_mag)
      cat(paste0("Found MAgPIE report here: ",normalizePath(already_mag),"\n"))
      iter_mag <- as.integer(sub(".*mag-(\\d.*)/.*","\\1",already_mag))
    }
    # decide whether to continue with REMIND or MAgPIE
    if (iter_rem > iter_mag) {
      # if only remind has finished an iteration -> start with magpie in this iteration using a REMIND report
      start_iter  <- iter_rem
      path_run    <- gsub("/fulldata.gdx","",already_rem)
      path_report <- Sys.glob(paste0(path_run,"/REMIND_generic_*","withoutPlus.mif"))
      if (identical(path_report,character(0))) stop("There is a fulldata.gdx but no REMIND_generic_.mif in",path_run)
      cat("Found REMIND report here: ",path_report,"\n")
      cat("Continuing with MAgPIE in iteration ",start_iter,"\n")
    } else {
      # if remind and magpie iteration is the same -> start next iteration with REMIND with or without MAgPIE report
      start_iter <- iter_rem + 1
    }
  }

  cat(paste0("Set start iteration to: ",start_iter,"\n"))

	# If a gdx is provided in scenario_config_coupled.csv use it instead of any previouly found 
  if (!is.na(scenarios_coupled[scen, "path_gdx"])) {
    settings_remind[scen, "path_gdx"] <- scenarios_coupled[scen, "path_gdx"]
    cat("Using gdx specified in\n  ",path_settings_coupled,"\n  ",settings_remind[scen, "path_gdx"],"\n")
  }
  
  # If provided replace the path to the MAgPIE report found automatically with path given in scenario_config_coupled.csv
  if (!is.na(scenarios_coupled[scen, "path_report"])) {
    path_report  <- scenarios_coupled[scen, "path_report"] # sets the path to the report REMIND is started with in the first loop
      cat("Replacing path to MAgPIE report with that one specified in\n  ",path_settings_coupled,"\n  ",scenarios_coupled[scen, "path_report"],"\n")
  }

  source(paste0(path_remind,"config/default.cfg")) # retrieve REMIND settings
  cfg_rem <- cfg
  rm(cfg)
  
  source(paste0(path_magpie,"config/default.cfg")) # retrieve MAgPIE settings
  cfg_mag <- cfg
  rm(cfg)

  # configure MAgPIE according to magpie_scen (scenario needs to be available in scenario_config.cfg)
  if(!is.null(scenarios_coupled[scen, "magpie_scen"])) cfg_mag <- setScenario(cfg_mag,c(trimws(unlist(strsplit(scenarios_coupled[scen, "magpie_scen"],split=","))),"coupling"),scenario_config=paste0(path_magpie,"config/scenario_config.csv"))
  cfg_mag <- check_config(cfg_mag, reference_file=paste0(path_magpie,"config/default.cfg"),modulepath = paste0(path_magpie,"modules/"))

  # How to provide the exogenous TC to MAgPIE:
  # Running MAgPIE with exogenous TC requires a path with exogenous TC. Using exo_indc_MAR17 the path is chosen via c13_tau_scen. 
  # Using exo_JUN13 the path is given in the file modules/13_tc/exo_JUN13/input/tau_scenario.csv
  # This file can be generated (prior to all runs that use exogenous TC) using the following lines of code:
  #  require(magpie) # for tau function
  #  write.magpie(tau("/p/projects/htc/MagpieEmulator/r11356/magmaster/output/SSP2-SSP2-Ref-SPA0-endo-73-lessts/fulldata.gdx"),"modules/13_tc/exo_JUN13/input/tau_scenario.csv")
  #  Useful in case years mismatch:
  #  t  <- tau("/p/projects/htc/MagpieEmulator/r11356/magmaster/output/SSP2-SSP2-Ref-SPA0-endo-73/fulldata.gdx")
  #  y  <- c(seq(2005,2060,5),seq(2070,2110,10),2130,2150)
  #  tn <- time_interpolate(t,y,integrate_interpolated_years=TRUE,extrapolation_type = "constant")
  #  write.magpie(tn,"modules/13_tc/exo_JUN13/input/tau_scenario.csv")

  # Switch REMIND and MAgPIE to endogenous TC
  #cat("Setting MAgPIE to endogenous TC\n")
  #cfg_mag$gms$tc      <- "inputlib"
  #cfg_rem$gms$biomass <- "magpie_linear"

  # Configure Afforestation in MAgPIE
   if (grepl("-aff760",scen)) {
      cat("Setting MAgPIE max_aff_area to 760\n")
      cfg_mag$gms$s32_max_aff_area <- 760
  } else if (grepl("-aff900",scen)) {
      cat("Setting MAgPIE max_aff_area to 900\n")
      cfg_mag$gms$s32_max_aff_area <- 900
  } else if (grepl("-affInf",scen)) {
      cat("Setting MAgPIE max_aff_area to Inf\n")
      cfg_mag$gms$s32_max_aff_area <- Inf
  } else if (grepl("-cost2",scen)) {
      cat("Setting MAgPIE cprice_red_factor to 0.2\n")
      cfg_mag$gms$s56_cprice_red_factor <- 0.2
      cfg_mag$gms$s32_max_aff_area <- Inf
  } else if (grepl("-cost3",scen)) {
      cat("Setting MAgPIE cprice_red_factor to 0.3\n")
      cfg_mag$gms$s56_cprice_red_factor <- 0.3
      cfg_mag$gms$s32_max_aff_area <- Inf
  }

  #cfg$logoption  <- 2  # Have the log output written in a file (not on the screen)

  # Add non-gms-switches manually
  if( "regionmapping" %in% names(settings_remind)){
    cfg_rem$regionmapping <- settings_remind[scen,"regionmapping"] 
  }
  
  # Edit default.cfg settings according to the SSP scenarios only for elements in 'scenarios' that exist in the cfg
  for (switchname in intersect(names(cfg_rem$gms),names(settings_remind))){
    cfg_rem$gms[[switchname]] <- settings_remind[scen,switchname]
  }
  
  # If provided replace gdx paths given in scenario_config_SSP with paths given in scenario_config_coupled
  if (!is.na(scenarios_coupled[scen, "path_gdx_bau"])) {
	  settings_remind[scen, "path_gdx_bau"] <- scenarios_coupled[scen, "path_gdx_bau"]
	  cat("Replacing gdx_bau information with those specified in\n  ",path_settings_coupled,"\n  ",settings_remind[scen, "path_gdx_bau"],"\n")
  }
  
  if (!is.na(scenarios_coupled[scen, "path_gdx_ref"])) {
	  settings_remind[scen, "path_gdx_ref"] <- scenarios_coupled[scen, "path_gdx_ref"]
	  cat("Replacing gdx_ref information with those specified in\n  ",path_settings_coupled,"\n  ",settings_remind[scen, "path_gdx_ref"],"\n")
  }
 
  # Create list of previously defined paths to gdxs
  gdxlist <- c(input.gdx     = settings_remind[scen, "path_gdx"], # eventually this was updated if older runs exists in this folder (see above)
               input_ref.gdx = settings_remind[scen, "path_gdx_ref"],
               input_bau.gdx = settings_remind[scen, "path_gdx_bau"])
Lavinia Baumstark's avatar
Lavinia Baumstark committed

  # Remove potential elements that contain ".gdx" and append gdxlist
  cfg_rem$files2export$start <- .setgdxcopy(".gdx",cfg_rem$files2export$start,gdxlist)
  
  # add information on subsequent runs to start after the current run is finished
  # take rownames (which is the runname) of that row, that has the current scenario in its gdx_ref
  cfg_rem$subsequentruns <- intersect(rownames(settings_remind[settings_remind$path_gdx_ref == scen & !is.na(settings_remind$path_gdx_ref),]),common)
Lavinia Baumstark's avatar
Lavinia Baumstark committed
     
  # immediately start run if it has a real gdx file (not a runname) given (last four letters are ".gdx") in path_gdx_ref or where this field is empty (NA)
  start_now <- (substr(settings_remind[scen,"path_gdx_ref"], nchar(settings_remind[scen,"path_gdx_ref"])-3, nchar(settings_remind[scen,"path_gdx_ref"])) == ".gdx" 
               | is.na(settings_remind[scen,"path_gdx_ref"]))
               
  if (!start_now) {
      # if no real file is given but a reference to another scenario (that has to run first) create path for input_ref and input_bau
      # using the scenario names given in the columns path_gdx_ref and path_gdx_ref in the REMIND standalone scenario config
      cfg_rem$files2export$start['input_ref.gdx'] <- paste0(path_remind,"output/",prefix_runname,settings_remind[scen,"path_gdx_ref"],"-rem-",max_iterations,"/fulldata.gdx")
      cfg_rem$files2export$start['input_bau.gdx'] <- paste0(path_remind,"output/",prefix_runname,settings_remind[scen,"path_gdx_bau"],"-rem-",max_iterations,"/fulldata.gdx")
      
      # If the preceding run has already finished (= their gdx files exist) start the current run immediately.
      # This might be the case e.g. if you started the baseline and NDC runs in a first batch and now want to start the subsequent policy runs by hand after the baselines have finished
      if (file.exists(cfg_rem$files2export$start['input_ref.gdx']) & file.exists(cfg_rem$files2export$start['input_bau.gdx'])) {
        start_now <- TRUE
      }
  }

  # set start year of GHG emission pricing phase-in (only used in price_jan19)
  cfg_mag$gms$s56_ghgprice_start <- cfg_rem$gms$cm_startyear
  
  save(path_remind,path_magpie,cfg_rem,cfg_mag,runname,max_iterations,start_iter,n600_iterations,path_report,LU_pricing,file=paste0(runname,".RData"))

  # Define colors for output
  red   <- "\033[0;31m"
  green <- "\033[0;32m"
  NC    <- "\033[0m"   # No Color

  # convert from logi to character so file.exists does not throw an error
  path_report <- as.character(path_report)
  
  cat("\nSUMMARY\n")
  cat("runname     :",runname,"\n")
  cat("start_iter  :",start_iter,"\n")
  cat("path_remind : ",ifelse(dir.exists(path_remind),green,red), path_remind, NC, "\n",sep="")
  cat("path_magpie : ",ifelse(dir.exists(path_magpie),green,red), path_magpie, NC, "\n",sep="")
  cat("remind gdx  : ",ifelse(file.exists(cfg_rem$files2export$start["input.gdx"]),green,red), cfg_rem$files2export$start["input.gdx"], NC, "\n",sep="")
  cat("ref_gdx     : ",ifelse(file.exists(cfg_rem$files2export$start["input_ref.gdx"]),green,red), cfg_rem$files2export$start["input_ref.gdx"], NC, "\n",sep="")
  cat("bau_gdx     : ",ifelse(file.exists(cfg_rem$files2export$start["input_bau.gdx"]),green,red), cfg_rem$files2export$start["input_bau.gdx"], NC, "\n",sep="")
  cat("path_report : ",ifelse(file.exists(path_report),green,red), path_report, NC, "\n",sep="")
  cat("LU_pricing  :",LU_pricing,"\n")
 
  if (cfg_rem$gms$optimization == "nash" && cfg_rem$gms$cm_nash_mode == "parallel") {
    # for nash: set the number of CPUs per node to number of regions + 1
    nr_of_regions <- length(levels(read.csv2(cfg_rem$regionmapping)$RegionCode)) + 1 
  } else {
    # for negishi: use only one CPU
Lavinia Baumstark's avatar
Lavinia Baumstark committed
  }

  if (start_now){
      if (!exists("test")) system(paste0("sbatch --qos=priority --job-name=",runname," --output=",runname,".log --mail-type=END --comment=REMIND-MAgPIE --tasks-per-node=",nr_of_regions," --wrap=\"Rscript start_coupled.R coupled_config=",runname,".RData\""))
Lavinia Baumstark's avatar
Lavinia Baumstark committed
      else cat("Test mode: run NOT submitted to the cluster\n")
  } else {
     cat(paste0("Run ",runname," will start after preceding run ",prefix_runname,settings_remind[scen,"path_gdx_ref"]," has finished\n"))
  }
}