Motivation

EnergyPlus provides a preprocessor call IDFVersionUpdater to update IDF to the latest version. It is written in Fortran and the program itself evolves along with EnergyPlus. Once a new version of EnergyPlus is published, IDFVersionUpdater will add the support of that version.

The original IDFVersionUpdater program is a GUI program and does not provide command line interface. This makes it hard to update lots of IDF files programmatically. The good news is that IDFVersionUpdater itself is a wrapper to call different standalone transition programs for each single version update. For example, when updating your model from EnergyPlus v8.7 to v8.9, Transition-V8-7-0-to-V8-8-0 will be called, and then Transition-V8-8-0-to-V8-9-0.

Introduce version_updater()

version_updater() is eplusr’s version of IDFVersionUpdater. version_updater() itself is not complicated. Compared to IDFVersionUpdater, version_updater() has some improvements:

  • IDFVersionUpdater in EnergyPlus v9.0 (both v9.0.0 and v9.01) fails to translate FenesreationSurface:Detailed objects. version_updater() will try to use the transition programs that come from the latest EnergyPlus installed on your computer, but will skip v9.0 if possible.

  • Like IDFVersionUpdater, version_updater() also renames all output file with suffix VXY0, where X and Y indicates the major and minor version of input IDF file. However, version_updater() always keep the original input file untouched and save a copy and rename it in the same pattern.

  • All messages generated from each transition program are parsed, stored in a list and saved as an attributes named errors. So that you can easily extract all messages by attr(results, "errors"). The error messages are parsed and stored as data.tables which make it easy for post-processing.

  • A dir argument can be given to further specify where the updated models to be saved.

Unfortunately, even though the transition programs are written in Fortran, it could still take several minutes to complete the update process

path <- "RefBldgLargeOfficeNew2004_Chicago.idf"
read_idf(path)$version()
#> IDD v8.2.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.2.0 installation folder '/usr/local/EnergyPlus-8-2-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.2.0 is not available.
#> Try to locate 'V8-2-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-2-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> [1] '8.2.0'

(t_vu <- system.time(verup <- version_updater(path, 9.2)))
#> IDFVersionUpdater: /usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV820.idf
#>  From  Ver: 8.2.0
#> Toward Ver: 8.3.0
#> [8.2.0 --> 8.3.0] SUCCEEDED.
#> IDD v8.3.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.3.0 installation folder '/usr/local/EnergyPlus-8-3-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.3.0 is not available.
#> Try to locate 'V8-3-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-3-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV830.idf
#>  From  Ver: 8.3.0
#> Toward Ver: 8.4.0
#> [8.3.0 --> 8.4.0] SUCCEEDED.
#> IDD v8.4.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.4.0 installation folder '/usr/local/EnergyPlus-8-4-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.4.0 is not available.
#> Try to locate 'V8-4-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-4-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV840.idf
#>  From  Ver: 8.4.0
#> Toward Ver: 8.5.0
#> [8.4.0 --> 8.5.0] SUCCEEDED.
#> IDD v8.5.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.5.0 installation folder '/usr/local/EnergyPlus-8-5-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.5.0 is not available.
#> Try to locate 'V8-5-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-5-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV850.idf
#>  From  Ver: 8.5.0
#> Toward Ver: 8.6.0
#> [8.5.0 --> 8.6.0] SUCCEEDED.
#> IDD v8.6.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.6.0 installation folder '/usr/local/EnergyPlus-8-6-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.6.0 is not available.
#> Try to locate 'V8-6-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-6-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV860.idf
#>  From  Ver: 8.6.0
#> Toward Ver: 8.7.0
#> [8.6.0 --> 8.7.0] SUCCEEDED.
#> IDD v8.7.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.7.0 installation folder '/usr/local/EnergyPlus-8-7-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.7.0 is not available.
#> Try to locate 'V8-7-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-7-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV870.idf
#>  From  Ver: 8.7.0
#> Toward Ver: 8.8.0
#> [8.7.0 --> 8.8.0] SUCCEEDED.
#> IDD v8.8.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.8.0 installation folder '/usr/local/EnergyPlus-8-8-0'.
#> IDD file found: '/home/travis/.local/EnergyPlus-8-8-0/Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV880.idf
#>  From  Ver: 8.8.0
#> Toward Ver: 8.9.0
#> [8.8.0 --> 8.9.0] SUCCEEDED.
#> IDD v8.9.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v8.9.0 installation folder '/usr/local/EnergyPlus-8-9-0'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v8.9.0 is not available.
#> Try to locate 'V8-9-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V8-9-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV890.idf
#>  From  Ver: 8.9.0
#> Toward Ver: 9.0.0
#> [8.9.0 --> 9.0.0] SUCCEEDED.
#> Multiple versions found for IDD v9.0: 'v9.0.1'. The last patched version v9.0.1 will be used. Please explicitly give the full version if you want to use the other versions.
#> IDD v9.0.1 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v9.0.1 installation folder '/usr/local/EnergyPlus-9-0-1'.
#> Failed to locate 'Energy+.idd' because EnergyPlus v9.0.1 is not available.
#> Try to locate 'V9-0-0-Energy+.idd' in EnergyPlus v9.3.0 IDFVersionUpdater folder '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater'. --> Succeeded
#> IDD file found: '/usr/local/EnergyPlus-9-3-0/PreProcess/IDFVersionUpdater/V9-0-0-Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV900.idf
#>  From  Ver: 9.0.1
#> Toward Ver: 9.1.0
#> [9.0.1 --> 9.1.0] SUCCEEDED.
#> IDD v9.1.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v9.1.0 installation folder '/usr/local/EnergyPlus-9-1-0'.
#> IDD file found: '/home/travis/.local/EnergyPlus-9-1-0/Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#> Input file: /home/travis/build/hongyuanjia/eplusr/vignettes/RefBldgLargeOfficeNew2004_ChicagoV910.idf
#>  From  Ver: 9.1.0
#> Toward Ver: 9.2.0
#> [9.1.0 --> 9.2.0] SUCCEEDED.
#> IDD v9.2.0 has not been parsed before.
#> Try to locate 'Energy+.idd' in EnergyPlus v9.2.0 installation folder '/usr/local/EnergyPlus-9-2-0'.
#> IDD file found: '/home/travis/.local/EnergyPlus-9-2-0/Energy+.idd'.
#> Start parsing...
#> Parsing completed.
#>    user  system elapsed 
#>  91.289   2.336  93.235

Introduce transition()

Having a clear mental model on how the transition works, the most cumbersome work left is to translate all those actions written in Fortran into R and write tests to make sure that the R implement should be the same as IDFVersionUpdater.

transition() is a pure R implementation of transition programs. It takes similar arguments as version_updater() except it has an additional argument save to control whether to save the resultant Idf objects to IDF files or not.

(t_tr <- system.time(trans <- transition(path, 9.2)))
#>  From  Ver: 8.2.0
#> Toward Ver: 8.3.0
#> [8.2.0 --> 8.3.0] SUCCEEDED.
#>  From  Ver: 8.3.0
#> Toward Ver: 8.4.0
#> [8.3.0 --> 8.4.0] SUCCEEDED.
#>  From  Ver: 8.4.0
#> Toward Ver: 8.5.0
#> [8.4.0 --> 8.5.0] SUCCEEDED.
#>  From  Ver: 8.5.0
#> Toward Ver: 8.6.0
#> [8.5.0 --> 8.6.0] SUCCEEDED.
#>  From  Ver: 8.6.0
#> Toward Ver: 8.7.0
#> [8.6.0 --> 8.7.0] SUCCEEDED.
#>  From  Ver: 8.7.0
#> Toward Ver: 8.8.0
#> [8.7.0 --> 8.8.0] SUCCEEDED.
#>  From  Ver: 8.8.0
#> Toward Ver: 8.9.0
#> [8.8.0 --> 8.9.0] SUCCEEDED.
#>  From  Ver: 8.9.0
#> Toward Ver: 9.0.0
#> [8.9.0 --> 9.0.0] SUCCEEDED.
#>  From  Ver: 9.0.0
#> Toward Ver: 9.1.0
#> [9.0.0 --> 9.1.0] SUCCEEDED.
#>  From  Ver: 9.1.0
#> Toward Ver: 9.2.0
#> [9.1.0 --> 9.2.0] SUCCEEDED.
#>    user  system elapsed 
#>   4.481   0.032   4.513

It is about 20.7 times faster.

Fast is always good. The most important thing is to ensure that transition() can provide reasonable results. Here we compare the results.

setdiff(verup$to_string(format = "sorted"), trans$to_string(format = "sorted"))
#> [1] "    Yes,                     !- Use Weather File Snow Indicators"
#> [2] "    ;                        !- Treat Weather as Actual"

As we can see from below, there is only one difference between results from transition() and version_updater():

  • An empty field Treat Weather as Actual in RunPeriod exists in version_updater() version, but not in transition() version. This is because this field is not an required field and eplusr tried to only save minimum-necessary fields.

How the transition works

During version updates, some classes in the original IDF are removed, some classes are splitted into several classes, some fields are removed and there is no way to extract those information back. For example, from EnergyPlus v8.8 to v8.9, one single object in class GroundHeatExchanger:Vertical will be splitted into 4 different objects in class:

  • GroundHeatExchanger:System,
  • GroundHeatExchanger:Vertical:Properties,
  • Site:GroundTemperature:Undisturbed:KusudaAchenbach
  • GroundHeatExchanger:ResponseFactors

A basic transition on a single class is a combination of different transition actions. Below I will describe most typical ones together with the related transition program source code:

The combinations of those four actions together builds a skeleton of an EnergyPlus transition program, together with some pre-processes and post-processes.

In eplusr, all IDF data are stored as data.tables. So transition means to write a function to perform the similar actions on field values stored in data.tables. trans_action() is designed for this purpose.

For example, the equivalent transition implemented in R for Exterior:FuelEquipment objects demonstrated in the Reset code block would be:

# Insert
dt1 <- trans_action(idf, "OtherEquipment", insert = list(2L, "None"))

# Reset
dt2 <- trans_action(idf, "Exterior:FuelEquipment",
    reset = list(2L, "Gas", "NaturalGas"),
    reset = list(2L, "LPG", "PropaneGas")
)

# Delete
dt3 <- trans_action(idf, "HVACTemplate:System:Unitary", delete = list(40L))

# Offset
dt4 <- trans_action(idf, "Daylighting:Controls",
    offset = list(20L, 4L),
    reset = list(3, "SplitFlux")
)

Having the updated IDF data, we can then easily insert them to the next new version of IDF by simply doing new_idf$load(dt).