-
Notifications
You must be signed in to change notification settings - Fork 44
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
adding average LCO-ccsinje and adjustment cost bugfixes #492
Changes from 6 commits
af9a3d7
0a75957
061fbdd
8d845f2
f9c005c
9acad08
b2dbc3d
78efc63
2164f40
d875e21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
Type: Package | ||
Package: remind2 | ||
Title: The REMIND R package (2nd generation) | ||
Version: 1.125.1 | ||
Date: 2023-12-07 | ||
Version: 1.125.2 | ||
Date: 2023-12-08 | ||
Authors@R: c( | ||
person("Renato", "Rodrigues", , "[email protected]", role = c("aut", "cre")), | ||
person("Lavinia", "Baumstark", role = "aut"), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,7 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
|
||
# read in general data (needed for average and marginal LCOE calculation) | ||
s_twa2mwh <- readGDX(gdx,c("sm_TWa_2_MWh","s_TWa_2_MWh","s_twa2mwh"),format="first_found") | ||
s_GtC2tCO2 <- 10^9 * readGDX(gdx,c("sm_c_2_co2","s_c_2_co2"),format="first_found") | ||
ttot <- as.numeric(readGDX(gdx,"ttot")) | ||
ttot_before2005 <- paste0("y",ttot[which(ttot <= 2000)]) | ||
ttot_from2005 <- paste0("y",ttot[which(ttot >= 2005)]) | ||
|
@@ -126,8 +127,9 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
p47_taxCO2eq_AggFE <- readGDX(gdx,"p47_taxCO2eq_AggFE", restore_zeros=F, react = "silent") | ||
|
||
## variables | ||
v_directteinv <- readGDX(gdx,name=c("v_costInvTeDir","vm_costInvTeDir","v_directteinv"),field="l",format="first_found")[,ttot,] | ||
v_directteinv_wadj <- readGDX(gdx,name=c("o_avgAdjCostInv"),field="l",format="first_found")[,ttot,] | ||
v_directteinv <- readGDX(gdx,name=c("v_costInvTeDir","vm_costInvTeDir","v_directteinv"),field="l",format="first_found")[,ttot,] ## Total direct Investment Cost in Timestep | ||
#v_directteinv_wadj <- readGDX(gdx,name=c("o_avgAdjCostInv"),field="l",format="first_found")[,ttot,] ## average adjustment cost per unit installed in period | ||
v_adjteinv <- readGDX(gdx,name=c("v_costInvTeAdj"),field="l",format="first_found")[,ttot,] ## total adjustment cost in period | ||
vm_capEarlyReti <- readGDX(gdx,name=c("vm_capEarlyReti"),field="l",format="first_found")[,ttot,] | ||
vm_deltaCap <- readGDX(gdx,name=c("vm_deltaCap"),field="l",format="first_found")[,ttot,] | ||
vm_demPe <- readGDX(gdx,name=c("vm_demPe","v_pedem"),field="l",restore_zeros=FALSE,format="first_found") | ||
|
@@ -179,7 +181,7 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
te_inv_annuity_wadj <- 1e+12 * te_annuity[,,te] * | ||
mbind( | ||
v_investcost[,ttot_before2005,te] * dimSums(vm_deltaCap[teall2rlf][,ttot_before2005,te],dim=3.2), | ||
v_directteinv_wadj[,ttot_from2005,te] | ||
v_adjteinv[,ttot_from2005,te] + v_directteinv[,ttot_from2005,te] | ||
) | ||
|
||
# average LCOE components ---- | ||
|
@@ -237,12 +239,28 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
|
||
# 2. sub-part: fuel cost ---- | ||
|
||
# fuel cost = PE price * PE demand of technology | ||
# 2.1 primary fuel cost = PE price * PE demand of technology | ||
|
||
te_annual_fuel_cost <- new.magpie(getRegions(te_inv_annuity),ttot_from2005,magclass::getNames(te_inv_annuity), fill=0) | ||
te_annual_fuel_cost[,,pe2se$all_te] <- setNames(1e+12 * qm_pebal[,ttot_from2005,pe2se$all_enty] / qm_budget[,ttot_from2005,] * | ||
setNames(vm_demPe[,,pe2se$all_te], pe2se$all_enty), pe2se$all_te) | ||
|
||
# 2.2 second fuel cost - !only CCSinje for now! | ||
# pm_prodCouple: Second fuel production or demand per unit output of technology. Negative values mean own consumption, positive values mean coupled product. | ||
pm_prodCouple <- readGDX(gdx, "pm_prodCouple", restore_zeros = F) | ||
# potential fuels and prices: not needed in this detail here, but copying approach in marginal section | ||
fuels <- c("peoil","pegas","pecoal","peur", "pebiolc" , "pebios","pebioil", | ||
"seel","seliqbio", "seliqfos","seliqsyn", "sesobio","sesofos","seh2","segabio" , | ||
"segafos","segasyn","sehe") | ||
pm_PEPrice <- readGDX(gdx, "pm_PEPrice", restore_zeros = F) | ||
pm_SEPrice <- readGDX(gdx, "pm_SEPrice", restore_zeros = F) | ||
Fuel.Price <- mbind(pm_PEPrice,pm_SEPrice )[,,fuels]*1e12 # convert from trUSD2005/TWa to USD2005/TWa | ||
|
||
# calculate secondary Fuel cost for ccsinje | ||
te_annual_secFuel_cost <- new.magpie(getRegions(te_inv_annuity),ttot_from2005, "ccsinje" , fill=0) | ||
te_annual_secFuel_cost[,,"ccsinje"] <- setNames(-pm_prodCouple[,,"ccsinje"] * Fuel.Price[,,"seel"] * vm_co2CCS[,,"ccsinje.1"], "ccsinje") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am probably missing something, but why negative here? (-pm_prodCouple) oh I see nevermind it is because CCS consumes energy, would be nice to write this more explicitly (like below) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could also write a short documentation of the meanings of the three things multiplied here, I read it as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It says in line 249 that negative values mean own consumption, positive values mean coupled product. As I want positive cost, I need to multiply. |
||
# units: pm_prodCouple[,,"ccsinje"] = [TWa/GtC]; Fuel.Price = [USD2005/GtC]; vm_co2CCS= [GtC]; te_annual_secFuel_cost = [USD2005] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fuel price has unit USD2005/TWa, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, will adjust |
||
|
||
# 3. sub-part: OMV cost ---- | ||
|
||
# omv cost (from pm_data) * SE production | ||
|
@@ -308,7 +326,7 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
vm_VRE_prodSe_grid | ||
|
||
|
||
# 7. sub-part: ccs injection cost ---- | ||
# 7. sub-part: ccs injection cost (for technologies capturing CO2) ---- | ||
|
||
# same as for storage/grid but with ccs inejection technology | ||
# distributed to technolgies according to share of total captured co2 of ccs technology | ||
|
@@ -319,8 +337,8 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
|
||
# calculate total ccsinjection cost for all techs | ||
total_ccsInj_cost <- dimReduce(te_annual_inv_cost[getRegions(te_annual_OMF_cost),getYears(te_annual_OMF_cost),"ccsinje"] + | ||
te_annual_OMF_cost[,,"ccsinje"]) | ||
# distribute ccs injection cost over techs | ||
te_annual_OMF_cost[,,"ccsinje"] + te_annual_secFuel_cost[,,"ccsinje"]) | ||
# distribute ccs injection cost over techs => this does not include adjustment cost incurred! => what is the reasoning behind it? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't quite understand this comment, do you mean why is adjustment cost not added as a OMF cost? What is the unit of total_ccsInj_cost? Btw I don't quite get the formula here; shouldn't the total cost = annuitized (investment cost + other fixed costs (OMF, adjCost)) + running cost (energy cost, OMV cost, CO2 tax)... It looks like OMF and energy cost are here, but the others(?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I put this in the commit accidentally. The point is that only ccs injection cost without adjustment cost are distributed across technologies. I just wondered why there is no version that includes adjustment cost as these can be very substantial There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The general formula for total cost should be (and is): |
||
te_annual_ccsInj_cost[,,teCCS] <- setNames(total_ccsInj_cost * dimSums(v_emiTeDetail[,,"cco2"][,,teCCS], dim = c(3.1,3.2,3.4), na.rm = T) / | ||
dimSums( v_emiTeDetail[,,"cco2"], dim = 3, na.rm = T), | ||
teCCS) | ||
|
@@ -384,7 +402,7 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
te_annual_ccsInj_cost + | ||
te_annual_co2_cost | ||
|
||
# calculate total energy production | ||
####### 10. sub-part: calculate total energy production and carbon storage ################################# | ||
# SE and FE production in MWh | ||
total_te_energy <- new.magpie(getRegions(vm_prodSe),getYears(vm_prodSe), | ||
c(magclass::getNames(collapseNames(vm_prodSe[temapse],collapsedim = c(1,2))), | ||
|
@@ -406,21 +424,24 @@ reportLCOE <- function(gdx, output.type = "both"){ | |
total_te_energy_usable <- total_te_energy | ||
total_te_energy_usable[,,teVRE] <- total_te_energy[,,teVRE] - v32_storloss[,ttot_from2005,teVRE]*s_twa2mwh | ||
|
||
# change unit of stored CO2 from GtC to tCO2 | ||
vm_co2CCS_tCO2 <- vm_co2CCS*s_GtC2tCO2 | ||
|
||
|
||
|
||
# LCOE Calculation (average) ---- | ||
LCOE.avg <- NULL | ||
#################################################### | ||
######### calculate average LCOE ################## | ||
#################################################### | ||
LCOE.avg <- NULL | ||
|
||
# calculate standing system LCOE | ||
# divide total cost of standing system in that time step by total generation (before curtailment) in that time step | ||
# exception: grid and storage cost are calculate by dividing by generation after curtailment | ||
# convert from USD2005/MWh to USD2015/MWh (*1.2) | ||
# exceptions: grid and storage cost are calculate by dividing by generation after curtailment | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add another exception here that for CCS, it is divided by CO2 (or C?) stored |
||
# convert from USD2005/MWh (or tCO2) to USD2015/MWh (or tCO2) (*1.2) | ||
LCOE.avg <- mbind( | ||
setNames(te_annual_inv_cost[,getYears(te_annual_fuel_cost),pe2se$all_te]/ | ||
#### Energy technologies (pe2se$all_te) | ||
setNames(te_annual_inv_cost[,ttot_from2005,pe2se$all_te]/ | ||
total_te_energy[,,pe2se$all_te], | ||
paste0("LCOE|average|",pe2se$all_enty1,"|",pe2se$all_te,"|supply-side", "|Investment Cost")), | ||
setNames(te_annual_inv_cost_wadj[,getYears(te_annual_fuel_cost),pe2se$all_te]/ | ||
setNames(te_annual_inv_cost_wadj[,ttot_from2005,pe2se$all_te]/ | ||
total_te_energy[,,pe2se$all_te], | ||
paste0("LCOE|average|",pe2se$all_enty1,"|",pe2se$all_te,"|supply-side", "|Investment Cost w/ Adj Cost")), | ||
setNames(te_annual_fuel_cost[,,pe2se$all_te]/total_te_energy[,,pe2se$all_te], | ||
|
@@ -445,7 +466,18 @@ LCOE.avg <- NULL | |
setNames(te_annual_co2_cost[,,pe2se$all_te]/total_te_energy[,,pe2se$all_te], | ||
paste0("LCOE|average|",pe2se$all_enty1,"|",pe2se$all_te, "|supply-side","|CO2 Cost")), | ||
setNames(te_curt_cost[,,pe2se$all_te], | ||
paste0("LCOE|average|",pe2se$all_enty1,"|",pe2se$all_te, "|supply-side","|Curtailment Cost")) | ||
paste0("LCOE|average|",pe2se$all_enty1,"|",pe2se$all_te, "|supply-side","|Curtailment Cost")), | ||
#### Carbon Transport and storage ("ccsinje") | ||
setNames(te_annual_inv_cost[,ttot_from2005,"ccsinje"]/ | ||
vm_co2CCS_tCO2[,,"ccsinje.1"], | ||
paste0("LCOx|average|","cco2_stored|","ccsinje","|supply-side", "|Investment Cost")), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of calling it LCOx, maybe something more concrete like "LCOCS" Levelized cost of carbon/Co2 storage? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we give "cco2_stored" in the variable name? I thought usually for readability we have something more like "Captured CO2|Injected CO2 |Supply side|..." etc. not sure what the convention is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I called it "cco2_stored" because the convention for the other items in this dimension is pe2se$all_te. In my understanding, "cco2" would be the remind element corresponding to that. However, it is not about cco2 (all captured co2) but only the part of it that is stored, thus the additional "_stored" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. about LCOx vs LCOCS: I think that is a general question of how we want to call "LCO other than E" in this script. There are plans to also add LCO of CDR options. Do we want to give all of them their own abbreviation? Or do we want to have a generic LCOx and then filter according to the technologies, as it is the case with LCOE? |
||
setNames(te_annual_inv_cost_wadj[,ttot_from2005,"ccsinje"]/ | ||
vm_co2CCS_tCO2[,,"ccsinje.1"], | ||
paste0("LCOx|average|","cco2_stored|","ccsinje","|supply-side", "|Investment Cost w/ Adj Cost")), | ||
setNames(te_annual_OMF_cost[,,"ccsinje"]/vm_co2CCS_tCO2[,,"ccsinje.1"], | ||
paste0("LCOx|average|","cco2_stored|","ccsinje", "|supply-side","|OMF Cost")), | ||
setNames(te_annual_secFuel_cost[,,"ccsinje"]/vm_co2CCS_tCO2[,,"ccsinje.1"], | ||
paste0("LCOE|average|","cco2_stored|","ccsinje", "|supply-side","|Second Fuel Cost")) | ||
)*1.2 | ||
|
||
# convert to better dimensional format | ||
|
@@ -472,7 +504,8 @@ LCOE.avg <- NULL | |
df.lcoe.avg$cost <- sapply(df.lcoe.avg$cost, "[[", 6) | ||
|
||
df.lcoe.avg <- df.lcoe.avg %>% | ||
mutate( unit = "US$2015/MWh") %>% | ||
mutate( unit = "US$2015/MWh") %>% | ||
mutate(unit = case_when(tech=="ccsinje" & output=="cco2_stored" ~ "US$2015/tCO2", TRUE ~ unit)) %>% | ||
select(region, period, type, output, tech, sector, unit, cost, value) | ||
|
||
# reconvert to magpie object | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the R variable can also be called "v_costInvTeAdj"? normally I think the convention is to go with the REMIND variable name unless it is not possible.. (like v_directteinv above this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree in principle, but wanted to stick with the convention used in this part of the script. "v_costInvTeDir" turns into "v_directteinv", and I just applied the same logic. What did you mean saying "(like v_directteinv above this)"?