Parametric simulation using eplurs #550
-
Hi, I want to ask a few questions regarding 'eplusr' in R. I want to perform parametric simulations with parameters such as: Orientation [0:45:360] How can I perform this using 'eplusr' in R? Once this is done and I have the dataset, I plan to perform sensitivity analysis to determine the influential parameters impacting various outputs such as: Zone-wise annual heating consumption Is there a way I can create a single csv file with all ranges of input parameters and corresponding output using eplur? Please guide me with some recommendations. Thanks for your help. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 14 replies
-
Hi @divyanshusood. eplusr has a dedicated vignette about parametric simulation. I would like you to first read through it to get a whole picture of how to perform parametric simulations. Basically you wrap your steps of modifying the IDF in a function (I call it a
Yes, you can. Let's say func <- function(orient, shgc, hgsp) {
...
}
csv <- read.csv(PATH_CSV)
param$apply_measure(
func,
orient = csv$orient,
shgc = csv$shgc,
hgsp = csv$hgsp
) |
Beta Was this translation helpful? Give feedback.
-
Hi Hongyuanjia, > create_schedules_for_all_profiles(idf_base_path, file_path, new_names_househousehold)
Error in `map()`:
ℹ In index: 41.
Caused by error in `fread()`:
! skip=5 but the input only has 2 lines
Run `rlang::last_trace()` to see where the error occurred. _code below this line library(eplusr)
library(purrr)
library(data.table)
library(lubridate)
library(hms)
read_sch_data <- function(path, profile_col, na = 0.0) {
meta <- fread(path, nrows = 5)
month <- as.integer(meta[1, 2])
num <- as.integer(meta[2, 2])
type <- meta[3, 2]
weekday <- meta[4, 2]
# Read the actual schedule data, skipping metadata
data <- fread(path, skip = 5)
# Get column names dynamically
col_names <- names(data)
# Ensure the correct column is selected based on profile_col index
if (length(col_names) < profile_col) {
stop("Profile column index exceeds number of columns in data.")
}
time_col_name <- col_names[1] # First column for time
profile_col_name <- col_names[profile_col] # Dynamically choose profile column
# Extract and rename selected columns
selected_data <- data[, .(Time = get(time_col_name), Profile = get(profile_col_name))]
selected_data[, Time := as.character(Time)]
selected_data[, Time := as_hms(Time)]
# Calculate interval assuming times are in 'HH:MM:SS' format
interval <- as.numeric(diff(as.POSIXct(selected_data$Time[1:2], format = "%H:%M:%S"))) / 60
return(list(month = month, num = num, type = type, weekday = weekday, interval = interval, data = selected_data))
}
create_sch_weekly <- function(idf, name, list_days) {
WEEKDAY <- c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" )
# stop if any weekday data is missing
if (any(mis_wd <- !WEEKDAY %in% names(list_days))) {
stop("Missing schedule for weekday [", paste(WEEKDAY[mis_wd], collapse = ", "), "]")
}
# create a "AlwaysOff" for weekends, design days and other days
# adjust this as you need
if (!idf$is_valid_class("Schedule:Day:Interval") ||
!idf$is_valid_name("AlwaysOff", "Schedule:Day:Interval")) {
idf$add(Schedule_Day_Interval = list("AlwaysOff", "On/Off", "No", "Until: 24:00", 0))
}
# create a daily schedule
idf$add(
Schedule_Week_Daily = list(
name,
list_days$Sunday$name(),
list_days$Monday$name(),
list_days$Tuesday$name(),
list_days$Wednesday$name(),
list_days$Thursday$name(),
list_days$Friday$name(),
list_days$Saturday$name(),
"AlwaysOff",
"AlwaysOff",
"AlwaysOff",
"AlwaysOff",
"AlwaysOff"
)
)[[1L]]
}
create_sch_yearly <- function(idf, name, list_months, type_limits = "Any number") {
# get the start and end day for each month
start <- lubridate::ymd("2022-01-01") + months(0:11)
end <- lubridate::rollforward(start)
# combine start day, end day and month schedules
data <- data.table::data.table(
index = seq(12),
start = start, end = end,
sch = purrr::map(list_months, ~.$name())
)
# get the start and end day field value
data[, `:=`(
start_month = as.list(lubridate::month(start)),
start_day = as.list(lubridate::mday(start)),
end_month = as.list(lubridate::month(end)),
end_day = as.list(lubridate::mday(end))
)]
# remove original start and end column since not needed
data[, `:=`(start = NULL, end = NULL)]
# melt the data based on index column
m <- data.table::melt.data.table(data, "index")
data.table::setorderv(m, "index")
idf$add(
Schedule_Year = as.list(c(name, type_limits, m$value))
)[[1L]]
}
# Function to create weekly and yearly schedules in the IDF
create_sch_weekly <- function(idf, name, list_days) { ... }
create_sch_yearly <- function(idf, name, list_months, type_limits = "Any number") { ... }
# Function to create schedules for all profiles
create_schedules_for_all_profiles <- function(idf_base_path, file_path, new_names) {
sample_file <- list.files(file_path, pattern = "\\.csv$", full.names = TRUE)[1]
sample_data <- fread(sample_file, nrows = 1)
num_profiles <- ncol(sample_data) - 1
for (profile_col in 2:(num_profiles + 1)) {
idf <- read_idf(idf_base_path)
sch_data <- map(list.files(file_path, pattern = "accom_apt_month[0-9]+_day.*\\.csv$", full.names = TRUE), read_sch_data, profile_col = profile_col, na = 0)
# Save a new IDF for each profile set
idf_save_path <- sprintf("%s/Dublin_Apartment_Profile_Set_%d.idf", file_path, profile_col - 1)
idf$save(path = idf_save_path, copy_external = TRUE)
}
}
idf_base_path <- "~/Documents/RQ-3_journal/DeterministicAnalysis/EnergyPlus_Models/Apartment/Apartment_all_idf/Dublin_Apartment_4occ.idf"
file_path <- "~/Documents/RQ-3_journal/DeterministicAnalysis/newtrial/1occ/apt"
new_names_household <- c("jan_house", "feb_house", "mar_house", "april_house", "may_house", "june_house", "july_house", "aug_house", "sept_house", "oct_house", "nov_house", "dec_house")
create_schedules_for_all_profiles(idf_base_path, file_path, new_names_househousehold) |
Beta Was this translation helpful? Give feedback.
Hi @divyanshusood. eplusr has a dedicated vignette about parametric simulation. I would like you to first read through it to get a whole picture of how to perform parametric simulations. Basically you wrap your steps of modifying the IDF in a function (I call it a
measure
in eplusr) and pass it toParametricJob$apply_measure()
.Yes, you can. Let's say
func
is your measure function which takes three arguments, i.e. orientation (orient
), SHGC (shgc
) and Heating setpoint (hgsp
). You can do whatever you want to generate values for those arguments, of cause, including readi…