#' Read solution
#'
#' The function and method read outputs of solved model/scenario and return the scenario object populated with variables data.
#'
#' @param obj scenario object
#' @param ... optional tmp.dir (if missing in the scenario object or to replace the saved path)
#'
#' @return
#' The function returns the scenario object with populated modOut slot
#' from the solved model directory.
#' @export
#' @seealso [solve()] to run the script, solve the scenario. [write_sc()] to read
#'
#' @rdname read
#' @examples
#' \dontrun{
#' scen <- read(scen)
#' }
read_solution <- function(obj, ...) {
scen <- obj
## arguments
# scen
# readOutputFunction = read.csv (may use data.table::fread)
# tmp.dir dir from wich read results, by default in scen@misc$tmp.dir
# echo = TRUE - print working data
arg <- list(...)
# browser()
read_result_time <- proc.time()[3]
if (is.null(arg$echo)) arg$echo <- TRUE
# if (is.null(arg$readOutputFunction)) arg$readOutputFunction <- read.csv
if (is.null(arg$readOutputFunction)) {
arg$readOutputFunction <- data.table::fread
}
if (is.null(arg$tmp.dir)) {
arg$tmp.dir <- scen@misc$tmp.dir
if (is.null(arg$tmp.dir)) {
stop('Directory "tmp.dir" not specified')
}
}
# Read basic variable list (vrb_list) and additional if user need (vrb_list2)
var_file <- paste(arg$tmp.dir, "/output/variable_list.csv", sep = "")
vrb_list <- try({
arg$readOutputFunction(
var_file,
stringsAsFactors = FALSE
)$value
})
if (inherits(vrb_list, "try-error")) {
msg <- paste0("Solution files not found\n", var_file)
if (!is.null(arg$stop_on_error) && arg$stop_on_error) {
stop(msg)
} else {
message(msg)
return(invisible(obj))
}
}
if (file.exists(paste(arg$tmp.dir, "/output/variable_list2.csv", sep = ""))) {
vrb_list2 <- arg$readOutputFunction(
paste(arg$tmp.dir, "/output/variable_list2.csv", sep = ""),
stringsAsFactors = FALSE
)$value
} else {
vrb_list2 <- character()
}
rr <- list(
variables = list(),
set = arg$readOutputFunction(
paste(arg$tmp.dir, "/output/raw_data_set.csv", sep = ""),
stringsAsFactors = FALSE
)
)
# Read set and alias
ss <- list()
for (k in unique(rr$set$set)) {
ss[[k]] <- rr$set$value[rr$set$set == k]
}
# add alias
ss$src <- ss$region
ss$dst <- ss$region
ss$regionp <- ss$region
ss$yearp <- ss$year
ss$acomm <- ss$comm
ss$commp <- ss$comm
ss$slicep <- ss$slice
rr$set_vec <- ss
if (is.null(scen@settings@solver$import_format)) {
scen@settings@solver$import_format <- "csv" # !!! workaround
}
# browser()
if (grepl("^gdx$", scen@settings@solver$import_format, ignore.case = TRUE)) {
# .check_load_gdxlib()
.check_load_gdxtools()
# Read variables gdx
gd <- gdxtools::gdx(paste(arg$tmp.dir, "/output/output.gdx", sep = ""))
for (i in c(vrb_list, vrb_list2)) {
# cat(i, "\n")
# if (i == "vTradeIr") browser() # debug
vr <- gd[i]
if (is.null(vr)) next
if (length(grep("region", colnames(vr))) == 2) {
colnames(vr)[grep("region", colnames(vr))] <- c("src", "dst")
}
if (ncol(vr) == 1) {
rr$variables[[i]] <- data.frame(value = vr[1, 1])
} else {
for (j in seq_len(ncol(vr))[colnames(vr) != "value"]) {
# Remove [.][:digit:] if any
if (all(colnames(vr)[j] != names(rr$set_vec))) {
colnames(vr)[j] <- gsub("[.].*", "", colnames(vr)[j])
}
sname <- colnames(vr)[j] # set name
# Save as.factor with existing levels
if (sname != "year") {
if (!is.null(scen@modInp@parameters[[sname]])) {
# !!! move to the top before aliases
set_levels <- scen@modInp@parameters[[sname]]@data[[sname]]
} else {
set_levels <- sort(rr$set_vec[[sname]])
}
# set_levels <- scen@modInp@parameters[[sname]]@data[[sname]]
# vr[[j]] <- factor(vr[[j]], levels = sort(rr$set_vec[[sname]]))
vr[[j]] <- factor(vr[[j]], levels = set_levels)
} else {
vr[[j]] <- as.integer(vr[[j]])
}
}
rr$variables[[i]] <- vr
}
}
} else {
# Read variables csv
for (i in c(vrb_list, vrb_list2)) {
vr <- arg$readOutputFunction(
paste(arg$tmp.dir, "/output/", i, ".csv",
sep = ""
),
stringsAsFactors = FALSE
)
if (ncol(vr) == 1) {
rr$variables[[i]] <- data.frame(value = vr[1, 1])
} else {
for (j in seq_len(ncol(vr))[colnames(vr) != "value"]) {
# Remove [.][:digit:] if any
if (all(colnames(vr)[j] != names(rr$set_vec))) {
colnames(vr)[j] <- gsub("[.].*", "", colnames(vr)[j])
}
# Save all data with all levels
if (colnames(vr)[j] != "year") {
vr[[j]] <- factor(vr[[j]],
levels = sort(rr$set_vec[[colnames(vr)[j]]])
)
}
}
rr$variables[[i]] <- vr
}
}
}
scen@modOut <- new("modOut")
# Read solution status
scen@modOut@solutionLogs <- read.csv(paste(arg$tmp.dir, "/output/log.csv",
sep = ""
))
solver_data <- read.csv(paste(arg$tmp.dir, "/solver", sep = ""),
stringsAsFactors = FALSE
)
codes <- solver_data[grep("^code", solver_data$name), ]
for (i in seq_len(nrow(codes))) {
scen@settings@solver[[codes[i, "name"]]] <-
readLines(paste(arg$tmp.dir, "/", codes[i, "value"], sep = ""))
}
if (all(scen@modOut@solutionLogs$parameter != "solution status")) {
scen@modOut@stage <- "Scenario is not solved"
} else if (all(scen@modOut@solutionLogs[
scen@modOut@solutionLogs$parameter == "solution status", "value"
] != 1)) {
scen@modOut@stage <- paste0(
"The solution status is not optimal (",
scen@modOut@solutionLogs[
scen@modOut@solutionLogs$parameter == "solution status", "value"
], ")"
)
} else if (all(scen@modOut@solutionLogs$parameter != "done")) {
scen@modOut@stage <- "Unexpected termination"
} else {
scen@modOut@stage <- "solved"
}
if (scen@modOut@stage != "solved") {
warning(scen@modOut@stage)
}
scen@modOut@sets <- rr$set_vec
scen@modOut@variables <- rr$variables
if (!is.null(scen@misc$data.before)) {
scen <- .paste_base_result2new(scen)
}
## Salvage cost calculation
salvage_cost0 <- function(scen, par) {
invcost <- .add_dropped_zeros(scen@modInp, paste0("p", par, "Invcost"))
olife <- .add_dropped_zeros(scen@modInp, paste0("p", par, "Olife"))
discount <- .add_dropped_zeros(scen@modInp, "pDiscount")
newcap <- scen@modOut@variables[[paste0("v", par, "NewCap")]]
invcost$invcost <- invcost$value
invcost$value <- NULL
olife$olife <- olife$value
olife$value <- NULL
discount$discount <- discount$value
discount$value <- NULL
newcap$newcap <- newcap$value
newcap$value <- NULL
salvage <-
merge0(
merge0(
newcap,
merge0(olife, invcost)
),
discount,
all.x = TRUE
)
end_year <- max(.get_data_slot(scen@modInp@parameters$mEndMilestone)$yearp)
salvage <- merge0(
salvage,
.get_data_slot(scen@modInp@parameters$mStartMilestone)
)
salvage$start <- salvage$yearp
salvage$yearp <- NULL
# if (F) {
# !!! unfinished
# browser()
salvage <- salvage[salvage$start + salvage$olife > end_year, ]
salvage$value <- salvage$newcap * salvage$invcost *
((1 + salvage$discount)^(salvage$olife) -
(1 + salvage$discount)^(end_year - salvage$start + 1)) /
((1 + salvage$discount)^salvage$olife - 1)
fl <- (salvage$discount == 0)
salvage$value[fl] <- (salvage$newcap * salvage$invcost *
(salvage$olife - (end_year - salvage$start + 1)) /
salvage$olife)[fl]
salvage[, c(3, 2, 1, 9)]
# }
# NULL # temporary
}
if (scen@modOut@stage == "solved") {
# Postprocessing
# scen@modOut@variables$vTechSalv <- salvage_cost0(scen, "Tech")
# scen@modOut@variables$vStorageSalv <- salvage_cost0(scen, "Storage")
# scen@modOut@variables$vTradeSalv <- salvage_cost0(scen, "Trade")
pDummyImportCost <- .get_data_slot(scen@modInp@parameters$pDummyImportCost)
# browser()
vDummyImportCost <- merge0(pDummyImportCost,
scen@modOut@variables$vDummyImport,
by = c("comm", "region", "year", "slice")[
c("comm", "region", "year", "slice") %in%
colnames(pDummyImportCost)
]
)
vDummyImportCost$value <- vDummyImportCost$value.x * vDummyImportCost$value.y
vDummyImportCost$value.x <- NULL
vDummyImportCost$value.y <- NULL
scen@modOut@variables$vDummyImportCost <- vDummyImportCost
pDummyExportCost <- .get_data_slot(scen@modInp@parameters$pDummyExportCost)
vDummyExportCost <- merge0(
pDummyExportCost,
scen@modOut@variables$vDummyExport,
by = c("comm", "region", "year", "slice")[
c("comm", "region", "year", "slice") %in% colnames(pDummyExportCost)
]
)
vDummyExportCost$value <- vDummyExportCost$value.x * vDummyExportCost$value.y
vDummyExportCost$value.x <- NULL
vDummyExportCost$value.y <- NULL
scen@modOut@variables$vDummyExportCost <- vDummyExportCost
tmp <- .get_data_slot(scen@modInp@parameters$pEmissionFactor)
tmp$comm2 <- tmp$commp
tmp$commp <- tmp$comm
tmp$comm <- tmp$comm2
tmp$comm2 <- NULL
pTechEmisComm <- .get_data_slot(scen@modInp@parameters$pTechEmisComm)
vTechEmsFuel <-
merge0(
merge0(pTechEmisComm, scen@modOut@variables$vTechInp,
by = c("tech", "comm")
),
tmp,
by = "comm"
)
vTechEmsFuel$comm <- vTechEmsFuel$commp
if (nrow(vTechEmsFuel) > 0) {
vTechEmsFuel <- aggregate(
vTechEmsFuel$value.x * vTechEmsFuel$value.y * vTechEmsFuel$value,
vTechEmsFuel[, c("tech", "comm", "region", "year", "slice")], sum
)
vTechEmsFuel$value <- vTechEmsFuel$x
vTechEmsFuel$x <- NULL
} else {
vTechEmsFuel <- data.frame(
tech = character(), comm = character(), region = character(),
year = integer(), value = numeric(), stringsAsFactors = FALSE
)
}
scen@modOut@variables$vTechEmsFuel <- vTechEmsFuel
# Estimate Costs
if (length(getNames(scen, "costs")) != 0) {
cst <- getObjects(scen, "costs")
costs_tot <- data.frame(
costs = character(), region = character(), year = integer(),
value = numeric(), stringsAsFactors = FALSE
)
for (tmp in cst) {
in_dat <- scen@modOut@variables[[tmp@variable]]
if (anyDuplicated(.variable_set[[tmp@variable]])) {
sets <- .variable_set[[tmp@variable]]
sets[duplicated(sets)] <- paste0(sets[duplicated(sets)], 2)
colnames(in_dat) <- c(sets, "value")
}
if (nrow(in_dat) != 0 &&
!is.null(scen@modInp@parameters[[paste0("mCosts", tmp@name)]])) {
in_dat <- merge0(
in_dat,
.get_data_slot(
scen@modInp@parameters[[paste0("mCosts", tmp@name)]]
)
)
}
if (nrow(in_dat) != 0 &&
!is.null(scen@modInp@parameters[[paste0("pCosts", tmp@name)]])) {
prm <- .get_data_slot(
scen@modInp@parameters[[paste0("pCosts", tmp@name)]]
)
if (ncol(prm) == 1) {
in_dat$value <- in_dat$value * prm$value
} else {
colnames(prm)[ncol(prm)] <- "par"
in_dat <- merge0(in_dat, prm)
in_dat$value <- in_dat$value * in_dat$par
in_dat$par <- NULL
}
}
if (nrow(in_dat) != 0) {
in_dat <- aggregate(
in_dat[, "value", drop = FALSE],
in_dat[, c("region", "year"), drop = FALSE], sum
)
in_dat$costs <- tmp@name
costs_tot <- rbind(
costs_tot,
in_dat[, c("costs", "region", "year", "value"),
drop = FALSE
]
)
}
}
scen@modOut@variables$vUserCosts <- costs_tot
}
}
if (arg$echo) {
cat("Reading solution: ", round(proc.time()[3] -
read_result_time, 2), "s\n", sep = "")
}
if (scen@modOut@stage == "solved") scen@status$optimal <- TRUE
invisible(scen)
}
#' @rdname read
#' @method read scenario
#' @export
setMethod("read", "scenario", read_solution)
# read_solution <- read.scenario
# read.scenario <- function(scen, ...) read_solution(scen, ...)
# .S3method("read", "scenario", read_solution)
.paste_base_result2new <- function(scen) {
# Have to recalculate vObjective (need recalculate salvage before and so on, draft in Github/Misc/package/temp/interpolate_after_for_rest.R)
for (i in names(scen@misc$data.before)) {
scen@modOut@variables[[i]] <- rbind(scen@modOut@variables[[i]], scen@misc$data.before[[i]])
}
# Correct RowTradeCum #!!! ToDO: ??? check
if (nrow(scen@modOut@variables$vExportRowCum) > 0) {
scen@modOut@variables$vExportRowCum <- aggregate(
scen@modOut@variables$vExportRowCum[, "value", drop = FALSE],
scen@modOut@variables$vExportRowCum[, c("expp", "comm"),
drop = FALSE
], sum
)
}
if (nrow(scen@modOut@variables$vImportRowCum) > 0) {
scen@modOut@variables$vImportRowCum <- aggregate(
scen@modOut@variables$vImportRowCum[, "value", drop = FALSE],
scen@modOut@variables$vImportRowCum[, c("imp", "comm"), drop = FALSE], sum
)
}
scen
}
#
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.