-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrap ZoneHVAC:EvaporativeCoolerUnit #215
base: develop
Are you sure you want to change the base?
Changes from all commits
be72603
fa5ae45
75f4ccc
96801a1
9eaada9
f16dda8
516030d
9670dce
f90ba33
9c626d4
0299faf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from itertools import product | ||
|
||
import openstudio | ||
from lib.baseline_model import BaselineModel | ||
|
||
model = BaselineModel() | ||
|
||
# make a 8 stories, 100m X 50m, 8 zones building | ||
model.add_geometry(length=100, width=50, num_floors=8, floor_to_floor_height=4, plenum_height=0, perimeter_zone_depth=0) | ||
|
||
# add windows at a 40% window-to-wall ratio | ||
model.add_windows(wwr=0.4, offset=1, application_type="Above Floor") | ||
|
||
# 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 thermostats | ||
model.add_thermostats(heating_setpoint=19, cooling_setpoint=26) | ||
|
||
|
||
def make_zone_hvac_cooler( | ||
z: openstudio.model.ThermalZone, | ||
direct_is_first: bool = False, | ||
add_secondary: bool = True, | ||
fan_placement: str = "BlowThrough", | ||
): | ||
model = z.model() | ||
indirect_evap = None | ||
direct_evap = None | ||
if direct_is_first: | ||
# There is a default ctor | ||
zoneHVACEvaporativeCoolerUnit = openstudio.model.ZoneHVACEvaporativeCoolerUnit(model) | ||
direct_evap = zoneHVACEvaporativeCoolerUnit.firstEvaporativeCooler() | ||
supplyAirFan = zoneHVACEvaporativeCoolerUnit.supplyAirFan() | ||
|
||
fan_system = openstudio.model.FanSystemModel(model) | ||
zoneHVACEvaporativeCoolerUnit.setSupplyAirFan(fan_system) | ||
supplyAirFan.remove() | ||
supplyAirFan = fan_system | ||
# An optional Second EvaporativeCooler | ||
if add_secondary: | ||
indirect_evap = openstudio.model.EvaporativeCoolerIndirectResearchSpecial(model) | ||
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(indirect_evap) | ||
else: | ||
# And an explicit Ctor: | ||
# ZoneHVACEvaporativeCoolerUnit(const Model& model, Schedule& availabilitySchedule, HVACComponent& supplyAirFan, HVACComponent& firstEvaporativeCooler); | ||
supplyAirFan = openstudio.model.FanSystemModel(model) | ||
|
||
indirect_evap = openstudio.model.EvaporativeCoolerIndirectResearchSpecial(model) | ||
zoneHVACEvaporativeCoolerUnit = openstudio.model.ZoneHVACEvaporativeCoolerUnit( | ||
model, model.alwaysOnDiscreteSchedule(), supplyAirFan, indirect_evap | ||
) | ||
# An optional Second EvaporativeCooler | ||
if add_secondary: | ||
direct_evap = openstudio.model.EvaporativeCoolerDirectResearchSpecial( | ||
model, model.alwaysOnDiscreteSchedule() | ||
) | ||
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(direct_evap) | ||
|
||
if indirect_evap is not None: | ||
indirect_evap.setName(f"{z.nameString()} Indirect Evaporative Cooler") | ||
if direct_evap is not None: | ||
direct_evap.setName(f"{z.nameString()} Direct Evaporative Cooler") | ||
|
||
supplyAirFan.setName(f"{z.nameString()} Supply Fan") | ||
zoneHVACEvaporativeCoolerUnit.setName(f"{z.nameString()} Evap Unit") | ||
# zoneHVACEvaporativeCoolerUnit.resetSecondEvaporativeCooler() | ||
# | ||
# Redoing what the default constructor does for demonstration purposes | ||
# zoneHVACEvaporativeCoolerUnit.setDesignSupplyAirFlowRate(1.0) | ||
zoneHVACEvaporativeCoolerUnit.autosizeDesignSupplyAirFlowRate() | ||
zoneHVACEvaporativeCoolerUnit.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule()) | ||
zoneHVACEvaporativeCoolerUnit.setFanPlacement(fan_placement) | ||
zoneHVACEvaporativeCoolerUnit.setCoolerUnitControlMethod("ZoneCoolingLoadVariableSpeedFan") | ||
zoneHVACEvaporativeCoolerUnit.setThrottlingRangeTemperatureDifference(1.1) | ||
zoneHVACEvaporativeCoolerUnit.setCoolingLoadControlThresholdHeatTransferRate(100.0) | ||
zoneHVACEvaporativeCoolerUnit.setShutOffRelativeHumidity(100.0) | ||
|
||
# Add it to a ThermalZone | ||
zoneHVACEvaporativeCoolerUnit.addToThermalZone(z) | ||
|
||
# Rename nodes for clarity | ||
z.zoneAirNode().setName(f"{z.nameString()} Zone Air Node") | ||
# z.returnAirModelObjects.modelObjects()[0].setName("{z.nameString()} Zone Return Air Node") | ||
z.inletPortList().modelObjects()[0].setName(f"{z.nameString()} Zone Air Inlet Node") | ||
z.exhaustPortList().modelObjects()[0].setName(f"{z.nameString()} Zone Air Exhaust Node") | ||
|
||
return zoneHVACEvaporativeCoolerUnit | ||
|
||
|
||
# In order to produce more consistent results between different runs, | ||
# we sort the zones by names | ||
zones = sorted(model.getThermalZones(), key=lambda z: z.nameString()) | ||
|
||
configs = [ | ||
{"zone_name": "DirectFirst", "direct_is_first": True, "add_secondary": True}, | ||
# Mimic SMStore8 from StripMallZoneEvapCoolerAutosized.idf | ||
# https://github.com/NREL/EnergyPlus/blob/31e3c33467c5873371bf48b12a7318215971c315/testfiles/StripMallZoneEvapCoolerAutosized.idf#L4767-L4784 | ||
{"zone_name": "IndirectFirst", "direct_is_first": False, "add_secondary": True}, | ||
{"zone_name": "DirectOnly", "direct_is_first": True, "add_secondary": False}, | ||
{"zone_name": "IndirectOnly", "direct_is_first": False, "add_secondary": False}, | ||
] | ||
fan_placements = ["BlowThrough", "DrawThrough"] | ||
assert len(configs) * len(fan_placements) == len(zones) | ||
|
||
for (config, fan_placement), z in zip(product(configs, fan_placements), zones): | ||
z.setName(f"{config['zone_name']} {fan_placement} Zn") | ||
make_zone_hvac_cooler( | ||
z=z, | ||
direct_is_first=config["direct_is_first"], | ||
add_secondary=config["add_secondary"], | ||
fan_placement=fan_placement, | ||
) | ||
|
||
# save the OpenStudio model (.osm) | ||
model.save_openstudio_osm(osm_save_directory=None, osm_name="in.osm") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'openstudio' | ||
require_relative 'lib/baseline_model' | ||
|
||
model = BaselineModel.new | ||
|
||
# make a 8 stories, 100m X 50m, 8 zone building | ||
model.add_geometry({ 'length' => 100, | ||
'width' => 50, | ||
'num_floors' => 8, | ||
'floor_to_floor_height' => 4, | ||
'plenum_height' => 0, | ||
'perimeter_zone_depth' => 0 }) | ||
Comment on lines
+8
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because I found the node connections to be broken, I'm using 8 zones... |
||
|
||
# add windows at a 40% window-to-wall ratio | ||
model.add_windows({ 'wwr' => 0.4, | ||
'offset' => 1, | ||
'application_type' => 'Above Floor' }) | ||
|
||
# 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 thermostats | ||
model.add_thermostats({ 'heating_setpoint' => 24, | ||
'cooling_setpoint' => 28 }) | ||
|
||
def make_zone_hvac_cooler(z, direct_is_first: false, add_secondary: true, fan_placement: 'BlowThrough') | ||
model = z.model | ||
indirect_evap = nil | ||
direct_evap = nil | ||
if direct_is_first | ||
# There is a default ctor | ||
zoneHVACEvaporativeCoolerUnit = OpenStudio::Model::ZoneHVACEvaporativeCoolerUnit.new(model) | ||
direct_evap = zoneHVACEvaporativeCoolerUnit.firstEvaporativeCooler | ||
supplyAirFan = zoneHVACEvaporativeCoolerUnit.supplyAirFan | ||
|
||
fan_system = OpenStudio::Model::FanSystemModel.new(model) | ||
zoneHVACEvaporativeCoolerUnit.setSupplyAirFan(fan_system) | ||
supplyAirFan.remove | ||
supplyAirFan = fan_system | ||
# An optional Second EvaporativeCooler | ||
if add_secondary | ||
indirect_evap = OpenStudio::Model::EvaporativeCoolerIndirectResearchSpecial.new(model) | ||
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(indirect_evap) | ||
end | ||
else | ||
# And an explicit Ctor: | ||
# ZoneHVACEvaporativeCoolerUnit(const Model& model, Schedule& availabilitySchedule, HVACComponent& supplyAirFan, HVACComponent& firstEvaporativeCooler); | ||
supplyAirFan = OpenStudio::Model::FanSystemModel.new(model) | ||
|
||
indirect_evap = OpenStudio::Model::EvaporativeCoolerIndirectResearchSpecial.new(model) | ||
zoneHVACEvaporativeCoolerUnit = OpenStudio::Model::ZoneHVACEvaporativeCoolerUnit.new( | ||
model, model.alwaysOnDiscreteSchedule, supplyAirFan, indirect_evap | ||
) | ||
# An optional Second EvaporativeCooler | ||
if add_secondary | ||
direct_evap = OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial.new(model, model.alwaysOnDiscreteSchedule) | ||
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(direct_evap) | ||
end | ||
end | ||
indirect_evap&.setName("#{z.nameString} Indirect Evaporative Cooler") | ||
direct_evap&.setName("#{z.nameString} Direct Evaporative Cooler") | ||
supplyAirFan.setName("#{z.nameString} Supply Fan") | ||
zoneHVACEvaporativeCoolerUnit.setName("#{z.nameString} Evap Unit") | ||
# zoneHVACEvaporativeCoolerUnit.resetSecondEvaporativeCooler | ||
# | ||
# Redoing what the default constructor does for demonstration purposes | ||
# zoneHVACEvaporativeCoolerUnit.setDesignSupplyAirFlowRate(1.0) | ||
zoneHVACEvaporativeCoolerUnit.autosizeDesignSupplyAirFlowRate | ||
zoneHVACEvaporativeCoolerUnit.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule) | ||
zoneHVACEvaporativeCoolerUnit.setSupplyAirFan(zoneHVACEvaporativeCoolerUnit.supplyAirFan) | ||
zoneHVACEvaporativeCoolerUnit.setFanPlacement(fan_placement) | ||
zoneHVACEvaporativeCoolerUnit.setCoolerUnitControlMethod('ZoneCoolingLoadVariableSpeedFan') | ||
zoneHVACEvaporativeCoolerUnit.setThrottlingRangeTemperatureDifference(1.1) | ||
zoneHVACEvaporativeCoolerUnit.setCoolingLoadControlThresholdHeatTransferRate(100.0) | ||
zoneHVACEvaporativeCoolerUnit.setShutOffRelativeHumidity(100.0) | ||
|
||
# Add it to a ThermalZone | ||
zoneHVACEvaporativeCoolerUnit.addToThermalZone(z) | ||
|
||
# Rename nodes for clarity | ||
z.zoneAirNode.setName("#{z.nameString} Zone Air Node") | ||
# z.returnAirModelObjects.modelObjects[0].setName("#{z.nameString} Zone Return Air Node") | ||
z.inletPortList.modelObjects[0].setName("#{z.nameString} Zone Air Inlet Node") | ||
z.exhaustPortList.modelObjects[0].setName("#{z.nameString} Zone Air Exhaust Node") | ||
end | ||
Comment on lines
+34
to
+93
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Helper to create a specific configuration |
||
|
||
# In order to produce more consistent results between different runs, | ||
# we sort the zones by names | ||
zones = model.getThermalZones.sort_by { |z| z.name.to_s } | ||
|
||
configs = [ | ||
{ zone_name: 'DirectFirst', direct_is_first: true, add_secondary: true }, | ||
|
||
# Mimic SMStore8 from StripMallZoneEvapCoolerAutosized.idf | ||
# https://github.com/NREL/EnergyPlus/blob/31e3c33467c5873371bf48b12a7318215971c315/testfiles/StripMallZoneEvapCoolerAutosized.idf#L4767-L4784 | ||
{ zone_name: 'IndirectFirst', direct_is_first: false, add_secondary: true }, | ||
|
||
{ zone_name: 'DirectOnly', direct_is_first: true, add_secondary: false }, | ||
|
||
{ zone_name: 'IndirectOnly', direct_is_first: false, add_secondary: false } | ||
] | ||
fan_placements = ['BlowThrough', 'DrawThrough'] | ||
raise 'Mismatch' unless configs.size * fan_placements.size == zones.size | ||
|
||
configs.product(fan_placements).zip(zones).each do |(config, fan_placement), z| | ||
z.setName("#{config[:zone_name]} #{fan_placement} Zn") | ||
make_zone_hvac_cooler( | ||
z, | ||
direct_is_first: config[:direct_is_first], | ||
add_secondary: config[:add_secondary], | ||
fan_placement: fan_placement | ||
) | ||
end | ||
Comment on lines
+95
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing 8 combinations: for each of these four, I test BlowThrough + DrawThrough
|
||
|
||
# save the OpenStudio model (.osm) | ||
model.save_openstudio_osm({ 'osm_save_directory' => Dir.pwd, | ||
'osm_name' => 'in.osm' }) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2147,6 +2147,19 @@ def test_zone_hvac_cooling_panel_osm | |
result = sim_test('zone_hvac_cooling_panel.osm') | ||
end | ||
|
||
def test_zone_hvac_evaporative_cooler_rb | ||
result = sim_test('zone_hvac_evaporative_cooler.rb') | ||
end | ||
|
||
def test_zone_hvac_evaporative_cooler_py | ||
result = sim_test('zone_hvac_evaporative_cooler.py') | ||
end | ||
|
||
# TODO: To be added in the next official release after: 3.9.0 | ||
# def test_zone_hvac_evaporative_cooler_osm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MISSING the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
# result = sim_test('zone_hvac_evaporative_cooler.osm') | ||
# end | ||
|
||
def test_zone_hvac_equipment_list_rb | ||
result = sim_test('zone_hvac_equipment_list.rb') | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to the autosize_hvac! Which told me the method was not implemented correctly so did NREL/OpenStudio@c969110