openstudio-standards 0.4.0 → 0.5.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/data/inventory/thermal_bridging.csv +90 -0
- data/data/standards/OpenStudio_Standards-deer-comstock.xlsx +0 -0
- data/data/standards/manage_OpenStudio_Standards.rb +1 -1
- data/data/standards/test_performance_expected_dd_results.csv +2014 -1891
- data/lib/openstudio-standards/btap/analysis.rb +8 -8
- data/lib/openstudio-standards/btap/bridging.rb +664 -645
- data/lib/openstudio-standards/btap/btap.model.rb +14 -14
- data/lib/openstudio-standards/btap/btap.rb +7 -7
- data/lib/openstudio-standards/btap/btap_result.rb +1 -1
- data/lib/openstudio-standards/btap/economics.rb +23 -23
- data/lib/openstudio-standards/btap/envelope.rb +8 -8
- data/lib/openstudio-standards/btap/equest.rb +1 -1
- data/lib/openstudio-standards/btap/geometry.rb +2 -2
- data/lib/openstudio-standards/btap/mpc.rb +7 -7
- data/lib/openstudio-standards/btap/schedules.rb +1 -1
- data/lib/openstudio-standards/btap/simmanager.rb +4 -4
- data/lib/openstudio-standards/btap/spaceloads.rb +26 -26
- data/lib/openstudio-standards/btap/utilities.rb +6 -6
- data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
- data/lib/openstudio-standards/constructions/information.rb +83 -0
- data/lib/openstudio-standards/constructions/materials/modify.rb +72 -0
- data/lib/openstudio-standards/constructions/modify.rb +80 -0
- data/lib/openstudio-standards/create_typical/create_typical.rb +983 -0
- data/lib/openstudio-standards/create_typical/enumerations.rb +484 -0
- data/lib/openstudio-standards/create_typical/space_type_blend.rb +791 -0
- data/lib/openstudio-standards/create_typical/space_type_ratios.rb +494 -0
- data/lib/openstudio-standards/daylighting/space.rb +47 -0
- data/lib/openstudio-standards/geometry/create.rb +801 -0
- data/lib/openstudio-standards/geometry/create_bar.rb +2171 -0
- data/lib/openstudio-standards/geometry/information.rb +462 -0
- data/lib/openstudio-standards/geometry/modify.rb +48 -0
- data/lib/openstudio-standards/hvac/air_loop/information.rb +79 -0
- data/lib/openstudio-standards/hvac/cbecs_hvac.rb +616 -0
- data/lib/openstudio-standards/hvac/setpoint_managers/information.rb +91 -0
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Model.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +2 -2
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.hvac_systems.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +4 -36
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.hvac_systems.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +4 -36
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +3 -3
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.elevators.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.CoilHeatingGas.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.elevators.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +7 -7
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Courthouse.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.FullServiceRestaurant.rb +14 -14
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.HighRiseApartment.rb +9 -9
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +16 -16
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +7 -7
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterHighITE.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterLowITE.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +11 -11
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +7 -7
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOfficeDetailed.rb +9 -9
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOfficeDetailed.rb +11 -11
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MidriseApartment.rb +9 -9
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Outpatient.rb +19 -19
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +10 -10
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.QuickServiceRestaurant.rb +13 -13
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStandalone.rb +6 -6
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStripmall.rb +6 -6
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +9 -9
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterHighITE.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterLowITE.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallHotel.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOffice.rb +8 -8
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOfficeDetailed.rb +11 -11
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperMarket.rb +10 -10
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +19 -19
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +18 -18
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Warehouse.rb +6 -6
- data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +957 -957
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirConditionerVariableRefrigerantFlow.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +84 -16
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingDXSingleSpeed.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingGas.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +61 -10
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.ControllerWaterCoil.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoolingTower.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanConstantVolume.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanOnOff.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanZoneExhaust.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.HeatExchangerAirToAirSensibleAndLatent.rb +2 -2
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +4 -4
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +4 -4
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +43 -30
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.swh.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +18 -11
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +774 -117
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.radiant_system_controls.rb +340 -481
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +3 -3
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +3 -3
- data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +22 -22
- data/lib/openstudio-standards/prototypes/deer/deer.Model.rb +1 -1
- data/lib/openstudio-standards/qaqc/calibration.rb +131 -0
- data/lib/openstudio-standards/qaqc/create_results.rb +983 -0
- data/lib/openstudio-standards/qaqc/envelope.rb +399 -0
- data/lib/openstudio-standards/qaqc/eui.rb +213 -0
- data/lib/openstudio-standards/qaqc/hvac.rb +1943 -0
- data/lib/openstudio-standards/qaqc/internal_loads.rb +568 -0
- data/lib/openstudio-standards/qaqc/reporting.rb +141 -0
- data/lib/openstudio-standards/qaqc/schedules.rb +129 -0
- data/lib/openstudio-standards/qaqc/service_water_heating.rb +273 -0
- data/lib/openstudio-standards/qaqc/weather_files.rb +497 -0
- data/lib/openstudio-standards/qaqc/zone_conditions.rb +278 -0
- data/lib/openstudio-standards/schedules/create.rb +364 -0
- data/lib/openstudio-standards/schedules/information.rb +169 -0
- data/lib/openstudio-standards/schedules/modify.rb +445 -0
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +110 -71
- data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +3 -3
- data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +4 -4
- data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +2 -1
- data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +16 -10
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +4 -4
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoilDX.rb +4 -4
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +5 -5
- data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoilHeatingWaterToAirHeatPumpEquationFit.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.Construction.rb +17 -18
- data/lib/openstudio-standards/standards/Standards.CoolingTower.rb +6 -6
- data/lib/openstudio-standards/standards/Standards.CoolingTowerSingleSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoolingTowerTwoSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.CoolingTowerVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.Fan.rb +6 -12
- data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.FluidCooler.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +3 -3
- data/lib/openstudio-standards/standards/Standards.Model.rb +411 -261
- data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +94 -29
- data/lib/openstudio-standards/standards/Standards.Pump.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +14 -14
- data/lib/openstudio-standards/standards/Standards.Space.rb +37 -30
- data/lib/openstudio-standards/standards/Standards.SpaceType.rb +38 -29
- data/lib/openstudio-standards/standards/Standards.SubSurface.rb +7 -7
- data/lib/openstudio-standards/standards/Standards.Surface.rb +13 -13
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +109 -66
- data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +11 -4
- data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +6 -6
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Space.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.Space.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirLoopHVAC.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Space.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirLoopHVAC.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.CoolingTowerVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +5 -21
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Space.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.WaterHeaterMixed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.ZoneHVACComponent.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirLoopHVAC.rb +36 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.CoolingTowerVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Space.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.ZoneHVACComponent.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/comstock_ashrae_90_1_2016.AirLoopHVAC.rb +26 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +53 -10
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +6 -6
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/comstock_ashrae_90_1_2019.AirLoopHVAC.rb +26 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.curves.json +211 -211
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.economizers.json +14 -14
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.PlantLoop.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.economizers.json +14 -14
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.PlantLoop.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +6 -6
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.CoolingTowerVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.PlantLoop.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.Space.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirLoopHVAC.rb +6 -6
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.CoolingTowerVariableSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.PlantLoop.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Space.rb +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +22 -28
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +1 -74
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +7 -59
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +1 -21
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.DesignSpecificationOutdoorAir.rb +101 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +643 -526
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +8 -2
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +17 -77
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +74 -16
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +96 -44
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +6 -6
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +18 -6
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +328 -74
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +0 -118
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +2 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_rejection.json +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_outdoor_air.md +35 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +228 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_enums.rb +131 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -1
- data/lib/openstudio-standards/standards/cbes/cbes.AirLoopHVAC.rb +5 -5
- data/lib/openstudio-standards/standards/cbes/cbes.Model.rb +1 -1
- data/lib/openstudio-standards/standards/cbes/cbes.PlantLoop.rb +1 -1
- data/lib/openstudio-standards/standards/cbes/cbes.Space.rb +1 -1
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/cbes_t24_2005.Space.rb +1 -1
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/cbes_t24_2008.Space.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb +109 -27
- data/lib/openstudio-standards/standards/deer/deer.Space.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_1985/data/deer_1985.economizers.json +246 -4
- data/lib/openstudio-standards/standards/deer/deer_1996/data/deer_1996.economizers.json +246 -4
- data/lib/openstudio-standards/standards/deer/deer_2003/data/deer_2003.economizers.json +246 -4
- data/lib/openstudio-standards/standards/deer/deer_2003/deer_2003.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2007/data/deer_2007.economizers.json +246 -4
- data/lib/openstudio-standards/standards/deer/deer_2007/deer_2007.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2011/data/deer_2011.economizers.json +246 -4
- data/lib/openstudio-standards/standards/deer/deer_2011/deer_2011.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2014/data/deer_2014.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2015/data/deer_2015.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2017/data/deer_2017.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2020/data/deer_2020.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.AirLoopHVAC.rb +18 -5
- data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.ThermalZone.rb +18 -18
- data/lib/openstudio-standards/standards/deer/deer_2025/data/deer_2025.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.heat_pumps.json +2 -2
- data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2035/data/deer_2035.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2040/data/deer_2040.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2045/data/deer_2045.economizers.json +260 -0
- data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2050/data/deer_2050.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2055/data/deer_2055.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2060/data/deer_2060.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2065/data/deer_2065.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2070/data/deer_2070.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2075/data/deer_2075.economizers.json +248 -6
- data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.FanVariableVolume.rb +1 -1
- data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.Space.rb +3 -3
- data/lib/openstudio-standards/standards/deer/deer_pre_1975/data/deer_pre_1975.economizers.json +246 -4
- data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/data/space_types.json +447 -223
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/building_envelope.rb +1 -1
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/data/space_types.json +447 -223
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +5 -2
- data/lib/openstudio-standards/standards/necb/ECMS/data/chiller_types.json +25 -0
- data/lib/openstudio-standards/standards/necb/ECMS/data/chillers.json +44 -0
- data/lib/openstudio-standards/standards/necb/ECMS/data/curves.json +225 -0
- data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +2 -2
- data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +193 -73
- data/lib/openstudio-standards/standards/necb/ECMS/pv_ground.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +10 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/beps_compliance_path.rb +7 -7
- data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +4 -5
- data/lib/openstudio-standards/standards/necb/NECB2011/data/chiller_types.json +32 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/chillers.json +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +36 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -7
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +47587 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +49764 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Warehouse.osm +283 -297
- data/lib/openstudio-standards/standards/necb/NECB2011/data/space_type_unit_definitions.txt +2 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +447 -223
- data/lib/openstudio-standards/standards/necb/NECB2011/data/standards_data.rb +3 -3
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +49 -27
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +400 -202
- data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +4 -4
- data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +637 -318
- data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +18 -1
- data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +3 -3
- data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +637 -318
- data/lib/openstudio-standards/standards/necb/NECB2017/hvac_systems.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +3 -3
- data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +615 -307
- data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +4 -4
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +10 -5
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +1 -1
- data/lib/openstudio-standards/utilities/assertion.rb +128 -0
- data/lib/openstudio-standards/utilities/logging.rb +2 -3
- data/lib/openstudio-standards/utilities/object_info.rb +39 -18
- data/lib/openstudio-standards/utilities/schedule_translator.rb +8 -6
- data/lib/openstudio-standards/utilities/simulation.rb +24 -11
- data/lib/openstudio-standards/utilities/sqlfile.rb +10 -5
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards/weather/Weather.Model.rb +8 -9
- data/lib/openstudio-standards/weather/Weather.stat_file.rb +3 -3
- data/lib/openstudio-standards/weather/information.rb +35 -0
- data/lib/openstudio-standards.rb +69 -5
- metadata +52 -16
- data/data/standards/OpenStudio_Standards-deer-ALL-comstock(space_types).xlsx +0 -0
- data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVAC.rb +0 -59
- data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingWater.rb +0 -13
- data/lib/openstudio-standards/hvac_sizing/Siz.HVACComponent.rb +0 -36
- data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +0 -898
- data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +0 -126
- data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +0 -356
- data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.Model.rb +0 -35
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +0 -110
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +0 -5
|
@@ -1,25 +1,10 @@
|
|
|
1
1
|
class ASHRAE901PRM < Standard
|
|
2
2
|
# @!group Model
|
|
3
3
|
|
|
4
|
-
# Determines
|
|
5
|
-
#
|
|
6
|
-
# @
|
|
7
|
-
|
|
8
|
-
exception_min_area_ft2 = 20_000
|
|
9
|
-
# Customization - Xcel EDA Program Manual 2014
|
|
10
|
-
# 3.2.1 Mechanical System Selection ii
|
|
11
|
-
if custom == 'Xcel Energy CO EDA'
|
|
12
|
-
exception_min_area_ft2 = 5000
|
|
13
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Customization; per Xcel EDA Program Manual 2014 3.2.1 Mechanical System Selection ii, minimum area for non-predominant conditions reduced to #{exception_min_area_ft2} ft2.")
|
|
14
|
-
end
|
|
15
|
-
exception_min_area_m2 = OpenStudio.convert(exception_min_area_ft2, 'ft^2', 'm^2').get
|
|
16
|
-
return exception_min_area_m2
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Determines which system number is used
|
|
20
|
-
# for the baseline system.
|
|
21
|
-
# @return [String] the system number: 1_or_2, 3_or_4,
|
|
22
|
-
# 5_or_6, 7_or_8, 9_or_10
|
|
4
|
+
# Determines which system number is used for the baseline system.
|
|
5
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
6
|
+
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
7
|
+
# @return [String] the system number: 1_or_2, 3_or_4, 5_or_6, 7_or_8, 9_or_10
|
|
23
8
|
def model_prm_baseline_system_number(model, climate_zone, area_type, fuel_type, area_ft2, num_stories, custom)
|
|
24
9
|
sys_num = nil
|
|
25
10
|
|
|
@@ -84,13 +69,12 @@ class ASHRAE901PRM < Standard
|
|
|
84
69
|
|
|
85
70
|
# Change the fuel type based on climate zone, depending on the standard.
|
|
86
71
|
# For 90.1-2013, fuel type is based on climate zone, not the proposed model.
|
|
72
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
73
|
+
# @param fuel_type [String] Valid choices are electric, fossil, fossilandelectric,
|
|
74
|
+
# purchasedheat, purchasedcooling, purchasedheatandcooling
|
|
75
|
+
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
87
76
|
# @return [String] the revised fuel type
|
|
88
|
-
def model_prm_baseline_system_change_fuel_type(model, fuel_type, climate_zone
|
|
89
|
-
if custom == 'Xcel Energy CO EDA'
|
|
90
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', 'Custom; per Xcel EDA Program Manual 2014 Table 3.2.2 Baseline HVAC System Types, the 90.1-2010 rules for heating fuel type (based on proposed model) rules apply.')
|
|
91
|
-
return fuel_type
|
|
92
|
-
end
|
|
93
|
-
|
|
77
|
+
def model_prm_baseline_system_change_fuel_type(model, fuel_type, climate_zone)
|
|
94
78
|
# For 90.1-2013 the fuel type is determined based on climate zone.
|
|
95
79
|
# Don't change the fuel if it purchased heating or cooling.
|
|
96
80
|
if fuel_type == 'electric' || fuel_type == 'fossil'
|
|
@@ -112,31 +96,21 @@ class ASHRAE901PRM < Standard
|
|
|
112
96
|
end
|
|
113
97
|
|
|
114
98
|
# Determines the fan type used by VAV_Reheat and VAV_PFP_Boxes systems.
|
|
115
|
-
# Variable speed fan for 90.1-
|
|
99
|
+
# Variable speed fan for 90.1-2019
|
|
100
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
116
101
|
# @return [String] the fan type: TwoSpeed Fan, Variable Speed Fan
|
|
117
102
|
def model_baseline_system_vav_fan_type(model)
|
|
118
103
|
fan_type = 'Variable Speed Fan'
|
|
119
104
|
return fan_type
|
|
120
105
|
end
|
|
121
106
|
|
|
122
|
-
#
|
|
123
|
-
# space and removes the SpaceType-level infiltration objects.
|
|
107
|
+
# Calculate the building envelope area according to the 90.1 definition
|
|
124
108
|
#
|
|
125
|
-
# @
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
#
|
|
129
|
-
|
|
130
|
-
# and is appropriate for smaller, residential-type buildings."
|
|
131
|
-
# Return an error if the model does use this object
|
|
132
|
-
ela = 0
|
|
133
|
-
model.getSpaceInfiltrationEffectiveLeakageAreas.sort.each do |eff_la|
|
|
134
|
-
ela += 1
|
|
135
|
-
end
|
|
136
|
-
if ela > 0
|
|
137
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', 'The current model cannot include SpaceInfiltrationEffectiveLeakageArea. These objects cannot be used to model infiltration according to the 90.1-PRM rules.')
|
|
138
|
-
end
|
|
139
|
-
|
|
109
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
110
|
+
# @return [Double] Building envelope area in m2
|
|
111
|
+
def model_building_envelope_area(model)
|
|
112
|
+
# Get climate zone
|
|
113
|
+
climate_zone = model_standards_climate_zone(model)
|
|
140
114
|
# Get the space building envelope area
|
|
141
115
|
# According to the 90.1 definition, building envelope include:
|
|
142
116
|
# - "the elements of a building that separate conditioned spaces from the exterior"
|
|
@@ -145,7 +119,7 @@ class ASHRAE901PRM < Standard
|
|
|
145
119
|
# transferred to or from the exterior, to or from unconditioned spaces or to or
|
|
146
120
|
# from conditioned spaces."
|
|
147
121
|
building_envelope_area_m2 = 0
|
|
148
|
-
model.getSpaces.
|
|
122
|
+
model.getSpaces.each do |space|
|
|
149
123
|
building_envelope_area_m2 += space_envelope_area(space, climate_zone)
|
|
150
124
|
end
|
|
151
125
|
if building_envelope_area_m2 == 0.0
|
|
@@ -153,13 +127,39 @@ class ASHRAE901PRM < Standard
|
|
|
153
127
|
return 0.0
|
|
154
128
|
end
|
|
155
129
|
|
|
130
|
+
return building_envelope_area_m2
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# This method creates customized infiltration objects for each
|
|
134
|
+
# space and removes the SpaceType-level infiltration objects.
|
|
135
|
+
# @param model [OpenStudio::Model::Model] openstudio model
|
|
136
|
+
# @param specific_space_infiltration_rate_75_pa [Double] space infiltration rate at a pressure differential of 75 Pa
|
|
137
|
+
# @return [Boolean] true if successful, false if not
|
|
138
|
+
def model_apply_standard_infiltration(model, specific_space_infiltration_rate_75_pa = nil)
|
|
139
|
+
# Model shouldn't use SpaceInfiltrationEffectiveLeakageArea
|
|
140
|
+
# Excerpt from the EnergyPlus Input/Output reference manual:
|
|
141
|
+
# "This model is based on work by Sherman and Grimsrud (1980)
|
|
142
|
+
# and is appropriate for smaller, residential-type buildings."
|
|
143
|
+
# Raise exception if the model does use this object
|
|
144
|
+
ela = 0
|
|
145
|
+
model.getSpaceInfiltrationEffectiveLeakageAreas.sort.each do |eff_la|
|
|
146
|
+
ela += 1
|
|
147
|
+
end
|
|
148
|
+
if ela > 0
|
|
149
|
+
OpenStudio.logFree(OpenStudio::Warn, 'prm.log', 'The current model cannot include SpaceInfiltrationEffectiveLeakageArea. These objects will be skipped in modeling infiltration according to the 90.1-PRM rules.')
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Get the space building envelope area
|
|
153
|
+
building_envelope_area_m2 = model_building_envelope_area(model)
|
|
154
|
+
prm_raise(building_envelope_area_m2 > 0.0, @sizing_run_dir, 'Calculated building envelope area is 0 m2, Please check model inputs.')
|
|
155
|
+
|
|
156
156
|
# Calculate current model air leakage rate @ 75 Pa and report it
|
|
157
157
|
curr_tot_infil_m3_per_s_per_envelope_area = model_current_building_envelope_infiltration_at_75pa(model, building_envelope_area_m2)
|
|
158
|
-
OpenStudio.logFree(OpenStudio::Info, '
|
|
158
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "The model's I_75Pa is estimated to be #{curr_tot_infil_m3_per_s_per_envelope_area} m3/s per m2 of total building envelope.")
|
|
159
159
|
|
|
160
160
|
# Calculate building adjusted building envelope
|
|
161
161
|
# air infiltration following the 90.1 PRM rules
|
|
162
|
-
tot_infil_m3_per_s = model_adjusted_building_envelope_infiltration(
|
|
162
|
+
tot_infil_m3_per_s = model_adjusted_building_envelope_infiltration(building_envelope_area_m2, specific_space_infiltration_rate_75_pa)
|
|
163
163
|
|
|
164
164
|
# Find infiltration method used in the model, if any.
|
|
165
165
|
#
|
|
@@ -171,12 +171,12 @@ class ASHRAE901PRM < Standard
|
|
|
171
171
|
infil_coefficients = model_get_infiltration_coefficients(model)
|
|
172
172
|
|
|
173
173
|
# Set the infiltration rate at each space
|
|
174
|
-
model.getSpaces.
|
|
174
|
+
model.getSpaces.each do |space|
|
|
175
175
|
space_apply_infiltration_rate(space, tot_infil_m3_per_s, infil_method, infil_coefficients)
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
# Remove infiltration rates set at the space type
|
|
179
|
-
model.getSpaceTypes.
|
|
179
|
+
model.getSpaceTypes.each do |space_type|
|
|
180
180
|
space_type.spaceInfiltrationDesignFlowRates.each(&:remove)
|
|
181
181
|
end
|
|
182
182
|
|
|
@@ -184,13 +184,13 @@ class ASHRAE901PRM < Standard
|
|
|
184
184
|
end
|
|
185
185
|
|
|
186
186
|
# This method retrieves the type of infiltration input
|
|
187
|
-
# used in the model. If input is
|
|
187
|
+
# used in the model. If input is inconsistent, returns
|
|
188
188
|
# Flow/Area
|
|
189
|
-
#
|
|
189
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
190
190
|
# @return [String] infiltration input type
|
|
191
191
|
def model_get_infiltration_method(model)
|
|
192
192
|
infil_method = nil
|
|
193
|
-
model.getSpaces.
|
|
193
|
+
model.getSpaces.each do |space|
|
|
194
194
|
# Infiltration at the space level
|
|
195
195
|
unless space.spaceInfiltrationDesignFlowRates.empty?
|
|
196
196
|
old_infil = space.spaceInfiltrationDesignFlowRates[0]
|
|
@@ -221,7 +221,7 @@ class ASHRAE901PRM < Standard
|
|
|
221
221
|
# This method retrieves the infiltration coefficients
|
|
222
222
|
# used in the model. If input is inconsitent, returns
|
|
223
223
|
# [0, 0, 0.224, 0] as per PRM user manual
|
|
224
|
-
#
|
|
224
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
225
225
|
# @return [String] infiltration input type
|
|
226
226
|
def model_get_infiltration_coefficients(model)
|
|
227
227
|
cst = nil
|
|
@@ -229,7 +229,7 @@ class ASHRAE901PRM < Standard
|
|
|
229
229
|
vel = nil
|
|
230
230
|
vel_2 = nil
|
|
231
231
|
infil_coeffs = [cst, temp, vel, vel_2]
|
|
232
|
-
model.getSpaces.
|
|
232
|
+
model.getSpaces.each do |space|
|
|
233
233
|
# Infiltration at the space level
|
|
234
234
|
unless space.spaceInfiltrationDesignFlowRates.empty?
|
|
235
235
|
old_infil = space.spaceInfiltrationDesignFlowRates[0]
|
|
@@ -270,52 +270,46 @@ class ASHRAE901PRM < Standard
|
|
|
270
270
|
return infil_coeffs
|
|
271
271
|
end
|
|
272
272
|
|
|
273
|
-
# This methods calculate the
|
|
274
|
-
# It assumes that the model follows the PRM methods, see G3.1.1.4
|
|
275
|
-
# in 90.1-2019 for reference.
|
|
276
|
-
#
|
|
277
|
-
# @param [OpenStudio::Model::Model] OpenStudio Model object
|
|
278
|
-
# @param [Double] Building envelope area as per 90.1 in m^2
|
|
273
|
+
# This methods calculate the air leakage rate of a space
|
|
279
274
|
#
|
|
280
|
-
# @
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
275
|
+
# @param space [OpenStudio::Model::Space] OpenStudio Space object
|
|
276
|
+
# @return [Double] Space air leakage rate
|
|
277
|
+
def model_get_space_air_leakage(space)
|
|
278
|
+
space_air_leakage = 0
|
|
279
|
+
space_multipler = space.multiplier
|
|
280
|
+
# Infiltration at the space level
|
|
281
|
+
unless space.spaceInfiltrationDesignFlowRates.empty?
|
|
282
|
+
space.spaceInfiltrationDesignFlowRates.each do |infil_obj|
|
|
287
283
|
unless infil_obj.designFlowRate.is_initialized
|
|
288
284
|
if infil_obj.flowperSpaceFloorArea.is_initialized
|
|
289
|
-
|
|
285
|
+
space_air_leakage += infil_obj.flowperSpaceFloorArea.get * space.floorArea * space_multipler
|
|
290
286
|
elsif infil_obj.flowperExteriorSurfaceArea.is_initialized
|
|
291
|
-
|
|
287
|
+
space_air_leakage += infil_obj.flowperExteriorSurfaceArea.get * space.exteriorArea * space_multipler
|
|
292
288
|
elsif infil_obj.flowperExteriorWallArea.is_initialized
|
|
293
|
-
|
|
289
|
+
space_air_leakage += infil_obj.flowperExteriorWallArea.get * space.exteriorWallArea * space_multipler
|
|
294
290
|
elsif infil_obj.airChangesperHour.is_initialized
|
|
295
|
-
|
|
291
|
+
space_air_leakage += infil_obj.airChangesperHour.get * space.volume * space_multipler / 3600
|
|
296
292
|
end
|
|
297
293
|
end
|
|
298
294
|
end
|
|
295
|
+
end
|
|
299
296
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
end
|
|
297
|
+
return space_air_leakage
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# This methods calculate the current model air leakage rate @ 75 Pa.
|
|
301
|
+
# It assumes that the model follows the PRM methods, see G3.1.1.4
|
|
302
|
+
# in 90.1-2019 for reference.
|
|
303
|
+
#
|
|
304
|
+
# @param model [OpenStudio::Model::Model] OpenStudio Model object
|
|
305
|
+
# @param building_envelope_area_m2 [Double] Building envelope area as per 90.1 in m^2
|
|
306
|
+
# @return [Double] building model air leakage rate
|
|
307
|
+
def model_current_building_envelope_infiltration_at_75pa(model, building_envelope_area_m2)
|
|
308
|
+
bldg_air_leakage_rate = 0
|
|
309
|
+
model.getSpaces.each do |space|
|
|
310
|
+
bldg_air_leakage_rate += model_get_space_air_leakage(space)
|
|
318
311
|
end
|
|
312
|
+
|
|
319
313
|
# adjust_infiltration_to_prototype_building_conditions(1) corresponds
|
|
320
314
|
# to the 0.112 shown in G3.1.1.4
|
|
321
315
|
curr_tot_infil_m3_per_s_per_envelope_area = bldg_air_leakage_rate / adjust_infiltration_to_prototype_building_conditions(1) / building_envelope_area_m2
|
|
@@ -325,13 +319,16 @@ class ASHRAE901PRM < Standard
|
|
|
325
319
|
# This method calculates the building envelope infiltration,
|
|
326
320
|
# this approach uses the 90.1 PRM rules
|
|
327
321
|
#
|
|
328
|
-
# @
|
|
329
|
-
|
|
322
|
+
# @param building_envelope_area_m2 [Double] Building envelope area as per 90.1 in m^2
|
|
323
|
+
# @param specific_space_infiltration_rate_75_pa [Double] Specific space infiltration rate at 75 pa
|
|
324
|
+
# @return [Double] building envelope infiltration
|
|
325
|
+
def model_adjusted_building_envelope_infiltration(building_envelope_area_m2, specific_space_infiltration_rate_75_pa = nil)
|
|
330
326
|
# Determine the total building baseline infiltration rate in cfm per ft2 of the building envelope at 75 Pa
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
327
|
+
if specific_space_infiltration_rate_75_pa.nil?
|
|
328
|
+
basic_infil_rate_cfm_per_ft2 = space_infiltration_rate_75_pa
|
|
329
|
+
else
|
|
330
|
+
basic_infil_rate_cfm_per_ft2 = specific_space_infiltration_rate_75_pa
|
|
331
|
+
end
|
|
335
332
|
|
|
336
333
|
# Conversion factor
|
|
337
334
|
conv_fact = OpenStudio.convert(1, 'm^3/s', 'ft^3/min').to_f / OpenStudio.convert(1, 'm^2', 'ft^2').to_f
|
|
@@ -349,10 +346,11 @@ class ASHRAE901PRM < Standard
|
|
|
349
346
|
|
|
350
347
|
# Apply the standard construction to each surface in the model, based on the construction type currently assigned.
|
|
351
348
|
#
|
|
352
|
-
# @return [Bool] true if successful, false if not
|
|
353
349
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
354
350
|
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
355
|
-
# @
|
|
351
|
+
# @param wwr_building_type [String] building type used for defining window to wall ratio, e.g. 'Office > 50,000 sq ft'
|
|
352
|
+
# @param wwr_info [Hash] A map that maps each building area type to its correspondent wwr.
|
|
353
|
+
# @return [Boolean] returns true if successful, false if not
|
|
356
354
|
def model_apply_standard_constructions(model, climate_zone, wwr_building_type: nil, wwr_info: {})
|
|
357
355
|
types_to_modify = []
|
|
358
356
|
|
|
@@ -502,10 +500,9 @@ class ASHRAE901PRM < Standard
|
|
|
502
500
|
# Go through the default construction sets and hard-assigned constructions.
|
|
503
501
|
# Clone the existing constructions and set their intended surface type and standards construction type per the PRM.
|
|
504
502
|
# For some standards, this will involve making modifications. For others, it will not.
|
|
505
|
-
#
|
|
506
|
-
# 90.1-2007, 90.1-2010, 90.1-2013
|
|
503
|
+
# 90.1-2019
|
|
507
504
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
508
|
-
# @return [
|
|
505
|
+
# @return [Boolean] returns true if successful, false if not
|
|
509
506
|
def model_apply_prm_construction_types(model)
|
|
510
507
|
types_to_modify = []
|
|
511
508
|
|
|
@@ -581,6 +578,10 @@ class ASHRAE901PRM < Standard
|
|
|
581
578
|
types_to_modify << ['Outdoors', 'ExteriorWall', 'SteelFramed']
|
|
582
579
|
types_to_modify << ['Outdoors', 'ExteriorRoof', 'IEAD']
|
|
583
580
|
types_to_modify << ['Outdoors', 'ExteriorFloor', 'SteelFramed']
|
|
581
|
+
types_to_modify << ['Outdoors', 'ExteriorWindow', 'Any Vertical Glazing']
|
|
582
|
+
types_to_modify << ['Outdoors', 'GlassDoor', 'Any Vertical Glazing']
|
|
583
|
+
types_to_modify << ['Outdoors', 'ExteriorDoor', 'NonSwinging']
|
|
584
|
+
types_to_modify << ['Outdoors', 'ExteriorDoor', 'Swinging']
|
|
584
585
|
types_to_modify << ['Ground', 'GroundContactFloor', 'Unheated']
|
|
585
586
|
types_to_modify << ['Ground', 'GroundContactWall', 'Mass']
|
|
586
587
|
|
|
@@ -625,7 +626,8 @@ class ASHRAE901PRM < Standard
|
|
|
625
626
|
|
|
626
627
|
# Reduces the SRR to the values specified by the PRM. SRR reduction will be done by shrinking vertices toward the centroid.
|
|
627
628
|
#
|
|
628
|
-
# @param model [OpenStudio::
|
|
629
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
630
|
+
# @return [Boolean] returns true if successful, false if not
|
|
629
631
|
def model_apply_prm_baseline_skylight_to_roof_ratio(model)
|
|
630
632
|
# Loop through all spaces in the model, and
|
|
631
633
|
# per the 90.1-2019 PRM User Manual, only
|
|
@@ -707,71 +709,18 @@ class ASHRAE901PRM < Standard
|
|
|
707
709
|
# Apply baseline values to exterior lights objects
|
|
708
710
|
# Characterization of objects must be done via user data
|
|
709
711
|
#
|
|
710
|
-
# @param model [OpenStudio::
|
|
712
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
711
713
|
def model_apply_baseline_exterior_lighting(model)
|
|
712
|
-
|
|
713
|
-
return false if user_ext_lights.nil?
|
|
714
|
-
|
|
715
|
-
non_tradeable_cats = ['nontradeable_general', 'building_facades_area', 'building_facades_perim', 'automated_teller_machines_per_location', 'automated_teller_machines_per_machine', 'entries_and_gates', 'loading_areas_for_emergency_vehicles', 'drive_through_windows_and_doors', 'parking_near_24_hour_entrances', 'roadway_parking']
|
|
716
|
-
search_criteria = {
|
|
717
|
-
'template' => template
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
ext_ltg_baseline_values = standards_lookup_table_first(table_name: 'prm_exterior_lighting', search_criteria: search_criteria)
|
|
721
|
-
|
|
722
|
-
user_ext_lights.each do |user_data|
|
|
723
|
-
lights_name = user_data['name']
|
|
724
|
-
|
|
725
|
-
# model.getExteriorLightss.each do |exterior_lights|
|
|
726
|
-
|
|
727
|
-
if model.getExteriorLightsByName(lights_name).is_initialized
|
|
728
|
-
ext_lights_obj = model.getExteriorLightsByName(lights_name).get
|
|
729
|
-
else
|
|
730
|
-
# Report invalid name in user data
|
|
731
|
-
OpenStudio.logFree(OpenStudio::Warn, 'prm.log', "ExteriorLights object named #{lights_name} from user data file not found in model")
|
|
732
|
-
next
|
|
733
|
-
end
|
|
734
|
-
|
|
735
|
-
# Make sure none of the categories are nontradeable and not a mix of tradeable and nontradeable
|
|
736
|
-
num_trade = 0
|
|
737
|
-
num_notrade = 0
|
|
738
|
-
ext_ltg_cats = {}
|
|
739
|
-
num_cats = user_data['num_ext_lights_subcats'].to_i
|
|
740
|
-
(1..num_cats).each do |icat|
|
|
741
|
-
cat_key = format('end_use_subcategory_%02d', icat)
|
|
742
|
-
subcat = user_data[cat_key]
|
|
743
|
-
if non_tradeable_cats.include?(subcat)
|
|
744
|
-
num_notrade += 1
|
|
745
|
-
else
|
|
746
|
-
num_trade += 1
|
|
747
|
-
meas_val_key = format('end_use_measurement_value_%02d', icat)
|
|
748
|
-
meas_val = user_data[meas_val_key]
|
|
749
|
-
ext_ltg_cats[subcat] = meas_val.to_f
|
|
750
|
-
end
|
|
751
|
-
end
|
|
752
|
-
|
|
753
|
-
# Skip this if all lights are non-tradeable
|
|
754
|
-
next if num_trade == 0
|
|
755
|
-
|
|
756
|
-
# Error if mix of tradeable and nontradeable
|
|
757
|
-
if (num_trade > 0) && (num_notrade > 0)
|
|
758
|
-
OpenStudio.logFree(OpenStudio::Warn, 'prm.log', "ExteriorLights object named #{lights_name} from user data file has mix of tradeable and non-tradeable lighting types. All will be treated as non-tradeable.")
|
|
759
|
-
next
|
|
760
|
-
end
|
|
761
|
-
|
|
762
|
-
ext_ltg_pwr = 0
|
|
763
|
-
ext_ltg_cats.each do |cat_key, meas_val|
|
|
764
|
-
# Get baseline power for this type of exterior lighting
|
|
765
|
-
baseline_value = ext_ltg_baseline_values[cat_key].to_f
|
|
766
|
-
ext_ltg_pwr += baseline_value * meas_val
|
|
767
|
-
end
|
|
768
|
-
|
|
714
|
+
model.getExteriorLightss.each do |ext_lights_obj|
|
|
769
715
|
# Update existing exterior lights object: control, schedule, power
|
|
770
716
|
ext_lights_obj.setControlOption('AstronomicalClock')
|
|
771
717
|
ext_lights_obj.setSchedule(model.alwaysOnDiscreteSchedule)
|
|
772
718
|
ext_lights_obj.setMultiplier(1)
|
|
773
719
|
ext_lights_def = ext_lights_obj.exteriorLightsDefinition
|
|
774
|
-
|
|
720
|
+
ext_ltg_pwr = get_additional_property_as_double(ext_lights_obj, 'design_level', 0.0)
|
|
721
|
+
if ext_ltg_pwr > 0.0
|
|
722
|
+
ext_lights_def.setDesignLevel(ext_ltg_pwr)
|
|
723
|
+
end
|
|
775
724
|
end
|
|
776
725
|
end
|
|
777
726
|
|
|
@@ -779,20 +728,19 @@ class ASHRAE901PRM < Standard
|
|
|
779
728
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
780
729
|
def model_add_prm_elevators(model)
|
|
781
730
|
# Load elevator data from userdata csv files
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
if number_of_levels < 5
|
|
731
|
+
equipment_array = model.getElectricEquipments + model.getExteriorFuelEquipments
|
|
732
|
+
equipment_array.each do |equipment|
|
|
733
|
+
elevator_number_of_lifts = get_additional_property_as_integer(equipment, 'elevator_number_of_lifts', 0)
|
|
734
|
+
next unless elevator_number_of_lifts > 0.0
|
|
735
|
+
|
|
736
|
+
elevator_name = equipment.name.get
|
|
737
|
+
elevator_number_of_stories = get_additional_property_as_integer(equipment, 'elevator_number_of_stories', 0)
|
|
738
|
+
elevator_weight_of_car = get_additional_property_as_double(equipment, 'elevator_weight_of_car', 0.0)
|
|
739
|
+
elevator_rated_load = get_additional_property_as_double(equipment, 'elevator_rated_load', 0.0)
|
|
740
|
+
elevator_speed_of_car = get_additional_property_as_double(equipment, 'elevator_speed_of_car', 0.0)
|
|
741
|
+
elevator_counter_weight_of_car = get_additional_property_as_double(equipment, 'elevator_counter_weight_of_car', 0.0)
|
|
742
|
+
|
|
743
|
+
if elevator_number_of_stories < 5
|
|
796
744
|
# From Table G3.9.2 performance rating method baseline elevator motor
|
|
797
745
|
elevator_mech_eff = 0.58
|
|
798
746
|
elevator_counter_weight_of_car = 0.0
|
|
@@ -804,29 +752,23 @@ class ASHRAE901PRM < Standard
|
|
|
804
752
|
# From Table G3.9.2 performance rating method baseline elevator motor
|
|
805
753
|
elevator_mech_eff = 0.64
|
|
806
754
|
# Determine the elevator counterweight
|
|
807
|
-
if
|
|
755
|
+
if elevator_counter_weight_of_car == 0.0
|
|
808
756
|
# When the proposed design counterweight is not specified
|
|
809
757
|
# it is determined as per Table G3.9.2
|
|
810
758
|
elevator_counter_weight_of_car = elevator_weight_of_car + 0.4 * elevator_rated_load
|
|
811
|
-
else
|
|
812
|
-
elevator_counter_weight_of_car = user_elevator['elevator_counter_weight_of_car'].to_f
|
|
813
759
|
end
|
|
814
760
|
search_criteria = {
|
|
815
761
|
'template' => template,
|
|
816
762
|
'type' => 'Any'
|
|
817
763
|
}
|
|
818
764
|
end
|
|
819
|
-
|
|
820
|
-
elevator_motor_bhp = (elevator_weight_of_car + elevator_rated_load - elevator_counter_weight_of_car) * elevator_speed_of_car / (33000 * elevator_mech_eff)
|
|
821
|
-
|
|
822
|
-
# Lookup the minimum motor efficiency
|
|
765
|
+
elevator_motor_bhp = (elevator_weight_of_car + elevator_rated_load - elevator_counter_weight_of_car) * elevator_speed_of_car / (33000 * elevator_mech_eff) # Lookup the minimum motor efficiency
|
|
823
766
|
elevator_motor_eff = standards_data['motors']
|
|
824
767
|
motor_properties = model_find_object(elevator_motor_eff, search_criteria, nil, nil, nil, nil, elevator_motor_bhp)
|
|
825
768
|
if motor_properties.nil?
|
|
826
|
-
OpenStudio.logFree(OpenStudio::Error, '
|
|
769
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{elevator_name}, could not find motor properties using search criteria: #{search_criteria}, motor_bhp = #{elevator_motor_bhp} hp.")
|
|
827
770
|
return false
|
|
828
771
|
end
|
|
829
|
-
|
|
830
772
|
nominal_hp = motor_properties['maximum_capacity'].to_f.round(1)
|
|
831
773
|
# Round to nearest whole HP for niceness
|
|
832
774
|
if nominal_hp >= 2
|
|
@@ -837,33 +779,28 @@ class ASHRAE901PRM < Standard
|
|
|
837
779
|
# Add 0.01 hp to avoid search errors.
|
|
838
780
|
motor_properties = model_find_object(elevator_motor_eff, search_criteria, nil, nil, nil, nil, nominal_hp + 0.01)
|
|
839
781
|
if motor_properties.nil?
|
|
840
|
-
OpenStudio.logFree(OpenStudio::Error, '
|
|
782
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{elevator_name}, could not find nominal motor properties using search criteria: #{search_criteria}, motor_hp = #{nominal_hp} hp.")
|
|
841
783
|
return false
|
|
842
784
|
end
|
|
843
785
|
motor_eff = motor_properties['nominal_full_load_efficiency'].to_f
|
|
844
|
-
elevator_power =
|
|
786
|
+
elevator_power = elevator_number_of_lifts * elevator_motor_bhp * 746 / motor_eff
|
|
845
787
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
elevator_space = model.getElectricEquipmentByName(equip_name).get.space.get
|
|
851
|
-
end
|
|
852
|
-
if model.getExteriorFuelEquipmentByName(equip_name).is_initialized
|
|
853
|
-
model.getExteriorFuelEquipmentByName(equip_name).exteriorFuelEquipmentDefinition.setDesignLevel(elevator_power)
|
|
854
|
-
elevator_space = model.getElectricEquipmentByName(equip_name).get.space.get
|
|
788
|
+
if equipment.is_a?(OpenStudio::Model::ElectricEquipment)
|
|
789
|
+
equipment.electricEquipmentDefinition.setDesignLevel(elevator_power)
|
|
790
|
+
else
|
|
791
|
+
equipment.exteriorFuelEquipmentDefinition.setDesignLevel(elevator_power)
|
|
855
792
|
end
|
|
856
|
-
|
|
793
|
+
elevator_space = prm_get_optional_handler(equipment, @sizing_run_dir, 'space')
|
|
857
794
|
# Add ventilation and lighting process loads if modeled in the proposed model
|
|
858
795
|
misc_elevator_process_loads = 0.0
|
|
859
|
-
misc_elevator_process_loads +=
|
|
860
|
-
misc_elevator_process_loads +=
|
|
796
|
+
misc_elevator_process_loads += get_additional_property_as_double(equipment, 'elevator_ventilation_cfm', 0.0) * 0.33
|
|
797
|
+
misc_elevator_process_loads += get_additional_property_as_double(equipment, 'elevator_area_ft2', 0.0) * 3.14
|
|
861
798
|
if misc_elevator_process_loads > 0
|
|
862
799
|
misc_elevator_process_loads_def = OpenStudio::Model::ElectricEquipmentDefinition.new(model)
|
|
863
|
-
misc_elevator_process_loads_def.setName("#{
|
|
800
|
+
misc_elevator_process_loads_def.setName("#{elevator_name} - Misc Process Loads - Def")
|
|
864
801
|
misc_elevator_process_loads_def.setDesignLevel(misc_elevator_process_loads)
|
|
865
802
|
misc_elevator_process_loads = OpenStudio::Model::ElectricEquipment.new(misc_elevator_process_loads_def)
|
|
866
|
-
misc_elevator_process_loads.setName("#{
|
|
803
|
+
misc_elevator_process_loads.setName("#{elevator_name} - Misc Process Loads")
|
|
867
804
|
misc_elevator_process_loads.setEndUseSubcategory('Elevators')
|
|
868
805
|
misc_elevator_process_loads.setSchedule(model.alwaysOnDiscreteSchedule)
|
|
869
806
|
misc_elevator_process_loads.setSpace(elevator_space)
|
|
@@ -873,20 +810,13 @@ class ASHRAE901PRM < Standard
|
|
|
873
810
|
|
|
874
811
|
# Add design day schedule objects for space loads, for PRM 2019 baseline models
|
|
875
812
|
# @author Xuechen (Jerry) Lei, PNNL
|
|
876
|
-
# @param model [OpenStudio::
|
|
877
|
-
#
|
|
813
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
878
814
|
def model_apply_prm_baseline_sizing_schedule(model)
|
|
879
815
|
space_loads = model.getSpaceLoads
|
|
880
816
|
loads = []
|
|
881
817
|
space_loads.sort.each do |space_load|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if space_load.respond_to?(casting_method_name)
|
|
885
|
-
casted_load = space_load.public_send(casting_method_name).get
|
|
886
|
-
loads << casted_load
|
|
887
|
-
else
|
|
888
|
-
p 'Need Debug, casting method not found @JXL'
|
|
889
|
-
end
|
|
818
|
+
casted_load = model_cast_model_object(space_load)
|
|
819
|
+
loads << casted_load unless casted_load.nil?
|
|
890
820
|
end
|
|
891
821
|
|
|
892
822
|
load_schedule_name_hash = {
|
|
@@ -966,40 +896,31 @@ class ASHRAE901PRM < Standard
|
|
|
966
896
|
# @note This is not applicable to the stable baseline; hence no action in this method
|
|
967
897
|
#
|
|
968
898
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
969
|
-
# @return [
|
|
899
|
+
# @return [Boolean] returns true if successful, false if not
|
|
970
900
|
def model_apply_multizone_vav_outdoor_air_sizing(model)
|
|
971
901
|
return true
|
|
972
902
|
end
|
|
973
903
|
|
|
974
904
|
# Identifies non mechanically cooled ("nmc") systems, if applicable
|
|
905
|
+
# and add a flag to the zone's and air loop's additional properties.
|
|
906
|
+
# @todo Zone-level evaporative cooler is not currently supported
|
|
907
|
+
# by OpenStudio, will need to be added to the method when supported.
|
|
975
908
|
#
|
|
976
|
-
#
|
|
977
|
-
#
|
|
978
|
-
# supported.
|
|
979
|
-
#
|
|
980
|
-
# @param model [OpenStudio::model::Model] OpenStudio model object
|
|
981
|
-
# @return zone_nmc_sys_type [Hash] Zone to nmc system type mapping
|
|
909
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
910
|
+
# @return [Hash] Zone to nmc system type mapping
|
|
982
911
|
def model_identify_non_mechanically_cooled_systems(model)
|
|
983
912
|
# Iterate through zones to find out if they are served by nmc systems
|
|
984
|
-
model.getThermalZones.
|
|
913
|
+
model.getThermalZones.each do |zone|
|
|
985
914
|
# Check if airloop has economizer and either:
|
|
986
915
|
# - No cooling coil and/or,
|
|
987
916
|
# - An evaporative cooling coil
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
air_loop
|
|
994
|
-
|
|
995
|
-
air_loop_hvac_include_evaporative_cooler?(air_loop)) ||
|
|
996
|
-
(!air_loop_hvac_include_cooling_coil?(air_loop) &&
|
|
997
|
-
air_loop_hvac_include_economizer?(air_loop))
|
|
998
|
-
air_loop.additionalProperties.setFeature('non_mechanically_cooled', true)
|
|
999
|
-
air_loop.thermalZones.each do |thermal_zone|
|
|
1000
|
-
thermal_zone.additionalProperties.setFeature('non_mechanically_cooled', true)
|
|
1001
|
-
end
|
|
1002
|
-
end
|
|
917
|
+
zone.airLoopHVACs.each do |air_loop|
|
|
918
|
+
if (!air_loop_hvac_include_cooling_coil?(air_loop) &&
|
|
919
|
+
air_loop_hvac_include_evaporative_cooler?(air_loop)) ||
|
|
920
|
+
(!air_loop_hvac_include_cooling_coil?(air_loop) &&
|
|
921
|
+
air_loop_hvac_include_economizer?(air_loop))
|
|
922
|
+
air_loop.additionalProperties.setFeature('non_mechanically_cooled', true)
|
|
923
|
+
zone.additionalProperties.setFeature('non_mechanically_cooled', true)
|
|
1003
924
|
end
|
|
1004
925
|
end
|
|
1005
926
|
end
|
|
@@ -1008,7 +929,6 @@ class ASHRAE901PRM < Standard
|
|
|
1008
929
|
# Specify supply air temperature setpoint for unit heaters based on 90.1 Appendix G G3.1.2.8.2
|
|
1009
930
|
#
|
|
1010
931
|
# @param thermal_zone [OpenStudio::Model::ThermalZone] OpenStudio ThermalZone Object
|
|
1011
|
-
#
|
|
1012
932
|
# @return [Double] for zone with unit heaters, return design supply temperature; otherwise, return nil
|
|
1013
933
|
def thermal_zone_prm_unitheater_design_supply_temperature(thermal_zone)
|
|
1014
934
|
thermal_zone.equipment.each do |eqt|
|
|
@@ -1022,7 +942,6 @@ class ASHRAE901PRM < Standard
|
|
|
1022
942
|
# Specify supply to room delta for laboratory spaces based on 90.1 Appendix G Exception to G3.1.2.8.1
|
|
1023
943
|
#
|
|
1024
944
|
# @param thermal_zone [OpenStudio::Model::ThermalZone] OpenStudio ThermalZone Object
|
|
1025
|
-
#
|
|
1026
945
|
# @return [Double] for zone with laboratory space, return 17; otherwise, return nil
|
|
1027
946
|
def thermal_zone_prm_lab_delta_t(thermal_zone)
|
|
1028
947
|
# For labs, add 17 delta-T; otherwise, add 20 delta-T
|
|
@@ -1046,9 +965,10 @@ class ASHRAE901PRM < Standard
|
|
|
1046
965
|
# Applies the HVAC parts of the template to all objects in the model using the the template specified in the model.
|
|
1047
966
|
#
|
|
1048
967
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
1049
|
-
# @param
|
|
968
|
+
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
969
|
+
# @param apply_controls [Boolean] toggle whether to apply air loop and plant loop controls
|
|
1050
970
|
# @param sql_db_vars_map [Hash] hash map
|
|
1051
|
-
# @return [
|
|
971
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1052
972
|
def model_apply_hvac_efficiency_standard(model, climate_zone, apply_controls: true, sql_db_vars_map: nil)
|
|
1053
973
|
sql_db_vars_map = {} if sql_db_vars_map.nil?
|
|
1054
974
|
|
|
@@ -1067,7 +987,7 @@ class ASHRAE901PRM < Standard
|
|
|
1067
987
|
# Zone HVAC Controls
|
|
1068
988
|
model.getZoneHVACComponents.sort.each { |obj| zone_hvac_component_apply_standard_controls(obj) }
|
|
1069
989
|
|
|
1070
|
-
#
|
|
990
|
+
# @todo The fan and pump efficiency will be done by another task.
|
|
1071
991
|
# Fans
|
|
1072
992
|
# model.getFanVariableVolumes.sort.each { |obj| fan_apply_standard_minimum_motor_efficiency(obj, fan_brake_horsepower(obj)) }
|
|
1073
993
|
# model.getFanConstantVolumes.sort.each { |obj| fan_apply_standard_minimum_motor_efficiency(obj, fan_brake_horsepower(obj)) }
|
|
@@ -1147,6 +1067,12 @@ class ASHRAE901PRM < Standard
|
|
|
1147
1067
|
return true
|
|
1148
1068
|
end
|
|
1149
1069
|
|
|
1070
|
+
# This function returns the cooling dx coil efficiency and curve coefficient in a Hashmap.
|
|
1071
|
+
#
|
|
1072
|
+
# @param cooling_coil [OpenStudio::Model::ModeObject]
|
|
1073
|
+
# @param sql_db_vars_map [Hash] hash map
|
|
1074
|
+
# @param sys_type [String] baseline system type string
|
|
1075
|
+
# @return [Hash] sql_db_vars_map
|
|
1150
1076
|
def set_coil_cooling_efficiency_and_curves(cooling_coil, sql_db_vars_map, sys_type)
|
|
1151
1077
|
if cooling_coil.to_CoilCoolingDXSingleSpeed.is_initialized
|
|
1152
1078
|
# single speed coil
|
|
@@ -1161,6 +1087,12 @@ class ASHRAE901PRM < Standard
|
|
|
1161
1087
|
return sql_db_vars_map
|
|
1162
1088
|
end
|
|
1163
1089
|
|
|
1090
|
+
# This function returns the heating dx coil efficiency and curve coefficient in a Hashmap.
|
|
1091
|
+
#
|
|
1092
|
+
# @param heating_coil [OpenStudio::Model::ModeObject]
|
|
1093
|
+
# @param sql_db_vars_map [Hash] hash map
|
|
1094
|
+
# @param sys_type [String] baseline system type string
|
|
1095
|
+
# @return [Hash] the hashmap contains the heating efficiency and curve coefficient for the heating_coil
|
|
1164
1096
|
def set_coil_heating_efficiency_and_curves(heating_coil, sql_db_vars_map, sys_type)
|
|
1165
1097
|
if heating_coil.to_CoilHeatingDXSingleSpeed.is_initialized
|
|
1166
1098
|
# single speed coil
|
|
@@ -1175,13 +1107,26 @@ class ASHRAE901PRM < Standard
|
|
|
1175
1107
|
return sql_db_vars_map
|
|
1176
1108
|
end
|
|
1177
1109
|
|
|
1110
|
+
# Template method for evaluate DCV requirements in the user model
|
|
1111
|
+
#
|
|
1112
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model
|
|
1113
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1114
|
+
def model_evaluate_dcv_requirements(model)
|
|
1115
|
+
model_mark_zone_dcv_existence(model)
|
|
1116
|
+
model_add_dcv_user_exception_properties(model)
|
|
1117
|
+
model_add_dcv_requirement_properties(model)
|
|
1118
|
+
model_add_apxg_dcv_properties(model)
|
|
1119
|
+
model_raise_user_model_dcv_errors(model)
|
|
1120
|
+
return true
|
|
1121
|
+
end
|
|
1122
|
+
|
|
1178
1123
|
# Template method for adding a setpoint manager for a coil control logic to a heating coil.
|
|
1179
1124
|
# ASHRAE 90.1-2019 Appendix G.
|
|
1180
1125
|
#
|
|
1181
1126
|
# @param model [OpenStudio::Model::Model] OpenStudio model
|
|
1182
|
-
# @param
|
|
1183
|
-
# @param coil
|
|
1184
|
-
# @return [Boolean] true
|
|
1127
|
+
# @param thermal_zones Array([OpenStudio::Model::ThermalZone]) thermal zone array
|
|
1128
|
+
# @param coil [OpenStudio::Model::StraightComponent] heating coil
|
|
1129
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1185
1130
|
def model_set_central_preheat_coil_spm(model, thermal_zones, coil)
|
|
1186
1131
|
# search for the highest zone setpoint temperature
|
|
1187
1132
|
max_heat_setpoint = 0.0
|
|
@@ -1231,6 +1176,7 @@ class ASHRAE901PRM < Standard
|
|
|
1231
1176
|
#
|
|
1232
1177
|
# @author Xuechen (Jerry) Lei, PNNL
|
|
1233
1178
|
# @param model [OpenStudio::Model::Model] OpenStudio model
|
|
1179
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1234
1180
|
def model_mark_zone_dcv_existence(model)
|
|
1235
1181
|
model.getAirLoopHVACs.each do |air_loop_hvac|
|
|
1236
1182
|
next unless air_loop_hvac.airLoopHVACOutdoorAirSystem.is_initialized
|
|
@@ -1255,7 +1201,7 @@ class ASHRAE901PRM < Standard
|
|
|
1255
1201
|
end
|
|
1256
1202
|
end
|
|
1257
1203
|
|
|
1258
|
-
if zone_dcv
|
|
1204
|
+
if zone_dcv
|
|
1259
1205
|
thermal_zone.additionalProperties.setFeature('zone DCV implemented in user model', true)
|
|
1260
1206
|
end
|
|
1261
1207
|
end
|
|
@@ -1373,8 +1319,8 @@ class ASHRAE901PRM < Standard
|
|
|
1373
1319
|
#
|
|
1374
1320
|
# @author Xuechen (Jerry) Lei, PNNL
|
|
1375
1321
|
# @param model [OpenStudio::Model::Model] OpenStudio model
|
|
1322
|
+
# @todo JXL add log msgs to PRM logger
|
|
1376
1323
|
def model_raise_user_model_dcv_errors(model)
|
|
1377
|
-
# TODO: JXL add log msgs to PRM logger
|
|
1378
1324
|
model.getThermalZones.each do |thermal_zone|
|
|
1379
1325
|
if thermal_zone.additionalProperties.getFeatureAsBoolean('zone DCV implemented in user model').get &&
|
|
1380
1326
|
(!thermal_zone.additionalProperties.getFeatureAsBoolean('zone dcv required by 901').get ||
|
|
@@ -1460,158 +1406,283 @@ class ASHRAE901PRM < Standard
|
|
|
1460
1406
|
# @param [String] default_wwr_building_type
|
|
1461
1407
|
# @param [String] default_swh_building_type
|
|
1462
1408
|
# @param [Hash] bldg_type_hvac_zone_hash A hash maps building type for hvac to a list of thermal zones
|
|
1463
|
-
# @return
|
|
1464
|
-
def handle_user_input_data(model, climate_zone, default_hvac_building_type, default_wwr_building_type, default_swh_building_type, bldg_type_hvac_zone_hash)
|
|
1409
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1410
|
+
def handle_user_input_data(model, climate_zone, sizing_run_dir, default_hvac_building_type, default_wwr_building_type, default_swh_building_type, bldg_type_hvac_zone_hash)
|
|
1411
|
+
# Set sizing run directory
|
|
1412
|
+
@sizing_run_dir = sizing_run_dir
|
|
1465
1413
|
# load the multiple building area types from user data
|
|
1466
1414
|
handle_multi_building_area_types(model, climate_zone, default_hvac_building_type, default_wwr_building_type, default_swh_building_type, bldg_type_hvac_zone_hash)
|
|
1467
1415
|
# load user data from proposed model
|
|
1468
1416
|
handle_airloop_user_input_data(model)
|
|
1417
|
+
# exterior lighting handler
|
|
1418
|
+
handle_exterior_lighting_user_input_data(model)
|
|
1419
|
+
# load OA data from user data
|
|
1420
|
+
handle_outdoor_air_user_input_data(model)
|
|
1469
1421
|
# load air loop DOAS user data from the proposed model
|
|
1470
1422
|
handle_airloop_doas_user_input_data(model)
|
|
1471
1423
|
# load zone HVAC user data from proposed model
|
|
1472
1424
|
handle_zone_hvac_user_input_data(model)
|
|
1473
1425
|
# load thermal zone user data from proposed model
|
|
1474
1426
|
handle_thermal_zone_user_input_data(model)
|
|
1427
|
+
# load electric equipment user data
|
|
1428
|
+
handle_electric_equipment_user_input_data(model)
|
|
1429
|
+
return true
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
# A function to load exterior lighting data from user data csv files
|
|
1433
|
+
# The file name is userdata_exterior_lighting.csv
|
|
1434
|
+
# @param [OpenStudio::Model::Model] model
|
|
1435
|
+
def handle_exterior_lighting_user_input_data(model)
|
|
1436
|
+
user_data_exterior_lighting_objects = get_userdata(UserDataFiles::EXTERIOR_LIGHTS)
|
|
1437
|
+
|
|
1438
|
+
search_criteria = {
|
|
1439
|
+
'template' => template
|
|
1440
|
+
}
|
|
1441
|
+
ext_ltg_baseline_values = standards_lookup_table_first(table_name: 'prm_exterior_lighting', search_criteria: search_criteria)
|
|
1442
|
+
|
|
1443
|
+
model.getExteriorLightss.each do |exterior_light|
|
|
1444
|
+
if user_data_exterior_lighting_objects
|
|
1445
|
+
user_data_updated = false
|
|
1446
|
+
# get exterior lighting object.
|
|
1447
|
+
user_data_exterior_lighting_objects.each do |user_exterior_lighting|
|
|
1448
|
+
next unless UserData.compare(exterior_light.name.get, user_exterior_lighting['name'])
|
|
1449
|
+
|
|
1450
|
+
num_cats = prm_read_user_data(user_exterior_lighting, 'num_ext_lights_subcats', '0').to_i
|
|
1451
|
+
# Make sure none of the categories are nontradeable and not a mix of tradeable and nontradeable
|
|
1452
|
+
num_trade = 0
|
|
1453
|
+
num_notrade = 0
|
|
1454
|
+
ext_ltg_cats = {}
|
|
1455
|
+
(1..num_cats).each do |icat|
|
|
1456
|
+
cat_key = format('end_use_subcategory_%02d', icat)
|
|
1457
|
+
# validated
|
|
1458
|
+
subcat = user_exterior_lighting[cat_key]
|
|
1459
|
+
# handle the userdata missing value issue.
|
|
1460
|
+
if UserDataNonTradableLightsCategory.matched_any?(subcat)
|
|
1461
|
+
num_notrade += 1
|
|
1462
|
+
else
|
|
1463
|
+
num_trade += 1
|
|
1464
|
+
meas_val_key = format('end_use_measurement_value_%02d', icat)
|
|
1465
|
+
meas_val = prm_read_user_data(user_exterior_lighting, meas_val_key, '0.0').to_f
|
|
1466
|
+
unless meas_val == 0
|
|
1467
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "End use subcategory #{subcat} has either missing measurement value or invalid measurement value, set to 0.0")
|
|
1468
|
+
end
|
|
1469
|
+
ext_ltg_cats[subcat] = meas_val
|
|
1470
|
+
end
|
|
1471
|
+
end
|
|
1472
|
+
|
|
1473
|
+
# skip this if all lights are non-tradeable
|
|
1474
|
+
if num_trade == 0
|
|
1475
|
+
exterior_light.additionalProperties.setFeature('design_level', 0.0)
|
|
1476
|
+
next
|
|
1477
|
+
end
|
|
1478
|
+
|
|
1479
|
+
if (num_trade > 0) && (num_notrade > 0)
|
|
1480
|
+
OpenStudio.logFree(OpenStudio::Warn, 'prm.log', "ExteriorLights object named #{user_exterior_lighting['name']} from user data file has a mix of tradeable and non-tradeable lighting types. All will be treated as non-tradeable.")
|
|
1481
|
+
next
|
|
1482
|
+
end
|
|
1483
|
+
|
|
1484
|
+
ext_ltg_pwr = 0
|
|
1485
|
+
ext_ltg_cats.each do |subcat, meas_val|
|
|
1486
|
+
# Get baseline power for this type of exterior lighting
|
|
1487
|
+
baseline_value = ext_ltg_baseline_values[subcat].to_f
|
|
1488
|
+
ext_ltg_pwr += baseline_value * meas_val
|
|
1489
|
+
end
|
|
1490
|
+
|
|
1491
|
+
exterior_light.additionalProperties.setFeature('design_level', ext_ltg_pwr)
|
|
1492
|
+
user_data_updated = true
|
|
1493
|
+
end
|
|
1494
|
+
unless user_data_updated
|
|
1495
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Exterior Lights name #{exterior_light.name.get} was not found in user data file: #{UserDataFiles::EXTERIOR_LIGHTS}; No user data applied.")
|
|
1496
|
+
end
|
|
1497
|
+
end
|
|
1498
|
+
end
|
|
1499
|
+
end
|
|
1500
|
+
|
|
1501
|
+
# A function to load electric equipment csv files
|
|
1502
|
+
# The file name is userdata_electric_equipment.csv
|
|
1503
|
+
# @param [OpenStudio::Model::Model] model
|
|
1504
|
+
def handle_electric_equipment_user_input_data(model)
|
|
1505
|
+
user_data_plug_load = get_userdata(UserDataFiles::ELECTRIC_EQUIPMENT)
|
|
1506
|
+
model.getElectricEquipments.each do |elevator_equipment|
|
|
1507
|
+
if user_data_plug_load
|
|
1508
|
+
user_data_updated = false
|
|
1509
|
+
user_data_plug_load.each do |user_plug_load|
|
|
1510
|
+
next unless UserData.compare(elevator_equipment.name.get, user_plug_load['name'])
|
|
1511
|
+
|
|
1512
|
+
num_lifts = prm_read_user_data(user_plug_load, 'elevator_number_of_lifts', '0').to_i
|
|
1513
|
+
if num_lifts > 0
|
|
1514
|
+
elevator_equipment.additionalProperties.setFeature('elevator_number_of_lifts', num_lifts)
|
|
1515
|
+
number_of_levels = prm_read_user_data(user_plug_load, 'elevator_number_of_stories', '0').to_i
|
|
1516
|
+
elevator_equipment.additionalProperties.setFeature('elevator_number_of_stories', number_of_levels)
|
|
1517
|
+
elevator_weight_of_car = prm_read_user_data(user_plug_load, 'elevator_weight_of_car', '0.0').to_f
|
|
1518
|
+
elevator_equipment.additionalProperties.setFeature('elevator_weight_of_car', elevator_weight_of_car)
|
|
1519
|
+
elevator_weight_of_car = prm_read_user_data(user_plug_load, 'elevator_counter_weight_of_car', '0.0').to_f
|
|
1520
|
+
elevator_equipment.additionalProperties.setFeature('elevator_counter_weight_of_car', elevator_weight_of_car)
|
|
1521
|
+
elevator_rated_load = prm_read_user_data(user_plug_load, 'elevator_rated_load', '0.0').to_f
|
|
1522
|
+
elevator_equipment.additionalProperties.setFeature('elevator_rated_load', elevator_rated_load)
|
|
1523
|
+
elevator_speed_of_car = prm_read_user_data(user_plug_load, 'elevator_speed_of_car', '0.0').to_f
|
|
1524
|
+
elevator_equipment.additionalProperties.setFeature('elevator_speed_of_car', elevator_speed_of_car)
|
|
1525
|
+
elevator_ventilation_cfm = prm_read_user_data(user_plug_load, 'elevator_ventilation_cfm', '0.0').to_f
|
|
1526
|
+
elevator_equipment.additionalProperties.setFeature('elevator_ventilation_cfm', elevator_ventilation_cfm)
|
|
1527
|
+
elevator_area_ft2 = prm_read_user_data(user_plug_load, 'elevator_area_ft2', '0.0').to_f
|
|
1528
|
+
elevator_equipment.additionalProperties.setFeature('elevator_area_ft2', elevator_area_ft2)
|
|
1529
|
+
end
|
|
1530
|
+
user_data_updated = true
|
|
1531
|
+
end
|
|
1532
|
+
|
|
1533
|
+
unless user_data_updated
|
|
1534
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Electric equipment name #{elevator_equipment.name.get} was not found in user data file: #{UserDataFiles::ELECTRIC_EQUIPMENT}; No user data applied.")
|
|
1535
|
+
end
|
|
1536
|
+
end
|
|
1537
|
+
end
|
|
1538
|
+
end
|
|
1539
|
+
|
|
1540
|
+
# A function to load outdoor air data from user data csv files
|
|
1541
|
+
# The file name is userdata_design_specification_outdoor_air.csv
|
|
1542
|
+
# @param [OpenStudio::Model::Model] model
|
|
1543
|
+
def handle_outdoor_air_user_input_data(model)
|
|
1544
|
+
user_data_oas = get_userdata(UserDataFiles::DESIGN_SPECIFICATION_OUTDOOR_AIR)
|
|
1545
|
+
model.getDesignSpecificationOutdoorAirs.each do |zone_oa|
|
|
1546
|
+
if user_data_oas
|
|
1547
|
+
user_data_updated = false
|
|
1548
|
+
user_data_oas.each do |user_oa|
|
|
1549
|
+
next unless UserData.compare(zone_oa.name.get, user_oa['name'])
|
|
1550
|
+
|
|
1551
|
+
user_oa.keys.each do |info_key|
|
|
1552
|
+
if info_key == 'name'
|
|
1553
|
+
zone_oa.additionalProperties.setFeature('has_user_data', true)
|
|
1554
|
+
else
|
|
1555
|
+
# this will capture the invalid string to 0.0, need to add note
|
|
1556
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Add user provided outdoor air field: #{info_key}, value: #{user_oa[info_key].to_f} to DesignSpecification:OutdoorAir #{zone_oa.name.get} ")
|
|
1557
|
+
zone_oa.additionalProperties.setFeature(info_key, user_oa[info_key].to_f)
|
|
1558
|
+
end
|
|
1559
|
+
end
|
|
1560
|
+
user_data_updated = true
|
|
1561
|
+
end
|
|
1562
|
+
|
|
1563
|
+
unless user_data_updated
|
|
1564
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Zone outdoor air name #{zone_oa.name.get} was not found in user data file: #{UserDataFiles::DESIGN_SPECIFICATION_OUTDOOR_AIR}; No user data applied.")
|
|
1565
|
+
end
|
|
1566
|
+
end
|
|
1567
|
+
end
|
|
1475
1568
|
end
|
|
1476
1569
|
|
|
1477
1570
|
# A function to load airloop data from userdata csv files
|
|
1478
|
-
#
|
|
1571
|
+
# The function works with validated user data only.
|
|
1572
|
+
#
|
|
1573
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
1479
1574
|
def handle_airloop_user_input_data(model)
|
|
1480
1575
|
# ============================Process airloop info ============================================
|
|
1481
|
-
user_airloops =
|
|
1576
|
+
user_airloops = get_userdata(UserDataFiles::AIRLOOP_HVAC)
|
|
1482
1577
|
model.getAirLoopHVACs.each do |air_loop|
|
|
1483
|
-
|
|
1484
|
-
|
|
1578
|
+
if user_airloops
|
|
1579
|
+
user_data_updated = false
|
|
1485
1580
|
user_airloops.each do |user_airloop|
|
|
1486
|
-
|
|
1581
|
+
next unless UserData.compare(air_loop.name.get, user_airloop['name'])
|
|
1582
|
+
|
|
1583
|
+
air_loop.thermalZones.each do |thermal_zone|
|
|
1487
1584
|
# gas phase air cleaning is system base - add proposed hvac system name to zones
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
air_loop.thermalZones.each do |thermal_zone|
|
|
1491
|
-
thermal_zone.additionalProperties.setFeature('economizer_exception_for_gas_phase_air_cleaning', air_loop_name)
|
|
1492
|
-
end
|
|
1493
|
-
end
|
|
1494
|
-
end
|
|
1495
|
-
# Open refrigerated cases is zone based - add yes or no to zones
|
|
1496
|
-
if user_airloop.key?('economizer_exception_for_open_refrigerated_cases') && !user_airloop['economizer_exception_for_open_refrigerated_cases'].nil?
|
|
1497
|
-
if user_airloop['economizer_exception_for_open_refrigerated_cases'].downcase == 'yes'
|
|
1498
|
-
air_loop.thermalZones.each do |thermal_zone|
|
|
1499
|
-
thermal_zone.additionalProperties.setFeature('economizer_exception_for_open_refrigerated_cases', 'yes')
|
|
1500
|
-
end
|
|
1501
|
-
end
|
|
1502
|
-
end
|
|
1503
|
-
# Fan power credits, exhaust air energy recovery
|
|
1585
|
+
economizer_exception_for_gas_phase_air_cleaning = user_airloop['economizer_exception_for_gas_phase_air_cleaning']
|
|
1586
|
+
economizer_exception_for_open_refrigerated_cases = user_airloop['economizer_exception_for_open_refrigerated_cases']
|
|
1504
1587
|
user_airloop.keys.each do |info_key|
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
thermal_zone.additionalProperties.setFeature(info_key, current_value + 1.0)
|
|
1514
|
-
else
|
|
1515
|
-
thermal_zone.additionalProperties.setFeature(info_key, 1.0)
|
|
1516
|
-
end
|
|
1517
|
-
end
|
|
1518
|
-
end
|
|
1519
|
-
else
|
|
1520
|
-
air_loop.thermalZones.each do |thermal_zones|
|
|
1521
|
-
if thermal_zone.additionalProperties.hasFeature(info_key)
|
|
1522
|
-
current_value = thermal_zone.additionalProperties.getFeatureAsDouble(info_key).to_f
|
|
1523
|
-
thermal_zone.additionalProperties.setFeature(info_key, current_value + user_airloop[info_key])
|
|
1524
|
-
else
|
|
1525
|
-
thermal_zone.additionalProperties.setFeature(info_key, user_airloop[info_key])
|
|
1526
|
-
end
|
|
1527
|
-
end
|
|
1528
|
-
end
|
|
1529
|
-
end
|
|
1588
|
+
if info_key.include?('has_fan_power_credit') && UserData.compare(user_airloop[info_key], UserDataBoolean::TRUE)
|
|
1589
|
+
current_value = get_additional_property_as_double(thermal_zone, info_key, 0.0)
|
|
1590
|
+
thermal_zone.additionalProperties.setFeature(info_key, current_value + 1.0)
|
|
1591
|
+
elsif info_key.include?('fan_power_credit')
|
|
1592
|
+
# Case 2: user provided value
|
|
1593
|
+
fan_power_credit = prm_read_user_data(user_airloop, info_key, '0.0').to_f
|
|
1594
|
+
current_value = get_additional_property_as_double(thermal_zone, info_key, 0.0)
|
|
1595
|
+
thermal_zone.additionalProperties.setFeature(info_key, current_value + fan_power_credit)
|
|
1530
1596
|
end
|
|
1597
|
+
|
|
1531
1598
|
# Exhaust air energy recovery
|
|
1532
|
-
if info_key.include?('exhaust_energy_recovery_exception')
|
|
1533
|
-
if user_airloop[info_key]
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1599
|
+
if info_key.include?('exhaust_energy_recovery_exception')
|
|
1600
|
+
if UserData.compare(user_airloop[info_key], UserDataBoolean::TRUE)
|
|
1601
|
+
thermal_zone.additionalProperties.setFeature(info_key, true)
|
|
1602
|
+
else
|
|
1603
|
+
thermal_zone.additionalProperties.setFeature(info_key, false)
|
|
1537
1604
|
end
|
|
1538
1605
|
end
|
|
1539
1606
|
end
|
|
1607
|
+
if UserData.compare(economizer_exception_for_gas_phase_air_cleaning, UserDataBoolean::TRUE)
|
|
1608
|
+
thermal_zone.additionalProperties.setFeature('economizer_exception_for_gas_phase_air_cleaning', true)
|
|
1609
|
+
else
|
|
1610
|
+
thermal_zone.additionalProperties.setFeature('economizer_exception_for_gas_phase_air_cleaning', false)
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
if UserData.compare(economizer_exception_for_open_refrigerated_cases, UserDataBoolean::TRUE)
|
|
1614
|
+
thermal_zone.additionalProperties.setFeature('economizer_exception_for_open_refrigerated_cases', true)
|
|
1615
|
+
else
|
|
1616
|
+
thermal_zone.additionalProperties.setFeature('economizer_exception_for_open_refrigerated_cases', false)
|
|
1617
|
+
end
|
|
1540
1618
|
end
|
|
1619
|
+
user_data_updated = true
|
|
1620
|
+
end
|
|
1621
|
+
unless user_data_updated
|
|
1622
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Air loop name #{air_loop.name.get} was not found in user data file: #{UserDataFiles::AIRLOOP_HVAC}; No user data applied.")
|
|
1541
1623
|
end
|
|
1542
1624
|
end
|
|
1543
1625
|
end
|
|
1544
1626
|
end
|
|
1545
1627
|
|
|
1546
1628
|
# A function to load airloop DOAS data from userdata csv files
|
|
1547
|
-
# @param [OpenStudio::Model::Model] OpenStudio model object
|
|
1629
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
1548
1630
|
def handle_airloop_doas_user_input_data(model)
|
|
1549
1631
|
# Get user data
|
|
1550
|
-
user_airloop_doass =
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
# Parse fan power credits data
|
|
1565
|
-
user_airloop_doas.keys.each do |info_key|
|
|
1566
|
-
if info_key.include?('fan_power_credit')
|
|
1567
|
-
if !user_airloop_doas[info_key].to_s.empty?
|
|
1568
|
-
# Case 1: Yes/no
|
|
1569
|
-
if info_key.include?('has_')
|
|
1570
|
-
if user_airloop_doas[info_key].downcase == 'yes'
|
|
1571
|
-
air_loop_doas.airLoops.each do |air_loop|
|
|
1572
|
-
air_loop.thermalZones.each do |thermal_zone|
|
|
1573
|
-
if thermal_zone.additionalProperties.hasFeature(info_key)
|
|
1574
|
-
current_value = thermal_zone.additionalProperties.getFeatureAsDouble(info_key).to_f
|
|
1575
|
-
thermal_zone.additionalProperties.setFeature(info_key, current_value + 1.0)
|
|
1576
|
-
else
|
|
1577
|
-
thermal_zone.additionalProperties.setFeature(info_key, 1.0)
|
|
1578
|
-
end
|
|
1579
|
-
end
|
|
1580
|
-
end
|
|
1632
|
+
user_airloop_doass = get_userdata(UserDataFiles::AIRLOOP_HVAC_DOAS)
|
|
1633
|
+
model.getAirLoopHVACDedicatedOutdoorAirSystems.each do |air_loop_doas|
|
|
1634
|
+
if user_airloop_doass
|
|
1635
|
+
user_data_updated = false
|
|
1636
|
+
user_airloop_doass.each do |user_airloop_doas|
|
|
1637
|
+
next unless UserData.compare(user_airloop_doas['name'], air_loop_doas.name.get)
|
|
1638
|
+
|
|
1639
|
+
# Parse fan power credits data
|
|
1640
|
+
user_airloop_doas.keys.each do |info_key|
|
|
1641
|
+
if info_key.include?('has_fan_power_credit') && UserDataBoolean.compare(user_airloop_doas[info_key], UserDataBoolean::TRUE)
|
|
1642
|
+
air_loop_doas.airLoops.each do |air_loop|
|
|
1643
|
+
air_loop.thermalZones.each do |thermal_zone|
|
|
1644
|
+
current_value = get_additional_property_as_double(thermal_zone, info_key, 0.0)
|
|
1645
|
+
thermal_zone.additionalProperties.setFeature(info_key, current_value + 1.0)
|
|
1581
1646
|
end
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
else
|
|
1590
|
-
thermal_zone.additionalProperties.setFeature(info_key, user_airloop_doas[info_key])
|
|
1591
|
-
end
|
|
1592
|
-
end
|
|
1647
|
+
end
|
|
1648
|
+
elsif info_key.include?('fan_power_credit')
|
|
1649
|
+
# Case 2: user provided value
|
|
1650
|
+
air_loop_doas.airLoops.each do |air_loop|
|
|
1651
|
+
air_loop.thermalZones.each do |thermal_zone|
|
|
1652
|
+
current_value = get_additional_property_as_double(thermal_zone, info_key, 0.0)
|
|
1653
|
+
thermal_zone.additionalProperties.setFeature(info_key, current_value + prm_read_user_data(user_airloop_doas, info_key, '0.0').to_f)
|
|
1593
1654
|
end
|
|
1594
1655
|
end
|
|
1595
1656
|
end
|
|
1596
1657
|
end
|
|
1658
|
+
user_data_updated = true
|
|
1659
|
+
end
|
|
1660
|
+
unless user_data_updated
|
|
1661
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Air Loop DOAS name #{air_loop_doas.name.get} was not found in user data file: #{UserDataFiles::AIRLOOP_HVAC_DOAS}; No user data applied.")
|
|
1597
1662
|
end
|
|
1598
1663
|
end
|
|
1599
1664
|
end
|
|
1600
1665
|
end
|
|
1601
1666
|
|
|
1602
1667
|
# A function to load thermal zone data from userdata csv files
|
|
1603
|
-
# @param [OpenStudio::Model::Model] OpenStudio model object
|
|
1668
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
1604
1669
|
def handle_thermal_zone_user_input_data(model)
|
|
1670
|
+
userdata_thermal_zones = get_userdata(UserDataFiles::THERMAL_ZONE)
|
|
1605
1671
|
model.getThermalZones.each do |thermal_zone|
|
|
1606
1672
|
nightcycle_exception = false
|
|
1607
|
-
if
|
|
1608
|
-
|
|
1609
|
-
|
|
1673
|
+
if userdata_thermal_zones
|
|
1674
|
+
user_data_updated = false
|
|
1675
|
+
userdata_thermal_zones.each do |row|
|
|
1676
|
+
next unless UserData.compare(row['name'], thermal_zone.name.get)
|
|
1610
1677
|
|
|
1611
|
-
if row['has_health_safety_night_cycle_exception']
|
|
1678
|
+
if UserData.compare(row['has_health_safety_night_cycle_exception'], UserDataBoolean::TRUE)
|
|
1612
1679
|
nightcycle_exception = true
|
|
1613
1680
|
break
|
|
1614
1681
|
end
|
|
1682
|
+
user_data_updated = true
|
|
1683
|
+
end
|
|
1684
|
+
unless user_data_updated
|
|
1685
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Thermal Zone name #{thermal_zone.name.get} was not found in user data file: #{UserDataFiles::THERMAL_ZONE}.")
|
|
1615
1686
|
end
|
|
1616
1687
|
end
|
|
1617
1688
|
if nightcycle_exception
|
|
@@ -1637,20 +1708,20 @@ class ASHRAE901PRM < Standard
|
|
|
1637
1708
|
# NOTE! This function will add building types to OpenStudio objects as an additional features for hierarchy 1-3
|
|
1638
1709
|
# The object additional feature is empty when the function determined it uses fourth hierarchy.
|
|
1639
1710
|
#
|
|
1640
|
-
# @param [OpenStudio::Model::Model] model
|
|
1641
|
-
# @param [String]
|
|
1642
|
-
# @param [String]
|
|
1643
|
-
# @param [String]
|
|
1644
|
-
# @param [String]
|
|
1645
|
-
# @param [Hash]
|
|
1646
|
-
# @return
|
|
1711
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
1712
|
+
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
1713
|
+
# @param default_hvac_building_type [String] (Fourth Hierarchy hvac building type)
|
|
1714
|
+
# @param default_wwr_building_type [String] (Fourth Hierarchy wwr building type)
|
|
1715
|
+
# @param default_swh_building_type [String] (Fourth Hierarchy swh building type)
|
|
1716
|
+
# @param bldg_type_hvac_zone_hash [Hash] An empty hash that maps building type for hvac to a list of thermal zones
|
|
1717
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1647
1718
|
def handle_multi_building_area_types(model, climate_zone, default_hvac_building_type, default_wwr_building_type, default_swh_building_type, bldg_type_hvac_zone_hash)
|
|
1648
1719
|
# Construct the user_building hashmap
|
|
1649
|
-
user_buildings =
|
|
1720
|
+
user_buildings = get_userdata(UserDataFiles::BUILDING)
|
|
1650
1721
|
|
|
1651
1722
|
# Build up a hvac_building_type : thermal zone hash map
|
|
1652
1723
|
# =============================HVAC user data process===========================================
|
|
1653
|
-
user_thermal_zones =
|
|
1724
|
+
user_thermal_zones = get_userdata(UserDataFiles::THERMAL_ZONE)
|
|
1654
1725
|
# First construct hvac building type -> thermal Zone hash and hvac building type -> floor area
|
|
1655
1726
|
bldg_type_zone_hash = {}
|
|
1656
1727
|
bldg_type_zone_area_hash = {}
|
|
@@ -1663,8 +1734,8 @@ class ASHRAE901PRM < Standard
|
|
|
1663
1734
|
|
|
1664
1735
|
# Check for Second hierarchy
|
|
1665
1736
|
hvac_building_type = nil
|
|
1666
|
-
if user_thermal_zones
|
|
1667
|
-
user_thermal_zone_index = user_thermal_zones.index { |user_thermal_zone| user_thermal_zone['name']
|
|
1737
|
+
if user_thermal_zones
|
|
1738
|
+
user_thermal_zone_index = user_thermal_zones.index { |user_thermal_zone| UserData.compare(user_thermal_zone['name'], thermal_zone.name.get) }
|
|
1668
1739
|
# make sure the thermal zone has assigned a building_type_for_hvac
|
|
1669
1740
|
unless user_thermal_zone_index.nil? || user_thermal_zones[user_thermal_zone_index]['building_type_for_hvac'].nil?
|
|
1670
1741
|
# Only thermal zone in the user data and have building_type_for_hvac data will be assigned.
|
|
@@ -1672,9 +1743,9 @@ class ASHRAE901PRM < Standard
|
|
|
1672
1743
|
end
|
|
1673
1744
|
end
|
|
1674
1745
|
# Second hierarchy does not apply, check Third hierarchy
|
|
1675
|
-
if hvac_building_type.nil? && user_buildings
|
|
1676
|
-
building_name = thermal_zone.model
|
|
1677
|
-
user_building_index = user_buildings.index { |user_building| user_building['name']
|
|
1746
|
+
if hvac_building_type.nil? && user_buildings
|
|
1747
|
+
building_name = prm_get_optional_handler(thermal_zone.model, @sizing_run_dir, 'building', 'name')
|
|
1748
|
+
user_building_index = user_buildings.index { |user_building| UserData.compare(user_building['name'], building_name) }
|
|
1678
1749
|
unless user_building_index.nil? || user_buildings[user_building_index]['building_type_for_hvac'].nil?
|
|
1679
1750
|
# Only thermal zone in the buildings user data and have building_type_for_hvac data will be assigned.
|
|
1680
1751
|
hvac_building_type = user_buildings[user_building_index]['building_type_for_hvac']
|
|
@@ -1738,12 +1809,12 @@ class ASHRAE901PRM < Standard
|
|
|
1738
1809
|
if OpenStudio.convert(total_floor_area, 'm^2', 'ft^2').get <= 40000
|
|
1739
1810
|
# Building is smaller than 40k sqft, it could only have one hvac_building_type, reset all the thermal zones.
|
|
1740
1811
|
bldg_type_hvac_zone_hash[hvac_bldg_type_with_max_floor].push(*bldg_type_zone)
|
|
1741
|
-
OpenStudio.logFree(OpenStudio::
|
|
1812
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "The building floor area is less than 40,000 square foot. Thermal zones under hvac building type #{bldg_type} is reset to #{hvac_bldg_type_with_max_floor}")
|
|
1742
1813
|
else
|
|
1743
1814
|
if OpenStudio.convert(bldg_type_zone_area_hash[bldg_type], 'm^2', 'ft^2').get < 20000
|
|
1744
1815
|
# in this case, all thermal zones shall be categorized as the primary hvac_building_type
|
|
1745
1816
|
bldg_type_hvac_zone_hash[hvac_bldg_type_with_max_floor].push(*bldg_type_zone)
|
|
1746
|
-
OpenStudio.logFree(OpenStudio::
|
|
1817
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "The floor area in hvac building type #{bldg_type} is less than 20,000 square foot. Thermal zones under this hvac building type is reset to #{hvac_bldg_type_with_max_floor}")
|
|
1747
1818
|
else
|
|
1748
1819
|
bldg_type_hvac_zone_hash[bldg_type] = bldg_type_zone
|
|
1749
1820
|
end
|
|
@@ -1760,14 +1831,14 @@ class ASHRAE901PRM < Standard
|
|
|
1760
1831
|
end
|
|
1761
1832
|
|
|
1762
1833
|
# =============================SPACE user data process===========================================
|
|
1763
|
-
user_spaces =
|
|
1834
|
+
user_spaces = get_userdata(UserDataFiles::SPACE)
|
|
1764
1835
|
model.getSpaces.each do |space|
|
|
1765
1836
|
type_for_wwr = nil
|
|
1766
1837
|
# Check for 2nd level hierarchy
|
|
1767
|
-
if user_spaces
|
|
1838
|
+
if user_spaces
|
|
1768
1839
|
user_spaces.each do |user_space|
|
|
1769
1840
|
unless user_space['building_type_for_wwr'].nil?
|
|
1770
|
-
if space.name.get
|
|
1841
|
+
if UserData.compare(space.name.get, user_space['name'])
|
|
1771
1842
|
type_for_wwr = user_space['building_type_for_wwr']
|
|
1772
1843
|
end
|
|
1773
1844
|
end
|
|
@@ -1776,11 +1847,11 @@ class ASHRAE901PRM < Standard
|
|
|
1776
1847
|
|
|
1777
1848
|
if type_for_wwr.nil?
|
|
1778
1849
|
# 2nd Hierarchy does not apply, check for 3rd level hierarchy
|
|
1779
|
-
building_name = space.model
|
|
1780
|
-
if user_buildings
|
|
1850
|
+
building_name = prm_get_optional_handler(space.model, @sizing_run_dir, 'building', 'name')
|
|
1851
|
+
if user_buildings
|
|
1781
1852
|
user_buildings.each do |user_building|
|
|
1782
1853
|
unless user_building['building_type_for_wwr'].nil?
|
|
1783
|
-
if user_building['name']
|
|
1854
|
+
if UserData.compare(user_building['name'], building_name)
|
|
1784
1855
|
type_for_wwr = user_building['building_type_for_wwr']
|
|
1785
1856
|
end
|
|
1786
1857
|
end
|
|
@@ -1796,14 +1867,14 @@ class ASHRAE901PRM < Standard
|
|
|
1796
1867
|
space.additionalProperties.setFeature('building_type_for_wwr', type_for_wwr)
|
|
1797
1868
|
end
|
|
1798
1869
|
# =============================SWH user data process===========================================
|
|
1799
|
-
user_wateruse_equipments =
|
|
1870
|
+
user_wateruse_equipments = get_userdata(UserDataFiles::WATERUSE_EQUIPMENT)
|
|
1800
1871
|
model.getWaterUseEquipments.each do |wateruse_equipment|
|
|
1801
1872
|
type_for_swh = nil
|
|
1802
1873
|
# Check for 2nd hierarchy
|
|
1803
|
-
if user_wateruse_equipments
|
|
1874
|
+
if user_wateruse_equipments
|
|
1804
1875
|
user_wateruse_equipments.each do |user_wateruse_equipment|
|
|
1805
1876
|
unless user_wateruse_equipment['building_type_for_swh'].nil?
|
|
1806
|
-
if wateruse_equipment.name.get
|
|
1877
|
+
if UserData.compare(wateruse_equipment.name.get, user_wateruse_equipment['name'])
|
|
1807
1878
|
type_for_swh = user_wateruse_equipment['building_type_for_swh']
|
|
1808
1879
|
end
|
|
1809
1880
|
end
|
|
@@ -1813,11 +1884,11 @@ class ASHRAE901PRM < Standard
|
|
|
1813
1884
|
if type_for_swh.nil?
|
|
1814
1885
|
# 2nd hierarchy does not apply, check for 3rd hierarchy
|
|
1815
1886
|
# get space building type
|
|
1816
|
-
building_name = wateruse_equipment.model
|
|
1817
|
-
if user_buildings
|
|
1887
|
+
building_name = prm_get_optional_handler(wateruse_equipment.model, @sizing_run_dir, 'building', 'name')
|
|
1888
|
+
if user_buildings
|
|
1818
1889
|
user_buildings.each do |user_building|
|
|
1819
1890
|
unless user_building['building_type_for_swh'].nil?
|
|
1820
|
-
if user_building['name']
|
|
1891
|
+
if UserData.compare(user_building['name'], building_name)
|
|
1821
1892
|
type_for_swh = user_building['building_type_for_swh']
|
|
1822
1893
|
end
|
|
1823
1894
|
end
|
|
@@ -1837,11 +1908,11 @@ class ASHRAE901PRM < Standard
|
|
|
1837
1908
|
|
|
1838
1909
|
# Modify the existing service water heating loops to match the baseline required heating type.
|
|
1839
1910
|
#
|
|
1840
|
-
# @param model [OpenStudio::Model::Model]
|
|
1911
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
1841
1912
|
# @param building_type [String] the building type
|
|
1842
|
-
# @return [
|
|
1913
|
+
# @return [Boolean] returns true if successful, false if not
|
|
1843
1914
|
def model_apply_baseline_swh_loops(model, building_type)
|
|
1844
|
-
model.getPlantLoops.
|
|
1915
|
+
model.getPlantLoops.each do |plant_loop|
|
|
1845
1916
|
# Skip non service water heating loops
|
|
1846
1917
|
next unless plant_loop_swh_loop?(plant_loop)
|
|
1847
1918
|
|
|
@@ -1850,10 +1921,7 @@ class ASHRAE901PRM < Standard
|
|
|
1850
1921
|
|
|
1851
1922
|
htg_fuels, combination_system, storage_capacity, total_heating_capacity = plant_loop_swh_system_type(plant_loop)
|
|
1852
1923
|
|
|
1853
|
-
# htg_fuels.size == 0 shoudln't happen
|
|
1854
|
-
|
|
1855
1924
|
electric = true
|
|
1856
|
-
|
|
1857
1925
|
if htg_fuels.include?('NaturalGas') ||
|
|
1858
1926
|
htg_fuels.include?('PropaneGas') ||
|
|
1859
1927
|
htg_fuels.include?('FuelOilNo1') ||
|
|
@@ -1866,12 +1934,11 @@ class ASHRAE901PRM < Standard
|
|
|
1866
1934
|
|
|
1867
1935
|
# Per Table G3.1 11.e, if the baseline system was a combination of heating and service water heating,
|
|
1868
1936
|
# delete all heating equipment and recreate a WaterHeater:Mixed.
|
|
1869
|
-
|
|
1870
1937
|
if combination_system
|
|
1871
1938
|
a = plant_loop.supplyComponents
|
|
1872
1939
|
b = plant_loop.demandComponents
|
|
1873
|
-
|
|
1874
|
-
|
|
1940
|
+
plantloop_components = a += b
|
|
1941
|
+
plantloop_components.each do |component|
|
|
1875
1942
|
# Get the object type
|
|
1876
1943
|
obj_type = component.iddObjectType.valueName.to_s
|
|
1877
1944
|
next if ['OS_Node', 'OS_Pump_ConstantSpeed', 'OS_Pump_VariableSpeed', 'OS_Connector_Splitter', 'OS_Connector_Mixer', 'OS_Pipe_Adiabatic'].include?(obj_type)
|
|
@@ -1903,27 +1970,7 @@ class ASHRAE901PRM < Standard
|
|
|
1903
1970
|
# to electric resistance if it's electric
|
|
1904
1971
|
else
|
|
1905
1972
|
# Per Table G3.1 11.i, piping losses was deleted
|
|
1906
|
-
|
|
1907
|
-
a = plant_loop.supplyComponents
|
|
1908
|
-
b = plant_loop.demandComponents
|
|
1909
|
-
plantloopComponents = a += b
|
|
1910
|
-
plantloopComponents.each do |component|
|
|
1911
|
-
# Get the object type
|
|
1912
|
-
obj_type = component.iddObjectType.valueName.to_s
|
|
1913
|
-
next if !['OS_Pipe_Indoor', 'OS_Pipe_Outdoor'].include?(obj_type)
|
|
1914
|
-
|
|
1915
|
-
pipe = component.to_PipeIndoor.get
|
|
1916
|
-
node = pipe.to_StraightComponent.get.outletModelObject.get.to_Node.get
|
|
1917
|
-
|
|
1918
|
-
node_name = node.name.get
|
|
1919
|
-
pipe_name = pipe.name.get
|
|
1920
|
-
|
|
1921
|
-
# Add Pipe_Adiabatic
|
|
1922
|
-
newpipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
|
1923
|
-
newpipe.setName(pipe_name)
|
|
1924
|
-
newpipe.addToNode(node)
|
|
1925
|
-
component.remove
|
|
1926
|
-
end
|
|
1973
|
+
plant_loop_adiabatic_pipes_only(plant_loop)
|
|
1927
1974
|
|
|
1928
1975
|
if electric
|
|
1929
1976
|
plant_loop.supplyComponents.each do |component|
|
|
@@ -1948,38 +1995,63 @@ class ASHRAE901PRM < Standard
|
|
|
1948
1995
|
|
|
1949
1996
|
# Check whether the baseline model generation needs to run all four orientations
|
|
1950
1997
|
# The default shall be true
|
|
1998
|
+
# The orientation takes priority of:
|
|
1999
|
+
# 1. Appx G
|
|
2000
|
+
# 2. Method user input.
|
|
2001
|
+
# 3. User data override.
|
|
1951
2002
|
#
|
|
1952
|
-
# @param [Boolean]
|
|
1953
|
-
# @param [OpenStudio::Model::Model] OpenStudio model
|
|
2003
|
+
# @param run_all_orients [Boolean] user inputs to indicate whether it is required to run all orientations
|
|
2004
|
+
# @param user_model [OpenStudio::Model::Model] OpenStudio model
|
|
2005
|
+
# @return [Boolean] True if run all orientation is required, false otherwise
|
|
1954
2006
|
def run_all_orientations(run_all_orients, user_model)
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
# Step 1 check orientation variations - priority 2
|
|
2007
|
+
run_orients_flag = false
|
|
2008
|
+
# Step 1 check orientation variations - priority 3
|
|
1958
2009
|
fenestration_area_hash = get_model_fenestration_area_by_orientation(user_model)
|
|
1959
2010
|
fenestration_area_hash.each do |orientation, fenestration_area|
|
|
2011
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log',
|
|
2012
|
+
"#{orientation} orientation has total fenestration area of #{fenestration_area} m2")
|
|
1960
2013
|
fenestration_area_hash.each do |other_orientation, other_fenestration_area|
|
|
1961
2014
|
next unless orientation != other_orientation
|
|
1962
2015
|
|
|
1963
2016
|
variance = (other_fenestration_area - fenestration_area) / fenestration_area
|
|
1964
2017
|
if variance.abs > 0.05
|
|
1965
2018
|
# if greater then 0.05
|
|
2019
|
+
OpenStudio.logFree(OpenStudio::Info,
|
|
2020
|
+
'prm.log',
|
|
2021
|
+
"#{orientation} has total fenestration area of #{fenestration_area} m2, which is higher than 5% variance compare to #{other_fenestration_area} at #{other_orientation}")
|
|
1966
2022
|
run_orients_flag = true
|
|
1967
2023
|
end
|
|
1968
2024
|
end
|
|
1969
2025
|
end
|
|
1970
|
-
# Step 2
|
|
2026
|
+
# Step 2, assign method user input if it is provided as false.
|
|
2027
|
+
unless run_all_orients
|
|
2028
|
+
OpenStudio.logFree(OpenStudio::Error,
|
|
2029
|
+
'prm.log',
|
|
2030
|
+
'The run_all_orientation flag is set to False, update the run to a single orientation PRM generation.')
|
|
2031
|
+
run_orients_flag = run_all_orients
|
|
2032
|
+
end
|
|
2033
|
+
# Step 3 read user data - priority 1 - user data will override the priority 2
|
|
1971
2034
|
user_buildings = @standards_data.key?('userdata_building') ? @standards_data['userdata_building'] : nil
|
|
1972
2035
|
if user_buildings
|
|
1973
2036
|
building_name = user_model.building.get.name.get
|
|
1974
2037
|
user_building_index = user_buildings.index { |user_building| building_name.include? user_building['name'] }
|
|
1975
2038
|
unless user_building_index.nil? || user_buildings[user_building_index]['is_exempt_from_rotations'].nil?
|
|
1976
2039
|
# user data exempt the rotation, No indicates true for running orients.
|
|
1977
|
-
|
|
2040
|
+
OpenStudio.logFree(OpenStudio::Error,
|
|
2041
|
+
'prm.log',
|
|
2042
|
+
"User data in the userdata_building.csv indicate building #{building_name} is exempted from rotation. Update the run to a single orientation PRM generation.")
|
|
2043
|
+
# @todo need to use user data enums later.
|
|
2044
|
+
run_orients_flag = user_buildings[user_building_index]['is_exempt_from_rotations'].casecmp('False') == 0
|
|
1978
2045
|
end
|
|
1979
2046
|
end
|
|
1980
2047
|
return run_orients_flag
|
|
1981
2048
|
end
|
|
1982
2049
|
|
|
2050
|
+
# Function that extract the total fenestration area from a model by orientations.
|
|
2051
|
+
# Orientation is identified as N (North), S (South), E (East), W (West)
|
|
2052
|
+
#
|
|
2053
|
+
# @param user_model [OpenStudio::Model::Model] OpenStudio model
|
|
2054
|
+
# @return [Hash] Hash map that contains the total area of fenestration at each orientation (N, S, E, W)
|
|
1983
2055
|
def get_model_fenestration_area_by_orientation(user_model)
|
|
1984
2056
|
# First index is wall, second index is window
|
|
1985
2057
|
fenestration_area_hash = {
|
|
@@ -1993,7 +2065,7 @@ class ASHRAE901PRM < Standard
|
|
|
1993
2065
|
next if space_cond_type == 'Unconditioned'
|
|
1994
2066
|
|
|
1995
2067
|
# Get zone multiplier
|
|
1996
|
-
multiplier = space
|
|
2068
|
+
multiplier = prm_get_optional_handler(space, @sizing_run_dir, 'thermalZone').multiplier
|
|
1997
2069
|
space.surfaces.each do |surface|
|
|
1998
2070
|
next if surface.surfaceType != 'Wall'
|
|
1999
2071
|
next if surface.outsideBoundaryCondition != 'Outdoors'
|
|
@@ -2013,10 +2085,9 @@ class ASHRAE901PRM < Standard
|
|
|
2013
2085
|
|
|
2014
2086
|
# Apply the standard construction to each surface in the model, based on the construction type currently assigned.
|
|
2015
2087
|
#
|
|
2016
|
-
# @return [Bool] true if successful, false if not
|
|
2017
2088
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
2018
2089
|
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
2019
|
-
# @return [
|
|
2090
|
+
# @return [Boolean] returns true if successful, false if not
|
|
2020
2091
|
def model_apply_constructions(model, climate_zone, wwr_building_type, wwr_info)
|
|
2021
2092
|
model_apply_standard_constructions(model, climate_zone, wwr_building_type: wwr_building_type, wwr_info: wwr_info)
|
|
2022
2093
|
|
|
@@ -2027,7 +2098,7 @@ class ASHRAE901PRM < Standard
|
|
|
2027
2098
|
#
|
|
2028
2099
|
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
2029
2100
|
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
|
2030
|
-
# @return [
|
|
2101
|
+
# @return [Boolean] surfaces_with_fc_factor_boundary, returns true if successful, false if not
|
|
2031
2102
|
def model_update_ground_temperature_profile(model, climate_zone)
|
|
2032
2103
|
# Check if the ground temperature profile is needed
|
|
2033
2104
|
surfaces_with_fc_factor_boundary = false
|
|
@@ -2038,32 +2109,35 @@ class ASHRAE901PRM < Standard
|
|
|
2038
2109
|
end
|
|
2039
2110
|
end
|
|
2040
2111
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
model.getSiteGroundTemperatureFCfactorMethod.remove
|
|
2112
|
+
if surfaces_with_fc_factor_boundary
|
|
2113
|
+
# Remove existing FCFactor temperature profile
|
|
2114
|
+
model.getSiteGroundTemperatureFCfactorMethod.remove
|
|
2045
2115
|
|
|
2046
|
-
|
|
2047
|
-
|
|
2116
|
+
# Get path to weather file specified in the model
|
|
2117
|
+
weather_file_path = prm_get_optional_handler(model.getWeatherFile, @sizing_run_dir, 'path').to_s
|
|
2048
2118
|
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2119
|
+
# Look for stat file corresponding to the weather file
|
|
2120
|
+
stat_file_path = weather_file_path.sub('.epw', '.stat').to_s
|
|
2121
|
+
if !File.exist? stat_file_path
|
|
2122
|
+
# When the stat file corresponding with the weather file in the model is missing,
|
|
2123
|
+
# use the weather file that represent the climate zone
|
|
2124
|
+
climate_zone_weather_file_map = model_get_climate_zone_weather_file_map
|
|
2125
|
+
prm_raise(climate_zone_weather_file_map.key?(climate_zone),
|
|
2126
|
+
@sizing_run_dir,
|
|
2127
|
+
"Failed to find a matching climate zone #{climate_zone} from the climate zone weather files.")
|
|
2128
|
+
weather_file = climate_zone_weather_file_map[climate_zone]
|
|
2129
|
+
stat_file_path = model_get_weather_file(weather_file).sub('.epw', '.stat').to_s
|
|
2130
|
+
end
|
|
2058
2131
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2132
|
+
ground_temp = OpenStudio::Model::SiteGroundTemperatureFCfactorMethod.new(model)
|
|
2133
|
+
ground_temperatures = model_get_monthly_ground_temps_from_stat_file(stat_file_path)
|
|
2134
|
+
unless ground_temperatures.empty?
|
|
2135
|
+
# set the site ground temperature building surface
|
|
2136
|
+
ground_temp.setAllMonthlyTemperatures(ground_temperatures)
|
|
2137
|
+
end
|
|
2064
2138
|
end
|
|
2065
2139
|
|
|
2066
|
-
return
|
|
2140
|
+
return surfaces_with_fc_factor_boundary
|
|
2067
2141
|
end
|
|
2068
2142
|
|
|
2069
2143
|
# Generate baseline log to a specific file directory
|
|
@@ -2074,7 +2148,7 @@ class ASHRAE901PRM < Standard
|
|
|
2074
2148
|
|
|
2075
2149
|
# Retrieve zone HVAC user specified compliance inputs from CSV file
|
|
2076
2150
|
#
|
|
2077
|
-
# @param [OpenStudio::Model::Model] OpenStudio model object
|
|
2151
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
|
2078
2152
|
def handle_zone_hvac_user_input_data(model)
|
|
2079
2153
|
user_zone_hvac = @standards_data.key?('userdata_zone_hvac') ? @standards_data['userdata_zone_hvac'] : nil
|
|
2080
2154
|
return unless user_zone_hvac && !user_zone_hvac.empty?
|
|
@@ -2148,9 +2222,9 @@ class ASHRAE901PRM < Standard
|
|
|
2148
2222
|
end
|
|
2149
2223
|
|
|
2150
2224
|
# This function checks whether it is required to adjust the window to wall ratio based on the model WWR and wwr limit.
|
|
2151
|
-
# @param wwr_limit [
|
|
2225
|
+
# @param wwr_limit [Double] window to wall ratio limit
|
|
2152
2226
|
# @param wwr_list [Array] list of wwr of zone conditioning category in a building area type category - residential, nonresidential and semiheated
|
|
2153
|
-
# @return
|
|
2227
|
+
# @return [Boolean] True, require adjustment, false not require adjustment
|
|
2154
2228
|
def model_does_require_wwr_adjustment?(wwr_limit, wwr_list)
|
|
2155
2229
|
# 90.1 PRM routine requires
|
|
2156
2230
|
return true
|
|
@@ -2160,7 +2234,7 @@ class ASHRAE901PRM < Standard
|
|
|
2160
2234
|
#
|
|
2161
2235
|
# @param bat [String] building category
|
|
2162
2236
|
# @param wwr_list [Array] list of zone conditioning category-based WWR - residential, nonresidential and semiheated
|
|
2163
|
-
# @return
|
|
2237
|
+
# @return [Double] return adjusted wwr_limit
|
|
2164
2238
|
def model_get_bat_wwr_target(bat, wwr_list)
|
|
2165
2239
|
wwr_limit = 40.0
|
|
2166
2240
|
# Lookup WWR target from stable baseline table
|
|
@@ -2186,32 +2260,35 @@ class ASHRAE901PRM < Standard
|
|
|
2186
2260
|
|
|
2187
2261
|
# Calculate the window to wall ratio reduction factor
|
|
2188
2262
|
#
|
|
2189
|
-
# @param multiplier [
|
|
2190
|
-
# @param
|
|
2191
|
-
# @param surface_dr [Float] the surface door to wall ratio
|
|
2263
|
+
# @param multiplier [Double] multiplier of the wwr
|
|
2264
|
+
# @param surface [OpenStudio::Model:Surface] the surface object
|
|
2192
2265
|
# @param wwr_building_type[String] building type for wwr
|
|
2193
|
-
# @param wwr_target [
|
|
2194
|
-
# @param total_wall_m2 [
|
|
2195
|
-
# @param total_wall_with_fene_m2 [
|
|
2196
|
-
# @param total_fene_m2 [
|
|
2197
|
-
# @return [
|
|
2198
|
-
def
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2266
|
+
# @param wwr_target [Double] target window to wall ratio
|
|
2267
|
+
# @param total_wall_m2 [Double] total wall area of the category in m2.
|
|
2268
|
+
# @param total_wall_with_fene_m2 [Double] total wall area of the category with fenestrations in m2.
|
|
2269
|
+
# @param total_fene_m2 [Double] total fenestration area
|
|
2270
|
+
# @return [Double] reduction factor
|
|
2271
|
+
def surface_get_wwr_reduction_ratio(multiplier,
|
|
2272
|
+
surface,
|
|
2273
|
+
wwr_building_type: 'All others',
|
|
2274
|
+
wwr_target: nil,
|
|
2275
|
+
total_wall_m2: 0.0, # prevent 0.0 division
|
|
2276
|
+
total_wall_with_fene_m2: 0.0,
|
|
2277
|
+
total_fene_m2: 0.0,
|
|
2278
|
+
total_plenum_wall_m2: 0.0)
|
|
2279
|
+
|
|
2280
|
+
surface_name = surface.name.get
|
|
2281
|
+
surface_wwr = surface_get_wwr(surface)
|
|
2282
|
+
surface_dr = surface_get_door_ratio(surface)
|
|
2207
2283
|
|
|
2208
2284
|
if multiplier < 1.0
|
|
2209
2285
|
# Case when reduction is required
|
|
2210
2286
|
reduction_ratio = 1.0 - multiplier
|
|
2287
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log',
|
|
2288
|
+
"Surface #{surface_name} WWR is #{surface_wwr}. Reduce its WWR to #{surface_wwr * reduction_ratio}%")
|
|
2211
2289
|
else
|
|
2212
2290
|
# Case when increase is required - takes the door area into consideration.
|
|
2213
2291
|
# The target is to increase each surface to maximum 90% WWR deduct the total door area.
|
|
2214
|
-
total_dr = 0.0
|
|
2215
2292
|
exist_max_wwr = 0.0
|
|
2216
2293
|
if total_wall_m2 > 0 then exist_max_wwr = total_wall_with_fene_m2 * 0.9 / total_wall_m2 end
|
|
2217
2294
|
if exist_max_wwr < wwr_target
|
|
@@ -2220,6 +2297,9 @@ class ASHRAE901PRM < Standard
|
|
|
2220
2297
|
# delta_fenestration_surface_area / delta_wall_surface_area + 1.0 = increase_ratio for a surface with no windows.
|
|
2221
2298
|
# ASSUMPTION!! assume adding windows to surface with no windows will never be window_m2 + door_m2 > surface_m2.
|
|
2222
2299
|
reduction_ratio = (wwr_target - exist_max_wwr) * total_wall_m2 / (total_wall_m2 - total_wall_with_fene_m2 - total_plenum_wall_m2) + 1.0
|
|
2300
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log',
|
|
2301
|
+
"The max window to wall ratio is #{exist_max_wwr}, smaller than the target window to wall ratio #{wwr_target}.
|
|
2302
|
+
Surface #{surface_name} has no fenestration subsurfaces. Adding new fenestration band with WWR of #{(reduction_ratio - 1) * 100}%")
|
|
2223
2303
|
else
|
|
2224
2304
|
# surface has fenestration - expand it to 90% WWR or surface area minus door area, whichever is smaller.
|
|
2225
2305
|
if (1.0 - surface_dr) < 0.9
|
|
@@ -2229,6 +2309,9 @@ class ASHRAE901PRM < Standard
|
|
|
2229
2309
|
else
|
|
2230
2310
|
reduction_ratio = 0.9 / surface_wwr
|
|
2231
2311
|
end
|
|
2312
|
+
OpenStudio.logFree(OpenStudio::Info, 'prm.log',
|
|
2313
|
+
"The max window to wall ratio is #{exist_max_wwr}, smaller than the target window to wall ratio #{wwr_target}.
|
|
2314
|
+
Surface #{surface_name} will expand its WWR to 90%")
|
|
2232
2315
|
end
|
|
2233
2316
|
else
|
|
2234
2317
|
# multiplier will be negative number thus resulting in > 1 reduction_ratio
|
|
@@ -2248,10 +2331,10 @@ class ASHRAE901PRM < Standard
|
|
|
2248
2331
|
# This function shall only be called if the maximum WWR value for surfaces with fenestration is lower than 90% due to
|
|
2249
2332
|
# accommodating the total door surface areas
|
|
2250
2333
|
#
|
|
2251
|
-
# @param residual_ratio
|
|
2334
|
+
# @param residual_ratio [Double] the ratio of residual surfaces among the total wall surface area with no fenestrations
|
|
2252
2335
|
# @param space [OpenStudio::Model:Space] a space
|
|
2253
2336
|
# @param model [OpenStudio::Model::Model] openstudio model
|
|
2254
|
-
# @return [
|
|
2337
|
+
# @return [Boolean] returns true if successful, false if not
|
|
2255
2338
|
def model_readjust_surface_wwr(residual_ratio, space, model)
|
|
2256
2339
|
# In this loop, we will focus on the surfaces with newly added a fenestration.
|
|
2257
2340
|
space.surfaces.sort.each do |surface|
|
|
@@ -2267,10 +2350,12 @@ class ASHRAE901PRM < Standard
|
|
|
2267
2350
|
|
|
2268
2351
|
# Assign spaces to system groups based on building area type
|
|
2269
2352
|
# Get zone groups separately for each hvac building type
|
|
2353
|
+
#
|
|
2354
|
+
# @param model [OpenStudio::Model::Model] openstudio model
|
|
2270
2355
|
# @param custom [String] identifier for custom programs, not used here, but included for backwards compatibility
|
|
2271
2356
|
# @param bldg_type_hvac_zone_hash [Hash of bldg_type:list of zone objects] association of zones to each hvac building type
|
|
2272
2357
|
# @return [Array<Hash>] an array of hashes of area information,
|
|
2273
|
-
#
|
|
2358
|
+
# with keys area_ft2, type, fuel, and zones (an array of zones)
|
|
2274
2359
|
def model_prm_baseline_system_groups(model, custom, bldg_type_hvac_zone_hash)
|
|
2275
2360
|
bldg_groups = []
|
|
2276
2361
|
|
|
@@ -2293,22 +2378,19 @@ class ASHRAE901PRM < Standard
|
|
|
2293
2378
|
# Groups may include zones from multiple floors; separating by floor is handled later
|
|
2294
2379
|
# For stable baseline, heating type is based on climate, not proposed heating type
|
|
2295
2380
|
# Isolate zones that have heating-only or district (purchased) heat or chilled water
|
|
2296
|
-
# @param
|
|
2381
|
+
# @param hvac_building_type [String] Chosen by user via measure interface or user data files
|
|
2382
|
+
# @param zones_in_building_type [Array<OpenStudio::Model::ThermalZone>] array of thermal zones
|
|
2297
2383
|
# @return [Array<Hash>] an array of hashes of area information,
|
|
2298
|
-
#
|
|
2384
|
+
# with keys area_ft2, type, fuel, and zones (an array of zones)
|
|
2299
2385
|
def get_baseline_system_groups_for_one_building_type(model, hvac_building_type, zones_in_building_type)
|
|
2300
2386
|
# Build zones hash of [zone, zone area, occupancy type, building type, fuel]
|
|
2301
2387
|
zones = model_zones_with_occ_and_fuel_type(model, 'custom')
|
|
2302
2388
|
|
|
2303
2389
|
# Ensure that there is at least one conditioned zone
|
|
2304
|
-
|
|
2305
|
-
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', 'The building does not appear to have any conditioned zones. Make sure zones have thermostat with appropriate heating and cooling setpoint schedules.')
|
|
2306
|
-
return []
|
|
2307
|
-
end
|
|
2390
|
+
prm_raise(!zones.empty?, @sizing_run_dir, 'The building does not appear to have any conditioned zones. Make sure zones have thermostat with appropriate heating and cooling setpoint schedules.')
|
|
2308
2391
|
|
|
2309
2392
|
# Consider special rules for computer rooms
|
|
2310
2393
|
# need load of all
|
|
2311
|
-
|
|
2312
2394
|
# Get cooling load of all computer rooms to establish system types
|
|
2313
2395
|
comp_room_loads = {}
|
|
2314
2396
|
bldg_comp_room_load = 0
|
|
@@ -2317,15 +2399,18 @@ class ASHRAE901PRM < Standard
|
|
|
2317
2399
|
has_computer_room = false
|
|
2318
2400
|
# First check if any space in zone has a computer room
|
|
2319
2401
|
zn['zone'].spaces.each do |space|
|
|
2320
|
-
if space
|
|
2402
|
+
if prm_get_optional_handler(space, @sizing_run_dir, 'spaceType', 'standardsSpaceType') == 'computer room'
|
|
2321
2403
|
has_computer_room = true
|
|
2322
2404
|
break
|
|
2323
2405
|
end
|
|
2324
2406
|
end
|
|
2325
2407
|
if has_computer_room
|
|
2326
2408
|
# Collect load for entire zone
|
|
2327
|
-
|
|
2328
|
-
|
|
2409
|
+
if zn['zone'].model.version < OpenStudio::VersionString.new('3.6.0')
|
|
2410
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.ashrae_90_1_prm.Model', 'Required ThermalZone method .autosizedCoolingDesignLoad is not available in pre-OpenStudio 3.6.0 versions. Use a more recent version of OpenStudio.')
|
|
2411
|
+
end
|
|
2412
|
+
zone_load_w = zn['zone'].autosizedCoolingDesignLoad.get
|
|
2413
|
+
zone_load_w *= zn['zone'].multiplier
|
|
2329
2414
|
zone_load = OpenStudio.convert(zone_load_w, 'W', 'Btu/hr').get
|
|
2330
2415
|
end
|
|
2331
2416
|
comp_room_loads[zn['zone'].name.get] = zone_load
|
|
@@ -2336,14 +2421,15 @@ class ASHRAE901PRM < Standard
|
|
|
2336
2421
|
# Make list of zone objects that contain laboratory spaces
|
|
2337
2422
|
lab_zones = []
|
|
2338
2423
|
has_lab_spaces = {}
|
|
2339
|
-
model.getThermalZones.
|
|
2424
|
+
model.getThermalZones.each do |zone|
|
|
2340
2425
|
# Check if this zone includes laboratory space
|
|
2341
2426
|
zone.spaces.each do |space|
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2427
|
+
space_type = prm_get_optional_handler(space, @sizing_run_dir, 'spaceType', 'standardsSpaceType')
|
|
2428
|
+
zone_name = zone.name.get
|
|
2429
|
+
has_lab_spaces[zone_name] = false
|
|
2430
|
+
if space_type == 'laboratory'
|
|
2345
2431
|
lab_zones << zone
|
|
2346
|
-
has_lab_spaces[
|
|
2432
|
+
has_lab_spaces[zone_name] = true
|
|
2347
2433
|
break
|
|
2348
2434
|
end
|
|
2349
2435
|
end
|
|
@@ -2371,17 +2457,16 @@ class ASHRAE901PRM < Standard
|
|
|
2371
2457
|
# Take from hourly reports created during sizing run
|
|
2372
2458
|
node_list.each do |node_name, zone_name|
|
|
2373
2459
|
sql = model.sqlFile
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
end
|
|
2460
|
+
prm_raise(sql.is_initialized, @sizing_run_dir, 'Model is missing SQL file. It is likely caused by: 1. unsuccessful simulation, 2. SQL is not set as one of the output file.')
|
|
2461
|
+
sql = sql.get
|
|
2462
|
+
query = "SELECT ReportDataDictionaryIndex FROM ReportDataDictionary WHERE KeyValue = '#{node_name}' COLLATE NOCASE"
|
|
2463
|
+
val = sql.execAndReturnFirstDouble(query)
|
|
2464
|
+
prm_raise(val.is_initialized, @sizing_run_dir, "No hourly return air flow data reported for node #{node_name}")
|
|
2465
|
+
report_data_dict_index = val.get
|
|
2466
|
+
query = "SELECT MAX(Value) FROM ReportData WHERE ReportDataDictionaryIndex = '#{report_data_dict_index}'"
|
|
2467
|
+
val = sql.execAndReturnFirstDouble(query)
|
|
2468
|
+
prm_raise(val.is_initialized, @sizing_run_dir, "No hourly return air flow data reported at report index #{report_data_dict_index}")
|
|
2469
|
+
zone_return_flow_si[zone_name] += OpenStudio::OptionalDouble.new(val.get).to_f
|
|
2385
2470
|
end
|
|
2386
2471
|
|
|
2387
2472
|
# Calc ratio of Air Loop relief to sum of zone return for each air loop
|
|
@@ -2390,24 +2475,23 @@ class ASHRAE901PRM < Standard
|
|
|
2390
2475
|
# For each air loop, get relief air flow and calculate lab exhaust from the central air handler
|
|
2391
2476
|
# Take from hourly reports created during sizing run
|
|
2392
2477
|
zone_relief_flow_si = {}
|
|
2393
|
-
model.getAirLoopHVACs.
|
|
2478
|
+
model.getAirLoopHVACs.each do |air_loop_hvac|
|
|
2394
2479
|
# First get relief air flow from sizing run sql file
|
|
2395
|
-
relief_node = air_loop_hvac
|
|
2480
|
+
relief_node = prm_get_optional_handler(air_loop_hvac, @sizing_run_dir, 'reliefAirNode')
|
|
2396
2481
|
node_name = relief_node.nameString
|
|
2397
2482
|
relief_flow_si = 0
|
|
2398
2483
|
relief_fraction = 0
|
|
2399
2484
|
sql = model.sqlFile
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
end
|
|
2409
|
-
relief_flow_si = result.to_f
|
|
2485
|
+
prm_raise(sql.is_initialized, @sizing_run_dir, 'Model is missing SQL file. It is likely caused by: 1. unsuccessful simulation, 2. SQL is not set as one of the output file.')
|
|
2486
|
+
sql = sql.get
|
|
2487
|
+
query = "SELECT ReportDataDictionaryIndex FROM ReportDataDictionary WHERE KeyValue = '#{node_name}' COLLATE NOCASE"
|
|
2488
|
+
val = sql.execAndReturnFirstDouble(query)
|
|
2489
|
+
query = "SELECT MAX(Value) FROM ReportData WHERE ReportDataDictionaryIndex = '#{val.get}'"
|
|
2490
|
+
val = sql.execAndReturnFirstDouble(query)
|
|
2491
|
+
if val.is_initialized
|
|
2492
|
+
result = OpenStudio::OptionalDouble.new(val.get)
|
|
2410
2493
|
end
|
|
2494
|
+
relief_flow_si = result.to_f
|
|
2411
2495
|
|
|
2412
2496
|
# Get total flow of zones on this air loop
|
|
2413
2497
|
total_zone_return_si = 0
|
|
@@ -2652,11 +2736,11 @@ class ASHRAE901PRM < Standard
|
|
|
2652
2736
|
# Heating fuel is based on climate zone, unless district heat is in proposed
|
|
2653
2737
|
#
|
|
2654
2738
|
# @note Select system type from data table base on key parameters
|
|
2655
|
-
# @param climate_zone [
|
|
2656
|
-
# @param sys_group [
|
|
2657
|
-
# @param custom [
|
|
2739
|
+
# @param climate_zone [String] id code for the climate
|
|
2740
|
+
# @param sys_group [Hash] Hash defining a group of zones that have the same Appendix G system type
|
|
2741
|
+
# @param custom [String] included here for backwards compatibility (not used here)
|
|
2658
2742
|
# @param hvac_building_type [String] Chosen by user via measure interface or user data files
|
|
2659
|
-
# @param district_heat_zones [
|
|
2743
|
+
# @param district_heat_zones [Hash] of zone name => true for has district heat, false for has not
|
|
2660
2744
|
# @return [String] The system type. Possibilities are PTHP, PTAC, PSZ_AC, PSZ_HP, PVAV_Reheat, PVAV_PFP_Boxes,
|
|
2661
2745
|
# VAV_Reheat, VAV_PFP_Boxes, Gas_Furnace, Electric_Furnace
|
|
2662
2746
|
def model_prm_baseline_system_type(model, climate_zone, sys_group, custom, hvac_building_type, district_heat_zones)
|
|
@@ -2664,26 +2748,23 @@ class ASHRAE901PRM < Standard
|
|
|
2664
2748
|
fuel_type = sys_group['fuel']
|
|
2665
2749
|
area_ft2 = sys_group['building_area_type_ft2']
|
|
2666
2750
|
num_stories = sys_group['stories']
|
|
2667
|
-
zones = sys_group['zones']
|
|
2668
2751
|
|
|
2669
2752
|
# [type, central_heating_fuel, zone_heating_fuel, cooling_fuel]
|
|
2670
2753
|
system_type = [nil, nil, nil, nil]
|
|
2671
2754
|
|
|
2672
2755
|
# Find matching record from prm baseline hvac table
|
|
2673
2756
|
# First filter by number of stories
|
|
2674
|
-
|
|
2757
|
+
i_story_group = 0
|
|
2675
2758
|
props = {}
|
|
2676
2759
|
0.upto(9) do |i|
|
|
2677
|
-
|
|
2760
|
+
i_story_group += 1
|
|
2678
2761
|
props = model_find_object(standards_data['prm_baseline_hvac'],
|
|
2679
2762
|
'template' => template,
|
|
2680
2763
|
'hvac_building_type' => area_type,
|
|
2681
|
-
'flrs_range_group' =>
|
|
2764
|
+
'flrs_range_group' => i_story_group,
|
|
2682
2765
|
'area_range_group' => 1)
|
|
2683
2766
|
|
|
2684
|
-
|
|
2685
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Could not find baseline HVAC type for: #{template}-#{area_type}.")
|
|
2686
|
-
end
|
|
2767
|
+
prm_raise(props, @sizing_run_dir, "Could not find baseline HVAC type for: #{template}-#{area_type}.")
|
|
2687
2768
|
if num_stories <= props['bldg_flrs_max']
|
|
2688
2769
|
# Story Group Is found
|
|
2689
2770
|
break
|
|
@@ -2691,19 +2772,16 @@ class ASHRAE901PRM < Standard
|
|
|
2691
2772
|
end
|
|
2692
2773
|
|
|
2693
2774
|
# Next filter by floor area
|
|
2694
|
-
|
|
2695
|
-
baseine_is_found = false
|
|
2775
|
+
i_area_group = 0
|
|
2696
2776
|
loop do
|
|
2697
|
-
|
|
2777
|
+
i_area_group += 1
|
|
2698
2778
|
props = model_find_object(standards_data['prm_baseline_hvac'],
|
|
2699
2779
|
'template' => template,
|
|
2700
2780
|
'hvac_building_type' => area_type,
|
|
2701
|
-
'flrs_range_group' =>
|
|
2702
|
-
'area_range_group' =>
|
|
2781
|
+
'flrs_range_group' => i_story_group,
|
|
2782
|
+
'area_range_group' => i_area_group)
|
|
2703
2783
|
|
|
2704
|
-
|
|
2705
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Could not find baseline HVAC type for: #{template}-#{area_type}.")
|
|
2706
|
-
end
|
|
2784
|
+
prm_raise(props && i_area_group <= 9, @sizing_run_dir, "Could not find baseline HVAC type for: #{template}-#{area_type}.")
|
|
2707
2785
|
below_max = false
|
|
2708
2786
|
above_min = false
|
|
2709
2787
|
# check if actual building floor area is within range for this area group
|
|
@@ -2725,12 +2803,8 @@ class ASHRAE901PRM < Standard
|
|
|
2725
2803
|
above_min = true
|
|
2726
2804
|
end
|
|
2727
2805
|
end
|
|
2728
|
-
if
|
|
2729
|
-
|
|
2730
|
-
break
|
|
2731
|
-
end
|
|
2732
|
-
if iAreaGroup > 9
|
|
2733
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Could not find baseline HVAC type for: #{template}-#{area_type}.")
|
|
2806
|
+
if above_min && below_max
|
|
2807
|
+
# break condition.
|
|
2734
2808
|
break
|
|
2735
2809
|
end
|
|
2736
2810
|
end
|
|
@@ -2790,8 +2864,8 @@ class ASHRAE901PRM < Standard
|
|
|
2790
2864
|
|
|
2791
2865
|
# For a multizone system, create the fan schedule based on zone occupancy/fan schedules
|
|
2792
2866
|
# @author Doug Maddox, PNNL
|
|
2793
|
-
# @param model
|
|
2794
|
-
# @param
|
|
2867
|
+
# @param model [OpenStudio::Model::Model] openstudio model
|
|
2868
|
+
# @param zone_op_hrs [Hash] of hash of zoneName zone_op_hrs
|
|
2795
2869
|
# @param pri_zones [Array<String>] names of zones served by the multizone system
|
|
2796
2870
|
# @param system_name [String] name of air loop
|
|
2797
2871
|
def model_create_multizone_fan_schedule(model, zone_op_hrs, pri_zones, system_name)
|
|
@@ -2823,7 +2897,7 @@ class ASHRAE901PRM < Standard
|
|
|
2823
2897
|
else
|
|
2824
2898
|
fan_sch_limits = fan_sch_limits.get
|
|
2825
2899
|
end
|
|
2826
|
-
sch_name = system_name
|
|
2900
|
+
sch_name = "#{system_name} fan schedule"
|
|
2827
2901
|
make_ruleset_sched_from_8760(model, fan_8760, sch_name, fan_sch_limits)
|
|
2828
2902
|
|
|
2829
2903
|
air_loop = model.getAirLoopHVACByName(system_name).get
|
|
@@ -2836,9 +2910,9 @@ class ASHRAE901PRM < Standard
|
|
|
2836
2910
|
# @author Doug Maddox, PNNL
|
|
2837
2911
|
# @param model
|
|
2838
2912
|
# @param zones [Array<Object>]
|
|
2839
|
-
# @param zone_fan_scheds [Hash] hash of zoneName
|
|
2913
|
+
# @param zone_fan_scheds [Hash] hash of zoneName 8760FanSchedPerZone
|
|
2840
2914
|
# @return [Hash] A hash of two arrays of ThermalZones,
|
|
2841
|
-
#
|
|
2915
|
+
# where the keys are 'primary' and 'secondary'
|
|
2842
2916
|
def model_differentiate_primary_secondary_thermal_zones(model, zones, zone_fan_scheds)
|
|
2843
2917
|
pri_zones = []
|
|
2844
2918
|
sec_zones = []
|
|
@@ -3015,7 +3089,7 @@ class ASHRAE901PRM < Standard
|
|
|
3015
3089
|
# to account for recent model changes
|
|
3016
3090
|
# @author Doug Maddox, PNNL
|
|
3017
3091
|
# @param model
|
|
3018
|
-
# @return [
|
|
3092
|
+
# @return [Boolean] returns true if successful, false if not
|
|
3019
3093
|
def model_refine_size_dependent_values(model, sizing_run_dir)
|
|
3020
3094
|
# Final sizing run before refining size-dependent values
|
|
3021
3095
|
if model_run_sizing_run(model, "#{sizing_run_dir}/SR3") == false
|
|
@@ -3044,4 +3118,47 @@ class ASHRAE901PRM < Standard
|
|
|
3044
3118
|
end
|
|
3045
3119
|
return true
|
|
3046
3120
|
end
|
|
3121
|
+
|
|
3122
|
+
# Determine whether heating type is fuel or electric
|
|
3123
|
+
# @param hvac_building_type [String] Key for lookup of baseline system type
|
|
3124
|
+
# @param climate_zone [String] full name of climate zone
|
|
3125
|
+
# @return [String] fuel or electric
|
|
3126
|
+
def find_prm_heat_type(hvac_building_type, climate_zone)
|
|
3127
|
+
climate_code = get_climate_zone_code(climate_zone)
|
|
3128
|
+
heat_type_props = model_find_object(standards_data['prm_heat_type'],
|
|
3129
|
+
'template' => template,
|
|
3130
|
+
'hvac_building_type' => hvac_building_type,
|
|
3131
|
+
'climate_zone' => climate_code)
|
|
3132
|
+
if !heat_type_props
|
|
3133
|
+
# try again with wild card for climate
|
|
3134
|
+
heat_type_props = model_find_object(standards_data['prm_heat_type'],
|
|
3135
|
+
'template' => template,
|
|
3136
|
+
'hvac_building_type' => hvac_building_type,
|
|
3137
|
+
'climate_zone' => 'any')
|
|
3138
|
+
end
|
|
3139
|
+
|
|
3140
|
+
if !heat_type_props
|
|
3141
|
+
# try again with wild card for building type
|
|
3142
|
+
heat_type_props = model_find_object(standards_data['prm_heat_type'],
|
|
3143
|
+
'template' => template,
|
|
3144
|
+
'hvac_building_type' => 'all others',
|
|
3145
|
+
'climate_zone' => climate_code)
|
|
3146
|
+
end
|
|
3147
|
+
prm_raise(heat_type_props, @sizing_run_dir, "Could not find baseline heat type for: #{template}-#{hvac_building_type}-#{climate_zone}.")
|
|
3148
|
+
return heat_type_props['heat_type']
|
|
3149
|
+
end
|
|
3150
|
+
|
|
3151
|
+
private
|
|
3152
|
+
|
|
3153
|
+
# Check if the PRM process uses user data. The function returns a hash when
|
|
3154
|
+
# 1. There is a matching user data
|
|
3155
|
+
# 2. The matching user data is not nil saved in the @standards_data
|
|
3156
|
+
# 3. The matching user data hash is not empty
|
|
3157
|
+
# The function returns nil if none of the above matched.
|
|
3158
|
+
#
|
|
3159
|
+
# @param user_data_csv [String] the name of the user data csv file
|
|
3160
|
+
# @return [hash | nil] Returns hash or nil.
|
|
3161
|
+
def get_userdata(user_data_csv)
|
|
3162
|
+
return @standards_data.key?(user_data_csv) && @standards_data[user_data_csv].length >= 1 ? @standards_data[user_data_csv] : nil
|
|
3163
|
+
end
|
|
3047
3164
|
end
|