Class: ASHRAE9012019
- Includes:
- ASHRAE9012019CoolingTower
- Defined in:
- lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Pump.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanOnOff.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ThermalZone.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.BoilerHotWater.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoilHeatingGas.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.elevators.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.WaterHeaterMixed.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanConstantVolume.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.PumpVariableSpeed.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ChillerElectricEIR.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerTwoSpeed.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerSingleSpeed.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb,
lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb,
lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb
Overview
This class holds methods that apply ASHRAE 90.1-2019 to a given model.
Direct Known Subclasses
ASHRAE9012019College, ASHRAE9012019Courthouse, ASHRAE9012019FullServiceRestaurant, ASHRAE9012019HighriseApartment, ASHRAE9012019Hospital, ASHRAE9012019Laboratory, ASHRAE9012019LargeDataCenterHighITE, ASHRAE9012019LargeDataCenterLowITE, ASHRAE9012019LargeHotel, ASHRAE9012019LargeOffice, ASHRAE9012019LargeOfficeDetailed, ASHRAE9012019MediumOffice, ASHRAE9012019MediumOfficeDetailed, ASHRAE9012019MidriseApartment, ASHRAE9012019Outpatient, ASHRAE9012019PrimarySchool, ASHRAE9012019QuickServiceRestaurant, ASHRAE9012019RetailStandalone, ASHRAE9012019RetailStripmall, ASHRAE9012019SecondarySchool, ASHRAE9012019SmallDataCenterHighITE, ASHRAE9012019SmallDataCenterLowITE, ASHRAE9012019SmallHotel, ASHRAE9012019SmallOffice, ASHRAE9012019SmallOfficeDetailed, ASHRAE9012019SuperMarket, ASHRAE9012019SuperTallBuilding, ASHRAE9012019TallBuilding, ASHRAE9012019Warehouse, ASHRAE9012019_Prototype, ComStockASHRAE9012019
Constant Summary
Constants inherited from Standard
Instance Attribute Summary collapse
-
#template ⇒ Object
readonly
Returns the value of attribute template.
Attributes inherited from Standard
#space_multiplier_map, #standards_data
Pump collapse
-
#pump_standard_minimum_motor_efficiency_and_size(pump, motor_bhp) ⇒ Array<Double>
Determines the minimum pump motor efficiency and nominal size for a given motor bhp.
-
#pump_variable_speed_get_control_type(pump, plant_loop_type, pump_nominal_hp) ⇒ String
Determine type of pump part load control type.
Space collapse
-
#space_daylighted_area_window_width(space) ⇒ String
Determines the method used to extend the daylighted area horizontally next to a window.
-
#space_daylighting_control_required?(space, areas) ⇒ Array<Bool>
Determine if the space requires daylighting controls for toplighting, primary sidelighting, and secondary sidelighting.
-
#space_daylighting_control_type(space) ⇒ Object
Provide the type of daylighting control type.
-
#space_daylighting_fractions_and_windows(space, areas, sorted_windows, sorted_skylights, req_top_ctrl, req_pri_ctrl, req_sec_ctrl) ⇒ Array
Determine the fraction controlled by each sensor and which window each sensor should go near.
-
#space_daylighting_minimum_input_power_fraction(space) ⇒ Object
Provide the minimum input power fraction for continuous dimming daylighting control.
-
#space_infiltration_rate_75_pa(space = nil) ⇒ Double
Determine the base infiltration rate at 75 Pa.
-
#space_occupancy_standby_mode(thermostat) ⇒ Boolean
Modify thermostat schedule to account for a thermostat setback/up.
-
#space_occupancy_standby_mode_required?(space) ⇒ Boolean
Determine if a space should be modeled with an occupancy standby mode.
Model collapse
-
#model_add_lights_shutoff(model) ⇒ Boolean
Implement occupancy based lighting level threshold (0.02 W/sqft).
-
#model_door_infil_flow_rate_metal_coiling_cfm_ft2(climate_zone) ⇒ Double
Metal coiling door code minimum infiltration rate at 75 Pa.
-
#model_fenestration_orientation(model, climate_zone) ⇒ Boolean
Adjust model to comply with fenestration orientation requirements.
-
#model_transfer_air_required?(model) ⇒ Boolean
Is transfer air required?.
FanOnOff collapse
-
#fan_on_off_airloop_or_unitary_fan_pressure_rise(fan_on_off) ⇒ Double
Determine the prototype fan pressure rise for an on off fan on an AirLoopHVAC or inside a unitary system based on system airflow.
AirLoopHVAC collapse
-
#air_loop_hvac_adjust_minimum_vav_damper_positions(air_loop_hvac) ⇒ Boolean
Adjust minimum VAV damper positions and set minimum design system outdoor air flow following ASHRAE Std.
-
#air_loop_hvac_demand_control_ventilation_limits(air_loop_hvac) ⇒ Array<Double>
Determines the OA flow rates above which an economizer is required.
-
#air_loop_hvac_economizer_limits(air_loop_hvac, climate_zone) ⇒ Array<Double>
Determine the limits for the type of economizer present on the AirLoopHVAC, if any.
-
#air_loop_hvac_economizer_type_allowable?(air_loop_hvac, climate_zone) ⇒ Boolean
Check the economizer type currently specified in the ControllerOutdoorAir object on this air loop is acceptable per the standard.
-
#air_loop_hvac_energy_recovery_ventilator_flow_limit(air_loop_hvac, climate_zone, pct_oa) ⇒ Double
Determine the airflow limits that govern whether or not an ERV is required.
-
#air_loop_hvac_integrated_economizer_required?(air_loop_hvac, climate_zone) ⇒ Boolean
Determine if the system economizer must be integrated or not.
-
#air_loop_hvac_motorized_oa_damper_limits(air_loop_hvac, climate_zone) ⇒ Array<Double>
Determine the air flow and number of story limits for whether motorized OA damper is required.
-
#air_loop_hvac_multizone_vav_optimization_required?(air_loop_hvac, climate_zone) ⇒ Boolean
Determine if multizone vav optimization is required.
-
#air_loop_hvac_single_zone_controls_num_stages(air_loop_hvac, climate_zone) ⇒ Integer
Determine the number of stages that should be used as controls for single zone DX systems.
-
#air_loop_hvac_standby_mode_occupancy_control(air_loop_hvac, standby_mode_spaces) ⇒ Boolean
Add occupant standby controls to air loop When the thermostat schedule is setup or setback the ventilation is shutoff.
-
#air_loop_hvac_supply_air_temperature_reset_required?(air_loop_hvac, climate_zone) ⇒ Boolean
Determine if the system required supply air temperature (SAT) reset.
-
#model_economizer_type(model, climate_zone) ⇒ String
Determine the prototypical economizer type for the model.
ThermalZone collapse
-
#thermal_zone_demand_control_ventilation_limits(thermal_zone) ⇒ Array<Double>
Determine the area and occupancy level limits for demand control ventilation.
-
#thermal_zone_occupancy_type(thermal_zone) ⇒ String
Determine the thermal zone’s occupancy type category.
hvac_systems collapse
-
#model_cw_loop_cooling_tower_fan_type(model) ⇒ String
Determine which type of fan the cooling tower will have.
-
#set_maximum_fraction_outdoor_air_schedule(air_loop_hvac, oa_control, snc) ⇒ OpenStudio::Model::ScheduleRuleset
Create an economizer maximum OA fraction schedule with For ASHRAE 90.1 2019, a maximum of 75% to reflect damper leakage per PNNL.
elevators collapse
-
#model_elevator_fan_pwr(model, vent_rate_cfm) ⇒ Double
Determines the power of the elevator ventilation fan.
-
#model_elevator_lighting_pct_incandescent(model) ⇒ Double
Determines the percentage of the elevator cab lighting that is incandescent.
FanVariableVolume collapse
-
#fan_variable_volume_airloop_fan_pressure_rise(fan_variable_volume) ⇒ Double
Determine the prototype fan pressure rise for a variable volume fan on an AirLoopHVAC based on system airflow.
-
#fan_variable_volume_part_load_fan_power_limitation_capacity_limit(fan_variable_volume) ⇒ Double
The threhold capacity below which part load control is not required.
-
#fan_variable_volume_part_load_fan_power_limitation_hp_limit(fan_variable_volume) ⇒ Double
The threhold horsepower below which part load control is not required.
ZoneHVACComponent collapse
-
#zone_hvac_component_vestibule_heating_control_required?(zone_hvac_component) ⇒ Boolean
Determine if vestibule heating control is required.
-
#zone_hvac_model_standby_mode_occupancy_control(zone_hvac_component) ⇒ Boolean
Add occupant standby controls to zone equipment Currently, the controls consists of cycling the fan during the occupant standby mode hours.
FanConstantVolume collapse
-
#fan_constant_volume_airloop_fan_pressure_rise(fan_constant_volume) ⇒ Double
Determine the prototype fan pressure rise for a constant volume fan on an AirLoopHVAC based on system airflow.
AirTerminalSingleDuctVAVReheat collapse
-
#air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(air_terminal_single_duct_vav_reheat, zone_oa_per_area) ⇒ Boolean
Set the initial minimum damper position based on OA rate of the space and the template.
-
#air_terminal_single_duct_vav_reheat_minimum_damper_position(air_terminal_single_duct_vav_reheat, has_ddc = false) ⇒ Double
Specifies the minimum damper position for VAV dampers.
Instance Method Summary collapse
-
#boiler_get_eff_fplr(boiler_hot_water) ⇒ String
Determine what part load efficiency degredation curve should be used for a boiler.
-
#chiller_electric_eir_get_cap_f_t_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) ⇒ String
Get applicable performance curve for capacity as a function of temperature.
-
#chiller_electric_eir_get_eir_f_plr_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) ⇒ String
Get applicable performance curve for EIR as a function of part load ratio.
-
#chiller_electric_eir_get_eir_f_t_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) ⇒ String
Get applicable performance curve for EIR as a function of temperature.
-
#coil_heating_gas_additional_search_criteria(coil_heating_gas, search_criteria) ⇒ Hash
Applies the standard efficiency ratings to CoilHeatingGas.
-
#cooling_tower_variable_speed_apply_efficiency_and_curves(cooling_tower_variable_speed) ⇒ Boolean
Apply the efficiency, plus Multicell heat rejection with VSD.
-
#initialize ⇒ ASHRAE9012019
constructor
A new instance of ASHRAE9012019.
-
#load_standards_database(data_directories = []) ⇒ Hash
Loads the openstudio standards dataset for this standard.
-
#water_heater_mixed_additional_search_criteria(water_heater_mixed, search_criteria) ⇒ Hash
Add additional search criteria for water heater lookup efficiency.
Methods included from ASHRAE9012019CoolingTower
#cooling_tower_apply_minimum_power_per_flow_gpm_limit
Methods inherited from Standard
#adjust_sizing_system, #afue_to_thermal_eff, #air_loop_hvac_add_motorized_oa_damper, #air_loop_hvac_adjust_minimum_vav_damper_positions_outpatient, #air_loop_hvac_allowable_system_brake_horsepower, #air_loop_hvac_apply_baseline_fan_pressure_rise, #air_loop_hvac_apply_economizer_integration, #air_loop_hvac_apply_economizer_limits, #air_loop_hvac_apply_energy_recovery_ventilator, #air_loop_hvac_apply_energy_recovery_ventilator_efficiency, #air_loop_hvac_apply_maximum_reheat_temperature, #air_loop_hvac_apply_minimum_vav_damper_positions, #air_loop_hvac_apply_multizone_vav_outdoor_air_sizing, #air_loop_hvac_apply_prm_baseline_controls, #air_loop_hvac_apply_prm_baseline_economizer, #air_loop_hvac_apply_prm_baseline_fan_power, #air_loop_hvac_apply_prm_sizing_temperatures, #air_loop_hvac_apply_single_zone_controls, #air_loop_hvac_apply_standard_controls, #air_loop_hvac_apply_vav_damper_action, #air_loop_hvac_data_center_area_served, #air_loop_hvac_dcv_required_when_erv, #air_loop_hvac_demand_control_ventilation_required?, #air_loop_hvac_disable_multizone_vav_optimization, #air_loop_hvac_dx_cooling?, #air_loop_hvac_economizer?, #air_loop_hvac_economizer_required?, #air_loop_hvac_enable_demand_control_ventilation, #air_loop_hvac_enable_multizone_vav_optimization, #air_loop_hvac_enable_optimum_start, #air_loop_hvac_enable_supply_air_temperature_reset_delta, #air_loop_hvac_enable_supply_air_temperature_reset_outdoor_temperature, #air_loop_hvac_enable_supply_air_temperature_reset_warmest_zone, #air_loop_hvac_enable_unoccupied_fan_shutoff, #air_loop_hvac_energy_recovery?, #air_loop_hvac_energy_recovery_ventilator_heat_exchanger_type, #air_loop_hvac_energy_recovery_ventilator_required?, #air_loop_hvac_energy_recovery_ventilator_type, #air_loop_hvac_fan_power_limitation_pressure_drop_adjustment_brake_horsepower, #air_loop_hvac_find_design_supply_air_flow_rate, #air_loop_hvac_floor_area_served, #air_loop_hvac_floor_area_served_exterior_zones, #air_loop_hvac_floor_area_served_interior_zones, #air_loop_hvac_get_occupancy_schedule, #air_loop_hvac_get_relief_fan_power, #air_loop_hvac_get_return_fan_power, #air_loop_hvac_get_supply_fan, #air_loop_hvac_get_supply_fan_power, #air_loop_hvac_has_parallel_piu_air_terminals?, #air_loop_hvac_has_simple_transfer_air?, #air_loop_hvac_humidifier_count, #air_loop_hvac_include_cooling_coil?, #air_loop_hvac_include_economizer?, #air_loop_hvac_include_evaporative_cooler?, #air_loop_hvac_include_hydronic_cooling_coil?, #air_loop_hvac_include_unitary_system?, #air_loop_hvac_include_wshp?, #air_loop_hvac_minimum_zone_ventilation_efficiency, #air_loop_hvac_motorized_oa_damper_required?, #air_loop_hvac_multi_stage_dx_cooling?, #air_loop_hvac_multizone_vav_system?, #air_loop_hvac_optimum_start_required?, #air_loop_hvac_prm_baseline_economizer_required?, #air_loop_hvac_prm_economizer_type_and_limits, #air_loop_hvac_remove_erv, #air_loop_hvac_remove_motorized_oa_damper, #air_loop_hvac_residential_area_served, #air_loop_hvac_return_air_plenum, #air_loop_hvac_set_minimum_damper_position, #air_loop_hvac_set_vsd_curve_type, #air_loop_hvac_static_pressure_reset_required?, #air_loop_hvac_supply_return_exhaust_relief_fans, #air_loop_hvac_system_fan_brake_horsepower, #air_loop_hvac_system_multiplier, #air_loop_hvac_terminal_reheat?, #air_loop_hvac_total_cooling_capacity, #air_loop_hvac_unitary_system?, #air_loop_hvac_unoccupied_fan_shutoff_required?, #air_loop_hvac_unoccupied_threshold, #air_loop_hvac_vav_damper_action, #air_loop_hvac_vav_system?, #air_terminal_single_duct_parallel_piu_reheat_apply_minimum_primary_airflow_fraction, #air_terminal_single_duct_parallel_piu_reheat_apply_prm_baseline_fan_power, #air_terminal_single_duct_parallel_piu_reheat_fan_on_flow_fraction, #air_terminal_single_duct_parallel_reheat_piu_minimum_primary_airflow_fraction, #air_terminal_single_duct_vav_reheat_apply_minimum_damper_position, #air_terminal_single_duct_vav_reheat_reheat_type, #air_terminal_single_duct_vav_reheat_set_heating_cap, #apply_lighting_schedule, #apply_limit_to_subsurface_ratio, #boiler_hot_water_apply_efficiency_and_curves, #boiler_hot_water_find_capacity, #boiler_hot_water_find_design_water_flow_rate, #boiler_hot_water_find_search_criteria, #boiler_hot_water_standard_minimum_thermal_efficiency, build, #chiller_electric_eir_apply_efficiency_and_curves, #chiller_electric_eir_find_capacity, #chiller_electric_eir_find_search_criteria, #chiller_electric_eir_standard_minimum_full_load_efficiency, #chw_sizing_control, #coil_cooling_dx_multi_speed_apply_efficiency_and_curves, #coil_cooling_dx_multi_speed_find_capacity, #coil_cooling_dx_multi_speed_standard_minimum_cop, #coil_cooling_dx_single_speed_apply_efficiency_and_curves, #coil_cooling_dx_single_speed_find_capacity, #coil_cooling_dx_single_speed_standard_minimum_cop, #coil_cooling_dx_two_speed_apply_efficiency_and_curves, #coil_cooling_dx_two_speed_find_capacity, #coil_cooling_dx_two_speed_standard_minimum_cop, #coil_cooling_water_to_air_heat_pump_apply_efficiency_and_curves, #coil_cooling_water_to_air_heat_pump_find_capacity, #coil_cooling_water_to_air_heat_pump_standard_minimum_cop, #coil_heating_dx_multi_speed_apply_efficiency_and_curves, #coil_heating_dx_single_speed_apply_defrost_eir_curve_limits, #coil_heating_dx_single_speed_apply_efficiency_and_curves, #coil_heating_dx_single_speed_find_capacity, #coil_heating_dx_single_speed_standard_minimum_cop, #coil_heating_gas_apply_efficiency_and_curves, #coil_heating_gas_apply_prototype_efficiency, #coil_heating_gas_find_capacity, #coil_heating_gas_multi_stage_apply_efficiency_and_curves, #coil_heating_gas_multi_stage_find_capacity, #coil_heating_gas_multi_stage_find_search_criteria, #coil_heating_water_to_air_heat_pump_apply_efficiency_and_curves, #coil_heating_water_to_air_heat_pump_find_capacity, #coil_heating_water_to_air_heat_pump_standard_minimum_cop, #combustion_eff_to_thermal_eff, #controller_water_coil_set_convergence_limits, #convert_curve_biquadratic, #cooling_tower_single_speed_apply_efficiency_and_curves, #cooling_tower_two_speed_apply_efficiency_and_curves, #cop_heating_to_cop_heating_no_fan, #cop_no_fan_to_eer, #cop_no_fan_to_seer, #cop_to_eer, #cop_to_kw_per_ton, #cop_to_seer, #create_air_conditioner_variable_refrigerant_flow, #create_boiler_hot_water, #create_central_air_source_heat_pump, #create_coil_cooling_dx_single_speed, #create_coil_cooling_dx_two_speed, #create_coil_cooling_water, #create_coil_cooling_water_to_air_heat_pump_equation_fit, #create_coil_heating_dx_single_speed, #create_coil_heating_electric, #create_coil_heating_gas, #create_coil_heating_water, #create_coil_heating_water_to_air_heat_pump_equation_fit, #create_curve_bicubic, #create_curve_biquadratic, #create_curve_cubic, #create_curve_exponent, #create_curve_quadratic, #create_fan_constant_volume, #create_fan_constant_volume_from_json, #create_fan_on_off, #create_fan_on_off_from_json, #create_fan_variable_volume, #create_fan_variable_volume_from_json, #create_fan_zone_exhaust, #create_fan_zone_exhaust_from_json, #define_space_multiplier, #eer_to_cop, #eer_to_cop_no_fan, #ems_friendly_name, #enthalpy_recovery_ratio_design_to_typical_adjustment, #fan_constant_volume_apply_prototype_fan_pressure_rise, #fan_on_off_apply_prototype_fan_pressure_rise, #fan_variable_volume_apply_prototype_fan_pressure_rise, #fan_variable_volume_cooling_system_type, #fan_variable_volume_part_load_fan_power_limitation?, #fan_variable_volume_set_control_type, #fan_zone_exhaust_apply_prototype_fan_pressure_rise, #find_exposed_conditioned_roof_surfaces, #find_exposed_conditioned_vertical_surfaces, #find_highest_roof_centre, #fluid_cooler_apply_minimum_power_per_flow, #get_avg_of_other_zones, #get_default_surface_cons_from_surface_type, #get_fan_object_for_airloop, #get_fan_schedule_for_each_zone, #get_group_heat_types, #get_outdoor_subsurface_ratio, #get_weekday_values_from_8760, #get_wtd_avg_of_other_zones, #headered_pumps_variable_speed_set_control_type, #heat_exchanger_air_to_air_sensible_and_latent_apply_effectiveness, #heat_exchanger_air_to_air_sensible_and_latent_apply_prototype_efficiency, #heat_exchanger_air_to_air_sensible_and_latent_apply_prototype_efficiency_enthalpy_recovery_ratio, #heat_exchanger_air_to_air_sensible_and_latent_apply_prototype_nominal_electric_power, #heat_exchanger_air_to_air_sensible_and_latent_enthalpy_recovery_ratio_to_effectiveness, #heat_exchanger_air_to_air_sensible_and_latent_minimum_effectiveness, #heat_exchanger_air_to_air_sensible_and_latent_prototype_default_fan_efficiency, #hspf_to_cop, #hspf_to_cop_no_fan, #interior_lighting_get_prm_data, #kw_per_ton_to_cop, #load_hvac_map, #load_initial_osm, #make_ruleset_sched_from_8760, #make_week_ruleset_sched_from_168, #model_add_baseboard, #model_add_cav, #model_add_central_air_source_heat_pump, #model_add_chw_loop, #model_add_construction, #model_add_construction_set, #model_add_crac, #model_add_crah, #model_add_curve, #model_add_cw_loop, #model_add_data_center_hvac, #model_add_data_center_load, #model_add_daylighting_controls, #model_add_district_ambient_loop, #model_add_doas, #model_add_doas_cold_supply, #model_add_elevator, #model_add_elevators, #model_add_evap_cooler, #model_add_exhaust_fan, #model_add_four_pipe_fan_coil, #model_add_furnace_central_ac, #model_add_ground_hx_loop, #model_add_high_temp_radiant, #model_add_hp_loop, #model_add_hvac, #model_add_hvac_system, #model_add_hw_loop, #model_add_ideal_air_loads, #model_add_low_temp_radiant, #model_add_material, #model_add_minisplit_hp, #model_add_plant_supply_water_temperature_control, #model_add_prm_baseline_system, #model_add_prm_elevators, #model_add_psz_ac, #model_add_psz_vav, #model_add_ptac, #model_add_pthp, #model_add_pvav, #model_add_pvav_pfp_boxes, #model_add_radiant_basic_controls, #model_add_radiant_proportional_controls, #model_add_refrigeration_case, #model_add_refrigeration_compressor, #model_add_refrigeration_system, #model_add_refrigeration_walkin, #model_add_residential_erv, #model_add_residential_ventilator, #model_add_schedule, #model_add_split_ac, #model_add_swh, #model_add_swh_end_uses_by_space, #model_add_transformer, #model_add_typical_exterior_lights, #model_add_typical_refrigeration, #model_add_typical_swh, #model_add_unitheater, #model_add_vav_pfp_boxes, #model_add_vav_reheat, #model_add_vrf, #model_add_water_source_hp, #model_add_waterside_economizer, #model_add_window_ac, #model_add_zone_erv, #model_add_zone_heat_cool_request_count_program, #model_add_zone_ventilation, #model_apply_baseline_exterior_lighting, #model_apply_hvac_efficiency_standard, #model_apply_infiltration_standard, #model_apply_multizone_vav_outdoor_air_sizing, #model_apply_prm_baseline_sizing_schedule, #model_apply_prm_baseline_skylight_to_roof_ratio, #model_apply_prm_baseline_window_to_wall_ratio, #model_apply_prm_construction_types, #model_apply_prm_sizing_parameters, #model_apply_standard_constructions, #model_apply_standard_infiltration, #model_baseline_system_vav_fan_type, #model_create_exterior_lighting_area_length_count_hash, #model_create_multizone_fan_schedule, #model_create_prm_any_baseline_building, #model_create_prm_baseline_building, #model_create_prm_baseline_building_requires_proposed_model_sizing_run, #model_create_prm_baseline_building_requires_vlt_sizing_run, #model_create_prm_proposed_building, #model_create_prm_stable_baseline_building, #model_create_space_type_hash, #model_create_story_hash, #model_differentiate_primary_secondary_thermal_zones, #model_effective_num_stories, #model_elevator_lift_power, #model_eliminate_outlier_zones, #model_find_and_add_construction, #model_find_ashrae_hot_water_demand, #model_find_climate_zone_set, #model_find_icc_iecc_2015_hot_water_demand, #model_find_icc_iecc_2015_internal_loads, #model_find_object, #model_find_objects, #model_find_prototype_floor_area, #model_find_target_eui, #model_find_target_eui_by_end_use, #model_find_water_heater_capacity_volume_and_parasitic, #model_get_baseline_system_type_by_zone, #model_get_building_properties, #model_get_climate_zone_set_from_list, #model_get_construction_properties, #model_get_construction_set, #model_get_district_heating_zones, #model_get_lookup_name, #model_get_or_add_ambient_water_loop, #model_get_or_add_chilled_water_loop, #model_get_or_add_ground_hx_loop, #model_get_or_add_heat_pump_loop, #model_get_or_add_hot_water_loop, #model_is_hvac_autosized, #model_legacy_results_by_end_use_and_fuel_type, #model_make_name, #model_prm_baseline_system_change_fuel_type, #model_prm_baseline_system_groups, #model_prm_baseline_system_number, #model_prm_baseline_system_type, #model_prm_skylight_to_roof_ratio_limit, #model_process_results_for_datapoint, #model_remap_office, #model_remove_external_shading_devices, #model_remove_prm_ems_objects, #model_remove_prm_hvac, #model_remove_unused_resource_objects, #model_set_vav_terminals_to_control_for_outdoor_air, #model_system_outdoor_air_sizing_vrp_method, #model_two_pipe_loop, #model_typical_display_case_zone, #model_typical_hvac_system_type, #model_typical_walkin_zone, #model_validate_standards_spacetypes_in_model, #model_ventilation_method, #model_walkin_freezer_latent_case_credit_curve, #model_zones_with_occ_and_fuel_type, #planar_surface_apply_standard_construction, #plant_loop_adiabatic_pipes_only, #plant_loop_apply_prm_baseline_chilled_water_pumping_type, #plant_loop_apply_prm_baseline_chilled_water_temperatures, #plant_loop_apply_prm_baseline_condenser_water_pumping_type, #plant_loop_apply_prm_baseline_condenser_water_temperatures, #plant_loop_apply_prm_baseline_hot_water_pumping_type, #plant_loop_apply_prm_baseline_hot_water_temperatures, #plant_loop_apply_prm_baseline_pump_power, #plant_loop_apply_prm_baseline_pumping_type, #plant_loop_apply_prm_baseline_temperatures, #plant_loop_apply_prm_number_of_boilers, #plant_loop_apply_prm_number_of_chillers, #plant_loop_apply_prm_number_of_cooling_towers, #plant_loop_apply_standard_controls, #plant_loop_capacity_w_by_maxflow_and_delta_t_forwater, #plant_loop_enable_supply_water_temperature_reset, #plant_loop_find_maximum_loop_flow_rate, #plant_loop_prm_baseline_condenser_water_temperatures, #plant_loop_set_chw_pri_sec_configuration, #plant_loop_supply_water_temperature_reset_required?, #plant_loop_swh_loop?, #plant_loop_swh_system_type, #plant_loop_total_cooling_capacity, #plant_loop_total_floor_area_served, #plant_loop_total_heating_capacity, #plant_loop_total_rated_w_per_gpm, #plant_loop_variable_flow_system?, #prototype_apply_condenser_water_temperatures, #prototype_condenser_water_temperatures, #pump_variable_speed_control_type, #pump_variable_speed_set_control_type, register_standard, #remove_air_loops, #remove_all_hvac, #remove_all_plant_loops, #remove_all_zone_equipment, #remove_hvac, #remove_plant_loops, #remove_unused_curves, #remove_vrf, #remove_zone_equipment, #rename_air_loop_nodes, #rename_plant_loop_nodes, #safe_load_model, #seer_to_cop, #seer_to_cop_no_fan, #space_add_daylighting_controls, #space_apply_infiltration_rate, #space_conditioning_category, #space_daylighted_areas, #space_get_equip_annual_array, #space_get_loads_for_all_equips, #space_internal_load_annual_array, #space_occupancy_annual_array, #space_remove_daylighting_controls, #space_set_baseline_daylighting_controls, #space_sidelighting_effective_aperture, #space_skylight_effective_aperture, #space_type_apply_int_loads_prm, #space_type_apply_internal_load_schedules, #space_type_apply_internal_loads, #space_type_apply_rendering_color, #space_type_get_construction_properties, #space_type_get_standards_data, #space_type_light_sch_change, #standard_design_sizing_temperatures, #standards_lookup_table_first, #standards_lookup_table_many, #strip_model, #sub_surface_create_centered_subsurface_from_scaled_surface, #sub_surface_create_scaled_subsurfaces_from_surface, #surface_adjust_fenestration_in_a_surface, #surface_subsurface_ua, #thermal_eff_to_afue, #thermal_eff_to_comb_eff, #thermal_zone_add_exhaust, #thermal_zone_add_exhaust_fan_dcv, #thermal_zone_apply_prm_baseline_supply_temperatures, #thermal_zone_conditioning_category, #thermal_zone_demand_control_ventilation_required?, #thermal_zone_exhaust_fan_dcv_required?, #thermal_zone_fossil_or_electric_type, #thermal_zone_get_annual_operating_hours, #thermal_zone_get_zone_fuels_for_occ_and_fuel_type, #thermal_zone_infer_system_type, #thermal_zone_occupancy_eflh, #thermal_zone_peak_internal_load, #thermal_zone_prm_baseline_cooling_design_supply_temperature, #thermal_zone_prm_baseline_heating_design_supply_temperature, #thermal_zone_prm_lab_delta_t, #thermal_zone_prm_unitheater_design_supply_temperature, #true?, #validate_initial_model, #water_heater_convert_energy_factor_to_thermal_efficiency_and_ua, #water_heater_convert_uniform_energy_factor_to_energy_factor, #water_heater_determine_sub_type, #water_heater_mixed_apply_efficiency, #water_heater_mixed_apply_prm_baseline_fuel_type, #water_heater_mixed_find_capacity, #water_heater_mixed_get_efficiency_requirement, #zone_hvac_component_apply_prm_baseline_fan_power, #zone_hvac_component_apply_standard_controls, #zone_hvac_component_apply_vestibule_heating_control, #zone_hvac_component_occupancy_ventilation_control, #zone_hvac_component_prm_baseline_fan_efficacy, #zone_hvac_get_fan_object, #zone_hvac_unoccupied_threshold
Methods included from PrototypeFan
apply_base_fan_variables, #create_fan_by_name, #get_fan_from_standards, #lookup_fan_curve_coefficients_from_json, #prototype_fan_apply_prototype_fan_efficiency
Methods included from CoilDX
#coil_dx_find_search_criteria, #coil_dx_heat_pump?, #coil_dx_heating_type, #coil_dx_subcategory
Methods included from CoolingTower
#cooling_tower_apply_minimum_power_per_flow, #cooling_tower_apply_minimum_power_per_flow_gpm_limit
Methods included from Pump
#pump_apply_prm_pressure_rise_and_motor_efficiency, #pump_apply_standard_minimum_motor_efficiency, #pump_brake_horsepower, #pump_motor_horsepower, #pump_pumppower, #pump_rated_w_per_gpm
Methods included from Fan
#fan_adjust_pressure_rise_to_meet_fan_power, #fan_apply_standard_minimum_motor_efficiency, #fan_baseline_impeller_efficiency, #fan_brake_horsepower, #fan_change_impeller_efficiency, #fan_change_motor_efficiency, #fan_design_air_flow, #fan_fanpower, #fan_motor_horsepower, #fan_rated_w_per_cfm, #fan_small_fan?, #fan_standard_minimum_motor_efficiency_and_size
Constructor Details
#initialize ⇒ ASHRAE9012019
Returns a new instance of ASHRAE9012019.
8 9 10 11 12 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.rb', line 8 def initialize super() @template = '90.1-2019' load_standards_database end |
Instance Attribute Details
#template ⇒ Object (readonly)
Returns the value of attribute template.
6 7 8 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.rb', line 6 def template @template end |
Instance Method Details
#air_loop_hvac_adjust_minimum_vav_damper_positions(air_loop_hvac) ⇒ Boolean
Add exception logic for systems serving parking garage, warehouse, or multifamily
Adjust minimum VAV damper positions and set minimum design system outdoor air flow following ASHRAE Std. 62.1-2019
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 562 def air_loop_hvac_adjust_minimum_vav_damper_positions(air_loop_hvac) # Do not apply the adjustment to some of the system in # the hospital and outpatient which have their minimum # damper position determined based on AIA 2001 ventilation # requirements if (@instvarbuilding_type == 'Hospital' && (air_loop_hvac.name.to_s.include?('VAV_ER') || air_loop_hvac.name.to_s.include?('VAV_ICU') || air_loop_hvac.name.to_s.include?('VAV_OR') || air_loop_hvac.name.to_s.include?('VAV_LABS') || air_loop_hvac.name.to_s.include?('VAV_PATRMS'))) || (@instvarbuilding_type == 'Outpatient' && air_loop_hvac.name.to_s.include?('Outpatient F1')) return true end # Total uncorrected outdoor airflow rate v_ou = 0.0 air_loop_hvac.thermalZones.each do |zone| # Vou is the system uncorrected outdoor airflow: # Zone airflow is multiplied by the zone multiplier v_ou += OpenstudioStandards::ThermalZone.thermal_zone_get_outdoor_airflow_rate(zone) * zone.multiplier.to_f end v_ou_cfm = OpenStudio.convert(v_ou, 'm^3/s', 'cfm').get OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: v_ou = #{v_ou_cfm.round} cfm.") # Retrieve the sum of the zone minimum primary airflow if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.6.0') OpenStudio.logFree(OpenStudio::Error, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', 'Required AirLoopHVAC method .autosizedSumMinimumHeatingAirFlowRates is not available in pre-OpenStudio 3.6.0 versions. Use a more recent version of OpenStudio.') else vpz_min_sum = air_loop_hvac.autosizedSumMinimumHeatingAirFlowRates end air_loop_hvac.thermalZones.sort.each do |zone| # Breathing zone airflow rate v_bz = OpenstudioStandards::ThermalZone.thermal_zone_get_outdoor_airflow_rate(zone) # Zone air distribution, assumed 1 per PNNL e_z = 1.0 # Zone airflow rate v_oz = v_bz / e_z # Primary design airflow rate # max of heating and cooling # design air flow rates v_pz = 0.0 # error if zone autosized methods are not available if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.6.0') OpenStudio.logFree(OpenStudio::Error, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', 'Required ThermalZone methods .autosizedCoolingDesignAirFlowRate and .autosizedHeatingDesignAirFlowRate are not available in pre-OpenStudio 3.6.0 versions. Use a more recent version of OpenStudio.') end clg_dsn_flow = zone.autosizedCoolingDesignAirFlowRate if clg_dsn_flow.is_initialized clg_dsn_flow = clg_dsn_flow.get if clg_dsn_flow > v_pz v_pz = clg_dsn_flow end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "For #{air_loop_hvac.name}: #{zone.name} clg_dsn_flow could not be found.") end htg_dsn_flow = zone.autosizedHeatingDesignAirFlowRate if htg_dsn_flow.is_initialized htg_dsn_flow = htg_dsn_flow.get if htg_dsn_flow > v_pz v_pz = htg_dsn_flow end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "For #{air_loop_hvac.name}: #{zone.name} htg_dsn_flow could not be found.") end # Zone ventilation efficiency calculation is computed # on a per zone basis, the zone primary airflow is # adjusted to removed the zone multiplier v_pz /= zone.multiplier.to_f # Set minimum damper position air_loop_hvac_set_minimum_damper_position(zone, [0.01, [1.5 * v_oz / v_pz, 1.0].min].max.round(3)) end # Occupant diversity (D): Ps / sum(Pz) # Current value is based on school prototypes # which are assumed to have the most diversity occ_diver_d = 0.66 # From ASHRAE Std 62.1-2019 Section 6.2.5.3 if occ_diver_d < 0.6 e_v = (0.88 * occ_diver_d) + 0.22 else e_v = 0.75 end # Total system outdoor intake flow rate v_ot = v_ou / e_v v_ot_cfm = OpenStudio.convert(v_ot, 'm^3/s', 'cfm').get # Get maximum OA fraction schedule oa_ctrl = air_loop_hvac.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir max_oa_frac_sch = oa_ctrl.maximumFractionofOutdoorAirSchedule if max_oa_frac_sch.is_initialized max_oa_frac_sch = max_oa_frac_sch.get if max_oa_frac_sch.to_ScheduleRuleset.is_initialized max_oa_frac_sch = max_oa_frac_sch.to_ScheduleRuleset.get max_oa_frac_sch_type = 'Schedule:Year' elsif max_oa_frac_sch.to_ScheduleConstant.is_initialized max_oa_frac_sch = max_oa_frac_sch.to_ScheduleConstant.get max_oa_frac_sch_type = 'Schedule:Constant' elsif max_oa_frac_sch.to_ScheduleCompact.is_initialized max_oa_frac_sch = max_oa_frac_sch.to_ScheduleCompact.get max_oa_frac_sch_type = 'Schedule:Compact' end else max_oa_frac_sch = OpenStudio::Model::ScheduleConstant.new(air_loop_hvac.model) max_oa_frac_sch.setName("#{air_loop_hvac.name}_MAX_OA_FRAC") max_oa_frac_sch.setValue(1.0) max_oa_frac_sch_type = 'Schedule:Constant' oa_ctrl.setMaximumFractionofOutdoorAirSchedule(max_oa_frac_sch) end # Add EMS to "cap" the OA calculated by the # Controller:MechanicalVentilation object # to the design v_ot using the maximum OA # fraction schedule # In newer EnergyPlus versions, this is handled by Standard62.1VentilationRateProcedureWithLimit # in the Controller:MechanicalVentilation object if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.3.0') # Add EMS sensors # OA mass flow calculated by the Controller:MechanicalVentilation air_loop_hvac_name_ems = ems_friendly_name(air_loop_hvac.name) oa_vrp_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mechanical Ventilation Requested Mass Flow Rate') oa_vrp_mass_flow.setKeyName(air_loop_hvac.name.to_s) oa_vrp_mass_flow.setName("#{air_loop_hvac_name_ems}_OA_VRP") # Actual sensed OA mass flow oa_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mass Flow Rate') oa_mass_flow.setKeyName(air_loop_hvac.name.to_s) oa_mass_flow.setName("#{air_loop_hvac_name_ems}_OA") # Actual sensed volumetric OA flow oa_vol_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'System Node Standard Density Volume Flow Rate') oa_vol_flow.setKeyName("#{air_loop_hvac.name} Mixed Air Node") oa_vol_flow.setName("#{air_loop_hvac_name_ems}_SUPPLY_FLOW") # Add EMS actuator max_oa_fraction = OpenStudio::Model::EnergyManagementSystemActuator.new(max_oa_frac_sch, max_oa_frac_sch_type, 'Schedule Value') max_oa_fraction.setName("#{air_loop_hvac_name_ems}_MAX_OA_FRAC") # Add EMS program max_oa_ems_prog = OpenStudio::Model::EnergyManagementSystemProgram.new(air_loop_hvac.model) max_oa_ems_prog.setName("#{air_loop_hvac.name}_MAX_OA_FRAC") max_oa_ems_prog_body = <<-EMS IF #{air_loop_hvac_name_ems}_OA > #{air_loop_hvac_name_ems}_OA_VRP, SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL, ELSE, IF #{air_loop_hvac_name_ems}_SUPPLY_FLOW > 0, SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = #{v_ot} / #{air_loop_hvac_name_ems}_SUPPLY_FLOW, ELSE, SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL, ENDIF, ENDIF EMS max_oa_ems_prog.setBody(max_oa_ems_prog_body) max_oa_ems_prog_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(air_loop_hvac.model) max_oa_ems_prog_manager.setName("SET_#{air_loop_hvac.name.to_s.gsub(' ', '_')}_MAX_OA_FRAC") max_oa_ems_prog_manager.setCallingPoint('InsideHVACSystemIterationLoop') max_oa_ems_prog_manager.addProgram(max_oa_ems_prog) end # Hard-size the sizing:system # object with the calculated min OA flow rate sizing_system = air_loop_hvac.sizingSystem sizing_system.setDesignOutdoorAirFlowRate(v_ot) sizing_system.setSystemOutdoorAirMethod('ZoneSum') return true end |
#air_loop_hvac_demand_control_ventilation_limits(air_loop_hvac) ⇒ Array<Double>
Determines the OA flow rates above which an economizer is required. Two separate rates, one for systems with an economizer and another for systems without.
264 265 266 267 268 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 264 def air_loop_hvac_demand_control_ventilation_limits(air_loop_hvac) min_oa_without_economizer_cfm = 3000 min_oa_with_economizer_cfm = 750 return [min_oa_without_economizer_cfm, min_oa_with_economizer_cfm] end |
#air_loop_hvac_economizer_limits(air_loop_hvac, climate_zone) ⇒ Array<Double>
Determine the limits for the type of economizer present on the AirLoopHVAC, if any.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 41 def air_loop_hvac_economizer_limits(air_loop_hvac, climate_zone) drybulb_limit_f = nil enthalpy_limit_btu_per_lb = nil dewpoint_limit_f = nil # Get the OA system and OA controller oa_sys = air_loop_hvac.airLoopHVACOutdoorAirSystem return [nil, nil, nil] unless oa_sys.is_initialized oa_sys = oa_sys.get oa_control = oa_sys.getControllerOutdoorAir economizer_type = oa_control.getEconomizerControlType oa_control.resetEconomizerMinimumLimitDryBulbTemperature case economizer_type when 'NoEconomizer' OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name} no economizer") return [nil, nil, nil] when 'FixedDryBulb' search_criteria = { 'template' => template, 'climate_zone' => climate_zone } econ_limits = model_find_object(standards_data['economizers'], search_criteria) drybulb_limit_f = econ_limits['fixed_dry_bulb_high_limit_shutoff_temp'] when 'FixedEnthalpy' enthalpy_limit_btu_per_lb = 28.0 when 'FixedDewPointAndDryBulb' drybulb_limit_f = 75.0 dewpoint_limit_f = 55.0 when 'DifferentialDryBulb', 'DifferentialEnthalpy' OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Economizer type = #{economizer_type}, no limits defined.") end OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Economizer type = #{economizer_type}, limits [#{drybulb_limit_f},#{enthalpy_limit_btu_per_lb},#{dewpoint_limit_f}]") return [drybulb_limit_f, enthalpy_limit_btu_per_lb, dewpoint_limit_f] end |
#air_loop_hvac_economizer_type_allowable?(air_loop_hvac, climate_zone) ⇒ Boolean
Check the economizer type currently specified in the ControllerOutdoorAir object on this air loop is acceptable per the standard.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 97 def air_loop_hvac_economizer_type_allowable?(air_loop_hvac, climate_zone) # EnergyPlus economizer types # 'NoEconomizer' # 'FixedDryBulb' # 'FixedEnthalpy' # 'DifferentialDryBulb' # 'DifferentialEnthalpy' # 'FixedDewPointAndDryBulb' # 'ElectronicEnthalpy' # 'DifferentialDryBulbAndEnthalpy' # Get the OA system and OA controller oa_sys = air_loop_hvac.airLoopHVACOutdoorAirSystem return true unless oa_sys.is_initialized oa_sys = oa_sys.get oa_control = oa_sys.getControllerOutdoorAir economizer_type = oa_control.getEconomizerControlType # Return true if no economizer is present if economizer_type == 'NoEconomizer' return true end # Determine the prohibited types prohibited_types = [] case climate_zone when 'ASHRAE 169-2006-0B', 'ASHRAE 169-2006-1B', 'ASHRAE 169-2006-2B', 'ASHRAE 169-2006-3B', 'ASHRAE 169-2006-3C', 'ASHRAE 169-2006-4B', 'ASHRAE 169-2006-4C', 'ASHRAE 169-2006-5B', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B', 'ASHRAE 169-2013-0B', 'ASHRAE 169-2013-1B', 'ASHRAE 169-2013-2B', 'ASHRAE 169-2013-3B', 'ASHRAE 169-2013-3C', 'ASHRAE 169-2013-4B', 'ASHRAE 169-2013-4C', 'ASHRAE 169-2013-5B', 'ASHRAE 169-2013-6B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B' prohibited_types = ['FixedEnthalpy'] when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2006-2A', 'ASHRAE 169-2006-3A', 'ASHRAE 169-2006-4A', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-1A', 'ASHRAE 169-2013-2A', 'ASHRAE 169-2013-3A', 'ASHRAE 169-2013-4A' prohibited_types = ['FixedDryBulb', 'DifferentialDryBulb'] when 'ASHRAE 169-2006-5A', 'ASHRAE 169-2006-6A', 'ASHRAE 169-2013-5A', 'ASHRAE 169-2013-6A' prohibited_types = [] end # Check if the specified type is allowed economizer_type_allowed = true if prohibited_types.include?(economizer_type) economizer_type_allowed = false end return economizer_type_allowed end |
#air_loop_hvac_energy_recovery_ventilator_flow_limit(air_loop_hvac, climate_zone, pct_oa) ⇒ Double
Determine the airflow limits that govern whether or not an ERV is required. Based on climate zone and % OA, plus the number of operating hours the system has.
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 442 def air_loop_hvac_energy_recovery_ventilator_flow_limit(air_loop_hvac, climate_zone, pct_oa) # Calculate the number of system operating hours # based on the availability schedule. ann_op_hrs = 0.0 avail_sch = air_loop_hvac.availabilitySchedule if avail_sch == air_loop_hvac.model.alwaysOnDiscreteSchedule ann_op_hrs = 8760.0 elsif avail_sch.to_ScheduleRuleset.is_initialized avail_sch = avail_sch.to_ScheduleRuleset.get ann_op_hrs = OpenstudioStandards::Schedules.schedule_ruleset_get_hours_above_value(avail_sch, 0.0) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "For #{air_loop_hvac.name}: could not determine annual operating hours. Assuming less than 8,000 for ERV determination.") end if ann_op_hrs < 8000.0 # Table 6.5.6.1-1, less than 8000 hrs search_criteria = { 'template' => template, 'climate_zone' => climate_zone, 'under_8000_hours' => true, 'nontransient_dwelling' => false, 'enthalpy_recovery_ratio_design_conditions' => 'Cooling' } energy_recovery_limits = model_find_object(standards_data['energy_recovery'], search_criteria) if energy_recovery_limits.nil? # Repeat the search for heating search_criteria['enthalpy_recovery_ratio_design_conditions'] = 'Heating' energy_recovery_limits = model_find_object(standards_data['energy_recovery'], search_criteria) if energy_recovery_limits.nil? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "Cannot find energy recovery limits for template '#{template}', climate zone '#{climate_zone}', and under 8000 hours, assuming no energy recovery required.") return nil end end if pct_oa < 0.1 erv_cfm = nil elsif pct_oa >= 0.1 && pct_oa < 0.2 erv_cfm = energy_recovery_limits['10_to_20_percent_oa'] elsif pct_oa >= 0.2 && pct_oa < 0.3 erv_cfm = energy_recovery_limits['20_to_30_percent_oa'] elsif pct_oa >= 0.3 && pct_oa < 0.4 erv_cfm = energy_recovery_limits['30_to_40_percent_oa'] elsif pct_oa >= 0.4 && pct_oa < 0.5 erv_cfm = energy_recovery_limits['40_to_50_percent_oa'] elsif pct_oa >= 0.5 && pct_oa < 0.6 erv_cfm = energy_recovery_limits['50_to_60_percent_oa'] elsif pct_oa >= 0.6 && pct_oa < 0.7 erv_cfm = energy_recovery_limits['60_to_70_percent_oa'] elsif pct_oa >= 0.7 && pct_oa < 0.8 erv_cfm = energy_recovery_limits['70_to_80_percent_oa'] elsif pct_oa >= 0.8 erv_cfm = energy_recovery_limits['greater_than_80_percent_oa'] end else # Check if air loop serves a non-transient dwelling unit, # currently non-transient dwelling units are residential # spaces in the apartment prototypes building_data = model_get_building_properties(air_loop_hvac.model) building_type = building_data['building_type'] nontrans_dwel = false if building_type == 'MidriseApartment' || building_type == 'HighriseApartment' air_loop_hvac.thermalZones.each do |zone| next unless OpenstudioStandards::ThermalZone.thermal_zone_residential?(zone) nontrans_dwel = true end end # Table 6.5.6.1-2, above 8000 hrs search_criteria = { 'template' => template, 'climate_zone' => climate_zone, 'under_8000_hours' => false, 'nontransient_dwelling' => nontrans_dwel, 'enthalpy_recovery_ratio_design_conditions' => 'Cooling' } energy_recovery_limits = model_find_object(standards_data['energy_recovery'], search_criteria) if energy_recovery_limits.nil? # Repeat the search for heating search_criteria['enthalpy_recovery_ratio_design_conditions'] = 'Heating' energy_recovery_limits = model_find_object(standards_data['energy_recovery'], search_criteria) if energy_recovery_limits.nil? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "Cannot find energy recovery limits for template '#{template}', climate zone '#{climate_zone}', and under 8000 hours, assuming no energy recovery required.") return nil end end if pct_oa < 0.1 if nontrans_dwel erv_cfm = energy_recovery_limits['0_to_10_percent_oa'] else erv_cfm = nil end elsif pct_oa >= 0.1 && pct_oa < 0.2 erv_cfm = energy_recovery_limits['10_to_20_percent_oa'] elsif pct_oa >= 0.2 && pct_oa < 0.3 erv_cfm = energy_recovery_limits['20_to_30_percent_oa'] elsif pct_oa >= 0.3 && pct_oa < 0.4 erv_cfm = energy_recovery_limits['30_to_40_percent_oa'] elsif pct_oa >= 0.4 && pct_oa < 0.5 erv_cfm = energy_recovery_limits['40_to_50_percent_oa'] elsif pct_oa >= 0.5 && pct_oa < 0.6 erv_cfm = energy_recovery_limits['50_to_60_percent_oa'] elsif pct_oa >= 0.6 && pct_oa < 0.7 erv_cfm = energy_recovery_limits['60_to_70_percent_oa'] elsif pct_oa >= 0.7 && pct_oa < 0.8 erv_cfm = energy_recovery_limits['70_to_80_percent_oa'] elsif pct_oa >= 0.8 erv_cfm = energy_recovery_limits['greater_than_80_percent_oa'] end end return erv_cfm end |
#air_loop_hvac_integrated_economizer_required?(air_loop_hvac, climate_zone) ⇒ Boolean
Determine if the system economizer must be integrated or not. All economizers must be integrated in 90.1-2019
86 87 88 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 86 def air_loop_hvac_integrated_economizer_required?(air_loop_hvac, climate_zone) return true end |
#air_loop_hvac_motorized_oa_damper_limits(air_loop_hvac, climate_zone) ⇒ Array<Double>
Determine the air flow and number of story limits for whether motorized OA damper is required.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 275 def air_loop_hvac_motorized_oa_damper_limits(air_loop_hvac, climate_zone) case climate_zone when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2006-0B', 'ASHRAE 169-2006-1B', 'ASHRAE 169-2006-2A', 'ASHRAE 169-2006-2B', 'ASHRAE 169-2006-3A', 'ASHRAE 169-2006-3B', 'ASHRAE 169-2006-3C', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-1A', 'ASHRAE 169-2013-0B', 'ASHRAE 169-2013-1B', 'ASHRAE 169-2013-2A', 'ASHRAE 169-2013-2B', 'ASHRAE 169-2013-3A', 'ASHRAE 169-2013-3B', 'ASHRAE 169-2013-3C' minimum_oa_flow_cfm = 0 maximum_stories = 999 # Any number of stories else minimum_oa_flow_cfm = 0 maximum_stories = 0 end return [minimum_oa_flow_cfm, maximum_stories] end |
#air_loop_hvac_multizone_vav_optimization_required?(air_loop_hvac, climate_zone) ⇒ Boolean
Add exception logic for systems with AIA healthcare ventilation requirements dual duct systems
code_sections [90.1-2019_6.5.3.3]
Determine if multizone vav optimization is required.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 185 def air_loop_hvac_multizone_vav_optimization_required?(air_loop_hvac, climate_zone) multizone_opt_required = false # Not required for systems with fan-powered terminals num_fan_powered_terminals = 0 air_loop_hvac.demandComponents.each do |comp| if comp.to_AirTerminalSingleDuctParallelPIUReheat.is_initialized || comp.to_AirTerminalSingleDuctSeriesPIUReheat.is_initialized num_fan_powered_terminals += 1 end end if num_fan_powered_terminals > 0 OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, multizone vav optimization is not required because the system has #{num_fan_powered_terminals} fan-powered terminals.") return multizone_opt_required end # Get the OA intake controller_oa = nil controller_mv = nil oa_system = nil if air_loop_hvac.airLoopHVACOutdoorAirSystem.is_initialized oa_system = air_loop_hvac.airLoopHVACOutdoorAirSystem.get controller_oa = oa_system.getControllerOutdoorAir controller_mv = controller_oa.controllerMechanicalVentilation else OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, multizone optimization is not applicable because system has no OA intake.") return multizone_opt_required end # Get the AHU design supply air flow rate dsn_flow_m3_per_s = nil if air_loop_hvac.designSupplyAirFlowRate.is_initialized dsn_flow_m3_per_s = air_loop_hvac.designSupplyAirFlowRate.get elsif air_loop_hvac.autosizedDesignSupplyAirFlowRate.is_initialized dsn_flow_m3_per_s = air_loop_hvac.autosizedDesignSupplyAirFlowRate.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name} design supply air flow rate is not available, cannot apply efficiency standard.") return multizone_opt_required end dsn_flow_cfm = OpenStudio.convert(dsn_flow_m3_per_s, 'm^3/s', 'cfm').get # Get the minimum OA flow rate min_oa_flow_m3_per_s = nil if controller_oa.minimumOutdoorAirFlowRate.is_initialized min_oa_flow_m3_per_s = controller_oa.minimumOutdoorAirFlowRate.get elsif controller_oa.autosizedMinimumOutdoorAirFlowRate.is_initialized min_oa_flow_m3_per_s = controller_oa.autosizedMinimumOutdoorAirFlowRate.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.AirLoopHVAC', "For #{controller_oa.name}: minimum OA flow rate is not available, cannot apply efficiency standard.") return multizone_opt_required end min_oa_flow_cfm = OpenStudio.convert(min_oa_flow_m3_per_s, 'm^3/s', 'cfm').get # Calculate the percent OA at design airflow pct_oa = min_oa_flow_m3_per_s / dsn_flow_m3_per_s # Not required for systems where # exhaust is more than 70% of the total OA intake. if pct_oa > 0.7 OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{controller_oa.name}: multizone optimization is not applicable because system is more than 70% OA.") return multizone_opt_required end # @todo Not required for dual-duct systems # if self.isDualDuct # OpenStudio::logFree(OpenStudio::Info, "openstudio.standards.AirLoopHVAC", "For #{controller_oa.name}: multizone optimization is not applicable because it is a dual duct system") # return multizone_opt_required # end # If here, multizone vav optimization is required multizone_opt_required = true return multizone_opt_required end |
#air_loop_hvac_single_zone_controls_num_stages(air_loop_hvac, climate_zone) ⇒ Integer
Determine the number of stages that should be used as controls for single zone DX systems. 90.1-2019 depends on the cooling capacity of the system.
311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 311 def air_loop_hvac_single_zone_controls_num_stages(air_loop_hvac, climate_zone) min_clg_cap_btu_per_hr = 65_000 clg_cap_btu_per_hr = OpenStudio.convert(air_loop_hvac_total_cooling_capacity(air_loop_hvac), 'W', 'Btu/hr').get if clg_cap_btu_per_hr >= min_clg_cap_btu_per_hr num_stages = 2 OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: two-stage control is required since cooling capacity of #{clg_cap_btu_per_hr.round} Btu/hr exceeds the minimum of #{min_clg_cap_btu_per_hr.round} Btu/hr .") else num_stages = 1 OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: two-stage control is not required since cooling capacity of #{clg_cap_btu_per_hr.round} Btu/hr is less than the minimum of #{min_clg_cap_btu_per_hr.round} Btu/hr .") end return num_stages end |
#air_loop_hvac_standby_mode_occupancy_control(air_loop_hvac, standby_mode_spaces) ⇒ Boolean
Add occupant standby controls to air loop When the thermostat schedule is setup or setback the ventilation is shutoff. Currently this is done by scheduling air terminal dampers (so load can still be met) and cycling unitary system fans
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 748 def air_loop_hvac_standby_mode_occupancy_control(air_loop_hvac, standby_mode_spaces) if air_loop_hvac_include_unitary_system?(air_loop_hvac) unitary_system = nil # Get unitary system air_loop_hvac.supplyComponents.each do |comp| if comp.to_AirLoopHVACUnitarySystem.is_initialized unitary_system = comp.to_AirLoopHVACUnitarySystem.get end end return false if unitary_system.nil? # Set fan operating schedule during assumed occupant standby mode time to 0 so the fan can cycle new_sch = model_set_schedule_value(unitary_system..get, '12' => 0) unitary_system.(new_sch) unless new_sch.nil? else # Get thermal zones associated with spaces having standby mode occupancy requirements standby_mode_zones = [] standby_mode_spaces.sort.each do |space| standby_mode_zones << space.thermalZone.get end # Schedule the MDP of terminals to a low value during occupant standby mode # The intent is to reduce ventilation while still allowing the terminal to # meet loads standby_mode_zones.each do |zone| air_terminal = zone.airLoopHVACTerminal if air_terminal.is_initialized air_terminal = air_terminal.get if air_terminal.to_AirTerminalSingleDuctVAVReheat.is_initialized air_terminal = air_terminal.to_AirTerminalSingleDuctVAVReheat.get if air_terminal.zoneMinimumAirFlowInputMethod == 'Constant' || air_terminal.zoneMinimumAirFlowInputMethod == 'FixedFlow' if air_terminal.zoneMinimumAirFlowInputMethod == 'FixedFlow' mdp_org = air_terminal.fixedMinimumAirFlowRate.get / air_terminal.autosizedMaximumAirFlowRate.get air_terminal.setFixedMinimumAirFlowRate(0) else mdp_org = air_terminal.constantMinimumAirFlowFraction.get air_terminal.setConstantMinimumAirFlowFraction(0) end air_terminal.setZoneMinimumAirFlowInputMethod('Scheduled') air_terminal.setMinimumAirFlowFractionSchedule(model_set_schedule_value(OpenstudioStandards::Schedules.create_constant_schedule_ruleset(air_loop_hvac.model, mdp_org, name: "#{air_terminal.name} - MDP", schedule_type_limit: 'Fraction'), '12' => 0.1)) elsif air_terminal.zoneMinimumAirFlowInputMethod == 'Scheduled' air_terminal.setMinimumAirFlowFractionSchedule(model_set_schedule_value(air_terminal.minimumAirFlowFractionSchedule.get, '12' => 0.1)) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "The air terminal associated with #{zone.name} uses a zone minimum air flow input method that is currently not supported so occupant standby controls were not modeled.") end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.AirLoopHVAC', "The air terminal associated with #{zone.name} isn't of the SingleDuctVAVReheat type so occupant standby controls were not modeled.") end end end end return true end |
#air_loop_hvac_supply_air_temperature_reset_required?(air_loop_hvac, climate_zone) ⇒ Boolean
Determine if the system required supply air temperature (SAT) reset. For 90.1-2019, SAT reset requirements are based on climate zone. More exceptions are added for 90.1 2019 6.5.3.5
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 331 def air_loop_hvac_supply_air_temperature_reset_required?(air_loop_hvac, climate_zone) is_sat_reset_required = false # Only required for multizone VAV systems unless air_loop_hvac_multizone_vav_system?(air_loop_hvac) return is_sat_reset_required end # check if design outside air is less than 10,000cfm (5000L/s) 90.1 2019 6.5.3.5 Exception 1 and 2 design_oa_m3s = nil if air_loop_hvac.sizingSystem.designOutdoorAirFlowRate.is_initialized design_oa_m3s = air_loop_hvac.sizingSystem.designOutdoorAirFlowRate.get elsif air_loop_hvac.sizingSystem.autosizedDesignOutdoorAirFlowRate.is_initialized design_oa_m3s = air_loop_hvac.sizingSystem.autosizedDesignOutdoorAirFlowRate.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name} design outdoor air flow rate is not available.") end design_oa_cfm = OpenStudio.convert(design_oa_m3s, 'm^3/s', 'cfm').get # check if there is erv 90.1 2019 Exceptions to 6.5.3.5 Exception 3 has_erv = air_loop_hvac_energy_recovery?(air_loop_hvac) design_sa_m3s = air_loop_hvac_find_design_supply_air_flow_rate(air_loop_hvac) oa_ratio = 0 if design_sa_m3s > 0 oa_ratio = design_oa_m3s / design_sa_m3s end has_large_oa = (oa_ratio >= 0.8) case climate_zone when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2006-3A', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-1A', 'ASHRAE 169-2013-3A' if design_oa_cfm < 3000 is_sat_reset_required = false OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is not required per 6.5.3.5 Exception 1, the system is located in climate zone #{climate_zone}.") return is_sat_reset_required end if has_erv && has_large_oa is_sat_reset_required = false OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is not required per 6.5.3.5 Exception 3, the system is located in climate zone #{climate_zone}.") return is_sat_reset_required end is_sat_reset_required = true OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is required.") return is_sat_reset_required when 'ASHRAE 169-2006-2A', 'ASHRAE 169-2013-2A' if design_oa_cfm < 10000 is_sat_reset_required = false OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is not required per 6.5.3.5 Exception 2, the system is located in climate zone #{climate_zone}.") return is_sat_reset_required end if has_erv && has_large_oa is_sat_reset_required = false OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is not required per 6.5.3.5 Exception 3, the system is located in climate zone #{climate_zone}.") return is_sat_reset_required end is_sat_reset_required = true OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is required.") return is_sat_reset_required when 'ASHRAE 169-2006-0B', 'ASHRAE 169-2006-1B', 'ASHRAE 169-2006-2B', 'ASHRAE 169-2006-3B', 'ASHRAE 169-2006-3C', 'ASHRAE 169-2006-4A', 'ASHRAE 169-2006-4B', 'ASHRAE 169-2006-4C', 'ASHRAE 169-2006-5A', 'ASHRAE 169-2006-5B', 'ASHRAE 169-2006-5C', 'ASHRAE 169-2006-6A', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B', 'ASHRAE 169-2013-0B', 'ASHRAE 169-2013-1B', 'ASHRAE 169-2013-2B', 'ASHRAE 169-2013-3B', 'ASHRAE 169-2013-3C', 'ASHRAE 169-2013-4A', 'ASHRAE 169-2013-4B', 'ASHRAE 169-2013-4C', 'ASHRAE 169-2013-5A', 'ASHRAE 169-2013-5B', 'ASHRAE 169-2013-5C', 'ASHRAE 169-2013-6A', 'ASHRAE 169-2013-6B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B' is_sat_reset_required = true OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Supply air temperature reset is required.") return is_sat_reset_required end end |
#air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(air_terminal_single_duct_vav_reheat, zone_oa_per_area) ⇒ Boolean
Set the initial minimum damper position based on OA rate of the space and the template. Zones with low OA per area get lower initial guesses. Final position will be adjusted upward as necessary by Standards.AirLoopHVAC.apply_minimum_vav_damper_positions
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb', line 10 def air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(air_terminal_single_duct_vav_reheat, zone_oa_per_area) min_damper_position = case air_terminal_single_duct_vav_reheat_reheat_type(air_terminal_single_duct_vav_reheat) when 'Electricity', 'NaturalGas' 0.3 else # 'HotWater', other 0.2 end # Set the minimum flow fraction air_terminal_single_duct_vav_reheat.setConstantMinimumAirFlowFraction(min_damper_position) return true end |
#air_terminal_single_duct_vav_reheat_minimum_damper_position(air_terminal_single_duct_vav_reheat, has_ddc = false) ⇒ Double
Specifies the minimum damper position for VAV dampers. For terminals with hot water heat and DDC, the minimum is 20%, otherwise the minimum is 30%.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb', line 10 def air_terminal_single_duct_vav_reheat_minimum_damper_position(air_terminal_single_duct_vav_reheat, has_ddc = false) min_damper_position = nil case air_terminal_single_duct_vav_reheat_reheat_type(air_terminal_single_duct_vav_reheat) when 'HotWater' min_damper_position = if has_ddc 0.2 else 0.3 end when 'Electricity', 'NaturalGas' min_damper_position = 0.3 end return min_damper_position end |
#boiler_get_eff_fplr(boiler_hot_water) ⇒ String
Determine what part load efficiency degredation curve should be used for a boiler
6 7 8 9 10 11 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.BoilerHotWater.rb', line 6 def boiler_get_eff_fplr(boiler_hot_water) capacity_w = boiler_hot_water_find_capacity(boiler_hot_water) capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get fplr = capacity_btu_per_hr >= 1_000_000 ? 'Boiler with Minimum Turndown' : 'Boiler with No Minimum Turndown' return fplr end |
#chiller_electric_eir_get_cap_f_t_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) ⇒ String
the current assingment is meant to replicate what was in the data, it probably needs to be reviewed
Get applicable performance curve for capacity as a function of temperature
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ChillerElectricEIR.rb', line 10 def chiller_electric_eir_get_cap_f_t_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) case cooling_type when 'AirCooled' return 'AirCooled_Chiller_2010_PathA_CAPFT' when 'WaterCooled' case compressor_type when 'Centrifugal' if compliance_path == 'Path A' return 'WaterCooled_Centrifugal_Chiller_2010_PathA_CAPFT' elsif compliance_path == 'Path B' return 'WaterCooled_Centrifugal_Chiller_2010_PathB_CAPFT' else return nil end when 'Reciprocating', 'Rotary Screw', 'Scroll' return 'ChlrWtrPosDispPathAAllQRatio_fTchwsTcwsSI' else return nil end else return nil end end |
#chiller_electric_eir_get_eir_f_plr_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) ⇒ String
the current assingment is meant to replicate what was in the data, it probably needs to be reviewed
Get applicable performance curve for EIR as a function of part load ratio
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ChillerElectricEIR.rb', line 74 def chiller_electric_eir_get_eir_f_plr_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) case cooling_type when 'AirCooled' return 'AirCooled_Chiller_AllCapacities_2004_2010_EIRFPLR' when 'WaterCooled' case compressor_type when 'Centrifugal' return 'ChlrWtrCentPathAAllEIRRatio_fQRatio' when 'Reciprocating', 'Rotary Screw', 'Scroll' return 'ChlrWtrPosDispPathAAllEIRRatio_fQRatio' else return nil end else return nil end end |
#chiller_electric_eir_get_eir_f_t_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) ⇒ String
the current assingment is meant to replicate what was in the data, it probably needs to be reviewed
Get applicable performance curve for EIR as a function of temperature
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ChillerElectricEIR.rb', line 42 def chiller_electric_eir_get_eir_f_t_curve_name(chiller_electric_eir, compressor_type, cooling_type, chiller_tonnage, compliance_path) case cooling_type when 'AirCooled' return 'AirCooled_Chiller_2010_PathA_EIRFT' when 'WaterCooled' case compressor_type when 'Centrifugal' if compliance_path == 'Path A' return 'WaterCooled_Centrifugal_Chiller_2010_PathA_EIRFT' elsif compliance_path == 'Path B' return 'WaterCooled_Centrifugal_Chiller_2010_PathB_EIRFT' else return nil end when 'Reciprocating', 'Rotary Screw', 'Scroll' return 'ChlrWtrPosDispPathAAllEIRRatio_fTchwsTcwsSI' else return nil end else return nil end end |
#coil_heating_gas_additional_search_criteria(coil_heating_gas, search_criteria) ⇒ Hash
Applies the standard efficiency ratings to CoilHeatingGas.
7 8 9 10 11 12 13 14 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoilHeatingGas.rb', line 7 def coil_heating_gas_additional_search_criteria(coil_heating_gas, search_criteria) capacity_w = coil_heating_gas_find_capacity(coil_heating_gas) capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get if capacity_btu_per_hr < 225_000 search_criteria['subtype'] = 'Weatherized' # assumption; could be based on input end return search_criteria end |
#cooling_tower_variable_speed_apply_efficiency_and_curves(cooling_tower_variable_speed) ⇒ Boolean
Apply the efficiency, plus Multicell heat rejection with VSD
10 11 12 13 14 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb', line 10 def cooling_tower_variable_speed_apply_efficiency_and_curves(cooling_tower_variable_speed) cooling_tower_apply_minimum_power_per_flow(cooling_tower_variable_speed) cooling_tower_variable_speed.setCellControl('MaximalCell') return true end |
#fan_constant_volume_airloop_fan_pressure_rise(fan_constant_volume) ⇒ Double
Determine the prototype fan pressure rise for a constant volume fan on an AirLoopHVAC based on system airflow. Defaults to the logic from ASHRAE 90.1-2004 prototypes.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanConstantVolume.rb', line 9 def fan_constant_volume_airloop_fan_pressure_rise(fan_constant_volume) # Get the max flow rate from the fan. maximum_flow_rate_m3_per_s = nil if fan_constant_volume.maximumFlowRate.is_initialized maximum_flow_rate_m3_per_s = fan_constant_volume.maximumFlowRate.get elsif fan_constant_volume.autosizedMaximumFlowRate.is_initialized maximum_flow_rate_m3_per_s = fan_constant_volume.autosizedMaximumFlowRate.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.prototype.FanConstantVolume', "For #{fan_constant_volume.name} max flow rate is not available, cannot apply prototype assumptions.") return false end # Convert max flow rate to cfm maximum_flow_rate_cfm = OpenStudio.convert(maximum_flow_rate_m3_per_s, 'm^3/s', 'cfm').get # Determine the pressure rise pressure_rise_in_h2o = if maximum_flow_rate_cfm < 7437 2.5 else # Over 7,437 cfm 4.09 end return pressure_rise_in_h2o end |
#fan_on_off_airloop_or_unitary_fan_pressure_rise(fan_on_off) ⇒ Double
Determine the prototype fan pressure rise for an on off fan on an AirLoopHVAC or inside a unitary system based on system airflow. Defaults to the logic from ASHRAE 90.1-2004 prototypes.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanOnOff.rb', line 9 def fan_on_off_airloop_or_unitary_fan_pressure_rise(fan_on_off) # Get the max flow rate from the fan. maximum_flow_rate_m3_per_s = nil if fan_on_off.maximumFlowRate.is_initialized maximum_flow_rate_m3_per_s = fan_on_off.maximumFlowRate.get elsif fan_on_off.autosizedMaximumFlowRate.is_initialized maximum_flow_rate_m3_per_s = fan_on_off.autosizedMaximumFlowRate.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.prototype.FanOnOff', "For #{fan_on_off.name} max flow rate is not available, cannot apply prototype assumptions.") return false end # Convert max flow rate to cfm maximum_flow_rate_cfm = OpenStudio.convert(maximum_flow_rate_m3_per_s, 'm^3/s', 'cfm').get # Determine the pressure rise pressure_rise_in_h2o = if maximum_flow_rate_cfm < 7437 2.5 else # Over 7,437 cfm 4.09 end return pressure_rise_in_h2o end |
#fan_variable_volume_airloop_fan_pressure_rise(fan_variable_volume) ⇒ Double
Determine the prototype fan pressure rise for a variable volume fan on an AirLoopHVAC based on system airflow. Defaults to the logic from ASHRAE 90.1-2004 prototypes.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb', line 9 def fan_variable_volume_airloop_fan_pressure_rise(fan_variable_volume) # Get the max flow rate from the fan. maximum_flow_rate_m3_per_s = nil if fan_variable_volume.maximumFlowRate.is_initialized maximum_flow_rate_m3_per_s = fan_variable_volume.maximumFlowRate.get elsif fan_variable_volume.autosizedMaximumFlowRate.is_initialized maximum_flow_rate_m3_per_s = fan_variable_volume.autosizedMaximumFlowRate.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.prototype.FanVariableVolume', "For #{fan_variable_volume.name} max flow rate is not available, cannot apply prototype assumptions.") return false end # Convert max flow rate to cfm maximum_flow_rate_cfm = OpenStudio.convert(maximum_flow_rate_m3_per_s, 'm^3/s', 'cfm').get # Determine the pressure rise pressure_rise_in_h2o = if maximum_flow_rate_cfm < 4648 4.0 else # Over 7,437 cfm 5.58 end return pressure_rise_in_h2o end |
#fan_variable_volume_part_load_fan_power_limitation_capacity_limit(fan_variable_volume) ⇒ Double
The threhold capacity below which part load control is not required. Per 90.1-2019, table 6.5.3.2.1: the cooling capacity threshold is 75000 instead of 110000 as of 1/1/2014
27 28 29 30 31 32 33 34 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb', line 27 def fan_variable_volume_part_load_fan_power_limitation_capacity_limit(fan_variable_volume) cap_limit_btu_per_hr = case fan_variable_volume_cooling_system_type(fan_variable_volume) when 'dx' 65_000 end return cap_limit_btu_per_hr end |
#fan_variable_volume_part_load_fan_power_limitation_hp_limit(fan_variable_volume) ⇒ Double
The threhold horsepower below which part load control is not required. Per 90.1-2019, table 6.5.3.2.1: the fan motor size for chiller-water and evaporative cooling is 0.25 hp as of 1/1/2014 instead of 5 hp
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb', line 10 def fan_variable_volume_part_load_fan_power_limitation_hp_limit(fan_variable_volume) hp_limit = case fan_variable_volume_cooling_system_type(fan_variable_volume) when 'dx' 0.0 when 'chw', 'evap' 0.25 end return hp_limit end |
#load_standards_database(data_directories = []) ⇒ Hash
Loads the openstudio standards dataset for this standard.
18 19 20 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.rb', line 18 def load_standards_database(data_directories = []) super([__dir__] + data_directories) end |
#model_add_lights_shutoff(model) ⇒ Boolean
code_sections [90.1-2016_9.4.1.1.h/i]
Implement occupancy based lighting level threshold (0.02 W/sqft). This is only for ASHRAE 90.1 2016 onwards.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb', line 237 def model_add_lights_shutoff(model) zones = model.getThermalZones num_zones = 0 business_sch_name = prototype_input['business_schedule'] return if business_sch_name.nil? # This is only for 10 prototypes that do not have continuous operation. # Add business schedule model_add_schedule(model, business_sch_name) # Add EMS object for business schedule variable business_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value') business_sensor.setKeyName(business_sch_name) business_sensor.setName('Business_Sensor') business_sensor_name = business_sensor.name.to_s space_types_affected = [] zones.sort.each do |zone| spaces = zone.spaces if spaces.length != 1 puts 'warning, there are more than one spaces in the zone, need to confirm the implementation' end space = spaces[0] space_lights = space.lights lights_defined_by_spacetype = false if space_lights.empty? space_lights = space.spaceType.get.lights lights_defined_by_spacetype = true space_types_affected << space.spaceType end space_people = space.people if space_people.empty? space_people = space.spaceType.get.people end # guard clause to skip space with no lights next if space_lights.empty? # if lights are defined at the space type level, clone each lights object and make it individual to the space new_space_lights = [] if lights_defined_by_spacetype space_lights.each do |lights| new_lights = lights.clone.to_Lights.get new_lights.setName("#{space.name}-#{lights.name}") new_lights.setSpace(space) new_space_lights << new_lights end space_lights = new_space_lights end zone_name = zone.name.to_s next if zone_name =~ /data\s*center/i # skip data centers # EnergyPlus v9.4.0 / OpenStudio v3.1.0 variable name change from 'Zone Lights Electric Power' to 'Zone Lights Electricity Rate' # EnergyPlus v9.6.0 / OpenStudio v3.3.0 added Space objects, variable name change from 'Zone Lights Electricity Rate' to 'Space Lights Electricity Rate' # https://github.com/NREL/OpenStudio/pull/4104 if model.version < OpenStudio::VersionString.new('3.1.0') light_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Lights Electric Power') key_name = zone_name elsif model.version < OpenStudio::VersionString.new('3.3.0') light_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Lights Electricity Rate') key_name = zone_name else light_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Space Lights Electricity Rate') key_name = space.name.to_s end light_sensor.setKeyName(key_name) light_sensor_name_ems = "#{ems_friendly_name(key_name)}_LSr" light_sensor.setName(light_sensor_name_ems) # get the space floor area for calculations space_floor_area = space.floorArea # account for multiple lights (also work for single light) big_light = space_lights[0] # find the light with highest power (assuming specified by watts/area) space_lights.each do |light_x| big_light_power = big_light.definition.to_LightsDefinition.get.wattsperSpaceFloorArea.to_f light_x_power = light_x.definition.to_LightsDefinition.get.wattsperSpaceFloorArea.to_f if light_x_power > big_light_power big_light = light_x end end add_lights_prog_0 = '' add_lights_prog_null = '' light_id = 0 space_lights.each do |light_x| light_id += 1 # EnergyPlus v9.4 name change for EMS actuators # https://github.com/NREL/OpenStudio/pull/4104 if model.version < OpenStudio::VersionString.new('3.1.0') light_x_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(light_x, 'Lights', 'Electric Power Level') else light_x_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(light_x, 'Lights', 'Electricity Rate') end light_x_actuator_name_ems = "#{ems_friendly_name(key_name)}_Light#{light_id}_Actuator" light_x_actuator.setName(light_x_actuator_name_ems) add_lights_prog_null += "\n SET #{light_x_actuator_name_ems} = NULL," if light_x == big_light add_lights_prog_0 += "\n SET #{light_x_actuator_name_ems} = 0.02*#{space_floor_area}/0.09290304," next end add_lights_prog_0 += "\n SET #{light_x_actuator_name_ems} = 0," end light_ems_prog = OpenStudio::Model::EnergyManagementSystemProgram.new(model) light_ems_prog.setName("SET_#{ems_friendly_name(key_name)}_Light_EMS_Program") light_ems_prog_body = <<-EMS SET #{light_sensor_name_ems}_IP=0.093*#{light_sensor_name_ems}/#{space_floor_area}, IF (#{business_sensor_name} <= 0) && (#{light_sensor_name_ems}_IP >= 0.02),#{add_lights_prog_0} ELSE,#{add_lights_prog_null} ENDIF EMS light_ems_prog.setBody(light_ems_prog_body) light_ems_prog_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model) light_ems_prog_manager.setName("SET_#{ems_friendly_name(key_name)}_Light_EMS_Program_Manager") light_ems_prog_manager.setCallingPoint('AfterPredictorAfterHVACManagers') light_ems_prog_manager.addProgram(light_ems_prog) end # remove lights at the space type level space_types_affected.each do |space_type| space_type.get.lights.each(&:remove) end return true end |
#model_cw_loop_cooling_tower_fan_type(model) ⇒ String
Determine which type of fan the cooling tower will have. Variable Speed Fan for ASHRAE 90.1-2019.
9 10 11 12 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb', line 9 def model_cw_loop_cooling_tower_fan_type(model) fan_type = 'Variable Speed Fan' return fan_type end |
#model_door_infil_flow_rate_metal_coiling_cfm_ft2(climate_zone) ⇒ Double
code_sections [90.1-2019_5.4.3.2]
Metal coiling door code minimum infiltration rate at 75 Pa
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb', line 215 def (climate_zone) case climate_zone when 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B' return 0.4 else return 1.0 end end |
#model_economizer_type(model, climate_zone) ⇒ String
Determine the prototypical economizer type for the model.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb', line 17 def model_economizer_type(model, climate_zone) economizer_type = case climate_zone when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2006-2A', 'ASHRAE 169-2006-3A', 'ASHRAE 169-2006-4A', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-1A', 'ASHRAE 169-2013-2A', 'ASHRAE 169-2013-3A', 'ASHRAE 169-2013-4A' 'DifferentialEnthalpy' else 'DifferentialDryBulb' end return economizer_type end |
#model_elevator_fan_pwr(model, vent_rate_cfm) ⇒ Double
Determines the power of the elevator ventilation fan. 90.1-2019 has a requirement for ventilation fan efficiency.
21 22 23 24 25 26 27 28 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.elevators.rb', line 21 def model_elevator_fan_pwr(model, vent_rate_cfm) vent_pwr_per_flow_w_per_cfm = 0.33 vent_pwr_w = vent_pwr_per_flow_w_per_cfm * vent_rate_cfm # addendum 90.1-2007 aj has requirement on efficiency vent_pwr_w = vent_pwr_w * 0.29 / 0.70 return vent_pwr_w end |
#model_elevator_lighting_pct_incandescent(model) ⇒ Double
Determines the percentage of the elevator cab lighting that is incandescent. The remainder is assumed to be LED. Defaults to 0% incandescent (100% LED), representing newer elevators.
10 11 12 13 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.elevators.rb', line 10 def model_elevator_lighting_pct_incandescent(model) pct_incandescent = 0.0 # 100% LED return pct_incandescent end |
#model_fenestration_orientation(model, climate_zone) ⇒ Boolean
code_sections [90.1-2013_5.5.4.5]
Adjust model to comply with fenestration orientation requirements
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb', line 10 def model_fenestration_orientation(model, climate_zone) # Building rotation to meet the same code requirement for # 90.1-2010 are kept if model.getBuilding.standardsBuildingType.is_initialized building_type = model.getBuilding.standardsBuildingType.get case building_type when 'Hospital' # Rotate the building counter-clockwise OpenstudioStandards::Geometry.model_set_building_north_axis(model, 270.0) when 'SmallHotel' # Rotate the building clockwise OpenstudioStandards::Geometry.model_set_building_north_axis(model, 180) end end wwr = false # Section 6.2.1.2 in the ANSI/ASHRAE/IES Standard 90.1-2013 Determination # of Energy Savings: Quantitative Analysis mentions that the SHGC trade-off # path is most likely to be used by designers for compliance. # # The following adjustment are only made for models with simple glazing objects non_simple_glazing = false shgc_a = 0 model.getSpaces.each do |space| # Get thermal zone multiplier multiplier = space.thermalZone.get.multiplier space.surfaces.each do |surface| surface.subSurfaces.each do |subsurface| # Get window subsurface type subsurface_type = subsurface.subSurfaceType.to_s.downcase # Window, glass doors next unless (subsurface_type.include? 'window') || (subsurface_type.include? 'glass') # Check if non simple glazing fenestration objects are used subsurface_cons = subsurface.construction.get.to_Construction.get non_simple_glazing = true unless subsurface_cons.layers[0].to_SimpleGlazing.is_initialized if non_simple_glazing OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2013.model', 'Fenestration objects in the model use non-simple glazing models, fenestration requirements are not applied') return false end # Get subsurface's simple glazing object subsurface_shgc = subsurface_cons.layers[0].to_SimpleGlazing.get.solarHeatGainCoefficient # Get subsurface area subsurface_area = subsurface.grossArea * subsurface.multiplier * multiplier # SHGC * Area shgc_a += subsurface_shgc * subsurface_area end end end # Calculate West, East and total fenestration area a_n = OpenstudioStandards::Geometry.model_get_exterior_window_and_wall_area_by_orientation(model)['north_window'] a_s = OpenstudioStandards::Geometry.model_get_exterior_window_and_wall_area_by_orientation(model)['south_window'] a_e = OpenstudioStandards::Geometry.model_get_exterior_window_and_wall_area_by_orientation(model)['east_window'] a_w = OpenstudioStandards::Geometry.model_get_exterior_window_and_wall_area_by_orientation(model)['west_window'] a_t = a_n + a_s + a_e + a_w return true if a_t.abs < 0.01 # For prototypes SHGC_c assumed to be the building's weighted average SHGC shgc_c = shgc_a / a_t shgc_c = shgc_c.round(2) # West and East facing WWR wwr_w = OpenstudioStandards::Geometry.model_get_exterior_window_to_wall_ratio(model, cardinal_direction: 'W') wwr_e = OpenstudioStandards::Geometry.model_get_exterior_window_to_wall_ratio(model, cardinal_direction: 'E') # Calculate new SHGC for west and east facing fenestration; # Create new simple glazing object and assign it to all # West and East fenestration # # Exception 5 is applied when applicable shgc_w = 0 shgc_e = 0 # Determine requirement criteria case climate_zone when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-0B', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2006-1B', 'ASHRAE 169-2006-2A', 'ASHRAE 169-2006-2B', 'ASHRAE 169-2006-3A', 'ASHRAE 169-2006-3B', 'ASHRAE 169-2006-3C', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-0B', 'ASHRAE 169-2013-1A', 'ASHRAE 169-2013-1B', 'ASHRAE 169-2013-2A', 'ASHRAE 169-2013-2B', 'ASHRAE 169-2013-3A', 'ASHRAE 169-2013-3B', 'ASHRAE 169-2013-3C' criteria = 4 when 'ASHRAE 169-2006-4A', 'ASHRAE 169-2006-4B', 'ASHRAE 169-2006-4C', 'ASHRAE 169-2006-5A', 'ASHRAE 169-2006-5B', 'ASHRAE 169-2006-5C', 'ASHRAE 169-2006-6A', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B', 'ASHRAE 169-2013-4A', 'ASHRAE 169-2013-4B', 'ASHRAE 169-2013-4C', 'ASHRAE 169-2013-5A', 'ASHRAE 169-2013-5B', 'ASHRAE 169-2013-5C', 'ASHRAE 169-2013-6A', 'ASHRAE 169-2013-6B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B' criteria = 5 else return false end if !((a_w <= a_t / criteria) && (a_e <= a_t / criteria)) # Calculate new SHGC if wwr_w > 0.2 shgc_w = a_t * shgc_c / (criteria * a_w) end if wwr_e > 0.2 shgc_e = a_t * shgc_c / (criteria * a_w) end # No SHGC adjustment needed return true if shgc_w == 0 && shgc_e == 0 model.getSpaces.each do |space| # Get thermal zone multiplier multiplier = space.thermalZone.get.multiplier space.surfaces.each do |surface| # Proceed only for East and West facing surfaces that are required # to have their SHGC adjusted next unless (OpenstudioStandards::Geometry.surface_get_cardinal_direction(surface) == 'W' && shgc_w > 0) || (OpenstudioStandards::Geometry.surface_get_cardinal_direction(surface) == 'E' && shgc_e > 0) surface.subSurfaces.each do |subsurface| # Get window subsurface type subsurface_type = subsurface.subSurfaceType.to_s.downcase # Window, glass doors next unless (subsurface_type.include? 'window') || (subsurface_type.include? 'glass') new_shgc = OpenstudioStandards::Geometry.surface_get_cardinal_direction(surface) == 'W' ? shgc_w : shgc_e new_shgc = new_shgc.round(2) # Get construction/simple glazing associated with the subsurface subsurface_org_cons = subsurface.construction.get.to_Construction.get subsurface_org_cons_mat = subsurface_org_cons.layers[0].to_SimpleGlazing.get # Only proceed if new SHGC is different than orignal one next unless (new_shgc - subsurface_org_cons_mat.solarHeatGainCoefficient).abs > 0 # Clone construction/simple glazing associated with the subsurface subsurface_new_cons = subsurface_org_cons.clone(model).to_Construction.get subsurface_new_cons.setName("#{subsurface.name} Wind Cons U-#{OpenStudio.convert(subsurface_org_cons_mat.uFactor, 'W/m^2*K', 'Btu/ft^2*h*R').get.round(2)} SHGC #{new_shgc}") subsurface_new_cons_mat = subsurface_org_cons_mat.clone(model).to_SimpleGlazing.get subsurface_new_cons_mat.setName("#{subsurface.name} Wind SG Mat U-#{OpenStudio.convert(subsurface_org_cons_mat.uFactor, 'W/m^2*K', 'Btu/ft^2*h*R').get.round(2)} SHGC #{new_shgc}") subsurface_new_cons_mat.setSolarHeatGainCoefficient(new_shgc) new_layers = OpenStudio::Model::MaterialVector.new new_layers << subsurface_new_cons_mat subsurface_new_cons.setLayers(new_layers) # Assign new construction to sub surface subsurface.setConstruction(subsurface_new_cons) end end end end return true end |
#model_transfer_air_required?(model) ⇒ Boolean
code_sections [90.1-2019_6.5.7.1]
Is transfer air required?
206 207 208 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb', line 206 def model_transfer_air_required?(model) return true end |
#pump_standard_minimum_motor_efficiency_and_size(pump, motor_bhp) ⇒ Array<Double>
Determines the minimum pump motor efficiency and nominal size for a given motor bhp. This should be the total brake horsepower with any desired safety factor already included. This method picks the next nominal motor catgory larger than the required brake horsepower, and the efficiency is based on that size. For example, if the bhp = 6.3, the nominal size will be 7.5HP and the efficiency for 90.1-2010 will be 91.7% from Table 10.8B. This method assumes 4-pole, 1800rpm totally-enclosed fan-cooled motors.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Pump.rb', line 15 def pump_standard_minimum_motor_efficiency_and_size(pump, motor_bhp) motor_eff = 0.85 nominal_hp = motor_bhp # Don't attempt to look up motor efficiency # for zero-hp pumps (required for circulation-pump-free # service water heating systems). return [1.0, 0] if motor_bhp < 0.0001 # Lookup the minimum motor efficiency motors = standards_data['motors'] # Assuming all pump motors are 4-pole ODP search_criteria = { 'template' => template, 'number_of_poles' => 4.0, 'type' => 'Enclosed' } motor_properties = model_find_object(motors, search_criteria, motor_bhp) if motor_properties.nil? OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Pump', "For #{pump.name}, could not find motor properties using search criteria: #{search_criteria}, motor_bhp = #{motor_bhp} hp.") return [motor_eff, nominal_hp] end motor_eff = motor_properties['nominal_full_load_efficiency'] nominal_hp = motor_properties['maximum_capacity'].to_f.round(1) # Round to nearest whole HP for niceness if nominal_hp >= 2 nominal_hp = nominal_hp.round end # Get the efficiency based on the nominal horsepower # Add 0.01 hp to avoid search errors. motor_properties = model_find_object(motors, search_criteria, nominal_hp + 0.01) if motor_properties.nil? OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Fan', "For #{pump.name}, could not find nominal motor properties using search criteria: #{search_criteria}, motor_hp = #{nominal_hp} hp.") return [motor_eff, nominal_hp] end motor_eff = motor_properties['nominal_full_load_efficiency'] # Get flow rate (whether autosized or hard-sized) flow_m3_per_s = 0 flow_m3_per_s = if pump.to_PumpVariableSpeed.is_initialized || pump.to_PumpConstantSpeed.is_initialized if pump.ratedFlowRate.is_initialized pump.ratedFlowRate.get elsif pump.autosizedRatedFlowRate.is_initialized pump.autosizedRatedFlowRate.get end elsif pump.to_HeaderedPumpsVariableSpeed.is_initialized || pump.to_HeaderedPumpsConstantSpeed.is_initialized if pump.totalRatedFlowRate.is_initialized pump.totalRatedFlowRate.get / pump.numberofPumpsinBank elsif pump.autosizedTotalRatedFlowRate.is_initialized pump.autosizedTotalRatedFlowRate.get / pump.numberofPumpsinBank end end flow_gpm = OpenStudio.convert(flow_m3_per_s, 'm^3/s', 'gal/min').get # Adjustment for clean water pumps requirement: # The adjustment is made based on results included # in https://www.energy.gov/sites/prod/files/2015/12/f28/Pumps%20ECS%20Final%20Rule.pdf # Table 1 summarizes final rule efficiency levels # analyzed with corresponding C-values. With the # rulemaking adopted TSL/EL2 from the report, it shows # about 4.3% of average efficiency improvement, and after # considering 25% of the market, about 1.1% of the # final average efficiency improvement is estimated. # # The clean water pump requirement is only # applied to pumps with a flow rate of at least 25 gpm motor_eff *= 1.011 unless flow_gpm < 25.0 return [motor_eff, nominal_hp] end |
#pump_variable_speed_get_control_type(pump, plant_loop_type, pump_nominal_hp) ⇒ String
code_sections [90.1-2019_6.5.4.2]
Determine type of pump part load control type
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.PumpVariableSpeed.rb', line 11 def pump_variable_speed_get_control_type(pump, plant_loop_type, pump_nominal_hp) # Sizing factor to take into account that pumps # are typically sized to handle a ~10% pressure # increase and ~10% flow increase. design_sizing_factor = 1.25 # Get climate zone climate_zone = pump.plantLoop.get.model.getClimateZones.getClimateZone(0) climate_zone = "#{climate_zone.institution} 169-#{climate_zone.year}-#{climate_zone.value}" # Get nameplate hp threshold: # The thresholds below represent the nameplate # hp one level lower than the threshold in the # code. Motor size from table in section 10 are # used as reference. case plant_loop_type when 'Heating' case climate_zone when 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B' threshold = 3 when 'ASHRAE 169-2006-3C', 'ASHRAE 169-2006-5A', 'ASHRAE 169-2006-5C', 'ASHRAE 169-2006-6A', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2013-3C', 'ASHRAE 169-2013-5A', 'ASHRAE 169-2013-5C', 'ASHRAE 169-2013-6A', 'ASHRAE 169-2013-6B' threshold = 5 when 'ASHRAE 169-2006-4A', 'ASHRAE 169-2006-4C', 'ASHRAE 169-2006-5B', 'ASHRAE 169-2013-4A', 'ASHRAE 169-2013-4C', 'ASHRAE 169-2013-5B' threshold = 7.5 when 'ASHRAE 169-2006-4B', 'ASHRAE 169-2013-4B' threshold = 10 when 'ASHRAE 169-2006-2A', 'ASHRAE 169-2006-2B', 'ASHRAE 169-2006-3A', 'ASHRAE 169-2006-3B', 'ASHRAE 169-2013-2A', 'ASHRAE 169-2013-2B', 'ASHRAE 169-2013-3A', 'ASHRAE 169-2013-3B' threshold = 20 when 'ASHRAE 169-2006-1B', 'ASHRAE 169-2013-1B' threshold = 75 when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-0B', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-0B', 'ASHRAE 169-2013-1A' threshold = 150 else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.PumpVariableSpeed', "Pump flow control requirement missing for heating water pumps in climate zone: #{climate_zone}.") end when 'Cooling' case climate_zone when 'ASHRAE 169-2006-0A', 'ASHRAE 169-2006-0B', 'ASHRAE 169-2006-1A', 'ASHRAE 169-2006-1B', 'ASHRAE 169-2006-2B', 'ASHRAE 169-2013-0A', 'ASHRAE 169-2013-0B', 'ASHRAE 169-2013-1A', 'ASHRAE 169-2013-1B', 'ASHRAE 169-2013-2B' threshold = 1.5 when 'ASHRAE 169-2006-2A', 'ASHRAE 169-2006-3B', 'ASHRAE 169-2013-2A', 'ASHRAE 169-2013-3B' threshold = 2 when 'ASHRAE 169-2006-3A', 'ASHRAE 169-2006-3C', 'ASHRAE 169-2006-4A', 'ASHRAE 169-2006-4B', 'ASHRAE 169-2013-3A', 'ASHRAE 169-2013-3C', 'ASHRAE 169-2013-4A', 'ASHRAE 169-2013-4B' threshold = 3 when 'ASHRAE 169-2006-4C', 'ASHRAE 169-2006-5A', 'ASHRAE 169-2006-5B', 'ASHRAE 169-2006-5C', 'ASHRAE 169-2006-6A', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2013-4C', 'ASHRAE 169-2013-5A', 'ASHRAE 169-2013-5B', 'ASHRAE 169-2013-5C', 'ASHRAE 169-2013-6A', 'ASHRAE 169-2013-6B' threshold = 5 when 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B' threshold = 10 else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.PumpVariableSpeed', "Pump flow control requirement missing for chilled water pumps in climate zone: #{climate_zone}.") end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.ashrae_90_1_2019.PumpVariableSpeed', "No pump flow requirement for #{plant_loop_type} plant loops.") return false end return 'VSD DP Reset' if pump_nominal_hp * design_sizing_factor > threshold # else return 'Riding Curve' end |
#set_maximum_fraction_outdoor_air_schedule(air_loop_hvac, oa_control, snc) ⇒ OpenStudio::Model::ScheduleRuleset
Create an economizer maximum OA fraction schedule with For ASHRAE 90.1 2019, a maximum of 75% to reflect damper leakage per PNNL
22 23 24 25 26 27 28 29 30 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb', line 22 def set_maximum_fraction_outdoor_air_schedule(air_loop_hvac, oa_control, snc) max_oa_sch_name = "#{snc}_maxOASch" max_oa_sch = OpenStudio::Model::ScheduleRuleset.new(air_loop_hvac.model) max_oa_sch.setName(max_oa_sch_name) max_oa_sch.defaultDaySchedule.setName("#{max_oa_sch_name}_Default") max_oa_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.75) oa_control.setMaximumFractionofOutdoorAirSchedule(max_oa_sch) max_oa_sch end |
#space_daylighted_area_window_width(space) ⇒ String
Determines the method used to extend the daylighted area horizontally next to a window. If the method is ‘fixed’, 2 ft is added to the width of each window. If the method is ‘proportional’, a distance equal to half of the head height of the window is added. If the method is ‘none’, no additional width is added.
11 12 13 14 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 11 def space_daylighted_area_window_width(space) method = 'proportional' return method end |
#space_daylighting_control_required?(space, areas) ⇒ Array<Bool>
Determine if the space requires daylighting controls for toplighting, primary sidelighting, and secondary sidelighting. Defaults to false for all types.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 23 def space_daylighting_control_required?(space, areas) req_top_ctrl = true req_pri_ctrl = true req_sec_ctrl = true # Get the LPD of the space space_lpd_w_per_m2 = space.lightingPowerPerFloorArea # Primary Sidelighting # Check if the primary sidelit area contains less than 150W of lighting if areas['primary_sidelighted_area'] < 0.01 OpenStudio.logFree(OpenStudio::Debug, 'openstudio.model.Space', "For #{space.name}, primary sidelighting control not required because primary sidelighted area = 0ft2 per 9.4.1.1(e).") req_pri_ctrl = false elsif areas['primary_sidelighted_area'] * space_lpd_w_per_m2 < 150.0 OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Space', "For #{space.name}, primary sidelighting control not required because less than 150W of lighting are present in the primary daylighted area per 9.4.1.1(e).") req_pri_ctrl = false else # Check the size of the windows if areas['total_window_area'] < OpenStudio.convert(20.0, 'ft^2', 'm^2').get OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Space', "For #{space.name}, primary sidelighting control not required because there are less than 20ft2 of window per 9.4.1.1(e) Exception 2.") req_pri_ctrl = false end end # Secondary Sidelighting # Check if the primary and secondary sidelit areas contains less than 300W of lighting if areas['secondary_sidelighted_area'] < 0.01 OpenStudio.logFree(OpenStudio::Debug, 'openstudio.model.Space', "For #{space.name}, secondary sidelighting control not required because secondary sidelighted area = 0ft2 per 9.4.1.1(e).") req_sec_ctrl = false elsif (areas['primary_sidelighted_area'] + areas['secondary_sidelighted_area']) * space_lpd_w_per_m2 < 300 OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Space', "For #{space.name}, secondary sidelighting control not required because less than 300W of lighting are present in the combined primary and secondary daylighted areas per 9.4.1.1(e).") req_sec_ctrl = false else # Check the size of the windows if areas['total_window_area'] < OpenStudio.convert(20.0, 'ft^2', 'm^2').get OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Space', "For #{space.name}, secondary sidelighting control not required because there are less than 20ft2 of window per 9.4.1.1(e) Exception 2.") req_sec_ctrl = false end end # Toplighting # Check if the toplit area contains less than 150W of lighting if areas['toplighted_area'] < 0.01 OpenStudio.logFree(OpenStudio::Debug, 'openstudio.model.Space', "For #{space.name}, toplighting control not required because toplighted area = 0ft2 per 9.4.1.1(f).") req_top_ctrl = false elsif areas['toplighted_area'] * space_lpd_w_per_m2 < 150 OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Space', "For #{space.name}, toplighting control not required because less than 150W of lighting are present in the toplighted area per 9.4.1.1(f).") req_top_ctrl = false end # Exceptions if space.spaceType.is_initialized case space.spaceType.get.standardsSpaceType.to_s when 'Core_Retail' # Retail spaces exception (c) to Section 9.4.1.4 # req_sec_ctrl set to true to create a second reference point req_pri_ctrl = false req_sec_ctrl = true when 'Entry', 'Front_Retail', 'Point_of_Sale', 'Strip mall - type 1', 'Strip mall - type 2', 'Strip mall - type 3' # Retail, Strip mall req_pri_ctrl = false req_sec_ctrl = false when 'Apartment', 'Apartment_topfloor_NS', 'Apartment_topfloor_WE' # Residential apartments req_top_ctrl = false req_pri_ctrl = false req_sec_ctrl = false end end return [req_top_ctrl, req_pri_ctrl, req_sec_ctrl] end |
#space_daylighting_control_type(space) ⇒ Object
Provide the type of daylighting control type
return [String] daylighting control type
194 195 196 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 194 def space_daylighting_control_type(space) return 'ContinuousOff' end |
#space_daylighting_fractions_and_windows(space, areas, sorted_windows, sorted_skylights, req_top_ctrl, req_pri_ctrl, req_sec_ctrl) ⇒ Array
Determine the fraction controlled by each sensor and which window each sensor should go near.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 107 def space_daylighting_fractions_and_windows(space, areas, sorted_windows, sorted_skylights, req_top_ctrl, req_pri_ctrl, req_sec_ctrl) sensor_1_frac = 0.0 sensor_2_frac = 0.0 sensor_1_window = nil sensor_2_window = nil # Get the area of the space space_area_m2 = space.floorArea # get the climate zone climate_zone = OpenstudioStandards::Weather.model_get_climate_zone(space.model) if req_top_ctrl && req_pri_ctrl && req_sec_ctrl # Sensor 1 controls toplighted area sensor_1_frac = areas['toplighted_area'] / space_area_m2 sensor_1_window = sorted_skylights[0] # Sensor 2 controls primary + secondary area sensor_2_frac = (areas['primary_sidelighted_area'] + areas['secondary_sidelighted_area']) / space_area_m2 sensor_2_window = sorted_windows[0] elsif !req_top_ctrl && req_pri_ctrl && req_sec_ctrl # Sensor 1 controls primary area sensor_1_frac = areas['primary_sidelighted_area'] / space_area_m2 sensor_1_window = sorted_windows[0] # Sensor 2 controls secondary area sensor_2_frac = (areas['secondary_sidelighted_area'] / space_area_m2) sensor_2_window = sorted_windows[0] elsif req_top_ctrl && !req_pri_ctrl && req_sec_ctrl # Sensor 1 controls toplighted area sensor_1_frac = areas['toplighted_area'] / space_area_m2 sensor_1_window = sorted_skylights[0] # Sensor 2 controls secondary area sensor_2_frac = (areas['secondary_sidelighted_area'] / space_area_m2) # sorted_skylights[0] assigned to sensor_2_window so a second reference point is added for top daylighting sensor_2_window = sorted_skylights[0] elsif req_top_ctrl && !req_pri_ctrl && !req_sec_ctrl case climate_zone when 'ASHRAE 169-2006-6A', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2006-7A', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2013-6A', 'ASHRAE 169-2013-6B', 'ASHRAE 169-2013-7A', 'ASHRAE 169-2013-8A' # Sensor 1 controls toplighted area sensor_1_frac = areas['toplighted_area'] / space_area_m2 sensor_1_window = sorted_skylights[0] else # Sensor 1 controls toplighted area num_sensors = 2 sensor_1_frac = areas['toplighted_area'] / space_area_m2 / num_sensors sensor_1_window = sorted_skylights[0] sensor_2_frac = sensor_1_frac sensor_2_window = sensor_1_window end elsif !req_top_ctrl && req_pri_ctrl && !req_sec_ctrl # Sensor 1 controls primary area sensor_1_frac = areas['primary_sidelighted_area'] / space_area_m2 sensor_1_window = sorted_windows[0] elsif !req_top_ctrl && !req_pri_ctrl && req_sec_ctrl # Sensor 1 controls secondary area sensor_1_frac = areas['secondary_sidelighted_area'] / space_area_m2 sensor_1_window = sorted_windows[0] end return [sensor_1_frac, sensor_2_frac, sensor_1_window, sensor_2_window] end |
#space_daylighting_minimum_input_power_fraction(space) ⇒ Object
Provide the minimum input power fraction for continuous dimming daylighting control
return [Float] daylighting minimum input power fraction
203 204 205 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 203 def space_daylighting_minimum_input_power_fraction(space) return 0.2 end |
#space_infiltration_rate_75_pa(space = nil) ⇒ Double
Determine the base infiltration rate at 75 Pa.
defaults to no infiltration.
185 186 187 188 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 185 def space_infiltration_rate_75_pa(space = nil) basic_infil_rate_cfm_per_ft2 = 1.0 return basic_infil_rate_cfm_per_ft2 end |
#space_occupancy_standby_mode(thermostat) ⇒ Boolean
Modify thermostat schedule to account for a thermostat setback/up
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 40 def space_occupancy_standby_mode(thermostat) htg_sch = thermostat.getHeatingSchedule.get clg_sch = thermostat.getCoolingSchedule.get # Setback heating schedule # Setback is 1 deg. F per code requirement # Time of the day is arbitrary lack of dynamic occupant modeling setup = 1 # deg. F htg_sch_mod = { '12' => -1 * OpenStudio.convert(setup, 'R', 'K').get } htg_sch_name = "#{htg_sch.name} - occupant standby mode" htg_sch_old = thermostat.model.getScheduleRulesetByName(htg_sch_name) if htg_sch_old.empty? htg_sch_offset = model_offset_schedule_value(htg_sch, htg_sch_mod) htg_sch_offset.setName(htg_sch_name) thermostat.setHeatingSchedule(htg_sch_offset) else thermostat.setHeatingSchedule(htg_sch_old.get) end # Setup cooling schedule # Setup is 1 deg. F per code requirement # Time of the day is arbitrary lack of dynamic occupant modeling setback = 1 # deg. F clg_sch_mod = { '12' => OpenStudio.convert(setback, 'R', 'K').get } clg_sch_name = "#{clg_sch.name} - occupant standby mode" clg_sch_old = thermostat.model.getScheduleRulesetByName(clg_sch_name) if clg_sch_old.empty? clg_sch_offset = model_offset_schedule_value(clg_sch, clg_sch_mod) clg_sch_offset.setName(clg_sch_name) thermostat.setCoolingSchedule(clg_sch_offset) else thermostat.setCoolingSchedule(clg_sch_old.get) end return true end |
#space_occupancy_standby_mode_required?(space) ⇒ Boolean
Determine if a space should be modeled with an occupancy standby mode
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb', line 8 def space_occupancy_standby_mode_required?(space) # Get space type return false if space.spaceType.empty? space_type = space.spaceType.get # Get standards space type return false if space_type.standardsSpaceType.empty? std_space_type = space_type.standardsSpaceType.get # Space with standby mode are determined based # on note H in Std 62.1 and their automatic partial # of full off lighting control requirement in 90.1. # In 90.1-2019/62.1-2016 this comes down to office # spaces (enclosed =< 250 ft2) and conference/meeting # and multipurpose rooms. # Currently standards doesn't excatly use the 90.1 # space description so all spaces types that include # office/meeting/conference are flagged as having # occupant standby mode. if std_space_type.downcase.include?('office') || std_space_type.downcase.include?('meeting') || std_space_type.downcase.include?('conference') return true end return false end |
#thermal_zone_demand_control_ventilation_limits(thermal_zone) ⇒ Array<Double>
Determine the area and occupancy level limits for demand control ventilation.
and the minimum occupancy density in m^2/person. Returns nil if there is no requirement.
46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ThermalZone.rb', line 46 def thermal_zone_demand_control_ventilation_limits(thermal_zone) min_area_ft2 = 500 min_occ_per_1000_ft2 = 25 # Convert to SI min_area_m2 = OpenStudio.convert(min_area_ft2, 'ft^2', 'm^2').get min_occ_per_ft2 = min_occ_per_1000_ft2 / 1000.0 min_ft2_per_occ = 1.0 / min_occ_per_ft2 min_m2_per_occ = OpenStudio.convert(min_ft2_per_occ, 'ft^2', 'm^2').get return [min_area_m2, min_m2_per_occ] end |
#thermal_zone_occupancy_type(thermal_zone) ⇒ String
Add public assembly building types
Determine the thermal zone’s occupancy type category. Options are: residential, nonresidential, publicassembly, retail
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ThermalZone.rb', line 9 def thermal_zone_occupancy_type(thermal_zone) occ_type = if OpenstudioStandards::ThermalZone.thermal_zone_residential?(thermal_zone) 'residential' else 'nonresidential' end # Based on the space type that # represents a majority of the zone. space_type = OpenstudioStandards::ThermalZone.thermal_zone_get_space_type(thermal_zone) if space_type.is_initialized space_type = space_type.get bldg_type = space_type.standardsBuildingType if bldg_type.is_initialized bldg_type = bldg_type.get case bldg_type when 'Retail', 'StripMall', 'SuperMarket' occ_type = 'retail' # when 'SomeBuildingType' # @todo add publicassembly building types # occ_type = 'publicassembly' end end end # OpenStudio::logFree(OpenStudio::Info, "openstudio.Standards.ThermalZone", "For #{self.name}, occupancy type = #{occ_type}.") return occ_type end |
#water_heater_mixed_additional_search_criteria(water_heater_mixed, search_criteria) ⇒ Hash
Add additional search criteria for water heater lookup efficiency.
7 8 9 10 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.WaterHeaterMixed.rb', line 7 def water_heater_mixed_additional_search_criteria(water_heater_mixed, search_criteria) search_criteria['draw_profile'] = 'medium' # assumption; could be based on inputs return search_criteria end |
#zone_hvac_component_vestibule_heating_control_required?(zone_hvac_component) ⇒ Boolean
Determine if vestibule heating control is required. Required for 90.1-2019 per 6.4.3.9.
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb', line 10 def zone_hvac_component_vestibule_heating_control_required?(zone_hvac_component) # Ensure that the equipment is assigned to a thermal zone if zone_hvac_component.thermalZone.empty? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.ZoneHVACComponent', "For #{zone_hvac_component.name}: equipment is not assigned to a thermal zone, cannot apply vestibule heating control.") return false end # Only applies to equipment that is in vestibule zones return true if OpenstudioStandards::ThermalZone.thermal_zone_vestibule?(zone_hvac_component.thermalZone.get) # If here, vestibule heating control not required return false end |
#zone_hvac_model_standby_mode_occupancy_control(zone_hvac_component) ⇒ Boolean
Add occupant standby controls to zone equipment Currently, the controls consists of cycling the fan during the occupant standby mode hours
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb', line 30 def zone_hvac_model_standby_mode_occupancy_control(zone_hvac_component) # Ensure that the equipment is assigned to a thermal zone if zone_hvac_component.thermalZone.empty? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.ZoneHVACComponent', "For #{zone_hvac_component.name}: equipment is not assigned to a thermal zone, cannot apply vestibule heating control.") return true end # Get supply fan # Only Fan:OnOff can cycle fan = zone_hvac_component.supplyAirFan return true unless fan.to_FanOnOff.is_initialized fan = fan.to_FanOnOff.get # Set fan operating schedule during assumed occupant standby mode time to 0 so the fan can cycle # ZoneHVACFourPipeFanCoil has it optional, PTAC/PTHP starting a 3.5.0 is required new_sch = model_set_schedule_value(OpenStudio::Model::OptionalSchedule.new(zone_hvac_component.).get, '12' => 0) zone_hvac_component.(new_sch) unless new_sch == true return true end |