From e69b541c51fb6cd00bf4df940d05bebf1ef28bb6 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Thu, 11 Apr 2019 11:05:58 -0600 Subject: [PATCH] Lots more cleanup. --- measure.rb | 100 ++++++++++++++++------- resources/geometry.rb | 34 -------- resources/hotwater_appliances.rb | 16 +--- resources/hvac.rb | 133 ++++++++++--------------------- resources/hvac_sizing.rb | 2 +- resources/lighting.rb | 96 +++++++++++----------- resources/misc_loads.rb | 21 ++--- 7 files changed, 173 insertions(+), 229 deletions(-) diff --git a/measure.rb b/measure.rb index 6444fd8617..90ed827a2b 100644 --- a/measure.rb +++ b/measure.rb @@ -276,6 +276,10 @@ def self.create(hpxml_doc, runner, model, weather, map_tsv_dir) # HVAC + control_zone = get_space_of_type(spaces, Constants.SpaceTypeLiving).thermalZone.get + slave_zones = get_spaces_of_type(spaces, [Constants.SpaceTypeFinishedBasement]).map { |z| z.thermalZone.get }.compact + @control_slave_zones_hash = { control_zone => slave_zones } + success = add_cooling_system(runner, model, building, loop_hvacs, zone_hvacs, use_only_ideal_air) return false if not success @@ -288,7 +292,7 @@ def self.create(hpxml_doc, runner, model, weather, map_tsv_dir) success = add_residual_hvac(runner, model, building, use_only_ideal_air) return false if not success - success = add_setpoints(runner, model, building, weather) + success = add_setpoints(runner, model, building, weather, spaces) return false if not success success = add_ceiling_fans(runner, model, building) @@ -314,7 +318,7 @@ def self.create(hpxml_doc, runner, model, weather, map_tsv_dir) success = add_mels(runner, model, building, spaces) return false if not success - success = add_lighting(runner, model, building, weather) + success = add_lighting(runner, model, building, weather, spaces) return false if not success # Other @@ -1778,8 +1782,6 @@ def self.apply_adiabatic_construction(runner, model, surfaces, type) end def self.add_hot_water_and_appliances(runner, model, building, weather, spaces, loop_dhws) - living_space = create_or_get_space(model, spaces, Constants.SpaceTypeLiving) - # Clothes Washer clothes_washer_values = HPXML.get_clothes_washer_values(clothes_washer: building.elements["BuildingDetails/Appliances/ClothesWasher"]) if not clothes_washer_values.nil? @@ -1988,8 +1990,10 @@ def self.add_hot_water_and_appliances(runner, model, building, weather, spaces, end end + wh_setpoint = Waterheater.get_default_hot_water_temperature(@eri_version) + living_space = get_space_of_type(spaces, Constants.SpaceTypeLiving) success = HotWaterAndAppliances.apply(model, runner, weather, living_space, - @cfa, @nbeds, @ncfl, @has_uncond_bsmnt, + @cfa, @nbeds, @ncfl, @has_uncond_bsmnt, wh_setpoint, cw_mef, cw_ler, cw_elec_rate, cw_gas_rate, cw_agc, cw_cap, cw_space, cd_fuel, cd_ef, cd_control, cd_space, dw_ef, dw_cap, fridge_annual_kwh, fridge_space, @@ -2043,7 +2047,7 @@ def self.add_cooling_system(runner, model, building, loop_hvacs, zone_hvacs, use success = HVAC.apply_central_ac_1speed(model, runner, seer, eers, shrs, fan_power_installed, crankcase_kw, crankcase_temp, eer_capacity_derates, cool_capacity_btuh, - dse_cool, load_frac) + dse_cool, load_frac, @control_slave_zones_hash) return false if not success elsif num_speeds == "2-Speed" @@ -2058,7 +2062,7 @@ def self.add_cooling_system(runner, model, building, loop_hvacs, zone_hvacs, use capacity_ratios, fan_speed_ratios, fan_power_installed, crankcase_kw, crankcase_temp, eer_capacity_derates, cool_capacity_btuh, - dse_cool, load_frac) + dse_cool, load_frac, @control_slave_zones_hash) return false if not success elsif num_speeds == "Variable-Speed" @@ -2073,7 +2077,7 @@ def self.add_cooling_system(runner, model, building, loop_hvacs, zone_hvacs, use capacity_ratios, fan_speed_ratios, fan_power_installed, crankcase_kw, crankcase_temp, eer_capacity_derates, cool_capacity_btuh, - dse_cool, load_frac) + dse_cool, load_frac, @control_slave_zones_hash) return false if not success else @@ -2088,8 +2092,8 @@ def self.add_cooling_system(runner, model, building, loop_hvacs, zone_hvacs, use shr = 0.65 airflow_rate = 350.0 - success = HVAC.apply_room_ac(model, runner, eer, shr, - airflow_rate, cool_capacity_btuh, load_frac) + success = HVAC.apply_room_ac(model, runner, eer, shr, airflow_rate, cool_capacity_btuh, + load_frac, @control_slave_zones_hash) return false if not success end @@ -2129,7 +2133,8 @@ def self.add_heating_system(runner, model, building, loop_hvacs, zone_hvacs, use attached_to_multispeed_ac = get_attached_to_multispeed_ac(heating_system_values, building) success = HVAC.apply_furnace(model, runner, fuel, afue, heat_capacity_btuh, fan_power, dse_heat, - load_frac, attached_to_multispeed_ac) + load_frac, attached_to_multispeed_ac, + @control_slave_zones_hash) return false if not success elsif htg_type == "WallFurnace" @@ -2140,7 +2145,8 @@ def self.add_heating_system(runner, model, building, loop_hvacs, zone_hvacs, use # TODO: Allow DSE success = HVAC.apply_unit_heater(model, runner, fuel, afue, heat_capacity_btuh, fan_power, - airflow_rate, load_frac) + airflow_rate, load_frac, + @control_slave_zones_hash) return false if not success elsif htg_type == "Boiler" @@ -2155,7 +2161,8 @@ def self.add_heating_system(runner, model, building, loop_hvacs, zone_hvacs, use design_temp = 180.0 success = HVAC.apply_boiler(model, runner, fuel, system_type, afue, oat_reset_enabled, oat_high, oat_low, oat_hwst_high, oat_hwst_low, - heat_capacity_btuh, design_temp, dse_heat, load_frac) + heat_capacity_btuh, design_temp, dse_heat, load_frac, + @control_slave_zones_hash) return false if not success elsif htg_type == "ElectricResistance" @@ -2163,7 +2170,8 @@ def self.add_heating_system(runner, model, building, loop_hvacs, zone_hvacs, use efficiency = heating_system_values[:heating_efficiency_percent] # TODO: Allow DSE success = HVAC.apply_electric_baseboard(model, runner, efficiency, - heat_capacity_btuh, load_frac) + heat_capacity_btuh, load_frac, + @control_slave_zones_hash) return false if not success elsif htg_type == "Stove" @@ -2174,7 +2182,8 @@ def self.add_heating_system(runner, model, building, loop_hvacs, zone_hvacs, use # TODO: Allow DSE success = HVAC.apply_unit_heater(model, runner, fuel, efficiency, heat_capacity_btuh, fan_power, - airflow_rate, load_frac) + airflow_rate, load_frac, + @control_slave_zones_hash) return false if not success end @@ -2246,7 +2255,8 @@ def self.add_heat_pump(runner, model, building, weather, loop_hvacs, zone_hvacs, eer_capacity_derates, cop_capacity_derates, cool_capacity_btuh, supplemental_efficiency, backup_heat_capacity_btuh, dse_heat, - load_frac_heat, load_frac_cool) + load_frac_heat, load_frac_cool, + @control_slave_zones_hash) return false if not success elsif num_speeds == "2-Speed" @@ -2268,7 +2278,8 @@ def self.add_heat_pump(runner, model, building, weather, loop_hvacs, zone_hvacs, eer_capacity_derates, cop_capacity_derates, cool_capacity_btuh, supplemental_efficiency, backup_heat_capacity_btuh, dse_heat, - load_frac_heat, load_frac_cool) + load_frac_heat, load_frac_cool, + @control_slave_zones_hash) return false if not success elsif num_speeds == "Variable-Speed" @@ -2290,7 +2301,8 @@ def self.add_heat_pump(runner, model, building, weather, loop_hvacs, zone_hvacs, eer_capacity_derates, cop_capacity_derates, cool_capacity_btuh, supplemental_efficiency, backup_heat_capacity_btuh, dse_heat, - load_frac_heat, load_frac_cool) + load_frac_heat, load_frac_cool, + @control_slave_zones_hash) return false if not success else @@ -2329,7 +2341,8 @@ def self.add_heat_pump(runner, model, building, weather, loop_hvacs, zone_hvacs, cap_retention_temp, pan_heater_power, fan_power, is_ducted, cool_capacity_btuh, supplemental_efficiency, backup_heat_capacity_btuh, - dse_heat, load_frac_heat, load_frac_cool) + dse_heat, load_frac_heat, load_frac_cool, + @control_slave_zones_hash) return false if not success elsif hp_type == "ground-to-air" @@ -2366,7 +2379,8 @@ def self.add_heat_pump(runner, model, building, weather, loop_hvacs, zone_hvacs, u_tube_leg_spacing, u_tube_spacing_type, fan_power, heat_pump_capacity, supplemental_efficiency, supplemental_capacity, dse_heat, - load_frac_heat, load_frac_cool) + load_frac_heat, load_frac_cool, + @control_slave_zones_hash) return false if not success end @@ -2409,10 +2423,12 @@ def self.add_residual_hvac(runner, model, building, use_only_ideal_air) return true end - def self.add_setpoints(runner, model, building, weather) + def self.add_setpoints(runner, model, building, weather, spaces) hvac_control_values = HPXML.get_hvac_control_values(hvac_control: building.elements["BuildingDetails/Systems/HVAC/HVACControl"]) return true if hvac_control_values.nil? + conditioned_zones = get_spaces_of_type(spaces, [Constants.SpaceTypeLiving, Constants.SpaceTypeFinishedBasement]).map { |z| z.thermalZone.get }.compact + control_type = hvac_control_values[:control_type] heating_temp = hvac_control_values[:setpoint_temp_heating_season] if not heating_temp.nil? # Use provided value @@ -2435,7 +2451,8 @@ def self.add_setpoints(runner, model, building, weather) htg_season_start_month = 1 htg_season_end_month = 12 success = HVAC.apply_heating_setpoints(model, runner, weather, htg_weekday_setpoints, htg_weekend_setpoints, - htg_use_auto_season, htg_season_start_month, htg_season_end_month) + htg_use_auto_season, htg_season_start_month, htg_season_end_month, + conditioned_zones) return false if not success cooling_temp = hvac_control_values[:setpoint_temp_cooling_season] @@ -2469,7 +2486,8 @@ def self.add_setpoints(runner, model, building, weather) clg_season_start_month = 1 clg_season_end_month = 12 success = HVAC.apply_cooling_setpoints(model, runner, weather, clg_weekday_setpoints, clg_weekend_setpoints, - clg_use_auto_season, clg_season_start_month, clg_season_end_month) + clg_use_auto_season, clg_season_start_month, clg_season_end_month, + conditioned_zones) return false if not success return true @@ -2495,7 +2513,9 @@ def self.add_ceiling_fans(runner, model, building) end annual_kwh = UnitConversions.convert(quantity * medium_cfm / cfm_per_w * hrs_per_day * 365.0, "Wh", "kWh") - success = HVAC.apply_ceiling_fans(model, runner, annual_kwh, weekday_sch, weekend_sch, @cfa) + conditioned_spaces = get_spaces_of_type(spaces, [Constants.SpaceTypeLiving, Constants.SpaceTypeFinishedBasement]) + success = HVAC.apply_ceiling_fans(model, runner, annual_kwh, weekday_sch, weekend_sch, + @cfa, conditioned_spaces) return false if not success return true @@ -2595,8 +2615,6 @@ def self.update_loop_dhws(loop_dhws, model, sys, orig_plant_loops) end def self.add_mels(runner, model, building, spaces) - living_space = create_or_get_space(model, spaces, Constants.SpaceTypeLiving) - # Misc plug_load_values = HPXML.get_plug_load_values(plug_load: building.elements["BuildingDetails/MiscLoads/PlugLoad[PlugLoadType='other']"]) if not plug_load_values.nil? @@ -2645,14 +2663,16 @@ def self.add_mels(runner, model, building, spaces) tv_annual_kwh = 0 end + conditioned_spaces = get_spaces_of_type(spaces, [Constants.SpaceTypeLiving, Constants.SpaceTypeFinishedBasement]) success, sch = MiscLoads.apply_plug(model, runner, misc_annual_kwh, misc_sens_frac, misc_lat_frac, - misc_weekday_sch, misc_weekend_sch, misc_monthly_sch, tv_annual_kwh, @cfa) + misc_weekday_sch, misc_weekend_sch, misc_monthly_sch, tv_annual_kwh, + @cfa, conditioned_spaces) return false if not success return true end - def self.add_lighting(runner, model, building, weather) + def self.add_lighting(runner, model, building, weather, spaces) lighting = building.elements["BuildingDetails/Lighting"] return true if lighting.nil? @@ -2677,7 +2697,10 @@ def self.add_lighting(runner, model, building, weather) lighting_values[:fraction_tier_ii_garage]) gfa = 0 # garage floor area FIXME - success, sch = Lighting.apply(model, runner, weather, int_kwh, grg_kwh, ext_kwh, @cfa, gfa) + conditioned_spaces = get_spaces_of_type(spaces, [Constants.SpaceTypeLiving, Constants.SpaceTypeFinishedBasement]) + garage_spaces = get_spaces_of_type(spaces, [Constants.SpaceTypeGarage]) + success, sch = Lighting.apply(model, runner, weather, int_kwh, grg_kwh, ext_kwh, @cfa, gfa, + conditioned_spaces, garage_spaces) return false if not success return true @@ -3762,6 +3785,25 @@ def self.get_space_from_location(location, object_name, model, spaces) return space end + + def self.get_spaces_of_type(spaces, space_types_list) + spaces_of_type = [] + space_types_list.each do |space_type| + spaces_of_type << spaces[space_type] unless spaces[space_type].nil? + end + return spaces_of_type + end + + def self.get_space_of_type(spaces, space_type) + spaces_of_type = self.get_spaces_of_type(spaces, [space_type]) + if spaces_of_type.size > 1 + fail "Unexpected number of spaces." + elsif spaces_of_type.size == 1 + return spaces_of_type[0] + end + + return nil + end end class WoodStudConstructionSet diff --git a/resources/geometry.rb b/resources/geometry.rb index cf6e6e3b46..3e74ecc56e 100644 --- a/resources/geometry.rb +++ b/resources/geometry.rb @@ -3,36 +3,6 @@ require_relative "util" class Geometry - def self.get_abs_azimuth(azimuth_type, relative_azimuth, building_orientation, offset = 180.0) - azimuth = nil - if azimuth_type == Constants.CoordRelative - azimuth = relative_azimuth + building_orientation + offset - elsif azimuth_type == Constants.CoordAbsolute - azimuth = relative_azimuth + offset - end - - # Ensure azimuth is >=0 and <=360 - while azimuth < 0.0 - azimuth += 360.0 - end - - while azimuth >= 360.0 - azimuth -= 360.0 - end - - return azimuth - end - - def self.get_abs_tilt(tilt_type, relative_tilt, roof_tilt, latitude) - if tilt_type == Constants.TiltPitch - return relative_tilt + roof_tilt - elsif tilt_type == Constants.TiltLatitude - return relative_tilt + latitude - elsif tilt_type == Constants.CoordAbsolute - return relative_tilt - end - end - def self.initialize_transformation_matrix(m) m[0, 0] = 1 m[1, 1] = 1 @@ -80,10 +50,6 @@ def self.get_above_grade_finished_volume(model, runner = nil) return volume end - def self.space_height(space) - return Geometry.get_height_of_spaces([space]) - end - # Calculates space heights as the max z coordinate minus the min z coordinate def self.get_height_of_spaces(spaces) minzs = [] diff --git a/resources/hotwater_appliances.rb b/resources/hotwater_appliances.rb index e18603c253..85b322b53a 100644 --- a/resources/hotwater_appliances.rb +++ b/resources/hotwater_appliances.rb @@ -5,7 +5,7 @@ class HotWaterAndAppliances def self.apply(model, runner, weather, living_space, - cfa, nbeds, ncfl, has_uncond_bsmnt, + cfa, nbeds, ncfl, has_uncond_bsmnt, wh_setpoint, cw_mef, cw_ler, cw_elec_rate, cw_gas_rate, cw_agc, cw_cap, cw_space, cd_fuel, cd_ef, cd_control, cd_space, dw_ef, dw_cap, fridge_annual_kwh, fridge_space, @@ -37,7 +37,6 @@ def self.apply(model, runner, weather, living_space, water_use_connections = {} setpoint_scheds = {} - setpoint_temps = {} dhw_loop_fracs.each do |dhw_loop, dhw_load_frac| water_use_connections[dhw_loop] = OpenStudio::Model::WaterUseConnections.new(model) @@ -48,18 +47,7 @@ def self.apply(model, runner, weather, living_space, if setpoint_scheds[dhw_loop].nil? return false end - - setpoint_temps[dhw_loop] = Waterheater.get_water_heater_setpoint(model, dhw_loop, runner) - if setpoint_temps[dhw_loop].nil? - return false - end - end - - if setpoint_temps.values.max - setpoint_temps.values.min > 0.1 - runner.registerError("Cannot handle different water heater setpoints.") - return false end - setpoint_temp = setpoint_temps.values.reduce(:+) / setpoint_temps.size.to_f # average # Create hot water draw profile schedule fractions_hw = [] @@ -78,7 +66,7 @@ def self.apply(model, runner, weather, living_space, # Create mixed water draw profile schedule dwhr_eff_adj, dwhr_iFrac, dwhr_plc, dwhr_locF, dwhr_fixF = get_dwhr_factors(nbeds, dist_type, std_pipe_length, recirc_branch_length, dwhr_is_equal_flow, dwhr_facilities_connected, has_low_flow_fixtures) daily_wh_inlet_temperatures = calc_water_heater_daily_inlet_temperatures(weather, dwhr_present, dwhr_iFrac, dwhr_efficiency, dwhr_eff_adj, dwhr_plc, dwhr_locF, dwhr_fixF) - daily_mw_fractions = calc_mixed_water_daily_fractions(daily_wh_inlet_temperatures, setpoint_temp) + daily_mw_fractions = calc_mixed_water_daily_fractions(daily_wh_inlet_temperatures, wh_setpoint) fractions_mw = [] for day in 0..364 for hr in 0..23 diff --git a/resources/hvac.rb b/resources/hvac.rb index ca467eddef..0135f88e62 100644 --- a/resources/hvac.rb +++ b/resources/hvac.rb @@ -9,7 +9,7 @@ class HVAC def self.apply_central_ac_1speed(model, runner, seer, eers, shrs, fan_power_installed, crankcase_kw, crankcase_temp, eer_capacity_derates, capacity, dse, - frac_cool_load_served) + frac_cool_load_served, control_slave_zones_hash) return true if frac_cool_load_served <= 0 @@ -36,9 +36,6 @@ def self.apply_central_ac_1speed(model, runner, seer, eers, shrs, obj_name = Constants.ObjectNameCentralAirConditioner - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXCooling @@ -146,7 +143,7 @@ def self.apply_central_ac_2speed(model, runner, seer, eers, shrs, capacity_ratios, fan_speed_ratios, fan_power_installed, crankcase_kw, crankcase_temp, eer_capacity_derates, capacity, dse, - frac_cool_load_served) + frac_cool_load_served, control_slave_zones_hash) return true if frac_cool_load_served <= 0 @@ -174,9 +171,6 @@ def self.apply_central_ac_2speed(model, runner, seer, eers, shrs, obj_name = Constants.ObjectNameCentralAirConditioner - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXCooling @@ -291,7 +285,7 @@ def self.apply_central_ac_4speed(model, runner, seer, eers, shrs, capacity_ratios, fan_speed_ratios, fan_power_installed, crankcase_kw, crankcase_temp, eer_capacity_derates, capacity, dse, - frac_cool_load_served) + frac_cool_load_served, control_slave_zones_hash) return true if frac_cool_load_served <= 0 @@ -321,9 +315,6 @@ def self.apply_central_ac_4speed(model, runner, seer, eers, shrs, obj_name = Constants.ObjectNameCentralAirConditioner - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXCooling @@ -439,7 +430,8 @@ def self.apply_central_ashp_1speed(model, runner, seer, hspf, eers, cops, shrs, eer_capacity_derates, cop_capacity_derates, heat_pump_capacity, supplemental_efficiency, supplemental_capacity, dse, - frac_heat_load_served, frac_cool_load_served) + frac_heat_load_served, frac_cool_load_served, + control_slave_zones_hash) if heat_pump_capacity == Constants.SizingAutoMaxLoad runner.registerWarning("Using #{Constants.SizingAutoMaxLoad} is not recommended for single-speed heat pumps. When sized larger than the cooling load, this can lead to humidity concerns due to reduced dehumidification performance by the heat pump.") @@ -482,9 +474,6 @@ def self.apply_central_ashp_1speed(model, runner, seer, hspf, eers, cops, shrs, obj_name = Constants.ObjectNameAirSourceHeatPump - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXHeating @@ -705,7 +694,8 @@ def self.apply_central_ashp_2speed(model, runner, seer, hspf, eers, cops, shrs, eer_capacity_derates, cop_capacity_derates, heat_pump_capacity, supplemental_efficiency, supplemental_capacity, dse, - frac_heat_load_served, frac_cool_load_served) + frac_heat_load_served, frac_cool_load_served, + control_slave_zones_hash) num_speeds = 2 fan_power_rated = get_fan_power_rated(seer) @@ -748,9 +738,6 @@ def self.apply_central_ashp_2speed(model, runner, seer, hspf, eers, cops, shrs, obj_name = Constants.ObjectNameAirSourceHeatPump - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXHeating htg_coil_stage_data = calc_coil_stage_data_heating(model, heat_pump_capacity, (0...num_speeds).to_a, heating_eirs, hEAT_CAP_FT_SPEC, hEAT_EIR_FT_SPEC, hEAT_CLOSS_FPLR_SPEC, hEAT_CAP_FFLOW_SPEC, hEAT_EIR_FFLOW_SPEC, curves_in_ip, dse) @@ -990,7 +977,8 @@ def self.apply_central_ashp_4speed(model, runner, seer, hspf, eers, cops, shrs, eer_capacity_derates, cop_capacity_derates, heat_pump_capacity, supplemental_efficiency, supplemental_capacity, dse, - frac_heat_load_served, frac_cool_load_served) + frac_heat_load_served, frac_cool_load_served, + control_slave_zones_hash) num_speeds = 4 fan_power_rated = get_fan_power_rated(seer) @@ -1037,9 +1025,6 @@ def self.apply_central_ashp_4speed(model, runner, seer, hspf, eers, cops, shrs, obj_name = Constants.ObjectNameAirSourceHeatPump - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXHeating @@ -1282,7 +1267,8 @@ def self.apply_mshp(model, runner, seer, hspf, shr, heating_capacity_offset, cap_retention_frac, cap_retention_temp, pan_heater_power, fan_power, is_ducted, heat_pump_capacity, supplemental_efficiency, supplemental_capacity, - dse, frac_heat_load_served, frac_cool_load_served) + dse, frac_heat_load_served, frac_cool_load_served, + control_slave_zones_hash) num_speeds = 10 @@ -1348,9 +1334,6 @@ def self.apply_mshp(model, runner, seer, hspf, shr, obj_name = Constants.ObjectNameMiniSplitHeatPump - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processCurvesDXHeating @@ -1660,7 +1643,8 @@ def self.apply_gshp(model, runner, weather, cop, eer, shr, u_tube_leg_spacing, u_tube_spacing_type, fan_power, heat_pump_capacity, supplemental_efficiency, supplemental_capacity, dse, - frac_heat_load_served, frac_cool_load_served) + frac_heat_load_served, frac_cool_load_served, + control_slave_zones_hash) if frac_glycol == 0 fluid_type = Constants.FluidWater @@ -1764,9 +1748,6 @@ def self.apply_gshp(model, runner, weather, cop, eer, shr, demand_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model) demand_outlet_pipe.addToNode(plant_loop.demandOutletNode) - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| gshp_HEAT_CAP_fT_coeff = convert_curve_gshp(hEAT_CAP_FT_SEC, false) gshp_HEAT_POWER_fT_coeff = convert_curve_gshp(hEAT_POWER_FT_SPEC, false) @@ -1972,7 +1953,8 @@ def self.apply_gshp(model, runner, weather, cop, eer, shr, end def self.apply_room_ac(model, runner, eer, shr, - airflow_rate, capacity, frac_cool_load_served) + airflow_rate, capacity, frac_cool_load_served, + control_slave_zones_hash) return true if frac_cool_load_served <= 0 @@ -1994,9 +1976,6 @@ def self.apply_room_ac(model, runner, eer, shr, obj_name = Constants.ObjectNameRoomAirConditioner - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| ([control_zone] + slave_zones).each do |zone| # _processSystemRoomAC @@ -2044,7 +2023,8 @@ def self.apply_room_ac(model, runner, eer, shr, def self.apply_furnace(model, runner, fuel_type, afue, capacity, fan_power_installed, dse, - frac_heat_load_served, attached_to_multispeed_ac) + frac_heat_load_served, attached_to_multispeed_ac, + control_slave_zones_hash) return true if frac_heat_load_served <= 0 @@ -2059,9 +2039,6 @@ def self.apply_furnace(model, runner, fuel_type, afue, obj_name = Constants.ObjectNameFurnace(fuel_type) - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| # _processSystemHeatingCoil @@ -2163,7 +2140,8 @@ def self.apply_furnace(model, runner, fuel_type, afue, def self.apply_boiler(model, runner, fuel_type, system_type, afue, oat_reset_enabled, oat_high, oat_low, oat_hwst_high, oat_hwst_low, - capacity, design_temp, dse, frac_heat_load_served) + capacity, design_temp, dse, frac_heat_load_served, + control_slave_zones_hash) return true if frac_heat_load_served <= 0 @@ -2286,9 +2264,6 @@ def self.apply_boiler(model, runner, fuel_type, system_type, afue, pipe_demand_inlet.addToNode(plant_loop.demandInletNode) pipe_demand_outlet.addToNode(plant_loop.demandOutletNode) - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| ([control_zone] + slave_zones).each do |zone| baseboard_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model) @@ -2315,14 +2290,12 @@ def self.apply_boiler(model, runner, fuel_type, system_type, afue, return true end - def self.apply_electric_baseboard(model, runner, efficiency, capacity, frac_heat_load_served) + def self.apply_electric_baseboard(model, runner, efficiency, capacity, frac_heat_load_served, + control_slave_zones_hash) return true if frac_heat_load_served <= 0 obj_name = Constants.ObjectNameElectricBaseboard - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| ([control_zone] + slave_zones).each do |zone| htg_coil = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model) @@ -2347,7 +2320,8 @@ def self.apply_electric_baseboard(model, runner, efficiency, capacity, frac_heat def self.apply_unit_heater(model, runner, fuel_type, efficiency, capacity, fan_power, - airflow_rate, frac_heat_load_served) + airflow_rate, frac_heat_load_served, + control_slave_zones_hash) return true if frac_heat_load_served <= 0 @@ -2358,9 +2332,6 @@ def self.apply_unit_heater(model, runner, fuel_type, obj_name = Constants.ObjectNameUnitHeater(fuel_type) - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| ([control_zone] + slave_zones).each do |zone| # _processSystemHeatingCoil @@ -2420,12 +2391,10 @@ def self.apply_unit_heater(model, runner, fuel_type, return true end - def self.apply_ideal_air_loads_cooling(model, runner, frac_cool_load_served) + def self.apply_ideal_air_loads_cooling(model, runner, frac_cool_load_served, + control_slave_zones_hash) return true if frac_cool_load_served <= 0 - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| ([control_zone] + slave_zones).each do |zone| ideal_air = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model) @@ -2450,12 +2419,10 @@ def self.apply_ideal_air_loads_cooling(model, runner, frac_cool_load_served) return true end - def self.apply_ideal_air_loads_heating(model, runner, frac_heat_load_served) + def self.apply_ideal_air_loads_heating(model, runner, frac_heat_load_served, + control_slave_zones_hash) return true if frac_heat_load_served <= 0 - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| ([control_zone] + slave_zones).each do |zone| ideal_air = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model) @@ -2481,7 +2448,8 @@ def self.apply_ideal_air_loads_heating(model, runner, frac_heat_load_served) end def self.apply_heating_setpoints(model, runner, weather, htg_wkdy_monthly, htg_wked_monthly, - use_auto_season, season_start_month, season_end_month) + use_auto_season, season_start_month, season_end_month, + conditioned_zones) # Get heating season if use_auto_season @@ -2507,17 +2475,10 @@ def self.apply_heating_setpoints(model, runner, weather, htg_wkdy_monthly, htg_w htg_wkdy_monthly = htg_wkdy_monthly.map { |i| i.map { |j| UnitConversions.convert(j, "F", "C") } } htg_wked_monthly = htg_wked_monthly.map { |i| i.map { |j| UnitConversions.convert(j, "F", "C") } } - finished_zones = [] - model.getThermalZones.each do |thermal_zone| - if Geometry.zone_is_finished(thermal_zone) - finished_zones << thermal_zone - end - end - # Make the setpoint schedules clg_wkdy_monthly = nil clg_wked_monthly = nil - finished_zones.each do |finished_zone| + conditioned_zones.each do |finished_zone| thermostat_setpoint = finished_zone.thermostatSetpointDualSetpoint if thermostat_setpoint.is_initialized @@ -2585,7 +2546,7 @@ def self.apply_heating_setpoints(model, runner, weather, htg_wkdy_monthly, htg_w end # Set the setpoint schedules - finished_zones.each do |finished_zone| + conditioned_zones.each do |finished_zone| thermostat_setpoint = finished_zone.thermostatSetpointDualSetpoint if thermostat_setpoint.is_initialized @@ -2618,7 +2579,8 @@ def self.apply_heating_setpoints(model, runner, weather, htg_wkdy_monthly, htg_w end def self.apply_cooling_setpoints(model, runner, weather, clg_wkdy_monthly, clg_wked_monthly, - use_auto_season, season_start_month, season_end_month) + use_auto_season, season_start_month, season_end_month, + conditioned_zones) # Get cooling season if use_auto_season @@ -2644,17 +2606,10 @@ def self.apply_cooling_setpoints(model, runner, weather, clg_wkdy_monthly, clg_w clg_wkdy_monthly = clg_wkdy_monthly.map { |i| i.map { |j| UnitConversions.convert(j, "F", "C") } } clg_wked_monthly = clg_wked_monthly.map { |i| i.map { |j| UnitConversions.convert(j, "F", "C") } } - finished_zones = [] - model.getThermalZones.each do |thermal_zone| - if Geometry.zone_is_finished(thermal_zone) - finished_zones << thermal_zone - end - end - # Make the setpoint schedules htg_wkdy_monthly = nil htg_wked_monthly = nil - finished_zones.each do |finished_zone| + conditioned_zones.each do |finished_zone| thermostat_setpoint = finished_zone.thermostatSetpointDualSetpoint if thermostat_setpoint.is_initialized @@ -2722,7 +2677,7 @@ def self.apply_cooling_setpoints(model, runner, weather, clg_wkdy_monthly, clg_w end # Set the setpoint schedules - finished_zones.each do |finished_zone| + conditioned_zones.each do |finished_zone| thermostat_setpoint = finished_zone.thermostatSetpointDualSetpoint if thermostat_setpoint.is_initialized @@ -2850,8 +2805,8 @@ def self.get_default_cooling_setpoint(control_type) return clg_sp, clg_setup_sp, clg_setup_hrs_per_week, clg_setup_start_hr end - def self.apply_dehumidifier(model, runner, energy_factor, - water_removal_rate, air_flow_rate, humidity_setpoint) + def self.apply_dehumidifier(model, runner, energy_factor, water_removal_rate, + air_flow_rate, humidity_setpoint, control_slave_zones_hash) # error checking if humidity_setpoint < 0 or humidity_setpoint > 1 @@ -2884,9 +2839,6 @@ def self.apply_dehumidifier(model, runner, energy_factor, energy_factor_curve = create_curve_biquadratic(model, [-1.902154518, 0.063466565, -0.000622839, 0.039540407, -0.000125637, -0.000176722], "DXDH-EnergyFactor-fT", -100, 100, -100, 100) part_load_frac_curve = create_curve_quadratic(model, [0.90, 0.10, 0.0], "DXDH-PLF-fPLR", 0, 1, 0.7, 1) - thermal_zones = Geometry.get_thermal_zones_from_spaces(model.getSpaces) - - control_slave_zones_hash = get_control_and_slave_zones(thermal_zones) control_slave_zones_hash.each do |control_zone, slave_zones| humidistat = OpenStudio::Model::ZoneControlHumidistat.new(model) humidistat.setName(obj_name + " #{control_zone.name} humidistat") @@ -2924,7 +2876,8 @@ def self.apply_dehumidifier(model, runner, energy_factor, return true end - def self.apply_ceiling_fans(model, runner, annual_kWh, weekday_sch, weekend_sch, cfa) + def self.apply_ceiling_fans(model, runner, annual_kWh, weekday_sch, weekend_sch, + cfa, conditioned_spaces) obj_name = Constants.ObjectNameCeilingFan ceiling_fan_sch = MonthWeekdayWeekendSchedule.new(model, runner, obj_name + " schedule", weekday_sch, weekend_sch, [1] * 12) @@ -2932,9 +2885,7 @@ def self.apply_ceiling_fans(model, runner, annual_kWh, weekday_sch, weekend_sch, return false end - model.getSpaces.each do |space| - next if Geometry.space_is_unfinished(space) - + conditioned_spaces.each do |space| space_obj_name = "#{obj_name}|#{space.name.to_s}" space_mel_ann = annual_kWh * UnitConversions.convert(space.floorArea, "m^2", "ft^2") / cfa @@ -3486,8 +3437,8 @@ def self.get_control_and_slave_zones(thermal_zones) finished_above_grade_zones, finished_below_grade_zones = Geometry.get_finished_above_and_below_grade_zones(thermal_zones) control_zone = nil slave_zones = [] - [finished_above_grade_zones, finished_below_grade_zones].each do |finished_zones| # Preference to above-grade zone as control zone - finished_zones.each do |finished_zone| + [finished_above_grade_zones, finished_below_grade_zones].each do |conditioned_zones| # Preference to above-grade zone as control zone + conditioned_zones.each do |finished_zone| if control_zone.nil? control_zone = finished_zone else diff --git a/resources/hvac_sizing.rb b/resources/hvac_sizing.rb index b954eeb676..55eee4909e 100644 --- a/resources/hvac_sizing.rb +++ b/resources/hvac_sizing.rb @@ -999,7 +999,7 @@ def self.process_load_walls(runner, mj8, thermal_zone, zone_loads, weather, htd) k_soil = UnitConversions.convert(BaseMaterial.Soil.k_in, "in", "ft") ins_wall_ufactor = 1.0 / (wall_constr_rvalue + wall_ins_rvalue + Material.AirFilmVertical.rvalue) unins_wall_ufactor = 1.0 / (wall_constr_rvalue + Material.AirFilmVertical.rvalue) - above_grade_height = Geometry.space_height(wall.space.get) - Geometry.surface_height(wall) + above_grade_height = Geometry.get_height_of_spaces([wall.space.get]) - Geometry.surface_height(wall) # Calculated based on Manual J 8th Ed. procedure in section A12-4 (15% decrease due to soil thermal storage) u_value_mj8 = 0.0 diff --git a/resources/lighting.rb b/resources/lighting.rb index 34f2ebe554..e84eeb2171 100644 --- a/resources/lighting.rb +++ b/resources/lighting.rb @@ -3,7 +3,8 @@ require_relative "unit_conversions" class Lighting - def self.apply(model, runner, weather, interior_kwh, garage_kwh, exterior_kwh, cfa, gfa) + def self.apply(model, runner, weather, interior_kwh, garage_kwh, exterior_kwh, cfa, gfa, + conditioned_spaces, garage_spaces) lat = weather.header.Latitude long = weather.header.Longitude tz = weather.header.Timezone @@ -116,68 +117,69 @@ def self.apply(model, runner, weather, interior_kwh, garage_kwh, exterior_kwh, c end end - # Get finished spaces - finished_spaces = Geometry.get_finished_spaces(model.getSpaces) - # Create schedule sch = HourlyByMonthSchedule.new(model, runner, Constants.ObjectNameLighting + " schedule", lighting_sch, lighting_sch) if not sch.validated? return false end - # Add lighting to each finished space - finished_spaces.each do |space| - space_obj_name = "#{Constants.ObjectNameLighting} #{space.name.to_s}" - - if finished_spaces.include?(space) - space_ltg_ann = interior_kwh * UnitConversions.convert(space.floorArea, "m^2", "ft^2") / cfa + # Add lighting to each conditioned space + if interior_kwh > 0 + conditioned_spaces.each do |conditioned_space| + space_obj_name = "#{Constants.ObjectNameLighting} #{conditioned_space.name.to_s}" + + space_ltg_ann = interior_kwh * UnitConversions.convert(conditioned_space.floorArea, "m^2", "ft^2") / cfa + space_design_level = sch.calcDesignLevel(sch.maxval * space_ltg_ann) + + # Add lighting + ltg_def = OpenStudio::Model::LightsDefinition.new(model) + ltg = OpenStudio::Model::Lights.new(ltg_def) + ltg.setName(space_obj_name) + ltg.setSpace(conditioned_space) + ltg_def.setName(space_obj_name) + ltg_def.setLightingLevel(space_design_level) + ltg_def.setFractionRadiant(0.6) + ltg_def.setFractionVisible(0.2) + ltg_def.setReturnAirFraction(0.0) + ltg.setSchedule(sch.schedule) end - space_design_level = sch.calcDesignLevel(sch.maxval * space_ltg_ann) - - # Add lighting - ltg_def = OpenStudio::Model::LightsDefinition.new(model) - ltg = OpenStudio::Model::Lights.new(ltg_def) - ltg.setName(space_obj_name) - ltg.setSpace(space) - ltg_def.setName(space_obj_name) - ltg_def.setLightingLevel(space_design_level) - ltg_def.setFractionRadiant(0.6) - ltg_def.setFractionVisible(0.2) - ltg_def.setReturnAirFraction(0.0) - ltg.setSchedule(sch.schedule) end - garage_spaces = Geometry.get_garage_spaces(model.getSpaces) - garage_spaces.each do |garage_space| - space_obj_name = "#{Constants.ObjectNameLighting} #{garage_space.name.to_s}" + # Add lighting to each garage space + if garage_kwh > 0 + garage_spaces.each do |garage_space| + space_obj_name = "#{Constants.ObjectNameLighting} #{garage_space.name.to_s}" + + space_ltg_ann = garage_kwh * UnitConversions.convert(garage_space.floorArea, "m^2", "ft^2") / gfa + space_design_level = sch.calcDesignLevel(sch.maxval * space_ltg_ann) + + # Add lighting + ltg_def = OpenStudio::Model::LightsDefinition.new(model) + ltg = OpenStudio::Model::Lights.new(ltg_def) + ltg.setName(space_obj_name) + ltg.setSpace(garage_space) + ltg_def.setName(space_obj_name) + ltg_def.setLightingLevel(space_design_level) + ltg_def.setFractionRadiant(0.6) + ltg_def.setFractionVisible(0.2) + ltg_def.setReturnAirFraction(0.0) + ltg.setSchedule(sch.schedule) + end + end - space_ltg_ann = garage_kwh * UnitConversions.convert(garage_space.floorArea, "m^2", "ft^2") / gfa - space_design_level = sch.calcDesignLevel(sch.maxval * space_ltg_ann) + if exterior_kwh > 0 + space_design_level = sch.calcDesignLevel(sch.maxval * exterior_kwh) + space_obj_name = "#{Constants.ObjectNameLighting} exterior" - # Add lighting - ltg_def = OpenStudio::Model::LightsDefinition.new(model) - ltg = OpenStudio::Model::Lights.new(ltg_def) + # Add exterior lighting + ltg_def = OpenStudio::Model::ExteriorLightsDefinition.new(model) + ltg = OpenStudio::Model::ExteriorLights.new(ltg_def) ltg.setName(space_obj_name) - ltg.setSpace(garage_space) ltg_def.setName(space_obj_name) - ltg_def.setLightingLevel(space_design_level) - ltg_def.setFractionRadiant(0.6) - ltg_def.setFractionVisible(0.2) - ltg_def.setReturnAirFraction(0.0) + ltg_def.setDesignLevel(space_design_level) ltg.setSchedule(sch.schedule) end - space_design_level = sch.calcDesignLevel(sch.maxval * exterior_kwh) - space_obj_name = "#{Constants.ObjectNameLighting} exterior" - - # Add exterior lighting - ltg_def = OpenStudio::Model::ExteriorLightsDefinition.new(model) - ltg = OpenStudio::Model::ExteriorLights.new(ltg_def) - ltg.setName(space_obj_name) - ltg_def.setName(space_obj_name) - ltg_def.setDesignLevel(space_design_level) - ltg.setSchedule(sch.schedule) - return true end diff --git a/resources/misc_loads.rb b/resources/misc_loads.rb index 944ef3e3c6..23475cca11 100644 --- a/resources/misc_loads.rb +++ b/resources/misc_loads.rb @@ -4,7 +4,8 @@ class MiscLoads def self.apply_plug(model, runner, misc_kwh, sens_frac, lat_frac, - weekday_sch, weekend_sch, monthly_sch, tv_kwh, cfa) + weekday_sch, weekend_sch, monthly_sch, tv_kwh, cfa, + conditioned_spaces) return true if misc_kwh + tv_kwh == 0 @@ -38,11 +39,8 @@ def self.apply_plug(model, runner, misc_kwh, sens_frac, lat_frac, # Misc plug loads if misc_kwh > 0 - model.getSpaces.each do |space| - next if Geometry.space_is_unfinished(space) - - obj_name = Constants.ObjectNameMiscPlugLoads - space_obj_name = "#{obj_name}|#{space.name.to_s}" + conditioned_spaces.each do |space| + space_obj_name = "#{Constants.ObjectNameMiscPlugLoads}|#{space.name.to_s}" space_mel_ann = misc_kwh * UnitConversions.convert(space.floorArea, "m^2", "ft^2") / cfa space_design_level = sch.calcDesignLevelFromDailykWh(space_mel_ann / 365.0) @@ -51,7 +49,7 @@ def self.apply_plug(model, runner, misc_kwh, sens_frac, lat_frac, mel_def = OpenStudio::Model::ElectricEquipmentDefinition.new(model) mel = OpenStudio::Model::ElectricEquipment.new(mel_def) mel.setName(space_obj_name) - mel.setEndUseSubcategory(obj_name) + mel.setEndUseSubcategory(Constants.ObjectNameMiscPlugLoads) mel.setSpace(space) mel_def.setName(space_obj_name) mel_def.setDesignLevel(space_design_level) @@ -67,11 +65,8 @@ def self.apply_plug(model, runner, misc_kwh, sens_frac, lat_frac, tv_lat_frac = 0.0 if tv_kwh > 0 - model.getSpaces.each do |space| - next if Geometry.space_is_unfinished(space) - - obj_name = Constants.ObjectNameMiscTelevision - space_obj_name = "#{obj_name}|#{space.name.to_s}" + conditioned_spaces.each do |space| + space_obj_name = "#{Constants.ObjectNameMiscTelevision}|#{space.name.to_s}" space_mel_ann = tv_kwh * UnitConversions.convert(space.floorArea, "m^2", "ft^2") / cfa space_design_level = sch.calcDesignLevelFromDailykWh(space_mel_ann / 365.0) @@ -80,7 +75,7 @@ def self.apply_plug(model, runner, misc_kwh, sens_frac, lat_frac, mel_def = OpenStudio::Model::ElectricEquipmentDefinition.new(model) mel = OpenStudio::Model::ElectricEquipment.new(mel_def) mel.setName(space_obj_name) - mel.setEndUseSubcategory(obj_name) + mel.setEndUseSubcategory(Constants.ObjectNameMiscTelevision) mel.setSpace(space) mel_def.setName(space_obj_name) mel_def.setDesignLevel(space_design_level)