Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

geographic trimming + updated thermal functions #195

Merged
merged 7 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export(extractDataList)
export(getAlias)
export(getAreas)
export(getDistricts)
export(getGeographicTrimming)
export(getIdCols)
export(getLinks)
export(hvdcModification)
Expand All @@ -52,6 +53,7 @@ export(readClusterResDesc)
export(readIni)
export(readIniAPI)
export(readIniFile)
export(readInputRES)
export(readInputTS)
export(readInputThermal)
export(readLayout)
Expand Down
10 changes: 6 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

NEW FEATURES:

Function `getLinks()` now has a new argument **withTransmission**. if TRUE, return additional
column with type of transmission capacities
* New function `getGeographicTrimming()` returns filtering options for selected areas (links optional).
* New function added : `readInputRes()` for reading renewable clusters input data


* Existing function `getLinks()` now has a new argument **withTransmission**. if TRUE, return additional column with type of transmission capacities.
* Existing function `readInputThermal()` : added new argument for thermalData


# antaresRead 2.4.1
Expand Down Expand Up @@ -38,11 +40,11 @@ Major upgrade to `aggregateResult()` and `parAggregateMCall()` :

NEW FEATURES:

added "profit by cluster" when reading cluster data
added "profit by cluster" when reading cluster data.

BUGFIXES:

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



Expand Down
49 changes: 49 additions & 0 deletions R/getGeographicTrimming.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#Copyright © 2016 RTE Réseau de transport d’électricité

#' Read geographic trimming (filtering) options
#'
#' @param areas Character. vector of areas
#' @param links Logical. if TRUE, return filtering options for all links starting from selected areas
#' @param opts List. simulation options
#'
#' @return list of filtering options for areas and links
#'
#' @export
getGeographicTrimming <- function(areas = NULL, links = TRUE, opts = simOptions()){
if (is.null(areas)) stop("You need to select at least one area.")
if (areas == "all") areas <- opts$areaList

res <- list()

if(!is.null(areas)){
areaData <- lapply(as.list(areas), .readPropertiesFunction, opts2 = opts, type = "areas")
names(areaData) <- areas
res$areas <- areaData
}

if (links){
linkData <- lapply(as.list(areas), .readPropertiesFunction, opts2 = opts, type = "links")
names(linkData) <- areas
linkData <- unlist(linkData, recursive = F)
names(linkData) <- gsub("\\.", " - ", names(linkData))
res$links <- linkData
}

res
}

.readPropertiesFunction <- function(x, opts2, type){
if (type == "areas"){
if (opts2$typeLoad != "api"){
inputPath <- file.path(opts2$inputPath, "areas", x, "optimization.ini")
readIniFile(inputPath)$filtering
} else readIni(file.path("input", "areas", x, "optimization"))$filtering

} else if (type == "links"){
if (opts2$typeLoad != "api"){
inputPath <- file.path(opts2$inputPath, "links", x, "properties.ini")
lapply(as.list(readIniFile(inputPath)), function(x){x[grep("filter", names(x))]})
} else lapply(as.list(readIni(file.path("input", "links", x, "properties"))), function(x){x[grep("filter", names(x))]})
}
}

49 changes: 46 additions & 3 deletions R/importInput.R
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,52 @@

}




.importThermalData <- function(area, opts, timeStep, unselect = NULL, ...) {
if (!area %in% opts$areasWithClusters) return(NULL)
unselect <- unselect$areas
path <- file.path(opts$inputPath, "thermal/prepro", area)

if(!"api" %in% opts$typeLoad){
clusters <- list.files(path)
} else {
clusters <- names(read_secure_json(path, token = opts$token, timeout = opts$timeout, config = opts$httr_config))
}

beginName <- c("FODuration", "PODuration", "FORate", "PORate", "NPOMin", "NPOMax")
if(!is.null(unselect)){
colSelect <- which(!beginName%in%unselect)
names <- beginName[colSelect]
}else{
colSelect <- NULL
names <- beginName
}


res <- ldply(clusters, function(cl) {
if(is.null(colSelect))
{
# data <- fread(file.path(path, cl, "data.txt"), colClasses = "numeric")
data <- fread_antares(opts = opts, file = file.path(path, cl, "data.txt"), colClasses = "numeric")
}else{
# data <- fread(file.path(path, cl, "data.txt"), select = colSelect, colClasses = "numeric")
data <- fread_antares(opts = opts, file = file.path(path, cl, "data.txt"), select = colSelect, colClasses = "numeric")
}

setnames(data,
names(data), names)

data$area <- area
data$cluster <- cl
data <- data[opts$timeIdMin:opts$timeIdMax]
data$timeId <- opts$timeIdMin:opts$timeIdMax

changeTimeStep(data, timeStep, "daily", fun = "mean")
})
}

.importThermalModulation <- function(area, opts, timeStep, unselect = NULL, ...) {
if (!area %in% opts$areasWithClusters) return(NULL)
unselect <- unselect$areas
Expand Down Expand Up @@ -359,11 +405,8 @@
setnames(modulation,
names(modulation), names)



if (all(modulation$minGenModulation == 0))
modulation[, minGenModulation := NA_real_]

modulation$area <- area
modulation$cluster <- cl
modulation <- modulation[opts$timeIdMin:opts$timeIdMax]
Expand Down
95 changes: 92 additions & 3 deletions R/readInputThermal.R → R/readInputClusters.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#'
#' @param clusters vector of clusters names for which thermal time series must be read.
#' @param thermalModulation if TRUE, return thermalModulation data
#' @param thermalData if TRUE, return thermalData from prepro
#' @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
#' If thermalModulation or thermalData is TRUE, an object of class "antaresDataList" is returned. It is a list of
#' data.tables for selected input
#'
#' Else the result is a data.table with class "antaresDataTable".
#'
Expand All @@ -26,7 +27,7 @@
#' \code{\link{getAreas}}, \code{\link{getLinks}}
#'
#' @export
readInputThermal <- function(clusters = NULL, thermalModulation = FALSE,
readInputThermal <- function(clusters = NULL, thermalModulation = FALSE, thermalData = FALSE,
opts = simOptions(),
timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
simplify = TRUE, parallel = FALSE,
Expand Down Expand Up @@ -86,9 +87,97 @@ readInputThermal <- function(clusters = NULL, thermalModulation = FALSE,

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

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

if (nrow(thermalDat) > 0) res$thermalData <- thermalDat
}

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)
}




#' Read Input RES time series
#'
#' @description
#' \code{readInputRes} is a function that reads renewable 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 RES clusters names for which renewable time series must be read.
#' @inheritParams readAntares
#'
#' @return
#' data.table with class "antaresDataTable".
#'
#' @seealso
#' \code{\link{setSimulationPath}}, \code{\link{readAntares}},
#' \code{\link{getAreas}}, \code{\link{getLinks}}
#'
#' @export
readInputRES <- function(clusters = NULL, 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 <- readClusterResDesc()[area %in% opts$areasWithResClusters, 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

ResTS <- 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", "renewables/series", x)
mid <- .importInputTS(cl, timeStep, opts, filePattern, "production",
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 = "production")
}))

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

if (nrow(ResTS) > 0) res$ResProduction <- ResTS

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

# Class and attributes
res <- .addClassAndAttributes(res, NULL, timeStep, opts, simplify)
addDateTimeColumns(res)
Expand Down
2 changes: 1 addition & 1 deletion docs/articles/antaresH5.html

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

2 changes: 1 addition & 1 deletion docs/articles/antaresRead.html

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

11 changes: 7 additions & 4 deletions docs/news/index.html

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

2 changes: 1 addition & 1 deletion docs/pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ pkgdown_sha: ~
articles:
antaresH5: antaresH5.html
antaresRead: antaresRead.html
last_built: 2023-02-10T15:06Z
last_built: 2023-02-14T09:00Z

Loading