⚠️There's a newer version (0.16.2) of this package. Take me there.

eplusr

A Toolkit for Using EnergyPlus in R.

eplusr provides a rich toolkit of using EnergyPlus directly in R, which enables programmatic navigation, modification of EnergyPlus models and makes it less painful to do parametric simulations and analysis.

Installation

eplusr is currently not on CRAN. You can install eplusr from GitHub with:

# install.packages("devtools")
devtools::install_github("hongyuanjia/eplusr")

Features

  • Read, parse and modify EnergyPlus Weather File (EPW).
  • Read and parse EnergyPlus IDF files.
  • Query on models, including classes, objects and fields
  • Directly add, modify, duplicate, and delete objects of IDF in R.
  • Automatically change referred fields when modifying objects.
  • Save the changed models into standard formats in the same way as IDFEditor distributed along with EnergyPlus.
  • Run your models directly and collect the simulation output of EnergyPlus in R.

Usage

library(eplusr)

eplusr uses Idf class to present the whole IDF file and use IdfObject class to present a single object in an IDF. Both Idf and IdfObject class contain member functions for helping modify the data in the IDF so it complies with the underlying IDD (EnergyPlus Input Data Dictionary). Similarly, IDD file is wrapped in two classes, i.e. Idd and IddObject.

It is highly recommended to read the documentation of Idf, IdfObject, Idd and IddObject to get a thorough understanding on what methods them have. You can do that by running ?idf, ?idf_object, ?idd and ?idd_object.

Extra vignettes may added in the future.

Read and parse

All IDF reading process starts with function read_idf, which returns an Idf object. The model will be printed in a similar style you see in IDFEditor, with additional heading lines show the Path, Version of the model. The classes of objects in the model are ordered by group and the number of objects in classes are shown in square bracket.

Parsing an IDF file requires the IDD data of that version, which serves as the schema. Usually, when you try to edit an IDF file, the corresponding EnergyPlus is likely to be installed already. If that EnergyPlus is installed in standard location (C:/EnergyPlusVX-Y-0 on Windows, /usr/local/EnergyPlus-X-Y-0 on Linux and /Applications/EnergyPlus-X-Y-0 on MacOS), eplusr is able to find it and use the Energy+.idd file distributed with that release to parse the input IDF file. The IDD file will be parsed first and an Idd object will be created and cached. That Idd object will be reused whenever parsing IDF files with that version. For more details, please see ?use_idd and ?idd.

Sometimes you may just want to edit the model without installing the whole EnergyPlus software. You can just download the IDD file of that version using download_idd or set download to TRUE in use_idd.

Now let’s read an IDF file distributed with EnergyPlus 8.8.0. As EnergyPlus 8.8.0 has been installed, we can just ignore the idd argument.

model <- read_idf(path = "5Zone_Transformer.idf", idd = NULL)
#> Idd v8.8.0 has not been parsed before. Try to locate `Energy+.idd` in EnergyPlus installation folder.
#> IDD file found: `C:\EnergyPlusV8-8-0\Energy+.idd`.
#> Start parsing...

model
#> # Path: `C:\Users\hongy\Desktop\5Zone_Transformer.idf`
#> # Version: `8.8`
#> 
#> Group: `Simulation Parameters`
#> ---------------------------------------------------------------------------------
#> [01] Version
#> [01] SimulationControl
#> [01] Building
#> [01] SurfaceConvectionAlgorithm:Inside
#> [01] SurfaceConvectionAlgorithm:Outside
#> [01] HeatBalanceAlgorithm
#> [01] Timestep
#> 
#> Group: `Location and Climate`
#> ---------------------------------------------------------------------------------
#> [01] Site:Location
#> [02] SizingPeriod:DesignDay
#> [02] RunPeriod
#> [01] Site:GroundTemperature:BuildingSurface
#> 
#> Group: `Schedules`
#> ---------------------------------------------------------------------------------
#> [06] ScheduleTypeLimits
#> [23] Schedule:Compact
#> 
#> Group: `Surface Construction Elements`
#> ---------------------------------------------------------------------------------
#> [10] Material
#> [04] Material:NoMass
#> [02] Material:AirGap
....

Idf class contains several methods to help to query, modify models.

setdiff(ls(model), "initialize")
#>  [1] "add_object"      "class_name"      "clone"          
#>  [4] "definition"      "del_object"      "dup_object"     
#>  [7] "group_name"      "ins_object"      "is_unsaved"     
#> [10] "is_valid"        "is_valid_class"  "is_valid_group" 
#> [13] "is_valid_id"     "is_valid_name"   "object"         
#> [16] "object_id"       "object_in_class" "object_name"    
#> [19] "object_num"      "path"            "print"          
#> [22] "replace_value"   "run"             "save"           
#> [25] "search_object"   "search_value"    "set_object"     
#> [28] "string"          "validate"        "version"

Below will show same example usage of methods listed above.

Basic Info

If you want to see all groups and classes in your model, use $group_name and $class_name respectively.

model$group_name()
#>  [1] "Simulation Parameters"                        
#>  [2] "Location and Climate"                         
#>  [3] "Schedules"                                    
#>  [4] "Surface Construction Elements"                
#>  [5] "Thermal Zones and Surfaces"                   
#>  [6] "Internal Gains"                               
#>  [7] "Zone Airflow"                                 
#>  [8] "HVAC Design Objects"                          
#>  [9] "Zone HVAC Controls and Thermostats"           
#> [10] "Zone HVAC Air Loop Terminal Units"            
#> [11] "Zone HVAC Equipment Connections"              
#> [12] "Fans"                                         
#> [13] "Coils"                                        
#> [14] "Controllers"                                  
....
model$class_name()
#>  [1] "Version"                                   
#>  [2] "SimulationControl"                         
#>  [3] "Building"                                  
#>  [4] "SurfaceConvectionAlgorithm:Inside"         
#>  [5] "SurfaceConvectionAlgorithm:Outside"        
#>  [6] "HeatBalanceAlgorithm"                      
#>  [7] "Timestep"                                  
#>  [8] "Site:Location"                             
#>  [9] "SizingPeriod:DesignDay"                    
#> [10] "RunPeriod"                                 
#> [11] "Site:GroundTemperature:BuildingSurface"    
#> [12] "ScheduleTypeLimits"                        
#> [13] "Schedule:Compact"                          
#> [14] "Material"                                  
....

Also $is_valid_group and $is_valid_class are provided to check if given group and class exists in current model.

Class definition

You can get the definition of classes using $definition, which returns a list of IddObjects. All required fields are marked with *. For example, you can find the IddObject of class Material:

def_mat <- model$definition(class = "Material")[[1]]
def_mat
#> << Class: `Material` >>
#> ------------------------------------ * MEMO * -----------------------------------
#>   "Regular materials described with full set of thermal properties"
#> --------------------------------- * PROPERTIES * --------------------------------
#>   Group: `Surface Construction Elements`
#>   Unique: FALSE
#>   Required: FALSE
#>   Total fields: 9
#> ----------------------------------- * FIELDS * ----------------------------------
#>   1:* Name
#>   2:* Roughness
#>   3:* Thickness {m}
#>   4:* Conductivity {W/m-K}
#>   5:* Density {kg/m3}
#>   6:* Specific Heat {J/kg-K}
#>   7:  Thermal Absorptance
#>   8:  Solar Absorptance
#>   9:  Visible Absorptance
#> ---------------------------------------------------------------------------------

You can also achieve this using methods in Idd class.

idd <- use_idd(8.8)

idd$Material
#> << Class: `Material` >>
#> ------------------------------------ * MEMO * -----------------------------------
#>   "Regular materials described with full set of thermal properties"
#> --------------------------------- * PROPERTIES * --------------------------------
#>   Group: `Surface Construction Elements`
#>   Unique: FALSE
#>   Required: FALSE
#>   Total fields: 9
#> ----------------------------------- * FIELDS * ----------------------------------
#>   1:* Name
#>   2:* Roughness
#>   3:* Thickness {m}
#>   4:* Conductivity {W/m-K}
#>   5:* Density {kg/m3}
#>   6:* Specific Heat {J/kg-K}
#>   7:  Thermal Absorptance
#>   8:  Solar Absorptance
#>   9:  Visible Absorptance
#> ---------------------------------------------------------------------------------

# OR
# idd$object("Material")[[1]]

With the IddObject, you can easily get class and field properties using methods it has.

setdiff(ls(def_mat), "initialize")
#>  [1] "add_extensible_group"      "class_format"             
#>  [3] "class_index"               "class_name"               
#>  [5] "clone"                     "del_extensible_group"     
#>  [7] "extensible_group_num"      "field_choice"             
#>  [9] "field_default"             "field_index"              
#> [11] "field_name"                "field_note"               
#> [13] "field_range"               "field_type"               
#> [15] "field_unit"                "first_extensible_index"   
#> [17] "group_index"               "group_name"               
#> [19] "has_name"                  "is_autocalculatable_field"
#> [21] "is_autosizable_field"      "is_extensible"            
#> [23] "is_extensible_index"       "is_integer_field"         
#> [25] "is_numeric_field"          "is_required"              
#> [27] "is_required_field"         "is_unique"                
#> [29] "is_valid_field_index"      "is_valid_field_name"      
#> [31] "is_valid_field_num"        "memo"                     
#> [33] "min_fields"                "num_extensible"           
#> [35] "num_fields"                "print"

For example, you can get all field default values using $field_default.

def_val <- def_mat$field_default()
def_val
#> [[1]]
#> [1] NA
#> 
#> [[2]]
#> [1] NA
#> 
#> [[3]]
#> [1] NA
#> 
#> [[4]]
#> [1] NA
#> 
#> [[5]]
#> [1] NA
#> 
#> [[6]]
#> [1] NA
#> 
#> [[7]]
#> [1] 0.9
#> 
#> [[8]]
#> [1] 0.7
#> 
#> [[9]]
#> [1] 0.7

As we did not give the field index and name, a list will be returned containing all field default values. Type of each value will be consistent with the field definition.

vapply(def_val, class, character(1))
#> [1] "character" "character" "numeric"   "numeric"   "numeric"   "numeric"  
#> [7] "numeric"   "numeric"   "numeric"

NOTE: For numeric fields with default values being "autosize" or "autocalculate", the type of returned values will be “character”.

Please see ?idd_object for detailed documentation on IddObject.

Get object

All objects in the model are assigned with an unique ID according to their appearance sequences in the IDF file. You can find all valid IDs using $object_id.

model$object_id(class = c("Material", "Construction"), simplify = FALSE)
#> $Material
#>  [1] 43 44 45 46 47 48 49 50 51 52
#> 
#> $Construction
#> [1] 66 67 68 69 70 71 72

You can get all object names using $object_name. If the class does not have name attribute, NA will returned.

model$object_name(class = c("Version", "Material", "Construction"), simplify = FALSE)
#> $Version
#> [1] NA
#> 
#> $Material
#>  [1] "WD10" "RG01" "BR01" "IN46" "WD01" "PW03" "IN02" "GP01" "GP02" "CC03"
#> 
#> $Construction
#> [1] "ROOF-1"               "WALL-1"               "CLNG-1"              
#> [4] "FLOOR-SLAB-1"         "INT-WALL-1"           "Dbl Clr 3mm/13mm Air"
#> [7] "Sgl Grey 3mm"

Object number in each class can be retrieved using $object_num.

model$object_num(c("BuildingSurface:Detailed", "Material", "Output:Variable"))
#> [1] 40 10 13

Having the object ID or name, you can easily get any object using $object.

NOTE: The matching of object names is case-insensitive, which means that model$object("rOoF") is equivalent to model$object("roof").

$object returns a list of IdfObjects. Each member of the list will have the same name of the object, except that all names are converted into valid R names, i.e. all other characters except letters and numbers are replaced by underscore.

model$object(c("WD10", "ROOF-1"))
#> $WD10
#> <<[ID:43] `WD10`>> Material
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: WD10,              !- Name
#> *2: MediumSmooth,      !- Roughness
#> *3: 0.667,             !- Thickness {m}
#> *4: 0.115,             !- Conductivity {W/m-K}
#> *5: 513,               !- Density {kg/m3}
#> *6: 1381,              !- Specific Heat {J/kg-K}
#>  7: 0.9,               !- Thermal Absorptance
#>  8: 0.78,              !- Solar Absorptance
#>  9: 0.78;              !- Visible Absorptance
#> ---------------------------------------------------------------------------------
#> 
#> $ROOF_1
#> <<[ID:66] `ROOF-1`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: ROOF-1,            !- Name
#> *2: RG01,              !- Outside Layer
#>  3: BR01,              !- Layer 2
#>  4: IN46,              !- Layer 3
#>  5: WD01;              !- Layer 4
#> ---------------------------------------------------------------------------------

If you want to get all objects in a single class, use $object_in_class.

model$object_in_class("Material")
#> $WD10
#> <<[ID:43] `WD10`>> Material
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: WD10,              !- Name
#> *2: MediumSmooth,      !- Roughness
#> *3: 0.667,             !- Thickness {m}
#> *4: 0.115,             !- Conductivity {W/m-K}
#> *5: 513,               !- Density {kg/m3}
#> *6: 1381,              !- Specific Heat {J/kg-K}
#>  7: 0.9,               !- Thermal Absorptance
#>  8: 0.78,              !- Solar Absorptance
#>  9: 0.78;              !- Visible Absorptance
#> ---------------------------------------------------------------------------------
#> 
#> $RG01
#> <<[ID:44] `RG01`>> Material
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: RG01,              !- Name
#> *2: Rough,             !- Roughness
#> *3: 0.0127,            !- Thickness {m}
#> *4: 1.442,             !- Conductivity {W/m-K}
#> *5: 881,               !- Density {kg/m3}
#> *6: 1674,              !- Specific Heat {J/kg-K}
#>  7: 0.9,               !- Thermal Absorptance
#>  8: 0.65,              !- Solar Absorptance
#>  9: 0.65;              !- Visible Absorptance
#> ---------------------------------------------------------------------------------
#> 
#> $BR01
#> <<[ID:45] `BR01`>> Material
....

Custom S3 methods are provided ("$" and "[") to get objects in a single class. Class names can be given in a style that : is replaced by underscore _. This is handy because it makes valid names in R so that you can just use model$Output_Variable instead of model$Output:Variable` `.

model$Material
#> $WD10
#> <<[ID:43] `WD10`>> Material
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: WD10,              !- Name
#> *2: MediumSmooth,      !- Roughness
#> *3: 0.667,             !- Thickness {m}
#> *4: 0.115,             !- Conductivity {W/m-K}
#> *5: 513,               !- Density {kg/m3}
#> *6: 1381,              !- Specific Heat {J/kg-K}
#>  7: 0.9,               !- Thermal Absorptance
#>  8: 0.78,              !- Solar Absorptance
#>  9: 0.78;              !- Visible Absorptance
#> ---------------------------------------------------------------------------------
#> 
#> $RG01
#> <<[ID:44] `RG01`>> Material
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: RG01,              !- Name
#> *2: Rough,             !- Roughness
#> *3: 0.0127,            !- Thickness {m}
#> *4: 1.442,             !- Conductivity {W/m-K}
#> *5: 881,               !- Density {kg/m3}
#> *6: 1674,              !- Specific Heat {J/kg-K}
#>  7: 0.9,               !- Thermal Absorptance
#>  8: 0.65,              !- Solar Absorptance
#>  9: 0.65;              !- Visible Absorptance
#> ---------------------------------------------------------------------------------
#> 
#> $BR01
#> <<[ID:45] `BR01`>> Material
....
# OR
# model[["Material"]]

Based on the above, if you want to get the first object in class RunPeriod, you can simply run:

rp <- model$RunPeriod[[1]]
rp
#> <<[ID:8] `WinterDay`>> RunPeriod
#> ----------------------------------- * FIELDS * ----------------------------------
#>   1: WinterDay,         !- Name
#> * 2: 1,                 !- Begin Month
#> * 3: 14,                !- Begin Day of Month
#> * 4: 1,                 !- End Month
#> * 5: 14,                !- End Day of Month
#>   6: Tuesday,           !- Day of Week for Start Day
#>   7: Yes,               !- Use Weather File Holidays and Special Days
#>   8: Yes,               !- Use Weather File Daylight Saving Period
#>   9: No,                !- Apply Weekend Holiday Rule
#>  10: Yes,               !- Use Weather File Rain Indicators
#>  11: Yes;               !- Use Weather File Snow Indicators
#> ---------------------------------------------------------------------------------

$search_object will search and return a list objects whose names meet the regular expression you give.

model$search_object("Demand", class = "Branch")
#> $`Heating Demand Inlet Branch`
#> <<[ID:222] `Heating Demand Inlet Branch`>> Branch
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: Heating Demand Inlet Branch,  !- Name
#>  2: <Blank>,           !- Pressure Drop Curve Name
#> *3: Pipe:Adiabatic,    !- Component 1 Object Type
#> *4: Heating Demand Inlet Pipe,  !- Component 1 Name
#> *5: HW Demand Inlet Node,  !- Component 1 Inlet Node Name
#> *6: HW Demand Entrance Pipe Outlet Node;  !- Component 1 Outlet Node Name
#> ---------------------------------------------------------------------------------
#> 
#> $`Heating Demand Outlet Branch`
#> <<[ID:223] `Heating Demand Outlet Branch`>> Branch
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: Heating Demand Outlet Branch,  !- Name
#>  2: <Blank>,           !- Pressure Drop Curve Name
#> *3: Pipe:Adiabatic,    !- Component 1 Object Type
#> *4: Heating Demand Outlet Pipe,  !- Component 1 Name
#> *5: HW Demand Exit Pipe Inlet Node,  !- Component 1 Inlet Node Name
#> *6: HW Demand Outlet Node;  !- Component 1 Outlet Node Name
....

NOTE: Under the hook, stringr::str_detect is used for searching, which is case-sensitive by default. If you want more controls on how the matching are performed, build your own regular expression using stringr::regex.

After you get the objects, you can perform detailed modifications on them using methods in IdfObject class.

setdiff(ls(rp), "initialize")
#>  [1] "class_name"      "clone"           "definition"     
#>  [4] "get_comment"     "get_value"       "group_name"     
#>  [7] "has_ref"         "has_ref_by"      "has_ref_from"   
#> [10] "id"              "is_valid"        "name"           
#> [13] "print"           "ref_by_object"   "ref_from_object"
#> [16] "set_comment"     "set_value"       "string"         
#> [19] "table"           "validate"

Also, custom S3 methods are provided ("$" and "[") to get a single value in an IdfObject class.

rp$Begin_Day_of_Month
#> [1] 14

You can also make a chain.

model$RunPeriod$WinterDay$Begin_Day_of_Month
#> [1] 14

Please run ?idf_object for detailed documentation on IdfObject.

Modify object

There are two ways to modify objects in eplusr. One is using methods in Idf which works on multiple objects, and the other way is using methods in IdfObject which only works for a single object.

Validations are made during object modifications, under different strictness level ("none", "draft", "final"). For detailed explanations, please see ?eplusr_option.

You can duplicate, add, modify and delete objects using dup_object, add_object, $set_object and $del_object in Idf, respectively.

Object IDs will be appended after $add_object and $dup_object, and the newly added (or duplicated) objects will have the max ID. Object IDs will never be reused, even though their associated objects have been deleted using $del_object.

For modifying object’s comments and values, you can also use $set_comment and $set_value in IdfObject class.

Duplicate objects

$dup_object will duplicate objects specified using object IDs or names. If the target classes have a name attribute, you can assign new names to the duplicated objects using argument new_name. If NULL, which is default, the duplicated objects will have the same name of the original object except with a suffix of “_1”, “_2” and etc. The duplicated objects will be returned.

model$dup_object(c("ROOF-1", "ROOF-1", "WALL-1"))
#> -- Info -------------------------------------------------------------------------
#> New names of duplicated objects were not given. Automatically generated names were assigned:
#>   * Target Object [ID: 66] Name `ROOF-1`--> Auto Assigned Name: `ROOF-1_1`
#>   * Target Object [ID: 66] Name `ROOF-1`--> Auto Assigned Name: `ROOF-1_2`
#>   * Target Object [ID: 67] Name `WALL-1`--> Auto Assigned Name: `WALL-1_1`
#> $ROOF_1_1
#> <<[ID:324] `ROOF-1_1`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: ROOF-1_1,          !- Name
#> *2: RG01,              !- Outside Layer
#>  3: BR01,              !- Layer 2
#>  4: IN46,              !- Layer 3
#>  5: WD01;              !- Layer 4
#> ---------------------------------------------------------------------------------
#> 
#> $ROOF_1_2
#> <<[ID:325] `ROOF-1_2`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: ROOF-1_2,          !- Name
#> *2: RG01,              !- Outside Layer
#>  3: BR01,              !- Layer 2
#>  4: IN46,              !- Layer 3
#>  5: WD01;              !- Layer 4
#> ---------------------------------------------------------------------------------
#> 
#> $WALL_1_1
#> <<[ID:326] `WALL-1_1`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: WALL-1_1,          !- Name
#> *2: WD01,              !- Outside Layer
#>  3: PW03,              !- Layer 2
#>  4: IN02,              !- Layer 3
#>  5: GP01;              !- Layer 4
#> ---------------------------------------------------------------------------------

Add new objects

You can add new objects using $add_object. With default setting to TRUE, all empty fields are filled with default values, if possible. Only minimum fields will be added by default. But you can change it by setting all to TRUE.

Field values should be given in a list following either pattern below:

  • directly list all field values with no name. The values will be assigned to fields according to the appearance order of values;
  • give both field names (without units) and values in pair, e.g. Name = "Test", "Begin Month" = 1. You can find all valid field names using $definition("class_name")[[1]]$field_name(). Field names can also be given in lower-style, e.g. name = "Test", begin_month = 1.

You can also add new comments alongside with new values to the new objects.

For example, you can add two new objects in RunPeriod:

model$add_object(rep("RunPeriod", 2),
  value = list(
    list("rp_test_1", 1, 1, 2, 1),

    list(name = "rp_test_2",
         begin_month = 3,
         begin_day_of_month = 1,
         end_month = 4,
         end_day_of_month = 1)
    ),
  comment = list(
    list("Comment for new object 1", "Another comment"),
    list("Comment for new object 2")),
  default = TRUE
)
#> $rp_test_1
#> <<[ID:327] `rp_test_1`>> RunPeriod
#> ---------------------------------- * COMMENTS * ---------------------------------
#> !Comment for new object 1
#> !Another comment
#> ----------------------------------- * FIELDS * ----------------------------------
#>   1: rp_test_1,         !- Name
#> * 2: 1,                 !- Begin Month
#> * 3: 1,                 !- Begin Day of Month
#> * 4: 2,                 !- End Month
#> * 5: 1,                 !- End Day of Month
#>   6: UseWeatherFile,    !- Day of Week for Start Day
#>   7: Yes,               !- Use Weather File Holidays and Special Days
#>   8: Yes,               !- Use Weather File Daylight Saving Period
#>   9: No,                !- Apply Weekend Holiday Rule
#>  10: Yes,               !- Use Weather File Rain Indicators
#>  11: Yes;               !- Use Weather File Snow Indicators
#> ---------------------------------------------------------------------------------
#> 
#> $rp_test_2
#> <<[ID:328] `rp_test_2`>> RunPeriod
#> ---------------------------------- * COMMENTS * ---------------------------------
#> !Comment for new object 2
#> ----------------------------------- * FIELDS * ----------------------------------
#>   1: rp_test_2,         !- Name
#> * 2: 3,                 !- Begin Month
#> * 3: 1,                 !- Begin Day of Month
#> * 4: 4,                 !- End Month
#> * 5: 1,                 !- End Day of Month
#>   6: UseWeatherFile,    !- Day of Week for Start Day
#>   7: Yes,               !- Use Weather File Holidays and Special Days
#>   8: Yes,               !- Use Weather File Daylight Saving Period
#>   9: No,                !- Apply Weekend Holiday Rule
#>  10: Yes,               !- Use Weather File Rain Indicators
#>  11: Yes;               !- Use Weather File Snow Indicators
#> ---------------------------------------------------------------------------------

Set new values and comments

Changing values of existing objects can be conducted using $set_object in Idf or $set_value in IdfObject. Basic rules above of field values also apply to $set_object, i.e. you should give either named values or non-named values in lists. For example:

model$set_object("rp_test_1", list(name = "rp_test_3", begin_day_of_month = 2),
  comment = list(format(Sys.Date()), "begin day has been changed."))
#> $rp_test_3
#> <<[ID:327] `rp_test_3`>> RunPeriod
#> ---------------------------------- * COMMENTS * ---------------------------------
#> !2018-07-15
#> !begin day has been changed.
#> ----------------------------------- * FIELDS * ----------------------------------
#>   1: rp_test_3,         !- Name
#> * 2: 1,                 !- Begin Month
#> * 3: 2,                 !- Begin Day of Month
#> * 4: 2,                 !- End Month
#> * 5: 1,                 !- End Day of Month
#>   6: UseWeatherFile,    !- Day of Week for Start Day
#>   7: Yes,               !- Use Weather File Holidays and Special Days
#>   8: Yes,               !- Use Weather File Daylight Saving Period
#>   9: No,                !- Apply Weekend Holiday Rule
#>  10: Yes,               !- Use Weather File Rain Indicators
#>  11: Yes;               !- Use Weather File Snow Indicators
#> ---------------------------------------------------------------------------------

Also, if the modified fields are referenced by fields in other objects, the corresponding fields will also be updated. You can check that by comparing the values referencing the target object before and after.

mat <- model$Material$CC03
mat$ref_by_object()
#> 1 object found that reference the target object [ID: 52].
#> $FLOOR_SLAB_1
#> <<[ID:69] `FLOOR-SLAB-1`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: FLOOR-SLAB-1,      !- Name
#> *2: CC03;              !- Outside Layer
#> ---------------------------------------------------------------------------------
mat$set_value(name = "CC03_renamed")
#> <<[ID:52] `CC03_renamed`>> Material
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: CC03_renamed,      !- Name
#> *2: MediumRough,       !- Roughness
#> *3: 0.1016,            !- Thickness {m}
#> *4: 1.31,              !- Conductivity {W/m-K}
#> *5: 2243,              !- Density {kg/m3}
#> *6: 837,               !- Specific Heat {J/kg-K}
#>  7: 0.9,               !- Thermal Absorptance
#>  8: 0.65,              !- Solar Absorptance
#>  9: 0.65;              !- Visible Absorptance
#> ---------------------------------------------------------------------------------
mat$ref_by_object()
#> 1 object found that reference the target object [ID: 52].
#> $FLOOR_SLAB_1
#> <<[ID:69] `FLOOR-SLAB-1`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: FLOOR-SLAB-1,      !- Name
#> *2: CC03_renamed;      !- Outside Layer
#> ---------------------------------------------------------------------------------

Insert objects

Sometime it may be useful to insert objects from other IDF files. For example, you may want to import some design day objects from a “.ddy” file. You can achieve that in eplusr using $ins_object.

ddy <- read_idf("San_Francisco.ddy", idd = 8.8)
#> Warning: Missing version field in input Idf file. The given Idd version
#> 8.8.0 will be used. Parsing errors may occur.

model$ins_object(ddy$SizingPeriod_DesignDay)
#> $San_Francisco_Intl_Ap_Ann_Htg_99_6_Condns_DB
#> <<[ID:329] `San Francisco Intl Ap Ann Htg 99.6% Condns DB`>> SizingPeriod:DesignDay
#> ----------------------------------- * FIELDS * ----------------------------------
#> * 1: San Francisco Intl Ap Ann Htg 99.6% Condns DB,  !- Name
#> * 2: 1,                 !- Month
#> * 3: 21,                !- Day of Month
#> * 4: WinterDesignDay,   !- Day Type
#>   5: 3.8,               !- Maximum Dry-Bulb Temperature {C}
#>   6: 0,                 !- Daily Dry-Bulb Temperature Range {deltaC}
#>   7: DefaultMultipliers,!- Dry-Bulb Temperature Range Modifier Type
#>   8: <Blank>,           !- Dry-Bulb Temperature Range Modifier Day Schedule Name
#>   9: Wetbulb,           !- Humidity Condition Type
#>  10: 3.8,               !- Wetbulb or DewPoint at Maximum Dry-Bulb {C}
#>  11: <Blank>,           !- Humidity Condition Day Schedule Name
#>  12: <Blank>,           !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir}
#>  13: <Blank>,           !- Enthalpy at Maximum Dry-Bulb {J/kg}
#>  14: <Blank>,           !- Daily Wet-Bulb Temperature Range {deltaC}
#>  15: 101301,            !- Barometric Pressure {Pa}
#> *16: 2.2,               !- Wind Speed {m/s}
#> *17: 150,               !- Wind Direction {deg}
....

Delete object

$del_object will delete current object specified by object ids or names. For example, there is a material named "MAT-CLNG-1" in class Material:NoMass. You can get objects referencing "MAT-CLNG-1" by using $ref_by_object in IdfObject class.

clng <- model$Material_NoMass$MAT_CLNG_1
clng$ref_by_object()
#> 1 object found that reference the target object [ID: 55].
#> $CLNG_1
#> <<[ID:68] `CLNG-1`>> Construction
#> ----------------------------------- * FIELDS * ----------------------------------
#> *1: CLNG-1,            !- Name
#> *2: MAT-CLNG-1;        !- Outside Layer
#> ---------------------------------------------------------------------------------

As we can see, "MAT-CLNG-1" has been referenced by a construction named "CLNG-1". In "final" validate level, if the object is referenced by other object(s), it cannot be deleted and an error will given.

eplusr_option("validate_level")
#> [1] "final"
model$del_object("mat-clng-1")
#> Error: Delete object that are referenced by others is prohibited in `final` validation level. Failed to delete target object [ID:`55`]:
#> 1: Object [ID:`55`] was referenced by other objects [ID:`68`].

In some cases, you may still want to delete that object. You can do that by changing validate level to "draft" or "none". For detail explanations on each validate level, please see ?eplusr_option.

You can also delete objects referencing the target objects as well, by setting referenced to TRUE.

eplusr_option(validate_level = "draft")
#> $validate_level
#> [1] "draft"
invisible(model$del_object(55, referenced = TRUE))
#> -- Info -------------------------------------------------------------------------
#> Delete target object [ID:`55`] and also objects [ID: `68`] that are referencing target object.

Validate

$validate will check the validation of all fields in current model, including missing required objected and fields, wrong value types, choices, references, any value range exceeding, invalid autosizable and autocalculatable fields. $is_valid will return TRUE if no error is found. Validate level can be changed using eplusr_option. The default level is "final". For more details, please see ?eplusr_option.

Material "MAT-CLNG-1" and construction "CLNG-1" have been all deleted. After that, invalid references will be detected during model validation, as construction "CLNG-1" was referenced by many other objects in BuildingSurface:Detailed.

eplusr_option(validate_level = "final")
#> $validate_level
#> [1] "final"
model$validate()
#>  <U+2716> [10] Errors found during validation.
#> =================================================================================
#> 
#> -- [10] Invalid Reference -------------------------------------------------------
#> (x) Fields below are not one of valid references.
#> 
#>   Class `BuildingSurface:Detailed`
#>   +- Object [ID:85]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:86]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:87]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:88]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:89]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:91]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:97]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:103]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   +- Object [ID:109]
#>   |  \- 3: CLNG-1;            !- Construction Name
#>   \- Object [ID:114]
#>      \- 3: CLNG-1;            !- Construction Name

Save

You can save your model using $save. If no path is given, the path of model itself will be used. This may overwrite the current file which has a risk of losing your original file and data. You have to set overwrite to TRUE to confirm the process.

model$save("test.idf")

Run and Collect Output

eplusr uses the EnergyPlus command line interface which was introduced since EnergyPlus 8.3.0. So $run only supports models with version higher than 8.3.0.

eplusr will auto-detect already installed EnergyPlus in the standard installation locations. You can get all detected EnergyPlus version using avail_eplus.

avail_eplus()
#> [1] "8.6.0" "8.8.0" "8.9.0"

$run will issue an error if corresponding version of EnergyPlus is not found. If your EnergyPlus was not installed in standard location, you can add that location into eplusr EnergyPlus location dictionary using use_eplus.

use_eplus("C:/EnergyPlusV8-8-0")
#> EnergyPlus v8.8.0 has been added to EnergyPlus location dictionary.

If the needed version of EnergyPlus was not installed, you can use install_eplus to install it.

eplusr::install_eplus(ver = 8.9)

Sometimes, before simulation, it may be useful to retrieve weather data from EnergyPlus Weather (EPW) files and conduct analysis on the weather. eplusr provides read_epw to let you parse and query on EPW files.

epw_sf <- read_epw("San_Francisco.epw")
epw_sf
#> -- Location ---------------------------------------------------------------------
#> * [ City    ]: San Francisco Intl Ap
#> * [ State   ]: CA
#> * [ Country ]: USA
#> * [ Source  ]: TMY3
#> * [ WMO Num ]: 724940
#> * [Latitude ]: 37.62
#> * [Longitude]: -122.4
#> * [Time Zone]: -8
#> * [Evevation]: 2
#> 
#> -- Data Period ------------------------------------------------------------------
#> * [Period Num ]: 1
#> * [Time Step  ]: 60 min
#> * [Date Range ]: Jan 01 - Dec 31
#> * [1st Weekday]: Sunday
#> * [Real Year  ]: 1
#> 
#> -- Holidays and Daylight Savings ------------------------------------------------
#> * [ Leap Year ]: FALSE
#> * [ DST Range ]: NA
#> * [Holiday Num]: 0

read_epw returns an Epw object. For details on Epw class, please see ?epw. Here are all methods of Epw:

setdiff(ls(epw_sf), "initialize")
#>  [1] "city"              "clone"             "country"          
#>  [4] "data_source"       "elevation"         "get_data"         
#>  [7] "latitude"          "longitude"         "path"             
#> [10] "print"             "save"              "set_data"         
#> [13] "start_day_of_week" "state_province"    "time_step"        
#> [16] "time_zone"         "wmo_number"

You can get all weather data using $get_data.

epw_data <- epw_sf$get_data()
names(epw_data)
#>  [1] "datetime"                                        
#>  [2] "year"                                            
#>  [3] "month"                                           
#>  [4] "day"                                             
#>  [5] "hour"                                            
#>  [6] "minute"                                          
#>  [7] "datasource"                                      
#>  [8] "dry_bulb_temperature"                            
#>  [9] "dew_point_temperature"                           
#> [10] "relative_humidity"                               
#> [11] "atmospheric_pressure"                            
#> [12] "extraterrestrial_horizontal_radiation"           
#> [13] "extraterrestrial_direct_normal_radiation"        
#> [14] "horizontal_infrared_radiation_intensity_from_sky"
#> [15] "global_horizontal_radiation"                     
#> [16] "direct_normal_radiation"                         
#> [17] "diffuse_horizontal_radiation"                    
#> [18] "global_horizontal_illuminance"                   
#> [19] "direct_normal_illuminance"                       
#> [20] "diffuse_horizontal_illuminance"                  
#> [21] "zenith_luminance"                                
#> [22] "wind_direction"                                  
#> [23] "wind_speed"                                      
#> [24] "total_sky_cover"                                 
#> [25] "opaque_sky_cover"                                
#> [26] "visibility"                                      
#> [27] "ceiling_height"                                  
#> [28] "present_weather_observation"                     
#> [29] "present_weather_codes"                           
#> [30] "precipitable_water"                              
#> [31] "aerosol_optical_depth"                           
#> [32] "snow_depth"                                      
#> [33] "days_since_last_snow"                            
#> [34] "albedo"                                          
#> [35] "liquid_precip_depth"                             
#> [36] "liquid_precip_rate"
str(epw_data)
#> Classes 'data.table' and 'data.frame':   8760 obs. of  36 variables:
#>  $ datetime                                        : POSIXct, format: "1999-01-01 01:00:00" "1999-01-01 02:00:00" ...
#>  $ year                                            : int  1999 1999 1999 1999 1999 1999 1999 1999 1999 1999 ...
#>  $ month                                           : int  1 1 1 1 1 1 1 1 1 1 ...
#>  $ day                                             : int  1 1 1 1 1 1 1 1 1 1 ...
#>  $ hour                                            : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ minute                                          : int  0 0 0 0 0 0 0 0 0 0 ...
#>  $ datasource                                      : chr  "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" ...
#>  $ dry_bulb_temperature                            : num  7.2 7.2 6.7 6.1 4.4 4.4 6.1 5 7.8 8.9 ...
#>  $ dew_point_temperature                           : num  5.6 5.6 5 5 3.9 3.9 4.4 2.8 5 6.7 ...
#>  $ relative_humidity                               : num  90 90 89 93 97 97 89 86 82 86 ...
#>  $ atmospheric_pressure                            : num  102200 102100 102200 102200 102200 ...
#>  $ extraterrestrial_horizontal_radiation           : num  0 0 0 0 0 0 0 36 243 443 ...
#>  $ extraterrestrial_direct_normal_radiation        : num  0 0 0 0 0 ...
#>  $ horizontal_infrared_radiation_intensity_from_sky: num  290 296 291 276 280 280 287 281 295 299 ...
#>  $ global_horizontal_radiation                     : num  0 0 0 0 0 0 0 2 121 276 ...
#>  $ direct_normal_radiation                         : num  0 0 0 0 0 0 0 69 477 651 ...
#>  $ diffuse_horizontal_radiation                    : num  0 0 0 0 0 0 0 1 39 71 ...
#>  $ global_horizontal_illuminance                   : num  0 0 0 0 0 ...
#>  $ direct_normal_illuminance                       : num  0 0 0 0 0 ...
#>  $ diffuse_horizontal_illuminance                  : num  0 0 0 0 0 ...
#>  $ zenith_luminance                                : num  0 0 0 0 0 ...
#>  $ wind_direction                                  : num  0 170 210 200 260 180 0 0 0 0 ...
#>  $ wind_speed                                      : num  0 2.1 2.1 1.5 3.1 2.1 0 0 0 0 ...
#>  $ total_sky_cover                                 : int  2 4 3 0 3 3 3 3 3 2 ...
#>  $ opaque_sky_cover                                : int  2 4 3 0 3 3 3 3 3 2 ...
#>  $ visibility                                      : num  16 16 16 16 16 16 16 16 16 16 ...
#>  $ ceiling_height                                  : num  77777 77777 77777 77777 77777 ...
#>  $ present_weather_observation                     : int  9 9 9 9 9 9 9 9 9 9 ...
#>  $ present_weather_codes                           : chr  NA NA NA NA ...
#>  $ precipitable_water                              : num  129 120 120 120 120 120 120 110 110 110 ...
#>  $ aerosol_optical_depth                           : num  0.108 0.108 0.108 0.108 0.108 0.108 0.108 0.108 0.108 0.108 ...
#>  $ snow_depth                                      : num  0 0 0 0 0 0 0 0 0 0 ...
#>  $ days_since_last_snow                            : int  88 88 88 88 88 88 88 88 88 88 ...
#>  $ albedo                                          : num  0.16 0.16 0.16 0.16 0.16 0.16 0.16 0.16 0.16 0.16 ...
#>  $ liquid_precip_depth                             : num  0 0 0 0 0 0 0 0 0 0 ...
#>  $ liquid_precip_rate                              : num  1 1 1 1 1 1 1 1 1 1 ...
#>  - attr(*, ".internal.selfref")=<externalptr>

After that, you should be able to run your model. $run will run the current model with specified weather using corresponding version of EnergyPlus. The model and the weather used will be copied to the output directory. An EplusJob will be returned which provides detailed infomation of the simulation and methods to collect simulation results. Please see ?job for more detailed.

# read the model again
model <- read_idf("5Zone_Transformer.idf", idd = NULL)

job <- model$run(epw_sf, dir = ".", wait = TRUE)
#> -- Info -------------------------------------------------------------------------
#> Replace the existing file located  at C:\Users\hongy\Desktop\5Zone_Transformer.idf.
#> 
#> EnergyPlus Starting
#> EnergyPlus, Version 8.8.0-7c3bbe4830, YMD=2018.07.15 02:46
#> Processing Data Dictionary
#> Processing Input File
#> Initializing Response Factors
#> Calculating CTFs for "ROOF-1", Construction # 1
#> Calculating CTFs for "WALL-1", Construction # 2
#> Calculating CTFs for "FLOOR-SLAB-1", Construction # 4
#> Calculating CTFs for "INT-WALL-1", Construction # 5
#> Initializing Window Optical Properties
#> Initializing Solar Calculations
#> Allocate Solar Module Arrays
#> Initializing Zone Report Variables
#> Initializing Surface (Shading) Report Variables
#> Computing Interior Solar Absorption Factors
#> Determining Shadowing Combinations
#> Computing Window Shade Absorption Factors
#> Proceeding with Initializing Solar Calculations
#> Initializing Surfaces
#> Initializing Outdoor environment for Surfaces
#> Setting up Surface Reporting Variables
#> Initializing Temperature and Flux Histories
#> Initializing Window Shading
#> Computing Interior Absorption Factors
#> Computing Interior Diffuse Solar Absorption Factors
#> Computing Interior Diffuse Solar Exchange through Interzone Windows
#> Initializing Solar Heat Gains
#> Initializing Internal Heat Gains
#> Initializing Interior Solar Distribution
#> Initializing Interior Convection Coefficients
#> Gathering Information for Predefined Reporting
#> Completed Initializing Surface Heat Balance
#> Calculate Outside Surface Heat Balance
#> Calculate Inside Surface Heat Balance
#> Calculate Air Heat Balance
#> Initializing HVAC
#> Warming up
#> Warming up
#> Warming up
#> Warming up
#> Warming up
#> Warming up
#> Performing Zone Sizing Simulation
#> ...for Sizing Period: #1 CHICAGO_IL_USA ANNUAL HEATING 99% DESIGN CONDITIONS DB
#> Warming up
#> Warming up
#> Warming up
#> Warming up
#> Warming up
#> Warming up
#> Performing Zone Sizing Simulation
#> ...for Sizing Period: #2 CHICAGO_IL_USA ANNUAL COOLING 1% DESIGN CONDITIONS DB/MCWB
#> Calculating System sizing
#> ...for Sizing Period: #1 CHICAGO_IL_USA ANNUAL HEATING 99% DESIGN CONDITIONS DB
#> Calculating System sizing
#> ...for Sizing Period: #2 CHICAGO_IL_USA ANNUAL COOLING 1% DESIGN CONDITIONS DB/MCWB
#> Initializing Simulation
#> Reporting Surfaces
#> Beginning Primary Simulation
#> Initializing New Environment Parameters
#> Warming up {1}
#> Warming up {2}
#> Warming up {3}
#> Warming up {4}
#> Warming up {5}
#> Warming up {6}
#> Starting Simulation at 01/14 for WINTERDAY
#> Initializing New Environment Parameters
#> Warming up {1}
#> Warming up {2}
#> Warming up {3}
#> Warming up {4}
#> Warming up {5}
#> Warming up {6}
#> Starting Simulation at 07/07 for SUMMERDAY
#> Writing tabular output file results using HTML format.
#> Writing final SQL reports
#> EnergyPlus Run Time=00hr 00min  2.94sec
#> EnergyPlus Completed Successfully.
job
#> -- EnergyPlus Simulation Job ----------------------------------------------------
#> # Model: `C:\Users\hongy\Desktop\5Zone_Transformer.idf`
#> # Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> # EnergyPlus Version: `8.8.0`
#> # EnergyPlus Path: `C:\EnergyPlusV8-8-0`
#>  Simulation started at `2018-07-15 02:46:38` and completed successfully after 3.48 secs.

Print simulation errors

You can get simulation errors using $errors in EplusJob class.

job$errors()
#> == During Zone Sizing Calculations ==============================================
#> +----------------------------------------------------------------------------------------------------------+
#> |Warning[1/1] Weather file location will be used rather than entered (IDF) Location object.                |
#> |  ..Location object=CHICAGO_IL_USA TMY2-94846                                                             |
#> |  ..Weather File Location=San Francisco Intl Ap CA USA TMY3 WMO#=724940                                   |
#> |  ..due to location differences, Latitude difference=[4.16] degrees, Longitude difference=[34.65] degrees.|
#> |  ..Time Zone difference=[2.0] hour(s), Elevation difference=[98.95] percent, [188.00] meters.            |
#> +----------------------------------------------------------------------------------------------------------+
#> 
#> EnergyPlus completed successfully with 1 Warning.

Retrieve simulation output

eplusr uses the EnergyPlus SQL output for extracting simulation results. In order to do so, a object in Output:SQLite with Option Type value of SimpleAndTabular will be automatically created if it does not exists. EplusJob has provide some wrappers that do SQL query to get report data results, i.e. results from Output:Variable and Output:Meter*. But for Output:Table results, you have to be familiar with the structure of the EnergyPlus SQL results, especially for table “TabularDataWithStrings”. For details, please see “2.20 eplusout.sql”, especially “2.20.4.4 TabularData Table” in EnergyPlus “Output Details and Examples” documentation.

$report_data_dict returns a data.frame which contains all information about report data. For details on the meaning of each columns, please see “2.20.2.1 ReportDataDictionary Table” in EnergyPlus “Output Details and Examples” documentation.

str(job$report_data_dict())
#> Classes 'data.table' and 'data.frame':   20 obs. of  10 variables:
#>  $ ReportDataDictionaryIndex: int  6 8 18 38 238 459 460 461 462 463 ...
#>  $ IsMeter                  : int  0 1 1 1 1 0 0 0 0 0 ...
#>  $ Type                     : chr  "Avg" "Sum" "Sum" "Sum" ...
#>  $ IndexGroup               : chr  "Zone" "Facility:Electricity" "Building:Electricity" "Facility:Electricity:InteriorLights" ...
#>  $ TimestepType             : chr  "HVAC System" "HVAC System" "HVAC System" "HVAC System" ...
#>  $ KeyValue                 : chr  "Environment" "" "" "" ...
#>  $ Name                     : chr  "Site Outdoor Air Drybulb Temperature" "Electricity:Facility" "Electricity:Building" "InteriorLights:Electricity" ...
#>  $ ReportingFrequency       : chr  "Zone Timestep" "Zone Timestep" "Zone Timestep" "Zone Timestep" ...
#>  $ ScheduleName             : chr  NA NA NA NA ...
#>  $ Units                    : chr  "C" "J" "J" "J" ...
#>  - attr(*, ".internal.selfref")=<externalptr>

$report_data extracts the report data using key values and variable names. Basically, key_value equals KeyValue and name equals Name in the report data dictionary you get from $report_data_dict.

str(job$report_data(name = "Site Outdoor Air Drybulb Temperature"))
#> Classes 'data.table' and 'data.frame':   192 obs. of  6 variables:
#>  $ Case    : chr  "5Zone_Transformer" "5Zone_Transformer" "5Zone_Transformer" "5Zone_Transformer" ...
#>  $ DateTime: POSIXct, format: "2018-01-14 00:15:00" "2018-01-14 00:30:00" ...
#>  $ KeyValue: chr  "Environment" "Environment" "Environment" "Environment" ...
#>  $ Name    : chr  "Site Outdoor Air Drybulb Temperature" "Site Outdoor Air Drybulb Temperature" "Site Outdoor Air Drybulb Temperature" "Site Outdoor Air Drybulb Temperature" ...
#>  $ Units   : chr  "C" "C" "C" "C" ...
#>  $ Value   : num  9.9 9.2 8.5 7.8 8.07 ...
#>  - attr(*, ".internal.selfref")=<externalptr>

$tabular_data extracts all tabular data. For details on the meaning of each columns, please see “2.20.4.4 TabularData Table” in EnergyPlus “Output Details and Examples” documentation.

str(job$tabular_data())
#> Classes 'data.table' and 'data.frame':   6662 obs. of  8 variables:
#>  $ TabularDataIndex: int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ Value           : chr  "        1.34" "        1.34" "        3.65" "        3.65" ...
#>  $ ReportName      : chr  "AnnualBuildingUtilityPerformanceSummary" "AnnualBuildingUtilityPerformanceSummary" "AnnualBuildingUtilityPerformanceSummary" "AnnualBuildingUtilityPerformanceSummary" ...
#>  $ ReportForString : chr  "Entire Facility" "Entire Facility" "Entire Facility" "Entire Facility" ...
#>  $ TableName       : chr  "Site and Source Energy" "Site and Source Energy" "Site and Source Energy" "Site and Source Energy" ...
#>  $ RowName         : chr  "Total Site Energy" "Net Site Energy" "Total Source Energy" "Net Source Energy" ...
#>  $ ColumnName      : chr  "Total Energy" "Total Energy" "Total Energy" "Total Energy" ...
#>  $ Units           : chr  "GJ" "GJ" "GJ" "GJ" ...
#>  - attr(*, ".internal.selfref")=<externalptr>

Run Parametric Analysis

eplusr provides tools to do parametric simulations which take full advantages of eplusr’s model editing and result collecting functionalities. You can create a parametric job using param_job, which takes an IDF file or Idf object as the seed and an EPW file or Epw object as input.

param <- param_job(idf = model, epw = epw_sf)

param
#> -- EnergPlus Parametric ---------------------------------------------------------
#> * Seed Model: `C:\Users\hongy\Desktop\5Zone_Transformer.idf`
#> * Default Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> << No measure has been applied >>

param_job returns a ParametricJob object which provides a prototype of conducting parametric analysis of EnergyPlus simulations. For more details, please see ?param.

Apply measure

$apply_measure allows to apply a measure to an Idf and then parametric models will be created for analysis. Basically, a measure is just a function that takes an Idf object and other arguments as input, and returns a modified Idf object as output. Use ... to supply different arguments to that measure.

Let’s create a function that modifies infiltration rate:

set_infil_rate <- function (idf, infil_rate) {

    # validate input value
    # this is optional, as validations will be made when setting values to `Idf`
    stopifnot(is.numeric(infil_rate), infil_rate >= 0)

    if (!idf$is_valid_class("ZoneInfiltration:DesignFlowRate"))
      stop("Input model does not have any object in class `ZoneInfiltration:DesignFlowRate`")

    ids <- idf$object_id("ZoneInfiltration:DesignFlowRate", simplify = TRUE)

    idf$set_object(ids,
        value = rep(list(list(
            design_flow_rate_calculation_method = "AirChanges/Hour",
            air_changes_per_hour = infil_rate)),
            times = length(ids))
        )

    idf
}

The measure (function) set_infil_rate is pretty simple. First, it gets all objects in class "ZoneInfiltration:DesignFlowRate". Then it sets ACH in all zones as the input value.

Now, let’s use apply this measure to the model with different infiltration rates from 0.0 to 4.0.

param$apply_measure(set_infil_rate, seq(0, 4, by = 1), .names = NULL)
#> Measure `set_infil_rate` has been applied with 5 new models created:
#> 1: set_infil_rate_1
#> 2: set_infil_rate_2
#> 3: set_infil_rate_3
#> 4: set_infil_rate_4
#> 5: set_infil_rate_5

As we can see, 5 models have been create. As we left .names as NULL, each newly created models will be named as a combination of measure name and model number.

Run in parallel and collect results

Now let’s run the parametric job. All simulations will be run in parallel. The number of parallel EnergyPlus processes can be specified using option "num_parallel".

param$run()
#> 
 Progress: ---------------------------------------                           100%
 Progress: ---------------------------------------                           100%
 Progress: ---------------------------------------                           100%
 Progress: ---------------------------------------                           100%
 Progress: ----------------------------------------------------              100%
 Progress: ----------------------------------------------------              100%
 Progress: ----------------------------------------------------------------- 100%
#> $set_infil_rate_1
#> -- EnergyPlus Simulation Job ----------------------------------------------------
#> # Model: `C:\Users\hongy\Desktop\set_infil_rate_1\set_infil_rate_1.idf`
#> # Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> # EnergyPlus Version: `8.8.0`
#> # EnergyPlus Path: `C:\EnergyPlusV8-8-0`
#>  Simulation started at `2018-07-15 02:46:45` and completed successfully after 17.48 secs.
#> 
#> $set_infil_rate_2
#> -- EnergyPlus Simulation Job ----------------------------------------------------
#> # Model: `C:\Users\hongy\Desktop\set_infil_rate_2\set_infil_rate_2.idf`
#> # Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> # EnergyPlus Version: `8.8.0`
#> # EnergyPlus Path: `C:\EnergyPlusV8-8-0`
#>  Simulation started at `2018-07-15 02:46:45` and completed successfully after 17.48 secs.
#> 
#> $set_infil_rate_3
#> -- EnergyPlus Simulation Job ----------------------------------------------------
#> # Model: `C:\Users\hongy\Desktop\set_infil_rate_3\set_infil_rate_3.idf`
#> # Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> # EnergyPlus Version: `8.8.0`
#> # EnergyPlus Path: `C:\EnergyPlusV8-8-0`
#>  Simulation started at `2018-07-15 02:46:45` and completed successfully after 17.48 secs.
#> 
#> $set_infil_rate_4
#> -- EnergyPlus Simulation Job ----------------------------------------------------
#> # Model: `C:\Users\hongy\Desktop\set_infil_rate_4\set_infil_rate_4.idf`
#> # Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> # EnergyPlus Version: `8.8.0`
#> # EnergyPlus Path: `C:\EnergyPlusV8-8-0`
#>  Simulation started at `2018-07-15 02:46:45` and completed successfully after 17.48 secs.
#> 
#> $set_infil_rate_5
#> -- EnergyPlus Simulation Job ----------------------------------------------------
#> # Model: `C:\Users\hongy\Desktop\set_infil_rate_5\set_infil_rate_5.idf`
#> # Weather: `C:\Users\hongy\Desktop\San_Francisco.epw`
#> # EnergyPlus Version: `8.8.0`
#> # EnergyPlus Path: `C:\EnergyPlusV8-8-0`
#>  Simulation started at `2018-07-15 02:46:45` and completed successfully after 17.48 secs.

After all simulations completed, let’s see the variations of total energy.

tab <- param$tabular_data()

total_eng <- tab[TableName == "Site and Source Energy" &
    ColumnName == "Total Energy" &
    RowName == "Total Site Energy",
    list(Case, `Total Energy (GJ)` = as.numeric(Value))]
total_eng
CaseTotal Energy (GJ)
set_infil_rate_11.33
set_infil_rate_21.35
set_infil_rate_31.36
set_infil_rate_41.38
set_infil_rate_51.39

Related Project

Author

Hongyuan Jia

Faculty of Urban Construction and Environmental Engineering, Chongqing University

Copy Link

Version

Down Chevron

Install

install.packages('eplusr')

Monthly Downloads

602

Version

0.8.2

License

GPL-3

Maintainer

Last Published

July 22nd, 2018

Functions in eplusr (0.8.2)