# class ######################################################################
#' An S4 class to represent technology
#'
#' @name class-technology
#'
#' @description
#' Technology of a technological process in the model is used to convert input
#' commodities into output commodities with consumption or production of auxiliary
#' commodities linked to other parameters or variables of the technology.
#' A broad set of parameters provides flexibility to model various technological
#' processes, including efficiency, availability, costs, and exogenous
#' shocks (weather factors).
#' @md
#'
#' @slot name `r get_slot_info("technology", "name")`
#' @slot desc `r get_slot_info("technology", "desc")`
#' @slot input `r get_slot_info("technology", "input")`
#' @slot output `r get_slot_info("technology", "output")`
#' @slot aux `r get_slot_info("technology", "aux")`
#' @slot units `r get_slot_info("technology", "units")`
#' @slot group `r get_slot_info("technology", "group")`
#' @slot cap2act `r get_slot_info("technology", "cap2act")`
#' @slot geff `r get_slot_info("technology", "geff")`
#' @slot ceff `r get_slot_info("technology", "ceff")`
#' @slot aeff `r get_slot_info("technology", "aeff")`
#' @slot af `r get_slot_info("technology", "af")`
#' @slot afs `r get_slot_info("technology", "afs")`
#' @slot weather `r get_slot_info("technology", "weather")`
#' @slot fixom `r get_slot_info("technology", "fixom")`
#' @slot varom `r get_slot_info("technology", "varom")`
#' @slot invcost `r get_slot_info("technology", "invcost")`
#' @slot start `r get_slot_info("technology", "start")`
#' @slot end `r get_slot_info("technology", "end")`
#' @slot olife `r get_slot_info("technology", "olife")`
#' @slot capacity `r get_slot_info("technology", "capacity")`
#' @slot optimizeRetirement `r get_slot_info("technology", "optimizeRetirement")`
#' @slot fullYear `r get_slot_info("technology", "fullYear")`
#' @slot timeframe `r get_slot_info("technology", "timeframe")`
#' @slot region `r get_slot_info("technology", "region")`
#' @slot misc `r get_slot_info("technology", "misc")`
#'
#' @rdname class-technology
#' @include class-supply.R
#' @family technology process class
#' @export
setClass("technology",
representation(
# General information
name = "character",
desc = "character",
input = "data.frame",
output = "data.frame",
aux = "data.frame",
units = "data.frame",
group = "data.frame",
cap2act = "numeric",
# Performance parameters
geff = "data.frame",
ceff = "data.frame",
aeff = "data.frame",
af = "data.frame",
afs = "data.frame",
weather = "data.frame",
# Costs
fixom = "data.frame",
varom = "data.frame",
invcost = "data.frame",
# Market
start = "data.frame",
end = "data.frame",
olife = "data.frame",
capacity = "data.frame",
optimizeRetirement = "logical",
# upgrade.technology = "character",
fullYear = "logical",
timeframe = "character",
region = "character",
misc = "list"
),
prototype(
name = "",
desc = "",
input = data.frame(
comm = character(),
unit = character(),
group = character(),
combustion = numeric(),
stringsAsFactors = FALSE
),
output = data.frame(
comm = character(),
unit = character(),
group = character(),
stringsAsFactors = FALSE
),
aux = data.frame(
acomm = character(),
unit = character(),
stringsAsFactors = FALSE
),
units = data.frame(
capacity = character(),
use = character(),
activity = character(),
costs = character(),
stringsAsFactors = FALSE
),
group = data.frame(
group = character(),
desc = character(),
unit = character(),
stringsAsFactors = FALSE
),
cap2act = 1,
# group efficiency
geff = data.frame(
region = character(),
year = integer(),
slice = character(),
group = character(),
ginp2use = numeric(),
stringsAsFactors = FALSE
),
# commodity efficiency
ceff = data.frame(
region = character(),
year = integer(),
slice = character(),
comm = character(),
cinp2use = numeric(),
use2cact = numeric(),
cact2cout = numeric(),
cinp2ginp = numeric(),
share.lo = numeric(),
share.up = numeric(),
share.fx = numeric(),
afc.lo = numeric(), # !!! check and potentially rename avc.*
afc.up = numeric(),
afc.fx = numeric(),
stringsAsFactors = FALSE
),
# Auxilary parameter
aeff = data.frame(
acomm = character(),
comm = character(),
region = character(),
year = integer(),
slice = character(),
cinp2ainp = numeric(),
cinp2aout = numeric(),
cout2ainp = numeric(),
cout2aout = numeric(),
act2ainp = numeric(),
act2aout = numeric(),
cap2ainp = numeric(),
cap2aout = numeric(),
ncap2ainp = numeric(),
ncap2aout = numeric(),
# storage part
stg2ainp = numeric(),
sinp2ainp = numeric(),
sout2ainp = numeric(),
stg2aout = numeric(),
sinp2aout = numeric(),
sout2aout = numeric(),
stringsAsFactors = FALSE
),
af = data.frame(
region = character(),
year = integer(),
slice = character(),
af.lo = numeric(),
af.up = numeric(),
af.fx = numeric(),
rampup = numeric(),
rampdown = numeric(),
stringsAsFactors = FALSE
),
afs = data.frame(
region = character(),
year = integer(),
slice = character(),
afs.lo = numeric(),
afs.up = numeric(),
afs.fx = numeric(),
stringsAsFactors = FALSE
),
weather = data.frame(
weather = character(),
comm = character(),
wafc.lo = numeric(),
wafc.up = numeric(),
wafc.fx = numeric(),
waf.lo = numeric(),
waf.up = numeric(),
waf.fx = numeric(),
wafs.lo = numeric(),
wafs.up = numeric(),
wafs.fx = numeric(),
stringsAsFactors = FALSE
),
fixom = data.frame(
region = character(),
year = integer(),
fixom = numeric(),
stringsAsFactors = FALSE
),
varom = data.frame(
region = character(),
year = integer(),
slice = character(),
comm = character(),
acomm = character(),
varom = numeric(),
cvarom = numeric(),
avarom = numeric(),
stringsAsFactors = FALSE
),
invcost = data.frame(
region = character(),
year = integer(),
invcost = numeric(),
wacc = numeric(),
retcost = numeric(),
stringsAsFactors = FALSE
),
start = data.frame(
region = character(),
start = integer(),
stringsAsFactors = FALSE
),
end = data.frame(
region = character(),
end = integer(),
stringsAsFactors = FALSE
),
olife = data.frame(
region = character(),
olife = integer(),
stringsAsFactors = FALSE
),
capacity = data.frame(
region = character(),
year = integer(),
stock = numeric(),
cap.lo = numeric(),
cap.up = numeric(),
cap.fx = numeric(),
ncap.lo = numeric(),
ncap.up = numeric(),
ncap.fx = numeric(),
ret.lo = numeric(),
ret.up = numeric(),
ret.fx = numeric(),
stringsAsFactors = FALSE
),
optimizeRetirement = TRUE,
# upgrade.technology = character(),
region = character(),
timeframe = character(),
misc = list()
),
# validity = .check_technology_data_frame,
S3methods = FALSE
)
setMethod("initialize", "technology", function(.Object, ...) {
.Object
})
# constructor ###############################################################
#' @title Create a new "technology" object.
#' @name newTechnology
#' @description
#' This function initializes and returns an S4 object of class `technology`,
#' representing a specific technology with given attributes.
#' The function has the same arguments as slot-names in the `technology` class.
#' Every argument has a specific format as described below and in the class
#' documentation.
#'
#' @param name `r get_slot_info("technology", "name")`
#' @param desc `r get_slot_info("technology", "desc")`
#' @param input `r get_slot_info("technology", "input")`
#' @param output `r get_slot_info("technology", "output")`
#' @param group `r get_slot_info("technology", "group")`
#' @param aux `r get_slot_info("technology", "aux")`
#' @param units `r get_slot_info("technology", "units")`
#' @param cap2act `r get_slot_info("technology", "cap2act")`
#' @param geff `r get_slot_info("technology", "geff")`
#' @param ceff `r get_slot_info("technology", "ceff")`
#' @param aeff `r get_slot_info("technology", "aeff")`
#' @param af `r get_slot_info("technology", "af")`
#' @param afs `r get_slot_info("technology", "afs")`
#' @param weather `r get_slot_info("technology", "weather")`
#' @param capacity `r get_slot_info("technology", "capacity")`
#' @param invcost `r get_slot_info("technology", "invcost")`
#' @param fixom `r get_slot_info("technology", "fixom")`
#' @param varom `r get_slot_info("technology", "varom")`
#' @param olife `r get_slot_info("technology", "olife")`
#' @param region `r get_slot_info("technology", "region")`
#' @param start `r get_slot_info("technology", "start")`
#' @param end `r get_slot_info("technology", "end")`
#' @param timeframe `r get_slot_info("technology", "timeframe")`
#' @param fullYear `r get_slot_info("technology", "fullYear")`
#' @param optimizeRetirement `r get_slot_info("technology", "optimizeRetirement")`
#' @param misc `r get_slot_info("technology", "misc")`
#'
#' @family technology process
#' @rdname technology
#'
#' @return An object of class technology.
#' @export
#' @inherit draw examples
#' @examples
#' ECOAL <- newTechnology(
#' name = "ECOAL", # name, used in sets, no white spaces or special characters
#' desc = "Generic coal power plant", # any description of the technology
#' input = data.frame(
#' comm = "COAL", # name of input commodity
#' unit = "MMBtu", # unit of the input commodity
#' # combustion factor from 0 to 1 (default 1) to calculate emissions
#' # from fuels combustion (commodities intermediate consumption, more broadly)
#' combustion = 1
#' ),
#' output = data.frame(
#' comm = "ELC", # name of output commodity
#' unit = "MWh" # unit of the output commodity
#' ),
#' aux = data.frame(
#' acomm = c("NOx", "SO2", "Hg"), # names of auxilary commodities
#' unit = c("kg", "kg", "g") # units
#' ),
#' # Capacity to activity ration: 8760 MWh output a year per MW of capacity
#' cap2act = 8760,
#' ceff = data.frame( # efficiency parameters for the main commodities
#' comm = "COAL",
#' # efficiency, 1/10 MWh per MMBtu, inverse heat rate
#' # check: 1 / convert(10, "MMBtu", "MWh") ~= 34% efficiency
#' cinp2use = 1 / 10
#' ),
#' aeff = data.frame( # paramaters for the auxilary commodities
#' acomm = c("NOx", "SO2", "Hg"),
#' act2aout = c(0.1, 0.2, 0.3) # emission factors, linked to activity
#' ),
#' af = data.frame( # availability (capacity) factor by time slices
#' af.up = 0.95 # maximum 95% per hour
#' ),
#' afs = data.frame( # availability factor by timeframes
#' slice = "ANNUAL", # annual availability factor
#' afs.lo = 0.40, # at least 40% per year
#' afs.up = 0.85 # maximum 85% per year
#' ),
#' fixom = data.frame( # fixed operational and maintenance cost
#' region = c("R1", "R2", NA), # regions, NA - all other regions
#' fixom = c(100, 200, 150) # MW a year
#' ),
#' varom = data.frame( # variable operational and maintenance cost
#' region = c("R1", "R2"), # regions
#' varom = c(1, 2) # $1 and $2 per MWh
#' ),
#' invcost = data.frame( # investment cost
#' year = c(2020, 2030, 2040), # to differentiate by years
#' invcost = c(1000, 900, 800) # $1000, $900, $800 per MW
#' ),
#' start = data.frame( # start year
#' start = 2020 # can be installed from 2020
#' ),
#' end = data.frame( # end year
#' end = 2040 # can be installed until 2040
#' ),
#' olife = data.frame( # operational life
#' olife = 30 # years
#' ),
#' capacity = data.frame( # existing capacity
#' year = c(2020, 2030, 2040), # to differentiate by years
#' region = c("R1"), # exists only in R1
#' stock = c(300, 200, 100) # age-based exogenous retirement
#' ),
#' # regions where the technology can be installed
#' region = c("R1", "R2", "R5", "R7"),
#' )
#' draw(ECOAL)
#'
newTechnology <- function(
name = "",
desc = "",
input = data.frame(),
output = data.frame(),
group = data.frame(),
aux = data.frame(),
units = data.frame(),
cap2act = as.numeric(1),
geff = data.frame(),
ceff = data.frame(),
aeff = data.frame(),
af = data.frame(),
afs = data.frame(),
weather = data.frame(),
# stock = data.frame(),
capacity = data.frame(),
invcost = data.frame(),
fixom = data.frame(),
varom = data.frame(),
olife = data.frame(),
region = character(),
start = data.frame(),
end = data.frame(),
timeframe = character(),
fullYear = TRUE,
optimizeRetirement = FALSE,
# upgrade.technology = character(),
misc = list(),
...) {
.data2slots("technology", name,
desc = desc,
input = input,
output = output,
group = group,
aux = aux,
units = units,
cap2act = cap2act,
geff = geff,
ceff = ceff,
aeff = aeff,
af = af,
afs = afs,
weather = weather,
capacity = capacity,
invcost = invcost,
fixom = fixom,
varom = varom,
olife = olife,
region = region,
start = start,
end = end,
timeframe = timeframe,
fullYear = fullYear,
optimizeRetirement = optimizeRetirement,
# upgrade.technology = upgrade.technology,
misc = misc,
...
)
}
# methods ###################################################################
#' @title Update a "technology" object.
#' @param object object of class technology
#'
#' @param ... slot-names with data to update (see `newTechnology`)
#'
#' @rdname technology
#' @family update technology process
#' @method update technology
#' @export
setMethod("update", "technology", function(object, ...) {
.data2slots("technology", object, ...)
})
# internal functions ########################################################
# get names of data.frame slots
.technology_data_frame <- function() {
# get technology slot data.frame names
g <- getClass("technology")
names(g@slots)[sapply(names(g@slots), function(z) g@slots[[z]] == "data.frame")]
}
# table commodity_type and checks
checkInpOut <- function(tech) {
ctype <- data.frame(
type = factor(NULL, c("input", "output", "aux")),
group = character(),
comb = numeric(),
unit = character(),
stringsAsFactors = FALSE
)
# Define type commodity
icomm <- tech@input$comm
ocomm <- tech@output$comm
acomm <- tech@aux$acomm
comm <- c(icomm, ocomm, acomm)
ctype[seq(along = comm), ] <- NA
rownames(ctype) <- comm
ctype[icomm, "type"] <- "input"
ctype[ocomm, "type"] <- "output"
ctype[acomm, "type"] <- "aux"
ctype[icomm, c("group", "unit")] <- tech@input[, c("group", "unit")]
ctype[ocomm, c("group", "unit")] <- tech@output[, c("group", "unit")]
ctype[, "comb"] <- 0
tech@input$combustion[is.na(tech@input$combustion)] <- 1
ctype[tech@input$comm, "comb"] <- tech@input$combustion
aux <- data.frame(
input = logical(),
output = logical(),
stringsAsFactors = FALSE
)
if (length(acomm)) {
aux[seq(along = acomm), ] <- FALSE
rownames(aux) <- acomm
}
# Check type
# ! have to realised
if (length(icomm) == 0 && length(ocomm) == 0) {
warnings("There is no input & output commodity")
}
# Define technology type by parameter
for (i in comm) {
# Group ?
if (any(!is.na(tech@ceff[tech@ceff$comm == i, c(
"cinp2ginp", "share.lo",
"share.up", "share.fx"
)]))) {
if (is.na(ctype[i, "group"])) {
stop('Wrong commodity "', tech@name, '": "', i, '"')
}
}
# Not group ?
if (any(!is.na(tech@ceff[tech@ceff$comm == i, "cinp2use"]))) {
if (!is.na(ctype[i, "group"])) {
stop('Wrong commodity "', tech@name, '": "', i, '"')
}
}
# Input ?
if (any(!is.na(tech@ceff[
tech@ceff$comm == i,
c("cinp2use", "cinp2ginp")
]))) {
if (ctype[i, "type"] != "input") {
stop('Wrong commodity "', tech@name, '": "', i, '"')
}
}
# Output ?
if (any(!is.na(tech@ceff[tech@ceff$comm == i, c(
"use2cact", "cact2cout" # , "afc.lo", "afc.up", "afc.fx"
)]))) {
if (ctype[i, "type"] != "output") {
stop('Wrong commodity "', tech@name, '": "', i, '"')
}
}
# Aux ?
if (any(!is.na(tech@aeff[tech@aeff$acomm == i, c(
"act2ainp", "act2aout",
"cap2ainp", "cap2aout", "ncap2ainp", "ncap2aout"
)])) ||
any(!is.na(tech@aeff[tech@aeff$acomm == i, c(
"cinp2ainp",
"cinp2aout", "cout2ainp", "cout2aout"
)]))) {
if (ctype[i, "type"] != "aux") {
stop('Wrong commodity "', tech@name, '": "', i, '"')
}
}
}
for (i in acomm) {
aux[i, "input"] <- (any(!is.na(
tech@aeff[tech@aeff$acomm == i, c("act2ainp", "cap2ainp", "ncap2ainp")]
)) ||
any(!is.na(tech@aeff[tech@aeff$acomm == i, c("cinp2ainp", "cout2ainp")])))
aux[i, "output"] <- (any(!is.na(
tech@aeff[tech@aeff$acomm == i, c("act2aout", "cap2aout", "ncap2aout")]
)) ||
any(!is.na(tech@aeff[tech@aeff$acomm == i, c("cinp2aout", "cout2aout")])))
}
gtype <- data.frame(
type = factor(NULL, c("input", "output")),
stringsAsFactors = FALSE
)
# Define type group
group <- unique(c(
tech@geff$group, tech@geff$geff,
tech@group$group, tech@group$geff,
tech@input$group, tech@output$group
))
group <- group[!is.na(group)]
if (length(group) != 0) {
if (any(is.na(c(tech@group$group, tech@group$geff)))) {
stop('There is NA group in technology "', tech@name, '"')
}
gtype[seq(along = group), ] <- NA
rownames(gtype) <- group
for (i in unique(tech@geff$group)) {
if (any(!is.na(tech@geff[tech@geff$group == i, "ginp2use"]))) {
if (!is.na(gtype[i, "type"]) && gtype[i, "type"] == "output") {
stop('Wrong group in technology "', tech@name, '": "', i, '"')
}
gtype[i, "type"] <- "input"
}
}
for (i in group) {
jj <- rownames(ctype)[!is.na(ctype$group) & ctype$group == i]
if (length(jj) != 0) {
if (any(ctype[jj, "type"] == "input")) {
if (!is.na(gtype[i, "type"]) && gtype[i, "type"] == "output") {
stop('Wrong group in technology "', tech@name, '": "', i, '"')
}
gtype[i, "type"] <- "input"
}
if (any(ctype[jj, "type"] == "output")) {
if (!is.na(gtype[i, "type"]) && gtype[i, "type"] == "input") {
stop('Wrong group in technology "', tech@name, '": "', i, '"')
}
gtype[i, "type"] <- "output"
}
}
}
if (any(is.na(gtype[, "type"]))) {
stop(
'Wrong group in technology "', tech@name, '": "',
paste(rownames(gtype)[is.na(gtype[, "type"])], collapse = '", "'), '"'
)
}
}
fcmd <- c(tech@ceff$comm, tech@aeff$comm[!is.na(tech@aeff$comm)], tech@aeff$acomm)
fcmd <- fcmd[!(fcmd %in% c(tech@input$comm, tech@output$comm, tech@aux$acomm))]
if (length(fcmd) != 0) {
stop(
'Unknow commodity in technology (there is not definition in input, output or aux) "',
tech@name, '": ', paste(fcmd, collapse = '", "'), '"'
)
}
list(comm = ctype, group = gtype, aux = aux)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.