From 3ba37a6d3ea7ec804fd46100a135f80b914db2cd Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 14 Jul 2025 19:41:06 -0700 Subject: [PATCH 1/4] Initial add of steam system test file. --- model/simulationtests/zone_hvac3.rb | 112 +++++++++++++++++++ model_tests.rb | 13 +++ test/heatpump_plantloop_eir.rb_3.9.0_out.osw | 4 +- 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 model/simulationtests/zone_hvac3.rb diff --git a/model/simulationtests/zone_hvac3.rb b/model/simulationtests/zone_hvac3.rb new file mode 100644 index 00000000..04988b4f --- /dev/null +++ b/model/simulationtests/zone_hvac3.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +require 'openstudio' +require_relative 'lib/baseline_model' + +model = BaselineModel.new + +# make a 3 story, 100m X 50m, 10 zone core/perimeter building +model.add_geometry({ 'length' => 100, + 'width' => 50, + 'num_floors' => 3, + 'floor_to_floor_height' => 4, + 'plenum_height' => 1, + 'perimeter_zone_depth' => 3 }) + +# add windows at a 40% window-to-wall ratio +model.add_windows({ 'wwr' => 0.4, + 'offset' => 1, + 'application_type' => 'Above Floor' }) + +# add thermostats +model.add_thermostats({ 'heating_setpoint' => 24, + 'cooling_setpoint' => 28 }) + +# Add a hot water plant to supply the baseboard heaters +# This could be baked into HVAC templates in the future +hotSteamPlant = OpenStudio::Model::PlantLoop.new(model) +hotSteamPlant.setName('Hot Steam Plant') +# hotSteamPlant.setFluidType('Steam') + +sizingPlant = hotSteamPlant.sizingPlant +sizingPlant.setLoopType('Heating') +sizingPlant.setDesignLoopExitTemperature(82.0) +sizingPlant.setLoopDesignTemperatureDifference(11.0) + +steamOutletNode = hotSteamPlant.supplyOutletNode +steamInletNode = hotSteamPlant.supplyInletNode + +pump = OpenStudio::Model::PumpVariableSpeedCondensate.new(model) +pump.addToNode(steamInletNode) + +boiler = OpenStudio::Model::BoilerSteam.new(model) +node = hotSteamPlant.supplySplitter.lastOutletModelObject.get.to_Node.get +boiler.addToNode(node) + +pipe = OpenStudio::Model::PipeAdiabatic.new(model) +hotSteamPlant.addSupplyBranchForComponent(pipe) + +pipe2 = OpenStudio::Model::PipeAdiabatic.new(model) +pipe2.addToNode(steamOutletNode) + +## Make a hot Water temperature schedule + +osTime = OpenStudio::Time.new(0, 24, 0, 0) + +steamTempSchedule = OpenStudio::Model::ScheduleRuleset.new(model) +steamTempSchedule.setName('Hot Water Temperature') + +### Winter Design Day +steamTempScheduleWinter = OpenStudio::Model::ScheduleDay.new(model) +steamTempSchedule.setWinterDesignDaySchedule(steamTempScheduleWinter) +steamTempSchedule.winterDesignDaySchedule.setName('Hot Water Temperature Winter Design Day') +steamTempSchedule.winterDesignDaySchedule.addValue(osTime, 67) + +### Summer Design Day +steamTempScheduleSummer = OpenStudio::Model::ScheduleDay.new(model) +steamTempSchedule.setSummerDesignDaySchedule(steamTempScheduleSummer) +steamTempSchedule.summerDesignDaySchedule.setName('Hot Water Temperature Summer Design Day') +steamTempSchedule.summerDesignDaySchedule.addValue(osTime, 67) + +### All other days +steamTempSchedule.defaultDaySchedule.setName('Hot Water Temperature Default') +steamTempSchedule.defaultDaySchedule.addValue(osTime, 67) + +steamSPM = OpenStudio::Model::SetpointManagerScheduled.new(model, steamTempSchedule) +steamSPM.addToNode(steamOutletNode) + +# 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 + +# assign thermal zones to variables +story_1_core_thermal_zone = model.getThermalZoneByName('Story 1 Core Thermal Zone').get +story_1_north_thermal_zone = model.getThermalZoneByName('Story 1 North Perimeter Thermal Zone').get +story_1_south_thermal_zone = model.getThermalZoneByName('Story 1 South Perimeter Thermal Zone').get +story_1_east_thermal_zone = model.getThermalZoneByName('Story 1 East Perimeter Thermal Zone').get +story_1_west_thermal_zone = model.getThermalZoneByName('Story 1 West Perimeter Thermal Zone').get +story_2_core_thermal_zone = model.getThermalZoneByName('Story 2 Core Thermal Zone').get +story_2_north_thermal_zone = model.getThermalZoneByName('Story 2 North Perimeter Thermal Zone').get +story_2_south_thermal_zone = model.getThermalZoneByName('Story 2 South Perimeter Thermal Zone').get +story_2_east_thermal_zone = model.getThermalZoneByName('Story 2 East Perimeter Thermal Zone').get +story_2_west_thermal_zone = model.getThermalZoneByName('Story 2 West Perimeter Thermal Zone').get +story_3_core_thermal_zone = model.getThermalZoneByName('Story 3 Core Thermal Zone').get +story_3_north_thermal_zone = model.getThermalZoneByName('Story 3 North Perimeter Thermal Zone').get +story_3_south_thermal_zone = model.getThermalZoneByName('Story 3 South Perimeter Thermal Zone').get +story_3_east_thermal_zone = model.getThermalZoneByName('Story 3 East Perimeter Thermal Zone').get +story_3_west_thermal_zone = model.getThermalZoneByName('Story 3 West Perimeter Thermal Zone').get + +# Add ZoneHVACBaseboardRadiantConvectiveWater +zoneHVACBaseboardRadiantConvectiveSteam = OpenStudio::Model::ZoneHVACBaseboardRadiantConvectiveSteam.new(model) +baseboard_coil = zoneHVACBaseboardRadiantConvectiveSteam.heatingCoil +hotSteamPlant.addDemandBranchForComponent(baseboard_coil) +zoneHVACBaseboardRadiantConvectiveSteam.addToThermalZone(story_1_core_thermal_zone) + +# save the OpenStudio model (.osm) +model.save_openstudio_osm({ 'osm_save_directory' => Dir.pwd, + 'osm_name' => 'in.osm' }) diff --git a/model_tests.rb b/model_tests.rb index 123f145d..9667dde7 100644 --- a/model_tests.rb +++ b/model_tests.rb @@ -2251,6 +2251,19 @@ def test_zone_hvac2_osm result = sim_test('zone_hvac2.osm') end + def test_zone_hvac3_rb + result = sim_test('zone_hvac3.rb') + end + + # def test_zone_hvac3_py + # result = sim_test('zone_hvac3.py') + # end + + # TODO: To be added in the next official release after: 3.10.0 + # def test_zone_hvac3_osm + # result = sim_test('zone_hvac3.osm') + # end + def test_zone_hvac_cooling_panel_rb result = sim_test('zone_hvac_cooling_panel.rb') end diff --git a/test/heatpump_plantloop_eir.rb_3.9.0_out.osw b/test/heatpump_plantloop_eir.rb_3.9.0_out.osw index 3dca11d5..dcf5e494 100644 --- a/test/heatpump_plantloop_eir.rb_3.9.0_out.osw +++ b/test/heatpump_plantloop_eir.rb_3.9.0_out.osw @@ -2,7 +2,7 @@ "completed_status": "Success", "current_step": 1, "file_paths": [ - "/home/julien/Software/Others/OpenStudio-resources/testruns/heatpump_plantloop_eir.rb/generated_files", + "C:/OpenStudio/OpenStudio-resources/testruns/heatpump_plantloop_eir.rb/generated_files", "./files", "./weather", "../../files", @@ -1568,7 +1568,7 @@ ], "step_warnings": [ "Envelope Summary section failed and was skipped because: undefined local variable or method `surface_construction' for OsLib_Reporting:Module. Detail on error follows.", - "/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1488:in `block in envelope_section_section'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `each'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `envelope_section_section'\n(eval):1:in `block in run'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `eval'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `block in run'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `each'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `run'" + "C:/OpenStudio/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1488:in `block in envelope_section_section'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `each'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `envelope_section_section'\n(eval):1:in `block in run'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `eval'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `block in run'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `each'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `run'" ] } } From e41b03155a0fb93ffbc15f808b6eec432a1ba453 Mon Sep 17 00:00:00 2001 From: "github-rubocop-actions[bot]" Date: Tue, 15 Jul 2025 02:44:04 +0000 Subject: [PATCH 2/4] Commit rubocop --auto-correct (Ruby ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux], Rubocop 1.50.0) --- model_tests.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model_tests.rb b/model_tests.rb index 9667dde7..63cee9ff 100644 --- a/model_tests.rb +++ b/model_tests.rb @@ -2256,12 +2256,12 @@ def test_zone_hvac3_rb end # def test_zone_hvac3_py - # result = sim_test('zone_hvac3.py') + # result = sim_test('zone_hvac3.py') # end # TODO: To be added in the next official release after: 3.10.0 # def test_zone_hvac3_osm - # result = sim_test('zone_hvac3.osm') + # result = sim_test('zone_hvac3.osm') # end def test_zone_hvac_cooling_panel_rb From e1eb9263433d5132f496eb534a0c2f43e762c66b Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 14 Jul 2025 19:48:59 -0700 Subject: [PATCH 3/4] Revert osw file. --- test/heatpump_plantloop_eir.rb_3.9.0_out.osw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/heatpump_plantloop_eir.rb_3.9.0_out.osw b/test/heatpump_plantloop_eir.rb_3.9.0_out.osw index dcf5e494..3dca11d5 100644 --- a/test/heatpump_plantloop_eir.rb_3.9.0_out.osw +++ b/test/heatpump_plantloop_eir.rb_3.9.0_out.osw @@ -2,7 +2,7 @@ "completed_status": "Success", "current_step": 1, "file_paths": [ - "C:/OpenStudio/OpenStudio-resources/testruns/heatpump_plantloop_eir.rb/generated_files", + "/home/julien/Software/Others/OpenStudio-resources/testruns/heatpump_plantloop_eir.rb/generated_files", "./files", "./weather", "../../files", @@ -1568,7 +1568,7 @@ ], "step_warnings": [ "Envelope Summary section failed and was skipped because: undefined local variable or method `surface_construction' for OsLib_Reporting:Module. Detail on error follows.", - "C:/OpenStudio/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1488:in `block in envelope_section_section'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `each'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `envelope_section_section'\n(eval):1:in `block in run'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `eval'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `block in run'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `each'\nC:/OpenStudio/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `run'" + "/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1488:in `block in envelope_section_section'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `each'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/resources/os_lib_reporting.rb:1468:in `envelope_section_section'\n(eval):1:in `block in run'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `eval'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:237:in `block in run'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `each'\n/home/julien/Software/Others/OpenStudio-resources/measures/openstudio_results/measure.rb:233:in `run'" ] } } From 48bde9f56654b9874d4c0bc8ffe8d9cc5135e1b0 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 16 Jul 2025 16:21:57 -0700 Subject: [PATCH 4/4] Add DistrictHeatingSteam and CoilHeatingSteam objects. --- .../{zone_hvac3.rb => steam_systems.rb} | 88 ++++++++++++++----- model_tests.rb | 12 +-- 2 files changed, 73 insertions(+), 27 deletions(-) rename model/simulationtests/{zone_hvac3.rb => steam_systems.rb} (56%) diff --git a/model/simulationtests/zone_hvac3.rb b/model/simulationtests/steam_systems.rb similarity index 56% rename from model/simulationtests/zone_hvac3.rb rename to model/simulationtests/steam_systems.rb index 04988b4f..c2cc0129 100644 --- a/model/simulationtests/zone_hvac3.rb +++ b/model/simulationtests/steam_systems.rb @@ -5,10 +5,10 @@ model = BaselineModel.new -# make a 3 story, 100m X 50m, 10 zone core/perimeter building +# make a 1 story, 100m X 50m, 10 zone core/perimeter building model.add_geometry({ 'length' => 100, 'width' => 50, - 'num_floors' => 3, + 'num_floors' => 1, 'floor_to_floor_height' => 4, 'plenum_height' => 1, 'perimeter_zone_depth' => 3 }) @@ -22,11 +22,23 @@ model.add_thermostats({ 'heating_setpoint' => 24, 'cooling_setpoint' => 28 }) -# Add a hot water plant to supply the baseboard heaters +# SteamSystemAutoSize_DistrictHeatingSteam.idf +# - DistrictHeating:Steam +# - Pump:VariableSpeed:Condensate +# - AirTerminal:SingleDuct:VAV:Reheat +# - Coil:Heating:Steam + +# 5ZoneSteamBaseboard.idf +# - Boiler:Steam +# - Pump:VariableSpeed:Condensate +# - AirTerminal:SingleDuct:VAV:Reheat +# - Coil:Heating:Steam +# - ZoneHVAC:Baseboard:RadiantConvective:Steam + +# Add a steam plant to supply the baseboard heaters # This could be baked into HVAC templates in the future hotSteamPlant = OpenStudio::Model::PlantLoop.new(model) hotSteamPlant.setName('Hot Steam Plant') -# hotSteamPlant.setFluidType('Steam') sizingPlant = hotSteamPlant.sizingPlant sizingPlant.setLoopType('Heating') @@ -39,37 +51,42 @@ pump = OpenStudio::Model::PumpVariableSpeedCondensate.new(model) pump.addToNode(steamInletNode) +# Boiler steam boiler = OpenStudio::Model::BoilerSteam.new(model) node = hotSteamPlant.supplySplitter.lastOutletModelObject.get.to_Node.get boiler.addToNode(node) +# District heating steam +district_heating_steam = OpenStudio::Model::DistrictHeatingSteam.new(model) +district_heating_steam.addToNode(node) + pipe = OpenStudio::Model::PipeAdiabatic.new(model) hotSteamPlant.addSupplyBranchForComponent(pipe) pipe2 = OpenStudio::Model::PipeAdiabatic.new(model) pipe2.addToNode(steamOutletNode) -## Make a hot Water temperature schedule +## Make a steam temperature schedule osTime = OpenStudio::Time.new(0, 24, 0, 0) steamTempSchedule = OpenStudio::Model::ScheduleRuleset.new(model) -steamTempSchedule.setName('Hot Water Temperature') +steamTempSchedule.setName('Steam Temperature') ### Winter Design Day steamTempScheduleWinter = OpenStudio::Model::ScheduleDay.new(model) steamTempSchedule.setWinterDesignDaySchedule(steamTempScheduleWinter) -steamTempSchedule.winterDesignDaySchedule.setName('Hot Water Temperature Winter Design Day') +steamTempSchedule.winterDesignDaySchedule.setName('Steam Temperature Winter Design Day') steamTempSchedule.winterDesignDaySchedule.addValue(osTime, 67) ### Summer Design Day steamTempScheduleSummer = OpenStudio::Model::ScheduleDay.new(model) steamTempSchedule.setSummerDesignDaySchedule(steamTempScheduleSummer) -steamTempSchedule.summerDesignDaySchedule.setName('Hot Water Temperature Summer Design Day') +steamTempSchedule.summerDesignDaySchedule.setName('Steam Temperature Summer Design Day') steamTempSchedule.summerDesignDaySchedule.addValue(osTime, 67) ### All other days -steamTempSchedule.defaultDaySchedule.setName('Hot Water Temperature Default') +steamTempSchedule.defaultDaySchedule.setName('Steam Temperature Default') steamTempSchedule.defaultDaySchedule.addValue(osTime, 67) steamSPM = OpenStudio::Model::SetpointManagerScheduled.new(model, steamTempSchedule) @@ -90,23 +107,52 @@ story_1_south_thermal_zone = model.getThermalZoneByName('Story 1 South Perimeter Thermal Zone').get story_1_east_thermal_zone = model.getThermalZoneByName('Story 1 East Perimeter Thermal Zone').get story_1_west_thermal_zone = model.getThermalZoneByName('Story 1 West Perimeter Thermal Zone').get -story_2_core_thermal_zone = model.getThermalZoneByName('Story 2 Core Thermal Zone').get -story_2_north_thermal_zone = model.getThermalZoneByName('Story 2 North Perimeter Thermal Zone').get -story_2_south_thermal_zone = model.getThermalZoneByName('Story 2 South Perimeter Thermal Zone').get -story_2_east_thermal_zone = model.getThermalZoneByName('Story 2 East Perimeter Thermal Zone').get -story_2_west_thermal_zone = model.getThermalZoneByName('Story 2 West Perimeter Thermal Zone').get -story_3_core_thermal_zone = model.getThermalZoneByName('Story 3 Core Thermal Zone').get -story_3_north_thermal_zone = model.getThermalZoneByName('Story 3 North Perimeter Thermal Zone').get -story_3_south_thermal_zone = model.getThermalZoneByName('Story 3 South Perimeter Thermal Zone').get -story_3_east_thermal_zone = model.getThermalZoneByName('Story 3 East Perimeter Thermal Zone').get -story_3_west_thermal_zone = model.getThermalZoneByName('Story 3 West Perimeter Thermal Zone').get - -# Add ZoneHVACBaseboardRadiantConvectiveWater + +# new airloop +airLoopHVAC = OpenStudio::Model::AirLoopHVAC.new(model) + +# OA controller +controllerOutdoorAir = OpenStudio::Model::ControllerOutdoorAir.new(model) +outdoorAirSystem = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, controllerOutdoorAir) + +# add the equipment to the airloop +supplyOutletNode = airLoopHVAC.supplyOutletNode +outdoorAirSystem.addToNode(supplyOutletNode) + +# Make a time stamp to use in multiple places +os_time = OpenStudio::Time.new(0, 24, 0, 0) + +# always On Schedule +# Schedule Ruleset +always_on_sch = OpenStudio::Model::ScheduleRuleset.new(model) +always_on_sch.setName('Always_On') +# Winter Design Day +always_on_sch_winter = OpenStudio::Model::ScheduleDay.new(model) +always_on_sch.setWinterDesignDaySchedule(always_on_sch_winter) +always_on_sch.winterDesignDaySchedule.setName('Always_On_Winter_Design_Day') +always_on_sch.winterDesignDaySchedule.addValue(os_time, 1) +# Summer Design Day +always_on_sch_summer = OpenStudio::Model::ScheduleDay.new(model) +always_on_sch.setSummerDesignDaySchedule(always_on_sch_summer) +always_on_sch.summerDesignDaySchedule.setName('Always_On_Summer_Design_Day') +always_on_sch.summerDesignDaySchedule.addValue(os_time, 1) +# All other days +always_on_sch.defaultDaySchedule.setName('Always_On_Default') +always_on_sch.defaultDaySchedule.addValue(os_time, 1) + +# Add ZoneHVACBaseboardRadiantConvectiveSteam zoneHVACBaseboardRadiantConvectiveSteam = OpenStudio::Model::ZoneHVACBaseboardRadiantConvectiveSteam.new(model) baseboard_coil = zoneHVACBaseboardRadiantConvectiveSteam.heatingCoil hotSteamPlant.addDemandBranchForComponent(baseboard_coil) zoneHVACBaseboardRadiantConvectiveSteam.addToThermalZone(story_1_core_thermal_zone) +# Add CoilHeatingSteam +steamReheatCoil = OpenStudio::Model::CoilHeatingSteam.new(model, always_on_sch) +steamTerminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(model, always_on_sch, steamReheatCoil) +airLoopHVAC.addBranchForHVACComponent(steamTerminal) +hotSteamPlant.addDemandBranchForComponent(steamReheatCoil) +airLoopHVAC.addBranchForZone(story_1_north_thermal_zone) + # save the OpenStudio model (.osm) model.save_openstudio_osm({ 'osm_save_directory' => Dir.pwd, 'osm_name' => 'in.osm' }) diff --git a/model_tests.rb b/model_tests.rb index 63cee9ff..8f6ba2f2 100644 --- a/model_tests.rb +++ b/model_tests.rb @@ -2251,17 +2251,17 @@ def test_zone_hvac2_osm result = sim_test('zone_hvac2.osm') end - def test_zone_hvac3_rb - result = sim_test('zone_hvac3.rb') + def test_steam_systems_rb + result = sim_test('steam_systems.rb') end - # def test_zone_hvac3_py - # result = sim_test('zone_hvac3.py') + # def test_steam_systems_py + # result = sim_test('steam_systems.py') # end # TODO: To be added in the next official release after: 3.10.0 - # def test_zone_hvac3_osm - # result = sim_test('zone_hvac3.osm') + # def test_steam_systems_osm + # result = sim_test('steam_systems.osm') # end def test_zone_hvac_cooling_panel_rb