diff --git a/DESCRIPTION b/DESCRIPTION index c190af07..f25f6ebe 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -39,7 +39,8 @@ Imports: pbapply, parallel, future, - plyr + plyr, + yaml Suggests: testthat, covr, diff --git a/NAMESPACE b/NAMESPACE index a4b04450..2a23fa51 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,6 +12,7 @@ export(clearScenarioBuilder) export(computeOtherFromHourlyMulti) export(computeOtherFromHourlyYear) export(computeTimeStampFromHourly) +export(convertConfigToAdq) export(copyOutput) export(createArea) export(createBindingConstraint) @@ -144,3 +145,4 @@ importFrom(utils,tar) importFrom(utils,unzip) importFrom(utils,write.table) importFrom(whisker,whisker.render) +importFrom(yaml,read_yaml) diff --git a/R/editArea.R b/R/editArea.R index a569ac04..c4e79ca5 100644 --- a/R/editArea.R +++ b/R/editArea.R @@ -189,7 +189,7 @@ editArea <- function(name, if (!is.null(adequacy)) { for (i in names(adequacy)) { - adequacyIni$`adequacy-patch-mode`[[i]] <- adequacy[[i]] + adequacyIni$`adequacy-patch`[[i]] <- adequacy[[i]] } } diff --git a/R/updateAdequacySettings.R b/R/updateAdequacySettings.R index ec0e4276..57628506 100644 --- a/R/updateAdequacySettings.R +++ b/R/updateAdequacySettings.R @@ -9,6 +9,12 @@ #' @param include_adq_patch Logical. If TRUE, will run Adequacy Patch #' @param set_to_null_ntc_from_physical_out_to_physical_in_for_first_step Logical. default to TRUE #' @param set_to_null_ntc_between_physical_out_for_first_step Logical. default to TRUE +#' @param price_taking_order Character. can take values DENS (default value) and Load. +#' @param include_hurdle_cost_csr Logical. default to FALSE +#' @param check_csr_cost_function Logical. default to FALSE +#' @param threshold_initiate_curtailment_sharing_rule Double. default to 0.0 +#' @param threshold_display_local_matching_rule_violations Double. default to 0.0 +#' @param threshold_csr_variable_bounds_relaxation Integer. default to 3 #' #' @template opts #' @@ -30,8 +36,16 @@ updateAdequacySettings <- function(include_adq_patch = NULL, set_to_null_ntc_from_physical_out_to_physical_in_for_first_step = NULL, set_to_null_ntc_between_physical_out_for_first_step = NULL, + price_taking_order = NULL, + include_hurdle_cost_csr = NULL, + check_csr_cost_function = NULL, + threshold_initiate_curtailment_sharing_rule = NULL, + threshold_display_local_matching_rule_violations = NULL, + threshold_csr_variable_bounds_relaxation = NULL, opts = antaresRead::simOptions()) { + if (opts$antaresVersion < 830) stop("This function is only available for studies v8.3 or higher.") + assertthat::assert_that(inherits(opts, "simOptions")) # API block @@ -41,7 +55,13 @@ updateAdequacySettings <- function(include_adq_patch = NULL, listData = list( `include-adq-patch` = include_adq_patch, `set-to-null-ntc-from-physical-out-to-physical-in-for-first-step` = set_to_null_ntc_from_physical_out_to_physical_in_for_first_step, - `set-to-null-ntc-between-physical-out-for-first-step` = set_to_null_ntc_between_physical_out_for_first_step + `set-to-null-ntc-between-physical-out-for-first-step` = set_to_null_ntc_between_physical_out_for_first_step, + `price-taking-order` = price_taking_order, + `include-hurdle-cost-csr` = include_hurdle_cost_csr, + `check-csr-cost-function` = check_csr_cost_function, + `threshold-initiate-curtailment-sharing-rule` = threshold_initiate_curtailment_sharing_rule, + `threshold-display-local-matching-rule-violations` = threshold_display_local_matching_rule_violations, + `threshold-csr-variable-bounds-relaxation` = threshold_csr_variable_bounds_relaxation ), pathIni = "settings/generaldata/adequacy patch", opts = opts @@ -60,6 +80,22 @@ updateAdequacySettings <- function(include_adq_patch = NULL, adequacy$`set-to-null-ntc-from-physical-out-to-physical-in-for-first-step` <- set_to_null_ntc_from_physical_out_to_physical_in_for_first_step if (!is.null(set_to_null_ntc_between_physical_out_for_first_step)) adequacy$`set-to-null-ntc-between-physical-out-for-first-step` <- set_to_null_ntc_between_physical_out_for_first_step + + if (opts$antaresVersion >= 850){ + if (!is.null(price_taking_order)) + adequacy$`price-taking-order` <- price_taking_order + if (!is.null(include_hurdle_cost_csr)) + adequacy$`include-hurdle-cost-csr` <- include_hurdle_cost_csr + if (!is.null(check_csr_cost_function)) + adequacy$`check-csr-cost-function` <- check_csr_cost_function + if (!is.null(threshold_initiate_curtailment_sharing_rule)) + adequacy$`threshold-initiate-curtailment-sharing-rule` <- threshold_initiate_curtailment_sharing_rule + if (!is.null(threshold_display_local_matching_rule_violations)) + adequacy$`threshold-display-local-matching-rule-violations` <- threshold_display_local_matching_rule_violations + if (!is.null(threshold_csr_variable_bounds_relaxation)) + adequacy$`threshold-csr-variable-bounds-relaxation` <- threshold_csr_variable_bounds_relaxation + } + general$`adequacy patch` <- adequacy writeIni(listData = general, pathIni = pathIni, overwrite = TRUE) @@ -71,3 +107,40 @@ updateAdequacySettings <- function(include_adq_patch = NULL, invisible(res) } + + + + +#' @title Read adequacy patch config.yml into Antares (v8.5+) +#' +#' @description +#' Use this function to load config.yml used in older Antares versions for adequacy patch. +#' Areas in config will be updated to be included in adequacy patch perimeter. +#' +#' @param opts List. study options. +#' @param path Character. path to config.yml. Default points to "/user/adequacypatch/" in study +#' +#' @importFrom yaml read_yaml +#' @export +#' +#' @seealso +#' \code{\link{updateAdequacySettings}} +#' +convertConfigToAdq <- function(opts = simOptions(), path = "default"){ + configAdq <- ifelse(path == "default", + file.path(opts$studyPath, "user", "adequacypatch", "config.yml"), + path) + if (!file.exists(configAdq)) stop("Config.yml not found in selected path.") + + config <- read_yaml(configAdq, fileEncoding = "UTF-8", text) + + pathOut <- character(0) + #temporarily switch to mode "input" if necessary + if (opts$mode != "input"){ + pathOut <- opts$simPath + setSimulationPath(opts$studyPath, "input") + } + lapply(setdiff(config$areas, config$excluded_areas), + editArea, adequacy = adequacyOptions(adequacy_patch_mode = "inside")) + if (length(pathOut) > 0) setSimulationPath(pathOut) +} diff --git a/R/zzz.R b/R/zzz.R index bd50be5b..3b32e7d3 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,8 +1,6 @@ utils::globalVariables( - c("rn", "variable", "value", "Mode", "Name", "Stats", + c("rn", "variable", "value", "text", "Mode", "Name", "Stats", "area", "day", "getGeographicTrimming", "getIdCols", "link", "time", "timeId", "week1", "week2", "year1", "year2")) - - diff --git a/man/convertConfigToAdq.Rd b/man/convertConfigToAdq.Rd new file mode 100644 index 00000000..9eb99e93 --- /dev/null +++ b/man/convertConfigToAdq.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/updateAdequacySettings.R +\name{convertConfigToAdq} +\alias{convertConfigToAdq} +\title{Read adequacy patch config.yml into Antares (v8.5+)} +\usage{ +convertConfigToAdq(opts = simOptions(), path = "default") +} +\arguments{ +\item{opts}{List. study options.} + +\item{path}{Character. path to config.yml. Default points to "/user/adequacypatch/" in study} +} +\description{ +Use this function to load config.yml used in older Antares versions for adequacy patch. +Areas in config will be updated to be included in adequacy patch perimeter. +} +\seealso{ +\code{\link{updateAdequacySettings}} +} diff --git a/man/updateAdequacySettings.Rd b/man/updateAdequacySettings.Rd index 196b0a2e..f8bdee24 100644 --- a/man/updateAdequacySettings.Rd +++ b/man/updateAdequacySettings.Rd @@ -8,6 +8,12 @@ updateAdequacySettings( include_adq_patch = NULL, set_to_null_ntc_from_physical_out_to_physical_in_for_first_step = NULL, set_to_null_ntc_between_physical_out_for_first_step = NULL, + price_taking_order = NULL, + include_hurdle_cost_csr = NULL, + check_csr_cost_function = NULL, + threshold_initiate_curtailment_sharing_rule = NULL, + threshold_display_local_matching_rule_violations = NULL, + threshold_csr_variable_bounds_relaxation = NULL, opts = antaresRead::simOptions() ) } @@ -18,6 +24,18 @@ updateAdequacySettings( \item{set_to_null_ntc_between_physical_out_for_first_step}{Logical. default to TRUE} +\item{price_taking_order}{Character. can take values DENS (default value) and Load.} + +\item{include_hurdle_cost_csr}{Logical. default to FALSE} + +\item{check_csr_cost_function}{Logical. default to FALSE} + +\item{threshold_initiate_curtailment_sharing_rule}{Double. default to 0.0} + +\item{threshold_display_local_matching_rule_violations}{Double. default to 0.0} + +\item{threshold_csr_variable_bounds_relaxation}{Integer. default to 3} + \item{opts}{List of simulation parameters returned by the function \code{\link[antaresRead:setSimulationPath]{antaresRead::setSimulationPath()}}} } diff --git a/tests/testthat/test-updateAdequacyPatch.R b/tests/testthat/test-updateAdequacyPatch.R index 0eebb2c9..b7f122e2 100644 --- a/tests/testthat/test-updateAdequacyPatch.R +++ b/tests/testthat/test-updateAdequacyPatch.R @@ -7,21 +7,24 @@ sapply(studies, function(study) { setup_study(study, sourcedir) opts <- antaresRead::setSimulationPath(studyPath, "input") - - - test_that("Update an adequacy parameter", { - - updateAdequacySettings(include_adq_patch = TRUE) - updateAdequacySettings(set_to_null_ntc_from_physical_out_to_physical_in_for_first_step = FALSE) - updateAdequacySettings(set_to_null_ntc_between_physical_out_for_first_step = FALSE) - - expect_true(getOption("antares")$parameters$`adequacy patch`$`include-adq-patch`) - expect_false(getOption("antares")$parameters$`adequacy patch`$`set-to-null-ntc-from-physical-out-to-physical-in-for-first-step`) - expect_false(getOption("antares")$parameters$`adequacy patch`$`set-to-null-ntc-between-physical-out-for-first-step`) + if (opts$antaresVersion >= 850){ + test_that("Update an adequacy parameter", { + + updateAdequacySettings(include_adq_patch = TRUE) + updateAdequacySettings(set_to_null_ntc_from_physical_out_to_physical_in_for_first_step = FALSE) + updateAdequacySettings(set_to_null_ntc_between_physical_out_for_first_step = FALSE) + updateAdequacySettings(check_csr_cost_function = TRUE) + + + expect_true(getOption("antares")$parameters$`adequacy patch`$`include-adq-patch`) + expect_false(getOption("antares")$parameters$`adequacy patch`$`set-to-null-ntc-from-physical-out-to-physical-in-for-first-step`) + expect_false(getOption("antares")$parameters$`adequacy patch`$`set-to-null-ntc-between-physical-out-for-first-step`) + expect_true(getOption("antares")$parameters$`adequacy patch`$`check-csr-cost-function`) + + }) - }) - - # remove temporary study - unlink(x = file.path(pathstd, "test_case"), recursive = TRUE) - + # remove temporary study + unlink(x = file.path(pathstd, "test_case"), recursive = TRUE) + } + }) \ No newline at end of file