Difference between revisions of "Energy balance"

From Testiwiki
Jump to: navigation, search
(Fuel shares in generic processes: District heat added)
(Calculations: energyBalancetest)
Line 238: Line 238:
 
:''Ovariable energyBalance below is used in [[Helsinki energy decision 2015]]. [[Prices of fuels in heat production]] are used as direct inputs in the optimising.
 
:''Ovariable energyBalance below is used in [[Helsinki energy decision 2015]]. [[Prices of fuels in heat production]] are used as direct inputs in the optimising.
  
<rcode name="energyBalance" label="Initiate energyBalance (developers only)" embed=1>
+
<rcode name="energyBalancetest" label="Initiate energyBalance (developers only)" embed=1>
 
## This code is  Op_en5141/energyBalance [[Energy balance]].
 
## This code is  Op_en5141/energyBalance [[Energy balance]].
 
library(OpasnetUtils)
 
library(OpasnetUtils)
  
 
energyBalance <- Ovariable("energyBalance",
 
energyBalance <- Ovariable("energyBalance",
dependencies = data.frame(
+
dependencies = data.frame(
Name = c(
+
Name = c(
"energyProcess", # Matric showing inputs and outputs the processes of each plant.
+
"energy", # Energy supply and demand in the system
"fuelPrice", # Prices of fuels (by Time)
+
#demand and supply that is not centrally controlled.
"plantParameters", # Capacities and costs of running plants
+
"nondynsupply", # Energy supply that is not optimised.
"requiredEnergy", # Energy demand that must be met by production plus all other energy
+
"requiredName", # Fuel name for the energy type that is balanced for inputs and outputs.
#demand and supply that is not centrally controlled.
+
"fuelShares", # Shares of fuels outside the balanced processes
"requiredName" # Fuel name for the energy type that is balanced for inputs and outputs.
+
"energyProcess", # Matric showing inputs and outputs the processes of each plant.
),
+
"fuelPrice", # Prices of fuels (by Time)
Ident = c(
+
"plantParameters" # Capacities and costs of running plants
NA,
 
"Op_en4151/fuelPrice",
 
NA,
 
NA,
 
NA
 
)
 
 
),
 
),
formula = function(...) {
+
Ident = c(
+
NA,
# First, define the optimising function
+
NA,
#optfunction <- function(
+
NA,
# x, # Variables to optimise (activities of power plants).
+
NA,
# amountRequired, # energy demand that must be met by supply (scalar)
+
NA,
# unitprice, # vector of prices per activity unit (by plant).
+
"Op_en4151/fuelPrice",
# unitRequired # vector of required energy produced per activity uniit (by plant).
+
NA
#) {
+
)
#
+
),
# out <- sum(x * unitprice) + (amountRequired - sum(x * unitRequired))^2 * 1E6
+
formula = function(...) {
#
+
# return(out)
+
# First, define the optimising function
#}
+
optfunction <- function(
 +
x, # Variables to optimise (activities of power plants).
 +
amountRequired, # energy demand that must be met by supply (scalar)
 +
unitprice, # vector of prices per activity unit (by plant).
 +
unitRequired # vector of required energy produced per activity uniit (by plant).
 +
) {
 +
 
 +
out <- sum(x * unitprice) + (amountRequired - sum(x * unitRequired))^2 * 1E6
 
 
 +
return(out)
 +
}
 +
 +
ene <- unkeep(energy, prevresults = TRUE, sources = TRUE) # Modified energy supply and demand
 +
ene <- oapply(ene, cols = c("Efficiency", "Renovation", "Building"), FUN = sum)
 +
#requiredEnergy@name <- "requiredEnergy"
 +
#colnames(requiredEnergy@output)[colnames(requiredEnergy@output) == "energyUseResult"] <- "requiredEnergyResult"
 +
#colnames(reqen@output)[colnames(reqen@output) == "Heating"] <- "Fuel"
 +
ene <- oapply(ene * fuelShares, cols = "Heating", FUN = sum)
 +
 +
if(!is.na(requiredName)) { # Energy balance is only done if requiredName is given
 +
 +
nondynen <- ene # Non-dynamic energy supply and demand, which is not optimised.
 +
nondynen@output <- nondynen@output[nondynen@output$Fuel != requiredName , ]
 +
 +
# Required energy supply and demand, which IS optmised.
 +
amountRequired <- ene
 +
if("Fuel" %in% colnames(amountRequired@output)) {
 +
amountRequired@output <- amountRequired@output[amountRequired@output$Fuel == requiredName , ]
 +
amountRequired <- unkeep(amountRequired, cols = "Fuel")
 +
}
 +
 
# Operational costs per unit of activity. Fuel price is excluded and calculated elsewhere.
 
# Operational costs per unit of activity. Fuel price is excluded and calculated elsewhere.
operationCost <- plantParameters * 1
+
operationCost <- plantParameters
 
operationCost@output <- operationCost@output[operationCost@output$Parameter == "Operation cost" , ]
 
operationCost@output <- operationCost@output[operationCost@output$Parameter == "Operation cost" , ]
 
operationCost <- unkeep(operationCost, cols = "Parameter")
 
operationCost <- unkeep(operationCost, cols = "Parameter")
+
 
 
# Costs per unit of activity by plant. Fuel price included.
 
# Costs per unit of activity by plant. Fuel price included.
consumption <- energyProcess
+
unitprice <- oapply(energyProcess * fuelPrice * -1, cols = "Fuel", FUN = sum) + operationCost
# Consumption is defined as negative coefficient in process table, so lets set all positive coefficients
 
# (production) to 0 for cost calculations.
 
result(consumption)[result(consumption) > 0] <- 0
 
unitprice <- oapply(consumption * fuelPrice * -1, cols = "Fuel", FUN = sum) + operationCost
 
 
 
 
colnames(unitprice@output)[colnames(unitprice@output) == "plantParametersResult"] <- "unitpriceResult"
 
colnames(unitprice@output)[colnames(unitprice@output) == "plantParametersResult"] <- "unitpriceResult"
Line 294: Line 313:
 
unitRequired@output <- unitRequired@output[unitRequired@output$Fuel == requiredName , ]
 
unitRequired@output <- unitRequired@output[unitRequired@output$Fuel == requiredName , ]
 
unitRequired <- unkeep(unitRequired, cols = "Fuel")
 
unitRequired <- unkeep(unitRequired, cols = "Fuel")
+
 
# Required energy amount in the system.
 
amountRequired <- requiredEnergy
 
if("Fuel" %in% colnames(amountRequired@output)) {
 
amountRequired@output <- amountRequired@output[amountRequired@output$Fuel == requiredName , ]
 
amountRequired <- unkeep(amountRequired, cols = "Fuel")
 
}
 
 
 
# Put all inputs into one ovariable and sort by Plant. Note: important outputs in columns
 
# Put all inputs into one ovariable and sort by Plant. Note: important outputs in columns
# unitpriceResult, requiredEnergyResult, energyProcessResult, and Result.
+
# unitpriceResult, requiredEnergyResult, energyProcessResult, and Result.
 
temp <- (unitprice * unitRequired * amountRequired * 0 +   
 
temp <- (unitprice * unitRequired * amountRequired * 0 +   
unkeep(plantParameters, prevresults = TRUE, sources = TRUE)
+
unkeep(plantParameters, prevresults = TRUE, sources = TRUE)
)
+
)
 
indices <- unique(temp@output[temp@marginal & !colnames(temp@output) %in% c("Plant", "Parameter")])
 
indices <- unique(temp@output[temp@marginal & !colnames(temp@output) %in% c("Plant", "Parameter")])
+
 
 
out <- data.frame()
 
out <- data.frame()
 
 
Line 314: Line 326:
 
temp2 <- merge(indices[i , , drop = FALSE], temp@output)
 
temp2 <- merge(indices[i , , drop = FALSE], temp@output)
 
temp2 <- temp2[order(temp2$Plant) , ]
 
temp2 <- temp2[order(temp2$Plant) , ]
#temp3 <- optim(
+
temp3 <- optim(
# par = temp2[temp2$Parameter == "Min" , "Result"], # from plantParameters
+
par = temp2[temp2$Parameter == "Min" , "Result"], # from plantParameters
# fn = optfunction,  
+
fn = optfunction,  
# lower = temp2[temp2$Parameter == "Min" , "Result"], # from plantParameters
+
lower = temp2[temp2$Parameter == "Min" , "Result"], # from plantParameters
# upper = temp2[temp2$Parameter == "Max" , "Result"], # from plantParameters
+
upper = temp2[temp2$Parameter == "Max" , "Result"], # from plantParameters
# unitprice = temp2[temp2$Parameter == "Min" , "unitpriceResult"], # from unitprice
+
unitprice = temp2[temp2$Parameter == "Min" , "unitpriceResult"], # from unitprice
# amountRequired = temp2[temp2$Parameter == "Min" , "requiredEnergyResult"][1], # from requiredEnergy
+
amountRequired = temp2[temp2$Parameter == "Min" , paste(ene@name, "Result", sep = "")][1], # from amountRequired
# unitRequired = temp2[temp2$Parameter == "Min" , "energyProcessResult"], # from energyProcess
+
unitRequired = temp2[temp2$Parameter == "Min" , "energyProcessResult"], # from energyProcess
# method = "L-BFGS-B"
+
method = "L-BFGS-B"
#)
 
 
require(lpSolve)
 
 
lower = temp2[temp2$Parameter == "Min" , "Result"] # from plantParameters
 
upper = temp2[temp2$Parameter == "Max" , "Result"] # from plantParameters
 
 
unitprice <- temp2[temp2$Parameter == "Min" , "unitpriceResult"]
 
amountRequired <- temp2[temp2$Parameter == "Min" , "requiredEnergyResult"][1] # from requiredEnergy
 
unitRequired <- temp2[temp2$Parameter == "Min" , "energyProcessResult"] # from energyProcess
 
 
# parameters in order: prices, deficit, excess
 
constraint_M <- matrix(
 
c(unitRequired, 1, -1),
 
1, # rows
 
length(unitprice) + 2 , # columns
 
byrow = TRUE
 
 
)
 
)
constraint_M <- rbind(constraint_M, diag(length(unitprice) + 2))
+
 
constraint_M <- rbind(constraint_M, diag(length(unitprice) + 2)[-(length(unitprice) + 1):-(length(unitprice) + 2),])
 
constraint_sign <- rep(c("==", ">=", "<="), c(1, length(unitprice) + 2, length(unitprice)))
 
constraint_constant <- c(amountRequired, lower, 0, 0, upper)
 
 
temp3 <- lp(
 
"min",
 
c(unitprice, 1e6, 0), # add large coefficient for deficit and 0 for excess
 
constraint_M,
 
constraint_sign,
 
constraint_constant
 
)
 
 
 
 
out <- rbind(out, data.frame(
 
out <- rbind(out, data.frame(
indices[i , , drop = FALSE],
+
indices[i , , drop = FALSE],
Plant = c(as.character(temp2$Plant[temp2$Parameter == "Min"]), paste(requiredName, c("Deficit", "Excess"), sep = "")),
+
Plant = temp2$Plant[temp2$Parameter == "Min"],
Result = temp3$solution
+
Result = temp3$par
))
+
))
 
}
 
}
return(out)
+
out <- Ovariable(output = out, marginal = c(rep(TRUE, ncol(out)-1), FALSE))
 +
out <- out * energyProcess # Optimised fuel usage
 +
# out <- combine(out, nondynen) # Combine optimised and non-optimised energy demand
 +
} else {
 +
out <- ene # If optimisation is not done, take the simple version updated with fuelShares.
 
}
 
}
 +
 +
# out <- combine(out, nondynsupply) # Combine also non-dynamic energy supply
 +
 +
return(out)
 +
}
 
)
 
)
  

Revision as of 12:33, 3 July 2015



The energy calculation based on two core concepts

  1. Energy production or source
  2. Energy consumption

Question

How to calculate energy balances?

Answer

Press button to run the model. Get a free user account and edit the table below to change the model inputs. You may also copy the model to your own page for your own purposes. For examples, see e.g. Energy balance in Kuopio or Energy balance in Suzhou.

+ Show code

Rationale

Input

Example table for making matrices from text format equations. CHPcapacity describes which of the piecewise linear equations should be used. Policy is a decision option that alters the outcome. Dummy is only for compatibility but it is not used.
Equations(GWh /a)
ObsCHPcapacityPolicyEquationDummyDescription
1BiofuelCHP renewable = CHP peat1Biofuel policy contains half biofuels, half peat
2BAUCHP renewable = 89.241
3CHP peat + CHP renewable + CHP oil = CHP heat + CHP electricity1
4CHP peat = 90-98*CHP oil1
5CHP electricity = 0.689*CHP heat1
6CHP<1000H heat = 0.08*CHP heat1Small heat plants reflect the total heat need
7CHP>1000CHP heat + CHP electricity = 10001But production capacity of CHP may be overwhelmed, decoupling CHP heat and H heat.
8H biogas + H oil = H heat1
9H oil = 18.973*H biogas1
10Bought electricity + CHP electricity = Cons electricity1
11CHP heat + H heat = Cons heat1
12Cons electricity = 900-11001
13Cons heat = 900-10001
Example table to describe the details about nonlinear equations.
Nonlinearity parameters(GWh /a)
ObscritVarcritIndexrescolcritLocLowcritLocHighcritValue
1Cons heatCHPcapacityResultCHP<1000CHP>10001080


This table is fetched if there are no nonlinearities. Therefore, there is no need to copy it to the case study page.
No nonlinearities(GWh /a)
ObscritVarcritIndexrescolcritLocLowcritLocHighcritValue
1
This table is fetched if there are no modelled upstream variables that would affect the equations.
No modelled upstream variables(-)
ObsenergybalanceVarsResult
1

Output

Output is an ovariable with column energy.balanceVar for the solved variables, a result column, and all other indices in the balance object used as input. This method has been used in several cases:

Data

  • Energy balances are described as input = output on a coarse level (called classes) where the structure is the same or similar to the OECD energy balance tables. If possible, this is described on the Energy balance method level and it is shared by all cities.
  • On more detailed (variable level in the matrix), the fraction of each variable of the total class are described separately. Fractions are city specific and they are described on city level in a separate table.
  • Based on the fraction table, detailed equations with variables are created. The format will be fraction * class total = variable.
  • The last fraction has zero degrees of freedom when the class total is given. However, it must have a variable and thus a row in the fraction table. The result for that variable is an empty cell (which results in NA).
  • Unlike in the previous version, all variables are given either as values or equations, and the user interface is not used for BAU. In contrast, user interface or decision table may be used to derive values for alternative scenarios.
  • To make this work, the city-specific fraction data must be defined as ovariable (so that it can be changed with a decision table), and also the energy balance method must be described asa ovariable. How are we going to make the two interplay, as we may want to have several cities?
    • Define one city ovariable and evaluate energy balance with that. The ovariable has a generic name. Then, define a new city ovariable with the same name and re-evaluate the energy balance ovariable; this must be done so that the two cities are appended rather than replaced.
    • city ovariables are appended first into a large fraction table, and then that is used to create the large energy balance matrix. # : This is clearly better. --Jouni 17:09, 21 February 2013 (EET)
  • The city-specific ovariable may have Iter and other indices. A separate matrix is created and solved for each unique combination of indices. This makes it possible to have a very flexible approach.
  • We should check if the energy balance matrix (see Matti's Excel) has city-specific equations. If possible, energy transformations are described as generic equations on the energy balance method.
  • Structure of OECD Energy balance tables (data):
    • Fuel (given as observation columns in OECD table)
    • Activity (row in OECD table)
    • Description
  • Structure of the generic process table
    • Equation,
    • Col,
    • Result,
    • Description? # : This does not join up in a coherent way. --Jouni 17:09, 21 February 2013 (EET)
  • Columns for fraction table
    • Class
    • Item
    • Result (fraction)
    • Indices as needed

'Additional thoughts

Energy balance has these parts

  • General table that describes balances and conversions from ole fuel to another.
    • Items and sums Are defined at generic level.
  • Data table that contains amounts from OECD table
  • Fraction table thAt describes how detailSs Are derived from sums.
  • if there Are additions to sta dard items, they descrided at city level in an addition table. It must have the struxture of the matrix table in long format.
  • can nonlinearities ne handled simply by indices separating two linear parts of nonlinear equations?

Old description

# : What are other energy sources,i wish it should be specific,how about air transport,does it included in the energy balance calculation? --Sam0911 16:29, 10 February 2013 (EET)

Use a table where different fuel types are columns and different stocks, energy production processes, or consumption types are rows called Energy accounts (Ene.account for short). See also an example File:Energy supply in Europe.xls. All Ene.accounts and fuel types used are listed on Energy consumption classes.

A part of a full energy balance sheet (ktoe/a).
Coal and peat Crude oil Petrochemical products Electricity Heat
Production and supply of primary energy
Production 129
Import 28 63
Export
Conversion of primary energy to use
Transfers
Electricity plants
CHP plants -129 -28 61 96
Final energy consumption
Industry
Road transport 54
Heating 10 96
Other energy use 9 51

Energy balance can be considered as double-entry bookkeeping. The production and conversion are typically credit (i.e., where the energy comes from), while consumption is debit (i.e., where the energy is used). In a typical case, both credit and debit are marked positive on the energy balance sheet. However, there are activities that convert one fuel to another, so that the energy is moved from one column to another. In this case, credit (the source) is marked negative and debit (the target) is marked positive. This is because the production and conversion rows together should reflect how much energy is actually available for final consumption. In other words, the sum of production and conversion rows should equal the sum of the consumption rows in every column.

Because production + conversion = consumption, also production = consumption - conversion. These equations are used to derive the supply that is needed to fulfil the demand.

Fuel shares in generic processes

The table below contains connections of heating types and fuel usage in generic situations. There may be case-specific differences, which must be handled separately.

Fuel use in different heating types(-)
ObsHeatingBurnerFuelFractionDescription
1WoodDomesticWood1
2OilDomesticLight oil1
3GasDomesticGas1
4Heating oilDomesticLight oil1
5CoalDomesticCoal1
6DistrictHeat1
7Other sourcesDomesticOther sources1
8No energy sourceDomesticOther sources1
9GeothermalGridElectricity0.3Geothermal does not sum up to 1 because more heat is produced than electricity consumed.
10Centrifuge, hydro-extractorGridElectricity0.3Not quite clear what this is but presumably a heat pump.
11Solar heater/ collectorGridElectricity0.1Use only; life-cycle impacts omitted.
12ElectricityGridElectricity1

+ Show code

# : District heating below moved out of the generic table. Should be put to city-specific pages. --Jouni (talk) 04:41, 12 June 2015 (UTC)

Long-distance heating|Large fluidized bed|Waste|0.5|The values are from Wikipedia for Basel. See below. Long-distance heating|Large fluidized bed|Wood|0.1| Long-distance heating|Large fluidized bed|Gas|0.4| Long-distance heating|Grid|Electricity|0|This is geothermally-generated district heating. Note: the fraction you need electricity is ca. 0.3*the amount of geoheat produced. Coal|Large fluidized bed|Coal|1| District|Large fluidized bed|Wood|0.04|These values are for Kuopio. District|Large fluidized bed|Peat|0.84| District|Large fluidized bed|Heavy oil|0.12| District heating|Large fluidized bed|Coal|0.6|These values are for Helsinki. District heating|Large fluidized bed|Gas|0.4|

For guesstimates about Long-distance heating (which is used in Basel), see Climate change policies in Basel and de:IWB.

Calculations

Ovariable energyBalance below is used in Helsinki energy decision 2015. Prices of fuels in heat production are used as direct inputs in the optimising.

+ Show code


Stored objects below used by Energy balance in Kuopio.

+ Show code

How to give uncertain parameters?

  • In equations, the content is interpreted only inside solveMatrix. Therefore, the typical approach where all unique index combinations are run one at a time does not work.
  • There should be an update in parameter interpretation for terms with one entry only. It can no longer be based on as.numeric, if distributions (=text) is allowed.
    • If it starts with [a-z.] it is a variable name.
    • If it starts with [0-9<\\-] it is a parameter value.
  • Instead of params[[i]] and [[vars]] vectors, a data.frame will be created with Result as the params column.
  • The data.frame is then interpreted with N = N. If parameters are probabilistic, Iter column will appear.
  • When all parameters have been interpreted, check if Iter exists.
  • If Iter exists, make a for loop for all values of Iter.
    • Create a matrix from the parameters and solve.
    • Rbind the result to a data.frame with Iter.
  • Return the output.
  • Old code with an input table with columns Equation, Col, Result, Description: [1]

See also

Helsinki energy decision 2015
In English
Assessment Main page | Helsinki energy decision options 2015
Helsinki data Building stock in Helsinki | Helsinki energy production | Helsinki energy consumption | Energy use of buildings | Emission factors for burning processes | Prices of fuels in heat production | External cost
Models Building model | Energy balance | Health impact assessment | Economic impacts
Related assessments Climate change policies in Helsinki | Climate change policies and health in Kuopio | Climate change policies in Basel
In Finnish
Yhteenveto Helsingin energiapäätös 2015 | Helsingin energiapäätöksen vaihtoehdot 2015 | Helsingin energiapäätökseen liittyviä arvoja | Helsingin energiapäätös 2015.pptx
Urgenche research project 2011 - 2014: city-level climate change mitigation
Urgenche pages

Urgenche main page · Category:Urgenche · Urgenche project page (password-protected)

Relevant data
Building stock data in Urgenche‎ · Building regulations in Finland · Concentration-response to PM2.5 · Emission factors for burning processes · ERF of indoor dampness on respiratory health effects · ERF of several environmental pollutions · General criteria for land use · Indoor environment quality (IEQ) factors · Intake fractions of PM · Land use in Urgenche · Land use and boundary in Urgenche · Energy use of buildings

Relevant methods
Building model · Energy balance · Health impact assessment · Opasnet map · Help:Drawing graphs · OpasnetUtils‎ · Recommended R functions‎ · Using summary tables‎

City Kuopio
Climate change policies and health in Kuopio (assessment) · Climate change policies in Kuopio (plausible city-level climate policies) · Health impacts of energy consumption in Kuopio · Building stock in Kuopio · Cost curves for energy (prioritization of options) · Energy balance in Kuopio (energy data) · Energy consumption and GHG emissions in Kuopio by sector · Energy consumption classes (categorisation) · Energy consumption of heating of buildings in Kuopio · Energy transformations (energy production and use processes) · Fuels used by Haapaniemi energy plant · Greenhouse gas emissions in Kuopio · Haapaniemi energy plant in Kuopio · Land use in Kuopio · Building data availability in Kuopio · Password-protected pages: File:Heat use in Kuopio.csv · Kuopio housing

City Basel
Buildings in Basel (password-protected)

Energy balances
Energy balance in Basel · Energy balance in Kuopio · Energy balance in Stuttgart · Energy balance in Suzhou


References


Related files