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
@@ -0,0 +1,666 @@
|
|
1
|
+
class ASHRAE901PRM2019 < ASHRAE901PRM
|
2
|
+
# @!group SpaceType
|
3
|
+
|
4
|
+
# Sets the selected internal loads to standards-based or typical values.
|
5
|
+
# For each category that is selected get all load instances. Remove all
|
6
|
+
# but the first instance if multiple instances. Add a new instance/definition
|
7
|
+
# if no instance exists. Modify the definition for the remaining instance
|
8
|
+
# to have the specified values. This method does not alter any
|
9
|
+
# loads directly assigned to spaces. This method skips plenums.
|
10
|
+
#
|
11
|
+
# @param space_type [OpenStudio::Model::SpaceType] space type object
|
12
|
+
# @param set_people [Bool] if true, set the people density.
|
13
|
+
# Also, assign reasonable clothing, air velocity, and work efficiency inputs
|
14
|
+
# to allow reasonable thermal comfort metrics to be calculated.
|
15
|
+
# @param set_lights [Bool] if true, set the lighting density, lighting fraction
|
16
|
+
# to return air, fraction radiant, and fraction visible.
|
17
|
+
# @param set_electric_equipment [Bool] if true, set the electric equipment density
|
18
|
+
# @param set_gas_equipment [Bool] if true, set the gas equipment density
|
19
|
+
# @param set_ventilation [Bool] if true, set the ventilation rates (per-person and per-area)
|
20
|
+
# @param set_infiltration [Bool] if true, set the infiltration rates
|
21
|
+
# @return [Bool] returns true if successful, false if not
|
22
|
+
def space_type_apply_internal_loads(space_type, set_people, set_lights, set_electric_equipment, set_gas_equipment, set_ventilation, set_infiltration)
|
23
|
+
# Skip plenums
|
24
|
+
# Check if the space type name
|
25
|
+
# contains the word plenum.
|
26
|
+
if space_type.name.get.to_s.downcase.include?('plenum')
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
if space_type.standardsSpaceType.is_initialized
|
31
|
+
if space_type.standardsSpaceType.get.downcase.include?('plenum')
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Save information about lighting exceptions before removing extra lights objects
|
37
|
+
# First get list of all lights objects that are exempt
|
38
|
+
regulated_lights = []
|
39
|
+
unregulated_lights = []
|
40
|
+
user_lights = @standards_data.key?('userdata_lights') ? @standards_data['userdata_lights'] : nil
|
41
|
+
if user_lights && user_lights.length >= 1
|
42
|
+
user_lights.each do |user_data|
|
43
|
+
lights_name = user_data['name']
|
44
|
+
lights_obj = space_type.model.getLightsByName(lights_name).get
|
45
|
+
|
46
|
+
if user_data['has_retail_display_exception'].to_s.downcase == 'yes' || user_data['has_unregulated_exception'].to_s.downcase == 'yes'
|
47
|
+
# If either exception is applicable
|
48
|
+
# Put this one on the unregulated list
|
49
|
+
unregulated_lights.push(lights_name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get all lights objects that are not exempt
|
55
|
+
space_type.lights.sort.each do |lights_obj|
|
56
|
+
lights_name = lights_obj.name.get
|
57
|
+
if !unregulated_lights.include? lights_name
|
58
|
+
regulated_lights << lights_obj
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Pre-process the light instances in the space type
|
63
|
+
# Remove all regulated instances but leave one in the space type
|
64
|
+
if regulated_lights.size.zero?
|
65
|
+
definition = OpenStudio::Model::LightsDefinition.new(space_type.model)
|
66
|
+
definition.setName("#{space_type.name} Lights Definition")
|
67
|
+
instance = OpenStudio::Model::Lights.new(definition)
|
68
|
+
lights_name = "#{space_type.name} Lights"
|
69
|
+
instance.setName(lights_name)
|
70
|
+
instance.setSpaceType(space_type)
|
71
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no lights, one has been created.")
|
72
|
+
space_type.additionalProperties.setFeature('regulated_lights_name', lights_name)
|
73
|
+
regulated_lights << instance
|
74
|
+
else
|
75
|
+
regulated_lights.each_with_index do |inst, i|
|
76
|
+
if i.zero?
|
77
|
+
# Save the name of the first instance to use as the baseline lights object
|
78
|
+
lights_name = inst.name.get
|
79
|
+
space_type.additionalProperties.setFeature('regulated_lights_name', lights_name)
|
80
|
+
next
|
81
|
+
end
|
82
|
+
|
83
|
+
# Remove all other lights objects that have not been identified as unregulated
|
84
|
+
if i == 1
|
85
|
+
ref_name = space_type.additionalProperties.getFeatureAsString('regulated_lights_name').to_s
|
86
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Multiple lights objects found in user model for #{space_type.name}. Baseline schedule will be determined from #{ref_name}")
|
87
|
+
end
|
88
|
+
|
89
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Removed lighting object #{inst.name} from #{space_type.name}. ")
|
90
|
+
inst.remove
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get userdata from userdata_space and userdata_spacetype
|
95
|
+
user_spaces = @standards_data.key?('userdata_space') ? @standards_data['userdata_space'] : nil
|
96
|
+
user_spacetypes = @standards_data.key?('userdata_spacetype') ? @standards_data['userdata_spacetype'] : nil
|
97
|
+
if user_spaces && user_spaces.length >= 1 && has_user_lpd_values(user_spaces)
|
98
|
+
# if space type has user data & data has lighting data for user space
|
99
|
+
# call this function to enforce space-space_type one on one relationship
|
100
|
+
new_space_array = space_to_space_type_apply_lighting(user_spaces, user_spacetypes, space_type)
|
101
|
+
# process power equipment with new spaces.
|
102
|
+
space_to_space_type_apply_power_equipment(user_spacetypes, user_spaces, new_space_array)
|
103
|
+
# remove the old space
|
104
|
+
space_type.remove
|
105
|
+
else
|
106
|
+
if user_spacetypes && user_spacetypes.length >= 1 && has_user_lpd_values(user_spacetypes)
|
107
|
+
# if space type has user data & data has lighting data for user space type
|
108
|
+
user_space_type_index = user_spacetypes.index { |user_spacetype| user_spacetype['name'] == space_type.name.get }
|
109
|
+
if user_space_type_index.nil?
|
110
|
+
# cannot find a matched user_spacetype to space_type, use space_type to set LPD
|
111
|
+
set_lpd_on_space_type(space_type, user_spaces, user_spacetypes)
|
112
|
+
space_type_apply_power_equipment(space_type)
|
113
|
+
else
|
114
|
+
user_space_type = user_spacetypes[user_space_type_index]
|
115
|
+
# If multiple LPD value exist - then enforce space-space_type one on one relationship
|
116
|
+
if has_multi_lpd_values_user_data(user_space_type, space_type)
|
117
|
+
new_space_array = space_to_space_type_apply_lighting(user_spaces, user_spacetypes, space_type)
|
118
|
+
space_to_space_type_apply_power_equipment(user_spacetypes, user_spaces, new_space_array)
|
119
|
+
space_type.remove
|
120
|
+
else
|
121
|
+
# Process the user_space type data - at this point, we are sure there is no lighting per length
|
122
|
+
# So all the LPD should be identical by space
|
123
|
+
# Loop because we need to assign the occupancy control credit to each space for
|
124
|
+
# Schedule processing.
|
125
|
+
space_type_lighting_per_area = 0.0
|
126
|
+
space_type.spaces.each do |space|
|
127
|
+
space_lighting_per_area = calculate_lpd_from_userdata(user_space_type, space)
|
128
|
+
space_type_lighting_per_area = space_lighting_per_area
|
129
|
+
end
|
130
|
+
if space_type.hasAdditionalProperties && space_type.additionalProperties.hasFeature('regulated_lights_name')
|
131
|
+
lights_name = space_type.additionalProperties.getFeatureAsString('regulated_lights_name').to_s
|
132
|
+
lights_obj = space_type.model.getLightsByName(lights_name).get
|
133
|
+
lights_obj.lightsDefinition.setWattsperSpaceFloorArea(OpenStudio.convert(space_type_lighting_per_area.to_f, 'W/ft^2', 'W/m^2').get)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
# process power equipment
|
137
|
+
space_type_apply_power_equipment(space_type)
|
138
|
+
end
|
139
|
+
else
|
140
|
+
# no user data, set space_type LPD
|
141
|
+
set_lpd_on_space_type(space_type, user_spaces, user_spacetypes)
|
142
|
+
# process power equipment
|
143
|
+
space_type_apply_power_equipment(space_type)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# A function to calculate electric value for an electric equipment.
|
149
|
+
# The function will check whether this electric equipment is motor, refrigeration, elevator or generic electric equipment
|
150
|
+
# and decide actions based on the equipment types
|
151
|
+
#
|
152
|
+
# @param user_equip_data [Hash] user equipment data
|
153
|
+
# @param power_equipment [OpenStudio::Model::ElectricEquipment] equipment
|
154
|
+
# @param power_schedule_hash [Hash] equipment operation schedule hash
|
155
|
+
# @param space_type [OpenStudio::Model:SpaceType] space type
|
156
|
+
# @param user_space_data [Hash] user space data
|
157
|
+
def calculate_electric_value_by_userdata(user_equip_data, power_equipment, power_schedule_hash, space_type, user_space_data = nil)
|
158
|
+
# Check if the plug load represents a motor (check if motorhorsepower exist), if so, record the motor HP and efficiency.
|
159
|
+
if !user_equip_data['motor_horsepower'].nil?
|
160
|
+
# Pre-processing will ensure these three user data are added correctly (float, float, boolean)
|
161
|
+
power_equipment.additionalProperties.setFeature('motor_horsepower', user_equip_data['motor_horsepower'].to_f)
|
162
|
+
power_equipment.additionalProperties.setFeature('motor_efficiency', user_equip_data['motor_efficiency'].to_f)
|
163
|
+
power_equipment.additionalProperties.setFeature('motor_is_exempt', user_equip_data['motor_is_exempt'])
|
164
|
+
elsif !(user_equip_data['fraction_of_controlled_receptacles'].nil? && user_equip_data['receptacle_power_savings'].nil?)
|
165
|
+
# If not a motor - update.
|
166
|
+
# Update the electric equipment occupancy credit (if it has)
|
167
|
+
update_power_equipment_credits(power_equipment, user_equip_data, power_schedule_hash, space_type, user_space_data)
|
168
|
+
else
|
169
|
+
# The electric equipment is either an elevator or refrigeration
|
170
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ElectricEquipment', "#{power_equipment.name} is an elevator or refrigeration according to the user data provided. Skip receptacle power credit.")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def space_type_apply_power_equipment(space_type)
|
175
|
+
# save schedules in a hash in case it is needed for new electric equipment
|
176
|
+
power_schedule_hash = {}
|
177
|
+
user_electric_equipment_data = @standards_data.key?('userdata_electric_equipment') ? @standards_data['userdata_electric_equipment'] : nil
|
178
|
+
user_gas_equipment_data = @standards_data.key?('userdata_gas_equipment') ? @standards_data['userdata_gas_equipment'] : nil
|
179
|
+
if user_electric_equipment_data && user_electric_equipment_data.length >= 1
|
180
|
+
space_type_electric_equipments = space_type.electricEquipment
|
181
|
+
space_type_electric_equipments.each do |sp_electric_equipment|
|
182
|
+
electric_equipment_name = sp_electric_equipment.name.get
|
183
|
+
select_user_electric_equipment_array = user_electric_equipment_data.select { |elec| elec['name'].casecmp(electric_equipment_name) == 0 }
|
184
|
+
unless select_user_electric_equipment_array.empty?
|
185
|
+
select_user_electric_equipment = select_user_electric_equipment_array[0]
|
186
|
+
calculate_electric_value_by_userdata(select_user_electric_equipment, sp_electric_equipment, power_schedule_hash, space_type, nil)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
elsif user_gas_equipment_data && user_gas_equipment_data.length >= 1
|
190
|
+
space_type_gas_equipments = space_type.gasEquipment
|
191
|
+
space_type_gas_equipments.each do |sp_gas_equipment|
|
192
|
+
gas_equipment_name = sp_gas_equipment.name.get
|
193
|
+
select_user_gas_equipment_array = user_gas_equipment_data.select { |gas| gas['name'].casecmp(gas_equipment_name) == 0 }
|
194
|
+
unless select_user_gas_equipment_array.empty?
|
195
|
+
select_user_gas_equipment = select_user_gas_equipment_array[0]
|
196
|
+
# Update the gas equipment occupancy credit (if it has)
|
197
|
+
update_power_equipment_credits(sp_gas_equipment, select_user_gas_equipment, power_schedule_hash, space_type.model, nil)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Apply space to space type power equipment adjustment.
|
204
|
+
# NOTE! this function shall only be used if the space to space type is one to one relationship.
|
205
|
+
# This function can process both electric equipment and gas equipment
|
206
|
+
# and this function will process user data from electric equipment and gas equipment user data
|
207
|
+
#
|
208
|
+
# @param user_spacetypes [Hash] spacetype user data
|
209
|
+
# @param user_spaces [Hash] space user data
|
210
|
+
# @param space_array [OpenStudio::Model:Space] list of spaces need for process
|
211
|
+
def space_to_space_type_apply_power_equipment(user_spacetypes, user_spaces, space_array)
|
212
|
+
# Step 1: Set electric / gas equipment
|
213
|
+
# save schedules in a hash in case it is needed for new electric equipment
|
214
|
+
power_schedule_hash = {}
|
215
|
+
# check if electric equipment data is available.
|
216
|
+
user_electric_equipment_data = @standards_data.key?('userdata_electric_equipment') ? @standards_data['userdata_electric_equipment'] : nil
|
217
|
+
user_gas_equipment_data = @standards_data.key?('userdata_gas_equipment') ? @standards_data['userdata_gas_equipment'] : nil
|
218
|
+
if user_electric_equipment_data && user_electric_equipment_data.length >= 1
|
219
|
+
space_array.each do |space|
|
220
|
+
# Each space has a unique space type
|
221
|
+
space_type = space.spaceType.get
|
222
|
+
user_spacestypes_index = user_spacetypes.index { |user_spacetype| /#{user_spacetype['name']}/i =~ space_type.name.get }
|
223
|
+
user_space_index = user_spaces.index { |user_space| user_space['name'] == space.name.get }
|
224
|
+
# Initialize with standard space_type
|
225
|
+
user_space_data = space_type.name.get
|
226
|
+
unless user_spacestypes_index.nil?
|
227
|
+
# override with user space type if specified
|
228
|
+
user_space_data = user_spacetypes[user_spacestypes_index]
|
229
|
+
end
|
230
|
+
unless user_space_index.nil?
|
231
|
+
# override with user space if specified
|
232
|
+
user_space_data = user_spaces[user_space_index]
|
233
|
+
end
|
234
|
+
space_type_electric_equipments = space_type.electricEquipment
|
235
|
+
space_type_electric_equipments.each do |sp_electric_equipment|
|
236
|
+
electric_equipment_name = sp_electric_equipment.name.get
|
237
|
+
select_user_electric_equipment_array = user_electric_equipment_data.select { |elec| /#{elec['name']}/i =~ electric_equipment_name }
|
238
|
+
unless select_user_electric_equipment_array.empty?
|
239
|
+
select_user_electric_equipment = select_user_electric_equipment_array[0]
|
240
|
+
calculate_electric_value_by_userdata(select_user_electric_equipment, sp_electric_equipment, power_schedule_hash, space_type, user_space_data)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
elsif user_gas_equipment_data && user_gas_equipment_data.length >= 1
|
245
|
+
space_array.each do |space|
|
246
|
+
space_type = space.spaceType.get
|
247
|
+
user_spacestypes_index = user_spacetypes.index { |user_spacetype| user_spacetype['name'] == space_type.name.get }
|
248
|
+
user_space_index = user_spaces.index { |user_space| user_space['name'] == space.name.get }
|
249
|
+
user_space_data = space_type.name.get
|
250
|
+
unless user_spacestypes_index.nil?
|
251
|
+
user_space_data = user_spacetypes[user_spacestypes_index]
|
252
|
+
end
|
253
|
+
unless user_space_index.nil?
|
254
|
+
user_space_data = user_spaces[user_space_index]
|
255
|
+
end
|
256
|
+
space_type_gas_equipments = space_type.gasEquipment
|
257
|
+
space_type_gas_equipments.each do |sp_gas_equipment|
|
258
|
+
gas_equipment_name = sp_gas_equipment.name.get
|
259
|
+
select_user_gas_equipment_array = user_gas_equipment_data.select { |gas| gas['name'].casecmp(gas_equipment_name) == 0 }
|
260
|
+
unless select_user_gas_equipment_array.empty?
|
261
|
+
select_user_gas_equipment = select_user_gas_equipment_array[0]
|
262
|
+
# Update the gas equipment occupancy credit (if it has)
|
263
|
+
update_power_equipment_credits(sp_gas_equipment, select_user_gas_equipment, power_schedule_hash, space_type.model, user_space_data)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Function update a power equipment schedule based on user data.
|
271
|
+
# This function works with both electric equipment and gas equipment and applies the ruleset on power equipment
|
272
|
+
# The function process user data including the fraction of controlled receptacles and receptacle power savings.
|
273
|
+
#
|
274
|
+
# @parma power_equipment [OpenStudio::Model::ElectricEquipment] or [OpenStudio::Model:GasEquipment]
|
275
|
+
# @param user_power_equipment [Hash] user data for the power equipment
|
276
|
+
# @param schedule_hash [Hash] power equipment operation schedules in a hash
|
277
|
+
# @param space_type [OpenStudio::Model:SpaceType] space type
|
278
|
+
# @param user_data [Hash] user space data
|
279
|
+
def update_power_equipment_credits(power_equipment, user_power_equipment, schedule_hash, space_type, user_data = nil)
|
280
|
+
exception_list = ['office - enclosed <= 250 sf', 'conference/meeting/multipurpose', 'copy/print',
|
281
|
+
'lounge/breakroom - all other', 'lounge/breakroom - healthcare facility', 'classroom/lecture/training - all other',
|
282
|
+
'classroom/lecture/training - preschool to 12th', 'office - open']
|
283
|
+
|
284
|
+
receptacle_power_credits = 0.0
|
285
|
+
# Check fraction_of_controlled_receptacles or receptacle_power_savings exist
|
286
|
+
if user_power_equipment.key?('fraction_of_controlled_receptacles') && !user_power_equipment['fraction_of_controlled_receptacles'].nil?
|
287
|
+
rc = user_power_equipment['fraction_of_controlled_receptacles'].to_f
|
288
|
+
# receptacle power credits = percent of all controlled receptacles * 10%
|
289
|
+
receptacle_power_credits = rc * 0.1
|
290
|
+
elsif user_power_equipment.key?('receptacle_power_savings') && !user_power_equipment['receptacle_power_savings'].nil?
|
291
|
+
receptacle_power_credits = user_power_equipment['receptacle_power_savings'].to_f
|
292
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ElectricEquipment', "#{power_equipment.name.get} has a user specified receptacle power saving credit #{receptacle_power_credits}. The modeler needs to make sure the credit is approved by a rating authority per Table G3.1 section 12.")
|
293
|
+
end
|
294
|
+
|
295
|
+
# process user space data
|
296
|
+
if user_data.is_a?(Hash)
|
297
|
+
if user_data.key?('num_std_ltg_types') && user_data['num_std_ltg_types'].to_f > 0
|
298
|
+
adjusted_receptacle_power_credits = 0.0
|
299
|
+
num_std_space_types = user_data['num_std_ltg_types'].to_i
|
300
|
+
std_space_index = 0 # loop index
|
301
|
+
# Loop through standard lighting type in a space
|
302
|
+
while std_space_index < num_std_space_types
|
303
|
+
std_space_index += 1
|
304
|
+
# Retrieve data from user_data
|
305
|
+
type_key = format('std_ltg_type%02d', std_space_index)
|
306
|
+
frac_key = format('std_ltg_type_frac%02d', std_space_index)
|
307
|
+
sub_space_type = user_data[type_key]
|
308
|
+
next if exception_list.include?(sub_space_type)
|
309
|
+
|
310
|
+
adjusted_receptacle_power_credits += user_data[frac_key].to_f * receptacle_power_credits
|
311
|
+
# Adjust while loop condition factors
|
312
|
+
end
|
313
|
+
receptacle_power_credits = adjusted_receptacle_power_credits
|
314
|
+
end
|
315
|
+
elsif user_data.is_a?(String)
|
316
|
+
if exception_list.include?(space_type.standardsSpaceType.get)
|
317
|
+
# the space type is in the exception list, no credit to the space type
|
318
|
+
receptacle_power_credits = 0.0
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# Step 2: check if need to adjust the electric equipment schedule. - apply credit if needed.
|
323
|
+
if receptacle_power_credits > 0.0
|
324
|
+
# get current schedule
|
325
|
+
power_schedule = power_equipment.schedule.get
|
326
|
+
power_schedule_name = power_schedule.name.get
|
327
|
+
new_power_schedule_name = format("#{power_schedule_name}_%.4f", receptacle_power_credits)
|
328
|
+
if schedule_hash.key?(new_power_schedule_name)
|
329
|
+
# In this case, there is a schedule created, can retrieve the schedule object and reset in this space type.
|
330
|
+
schedule_rule = schedule_hash[new_power_schedule_name]
|
331
|
+
power_equipment.setSchedule(schedule_rule)
|
332
|
+
else
|
333
|
+
# In this case, create a new schedule
|
334
|
+
# 1. Clone the existing schedule
|
335
|
+
new_rule_set_schedule = deep_copy_schedule(new_power_schedule_name, power_schedule, receptacle_power_credits, space_type.model)
|
336
|
+
if power_equipment.setSchedule(new_rule_set_schedule)
|
337
|
+
schedule_hash[new_power_schedule_name] = new_rule_set_schedule
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
# Function to tset LPD on default space type
|
344
|
+
def set_lpd_on_space_type(space_type, user_spaces, user_spacetypes)
|
345
|
+
if has_multi_lpd_values_space_type(space_type)
|
346
|
+
# If multiple LPD value exist - then enforce space-space_type one on one relationship
|
347
|
+
space_to_space_type_apply_lighting(user_spaces, user_spacetypes, space_type)
|
348
|
+
else
|
349
|
+
# use default - loop through space to assign occupancy credit to each space.
|
350
|
+
space_type_lighting_per_area = 0.0
|
351
|
+
space_type.spaces.each do |space|
|
352
|
+
space_lighting_per_area = calculate_lpd_by_space(space_type, space)
|
353
|
+
space_type_lighting_per_area = space_lighting_per_area
|
354
|
+
end
|
355
|
+
if space_type.hasAdditionalProperties && space_type.additionalProperties.hasFeature('regulated_lights_name')
|
356
|
+
lights_name = space_type.additionalProperties.getFeatureAsString('regulated_lights_name').to_s
|
357
|
+
lights_obj = space_type.model.getLightsByName(lights_name).get
|
358
|
+
lights_obj.lightsDefinition.setWattsperSpaceFloorArea(OpenStudio.convert(space_type_lighting_per_area.to_f, 'W/ft^2', 'W/m^2').get)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# Function that applies user LPD to each space by duplicating space types
|
364
|
+
# This function is used when there are user space data available or
|
365
|
+
# the spaces under space type has lighting per length value which may cause multiple
|
366
|
+
# lighting power densities under one space_type.
|
367
|
+
# @param user_spaces hash data contained in the user space
|
368
|
+
# @param user_spacetypes hash data contained in the user spacetypes
|
369
|
+
# @param space_type OpenStudio::Model::SpaceType object
|
370
|
+
def space_to_space_type_apply_lighting(user_spaces, user_spacetypes, space_type)
|
371
|
+
space_lighting_per_area_hash = {}
|
372
|
+
# first priority - user_space data
|
373
|
+
if user_spaces && user_spaces.length >= 1
|
374
|
+
space_type.spaces.each do |space|
|
375
|
+
user_space_index = user_spaces.index { |user_space| user_space['name'] == space.name.get }
|
376
|
+
unless user_space_index.nil?
|
377
|
+
user_space_data = user_spaces[user_space_index]
|
378
|
+
if user_space_data.key?('num_std_ltg_types') && user_space_data['num_std_ltg_types'].to_f > 0
|
379
|
+
space_lighting_per_area = calculate_lpd_from_userdata(user_space_data, space)
|
380
|
+
space_lighting_per_area_hash[space.name.get] = space_lighting_per_area
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
# second priority - user_spacetype
|
386
|
+
if user_spacetypes && user_spacetypes.length >= 1
|
387
|
+
# if space type has user data
|
388
|
+
user_space_type_index = user_spacetypes.index { |user_spacetype| user_spacetype['name'] == space_type.name.get }
|
389
|
+
unless user_space_type_index.nil?
|
390
|
+
user_space_type_data = user_spacetypes[user_space_type_index]
|
391
|
+
if user_space_type_data.key?('num_std_ltg_types') && user_space_type_data['num_std_ltg_types'].to_f > 0
|
392
|
+
space_type.spaces.each do |space|
|
393
|
+
# unless the space is in the hash, we will add lighting per area to the space
|
394
|
+
space_name = space.name.get
|
395
|
+
unless space_lighting_per_area_hash.key?(space_name)
|
396
|
+
space_lighting_per_area = calculate_lpd_from_userdata(user_space_type_data, space)
|
397
|
+
space_lighting_per_area_hash[space_name] = space_lighting_per_area
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
# Third priority
|
404
|
+
# set space type to every space in the space_type, third priority
|
405
|
+
# will also be assigned from the default space type
|
406
|
+
space_type.spaces.each do |space|
|
407
|
+
space_name = space.name.get
|
408
|
+
unless space_lighting_per_area_hash.key?(space_name)
|
409
|
+
space_lighting_per_area = calculate_lpd_by_space(space_type, space)
|
410
|
+
space_lighting_per_area_hash[space_name] = space_lighting_per_area
|
411
|
+
end
|
412
|
+
end
|
413
|
+
# All space is explored.
|
414
|
+
# Now rewrite the space type in each space - might need to change the logic
|
415
|
+
space_array = []
|
416
|
+
space_type.spaces.each do |space|
|
417
|
+
space_name = space.name.get
|
418
|
+
new_space_type = space_type.clone.to_SpaceType.get
|
419
|
+
space.setSpaceType(new_space_type)
|
420
|
+
lighting_per_area = space_lighting_per_area_hash[space_name]
|
421
|
+
new_space_type.lights.each do |inst|
|
422
|
+
lights_name = inst.name.get
|
423
|
+
new_space_type.additionalProperties.setFeature('regulated_lights_name', lights_name)
|
424
|
+
definition = inst.lightsDefinition
|
425
|
+
unless lighting_per_area.zero?
|
426
|
+
new_definition = definition.clone.to_LightsDefinition.get
|
427
|
+
new_definition.setWattsperSpaceFloorArea(OpenStudio.convert(lighting_per_area.to_f, 'W/ft^2', 'W/m^2').get)
|
428
|
+
inst.setLightsDefinition(new_definition)
|
429
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set LPD to #{lighting_per_area} W/ft^2.")
|
430
|
+
end
|
431
|
+
end
|
432
|
+
space_array.push(space)
|
433
|
+
end
|
434
|
+
return space_array
|
435
|
+
end
|
436
|
+
|
437
|
+
# Modify the lighting schedules for Appendix G PRM for 2016 and later
|
438
|
+
#
|
439
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
440
|
+
def space_type_light_sch_change(model)
|
441
|
+
# set schedule for lighting
|
442
|
+
schedule_hash = {}
|
443
|
+
model.getSpaces.each do |space|
|
444
|
+
space_type = space.spaceType.get
|
445
|
+
if space_type.hasAdditionalProperties && space_type.additionalProperties.hasFeature('regulated_lights_name')
|
446
|
+
lights_name = space_type.additionalProperties.getFeatureAsString('regulated_lights_name').to_s
|
447
|
+
ltg = space_type.model.getLightsByName(lights_name).get
|
448
|
+
if ltg.schedule.is_initialized
|
449
|
+
ltg_schedule = ltg.schedule.get
|
450
|
+
ltg_schedule_name = ltg_schedule.name
|
451
|
+
occupancy_sensor_credit = space.additionalProperties.getFeatureAsDouble('occ_control_credit')
|
452
|
+
new_ltg_schedule_name = format("#{ltg_schedule_name}_%.4f", occupancy_sensor_credit)
|
453
|
+
if schedule_hash.key?(new_ltg_schedule_name)
|
454
|
+
# In this case, there is a schedule created, can retrieve the schedule object and reset in this space type
|
455
|
+
schedule_rule = schedule_hash[new_ltg_schedule_name]
|
456
|
+
ltg.setSchedule(schedule_rule)
|
457
|
+
else
|
458
|
+
# In this case, create a new schedule
|
459
|
+
# 1. Clone the existing schedule
|
460
|
+
new_rule_set_schedule = deep_copy_schedule(new_ltg_schedule_name, ltg_schedule, occupancy_sensor_credit, model)
|
461
|
+
if ltg.setSchedule(new_rule_set_schedule)
|
462
|
+
schedule_hash[new_ltg_schedule_name] = new_rule_set_schedule
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
def deep_copy_schedule(new_schedule_name, schedule, adjustment_factor, model)
|
471
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.ScheduleRuleset', "Creating a new lighting schedule that applies occupancy sensor adjustment factor: #{adjustment_factor} based on #{schedule.name.get} schedule")
|
472
|
+
ruleset = OpenStudio::Model::ScheduleRuleset.new(model)
|
473
|
+
ruleset.setName(new_schedule_name)
|
474
|
+
|
475
|
+
# schedule types limits and default day schedule - keep the copy
|
476
|
+
schedule_ruleset = schedule.to_ScheduleRuleset.get
|
477
|
+
schedule_type_limit = schedule_ruleset.scheduleTypeLimits.get
|
478
|
+
default_day_schedule = schedule_ruleset.defaultDaySchedule
|
479
|
+
default_winter_design_day_schedule = schedule_ruleset.winterDesignDaySchedule
|
480
|
+
default_summer_design_day_schedule = schedule_ruleset.summerDesignDaySchedule
|
481
|
+
|
482
|
+
schedule_ruleset.scheduleRules.each do |week_rule|
|
483
|
+
day_rule = week_rule.daySchedule
|
484
|
+
start_date = week_rule.startDate.get
|
485
|
+
end_date = week_rule.endDate.get
|
486
|
+
|
487
|
+
# create a new day rule - copy and apply the ajustment factor
|
488
|
+
new_day_rule = OpenStudio::Model::ScheduleDay.new(model)
|
489
|
+
new_day_rule.setName(format("#{day_rule.name.get}_%.4f", adjustment_factor))
|
490
|
+
new_day_rule.setScheduleTypeLimits(schedule_type_limit)
|
491
|
+
|
492
|
+
# process day rule
|
493
|
+
times = day_rule.times()
|
494
|
+
# remove the effect of occupancy sensors
|
495
|
+
times.each do |time|
|
496
|
+
hour_value = day_rule.getValue(time)
|
497
|
+
new_value = hour_value / (1.0 - adjustment_factor.to_f)
|
498
|
+
if new_value > 1
|
499
|
+
new_day_rule.addValue(time, 1.0)
|
500
|
+
else
|
501
|
+
new_day_rule.addValue(time, new_value)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
# create week rule schedule
|
506
|
+
new_week_rule = OpenStudio::Model::ScheduleRule.new(ruleset, new_day_rule)
|
507
|
+
new_week_rule.setName(format("#{week_rule.name.get}_%.4f", adjustment_factor))
|
508
|
+
new_week_rule.setApplySunday(week_rule.applySunday)
|
509
|
+
new_week_rule.setApplyMonday(week_rule.applyMonday)
|
510
|
+
new_week_rule.setApplyTuesday(week_rule.applyTuesday)
|
511
|
+
new_week_rule.setApplyWednesday(week_rule.applyWednesday)
|
512
|
+
new_week_rule.setApplyThursday(week_rule.applyThursday)
|
513
|
+
new_week_rule.setApplyFriday(week_rule.applyFriday)
|
514
|
+
new_week_rule.setApplySaturday(week_rule.applySaturday)
|
515
|
+
new_week_rule.setStartDate(start_date)
|
516
|
+
new_week_rule.setEndDate(end_date)
|
517
|
+
end
|
518
|
+
# default day schedule
|
519
|
+
default_day = ruleset.defaultDaySchedule
|
520
|
+
default_day.clearValues
|
521
|
+
default_day.times.each_index { |counter| default_day.addValue(default_day_schedule.times[counter], default_day_schedule.values[counter]) }
|
522
|
+
# winter design day schedule
|
523
|
+
winter_design_day_schedule = ruleset.winterDesignDaySchedule
|
524
|
+
winter_design_day_schedule.clearValues
|
525
|
+
winter_design_day_schedule.times.each_index { |counter| winter_design_day_schedule.addValue(default_winter_design_day_schedule.times[counter], default_winter_design_day_schedule.values[counter]) }
|
526
|
+
summer_design_day_schedule = ruleset.summerDesignDaySchedule
|
527
|
+
summer_design_day_schedule.clearValues
|
528
|
+
summer_design_day_schedule.times.each_index { |counter| summer_design_day_schedule.addValue(default_summer_design_day_schedule.times[counter], default_summer_design_day_schedule.values[counter]) }
|
529
|
+
return ruleset
|
530
|
+
end
|
531
|
+
|
532
|
+
# calculate the lighting power density per area based on space type
|
533
|
+
# The function will calculate the LPD based on the space type (STRING)
|
534
|
+
# It considers lighting per area, lighting per length as well as occupancy factors in the database.
|
535
|
+
# @param space_type [String]
|
536
|
+
# @param space [OpenStudio::Model::Space]
|
537
|
+
def calculate_lpd_by_space(space_type, space)
|
538
|
+
# get interior lighting data
|
539
|
+
space_type_properties = interior_lighting_get_prm_data(space_type)
|
540
|
+
space_lighting_per_area = 0.0
|
541
|
+
# Assign data
|
542
|
+
lights_have_info = false
|
543
|
+
lighting_per_area = space_type_properties['w/ft^2'].to_f
|
544
|
+
lighting_per_length = space_type_properties['w/ft'].to_f
|
545
|
+
manon_or_partauto = space_type_properties['manon_or_partauto'].to_i
|
546
|
+
lights_have_info = true unless lighting_per_area.zero? && lighting_per_length.zero?
|
547
|
+
occ_control_reduction_factor = 0.0
|
548
|
+
|
549
|
+
if lights_have_info
|
550
|
+
# Space height
|
551
|
+
space_volume = space.volume
|
552
|
+
space_area = space.floorArea
|
553
|
+
space_height = OpenStudio.convert(space_volume / space_area, 'm', 'ft').get
|
554
|
+
# calculate the new lpd values
|
555
|
+
space_lighting_per_area = lighting_per_length * space_height + lighting_per_area
|
556
|
+
|
557
|
+
# Adjust the occupancy control sensor reduction factor from dataset
|
558
|
+
if manon_or_partauto == 1
|
559
|
+
occ_control_reduction_factor = space_type_properties['occup_sensor_savings'].to_f
|
560
|
+
else
|
561
|
+
occ_control_reduction_factor = space_type_properties['occup_sensor_auto_on_svgs'].to_f
|
562
|
+
end
|
563
|
+
end
|
564
|
+
# add calculated occupancy control credit for later ltg schedule adjustment
|
565
|
+
space.additionalProperties.setFeature('occ_control_credit', occ_control_reduction_factor)
|
566
|
+
return space_lighting_per_area
|
567
|
+
end
|
568
|
+
|
569
|
+
# Function checks whether the user data contains lighting data
|
570
|
+
def has_user_lpd_values(user_space_data)
|
571
|
+
user_space_data.each do |user_data|
|
572
|
+
if user_data.key?('num_std_ltg_types') && user_data['num_std_ltg_types'].to_f > 0
|
573
|
+
return true
|
574
|
+
end
|
575
|
+
end
|
576
|
+
return false
|
577
|
+
end
|
578
|
+
|
579
|
+
# Function checks whether there are multi lpd values in the space type
|
580
|
+
# multi-lpd value means there are multiple spaces and the lighting_per_length > 0
|
581
|
+
def has_multi_lpd_values_space_type(space_type)
|
582
|
+
space_type_properties = interior_lighting_get_prm_data(space_type)
|
583
|
+
lighting_per_length = space_type_properties['w/ft'].to_f
|
584
|
+
return space_type.spaces.size > 1 && lighting_per_length > 0
|
585
|
+
end
|
586
|
+
|
587
|
+
# Function checks whether there are multi lpd values in the space type from user's data
|
588
|
+
# The sum of each space fraction in the user_data is assumed to be 1.0
|
589
|
+
# multi-lpd value means lighting per area > 0 and lighting_per_length > 0
|
590
|
+
def has_multi_lpd_values_user_data(user_data, space_type)
|
591
|
+
num_std_ltg_types = user_data['num_std_ltg_types'].to_i
|
592
|
+
std_ltg_index = 0 # loop index
|
593
|
+
# Loop through standard lighting type in a space
|
594
|
+
sum_lighting_per_area = 0
|
595
|
+
sum_lighting_per_length = 0
|
596
|
+
while std_ltg_index < num_std_ltg_types
|
597
|
+
# Retrieve data from user_data
|
598
|
+
type_key = format('std_ltg_type%02d', (std_ltg_index + 1))
|
599
|
+
sub_space_type = user_data[type_key]
|
600
|
+
# Adjust while loop condition factors
|
601
|
+
std_ltg_index += 1
|
602
|
+
# get interior lighting data
|
603
|
+
sub_space_type_properties = interior_lighting_get_prm_data(sub_space_type)
|
604
|
+
# Assign data
|
605
|
+
lighting_per_length = sub_space_type_properties['w/ft'].to_f
|
606
|
+
sum_lighting_per_length += lighting_per_length
|
607
|
+
end
|
608
|
+
return space_type.spaces.size > 1 && sum_lighting_per_length > 0
|
609
|
+
end
|
610
|
+
|
611
|
+
# Calculate the lighting power density per area based on user data (space_based)
|
612
|
+
# The function will calculate the LPD based on the space type (STRING)
|
613
|
+
# It considers lighting per area, lighting per length as well as occupancy factors in the database.
|
614
|
+
# The sum of each space fraction in the user_data is assumed to be 1.0
|
615
|
+
# @param user_data [Hash] user data from the user csv
|
616
|
+
# @param space [OpenStudio::Model::Space]
|
617
|
+
def calculate_lpd_from_userdata(user_data, space)
|
618
|
+
num_std_ltg_types = user_data['num_std_ltg_types'].to_i
|
619
|
+
space_lighting_per_area = 0.0
|
620
|
+
occupancy_control_credit_sum = 0.0
|
621
|
+
std_ltg_index = 0 # loop index
|
622
|
+
# Loop through standard lighting type in a space
|
623
|
+
while std_ltg_index < num_std_ltg_types
|
624
|
+
# Retrieve data from user_data
|
625
|
+
type_key = format('std_ltg_type%02d', (std_ltg_index + 1))
|
626
|
+
frac_key = format('std_ltg_type_frac%02d', (std_ltg_index + 1))
|
627
|
+
sub_space_type = user_data[type_key]
|
628
|
+
sub_space_type_frac = user_data[frac_key].to_f
|
629
|
+
# Adjust while loop condition factors
|
630
|
+
std_ltg_index += 1
|
631
|
+
# get interior lighting data
|
632
|
+
sub_space_type_properties = interior_lighting_get_prm_data(sub_space_type)
|
633
|
+
# Assign data
|
634
|
+
lights_have_info = false
|
635
|
+
lighting_per_area = sub_space_type_properties['w/ft^2'].to_f
|
636
|
+
lighting_per_length = sub_space_type_properties['w/ft'].to_f
|
637
|
+
lights_have_info = true unless lighting_per_area.zero? && lighting_per_length.zero?
|
638
|
+
manon_or_partauto = sub_space_type_properties['manon_or_partauto'].to_i
|
639
|
+
|
640
|
+
if lights_have_info
|
641
|
+
# Space height
|
642
|
+
space_volume = space.volume
|
643
|
+
space_area = space.floorArea
|
644
|
+
space_height = OpenStudio.convert(space_volume / space_area, 'm', 'ft').get
|
645
|
+
# calculate and add new lpd values
|
646
|
+
user_space_type_lighting_per_area = (lighting_per_length * space_height +
|
647
|
+
lighting_per_area) * sub_space_type_frac
|
648
|
+
space_lighting_per_area += user_space_type_lighting_per_area
|
649
|
+
|
650
|
+
# Adjust the occupancy control sensor reduction factor from dataset
|
651
|
+
occ_control_reduction_factor = 0.0
|
652
|
+
if manon_or_partauto == 1
|
653
|
+
occ_control_reduction_factor = sub_space_type_properties['occup_sensor_savings'].to_f
|
654
|
+
else
|
655
|
+
occ_control_reduction_factor = sub_space_type_properties['occup_sensor_auto_on_svgs'].to_f
|
656
|
+
end
|
657
|
+
# Now calculate the occupancy control credit factor (weighted by frac_lpd)
|
658
|
+
occupancy_control_credit_sum += occ_control_reduction_factor * user_space_type_lighting_per_area
|
659
|
+
end
|
660
|
+
end
|
661
|
+
# add calculated occupancy control credit for later ltg schedule adjustment
|
662
|
+
# If space_lighting_per_area = 0, it means there is no lights_have_info, and subsequently, the occupancy_control_credit_sum should be 0
|
663
|
+
space.additionalProperties.setFeature('occ_control_credit', space_lighting_per_area > 0 ? occupancy_control_credit_sum / space_lighting_per_area : occupancy_control_credit_sum)
|
664
|
+
return space_lighting_per_area
|
665
|
+
end
|
666
|
+
end
|