lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb in openstudio-standards-0.4.0 vs lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb in openstudio-standards-0.5.0.rc1

- old
+ new

@@ -3,23 +3,122 @@ # For LA100 calibration, default to systems being left on # Overwritten to be required for DEER2020 and beyond # # @param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop - # @return [Bool] returns true if required, false if not + # @return [Boolean] returns true if required, false if not def air_loop_hvac_unoccupied_fan_shutoff_required?(air_loop_hvac) shutoff_required = false return shutoff_required end + # 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. + # The small numbers here are to reflect that there is not a minimum + # airflow requirement in Title 24. + # @return [Array<Double>] [min_oa_without_economizer_cfm, min_oa_with_economizer_cfm] + def air_loop_hvac_demand_control_ventilation_limits(air_loop_hvac) + min_oa_without_economizer_cfm = 0.01 + min_oa_with_economizer_cfm = 0.01 + return [min_oa_without_economizer_cfm, min_oa_with_economizer_cfm] + end + + # Determine if the standard has an exception for demand control ventilation + # when an energy recovery device is present. + # Unlike ASHRAE 90.1, Title 24 does not have an ERV exception to DCV. + # This method is a copy of what is in Standards.AirLoopHVAC.rb and ensures + # ERVs will not prevent DCV from being applied to DEER models. + def air_loop_hvac_dcv_required_when_erv(air_loop_hvac) + dcv_required_when_erv_present = true + return dcv_required_when_erv_present + end + + # Determine whether or not this system is required to have an economizer. + # Logic inferred from MASControl3 INP files and parameters database. + # + # @param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop + # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A' + # @return [Boolean] returns true if an economizer is required, false if not + def air_loop_hvac_economizer_required?(air_loop_hvac, climate_zone) + economizer_required = false + + # skip systems without outdoor air + return economizer_required unless air_loop_hvac.airLoopHVACOutdoorAirSystem.is_initialized + + # Determine if the airloop serves any computer rooms + # / data centers, which changes the economizer. + is_dc = false + if air_loop_hvac_data_center_area_served(air_loop_hvac) > 0 + is_dc = true + end + + # Retrieve economizer limits from JSON + search_criteria = { + 'template' => template, + 'climate_zone' => climate_zone, + 'data_center' => is_dc + } + econ_limits = model_find_object(standards_data['economizers'], search_criteria) + if econ_limits.nil? + OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.AirLoopHVAC', "Cannot find economizer limits for template '#{template}' and climate zone '#{climate_zone}', assuming no economizer required.") + return economizer_required + end + + # Determine the minimum capacity and whether or not it is a data center + minimum_capacity_btu_per_hr = econ_limits['capacity_limit'] + + # A big number of btu per hr as the minimum requirement if nil in spreadsheet + infinity_btu_per_hr = 999_999_999_999 + minimum_capacity_btu_per_hr = infinity_btu_per_hr if minimum_capacity_btu_per_hr.nil? + + # Check whether the system requires an economizer by comparing + # the system capacity to the minimum capacity. + total_cooling_capacity_w = air_loop_hvac_total_cooling_capacity(air_loop_hvac) + total_cooling_capacity_btu_per_hr = OpenStudio.convert(total_cooling_capacity_w, 'W', 'Btu/hr').get + + # Check whether the system has chilled water cooling + has_chilled_water_cooling = false + air_loop_hvac.supplyComponents.each do |equip| + if equip.to_CoilCoolingWater.is_initialized + has_chilled_water_cooling = true + end + end + + # Applicability logic from MASControl3 + if has_chilled_water_cooling + # All systems with chilled water cooling get an economizer regardless of capacity + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "#{air_loop_hvac.name} requires an economizer because it has chilled water cooling.") + economizer_required = true + else + # DX and other systems may have a capacity limit + if total_cooling_capacity_btu_per_hr >= minimum_capacity_btu_per_hr + if is_dc + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "#{air_loop_hvac.name} requires an economizer because the total cooling capacity of #{total_cooling_capacity_btu_per_hr.round} Btu/hr exceeds the minimum capacity of #{minimum_capacity_btu_per_hr.round} Btu/hr for data centers.") + else + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "#{air_loop_hvac.name} requires an economizer because the total cooling capacity of #{total_cooling_capacity_btu_per_hr.round} Btu/hr exceeds the minimum capacity of #{minimum_capacity_btu_per_hr.round} Btu/hr.") + end + economizer_required = true + else + if is_dc + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "#{air_loop_hvac.name} does not require an economizer because the total cooling capacity of #{total_cooling_capacity_btu_per_hr.round} Btu/hr is less than the minimum capacity of #{minimum_capacity_btu_per_hr.round} Btu/hr for data centers.") + else + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "#{air_loop_hvac.name} does not require an economizer because the total cooling capacity of #{total_cooling_capacity_btu_per_hr.round} Btu/hr is less than the minimum capacity of #{minimum_capacity_btu_per_hr.round} Btu/hr.") + end + end + end + + return economizer_required + end + # Check the economizer type currently specified in the ControllerOutdoorAir object on this air loop # is acceptable per the standard. Based on the MASControl rules, it appears that # only NoEconomizer and FixedDryBulb are allowed. # # @param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A' - # @return [Bool] Returns true if allowable, if the system has no economizer or no OA system. + # @return [Boolean] Returns true if allowable, if the system has no economizer or no OA system. # Returns false if the economizer type is not allowable. def air_loop_hvac_economizer_type_allowable?(air_loop_hvac, climate_zone) # EnergyPlus economizer types # 'NoEconomizer' # 'FixedDryBulb' @@ -46,54 +145,37 @@ return false end end # Determine the limits for the type of economizer present on the AirLoopHVAC, if any. - # + # Enthalpy limit is from MASControl3. # @param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A' # @return [Array<Double>] [drybulb_limit_f, enthalpy_limit_btu_per_lb, dewpoint_limit_f] 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 # No OA system + return [nil, nil, nil] unless oa_sys.is_initialized oa_sys = oa_sys.get oa_control = oa_sys.getControllerOutdoorAir economizer_type = oa_control.getEconomizerControlType case economizer_type when 'NoEconomizer' return [nil, nil, nil] when 'FixedDryBulb' enthalpy_limit_btu_per_lb = 28 - case climate_zone - when 'CEC T24-CEC7' - drybulb_limit_f = 69 - when 'CEC T24-CEC1', - 'CEC T24-CEC3', - 'CEC T24-CEC5' - drybulb_limit_f = 70 - when 'CEC T24-CEC6', - 'CEC T24-CEC8', - 'CEC T24-CEC9' - drybulb_limit_f = 71 - when 'CEC T24-CEC2', - 'CEC T24-CEC4', - 'CEC T24-CEC10', - drybulb_limit_f = 73 - when 'CEC T24-CEC11', - 'CEC T24-CEC12', - 'CEC T24-CEC13', - 'CEC T24-CEC14', - 'CEC T24-CEC15', - 'CEC T24-CEC16' - drybulb_limit_f = 75 - end + 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'] end return [drybulb_limit_f, enthalpy_limit_btu_per_lb, dewpoint_limit_f] end end