From 151ca4bd65d947e181468034aef73931b51540ba Mon Sep 17 00:00:00 2001 From: Mengqi Zhao Date: Tue, 16 Jul 2024 18:13:25 -0700 Subject: [PATCH] Add capability to calculate pop-weighted hdcd at electricity interconnection level (WECC, ERCOT, EI) --- DESCRIPTION | 2 +- R/data.R | 14 +++++++ R/diagnostics.R | 24 +++++++++++- R/format_temperature.R | 4 +- R/hdcd.R | 53 +++++++++++++++++++++------ R/process_population.R | 13 ++++++- data/mapping_states_interconnect.rda | Bin 0 -> 378 bytes inst/extras/dev_tests.R | 22 ++++++++--- inst/extras/saveDataFiles.R | 16 ++++++++ man/format_temperature.Rd | 2 +- man/hdcd.Rd | 5 ++- man/helios.Rd | 20 ++++++++++ man/mapping_states_interconnect.Rd | 25 +++++++++++++ man/process_population.Rd | 5 ++- 14 files changed, 179 insertions(+), 26 deletions(-) create mode 100644 data/mapping_states_interconnect.rda create mode 100644 man/mapping_states_interconnect.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 42242bd..230a742 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,4 +47,4 @@ Remotes: Config/testthat/edition: 3 Encoding: UTF-8 LazyData: true -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 diff --git a/R/data.R b/R/data.R index 44b4bdf..8503f03 100644 --- a/R/data.R +++ b/R/data.R @@ -238,6 +238,20 @@ #' } "mapping_states_gridregion" +#-------------------------------- +# State to Electricity Interconnection Mapping +#-------------------------------- +#' mapping_states_interconnect +#' +#' @source electricity trade update from Matthew Binsted +#' @format tibble::tribble +#' @examples +#' \dontrun{ +#' library(helios); +#' mapping_states_interconnect <- helios::mapping_states_interconnect +#' } +"mapping_states_interconnect" + #................................. # Pre-processed Population Files diff --git a/R/diagnostics.R b/R/diagnostics.R index 3b28594..6bc7768 100644 --- a/R/diagnostics.R +++ b/R/diagnostics.R @@ -66,7 +66,7 @@ diagnostics <- function(hdcd_segment = tibble::tibble(), # calculate the number of hours in each segment by state segment_hours <- helios::segment_map_utc %>% dplyr::group_by(subRegion, segment) %>% - dplyr::summarise(segment_hours = n()) %>% + dplyr::summarise(segment_hours = dplyr::n()) %>% dplyr::ungroup() if(any(grepl('grid', unique(hdcd_segment$subRegion)))) { @@ -77,11 +77,31 @@ diagnostics <- function(hdcd_segment = tibble::tibble(), dplyr::rename(subRegion = grid_region) %>% dplyr::distinct() } + + if(any(grepl('WECC', unique(hdcd_segment$subRegion)))) { + # calculate the number of hours in each segment by electricity interconnection region + # if at electricity interconnection level, select Central Northeast grid region (e.g., Montana) as the + # Eastern interconnection's segment time + # Note: The eastern interconnection is not suppose to be used in GO-CERF-GO (WECC is the one to be used) + segment_hours_temp <- segment_hours %>% + dplyr::filter(subRegion == 'MO') %>% + dplyr::mutate(subRegion = 'EI') + + segment_hours <- segment_hours %>% + dplyr::left_join(helios::mapping_states_interconnect, by = 'subRegion') %>% + dplyr::select(-subRegion) %>% + dplyr::distinct() %>% + dplyr::rename(subRegion = grid_region) %>% + dplyr::filter(!subRegion == 'EI') %>% + dplyr::bind_rows(segment_hours_temp) + + } + } else { segment_hours <- segment_map %>% dplyr::group_by(subRegion, year, segment) %>% - dplyr::summarise(segment_hours = n()) %>% + dplyr::summarise(segment_hours = dplyr::n()) %>% dplyr::ungroup() } diff --git a/R/format_temperature.R b/R/format_temperature.R index ae8fac2..2b19db1 100644 --- a/R/format_temperature.R +++ b/R/format_temperature.R @@ -6,7 +6,7 @@ #' @param ncdf_grid Default = NULL. output from process_temperature. #' @param model Default = NULL. String for climate model that generates the ncdf file. Options: 'wrf' or 'cmip'. #' @param time_periods Default = NULL. Integer vector for selected time periods to process. If not specified, set to GCAM periods seq(2020, 2100, 5). -#' @param to_year Default = NULL. Integer for the time step the design year/representative year is for. +#' @param to_year Default = NULL. Integer for renaming the time step the design year/representative year is for. #' @importFrom magrittr %>% #' @importFrom data.table := #' @export @@ -32,7 +32,7 @@ format_temperature <- function(ncdf_grid = NULL, ncdf_times_update <- gsub(years, to_year, ncdf_times) ncdf_grid <- ncdf_grid %>% - dplyr::rename_at(vars(ncdf_times), ~ ncdf_times_update) + dplyr::rename_at(dplyr::vars(ncdf_times), ~ ncdf_times_update) ncdf_times <- ncdf_times_update diff --git a/R/hdcd.R b/R/hdcd.R index 5f3978f..d79f58f 100644 --- a/R/hdcd.R +++ b/R/hdcd.R @@ -19,6 +19,7 @@ #' @param im3_analysis Default = T. Output annual HDCD at grid region scale for trend-representative year analysis #' @param elec_share Default = NULL. data frame for the fraction of building heating and cooling energy consumption met by electricity at grid region scale. Column [subRegion, year, HDCD, elec_frac]. If elec_share is provided, helios will recalculate the super peak hours; Otherwise, helios will use the default super peak hours. Note, to get the correct super peak hours, the ncdf argument should include all files that cover full years. #' @param to_year Default = NULL. Integer for the time step the design year/representative year is for. +#' @param use_elec_interconnect Default = F. Set to TRUE to output degree-days and degree-hours at electricity interconnection level (instead of grid region level). IM3 analysis enabled only. #' @importFrom magrittr %>% #' @importFrom data.table := #' @export @@ -39,7 +40,8 @@ hdcd <- function(ncdf = NULL, save = T, im3_analysis = T, elec_share = NULL, - to_year = NULL) { + to_year = NULL, + use_elec_interconnect = F) { print('Starting function process_hdcd...') @@ -177,7 +179,8 @@ hdcd <- function(ncdf = NULL, time_periods = time_periods, climate_years = years, spatial = spatial, - im3_analysis = im3_analysis) + im3_analysis = im3_analysis, + use_elec_interconnect = use_elec_interconnect) population_j_weighted <- pop_list$population_weighted population_j_weighted_gridregion <- pop_list$population_weighted_gridregion @@ -207,8 +210,15 @@ hdcd <- function(ncdf = NULL, # for IM3 grid region analysis if(im3_analysis){ + if(use_elec_interconnect){ + mapping_elec_subregion <- helios::mapping_states_interconnect + } else { + mapping_elec_subregion <- helios::mapping_states_gridregion + } + + ncdf_pivot_gridregion <- ncdf_pivot %>% - dplyr::left_join(helios::mapping_states_gridregion, by = 'subRegion') %>% + dplyr::left_join(mapping_elec_subregion, by = 'subRegion') %>% dplyr::mutate(subRegion = grid_region, ID = grid_region) %>% dplyr::select(-grid_region) @@ -311,7 +321,7 @@ hdcd <- function(ncdf = NULL, dplyr::select(grid_region = subRegion, year, HDCD, elec_frac) # for state level calculation - elec_share_region <- helios::mapping_states_gridregion %>% + elec_share_region <- mapping_elec_subregion %>% dplyr::left_join(elec_share_region, by = c('grid_region')) %>% dplyr::select(subRegion, year, HDCD, elec_frac) @@ -430,11 +440,32 @@ hdcd <- function(ncdf = NULL, dplyr::select(subRegion, year, HDCD, elec_frac) # segment map for grid regions - segment_map_utc_no_superpeak_gridregion <- helios::segment_map_utc_no_superpeak %>% - dplyr::left_join(helios::mapping_states_gridregion, by = 'subRegion') %>% - dplyr::select(-subRegion) %>% - dplyr::distinct() %>% - dplyr::rename(subRegion = grid_region) + if(use_elec_interconnect){ + # if at electricity interconnection level, select Central Northeast grid region (e.g., Montana) as the + # Eastern interconnection's segment time + # Note: The eastern interconnection is not suppose to be used in GO-CERF-GO (WECC is the one to be used) + segment_map_utc_no_superpeak_gridregion_temp <- helios::segment_map_utc_no_superpeak %>% + dplyr::filter(subRegion == 'MO') %>% + dplyr::mutate(subRegion = 'EI') + + segment_map_utc_no_superpeak_gridregion <- helios::segment_map_utc_no_superpeak %>% + dplyr::left_join(mapping_elec_subregion, by = 'subRegion') %>% + dplyr::select(-subRegion) %>% + dplyr::distinct() %>% + dplyr::rename(subRegion = grid_region) %>% + dplyr::filter(!subRegion == 'EI') %>% + dplyr::bind_rows(segment_map_utc_no_superpeak_gridregion_temp) + + } else { + + segment_map_utc_no_superpeak_gridregion <- helios::segment_map_utc_no_superpeak %>% + dplyr::left_join(mapping_elec_subregion, by = 'subRegion') %>% + dplyr::select(-subRegion) %>% + dplyr::distinct() %>% + dplyr::rename(subRegion = grid_region) + + } + # calculate the HDCD hdcd_gridregion_segments <- hdcd_gridregion %>% @@ -465,7 +496,7 @@ hdcd <- function(ncdf = NULL, # segment map for grid regions segment_map_utc_gridregion <- helios::segment_map_utc %>% - dplyr::left_join(helios::mapping_states_gridregion, by = 'subRegion') %>% + dplyr::left_join(mapping_elec_subregion, by = 'subRegion') %>% dplyr::select(-subRegion) %>% dplyr::distinct() %>% dplyr::rename(subRegion = grid_region) @@ -532,7 +563,7 @@ hdcd <- function(ncdf = NULL, # create building service structure for grid region L2441.HDDCDD_Fixed_gcamusa_seg_gridregion <- helios::L2441.HDDCDD_Fixed_gcamusa_seg %>% - dplyr::left_join(helios::mapping_states_gridregion, by = 'subRegion') %>% + dplyr::left_join(mapping_elec_subregion, by = 'subRegion') %>% dplyr::select(-subRegion) %>% dplyr::rename(subRegion = grid_region) %>% dplyr::distinct() diff --git a/R/process_population.R b/R/process_population.R index 02ce4bf..a7ddcc2 100644 --- a/R/process_population.R +++ b/R/process_population.R @@ -8,6 +8,7 @@ #' @param climate_years Default = NULL. Integer vector of years that is covered by the climate data to check if the population years overlap with the climate years. If Null, skip the check. #' @param spatial Default = NULL. String for spatial aggregation boundaries. Options: check helios::spatial_options. 'gcam_us49', 'gcam_regions32', 'gcam_regions31_us52', 'gcam_countries', 'gcam_basins'. #' @param im3_analysis Default = TRUE. Output annual HDCD at grid region scale for trend-representative year analysis +#' @param use_elec_interconnect Default = F. Set to TRUE to output degree-days and degree-hours at electricity interconnection level (instead of grid region level). IM3 analysis enabled only. #' @importFrom magrittr %>% #' @importFrom data.table := #' @export @@ -17,7 +18,8 @@ process_population <- function(population = NULL, time_periods = NULL, climate_years = NULL, spatial = NULL, - im3_analysis = TRUE){ + im3_analysis = TRUE, + use_elec_interconnect = FALSE){ if (im3_analysis) { @@ -96,8 +98,15 @@ process_population <- function(population = NULL, # for IM3 grid region analysis if(im3_analysis){ + + if(use_elec_interconnect){ + mapping_elec_subregion <- helios::mapping_states_interconnect + } else { + mapping_elec_subregion <- helios::mapping_states_gridregion + } + population_weighted_gridregion <- population_grid %>% - dplyr::left_join(helios::mapping_states_gridregion, by = 'subRegion') %>% + dplyr::left_join(mapping_elec_subregion, by = 'subRegion') %>% dplyr::mutate(subRegion = grid_region, ID = grid_region) %>% dplyr::select(-grid_region) %>% diff --git a/data/mapping_states_interconnect.rda b/data/mapping_states_interconnect.rda new file mode 100644 index 0000000000000000000000000000000000000000..488711139381dccdde6e56e38e10546eb1184d42 GIT binary patch literal 378 zcmV-=0fqiTT4*^jL0KkKSr{=8aR35tf5iSeX$SxV2tY6Y-|)Yu-he;=00IC3umM`z zWQ3xprV~_eTodF&0uK5BGDmP1wV#KM_jSY67r)Con*1??n~(k% dplyr::filter(scenario == 'rcp85hotter_ssp5') +# for electricity interconnection +elec_share <- data.table::fread( + 'C:/WorkSpace/IM3/helios/hddcdd/constance/output/im3_bldg_hdcd_electricity_intensity_interconnection.csv') %>% + dplyr::filter(scenario == 'rcp85hotter_ssp5') + # test file list # path_to_climate_ncdf <- c( # helios::pkg_example('wrfout_d01_2020-01-01_01%3A00%3A00_sub.nc'), @@ -175,11 +182,12 @@ hdcd_wrf_all <- helios::hdcd( folder = file.path(getwd(), 'output_im3_test'), diagnostics = F, xml = F, - name_append = '', + name_append = 'interconnection', save = T, im3_analysis = T, elec_share = elec_share, - to_year = NULL + to_year = NULL, + use_elec_interconnect = T ) helios::diagnostics( @@ -187,7 +195,7 @@ helios::diagnostics( hdcd_monthly = hdcd_wrf_all$hdcd_comb_monthly, min_diagnostic_months = 1, folder = file.path(getwd(), 'output_im3_test'), - name_append = 'wrf_all' + name_append = 'interconnection' ) @@ -208,6 +216,10 @@ ncdf_grid <- helios::read_ncdf(ncdf = path_to_climate_ncdf, time_periods = 2020) population_j_grid <- helios::read_population(path_to_population, time_periods = 2020) +ncdf_format <- helios::format_temperature(ncdf_grid = ncdf_grid, + model = 'cmip', + to_year = NULL)$ncdf_pivot + hdcd_cmip_all <- helios::hdcd( ncdf = path_to_climate_ncdf, ncdf_var = 'tas', diff --git a/inst/extras/saveDataFiles.R b/inst/extras/saveDataFiles.R index ec93e6d..ae093e8 100644 --- a/inst/extras/saveDataFiles.R +++ b/inst/extras/saveDataFiles.R @@ -437,3 +437,19 @@ mapping_states_gridregion <- data.table::fread( dplyr::select(subRegion = state, grid_region) usethis::use_data(mapping_states_gridregion, version = 3, overwrite = T) + + +#-------------------------------- +# State to Grid Region Mapping +#-------------------------------- +# read state to grid region mapping from gcamdata +mapping_states_interconnect <- data.table::fread( + file.path('C:/WorkSpace/github/helios/inst/extras/GCAM-USA_interconnections.csv')) %>% + dplyr::left_join(rmap::mapUS52 %>% tibble::as_tibble() %>% dplyr::select(state_name = subRegionAlt, state = subRegion), + by = 'state_name') %>% + dplyr::mutate(interconnect = ifelse(interconnect == 'n/a', NA, interconnect), + interconnect = ifelse(interconnect == 'Eastern Interconnection', 'EI', interconnect), + interconnect = ifelse(is.na(interconnect), state, interconnect)) %>% + dplyr::select(subRegion = state, grid_region = interconnect) + +usethis::use_data(mapping_states_interconnect, version = 3, overwrite = T) diff --git a/man/format_temperature.Rd b/man/format_temperature.Rd index edcd929..6dcb89c 100644 --- a/man/format_temperature.Rd +++ b/man/format_temperature.Rd @@ -18,7 +18,7 @@ format_temperature( \item{time_periods}{Default = NULL. Integer vector for selected time periods to process. If not specified, set to GCAM periods seq(2020, 2100, 5).} -\item{to_year}{Default = NULL. Integer for the time step the design year/representative year is for.} +\item{to_year}{Default = NULL. Integer for renaming the time step the design year/representative year is for.} } \description{ Format gridded temperature data and pivot it longer diff --git a/man/hdcd.Rd b/man/hdcd.Rd index cbfdbd9..6fd5c2e 100644 --- a/man/hdcd.Rd +++ b/man/hdcd.Rd @@ -21,7 +21,8 @@ hdcd( save = T, im3_analysis = T, elec_share = NULL, - to_year = NULL + to_year = NULL, + use_elec_interconnect = F ) } \arguments{ @@ -58,6 +59,8 @@ hdcd( \item{elec_share}{Default = NULL. data frame for the fraction of building heating and cooling energy consumption met by electricity at grid region scale. Column [subRegion, year, HDCD, elec_frac]. If elec_share is provided, helios will recalculate the super peak hours; Otherwise, helios will use the default super peak hours. Note, to get the correct super peak hours, the ncdf argument should include all files that cover full years.} \item{to_year}{Default = NULL. Integer for the time step the design year/representative year is for.} + +\item{use_elec_interconnect}{Default = F. Set to TRUE to output degree-days and degree-hours at electricity interconnection level (instead of grid region level). IM3 analysis enabled only.} } \description{ Heating and Cooling Degree processing for GCAM from various sources such as WRF and CMIP diff --git a/man/helios.Rd b/man/helios.Rd index 0e9acf3..662fc80 100644 --- a/man/helios.Rd +++ b/man/helios.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/helios.R \docType{package} \name{helios} +\alias{helios-package} \alias{helios} \title{helios} \description{ @@ -12,3 +13,22 @@ Heating and Cooling Degree processing for GCAM from various sources such as WRF \item Github: https://github.com/JGCRI/helios \item Webpage: https://jgcri.github.io/helios} } +\seealso{ +Useful links: +\itemize{ + \item \url{https://github.com/JGCRI/helios} + \item Report bugs at \url{https://github.com/JGCRI/helios/issues} +} + +} +\author{ +\strong{Maintainer}: Mengqi Zhao \email{mengqi.zhao@pnnl.gov} (\href{https://orcid.org/0000-0001-5385-2758}{ORCID}) + +Authors: +\itemize{ + \item Zarrar Khan \email{zarrar.khan@pnnl.gov} (\href{https://orcid.org/0000-0002-8147-8553}{ORCID}) + \item Kalyn Dorheim (\href{https://orcid.org/0000-0001-8093-8397}{ORCID}) + \item Chris Vernon (\href{https://orcid.org/0000-0002-3406-6214}{ORCID}) +} + +} diff --git a/man/mapping_states_interconnect.Rd b/man/mapping_states_interconnect.Rd new file mode 100644 index 0000000..77c7293 --- /dev/null +++ b/man/mapping_states_interconnect.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{mapping_states_interconnect} +\alias{mapping_states_interconnect} +\title{mapping_states_interconnect} +\format{ +tibble::tribble +} +\source{ +electricity trade update from Matthew Binsted +} +\usage{ +mapping_states_interconnect +} +\description{ +mapping_states_interconnect +} +\examples{ +\dontrun{ + library(helios); + mapping_states_interconnect <- helios::mapping_states_interconnect +} +} +\keyword{datasets} diff --git a/man/process_population.Rd b/man/process_population.Rd index 6238555..943b437 100644 --- a/man/process_population.Rd +++ b/man/process_population.Rd @@ -10,7 +10,8 @@ process_population( time_periods = NULL, climate_years = NULL, spatial = NULL, - im3_analysis = TRUE + im3_analysis = TRUE, + use_elec_interconnect = FALSE ) } \arguments{ @@ -25,6 +26,8 @@ process_population( \item{spatial}{Default = NULL. String for spatial aggregation boundaries. Options: check helios::spatial_options. 'gcam_us49', 'gcam_regions32', 'gcam_regions31_us52', 'gcam_countries', 'gcam_basins'.} \item{im3_analysis}{Default = TRUE. Output annual HDCD at grid region scale for trend-representative year analysis} + +\item{use_elec_interconnect}{Default = F. Set to TRUE to output degree-days and degree-hours at electricity interconnection level (instead of grid region level). IM3 analysis enabled only.} } \description{ Process population and output standard population structure given the spatial scale