Skip to content

Commit

Permalink
New functions for thermal (#193)
Browse files Browse the repository at this point in the history
* new function readInputThermal()
* added support + warning for same clusters in multiple areas

* added new fct : readAntaresClusters()
* addedv case insensitivity for readAntaresClusters()

Co-authored-by: MANSOURI Assil Ext <[email protected]>
  • Loading branch information
AssilMa and MANSOURI Assil Ext authored Jan 17, 2023
1 parent eeb227a commit bd65f4e
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 1 deletion.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: antaresRead
Type: Package
Title: Import, Manipulate and Explore the Results of an 'Antares' Simulation
Version: 2.4.0
Version: 2.4.1
Authors@R: c(
person("Veronique", "Bachelier", email = "[email protected]", role = c("aut", "cre")),
person("Jalal-Edine", "ZAWAM", role = "aut"),
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ export(parAggregateMCall)
export(ponderateMcAggregation)
export(readAntares)
export(readAntaresAreas)
export(readAntaresClusters)
export(readBindingConstraints)
export(readClusterDesc)
export(readClusterResDesc)
export(readIni)
export(readIniAPI)
export(readIniFile)
export(readInputTS)
export(readInputThermal)
export(readLayout)
export(readOptimCriteria)
export(removeVirtualAreas)
Expand Down
14 changes: 14 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
> Copyright © 2016 RTE Réseau de transport d’électricité
# antaresRead 2.4.1

NEW FEATURES:

Added new functions `readInputThermal()` and `readAntaresClusters()` :
Both functions take a vector of **clusters** instead of **areas**
* `readInputThermal()` : read thermal TS (availabilities) and modulation in Input mode
* `readAntaresClusters()` : read output data for clusters only with thematic trimming



# antaresRead 2.4.0

NEW FEATURES:

Major upgrade to `aggregateResult()` and `parAggregateMCall()` :
* Faster & memory efficient
* Support for Antares studies up to v8.3 (v8.4 experimental)
Expand All @@ -15,9 +27,11 @@ Major upgrade to `aggregateResult()` and `parAggregateMCall()` :
# antaresRead 2.3.2

NEW FEATURES:

added "profit by cluster" when reading cluster data

BUGFIXES:

Fix for 404 error when some output is missing in API mode(#188)


Expand Down
39 changes: 39 additions & 0 deletions R/readAntaresClusters.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#Copyright © 2016 RTE Réseau de transport d’électricité
#' Read output for a list of clusters
#'
#' @param clusters vector of thermal clusters to be imported
#' @param selected vector of thematic trimming
#' @inheritParams readAntares
#'
#' @return data.table of results for thermal clusters
#'
#' @export
readAntaresClusters <- function(clusters, selected = c("production", "NP Cost", "NODU", "profit"),
timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
opts = simOptions(), parallel = FALSE, showProgress = TRUE) {

if (missing(clusters))
stop("The function 'readAntaresClusters' expects a vector of cluster names as argument.")
if ("Input" %in% opts$mode)
stop("Cannot use 'readAntaresClusters' in 'Input' mode.")

##Add check control for all
allClusters <- readClusterDesc()[, c("area","cluster")]
ind_cluster <- which(tolower(allClusters$cluster) %in% .checkArg(tolower(clusters),
tolower(unique(allClusters$cluster)),
"clusters %s do not exist in the simulation."))
clusters <- allClusters$cluster[ind_cluster]

ind_cluster <- which(tolower(allClusters$cluster) %in% .checkArg(tolower(clusters),
tolower(unique(allClusters[area %in% opts$areasWithClusters]$cluster)),
"clusters %s have no output."))
clusters <- unique(allClusters$cluster[ind_cluster])

areas <- unique(allClusters[cluster %in% clusters]$area)

res <- readAntares(clusters = areas, timeStep = timeStep, opts = opts,
parallel = parallel, showProgress = showProgress)

subset(res, cluster %in% clusters, select = c(setdiff(colnames(res),c("production", "NP Cost", "NODU", "profit")),
intersect(colnames(res),selected))) #support for up to v8.4
}
95 changes: 95 additions & 0 deletions R/readInputThermal.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#Copyright © 2016 RTE Réseau de transport d’électricité

#' Read Input thermal time series
#'
#' @description
#' \code{readInputThermal} is a function that reads thermal time series from an antares
#' project. But contrary to \code{\link{readAntares}}, it only reads time series
#' stored in the input folder, so it can work in "input" mode.
#'
#' @param clusters vector of clusters names for which thermal time series must be read.
#' @param thermalModulation if TRUE, return thermalModulation data
#' @inheritParams readAntares
#'
#' @return
#' If thermalModulation is TRUE, an object of class "antaresDataList" is returned. It is a list of
#' data.tables for thermalAvailabilities and thermalModulation
#'
#' Else the result is a data.table with class "antaresDataTable".
#'
#' @note
#' the clusters parameter can also accept the special value "all".
#' It indicates the function to read the desired time series for all clusters.
#'
#' @seealso
#' \code{\link{setSimulationPath}}, \code{\link{readAntares}},
#' \code{\link{getAreas}}, \code{\link{getLinks}}
#'
#' @export
readInputThermal <- function(clusters = NULL, thermalModulation = FALSE,
opts = simOptions(),
timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
simplify = TRUE, parallel = FALSE,
showProgress = TRUE) {

timeStep <- match.arg(timeStep)

# Can the importation be parallelized ?
if (parallel) {
if(!requireNamespace("foreach")) stop("Parallelized importation impossible. Please install the 'foreach' package and a parallel backend provider like 'doParallel'.")
if (!foreach::getDoParRegistered()) stop("Parallelized importation impossible. Please register a parallel backend, for instance with function 'registerDoParallel'")
}

allAreasClusters <- readClusterDesc()[area %in% opts$areasWithClusters, c("area", "cluster")]
allClusters <- unique(allAreasClusters$cluster)
# Manage special value "all"
if(identical(clusters, "all")) clusters <- allClusters

if (length(setdiff(tolower(clusters), tolower(allClusters))) > 0){
cat(c("the following clusters are not available : ",setdiff(tolower(clusters), tolower(allClusters))))
stop("Some clusters are not available in the areas specified")
}

ind_cluster <- which(tolower(allClusters) %in% tolower(clusters))
clusters <- unique(allClusters[ind_cluster])
res <- list() # Object the function will return

thermalTS <- as.data.table(ldply(clusters, function(cl) {

area <- unique(allAreasClusters[cluster == cl]$area)
if (length(area) > 1) warning(cl," is in more than one area")
resCl <- ldply(area, function(x){
filePattern <- sprintf("%s/%s/%%s/series.txt", "thermal/series", x)
mid <- .importInputTS(cl, timeStep, opts, filePattern, "ThermalAvailabilities",
inputTimeStep = "hourly", type = "matrix")
if (is.null(mid)) return (data.table())
mid$area <- x
mid$cluster <- cl
mid
})

resCl <- dcast(as.data.table(resCl), area + cluster + timeId ~ tsId, value.var = "ThermalAvailabilities")
}))

tsCols <- setdiff(colnames(thermalTS), c("area", "cluster", "timeId"))
setnames(thermalTS, tsCols, paste0("ts",tsCols))
setcolorder(thermalTS, c("area", "cluster", "timeId", setdiff(names(thermalTS), c("area", "cluster", "timeId"))))

if (nrow(thermalTS) > 0) res$thermalAvailabilities <- thermalTS

# thermalModulation processing
if (thermalModulation){
areas <- unique(allAreasClusters[cluster %in% clusters]$area)
thermalMod <- as.data.table(ldply(areas, .importThermalModulation, opts = opts, timeStep = timeStep))
thermalMod <- thermalMod[cluster %in% clusters]
setcolorder(thermalMod, c("area", "cluster", "timeId", setdiff(names(thermalMod), c("area", "cluster", "timeId"))))

if (nrow(thermalMod) > 0) res$thermalModulation <- thermalMod
}

if (length(res) == 0) stop("At least one argument of readInputTS has to be defined.")

# Class and attributes
res <- .addClassAndAttributes(res, NULL, timeStep, opts, simplify)
addDateTimeColumns(res)
}
37 changes: 37 additions & 0 deletions man/readAntaresClusters.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 55 additions & 0 deletions man/readInputThermal.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions tests/testthat/test-readAntaresClusters.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#Copyright © 2016 RTE Réseau de transport d’électricité

context("Function readAntaresClusters")

sapply(studyPathS, function(studyPath){

opts <- setSimulationPath(studyPath)

test_that("Clusters importation is ok", {
clusters <- readAntaresClusters(clusters = "peak_must_run_partial", showProgress = FALSE)
expect_is(clusters, "data.table")
expect_true(!is.null(clusters$cluster))
expect_equal(nrow(clusters), 24 * 7 * nweeks)
})


# Test that importation works for all time resolutions.
for (timeStep in c("hourly", "daily", "weekly", "monthly", "annual")) {
expected_rows = switch(timeStep,
hourly = 24 * 7 * nweeks,
daily = 7 * nweeks,
weekly = nweeks,
monthly = nmonths,
annual = 1)

test_that(sprintf("one can import cluster %s output", timeStep), {
clusters <- readAntaresClusters(clusters = "peak_must_run_partial", showProgress = FALSE, timeStep = timeStep)
expect_equal(nrow(clusters), expected_rows)
})
}

})
27 changes: 27 additions & 0 deletions tests/testthat/test-readInputThermal.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#Copyright © 2016 RTE Réseau de transport d’électricité

context("Function readInputThermal")
sapply(studyPathS, function(studyPath){

opts <- setSimulationPath(studyPath)


if(!isH5Opts(opts)){

test_that("Thermal availabilities importation works", {
input <- readInputThermal(clusters = "peak_must_run_partial", showProgress = FALSE)
expect_is(input, "antaresDataTable")
expect_gt(nrow(input), 0)
expect_equal(nrow(input) %% (24 * 7 * nweeks), 0)
})

test_that("Thermal modulation importation works", {
input <- readInputThermal(clusters = "peak_must_run_partial", thermalModulation = TRUE, showProgress = FALSE)
expect_is(input, "antaresDataList")
expect_is(input$thermalModulation, "antaresDataTable")
expect_gt(nrow(input$thermalModulation), 0)
expect_equal(nrow(input$thermalModulation) %% (24 * 7 * nweeks), 0)
})

}
})

0 comments on commit bd65f4e

Please sign in to comment.