Co-simulation between two models requires the use (and often the development!) of middleware to homogenize the data structures (especially for the exchanged variables). The use of a common data standard allows to avoid this problem, so here is a tutorial on EnergyPlus/Python coupling to FMI format realized by EnergyPlusToFMU (Windows installation).

Prerequisite (to install in that order!):

EnergyPlusToFMU requires a specific configuration after installation. In order to activate the Python environment within JModelica, the following command need to be run in the Windows command line terminal (cmd):

C:\> <path-to-JModelica-install>\Python64.bat

It is recommended to create a permanent alias for the Python environment of JModelica. Once the environment is activated, it becomes possible to onvert a .idf file to a .FMU one, with the following instruction (Windows command line terminal):

C:\> <path-to-JModelica-install>\Python64.bat <path-to-scripts-subdir>  \
        -i <path-to-idd-file> -w <path-to-weather-file> -a <fmi-version> <path-to-idf-file>

It is important to clearly define the exchanged variables from the .idf file before it conversion to a .FMU file, according the the procedure explained in the External Interface Application . The .FMU is now ready to interact with the other models (Python script, JModelica model, other .FMUs…).

We can then use an IDE allowing to easily change Python interpreter (PyCharm is warmly recommended) and use PyFMI, included in JModelica’s Python version, to run a cosimulation:

lancement python
Python run / JModelica

param IDE
IDE (PyCharm) settings for the proper environment

A first script as an example to adapt:

import os
from pymodelica import compil_fmu
from pyfmi import load_fmu
import matplotlib.pyplot as plt

# Add EnergyPLus cli script to $PATH, not neeeded if already in $PATH
os.environ['PATH'] = os.environ['PATH'] + ":/EnergyPlus-v9-4-0"

# Load `.fmu` with pyfmi
fmu_path = "<path>/<file.FMU>"
model = load_fmu(fmu=fmu_path)

# Change Input variable (default in `.idf` is given to be 6)
model.set("<variale_name>", <value>)

# Set number of communication points dependent on "final_time" and `.idf`
# steps per hour
final_time = <max_duration> # 72 jour simulation
idf_steps_per_hour = <step_length>
ncp = final_time / (3600. / idf_steps_per_hour)
opts["ncp"] = ncp

# Run simulation and return results
res = model.simulate(start_time=0., final_time=final_time, options=opts)
# Show result variables names