EnergyPlus Scripting and epJSON
IDF
Using scripts to manipulate EnergyPlus input files can be an incredibly powerful way to automate the model development process. Until recently, EnergyPlus input files were formatted exclusively in Input Data File (IDF). IDF is a text file that is structured as a list of input objects, where each object has a number of comma-separated fields/parameters associated with it, ending in a semi-colon. The image below shows the Building object from the example file "1ZoneUncontrolled.idf".
In IDF, the order of the fields matter. The field descriptions (which start with "!-") are really just comments or annotations; they only serve to help the user identify the field order and are not actually used by EnergyPlus. The object above could just as easily be specified as a set of comma-separated values in a single line, such as:
IDF Scripting
Common scripting languages like Python and Ruby are able to read IDF files line-by-line, like any other ASCII text file, but are unable to interpret the blocks of comma-separated fields as objects. Without using a specialized parsing library, writing scripts to modify IDF fields is a tedious and inefficient endeavor.
For example, let's say we want to write a Python script, using only the Python Standard Library, to change the 'North Axis' field in the 'Building' object (above) from 0 to 45 (degrees). We could write a script similar to below, where we open the IDF and read line-by-line until we read the "-! North Axis" field description, at which point we substitute the text that we want to replace that line:
The drawbacks of this approach are quite apparent even to the novice programmer. First, it relies on the field descriptions being present (and written in a camel case), which are not required for the simulation and are often missing or vary (in case or units) depending on how the model was developed. Secondly, this method is fairly inefficient as it requires the entire file to be read and copied line-by-line in order to make a two-character substitution. Luckily, there is only one instance in this IDF where the words "North Axis" exist. Other field descriptions (e.g. "Cooling Design Capacity") could be found in numerous lines within an IDF, so this approach would not work. Improvements could be made to search instead for the object's Class name, then loop through each field and do a line substitution with some logic. But there is no great way to write a script to manipulate IDFs using only standard libraries.
Luckily, several open-source libraries have been developed to facilitate reading and modifing IDF files in a conveinient, object-oriented approach without the drawbacks illustrated above.
eppy
A popular Python library for EnergyPlus is called eppy (EnergyPlus PYthon), developed by Santosh Philip. Using the eppy library, a Python script that changes the North Axis field to '45' is shown below.
Scripting libraries like eppy use the EnergyPlus IDD (input data dictionary) to create a data structure called a 'dictionary' in Python or, more generically, a 'hash table' containing each EnergyPlus Class along with all the relevant data for that class, including the number of fields, field descriptions, valid data types for each field, etc. Since the field descriptions and number of fields can change with each version of EnergyPlus, it is important that the IDD is associated with the same version of EnergyPlus as in the IDF.
The IDD file is specified in the first two lines in the script above, immediately following the library imports. A shortcut method for setting the IDD is to use the easyopen function. As long as the IDF contains a Version object and EnergyPlus is installed on your machine in the standard directory, we can re-write the script above more succinctly using easyopen:
Both of the scripts above save a new file ("1ZoneUncontrolled_out.idf") which is substantively identical to the original example file, except with the North Axis changed to 45 degrees. The reason I said "substantively identical" is because eppy sorts the file prior to saving it, which removes all comments and groups all objects by class. This is similar to how IDFEditor saves IDFs when the "Sorted" option is selected for "Save Order of Objects". Sorting provides a consistent format which is helpful for viewing differences between two sorted files. To my knowledge, it is not possible to save IDFs in eppy without sorting.
Modelkit
Modelkit (formerly called Params) is a Ruby framework for parametric modeling, developed by Big Ladder Software. Modelkit is probably better known for its templating system for composing new IDFs, but Modelkit also contains a scripting library that can be used for reading and modifying existing IDF files. Unlike Eppy, Modelkit does not delete comments or sort objects when saving the IDF. Using the Modelkit library, a Ruby script that changes the North Axis field to '45' is shown below.
A key difference between this Modelkit script and the eppy scripts above: eppy uses the field description to access and change field values, whereas Modelkit uses the field number to access and change field values:
eppy:
Modelkit:
Using field descriptions instead of field numbers is arguably more convenient for accessing field values, since field number/order changes are more common between versions of EnergyPlus. The field_number_lookup method in the script below takes arguments of class_name and field_def and returns the field number. Using this method to lookup field numbers allows the North Axis field to be changed based on the field description instead of the field number.
You may notice the use of an OpenStudio library in the Modelkit scripts above. The history of Modelkit goes back to early versions of OpenStudio. Before the conception of the OpenStudio Model (.osm), OpenStudio was a Ruby library that worked directly with IDF, including the OpenStudio Sketchup plugin, which allowed users to create, edit, and save IDF geometry. When OpenStudio began using OSM as an intermediary to IDF, the 'old' OpenStudio was referred to as 'Legacy OpenStudio' and its continued maintenance and development was granted to Big Ladder Software. Big Ladder has developed the Sketchup plugin, renamed it Euclid, and the legacy OpenStudio scripting library is now incorporated into the Modelkit framework.
epJSON
Since the release of version 9.6, EnergyPlus supports input files formatted in epJSON (EnergyPlus JSON), in addition to IDF. Converting between IDF and epJSON is trivial, and can be executed at the command line with:
C:\EnergyPlusV22-1-0\energyplus --convert-only filenameIn this case, filename can be either an epJSON or an IDF; the command will convert the file type into the other type (e.g. epJSON files will be converted to IDF and vice versa).
A convenient way to convert EnergyPlus input file types in Windows is to create a batch file. The batch file below allows the user to drag-and-drop an IDF or epJSON onto the batch file, and the corresponding file with the other format and extension will be generated.
The image below shows the IDF format on the left and the epJSON format on the right. epJSON structure and syntax is similar to a Python dictionary, with EnergyPlus Classes as keys.
A Python dictionary can be generated from the epJSON file using the 'json' library, which is included in the Python Standard Library. JSON (JavaScript Object Notation) is a widely used data-interchange format for which there are reliable parsers that come with the standard libraries of all modern scripting languages, including Python and Ruby. This means that we can write scripts to manipulate epJSON files using only standard libraries with similar fluency as using 3rd-party libraries like eppy and Modelkit. A Python script that changes the North Axis field to '45', using only the 'json' library is shown below.
Similarly, a Ruby script that changes the North Axis field to '45', using only the 'json' library is shown below.
The scripts above are not only shorter and simpler than the IDF scripts, but are also computationally more efficient because they don't require parsing the IDD. One could argue that the IDF parsers are now obsolete, because one can easily convert the IDF to epJSON, execute whatever scripts are neccessary on the epJSON, and convert back to IDF, if neccessary. The downside of converting from IDF to epJSON and back to IDF, is that all comments and field descriptions are deleted and objects will be sorted by class alphabetically. An additional script could be used to re-sort the objects and restore the field descriptions, but comments are permanently lost when an IDF is converted to epJSON.