openstudio-standards 0.2.16 → 0.2.17.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/data/standards/manage_OpenStudio_Standards.rb +31 -4
  3. data/lib/openstudio-standards/btap/geometry.rb +1 -1
  4. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +354 -2
  5. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +79 -0
  6. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +1 -1
  7. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +1 -1
  8. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +3313 -0
  9. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +12 -0
  10. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +3 -4
  11. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
  12. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +167 -93
  13. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +2 -4
  14. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +1 -0
  15. data/lib/openstudio-standards/refs/references.rb +3 -0
  16. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +279 -6
  17. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +50 -2
  18. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +4 -0
  19. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -1
  20. data/lib/openstudio-standards/standards/Standards.Construction.rb +185 -3
  21. data/lib/openstudio-standards/standards/Standards.Fan.rb +14 -6
  22. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +1 -0
  23. data/lib/openstudio-standards/standards/Standards.Model.rb +1751 -383
  24. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +130 -9
  25. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +50 -3
  26. data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +44 -0
  27. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +27 -0
  28. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +543 -0
  29. data/lib/openstudio-standards/standards/Standards.Space.rb +665 -15
  30. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +141 -4
  31. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +2 -1
  32. data/lib/openstudio-standards/standards/Standards.Surface.rb +117 -0
  33. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +197 -49
  34. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +41 -0
  35. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +6 -8
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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
  44. 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
  45. 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
  46. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +5 -5
  47. 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
  48. 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
  49. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +2 -2
  50. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.fans.json +12 -0
  51. 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
  52. 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
  53. 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
  54. 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
  55. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +1 -0
  56. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +792 -0
  57. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +10 -0
  58. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +31 -0
  59. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +91 -0
  60. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +84 -0
  61. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +145 -0
  62. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +106 -0
  63. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +71 -0
  64. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +194 -0
  65. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +120 -0
  66. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +110 -0
  67. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +5 -0
  68. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Fan.rb +73 -0
  69. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +5 -0
  70. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +5 -0
  71. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +24 -0
  72. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanZoneExhaust.rb +5 -0
  73. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +55 -0
  74. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +3045 -0
  75. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +187 -0
  76. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +450 -0
  77. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +106 -0
  78. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +666 -0
  79. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +54 -0
  80. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +168 -0
  81. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +132 -0
  82. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +239 -0
  83. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +176 -0
  84. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +25 -0
  85. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +52 -0
  86. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.chillers.json +112 -0
  87. 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
  88. 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
  89. 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
  90. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.furnaces.json +43 -0
  91. 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
  92. 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
  93. 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
  94. 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
  95. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.motors.json +264 -0
  96. 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
  97. 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
  98. 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
  99. 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
  100. 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
  101. 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
  102. 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
  103. 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
  104. 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
  105. 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
  106. 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
  107. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.climate_zone_sets.json +210 -0
  108. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.curves.json +18329 -0
  109. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.fans.json +340 -0
  110. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.materials.json +49924 -0
  111. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_building_rotation_exception.md +44 -0
  112. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/check_pump_power_and_control.md +71 -0
  113. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv.md +68 -0
  114. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv_implementation.png +0 -0
  115. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/elevators.md +14 -0
  116. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/exhaust_air_energy_recovery.md +36 -0
  117. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/f_c_factors.md +19 -0
  118. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/fan_power_credits.md +15 -0
  119. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/preheat_coil.md +59 -0
  120. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/pump_power_control.md +46 -0
  121. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/return_air_type.md +31 -0
  122. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_baseline_wwr.md +191 -0
  123. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_hw_and_chw_supply_water_temp_reset_control.md +24 -0
  124. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_num_boilers_chillers_towers.md +49 -0
  125. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +80 -0
  126. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_space_lpd.md +73 -0
  127. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unenclosed_and_unconditioned_spaces.md +11 -0
  128. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unmet_load_hours.md +20 -0
  129. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_parallel_piu_terminals_fan_control.md +23 -0
  130. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_terminals_min_flow_setpoint.md +21 -0
  131. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac.csv +1 -0
  132. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac_doas.csv +1 -0
  133. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_building.csv +1 -0
  134. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_design_specification_outdoor_air.csv +1 -0
  135. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_electric_equipment.csv +1 -0
  136. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_exterior_lights.csv +1 -0
  137. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_gas_equipment.csv +1 -0
  138. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_lights.csv +1 -0
  139. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -0
  140. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_spacetype.csv +1 -0
  141. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_thermal_zone.csv +1 -0
  142. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_connections.csv +1 -0
  143. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment.csv +1 -0
  144. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment_definition.csv +1 -0
  145. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_hvac.csv +1 -0
  146. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_infiltration.csv +1 -0
  147. data/lib/openstudio-standards/standards/cbes/data/cbes.fans.json +12 -0
  148. data/lib/openstudio-standards/standards/deer/data/deer.fans.json +12 -0
  149. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps.json +1 -1
  150. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps_heating.json +1 -1
  151. data/lib/openstudio-standards/standards/necb/ECMS/data/unitary_acs.json +24 -11
  152. data/lib/openstudio-standards/standards/necb/ECMS/erv.rb +13 -15
  153. data/lib/openstudio-standards/standards/necb/NECB2011/data/province_map.json +17 -0
  154. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +1 -1
  155. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +1 -1
  156. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +2 -2
  157. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +6 -5
  158. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +3 -2
  159. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +2 -3
  160. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +2 -2
  161. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +33 -924
  162. data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +15 -15
  163. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +135 -29
  164. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +16 -4
  165. data/lib/openstudio-standards/standards/necb/common/neb_end_use_prices.csv +40 -42
  166. data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +1 -1
  167. data/lib/openstudio-standards/standards/necb/common/space_type_upgrade_map.json +89 -89
  168. data/lib/openstudio-standards/utilities/array.rb +11 -0
  169. data/lib/openstudio-standards/utilities/logging.rb +48 -0
  170. data/lib/openstudio-standards/utilities/object_info.rb +20 -0
  171. data/lib/openstudio-standards/utilities/schedule_translator.rb +348 -0
  172. data/lib/openstudio-standards/utilities/sqlfile.rb +68 -0
  173. data/lib/openstudio-standards/version.rb +2 -2
  174. data/lib/openstudio-standards/weather/Weather.Model.rb +42 -55
  175. data/lib/openstudio-standards/weather/Weather.stat_file.rb +1 -1
  176. data/lib/openstudio-standards.rb +35 -1
  177. metadata +111 -6
  178. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  179. data/data/standards/OpenStudio_Standards-ashrae_90_1_28Jan2022.xlsx +0 -0
  180. data/data/standards/OpenStudio_Standards-ashrae_90_1_28_Jan2022_2.xlsx +0 -0
  181. data/data/standards/openstudio_standards_duplicates_log.csv +0 -143
@@ -0,0 +1,11 @@
1
+ # Taken from: https://github.com/rubyworks/facets/blob/master/lib/core/facets/array/mode.rb#L14
2
+ class Array
3
+ # Get most common value from an array
4
+ # If there is a tie for most common, an array is returned of the tied values
5
+ def mode
6
+ max = 0
7
+ c = Hash.new 0
8
+ each { |x| cc = c[x] += 1; max = cc if cc > max }
9
+ c.select { |k, v| v == max }.map { |k, v| k }
10
+ end
11
+ end
@@ -36,6 +36,54 @@ def log_messages_to_runner(runner, debug = false)
36
36
  end
37
37
  end
38
38
 
39
+ # A function that writes error message to log file and stop the execution.
40
+ #
41
+ # @param msg [String] error message
42
+ # @param log_level [OpenStudio::LogLevel] log level, eg. OpenStudio::Info
43
+ # @param log_path [String] the log file directory
44
+ # @param debug [Boolean] debug mode
45
+ def terminate_prm_write_log(msg, log_path, debug = false)
46
+ OpenStudio.logFree(OpenStudio::ERROR, 'prm.log', msg)
47
+ log_messages_to_file_prm("#{log_path}/prm.log", debug)
48
+ raise msg
49
+ end
50
+
51
+ # A function to export log messages specific to PRM to a log file.
52
+ #
53
+ # @param file_path [String] the file path to the log file
54
+ # @param debug [Boolean] debug mode
55
+ # @return message [Array] array of message strings
56
+ def log_messages_to_file_prm(file_path, debug = false)
57
+ messages = []
58
+
59
+ File.open(file_path, 'w') do |file|
60
+ $OPENSTUDIO_LOG.logMessages.each do |msg|
61
+ # only apply to prm
62
+ if msg.logChannel.casecmp? 'prm.log'
63
+ # Report the message in the correct way
64
+ if msg.logLevel == OpenStudio::Info
65
+ s = "[#{msg.logChannel}] INFO #{msg.logMessage}"
66
+ file.puts(s)
67
+ messages << s
68
+ elsif msg.logLevel == OpenStudio::Warn
69
+ s = "[#{msg.logChannel}] WARN #{msg.logMessage}"
70
+ file.puts(s)
71
+ messages << s
72
+ elsif msg.logLevel == OpenStudio::Error
73
+ s = "[#{msg.logChannel}] ERROR #{msg.logMessage}"
74
+ file.puts(s)
75
+ messages << s
76
+ elsif msg.logLevel == OpenStudio::Debug && debug
77
+ s = "[#{msg.logChannel}] DEBUG #{msg.logMessage}"
78
+ file.puts(s)
79
+ messages << s
80
+ end
81
+ end
82
+ end
83
+ end
84
+ return messages
85
+ end
86
+
39
87
  # Log the info, warning, and error messages to a file.
40
88
  #
41
89
  # runner @param [file_path] The path to the log file
@@ -0,0 +1,20 @@
1
+ #
2
+ # Get hash of object field names and values
3
+ # @author: Xuechen (Jerry) Lei, PNNL
4
+ # @param obj [object]
5
+ #
6
+ # @return [Hash<String>] FieldName:Value
7
+ #
8
+ def getObjectHash(obj)
9
+ fields_array = obj.to_s.split(/\n/)
10
+ output_hash = { 'object type' => fields_array.shift.split(/,/)[0] }
11
+ right = nil
12
+ fields_array.each do |ori_field|
13
+ left, right = ori_field.split(/[,;]/)
14
+ left = left.strip
15
+ right.slice!('!-')
16
+ right = right.strip
17
+ output_hash[right] = left
18
+ end
19
+ return output_hash
20
+ end
@@ -0,0 +1,348 @@
1
+ # *******************************************************************************
2
+ # The following notice pertains to the function below named
3
+ # convert_schedule_compact_to_schedule_ruleset
4
+ # *******************************************************************************
5
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
6
+ # All rights reserved.
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are met:
9
+ #
10
+ # (1) Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ #
13
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ #
17
+ # (3) Neither the name of the copyright holder nor the names of any contributors
18
+ # may be used to endorse or promote products derived from this software without
19
+ # specific prior written permission from the respective party.
20
+ #
21
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
22
+ # of modifications or other derivative works may not use the "OpenStudio"
23
+ # trademark, "OS", "os", or any other confusingly similar designation without
24
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
25
+ #
26
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
27
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
30
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
31
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
33
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
+ # *******************************************************************************
38
+
39
+ ForStruct = Struct.new(:daytypes)
40
+ UntilStruct = Struct.new(:timestamp)
41
+ ThroughStruct = Struct.new(:startdate)
42
+
43
+ class ScheduleTranslator
44
+ attr_accessor :os_schedule
45
+
46
+ def initialize(os_model, os_schedule, name_prefix = nil)
47
+ @os_schedule = os_schedule
48
+ @os = os_model
49
+ @sched_name = os_schedule.name.get.to_s
50
+ @sched_type = os_schedule.scheduleTypeLimits.get
51
+ @base_year = os_model.getYearDescription.assumedYear
52
+ @schedule = []
53
+ @name_prefix = name_prefix
54
+ end
55
+
56
+ # Convert from scheduleCompact to scheduleRuleset
57
+ # @Author Nicholas Long and Andrew Parker, NREL
58
+ # @Return ScheduleRuleset object
59
+ def convert_schedule_compact_to_schedule_ruleset
60
+ @sched_name = @os_schedule.getString(1).get
61
+ @sched_name = "#{@name_prefix} #{@sched_name}" unless @name_prefix.nil?
62
+ @sched_type = @os_schedule.scheduleTypeLimits.get # TODO: - will fail if no limits set in source schedule
63
+
64
+ # puts "Translating #{@sched_name}"
65
+
66
+ i_thru = -1
67
+ i_for = -1
68
+ i_until = -1
69
+ sUntil = ''
70
+
71
+ (3..@os_schedule.numFields - 1).each do |i|
72
+ val = @os_schedule.getString(i).get
73
+
74
+ # Trap for interpolated schedules
75
+ if val =~ /Interpolate/
76
+ puts "[WARNING] Schedule #{@sched_name} is interpolated. It will not be translated to .osm"
77
+ return false
78
+ end
79
+
80
+ # add : if it doesn't already exist
81
+ val = val.gsub(/Through\s/, 'Through: ')
82
+ val = val.gsub(/For\s/, 'For: ')
83
+ val = val.gsub(/Until\s/, 'Until: ')
84
+
85
+ if val =~ /through:/i
86
+ i_thru += 1
87
+ i_for = -1
88
+ i_until = -1
89
+
90
+ str = val.split(':')[1].strip
91
+ if @schedule.empty?
92
+ @schedule << { start_date: '01/01', end_date: str, for: [] }
93
+ else
94
+ @schedule << { start_date: @schedule[@schedule.size - 1][:end_date], end_date: str, for: [] }
95
+ end
96
+
97
+ next
98
+ end
99
+
100
+ if val =~ /for[:\s]/i
101
+ i_for += 1
102
+ i_until = -1
103
+
104
+ arr = val.match(/for[:\s](.*)/i)[0].strip.downcase.split(' ')
105
+ @schedule[i_thru][:for] << { daytype: arr, until: [] }
106
+ next
107
+ end
108
+
109
+ if val =~ /until:/i
110
+ i_until += 1
111
+
112
+ str = val.split(':')[1..2].join(':').strip
113
+ sUntil = str
114
+
115
+ next
116
+ end
117
+
118
+ dVal = @os_schedule.getDouble(i).get
119
+ # puts "thru: #{i_thru} for: #{i_for} until #{i_until}"
120
+ @schedule[i_thru][:for][i_for][:until] << { timestamp: sUntil, value: dVal }
121
+ end
122
+
123
+ # DEBUG spit out the schedule for quick check\
124
+ # puts @schedule.inspect
125
+ # @schedule.each do |sch|
126
+ # puts "#{sch[:start_date]} to #{sch[:end_date]}"
127
+ # sch[:for].each do |fr|
128
+ # puts fr[:daytype]
129
+ # fr[:until].each do |ut|
130
+ # puts "#{ut[:timestamp]} : #{ut[:value]}"
131
+ # end
132
+ # end
133
+ # end
134
+
135
+ os_schedule_ruleset = OpenStudio::Model::ScheduleRuleset.new(@os)
136
+ os_schedule_ruleset.setName(@sched_name)
137
+ os_schedule_ruleset.setScheduleTypeLimits(@sched_type)
138
+
139
+ i_rule = 0
140
+ @schedule.each do |sch|
141
+ # create a simple hash to make sure that the schedule covers all days needed
142
+ # and that "allotherdays", can adequately be handled
143
+ coverage = { mon: false, tue: false, wed: false, thu: false, fri: false, sat: false,
144
+ sun: false, sdd: false, wdd: false, hol: false }
145
+ sch[:for].each do |fr|
146
+ i_rule += 1
147
+ os_schedule_rule = OpenStudio::Model::ScheduleRule.new(os_schedule_ruleset)
148
+ os_schedule_rule.setName("#{@sched_name} Rule #{i_rule}")
149
+ os_schedule_rule.setApplyMonday(false)
150
+ os_schedule_rule.setApplyTuesday(false)
151
+ os_schedule_rule.setApplyWednesday(false)
152
+ os_schedule_rule.setApplyThursday(false)
153
+ os_schedule_rule.setApplyFriday(false)
154
+ os_schedule_rule.setApplySaturday(false)
155
+ os_schedule_rule.setApplySunday(false)
156
+
157
+ mody = sch[:start_date].split('/')
158
+ mo = mody[0].to_i
159
+ dy = mody[1].to_i
160
+ osdate_start = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(mo.to_i), dy.to_i)
161
+ if mo != 1 && dy != 1
162
+ osdate_start += OpenStudio::Time.new(1)
163
+ end
164
+ os_schedule_rule.setStartDate(osdate_start)
165
+ mody = sch[:end_date].split('/')
166
+ mo = mody[0].to_i
167
+ dy = mody[1].to_i
168
+ osdate_end = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(mo.to_i), dy.to_i)
169
+ os_schedule_rule.setEndDate(osdate_end)
170
+
171
+ # create os day model
172
+ # TODO break this out as a method
173
+ if fr[:daytype].include?('monday') || fr[:daytype].include?('alldays') || fr[:daytype].include?('weekdays')
174
+ os_schedule_rule.setApplyMonday(true)
175
+ coverage[:mon] = true
176
+ end
177
+ if fr[:daytype].include?('tuesday') || fr[:daytype].include?('alldays') || fr[:daytype].include?('weekdays')
178
+ os_schedule_rule.setApplyTuesday(true)
179
+ coverage[:tue] = true
180
+ end
181
+ if fr[:daytype].include?('wednesday') || fr[:daytype].include?('alldays') || fr[:daytype].include?('weekdays')
182
+ os_schedule_rule.setApplyWednesday(true)
183
+ coverage[:wed] = true
184
+ end
185
+ if fr[:daytype].include?('thursday') || fr[:daytype].include?('alldays') || fr[:daytype].include?('weekdays')
186
+ os_schedule_rule.setApplyThursday(true)
187
+ coverage[:thu] = true
188
+ end
189
+ if fr[:daytype].include?('friday') || fr[:daytype].include?('alldays') || fr[:daytype].include?('weekdays')
190
+ os_schedule_rule.setApplyFriday(true)
191
+ coverage[:fri] = true
192
+ end
193
+ if fr[:daytype].include?('saturday') || fr[:daytype].include?('alldays')
194
+ os_schedule_rule.setApplySaturday(true)
195
+ coverage[:sat] = true
196
+ end
197
+ if fr[:daytype].include?('sunday') || fr[:daytype].include?('alldays')
198
+ os_schedule_rule.setApplySunday(true)
199
+ coverage[:sun] = true
200
+ end
201
+ if fr[:daytype].include?('allotherdays')
202
+ # needs to be a unique rule set
203
+ if !coverage[:mon]
204
+ os_schedule_rule.setApplyMonday(true)
205
+ coverage[:mon] = true
206
+ end
207
+ if !coverage[:tue]
208
+ os_schedule_rule.setApplyTuesday(true)
209
+ coverage[:tue] = true
210
+ end
211
+ if !coverage[:wed]
212
+ os_schedule_rule.setApplyWednesday(true)
213
+ coverage[:wed] = true
214
+ end
215
+ if !coverage[:thu]
216
+ os_schedule_rule.setApplyThursday(true)
217
+ coverage[:thu] = true
218
+ end
219
+ if !coverage[:fri]
220
+ os_schedule_rule.setApplyFriday(true)
221
+ coverage[:fri] = true
222
+ end
223
+ if !coverage[:sat]
224
+ os_schedule_rule.setApplySaturday(true)
225
+ coverage[:sat] = true
226
+ end
227
+ if !coverage[:sun]
228
+ os_schedule_rule.setApplySunday(true)
229
+ coverage[:sun] = true
230
+ end
231
+ end
232
+
233
+ osday = os_schedule_rule.daySchedule
234
+ osday.setName("#{@sched_name} Rule #{i_rule} Day Sch")
235
+ # osday.setString(1, @sched_type)
236
+ fr[:until].each do |ut|
237
+ hr = ut[:timestamp].split(':')[0].to_i
238
+ mn = ut[:timestamp].split(':')[1].to_i
239
+
240
+ ostime = OpenStudio::Time.new(0, hr, mn, 0)
241
+ osday.addValue(ostime, ut[:value])
242
+ end
243
+
244
+ # set the winter and summer design days
245
+ if fr[:daytype].include?('winterdesignday') ||
246
+ (fr[:daytype].include?('allotherdays') && !coverage[:wdd])
247
+
248
+ # this actually clones osday
249
+ os_schedule_ruleset.setWinterDesignDaySchedule(osday)
250
+
251
+ coverage[:wdd] = true
252
+ end
253
+ if fr[:daytype].include?('summerdesignday') ||
254
+ (fr[:daytype].include?('allotherdays') && !coverage[:sdd])
255
+
256
+ # this actually clones osday
257
+ os_schedule_ruleset.setSummerDesignDaySchedule(osday)
258
+
259
+ coverage[:sdd] = true
260
+ end
261
+
262
+ # now check if for some reason that we have alldays for section
263
+ # but the date/time stamp is not in the winter/summer
264
+ if !coverage[:wdd]
265
+ osdate_wdd = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(1), 15)
266
+ if fr[:daytype].include?('alldays') && (osdate_start < osdate_wdd) && (osdate_end > osdate_wdd)
267
+ os_schedule_ruleset.setWinterDesignDaySchedule(osday)
268
+ coverage[:wdd] = true
269
+ # puts "[INFO] **** Setting DesignDay based on date, not by actual schedule ****"
270
+ end
271
+ end
272
+ if !coverage[:sdd]
273
+ osdate_wdd = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(7), 15)
274
+ if fr[:daytype].include?('alldays') && (osdate_start < osdate_wdd) && (osdate_end > osdate_wdd)
275
+ os_schedule_ruleset.setSummerDesignDaySchedule(osday)
276
+ coverage[:sdd] = true
277
+ # puts "[INFO] **** Setting DesignDay based on date, not by actual schedule ****"
278
+ end
279
+ end
280
+ end
281
+ end
282
+
283
+ # Clean up tasks on the naming after all the schedule rule and days are
284
+ # configured
285
+ ostemp = os_schedule_ruleset.winterDesignDaySchedule
286
+ ostemp.setName("#{@sched_name} Winter Design Day")
287
+ # ostemp.setString(1, @sched_type)
288
+
289
+ ostemp = os_schedule_ruleset.summerDesignDaySchedule
290
+ ostemp.setName("#{@sched_name} Summer Design Day")
291
+ # ostemp.setString(1, @sched_type)
292
+
293
+ ostemp = os_schedule_ruleset.defaultDaySchedule
294
+ ostemp.setName("#{@sched_name} Default Schedule")
295
+ # ostemp.setString(1, @sched_type)
296
+
297
+ # Remove rules that don't apply to any days
298
+ os_schedule_ruleset.scheduleRules.each do |sr|
299
+ if !sr.applySunday && !sr.applyMonday && !sr.applyTuesday &&
300
+ !sr.applyWednesday && !sr.applyThursday && !sr.applyFriday &&
301
+ !sr.applySaturday
302
+ sr.daySchedule.remove
303
+ sr.remove
304
+ end
305
+ end
306
+
307
+ sched_i = 0
308
+ os_schedule_ruleset.scheduleRules.each do |sr|
309
+ sched_i += 1
310
+ sr.setName("#{@sched_name} Rule #{sched_i}")
311
+ sr.daySchedule.setName("#{@sched_name} Rule #{sched_i} Day Schedule")
312
+ end
313
+
314
+ # If the default profile is never used throughout the year,
315
+ # make the most commonly used rule the default instead.
316
+
317
+ # Get an array that shows which rule is used on each day in the date range.
318
+ # A value of -1 means that the default profile is used on that day,
319
+ # so if -1 never appears in the list, it isn't used.
320
+ year = @base_year
321
+ year_start_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('January'), 1, year)
322
+ year_end_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('December'), 31, year)
323
+ rules_used_each_day = os_schedule_ruleset.getActiveRuleIndices(year_start_date, year_end_date)
324
+ rules_freq = rules_used_each_day.group_by { |n| n }
325
+ most_freq_rule_index = rules_freq.values.max_by(&:size).first
326
+ if !rules_used_each_day.include?(-1)
327
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.schedule_translator', "#{os_schedule_ruleset.name} does not use the default profile, it will be replaced.")
328
+
329
+ # Get times/values from the most commonly used rule then remove that rule.
330
+ rule_vector = os_schedule_ruleset.scheduleRules
331
+ new_default_day_sch = rule_vector[most_freq_rule_index].daySchedule
332
+ new_default_day_sch_values = new_default_day_sch.values
333
+ new_default_day_sch_times = new_default_day_sch.times
334
+ rule_vector[most_freq_rule_index].remove
335
+
336
+ # Reset values in default profile
337
+ default_day_sch = os_schedule_ruleset.defaultDaySchedule
338
+ default_day_sch.clearValues
339
+
340
+ # Update values and times for default profile
341
+ for i in 0..(new_default_day_sch_values.size - 1)
342
+ default_day_sch.addValue(new_default_day_sch_times[i], new_default_day_sch_values[i])
343
+ end
344
+ end
345
+
346
+ return os_schedule_ruleset
347
+ end
348
+ end
@@ -16,6 +16,34 @@ Standard.class_eval do
16
16
  return model.sqlFile.get
17
17
  end
18
18
 
19
+ # Write out a SQL query to retrieve simulation outputs
20
+ # from the TabularDataWithStrings table in the SQL
21
+ # database produced by OpenStudio/EnergyPlus after
22
+ # running a simulation.
23
+ #
24
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
25
+ # @param report_name [String] Name of the report as defined in the HTM simulation output file
26
+ # @param table_name [String] Name of the table as defined in the HTM simulation output file
27
+ # @param row_name [String] Name of the row as defined in the HTM simulation output file
28
+ # @param column_name [String] Name of the column as defined in the HTM simulation output file
29
+ # @param units [String] Unit of the value to be retrieved
30
+ #
31
+ # @return [String] Result of the query
32
+ def run_query_tabulardatawithstrings(model, report_name, table_name, row_name, column_name, units = '*')
33
+ # Define the query
34
+ query = "Select Value FROM TabularDataWithStrings WHERE
35
+ ReportName = '#{report_name}' AND
36
+ TableName = '#{table_name}' AND
37
+ RowName = '#{row_name}' AND
38
+ ColumnName = '#{column_name}' AND
39
+ Units = '#{units}'"
40
+ # Run the query if the expected output is a string
41
+ return model.sqlFile.get.execAndReturnFirstString(query).get if units.empty?
42
+
43
+ # Run the query if the expected output is a double
44
+ return model.sqlFile.get.execAndReturnFirstDouble(query).get
45
+ end
46
+
19
47
  # Get the weather run period for the model
20
48
  #
21
49
  # @param model [OpenStudio::Model::Model] OpenStudio model object
@@ -384,6 +412,46 @@ Standard.class_eval do
384
412
  return heating_or_cooling_setpoint_unmet
385
413
  end
386
414
 
415
+ # Get the total unmet load hours during occupancy of a model that has been simulated
416
+ #
417
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
418
+ # @return [Float] returns the number of total unmet load hours during occupancy in a simulated model
419
+ def model_get_unmet_load_hours(model)
420
+ result = OpenStudio::OptionalDouble.new
421
+ sql = model.sqlFile
422
+ if sql.is_initialized
423
+ sql = sql.get
424
+ query = "SELECT Value
425
+ FROM tabulardatawithstrings
426
+ WHERE ReportName='AnnualBuildingUtilityPerformanceSummary'
427
+ AND ReportForString='Entire Facility'
428
+ AND TableName='Comfort and Setpoint Not Met Summary'
429
+ AND ColumnName='Facility'
430
+ AND RowName='Time Setpoint Not Met During Occupied Heating'
431
+ AND Units='Hours'"
432
+ val = sql.execAndReturnFirstDouble(query)
433
+ if val.is_initialized
434
+ result = OpenStudio::OptionalDouble.new(val.get).to_f
435
+ end
436
+ query = "SELECT Value
437
+ FROM tabulardatawithstrings
438
+ WHERE ReportName='AnnualBuildingUtilityPerformanceSummary'
439
+ AND ReportForString='Entire Facility'
440
+ AND TableName='Comfort and Setpoint Not Met Summary'
441
+ AND ColumnName='Facility'
442
+ AND RowName='Time Setpoint Not Met During Occupied Cooling'
443
+ AND Units='Hours'"
444
+ val = sql.execAndReturnFirstDouble(query)
445
+ if val.is_initialized
446
+ result += OpenStudio::OptionalDouble.new(val.get).to_f
447
+ end
448
+ else
449
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'Model has no sql file containing results, cannot lookup data.')
450
+ end
451
+
452
+ return result
453
+ end
454
+
387
455
  # Gets the model annual energy consumption by fuel and enduse in GJ from the sql file
388
456
  #
389
457
  # @param model [OpenStudio::Model::Model] OpenStudio model object
@@ -13,5 +13,5 @@ module OpenstudioStandards
13
13
  end
14
14
  return 'git-not-found-on-this-system'
15
15
  end
16
- VERSION = '0.2.16'.freeze
17
- end
16
+ VERSION = '0.2.17.rc1'.freeze
17
+ end
@@ -81,13 +81,49 @@ class Standard
81
81
  return climate_zone_weather_file_map
82
82
  end
83
83
 
84
+ # Get absolute path of a weather file included within openstudio-standards
85
+ #
86
+ # @param weather_file_name [String] Name of a weather file include within openstudio-standards
87
+ # @return [String] Weather file path
88
+ def model_get_weather_file(weather_file_name)
89
+ # Define where the weather files lives
90
+ weather_dir = nil
91
+ if __dir__[0] == ':' # Running from OpenStudio CLI
92
+ # load weather file from embedded files
93
+ epw_string = load_resource_relative("../../../data/weather/#{weather_file_name}")
94
+ ddy_string = load_resource_relative("../../../data/weather/#{weather_file_name.gsub('.epw', '.ddy')}")
95
+ stat_string = load_resource_relative("../../../data/weather/#{weather_file_name.gsub('.epw', '.stat')}")
96
+
97
+ # extract to local weather dir
98
+ weather_dir = File.expand_path(File.join(Dir.pwd, 'extracted_files/weather/'))
99
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.weather.Model', "Extracting weather files from OpenStudio CLI to #{weather_dir}")
100
+ FileUtils.mkdir_p(weather_dir)
101
+ File.open("#{weather_dir}/#{weather_file_name}", 'wb') { |f| f << epw_string; f.flush }
102
+ File.open("#{weather_dir}/#{weather_file_name.gsub('.epw', '.ddy')}", 'wb') { |f| f << ddy_string; f.flush }
103
+ File.open("#{weather_dir}/#{weather_file_name.gsub('.epw', '.stat')}", 'wb') { |f| f << stat_string; f.flush }
104
+ else
105
+ # loaded gem from system path
106
+ top_dir = File.expand_path('../../..', File.dirname(__FILE__))
107
+ weather_dir = File.expand_path("#{top_dir}/data/weather")
108
+ end
109
+
110
+ # Add Weather File
111
+ unless (Pathname.new weather_dir).absolute?
112
+ weather_dir = File.expand_path(File.join(File.dirname(__FILE__), weather_dir))
113
+ end
114
+
115
+ weather_file = File.join(weather_dir, weather_file_name)
116
+
117
+ return weather_file
118
+ end
119
+
84
120
  # Adds the design days and weather file for the specified climate zone
85
121
  #
86
122
  # @param model [OpenStudio::Model::Model] OpenStudio model object
87
123
  # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
88
124
  # @param epw_file [String] the name of the epw file; if blank will default to epw file for the ASHRAE climate zone
89
125
  # @return [Bool] returns true if successful, false if not
90
- def model_add_design_days_and_weather_file(model, climate_zone, epw_file = '')
126
+ def model_add_design_days_and_weather_file(model, climate_zone, epw_file = '', weather_dir = nil)
91
127
  success = true
92
128
  require_relative 'Weather.stat_file'
93
129
 
@@ -110,33 +146,8 @@ class Standard
110
146
  success = false
111
147
  end
112
148
 
113
- # Define where the weather files lives
114
- weather_dir = nil
115
- if __dir__[0] == ':' # Running from OpenStudio CLI
116
- # load weather file from embedded files
117
- epw_string = load_resource_relative("../../../data/weather/#{weather_file_name}")
118
- ddy_string = load_resource_relative("../../../data/weather/#{weather_file_name.gsub('.epw', '.ddy')}")
119
- stat_string = load_resource_relative("../../../data/weather/#{weather_file_name.gsub('.epw', '.stat')}")
120
-
121
- # extract to local weather dir
122
- weather_dir = File.expand_path(File.join(Dir.pwd, 'extracted_files/weather/'))
123
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.weather.Model', "Extracting weather files from OpenStudio CLI to #{weather_dir}")
124
- FileUtils.mkdir_p(weather_dir)
125
- File.open("#{weather_dir}/#{weather_file_name}", 'wb') { |f| f << epw_string; f.flush }
126
- File.open("#{weather_dir}/#{weather_file_name.gsub('.epw', '.ddy')}", 'wb') { |f| f << ddy_string; f.flush }
127
- File.open("#{weather_dir}/#{weather_file_name.gsub('.epw', '.stat')}", 'wb') { |f| f << stat_string; f.flush }
128
- else
129
- # loaded gem from system path
130
- top_dir = File.expand_path('../../..', File.dirname(__FILE__))
131
- weather_dir = File.expand_path("#{top_dir}/data/weather")
132
- end
133
-
134
- # Add Weather File
135
- unless (Pathname.new weather_dir).absolute?
136
- weather_dir = File.expand_path(File.join(File.dirname(__FILE__), weather_dir))
137
- end
149
+ weather_file = model_get_weather_file(weather_file_name)
138
150
 
139
- weather_file = File.join(weather_dir, weather_file_name)
140
151
  epw_file = OpenStudio::EpwFile.new(weather_file)
141
152
  OpenStudio::Model::WeatherFile.setWeatherFile(model, epw_file).get
142
153
 
@@ -212,30 +223,8 @@ class Standard
212
223
  OpenStudio.logFree(OpenStudio::Warn, 'openstudio.weather.Model', "Could not determine the weather file for climate zone: #{climate_zone}, cannot get ground temperatures from stat file.")
213
224
  end
214
225
 
215
- # Define where the weather files lives
216
- weather_dir = nil
217
- if __dir__[0] == ':' # Running from OpenStudio CLI
218
- # load stat file from embedded files
219
- stat_string = load_resource_relative("../../../data/weather/#{weather_file_name.gsub('.epw', '.stat')}")
220
-
221
- # extract to local weather dir
222
- weather_dir = File.expand_path(File.join(Dir.pwd, 'extracted_files/weather/'))
223
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.weather.Model', "Extracting stat file from OpenStudio CLI to #{weather_dir}")
224
- FileUtils.mkdir_p(weather_dir)
225
- File.open("#{weather_dir}/#{weather_file_name.gsub('.epw', '.stat')}", 'wb') { |f| f << stat_string; f.flush }
226
- else
227
- # loaded gem from system path
228
- top_dir = File.expand_path('../../..', File.dirname(__FILE__))
229
- weather_dir = File.expand_path("#{top_dir}/data/weather")
230
- end
231
-
232
- # Expand the weather directory path
233
- unless (Pathname.new weather_dir).absolute?
234
- weather_dir = File.expand_path(File.join(File.dirname(__FILE__), weather_dir))
235
- end
236
-
237
226
  # Get the path to the stat file
238
- weather_file = File.join(weather_dir, weather_file_name)
227
+ weather_file = model_get_weather_file(weather_file_name)
239
228
 
240
229
  # Add ground temperatures via parsing of STAT file.
241
230
  ground_temperatures = []
@@ -347,7 +336,6 @@ end
347
336
  module BTAP
348
337
  module Environment
349
338
  require_relative 'Weather.stat_file'
350
- # rubocop:enable Style/MutableConstant
351
339
 
352
340
  # this method is used to populate user interfaces if needed from the hash above.
353
341
  def self.get_canadian_weather_file_names
@@ -922,7 +910,7 @@ module BTAP
922
910
  end
923
911
  end
924
912
  return heating_design_day_number, cooling_design_day_number
925
- end #def get_heating_design_day_number
913
+ end # def get_heating_design_day_number
926
914
 
927
915
  # This method calculates dehumidification degree days (DDD)
928
916
  # @author sara.gilani@canada.ca
@@ -960,7 +948,7 @@ module BTAP
960
948
  c5 * (line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k)**3 +
961
949
  c6 * (line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k)**4 +
962
950
  c7 * Math.log((line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k), Math.exp(1)) # 2.718281828459
963
- line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR] = (Math.exp(1))**(line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR].to_f)
951
+ line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR] = Math.exp(1)**line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR].to_f
964
952
  else # if line[DRY_BULB_TEMPERATURE].to_f > 0.0
965
953
  line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR] = c8 / (line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k) +
966
954
  c9 +
@@ -968,7 +956,7 @@ module BTAP
968
956
  c11 * (line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k)**2 +
969
957
  c12 * (line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k)**3 +
970
958
  c13 * Math.log((line[DRY_BULB_TEMPERATURE].to_f + convert_c_to_k), Math.exp(1))
971
- line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR] = (Math.exp(1))**(line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR].to_f)
959
+ line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR] = Math.exp(1)**line[CALCULATED_SATURATION_PRESSURE_OF_WATER_VAPOR].to_f
972
960
  end
973
961
 
974
962
  # Step 2: calculate pw (PARTIAL_PRESSURE_OF_WATER_VAPOR), [Pascal]
@@ -1003,7 +991,6 @@ module BTAP
1003
991
  # puts @filearray
1004
992
  return ddd
1005
993
  end # def calculate_humidity_ratio
1006
-
1007
994
  end # Environment
1008
995
  end
1009
996
  end