hongyuanjia / epluspar

Conduct parametric analysis on EnergyPlus models in R
https://hongyuanjia.github.io/epluspar
Other
9 stars 0 forks source link

Error encountered while trying to run a simple optimization problem with Epluspar R package #22

Closed mdakyen closed 4 years ago

mdakyen commented 4 years ago

Hello @hongyuanjia I have read your publication titled: eplusr: A framework for integrating building energy simulation and data-driven analytics. I tried to run a simply optimization problem to help me understand Epluspar R package much better, but I kept encountering an error. I selected only one parameter for my optimization, which is the wall insulation, to be varied from 1cm to 6cm. My objective function is to minimize Energy Per Conditioned Building Area [kWh/m2].

Here is the modified listing I tried to run:

#load packages
library(eplusr)
library(tidyverse) # for data-driven analysis
library(epluspar)

# read IDF
idf <- read_idf(system.file("extdata/1D 2F.idf", package = "eplusr"))

# read EPW
path_epw <- file.path(eplus_config(8.9)$dir, "WeatherData/Nicosia_hour.epw")
epw <- read_epw(path_epw)

# create a GA optimization job
ga <- gaoptim_job(idf, epw)

#Optimization variables#
# define a measure to change the insulation thickness of the exterior wall
set_insulation <- function (idf, thickness) {
  idf$set(`polystyrene eps (5 cm)` = list(thickness = thickness))
  idf
}

# combine measures into one
design_options <- function (idf,insulation_thickness) { 
  idf <- set_insulation(idf, insulation_thickness) 
  idf
}    

# specify design space of parameters 
ga$apply_measure(design_options,insulation_thickness = float_space(0.01, 0.06,0.01))

# define an objective function to  energy per conditioned building area
primary_energy <- function (idf) {
  as.double(idf$last_job()$tabular_data( 
    report_name = "Site and Source Energy", 
    row_name = "Total Site Energy",
    column_name = "Energy Per Conditioned Building Area [kWh/m2]" )
    $value) 
}

# set optimization objectives 
ga$objective(primary_energy,.n=NULL, .dir = "min")

# specify how to mix solutions 
ga$recombinator()
# specify how to change parts of one solution randomly 
ga$mutator()
# specify how to select best solutions 
ga$selector()
# specify the conditions when to terminate the computation 
ga$terminator(max_gen = 100L)

# run optimization 
ga$run(mu = 20)

# get all population 
population <- ga$population()
# get Pareto set 
pareto <- ga$pareto_set()

Here is the error I kept encountered when I tried to run it:

> # run optimization 
> ga$run(mu = 20)
-- Initialization --------------------------------------------------------------
  * Create initial population
Checking if parameter(s) has been set ...
Checking if objective(s) has been set ...
Validating parameter function 'design_options' ...
Validating objective function(s)...
Error: Idf has been modified since read or last saved. Please save it using `$save()` before running.
>
hongyuanjia commented 4 years ago

@mdakyen Thanks for reporting this bug. It should have been fixed via #23. Please try it by installing the latest version: remotes::install_github("hongyuanjia/epluspar")

There is something wrong with your code also.

1. system.file only gives you the file distributed with pacakge you specified

idf <- read_idf(system.file("extdata/1D 2F.idf", package = "eplusr")) 

2. You can directly give the paths of IDF and EPW to gaoptim_job(), if you do not need to manipulate them in advance.

path_idf <- system.file("extdata/1ZoneUncontrolled.idf", package = "eplusr")
path_epw <- file.path(eplus_config(9.2)$dir, "WeatherData/USA_CA_San.Francisco.Intl.AP.724940_TMY3.epw")
ga <- gaoptim_job(path_idf, path_epw)

3. Your specification of tabular table is not right:

primary_energy <- function (idf) {
  as.double(idf$last_job()$tabular_data( 
    report_name = "Site and Source Energy", 
    row_name = "Total Site Energy",
    column_name = "Energy Per Conditioned Building Area [kWh/m2]" )
    $value) 
}

image

"Site and Source Energy" is the table name, not report name. The correct report name is "AnnualBuildingUtilityPerformanceSummary" (note there is no spacing compared to the one shown in HTML). The column name should be given without units, i.e. "Energy Per Conditioned Building Area".

The correct one will be:

primary_energy <- function (idf) {
  as.double(idf$last_job()$tabular_data( 
    report_name = "AnnualBuildingUtilityPerformanceSummary",
    table_name = "Site and Source Energy",
    row_name = "Total Site Energy",
    column_name = "Energy Per Conditioned Building Area")
    $value) 
}

Please let me know if you still encounter errors.

mdakyen commented 4 years ago

Good day @hongyuanjia , thank you so much for your swift responses to my issues. I have followed the suggestions you made earlier on. Now am faced with a different error. Please can you help me resolve this error. Bellow is my code:

#load packages
library(eplusr)
library(tidyverse) # for data-driven analysis
library(epluspar)

# read file
idf <- read_idf(system.file("extdata/1D 2F.idf", package = "eplusr"))

# read file paths
path_idf <- system.file("extdata/1D 2F.idf", package = "eplusr")
path_epw <- file.path(eplus_config(8.9)$dir, "WeatherData/Nicosia_hour.epw")

ga <- gaoptim_job(path_idf, path_epw)

#define a measure to change the insulation thickness of the exterior wall
set_insulation <- function (idf, thickness) {
  idf$set(.("polystyrene eps (5 cm)") := list(Thickness = thickness))
  idf
}

# combine all measures into one
design_options <- function (idf,insulation_thickness) { 
  idf <- set_insulation(idf, insulation_thickness) 
  idf
}

# specify design space of parameters 
ga$apply_measure(design_options,insulation_thickness = float_space(0.01, 0.06,0.01))

primary_energy <- function (idf) {
  as.double(idf$last_job()$tabular_data( 
    report_name = "AnnualBuildingUtilityPerformanceSummary",
    table_name = "Site and Source Energy",
    row_name = "Total Site Energy",
    column_name = "Energy Per Conditioned Building Area")
    $value) 
}

# set optimization objectives 
ga$objective(primary_energy, .dir = "min")

# specify how to mix solutions 
ga$recombinator()
# specify how to change parts of one solution randomly 
ga$mutator()
# specify how to select best solutions 
ga$selector()
# specify the conditions when to terminate the computation 
ga$terminator(max_gen = 100L)

# run optimization 
ga$run(mu = 20)

# get all population 
population <- ga$population()
# get Pareto set 
pareto <- ga$pareto_set()

Bellow is the error I have encountered:
-- Initialization --------------------------------------------------------------
  * Create initial population
Checking if parameter(s) has been set ...
Checking if objective(s) has been set ...
Validating parameter function 'design_options' ...
Validating objective function(s)...
  [1] 'primary_energy' --> OK
All checks have been passed.
  * Evaluate fitness values
Error in set_insulation(idf, insulation_thickness) : 
  could not find function "set_insulation"
hongyuanjia commented 4 years ago

@mdakyen Thanks again for the bug report. This is due to future::Future failed to resolve the nested function references when GAOptim$run(parallel = TRUE) (default). It should have been fixed via #24.

Another issue here is that, by default, GAOptim$selector() is set to work for multi-objective optimization, where the survival is set to ecr::selNondom. Since you are doing a single-objective optimization, you should provide another survival argument. One possible value would be ecr::selGreedy, i.e.

ga$selector(survival = ecr::selGreedy)

Also if you want to get the results, you should use $best_set(). Because $pareto_set() is only available for multi-objective optimization.

ga$best_set()

If you want to know the individual indices, you can

ga$best_set(unique = FALSE)
mdakyen commented 3 years ago

Good day @hongyuanjia, I followed all the recommendations you have made earlier on so I can perform a simple optimization in R, to help me understand epluspar package, but my effort for the past two days was unsuccessful. So I decided to make my parameters to be two ( rotation angle and insulation thickness) and I made my objectives to be two. But it still displays an error when I try to run it. Please sir, if you have more materials that can help me understand epluspar package properly, I will be delighted if you can share them with me. I have studied your materials online (slides and publication), but still am unable to run an optimization problem.

Please below is my code:

#load packages
library(eplusr)
library(tidyverse) # for data-driven analysis
library(epluspar)

# read file
idf <- read_idf(system.file("extdata/1D 2F.idf", package = "eplusr"))

# read file paths
path_idf <- system.file("extdata/1D 2F.idf", package = "eplusr")
path_epw <- file.path(eplus_config(8.9)$dir, "WeatherData/Nicosia_hour.epw")

ga <- gaoptim_job(path_idf, path_epw)

#define a measure to change the insulation thickness of the exterior wall
set_rotation <- function (idf, degree) {
  idf$set(.("TWO FLOORS TWO DWELLINGS") := list(North_Axis = degree))
  idf
}

#define a measure to change the insulation thickness of the exterior wall
set_insulation <- function (idf, thickness) {
  # idf$set(.("polystyrene eps (5 cm)") := list(Thickness = thickness))
  idf$set(`polystyrene eps (5 cm)` = list(thickness = thickness))
  idf
}

# combine all measures into one
design_options <- function (idf, degree, insulation_thickness) {
  idf <- set_rotation (idf, degree) 
  idf <- set_insulation (idf, insulation_thickness) 
  idf
}

# specify design space of parameters 
ga$apply_measure(design_options, degree = integer_space(30:60), 
                 insulation_thickness = float_space(0.01,0.06,0.01))

primary_energy1 <- function (idf) {
  as.double(idf$last_job()$tabular_data( 
    report_name = "AnnualBuildingUtilityPerformanceSummary",
    table_name = "End Uses By Subcategory",
    row_name = "Heating",
    column_name = "District Heating")
    $value) 
}

primary_energy2 <- function (idf) {
  as.double(idf$last_job()$tabular_data( 
    report_name = "AnnualBuildingUtilityPerformanceSummary",
    table_name = "End Uses By Subcategory",
    row_name = "Cooling",
    column_name = "District Cooling")
    $value) 
}

# set optimization objectives 
ga$objective(primary_energy1,primary_energy2, .dir = "min")

# specify how to mix solutions 
ga$recombinator()
# specify how to change parts of one solution randomly 
ga$mutator()
# specify how to select best solutions 
ga$selector()
# specify the conditions when to terminate the computation 
ga$terminator(max_gen = 100L)

# run optimization 
ga$run(mu = 20)

# get all population 
population <- ga$population()
# get Pareto set 
pareto <- ga$pareto_set()

Below is the error I am faced with:

-- Initialization --------------------------------------------------------------
  * Create initial population
Checking if parameter(s) has been set ...
Checking if objective(s) has been set ...
Validating parameter function 'design_options' ...
Validating objective function(s)...
  [1] 'primary_energy1' --> OK
  [2] 'primary_energy2' --> OK
All checks have been passed.
  * Evaluate fitness values
Error in set_rotation(idf, degree) : 
  could not find function "set_rotation"
hongyuanjia commented 3 years ago

@mdakyen Sorry for the inconvenience. The root reason of this error was what I mentioned previously and should have been fixed via #24. Please make sure you have installed the latest version via remotes::install_github("ideas-lab-nus/epluspar"). I would suggest you run this command to make sure the latest version is installed.

If the latest version still did not work for you, for a simple workaround, you can just write your design_options() without referencing any other functions, i.e.:

design_options <- function (idf, degree, insulation_thickness) {
  idf$set(.("TWO FLOORS TWO DWELLINGS") := list(North_Axis = degree))
  idf$set(`polystyrene eps (5 cm)` = list(thickness = insulation_thickness))
  idf
}

Then things should work fine.


Unfortunately, unlike eplusr, I did not have enough time to work on epluspar's documentation. But definitely I see a need to improve the documentation. I will work on this when I have time.

if you have more materials that can help me understand epluspar package properly, I will be delighted if you can share them with me. I have studied your materials online (slides and publication), but still am unable to run an optimization problem.

mdakyen commented 3 years ago

@hongyuanjia Thanks for your support. Your response was helpful this time around. I uninstalled the epluspar version I had, then installed it again from remotes::install_github("ideas-lab-nus/epluspar"). I will let you know if I eventually encounter any difficulty with epluspar package. Thanks once more sir, for your quick response.