openstudio-standards 0.2.16 → 0.2.17.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/standards/manage_OpenStudio_Standards.rb +31 -4
- data/lib/openstudio-standards/btap/geometry.rb +1 -1
- data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +354 -2
- data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +79 -0
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +3313 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +12 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +3 -4
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +167 -93
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +2 -4
- data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +1 -0
- data/lib/openstudio-standards/refs/references.rb +3 -0
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +279 -6
- data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +50 -2
- data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +4 -0
- data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -1
- data/lib/openstudio-standards/standards/Standards.Construction.rb +185 -3
- data/lib/openstudio-standards/standards/Standards.Fan.rb +14 -6
- data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +1 -0
- data/lib/openstudio-standards/standards/Standards.Model.rb +1751 -383
- data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +130 -9
- data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +50 -3
- data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +44 -0
- data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +27 -0
- data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +543 -0
- data/lib/openstudio-standards/standards/Standards.Space.rb +665 -15
- data/lib/openstudio-standards/standards/Standards.SpaceType.rb +141 -4
- data/lib/openstudio-standards/standards/Standards.SubSurface.rb +2 -1
- data/lib/openstudio-standards/standards/Standards.Surface.rb +117 -0
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +197 -49
- data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +41 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +6 -8
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/comstock_ashrae_90_1_2004.spc_typ.json +7 -7
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/comstock_ashrae_90_1_2007.spc_typ.json +7 -7
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/comstock_ashrae_90_1_2010.spc_typ.json +9 -9
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/comstock_ashrae_90_1_2013.spc_typ.json +4 -4
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/comstock_ashrae_90_1_2016.spc_typ.json +5 -5
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +5 -5
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/comstock_ashrae_90_1_2019.spc_typ.json +5 -5
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.fans.json +12 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/comstock_doe_ref_1980_2004.spc_typ.json +10 -10
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/ashrae_90_1.schedules.json +45 -45
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/comstock_doe_ref_pre_1980.spc_typ.json +10 -10
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +792 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +10 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +31 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +91 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +84 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +145 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +106 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +71 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +194 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +120 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +110 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Fan.rb +73 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +24 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanZoneExhaust.rb +5 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +55 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +3045 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +187 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +450 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +106 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +666 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +54 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +168 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +132 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +239 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +176 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +25 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +52 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.chillers.json +112 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.climate_zone_sets.json +210 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +10384 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_sets.json +133 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.furnaces.json +43 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_pumps.json +119 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_pumps_heating.json +130 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_rejection.json +13 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.lpd_space_type.json +568 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.motors.json +264 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_baseline_hvac.json +439 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_constructions.json +685 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_economizers.json +213 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_ext_ltg.json +32 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_heat_type.json +136 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_hvac_bldg_type.json +32 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json +1837 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_swh_bldg_type.json +184 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_wwr_bldg_type.json +84 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.unitary_acs.json +148 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.water_heaters.json +157 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.climate_zone_sets.json +210 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.curves.json +18329 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.fans.json +340 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.materials.json +49924 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_building_rotation_exception.md +44 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/check_pump_power_and_control.md +71 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv.md +68 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv_implementation.png +0 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/elevators.md +14 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/exhaust_air_energy_recovery.md +36 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/f_c_factors.md +19 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/fan_power_credits.md +15 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/preheat_coil.md +59 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/pump_power_control.md +46 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/return_air_type.md +31 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_baseline_wwr.md +191 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_hw_and_chw_supply_water_temp_reset_control.md +24 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_num_boilers_chillers_towers.md +49 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +80 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_space_lpd.md +73 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unenclosed_and_unconditioned_spaces.md +11 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unmet_load_hours.md +20 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_parallel_piu_terminals_fan_control.md +23 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_terminals_min_flow_setpoint.md +21 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac_doas.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_building.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_design_specification_outdoor_air.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_electric_equipment.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_exterior_lights.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_gas_equipment.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_lights.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_spacetype.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_thermal_zone.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_connections.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment_definition.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_hvac.csv +1 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_infiltration.csv +1 -0
- data/lib/openstudio-standards/standards/cbes/data/cbes.fans.json +12 -0
- data/lib/openstudio-standards/standards/deer/data/deer.fans.json +12 -0
- data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps.json +1 -1
- data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps_heating.json +1 -1
- data/lib/openstudio-standards/standards/necb/ECMS/data/unitary_acs.json +24 -11
- data/lib/openstudio-standards/standards/necb/ECMS/erv.rb +13 -15
- data/lib/openstudio-standards/standards/necb/NECB2011/data/province_map.json +17 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +2 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +6 -5
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +3 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +2 -3
- data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +2 -2
- data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +33 -924
- data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +15 -15
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +135 -29
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +16 -4
- data/lib/openstudio-standards/standards/necb/common/neb_end_use_prices.csv +40 -42
- data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +1 -1
- data/lib/openstudio-standards/standards/necb/common/space_type_upgrade_map.json +89 -89
- data/lib/openstudio-standards/utilities/array.rb +11 -0
- data/lib/openstudio-standards/utilities/logging.rb +48 -0
- data/lib/openstudio-standards/utilities/object_info.rb +20 -0
- data/lib/openstudio-standards/utilities/schedule_translator.rb +348 -0
- data/lib/openstudio-standards/utilities/sqlfile.rb +68 -0
- data/lib/openstudio-standards/version.rb +2 -2
- data/lib/openstudio-standards/weather/Weather.Model.rb +42 -55
- data/lib/openstudio-standards/weather/Weather.stat_file.rb +1 -1
- data/lib/openstudio-standards.rb +35 -1
- metadata +111 -6
- data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
- data/data/standards/OpenStudio_Standards-ashrae_90_1_28Jan2022.xlsx +0 -0
- data/data/standards/OpenStudio_Standards-ashrae_90_1_28_Jan2022_2.xlsx +0 -0
- data/data/standards/openstudio_standards_duplicates_log.csv +0 -143
@@ -0,0 +1,187 @@
|
|
1
|
+
class ASHRAE901PRM < Standard
|
2
|
+
# @!group PlanarSurface
|
3
|
+
|
4
|
+
# If construction properties can be found based on the template,
|
5
|
+
# the standards intended surface type, the standards construction type,
|
6
|
+
# the climate zone, and the occupancy type,
|
7
|
+
# create a construction that meets those properties and assign it to this surface.
|
8
|
+
# 90.1-PRM-2019
|
9
|
+
#
|
10
|
+
# @param planar_surface [Openstudio::Model:PlanarSurface] surface object
|
11
|
+
# @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
|
12
|
+
# @param previous_construction_map [Hash] a hash where the keys are an array of inputs
|
13
|
+
# [template, climate_zone, intended_surface_type, standards_construction_type, occ_type]
|
14
|
+
# and the values are the constructions. If supplied, constructions will be pulled
|
15
|
+
# from this hash if already created to avoid creating duplicate constructions.
|
16
|
+
# @return [Hash] returns a hash where the key is an array of inputs
|
17
|
+
# [template, climate_zone, intended_surface_type, standards_construction_type, occ_type]
|
18
|
+
# and the value is the newly created construction.
|
19
|
+
# This can be used to avoid creating duplicate constructions.
|
20
|
+
# @todo Align the standard construction enumerations in the
|
21
|
+
# spreadsheet with the enumerations in OpenStudio (follow CBECC-Com).
|
22
|
+
def planar_surface_apply_standard_construction(planar_surface, climate_zone, previous_construction_map = {}, wwr_building_type = nil, wwr_info = {}, surface_category)
|
23
|
+
# Skip surfaces not in a space
|
24
|
+
return previous_construction_map if planar_surface.space.empty?
|
25
|
+
|
26
|
+
space = planar_surface.space.get
|
27
|
+
if surface_category == 'ExteriorSubSurface'
|
28
|
+
surface_type = planar_surface.subSurfaceType
|
29
|
+
else
|
30
|
+
surface_type = planar_surface.surfaceType
|
31
|
+
end
|
32
|
+
|
33
|
+
# Skip surfaces that don't have a construction
|
34
|
+
# return previous_construction_map if planar_surface.construction.empty?
|
35
|
+
if !planar_surface.construction.empty?
|
36
|
+
construction = planar_surface.construction.get
|
37
|
+
else
|
38
|
+
# Get appropriate default construction if not defined inside surface object
|
39
|
+
construction = nil
|
40
|
+
space_type = space.spaceType.get
|
41
|
+
if space.defaultConstructionSet.is_initialized
|
42
|
+
cons_set = space.defaultConstructionSet.get
|
43
|
+
construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
|
44
|
+
end
|
45
|
+
if construction.nil? && space_type.defaultConstructionSet.is_initialized
|
46
|
+
cons_set = space_type.defaultConstructionSet.get
|
47
|
+
construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
|
48
|
+
end
|
49
|
+
if construction.nil? && space.buildingStory.get.defaultConstructionSet.is_initialized
|
50
|
+
cons_set = space.buildingStory.get.defaultConstructionSet.get
|
51
|
+
construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
|
52
|
+
end
|
53
|
+
if construction.nil? && space.model.building.get.defaultConstructionSet.is_initialized
|
54
|
+
cons_set = space.model.building.get.defaultConstructionSet.get
|
55
|
+
construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
|
56
|
+
end
|
57
|
+
|
58
|
+
return previous_construction_map if construction.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Determine if residential or nonresidential
|
62
|
+
# based on the space type.
|
63
|
+
occ_type = 'Nonresidential'
|
64
|
+
if space_residential?(space)
|
65
|
+
occ_type = 'Residential'
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get the climate zone set
|
69
|
+
climate_zone_set = model_find_climate_zone_set(planar_surface.model, climate_zone)
|
70
|
+
|
71
|
+
# Get the intended surface type
|
72
|
+
standards_info = construction.standardsInformation
|
73
|
+
surf_type = standards_info.intendedSurfaceType
|
74
|
+
|
75
|
+
if surf_type.empty?
|
76
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not determine the intended surface type for #{planar_surface.name} from #{construction.name}. This surface will not have the standard applied.")
|
77
|
+
return previous_construction_map
|
78
|
+
end
|
79
|
+
surf_type = surf_type.get
|
80
|
+
|
81
|
+
# Get the standards type, which is based on different fields
|
82
|
+
# if is intended for a window, a skylight, or something else.
|
83
|
+
# Mapping is between standards-defined enumerations and the
|
84
|
+
# enumerations available in OpenStudio.
|
85
|
+
stds_type = nil
|
86
|
+
# Windows and Glass Doors
|
87
|
+
if surf_type == 'ExteriorWindow' || surf_type == 'GlassDoor'
|
88
|
+
stds_type = standards_info.fenestrationFrameType
|
89
|
+
if stds_type.is_initialized
|
90
|
+
stds_type = stds_type.get
|
91
|
+
if !wwr_building_type.nil?
|
92
|
+
stds_type = 'Any Vertical Glazing'
|
93
|
+
end
|
94
|
+
case stds_type
|
95
|
+
when 'Metal Framing', 'Metal Framing with Thermal Break'
|
96
|
+
stds_type = 'Metal framing (all other)'
|
97
|
+
when 'Non-Metal Framing'
|
98
|
+
stds_type = 'Nonmetal framing (all)'
|
99
|
+
when 'Any Vertical Glazing'
|
100
|
+
stds_type = 'Any Vertical Glazing'
|
101
|
+
else
|
102
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "The standards fenestration frame type #{stds_type} cannot be used on #{surf_type} in #{planar_surface.name}. This surface will not have the standard applied.")
|
103
|
+
return previous_construction_map
|
104
|
+
end
|
105
|
+
else
|
106
|
+
if !wwr_building_type.nil?
|
107
|
+
stds_type = 'Any Vertical Glazing'
|
108
|
+
else
|
109
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not determine the standards fenestration frame type for #{planar_surface.name} from #{construction.name}. This surface will not have the standard applied.")
|
110
|
+
return previous_construction_map
|
111
|
+
end
|
112
|
+
end
|
113
|
+
# Exterior Doors
|
114
|
+
elsif surf_type == 'ExteriorDoor'
|
115
|
+
stds_type = standards_info.standardsConstructionType
|
116
|
+
if stds_type.is_initialized
|
117
|
+
stds_type = stds_type.get
|
118
|
+
case stds_type
|
119
|
+
when 'RollUp'
|
120
|
+
stds_type = 'NonSwinging'
|
121
|
+
end
|
122
|
+
else
|
123
|
+
stds_type = 'Swinging'
|
124
|
+
end
|
125
|
+
# Skylights
|
126
|
+
elsif surf_type == 'Skylight'
|
127
|
+
# There is only one type for AppendixG stable baseline
|
128
|
+
stds_type = 'Any Skylight'
|
129
|
+
# All other surface types
|
130
|
+
else
|
131
|
+
stds_type = standards_info.standardsConstructionType
|
132
|
+
if stds_type.is_initialized
|
133
|
+
stds_type = stds_type.get
|
134
|
+
else
|
135
|
+
if planar_surface.outsideBoundaryCondition == 'Surface' && surface_category == 'NA'
|
136
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlanarSurface', "Standards construction is not needed and not applied for interior wall: #{planar_surface.name}.")
|
137
|
+
else
|
138
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not determine the standards construction type for #{planar_surface.name}. This surface will not have the standard applied.")
|
139
|
+
end
|
140
|
+
return previous_construction_map
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Check if the construction type was already created.
|
145
|
+
# If yes, use that construction. If no, make a new one.
|
146
|
+
|
147
|
+
# for multi-building type - search for the surface wwr type
|
148
|
+
surface_std_wwr_type = wwr_building_type
|
149
|
+
new_construction = nil
|
150
|
+
type = [template, climate_zone, surf_type, stds_type, occ_type]
|
151
|
+
# Only apply the surface_std_wwr_type update when wwr_building_type has Truthy values
|
152
|
+
if !wwr_building_type.nil? && (surf_type == 'ExteriorWindow' || surf_type == 'GlassDoor')
|
153
|
+
space = planar_surface.space.get
|
154
|
+
if space.hasAdditionalProperties && space.additionalProperties.hasFeature('building_type_for_wwr')
|
155
|
+
surface_std_wwr_type = space.additionalProperties.getFeatureAsString('building_type_for_wwr').get
|
156
|
+
end
|
157
|
+
type.push(surface_std_wwr_type)
|
158
|
+
end
|
159
|
+
|
160
|
+
if previous_construction_map[type] && !previous_construction_map[type].iddObjectType.valueName.to_s.include?('factorGround')
|
161
|
+
new_construction = previous_construction_map[type]
|
162
|
+
else
|
163
|
+
new_construction = model_find_and_add_construction(planar_surface.model,
|
164
|
+
climate_zone_set,
|
165
|
+
surf_type,
|
166
|
+
stds_type,
|
167
|
+
occ_type,
|
168
|
+
wwr_building_type: surface_std_wwr_type,
|
169
|
+
wwr_info: wwr_info,
|
170
|
+
surface: planar_surface)
|
171
|
+
if !new_construction == false
|
172
|
+
previous_construction_map[type] = new_construction
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Assign the new construction to the surface
|
177
|
+
if new_construction
|
178
|
+
planar_surface.setConstruction(new_construction)
|
179
|
+
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.PlanarSurface', "Set the construction for #{planar_surface.name} to #{new_construction.name}.")
|
180
|
+
else
|
181
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not generate a standard construction for #{planar_surface.name}.")
|
182
|
+
return previous_construction_map
|
183
|
+
end
|
184
|
+
|
185
|
+
return previous_construction_map
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,450 @@
|
|
1
|
+
class ASHRAE901PRM < Standard
|
2
|
+
# Keep only one cooling tower, but use one condenser pump per chiller
|
3
|
+
|
4
|
+
# @param plant_loop [OpenStudio::Model::PlantLoop] plant loop
|
5
|
+
# @return [Bool] returns true if successful, false if not
|
6
|
+
def plant_loop_apply_prm_number_of_cooling_towers(plant_loop)
|
7
|
+
# Skip non-cooling plants
|
8
|
+
return true unless plant_loop.sizingPlant.loopType == 'Condenser'
|
9
|
+
|
10
|
+
# Determine the number of chillers
|
11
|
+
# already in the model
|
12
|
+
num_chillers = plant_loop.model.getChillerElectricEIRs.size
|
13
|
+
|
14
|
+
# Get all existing cooling towers and pumps
|
15
|
+
clg_twrs = []
|
16
|
+
pumps = []
|
17
|
+
plant_loop.supplyComponents.each do |sc|
|
18
|
+
if sc.to_CoolingTowerSingleSpeed.is_initialized
|
19
|
+
clg_twrs << sc.to_CoolingTowerSingleSpeed.get
|
20
|
+
elsif sc.to_CoolingTowerTwoSpeed.is_initialized
|
21
|
+
clg_twrs << sc.to_CoolingTowerTwoSpeed.get
|
22
|
+
elsif sc.to_CoolingTowerVariableSpeed.is_initialized
|
23
|
+
clg_twrs << sc.to_CoolingTowerVariableSpeed.get
|
24
|
+
elsif sc.to_PumpConstantSpeed.is_initialized
|
25
|
+
pumps << sc.to_PumpConstantSpeed.get
|
26
|
+
elsif sc.to_PumpVariableSpeed.is_initialized
|
27
|
+
pumps << sc.to_PumpVariableSpeed.get
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Ensure there is only 1 cooling tower to start
|
32
|
+
orig_twr = nil
|
33
|
+
if clg_twrs.size.zero?
|
34
|
+
return true
|
35
|
+
elsif clg_twrs.size > 1
|
36
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, found #{clg_twrs.size} cooling towers, cannot split up per performance rating method baseline requirements.")
|
37
|
+
return false
|
38
|
+
else
|
39
|
+
orig_twr = clg_twrs[0]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Ensure there is only 1 pump to start
|
43
|
+
orig_pump = nil
|
44
|
+
if pumps.size.zero?
|
45
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, found #{pumps.size} pumps. A loop must have at least one pump.")
|
46
|
+
return false
|
47
|
+
elsif pumps.size > 1
|
48
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, found #{pumps.size} pumps, cannot split up per performance rating method baseline requirements.")
|
49
|
+
return false
|
50
|
+
else
|
51
|
+
orig_pump = pumps[0]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Determine the per-cooling_tower sizing factor
|
55
|
+
clg_twr_sizing_factor = (1.0 / num_chillers).round(2)
|
56
|
+
|
57
|
+
final_twrs = [orig_twr]
|
58
|
+
|
59
|
+
# If there is more than one chiller,
|
60
|
+
# replace the original pump with a headered pump
|
61
|
+
# of the same type and properties.
|
62
|
+
if num_chillers > 1
|
63
|
+
num_pumps = num_chillers
|
64
|
+
new_pump = nil
|
65
|
+
if orig_pump.to_PumpConstantSpeed.is_initialized
|
66
|
+
new_pump = OpenStudio::Model::HeaderedPumpsConstantSpeed.new(plant_loop.model)
|
67
|
+
new_pump.setNumberofPumpsinBank(num_pumps)
|
68
|
+
new_pump.setName("#{orig_pump.name} Bank of #{num_pumps}")
|
69
|
+
new_pump.setRatedPumpHead(orig_pump.ratedPumpHead)
|
70
|
+
new_pump.setMotorEfficiency(orig_pump.motorEfficiency)
|
71
|
+
new_pump.setFractionofMotorInefficienciestoFluidStream(orig_pump.fractionofMotorInefficienciestoFluidStream)
|
72
|
+
new_pump.setPumpControlType(orig_pump.pumpControlType)
|
73
|
+
elsif orig_pump.to_PumpVariableSpeed.is_initialized
|
74
|
+
new_pump = OpenStudio::Model::HeaderedPumpsVariableSpeed.new(plant_loop.model)
|
75
|
+
new_pump.setNumberofPumpsinBank(num_pumps)
|
76
|
+
new_pump.setName("#{orig_pump.name} Bank of #{num_pumps}")
|
77
|
+
new_pump.setRatedPumpHead(orig_pump.ratedPumpHead)
|
78
|
+
new_pump.setMotorEfficiency(orig_pump.motorEfficiency)
|
79
|
+
new_pump.setFractionofMotorInefficienciestoFluidStream(orig_pump.fractionofMotorInefficienciestoFluidStream)
|
80
|
+
new_pump.setPumpControlType(orig_pump.pumpControlType)
|
81
|
+
new_pump.setCoefficient1ofthePartLoadPerformanceCurve(orig_pump.coefficient1ofthePartLoadPerformanceCurve)
|
82
|
+
new_pump.setCoefficient2ofthePartLoadPerformanceCurve(orig_pump.coefficient2ofthePartLoadPerformanceCurve)
|
83
|
+
new_pump.setCoefficient3ofthePartLoadPerformanceCurve(orig_pump.coefficient3ofthePartLoadPerformanceCurve)
|
84
|
+
new_pump.setCoefficient4ofthePartLoadPerformanceCurve(orig_pump.coefficient4ofthePartLoadPerformanceCurve)
|
85
|
+
end
|
86
|
+
# Remove the old pump
|
87
|
+
orig_pump.remove
|
88
|
+
# Attach the new headered pumps
|
89
|
+
new_pump.addToNode(plant_loop.supplyInletNode)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Get the total cooling capacity for the plant loop
|
94
|
+
#
|
95
|
+
# @param plant_loop [OpenStudio::Model::PlantLoop] plant loop
|
96
|
+
# @param [String] sizing_run_dir
|
97
|
+
# @return [Double] total cooling capacity in watts
|
98
|
+
def plant_loop_total_cooling_capacity(plant_loop, sizing_run_dir = Dir.pwd)
|
99
|
+
# Sum the cooling capacity for all cooling components
|
100
|
+
# on the plant loop.
|
101
|
+
total_cooling_capacity_w = 0
|
102
|
+
sizing_run_ran = false
|
103
|
+
|
104
|
+
plant_loop.supplyComponents.each do |sc|
|
105
|
+
# ChillerElectricEIR
|
106
|
+
if sc.to_ChillerElectricEIR.is_initialized
|
107
|
+
chiller = sc.to_ChillerElectricEIR.get
|
108
|
+
|
109
|
+
# If chiller is autosized, check sizing run results. If sizing run not ran, run it first
|
110
|
+
if chiller.isReferenceCapacityAutosized
|
111
|
+
model = chiller.model
|
112
|
+
sizing_run_ran = model_run_sizing_run(model, "#{sizing_run_dir}/SR_cooling_plant") if !sizing_run_ran
|
113
|
+
|
114
|
+
if sizing_run_ran
|
115
|
+
sizing_run_capacity = model.getAutosizedValueFromEquipmentSummary(chiller, 'Central Plant', 'Nominal Capacity', 'W').get
|
116
|
+
chiller.setReferenceCapacity(sizing_run_capacity)
|
117
|
+
total_cooling_capacity_w += sizing_run_capacity
|
118
|
+
else
|
119
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{plant_loop.name} capacity of #{chiller.name} is not available due to a sizing run failure, total cooling capacity of plant loop will be incorrect when applying standard.")
|
120
|
+
end
|
121
|
+
|
122
|
+
elsif chiller.referenceCapacity.is_initialized
|
123
|
+
total_cooling_capacity_w += chiller.referenceCapacity.get
|
124
|
+
elsif chiller.autosizedReferenceCapacity.is_initialized
|
125
|
+
total_cooling_capacity_w += chiller.autosizedReferenceCapacity.get
|
126
|
+
else
|
127
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{plant_loop.name} capacity of #{chiller.name} is not available, total cooling capacity of plant loop will be incorrect when applying standard.")
|
128
|
+
end
|
129
|
+
# DistrictCooling
|
130
|
+
elsif sc.to_DistrictCooling.is_initialized
|
131
|
+
dist_clg = sc.to_DistrictCooling.get
|
132
|
+
if dist_clg.nominalCapacity.is_initialized
|
133
|
+
total_cooling_capacity_w += dist_clg.nominalCapacity.get
|
134
|
+
elsif dist_clg.autosizedNominalCapacity.is_initialized
|
135
|
+
total_cooling_capacity_w += dist_clg.autosizedNominalCapacity.get
|
136
|
+
else
|
137
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{plant_loop.name} capacity of DistrictCooling #{dist_clg.name} is not available, total heating capacity of plant loop will be incorrect when applying standard.")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
total_cooling_capacity_tons = OpenStudio.convert(total_cooling_capacity_w, 'W', 'ton').get
|
143
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, cooling capacity is #{total_cooling_capacity_tons.round} tons of refrigeration.")
|
144
|
+
|
145
|
+
return total_cooling_capacity_w
|
146
|
+
end
|
147
|
+
|
148
|
+
# Splits the single chiller used for the initial sizing run
|
149
|
+
# into multiple separate chillers based on Appendix G.
|
150
|
+
#
|
151
|
+
# @param plant_loop_args [Array] chilled water loop (OpenStudio::Model::PlantLoop), sizing run directory
|
152
|
+
# @return [Bool] returns true if successful, false if not
|
153
|
+
def plant_loop_apply_prm_number_of_chillers(plant_loop, sizing_run_dir = nil)
|
154
|
+
# Skip non-cooling plants & secondary cooling loop
|
155
|
+
return true unless plant_loop.sizingPlant.loopType == 'Cooling'
|
156
|
+
# If the loop is cooling but it is a secondary loop, then skip.
|
157
|
+
return true if plant_loop.additionalProperties.hasFeature('is_secondary_loop')
|
158
|
+
|
159
|
+
# Determine the number and type of chillers
|
160
|
+
num_chillers = nil
|
161
|
+
chiller_cooling_type = nil
|
162
|
+
chiller_compressor_type = nil
|
163
|
+
|
164
|
+
# Set the equipment to stage sequentially or uniformload if there is secondary loop
|
165
|
+
if plant_loop.additionalProperties.hasFeature('is_primary_loop')
|
166
|
+
plant_loop.setLoadDistributionScheme('UniformLoad')
|
167
|
+
else
|
168
|
+
plant_loop.setLoadDistributionScheme('SequentialLoad')
|
169
|
+
end
|
170
|
+
|
171
|
+
# Determine the capacity of the loop
|
172
|
+
cap_w = plant_loop_total_cooling_capacity(plant_loop, sizing_run_dir)
|
173
|
+
cap_tons = OpenStudio.convert(cap_w, 'W', 'ton').get
|
174
|
+
if cap_tons <= 300
|
175
|
+
num_chillers = 1
|
176
|
+
chiller_cooling_type = 'WaterCooled'
|
177
|
+
chiller_compressor_type = 'Rotary Screw and Scroll'
|
178
|
+
elsif cap_tons > 300 && cap_tons < 600
|
179
|
+
num_chillers = 2
|
180
|
+
chiller_cooling_type = 'WaterCooled'
|
181
|
+
chiller_compressor_type = 'Rotary Screw and Scroll'
|
182
|
+
else
|
183
|
+
# Max capacity of a single chiller
|
184
|
+
max_cap_ton = 800.0
|
185
|
+
num_chillers = (cap_tons / max_cap_ton).floor + 1
|
186
|
+
# Must be at least 2 chillers
|
187
|
+
num_chillers += 1 if num_chillers == 1
|
188
|
+
chiller_cooling_type = 'WaterCooled'
|
189
|
+
chiller_compressor_type = 'Centrifugal'
|
190
|
+
end
|
191
|
+
|
192
|
+
# Get all existing chillers and pumps
|
193
|
+
chillers = []
|
194
|
+
pumps = []
|
195
|
+
plant_loop.supplyComponents.each do |sc|
|
196
|
+
if sc.to_ChillerElectricEIR.is_initialized
|
197
|
+
chillers << sc.to_ChillerElectricEIR.get
|
198
|
+
elsif sc.to_PumpConstantSpeed.is_initialized
|
199
|
+
pumps << sc.to_PumpConstantSpeed.get
|
200
|
+
elsif sc.to_PumpVariableSpeed.is_initialized
|
201
|
+
pumps << sc.to_PumpVariableSpeed.get
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Ensure there is only 1 chiller to start
|
206
|
+
first_chiller = nil
|
207
|
+
return true if chillers.size.zero?
|
208
|
+
|
209
|
+
if chillers.size > 1
|
210
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{chillers.size} chillers, cannot split up per performance rating method baseline requirements.")
|
211
|
+
else
|
212
|
+
first_chiller = chillers[0]
|
213
|
+
end
|
214
|
+
|
215
|
+
# Ensure there is only 1 pump to start
|
216
|
+
orig_pump = nil
|
217
|
+
if pumps.size.zero?
|
218
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{pumps.size} pumps. A loop must have at least one pump.")
|
219
|
+
return false
|
220
|
+
elsif pumps.size > 1
|
221
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{pumps.size} pumps, cannot split up per performance rating method baseline requirements.")
|
222
|
+
return false
|
223
|
+
else
|
224
|
+
orig_pump = pumps[0]
|
225
|
+
end
|
226
|
+
|
227
|
+
# Determine the per-chiller capacity
|
228
|
+
# and sizing factor
|
229
|
+
per_chiller_sizing_factor = (1.0 / num_chillers).round(2)
|
230
|
+
# This is unused
|
231
|
+
per_chiller_cap_tons = cap_tons / num_chillers
|
232
|
+
per_chiller_cap_w = cap_w / num_chillers
|
233
|
+
|
234
|
+
# Set the sizing factor and the chiller type: could do it on the first chiller before cloning it, but renaming warrants looping on chillers anyways
|
235
|
+
|
236
|
+
# Add any new chillers
|
237
|
+
final_chillers = [first_chiller]
|
238
|
+
(num_chillers - 1).times do
|
239
|
+
new_chiller = first_chiller.clone(plant_loop.model)
|
240
|
+
if new_chiller.to_ChillerElectricEIR.is_initialized
|
241
|
+
new_chiller = new_chiller.to_ChillerElectricEIR.get
|
242
|
+
else
|
243
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, could not clone chiller #{first_chiller.name}, cannot apply the performance rating method number of chillers.")
|
244
|
+
return false
|
245
|
+
end
|
246
|
+
# Connect the new chiller to the same CHW loop
|
247
|
+
# as the old chiller.
|
248
|
+
plant_loop.addSupplyBranchForComponent(new_chiller)
|
249
|
+
# Connect the new chiller to the same CW loop
|
250
|
+
# as the old chiller, if it was water-cooled.
|
251
|
+
cw_loop = first_chiller.secondaryPlantLoop
|
252
|
+
if cw_loop.is_initialized
|
253
|
+
cw_loop.get.addDemandBranchForComponent(new_chiller)
|
254
|
+
end
|
255
|
+
|
256
|
+
final_chillers << new_chiller
|
257
|
+
end
|
258
|
+
|
259
|
+
# If there is more than one cooling tower,
|
260
|
+
# add one pump to each chiller, assume chillers are equally sized
|
261
|
+
if final_chillers.size > 1
|
262
|
+
num_pumps = final_chillers.size
|
263
|
+
final_chillers.each do |chiller|
|
264
|
+
if orig_pump.to_PumpConstantSpeed.is_initialized
|
265
|
+
new_pump = OpenStudio::Model::PumpConstantSpeed.new(plant_loop.model)
|
266
|
+
new_pump.setName("#{chiller.name} Primary Pump")
|
267
|
+
# Will need to adjust the pump power after a sizing run
|
268
|
+
new_pump.setRatedPumpHead(orig_pump.ratedPumpHead / num_pumps)
|
269
|
+
new_pump.setMotorEfficiency(0.9)
|
270
|
+
new_pump.setPumpControlType('Intermittent')
|
271
|
+
chiller_inlet_node = chiller.connectedObject(chiller.supplyInletPort).get.to_Node.get
|
272
|
+
new_pump.addToNode(chiller_inlet_node)
|
273
|
+
elsif orig_pump.to_PumpVariableSpeed.is_initialized
|
274
|
+
new_pump = OpenStudio::Model::PumpVariableSpeed.new(plant_loop.model)
|
275
|
+
new_pump.setName("#{chiller.name} Primary Pump")
|
276
|
+
new_pump.setRatedPumpHead(orig_pump.ratedPumpHead / num_pumps)
|
277
|
+
new_pump.setCoefficient1ofthePartLoadPerformanceCurve(orig_pump.coefficient1ofthePartLoadPerformanceCurve)
|
278
|
+
new_pump.setCoefficient2ofthePartLoadPerformanceCurve(orig_pump.coefficient2ofthePartLoadPerformanceCurve)
|
279
|
+
new_pump.setCoefficient3ofthePartLoadPerformanceCurve(orig_pump.coefficient3ofthePartLoadPerformanceCurve)
|
280
|
+
new_pump.setCoefficient4ofthePartLoadPerformanceCurve(orig_pump.coefficient4ofthePartLoadPerformanceCurve)
|
281
|
+
chiller_inlet_node = chiller.connectedObject(chiller.supplyInletPort).get.to_Node.get
|
282
|
+
new_pump.addToNode(chiller_inlet_node)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
# Remove the old pump
|
286
|
+
orig_pump.remove
|
287
|
+
end
|
288
|
+
|
289
|
+
# Set the sizing factor and the chiller types
|
290
|
+
final_chillers.each_with_index do |final_chiller, i|
|
291
|
+
final_chiller.setName("#{template} #{chiller_cooling_type} #{chiller_compressor_type} Chiller #{i + 1} of #{final_chillers.size}")
|
292
|
+
final_chiller.setSizingFactor(per_chiller_sizing_factor)
|
293
|
+
final_chiller.setReferenceCapacity(per_chiller_cap_w)
|
294
|
+
final_chiller.setCondenserType(chiller_cooling_type)
|
295
|
+
final_chiller.additionalProperties.setFeature('compressor_type', chiller_compressor_type)
|
296
|
+
end
|
297
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, there are #{final_chillers.size} #{chiller_cooling_type} #{chiller_compressor_type} chillers.")
|
298
|
+
|
299
|
+
return true
|
300
|
+
end
|
301
|
+
|
302
|
+
# Apply prm baseline pump power
|
303
|
+
# @note I think it makes more sense to sense the motor efficiency right there...
|
304
|
+
# But actually it's completely irrelevant...
|
305
|
+
# you could set at 0.9 and just calculate the pressure rise to have your 19 W/GPM or whatever
|
306
|
+
#
|
307
|
+
# @param plant_loop [OpenStudio::Model::PlantLoop] plant loop
|
308
|
+
# @return [Bool] returns true if successful, false if not
|
309
|
+
def plant_loop_apply_prm_baseline_pump_power(plant_loop)
|
310
|
+
hot_water_pump_power = 19 # W/gpm
|
311
|
+
hot_water_district_pump_power = 14 # W/gpm
|
312
|
+
chilled_water_primary_pump_power = 9 # W/gpm
|
313
|
+
chilled_water_secondary_pump_power = 13 # W/gpm
|
314
|
+
chilled_water_district_pump_power = 16 # W/gpm
|
315
|
+
condenser_water_pump_power = 19 # W/gpm
|
316
|
+
# Determine the pumping power per
|
317
|
+
# flow based on loop type.
|
318
|
+
w_per_gpm = nil
|
319
|
+
chiller_counter = 0
|
320
|
+
|
321
|
+
sizing_plant = plant_loop.sizingPlant
|
322
|
+
loop_type = sizing_plant.loopType
|
323
|
+
|
324
|
+
case loop_type
|
325
|
+
when 'Heating'
|
326
|
+
|
327
|
+
has_district_heating = false
|
328
|
+
plant_loop.supplyComponents.each do |sc|
|
329
|
+
if sc.to_DistrictHeating.is_initialized
|
330
|
+
has_district_heating = true
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
w_per_gpm = if has_district_heating # District HW
|
335
|
+
hot_water_district_pump_power
|
336
|
+
else # HW
|
337
|
+
hot_water_pump_power
|
338
|
+
end
|
339
|
+
|
340
|
+
when 'Cooling'
|
341
|
+
has_district_cooling = false
|
342
|
+
plant_loop.supplyComponents.each do |sc|
|
343
|
+
if sc.to_DistrictCooling.is_initialized
|
344
|
+
has_district_cooling = true
|
345
|
+
elsif sc.to_ChillerElectricEIR.is_initialized
|
346
|
+
chiller_counter += 1
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
if has_district_cooling # District CHW
|
351
|
+
w_per_gpm = chilled_water_district_pump_power
|
352
|
+
elsif plant_loop.additionalProperties.hasFeature('is_primary_loop') # The primary loop of the primary/secondary CHW
|
353
|
+
w_per_gpm = chilled_water_primary_pump_power
|
354
|
+
elsif plant_loop.additionalProperties.hasFeature('is_secondary_loop') # The secondary loop of the primary/secondary CHW
|
355
|
+
w_per_gpm = chilled_water_secondary_pump_power
|
356
|
+
else # Primary only CHW combine 9W/gpm + 13W/gpm
|
357
|
+
w_per_gpm = chilled_water_primary_pump_power + chilled_water_secondary_pump_power
|
358
|
+
end
|
359
|
+
|
360
|
+
when 'Condenser'
|
361
|
+
# @todo prm condenser loop pump power
|
362
|
+
w_per_gpm = condenser_water_pump_power
|
363
|
+
end
|
364
|
+
|
365
|
+
# Modify all the primary pumps
|
366
|
+
plant_loop.supplyComponents.each do |sc|
|
367
|
+
if sc.to_PumpConstantSpeed.is_initialized
|
368
|
+
pump = sc.to_PumpConstantSpeed.get
|
369
|
+
if chiller_counter > 0
|
370
|
+
w_per_gpm /= chiller_counter
|
371
|
+
end
|
372
|
+
pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
|
373
|
+
elsif sc.to_PumpVariableSpeed.is_initialized
|
374
|
+
pump = sc.to_PumpVariableSpeed.get
|
375
|
+
pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
|
376
|
+
elsif sc.to_HeaderedPumpsConstantSpeed.is_initialized
|
377
|
+
pump = sc.to_HeaderedPumpsConstantSpeed.get
|
378
|
+
pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
|
379
|
+
elsif sc.to_HeaderedPumpsVariableSpeed.is_initialized
|
380
|
+
pump = sc.to_HeaderedPumpsVariableSpeed.get
|
381
|
+
pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
return true
|
385
|
+
end
|
386
|
+
|
387
|
+
# Apply sizing and controls to chilled water loop
|
388
|
+
#
|
389
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
390
|
+
# @param chilled_water_loop [OpenStudio::Model::PlantLoop] chilled water loop
|
391
|
+
# @param dsgn_sup_wtr_temp [Double] design chilled water supply T
|
392
|
+
# @param dsgn_sup_wtr_temp_delt [Double] design chilled water supply delta T
|
393
|
+
# @return [Bool] returns true if successful, false if not
|
394
|
+
def chw_sizing_control(model, chilled_water_loop, dsgn_sup_wtr_temp, dsgn_sup_wtr_temp_delt)
|
395
|
+
|
396
|
+
design_chilled_water_temperature = 44 # Loop design chilled water temperature (F)
|
397
|
+
design_chilled_water_temperature_delta = 10.1 # Loop design chilled water temperature (deltaF)
|
398
|
+
chw_outdoor_temperature_high = 80 # Chilled water temperature reset at high outdoor air temperature (F)
|
399
|
+
chw_outdoor_temperature_low = 60 # Chilled water temperature reset at low outdoor air temperature (F)
|
400
|
+
chw_outdoor_high_setpoint = 44 # Chilled water setpoint temperature at high outdoor air temperature (F)
|
401
|
+
chw_outdoor_low_setpoint = 54 # Chilled water setpoint temperature at low outdoor air temperature (F)
|
402
|
+
chiller_chw_low_temp_limit = 36 # Chiller leaving chilled water lower temperature limit (F)
|
403
|
+
chiller_chw_cond_temp = 95 # Chiller entering condenser fluid temperature (F)
|
404
|
+
primary_pump_power = 9 # primary pump power (W/gpm)
|
405
|
+
|
406
|
+
if dsgn_sup_wtr_temp.nil?
|
407
|
+
dsgn_sup_wtr_temp_c = OpenStudio.convert(design_chilled_water_temperature, 'F', 'C').get
|
408
|
+
else
|
409
|
+
dsgn_sup_wtr_temp_c = OpenStudio.convert(dsgn_sup_wtr_temp, 'F', 'C').get
|
410
|
+
end
|
411
|
+
if dsgn_sup_wtr_temp_delt.nil?
|
412
|
+
dsgn_sup_wtr_temp_delt_k = OpenStudio.convert(design_chilled_water_temperature_delta, 'R', 'K').get
|
413
|
+
else
|
414
|
+
dsgn_sup_wtr_temp_delt_k = OpenStudio.convert(dsgn_sup_wtr_temp_delt, 'R', 'K').get
|
415
|
+
end
|
416
|
+
chilled_water_loop.setMinimumLoopTemperature(1.0)
|
417
|
+
chilled_water_loop.setMaximumLoopTemperature(40.0)
|
418
|
+
|
419
|
+
sizing_plant = chilled_water_loop.sizingPlant
|
420
|
+
sizing_plant.setLoopType('Cooling')
|
421
|
+
sizing_plant.setDesignLoopExitTemperature(dsgn_sup_wtr_temp_c)
|
422
|
+
sizing_plant.setLoopDesignTemperatureDifference(dsgn_sup_wtr_temp_delt_k)
|
423
|
+
# Use OA reset setpoint manager
|
424
|
+
outdoor_low_temperature_C = OpenStudio.convert(chw_outdoor_temperature_low, 'F', 'C').get.round(1)
|
425
|
+
outdoor_high_temperature_C = OpenStudio.convert(chw_outdoor_temperature_high, 'F', 'C').get.round(1)
|
426
|
+
setpoint_temperature_outdoor_high_C = OpenStudio.convert(chw_outdoor_high_setpoint, 'F', 'C').get.round(1)
|
427
|
+
setpoint_temperature_outdoor_low_C = OpenStudio.convert(chw_outdoor_low_setpoint, 'F', 'C').get.round(1)
|
428
|
+
|
429
|
+
chw_stpt_manager = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model)
|
430
|
+
chw_stpt_manager.setName("#{chilled_water_loop.name} Setpoint Manager")
|
431
|
+
chw_stpt_manager.setOutdoorHighTemperature(outdoor_high_temperature_C) # Degrees Celsius
|
432
|
+
chw_stpt_manager.setSetpointatOutdoorHighTemperature(setpoint_temperature_outdoor_high_C) # Degrees Celsius
|
433
|
+
chw_stpt_manager.setOutdoorLowTemperature(outdoor_low_temperature_C) # Degrees Celsius
|
434
|
+
chw_stpt_manager.setSetpointatOutdoorLowTemperature(setpoint_temperature_outdoor_low_C) # Degrees Celsius
|
435
|
+
chw_stpt_manager.addToNode(chilled_water_loop.supplyOutletNode)
|
436
|
+
|
437
|
+
return true
|
438
|
+
end
|
439
|
+
|
440
|
+
# Set configuration in model for chilled water primary/secondary loop interface
|
441
|
+
# Use heat_exchanger for stable baseline
|
442
|
+
#
|
443
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
444
|
+
# @return [String] common_pipe or heat_exchanger
|
445
|
+
def plant_loop_set_chw_pri_sec_configuration(model)
|
446
|
+
pri_sec_config = 'heat_exchanger'
|
447
|
+
return pri_sec_config
|
448
|
+
end
|
449
|
+
|
450
|
+
end
|