Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

API Python examples of Data Transfer in EnergyPlus

Hi everyone. I have been working for a while trying to call Python scripts during a simulation to perform some calculations to then override some actuators. However, I am stuck with some issues. I’ll appreciate your advice and/or examples on these topics:

1) I know certain variables cannot be actuated; however, when I actuated over “Outdoor Relative Humidity” during “begin_zone_timestep_before_set_current_weather” (which theoretically can be actuated), I do not get different results in my simulations. How can I know which variable can be actuated and the specific calling point to perform these tasks?

2) I would like to know if there is a way to save the outputs of the API python functions as part of the output variable or output meter reports. Since the length of the arrays or data frames are unknown, I do not know how to collect the time step generated data while running a callback function.

3) Where can I find an example of how to return variables from a call-back function at a specific calling point to be used with another python function or callback function into a further calling point. In summary, I am having trouble returning values to other functions at different calling points.

Thank you for your advice in advance.

API Python examples of Data Transfer in EnergyPlus

Hi everyone. I have been working for a while trying to call Python scripts during a simulation to perform some calculations to then override some actuators. However, I am stuck with some issues. I’ll appreciate your advice and/or examples on these topics:

1) I know certain variables cannot be actuated; however, when I actuated over “Outdoor Relative Humidity” during “begin_zone_timestep_before_set_current_weather” (which theoretically can be actuated), I do not get different results in my simulations. How can I know which variable can be actuated and the specific calling point to perform these tasks?

2) I would like to know if there is a way to save the outputs of the API python functions as part of the output variable or output meter reports. Since the length of the arrays or data frames are unknown, I do not know how to collect the time step generated data while running a callback function.

3) Where can I find an example of how to return variables from a call-back function at a specific calling point to be used with another python function or callback function into a further calling point. In summary, I am having trouble returning values to other functions at different calling points.

Thank you for your advice in advance.

API Python examples of Data Transfer in EnergyPlus

Hi everyone. Thank you for your response. Now I have been working for a while better understanding of how to use sensors and actuators. However, I still have other issues, I will try to give good detail in my questions.

1) In my simulations, I am using the API to “Call EnergyPlus as a library”, so from my understanding I cannot use global variables because they are meant to work with Python Plugin applications, right?

2) What I’m trying to call Python scripts during do is to model different configurations of dehumidification devices. Thus, the idea is to get air properties from the weather variables, run a simulation to perform some calculations to then override some actuators. However, I am stuck with some issues. I’ll appreciate your advice and/or examples on these topics:

1) I know certain variables cannot be actuated; however, when I actuated over “Outdoor Relative Humidity” during “begin_zone_timestep_before_set_current_weather” (which theoretically can be actuated), I do not get different results in my simulations. How can I know which variable can be actuated and the specific calling point to perform these tasks?

2) script to calculate the parameters of the dehumidification device, including the properties of the dehumidified air. Then I would like to know if there is a way to save the send these outputs of the API python to the simulation again to continue with the calculations of the HVAC equipment. Could be performed something like this?

3) From my understanding, when using callbacks, those are meant to callback only one function, so, should I use nested functions as part of the output variable or output meter reports. Since the length of the arrays or data frames are unknown, I do not know how to collect the time step generated data while running a callback function.

3) Where can I find an example of how to return variables from a call-back function at a specific calling point to be used with another python function or callback function into a further calling point. for these purposes?

In summary, I am having trouble I'm planning to use the Python API as "bypass" during the simulation by getting data, performing calculations, and then returning values to other functions at different calling points. outputs to continue with the simulation.

Thank you for your advice in advance.

API Python examples of Data Transfer in EnergyPlus

Thank you for your response. Now I have a better understanding of how to use sensors and actuators. However, I still have other issues, I will try to give good detail in my questions.

1) In my simulations, I am using the API to “Call EnergyPlus as a library”, so from my understanding I cannot use global variables because they are meant to work with Python Plugin applications, right?

2) What I’m trying to do is to model different configurations of dehumidification devices. Thus, the idea is to get air properties from the weather variables, run a script to calculate the parameters of the dehumidification device, including the properties of the dehumidified air. Then I would like to send these outputs to the simulation again to continue with the calculations of the HVAC equipment. Could be performed something like this?

3) From my understanding, when using callbacks, those are meant to callback only one function, so, should I use nested functions for these purposes?

In summary, I'm planning to use the Python API as "bypass" during the simulation by getting data, performing calculations, and then returning outputs to continue with the simulation.

Thank you for your advice in advance.

API Python examples of Data Transfer in EnergyPlus

Thank you again for your response. Now responses. I have am attaching the Python script and the list of actuators for a better understanding understanding.

1) My goal is to override the air properties at the inlet of how the AHUs (not the weather file). Thus, from the available API data list of the simulation, I chose all the actuators related to the “Outdoor Air System Node” to perform the override of the Wet bulb temperature, which are (…._OAINLET NODE, …._COOLC COND OA NODE, … _COOLCOA REF NODE) and I used almost all the calling points. However, I could not get any satisfactory overrideC:\fakepath\Actuators.png.

class AverageZoneCalcs(EnergyPlusPlugin):

def __init__(self):
    super().__init__()
    self.do_setup = True

def on_end_of_zone_timestep_before_zone_reporting(self, state) -> int:
    if self.do_setup:
        self.data["zone_volumes"] = []
        self.data["zone_temps"] = []
        self.data["zone_humidity_ratios"] = []
        zone_names = ["Perimeter_top_ZN_" + str(i) for i in range(1, 5)] + ["Perimeter_mid_ZN_" + str(i) for i in range(1, 5)] + ["Perimeter_bot_ZN_" + str(i) for i in range(1, 5)] + ["Core_bottom", "TopFloor_Plenum", "MidFloor_Plenum", "FirstFloor_Plenum", "Core_mid", "Core_top"]
        for zone_name in zone_names: 
            handle = self.api.exchange.get_internal_variable_handle(state, "Zone Air Volume", zone_name)
            zone_volume = self.api.exchange.get_internal_variable_value(state, handle)
            self.data["zone_volumes"].append(zone_volume)
            self.data["zone_temps"].append(
                self.api.exchange.get_variable_handle(state, "Zone Mean Air Temperature", zone_name)
            )
            self.data["zone_humidity_ratios"].append(
                self.api.exchange.get_variable_handle(state, "Zone Mean Air Humidity Ratio", zone_name)
            )
        self.data["avg_temp_variable"] = self.api.exchange.get_global_handle(state, "AverageBuildingTemp")
        self.data["avg_hum_ratio_variable"] = self.api.exchange.get_global_handle(state, "AverageBuildingHR")
        self.do_setup = False
    zone_temps = list()
    zone_humidity_ratios = list()
    for t_handle in self.data["zone_temps"]:
        zone_temps.append(self.api.exchange.get_variable_value(state, t_handle))
    for hr_handle in self.data["zone_humidity_ratios"]:
        zone_humidity_ratios.append(self.api.exchange.get_variable_value(state, hr_handle))
    numerator_t  = 0.0
    numerator_hr = 0.0
    denominator = 0.0
    for i in range(5):
        numerator_t += self.data["zone_volumes"][i] * zone_temps[i]
        numerator_hr += self.data["zone_volumes"][i] * zone_humidity_ratios[i]
        denominator += self.data["zone_volumes"][i]
    average_temp = numerator_t / denominator
    average_HR = numerator_hr / denominator
    self.api.exchange.set_global_value(state, self.data["avg_temp_variable"], average_temp)
    self.api.exchange.set_global_value(state, self.data["avg_hum_ratio_variable"], average_HR)
    return 0

class Dehumidifier(EnergyPlusPlugin):

def __init__(self):
    super().__init__()
    self.need_to_get_handles = True
    self.handles = {}
    self.values = {}
    self.psych = None
    self.OA_DBT_handle = None
    self.OA_WBT_handle = None
    self.Patm_handle = None
    self.WBT_override_handle = None

def get_handles(self, state):
    if self.need_to_get_handles:
        self.handles["OA_DBT"] = self.api.exchange.get_variable_handle(
            state,
            "Site Outdoor Air Drybulb Temperature",
            "Environment"
            )
        self.handles["OA_WBT"] = self.api.exchange.get_variable_handle(
            state,
            "Site Outdoor Air Wetbulb Temperature",
            "Environment"
            )
        self.handles["Patm"] = self.api.exchange.get_variable_handle(
            state,
            "Site Outdoor Air Barometric Pressure",
            "Environment"
            )
        self.handles["PACU_BOT_WBT_override"] = self.api.exchange.get_actuator_handle(
            state,
            "Outdoor Air System Node", 
            "Wetbulb Temperature", 
            "PACU_VAV_BOT_OAINLET NODE"
        )
        self.handles["PACU_MID_WBT_override"] = self.api.exchange.get_actuator_handle(
            state,
            "Outdoor Air System Node", 
            "Wetbulb Temperature", 
            "PACU_VAV_MID_OAINLET NODE"
        )
        self.handles["PACU_TOP_WBT_override"] = self.api.exchange.get_actuator_handle(
            state,
            "Outdoor Air System Node", 
            "Wetbulb Temperature", 
            "PACU_VAV_TOP_OAINLET NODE"
        )

    self.need_to_get_handles = False

def handles_are_valid(self, state):
    handles_are_valid = True
    for (k, v) in self.handles.items():
        if v == -1:
            handles_are_valid = False
            print(k, v)
            self.api.runtime.issue_severe(state, f"Handle not found for '{k}'")
    return handles_are_valid

def OA_inlet_manager(self, state):
    if not self.psych:
        self.psych = self.api.functional.psychrometrics(state)

    self.values["OA_DBT"] = self.api.exchange.get_variable_value(state, self.handles["OA_DBT"])
    self.values["OA_WBT"] = self.api.exchange.get_variable_value(state, self.handles["OA_WBT"])
    self.values["Patm"] = self.api.exchange.get_variable_value(state, self.handles["Patm"])

    OA_DBT = self.values["OA_DBT"]
    OA_WBT = self.values["OA_WBT"]
    Patm = self.values["Patm"]

    OA_HR = self.psych.humidity_ratio_d(state, OA_DBT, OA_WBT, Patm)

    if OA_HR >= 0.0092:
        HR_deh = 0.0092
        WBT_in = self.psych.wet_bulb(state, OA_DBT, HR_deh, Patm)

        self.api.exchange.set_actuator_value(state, self.handles["PACU_BOT_WBT_override"], WBT_in ) 
        self.api.exchange.set_actuator_value(state, self.handles["PACU_MID_WBT_override"], WBT_in ) 
        self.api.exchange.set_actuator_value(state, self.handles["PACU_TOP_WBT_override"], WBT_in ) 

def on_begin_zone_timestep_before_set_current_weather(self, state):
    if not self.api.exchange.api_data_fully_ready(state):
        return 0
    if self.need_to_get_handles:
        self.get_handles(state)
        if not self.handles_are_valid(state):
            return 1
    self.OA_inlet_manager(state)
    return 0

2) As you can see in the script, there is a global variable for the average building humidity ratio which is calculated with a callback function “on_end_of_zone_timestep_before_zone_reporting” in the first class instance, however, I am not able to use sensors and actuators. However, I still have other issues, I will try to give good detail that variable in my questions.the second class instance, which is the one that overrides the air Wet bulb temperature.

1) In my simulations, I am using the API to “Call EnergyPlus as a library”, so from my understanding I cannot use global variables because they are meant to work Could you please help me with Python Plugin applications, right?

2) What I’m trying to do is to model different configurations of dehumidification devices. Thus, the idea is to get air properties from the weather variables, run a script to calculate the parameters of the dehumidification device, including the properties of the dehumidified air. Then I would like to send these outputs to the simulation again to continue with the calculations of the HVAC equipment. Could be performed something like this?

3) From my understanding, when using callbacks, those are meant to callback only one function, so, should I use nested functions for these purposes?

In summary, I'm planning to use the Python API as "bypass" during the simulation by getting data, performing calculations, and then returning outputs to continue with the simulation.issues?

Thank you for your advice in advance.