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.
- checksums.yaml +4 -4
- data/data/standards/manage_OpenStudio_Standards.rb +31 -4
- data/lib/openstudio-standards/btap/geometry.rb +1 -1
- data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +354 -2
- data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +79 -0
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +3313 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +12 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +3 -4
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +167 -93
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +2 -4
- data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +1 -0
- data/lib/openstudio-standards/refs/references.rb +3 -0
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +279 -6
- data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +50 -2
- data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +4 -0
- data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -1
- data/lib/openstudio-standards/standards/Standards.Construction.rb +185 -3
- data/lib/openstudio-standards/standards/Standards.Fan.rb +14 -6
- data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +1 -0
- data/lib/openstudio-standards/standards/Standards.Model.rb +1751 -383
- data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +130 -9
- data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +50 -3
- data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +44 -0
- data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +27 -0
- data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +543 -0
- data/lib/openstudio-standards/standards/Standards.Space.rb +665 -15
- data/lib/openstudio-standards/standards/Standards.SpaceType.rb +141 -4
- data/lib/openstudio-standards/standards/Standards.SubSurface.rb +2 -1
- data/lib/openstudio-standards/standards/Standards.Surface.rb +117 -0
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +197 -49
- data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +41 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +6 -8
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +5 -5
- 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
- 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
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.fans.json +12 -0
- 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
- 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
- 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
- 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
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +792 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +10 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +31 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +91 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +84 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +145 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +106 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +71 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +194 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +120 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +110 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Fan.rb +73 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +24 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanZoneExhaust.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +55 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +3045 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +187 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +450 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +106 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +666 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +54 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +168 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +132 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +239 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +176 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +25 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +52 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.chillers.json +112 -0
- 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
- 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
- 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
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.furnaces.json +43 -0
- 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
- 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
- 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
- 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
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.motors.json +264 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.climate_zone_sets.json +210 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.curves.json +18329 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.fans.json +340 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.materials.json +49924 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_building_rotation_exception.md +44 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/check_pump_power_and_control.md +71 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv.md +68 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv_implementation.png +0 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/elevators.md +14 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/exhaust_air_energy_recovery.md +36 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/f_c_factors.md +19 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/fan_power_credits.md +15 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/preheat_coil.md +59 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/pump_power_control.md +46 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/return_air_type.md +31 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_baseline_wwr.md +191 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_hw_and_chw_supply_water_temp_reset_control.md +24 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_num_boilers_chillers_towers.md +49 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +80 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_space_lpd.md +73 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unenclosed_and_unconditioned_spaces.md +11 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unmet_load_hours.md +20 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_parallel_piu_terminals_fan_control.md +23 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_terminals_min_flow_setpoint.md +21 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac_doas.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_building.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_design_specification_outdoor_air.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_electric_equipment.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_exterior_lights.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_gas_equipment.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_lights.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_spacetype.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_thermal_zone.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_connections.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment_definition.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_hvac.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_infiltration.csv +1 -0
- data/lib/openstudio-standards/standards/cbes/data/cbes.fans.json +12 -0
- data/lib/openstudio-standards/standards/deer/data/deer.fans.json +12 -0
- data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps.json +1 -1
- data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps_heating.json +1 -1
- data/lib/openstudio-standards/standards/necb/ECMS/data/unitary_acs.json +24 -11
- data/lib/openstudio-standards/standards/necb/ECMS/erv.rb +13 -15
- data/lib/openstudio-standards/standards/necb/NECB2011/data/province_map.json +17 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +2 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +6 -5
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +3 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +2 -3
- data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +2 -2
- data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +33 -924
- data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +15 -15
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +135 -29
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +16 -4
- data/lib/openstudio-standards/standards/necb/common/neb_end_use_prices.csv +40 -42
- data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +1 -1
- data/lib/openstudio-standards/standards/necb/common/space_type_upgrade_map.json +89 -89
- data/lib/openstudio-standards/utilities/array.rb +11 -0
- data/lib/openstudio-standards/utilities/logging.rb +48 -0
- data/lib/openstudio-standards/utilities/object_info.rb +20 -0
- data/lib/openstudio-standards/utilities/schedule_translator.rb +348 -0
- data/lib/openstudio-standards/utilities/sqlfile.rb +68 -0
- data/lib/openstudio-standards/version.rb +2 -2
- data/lib/openstudio-standards/weather/Weather.Model.rb +42 -55
- data/lib/openstudio-standards/weather/Weather.stat_file.rb +1 -1
- data/lib/openstudio-standards.rb +35 -1
- metadata +111 -6
- data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
- data/data/standards/OpenStudio_Standards-ashrae_90_1_28Jan2022.xlsx +0 -0
- data/data/standards/OpenStudio_Standards-ashrae_90_1_28_Jan2022_2.xlsx +0 -0
- data/data/standards/openstudio_standards_duplicates_log.csv +0 -143
@@ -786,6 +786,32 @@ class Standard
|
|
786
786
|
return skylight_effective_aperture
|
787
787
|
end
|
788
788
|
|
789
|
+
# Removes daylighting controls from model
|
790
|
+
#
|
791
|
+
# @param space [OpenStudio::Model::Space] OpenStudio space object
|
792
|
+
#
|
793
|
+
# @return [Boolean] Returns true if a sizing run is required
|
794
|
+
def space_remove_daylighting_controls(space)
|
795
|
+
# Retrieves daylighting control objects
|
796
|
+
existing_daylighting_controls = space.daylightingControls
|
797
|
+
unless existing_daylighting_controls.empty?
|
798
|
+
existing_daylighting_controls.each(&:remove)
|
799
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Space', "For #{space.name}, removed #{existing_daylighting_controls.size} existing daylight controls before adding new controls.")
|
800
|
+
return true
|
801
|
+
end
|
802
|
+
return false
|
803
|
+
end
|
804
|
+
|
805
|
+
# Default for 2013 and earlier is to Add daylighting controls (sidelighting and toplighting) per the template
|
806
|
+
# @param space [OpenStudio::Model::Space] the space with daylighting
|
807
|
+
# @param remove_existing_controls [Bool] if true, will remove existing controls then add new ones
|
808
|
+
# @param draw_daylight_areas_for_debugging [Bool] If this argument is set to true,
|
809
|
+
# @return [boolean] true if successful
|
810
|
+
def space_set_baseline_daylighting_controls(space, remove_existing = false, draw_areas_for_debug = false)
|
811
|
+
added = space_add_daylighting_controls(space, remove_existing, draw_areas_for_debug)
|
812
|
+
return added
|
813
|
+
end
|
814
|
+
|
789
815
|
# Adds daylighting controls (sidelighting and toplighting) per the template
|
790
816
|
# @note This method is super complicated because of all the polygon/geometry math required.
|
791
817
|
# and therefore may not return perfect results. However, it works well in most tested
|
@@ -797,9 +823,7 @@ class Standard
|
|
797
823
|
# daylight areas will be added to the model as surfaces for visual debugging.
|
798
824
|
# Yellow = toplighted area, Red = primary sidelighted area,
|
799
825
|
# Blue = secondary sidelighted area, Light Blue = floor
|
800
|
-
# @return [
|
801
|
-
# Hash keys are: 'toplighted_area', 'primary_sidelighted_area',
|
802
|
-
# 'secondary_sidelighted_area', 'total_window_area', 'total_skylight_area'
|
826
|
+
# @return [boolean] true if successful
|
803
827
|
# @todo add a list of valid choices for template argument
|
804
828
|
# @todo add exception for retail spaces
|
805
829
|
# @todo add exception 2 for skylights with VT < 0.4
|
@@ -816,8 +840,7 @@ class Standard
|
|
816
840
|
existing_daylighting_controls = space.daylightingControls
|
817
841
|
unless existing_daylighting_controls.empty?
|
818
842
|
if remove_existing_controls
|
819
|
-
|
820
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Space', "For #{space.name}, removed #{existing_daylighting_controls.size} existing daylight controls before adding new controls.")
|
843
|
+
space_remove_daylighting_controls(space)
|
821
844
|
else
|
822
845
|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Space', "For #{space.name}, daylight controls were already present, no additional controls added.")
|
823
846
|
return false
|
@@ -1344,7 +1367,8 @@ class Standard
|
|
1344
1367
|
return area_m2
|
1345
1368
|
end
|
1346
1369
|
|
1347
|
-
# Calculate the area of the exterior walls,
|
1370
|
+
# Calculate the area of the exterior walls, and roofs
|
1371
|
+
# including the area of the windows on these walls.
|
1348
1372
|
#
|
1349
1373
|
# @param space [OpenStudio::Model::Space] space object
|
1350
1374
|
# @return [Double] area in m^2
|
@@ -1369,6 +1393,83 @@ class Standard
|
|
1369
1393
|
return area_m2
|
1370
1394
|
end
|
1371
1395
|
|
1396
|
+
# Calculate the space envelope area.
|
1397
|
+
# According to the 90.1 definition, building envelope include:
|
1398
|
+
# 1. "the elements of a building that separate conditioned spaces from the exterior"
|
1399
|
+
# 2. "the elements of a building that separate conditioned space from unconditioned
|
1400
|
+
# space or that enclose semiheated spaces through which thermal energy may be
|
1401
|
+
# transferred to or from the exterior, to or from unconditioned spaces or to or
|
1402
|
+
# from conditioned spaces."
|
1403
|
+
#
|
1404
|
+
# Outside boundary conditions currently supported:
|
1405
|
+
# - Adiabatic
|
1406
|
+
# - Surface
|
1407
|
+
# - Outdoors
|
1408
|
+
# - Foundation
|
1409
|
+
# - Ground
|
1410
|
+
# - GroundFCfactorMethod
|
1411
|
+
# - OtherSideCoefficients
|
1412
|
+
# - OtherSideConditionsModel
|
1413
|
+
# - GroundSlabPreprocessorAverage
|
1414
|
+
# - GroundSlabPreprocessorCore
|
1415
|
+
# - GroundSlabPreprocessorPerimeter
|
1416
|
+
# - GroundBasementPreprocessorAverageWall
|
1417
|
+
# - GroundBasementPreprocessorAverageFloor
|
1418
|
+
# - GroundBasementPreprocessorUpperWall
|
1419
|
+
# - GroundBasementPreprocessorLowerWall
|
1420
|
+
#
|
1421
|
+
# Surface type currently supported:
|
1422
|
+
# - Floor
|
1423
|
+
# - Wall
|
1424
|
+
# - RoofCeiling
|
1425
|
+
#
|
1426
|
+
# @param space [OpenStudio::Model::Space] OpenStudio space object
|
1427
|
+
# @param climate_zone [String] Climate zone, used for space heating/cooling thresholds
|
1428
|
+
#
|
1429
|
+
# @return [Double] area in m^2
|
1430
|
+
def space_envelope_area(space, climate_zone)
|
1431
|
+
area_m2 = 0.0
|
1432
|
+
|
1433
|
+
# Get the space conditioning type
|
1434
|
+
space_cond_type = space_conditioning_category(space)
|
1435
|
+
|
1436
|
+
# Loop through all surfaces in this space
|
1437
|
+
space.surfaces.sort.each do |surface|
|
1438
|
+
# Only account for spaces that are conditioned or semi-heated
|
1439
|
+
next unless space_cond_type != 'Unconditioned'
|
1440
|
+
|
1441
|
+
surf_cnt = false
|
1442
|
+
|
1443
|
+
# Conditioned space OR semi-heated space <-> exterior
|
1444
|
+
# Conditioned space OR semi-heated space <-> ground
|
1445
|
+
if surface.outsideBoundaryCondition == 'Outdoors' ||
|
1446
|
+
surface.isGroundSurface
|
1447
|
+
surf_cnt = true
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
# Conditioned space OR semi-heated space <-> unconditioned spaces
|
1451
|
+
unless surf_cnt
|
1452
|
+
# TODO: add a case for 'Zone' when supported
|
1453
|
+
if surface.outsideBoundaryCondition == 'Surface'
|
1454
|
+
adj_space = surface.adjacentSurface.get.space.get
|
1455
|
+
adj_space_cond_type = space_conditioning_category(adj_space)
|
1456
|
+
surf_cnt = true unless adj_space_cond_type != 'Unconditioned'
|
1457
|
+
end
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
if surf_cnt
|
1461
|
+
# This surface
|
1462
|
+
area_m2 += surface.netArea
|
1463
|
+
# Subsurfaces in this surface
|
1464
|
+
surface.subSurfaces.sort.each do |subsurface|
|
1465
|
+
area_m2 += subsurface.netArea
|
1466
|
+
end
|
1467
|
+
end
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
return area_m2 * space.multiplier
|
1471
|
+
end
|
1472
|
+
|
1372
1473
|
# Determine if the space is a plenum.
|
1373
1474
|
# Assume it is a plenum if it is a supply or return plenum for an AirLoop,
|
1374
1475
|
# if it is not part of the total floor area,
|
@@ -1460,12 +1561,24 @@ class Standard
|
|
1460
1561
|
if space_type.is_initialized
|
1461
1562
|
space_type = space_type.get
|
1462
1563
|
# Get the space type data
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1564
|
+
if /prm/i !~ template
|
1565
|
+
# This is the PRM method for 2013 and prior
|
1566
|
+
space_type_properties = space_type_get_standards_data(space_type)
|
1567
|
+
if space_type_properties.nil?
|
1568
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Could not find space type properties for #{space_to_check.name}, assuming nonresidential.")
|
1569
|
+
is_res = false
|
1570
|
+
else
|
1571
|
+
is_res = space_type_properties['is_residential'] == 'Yes'
|
1572
|
+
end
|
1467
1573
|
else
|
1468
|
-
|
1574
|
+
# This is the 2019 PRM method
|
1575
|
+
lighting_properties = interior_lighting_get_prm_data(space_type)
|
1576
|
+
if lighting_properties.empty?
|
1577
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Could not find lighting properties for #{space_to_check.name}, assuming nonresidential.")
|
1578
|
+
is_res = false
|
1579
|
+
else
|
1580
|
+
is_res = lighting_properties['isresidential'].to_s == '1'
|
1581
|
+
end
|
1469
1582
|
end
|
1470
1583
|
else
|
1471
1584
|
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Could not find a space type for #{space_to_check.name}, assuming nonresidential.")
|
@@ -1480,8 +1593,14 @@ class Standard
|
|
1480
1593
|
# @param space [OpenStudio::Model::Space] space object
|
1481
1594
|
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
1482
1595
|
# @return [String] NonResConditioned, ResConditioned, Semiheated, Unconditioned
|
1483
|
-
# @todo add logic to detect indirectly-conditioned spaces
|
1484
|
-
def space_conditioning_category(space
|
1596
|
+
# @todo add logic to detect indirectly-conditioned spaces based on air transfer
|
1597
|
+
def space_conditioning_category(space)
|
1598
|
+
# Return space conditioning category if already assigned as an additional properties
|
1599
|
+
return space.additionalProperties.getFeatureAsString('space_conditioning_category').get if space.additionalProperties.hasFeature('space_conditioning_category')
|
1600
|
+
|
1601
|
+
# Get climate zone
|
1602
|
+
climate_zone = model_standards_climate_zone(space.model)
|
1603
|
+
|
1485
1604
|
# Get the zone this space is inside
|
1486
1605
|
zone = space.thermalZone
|
1487
1606
|
|
@@ -1490,8 +1609,100 @@ class Standard
|
|
1490
1609
|
return 'Unconditioned'
|
1491
1610
|
end
|
1492
1611
|
|
1493
|
-
#
|
1494
|
-
|
1612
|
+
# Return air plenums are indirectly conditioned spaces according to the
|
1613
|
+
# 90.1-2019 Performance Rating Method Reference Manual
|
1614
|
+
# #
|
1615
|
+
# Additionally, Section 2 of ASHRAE 90.1 states that indirectly
|
1616
|
+
# conditioned spaces are unconditioned spaces that are adjacent to
|
1617
|
+
# heated or cooled spaced and provided that air from these spaces is
|
1618
|
+
# intentionally transferred into the space at a rate exceeding 3 ach
|
1619
|
+
# which most if not all return air plenum do.
|
1620
|
+
space.model.getAirLoopHVACReturnPlenums.each do |return_air_plenum|
|
1621
|
+
if return_air_plenum.thermalZone.get.name.to_s == zone.get.name.to_s
|
1622
|
+
# Determine if residential
|
1623
|
+
res = thermal_zone_residential?(zone.get) ? true : false
|
1624
|
+
|
1625
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Standards.ThermalZone', "Zone #{zone.get.name} is (indirectly) conditioned (return air plenum).")
|
1626
|
+
cond_cat = res ? 'ResConditioned' : 'NonResConditioned'
|
1627
|
+
|
1628
|
+
return cond_cat
|
1629
|
+
end
|
1630
|
+
end
|
1631
|
+
# Following the same assumptions, we designate supply air plenums
|
1632
|
+
# as indirectly conditioned as well
|
1633
|
+
space.model.getAirLoopHVACSupplyPlenums.each do |supply_air_plenum|
|
1634
|
+
if supply_air_plenum.thermalZone.get.name.to_s == zone.get.name.to_s
|
1635
|
+
# Determine if residential
|
1636
|
+
res = thermal_zone_residential?(zone.get) ? true : false
|
1637
|
+
|
1638
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Standards.ThermalZone', "Zone #{zone.get.name} is (indirectly) conditioned (supply air plenum).")
|
1639
|
+
cond_cat = res ? 'ResConditioned' : 'NonResConditioned'
|
1640
|
+
|
1641
|
+
return cond_cat
|
1642
|
+
end
|
1643
|
+
end
|
1644
|
+
|
1645
|
+
# Get the category from the zone, this methods does NOT detect indirectly
|
1646
|
+
# conditioned spaces
|
1647
|
+
cond_cat = thermal_zone_conditioning_category(zone.get, climate_zone)
|
1648
|
+
|
1649
|
+
# Detect indirectly conditioned spaces based on UA sum product comparison
|
1650
|
+
if cond_cat == 'Unconditioned'
|
1651
|
+
|
1652
|
+
# Initialize UA sum product for surfaces adjacent to conditioned spaces
|
1653
|
+
cond_ua = 0
|
1654
|
+
|
1655
|
+
# Initialize UA sum product for surfaces adjacent to unconditoned spaces,
|
1656
|
+
# semi-heated spaces and outdoors
|
1657
|
+
otr_ua = 0
|
1658
|
+
|
1659
|
+
space.surfaces.sort.each do |surface|
|
1660
|
+
# Surfaces adjacent to other surfaces can be next to conditioned,
|
1661
|
+
# unconditioned or semi-heated spaces
|
1662
|
+
if surface.outsideBoundaryCondition == 'Surface'
|
1663
|
+
|
1664
|
+
# Retrieve adjacent space conditioning category
|
1665
|
+
adj_space = surface.adjacentSurface.get.space.get
|
1666
|
+
adj_zone = adj_space.thermalZone.get
|
1667
|
+
adj_space_cond_type = thermal_zone_conditioning_category(adj_zone, climate_zone)
|
1668
|
+
|
1669
|
+
# adj_zone == zone.get means that the surface is adjacent to its zone
|
1670
|
+
# This is translated by an adiabtic outside boundary condition, which are
|
1671
|
+
# assumed to be used only if the surface is adjacent to a conditioned space
|
1672
|
+
if adj_space_cond_type == 'ResConditioned' || adj_space_cond_type == 'NonResConditioned' || adj_zone == zone.get
|
1673
|
+
cond_ua += surface_subsurface_ua(surface)
|
1674
|
+
else
|
1675
|
+
otr_ua += surface_subsurface_ua(surface)
|
1676
|
+
end
|
1677
|
+
|
1678
|
+
# Adiabtic outside boundary condition are assumed to be used only if the
|
1679
|
+
# surface is adjacent to a conditioned space
|
1680
|
+
elsif surface.outsideBoundaryCondition == 'Adiabatic'
|
1681
|
+
|
1682
|
+
# If the surface is a floor and is located at the lowest floor of the
|
1683
|
+
# building it is assumed to be adjacent to an unconditioned space
|
1684
|
+
# (i.e. ground)
|
1685
|
+
if surface.surfaceType == 'Floor' && surface.space.get.buildingStory == find_lowest_story(surface.model)
|
1686
|
+
otr_ua += surface_subsurface_ua(surface)
|
1687
|
+
else
|
1688
|
+
cond_ua += surface_subsurface_ua(surface)
|
1689
|
+
end
|
1690
|
+
|
1691
|
+
# All other outside boundary conditions are assumed to be adjacent to either:
|
1692
|
+
# outdoors or ground and hence count towards the unconditioned UA product
|
1693
|
+
else
|
1694
|
+
otr_ua += surface_subsurface_ua(surface)
|
1695
|
+
end
|
1696
|
+
end
|
1697
|
+
|
1698
|
+
# Determine if residential
|
1699
|
+
res = thermal_zone_residential?(zone.get) ? true : false
|
1700
|
+
|
1701
|
+
return cond_cat unless cond_ua > otr_ua
|
1702
|
+
|
1703
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Standards.ThermalZone', "Zone #{zone.get.name} is (indirectly) conditioned because its conditioned UA product (#{cond_ua.round} W/K) exceeds its non-conditioned UA product (#{otr_ua.round} W/K).")
|
1704
|
+
cond_cat = res ? 'ResConditioned' : 'NonResConditioned'
|
1705
|
+
end
|
1495
1706
|
|
1496
1707
|
return cond_cat
|
1497
1708
|
end
|
@@ -1582,6 +1793,421 @@ class Standard
|
|
1582
1793
|
return load_w
|
1583
1794
|
end
|
1584
1795
|
|
1796
|
+
# Create annual array of occupancy for the space: 1 = occupied, 0 = unoccupied
|
1797
|
+
# @author Doug Maddox, PNNL
|
1798
|
+
# @param space object
|
1799
|
+
# @return [Double] 8760 array of the occupancy flag
|
1800
|
+
def space_occupancy_annual_array(model, space)
|
1801
|
+
occ_sch_values = nil
|
1802
|
+
ppl_values = Array.new(8760, 0)
|
1803
|
+
|
1804
|
+
# Need to review all people objects in this space
|
1805
|
+
space_name = space.name.get
|
1806
|
+
space_type_name = space.spaceType.get.name.get
|
1807
|
+
people_objs = []
|
1808
|
+
model.getPeoples.sort.each do |people|
|
1809
|
+
parent_obj = people.parent.get.iddObjectType.valueName.to_s
|
1810
|
+
if parent_obj == 'OS_Space'
|
1811
|
+
# This object is associated with a single space
|
1812
|
+
# Check if it is the current space
|
1813
|
+
if space_name == people.space.get.name.get
|
1814
|
+
people_objs << people
|
1815
|
+
end
|
1816
|
+
elsif parent_obj == 'OS_SpaceType'
|
1817
|
+
# This object is associated with a space type
|
1818
|
+
# Check if it is the current space type
|
1819
|
+
if space_type_name == people.spaceType.get.name.get
|
1820
|
+
people_objs << people
|
1821
|
+
end
|
1822
|
+
end
|
1823
|
+
end
|
1824
|
+
|
1825
|
+
unoccupied_threshold = air_loop_hvac_unoccupied_threshold
|
1826
|
+
people_objs.each do |people|
|
1827
|
+
occ_sch = people.numberofPeopleSchedule
|
1828
|
+
if occ_sch.is_initialized
|
1829
|
+
occ_sch_obj = occ_sch.get
|
1830
|
+
occ_sch_values = get_8760_values_from_schedule(model, occ_sch_obj)
|
1831
|
+
# Flag = 1 if any schedule shows occupancy for a given hour
|
1832
|
+
if !occ_sch_values.nil?
|
1833
|
+
(0..8759).each do |ihr|
|
1834
|
+
ppl_values[ihr] = 1 if occ_sch_values[ihr] >= unoccupied_threshold
|
1835
|
+
end
|
1836
|
+
else
|
1837
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Failed to retrieve people schedule for #{space.name}. Assuming #{w_per_person}W/person.")
|
1838
|
+
end
|
1839
|
+
end
|
1840
|
+
end
|
1841
|
+
|
1842
|
+
return ppl_values
|
1843
|
+
end
|
1844
|
+
|
1845
|
+
# Determine the design internal gain (W) for
|
1846
|
+
# this space without space multipliers.
|
1847
|
+
# This includes People, Lights, Electric Equipment, and Gas Equipment.
|
1848
|
+
# This version accounts for operating schedules
|
1849
|
+
# and fraction lost for equipment
|
1850
|
+
# @author Doug Maddox, PNNL
|
1851
|
+
# @param space object
|
1852
|
+
# @param return_noncoincident_value [boolean] if true, return value is noncoincident peak; if false, return is array off coincident load
|
1853
|
+
# @return [Double] 8760 array of the design internal load, in W, for this space
|
1854
|
+
def space_internal_load_annual_array(model, space, return_noncoincident_value)
|
1855
|
+
# For each type of load, first convert schedules to 8760 arrays so coincident load can be determined
|
1856
|
+
ppl_values = Array.new(8760, 0)
|
1857
|
+
ltg_values = Array.new(8760, 0)
|
1858
|
+
load_values = Array.new(8760, 0)
|
1859
|
+
noncoincident_peak_load = 0
|
1860
|
+
space_name = space.name.get
|
1861
|
+
space_type_name = space.spaceType.get.name.get
|
1862
|
+
|
1863
|
+
# People
|
1864
|
+
# Make list of people objects for this space
|
1865
|
+
# Including those associated with space directly and those associated with space type
|
1866
|
+
ppl_total = 0
|
1867
|
+
people_objs = []
|
1868
|
+
model.getPeoples.sort.each do |people|
|
1869
|
+
parent_obj = people.parent.get.iddObjectType.valueName.to_s
|
1870
|
+
if parent_obj == 'OS_Space'
|
1871
|
+
# This object is associated with a single space
|
1872
|
+
# Check if it is the current space
|
1873
|
+
if space_name == people.space.get.name.get
|
1874
|
+
people_objs << people
|
1875
|
+
end
|
1876
|
+
elsif parent_obj == 'OS_SpaceType'
|
1877
|
+
# This object is associated with a space type
|
1878
|
+
# Check if it is the current space type
|
1879
|
+
if space_type_name == people.spaceType.get.name.get
|
1880
|
+
people_objs << people
|
1881
|
+
end
|
1882
|
+
end
|
1883
|
+
end
|
1884
|
+
|
1885
|
+
people_objs.each do |people|
|
1886
|
+
w_per_person = 125 # Initial assumption
|
1887
|
+
occ_sch_max = 1
|
1888
|
+
act_sch = people.activityLevelSchedule
|
1889
|
+
if people.isActivityLevelScheduleDefaulted
|
1890
|
+
# Check default schedule set
|
1891
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
1892
|
+
unless space.spaceType.get.defaultScheduleSet.get.peopleActivityLevelSchedule.empty?
|
1893
|
+
act_sch = space.spaceType.get.defaultScheduleSet.get.peopleActivityLevelSchedule
|
1894
|
+
end
|
1895
|
+
end
|
1896
|
+
end
|
1897
|
+
if act_sch.is_initialized
|
1898
|
+
act_sch_obj = act_sch.get
|
1899
|
+
act_sch_values = get_8760_values_from_schedule(model, act_sch_obj)
|
1900
|
+
if !act_sch_values.nil?
|
1901
|
+
w_per_person = act_sch_values.max
|
1902
|
+
else
|
1903
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Failed to retrieve people activity schedule for #{space.name}. Assuming #{w_per_person}W/person.")
|
1904
|
+
end
|
1905
|
+
end
|
1906
|
+
|
1907
|
+
occ_sch_ruleset = nil
|
1908
|
+
occ_sch = people.numberofPeopleSchedule
|
1909
|
+
if people.isNumberofPeopleScheduleDefaulted
|
1910
|
+
# Check default schedule set
|
1911
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
1912
|
+
unless space.spaceType.get.defaultScheduleSet.get.numberofPeopleSchedule.empty?
|
1913
|
+
occ_sch = space.spaceType.get.defaultScheduleSet.get.numberofPeopleSchedule
|
1914
|
+
end
|
1915
|
+
end
|
1916
|
+
end
|
1917
|
+
if occ_sch.is_initialized
|
1918
|
+
occ_sch_obj = occ_sch.get
|
1919
|
+
occ_sch_values = get_8760_values_from_schedule(model, occ_sch_obj)
|
1920
|
+
if !occ_sch_max.nil?
|
1921
|
+
occ_sch_max = occ_sch_values.max
|
1922
|
+
else
|
1923
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Failed to retrieve people schedule for #{space.name}. Assuming #{w_per_person}W/person.")
|
1924
|
+
end
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
num_ppl = people.getNumberOfPeople(space.floorArea)
|
1928
|
+
ppl_total += num_ppl
|
1929
|
+
|
1930
|
+
act_sch_value = w_per_person
|
1931
|
+
occ_sch_value = occ_sch_max
|
1932
|
+
(0..8759).each do |ihr|
|
1933
|
+
act_sch_value = act_sch_values[ihr] unless act_sch_values.nil?
|
1934
|
+
occ_sch_value = occ_sch_values[ihr] unless occ_sch_values.nil?
|
1935
|
+
ppl_values[ihr] += num_ppl * act_sch_value * occ_sch_value
|
1936
|
+
end
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
# Make list of lights objects for this space
|
1940
|
+
# Including those associated with space directly and those associated with space type
|
1941
|
+
# Note: in EnergyPlus, Lights are associated with zone or zonelist
|
1942
|
+
# In OS, they are associated with space or space type
|
1943
|
+
light_objs = []
|
1944
|
+
model.getLightss.sort.each do |light|
|
1945
|
+
parent_obj = light.parent.get.iddObjectType.valueName.to_s
|
1946
|
+
if parent_obj == 'OS_Space'
|
1947
|
+
# This object is associated with a single space
|
1948
|
+
# Check if it is the current space
|
1949
|
+
if space_name == light.space.get.name.get
|
1950
|
+
light_objs << light
|
1951
|
+
end
|
1952
|
+
elsif parent_obj == 'OS_SpaceType'
|
1953
|
+
# This object is associated with a space type
|
1954
|
+
# Check if it is the current space type
|
1955
|
+
if space_type_name == light.spaceType.get.name.get
|
1956
|
+
light_objs << light
|
1957
|
+
end
|
1958
|
+
end
|
1959
|
+
end
|
1960
|
+
|
1961
|
+
light_objs.each do |light|
|
1962
|
+
ltg_sch_ruleset = nil
|
1963
|
+
ltg_sch = light.schedule
|
1964
|
+
ltg_w = light.getLightingPower(space.floorArea, ppl_total)
|
1965
|
+
|
1966
|
+
if light.isScheduleDefaulted
|
1967
|
+
# Check default schedule set
|
1968
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
1969
|
+
unless space.spaceType.get.defaultScheduleSet.get.lightingSchedule.empty?
|
1970
|
+
ltg_sch = space.spaceType.get.defaultScheduleSet.get.lightingSchedule
|
1971
|
+
end
|
1972
|
+
end
|
1973
|
+
end
|
1974
|
+
if ltg_sch.is_initialized
|
1975
|
+
ltg_sch_obj = ltg_sch.get
|
1976
|
+
ltg_sch_values = get_8760_values_from_schedule(model, ltg_sch_obj)
|
1977
|
+
if !ltg_sch_values.nil?
|
1978
|
+
ltg_sch_max = ltg_sch_values.max
|
1979
|
+
else
|
1980
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Failed to retreive lighting schedule for #{space.name}. Assuming #{ltg_w} W.")
|
1981
|
+
end
|
1982
|
+
end
|
1983
|
+
|
1984
|
+
if !ltg_sch_values.nil?
|
1985
|
+
ltg_sch_value = 1.0
|
1986
|
+
(0..8759).each do |ihr|
|
1987
|
+
ltg_sch_value = ltg_sch_values[ihr] unless ltg_sch_ruleset.nil?
|
1988
|
+
ltg_values[ihr] += ltg_w * ltg_sch_value
|
1989
|
+
end
|
1990
|
+
end
|
1991
|
+
end
|
1992
|
+
|
1993
|
+
# Luminaire Objects
|
1994
|
+
space.spaceType.get.luminaires.each do |light|
|
1995
|
+
ltg_sch_values = nil
|
1996
|
+
ltg_sch = light.schedule
|
1997
|
+
ltg_w = light.lightingPower(space.floorArea, ppl_total)
|
1998
|
+
# not sure if above line is valid, so calculate from parts instead until above can be verified
|
1999
|
+
ltg_w = light.getPowerPerFloorArea(space.floorArea) * space.floorArea
|
2000
|
+
ltg_w += light.getPowerPerPerson(ppl_total) * ppl_total
|
2001
|
+
|
2002
|
+
if light.isScheduleDefaulted
|
2003
|
+
# Check default schedule set
|
2004
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
2005
|
+
unless space.spaceType.get.defaultScheduleSet.get.lightingSchedule.empty?
|
2006
|
+
ltg_sch = space.spaceType.get.defaultScheduleSet.get.lightingSchedule
|
2007
|
+
end
|
2008
|
+
end
|
2009
|
+
end
|
2010
|
+
if ltg_sch.is_initialized
|
2011
|
+
ltg_sch_obj = ltg_sch.get
|
2012
|
+
ltg_sch_values = get_8760_values_from_schedule(model, ltg_sch_obj)
|
2013
|
+
if !ltg_sch_values.nil?
|
2014
|
+
ltg_sch_max = ltg_sch_values.max
|
2015
|
+
else
|
2016
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Failed to retreive lighting schedule for luminaires for #{space.name}. Assuming #{ltg_w} W.")
|
2017
|
+
end
|
2018
|
+
end
|
2019
|
+
|
2020
|
+
if !ltg_sch_values.nil?
|
2021
|
+
ltg_sch_value = 1.0
|
2022
|
+
(0..8759).each do |ihr|
|
2023
|
+
ltg_sch_value = ltg_sch_values[ihr] unless ltg_sch_ruleset.nil?
|
2024
|
+
ltg_values[ihr] += ltg_w * ltg_sch_value
|
2025
|
+
end
|
2026
|
+
end
|
2027
|
+
end
|
2028
|
+
|
2029
|
+
# Equipment Loads
|
2030
|
+
eqp_type = 'electric equipment'
|
2031
|
+
equips = model.getElectricEquipments
|
2032
|
+
load_values = space_get_loads_for_all_equips(model, space, equips, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2033
|
+
|
2034
|
+
eqp_type = 'gas equipment'
|
2035
|
+
equips = model.getGasEquipments
|
2036
|
+
load_values = space_get_loads_for_all_equips(model, space, equips, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2037
|
+
|
2038
|
+
eqp_type = 'steam equipment'
|
2039
|
+
equips = model.getSteamEquipments
|
2040
|
+
load_values = space_get_loads_for_all_equips(model, space, equips, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2041
|
+
|
2042
|
+
eqp_type = 'hot water equipment'
|
2043
|
+
equips = model.getHotWaterEquipments
|
2044
|
+
load_values = space_get_loads_for_all_equips(model, space, equips, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2045
|
+
|
2046
|
+
eqp_type = 'other equipment'
|
2047
|
+
equips = model.getOtherEquipments
|
2048
|
+
load_values = space_get_loads_for_all_equips(model, space, equips, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2049
|
+
|
2050
|
+
# Add lighting and people to the load values array
|
2051
|
+
if return_noncoincident_value
|
2052
|
+
noncoincident_peak_load = load_values[0] + ppl_values.max + ltg_values.max
|
2053
|
+
return noncoincident_peak_load
|
2054
|
+
else
|
2055
|
+
(0..8759).each do |ihr|
|
2056
|
+
load_values[ihr] += ppl_values[ihr] + ltg_values[ihr]
|
2057
|
+
end
|
2058
|
+
return load_values
|
2059
|
+
end
|
2060
|
+
end
|
2061
|
+
|
2062
|
+
# Loops through a set of equipment objects of one type
|
2063
|
+
# For each applicable equipment object, call method to get annual gain values
|
2064
|
+
# This is useful for the Appendix G test for multizone systems
|
2065
|
+
# to determine whether specific zones should be isolated to PSZ based on
|
2066
|
+
# space loads that differ significantly from other zones on the multizone system
|
2067
|
+
#
|
2068
|
+
# @param model [OpenStudio::Model::Model] the model
|
2069
|
+
# @param space [OpenStudio::Model::Space] the space
|
2070
|
+
# @param equips [object] This is an array of equipment objects in the model
|
2071
|
+
# @param eqp_type [String] string description of the type of equipment object
|
2072
|
+
# @param ppl_total [Numeric] total number of people in the space
|
2073
|
+
# @param load_values [Array] 8760 array of load values for the equipment type
|
2074
|
+
# @param return_noncoincident_value [boolean] return a single peak value if true; return 8760 gain profile if false
|
2075
|
+
#
|
2076
|
+
# @return [Array] load values array; if return_noncoincident_value is true, array has only one value
|
2077
|
+
#
|
2078
|
+
def space_get_loads_for_all_equips(model, space, equips, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2079
|
+
space_name = space.name.get
|
2080
|
+
space_type_name = space.spaceType.get.name.get
|
2081
|
+
equips.sort.each do |equip|
|
2082
|
+
parent_obj = equip.parent.get.iddObjectType.valueName.to_s
|
2083
|
+
if parent_obj == 'OS_Space'
|
2084
|
+
# This object is associated with a single space
|
2085
|
+
# Check if it is the current space
|
2086
|
+
if space_name == equip.space.get.name.get
|
2087
|
+
euip_name = equip.name.get
|
2088
|
+
load_values = space_get_equip_annual_array(model, space, equip, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2089
|
+
end
|
2090
|
+
elsif parent_obj == 'OS_SpaceType'
|
2091
|
+
# This object is associated with a space type
|
2092
|
+
# Check if it is the current space type
|
2093
|
+
if space_type_name == equip.spaceType.get.name.get
|
2094
|
+
load_values = space_get_equip_annual_array(model, space, equip, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2095
|
+
end
|
2096
|
+
end
|
2097
|
+
end
|
2098
|
+
return load_values
|
2099
|
+
end
|
2100
|
+
|
2101
|
+
# Returns an 8760 array of load values for a specific type of load in a space.
|
2102
|
+
# This is useful for the Appendix G test for multizone systems
|
2103
|
+
# to determine whether specific zones should be isolated to PSZ based on
|
2104
|
+
# space loads that differ significantly from other zones on the multizone system
|
2105
|
+
#
|
2106
|
+
# @param model [OpenStudio::Model::Model] the model
|
2107
|
+
# @param space [OpenStudio::Model::Space] the space
|
2108
|
+
# @param equip [object] This can be any type of equipment object in the space
|
2109
|
+
# @param eqp_type [String] string description of the type of equipment object
|
2110
|
+
# @param ppl_total [Numeric] total number of people in the space
|
2111
|
+
# @param load_values [Array] 8760 array of load values for the equipment type
|
2112
|
+
# @param return_noncoincident_value [boolean] return a single peak value if true; return 8760 gain profile if false
|
2113
|
+
#
|
2114
|
+
# @return [Array] load values array; if return_noncoincident_value is true, array has only one value
|
2115
|
+
#
|
2116
|
+
def space_get_equip_annual_array(model, space, equip, eqp_type, ppl_total, load_values, return_noncoincident_value)
|
2117
|
+
# Get load schedule and load lost value depending on equipment type
|
2118
|
+
case eqp_type
|
2119
|
+
when 'electric equipment'
|
2120
|
+
load_sch = equip.schedule
|
2121
|
+
load_lost = equip.electricEquipmentDefinition.fractionLost # eqp-type-specific
|
2122
|
+
load_w = equip.getDesignLevel(space.floorArea, ppl_total) * (1 - load_lost)
|
2123
|
+
|
2124
|
+
if equip.isScheduleDefaulted
|
2125
|
+
# Check default schedule set
|
2126
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
2127
|
+
unless space.spaceType.get.defaultScheduleSet.get.electricEquipmentSchedule.empty? # eqp-type-specific
|
2128
|
+
load_sch = space.spaceType.get.defaultScheduleSet.get.electricEquipmentSchedule # eqp-type-specific
|
2129
|
+
end
|
2130
|
+
end
|
2131
|
+
end
|
2132
|
+
when 'gas equipment'
|
2133
|
+
load_sch = equip.schedule
|
2134
|
+
load_lost = equip.gasEquipmentDefinition.fractionLost # eqp-type-specific
|
2135
|
+
load_w = equip.getDesignLevel(space.floorArea, ppl_total) * (1 - load_lost)
|
2136
|
+
|
2137
|
+
if equip.isScheduleDefaulted
|
2138
|
+
# Check default schedule set
|
2139
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
2140
|
+
unless space.spaceType.get.defaultScheduleSet.get.gasEquipmentSchedule.empty? # eqp-type-specific
|
2141
|
+
load_sch = space.spaceType.get.defaultScheduleSet.get.gasEquipmentSchedule # eqp-type-specific
|
2142
|
+
end
|
2143
|
+
end
|
2144
|
+
end
|
2145
|
+
when 'steam equipment'
|
2146
|
+
load_sch = equip.schedule
|
2147
|
+
load_lost = equip.steamEquipmentDefinition.fractionLost # eqp-type-specific
|
2148
|
+
load_w = equip.getDesignLevel(space.floorArea, ppl_total) * (1 - load_lost)
|
2149
|
+
|
2150
|
+
if equip.isScheduleDefaulted
|
2151
|
+
# Check default schedule set
|
2152
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
2153
|
+
unless space.spaceType.get.defaultScheduleSet.get.steamEquipmentSchedule.empty? # eqp-type-specific
|
2154
|
+
load_sch = space.spaceType.get.defaultScheduleSet.get.steamEquipmentSchedule # eqp-type-specific
|
2155
|
+
end
|
2156
|
+
end
|
2157
|
+
end
|
2158
|
+
when 'hot water equipment'
|
2159
|
+
load_sch = equip.schedule
|
2160
|
+
load_lost = equip.hotWaterEquipmentDefinition.fractionLost # eqp-type-specific
|
2161
|
+
load_w = equip.getDesignLevel(space.floorArea, ppl_total) * (1 - load_lost)
|
2162
|
+
|
2163
|
+
if equip.isScheduleDefaulted
|
2164
|
+
# Check default schedule set
|
2165
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
2166
|
+
unless space.spaceType.get.defaultScheduleSet.get.hotWaterEquipmentSchedule.empty? # eqp-type-specific
|
2167
|
+
load_sch = space.spaceType.get.defaultScheduleSet.get.hotWaterEquipmentSchedule # eqp-type-specific
|
2168
|
+
end
|
2169
|
+
end
|
2170
|
+
end
|
2171
|
+
when 'other equipment'
|
2172
|
+
load_sch = equip.schedule
|
2173
|
+
load_lost = equip.otherEquipmentDefinition.fractionLost # eqp-type-specific
|
2174
|
+
load_w = equip.getDesignLevel(space.floorArea, ppl_total) * (1 - load_lost)
|
2175
|
+
|
2176
|
+
if equip.isScheduleDefaulted
|
2177
|
+
# Check default schedule set
|
2178
|
+
unless space.spaceType.get.defaultScheduleSet.empty?
|
2179
|
+
unless space.spaceType.get.defaultScheduleSet.get.otherEquipmentSchedule.empty? # eqp-type-specific
|
2180
|
+
load_sch = space.spaceType.get.defaultScheduleSet.get.otherEquipmentSchedule # eqp-type-specific
|
2181
|
+
end
|
2182
|
+
end
|
2183
|
+
end
|
2184
|
+
end
|
2185
|
+
|
2186
|
+
load_sch_ruleset = nil
|
2187
|
+
if load_sch.is_initialized
|
2188
|
+
load_sch_obj = load_sch.get
|
2189
|
+
load_sch_values = get_8760_values_from_schedule(model, load_sch_obj)
|
2190
|
+
if !load_sch_values.nil?
|
2191
|
+
load_sch_max = load_sch_values.max
|
2192
|
+
else
|
2193
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Space', "Failed to retreive schedule for equipment type #{eqp_type} in space #{space.name}. Assuming #{load_w} W.")
|
2194
|
+
end
|
2195
|
+
end
|
2196
|
+
|
2197
|
+
if return_noncoincident_value
|
2198
|
+
load_values[0] += load_w * load_sch_values.max
|
2199
|
+
else
|
2200
|
+
if !load_sch_values.nil?
|
2201
|
+
load_sch_value = 1.0
|
2202
|
+
(0..8759).each do |ihr|
|
2203
|
+
load_sch_value = load_sch_values[ihr]
|
2204
|
+
load_values[ihr] += load_w * load_sch_value
|
2205
|
+
end
|
2206
|
+
end
|
2207
|
+
end
|
2208
|
+
return load_values
|
2209
|
+
end
|
2210
|
+
|
1585
2211
|
# will return a sorted array of array of spaces and connected area (Descending)
|
1586
2212
|
#
|
1587
2213
|
# @param space [OpenStudio::Model::Space] space object
|
@@ -2305,6 +2931,30 @@ class Standard
|
|
2305
2931
|
return overlap_area
|
2306
2932
|
end
|
2307
2933
|
|
2934
|
+
# A function to check whether a space is a return / supply plenum.
|
2935
|
+
# This function only works on spaces used as a AirLoopSupplyPlenum or AirLoopReturnPlenum
|
2936
|
+
# @param [OpenStudio::Model::Space] space
|
2937
|
+
# @return boolean true if it is plenum, else false.
|
2938
|
+
def space_is_plenum(space)
|
2939
|
+
# Get the zone this space is inside
|
2940
|
+
zone = space.thermalZone
|
2941
|
+
# the zone is a return air plenum
|
2942
|
+
space.model.getAirLoopHVACReturnPlenums.each do |return_air_plenum|
|
2943
|
+
if return_air_plenum.thermalZone.get.name.to_s == zone.get.name.to_s
|
2944
|
+
# Determine if residential
|
2945
|
+
return true
|
2946
|
+
end
|
2947
|
+
end
|
2948
|
+
# the zone is a supply plenum
|
2949
|
+
space.model.getAirLoopHVACSupplyPlenums.each do |supply_air_plenum|
|
2950
|
+
if supply_air_plenum.thermalZone.get.name.to_s == zone.get.name.to_s
|
2951
|
+
return true
|
2952
|
+
end
|
2953
|
+
end
|
2954
|
+
# None match, return false
|
2955
|
+
return false
|
2956
|
+
end
|
2957
|
+
|
2308
2958
|
# Determine if a space should be modeled with an occupancy standby mode
|
2309
2959
|
#
|
2310
2960
|
# @param space [OpenStudio::Model::Space] OpenStudio Space object
|