-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
create emep_europe wear emissions function
- Loading branch information
Showing
3 changed files
with
559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,349 @@ | ||
#' @title | ||
#' Emissions from road vehicle tyre, brake, and surface wear from the European | ||
#' Environment Agency (EMEP/EEA) model | ||
#' | ||
#' @description | ||
#' Returns a list or data.table of emissions for urban buses based on Tier 2 of | ||
#' EMEP/EEA air pollutant emission inventory guidebooks (2019). The function concerns | ||
#' the emissions of particulate matter (PM), encompassing black carbon (BC) (1), | ||
#' which arises from distinct sources, namely, road vehicle tire and brake wear | ||
#' (NFR code 1.A.3.b.vi), and road surface wear (NFR code 1.A.3.b.vii). It is | ||
#' important to note that PM emissions exhaust from vehicle exhaust are excluded. | ||
#' The focus is on primary particles, which refer to those that are directly | ||
#' emitted due to surface wear, rather than those generated from the | ||
#' resuspension of previously deposited material. See more in @details. | ||
#' | ||
#' @param dist units; Length of each link in 'km'. | ||
#' @param speed units; Speed in 'km/h'. | ||
#' @param pollutant character; Pollutant, classified in "TSP"(Total Suspended Particles), | ||
#' "PM10","PM2.5", "PM1.0","PM0.1". Please note that emissions factors for | ||
#' "PM1.0" and "PM0.1" are not available for road surface wear process. | ||
#' @param veh_type character; Bus type, classified in "Ubus Midi <=15 t", | ||
#' "Ubus Std 15 - 18 t", "Ubus Artic >18 t", "Coaches Std >18 t", or "Coaches Artic >18 t". | ||
#' @param fleet_composition vector; Fleet composition, which is a distribution | ||
#' of fleet based on frequency. If there is only one, 'fleet_composition' is 1.0. | ||
#' @param load numeric; Load ratio, classified in 0.0, 0.5 and 1.0. Default is 0.5. | ||
#' @param process character; Emission process sources, classified in "tyre","brake" and/or | ||
#' "road". | ||
#' @param as_list logical; Returns emission factors as a list, instead of data.table format. Default is TRUE. | ||
#' | ||
#' @return List. emission in units 'g' (list or a data.table). | ||
#' @details | ||
#' | ||
#' The following equation is employed to evaluate emissions originating from tyre | ||
#' and brake wear, respectively. | ||
#' | ||
#' TE(i) = dist x EF_tsp(j) x mf_s(i) x sc(speed) | ||
#' | ||
#' where: | ||
#' - TE(i) = total emissions of pollutant i [g], | ||
#' - dist = distance driven by each vehicle [km], | ||
#' - EF_tsp(j) = TSP mass emission factor for vehicles of category j [g/km], | ||
#' - mf_s(i) = mass fraction of TSP that can be attributed to particle size class i, | ||
#' - sc(speed) = correction factor for a mean vehicle travelling at a given speed [-]. | ||
#' | ||
#' *Tyre* | ||
#' | ||
#' In the case of heavy-duty vehicles, the emission factor needs the | ||
#' incorporation of vehicle size, as determined by the number of axles, and load. | ||
#' These parameters are introduced into the equation as follows: | ||
#' | ||
#' EF_tsp_tyre_hdv = 0.5 x N_axle x LCF_tyre x EF_tsp_tyre_pc | ||
#' | ||
#' where | ||
#' - EF_tsp_tyre_hdv = TSP emission factor for tyre wear from heavy-duty | ||
#' vehicles [g/km], | ||
#' - N_axle = number of vehicle axles [-], | ||
#' - LCF_t = a load correction factor for tyre wear [-], | ||
#' - EF_tsp_tyre_pc = TSP emission factor for tyre wear from passenger car | ||
#' vehicles [g/km]. | ||
#' | ||
#' and | ||
#' LCF_tyre = 1.41 + (1.38 x LF), | ||
#' | ||
#' where: | ||
#' - LF = load factor [-], ranging from 0 for an empty bus to 1 for a fully laden one. | ||
#' | ||
#' The function considers the following look-up table for number of vehicle axes: | ||
#' | ||
#' | vehicle class (j) | number of axes | | ||
#' | ------------------- | -------------- | | ||
#' | Ubus Midi <=15 t | 2 | | ||
#' | Ubus Std 15 - 18 t | 2 | | ||
#' | Ubus Artic >18 t | 3 | | ||
#' | Coaches Std <=18 t | 2 | | ||
#' | Coaches Artic >18 t | 3 | | ||
#' | ||
#' The size distribution of tyre wear particles are given by: | ||
#' | ||
#' | particle size class (i) | mass fraction of TSP | | ||
#' | ----------------------- | -------------------- | | ||
#' | TSP | 1.000 | | ||
#' | PM10 | 0.600 | | ||
#' | PM2.5 | 0.420 | | ||
#' | PM1.0 | 0.060 | | ||
#' | PM0.1 | 0.048 | | ||
#' | ||
#' Finally, the speed correction is: | ||
#' | ||
#' sc_tyre(speed) = 1.39, when V < 40 km/h; | ||
#' sc_tyre(speed) = -0.00974 x speed + 1.78, when 40 <= speed <= 90 km/h; | ||
#' sc_tyre(speed) = 0.902, when speed > 90 km/h. | ||
#' | ||
#' *Brake* | ||
#' | ||
#' The heavy-duty vehicle emission factor is derived by modifying the passenger | ||
#' car emission factor to conform to experimental data obtained from | ||
#' heavy-duty vehicles. | ||
#' | ||
#' EF_tsp_brake_hdv = 1.956 x LCF_brake x EF_tsp_brake_pc | ||
#' | ||
#' where: | ||
#' - EF_tsp_brake_hdv = heavy-duty vehicle emission factor for TSP, | ||
#' - LCF_brake = load correction factor for brake wear, | ||
#' - EF_tsp_brake_pc = passenger car emission factor for TSP, | ||
#' | ||
#' and | ||
#' LCF_brake = 1 + (0.79 x LF), | ||
#' | ||
#' where: | ||
#' - LF = load factor [-], ranging from 0 for an empty bus to 1 for a fully laden one. | ||
#' | ||
#' The size distribution of brake wear particles are given by: | ||
#' | ||
#' | particle size class (i) | mass fraction of TSP | | ||
#' | ----------------------- | -------------------- | | ||
#' | TSP | 1.000 | | ||
#' | PM10 | 0.980 | | ||
#' | PM2.5 | 0.390 | | ||
#' | PM1.0 | 0.100 | | ||
#' | PM0.1 | 0.080 | | ||
#' | ||
#' Finally, the speed correction is: | ||
#' | ||
#' sc_brake(speed) = 1.67, when V < 40 km/h; | ||
#' sc_brake(speed) = -0.0270 x speed + 2.75, when 40 <= speed <= 95 km/h; | ||
#' sc_brake(speed) = 0.185, when speed > 95 km/h. | ||
#' | ||
#' *Road Wear* | ||
#' | ||
#' Emissions are calculated according to the equation: | ||
#' | ||
#' TE(i) = dist x EF_tsp_road(j) x mf_road | ||
#' | ||
#' where: | ||
#' - TE = total emissions of pollutant i (g), | ||
#' - dist = total distance driven by vehicles in category j (km), | ||
#' - EF_tsp_road = TSP mass emission factor from road wear for vehicles j (0.0760 g/km), | ||
#' - mf_road = mass fraction of TSP that can be attributed to particle size | ||
#' class i (-). | ||
#' | ||
#' The following table shows the size distribution of road surface wear particles | ||
#' | ||
#' | particle size class (i) | mass fraction of TSP | | ||
#' | ----------------------- | -------------------- | | ||
#' | TSP | 1.00 | | ||
#' | PM10 | 0.50 | | ||
#' | PM2.5 | 0.27 | | ||
#' | ||
#' *References* | ||
#' | ||
#' #' EMEP/EEA data and reports can be accessed in the following links: | ||
#' - 2019 edition \url{https://www.eea.europa.eu/publications/emep-eea-guidebook-2019/part-b-sectoral-guidance-chapters/1-energy/1-a-combustion/1-a-3-b-vi/view}. | ||
#' | ||
#' @family Emission factor model | ||
#' | ||
#' @export | ||
#' | ||
#' @examples | ||
#' emi_europe_emep_wear(dist = units::set_units(1,"km"), | ||
#' speed = units::set_units(30,"km/h"), | ||
#' pollutant = c("PM10","TSP","PM2.5"), | ||
#' veh_type = c("Ubus Std 15 - 18 t","Ubus Artic >18 t"), | ||
#' fleet_composition = c(0.5,0.5), | ||
#' load = 0.5, | ||
#' process = c("brake","tyre","road"), | ||
#' as_list = TRUE) | ||
emi_europe_emep_wear <- function(dist,speed,pollutant,veh_type, | ||
fleet_composition,load = 0.5,process = "tyre",as_list = TRUE){ | ||
|
||
# dist = units::set_units(tp_model$dist, "km") | ||
# speed = units::set_units(tp_model$speed, "km/h") | ||
# pollutant = "PM10" | ||
# veh_type = my_fleet$veh_type | ||
# fleet_composition = my_fleet$fleet_composition | ||
# load = 0.5 | ||
# process = c("tyre","brake","road") | ||
# as_list = TRUE | ||
# check inputs ---------- | ||
# speed | ||
checkmate::assert_vector(speed,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_numeric(speed,lower = 1,upper = 130) | ||
checkmate::assert_class(speed,"units") | ||
if(units(speed)$numerator != "km" | units(speed)$denominator != "h"){ | ||
stop("Invalid 'speed' units: 'speed' needs to be in 'km/h' units.") | ||
} | ||
# dist | ||
checkmate::assert_vector(dist,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_numeric(dist,any.missing = FALSE,min.len = 1) | ||
checkmate::assert_class(dist,"units") | ||
if(units(dist)$numerator != "km"){ | ||
stop("Invalid 'dist' argument: 'units' should be in 'km'.") | ||
} | ||
# length dist and speed | ||
checkmate::check_true(length(speed) == length(dist),na.ok = FALSE) | ||
# veh_type | ||
checkmate::assert_vector(veh_type,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_class(veh_type,"character") | ||
names_veh <- c("Ubus Midi <=15 t","Ubus Std 15 - 18 t","Ubus Artic >18 t" | ||
,"Coaches Std <=18 t","Coaches Artic >18 t") | ||
for(i in veh_type) checkmate::assert_choice(i,names_veh) | ||
# process | ||
checkmate::assert_vector(process,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_class(process,"character") | ||
name_process <- c('tyre','brake','road') | ||
for(i in process) checkmate::assert_choice(i,name_process) | ||
# pollutant | ||
checkmate::assert_vector(pollutant,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_character(pollutant,any.missing = FALSE,min.len = 1) | ||
for(i in process){ | ||
if(i != "road"){ | ||
for(j in pollutant) checkmate::assert_choice(j,c('TSP','PM10','PM2.5','PM1.0','PM0.1'),null.ok = FALSE) | ||
}else{ | ||
for(j in pollutant) checkmate::assert_choice(j,c('TSP','PM10','PM2.5'),null.ok = FALSE) | ||
} | ||
} | ||
# fleet_composition | ||
checkmate::assert_vector(fleet_composition,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_numeric(fleet_composition,any.missing = FALSE,min.len = 1,lower = 0,upper = 1) | ||
# load factor | ||
checkmate::assert_vector(load,any.missing = FALSE,min.len = 1,null.ok = FALSE) | ||
checkmate::assert_numeric(load,lower = 0,upper = 1) | ||
checkmate::assert_class(load,"numeric") | ||
if(length(load) != 1){ | ||
checkmate::check_true(length(load) == length(dist),na.ok = FALSE) | ||
checkmate::check_true(length(load) == length(speed),na.ok = FALSE) | ||
} | ||
# as_list | ||
checkmate::assert_logical(as_list, any.missing = FALSE) | ||
|
||
# Adjust lengths | ||
# check lengths---- | ||
if(length(fleet_composition) != length(veh_type) && length(veh_type) == 1){ | ||
tmp_veh_type <- rep(veh_type,length(fleet_composition)) | ||
}else{ | ||
tmp_veh_type <- veh_type | ||
} | ||
# internal functions | ||
speed_cor_tw_f <- function(speed){ | ||
st <- vector(length = length(speed)) | ||
# interv. 1 | ||
st[speed < units::set_units(40,'km/h')] <- 1.39 | ||
# interv. 2 | ||
id_speed <- which(speed >= units::set_units(40,'km/h') & | ||
speed <= units::set_units(90,'km/h')) | ||
st[id_speed] <- -0.00974 * as.numeric(speed[id_speed]) + 1.78 | ||
# interv. 3 | ||
st[speed > units::set_units(90,'km/h')] <- 0.902 | ||
return(st) | ||
} | ||
speed_cor_bw_f <- function(speed){ | ||
sb <- vector(length = length(speed)) | ||
# interv. 1 | ||
sb[speed < units::set_units(40,'km/h')] <- 1.67 | ||
# interv. 2 | ||
id_speed <- which(speed >= units::set_units(40,'km/h') & | ||
speed <= units::set_units(95,'km/h')) | ||
sb[id_speed] <- -0.0270 * as.numeric(speed[id_speed]) + 2.75 | ||
# interv. 3 | ||
sb[speed > units::set_units(90,'km/h')] <- 0.185 | ||
return(sb) | ||
} | ||
# internal tables from EMEP | ||
# tyre wear | break wear | ||
size_class <- data.table::data.table("pol" = c('TSP','PM10','PM2.5','PM1','PM0.1') | ||
,"mf_tw" = c(1.000,0.600,0.420,0.060,0.048) | ||
,"mf_bw" = c(1.000,0.980,0.390,0.100,0.080) | ||
,"mf_rs" = c(1.000,0.500,0.270,NA ,NA )) | ||
# number of axles | ||
n_axle_table <- data.table::data.table(veh = c("Ubus Midi <=15 t" | ||
,"Ubus Std 15 - 18 t" | ||
,"Ubus Artic >18 t" | ||
,"Coaches Std <=18 t" | ||
,"Coaches Artic >18 t") | ||
,n_axle = c(2,2,3,2,3)) | ||
# emissions process | ||
emi_wear <- function(pollutant,process){ | ||
if(process == "tyre"){ | ||
# load correction factor | ||
lcf_tw <- 1.41 + 1.38 * load | ||
# number of axles | ||
n_axle <- n_axle_table[veh %in% tmp_veh_type,n_axle] | ||
# emission factor | ||
ef_tsp_pc_tw <- units::set_units(0.0107,'g/km') | ||
ef_tsp_bus_tw <- as.matrix(n_axle * fleet_composition) %*% t(lcf_tw * ef_tsp_pc_tw * 0.5) | ||
ef_tsp_bus_tw <- t(ef_tsp_bus_tw) | ||
# mass fraction | ||
mass_tw <- size_class[pol %in% pollutant,mf_tw] | ||
# speed correction | ||
speed_cor_tw <- speed_cor_tw_f(speed) | ||
# emission | ||
tmp1 <- (dist * speed_cor_tw) %*% as.matrix(t(mass_tw)) | ||
tmp2 <- lapply(1:ncol(ef_tsp_bus_tw),function(i){ef_tsp_bus_tw[,i] * tmp1}) | ||
tmp_emi <- do.call(cbind,tmp2) | ||
tmp_emi <- units::set_units(tmp_emi,"g") | ||
} | ||
if(process == "brake"){ | ||
# load factor | ||
lcf_bw <- 1.00 + 0.79 * load | ||
# mass fraction | ||
mass_bw <- size_class[pol %in% pollutant,mf_bw] | ||
# emission factor | ||
ef_tsp_pc_bw <- 0.0075 # g/km | ||
ef_tsp_bus_bw <- 1.956 * lcf_bw * ef_tsp_pc_bw | ||
#ef_tsp_bus_bw <- units::set_units(ef_tsp_bus_bw,'g/km') | ||
# speed corrections | ||
speed_cor_bw <- speed_cor_bw_f(speed) | ||
# emission | ||
tmp_emi <- as.matrix(ef_tsp_bus_bw) %*% as.matrix(t((fleet_composition * mass_bw))) | ||
tmp2 <- as.matrix(dist) * speed_cor_bw | ||
tmp3 <- lapply(1:ncol(tmp_emi),function(i){tmp2 %*% tmp_emi[,i]}) | ||
tmp3 <- do.call(cbind,tmp3) | ||
tmp_emi <- units::set_units(tmp3,"g") | ||
} | ||
if(process == "road"){ | ||
ef_tsp_bus_rs <- units::set_units(0.0760,'g/km') | ||
# emission factor - urban bus | ||
mass_rs <- size_class[pol == pollutant,mf_rs] | ||
# emission | ||
tmp_emi <- dist * ef_tsp_bus_rs * mass_rs | ||
tmp_emi <- as.matrix(tmp_emi) %*% as.matrix(t(fleet_composition)) | ||
tmp_emi <- units::set_units(tmp_emi,"g") | ||
} | ||
tmp_emi <- data.table::as.data.table(tmp_emi) | ||
names(tmp_emi) <- paste0(pollutant,"_",process,"_veh_",1:ncol(tmp_emi)) | ||
return(tmp_emi) | ||
} | ||
tmp_emi <- lapply(process,function(i){ # i = "brake" | ||
tmp_emi1 <- lapply(pollutant,emi_wear,i) | ||
tmp_emi1 <- do.call(cbind,tmp_emi1) | ||
return(tmp_emi1) | ||
}) | ||
tmp_emi <- do.call(cbind,tmp_emi) | ||
|
||
# names(tmp_emi) | ||
|
||
if(as_list){ | ||
# local test | ||
emi_final <- list("pollutant" = pollutant, | ||
"veh_type" = veh_type, | ||
"fleet_composition" = fleet_composition, | ||
"speed" = units::set_units(speed,"km/h"), | ||
"dist" = units::set_units(dist,"km"), | ||
"emi" = tmp_emi, | ||
"process" = process) | ||
}else{ | ||
emi_final <- tmp_emi | ||
} | ||
return(emi_final) | ||
} |
Oops, something went wrong.