Skip to content

Commit

Permalink
reactive check_config, add regexp check for cfg$… values
Browse files Browse the repository at this point in the history
  • Loading branch information
orichters committed Jul 12, 2023
1 parent 8b10e06 commit 3ed5db8
Show file tree
Hide file tree
Showing 15 changed files with 288 additions and 88 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ test-coupled: ## Test if the coupling with MAgPIE works. Takes significantly
$(info Coupling tests take around 75 minutes to run, please be patient)
@R_PROFILE_USER= TESTTHAT_RUN_SLOW=TRUE Rscript -e 'testthat::test_file("tests/testthat/test_20-coupled.R")'

test-coupled-slurm: ## test-coupled, but on slurm
$(info Coupling tests take around 75 minutes to run. Sent to slurm, find log in test-coupled.log)
@sbatch --qos=priority --wrap="make test-coupled" --job-name=test-coupled --mail-type=END --output=test-coupled.log

test-full: ## Run all tests, including coupling tests and a default
## REMIND scenario. Takes significantly longer than 10 minutes to run.
$(info Full tests take more than an hour to run, please be patient)
Expand Down
102 changes: 59 additions & 43 deletions main.gms

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions modules/46_carbonpriceRegi/NDC/datainput.gms
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $offdelim
$onlisting
;

Parameter p46_factorTargetyear(t,all_regi) "Multiplier for target year emissions vs 2005 emissions, as weighted average for all countries with quantifyable emissions under NDC in particular region";
Parameter p46_factorTargetyear(ttot,all_regi) "Multiplier for target year emissions vs 2005 emissions, as weighted average for all countries with quantifyable emissions under NDC in particular region";
p46_factorTargetyear(t,all_regi) = f46_factorTargetyear(t,all_regi,"%cm_NDC_version%","%cm_GDPscen%");

display p46_factorTargetyear;
Expand All @@ -34,7 +34,7 @@ $offdelim
$onlisting
;

Parameter p46_2005shareTarget(t,all_regi) "2005 GHG emission share of countries with quantifyable emissions under NDC in particular region, time dimension specifies alternative future target years";
Parameter p46_2005shareTarget(ttot,all_regi) "2005 GHG emission share of countries with quantifyable emissions under NDC in particular region, time dimension specifies alternative future target years";
p46_2005shareTarget(t,all_regi) = f46_2005shareTarget(t,all_regi,"%cm_NDC_version%","%cm_GDPscen%");

display p46_2005shareTarget;
Expand All @@ -52,7 +52,7 @@ p46_histShare(tall,all_regi) = f46_histShare(tall,all_regi,"%cm_NDC_version%");

display p46_histShare;

Parameter p46_BAU_reg_emi_wo_LU_bunkers(t,all_regi) "regional GHG emissions (without LU and bunkers) in BAU scenario"
Parameter p46_BAU_reg_emi_wo_LU_bunkers(ttot,all_regi) "regional GHG emissions (without LU and bunkers) in BAU scenario"
/
$ondelim
$ifthen exist "./modules/46_carbonpriceRegi/NDC/input/pm_BAU_reg_emi_wo_LU_bunkers.cs4r"
Expand Down Expand Up @@ -86,9 +86,9 @@ Scalar p46_ignoreNDCafter "NDC targets after this years are ignored,
Scalar p46_minRatioOfCoverageToMax "only targets whose coverage is this times p46_bestNDCcoverage are considered. Use 1 for only best." /0.2/;
Scalar p46_useSingleYearCloseTo "if 0: use all. If > 0: use only one single NDC target per country closest to this year (use 2030.4 to prefer 2030 over 2035 over 2025)" /0/;

Set p46_NDCyearSet(t,all_regi) "YES for years whose NDC targets is used";
Set p46_NDCyearSet(ttot,all_regi) "YES for years whose NDC targets is used";
Parameter p46_bestNDCcoverage(all_regi) "highest coverage of NDC targets within region";
Parameter p46_distanceToOptyear(t,all_regi) "distance to p46_useSingleYearCloseTo to favor years in case of multiple equally good targets";
Parameter p46_distanceToOptyear(ttot,all_regi) "distance to p46_useSingleYearCloseTo to favor years in case of multiple equally good targets";
Parameter p46_minDistanceToOptyear(all_regi) "minimal distance to p46_useSingleYearCloseTo per region";

p46_bestNDCcoverage(regi) = smax(t$(t.val <= p46_ignoreNDCafter AND t.val >= p46_ignoreNDCbefore), p46_2005shareTarget(t,regi));
Expand Down
50 changes: 50 additions & 0 deletions scripts/start/checkFixCfg.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
checkFixCfg <- function(cfg, remindPath = ".", testmode = FALSE) {
refcfg <- gms::readDefaultConfig(remindPath)
gms::check_config(cfg, reference_file = refcfg, modulepath = file.path(remindPath, "modules"),
settings_config = file.path(remindPath, "config", "settings_config.csv"),
extras = c("backup", "remind_folder", "pathToMagpieReport", "cm_nash_autoconverge_lastrun",
"gms$c_expname", "restart_subsequent_runs", "gms$c_GDPpcScen",
"gms$cm_CES_configuration", "gms$c_description", "model"))

errorsfound <- 0

code <- system(paste0("grep regexp ", file.path(remindPath, "main.gms")), intern = TRUE)
grepisnum <- "((\\+|-)?[0-9]*([0-9]\\.?|\\.?[0-9])[0-9]*)"

for (n in names(cfg$gms)) {
errormsg <- NULL
paramdef <- paste0("^([ ]*", n, "[ ]*=|\\$setglobal[ ]+", n, " )")
filtered <- grep(paste0(paramdef, ".*regexp[ ]*=[ ]*"), code, value = TRUE)
if (length(filtered) == 1) {
# search for string '!! regexp = whatever', potentially followed by '!! otherstuff' and extract 'whatever'
regexp <- paste0("^(", trimws(gsub("!!.*", "", gsub("^.*regexp[ ]*=", "", filtered))), ")$")
useregexp <- gsub("is.numeric", grepisnum, regexp, fixed = TRUE)
if (! grepl(useregexp, cfg$gms[[n]])) {
errormsg <- paste0("Parameter cfg$gms$", n, "=", cfg$gms[[n]], " does not fit this regular expression: ", regexp)
}
} else if (length(filtered) > 1) {
errormsg <- paste0("More than one regexp found for ", n, ". These are the code lines:\n", paste(filtered, collapse = "\n"))
}
if (! is.null(errormsg)) {
errorsfound <- errorsfound + 1
if (testmode) warning(errormsg) else message(errormsg)
}
}

# Check for compatibility with subsidizeLearning
if ((cfg$gms$optimization != "nash") && (cfg$gms$subsidizeLearning == "globallyOptimal") ) {
message("Only optimization='nash' is compatible with subsidizeLearning='globallyOptimal'. Switching subsidizeLearning to 'off' now.\n")
cfg$gms$subsidizeLearning <- "off"
}

# reportCEScalib only works with the calibrate module
if (! isTRUE(cfg$gms$CES_parameters == "calibrate")) {
cfg$output <- setdiff(cfg$output, "reportCEScalib")
}
if (errorsfound > 0) {
if (testmode) warning(errorsfound, " errors found.")
else stop(errorsfound, " errors found, see above. Either adapt the parameter choice or the regexp in main.gms")
}

return(cfg)
}
17 changes: 1 addition & 16 deletions scripts/start/prepare.R
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,13 @@ prepare <- function() {
# change to REMIND main folder
setwd(cfg$remind_folder)

# Check configuration for consistency
# cfg <- check_config(cfg, reference_file="config/default.cfg",
# settings_config = "config/settings_config.csv",
# extras = c("backup", "remind_folder", "pathToMagpieReport", "cm_nash_autoconverge_lastrun",
# "gms$c_expname", "restart_subsequent_runs", "gms$c_GDPpcScen",
# "gms$cm_CES_configuration", "gms$c_description"))

# Check for compatibility with subsidizeLearning
if ( (cfg$gms$optimization != 'nash') & (cfg$gms$subsidizeLearning == 'globallyOptimal') ) {
cat("Only optimization='nash' is compatible with subsudizeLearning='globallyOptimal'. Switching subsidizeLearning to 'off' now. \n")
cfg$gms$subsidizeLearning = 'off'
}

# reportCEScalib only works with the calibrate module
if ( cfg$gms$CES_parameters != "calibrate" ) cfg$output <- setdiff(cfg$output,"reportCEScalib")
cfg <- checkFixCfg(cfg, remindPath = cfg$remind_folder)

#AJS quit if title is too long - GAMS can't handle that
if( nchar(cfg$title) > 75 | grepl("\\.",cfg$title) ) {
stop("This title is too long or the name contains dots - GAMS would not tolerate this, and quit working at a point where you least expect it. Stopping now. ")
}


# adjust GDPpcScen based on GDPscen
cfg$gms$c_GDPpcScen <- gsub("gdp_","",cfg$gms$cm_GDPscen)

Expand Down
7 changes: 5 additions & 2 deletions scripts/start/runGamsCompile.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ runGamsCompile <- function(modelFile, cfg, interactive = TRUE) {
gcdir <- file.path(dirname(modelFile), "output", "gamscompile")
dir.create(gcdir, recursive = TRUE, showWarnings = FALSE)
tmpModelFile <- file.path(gcdir, paste0("main_", cfg$title, ".gms"))
tmpModelLst <- gsub("gms$", "lst", tmpModelFile)
file.copy(modelFile, tmpModelFile, overwrite = TRUE)
lucode2::manipulateConfig(tmpModelFile, cfg$gms)
exitcode <- system2(
command = cfg$gamsv,
args = paste(tmpModelFile, "-o", gsub("gms$", "lst", tmpModelFile),
"-action=c -errmsg=1 -pw=132 -ps=0 -logoption=0"))
args = paste(tmpModelFile, "-o", tmpModelLst, "-action=c -errmsg=1 -pw=132 -ps=0 -logoption=0"))
if (0 < exitcode) {
message(red, "FAIL ", NC, gsub("gms$", "lst", tmpModelFile))
if (interactive) {
Expand All @@ -39,6 +39,9 @@ runGamsCompile <- function(modelFile, cfg, interactive = TRUE) {
return(FALSE)
} else {
message(green, " OK ", NC, gsub("gms$", "lst", tmpModelFile))
if (isTRUE(grepl("TESTTHAT_scenario_config", cfg$title))) { # for test_04-gamscompile
unlink(c(tmpModelFile, tmpModelLst))
}
return(TRUE)
}
}
1 change: 1 addition & 0 deletions scripts/start/selectScenarios.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#' @return dataframe with scenarios from settings which should be started

selectScenarios <- function (settings, interactive, startgroup) {
if (isTRUE(startgroup == "*")) return(settings)
scenariosInGroup <- grepl(paste0("(^|,)", startgroup, "($|,)"), as.character(settings$start), perl = TRUE)
if (interactive | ! any(scenariosInGroup)) {
scenariosInGroup <- gms::chooseFromList(setNames(rownames(settings), settings$start), type = "runs", returnBoolean = TRUE)
Expand Down
4 changes: 3 additions & 1 deletion start.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ helpText <- "
#' --testOneRegi, -1: starting the REMIND run(s) in testOneRegi mode
#' startgroup=MYGROUP when reading a scenario config .csv file, don't start
#' everything specified by \"start = 1\", instead start everything
#' specified by \"start = MYGROUP\"
#' specified by \"start = MYGROUP\". Use startgroup=* to start all.
#' titletag=MYTAG append \"-MYTAG\" to all titles of all runs that are started
#' slurmConfig=CONFIG use the provided CONFIG as slurmConfig: a string, or an integer <= 16
#' to select one of the options shown when running './start.R -t'.
Expand Down Expand Up @@ -328,6 +328,8 @@ if (any(c("--reprepare", "--restart") %in% flags)) {
# abort on too long paths ----
cfg$gms$cm_CES_configuration <- calculate_CES_configuration(cfg, check = TRUE)

cfg <- checkFixCfg(cfg)

# save the cfg object for the later automatic start of subsequent runs (after preceding run finished)
if (! "--gamscompile" %in% flags) {
filename <- paste0(cfg$title,".RData")
Expand Down
4 changes: 3 additions & 1 deletion start_bundle_coupled.R
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ if (length(argv) > 0) {
if (sum(file_exists) > 1) stop("Enter only a scenario_config_coupled* file via command line or set all files manually in start_bundle_coupled.R")
if (!all(file_exists)) stop("Unknown parameter provided: ", paste(argv[!file_exists], collapse = ", "))
# set config file to not known parameter where the file actually exists
path_settings_coupled <- file.path(path_remind, argv[[1]])
path_settings_coupled <- normalizePath(argv[[1]])
if (! isTRUE(grepl("scenario_config_coupled", path_settings_coupled)))
stop("Enter only a scenario_config_coupled* file via command line or set all files manually in start_bundle_coupled.R.\n",
"Your command line arguments were: ", paste0(argv, collapse = " "))
Expand Down Expand Up @@ -549,6 +549,8 @@ for(scen in common){
numberOfTasks <- 1
}

cfg_rem <- checkFixCfg(cfg_rem, remindPath = path_remind)

Rdatafile <- paste0(fullrunname, ".RData")
message("Save settings to ", Rdatafile)
save(path_remind, path_magpie, cfg_rem, cfg_mag, runname, fullrunname, max_iterations, start_iter,
Expand Down
34 changes: 34 additions & 0 deletions tests/testthat/test_01-checkFixCfg.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# | (C) 2006-2023 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: [email protected]
test_that("checkFixCfg works", {
remind_folder <- "../.."
savecfg <- cfg <- gms::readDefaultConfig(remind_folder)
# regexp = NA means: no warning
expect_warning(checkFixCfg(cfg, remind_folder, testmode = TRUE), regexp = NA)

wrongsetting <- c(
"cm_NDC_version" = "2004_cond",
"cm_emiscen" = "123",
"cm_nash_autoconverge" = "NA",
"cm_co2_tax_2020" = "2.2.2",
"cm_co2_tax_growth" = "333++",
"c_macscen" = "-1",
"cm_keep_presolve_gdxes" = "1.1",
"cm_startyear" = "1985",
"cm_netZeroScen" = "NöööGFS_v4",
"cm_rcp_scen" = "apocalypse",
NULL)

cfg <- savecfg
cfg$gms[names(wrongsetting)] <- wrongsetting
w <- capture_warnings(checkFixCfg(cfg, remind_folder, testmode = TRUE))
for (n in names(wrongsetting)) {
expect_match(w, paste0(n, "=", wrongsetting[[n]]), all = FALSE, fixed = TRUE)
}
expect_match(w, paste0(length(wrongsetting), " errors found"), all = FALSE, fixed = TRUE)
expect_equal(length(w), length(wrongsetting) + 1)
})
18 changes: 9 additions & 9 deletions tests/testthat/test_01-readCheckScenarioConfig.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (length(csvfiles) == 0) {
file.path("../../config", "*", "scenario_config*.csv")))
}
for (csvfile in csvfiles) {
test_that(paste("perform readCheckScenarioConfig with", gsub("../../config/", "", csvfile, fixed = TRUE)), {
test_that(paste("perform readCheckScenarioConfig with", basename(csvfile)), {
# regexp = NA means: expect no warning
expect_warning(readCheckScenarioConfig(csvfile, remindPath = "../../", testmode = TRUE), regexp = NA)
})
Expand All @@ -24,15 +24,15 @@ test_that("readCheckScenarioConfig fails on error-loaden config", {
"PBScopy;0;PBS;;;mustbedifferenttoPBS"),
con = csvfile, sep = "\n")
w <- capture_warnings(scenConf <- readCheckScenarioConfig(csvfile, remindPath = "../../", testmode = TRUE))
expect_match(w, "11 errors found", all = FALSE)
expect_match(w, "These titles are too long", all = FALSE)
expect_match(w, "These titles may be confused with regions", all = FALSE)
expect_match(w, "These titles contain illegal characters", all = FALSE)
expect_match(w, "11 errors found", all = FALSE, fixed = TRUE)
expect_match(w, "These titles are too long", all = FALSE, fixed = TRUE)
expect_match(w, "These titles may be confused with regions", all = FALSE, fixed = TRUE)
expect_match(w, "These titles contain illegal characters", all = FALSE, fixed = TRUE)
expect_match(w, "\\.@&", all = FALSE)
expect_match(w, "Outdated column names found that must not be used", all = FALSE)
expect_match(w, "contain whitespaces", all = FALSE)
expect_match(w, "scenario names indicated in copyConfigFrom column were not found", all = FALSE)
expect_match(w, "specify in copyConfigFrom column a scenario name defined below in the file", all = FALSE)
expect_match(w, "Outdated column names found that must not be used", all = FALSE, fixed = TRUE)
expect_match(w, "contain whitespaces", all = FALSE, fixed = TRUE)
expect_match(w, "scenario names indicated in copyConfigFrom column were not found", all = FALSE, fixed = TRUE)
expect_match(w, "specify in copyConfigFrom column a scenario name defined below in the file", all = FALSE, fixed = TRUE)
copiedFromPBS <- c("c_budgetCO2", "path_gdx", "path_gdx_ref")
expect_identical(unlist(scenConf["PBS", copiedFromPBS]),
unlist(scenConf["PBScopy", copiedFromPBS]))
Expand Down
42 changes: 42 additions & 0 deletions tests/testthat/test_01-start.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,45 @@ test_that("start.R fails on missing path_gdx* files", {
expect_true(any(grepl("2 errors were identified", output)))
expectFailStatus(output)
})

test_that("start.R --test startgroup=AMT titletag=AMT config/scenario_config.csv works", {
with_mocked_bindings({
skipIfPreviousFailed()
output <- localSystem2("Rscript",
c("start.R", "--test", "slurmConfig=16", "startgroup=AMT", "titletag=TESTTHAT", "config/scenario_config.csv"))
printIfFailed(output)
expectSuccessStatus(output)
},
getLine = function() stop("getLine should not called."),
.package = "gms"
)
unlink("../../*TESTTHAT.RData")
})

test_that("start.R --test succeeds on all configs", {
# skipIfFast()
skipIfPreviousFailed()
csvfiles <- system("git ls-files ../../config/scenario_config*.csv ../../config/*/scenario_config*.csv", intern = TRUE)
if (length(csvfiles) == 0) {
csvfiles <- Sys.glob(c(file.path("../../config/scenario_config*.csv"),
file.path("../../config", "*", "scenario_config*.csv")))
}
csvfiles <- normalizePath(grep("scenario_config_coupled", csvfiles, invert = TRUE, value = TRUE))
skipfiles <- c("scenario_config_21_EU11_ECEMF", "scenario_config_DeepEl",
"scenario_config_EDGE-T_NDC_NPi_pkbudget", "scenario_config_NAVIGATE_300")
csvfiles <- grep(paste(skipfiles, collapse = "|"), csvfiles, invert = TRUE, value = TRUE)
expect_true(length(csvfiles) > 0)
with_mocked_bindings(
for (csvfile in csvfiles) {
test_that(paste("perform start.R --test with", basename(csvfile)), {
output <- localSystem2("Rscript",
c("start.R", "--test", "slurmConfig=16", "startgroup=*", "titletag=TESTTHAT", csvfile))
printIfFailed(output)
expectSuccessStatus(output)
})
},
getLine = function() stop("getLine should not called."),
.package = "gms"
)
unlink("../../*TESTTHAT.RData")
})
48 changes: 43 additions & 5 deletions tests/testthat/test_04-gamscompile.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,48 @@
# | AGPL-3.0, you are granted additional permissions described in the
# | REMIND License Exception, version 1.0 (see LICENSE file).
# | Contact: [email protected]
test_that("start.R --gamscompile startgroup=AMT titletag=AMT config/scenario_config.csv works", {
test_that("start.R --gamscompile startgroup=AMT config/scenario_config.csv works", {
unlink(paste0("../../output/gamscompile/*TESTTHAT", c(".gms", ".lst")))
csvfile <- "config/scenario_config.csv"
titletag <- paste0("titletag=TESTTHAT-", gsub(".csv$", "", basename(csvfile)))
with_mocked_bindings({
skipIfPreviousFailed()
output <- localSystem2("Rscript",
c("start.R", "--gamscompile", "startgroup=AMT", titletag, csvfile))
printIfFailed(output)
expectSuccessStatus(output)
},
getLine = function() stop("getLine should not called."),
.package = "gms"
)
unlink("../../*TESTTHAT.RData")
})

test_that("start.R --gamscompile works on all configs and scenarios", {
skipIfFast()
skipIfPreviousFailed()
output <- localSystem2("Rscript",
c("start.R", "--gamscompile", "startgroup=AMT", "titletag=AMT", "config/scenario_config.csv"))
printIfFailed(output)
expectSuccessStatus(output)
csvfiles <- system("git ls-files ../../config/scenario_config*.csv ../../config/*/scenario_config*.csv", intern = TRUE)
if (length(csvfiles) == 0) {
csvfiles <- Sys.glob(c(file.path("../../config/scenario_config*.csv"),
file.path("../../config", "*", "scenario_config*.csv")))
}
csvfiles <- normalizePath(grep("^scenario_config_coupled.*", csvfiles, invert = TRUE, value = TRUE))
skipfiles <- c("scenario_config_21_EU11_ECEMF", "scenario_config_EDGE-T_NDC_NPi_pkbudget",
"scenario_config_NAVIGATE_300", "21_regions_EU11", "scenario_config_tradeCap_standalone")
csvfiles <- grep(paste(skipfiles, collapse = "|"), csvfiles, invert = TRUE, value = TRUE)
expect_true(length(csvfiles) > 0)
with_mocked_bindings(
for (csvfile in csvfiles) {
test_that(paste("perform start.R --gamscompile with", basename(csvfile)), {
titletag <- paste0("titletag=TESTTHAT-", gsub(".csv$", "", basename(csvfile)))
output <- localSystem2("Rscript",
c("start.R", "--gamscompile", "startgroup=*", titletag, csvfile))
printIfFailed(output)
expectSuccessStatus(output)
})
},
getLine = function() stop("getLine should not called."),
.package = "gms"
)
unlink("../../*TESTTHAT.RData")
})
Loading

0 comments on commit 3ed5db8

Please sign in to comment.