Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions model/simulationtests/lib/python_plugin_program.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
numerator,denominator
0,0
44 changes: 44 additions & 0 deletions model/simulationtests/lib/python_plugin_program.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from pyenergyplus.plugin import EnergyPlusPlugin

import os, sys
sys.path.append('C:/Python38/Lib/site-packages') # this should (needs to?) be same version as E+'s version
import pandas as pd

class <%= pluginClassName %>(EnergyPlusPlugin):

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

self.df = pd.read_csv(os.path.join(os.path.dirname(__file__), 'python_plugin_program.csv'))

def on_end_of_zone_timestep_before_zone_reporting(self, state) -> int:
if self.do_setup:
self.data['zone_volumes'] = []
self.data['zone_temps'] = []
zone_names = <%= model.getThermalZones.map(&:nameString).sort %>
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['avg_temp_variable'] = self.api.exchange.get_global_handle(state, '<%= py_var.nameString %>')
self.data['trend'] = self.api.exchange.get_trend_handle(state, '<%= py_trend_var.nameString %>')
self.data['running_avg_temp_variable'] = self.api.exchange.get_global_handle(state, '<%= py_var2.nameString %>')
self.do_setup = False
zone_temps = list()
for t_handle in self.data['zone_temps']:
zone_temps.append(self.api.exchange.get_variable_value(state, t_handle))
numerator = float(self.df.iloc[0]['numerator'])
denominator = float(self.df.iloc[0]['denominator'])
for i in range(len(self.data['zone_volumes'])):
numerator += self.data['zone_volumes'][i] * zone_temps[i]
denominator += self.data['zone_volumes'][i]
average_temp = numerator / denominator
self.api.exchange.set_global_value(state, self.data['avg_temp_variable'], average_temp)

past_daily_avg_temp = self.api.exchange.get_trend_average(state, self.data['trend'], 96)
self.api.exchange.set_global_value(state, self.data['running_avg_temp_variable'], past_daily_avg_temp)
return 0
99 changes: 99 additions & 0 deletions model/simulationtests/python_plugin_2.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# frozen_string_literal: true

require 'openstudio'
require_relative 'lib/baseline_model'
require 'tmpdir'
require 'erb'

model = BaselineModel.new

# make a 1 story, 100m X 50m, 5 zone core/perimeter building
model.add_geometry({ 'length' => 100,
'width' => 50,
'num_floors' => 1,
'floor_to_floor_height' => 4,
'plenum_height' => 0,
'perimeter_zone_depth' => 3 })

# assign constructions from a local library to the walls/windows/etc. in the model
model.set_constructions

# set whole building space type; simplified 90.1-2004 Large Office Whole Building
model.set_space_type

# add design days to the model (Chicago)
model.add_design_days

# Add a PythonPlugin:Variable (all OS SDK PythonPluginVariable objects are
# translated to a single E+ PythonPlugin:Variables (extensible object))
py_var = OpenStudio::Model::PythonPluginVariable.new(model)
py_var.setName('AverageBuildingTemp')

# Add a PythonPlugin:OutputVariable for that variable
py_out_var = OpenStudio::Model::PythonPluginOutputVariable.new(py_var)
py_out_var.setName('Averaged Building Temperature')
py_out_var.setTypeofDatainVariable('Averaged')
py_out_var.setUpdateFrequency('ZoneTimestep')
py_out_var.setUnits('C')

# Add a regular Output:Variable that references it
out_var = OpenStudio::Model::OutputVariable.new('PythonPlugin:OutputVariable', model)
out_var.setKeyValue(py_out_var.nameString)
out_var.setReportingFrequency('Timestep')

# Add output variables for Zone Mean Air Temperature, so we can compare
outputVariable = OpenStudio::Model::OutputVariable.new('Zone Mean Air Temperature', model)
outputVariable.setReportingFrequency('Timestep')

# Trend Variable: while this is a fully functioning object, you're probably
# best just using a storage variable on the Python side (eg: a list)
py_trend_var = OpenStudio::Model::PythonPluginTrendVariable.new(py_var)
py_trend_var.setName('Running Averaged Building Temperature')
n_timesteps = 24 * model.getTimestep.numberOfTimestepsPerHour
py_trend_var.setNumberofTimestepstobeLogged(n_timesteps)

py_var2 = OpenStudio::Model::PythonPluginVariable.new(model)
py_var2.setName('RunningAverageBuildingTemp')

py_out_trend_var = OpenStudio::Model::PythonPluginOutputVariable.new(py_var2)
py_out_trend_var.setName('Running Averaged Building Temperature')
py_out_trend_var.setTypeofDatainVariable('Averaged')
py_out_trend_var.setUpdateFrequency('ZoneTimestep')
py_out_trend_var.setUnits('C')

out_trend_var = OpenStudio::Model::OutputVariable.new('PythonPlugin:OutputVariable', model)
out_trend_var.setReportingFrequency('Timestep')

pluginClassName = 'AverageZoneTemps'

# get the python plugin program (erb template)
pluginTemplatePath = File.join(File.dirname(__FILE__), 'lib/python_plugin_program.py')
in_py = ''
File.open(pluginTemplatePath, 'r') do |file|
in_py = file.read
end

dataPath = File.join(File.dirname(__FILE__), 'lib/python_plugin_program.csv')
OpenStudio::Model::ExternalFile.getExternalFile(model, dataPath)

# configure plugin template with variable values
renderer = ERB.new(in_py)
out_py = renderer.result(binding)

# Write it to a temporary directory so we don't pollute the current directory
# ExternalFile will copy it
pluginPath = File.join(Dir.tmpdir, 'python_plugin_program.py')
File.open(pluginPath, 'w') do |file|
file << out_py
end

# create the external file object
external_file = OpenStudio::Model::ExternalFile.getExternalFile(model, pluginPath)
external_file = external_file.get

# create the python plugin instance object
python_plugin_instance = OpenStudio::Model::PythonPluginInstance.new(external_file, pluginClassName)
python_plugin_instance.setRunDuringWarmupDays(false)

# save the OpenStudio model (.osm)
model.save_openstudio_osm({ 'osm_save_directory' => Dir.pwd, 'osm_name' => 'in.osm' })
9 changes: 9 additions & 0 deletions model_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,15 @@ def test_python_plugin_osm
result = sim_test('python_plugin.osm')
end

def test_python_plugin_2_rb
result = sim_test('python_plugin_2.rb')
end

# TODO: To be added in the next official release after: 3.5.0
# def test_python_plugin_2_osm
# result = sim_test('python_plugin_2.osm')
# end

def test_refrigeration_system_rb
result = sim_test('refrigeration_system.rb')
end
Expand Down