openstudio-standards 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.md +33 -0
- 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 +2170 -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 +54 -18
- data/License.txt +0 -65
- 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
|