openstudio-standards 0.2.16.rc2 → 0.2.17.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/data/geometry/ASHRAECollege.osm +117 -117
  3. data/data/standards/manage_OpenStudio_Standards.rb +31 -4
  4. data/data/standards/test_performance_expected_dd_results.csv +287 -287
  5. data/lib/openstudio-standards/btap/geometry.rb +1 -1
  6. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +354 -2
  7. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +79 -0
  8. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +1 -1
  9. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +1 -1
  10. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +3376 -63
  11. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +12 -0
  12. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +3 -4
  13. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
  14. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +168 -93
  15. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +2 -4
  16. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +2 -1
  17. data/lib/openstudio-standards/refs/references.rb +3 -0
  18. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +279 -6
  19. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +50 -2
  20. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +4 -0
  21. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -1
  22. data/lib/openstudio-standards/standards/Standards.Construction.rb +185 -3
  23. data/lib/openstudio-standards/standards/Standards.Fan.rb +14 -6
  24. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +1 -0
  25. data/lib/openstudio-standards/standards/Standards.Model.rb +1752 -384
  26. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +130 -9
  27. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +50 -3
  28. data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +44 -0
  29. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +27 -0
  30. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +543 -0
  31. data/lib/openstudio-standards/standards/Standards.Space.rb +665 -15
  32. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +141 -4
  33. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +2 -1
  34. data/lib/openstudio-standards/standards/Standards.Surface.rb +117 -0
  35. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +197 -49
  36. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +41 -0
  37. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +6 -8
  38. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/ashrae_90_1.schedules.json +45 -45
  39. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/comstock_ashrae_90_1_2004.spc_typ.json +7 -7
  40. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.spc_typ.json +19 -19
  41. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/ashrae_90_1.schedules.json +45 -45
  42. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/comstock_ashrae_90_1_2007.spc_typ.json +7 -7
  43. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.spc_typ.json +5 -5
  44. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/ashrae_90_1.schedules.json +45 -45
  45. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/comstock_ashrae_90_1_2010.spc_typ.json +9 -9
  46. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.spc_typ.json +3 -3
  47. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/ashrae_90_1.schedules.json +45 -45
  48. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/comstock_ashrae_90_1_2013.spc_typ.json +4 -4
  49. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.spc_typ.json +6 -6
  50. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/ashrae_90_1.schedules.json +45 -45
  51. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/comstock_ashrae_90_1_2016.spc_typ.json +5 -5
  52. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.spc_typ.json +6 -6
  53. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +5 -5
  54. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/ashrae_90_1.schedules.json +45 -45
  55. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/comstock_ashrae_90_1_2019.spc_typ.json +5 -5
  56. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.spc_typ.json +6 -6
  57. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +2 -2
  58. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.fans.json +12 -0
  59. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/ashrae_90_1.schedules.json +45 -45
  60. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/comstock_doe_ref_1980_2004.spc_typ.json +10 -10
  61. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/ashrae_90_1.schedules.json +45 -45
  62. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/comstock_doe_ref_pre_1980.spc_typ.json +10 -10
  63. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +1 -0
  64. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +792 -0
  65. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +10 -0
  66. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +31 -0
  67. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +91 -0
  68. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +84 -0
  69. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +145 -0
  70. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +106 -0
  71. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +71 -0
  72. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +194 -0
  73. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +120 -0
  74. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +110 -0
  75. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +5 -0
  76. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Fan.rb +73 -0
  77. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +5 -0
  78. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +5 -0
  79. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +24 -0
  80. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanZoneExhaust.rb +5 -0
  81. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +55 -0
  82. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +3045 -0
  83. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +187 -0
  84. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +450 -0
  85. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +106 -0
  86. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +666 -0
  87. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +54 -0
  88. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +168 -0
  89. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +132 -0
  90. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +239 -0
  91. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +176 -0
  92. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +25 -0
  93. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +52 -0
  94. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.chillers.json +112 -0
  95. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.climate_zone_sets.json +210 -0
  96. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +10384 -0
  97. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_sets.json +133 -0
  98. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.furnaces.json +43 -0
  99. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_pumps.json +119 -0
  100. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_pumps_heating.json +130 -0
  101. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_rejection.json +13 -0
  102. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.lpd_space_type.json +568 -0
  103. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.motors.json +264 -0
  104. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_baseline_hvac.json +439 -0
  105. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_constructions.json +685 -0
  106. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_economizers.json +213 -0
  107. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_ext_ltg.json +32 -0
  108. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_heat_type.json +136 -0
  109. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_hvac_bldg_type.json +32 -0
  110. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json +1837 -0
  111. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_swh_bldg_type.json +184 -0
  112. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_wwr_bldg_type.json +84 -0
  113. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.unitary_acs.json +148 -0
  114. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.water_heaters.json +157 -0
  115. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.climate_zone_sets.json +210 -0
  116. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.curves.json +18329 -0
  117. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.fans.json +340 -0
  118. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.materials.json +49924 -0
  119. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_building_rotation_exception.md +44 -0
  120. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/check_pump_power_and_control.md +71 -0
  121. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv.md +68 -0
  122. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv_implementation.png +0 -0
  123. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/elevators.md +14 -0
  124. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/exhaust_air_energy_recovery.md +36 -0
  125. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/f_c_factors.md +19 -0
  126. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/fan_power_credits.md +15 -0
  127. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/preheat_coil.md +59 -0
  128. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/pump_power_control.md +46 -0
  129. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/return_air_type.md +31 -0
  130. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_baseline_wwr.md +191 -0
  131. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_hw_and_chw_supply_water_temp_reset_control.md +24 -0
  132. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_num_boilers_chillers_towers.md +49 -0
  133. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +80 -0
  134. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_space_lpd.md +73 -0
  135. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unenclosed_and_unconditioned_spaces.md +11 -0
  136. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unmet_load_hours.md +20 -0
  137. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_parallel_piu_terminals_fan_control.md +23 -0
  138. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_terminals_min_flow_setpoint.md +21 -0
  139. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac.csv +1 -0
  140. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac_doas.csv +1 -0
  141. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_building.csv +1 -0
  142. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_design_specification_outdoor_air.csv +1 -0
  143. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_electric_equipment.csv +1 -0
  144. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_exterior_lights.csv +1 -0
  145. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_gas_equipment.csv +1 -0
  146. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_lights.csv +1 -0
  147. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -0
  148. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_spacetype.csv +1 -0
  149. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_thermal_zone.csv +1 -0
  150. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_connections.csv +1 -0
  151. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment.csv +1 -0
  152. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment_definition.csv +1 -0
  153. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_hvac.csv +1 -0
  154. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_infiltration.csv +1 -0
  155. data/lib/openstudio-standards/standards/cbes/data/cbes.fans.json +12 -0
  156. data/lib/openstudio-standards/standards/deer/data/deer.fans.json +12 -0
  157. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps.json +1 -1
  158. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps_heating.json +1 -1
  159. data/lib/openstudio-standards/standards/necb/ECMS/data/unitary_acs.json +24 -11
  160. data/lib/openstudio-standards/standards/necb/ECMS/erv.rb +13 -15
  161. data/lib/openstudio-standards/standards/necb/NECB2011/data/province_map.json +17 -0
  162. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +1 -1
  163. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +1 -1
  164. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +2 -2
  165. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +6 -5
  166. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +3 -2
  167. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +2 -3
  168. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +2 -2
  169. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +33 -924
  170. data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +15 -15
  171. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +135 -29
  172. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +16 -4
  173. data/lib/openstudio-standards/standards/necb/common/neb_end_use_prices.csv +40 -42
  174. data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +1 -1
  175. data/lib/openstudio-standards/standards/necb/common/space_type_upgrade_map.json +89 -89
  176. data/lib/openstudio-standards/utilities/array.rb +11 -0
  177. data/lib/openstudio-standards/utilities/logging.rb +48 -0
  178. data/lib/openstudio-standards/utilities/object_info.rb +20 -0
  179. data/lib/openstudio-standards/utilities/schedule_translator.rb +348 -0
  180. data/lib/openstudio-standards/utilities/sqlfile.rb +68 -0
  181. data/lib/openstudio-standards/version.rb +2 -2
  182. data/lib/openstudio-standards/weather/Weather.Model.rb +42 -55
  183. data/lib/openstudio-standards/weather/Weather.stat_file.rb +1 -1
  184. data/lib/openstudio-standards.rb +35 -1
  185. metadata +111 -6
  186. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  187. data/data/standards/OpenStudio_Standards-ashrae_90_1_28Jan2022.xlsx +0 -0
  188. data/data/standards/OpenStudio_Standards-ashrae_90_1_28_Jan2022_2.xlsx +0 -0
  189. data/data/standards/openstudio_standards_duplicates_log.csv +0 -143
@@ -31,6 +31,30 @@ class Standard
31
31
  return space_type_properties
32
32
  end
33
33
 
34
+ def interior_lighting_get_prm_data(space_type)
35
+ standards_space_type = if space_type.is_a? String
36
+ space_type
37
+ elsif space_type.standardsSpaceType.is_initialized
38
+ space_type.standardsSpaceType.get
39
+ end
40
+
41
+ # populate search hash
42
+ search_criteria = {
43
+ 'template' => template,
44
+ 'lpd_space_type' => standards_space_type
45
+ }
46
+
47
+ # lookup space type properties
48
+ interior_lighting_properties = model_find_object(standards_data['prm_interior_lighting'], search_criteria)
49
+
50
+ if interior_lighting_properties.nil?
51
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.SpaceType', "Interior lighting PRM properties lookup failed: #{search_criteria}.")
52
+ interior_lighting_properties = {}
53
+ end
54
+
55
+ return interior_lighting_properties
56
+ end
57
+
34
58
  # Sets the color for the space types as shown in the SketchUp plugin using render by space type.
35
59
  #
36
60
  # @param space_type [OpenStudio::Model::SpaceType] space type object
@@ -194,8 +218,7 @@ class Standard
194
218
  lights_frac_high_bay = space_type_properties['lpd_fraction_high_bay']
195
219
  lights_frac_specialty_lighting = space_type_properties['lpd_fraction_specialty_lighting']
196
220
  lights_frac_exit_lighting = space_type_properties['lpd_fraction_exit_lighting']
197
- lights_have_info = true unless lighting_per_area.zero?
198
- lights_have_info = true unless lighting_per_person.zero?
221
+ lights_have_info = true unless lighting_per_area.zero? && lighting_per_person.zero?
199
222
 
200
223
  if set_lights && lights_have_info
201
224
 
@@ -451,6 +474,121 @@ class Standard
451
474
  end
452
475
  end
453
476
 
477
+ # Sets the internal loads for Appendix G PRM for 2016 and later
478
+ # Initially, only lighting power density will be set
479
+ # Possibly infiltration will also be set from here
480
+ #
481
+ # @param model [OpenStudio::Model::SpaceType] OpenStudio space type object
482
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
483
+ def space_type_apply_int_loads_prm(space_type, model)
484
+ # Skip plenums
485
+ # Check if the space type name
486
+ # contains the word plenum.
487
+ if space_type.name.get.to_s.downcase.include?('plenum')
488
+ return false
489
+ end
490
+
491
+ if space_type.standardsSpaceType.is_initialized
492
+ if space_type.standardsSpaceType.get.downcase.include?('plenum')
493
+ return false
494
+ end
495
+ end
496
+
497
+ # Get the standards data
498
+ space_type_properties = interior_lighting_get_prm_data(space_type)
499
+
500
+ # Need to add a check, or it'll crash on space_type_properties['occupancy_per_area'].to_f below
501
+ if space_type_properties.nil?
502
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} was not found in the standards data.")
503
+ return false
504
+ end
505
+
506
+ # Lights
507
+ lights_have_info = false
508
+ lighting_per_area = space_type_properties['w/ft^2'].to_f
509
+ lighting_per_length = space_type_properties['w/ft'].to_f
510
+ lights_have_info = true unless lighting_per_area.zero? && lighting_per_length.zero?
511
+ multiple_lpd_value_check = false
512
+
513
+ if lighting_per_length > 0
514
+ if space_type.spaces.size == 1
515
+ # Space height
516
+ space = space_type.spaces[0]
517
+ space_volume = space.volume
518
+ space_area = space.floorArea
519
+ space_height = space_volume / space_area
520
+ # New lpd value
521
+ lighting_per_area += lighting_per_length * space_height
522
+ else
523
+ lighting_per_area_hash = {}
524
+ multiple_lpd_value_check = true
525
+ space_type.spaces.each do |space|
526
+ # Space height
527
+ space_volume = space.volume
528
+ space_area = space.floorArea
529
+ space_height = space_volume / space_area
530
+ # New lpd values
531
+ lighting_per_area_new = lighting_per_area + lighting_per_length * space_height
532
+ lighting_per_area_hash[space.name.to_s] = lighting_per_area_new
533
+ end
534
+ end
535
+ end
536
+
537
+ if lights_have_info
538
+ # Remove all but the first instance
539
+ instances = space_type.lights.sort
540
+ if instances.size.zero?
541
+ definition = OpenStudio::Model::LightsDefinition.new(space_type.model)
542
+ definition.setName("#{space_type.name} Lights Definition")
543
+ instance = OpenStudio::Model::Lights.new(definition)
544
+ instance.setName("#{space_type.name} Lights")
545
+ instance.setSpaceType(space_type)
546
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no lights, one has been created.")
547
+ instances << instance
548
+ elsif instances.size > 1
549
+ instances.each_with_index do |inst, i|
550
+ next if i.zero?
551
+
552
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "Removed #{inst.name} from #{space_type.name}.")
553
+ inst.remove
554
+ end
555
+ end
556
+ # Modify the definition of the instance
557
+ if multiple_lpd_value_check == false
558
+ space_type.lights.sort.each do |inst|
559
+ definition = inst.lightsDefinition
560
+ unless lighting_per_area.zero?
561
+ occ_sens_lpd_factor = 1.0
562
+ definition.setWattsperSpaceFloorArea(OpenStudio.convert(lighting_per_area.to_f * occ_sens_lpd_factor, 'W/ft^2', 'W/m^2').get)
563
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set LPD to #{lighting_per_area} W/ft^2.")
564
+ end
565
+ end
566
+ else
567
+ space_type.spaces.each do |space|
568
+ new_space_type = space_type.clone.to_SpaceType.get
569
+ space.setSpaceType(new_space_type)
570
+ lighting_per_area = lighting_per_area_hash[space.name.to_s]
571
+ new_space_type.lights.sort.each do |inst|
572
+ definition = inst.lightsDefinition
573
+ unless lighting_per_area.zero?
574
+ occ_sens_lpd_factor = 1.0
575
+ definition.setWattsperSpaceFloorArea(OpenStudio.convert(lighting_per_area.to_f * occ_sens_lpd_factor, 'W/ft^2', 'W/m^2').get)
576
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set LPD to #{lighting_per_area} W/ft^2.")
577
+ end
578
+ end
579
+ end
580
+ space_type.remove
581
+ end
582
+ end
583
+ end
584
+
585
+ # Modify the lighting schedules for Appendix G PRM for 2016 and later
586
+ #
587
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
588
+ def space_type_light_sch_change(model)
589
+ return true
590
+ end
591
+
454
592
  # Sets the schedules for the selected internal loads to typical schedules.
455
593
  # Get the default schedule set for this space type if one exists or make
456
594
  # one if none exists. For each category that is selected, add the typical
@@ -584,7 +722,7 @@ class Standard
584
722
  end
585
723
 
586
724
  # get climate_zone_set
587
- climate_zone = model_get_building_climate_zone_and_building_type(space_type.model)['climate_zone']
725
+ climate_zone = model_get_building_properties(space_type.model)['climate_zone']
588
726
  climate_zone_set = model_find_climate_zone_set(space_type.model, climate_zone)
589
727
 
590
728
  # populate search hash
@@ -605,7 +743,6 @@ class Standard
605
743
  construction_properties = model_find_object(standards_data['construction_properties'], search_criteria)
606
744
  end
607
745
 
608
-
609
746
  return construction_properties
610
747
  end
611
748
  end
@@ -80,7 +80,8 @@ class Standard
80
80
  # @param percent_reduction [Double] the fractional amount to reduce the area
81
81
  # @return [Bool] returns true if successful, false if not
82
82
  def sub_surface_reduce_area_by_percent_by_shrinking_toward_centroid(sub_surface, percent_reduction)
83
- mult = 1 - percent_reduction
83
+ # if percent_reduction > 1=> percent increase instead of reduction
84
+ mult = percent_reduction <= 1 ? 1 - percent_reduction : percent_reduction
84
85
  scale_factor = mult**0.5
85
86
 
86
87
  # Get the centroid (Point3d)
@@ -379,6 +379,70 @@ class Standard
379
379
  return roof_cent
380
380
  end
381
381
 
382
+ # Returns the surface and subsurface UA product
383
+ #
384
+ # @param [OpenStudio::Model::Surface] OpenStudio model surface object
385
+ #
386
+ # @retrun [Double] UA product in W/K
387
+ def surface_subsurface_ua(surface)
388
+ # Compute the surface UA product
389
+ if surface.outsideBoundaryCondition.to_s == 'GroundFCfactorMethod' && surface.construction.is_initialized
390
+ cons = surface.construction.get
391
+ fc_obj_type = cons.iddObjectType.valueName.to_s
392
+ case fc_obj_type
393
+ when 'OS_Construction_FfactorGroundFloor'
394
+ cons = surface.construction.get.to_FFactorGroundFloorConstruction.get
395
+ ffac = cons.fFactor
396
+ area = cons.area
397
+ peri = cons.perimeterExposed
398
+ ua = ffac * peri * surface.netArea / area
399
+ when 'OS_Construction_CfactorUndergroundWall'
400
+ cons = surface.construction.get.to_CFactorUndergroundWallConstruction.get
401
+ cfac = cons.cFactor
402
+ heig = cons.height
403
+
404
+ # From 90.1-2019 Section A.9.4.1: Interior vertical surfaces (SI units)
405
+ r_inside_film = 0.1197548
406
+ r_outside_film = 0.0
407
+
408
+ # EnergyPlus Engineering Manual equation 3.195
409
+ r_soil = 0.0607 + 0.3479 * heig
410
+
411
+ r_eff = 1 / cfac + r_soil
412
+ u_eff = 1 / (r_eff + r_inside_film + r_outside_film)
413
+
414
+ ua = u_eff * surface.netArea
415
+ end
416
+ else
417
+ ua = surface.uFactor.get * surface.netArea
418
+ end
419
+
420
+ surface.subSurfaces.sort.each do |subsurface|
421
+ if subsurface.construction.get.to_Construction.get.layers[0].to_Material.get.to_SimpleGlazing.empty?
422
+ # the uFactor() method does not work for complex glazing inputs
423
+ # For this case the U-Factor is retrieved from previous sizing run
424
+ u_factor = construction_calculated_fenestration_u_factor_w_frame(subsurface.construction.get)
425
+ else
426
+ # replace with direct query: u_factor = subsurface.uFactor.get
427
+ glass_u_factor_query = "SELECT Value
428
+ FROM tabulardatawithstrings
429
+ WHERE ReportName='EnvelopeSummary'
430
+ AND ReportForString='Entire Facility'
431
+ AND TableName='Exterior Fenestration'
432
+ AND ColumnName='Glass U-Factor'
433
+ AND RowName='#{subsurface.name.get.upcase}'"
434
+ sql = surface.model.sqlFile.get
435
+
436
+ glass_u_factor_w_per_m2_k = sql.execAndReturnFirstDouble(glass_u_factor_query)
437
+ u_factor = glass_u_factor_w_per_m2_k.is_initialized ? glass_u_factor_w_per_m2_k.get : 0.0
438
+ end
439
+ # u_factor = subsurface.uFactor.is_initialized ? (subsurface.uFactor.get) : (construction_calculated_fenestration_u_factor_w_frame(subsurface.construction.get))
440
+ ua += u_factor * subsurface.netArea
441
+ end
442
+
443
+ return ua
444
+ end
445
+
382
446
  # Calculate a surface's absolute azimuth
383
447
  # source: https://github.com/NREL/openstudio-extension-gem/blob/e354355054b83ffc26e3b69befa20d6baf5ef242/lib/openstudio/extension/core/os_lib_geometry.rb#L913
384
448
  #
@@ -422,4 +486,57 @@ class Standard
422
486
  return 'W'
423
487
  end
424
488
  end
489
+
490
+ # Calculate the wwr of a surface
491
+ #
492
+ # @param surface [OpenStudio::Model::Surface]
493
+ # @return [Float] window to wall ratio of a surface
494
+ def surface_get_wwr_of_a_surface(surface)
495
+ surface_area = surface.grossArea
496
+ surface_fene_area = 0.0
497
+ surface.subSurfaces.sort.each do |ss|
498
+ next unless ss.subSurfaceType == 'FixedWindow' || ss.subSurfaceType == 'OperableWindow' || ss.subSurfaceType == 'GlassDoor'
499
+
500
+ surface_fene_area += ss.netArea
501
+ end
502
+ return surface_fene_area / surface_area
503
+ end
504
+
505
+ # Adjust the fenestration area to the values specified by the reduction value in a surface
506
+ #
507
+ # @param surface [OpenStudio::Model:Surface] openstudio surface object
508
+ # @param reduction [Float] ratio of adjustments
509
+ # @param model [OpenStudio::Model::Model] openstudio model
510
+ # @return [Bool] return true if successful, false if not
511
+ def surface_adjust_fenestration_in_a_surface(surface, reduction, model)
512
+ # Subsurfaces in this surface
513
+ # Default case only handles reduction
514
+ if reduction < 1.0
515
+ surface.subSurfaces.sort.each do |ss|
516
+ next unless ss.subSurfaceType == 'FixedWindow' || ss.subSurfaceType == 'OperableWindow' || ss.subSurfaceType == 'GlassDoor'
517
+
518
+ if sub_surface_vertical_rectangle?(ss)
519
+ sub_surface_reduce_area_by_percent_by_raising_sill(ss, reduction)
520
+ else
521
+ sub_surface_reduce_area_by_percent_by_shrinking_toward_centroid(ss, reduction)
522
+ end
523
+ end
524
+ end
525
+ return true
526
+ end
527
+
528
+ # Calculate the door ratio of a surface
529
+ #
530
+ # @param surface [OpenStudio::Model::Surface]
531
+ # @return [Float] window to wall ratio of a surface
532
+ def surface_get_door_ratio_of_a_surface(surface)
533
+ surface_area = surface.grossArea
534
+ surface_door_area = 0.0
535
+ surface.subSurfaces.sort.each do |ss|
536
+ next unless ss.subSurfaceType == 'Door'
537
+
538
+ surface_door_area += ss.netArea
539
+ end
540
+ return surface_door_area / surface_area
541
+ end
425
542
  end
@@ -625,6 +625,14 @@ class Standard
625
625
  return is_fossil
626
626
  end
627
627
 
628
+ # for 2013 and prior, baseline fuel = proposed fuel
629
+ # @param themal_zone
630
+ # @return [string] with applicable DistrictHeating and/or DistrictCooling
631
+ def thermal_zone_get_zone_fuels_for_occ_and_fuel_type(zone)
632
+ zone_fuels = thermal_zone_fossil_or_electric_type(zone, '')
633
+ return zone_fuels
634
+ end
635
+
628
636
  # Determine if the thermal zone's fuel type category.
629
637
  # Options are:
630
638
  # fossil, electric, unconditioned
@@ -1217,6 +1225,8 @@ class Standard
1217
1225
  end
1218
1226
  end
1219
1227
  end
1228
+ elsif tstat.to_ThermostatSetpointSingleHeating
1229
+ cld = false
1220
1230
  end
1221
1231
 
1222
1232
  return cld
@@ -1273,11 +1283,14 @@ class Standard
1273
1283
  end
1274
1284
 
1275
1285
  # Determines whether the zone is conditioned per 90.1, which is based on heating and cooling loads.
1286
+ # Logic to detect indirectly-conditioned spaces cannot be implemented
1287
+ # as part of this measure as it would need to call itself.
1288
+ # It is implemented as part of space_conditioning_category().
1289
+ # TODO: Add addendum db rules to 90.1-2019 for 90.1-2022 (use stable baseline value for zones designated as semiheated using proposed sizing run)
1276
1290
  #
1277
1291
  # @param thermal_zone [OpenStudio::Model::ThermalZone] thermal zone
1278
1292
  # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
1279
1293
  # @return [String] NonResConditioned, ResConditioned, Semiheated, Unconditioned
1280
- # @todo add logic to detect indirectly-conditioned spaces
1281
1294
  def thermal_zone_conditioning_category(thermal_zone, climate_zone)
1282
1295
  # Get the heating load
1283
1296
  htg_load_btu_per_ft2 = 0.0
@@ -1296,58 +1309,48 @@ class Standard
1296
1309
  # Determine the heating limit based on climate zone
1297
1310
  # From Table 3.1 Heated Space Criteria
1298
1311
  htg_lim_btu_per_ft2 = 0.0
1299
- case climate_zone
1300
- when 'ASHRAE 169-2006-0A',
1301
- 'ASHRAE 169-2006-0B',
1302
- 'ASHRAE 169-2006-1A',
1303
- 'ASHRAE 169-2006-1B',
1304
- 'ASHRAE 169-2006-2A',
1305
- 'ASHRAE 169-2006-2B',
1306
- 'ASHRAE 169-2013-0A',
1307
- 'ASHRAE 169-2013-0B',
1308
- 'ASHRAE 169-2013-1A',
1309
- 'ASHRAE 169-2013-1B',
1310
- 'ASHRAE 169-2013-2A',
1311
- 'ASHRAE 169-2013-2B'
1312
+ climate_zone_code = climate_zone.split('-')[-1]
1313
+ if ['0A', '0B', '1A', '1B', '2A', '2B'].include? climate_zone_code
1312
1314
  htg_lim_btu_per_ft2 = 5
1313
- when 'ASHRAE 169-2006-3A',
1314
- 'ASHRAE 169-2006-3B',
1315
- 'ASHRAE 169-2006-3C',
1316
- 'ASHRAE 169-2013-3A',
1317
- 'ASHRAE 169-2013-3B',
1318
- 'ASHRAE 169-2013-3C'
1315
+ stable_htg_lim_btu_per_ft2 = 5
1316
+ elsif ['3A', '3B'].include? climate_zone_code
1317
+ htg_lim_btu_per_ft2 = 9
1318
+ stable_htg_lim_btu_per_ft2 = 10
1319
+ elsif climate_zone_code == '3C'
1320
+ htg_lim_btu_per_ft2 = 7
1321
+ stable_htg_lim_btu_per_ft2 = 10
1322
+ elsif ['4A', '4B'].include? climate_zone_code
1319
1323
  htg_lim_btu_per_ft2 = 10
1320
- when 'ASHRAE 169-2006-4A',
1321
- 'ASHRAE 169-2006-4B',
1322
- 'ASHRAE 169-2006-4C',
1323
- 'ASHRAE 169-2006-5A',
1324
- 'ASHRAE 169-2006-5B',
1325
- 'ASHRAE 169-2006-5C',
1326
- 'ASHRAE 169-2013-4A',
1327
- 'ASHRAE 169-2013-4B',
1328
- 'ASHRAE 169-2013-4C',
1329
- 'ASHRAE 169-2013-5A',
1330
- 'ASHRAE 169-2013-5B',
1331
- 'ASHRAE 169-2013-5C'
1332
- htg_lim_btu_per_ft2 = 15
1333
- when 'ASHRAE 169-2006-6A',
1334
- 'ASHRAE 169-2006-6B',
1335
- 'ASHRAE 169-2006-7A',
1336
- 'ASHRAE 169-2006-7B',
1337
- 'ASHRAE 169-2013-6A',
1338
- 'ASHRAE 169-2013-6B',
1339
- 'ASHRAE 169-2013-7A',
1340
- 'ASHRAE 169-2013-7B'
1341
- htg_lim_btu_per_ft2 = 20
1342
- when 'ASHRAE 169-2006-8A',
1343
- 'ASHRAE 169-2006-8B',
1344
- 'ASHRAE 169-2013-8A',
1345
- 'ASHRAE 169-2013-8B'
1346
- htg_lim_btu_per_ft2 = 25
1324
+ stable_htg_lim_btu_per_ft2 = 15
1325
+ elsif climate_zone_code == '4C'
1326
+ htg_lim_btu_per_ft2 = 8
1327
+ stable_htg_lim_btu_per_ft2 = 15
1328
+ elsif ['5A', '5B', '5C'].include? climate_zone_code
1329
+ htg_lim_btu_per_ft2 = 12
1330
+ stable_htg_lim_btu_per_ft2 = 15
1331
+ elsif ['6A', '6B'].include? climate_zone_code
1332
+ htg_lim_btu_per_ft2 = 14
1333
+ stable_htg_lim_btu_per_ft2 = 20
1334
+ elsif ['7A', '7B'].include? climate_zone_code
1335
+ htg_lim_btu_per_ft2 = 16
1336
+ stable_htg_lim_btu_per_ft2 = 20
1337
+ elsif ['8A', '8B'].include? climate_zone_code
1338
+ htg_lim_btu_per_ft2 = 19
1339
+ stable_htg_lim_btu_per_ft2 = 25
1340
+ end
1341
+
1342
+ # for older code versions use stable baseline value as primary target
1343
+ if ['90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013'].include? template
1344
+ htg_lim_btu_per_ft2 = stable_htg_lim_btu_per_ft2
1347
1345
  end
1348
1346
 
1349
1347
  # Cooling limit is climate-independent
1350
- clg_lim_btu_per_ft2 = 5
1348
+ case template
1349
+ when '90.1-2016', '90.1-PRM-2019'
1350
+ clg_lim_btu_per_ft2 = 3.4
1351
+ else
1352
+ clg_lim_btu_per_ft2 = 5
1353
+ end
1351
1354
 
1352
1355
  # Semiheated limit is climate-independent
1353
1356
  semihtd_lim_btu_per_ft2 = 3.4
@@ -1388,6 +1391,11 @@ class Standard
1388
1391
  # @return [Double] the design heating supply temperature, in degrees Celsius
1389
1392
  # @todo Exception: 17F delta-T for labs
1390
1393
  def thermal_zone_prm_baseline_heating_design_supply_temperature(thermal_zone)
1394
+ unit_heater_sup_temp = thermal_zone_prm_unitheater_design_supply_temperature(thermal_zone)
1395
+ unless unit_heater_sup_temp.nil?
1396
+ return unit_heater_sup_temp
1397
+ end
1398
+
1391
1399
  setpoint_c = nil
1392
1400
 
1393
1401
  # Setpoint schedule
@@ -1431,6 +1439,12 @@ class Standard
1431
1439
 
1432
1440
  # Add 20F delta-T
1433
1441
  delta_t_r = 20
1442
+
1443
+ new_delta_t = thermal_zone_prm_lab_delta_t(thermal_zone)
1444
+ unless new_delta_t.nil?
1445
+ delta_t_r = new_delta_t
1446
+ end
1447
+
1434
1448
  delta_t_k = OpenStudio.convert(delta_t_r, 'R', 'K').get
1435
1449
 
1436
1450
  sat_c = setpoint_c + delta_t_k # Add for heating
@@ -1488,6 +1502,16 @@ class Standard
1488
1502
 
1489
1503
  # Subtract 20F delta-T
1490
1504
  delta_t_r = 20
1505
+ if /prm/i =~ template # avoid affecting previous PRM tests
1506
+ # For labs, substract 17 delta-T; otherwise, substract 20 delta-T
1507
+ thermal_zone.spaces.each do |space|
1508
+ space_std_type = space.spaceType.get.standardsSpaceType.get
1509
+ if space_std_type == 'laboratory'
1510
+ delta_t_r = 17
1511
+ end
1512
+ end
1513
+ end
1514
+
1491
1515
  delta_t_k = OpenStudio.convert(delta_t_r, 'R', 'K').get
1492
1516
 
1493
1517
  sat_c = setpoint_c - delta_t_k # Subtract for cooling
@@ -1572,6 +1596,93 @@ class Standard
1572
1596
  return load_w
1573
1597
  end
1574
1598
 
1599
+ # Determine the peak internal load (W) for
1600
+ # this zone without space multipliers.
1601
+ # This includes People, Lights, and all equipment types
1602
+ # in all spaces in this zone.
1603
+ # @author Doug Maddox, PNNL
1604
+ # @return [Double] the design internal load, in W
1605
+ def thermal_zone_peak_internal_load(model, thermal_zone, use_noncoincident_value: true)
1606
+ load_w = 0.0
1607
+ load_hrs_sum = Array.new(8760, 0)
1608
+
1609
+ if !use_noncoincident_value
1610
+ # Get array of coincident internal gain
1611
+ thermal_zone.spaces.each do |space|
1612
+ load_hrs = space_internal_load_annual_array(model, space, use_noncoincident_value)
1613
+ (0..8759).each do |ihr|
1614
+ load_hrs_sum[ihr] += load_hrs[ihr]
1615
+ end
1616
+ end
1617
+ load_w = load_hrs_sum.max
1618
+ else
1619
+ # Get the non-coincident sum of peak internal gains
1620
+ thermal_zone.spaces.each do |space|
1621
+ load_w += space_internal_load_annual_array(model, space, use_noncoincident_value)
1622
+ end
1623
+ end
1624
+
1625
+ return load_w
1626
+ end
1627
+
1628
+ # This is the operating hours for calulating EFLH which is used for determining whether a zone
1629
+ # should be included in a multizone system or isolated to a separate PSZ system
1630
+ # Based on the occupancy schedule for that zone
1631
+ # @author Doug Maddox, PNNL
1632
+ # @return [Array] 8760 array with 1 = operating, 0 = not operating
1633
+ def thermal_zone_get_annual_operating_hours(model, zone, zone_fan_sched)
1634
+ zone_ppl_sch = Array.new(8760, 0) # merged people schedule for zone
1635
+ zone_op_sch = Array.new(8760, 0) # intersection of fan and people scheds
1636
+
1637
+ unoccupied_threshold = air_loop_hvac_unoccupied_threshold
1638
+ # Need composite occupant schedule for spaces in the zone
1639
+ zone.spaces.each do |space|
1640
+ space_ppl_sch = space_occupancy_annual_array(model, space)
1641
+ # If any space is occupied, make zone occupied
1642
+ (0..8759).each do |ihr|
1643
+ zone_ppl_sch[ihr] = 1 if space_ppl_sch[ihr] > 0
1644
+ end
1645
+ end
1646
+
1647
+ zone_op_sch = zone_ppl_sch
1648
+
1649
+ return zone_op_sch
1650
+ end
1651
+
1652
+ # This is the EFLH for determining whether a zone should be included in a multizone system
1653
+ # or isolated to a separate PSZ system
1654
+ # Based on the intersection of the fan schedule for that zone and the occupancy schedule for that zone
1655
+ # @author Doug Maddox, PNNL
1656
+ # @return [Double] the design internal load, in W
1657
+ def thermal_zone_occupancy_eflh(zone, zone_op_sch)
1658
+ eflhs = [] # weekly array of eflh values
1659
+
1660
+ # Convert 8760 array to weekly eflh values
1661
+ hr_of_yr = -1
1662
+ (0..51).each do |iweek|
1663
+ eflh = 0
1664
+ (0..6).each do |iday|
1665
+ (0..23).each do |ihr|
1666
+ hr_of_yr += 1
1667
+ eflh += zone_op_sch[hr_of_yr]
1668
+ end
1669
+ end
1670
+ eflhs << eflh
1671
+ end
1672
+
1673
+ # Choose the most used weekly schedule as the representative eflh
1674
+ # This is the statistical mode of the array of values
1675
+ eflh_mode_list = eflhs.mode
1676
+
1677
+ if eflh_mode_list.size > 1
1678
+ # Mode is an array of multiple values, take the largest value
1679
+ eflh = eflh_mode_list.max
1680
+ else
1681
+ eflh = eflh_mode_list[0]
1682
+ end
1683
+ return eflh
1684
+ end
1685
+
1575
1686
  # Returns the space type that represents a majority of the floor area.
1576
1687
  #
1577
1688
  # @param thermal_zone [OpenStudio::Model::ThermalZone] thermal zone
@@ -1889,7 +2000,6 @@ class Standard
1889
2000
  # @return [Bool] returns true if successful, false if not
1890
2001
  # @todo this method is currently empty
1891
2002
  def thermal_zone_add_exhaust_fan_dcv(thermal_zone, change_related_objects = true, zone_mixing_objects = [], transfer_air_source_zones = [])
1892
-
1893
2003
  # set flow fraction schedule for all zone exhaust fans and then set zone mixing schedule to the intersection of exhaust availability and exhaust fractional schedule
1894
2004
 
1895
2005
  # are there associated zone mixing or dummy exhaust objects that need to change when this changes?
@@ -1897,4 +2007,42 @@ class Standard
1897
2007
  # If this is run directly after thermal_zone_add_exhaust(thermal_zone) it will return a hash where each key is an exhaust object and hash is a hash of related zone mixing and dummy exhaust from the source zone
1898
2008
  return true
1899
2009
  end
2010
+
2011
+ # Specify supply air temperature setpoint for unit heaters based on 90.1 Appendix G G3.1.2.8.2 (implementation in PRM subclass)
2012
+ def thermal_zone_prm_unitheater_design_supply_temperature(thermal_zone)
2013
+ return nil
2014
+ end
2015
+
2016
+ # Specify supply to room delta for laboratory spaces based on 90.1 Appendix G Exception to G3.1.2.8.1 (implementation in PRM subclass)
2017
+ def thermal_zone_prm_lab_delta_t(thermal_zone)
2018
+ return nil
2019
+ end
2020
+
2021
+ # Determine the number of unmet load hours during occupancy for a thermal zone
2022
+ #
2023
+ # @param thermal_zone [OpenStudio::Model::ThermalZone] OpenStudio ThermalZone object
2024
+ # @param umlh_type [String] Type of unmet load hours, either 'Cooling' or 'Heating'
2025
+ def thermal_zone_get_unmet_load_hours(thermal_zone, umlh_type)
2026
+ umlh = OpenStudio::OptionalDouble.new
2027
+ sql = thermal_zone.model.sqlFile
2028
+ if sql.is_initialized
2029
+ sql = sql.get
2030
+ query = "SELECT Value
2031
+ FROM tabulardatawithstrings
2032
+ WHERE ReportName='SystemSummary'
2033
+ AND ReportForString='Entire Facility'
2034
+ AND TableName='Time Setpoint Not Met'
2035
+ AND ColumnName='During Occupied #{umlh_type.capitalize}'
2036
+ AND RowName='#{thermal_zone.name.to_s.upcase}'
2037
+ AND Units='hr'"
2038
+ val = sql.execAndReturnFirstDouble(query)
2039
+ if val.is_initialized
2040
+ umlh = OpenStudio::OptionalDouble.new(val.get)
2041
+ end
2042
+ else
2043
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'Model has no sql file containing results, cannot lookup data.')
2044
+ end
2045
+
2046
+ return umlh.to_f
2047
+ end
1900
2048
  end
@@ -86,6 +86,47 @@ class Standard
86
86
  return true
87
87
  end
88
88
 
89
+ # Get the supply fan object for a zone equipment component
90
+ # @author Doug Maddox, PNNL
91
+ # @param zone_hvac_component [object]
92
+ # @return [object] supply fan of zone equipment component
93
+ def zone_hvac_get_fan_object(zone_hvac_component)
94
+ zone_hvac = nil
95
+ # Check for any zone equipment type that has a supply fan
96
+ # except EnergyRecoveryVentilator, which is not a primary conditioning system
97
+ zone_hvac = if zone_hvac_component.to_ZoneHVACFourPipeFanCoil.is_initialized
98
+ zone_hvac_component.to_ZoneHVACFourPipeFanCoil.get
99
+ elsif zone_hvac_component.to_ZoneHVACPackagedTerminalAirConditioner.is_initialized
100
+ zone_hvac_component.to_ZoneHVACPackagedTerminalAirConditioner.get
101
+ elsif zone_hvac_component.to_ZoneHVACPackagedTerminalHeatPump.is_initialized
102
+ zone_hvac_component.to_ZoneHVACPackagedTerminalHeatPump.get
103
+ elsif zone_hvac_component.to_ZoneHVACTerminalUnitVariableRefrigerantFlow.is_initialized
104
+ zone_hvac_component.to_ZoneHVACTerminalUnitVariableRefrigerantFlow.get
105
+ elsif zone_hvac_component.to_ZoneHVACUnitHeater.is_initialized
106
+ zone_hvac_component.to_ZoneHVACUnitHeater.get
107
+ elsif zone_hvac_component.to_ZoneHVACUnitVentilator.is_initialized
108
+ zone_hvac_component.to_ZoneHVACUnitVentilator.get
109
+ elsif zone_hvac_component.to_ZoneHVACWaterToAirHeatPump.is_initialized
110
+ zone_hvac_component.to_ZoneHVACWaterToAirHeatPump.get
111
+ end
112
+
113
+ # Get the fan
114
+ if !zone_hvac.nil?
115
+ fan_obj = if zone_hvac.supplyAirFan.to_FanConstantVolume.is_initialized
116
+ zone_hvac.supplyAirFan.to_FanConstantVolume.get
117
+ elsif zone_hvac.supplyAirFan.to_FanVariableVolume.is_initialized
118
+ zone_hvac.supplyAirFan.to_FanVariableVolume.get
119
+ elsif zone_hvac.supplyAirFan.to_FanOnOff.is_initialized
120
+ zone_hvac.supplyAirFan.to_FanOnOff.get
121
+ elsif zone_hvac.supplyAirFan.to_FanSystemModel.is_initialized
122
+ zone_hvac.supplyAirFan.to_FanSystemModel.get
123
+ end
124
+ return fan_obj
125
+ else
126
+ return nil
127
+ end
128
+ end
129
+
89
130
  # Default occupancy fraction threshold for determining if the spaces served by the zone hvac are occupied
90
131
  #
91
132
  # @return [Double] unoccupied threshold