openstudio-standards 0.2.17.rc1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  3. data/data/standards/openstudio_standards_duplicates_log.csv +5 -0
  4. data/lib/openstudio-standards/btap/btap_result.rb +138 -138
  5. data/lib/openstudio-standards/btap/economics.rb +58 -53
  6. data/lib/openstudio-standards/btap/envelope.rb +1 -1
  7. data/lib/openstudio-standards/btap/fileio.rb +12 -12
  8. data/lib/openstudio-standards/btap/measures.rb +63 -59
  9. data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
  10. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +7 -7
  11. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +5 -1
  12. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +8 -0
  13. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +9 -3
  14. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +53 -23
  15. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +15 -1
  16. data/lib/openstudio-standards/standards/Standards.Construction.rb +1 -1
  17. data/lib/openstudio-standards/standards/Standards.Model.rb +18 -18
  18. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +1 -1
  19. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +1 -1
  20. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +5 -5
  21. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +3 -2
  22. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +43 -40
  23. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +2 -1
  24. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.entryways.json +19 -8
  25. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.parking.json +13 -4
  26. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +11 -0
  27. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +11 -0
  28. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +1 -1
  29. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +9 -9
  30. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +1 -1
  31. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +5 -1
  32. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +5 -1
  33. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +8 -4
  34. data/lib/openstudio-standards/standards/necb/ECMS/nv.rb +8 -2
  35. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +7 -3
  36. data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +4 -4
  37. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +1 -1
  38. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +1 -1
  39. data/lib/openstudio-standards/version.rb +1 -1
  40. data/lib/openstudio-standards/weather/Weather.Model.rb +5 -0
  41. metadata +4 -2
@@ -19,21 +19,18 @@ class Standard
19
19
  # @note Per 90.1, the Performance Rating Method "does NOT offer an alternative compliance path for minimum standard compliance."
20
20
  # This means you can't use this method for code compliance to get a permit.
21
21
  # @param user_model [OpenStudio::model::Model] User specified OpenStudio model
22
- # @param building_type [String] the building type
23
22
  # @param climate_zone [String] the climate zone
24
23
  # @param hvac_building_type [String] the building type for baseline HVAC system determination (90.1-2016 and onward)
25
24
  # @param wwr_building_type [String] the building type for baseline WWR determination (90.1-2016 and onward)
26
25
  # @param swh_building_type [String] the building type for baseline SWH determination (90.1-2016 and onward)
27
- # @param custom [String] the custom logic that will be applied during baseline creation. Valid choices are 'Xcel Energy CO EDA' or '90.1-2007 with addenda dn'.
28
- # If nothing is specified, no custom logic will be applied; the process will follow the template logic explicitly.
29
- # @param sizing_run_dir [String] the directory where the sizing runs will be performed
26
+ # @param output_dir [String] the directory where the PRM generations will be performed
30
27
  # @param run_all_orients [Boolean] indicate weather a baseline model should be created for all 4 orientations: same as user model, +90 deg, +180 deg, +270 deg
31
28
  # @param debug [Boolean] If true, will report out more detailed debugging output
32
29
  # @return [Bool] returns true if successful, false if not
33
30
 
34
31
  # Method used for 90.1-2016 and onward
35
- def model_create_prm_stable_baseline_building(model, building_type, climate_zone, hvac_building_type, wwr_building_type, swh_building_type, custom = nil, sizing_run_dir = Dir.pwd, run_all_orients = true, unmet_load_hours_check = true, debug = false)
36
- model_create_prm_any_baseline_building(model, building_type, climate_zone, hvac_building_type, wwr_building_type, swh_building_type, true, custom, sizing_run_dir, run_all_orients, unmet_load_hours_check, debug)
32
+ def model_create_prm_stable_baseline_building(model, climate_zone, hvac_building_type, wwr_building_type, swh_building_type, output_dir = Dir.pwd, unmet_load_hours_check = true, debug = false)
33
+ model_create_prm_any_baseline_building(model, '', climate_zone, hvac_building_type, wwr_building_type, swh_building_type, true, false, output_dir, true, unmet_load_hours_check, debug)
37
34
  end
38
35
 
39
36
  # Creates a Performance Rating Method (aka Appendix G aka LEED) baseline building model
@@ -77,6 +74,9 @@ class Standard
77
74
  OpenStudio.logFree(OpenStudio::Error, 'prm.log', "Proposed model unmet load hours exceed 300. Baseline model(s) won't be created.")
78
75
  raise "Proposed model unmet load hours exceed 300. Baseline model(s) won't be created."
79
76
  end
77
+ else
78
+ OpenStudio.logFree(OpenStudio::Error, 'prm.log', "Simulation failed. Check the model to make sure no severe errors.")
79
+ raise "Simulation on proposed model failed. Baseline generation is stopped."
80
80
  end
81
81
  end
82
82
 
@@ -1885,9 +1885,9 @@ class Standard
1885
1885
  # separate the primary zones from the secondary zones.
1886
1886
  # Add the baseline system type to the primary zones
1887
1887
  # and add the suplemental system type to the secondary zones.
1888
- story_zone_lists.each do |zones|
1888
+ story_zone_lists.each do |story_group|
1889
1889
  # Differentiate primary and secondary zones
1890
- pri_sec_zone_lists = model_differentiate_primary_secondary_thermal_zones(model, story_group, zone_fan_scheds)
1890
+ pri_sec_zone_lists = model_differentiate_primary_secondary_thermal_zones(model, story_group)
1891
1891
  # Record the primary zone system types
1892
1892
  pri_sec_zone_lists['primary'].each do |zone|
1893
1893
  zone_to_sys_type[zone] = pri_system_type
@@ -6926,7 +6926,7 @@ class Standard
6926
6926
  # include data source from:
6927
6927
  # 1. user data csv files
6928
6928
  # 2. data from measure and OpenStudio interface
6929
- # @param [Openstudio:model:Model] model
6929
+ # @param [OpenStudio:model:Model] model
6930
6930
  # @param [String] climate_zone
6931
6931
  # @param [String] default_hvac_building_type
6932
6932
  # @param [String] default_wwr_building_type
@@ -6940,7 +6940,7 @@ class Standard
6940
6940
  # Template method for adding a setpoint manager for a coil control logic to a heating coil.
6941
6941
  # ASHRAE 90.1-2019 Appendix G.
6942
6942
  #
6943
- # @param model [OpenStudio::Model::Model] Openstudio model
6943
+ # @param model [OpenStudio::Model::Model] OpenStudio model
6944
6944
  # @param thermalZones Array([OpenStudio::Model::ThermalZone]) thermal zone array
6945
6945
  # @param coil Heating Coils
6946
6946
  # @return [Boolean] true
@@ -6951,7 +6951,7 @@ class Standard
6951
6951
  # Template method for adding zone additional property "zone DCV implemented in user model"
6952
6952
  #
6953
6953
  # @author Xuechen (Jerry) Lei, PNNL
6954
- # @param model [OpenStudio::Model::Model] Openstudio model
6954
+ # @param model [OpenStudio::Model::Model] OpenStudio model
6955
6955
  def model_mark_zone_dcv_existence(model)
6956
6956
  return true
6957
6957
  end
@@ -6960,7 +6960,7 @@ class Standard
6960
6960
  # The default shall be true
6961
6961
  #
6962
6962
  # @param [Boolean] run_all_orients: user inputs to indicate whether it is required to run all orientations
6963
- # @param [OpenStudio::Model::Model] Openstudio model
6963
+ # @param [OpenStudio::Model::Model] OpenStudio model
6964
6964
  def run_all_orientations(run_all_orients, user_model)
6965
6965
  return run_all_orients
6966
6966
  end
@@ -6968,7 +6968,7 @@ class Standard
6968
6968
  # Template method for reading user data and adding to zone additional properties
6969
6969
  #
6970
6970
  # @author Xuechen (Jerry) Lei, PNNL
6971
- # @param model [OpenStudio::Model::Model] Openstudio model
6971
+ # @param model [OpenStudio::Model::Model] OpenStudio model
6972
6972
  def model_add_dcv_user_exception_properties(model)
6973
6973
  return true
6974
6974
  end
@@ -6976,7 +6976,7 @@ class Standard
6976
6976
  # Template method for raising user model DCV warning and errors
6977
6977
  #
6978
6978
  # @author Xuechen (Jerry) Lei, PNNL
6979
- # @param model [OpenStudio::Model::Model] Openstudio model
6979
+ # @param model [OpenStudio::Model::Model] OpenStudio model
6980
6980
  def model_raise_user_model_dcv_errors(model)
6981
6981
  return true
6982
6982
  end
@@ -6984,7 +6984,7 @@ class Standard
6984
6984
  # Template method for adding zone additional property "airloop dcv required by 901" and "zone dcv required by 901"
6985
6985
  #
6986
6986
  # @author Xuechen (Jerry) Lei, PNNL
6987
- # @param model [OpenStudio::Model::Model] Openstudio model
6987
+ # @param model [OpenStudio::Model::Model] OpenStudio model
6988
6988
  def model_add_dcv_requirement_properties(model)
6989
6989
  return true
6990
6990
  end
@@ -6993,7 +6993,7 @@ class Standard
6993
6993
  # Zone additional property 'apxg no need to have DCV' added
6994
6994
  #
6995
6995
  # @author Xuechen (Jerry) Lei, PNNL
6996
- # @param model [OpenStudio::Model::Model] Openstudio model
6996
+ # @param model [OpenStudio::Model::Model] OpenStudio model
6997
6997
  def model_add_apxg_dcv_properties(model)
6998
6998
  return true
6999
6999
  end
@@ -7001,14 +7001,14 @@ class Standard
7001
7001
  # Template method for setting DCV in baseline HVAC system if required
7002
7002
  #
7003
7003
  # @author Xuechen (Jerry) Lei, PNNL
7004
- # @param model [OpenStudio::Model::Model] Openstudio model
7004
+ # @param model [OpenStudio::Model::Model] OpenStudio model
7005
7005
  def model_set_baseline_demand_control_ventilation(model, climate_zone)
7006
7006
  return true
7007
7007
  end
7008
7008
 
7009
7009
  # Identify the return air type associated with each thermal zone
7010
7010
  #
7011
- # @param model [OpenStudio::Model::Model] Openstudio model object
7011
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
7012
7012
  def model_identify_return_air_type(model)
7013
7013
  # air-loop based system
7014
7014
  model.getThermalZones.each do |zone|
@@ -7,7 +7,7 @@ class Standard
7
7
  # create a construction that meets those properties and assign it to this surface.
8
8
  # 90.1-2007, 90.1-2010, 90.1-2013
9
9
  #
10
- # @param planar_surface [Openstudio::Model:PlanarSurface] surface object
10
+ # @param planar_surface [OpenStudio::Model:PlanarSurface] surface object
11
11
  # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
12
12
  # @param previous_construction_map [Hash] a hash where the keys are an array of inputs
13
13
  # [template, climate_zone, intended_surface_type, standards_construction_type, occ_type]
@@ -980,7 +980,7 @@ class Standard
980
980
  end
981
981
  elsif equip.to_ZoneHVACLowTemperatureRadiantElectric.is_initialized
982
982
  equip = equip.to_ZoneHVACLowTemperatureRadiantElectric.get
983
- htg_sch = equip.heatingSetpointTemperatureSchedule.get
983
+ htg_sch = equip.heatingSetpointTemperatureSchedule
984
984
  elsif equip.to_ZoneHVACLowTempRadiantConstFlow.is_initialized
985
985
  equip = equip.to_ZoneHVACLowTempRadiantConstFlow.get
986
986
  htg_coil = equip.heatingCoil
@@ -169,15 +169,15 @@ class Standard
169
169
  end
170
170
 
171
171
  # Convert to SI
172
- ua_btu_per_hr_per_c = OpenStudio.convert(ua_btu_per_hr_per_f, 'Btu/hr*R', 'W/K').get
173
- OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.WaterHeaterMixed', "For #{water_heater_mixed.name}, skin-loss UA = #{ua_btu_per_hr_per_c} W/K.")
172
+ ua_w_per_k = OpenStudio.convert(ua_btu_per_hr_per_f, 'Btu/hr*R', 'W/K').get
173
+ OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.WaterHeaterMixed', "For #{water_heater_mixed.name}, skin-loss UA = #{ua_w_per_k} W/K.")
174
174
 
175
175
  # Set the water heater properties
176
176
  # Efficiency
177
177
  water_heater_mixed.setHeaterThermalEfficiency(water_heater_eff)
178
178
  # Skin loss
179
- water_heater_mixed.setOffCycleLossCoefficienttoAmbientTemperature(ua_btu_per_hr_per_c)
180
- water_heater_mixed.setOnCycleLossCoefficienttoAmbientTemperature(ua_btu_per_hr_per_c)
179
+ water_heater_mixed.setOffCycleLossCoefficienttoAmbientTemperature(ua_w_per_k)
180
+ water_heater_mixed.setOnCycleLossCoefficienttoAmbientTemperature(ua_w_per_k)
181
181
  # @todo Parasitic loss (pilot light)
182
182
  # PNNL document says pilot lights were removed, but IDFs
183
183
  # still have the on/off cycle parasitic fuel consumptions filled in
@@ -190,7 +190,7 @@ class Standard
190
190
 
191
191
  # Append the name with standards information
192
192
  water_heater_mixed.setName("#{water_heater_mixed.name} #{water_heater_eff.round(3)} Therm Eff")
193
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.WaterHeaterMixed', "For #{template}: #{water_heater_mixed.name}; thermal efficiency = #{water_heater_eff.round(3)}, skin-loss UA = #{ua_btu_per_hr_per_f.round}Btu/hr")
193
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.WaterHeaterMixed', "For #{template}: #{water_heater_mixed.name}; thermal efficiency = #{water_heater_eff.round(3)}, skin-loss UA = #{ua_btu_per_hr_per_f.round}Btu/hr-R")
194
194
 
195
195
  return true
196
196
  end
@@ -144,6 +144,7 @@ class Standard
144
144
  # Zone HVAC operating schedule if providing ventilation
145
145
  # Zone HVAC components return an OptionalSchedule object for supplyAirFanOperatingModeSchedule
146
146
  # except for ZoneHVACTerminalUnitVariableRefrigerantFlow which returns a Schedule
147
+ # and starting at 3.5.0, PTAC / PTHP also return a Schedule, optional before that
147
148
  existing_sch = nil
148
149
  if zone_hvac_component.to_ZoneHVACFourPipeFanCoil.is_initialized
149
150
  zone_hvac_component = zone_hvac_component.to_ZoneHVACFourPipeFanCoil.get
@@ -161,7 +162,7 @@ class Standard
161
162
  ventilation = true if oa_rate > 0.0
162
163
  end
163
164
  ventilation = true if zone_hvac_component.isOutdoorAirFlowRateWhenNoCoolingorHeatingisNeededAutosized
164
- fan_op_sch = zone_hvac_component.supplyAirFanOperatingModeSchedule
165
+ fan_op_sch = OpenStudio::Model::OptionalSchedule.new(zone_hvac_component.supplyAirFanOperatingModeSchedule)
165
166
  existing_sch = fan_op_sch.get if fan_op_sch.is_initialized
166
167
  elsif zone_hvac_component.to_ZoneHVACPackagedTerminalHeatPump.is_initialized
167
168
  zone_hvac_component = zone_hvac_component.to_ZoneHVACPackagedTerminalHeatPump.get
@@ -170,7 +171,7 @@ class Standard
170
171
  ventilation = true if oa_rate > 0.0
171
172
  end
172
173
  ventilation = true if zone_hvac_component.isOutdoorAirFlowRateWhenNoCoolingorHeatingisNeededAutosized
173
- fan_op_sch = zone_hvac_component.supplyAirFanOperatingModeSchedule
174
+ fan_op_sch = OpenStudio::Model::OptionalSchedule.new(zone_hvac_component.supplyAirFanOperatingModeSchedule)
174
175
  existing_sch = fan_op_sch.get if fan_op_sch.is_initialized
175
176
  elsif zone_hvac_component.to_ZoneHVACTerminalUnitVariableRefrigerantFlow.is_initialized
176
177
  zone_hvac_component = zone_hvac_component.to_ZoneHVACTerminalUnitVariableRefrigerantFlow.get
@@ -640,46 +640,49 @@ class ASHRAE9012019 < ASHRAE901
640
640
  # Controller:MechanicalVentilation object
641
641
  # to the design v_ot using the maximum OA
642
642
  # fraction schedule
643
-
644
- # Add EMS sensors
645
- # OA mass flow calculated by the Controller:MechanicalVentilation
646
- air_loop_hvac_name_ems = "EMS_#{air_loop_hvac.name.to_s.gsub(' ', '_')}"
647
- oa_vrp_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mechanical Ventilation Requested Mass Flow Rate')
648
- oa_vrp_mass_flow.setKeyName(air_loop_hvac.name.to_s)
649
- oa_vrp_mass_flow.setName("#{air_loop_hvac_name_ems}_OA_VRP")
650
- # Actual sensed OA mass flow
651
- oa_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mass Flow Rate')
652
- oa_mass_flow.setKeyName(air_loop_hvac.name.to_s)
653
- oa_mass_flow.setName("#{air_loop_hvac_name_ems}_OA")
654
- # Actual sensed volumetric OA flow
655
- oa_vol_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'System Node Standard Density Volume Flow Rate')
656
- oa_vol_flow.setKeyName("#{air_loop_hvac.name} Mixed Air Node")
657
- oa_vol_flow.setName("#{air_loop_hvac_name_ems}_SUPPLY_FLOW")
658
-
659
- # Add EMS actuator
660
- max_oa_fraction = OpenStudio::Model::EnergyManagementSystemActuator.new(max_oa_frac_sch, max_oa_frac_sch_type, 'Schedule Value')
661
- max_oa_fraction.setName("#{air_loop_hvac_name_ems}_MAX_OA_FRAC")
662
-
663
- # Add EMS program
664
- max_oa_ems_prog = OpenStudio::Model::EnergyManagementSystemProgram.new(air_loop_hvac.model)
665
- max_oa_ems_prog.setName("#{air_loop_hvac.name}_MAX_OA_FRAC")
666
- max_oa_ems_prog_body = <<-EMS
667
- IF #{air_loop_hvac_name_ems}_OA > #{air_loop_hvac_name_ems}_OA_VRP,
668
- SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL,
669
- ELSE,
670
- IF #{air_loop_hvac_name_ems}_SUPPLY_FLOW > 0,
671
- SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = #{v_ot} / #{air_loop_hvac_name_ems}_SUPPLY_FLOW,
672
- ELSE,
673
- SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL,
674
- ENDIF,
675
- ENDIF
676
- EMS
677
- max_oa_ems_prog.setBody(max_oa_ems_prog_body)
678
-
679
- max_oa_ems_prog_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(air_loop_hvac.model)
680
- max_oa_ems_prog_manager.setName("SET_#{air_loop_hvac.name.to_s.gsub(' ', '_')}_MAX_OA_FRAC")
681
- max_oa_ems_prog_manager.setCallingPoint('InsideHVACSystemIterationLoop')
682
- max_oa_ems_prog_manager.addProgram(max_oa_ems_prog)
643
+ # In newer EnergyPlus versions, this is handled by Standard62.1VentilationRateProcedureWithLimit
644
+ # in the Controller:MechanicalVentilation object
645
+ if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.3.0')
646
+ # Add EMS sensors
647
+ # OA mass flow calculated by the Controller:MechanicalVentilation
648
+ air_loop_hvac_name_ems = "EMS_#{air_loop_hvac.name.to_s.gsub(' ', '_')}"
649
+ oa_vrp_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mechanical Ventilation Requested Mass Flow Rate')
650
+ oa_vrp_mass_flow.setKeyName(air_loop_hvac.name.to_s)
651
+ oa_vrp_mass_flow.setName("#{air_loop_hvac_name_ems}_OA_VRP")
652
+ # Actual sensed OA mass flow
653
+ oa_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mass Flow Rate')
654
+ oa_mass_flow.setKeyName(air_loop_hvac.name.to_s)
655
+ oa_mass_flow.setName("#{air_loop_hvac_name_ems}_OA")
656
+ # Actual sensed volumetric OA flow
657
+ oa_vol_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'System Node Standard Density Volume Flow Rate')
658
+ oa_vol_flow.setKeyName("#{air_loop_hvac.name} Mixed Air Node")
659
+ oa_vol_flow.setName("#{air_loop_hvac_name_ems}_SUPPLY_FLOW")
660
+
661
+ # Add EMS actuator
662
+ max_oa_fraction = OpenStudio::Model::EnergyManagementSystemActuator.new(max_oa_frac_sch, max_oa_frac_sch_type, 'Schedule Value')
663
+ max_oa_fraction.setName("#{air_loop_hvac_name_ems}_MAX_OA_FRAC")
664
+
665
+ # Add EMS program
666
+ max_oa_ems_prog = OpenStudio::Model::EnergyManagementSystemProgram.new(air_loop_hvac.model)
667
+ max_oa_ems_prog.setName("#{air_loop_hvac.name}_MAX_OA_FRAC")
668
+ max_oa_ems_prog_body = <<-EMS
669
+ IF #{air_loop_hvac_name_ems}_OA > #{air_loop_hvac_name_ems}_OA_VRP,
670
+ SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL,
671
+ ELSE,
672
+ IF #{air_loop_hvac_name_ems}_SUPPLY_FLOW > 0,
673
+ SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = #{v_ot} / #{air_loop_hvac_name_ems}_SUPPLY_FLOW,
674
+ ELSE,
675
+ SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL,
676
+ ENDIF,
677
+ ENDIF
678
+ EMS
679
+ max_oa_ems_prog.setBody(max_oa_ems_prog_body)
680
+
681
+ max_oa_ems_prog_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(air_loop_hvac.model)
682
+ max_oa_ems_prog_manager.setName("SET_#{air_loop_hvac.name.to_s.gsub(' ', '_')}_MAX_OA_FRAC")
683
+ max_oa_ems_prog_manager.setCallingPoint('InsideHVACSystemIterationLoop')
684
+ max_oa_ems_prog_manager.addProgram(max_oa_ems_prog)
685
+ end
683
686
 
684
687
  # Hard-size the sizing:system
685
688
  # object with the calculated min OA flow rate
@@ -44,7 +44,8 @@ class ASHRAE9012019 < ASHRAE901
44
44
  end
45
45
 
46
46
  # Set fan operating schedule during assumed occupant standby mode time to 0 so the fan can cycle
47
- new_sch = model_set_schedule_value(zone_hvac_component.supplyAirFanOperatingModeSchedule.get, '12' => 0)
47
+ # ZoneHVACFourPipeFanCoil has it optional, PTAC/PTHP starting a 3.5.0 is required
48
+ new_sch = model_set_schedule_value(OpenStudio::Model::OptionalSchedule.new(zone_hvac_component.supplyAirFanOperatingModeSchedule).get, '12' => 0)
48
49
  zone_hvac_component.setSupplyAirFanOperatingModeSchedule(new_sch) unless new_sch == true
49
50
 
50
51
  return true
@@ -2,25 +2,25 @@
2
2
  "entryways": [
3
3
  {
4
4
  "building_type": "College",
5
- "rollup_doors_per_10,000": null,
6
- "entrance_doors_per_10,000": null,
7
- "others_doors_per_10,000": null,
5
+ "rollup_doors_per_10,000": 0.0,
6
+ "entrance_doors_per_10,000": 2.0,
7
+ "others_doors_per_10,000": 2.45,
8
8
  "entrance_canopies": null,
9
9
  "emergency_canopies": null,
10
10
  "canopy_size": null,
11
11
  "floor_area_per_drive_through_window": null,
12
- "notes": null
12
+ "notes": "match SecondarySchool"
13
13
  },
14
14
  {
15
15
  "building_type": "Courthouse",
16
- "rollup_doors_per_10,000": null,
17
- "entrance_doors_per_10,000": null,
18
- "others_doors_per_10,000": null,
16
+ "rollup_doors_per_10,000": 0.0,
17
+ "entrance_doors_per_10,000": 1.0,
18
+ "others_doors_per_10,000": 3.0,
19
19
  "entrance_canopies": null,
20
20
  "emergency_canopies": null,
21
21
  "canopy_size": null,
22
22
  "floor_area_per_drive_through_window": null,
23
- "notes": null
23
+ "notes": "match MediumOffice"
24
24
  },
25
25
  {
26
26
  "building_type": "FullServiceRestaurant",
@@ -55,6 +55,17 @@
55
55
  "floor_area_per_drive_through_window": null,
56
56
  "notes": "No source for canopy size, Table 5.41. Exterior Lighting Savings Summary for Addendum 90.1-07i doesn't indicate canopy lighting. Section 5.4.2 Exterior Lights in U.S. Department of Energy Commercial Reference Building Models of the National Building Stock shows their use."
57
57
  },
58
+ {
59
+ "building_type": "Laboratory",
60
+ "rollup_doors_per_10,000": 0.0,
61
+ "entrance_doors_per_10,000": 2.0,
62
+ "others_doors_per_10,000": 2.45,
63
+ "entrance_canopies": null,
64
+ "emergency_canopies": null,
65
+ "canopy_size": null,
66
+ "floor_area_per_drive_through_window": null,
67
+ "notes": "match SecondarySchool"
68
+ },
58
69
  {
59
70
  "building_type": "LargeDataCenterHighITE",
60
71
  "rollup_doors_per_10,000": null,
@@ -2,21 +2,21 @@
2
2
  "parking": [
3
3
  {
4
4
  "building_type": "College",
5
- "building_area_per_spot": null,
5
+ "building_area_per_spot": 250.0,
6
6
  "units_per_spot": null,
7
7
  "students_per_spot": null,
8
8
  "beds_per_spot": null,
9
9
  "parking_area_per_spot": 405.0,
10
- "notes": "Based on Table 4.17 Illuminated Parking Area from Achieving the 30% Goal: Energy and Cost Savings Analysis of ASHRAE Standard 90.1-2010"
10
+ "notes": "match MediumOffice"
11
11
  },
12
12
  {
13
13
  "building_type": "Courthouse",
14
- "building_area_per_spot": null,
14
+ "building_area_per_spot": 250.0,
15
15
  "units_per_spot": null,
16
16
  "students_per_spot": null,
17
17
  "beds_per_spot": null,
18
18
  "parking_area_per_spot": 405.0,
19
- "notes": "Based on Table 4.17 Illuminated Parking Area from Achieving the 30% Goal: Energy and Cost Savings Analysis of ASHRAE Standard 90.1-2010"
19
+ "notes": "match MediumOffice"
20
20
  },
21
21
  {
22
22
  "building_type": "FullServiceRestaurant",
@@ -45,6 +45,15 @@
45
45
  "parking_area_per_spot": 405.0,
46
46
  "notes": "Based on Table 4.17 Illuminated Parking Area from Achieving the 30% Goal: Energy and Cost Savings Analysis of ASHRAE Standard 90.1-2010"
47
47
  },
48
+ {
49
+ "building_type": "Laboratory",
50
+ "building_area_per_spot": 250.0,
51
+ "units_per_spot": null,
52
+ "students_per_spot": null,
53
+ "beds_per_spot": null,
54
+ "parking_area_per_spot": 405.0,
55
+ "notes": "match MediumOffice"
56
+ },
48
57
  {
49
58
  "building_type": "LargeDataCenterHighITE",
50
59
  "building_area_per_spot": 0.0,
@@ -47,4 +47,15 @@ class DOERef1980to2004 < ASHRAE901
47
47
  damper_action = 'Single Maximum'
48
48
  return damper_action
49
49
  end
50
+
51
+ # Determine minimum ventilation efficiency for zones.
52
+ # For DOE Ref 1980-2004, assume that VAV system designers did not
53
+ # care about decreasing system OA flow rates and therefore did not
54
+ # adjust minimum damper positions to achieve any specific
55
+ # ventilation efficiency.
56
+ def air_loop_hvac_minimum_zone_ventilation_efficiency(air_loop_hvac)
57
+ min_ventilation_efficiency = 0
58
+
59
+ return min_ventilation_efficiency
60
+ end
50
61
  end
@@ -47,4 +47,15 @@ class DOERefPre1980 < ASHRAE901
47
47
  damper_action = 'Single Maximum'
48
48
  return damper_action
49
49
  end
50
+
51
+ # Determine minimum ventilation efficiency for zones.
52
+ # For DOE Ref Pre-1980, assume that VAV system designers did not
53
+ # care about decreasing system OA flow rates and therefore did not
54
+ # adjust minimum damper positions to achieve any specific
55
+ # ventilation efficiency.
56
+ def air_loop_hvac_minimum_zone_ventilation_efficiency(air_loop_hvac)
57
+ min_ventilation_efficiency = 0
58
+
59
+ return min_ventilation_efficiency
60
+ end
50
61
  end
@@ -272,7 +272,7 @@ class ASHRAE901PRM < Standard
272
272
  return_fan_power_fraction /= total_fan_avg_fan_w
273
273
  relief_fan_power_fraction /= total_fan_avg_fan_w
274
274
  else
275
- Openstudio.logFree(OpenStudio::Error, "Total zone design airflow for #{air_loop_hvac.name} is 0.")
275
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.ashrae_90_1_prm.AirLoopHVAC', "Total zone design airflow for #{air_loop_hvac.name} is 0.")
276
276
  end
277
277
  elsif system_type == 'PTAC' ||
278
278
  system_type == 'PTHP' ||
@@ -1176,7 +1176,7 @@ class ASHRAE901PRM < Standard
1176
1176
  # Template method for adding a setpoint manager for a coil control logic to a heating coil.
1177
1177
  # ASHRAE 90.1-2019 Appendix G.
1178
1178
  #
1179
- # @param model [OpenStudio::Model::Model] Openstudio model
1179
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1180
1180
  # @param thermalZones Array([OpenStudio::Model::ThermalZone]) thermal zone array
1181
1181
  # @param coil Heating Coils
1182
1182
  # @return [Boolean] true
@@ -1228,7 +1228,7 @@ class ASHRAE901PRM < Standard
1228
1228
  # - 'false' otherwise
1229
1229
  #
1230
1230
  # @author Xuechen (Jerry) Lei, PNNL
1231
- # @param model [OpenStudio::Model::Model] Openstudio model
1231
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1232
1232
  def model_mark_zone_dcv_existence(model)
1233
1233
  model.getAirLoopHVACs.each do |air_loop_hvac|
1234
1234
  next unless air_loop_hvac.airLoopHVACOutdoorAirSystem.is_initialized
@@ -1274,7 +1274,7 @@ class ASHRAE901PRM < Standard
1274
1274
  # "one user specified DCV exception"
1275
1275
  #
1276
1276
  # @author Xuechen (Jerry) Lei, PNNL
1277
- # @param model [OpenStudio::Model::Model] Openstudio model
1277
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1278
1278
  def model_add_dcv_user_exception_properties(model)
1279
1279
  model.getAirLoopHVACs.each do |air_loop_hvac|
1280
1280
  dcv_airloop_user_exception = false
@@ -1336,7 +1336,7 @@ class ASHRAE901PRM < Standard
1336
1336
  # - 'flase' otherwise
1337
1337
  #
1338
1338
  # @author Xuechen (Jerry) Lei, PNNL
1339
- # @param model [OpenStudio::Model::Model] Openstudio model
1339
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1340
1340
  def model_add_dcv_requirement_properties(model)
1341
1341
  model.getAirLoopHVACs.each do |air_loop_hvac|
1342
1342
  if user_model_air_loop_hvac_demand_control_ventilation_required?(air_loop_hvac)
@@ -1370,7 +1370,7 @@ class ASHRAE901PRM < Standard
1370
1370
  # generation
1371
1371
  #
1372
1372
  # @author Xuechen (Jerry) Lei, PNNL
1373
- # @param model [OpenStudio::Model::Model] Openstudio model
1373
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1374
1374
  def model_raise_user_model_dcv_errors(model)
1375
1375
  # TODO: JXL add log msgs to PRM logger
1376
1376
  model.getThermalZones.each do |thermal_zone|
@@ -1396,7 +1396,7 @@ class ASHRAE901PRM < Standard
1396
1396
  # property 'apxg no need to have DCV' added
1397
1397
  #
1398
1398
  # @author Xuechen (Jerry) Lei, PNNL
1399
- # @param model [OpenStudio::Model::Model] Openstudio model
1399
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1400
1400
  def model_add_apxg_dcv_properties(model)
1401
1401
  model.getAirLoopHVACs.each do |air_loop_hvac|
1402
1402
  if air_loop_hvac.airLoopHVACOutdoorAirSystem.is_initialized
@@ -1434,7 +1434,7 @@ class ASHRAE901PRM < Standard
1434
1434
  # Set DCV in baseline HVAC system if required
1435
1435
  #
1436
1436
  # @author Xuechen (Jerry) Lei, PNNL
1437
- # @param model [OpenStudio::Model::Model] Openstudio model
1437
+ # @param model [OpenStudio::Model::Model] OpenStudio model
1438
1438
  def model_set_baseline_demand_control_ventilation(model, climate_zone)
1439
1439
  model.getAirLoopHVACs.each do |air_loop_hvac|
1440
1440
  if baseline_air_loop_hvac_demand_control_ventilation_required?(air_loop_hvac)
@@ -1452,7 +1452,7 @@ class ASHRAE901PRM < Standard
1452
1452
  # include data source from:
1453
1453
  # 1. user data csv files
1454
1454
  # 2. data from measure and OpenStudio interface
1455
- # @param [Openstudio:model:Model] model
1455
+ # @param [OpenStudio:model:Model] model
1456
1456
  # @param [String] climate_zone
1457
1457
  # @param [String] default_hvac_building_type
1458
1458
  # @param [String] default_wwr_building_type
@@ -1948,7 +1948,7 @@ class ASHRAE901PRM < Standard
1948
1948
  # The default shall be true
1949
1949
  #
1950
1950
  # @param [Boolean] run_all_orients: user inputs to indicate whether it is required to run all orientations
1951
- # @param [OpenStudio::Model::Model] Openstudio model
1951
+ # @param [OpenStudio::Model::Model] OpenStudio model
1952
1952
  def run_all_orientations(run_all_orients, user_model)
1953
1953
  # Step 0, assign the default value
1954
1954
  run_orients_flag = run_all_orients
@@ -7,7 +7,7 @@ class ASHRAE901PRM < Standard
7
7
  # create a construction that meets those properties and assign it to this surface.
8
8
  # 90.1-PRM-2019
9
9
  #
10
- # @param planar_surface [Openstudio::Model:PlanarSurface] surface object
10
+ # @param planar_surface [OpenStudio::Model:PlanarSurface] surface object
11
11
  # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
12
12
  # @param previous_construction_map [Hash] a hash where the keys are an array of inputs
13
13
  # [template, climate_zone, intended_surface_type, standards_construction_type, occ_type]
@@ -112,7 +112,11 @@ class ASHRAE901PRM < Standard
112
112
  sizing_run_ran = model_run_sizing_run(model, "#{sizing_run_dir}/SR_cooling_plant") if !sizing_run_ran
113
113
 
114
114
  if sizing_run_ran
115
- sizing_run_capacity = model.getAutosizedValueFromEquipmentSummary(chiller, 'Central Plant', 'Nominal Capacity', 'W').get
115
+ if model.version <= OpenStudio::VersionString.new('3.2.1')
116
+ sizing_run_capacity = model.getAutosizedValueFromEquipmentSummary(chiller, 'Central Plant', 'Nominal Capacity', 'W').get
117
+ else
118
+ sizing_run_capacity = model.getAutosizedValueFromEquipmentSummary(chiller, 'Central Plant', 'Rated Capacity', 'W').get
119
+ end
116
120
  chiller.setReferenceCapacity(sizing_run_capacity)
117
121
  total_cooling_capacity_w += sizing_run_capacity
118
122
  else
@@ -235,7 +235,11 @@ class BTAPPRE1980
235
235
  air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(system_data[:CentralHeatingDesignSupplyAirTemperature])
236
236
  air_loop_sizing.setAllOutdoorAirinCooling(system_data[:AllOutdoorAirinCooling])
237
237
  air_loop_sizing.setAllOutdoorAirinHeating(system_data[:AllOutdoorAirinHeating])
238
- air_loop_sizing.setMinimumSystemAirFlowRatio(system_data[:MinimumSystemAirFlowRatio])
238
+ if model.version < OpenStudio::VersionString.new('2.7.0')
239
+ air_loop_sizing.setMinimumSystemAirFlowRatio(system_data[:MinimumSystemAirFlowRatio])
240
+ else
241
+ air_loop_sizing.setCentralHeatingMaximumSystemAirFlowRatio(system_data[:MinimumSystemAirFlowRatio])
242
+ end
239
243
 
240
244
  supply_fan = OpenStudio::Model::FanVariableVolume.new(model, always_on)
241
245
  supply_fan.setName('Sys6 Supply Fan')
@@ -442,7 +442,7 @@ class ECMS
442
442
  end
443
443
  return storey_zones_map
444
444
  end
445
-
445
+
446
446
  #==============================================================================================================================
447
447
  # Update the map between systems and zones
448
448
  def update_system_zones_map(model,system_zones_map,system_zones_map_option,system_key)
@@ -482,7 +482,7 @@ class ECMS
482
482
  system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1')
483
483
  else
484
484
  updated_system_zones_map = {}
485
- system_zones_map.each {|sname,zones| updated_system_zones_map["sys_1#{sname[5..-1]}"] = zones} # doas unit is an NECB sys_1
485
+ system_zones_map.each {|sname,zones| updated_system_zones_map["sys_1#{sname[5..-1]}"] = zones} # doas unit is an NECB sys_1
486
486
  system_zones_map = updated_system_zones_map
487
487
  end
488
488
  # Add outdoor VRF unit
@@ -612,7 +612,11 @@ class ECMS
612
612
  airloop.sizingSystem.setSystemOutdoorAirMethod('ZoneSum')
613
613
  airloop.sizingSystem.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085)
614
614
  airloop.sizingSystem.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080)
615
- airloop.sizingSystem.setMinimumSystemAirFlowRatio(1.0)
615
+ if model.version < OpenStudio::VersionString.new('2.7.0')
616
+ airloop.sizingSystem.setMinimumSystemAirFlowRatio(1.0)
617
+ else
618
+ airloop.sizingSystem.setCentralHeatingMaximumSystemAirFlowRatio(1.0)
619
+ end
616
620
  case sys_vent_type.downcase
617
621
  when 'doas'
618
622
  airloop.sizingSystem.setAllOutdoorAirinCooling(true)
@@ -1126,7 +1130,7 @@ class ECMS
1126
1130
  # There is an error in EnergyPlus in the estimated capacity of the coil "CoilCoolingDXVariableSpeed".
1127
1131
  # Here the capacity reported by OS is adjusted to estimate an appropriate capacity for the cooling coil.
1128
1132
  # The autosized capacity is corrected for the actual fan flow rate and fan power.
1129
- if supply_fan.autosizedMaximumFlowRate.is_initialized
1133
+ if supply_fan.autosizedMaximumFlowRate.is_initialized
1130
1134
  fan_max_afr = supply_fan.autosizedMaximumFlowRate.to_f
1131
1135
  elsif supply_fan.maximumFlowRate.is_initialized
1132
1136
  fan_max_afr = supply_fan.maximumFlowRate.to_f
@@ -121,8 +121,11 @@ class ECMS
121
121
 
122
122
  ##### Add a "ZoneVentilation:DesignFlowRate" object for NV to set OA per person.
123
123
  zn_vent_design_flow_rate_1 = OpenStudio::Model::ZoneVentilationDesignFlowRate.new(model)
124
- zn_vent_design_flow_rate_1.setDesignFlowRateCalculationMethod('Flow/Person')
125
124
  zn_vent_design_flow_rate_1.setFlowRateperPerson(oa_per_person_normalized_by_number_of_windows)
125
+ if model.version < OpenStudio::VersionString.new('3.5.0')
126
+ # Design Flow Rate Calculation Method is automatically set in 3.5.0+
127
+ zn_vent_design_flow_rate_1.setDesignFlowRateCalculationMethod('Flow/Person')
128
+ end
126
129
  zn_vent_design_flow_rate_1.setVentilationType('Natural')
127
130
  zn_vent_design_flow_rate_1.setMinimumIndoorTemperatureSchedule(min_Tin_schedule)
128
131
  zn_vent_design_flow_rate_1.setMaximumIndoorTemperatureSchedule(max_Tin_schedule)
@@ -133,8 +136,11 @@ class ECMS
133
136
 
134
137
  ##### Add another "ZoneVentilation:DesignFlowRate" object for NV to set OA per floor area.
135
138
  zn_vent_design_flow_rate_2 = OpenStudio::Model::ZoneVentilationDesignFlowRate.new(model)
136
- zn_vent_design_flow_rate_2.setDesignFlowRateCalculationMethod('Flow/Area')
137
139
  zn_vent_design_flow_rate_2.setFlowRateperZoneFloorArea(oa_per_floor_area_normalized_by_number_of_windows)
140
+ if model.version < OpenStudio::VersionString.new('3.5.0')
141
+ # Design Flow Rate Calculation Method is automatically set in 3.5.0+
142
+ zn_vent_design_flow_rate_2.setDesignFlowRateCalculationMethod('Flow/Area')
143
+ end
138
144
  zn_vent_design_flow_rate_2.setVentilationType('Natural')
139
145
  zn_vent_design_flow_rate_2.setMinimumIndoorTemperatureSchedule(min_Tin_schedule)
140
146
  zn_vent_design_flow_rate_2.setMaximumIndoorTemperatureSchedule(max_Tin_schedule)