Source code for honeybee_openstudio.hvac.standards.fan

# coding=utf-8
"""Module taken from OpenStudio-standards.

Prototype fan calculation methods that are the same regardless of fan type.
These methods are available to FanConstantVolume, FanOnOff, FanVariableVolume,
and FanZoneExhaust.

https://github.com/NREL/openstudio-standards/blob/master/
lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb
"""
from __future__ import division
import os
import json

from ladybug.datatype.pressure import Pressure

from honeybee_openstudio.openstudio import openstudio_model


def _load_json_data(json_name):
    """load the fan data from the JSON file."""
    try:
        cur_dir = os.path.dirname(__file__)
        data_file = os.path.join(cur_dir, 'data', json_name)
        with open(data_file, 'r') as inf:
            fan_data = json.load(inf)
    except IOError:
        fan_data = {}
        print('Failed to import fan JSON data.')
    return fan_data


def _fan_curve_coefficients_from_json(fan_curve_name):
    """Lookup fan curve coefficients."""
    for curve_obj in CURVE_DATA:
        if curve_obj['name'] == fan_curve_name:
            return curve_obj['coeff_1'], curve_obj['coeff_2'], \
                curve_obj['coeff_3'], curve_obj['coeff_4'], curve_obj['coeff_5']
    return None, None, None, None, None


PRESSURE = Pressure()
FAN_DATA = _load_json_data('ashrae_90_1.fans.json')['fans']
CURVE_DATA = _load_json_data('ashrae_90_1.curves.json')['curves']


[docs] def create_fan_by_name( model, standards_name, fan_name=None, fan_efficiency=None, pressure_rise=None, motor_efficiency=None, motor_in_airstream_fraction=None, fan_power_minimum_flow_rate_input_method=None, fan_power_minimum_flow_rate_fraction=None, system_availability_manager_coupling_mode=None, end_use_subcategory=None): """Create a fan with properties for a fan name in the standards data. Args: fan_name: [String] fan name. fan_efficiency: [Double] fan efficiency. pressure_rise: [Double] fan pressure rise in Pa. end_use_subcategory: [String] end use subcategory name. """ # get the data from the JSON for fan_obj in FAN_DATA: if fan_obj['name'] == standards_name: fan_json = fan_obj break # create the fan if fan_json['type'] == 'ConstantVolume': fan = create_fan_constant_volume_from_json( model, fan_json, fan_name=fan_name, fan_efficiency=fan_efficiency, pressure_rise=pressure_rise, motor_efficiency=motor_efficiency, motor_in_airstream_fraction=motor_in_airstream_fraction, end_use_subcategory=end_use_subcategory) elif fan_json['type'] == 'OnOff': fan = create_fan_on_off_from_json( model, fan_json, fan_name=fan_name, fan_efficiency=fan_efficiency, pressure_rise=pressure_rise, motor_efficiency=motor_efficiency, motor_in_airstream_fraction=motor_in_airstream_fraction, end_use_subcategory=end_use_subcategory) elif fan_json['type'] == 'VariableVolume': fpc_1, fpc_2, fpc_3, fpc_4, fpc_5 = \ _fan_curve_coefficients_from_json(fan_json['fan_curve']) fan = create_fan_variable_volume_from_json( model, fan_json, fan_name=fan_name, fan_efficiency=fan_efficiency, pressure_rise=pressure_rise, motor_efficiency=motor_efficiency, motor_in_airstream_fraction=motor_in_airstream_fraction, fan_power_minimum_flow_rate_input_method=fan_power_minimum_flow_rate_input_method, fan_power_minimum_flow_rate_fraction=fan_power_minimum_flow_rate_fraction, fan_power_coefficient_1=fpc_1, fan_power_coefficient_2=fpc_2, fan_power_coefficient_3=fpc_3, fan_power_coefficient_4=fpc_4, fan_power_coefficient_5=fpc_5, end_use_subcategory=end_use_subcategory) elif fan_json['type'] == 'ZoneExhaust': fan = create_fan_zone_exhaust_from_json( model, fan_json, fan_name=fan_name, fan_efficiency=fan_efficiency, pressure_rise=pressure_rise, system_availability_manager_coupling_mode=system_availability_manager_coupling_mode, end_use_subcategory=end_use_subcategory) return fan
[docs] def create_fan_constant_volume_from_json( model, fan_json, fan_name=None, fan_efficiency=None, pressure_rise=None, motor_efficiency=None, motor_in_airstream_fraction=None, end_use_subcategory=None): """Creates a constant volume fan from a json.""" fan_efficiency = fan_json['fan_efficiency'] \ if fan_efficiency is None else fan_efficiency pressure_rise = fan_json['pressure_rise'] \ if pressure_rise is None else pressure_rise motor_efficiency = fan_json['motor_efficiency'] \ if motor_efficiency is None else motor_efficiency motor_in_airstream_fraction = fan_json['motor_in_airstream_fraction'] \ if motor_in_airstream_fraction is None else motor_in_airstream_fraction pressure_rise = PRESSURE.to_unit([pressure_rise], 'Pa', 'inH2O')[0] fan = openstudio_model.FanConstantVolume(model) _apply_base_fan_variables( fan, fan_name, fan_efficiency, pressure_rise, end_use_subcategory) if motor_efficiency is not None: fan.setMotorEfficiency(motor_efficiency) if motor_in_airstream_fraction is not None: fan.setMotorInAirstreamFraction(motor_in_airstream_fraction) return fan
[docs] def create_fan_on_off_from_json( model, fan_json, fan_name=None, fan_efficiency=None, pressure_rise=None, motor_efficiency=None, motor_in_airstream_fraction=None, end_use_subcategory=None): """Creates a on off fan from a json.""" fan_efficiency = fan_json['fan_efficiency'] \ if fan_efficiency is None else fan_efficiency pressure_rise = fan_json['pressure_rise'] \ if pressure_rise is None else pressure_rise motor_efficiency = fan_json['motor_efficiency'] \ if motor_efficiency is None else motor_efficiency motor_in_airstream_fraction = fan_json['motor_in_airstream_fraction'] \ if motor_in_airstream_fraction is None else motor_in_airstream_fraction pressure_rise = PRESSURE.to_unit([pressure_rise], 'Pa', 'inH2O')[0] fan = openstudio_model.FanOnOff(model) _apply_base_fan_variables( fan, fan_name, fan_efficiency, pressure_rise, end_use_subcategory) if motor_efficiency is not None: fan.setMotorEfficiency(motor_efficiency) if motor_in_airstream_fraction is not None: fan.setMotorInAirstreamFraction(motor_in_airstream_fraction) return fan
[docs] def create_fan_variable_volume_from_json( model, fan_json, fan_name=None, fan_efficiency=None, pressure_rise=None, motor_efficiency=None, motor_in_airstream_fraction=None, fan_power_minimum_flow_rate_input_method=None, fan_power_minimum_flow_rate_fraction=None, end_use_subcategory=None, fan_power_coefficient_1=None, fan_power_coefficient_2=None, fan_power_coefficient_3=None, fan_power_coefficient_4=None, fan_power_coefficient_5=None): """Creates a variable volume fan from a json.""" fan_efficiency = fan_json['fan_efficiency'] \ if fan_efficiency is None else fan_efficiency pressure_rise = fan_json['pressure_rise'] \ if pressure_rise is None else pressure_rise motor_efficiency = fan_json['motor_efficiency'] \ if motor_efficiency is None else motor_efficiency motor_in_airstream_fraction = fan_json['motor_in_airstream_fraction'] \ if motor_in_airstream_fraction is None else motor_in_airstream_fraction if fan_power_minimum_flow_rate_input_method is None: fan_power_minimum_flow_rate_input_method = \ fan_json['fan_power_minimum_flow_rate_input_method'] if fan_power_minimum_flow_rate_fraction is None: fan_power_minimum_flow_rate_fraction = \ fan_json['fan_power_minimum_flow_rate_fraction'] pressure_rise = PRESSURE.to_unit([pressure_rise], 'Pa', 'inH2O')[0] fan = openstudio_model.FanVariableVolume(model) _apply_base_fan_variables( fan, fan_name, fan_efficiency, pressure_rise, end_use_subcategory) if motor_efficiency is not None: fan.setMotorEfficiency(motor_efficiency) if motor_in_airstream_fraction is not None: fan.setMotorInAirstreamFraction(motor_in_airstream_fraction) if fan_power_minimum_flow_rate_input_method is not None: fan.setFanPowerMinimumFlowRateInputMethod(fan_power_minimum_flow_rate_input_method) if fan_power_minimum_flow_rate_fraction is not None: fan.setFanPowerMinimumFlowFraction(fan_power_minimum_flow_rate_fraction) if fan_power_coefficient_1 is not None: fan.setFanPowerCoefficient1(fan_power_coefficient_1) if fan_power_coefficient_2 is not None: fan.setFanPowerCoefficient2(fan_power_coefficient_2) if fan_power_coefficient_3 is not None: fan.setFanPowerCoefficient3(fan_power_coefficient_3) if fan_power_coefficient_4 is not None: fan.setFanPowerCoefficient4(fan_power_coefficient_4) if fan_power_coefficient_5 is not None: fan.setFanPowerCoefficient5(fan_power_coefficient_5) return fan
[docs] def create_fan_zone_exhaust_from_json( model, fan_json, fan_name=None, fan_efficiency=None, pressure_rise=None, system_availability_manager_coupling_mode=None, end_use_subcategory=None): """Creates a FanZoneExhaust from a json.""" fan_efficiency = fan_json['fan_efficiency'] \ if fan_efficiency is None else fan_efficiency pressure_rise = fan_json['pressure_rise'] \ if pressure_rise is None else pressure_rise pressure_rise = PRESSURE.to_unit([pressure_rise], 'Pa', 'inH2O')[0] fan = openstudio_model.FanZoneExhaust(model) _apply_base_fan_variables( fan, fan_name, fan_efficiency, pressure_rise, end_use_subcategory) if system_availability_manager_coupling_mode is not None: fan.setSystemAvailabilityManagerCouplingMode( system_availability_manager_coupling_mode) return fan
def _apply_base_fan_variables(fan, fan_name=None, fan_efficiency=None, pressure_rise=None, end_use_subcategory=None): if fan_name is not None: fan.setName(fan_name) if fan_efficiency is not None: fan.setFanEfficiency(fan_efficiency) if pressure_rise is not None: fan.setPressureRise(pressure_rise) if end_use_subcategory is not None: fan.setEndUseSubcategory(end_use_subcategory) return fan
[docs] def fan_change_impeller_efficiency(fan, impeller_eff): """Changes the fan impeller efficiency and also the fan total efficiency. Motor efficiency is preserved. Args: fan: [OpenStudio::Model::StraightComponent] Fan object. Allowable types include FanConstantVolume, FanOnOff, FanVariableVolume, and FanZoneExhaust. impeller_eff: [Double] impeller efficiency (0.0 to 1.0). """ # Get the existing motor efficiency existing_motor_eff = 0.7 if fan.to_FanZoneExhaust().is_initialized(): existing_motor_eff = fan.motorEfficiency() # Calculate the new total efficiency new_total_eff = existing_motor_eff * impeller_eff # Set the revised motor and total fan efficiencies fan.setFanEfficiency(new_total_eff)
[docs] def fan_baseline_impeller_efficiency(fan): """Assume that the fan efficiency is 65% for normal fans and 55% for small fans.""" fan_impeller_eff = 0.65 if is_small_fan(fan): fan_impeller_eff = 0.55 return fan_impeller_eff
[docs] def is_small_fan(fan): """Zone exhaust fans, FCU fans, and VAV terminal fans all count as small fans. Small fans get different impeller efficiencies and motor efficiencies than other fans. Args: fan: [OpenStudio::Model::StraightComponent] Fan object. Allowable types includeFanConstantVolume, FanOnOff, FanVariableVolume, and FanZoneExhaust """ is_small = False # Exhaust fan if fan.to_FanZoneExhaust().is_initialized(): is_small = True # Fan coil unit, unit heater, PTAC, PTHP, VRF terminals, WSHP, ERV elif fan.containingZoneHVACComponent().is_initialized(): zone_hvac = fan.containingZoneHVACComponent().get() if zone_hvac.to_ZoneHVACFourPipeFanCoil().is_initialized(): is_small = True elif zone_hvac.to_ZoneHVACPackagedTerminalAirConditioner().is_initialized() or \ zone_hvac.to_ZoneHVACPackagedTerminalHeatPump().is_initialized() or \ zone_hvac.to_ZoneHVACTerminalUnitVariableRefrigerantFlow().is_initialized() or \ zone_hvac.to_ZoneHVACWaterToAirHeatPump().is_initialized() or \ zone_hvac.to_ZoneHVACEnergyRecoveryVentilator().is_initialized(): is_small = True # Powered VAV terminal elif fan.containingHVACComponent().is_initialized(): zone_hvac = fan.containingHVACComponent().get() if zone_hvac.to_AirTerminalSingleDuctParallelPIUReheat().is_initialized() or \ zone_hvac.to_AirTerminalSingleDuctSeriesPIUReheat().is_initialized(): is_small = True return is_small