Class: NECB2011
- Defined in:
- lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb,
lib/openstudio-standards/standards/necb/necb_2011/lighting.rb,
lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb,
lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb,
lib/openstudio-standards/standards/necb/necb_2011/beps_compliance_path.rb,
lib/openstudio-standards/standards/necb/necb_2011/service_water_heating.rb
Overview
This class holds methods that apply NECB2011 rules.
Direct Known Subclasses
NECB2011FullServiceRestaurant, NECB2011HighriseApartment, NECB2011Hospital, NECB2011LargeHotel, NECB2011LargeOffice, NECB2011MediumOffice, NECB2011MidriseApartment, NECB2011Outpatient, NECB2011PrimarySchool, NECB2011QuickServiceRestaurant, NECB2011RetailStandalone, NECB2011RetailStripmall, NECB2011SecondarySchool, NECB2011SmallHotel, NECB2011SmallOffice, NECB2011SuperMarket, NECB2011Warehouse, NECB2011_Prototype, NECB2015
Constant Summary
Constants inherited from Standard
Instance Attribute Summary collapse
-
#standards_data ⇒ Object
Returns the value of attribute standards_data.
-
#template ⇒ Object
readonly
Returns the value of attribute template.
Attributes inherited from Standard
Instance Method Summary collapse
- #add_sys1_unitary_ac_baseboard_heating(model, zones, boiler_fueltype, mau, mau_heating_coil_type, baseboard_type, hw_loop) ⇒ Object
-
#add_sys1_unitary_ac_baseboard_heating_multi_speed(model, zones, boiler_fueltype, mau, mau_heating_coil_type, baseboard_type, hw_loop) ⇒ Object
sys1_unitary_ac_baseboard_heating.
-
#add_sys2_FPFC_sys5_TPFC(model, zones, boiler_fueltype, chiller_type, fan_coil_type, mua_cooling_type, hw_loop) ⇒ Object
sys1_unitary_ac_baseboard_heating.
-
#add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_multi_speed(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) ⇒ Object
end add_sys3_single_zone_packaged_rooftop_unit_with_baseboard_heating_single_speed.
-
#add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_single_speed(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) ⇒ Object
add_sys2_FPFC_sys5_TPFC.
-
#add_sys4_single_zone_make_up_air_unit_with_baseboard_heating(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) ⇒ Object
end add_sys3_single_zone_packaged_rooftop_unit_with_baseboard_heating_multi_speed.
-
#add_sys6_multi_zone_built_up_system_with_baseboard_heating(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, chiller_type, fan_type, hw_loop) ⇒ Object
end add_sys4_single_zone_make_up_air_unit_with_baseboard_heating.
-
#air_loop_hvac_apply_economizer_integration(air_loop_hvac, climate_zone) ⇒ Bool
NECB always requires an integrated economizer (NoLockout); as per 5.2.2.8(3) this means that compressor allowed to turn on when economizer is open.
-
#air_loop_hvac_apply_energy_recovery_ventilator(air_loop_hvac) ⇒ Bool
Add an ERV to this airloop.
-
#air_loop_hvac_apply_multizone_vav_outdoor_air_sizing(air_loop_hvac) ⇒ Object
NECB does not change damper positions.
-
#air_loop_hvac_apply_single_zone_controls(air_loop_hvac, climate_zone) ⇒ Bool
NECB has no single zone air loop control requirements.
-
#air_loop_hvac_apply_vav_damper_action(air_loop_hvac) ⇒ Bool
Set the VAV damper control to single maximum or dual maximum control depending on the standard.
-
#air_loop_hvac_demand_control_ventilation_required?(air_loop_hvac, climate_zone) ⇒ Bool
Determine if demand control ventilation (DCV) is required for this air loop.
-
#air_loop_hvac_economizer_required?(air_loop_hvac) ⇒ Bool
Determine whether or not this system is required to have an economizer.
-
#air_loop_hvac_energy_recovery_ventilator_required?(air_loop_hvac, climate_zone) ⇒ Bool
Check if ERV is required on this airloop.
-
#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_static_pressure_reset_required?(air_loop_hvac, has_ddc) ⇒ Boolean
NECB doesn’t require static pressure reset.
- #apply_building_default_constructionset(building_type, climate_zone, model) ⇒ Object
- #apply_default_constructionsets_to_spacetypes(climate_zone, model) ⇒ Object
- #apply_economizers(climate_zone, model) ⇒ Object
-
#apply_standard_construction_properties(model, runner = nil, scale_wall = 1.0, scale_floor = 1.0, scale_roof = 1.0, scale_ground_wall = 1.0, scale_ground_floor = 1.0, scale_ground_roof = 1.0, scale_door = 1.0, scale_window = 1.0) ⇒ Bool
Go through the default construction sets and hard-assigned constructions.
- #apply_standard_lights(set_lights, space_type, space_type_properties) ⇒ Object
-
#apply_standard_skylight_to_roof_ratio(model) ⇒ Object
Reduces the SRR to the values specified by the PRM.
-
#apply_standard_window_to_wall_ratio(model) ⇒ Object
Reduces the WWR to the values specified by the NECB NECB 3.2.1.4.
- #assign_contruction_to_adiabatic_surfaces(model) ⇒ Object
-
#boiler_hot_water_apply_efficiency_and_curves(boiler_hot_water) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
-
#chiller_electric_eir_apply_efficiency_and_curves(chiller_electric_eir, clg_tower_objs) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
-
#coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_multi_speed, sql_db_vars_map) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
-
#coil_heating_gas_multi_stage_apply_efficiency_and_curves(coil_heating_gas_multi_stage, standards) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
-
#determine_dominant_necb_schedule_type(model) ⇒ Object
This model determines the dominant NECB schedule type return s.each [String].
-
#determine_necb_schedule_type(space) ⇒ String
This method determines the spacetype schedule type.
-
#distance(loc1, loc2) ⇒ Object
Enter in [latitude, longitude] for each loc and this method will return the distance.
-
#fan_baseline_impeller_efficiency(fan) ⇒ Double
Determines the baseline fan impeller efficiency based on the specified fan type.
- #fan_constant_volume_apply_prototype_fan_pressure_rise(fan_constant_volume) ⇒ Object
-
#fan_standard_minimum_motor_efficiency_and_size(fan, motor_bhp) ⇒ Array<Double>
Determines the minimum fan motor efficiency and nominal size for a given motor bhp.
-
#fan_variable_volume_apply_prototype_fan_pressure_rise(fan_variable_volume) ⇒ Object
Sets the fan pressure rise based on the Prototype buildings inputs which are governed by the flow rate coming through the fan and whether the fan lives inside a unit heater, PTAC, etc.
-
#fan_variable_volume_part_load_fan_power_limitation?(fan_variable_volume) ⇒ Boolean
Determines whether there is a requirement to have a VSD or some other method to reduce fan power at low part load ratios.
- #get_all_spacetype_names ⇒ Object
-
#get_canadian_system_defaults_by_weatherfile_name(model) ⇒ Object
this method returns the default system fuel types by epw_file.
- #get_necb_hdd18(model) ⇒ Object
- #get_standards_constant(name) ⇒ Object
- #get_standards_formula(name) ⇒ Object
- #get_standards_table(table_name, search_criteria = nil) ⇒ Object
-
#initialize ⇒ NECB2011
constructor
A new instance of NECB2011.
-
#load_standards_database_new ⇒ Object
Combine the data from the JSON files into a single hash Load JSON files differently depending on whether loading from the OpenStudio CLI embedded filesystem or from typical gem installation.
-
#max_fwdr(hdd) ⇒ Double
A constant float.
-
#model_add_construction_set(model, clim, building_type, spc_type, is_residential = 'No') ⇒ Object
Create a construction set from the openstudio standards dataset.
-
#model_add_constructions(model, building_type, climate_zone) ⇒ Bool
Adds code-minimum constructions based on the building type as defined in the OpenStudio_Standards_construction_sets.json file.
- #model_add_hvac(model, epw_file) ⇒ Object
-
#model_add_schedule(model, schedule_name) ⇒ ScheduleRuleset
Create a schedule from the openstudio standards dataset and add it to the model.
- #model_add_swh(model, building_type, climate_zone, prototype_input, epw_file) ⇒ Object
- #model_apply_sizing_parameters(model) ⇒ Object
-
#model_attach_water_fixtures_to_spaces?(model) ⇒ Boolean
Determine whether or not water fixtures are attached to spaces.
- #model_create_prototype_model(climate_zone, epw_file, sizing_run_dir = Dir.pwd, debug = false, measure_model = nil) ⇒ Object
-
#model_create_thermal_zones(model, space_multiplier_map = nil) ⇒ Bool
Creates thermal zones to contain each space, as defined for each building in the system_to_space_map inside the Prototype.building_name e.g.
-
#model_find_and_add_construction(model, climate_zone_set, intended_surface_type, standards_construction_type, building_category) ⇒ Object
Helper method to find a particular construction and add it to the model after modifying the insulation value if necessary.
-
#model_find_climate_zone_set(model, clim) ⇒ Object
Helper method to find out which climate zone set contains a specific climate zone.
-
#necb_autozone_and_autosystem(model = nil, runner = nil, use_ideal_air_loads = false, system_fuel_defaults) ⇒ String
This method will take a model that uses NECB2011 spacetypes , and..
- #necb_spacetype_system_selection(model, heating_design_load = nil, cooling_design_load = nil) ⇒ Object
-
#set_construction_set_to_necb!(model, default_surface_construction_set, runner = nil, scale_wall = 1.0, scale_floor = 1.0, scale_roof = 1.0, scale_ground_wall = 1.0, scale_ground_floor = 1.0, scale_ground_roof = 1.0, scale_door = 1.0, scale_window = 1.0) ⇒ Boolean
this will create a copy and convert all construction sets to NECB reference conductances.
-
#set_necb_external_subsurface_conductance(subsurface, hdd) ⇒ Object
Set all external subsurfaces (doors, windows, skylights) to NECB values.
-
#set_necb_external_surface_conductance(surface, hdd, is_radiant = false, scaling_factor = 1.0) ⇒ String
Set all external surface conductances to NECB values.
-
#set_occ_sensor_spacetypes(model, space_type_map) ⇒ Bool
Returns true if successful, false if not.
- #set_wildcard_schedules_to_dominant_building_schedule(model, runner = nil) ⇒ Object
- #set_zones_thermostat_schedule_based_on_space_type_schedules(model, runner = nil) ⇒ Object
-
#setup_chw_loop_with_components(model, chw_loop, chiller_type) ⇒ Object
of setup_hw_loop_with_components.
-
#setup_cw_loop_with_components(model, cw_loop, chiller1, chiller2) ⇒ Object
of setup_chw_loop_with_components.
- #setup_hw_loop_with_components(model, hw_loop, boiler_fueltype, pump_flow_sch) ⇒ Object
-
#space_apply_infiltration_rate(space) ⇒ Double
Set the infiltration rate for this space to include the impact of air leakage requirements in the standard.
-
#space_type_apply_internal_loads(space_type, set_people, set_lights, set_electric_equipment, set_gas_equipment, set_ventilation, set_infiltration) ⇒ Bool
Sets the selected internal loads to standards-based or typical values.
-
#thermal_zone_demand_control_ventilation_required?(thermal_zone, climate_zone) ⇒ Bool
Determine if demand control ventilation (DCV) is required for this zone based on area and occupant density.
-
#water_heater_mixed_apply_efficiency(water_heater_mixed) ⇒ Bool
Applies the standard efficiency ratings and typical losses and paraisitic loads to this object.
Methods inherited from Standard
#adjust_infiltration_to_lower_pressure, #adjust_infiltration_to_prototype_building_conditions, #afue_to_thermal_eff, #air_loop_hvac_add_motorized_oa_damper, #air_loop_hvac_adjust_minimum_vav_damper_positions, #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_limits, #air_loop_hvac_apply_maximum_reheat_temperature, #air_loop_hvac_apply_minimum_vav_damper_positions, #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_standard_controls, #air_loop_hvac_data_center_area_served, #air_loop_hvac_dcv_required_when_erv, #air_loop_hvac_demand_control_ventilation_limits, #air_loop_hvac_disable_multizone_vav_optimization, #air_loop_hvac_dx_cooling?, #air_loop_hvac_economizer?, #air_loop_hvac_economizer_limits, #air_loop_hvac_economizer_type_allowable?, #air_loop_hvac_enable_demand_control_ventilation, #air_loop_hvac_enable_multizone_vav_optimization, #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_flow_limit, #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_integrated_economizer_required?, #air_loop_hvac_motorized_oa_damper_required?, #air_loop_hvac_multi_stage_dx_cooling?, #air_loop_hvac_multizone_vav_optimization_required?, #air_loop_hvac_multizone_vav_system?, #air_loop_hvac_prm_baseline_economizer_required?, #air_loop_hvac_prm_economizer_type_and_limits, #air_loop_hvac_remove_motorized_oa_damper, #air_loop_hvac_single_zone_controls_num_stages, #air_loop_hvac_supply_air_temperature_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_unoccupied_fan_shutoff_required?, #air_loop_hvac_vav_damper_action, #air_loop_hvac_vav_system?, #air_terminal_single_duct_parallel_piu_reheat_apply_prm_baseline_fan_power, #air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position, #air_terminal_single_duct_vav_reheat_apply_minimum_damper_position, #air_terminal_single_duct_vav_reheat_minimum_damper_position, #air_terminal_single_duct_vav_reheat_reheat_type, #air_terminal_single_duct_vav_reheat_set_heating_cap, #boiler_hot_water_find_capacity, #boiler_hot_water_find_search_criteria, #boiler_hot_water_standard_minimum_thermal_efficiency, build, #building_story_floor_multiplier, #building_story_minimum_z_value, #chiller_electric_eir_find_capacity, #chiller_electric_eir_find_search_criteria, #chiller_electric_eir_standard_minimum_full_load_efficiency, #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_heating_dx_multi_speed_apply_efficiency_and_curves, #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_prototype_efficiency, #combustion_eff_to_thermal_eff, #construction_calculated_solar_heat_gain_coefficient, #construction_calculated_u_factor, #construction_calculated_visible_transmittance, #construction_set_glazing_shgc, #construction_set_glazing_u_value, #construction_set_slab_f_factor, #construction_set_u_value, #construction_set_underground_wall_c_factor, #construction_simple_glazing?, #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, #cooling_tower_variable_speed_apply_efficiency_and_curves, #cop_heating_to_cop_heating_no_fan, #cop_to_eer, #cop_to_kw_per_ton, #cop_to_seer, #create_curve_bicubic, #create_curve_biquadratic, #create_curve_cubic, #create_curve_exponent, #create_curve_quadratic, #define_space_multiplier, #eer_to_cop, #fan_constant_volume_airloop_fan_pressure_rise, #fan_on_off_airloop_or_unitary_fan_pressure_rise, #fan_on_off_apply_prototype_fan_pressure_rise, #fan_variable_volume_airloop_fan_pressure_rise, #fan_variable_volume_cooling_system_type, #fan_variable_volume_part_load_fan_power_limitation_capacity_limit, #fan_variable_volume_part_load_fan_power_limitation_hp_limit, #fan_variable_volume_set_control_type, #fan_zone_exhaust_apply_prototype_fan_pressure_rise, #film_coefficients_r_value, #headered_pumps_variable_speed_set_control_type, #heat_exchanger_air_to_air_sensible_and_latent_apply_efficiency, #heat_exchanger_air_to_air_sensible_and_latent_apply_prototype_nominal_electric_power, #heat_exchanger_air_to_air_sensible_and_latent_minimum_efficiency, #heating_design_outdoor_temperatures, #hspf_to_cop_heating_no_fan, #intialize, #kw_per_ton_to_cop, #load_hvac_map, #load_standards_database, #model_add_baseboard, #model_add_booster_swh_end_uses, #model_add_cav, #model_add_central_air_source_heat_pump, #model_add_chw_loop, #model_add_constant_schedule_ruleset, #model_add_construction, #model_add_curve, #model_add_cw_loop, #model_add_data_center_hvac, #model_add_data_center_load, #model_add_daylighting_controls, #model_add_design_days_and_weather_file, #model_add_district_ambient_loop, #model_add_doas, #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_ground_temperatures, #model_add_high_temp_radiant, #model_add_hp_loop, #model_add_hvac_system, #model_add_hw_loop, #model_add_ideal_air_loads, #model_add_material, #model_add_prm_baseline_system, #model_add_prm_construction_set, #model_add_psz_ac, #model_add_psz_vav, #model_add_ptac, #model_add_pthp, #model_add_pvav, #model_add_pvav_pfp_boxes, #model_add_refrigeration, #model_add_refrigeration_case, #model_add_refrigeration_compressor, #model_add_refrigeration_system, #model_add_refrigeration_walkin, #model_add_split_ac, #model_add_swh_booster, #model_add_swh_end_uses, #model_add_swh_end_uses_by_space, #model_add_swh_loop, #model_add_typical_exterior_lights, #model_add_typical_swh, #model_add_unitheater, #model_add_vav_pfp_boxes, #model_add_vav_reheat, #model_add_water_heater, #model_add_water_source_hp, #model_add_window_ac, #model_add_zone_erv, #model_add_zone_ventilation, #model_apply_hvac_efficiency_standard, #model_apply_infiltration_standard, #model_apply_multizone_vav_outdoor_air_sizing, #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_assign_spaces_to_stories, #model_baseline_system_vav_fan_type, #model_create_exterior_lighting_area_length_count_hash, #model_create_prm_baseline_building, #model_create_prm_baseline_building_requires_vlt_sizing_run, #model_create_space_type_hash, #model_create_story_hash, #model_cw_loop_cooling_tower_fan_type, #model_differentiate_primary_secondary_thermal_zones, #model_effective_num_stories, #model_elevator_fan_pwr, #model_elevator_lift_power, #model_elevator_lighting_pct_incandescent, #model_eliminate_outlier_zones, #model_find_ashrae_hot_water_demand, #model_find_constructions, #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_climate_zone_and_building_type, #model_get_climate_zone_set_from_list, #model_get_construction_properties, #model_get_full_weather_file_path, #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_get_story_for_nominal_z_coordinate, #model_group_zones_by_story, #model_make_name, #model_num_stories_spanned, #model_prm_baseline_system_change_fuel_type, #model_prm_baseline_system_group_minimum_area, #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_hvac, #model_residential_and_nonresidential_floor_areas, #model_swh_pump_type, #model_typical_hvac_system_type, #model_validate_standards_spacetypes_in_model, #model_walkin_freezer_latent_case_credit_curve, #model_zones_with_occ_and_fuel_type, #planar_surface_apply_standard_construction, #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_enable_supply_water_temperature_reset, #plant_loop_find_maximum_loop_flow_rate, #plant_loop_prm_baseline_condenser_water_temperatures, #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?, #pump_variable_speed_set_control_type, register_standard, #safe_load_model, #safe_load_sql, #schedule_compact_annual_min_max_value, #schedule_constant_annual_equivalent_full_load_hrs, #schedule_constant_annual_min_max_value, #schedule_ruleset_annual_equivalent_full_load_hrs, #schedule_ruleset_annual_hours_above_value, #schedule_ruleset_annual_min_max_value, #seer_to_cop_cooling_no_fan, #space_add_daylighting_controls, #space_conditioning_category, #space_cooled?, #space_daylighted_area_window_width, #space_daylighted_areas, #space_daylighting_control_required?, #space_daylighting_fractions_and_windows, #space_design_internal_load, #space_exterior_wall_and_roof_and_subsurface_area, #space_exterior_wall_and_window_area, #space_get_adjacent_space_with_most_shared_wall_area, #space_get_adjacent_spaces_with_shared_wall_areas, #space_heated?, #space_infiltration_rate_75_pa, #space_plenum?, #space_residential?, #space_sidelighting_effective_aperture, #space_skylight_effective_aperture, #space_type_apply_internal_load_schedules, #space_type_apply_rendering_color, #space_type_get_construction_properties, #space_type_get_standards_data, #strip_model, #sub_surface_component_infiltration_rate, #sub_surface_reduce_area_by_percent_by_raising_sill, #sub_surface_reduce_area_by_percent_by_shrinking_toward_centroid, #sub_surface_vertical_rectangle?, #surface_component_infiltration_rate, #thermal_eff_to_afue, #thermal_eff_to_comb_eff, #thermal_zone_add_exhaust, #thermal_zone_add_exhaust_fan_dcv, #thermal_zone_add_unconditioned_thermostat, #thermal_zone_apply_prm_baseline_supply_temperatures, #thermal_zone_conditioning_category, #thermal_zone_convert_oa_req_to_per_area, #thermal_zone_cooled?, #thermal_zone_demand_control_ventilation_limits, #thermal_zone_design_internal_load, #thermal_zone_exhaust_fan_dcv_required?, #thermal_zone_floor_area_with_zone_multipliers, #thermal_zone_fossil_hybrid_or_purchased_heat?, #thermal_zone_fossil_or_electric_type, #thermal_zone_get_adjacent_zones_with_shared_wall_areas, #thermal_zone_get_occupancy_schedule, #thermal_zone_heated?, #thermal_zone_infer_system_type, #thermal_zone_majority_space_type, #thermal_zone_mixed_heating_fuel?, #thermal_zone_occupancy_type, #thermal_zone_outdoor_airflow_rate, #thermal_zone_outdoor_airflow_rate_per_area, #thermal_zone_plenum?, #thermal_zone_prm_baseline_cooling_design_supply_temperature, #thermal_zone_prm_baseline_heating_design_supply_temperature, #thermal_zone_residential?, #water_heater_mixed_apply_prm_baseline_fuel_type, #water_heater_mixed_find_capacity, #zone_hvac_component_apply_prm_baseline_fan_power
Methods included from PrototypeFan
#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, #pump_standard_minimum_motor_efficiency_and_size
Methods included from Fan
#fan_adjust_pressure_rise_to_meet_fan_power, #fan_apply_standard_minimum_motor_efficiency, #fan_brake_horsepower, #fan_change_impeller_efficiency, #fan_change_motor_efficiency, #fan_fanpower, #fan_motor_horsepower, #fan_rated_w_per_cfm, #fan_small_fan?
Constructor Details
#initialize ⇒ NECB2011
Returns a new instance of NECB2011.
81 82 83 84 85 86 87 88 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 81 def initialize super() @template = self.class.name @standards_data = self.load_standards_database_new() #puts "loaded these tables..." #puts @standards_data.keys.size #raise("tables not all loaded in parent #{}") if @standards_data.keys.size < 24 end |
Instance Attribute Details
#standards_data ⇒ Object
Returns the value of attribute standards_data.
7 8 9 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 7 def standards_data @standards_data end |
#template ⇒ Object (readonly)
Returns the value of attribute template.
6 7 8 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 6 def template @template end |
Instance Method Details
#add_sys1_unitary_ac_baseboard_heating(model, zones, boiler_fueltype, mau, mau_heating_coil_type, baseboard_type, hw_loop) ⇒ Object
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1189 def add_sys1_unitary_ac_baseboard_heating(model, zones, boiler_fueltype, mau, mau_heating_coil_type, baseboard_type, hw_loop) # System Type 1: PTAC with no heating (unitary AC) # Zone baseboards, electric or hot water depending on argument baseboard_type # baseboard_type choices are "Hot Water" or "Electric" # PSZ to represent make-up air unit (if present) # This measure creates: # a PTAC unit for each zone in the building; DX cooling coil # and heating coil that is always off # Baseboards ("Hot Water or "Electric") in zones connected to hot water loop # MAU is present if argument mau == true, not present if argument mau == false # MAU is PSZ; DX cooling # MAU heating coil: hot water coil or electric, depending on argument mau_heating_coil_type # mau_heating_coil_type choices are "Hot Water", "Electric" # boiler_fueltype choices match OS choices for Boiler component fuel type, i.e. # "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" # Some system parameters are set after system is set up; by applying method 'apply_hvac_efficiency_standard' always_on = model.alwaysOnDiscreteSchedule # define always off schedule for ptac heating coil always_off = BTAP::Resources::Schedules::StandardSchedules::ON_OFF.always_off(model) # Create MAU # TO DO: MAU sizing, characteristics (fan operation schedules, temperature setpoints, outdoor air, etc) if mau == true mau_air_loop = OpenStudio::Model::AirLoopHVAC.new(model) mau_air_loop.setName('Make-up air unit') # When an air_loop is constructed, its constructor creates a sizing:system object # the default sizing:system constructor makes a system:sizing object # appropriate for a multizone VAV system # this systems is a constant volume system with no VAV terminals, # and therfore needs different default settings air_loop_sizing = mau_air_loop.sizingSystem # TODO units air_loop_sizing.setTypeofLoadtoSizeOn('VentilationRequirement') air_loop_sizing.autosizeDesignOutdoorAirFlowRate air_loop_sizing.setMinimumSystemAirFlowRatio(1.0) air_loop_sizing.setPreheatDesignTemperature(7.0) air_loop_sizing.setPreheatDesignHumidityRatio(0.008) air_loop_sizing.setPrecoolDesignTemperature(13.0) air_loop_sizing.setPrecoolDesignHumidityRatio(0.008) air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(13) air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(43) air_loop_sizing.setSizingOption('NonCoincident') air_loop_sizing.setAllOutdoorAirinCooling(true) air_loop_sizing.setAllOutdoorAirinHeating(true) air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085) air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080) air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay') air_loop_sizing.setCoolingDesignAirFlowRate(0.0) air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay') air_loop_sizing.setHeatingDesignAirFlowRate(0.0) air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum') mau_fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) if mau_heating_coil_type == 'Electric' # electric coil mau_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) end if mau_heating_coil_type == 'Hot Water' mau_htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on) hw_loop.addDemandBranchForComponent(mau_htg_coil) end # Set up DX coil with default curves (set to NECB); mau_clg_coil = BTAP::Resources::HVAC::Plant.add_onespeed_DX_coil(model, always_on) # oa_controller oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) # oa_controller.setEconomizerControlType("DifferentialEnthalpy") # oa_system oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone supply_inlet_node = mau_air_loop.supplyInletNode mau_fan.addToNode(supply_inlet_node) mau_htg_coil.addToNode(supply_inlet_node) mau_clg_coil.addToNode(supply_inlet_node) oa_system.addToNode(supply_inlet_node) # Add a setpoint manager to control the supply air temperature sat = 20.0 sat_sch = OpenStudio::Model::ScheduleRuleset.new(model) sat_sch.setName('Makeup-Air Unit Supply Air Temp') sat_sch.defaultDaySchedule.setName('Makeup Air Unit Supply Air Temp Default') sat_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), sat) setpoint_mgr = OpenStudio::Model::SetpointManagerScheduled.new(model, sat_sch) setpoint_mgr.addToNode(mau_air_loop.supplyOutletNode) end # Create MAU # Create a PTAC for each zone: # PTAC DX Cooling with electric heating coil; electric heating coil is always off # TO DO: need to apply this system to space types: # (1) data processing area: control room, data centre # when cooling capacity <= 20kW and # (2) residential/accommodation: murb, hotel/motel guest room # when building/space heated only (this as per NECB; apply to # all for initial work? CAN-QUEST limitation) # TO DO: PTAC characteristics: sizing, fan schedules, temperature setpoints, interaction with MAU zones.each do |zone| # Zone sizing temperature sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) # Set up PTAC heating coil; apply always off schedule # htg_coil_elec = OpenStudio::Model::CoilHeatingElectric.new(model,always_on) htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_off) # Set up PTAC DX coil with NECB performance curve characteristics; clg_coil = BTAP::Resources::HVAC::Plant.add_onespeed_DX_coil(model, always_on) # Set up PTAC constant volume supply fan fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) fan.setPressureRise(640) ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model, always_on, fan, htg_coil, clg_coil) ptac.setName("#{zone.name} PTAC") ptac.addToThermalZone(zone) # add zone baseboards if baseboard_type == 'Electric' # zone_elec_baseboard = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model) zone_elec_baseboard = BTAP::Resources::HVAC::Plant.add_elec_baseboard(model) zone_elec_baseboard.addToThermalZone(zone) end if baseboard_type == 'Hot Water' baseboard_coil = BTAP::Resources::HVAC::Plant.add_hw_baseboard_coil(model) # Connect baseboard coil to hot water loop hw_loop.addDemandBranchForComponent(baseboard_coil) zone_baseboard = BTAP::Resources::HVAC::ZoneEquipment.add_zone_baseboard_convective_water(model, always_on, baseboard_coil) # add zone_baseboard to zone zone_baseboard.addToThermalZone(zone) end # # Create a diffuser and attach the zone/diffuser pair to the MAU air loop, if applicable if mau == true diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on) mau_air_loop.addBranchForZone(zone, diffuser.to_StraightComponent) end # components for MAU end # of zone loop return true end |
#add_sys1_unitary_ac_baseboard_heating_multi_speed(model, zones, boiler_fueltype, mau, mau_heating_coil_type, baseboard_type, hw_loop) ⇒ Object
sys1_unitary_ac_baseboard_heating
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1362 def add_sys1_unitary_ac_baseboard_heating_multi_speed(model, zones, boiler_fueltype, mau, mau_heating_coil_type, baseboard_type, hw_loop) # System Type 1: PTAC with no heating (unitary AC) # Zone baseboards, electric or hot water depending on argument baseboard_type # baseboard_type choices are "Hot Water" or "Electric" # PSZ to represent make-up air unit (if present) # This measure creates: # a PTAC unit for each zone in the building; DX cooling coil # and heating coil that is always off # Baseboards ("Hot Water or "Electric") in zones connected to hot water loop # MAU is present if argument mau == true, not present if argument mau == false # MAU is PSZ; DX cooling # MAU heating coil: hot water coil or electric, depending on argument mau_heating_coil_type # mau_heating_coil_type choices are "Hot Water", "Electric" # boiler_fueltype choices match OS choices for Boiler component fuel type, i.e. # "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" # Some system parameters are set after system is set up; by applying method 'apply_hvac_efficiency_standard' always_on = model.alwaysOnDiscreteSchedule # define always off schedule for ptac heating coil always_off = BTAP::Resources::Schedules::StandardSchedules::ON_OFF.always_off(model) # TODO: Heating and cooling temperature set point schedules are set somewhere else # TODO: For now fetch the schedules and use them in setting up the heat pump system # TODO: Later on these schedules need to be passed on to this method htg_temp_sch = nil clg_temp_sch = nil zones.each do |izone| if izone.thermostat.is_initialized zone_thermostat = izone.thermostat.get if zone_thermostat.to_ThermostatSetpointDualSetpoint.is_initialized dual_thermostat = zone_thermostat.to_ThermostatSetpointDualSetpoint.get htg_temp_sch = dual_thermostat.heatingSetpointTemperatureSchedule.get clg_temp_sch = dual_thermostat.coolingSetpointTemperatureSchedule.get break end end end # Create MAU # TO DO: MAU sizing, characteristics (fan operation schedules, temperature setpoints, outdoor air, etc) if mau == true staged_thermostat = OpenStudio::Model::ZoneControlThermostatStagedDualSetpoint.new(model) staged_thermostat.setHeatingTemperatureSetpointSchedule(htg_temp_sch) staged_thermostat.setNumberofHeatingStages(4) staged_thermostat.setCoolingTemperatureSetpointBaseSchedule(clg_temp_sch) staged_thermostat.setNumberofCoolingStages(4) mau_air_loop = OpenStudio::Model::AirLoopHVAC.new(model) mau_air_loop.setName('Make-up air unit') # When an air_loop is constructed, its constructor creates a sizing:system object # the default sizing:system constructor makes a system:sizing object # appropriate for a multizone VAV system # this systems is a constant volume system with no VAV terminals, # and therfore needs different default settings air_loop_sizing = mau_air_loop.sizingSystem # TODO units air_loop_sizing.setTypeofLoadtoSizeOn('Sensible') air_loop_sizing.autosizeDesignOutdoorAirFlowRate air_loop_sizing.setMinimumSystemAirFlowRatio(1.0) air_loop_sizing.setPreheatDesignTemperature(7.0) air_loop_sizing.setPreheatDesignHumidityRatio(0.008) air_loop_sizing.setPrecoolDesignTemperature(12.8) air_loop_sizing.setPrecoolDesignHumidityRatio(0.008) air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(13.0) air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(43.0) air_loop_sizing.setSizingOption('NonCoincident') air_loop_sizing.setAllOutdoorAirinCooling(false) air_loop_sizing.setAllOutdoorAirinHeating(false) air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085) air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080) air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay') air_loop_sizing.setCoolingDesignAirFlowRate(0.0) air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay') air_loop_sizing.setHeatingDesignAirFlowRate(0.0) air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum') mau_fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) # Multi-stage gas heating coil if mau_heating_coil_type == 'Electric' || mau_heating_coil_type == 'Hot Water' mau_htg_coil = OpenStudio::Model::CoilHeatingGasMultiStage.new(model) mau_htg_stage_1 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) mau_htg_stage_2 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) mau_htg_stage_3 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) mau_htg_stage_4 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) if mau_heating_coil_type == 'Electric' mau_supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) elsif mau_heating_coil_type == 'Hot Water' mau_supplemental_htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on) hw_loop.addDemandBranchForComponent(mau_supplemental_htg_coil) end mau_htg_stage_1.setNominalCapacity(0.1) mau_htg_stage_2.setNominalCapacity(0.2) mau_htg_stage_3.setNominalCapacity(0.3) mau_htg_stage_4.setNominalCapacity(0.4) end # Add stages to heating coil mau_htg_coil.addStage(mau_htg_stage_1) mau_htg_coil.addStage(mau_htg_stage_2) mau_htg_coil.addStage(mau_htg_stage_3) mau_htg_coil.addStage(mau_htg_stage_4) # TODO: other fuel-fired heating coil types? (not available in OpenStudio/E+ - may need to play with efficiency to mimic other fuel types) # Set up DX cooling coil mau_clg_coil = OpenStudio::Model::CoilCoolingDXMultiSpeed.new(model) mau_clg_coil.setFuelType('Electricity') mau_clg_stage_1 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) mau_clg_stage_2 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) mau_clg_stage_3 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) mau_clg_stage_4 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) mau_clg_coil.addStage(mau_clg_stage_1) mau_clg_coil.addStage(mau_clg_stage_2) mau_clg_coil.addStage(mau_clg_stage_3) mau_clg_coil.addStage(mau_clg_stage_4) air_to_air_heatpump = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed.new(model, mau_fan, mau_htg_coil, mau_clg_coil, mau_supplemental_htg_coil) # air_to_air_heatpump.setName("#{zone.name} ASHP") air_to_air_heatpump.setControllingZoneorThermostatLocation(zones[1]) air_to_air_heatpump.(always_on) air_to_air_heatpump.setNumberofSpeedsforHeating(4) air_to_air_heatpump.setNumberofSpeedsforCooling(4) # oa_controller oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) # oa_controller.setEconomizerControlType("DifferentialEnthalpy") # oa_system oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone supply_inlet_node = mau_air_loop.supplyInletNode air_to_air_heatpump.addToNode(supply_inlet_node) oa_system.addToNode(supply_inlet_node) end # Create MAU # Create a PTAC for each zone: # PTAC DX Cooling with electric heating coil; electric heating coil is always off # TO DO: need to apply this system to space types: # (1) data processing area: control room, data centre # when cooling capacity <= 20kW and # (2) residential/accommodation: murb, hotel/motel guest room # when building/space heated only (this as per NECB; apply to # all for initial work? CAN-QUEST limitation) # TO DO: PTAC characteristics: sizing, fan schedules, temperature setpoints, interaction with MAU zones.each do |zone| # Zone sizing temperature sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) # Set up PTAC heating coil; apply always off schedule # htg_coil_elec = OpenStudio::Model::CoilHeatingElectric.new(model,always_on) htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_off) # Set up PTAC DX coil with NECB performance curve characteristics; clg_coil = BTAP::Resources::HVAC::Plant.add_onespeed_DX_coil(model, always_on) # Set up PTAC constant volume supply fan fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) fan.setPressureRise(640) ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model, always_on, fan, htg_coil, clg_coil) ptac.setName("#{zone.name} PTAC") ptac.addToThermalZone(zone) # add zone baseboards if baseboard_type == 'Electric' # zone_elec_baseboard = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model) zone_elec_baseboard = BTAP::Resources::HVAC::Plant.add_elec_baseboard(model) zone_elec_baseboard.addToThermalZone(zone) end if baseboard_type == 'Hot Water' baseboard_coil = BTAP::Resources::HVAC::Plant.add_hw_baseboard_coil(model) # Connect baseboard coil to hot water loop hw_loop.addDemandBranchForComponent(baseboard_coil) zone_baseboard = BTAP::Resources::HVAC::ZoneEquipment.add_zone_baseboard_convective_water(model, always_on, baseboard_coil) # add zone_baseboard to zone zone_baseboard.addToThermalZone(zone) end # # Create a diffuser and attach the zone/diffuser pair to the MAU air loop, if applicable if mau == true diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on) mau_air_loop.addBranchForZone(zone, diffuser.to_StraightComponent) end # components for MAU end # of zone loop return true end |
#add_sys2_FPFC_sys5_TPFC(model, zones, boiler_fueltype, chiller_type, fan_coil_type, mua_cooling_type, hw_loop) ⇒ Object
sys1_unitary_ac_baseboard_heating
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1588 def add_sys2_FPFC_sys5_TPFC(model, zones, boiler_fueltype, chiller_type, fan_coil_type, mua_cooling_type, hw_loop) # System Type 2: FPFC or System 5: TPFC # This measure creates: # -a four pipe or a two pipe fan coil unit for each zone in the building; # -a make up air-unit to provide ventilation to each zone; # -a heating loop, cooling loop and condenser loop to serve four pipe fan coil units # Arguments: # boiler_fueltype: "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" # chiller_type: "Scroll";"Centrifugal";"Rotary Screw";"Reciprocating" # mua_cooling_type: make-up air unit cooling type "DX";"Hydronic" # fan_coil_type options are "TPFC" or "FPFC" # TODO: Add arguments as needed when the sizing routine is finalized. For example we will need to know the # required size of the boilers to decide on how many units are needed based on NECB rules. always_on = model.alwaysOnDiscreteSchedule # schedule for two-pipe fan coil operation twenty_four_hrs = OpenStudio::Time.new(0, 24, 0, 0) # Heating coil availability schedule for tpfc tpfc_htg_availability_sch = OpenStudio::Model::ScheduleRuleset.new(model) tpfc_htg_availability_sch.setName('tpfc_htg_availability') # Cooling coil availability schedule for tpfc tpfc_clg_availability_sch = OpenStudio::Model::ScheduleRuleset.new(model) tpfc_clg_availability_sch.setName('tpfc_clg_availability') istart_month = [1, 7, 11] istart_day = [1, 1, 1] iend_month = [6, 10, 12] iend_day = [30, 31, 31] sch_htg_value = [1, 0, 1] sch_clg_value = [0, 1, 0] for i in 0..2 tpfc_htg_availability_sch_rule = OpenStudio::Model::ScheduleRule.new(tpfc_htg_availability_sch) tpfc_htg_availability_sch_rule.setName('tpfc_htg_availability_sch_rule') tpfc_htg_availability_sch_rule.setStartDate(model.getYearDescription.makeDate(istart_month[i], istart_day[i])) tpfc_htg_availability_sch_rule.setEndDate(model.getYearDescription.makeDate(iend_month[i], iend_day[i])) tpfc_htg_availability_sch_rule.setApplySunday(true) tpfc_htg_availability_sch_rule.setApplyMonday(true) tpfc_htg_availability_sch_rule.setApplyTuesday(true) tpfc_htg_availability_sch_rule.setApplyWednesday(true) tpfc_htg_availability_sch_rule.setApplyThursday(true) tpfc_htg_availability_sch_rule.setApplyFriday(true) tpfc_htg_availability_sch_rule.setApplySaturday(true) day_schedule = tpfc_htg_availability_sch_rule.daySchedule day_schedule.setName('tpfc_htg_availability_sch_rule_day') day_schedule.addValue(twenty_four_hrs, sch_htg_value[i]) tpfc_clg_availability_sch_rule = OpenStudio::Model::ScheduleRule.new(tpfc_clg_availability_sch) tpfc_clg_availability_sch_rule.setName('tpfc_clg_availability_sch_rule') tpfc_clg_availability_sch_rule.setStartDate(model.getYearDescription.makeDate(istart_month[i], istart_day[i])) tpfc_clg_availability_sch_rule.setEndDate(model.getYearDescription.makeDate(iend_month[i], iend_day[i])) tpfc_clg_availability_sch_rule.setApplySunday(true) tpfc_clg_availability_sch_rule.setApplyMonday(true) tpfc_clg_availability_sch_rule.setApplyTuesday(true) tpfc_clg_availability_sch_rule.setApplyWednesday(true) tpfc_clg_availability_sch_rule.setApplyThursday(true) tpfc_clg_availability_sch_rule.setApplyFriday(true) tpfc_clg_availability_sch_rule.setApplySaturday(true) day_schedule = tpfc_clg_availability_sch_rule.daySchedule day_schedule.setName('tpfc_clg_availability_sch_rule_day') day_schedule.addValue(twenty_four_hrs, sch_clg_value[i]) end # Create a chilled water loop chw_loop = OpenStudio::Model::PlantLoop.new(model) chiller1, chiller2 = BTAP::Resources::HVAC::HVACTemplates::NECB2011.setup_chw_loop_with_components(model, chw_loop, chiller_type) # Create a condenser Loop cw_loop = OpenStudio::Model::PlantLoop.new(model) ctower = BTAP::Resources::HVAC::HVACTemplates::NECB2011.setup_cw_loop_with_components(model, cw_loop, chiller1, chiller2) # Set up make-up air unit for ventilation # TO DO: Need to investigate characteristics of make-up air unit for NECB reference # and define them here air_loop = OpenStudio::Model::AirLoopHVAC.new(model) air_loop.setName('Make-up air unit') # When an air_loop is contructed, its constructor creates a sizing:system object # the default sizing:system constructor makes a system:sizing object # appropriate for a multizone VAV system # this systems is a constant volume system with no VAV terminals, # and therfore needs different default settings air_loop_sizing = air_loop.sizingSystem # TODO units air_loop_sizing.setTypeofLoadtoSizeOn('Sensible') air_loop_sizing.autosizeDesignOutdoorAirFlowRate air_loop_sizing.setMinimumSystemAirFlowRatio(1.0) air_loop_sizing.setPreheatDesignTemperature(7.0) air_loop_sizing.setPreheatDesignHumidityRatio(0.008) air_loop_sizing.setPrecoolDesignTemperature(13.0) air_loop_sizing.setPrecoolDesignHumidityRatio(0.008) air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(13.0) air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(13.1) air_loop_sizing.setSizingOption('NonCoincident') air_loop_sizing.setAllOutdoorAirinCooling(false) air_loop_sizing.setAllOutdoorAirinHeating(false) air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.008) air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.008) air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay') air_loop_sizing.setCoolingDesignAirFlowRate(0.0) air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay') air_loop_sizing.setHeatingDesignAirFlowRate(0.0) air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum') fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) # Assume direct-fired gas heating coil for now; need to add logic # to set up hydronic or electric coil depending on proposed? htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on) # Add DX or hydronic cooling coil if mua_cooling_type == 'DX' clg_coil = BTAP::Resources::HVAC::Plant.add_onespeed_DX_coil(model, tpfc_clg_availability_sch) elsif mua_cooling_type == 'Hydronic' clg_coil = OpenStudio::Model::CoilCoolingWater.new(model, tpfc_clg_availability_sch) chw_loop.addDemandBranchForComponent(clg_coil) end # does MAU have an economizer? oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) # oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model,oa_controller) oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone supply_inlet_node = air_loop.supplyInletNode fan.addToNode(supply_inlet_node) htg_coil.addToNode(supply_inlet_node) clg_coil.addToNode(supply_inlet_node) oa_system.addToNode(supply_inlet_node) # Add a setpoint manager single zone reheat to control the # supply air temperature based on the needs of default zone (OpenStudio picks one) # TO DO: need to have method to pick appropriate control zone? setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model) setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(13.0) setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(13.1) setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode) # Set up FC (ZoneHVAC,cooling coil, heating coil, fan) in each zone zones.each do |zone| # Zone sizing temperature sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) # fc supply fan fc_fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) if fan_coil_type == 'FPFC' # heating coil fc_htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on) # cooling coil fc_clg_coil = OpenStudio::Model::CoilCoolingWater.new(model, always_on) elsif fan_coil_type == 'TPFC' # heating coil fc_htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, tpfc_htg_availability_sch) # cooling coil fc_clg_coil = OpenStudio::Model::CoilCoolingWater.new(model, tpfc_clg_availability_sch) end # connect heating coil to hot water loop hw_loop.addDemandBranchForComponent(fc_htg_coil) # connect cooling coil to chilled water loop chw_loop.addDemandBranchForComponent(fc_clg_coil) zone_fc = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model, always_on, fc_fan, fc_clg_coil, fc_htg_coil) zone_fc.addToThermalZone(zone) # Create a diffuser and attach the zone/diffuser pair to the air loop (make-up air unit) diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on) air_loop.addBranchForZone(zone, diffuser.to_StraightComponent) end # zone loop end |
#add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_multi_speed(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) ⇒ Object
end add_sys3_single_zone_packaged_rooftop_unit_with_baseboard_heating_single_speed
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1919 def add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_multi_speed(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) # System Type 3: PSZ-AC # This measure creates: # -a constant volume packaged single-zone A/C unit # for each zone in the building; DX cooling with # heating coil: fuel-fired or electric, depending on argument heating_coil_type # heating_coil_type choices are "Electric", "Gas", "DX" # zone baseboards: hot water or electric, depending on argument baseboard_type # baseboard_type choices are "Hot Water" or "Electric" # boiler_fueltype choices match OS choices for Boiler component fuel type, i.e. # "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" always_on = model.alwaysOnDiscreteSchedule # TODO: Heating and cooling temperature set point schedules are set somewhere else # TODO: For now fetch the schedules and use them in setting up the heat pump system # TODO: Later on these schedules need to be passed on to this method htg_temp_sch = nil clg_temp_sch = nil zones.each do |izone| if izone.thermostat.is_initialized zone_thermostat = izone.thermostat.get if zone_thermostat.to_ThermostatSetpointDualSetpoint.is_initialized dual_thermostat = zone_thermostat.to_ThermostatSetpointDualSetpoint.get htg_temp_sch = dual_thermostat.heatingSetpointTemperatureSchedule.get clg_temp_sch = dual_thermostat.coolingSetpointTemperatureSchedule.get break end end end zones.each do |zone| air_loop = OpenStudio::Model::AirLoopHVAC.new(model) air_loop.setName("#{zone.name} NECB System 3 PSZ") # When an air_loop is constructed, its constructor creates a sizing:system object # the default sizing:system constructor makes a system:sizing object # appropriate for a multizone VAV system # this systems is a constant volume system with no VAV terminals, # and therfore needs different default settings air_loop_sizing = air_loop.sizingSystem # TODO units air_loop_sizing.setTypeofLoadtoSizeOn('Sensible') air_loop_sizing.autosizeDesignOutdoorAirFlowRate air_loop_sizing.setMinimumSystemAirFlowRatio(1.0) air_loop_sizing.setPreheatDesignTemperature(7.0) air_loop_sizing.setPreheatDesignHumidityRatio(0.008) air_loop_sizing.setPrecoolDesignTemperature(13.0) air_loop_sizing.setPrecoolDesignHumidityRatio(0.008) air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(13.0) air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(43.0) air_loop_sizing.setSizingOption('NonCoincident') air_loop_sizing.setAllOutdoorAirinCooling(false) air_loop_sizing.setAllOutdoorAirinHeating(false) air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085) air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080) air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay') air_loop_sizing.setCoolingDesignAirFlowRate(0.0) air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay') air_loop_sizing.setHeatingDesignAirFlowRate(0.0) air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum') # Zone sizing temperature sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) staged_thermostat = OpenStudio::Model::ZoneControlThermostatStagedDualSetpoint.new(model) staged_thermostat.setHeatingTemperatureSetpointSchedule(htg_temp_sch) staged_thermostat.setNumberofHeatingStages(4) staged_thermostat.setCoolingTemperatureSetpointBaseSchedule(clg_temp_sch) staged_thermostat.setNumberofCoolingStages(4) zone.setThermostat(staged_thermostat) # Multi-stage gas heating coil if heating_coil_type == 'Gas' || heating_coil_type == 'Electric' htg_coil = OpenStudio::Model::CoilHeatingGasMultiStage.new(model) htg_stage_1 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) htg_stage_2 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) htg_stage_3 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) htg_stage_4 = OpenStudio::Model::CoilHeatingGasMultiStageStageData.new(model) if heating_coil_type == 'Gas' supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on) elsif heating_coil_type == 'Electric' supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) htg_stage_1.setNominalCapacity(0.1) htg_stage_2.setNominalCapacity(0.2) htg_stage_3.setNominalCapacity(0.3) htg_stage_4.setNominalCapacity(0.4) end # Multi-Stage DX or Electric heating coil elsif heating_coil_type == 'DX' htg_coil = OpenStudio::Model::CoilHeatingDXMultiSpeed.new(model) htg_stage_1 = OpenStudio::Model::CoilHeatingDXMultiSpeedStageData.new(model) htg_stage_2 = OpenStudio::Model::CoilHeatingDXMultiSpeedStageData.new(model) htg_stage_3 = OpenStudio::Model::CoilHeatingDXMultiSpeedStageData.new(model) htg_stage_4 = OpenStudio::Model::CoilHeatingDXMultiSpeedStageData.new(model) supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) sizing_zone.setZoneHeatingSizingFactor(1.3) sizing_zone.setZoneCoolingSizingFactor(1.0) else raise("#{heating_coil_type} is not a valid heating coil type.)") end # Add stages to heating coil htg_coil.addStage(htg_stage_1) htg_coil.addStage(htg_stage_2) htg_coil.addStage(htg_stage_3) htg_coil.addStage(htg_stage_4) # TODO: other fuel-fired heating coil types? (not available in OpenStudio/E+ - may need to play with efficiency to mimic other fuel types) # Set up DX cooling coil clg_coil = OpenStudio::Model::CoilCoolingDXMultiSpeed.new(model) clg_coil.setFuelType('Electricity') clg_stage_1 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) clg_stage_2 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) clg_stage_3 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) clg_stage_4 = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model) clg_coil.addStage(clg_stage_1) clg_coil.addStage(clg_stage_2) clg_coil.addStage(clg_stage_3) clg_coil.addStage(clg_stage_4) # oa_controller oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) # oa_system oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone supply_inlet_node = air_loop.supplyInletNode air_to_air_heatpump = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed.new(model, fan, htg_coil, clg_coil, supplemental_htg_coil) air_to_air_heatpump.setName("#{zone.name} ASHP") air_to_air_heatpump.setControllingZoneorThermostatLocation(zone) air_to_air_heatpump.(always_on) air_to_air_heatpump.addToNode(supply_inlet_node) air_to_air_heatpump.setNumberofSpeedsforHeating(4) air_to_air_heatpump.setNumberofSpeedsforCooling(4) oa_system.addToNode(supply_inlet_node) # Create a diffuser and attach the zone/diffuser pair to the air loop # diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model,always_on) diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on) air_loop.addBranchForZone(zone, diffuser.to_StraightComponent) if baseboard_type == 'Electric' # zone_elec_baseboard = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model) zone_elec_baseboard = BTAP::Resources::HVAC::Plant.add_elec_baseboard(model) zone_elec_baseboard.addToThermalZone(zone) end if baseboard_type == 'Hot Water' baseboard_coil = BTAP::Resources::HVAC::Plant.add_hw_baseboard_coil(model) # Connect baseboard coil to hot water loop hw_loop.addDemandBranchForComponent(baseboard_coil) zone_baseboard = BTAP::Resources::HVAC::ZoneEquipment.add_zone_baseboard_convective_water(model, always_on, baseboard_coil) # add zone_baseboard to zone zone_baseboard.addToThermalZone(zone) end end # zone loop return true end |
#add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_single_speed(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) ⇒ Object
add_sys2_FPFC_sys5_TPFC
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1779 def add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_single_speed(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) # System Type 3: PSZ-AC # This measure creates: # -a constant volume packaged single-zone A/C unit # for each zone in the building; DX cooling with # heating coil: fuel-fired or electric, depending on argument heating_coil_type # heating_coil_type choices are "Electric", "Gas", "DX" # zone baseboards: hot water or electric, depending on argument baseboard_type # baseboard_type choices are "Hot Water" or "Electric" # boiler_fueltype choices match OS choices for Boiler component fuel type, i.e. # "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" always_on = model.alwaysOnDiscreteSchedule zones.each do |zone| air_loop = OpenStudio::Model::AirLoopHVAC.new(model) air_loop.setName("#{zone.name} NECB System 3 PSZ") # When an air_loop is constructed, its constructor creates a sizing:system object # the default sizing:system constructor makes a system:sizing object # appropriate for a multizone VAV system # this systems is a constant volume system with no VAV terminals, # and therfore needs different default settings air_loop_sizing = air_loop.sizingSystem # TODO units air_loop_sizing.setTypeofLoadtoSizeOn('Sensible') air_loop_sizing.autosizeDesignOutdoorAirFlowRate air_loop_sizing.setMinimumSystemAirFlowRatio(1.0) air_loop_sizing.setPreheatDesignTemperature(7.0) air_loop_sizing.setPreheatDesignHumidityRatio(0.008) air_loop_sizing.setPrecoolDesignTemperature(13.0) air_loop_sizing.setPrecoolDesignHumidityRatio(0.008) air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(13.0) air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(43) air_loop_sizing.setSizingOption('NonCoincident') air_loop_sizing.setAllOutdoorAirinCooling(false) air_loop_sizing.setAllOutdoorAirinHeating(false) air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085) air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080) air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay') air_loop_sizing.setCoolingDesignAirFlowRate(0.0) air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay') air_loop_sizing.setHeatingDesignAirFlowRate(0.0) air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum') # Zone sizing temperature sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) case heating_coil_type when 'Electric' # electric coil htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) when 'Gas' htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on) when 'DX' htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model) supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(-10.0) sizing_zone.setZoneHeatingSizingFactor(1.3) sizing_zone.setZoneCoolingSizingFactor(1.0) else raise("#{heating_coil_type} is not a valid heating coil type.)") end # TO DO: other fuel-fired heating coil types? (not available in OpenStudio/E+ - may need to play with efficiency to mimic other fuel types) # Set up DX coil with NECB performance curve characteristics; clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model) # oa_controller oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) # oa_system oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone supply_inlet_node = air_loop.supplyInletNode # fan.addToNode(supply_inlet_node) # supplemental_htg_coil.addToNode(supply_inlet_node) if heating_coil_type == "DX" # htg_coil.addToNode(supply_inlet_node) # clg_coil.addToNode(supply_inlet_node) # oa_system.addToNode(supply_inlet_node) if heating_coil_type == 'DX' air_to_air_heatpump = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(model, always_on, fan, htg_coil, clg_coil, supplemental_htg_coil) air_to_air_heatpump.setName("#{zone.name} ASHP") air_to_air_heatpump.setControllingZone(zone) air_to_air_heatpump.(always_on) air_to_air_heatpump.addToNode(supply_inlet_node) else fan.addToNode(supply_inlet_node) htg_coil.addToNode(supply_inlet_node) clg_coil.addToNode(supply_inlet_node) end oa_system.addToNode(supply_inlet_node) # Add a setpoint manager single zone reheat to control the # supply air temperature based on the needs of this zone setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model) setpoint_mgr_single_zone_reheat.setControlZone(zone) setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(13) setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(43) setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode) # Create a diffuser and attach the zone/diffuser pair to the air loop # diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model,always_on) diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on) air_loop.addBranchForZone(zone, diffuser.to_StraightComponent) if baseboard_type == 'Electric' # zone_elec_baseboard = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model) zone_elec_baseboard = BTAP::Resources::HVAC::Plant.add_elec_baseboard(model) zone_elec_baseboard.addToThermalZone(zone) end if baseboard_type == 'Hot Water' baseboard_coil = BTAP::Resources::HVAC::Plant.add_hw_baseboard_coil(model) # Connect baseboard coil to hot water loop hw_loop.addDemandBranchForComponent(baseboard_coil) zone_baseboard = BTAP::Resources::HVAC::ZoneEquipment.add_zone_baseboard_convective_water(model, always_on, baseboard_coil) # add zone_baseboard to zone zone_baseboard.addToThermalZone(zone) end end # zone loop return true end |
#add_sys4_single_zone_make_up_air_unit_with_baseboard_heating(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) ⇒ Object
end add_sys3_single_zone_packaged_rooftop_unit_with_baseboard_heating_multi_speed
2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2097 def add_sys4_single_zone_make_up_air_unit_with_baseboard_heating(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, hw_loop) # System Type 4: PSZ-AC # This measure creates: # -a constant volume packaged single-zone A/C unit # for each zone in the building; DX cooling with # heating coil: fuel-fired or electric, depending on argument heating_coil_type # heating_coil_type choices are "Electric", "Gas" # zone baseboards: hot water or electric, depending on argument baseboard_type # baseboard_type choices are "Hot Water" or "Electric" # boiler_fueltype choices match OS choices for Boiler component fuel type, i.e. # "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" # NOTE: This is the same as system type 3 (single zone make-up air unit and single zone rooftop unit are both PSZ systems) # SHOULD WE COMBINE sys3 and sys4 into one script? always_on = model.alwaysOnDiscreteSchedule # Create a PSZ for each zone # TO DO: need to apply this system to space types: # (1) automotive area: repair/parking garage, fire engine room, indoor truck bay # (2) supermarket/food service: food preparation with kitchen hood/vented appliance # (3) warehouse area (non-refrigerated spaces) zones.each do |zone| air_loop = OpenStudio::Model::AirLoopHVAC.new(model) air_loop.setName("#{zone.name} NECB System 4 PSZ") # When an air_loop is constructed, its constructor creates a sizing:system object # the default sizing:system constructor makes a system:sizing object # appropriate for a multizone VAV system # this systems is a constant volume system with no VAV terminals, # and therfore needs different default settings air_loop_sizing = air_loop.sizingSystem # TODO units air_loop_sizing.setTypeofLoadtoSizeOn('Sensible') air_loop_sizing.autosizeDesignOutdoorAirFlowRate air_loop_sizing.setMinimumSystemAirFlowRatio(1.0) air_loop_sizing.setPreheatDesignTemperature(7.0) air_loop_sizing.setPreheatDesignHumidityRatio(0.008) air_loop_sizing.setPrecoolDesignTemperature(13.0) air_loop_sizing.setPrecoolDesignHumidityRatio(0.008) air_loop_sizing.setCentralCoolingDesignSupplyAirTemperature(13.0) air_loop_sizing.setCentralHeatingDesignSupplyAirTemperature(43.0) air_loop_sizing.setSizingOption('NonCoincident') air_loop_sizing.setAllOutdoorAirinCooling(false) air_loop_sizing.setAllOutdoorAirinHeating(false) air_loop_sizing.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085) air_loop_sizing.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080) air_loop_sizing.setCoolingDesignAirFlowMethod('DesignDay') air_loop_sizing.setCoolingDesignAirFlowRate(0.0) air_loop_sizing.setHeatingDesignAirFlowMethod('DesignDay') air_loop_sizing.setHeatingDesignAirFlowRate(0.0) air_loop_sizing.setSystemOutdoorAirMethod('ZoneSum') # Zone sizing temperature sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) fan = OpenStudio::Model::FanConstantVolume.new(model, always_on) if heating_coil_type == 'Electric' # electric coil htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) end if heating_coil_type == 'Gas' htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on) end # TO DO: other fuel-fired heating coil types? (not available in OpenStudio/E+ - may need to play with efficiency to mimic other fuel types) # Set up DX coil with NECB performance curve characteristics; clg_coil = BTAP::Resources::HVAC::Plant.add_onespeed_DX_coil(model, always_on) # oa_controller oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) # oa_system oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone supply_inlet_node = air_loop.supplyInletNode fan.addToNode(supply_inlet_node) htg_coil.addToNode(supply_inlet_node) clg_coil.addToNode(supply_inlet_node) oa_system.addToNode(supply_inlet_node) # Add a setpoint manager single zone reheat to control the # supply air temperature based on the needs of this zone setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model) setpoint_mgr_single_zone_reheat.setControlZone(zone) setpoint_mgr_single_zone_reheat.setMinimumSupplyAirTemperature(13.0) setpoint_mgr_single_zone_reheat.setMaximumSupplyAirTemperature(43.0) setpoint_mgr_single_zone_reheat.addToNode(air_loop.supplyOutletNode) # Create sensible heat exchanger # heat_exchanger = BTAP::Resources::HVAC::Plant::add_hrv(model) # heat_exchanger.setSensibleEffectivenessat100HeatingAirFlow(0.5) # heat_exchanger.setSensibleEffectivenessat75HeatingAirFlow(0.5) # heat_exchanger.setSensibleEffectivenessat100CoolingAirFlow(0.5) # heat_exchanger.setSensibleEffectivenessat75CoolingAirFlow(0.5) # heat_exchanger.setLatentEffectivenessat100HeatingAirFlow(0.0) # heat_exchanger.setLatentEffectivenessat75HeatingAirFlow(0.0) # heat_exchanger.setLatentEffectivenessat100CoolingAirFlow(0.0) # heat_exchanger.setLatentEffectivenessat75CoolingAirFlow(0.0) # heat_exchanger.setSupplyAirOutletTemperatureControl(false) # # Connect heat exchanger # oa_node = oa_system.outboardOANode # heat_exchanger.addToNode(oa_node.get) # Create a diffuser and attach the zone/diffuser pair to the air loop # diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model,always_on) diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on) air_loop.addBranchForZone(zone, diffuser.to_StraightComponent) if baseboard_type == 'Electric' # zone_elec_baseboard = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model) zone_elec_baseboard = BTAP::Resources::HVAC::Plant.add_elec_baseboard(model) zone_elec_baseboard.addToThermalZone(zone) end if baseboard_type == 'Hot Water' baseboard_coil = BTAP::Resources::HVAC::Plant.add_hw_baseboard_coil(model) # Connect baseboard coil to hot water loop hw_loop.addDemandBranchForComponent(baseboard_coil) zone_baseboard = BTAP::Resources::HVAC::ZoneEquipment.add_zone_baseboard_convective_water(model, always_on, baseboard_coil) # add zone_baseboard to zone zone_baseboard.addToThermalZone(zone) end end # zone loop return true end |
#add_sys6_multi_zone_built_up_system_with_baseboard_heating(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, chiller_type, fan_type, hw_loop) ⇒ Object
end add_sys4_single_zone_make_up_air_unit_with_baseboard_heating
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2240 def add_sys6_multi_zone_built_up_system_with_baseboard_heating(model, zones, boiler_fueltype, heating_coil_type, baseboard_type, chiller_type, fan_type, hw_loop) # System Type 6: VAV w/ Reheat # This measure creates: # a single hot water loop with a natural gas or electric boiler or for the building # a single chilled water loop with water cooled chiller for the building # a single condenser water loop for heat rejection from the chiller # a VAV system w/ hot water or electric heating, chilled water cooling, and # hot water or electric reheat for each story of the building # Arguments: # "boiler_fueltype" choices match OS choices for boiler fuel type: # "NaturalGas","Electricity","PropaneGas","FuelOil#1","FuelOil#2","Coal","Diesel","Gasoline","OtherFuel1" # "heating_coil_type": "Electric" or "Hot Water" # "baseboard_type": "Electric" and "Hot Water" # "chiller_type": "Scroll";"Centrifugal";""Screw";"Reciprocating" # "fan_type": "AF_or_BI_rdg_fancurve";"AF_or_BI_inletvanes";"fc_inletvanes";"var_speed_drive" always_on = model.alwaysOnDiscreteSchedule # Chilled Water Plant chw_loop = OpenStudio::Model::PlantLoop.new(model) chiller1, chiller2 = BTAP::Resources::HVAC::HVACTemplates::NECB2011.setup_chw_loop_with_components(model, chw_loop, chiller_type) # Condenser System cw_loop = OpenStudio::Model::PlantLoop.new(model) ctower = BTAP::Resources::HVAC::HVACTemplates::NECB2011.setup_cw_loop_with_components(model, cw_loop, chiller1, chiller2) # Make a Packaged VAV w/ PFP Boxes for each story of the building model.getBuildingStorys.sort.each do |story| unless (BTAP::Geometry::BuildingStoreys.get_zones_from_storey(story) & zones).empty? air_loop = OpenStudio::Model::AirLoopHVAC.new(model) air_loop.setName('VAV with Reheat') sizing_system = air_loop.sizingSystem sizing_system.setCentralCoolingDesignSupplyAirTemperature(13.0) sizing_system.setCentralHeatingDesignSupplyAirTemperature(13.1) sizing_system.autosizeDesignOutdoorAirFlowRate sizing_system.setMinimumSystemAirFlowRatio(0.3) sizing_system.setPreheatDesignTemperature(7.0) sizing_system.setPreheatDesignHumidityRatio(0.008) sizing_system.setPrecoolDesignTemperature(13.0) sizing_system.setPrecoolDesignHumidityRatio(0.008) sizing_system.setSizingOption('NonCoincident') sizing_system.setAllOutdoorAirinCooling(false) sizing_system.setAllOutdoorAirinHeating(false) sizing_system.setCentralCoolingDesignSupplyAirHumidityRatio(0.0085) sizing_system.setCentralHeatingDesignSupplyAirHumidityRatio(0.0080) sizing_system.setCoolingDesignAirFlowMethod('DesignDay') sizing_system.setCoolingDesignAirFlowRate(0.0) sizing_system.setHeatingDesignAirFlowMethod('DesignDay') sizing_system.setHeatingDesignAirFlowRate(0.0) sizing_system.setSystemOutdoorAirMethod('ZoneSum') fan = OpenStudio::Model::FanVariableVolume.new(model, always_on) if heating_coil_type == 'Hot Water' htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on) hw_loop.addDemandBranchForComponent(htg_coil) end if heating_coil_type == 'Electric' htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) end clg_coil = OpenStudio::Model::CoilCoolingWater.new(model, always_on) chw_loop.addDemandBranchForComponent(clg_coil) oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model) oa_system = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_controller) # Add the components to the air loop # in order from closest to zone to furthest from zone # TODO: still need to define the return fan (tried to access the air loop "returnAirNode" without success) # TODO: The OS sdk indicates that this keyword should be active but I get a "Not implemented" error when I # TODO: try to access it through "air_loop.returnAirNode" supply_inlet_node = air_loop.supplyInletNode supply_outlet_node = air_loop.supplyOutletNode fan.addToNode(supply_inlet_node) htg_coil.addToNode(supply_inlet_node) clg_coil.addToNode(supply_inlet_node) oa_system.addToNode(supply_inlet_node) # return_inlet_node = air_loop.returnAirNode # Add a setpoint manager to control the # supply air to a constant temperature sat_c = 13.0 sat_sch = OpenStudio::Model::ScheduleRuleset.new(model) sat_sch.setName('Supply Air Temp') sat_sch.defaultDaySchedule.setName('Supply Air Temp Default') sat_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), sat_c) sat_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, sat_sch) sat_stpt_manager.addToNode(supply_outlet_node) # TO-do ask Kamel about zonal assignments per storey. # Make a VAV terminal with HW reheat for each zone on this story that is in intersection with the zones array. # and hook the reheat coil to the HW loop (BTAP::Geometry::BuildingStoreys.get_zones_from_storey(story) & zones).each do |zone| # Zone sizing parameters sizing_zone = zone.sizingZone sizing_zone.setZoneCoolingDesignSupplyAirTemperature(13.0) sizing_zone.setZoneHeatingDesignSupplyAirTemperature(43.0) sizing_zone.setZoneCoolingSizingFactor(1.1) sizing_zone.setZoneHeatingSizingFactor(1.3) if heating_coil_type == 'Hot Water' reheat_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on) hw_loop.addDemandBranchForComponent(reheat_coil) elsif heating_coil_type == 'Electric' reheat_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on) end vav_terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(model, always_on, reheat_coil) air_loop.addBranchForZone(zone, vav_terminal.to_StraightComponent) # NECB2011 minimum zone airflow setting min_flow_rate = 0.002 * zone.floorArea vav_terminal.setFixedMinimumAirFlowRate(min_flow_rate) vav_terminal.setMaximumReheatAirTemperature(43.0) vav_terminal.setDamperHeatingAction('Normal') # Set zone baseboards if baseboard_type == 'Electric' zone_elec_baseboard = BTAP::Resources::HVAC::Plant.add_elec_baseboard(model) zone_elec_baseboard.addToThermalZone(zone) end if baseboard_type == 'Hot Water' baseboard_coil = BTAP::Resources::HVAC::Plant.add_hw_baseboard_coil(model) # Connect baseboard coil to hot water loop hw_loop.addDemandBranchForComponent(baseboard_coil) zone_baseboard = BTAP::Resources::HVAC::ZoneEquipment.add_zone_baseboard_convective_water(model, always_on, baseboard_coil) # add zone_baseboard to zone zone_baseboard.addToThermalZone(zone) end end end end # next story # for debugging # puts "end add_sys6_multi_zone_built_up_with_baseboard_heating" return true end |
#air_loop_hvac_apply_economizer_integration(air_loop_hvac, climate_zone) ⇒ Bool
this method assumes you previously checked that an economizer is required at all via #economizer_required?
NECB always requires an integrated economizer (NoLockout); as per 5.2.2.8(3) this means that compressor allowed to turn on when economizer is open
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 72 def air_loop_hvac_apply_economizer_integration(air_loop_hvac, climate_zone) # Get the OA system and OA controller oa_sys = air_loop_hvac.airLoopHVACOutdoorAirSystem if oa_sys.is_initialized oa_sys = oa_sys.get else return false # No OA system end oa_control = oa_sys.getControllerOutdoorAir # Apply integrated economizer oa_control.setLockoutType('NoLockout') return true end |
#air_loop_hvac_apply_energy_recovery_ventilator(air_loop_hvac) ⇒ Bool
Add exception logic for systems serving parking garage, warehouse, or multifamily
Add an ERV to this airloop. Will be a rotary-type HX
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 268 def air_loop_hvac_apply_energy_recovery_ventilator(air_loop_hvac) # Get the oa system oa_system = nil if air_loop_hvac.airLoopHVACOutdoorAirSystem.is_initialized oa_system = air_loop_hvac.airLoopHVACOutdoorAirSystem.get else OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV cannot be added because the system has no OA intake.") return false end # Create an ERV erv = OpenStudio::Model::HeatExchangerAirToAirSensibleAndLatent.new(air_loop_hvac.model) erv.setName("#{air_loop_hvac.name} ERV") erv.setSensibleEffectivenessat100HeatingAirFlow(0.5) erv.setLatentEffectivenessat100HeatingAirFlow(0.5) erv.setSensibleEffectivenessat75HeatingAirFlow(0.5) erv.setLatentEffectivenessat75HeatingAirFlow(0.5) erv.setSensibleEffectivenessat100CoolingAirFlow(0.5) erv.setLatentEffectivenessat100CoolingAirFlow(0.5) erv.setSensibleEffectivenessat75CoolingAirFlow(0.5) erv.setLatentEffectivenessat75CoolingAirFlow(0.5) erv.setSupplyAirOutletTemperatureControl(true) erv.setHeatExchangerType('Rotary') erv.setFrostControlType('ExhaustOnly') erv.setEconomizerLockout(true) erv.setThresholdTemperature(-23.3) # -10F erv.setInitialDefrostTimeFraction(0.167) erv.setRateofDefrostTimeFractionIncrease(1.44) # Add the ERV to the OA system erv.addToNode(oa_system.outboardOANode.get) # Add a setpoint manager OA pretreat # to control the ERV spm_oa_pretreat = OpenStudio::Model::SetpointManagerOutdoorAirPretreat.new(air_loop_hvac.model) spm_oa_pretreat.setMinimumSetpointTemperature(-99.0) spm_oa_pretreat.setMaximumSetpointTemperature(99.0) spm_oa_pretreat.setMinimumSetpointHumidityRatio(0.00001) spm_oa_pretreat.setMaximumSetpointHumidityRatio(1.0) # Reference setpoint node and # Mixed air stream node are outlet # node of the OA system mixed_air_node = oa_system.mixedAirModelObject.get.to_Node.get spm_oa_pretreat.setReferenceSetpointNode(mixed_air_node) spm_oa_pretreat.setMixedAirStreamNode(mixed_air_node) # Outdoor air node is # the outboard OA node of teh OA system spm_oa_pretreat.setOutdoorAirStreamNode(oa_system.outboardOANode.get) # Return air node is the inlet # node of the OA system return_air_node = oa_system.returnAirModelObject.get.to_Node.get spm_oa_pretreat.setReturnAirStreamNode(return_air_node) # Attach to the outlet of the ERV erv_outlet = erv.primaryAirOutletModelObject.get.to_Node.get spm_oa_pretreat.addToNode(erv_outlet) # Apply the prototype Heat Exchanger power assumptions. heat_exchanger_air_to_air_sensible_and_latent_apply_prototype_nominal_electric_power(erv) # Determine if the system is a DOAS based on # whether there is 100% OA in heating and cooling sizing. is_doas = false sizing_system = air_loop_hvac.sizingSystem if sizing_system.allOutdoorAirinCooling && sizing_system.allOutdoorAirinHeating is_doas = true end # Set the bypass control type # If DOAS system, BypassWhenWithinEconomizerLimits # to disable ERV during economizing. # Otherwise, BypassWhenOAFlowGreaterThanMinimum # to disable ERV during economizing and when OA # is also greater than minimum. bypass_ctrl_type = if is_doas 'BypassWhenWithinEconomizerLimits' else 'BypassWhenOAFlowGreaterThanMinimum' end oa_system.getControllerOutdoorAir.setHeatRecoveryBypassControlType(bypass_ctrl_type) return true end |
#air_loop_hvac_apply_multizone_vav_outdoor_air_sizing(air_loop_hvac) ⇒ Object
NECB does not change damper positions
return [Bool] returns true if successful, false if not
13 14 15 16 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 13 def air_loop_hvac_apply_multizone_vav_outdoor_air_sizing(air_loop_hvac) # Do not change anything. return true end |
#air_loop_hvac_apply_single_zone_controls(air_loop_hvac, climate_zone) ⇒ Bool
NECB has no single zone air loop control requirements
417 418 419 420 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 417 def air_loop_hvac_apply_single_zone_controls(air_loop_hvac, climate_zone) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: No special economizer controls were modeled.") return true end |
#air_loop_hvac_apply_vav_damper_action(air_loop_hvac) ⇒ Bool
see if this impacts the sizing run.
Set the VAV damper control to single maximum or dual maximum control depending on the standard.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 369 def air_loop_hvac_apply_vav_damper_action(air_loop_hvac) damper_action = 'Single Maximum' # Interpret this as an EnergyPlus input damper_action_eplus = nil if damper_action == 'Single Maximum' damper_action_eplus = 'Normal' elsif damper_action == 'Dual Maximum' # EnergyPlus 8.7 changed the meaning of 'Reverse'. # For versions of OpenStudio using E+ 8.6 or lower damper_action_eplus = if air_loop_hvac.model.version < OpenStudio::VersionString.new('2.0.5') 'Reverse' # For versions of OpenStudio using E+ 8.7 or higher else 'ReverseWithLimits' end end # Set the control for any VAV reheat terminals # on this airloop. control_type_set = false air_loop_hvac.demandComponents.each do |equip| if equip.to_AirTerminalSingleDuctVAVReheat.is_initialized term = equip.to_AirTerminalSingleDuctVAVReheat.get # Dual maximum only applies to terminals with HW reheat coils if damper_action == 'Dual Maximum' if term.reheatCoil.to_CoilHeatingWater.is_initialized term.setDamperHeatingAction(damper_action_eplus) control_type_set = true end else term.setDamperHeatingAction(damper_action_eplus) control_type_set = true term.setMaximumFlowFractionDuringReheat(0.5) end end end if control_type_set OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: VAV damper action was set to #{damper_action} control.") end return true end |
#air_loop_hvac_demand_control_ventilation_required?(air_loop_hvac, climate_zone) ⇒ Bool
Add exception logic for systems that serve multifamily, parking garage, warehouse
Determine if demand control ventilation (DCV) is required for this air loop.
358 359 360 361 362 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 358 def air_loop_hvac_demand_control_ventilation_required?(air_loop_hvac, climate_zone) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{template} #{climate_zone}: #{air_loop_hvac.name}: DCV is not required for any system.") dcv_required = false return dcv_required end |
#air_loop_hvac_economizer_required?(air_loop_hvac) ⇒ Bool
Determine whether or not this system is required to have an economizer.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 22 def air_loop_hvac_economizer_required?(air_loop_hvac) economizer_required = false # need a better way to determine if an economizer is needed. return economizer_required if air_loop_hvac.name.to_s.include? 'Outpatient F1' # A big number of btu per hr as the minimum requirement infinity_btu_per_hr = 999_999_999_999 minimum_capacity_btu_per_hr = infinity_btu_per_hr # 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 # Determine the minimum capacity that requires an economizer minimum_capacity_btu_per_hr = 68_243 # NECB requires economizer for cooling cap > 20 kW # 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 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 return economizer_required end |
#air_loop_hvac_energy_recovery_ventilator_required?(air_loop_hvac, climate_zone) ⇒ Bool
Add exception logic for systems serving parking garage, warehouse, or multifamily
Check if ERV is required on this airloop.
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 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 258 259 260 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 93 def air_loop_hvac_energy_recovery_ventilator_required?(air_loop_hvac, climate_zone) # ERV Not Applicable for AHUs that serve # parking garage, warehouse, or multifamily # if space_types_served_names.include?('PNNL_Asset_Rating_Apartment_Space_Type') || # space_types_served_names.include?('PNNL_Asset_Rating_LowRiseApartment_Space_Type') || # space_types_served_names.include?('PNNL_Asset_Rating_ParkingGarage_Space_Type') || # space_types_served_names.include?('PNNL_Asset_Rating_Warehouse_Space_Type') # OpenStudio::logFree(OpenStudio::Info, "openstudio.standards.AirLoopHVAC", "For #{self.name}, ERV not applicable because it because it serves parking garage, warehouse, or multifamily.") # return false # end erv_required = nil # ERV not applicable for medical AHUs (AHU1 in Outpatient), per AIA 2001 - 7.31.D2. if air_loop_hvac.name.to_s.include? 'Outpatient F1' erv_required = false return erv_required end # ERV not applicable for medical AHUs, per AIA 2001 - 7.31.D2. if air_loop_hvac.name.to_s.include? 'VAV_ER' erv_required = false return erv_required elsif air_loop_hvac.name.to_s.include? 'VAV_OR' erv_required = false return erv_required end # ERV Not Applicable for AHUs that have DCV # or that have no 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 if controller_mv.demandControlledVentilation == true OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV not applicable because DCV enabled.") return false end else OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV not applicable because it has no OA intake.") return false 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 false 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 false 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 # The NECB2011 requirement is that systems with an exhaust heat content > 150 kW require an HRV # The calculation for this is done below, to modify erv_required # erv_cfm set to nil here as placeholder, will lead to erv_required = false erv_cfm = nil # Determine if an ERV is required # erv_required = nil if erv_cfm.nil? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV not required based on #{(pct_oa * 100).round}% OA flow, design supply air flow of #{dsn_flow_cfm.round}cfm, and climate zone #{climate_zone}.") erv_required = false elsif dsn_flow_cfm < erv_cfm OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV not required based on #{(pct_oa * 100).round}% OA flow, design supply air flow of #{dsn_flow_cfm.round}cfm, and climate zone #{climate_zone}. Does not exceed minimum flow requirement of #{erv_cfm}cfm.") erv_required = false else OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV required based on #{(pct_oa * 100).round}% OA flow, design supply air flow of #{dsn_flow_cfm.round}cfm, and climate zone #{climate_zone}. Exceeds minimum flow requirement of #{erv_cfm}cfm.") erv_required = true end # This code modifies erv_required for NECB2011 # Calculation of exhaust heat content and check whether it is > 150 kW # get all zones in the model zones = air_loop_hvac.thermalZones # initialize counters sum_zone_oa = 0.0 sum_zone_oa_times_heat_design_t = 0.0 # zone loop zones.each do |zone| # get design heat temperature for each zone; this is equivalent to design exhaust temperature heat_design_t = 21.0 zone_thermostat = zone.thermostat.get if zone_thermostat.to_ThermostatSetpointDualSetpoint.is_initialized dual_thermostat = zone_thermostat.to_ThermostatSetpointDualSetpoint.get htg_temp_sch = dual_thermostat.heatingSetpointTemperatureSchedule.get htg_temp_sch_ruleset = htg_temp_sch.to_ScheduleRuleset.get winter_dd_sch = htg_temp_sch_ruleset.winterDesignDaySchedule heat_design_t = winter_dd_sch.values.max end # initialize counter zone_oa = 0.0 # outdoor defined at space level; get OA flow for all spaces within zone spaces = zone.spaces # space loop spaces.each do |space| unless space.designSpecificationOutdoorAir.empty? # if empty, don't do anything outdoor_air = space.designSpecificationOutdoorAir.get # in bTAP, outdoor air specified as outdoor air per oa_flow_per_floor_area = outdoor_air.outdoorAirFlowperFloorArea oa_flow = oa_flow_per_floor_area * space.floorArea * zone.multiplier # oa flow for the space zone_oa += oa_flow # add up oa flow for all spaces to get zone air flow end end # space loop sum_zone_oa += zone_oa # sum of all zone oa flows to get system oa flow sum_zone_oa_times_heat_design_t += (zone_oa * heat_design_t) # calculated to get oa flow weighted average of design exhaust temperature end # zone loop # Calculate average exhaust temperature (oa flow weighted average) avg_exhaust_temp = sum_zone_oa_times_heat_design_t / sum_zone_oa # for debugging/testing # puts "average exhaust temp = #{avg_exhaust_temp}" # puts "sum_zone_oa = #{sum_zone_oa}" # Get January winter design temperature # get model weather file name weather_file = BTAP::Environment::WeatherFile.new(air_loop_hvac.model.weatherFile.get.path.get) # get winter(heating) design temp stored in array # Note that the NECB2011 specifies using the 2.5% january design temperature # The outdoor temperature used here is the 0.4% heating design temperature of the coldest month, available in stat file outdoor_temp = weather_file.heating_design_info[1] # for debugging/testing # puts "outdoor design temp = #{outdoor_temp}" # Calculate exhaust heat content exhaust_heat_content = 0.00123 * sum_zone_oa * 1000.0 * (avg_exhaust_temp - outdoor_temp) # for debugging/testing # puts "exhaust heat content = #{exhaust_heat_content}" # Modify erv_required based on exhaust heat content if exhaust_heat_content > 150.0 erv_required = true OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV required based on exhaust heat content.") else erv_required = false OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}, ERV not required based on exhaust heat content.") end return erv_required 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. If both nil, never required
435 436 437 438 439 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 435 def air_loop_hvac_motorized_oa_damper_limits(air_loop_hvac, climate_zone) minimum_oa_flow_cfm = 0 maximum_stories = 0 return [minimum_oa_flow_cfm, maximum_stories] end |
#air_loop_hvac_static_pressure_reset_required?(air_loop_hvac, has_ddc) ⇒ Boolean
NECB doesn’t require static pressure reset.
return [Bool] returns true if static pressure reset is required, false if not
425 426 427 428 429 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 425 def air_loop_hvac_static_pressure_reset_required?(air_loop_hvac, has_ddc) # static pressure reset not required sp_reset_required = false return sp_reset_required end |
#apply_building_default_constructionset(building_type, climate_zone, model) ⇒ Object
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 421 def apply_building_default_constructionset(building_type, climate_zone, model) @lookup_building_type = model_get_lookup_name(building_type) # TODO: this is a workaround. Need to synchronize the building type names # across different parts of the code, including splitting of Office types case building_type when 'SmallOffice', 'MediumOffice', 'LargeOffice' new_lookup_building_type = building_type else new_lookup_building_type = model_get_lookup_name(building_type) end # Make the default construction set for the building spc_type = 'WholeBuilding' bldg_def_const_set = model_add_construction_set(model, climate_zone, new_lookup_building_type, spc_type) if bldg_def_const_set.is_initialized model.getBuilding.setDefaultConstructionSet(bldg_def_const_set.get) else OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'Could not create default construction set for the building.') raise('hell') end end |
#apply_default_constructionsets_to_spacetypes(climate_zone, model) ⇒ Object
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 443 def apply_default_constructionsets_to_spacetypes(climate_zone, model) model.getSpaceTypes.sort.each do |space_type| # Get the standards building type stds_building_type = nil if space_type.standardsBuildingType.is_initialized stds_building_type = space_type.standardsBuildingType.get else OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', "Space type called '#{space_type.name}' has no standards building type.") end # Get the standards space type stds_spc_type = nil if space_type.standardsSpaceType.is_initialized stds_spc_type = space_type.standardsSpaceType.get else OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', "Space type called '#{space_type.name}' has no standards space type.") end # If the standards space type is Attic, # the building type should be blank. if stds_spc_type == 'Attic' stds_building_type = '' end # Attempt to make a construction set for this space type # and assign it if it can be created. spc_type_const_set = model_add_construction_set(model, climate_zone, stds_building_type, stds_spc_type) if spc_type_const_set.is_initialized space_type.setDefaultConstructionSet(spc_type_const_set.get) end end end |
#apply_economizers(climate_zone, model) ⇒ Object
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1090 def apply_economizers(climate_zone, model) # NECB2011 prescribes ability to provide 100% OA (5.2.2.7-5.2.2.9) econ_max_100_pct_oa_sch = OpenStudio::Model::ScheduleRuleset.new(model) econ_max_100_pct_oa_sch.setName('Economizer Max OA Fraction 100 pct') econ_max_100_pct_oa_sch.defaultDaySchedule.setName('Economizer Max OA Fraction 100 pct Default') econ_max_100_pct_oa_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0) # Check each airloop model.getAirLoopHVACs.sort.each do |air_loop| if air_loop_hvac_economizer_required?(air_loop) == true # If an economizer is required, determine the economizer type # in the prototype buildings, which depends on climate zone. economizer_type = nil # NECB 5.2.2.8 states that economizer can be controlled based on difference betweeen # return air temperature and outside air temperature OR return air enthalpy # and outside air enthalphy; latter chosen to be consistent with MNECB and CAN-QUEST implementation economizer_type = 'DifferentialEnthalpy' # Set the economizer type # Get the OA system and OA controller oa_sys = air_loop.airLoopHVACOutdoorAirSystem if oa_sys.is_initialized oa_sys = oa_sys.get else OpenStudio.logFree(OpenStudio::Error, 'openstudio.prototype.Model', "#{air_loop.name} is required to have an economizer, but it has no OA system.") next end oa_control = oa_sys.getControllerOutdoorAir oa_control.setEconomizerControlType(economizer_type) end end end |
#apply_standard_construction_properties(model, runner = nil, scale_wall = 1.0, scale_floor = 1.0, scale_roof = 1.0, scale_ground_wall = 1.0, scale_ground_floor = 1.0, scale_ground_roof = 1.0, scale_door = 1.0, scale_window = 1.0) ⇒ Bool
Go through the default construction sets and hard-assigned constructions. Clone the existing constructions and set their intended surface type and standards construction type per the PRM. For some standards, this will involve making modifications. For others, it will not.
90.1-2007, 90.1-2010, 90.1-2013
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 254 def apply_standard_construction_properties(model, runner = nil, scale_wall = 1.0, scale_floor = 1.0, scale_roof = 1.0, scale_ground_wall = 1.0, scale_ground_floor = 1.0, scale_ground_roof = 1.0, scale_door = 1.0, scale_window = 1.0) model.getDefaultConstructionSets.sort.each do |set| set_construction_set_to_necb!(model, set, runner, scale_wall, scale_floor, scale_roof, scale_ground_wall, scale_ground_floor, scale_ground_roof, scale_door, scale_window) end # sets all surfaces to use default constructions sets except adiabatic, where it does a hard assignment of the interior wall construction type. model.getPlanarSurfaces.sort.each(&:resetConstruction) # if the default construction set is defined..try to assign the interior wall to the adiabatic surfaces BTAP::Resources::Envelope.assign_interior_surface_construction_to_adiabatic_surfaces(model, nil) end |
#apply_standard_lights(set_lights, space_type, space_type_properties) ⇒ Object
2 3 4 5 6 7 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 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/lighting.rb', line 2 def apply_standard_lights(set_lights, space_type, space_type_properties) lights_have_info = false lighting_per_area = space_type_properties['lighting_per_area'].to_f lighting_per_person = space_type_properties['lighting_per_person'].to_f lights_frac_to_return_air = space_type_properties['lighting_fraction_to_return_air'].to_f lights_frac_radiant = space_type_properties['lighting_fraction_radiant'].to_f lights_frac_visible = space_type_properties['lighting_fraction_visible'].to_f lights_frac_replaceable = space_type_properties['lighting_fraction_replaceable'].to_f lights_have_info = true unless lighting_per_area.zero? lights_have_info = true unless lighting_per_person.zero? if set_lights && lights_have_info # Remove all but the first instance instances = space_type.lights.sort if instances.size.zero? definition = OpenStudio::Model::LightsDefinition.new(space_type.model) definition.setName("#{space_type.name} Lights Definition") instance = OpenStudio::Model::Lights.new(definition) instance.setName("#{space_type.name} Lights") instance.setSpaceType(space_type) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no lights, one has been created.") instances << instance elsif instances.size > 1 instances.each_with_index do |inst, i| next if i.zero? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "Removed #{inst.name} from #{space_type.name}.") inst.remove end end # Modify the definition of the instance space_type.lights.sort.each do |inst| definition = inst.lightsDefinition unless lighting_per_area.zero? occ_sens_lpd_frac = 1.0 # NECB2011 space types that require a reduction in the LPD to account for # the requirement of an occupancy sensor (8.4.4.6(3) and 4.2.2.2(2)) reduce_lpd_spaces = ['Classroom/lecture/training', 'Conf./meet./multi-purpose', 'Lounge/recreation', 'Conf./meet./multi-purpose', 'Washroom-sch-A', 'Washroom-sch-B', 'Washroom-sch-C', 'Washroom-sch-D', 'Washroom-sch-E', 'Washroom-sch-F', 'Washroom-sch-G', 'Washroom-sch-H', 'Washroom-sch-I', 'Dress./fitt. - performance arts', 'Locker room', 'Locker room-sch-A', 'Locker room-sch-B', 'Locker room-sch-C', 'Locker room-sch-D', 'Locker room-sch-E', 'Locker room-sch-F', 'Locker room-sch-G', 'Locker room-sch-H', 'Locker room-sch-I', 'Retail - dressing/fitting'] if reduce_lpd_spaces.include?(space_type.standardsSpaceType.get) # Note that "Storage area", "Storage area - refrigerated", "Hospital - medical supply" and "Office - enclosed" # LPD should only be reduced if their space areas are less than specific area values. # This is checked in a space loop after this function in the calling routine. occ_sens_lpd_frac = 0.9 end definition.setWattsperSpaceFloorArea(OpenStudio.convert(lighting_per_area.to_f * occ_sens_lpd_frac, 'W/ft^2', 'W/m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set LPD to #{lighting_per_area} W/ft^2.") end unless lighting_per_person.zero? definition.setWattsperPerson(OpenStudio.convert(lighting_per_person.to_f, 'W/person', 'W/person').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set lighting to #{lighting_per_person} W/person.") end unless lights_frac_to_return_air.zero? definition.setReturnAirFraction(lights_frac_to_return_air) end unless lights_frac_radiant.zero? definition.setFractionRadiant(lights_frac_radiant) end unless lights_frac_visible.zero? definition.setFractionVisible(lights_frac_visible) end # unless lights_frac_replaceable.zero? # definition.setFractionReplaceable(lights_frac_replaceable) # end end # If additional lights are specified, add those too additional_lighting_per_area = space_type_properties['additional_lighting_per_area'].to_f unless additional_lighting_per_area.zero? # Create the lighting definition additional_lights_def = OpenStudio::Model::LightsDefinition.new(space_type.model) additional_lights_def.setName("#{space_type.name} Additional Lights Definition") additional_lights_def.setWattsperSpaceFloorArea(OpenStudio.convert(additional_lighting_per_area.to_f, 'W/ft^2', 'W/m^2').get) additional_lights_def.setReturnAirFraction(lights_frac_to_return_air) additional_lights_def.setFractionRadiant(lights_frac_radiant) additional_lights_def.setFractionVisible(lights_frac_visible) # Create the lighting instance and hook it up to the space type additional_lights = OpenStudio::Model::Lights.new(additional_lights_def) additional_lights.setName("#{space_type.name} Additional Lights") additional_lights.setSpaceType(space_type) end end end |
#apply_standard_skylight_to_roof_ratio(model) ⇒ Object
Reduces the SRR to the values specified by the PRM. SRR reduction will be done by shrinking vertices toward the centroid.
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 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 143 def apply_standard_skylight_to_roof_ratio(model) # Loop through all spaces in the model, and # per the PNNL PRM Reference Manual, find the areas # of each space conditioning category (res, nonres, semi-heated) # separately. Include space multipliers. nr_wall_m2 = 0.001 # Avoids divide by zero errors later nr_sky_m2 = 0 res_wall_m2 = 0.001 res_sky_m2 = 0 sh_wall_m2 = 0.001 sh_sky_m2 = 0 total_roof_m2 = 0.001 total_subsurface_m2 = 0 model.getSpaces.sort.each do |space| # Loop through all surfaces in this space wall_area_m2 = 0 sky_area_m2 = 0 space.surfaces.sort.each do |surface| # Skip non-outdoor surfaces next unless surface.outsideBoundaryCondition == 'Outdoors' # Skip non-walls next unless surface.surfaceType == 'RoofCeiling' # This wall's gross area (including skylight area) wall_area_m2 += surface.grossArea * space.multiplier # Subsurfaces in this surface surface.subSurfaces.sort.each do |ss| sky_area_m2 += ss.netArea * space.multiplier end end # Determine the space category cat = 'NonRes' if space_residential?(space) cat = 'Res' end # if space.is_semiheated # cat = 'Semiheated' # end # Add to the correct category case cat when 'NonRes' nr_wall_m2 += wall_area_m2 nr_sky_m2 += sky_area_m2 when 'Res' res_wall_m2 += wall_area_m2 res_sky_m2 += sky_area_m2 when 'Semiheated' sh_wall_m2 += wall_area_m2 sh_sky_m2 += sky_area_m2 end total_roof_m2 += wall_area_m2 total_subsurface_m2 += sky_area_m2 end # Calculate the SRR of each category srr_nr = ((nr_sky_m2 / nr_wall_m2) * 100).round(1) srr_res = ((res_sky_m2 / res_wall_m2) * 100).round(1) srr_sh = ((sh_sky_m2 / sh_wall_m2) * 100).round(1) srr = ((total_subsurface_m2 / total_roof_m2) * 100.0).round(1) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "The skylight to roof ratios (SRRs) are: NonRes: #{srr_nr.round}%, Res: #{srr_res.round}%.") # SRR limit srr_lim = self.get_standards_constant('skylight_to_roof_ratio_max_value') * 100.0 # Check against SRR limit red_nr = srr_nr > srr_lim red_res = srr_res > srr_lim red_sh = srr_sh > srr_lim # Stop here unless windows need reducing return true unless srr > srr_lim OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Reducing the size of all windows (by raising sill height) to reduce window area down to the limit of #{srr_lim.round}%.") # Determine the factors by which to reduce the window / door area mult = srr_lim / srr # Reduce the subsurface areas model.getSpaces.sort.each do |space| # Loop through all surfaces in this space space.surfaces.sort.each do |surface| # Skip non-outdoor surfaces next unless surface.outsideBoundaryCondition == 'Outdoors' # Skip non-walls next unless surface.surfaceType == 'RoofCeiling' # Subsurfaces in this surface surface.subSurfaces.sort.each do |ss| # Reduce the size of the subsurface red = 1.0 - mult sub_surface_reduce_area_by_percent_by_shrinking_toward_centroid(ss, red) end end end return true end |
#apply_standard_window_to_wall_ratio(model) ⇒ Object
Reduces the WWR to the values specified by the NECB NECB 3.2.1.4
4 5 6 7 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 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 4 def apply_standard_window_to_wall_ratio(model) # Loop through all spaces in the model, and # per the PNNL PRM Reference Manual, find the areas # of each space conditioning category (res, nonres, semi-heated) # separately. Include space multipliers. nr_wall_m2 = 0.001 # Avoids divide by zero errors later nr_wind_m2 = 0 res_wall_m2 = 0.001 res_wind_m2 = 0 sh_wall_m2 = 0.001 sh_wind_m2 = 0 total_wall_m2 = 0.001 total_subsurface_m2 = 0.0 # Store the space conditioning category for later use space_cats = {} model.getSpaces.sort.each do |space| # Loop through all surfaces in this space wall_area_m2 = 0 wind_area_m2 = 0 space.surfaces.sort.each do |surface| # Skip non-outdoor surfaces next unless surface.outsideBoundaryCondition == 'Outdoors' # Skip non-walls next unless surface.surfaceType.casecmp('wall').zero? # This wall's gross area (including window area) wall_area_m2 += surface.grossArea * space.multiplier # Subsurfaces in this surface surface.subSurfaces.sort.each do |ss| wind_area_m2 += ss.netArea * space.multiplier end end # Determine the space category # zTODO This should really use the heating/cooling loads # from the proposed building. However, in an attempt # to avoid another sizing run just for this purpose, # conditioned status is based on heating/cooling # setpoints. If heated-only, will be assumed Semiheated. # The full-bore method is on the next line in case needed. # cat = thermal_zone_conditioning_category(space, template, climate_zone) cooled = space_cooled?(space) heated = space_heated?(space) cat = 'Unconditioned' # Unconditioned if !heated && !cooled cat = 'Unconditioned' # Heated-Only elsif heated && !cooled cat = 'Semiheated' # Heated and Cooled else res = thermal_zone_residential?(space.thermalZone.get) cat = if res 'ResConditioned' else 'NonResConditioned' end end space_cats[space] = cat # NECB2011 keep track of totals for NECB regardless of conditioned or not. total_wall_m2 += wall_area_m2 total_subsurface_m2 += wind_area_m2 # this contains doors as well. # Add to the correct category case cat when 'Unconditioned' next # Skip unconditioned spaces when 'NonResConditioned' nr_wall_m2 += wall_area_m2 nr_wind_m2 += wind_area_m2 when 'ResConditioned' res_wall_m2 += wall_area_m2 res_wind_m2 += wind_area_m2 when 'Semiheated' sh_wall_m2 += wall_area_m2 sh_wind_m2 += wind_area_m2 end end # Calculate the WWR of each category wwr_nr = ((nr_wind_m2 / nr_wall_m2) * 100.0).round(1) wwr_res = ((res_wind_m2 / res_wall_m2) * 100).round(1) wwr_sh = ((sh_wind_m2 / sh_wall_m2) * 100).round(1) fdwr = ((total_subsurface_m2 / total_wall_m2) * 100).round(1) # used by NECB2011 # Convert to IP and report nr_wind_ft2 = OpenStudio.convert(nr_wind_m2, 'm^2', 'ft^2').get nr_wall_ft2 = OpenStudio.convert(nr_wall_m2, 'm^2', 'ft^2').get res_wind_ft2 = OpenStudio.convert(res_wind_m2, 'm^2', 'ft^2').get res_wall_ft2 = OpenStudio.convert(res_wall_m2, 'm^2', 'ft^2').get sh_wind_ft2 = OpenStudio.convert(sh_wind_m2, 'm^2', 'ft^2').get sh_wall_ft2 = OpenStudio.convert(sh_wall_m2, 'm^2', 'ft^2').get OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "WWR NonRes = #{wwr_nr.round}%; window = #{nr_wind_ft2.round} ft2, wall = #{nr_wall_ft2.round} ft2.") OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "WWR Res = #{wwr_res.round}%; window = #{res_wind_ft2.round} ft2, wall = #{res_wall_ft2.round} ft2.") OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "WWR Semiheated = #{wwr_sh.round}%; window = #{sh_wind_ft2.round} ft2, wall = #{sh_wall_ft2.round} ft2.") # WWR limit wwr_lim = 40.0 # Check against WWR limit red_nr = wwr_nr > wwr_lim red_res = wwr_res > wwr_lim red_sh = wwr_sh > wwr_lim # NECB FDWR limit hdd = self.get_necb_hdd18(model) fdwr_lim = (max_fwdr(hdd) * 100.0).round(1) # puts "Current FDWR is #{fdwr}, must be less than #{fdwr_lim}." # puts "Current subsurf area is #{total_subsurface_m2} and gross surface area is #{total_wall_m2}" # Stop here unless windows / doors need reducing return true unless fdwr > fdwr_lim OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Reducing the size of all windows (by raising sill height) to reduce window area down to the limit of #{wwr_lim.round}%.") # Determine the factors by which to reduce the window / door area mult = fdwr_lim / fdwr # Reduce the window area if any of the categories necessary model.getSpaces.sort.each do |space| # Loop through all surfaces in this space space.surfaces.sort.each do |surface| # Skip non-outdoor surfaces next unless surface.outsideBoundaryCondition == 'Outdoors' # Skip non-walls next unless surface.surfaceType == 'Wall' # Subsurfaces in this surface surface.subSurfaces.sort.each do |ss| # Reduce the size of the window red = 1.0 - mult sub_surface_reduce_area_by_percent_by_raising_sill(ss, red) end end end return true end |
#assign_contruction_to_adiabatic_surfaces(model) ⇒ Object
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 738 739 740 741 742 743 744 745 746 747 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 697 def assign_contruction_to_adiabatic_surfaces(model) cp02_carpet_pad = OpenStudio::Model::MasslessOpaqueMaterial.new(model) cp02_carpet_pad.setName('CP02 CARPET PAD') cp02_carpet_pad.setRoughness('VeryRough') cp02_carpet_pad.setThermalResistance(0.21648) cp02_carpet_pad.setThermalAbsorptance(0.9) cp02_carpet_pad.setSolarAbsorptance(0.7) cp02_carpet_pad.setVisibleAbsorptance(0.8) normalweight_concrete_floor = OpenStudio::Model::StandardOpaqueMaterial.new(model) normalweight_concrete_floor.setName('100mm Normalweight concrete floor') normalweight_concrete_floor.setRoughness('MediumSmooth') normalweight_concrete_floor.setThickness(0.1016) normalweight_concrete_floor.setConductivity(2.31) normalweight_concrete_floor.setDensity(2322) normalweight_concrete_floor.setSpecificHeat(832) nonres_floor_insulation = OpenStudio::Model::MasslessOpaqueMaterial.new(model) nonres_floor_insulation.setName('Nonres_Floor_Insulation') nonres_floor_insulation.setRoughness('MediumSmooth') nonres_floor_insulation.setThermalResistance(2.88291975297193) nonres_floor_insulation.setThermalAbsorptance(0.9) nonres_floor_insulation.setSolarAbsorptance(0.7) nonres_floor_insulation.setVisibleAbsorptance(0.7) floor_adiabatic_construction = OpenStudio::Model::Construction.new(model) floor_adiabatic_construction.setName('Floor Adiabatic construction') floor_layers = OpenStudio::Model::MaterialVector.new floor_layers << cp02_carpet_pad floor_layers << normalweight_concrete_floor floor_layers << nonres_floor_insulation floor_adiabatic_construction.setLayers(floor_layers) g01_13mm_gypsum_board = OpenStudio::Model::StandardOpaqueMaterial.new(model) g01_13mm_gypsum_board.setName('G01 13mm gypsum board') g01_13mm_gypsum_board.setRoughness('Smooth') g01_13mm_gypsum_board.setThickness(0.0127) g01_13mm_gypsum_board.setConductivity(0.1600) g01_13mm_gypsum_board.setDensity(800) g01_13mm_gypsum_board.setSpecificHeat(1090) g01_13mm_gypsum_board.setThermalAbsorptance(0.9) g01_13mm_gypsum_board.setSolarAbsorptance(0.7) g01_13mm_gypsum_board.setVisibleAbsorptance(0.5) wall_adiabatic_construction = OpenStudio::Model::Construction.new(model) wall_adiabatic_construction.setName('Wall Adiabatic construction') wall_layers = OpenStudio::Model::MaterialVector.new wall_layers << g01_13mm_gypsum_board wall_layers << g01_13mm_gypsum_board wall_adiabatic_construction.setLayers(wall_layers) m10_200mm_concrete_block_basement_wall = OpenStudio::Model::StandardOpaqueMaterial.new(model) m10_200mm_concrete_block_basement_wall.setName('M10 200mm concrete block basement wall') m10_200mm_concrete_block_basement_wall.setRoughness('MediumRough') m10_200mm_concrete_block_basement_wall.setThickness(0.2032) m10_200mm_concrete_block_basement_wall.setConductivity(1.326) m10_200mm_concrete_block_basement_wall.setDensity(1842) m10_200mm_concrete_block_basement_wall.setSpecificHeat(912) basement_wall_construction = OpenStudio::Model::Construction.new(model) basement_wall_construction.setName('Basement Wall construction') basement_wall_layers = OpenStudio::Model::MaterialVector.new basement_wall_layers << m10_200mm_concrete_block_basement_wall basement_wall_construction.setLayers(basement_wall_layers) basement_floor_construction = OpenStudio::Model::Construction.new(model) basement_floor_construction.setName('Basement Floor construction') basement_floor_layers = OpenStudio::Model::MaterialVector.new basement_floor_layers << m10_200mm_concrete_block_basement_wall basement_floor_layers << cp02_carpet_pad basement_floor_construction.setLayers(basement_floor_layers) model.getSurfaces.sort.each do |surface| if surface.outsideBoundaryCondition.to_s == 'Adiabatic' if surface.surfaceType.to_s == 'Wall' surface.setConstruction(wall_adiabatic_construction) else surface.setConstruction(floor_adiabatic_construction) end elsif surface.outsideBoundaryCondition.to_s == 'OtherSideCoefficients' # Ground if surface.surfaceType.to_s == 'Wall' surface.setOutsideBoundaryCondition('Ground') surface.setConstruction(basement_wall_construction) else surface.setOutsideBoundaryCondition('Ground') surface.setConstruction(basement_floor_construction) end end end end |
#boiler_hot_water_apply_efficiency_and_curves(boiler_hot_water) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 445 def boiler_hot_water_apply_efficiency_and_curves(boiler_hot_water) successfully_set_all_properties = false # Define the criteria to find the boiler properties # in the hvac standards data set. search_criteria = boiler_hot_water_find_search_criteria(boiler_hot_water) fuel_type = search_criteria['fuel_type'] fluid_type = search_criteria['fluid_type'] # Get the capacity capacity_w = boiler_hot_water_find_capacity(boiler_hot_water) # Check if secondary and/or modulating boiler required if capacity_w / 1000.0 >= 352.0 if boiler_hot_water.name.to_s.include?('Primary Boiler') boiler_capacity = capacity_w boiler_hot_water.setBoilerFlowMode('LeavingSetpointModulated') boiler_hot_water.setMinimumPartLoadRatio(0.25) elsif boiler_hot_water.name.to_s.include?('Secondary Boiler') boiler_capacity = 0.001 end elsif ((capacity_w / 1000.0) >= 176.0) && ((capacity_w / 1000.0) < 352.0) boiler_capacity = capacity_w / 2 elsif (capacity_w / 1000.0) <= 176.0 if boiler_hot_water.name.to_s.include?('Primary Boiler') boiler_capacity = capacity_w elsif boiler_hot_water.name.to_s.include?('Secondary Boiler') boiler_capacity = 0.001 end end boiler_hot_water.setNominalCapacity(boiler_capacity) # Convert capacity to Btu/hr capacity_btu_per_hr = OpenStudio.convert(boiler_capacity, 'W', 'Btu/hr').get capacity_kbtu_per_hr = OpenStudio.convert(boiler_capacity, 'W', 'kBtu/hr').get # Get the boiler properties blr_props = model_find_object(standards_data['boilers'], search_criteria, capacity_btu_per_hr) unless blr_props OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.BoilerHotWater', "For #{boiler_hot_water.name}, cannot find boiler properties, cannot apply efficiency standard.") successfully_set_all_properties = false return successfully_set_all_properties end # Make the EFFFPLR curve eff_fplr = model_add_curve(boiler_hot_water.model, blr_props['efffplr']) if eff_fplr boiler_hot_water.setNormalizedBoilerEfficiencyCurve(eff_fplr) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.BoilerHotWater', "For #{boiler_hot_water.name}, cannot find eff_fplr curve, will not be set.") successfully_set_all_properties = false end # Get the minimum efficiency standards thermal_eff = nil # If specified as AFUE unless blr_props['minimum_annual_fuel_utilization_efficiency'].nil? min_afue = blr_props['minimum_annual_fuel_utilization_efficiency'] thermal_eff = afue_to_thermal_eff(min_afue) new_comp_name = "#{boiler_hot_water.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_afue} AFUE" OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.BoilerHotWater', "For #{template}: #{boiler_hot_water.name}: #{fuel_type} #{fluid_type} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; AFUE = #{min_afue}") end # If specified as thermal efficiency unless blr_props['minimum_thermal_efficiency'].nil? thermal_eff = blr_props['minimum_thermal_efficiency'] new_comp_name = "#{boiler_hot_water.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{thermal_eff} Thermal Eff" OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.BoilerHotWater', "For #{template}: #{boiler_hot_water.name}: #{fuel_type} #{fluid_type} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; Thermal Efficiency = #{thermal_eff}") end # If specified as combustion efficiency unless blr_props['minimum_combustion_efficiency'].nil? min_comb_eff = blr_props['minimum_combustion_efficiency'] thermal_eff = combustion_eff_to_thermal_eff(min_comb_eff) new_comp_name = "#{boiler_hot_water.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_comb_eff} Combustion Eff" OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.BoilerHotWater', "For #{template}: #{boiler_hot_water.name}: #{fuel_type} #{fluid_type} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; Combustion Efficiency = #{min_comb_eff}") end # Set the name boiler_hot_water.setName(new_comp_name) # Set the efficiency values unless thermal_eff.nil? boiler_hot_water.setNominalThermalEfficiency(thermal_eff) end return successfully_set_all_properties end |
#chiller_electric_eir_apply_efficiency_and_curves(chiller_electric_eir, clg_tower_objs) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 538 def chiller_electric_eir_apply_efficiency_and_curves(chiller_electric_eir, clg_tower_objs) chillers = standards_data['chillers'] # Define the criteria to find the chiller properties # in the hvac standards data set. search_criteria = chiller_electric_eir_find_search_criteria(chiller_electric_eir) cooling_type = search_criteria['cooling_type'] condenser_type = search_criteria['condenser_type'] compressor_type = search_criteria['compressor_type'] # Get the chiller capacity capacity_w = chiller_electric_eir_find_capacity(chiller_electric_eir) # All chillers must be modulating down to 25% of their capacity chiller_electric_eir.setChillerFlowMode('LeavingSetpointModulated') chiller_electric_eir.setMinimumPartLoadRatio(0.25) chiller_electric_eir.setMinimumUnloadingRatio(0.25) if (capacity_w / 1000.0) < 2100.0 if chiller_electric_eir.name.to_s.include? 'Primary Chiller' chiller_capacity = capacity_w elsif chiller_electric_eir.name.to_s.include? 'Secondary Chiller' chiller_capacity = 0.001 end else chiller_capacity = capacity_w / 2.0 end chiller_electric_eir.setReferenceCapacity(chiller_capacity) # Convert capacity to tons capacity_tons = OpenStudio.convert(chiller_capacity, 'W', 'ton').get # Get the chiller properties chlr_props = model_find_object(chillers, search_criteria, capacity_tons, Date.today) unless chlr_props OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ChillerElectricEIR', "For #{chiller_electric_eir.name}, cannot find chiller properties, cannot apply standard efficiencies or curves.") successfully_set_all_properties = false return successfully_set_all_properties end # Make the CAPFT curve cool_cap_ft = model_add_curve(chiller_electric_eir.model, chlr_props['capft']) if cool_cap_ft chiller_electric_eir.setCoolingCapacityFunctionOfTemperature(cool_cap_ft) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ChillerElectricEIR', "For #{chiller_electric_eir.name}, cannot find cool_cap_ft curve, will not be set.") successfully_set_all_properties = false end # Make the EIRFT curve cool_eir_ft = model_add_curve(chiller_electric_eir.model, chlr_props['eirft']) if cool_eir_ft chiller_electric_eir.setElectricInputToCoolingOutputRatioFunctionOfTemperature(cool_eir_ft) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ChillerElectricEIR', "For #{chiller_electric_eir.name}, cannot find cool_eir_ft curve, will not be set.") successfully_set_all_properties = false end # Make the EIRFPLR curve # which may be either a CurveBicubic or a CurveQuadratic based on chiller type cool_plf_fplr = model_add_curve(chiller_electric_eir.model, chlr_props['eirfplr']) if cool_plf_fplr chiller_electric_eir.setElectricInputToCoolingOutputRatioFunctionOfPLR(cool_plf_fplr) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ChillerElectricEIR', "For #{chiller_electric_eir.name}, cannot find cool_plf_fplr curve, will not be set.") successfully_set_all_properties = false end # Set the efficiency value kw_per_ton = nil cop = nil if chlr_props['minimum_full_load_efficiency'] kw_per_ton = chlr_props['minimum_full_load_efficiency'] cop = kw_per_ton_to_cop(kw_per_ton) chiller_electric_eir.setReferenceCOP(cop) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ChillerElectricEIR', "For #{chiller_electric_eir.name}, cannot find minimum full load efficiency, will not be set.") successfully_set_all_properties = false end # Set cooling tower properties now that the new COP of the chiller is set if chiller_electric_eir.name.to_s.include? 'Primary Chiller' # Single speed tower model assumes 25% extra for compressor power tower_cap = capacity_w * (1.0 + 1.0 / chiller_electric_eir.referenceCOP) if (tower_cap / 1000.0) < 1750 clg_tower_objs[0].setNumberofCells(1) else clg_tower_objs[0].setNumberofCells((tower_cap / (1000 * 1750) + 0.5).round) end clg_tower_objs[0].setFanPoweratDesignAirFlowRate(0.015 * tower_cap) end # Append the name with size and kw/ton chiller_electric_eir.setName("#{chiller_electric_eir.name} #{capacity_tons.round}tons #{kw_per_ton.round(1)}kW/ton") OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.ChillerElectricEIR', "For #{template}: #{chiller_electric_eir.name}: #{cooling_type} #{condenser_type} #{compressor_type} Capacity = #{capacity_tons.round}tons; COP = #{cop.round(1)} (#{kw_per_ton.round(1)}kW/ton)") return successfully_set_all_properties end |
#coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_multi_speed, sql_db_vars_map) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
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 738 739 740 741 742 743 744 745 746 747 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 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 639 def coil_cooling_dx_multi_speed_apply_efficiency_and_curves(coil_cooling_dx_multi_speed, sql_db_vars_map) successfully_set_all_properties = true # Define the criteria to find the chiller properties # in the hvac standards data set. search_criteria = {} search_criteria['template'] = template cooling_type = coil_cooling_dx_multi_speed.condenserType search_criteria['cooling_type'] = cooling_type # TODO: Standards - add split system vs single package to model # For now, assume single package as default sub_category = 'Single Package' # Determine the heating type if unitary or zone hvac heat_pump = false heating_type = nil containing_comp = nil if coil_cooling_dx_multi_speed.airLoopHVAC.empty? if coil_cooling_dx_multi_speed.containingHVACComponent.is_initialized containing_comp = coil_cooling_dx_multi_speed.containingHVACComponent.get if containing_comp.to_AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed.is_initialized htg_coil = containing_comp.to_AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed.get.heatingCoil if htg_coil.to_CoilHeatingDXMultiSpeed.is_initialized heat_pump = true heating_type = 'Electric Resistance or None' elsif htg_coil.to_CoilHeatingGasMultiStage.is_initialized heating_type = 'All Other' end end # TODO: Add other unitary systems elsif coil_cooling_dx_multi_speed.containingZoneHVACComponent.is_initialized containing_comp = coil_cooling_dx_multi_speed.containingZoneHVACComponent.get if containing_comp.to_ZoneHVACPackagedTerminalAirConditioner.is_initialized sub_category = 'PTAC' htg_coil = containing_comp.to_ZoneHVACPackagedTerminalAirConditioner.get.heatingCoil if htg_coil.to_CoilHeatingElectric.is_initialized heating_type = 'Electric Resistance or None' elsif htg_coil.to_CoilHeatingWater.is_initialized || htg_coil.to_CoilHeatingGas.is_initialized || htg_col.to_CoilHeatingGasMultiStage heating_type = 'All Other' end end # TODO: Add other zone hvac systems end end # Add the heating type to the search criteria unless heating_type.nil? search_criteria['heating_type'] = heating_type end search_criteria['subcategory'] = sub_category # Get the coil capacity capacity_w = nil clg_stages = stages if clg_stages.last.grossRatedTotalCoolingCapacity.is_initialized capacity_w = clg_stages.last.grossRatedTotalCoolingCapacity.get elsif coil_cooling_dx_multi_speed.autosizedSpeed4GrossRatedTotalCoolingCapacity.is_initialized capacity_w = coil_cooling_dx_multi_speed.autosizedSpeed4GrossRatedTotalCoolingCapacity.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name} capacity is not available, cannot apply efficiency standard.") successfully_set_all_properties = false return successfully_set_all_properties end # Volume flow rate flow_rate4 = nil if clg_stages.last.ratedAirFlowRate.is_initialized flow_rate4 = clg_stages.last.ratedAirFlowRate.get elsif coil_cooling_dx_multi_speed.autosizedSpeed4RatedAirFlowRate.is_initialized flow_rate4 = coil_cooling_dx_multi_speed.autosizedSpeed4RatedAirFlowRate.get end # Set number of stages stage_cap = [] num_stages = (capacity_w / (66.0 * 1000.0) + 0.5).round num_stages = [num_stages, 4].min if num_stages == 1 stage_cap[0] = capacity_w / 2.0 stage_cap[1] = 2.0 * stage_cap[0] stage_cap[2] = stage_cap[1] + 0.1 stage_cap[3] = stage_cap[2] + 0.1 else stage_cap[0] = 66.0 * 1000.0 stage_cap[1] = 2.0 * stage_cap[0] if num_stages == 2 stage_cap[2] = stage_cap[1] + 0.1 stage_cap[3] = stage_cap[2] + 0.1 elsif num_stages == 3 stage_cap[2] = 3.0 * stage_cap[0] stage_cap[3] = stage_cap[2] + 0.1 elsif num_stages == 4 stage_cap[2] = 3.0 * stage_cap[0] stage_cap[3] = 4.0 * stage_cap[0] end end # set capacities, flow rates, and sensible heat ratio for stages (0..3).each do |istage| clg_stages[istage].setGrossRatedTotalCoolingCapacity(stage_cap[istage]) clg_stages[istage].setRatedAirFlowRate(flow_rate4 * stage_cap[istage] / capacity_w) end # Convert capacity to Btu/hr capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get # Lookup efficiencies depending on whether it is a unitary AC or a heat pump ac_props = nil ac_props = if heat_pump == true model_find_object(standards_data['heat_pumps'], search_criteria, capacity_btu_per_hr, Date.today) else model_find_object(standards_data['unitary_acs'], search_criteria, capacity_btu_per_hr, Date.today) end # Check to make sure properties were found if ac_props.nil? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name}, cannot find efficiency info, cannot apply efficiency standard.") successfully_set_all_properties = false return successfully_set_all_properties end # Make the COOL-CAP-FT curve cool_cap_ft = model_add_curve(model, ac_props['cool_cap_ft'], standards) if cool_cap_ft clg_stages.each do |stage| stage.setTotalCoolingCapacityFunctionofTemperatureCurve(cool_cap_ft) end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name}, cannot find cool_cap_ft curve, will not be set.") successfully_set_all_properties = false end # Make the COOL-CAP-FFLOW curve cool_cap_fflow = model_add_curve(model, ac_props['cool_cap_fflow'], standards) if cool_cap_fflow clg_stages.each do |stage| stage.setTotalCoolingCapacityFunctionofFlowFractionCurve(cool_cap_fflow) end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name}, cannot find cool_cap_fflow curve, will not be set.") successfully_set_all_properties = false end # Make the COOL-EIR-FT curve cool_eir_ft = model_add_curve(model, ac_props['cool_eir_ft'], standards) if cool_eir_ft clg_stages.each do |stage| stage.setEnergyInputRatioFunctionofTemperatureCurve(cool_eir_ft) end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name}, cannot find cool_eir_ft curve, will not be set.") successfully_set_all_properties = false end # Make the COOL-EIR-FFLOW curve cool_eir_fflow = model_add_curve(model, ac_props['cool_eir_fflow'], standards) if cool_eir_fflow clg_stages.each do |stage| stage.setEnergyInputRatioFunctionofFlowFractionCurve(cool_eir_fflow) end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name}, cannot find cool_eir_fflow curve, will not be set.") successfully_set_all_properties = false end # Make the COOL-PLF-FPLR curve cool_plf_fplr = model_add_curve(model, ac_props['cool_plf_fplr'], standards) if cool_plf_fplr clg_stages.each do |stage| stage.setPartLoadFractionCorrelationCurve(cool_plf_fplr) end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_cooling_dx_multi_speed.name}, cannot find cool_plf_fplr curve, will not be set.") successfully_set_all_properties = false end # Get the minimum efficiency standards cop = nil if coil_dx_subcategory(coil_cooling_dx_multi_speed) == 'PTAC' ptac_eer_coeff_1 = ac_props['ptac_eer_coefficient_1'] ptac_eer_coeff_2 = ac_props['ptac_eer_coefficient_2'] capacity_btu_per_hr = 7000 if capacity_btu_per_hr < 7000 capacity_btu_per_hr = 15_000 if capacity_btu_per_hr > 15_000 ptac_eer = ptac_eer_coeff_1 + (ptac_eer_coeff_2 * capacity_btu_per_hr) cop = eer_to_cop(ptac_eer) # self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{ptac_eer}EER") new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{ptac_eer}EER" OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{ptac_eer}") end # If specified as SEER unless ac_props['minimum_seasonal_energy_efficiency_ratio'].nil? min_seer = ac_props['minimum_seasonal_energy_efficiency_ratio'] cop = seer_to_cop(min_seer) new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER" # self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER") OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}") end # If specified as EER unless ac_props['minimum_energy_efficiency_ratio'].nil? min_eer = ac_props['minimum_energy_efficiency_ratio'] cop = eer_to_cop(min_eer) new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_eer}EER" OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{min_eer}") end # if specified as SEER (heat pump) unless ac_props['minimum_seasonal_efficiency'].nil? min_seer = ac_props['minimum_seasonal_efficiency'] cop = seer_to_cop(min_seer) new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER" # self.setName("#{self.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_seer}SEER") OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; SEER = #{min_seer}") end # If specified as EER (heat pump) unless ac_props['minimum_full_load_efficiency'].nil? min_eer = ac_props['minimum_full_load_efficiency'] cop = eer_to_cop(min_eer) new_comp_name = "#{coil_cooling_dx_multi_speed.name} #{capacity_kbtu_per_hr.round}kBtu/hr #{min_eer}EER" OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{template}: #{coil_cooling_dx_multi_speed.name}: #{cooling_type} #{heating_type} #{subcategory} Capacity = #{capacity_kbtu_per_hr.round}kBtu/hr; EER = #{min_eer}") end sql_db_vars_map[new_comp_name] = name.to_s coil_cooling_dx_multi_speed.setName(new_comp_name) # Set the efficiency values unless cop.nil? clg_stages.each do |istage| istage.setGrossRatedCoolingCOP(cop) end end return sql_db_vars_map end |
#coil_heating_gas_multi_stage_apply_efficiency_and_curves(coil_heating_gas_multi_stage, standards) ⇒ Bool
Applies the standard efficiency ratings and typical performance curves to this object.
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 880 def coil_heating_gas_multi_stage_apply_efficiency_and_curves(coil_heating_gas_multi_stage, standards) successfully_set_all_properties = true # Get the coil capacity capacity_w = nil htg_stages = stages if htg_stages.last.nominalCapacity.is_initialized capacity_w = htg_stages.last.nominalCapacity.get elsif coil_heating_gas_multi_stage.autosizedStage4NominalCapacity.is_initialized capacity_w = coil_heating_gas_multi_stage.autosizedStage4NominalCapacity.get else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXMultiSpeed', "For #{coil_heating_gas_multi_stage.name} capacity is not available, cannot apply efficiency standard.") successfully_set_all_properties = false return successfully_set_all_properties end # Set number of stages num_stages = (capacity_w / (66.0 * 1000.0) + 0.5).round num_stages = [num_stages, 4].min stage_cap = [] if num_stages == 1 stage_cap[0] = capacity_w / 2.0 stage_cap[1] = 2.0 * stage_cap[0] stage_cap[2] = stage_cap[1] + 0.1 stage_cap[3] = stage_cap[2] + 0.1 else stage_cap[0] = 66.0 * 1000.0 stage_cap[1] = 2.0 * stage_cap[0] if num_stages == 2 stage_cap[2] = stage_cap[1] + 0.1 stage_cap[3] = stage_cap[2] + 0.1 elsif num_stages == 3 stage_cap[2] = 3.0 * stage_cap[0] stage_cap[3] = stage_cap[2] + 0.1 elsif num_stages == 4 stage_cap[2] = 3.0 * stage_cap[0] stage_cap[3] = 4.0 * stage_cap[0] end end # set capacities, flow rates, and sensible heat ratio for stages (0..3).each do |istage| htg_stages[istage].setNominalCapacity(stage_cap[istage]) end # PLF vs PLR curve furnace_plffplr_curve_name = 'FURNACE-EFFPLR-NECB2011' # plf vs plr curve for furnace furnace_plffplr_curve = model_add_curve(coil_heating_gas_multi_stage.model, furnace_plffplr_curve_name, standards) if furnace_plffplr_curve coil_heating_gas_multi_stage.setPartLoadFractionCorrelationCurve(furnace_plffplr_curve) else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingGasMultiStage', "For #{coil_heating_gas_multi_stage.name}, cannot find plffplr curve, will not be set.") successfully_set_all_properties = false end end |
#determine_dominant_necb_schedule_type(model) ⇒ Object
This model determines the dominant NECB schedule type return s.each [String]
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 260 def determine_dominant_necb_schedule_type(model) # lookup necb space type properties space_type_properties = @standards_data['space_types'] # Here is a hash to keep track of the m2 running total of spacetypes for each # sched type. s = Hash[ 'A', 0, 'B', 0, 'C', 0, 'D', 0, 'E', 0, 'F', 0, 'G', 0, 'H', 0, 'I', 0 ] # iterate through spaces in building. wildcard_spaces = 0 model.getSpaces.sort.each do |space| found_space_type = false # iterate through the NECB spacetype property table space_type_properties.each do |spacetype| unless space.spaceType.empty? if space.spaceType.get.standardsSpaceType.empty? || space.spaceType.get.standardsBuildingType.empty? OpenStudio.logFree(OpenStudio::Error, 'openstudio.Standards.Model', "Space #{space.name} does not have a standardSpaceType defined") found_space_type = false elsif space.spaceType.get.standardsSpaceType.get == spacetype['space_type'] && space.spaceType.get.standardsBuildingType.get == spacetype['building_type'] if spacetype['necb_schedule_type'] == '*' wildcard_spaces = +1 else s[spacetype['necb_schedule_type']] = s[spacetype['necb_schedule_type']] + space.floorArea if (spacetype['necb_schedule_type'] != '*') && (spacetype['necb_schedule_type'] != '- undefined -') end # puts "Found #{space.spaceType.get.name} schedule #{spacetype[2]} match with floor area of #{space.floorArea()}" found_space_type = true elsif spacetype['necb_schedule_type'] != '*' # found wildcard..will not count to total. found_space_type = true end end end raise "Did not find #{space.spaceType.get.name} in NECB space types." if found_space_type == false end # finds max value and returns NECB schedule letter. raise('Only wildcard spaces in model. You need to define the actual spaces. ') if wildcard_spaces == model.getSpaces.size dominant_schedule = s.each {|k, v| return k.to_s if v == s.values.max} return dominant_schedule end |
#determine_necb_schedule_type(space) ⇒ String
This method determines the spacetype schedule type. This will re
313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 313 def determine_necb_schedule_type(space) spacetype_data = nil if @standards_data['space_types'].is_a?(Hash) == true spacetype_data = @standards_data['space_types']['table'] else spacetype_data = @standards_data['space_types'] end raise "Undefined spacetype for space #{space.get.name}) if space.spaceType.empty?" if space.spaceType.empty? raise "Undefined standardsSpaceType or StandardsBuildingType for space #{space.spaceType.get.name}) if space.spaceType.empty?" if space.spaceType.get.standardsSpaceType.empty? | space.spaceType.get.standardsBuildingType.empty? space_type_properties = spacetype_data.detect {|st| (st['space_type'] == space.spaceType.get.standardsSpaceType.get) && (st['building_type'] == space.spaceType.get.standardsBuildingType.get)} return space_type_properties['necb_schedule_type'].strip end |
#distance(loc1, loc2) ⇒ Object
Enter in [latitude, longitude] for each loc and this method will return the distance.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 95 def distance(loc1, loc2) rad_per_deg = Math::PI/180 # PI / 180 rkm = 6371 # Earth radius in kilometers rm = rkm * 1000 # Radius in meters dlat_rad = (loc2[0]-loc1[0]) * rad_per_deg # Delta, converted to rad dlon_rad = (loc2[1]-loc1[1]) * rad_per_deg lat1_rad, lon1_rad = loc1.map {|i| i * rad_per_deg} lat2_rad, lon2_rad = loc2.map {|i| i * rad_per_deg} a = Math.sin(dlat_rad/2)**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin(dlon_rad/2)**2 c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a)) rm * c # Delta in meters end |
#fan_baseline_impeller_efficiency(fan) ⇒ Double
Add fan type to data model and modify this method
Determines the baseline fan impeller efficiency based on the specified fan type.
941 942 943 944 945 946 947 948 949 950 951 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 941 def fan_baseline_impeller_efficiency(fan) # Assume that the fan efficiency is 65% for normal fans # TODO add fan type to fan data model # and infer impeller efficiency from that? # or do we always assume a certain type of # fan impeller for the baseline system? # TODO check COMNET and T24 ACM and PNNL 90.1 doc fan_impeller_eff = 0.65 return fan_impeller_eff end |
#fan_constant_volume_apply_prototype_fan_pressure_rise(fan_constant_volume) ⇒ Object
1076 1077 1078 1079 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1076 def fan_constant_volume_apply_prototype_fan_pressure_rise(fan_constant_volume) fan_constant_volume.setPressureRise( self.get_standards_constant('fan_constant_volume_pressure_rise_value')) return true end |
#fan_standard_minimum_motor_efficiency_and_size(fan, motor_bhp) ⇒ Array<Double>
Determines the minimum fan 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.
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 964 def fan_standard_minimum_motor_efficiency_and_size(fan, motor_bhp) fan_motor_eff = 0.85 nominal_hp = motor_bhp # Don't attempt to look up motor efficiency # for zero-hp fans, which may occur when there is no # airflow required for a particular system, typically # heated-only spaces with high internal gains # and no OA requirements such as elevator shafts. return [fan_motor_eff, 0] if motor_bhp == 0.0 # Lookup the minimum motor efficiency motors = standards_data['motors'] # Assuming all fan motors are 4-pole ODP template_mod = @template if fan.class.name == 'OpenStudio::Model::FanConstantVolume' template_mod += '-CONSTANT' elsif fan.class.name == 'OpenStudio::Model::FanVariableVolume' template_mod += '-VARIABLE' # 0.909 corrects for 10% over sizing implemented upstream # 0.7457 is to convert from bhp to kW fan_power_kw = 0.909 * 0.7457 * motor_bhp power_vs_flow_curve_name = if fan_power_kw >= 25.0 'VarVolFan-FCInletVanes-NECB2011-FPLR' elsif fan_power_kw >= 7.5 && fan_power_kw < 25 'VarVolFan-AFBIInletVanes-NECB2011-FPLR' else 'VarVolFan-AFBIFanCurve-NECB2011-FPLR' end power_vs_flow_curve = model_add_curve(fan.model, power_vs_flow_curve_name) fan.setFanPowerMinimumFlowRateInputMethod('Fraction') fan.setFanPowerCoefficient5(0.0) fan.setFanPowerMinimumFlowFraction(power_vs_flow_curve.minimumValueofx) fan.setFanPowerCoefficient1(power_vs_flow_curve.coefficient1Constant) fan.setFanPowerCoefficient2(power_vs_flow_curve.coefficient2x) fan.setFanPowerCoefficient3(power_vs_flow_curve.coefficient3xPOW2) fan.setFanPowerCoefficient4(power_vs_flow_curve.coefficient4xPOW3) else raise('') end search_criteria = { 'template' => template_mod, 'number_of_poles' => 4.0, 'type' => 'Enclosed' } # Exception for small fans, including # zone exhaust, fan coil, and fan powered terminals. # In this case, use the 0.5 HP for the lookup. if fan_small_fan?(fan) nominal_hp = 0.5 else motor_properties = model_find_object(motors, search_criteria, motor_bhp) if motor_properties.nil? OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Fan', "For #{fan.name}, could not find motor properties using search criteria: #{search_criteria}, motor_bhp = #{motor_bhp} hp.") return [fan_motor_eff, nominal_hp] end nominal_hp = motor_properties['maximum_capacity'].to_f.round(1) # If the biggest fan motor size is hit, use the highest category efficiency if nominal_hp == 9999.0 OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Fan', "For #{fan.name}, there is no greater nominal HP. Use the efficiency of the largest motor category.") nominal_hp = motor_bhp end # Round to nearest whole HP for niceness if nominal_hp >= 2 nominal_hp = nominal_hp.round end 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 #{fan.name}, could not find nominal motor properties using search criteria: #{search_criteria}, motor_hp = #{nominal_hp} hp.") return [fan_motor_eff, nominal_hp] end fan_motor_eff = motor_properties['nominal_full_load_efficiency'] return [fan_motor_eff, nominal_hp] end |
#fan_variable_volume_apply_prototype_fan_pressure_rise(fan_variable_volume) ⇒ Object
Sets the fan pressure rise based on the Prototype buildings inputs which are governed by the flow rate coming through the fan and whether the fan lives inside a unit heater, PTAC, etc.
1084 1085 1086 1087 1088 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1084 def fan_variable_volume_apply_prototype_fan_pressure_rise(fan_variable_volume) # 1000 Pa for supply fan and 458.33 Pa for return fan (accounts for efficiency differences between two fans) fan_variable_volume.setPressureRise(self.get_standards_constant('fan_variable_volume_pressure_rise_value')) return true end |
#fan_variable_volume_part_load_fan_power_limitation?(fan_variable_volume) ⇒ Boolean
Determines whether there is a requirement to have a VSD or some other method to reduce fan power at low part load ratios.
1052 1053 1054 1055 1056 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1052 def fan_variable_volume_part_load_fan_power_limitation?(fan_variable_volume) part_load_control_required = false return part_load_control_required end |
#get_all_spacetype_names ⇒ Object
90 91 92 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 90 def get_all_spacetype_names return @standards_data['space_types']['table'].map {|space_types| [space_types['building_type'], space_types['space_type']]} end |
#get_canadian_system_defaults_by_weatherfile_name(model) ⇒ Object
this method returns the default system fuel types by epw_file.
112 113 114 115 116 117 118 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 112 def get_canadian_system_defaults_by_weatherfile_name(model) #get models weather object to get the province. Then use that to look up the province. epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get) fuel_sources = @standards_data['tables'].detect {|table| table['name'] == 'regional_fuel_use'}['table'].detect {|fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region)} raise("Could not find fuel sources for weather file, make sure it is a Canadian weather file.") if fuel_sources.nil? #this should never happen since we are using only canadian weather files. return fuel_sources end |
#get_necb_hdd18(model) ⇒ Object
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/standards/necb/necb_2011/necb_2011.rb', line 120 def get_necb_hdd18(model) max_distance_tolerance = 500000 min_distance = 100000000000000.0 necb_closest = nil epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get) #this extracts the table from the json database. necb_2015_table_c1 = @standards_data['tables'].detect {|table| table['name'] == 'necb_2015_table_c1'}['table'] necb_2015_table_c1.each do |necb| next if necb['lat_long'].nil? #Need this until Tyson cleans up table. dist = distance([epw.latitude.to_f, epw.longitude.to_f], necb['lat_long']) if min_distance > dist min_distance = dist necb_closest = necb end end if (min_distance / 1000.0) > max_distance_tolerance and not epw.hdd18.nil? puts "Could not find close NECB HDD from Table C1 < #{max_distance_tolerance}km. Closest city is #{min_distance/1000.0}km away. Using epw hdd18 instead." return epw.hdd18.to_f else puts "INFO:NECB HDD18 of #{necb_closest['degree_days_below_18_c'].to_f} at nearest city #{necb_closest['city']},#{necb_closest['province']}, at a distance of #{'%.2f' % (min_distance/1000.0)}km from epw location. Ref:necb_2015_table_c1" return necb_closest['degree_days_below_18_c'].to_f end end |
#get_standards_constant(name) ⇒ Object
56 57 58 59 60 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 56 def get_standards_constant(name) object = @standards_data['constants'].detect {|constant| constant['name'] == name} raise("could not find #{name} in standards constants database. ") if object.nil? or object['value'].nil? return object['value'] end |
#get_standards_formula(name) ⇒ Object
62 63 64 65 66 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 62 def get_standards_formula(name) object = @standards_data['formulas'].detect {|formula| formula['name'] == name} raise("could not find #{name} in standards formual database. ") if object.nil? or object['value'].nil? return object['value'] end |
#get_standards_table(table_name, search_criteria = nil) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 68 def get_standards_table(table_name, search_criteria = nil) return_objects = nil object = @standards_data['tables'].detect {|table| table['name'] == table_name} raise("could not find #{table_name} in standards table database. ") if object.nil? or object['table'].nil? if search_criteria.nil? return object['table'] else return_objects = model_find_objects(object['table'], search_criteria) return return_objects end end |
#load_standards_database_new ⇒ Object
Combine the data from the JSON files into a single hash Load JSON files differently depending on whether loading from the OpenStudio CLI embedded filesystem or from typical gem installation
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 12 def load_standards_database_new() @standards_data = {} @standards_data["tables"] = [] if __dir__[0] == ':' # Running from OpenStudio CLI ('data/', /.*\.json/).each do |file| data = JSON.parse(EmbeddedScripting.getFileAsString(file)) if not data["tables"].nil? and data["tables"].first["data_type"] =="table" @standards_data["tables"] << data["tables"].first else @standards_data[data.keys.first] = data[data.keys.first] end end else files = Dir.glob("#{File.dirname(__FILE__)}/data/*.json").select {|e| File.file? e} files.each do |file| data = JSON.parse(File.read(file)) if not data["tables"].nil? and data["tables"].first["data_type"] =="table" @standards_data["tables"] << data["tables"].first else @standards_data[data.keys.first] = data[data.keys.first] end end end #needed for compatibility of standards database format @standards_data['tables'].each do |table| @standards_data[table['name']] = table end return @standards_data end |
#max_fwdr(hdd) ⇒ Double
Returns a constant float.
241 242 243 244 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 241 def max_fwdr(hdd) #get formula from json database. return eval(self.get_standards_formula('fdwr_formula')) end |
#model_add_construction_set(model, clim, building_type, spc_type, is_residential = 'No') ⇒ Object
Create a construction set from the openstudio standards dataset. Returns an Optional DefaultConstructionSet
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 555 556 557 558 559 560 561 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 478 def model_add_construction_set(model, clim, building_type, spc_type, is_residential = 'No') construction_set = OpenStudio::Model::OptionalDefaultConstructionSet.new # Find the climate zone set that this climate zone falls into climate_zone_set = model_find_climate_zone_set(model, clim) unless climate_zone_set return construction_set end # Get the object data data = model_find_object(@standards_data['construction_sets'], 'template' => template, 'building_type' => building_type, 'space_type' => spc_type) unless data # if nothing matches say that we could not find it. = "Construction set for template =#{template}, building type = #{building_type}, space type = #{spc_type}, is residential = #{is_residential} was not found in standards_data['construction_sets']" OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', ) puts return construction_set end OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Adding construction set: #{template}-#{clim}-#{building_type}-#{spc_type}-is_residential#{is_residential}") name = model_make_name(model, clim, building_type, spc_type) # Create a new construction set and name it construction_set = OpenStudio::Model::DefaultConstructionSet.new(model) construction_set.setName(name) # Exterior surfaces constructions exterior_surfaces = OpenStudio::Model::DefaultSurfaceConstructions.new(model) construction_set.setDefaultExteriorSurfaceConstructions(exterior_surfaces) if data['exterior_floor_standards_construction_type'] exterior_surfaces.setFloorConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorFloor', data['exterior_floor_standards_construction_type'], data['exterior_floor_building_category'])) end if data['exterior_wall_standards_construction_type'] && data['exterior_wall_building_category'] exterior_surfaces.setWallConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorWall', data['exterior_wall_standards_construction_type'], data['exterior_wall_building_category'])) end if data['exterior_roof_standards_construction_type'] && data['exterior_roof_building_category'] exterior_surfaces.setRoofCeilingConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorRoof', data['exterior_roof_standards_construction_type'], data['exterior_roof_building_category'])) end # Interior surfaces constructions interior_surfaces = OpenStudio::Model::DefaultSurfaceConstructions.new(model) construction_set.setDefaultInteriorSurfaceConstructions(interior_surfaces) construction_name = data['interior_floors'] unless construction_name.nil? interior_surfaces.setFloorConstruction(model_add_construction(model, construction_name)) end construction_name = data['interior_walls'] unless construction_name.nil? interior_surfaces.setWallConstruction(model_add_construction(model, construction_name)) end construction_name = data['interior_ceilings'] unless construction_name.nil? interior_surfaces.setRoofCeilingConstruction(model_add_construction(model, construction_name)) end # Ground contact surfaces constructions ground_surfaces = OpenStudio::Model::DefaultSurfaceConstructions.new(model) construction_set.setDefaultGroundContactSurfaceConstructions(ground_surfaces) if data['ground_contact_floor_standards_construction_type'] && data['ground_contact_floor_building_category'] ground_surfaces.setFloorConstruction(model_find_and_add_construction(model, climate_zone_set, 'GroundContactFloor', data['ground_contact_floor_standards_construction_type'], data['ground_contact_floor_building_category'])) end if data['ground_contact_wall_standards_construction_type'] && data['ground_contact_wall_building_category'] ground_surfaces.setWallConstruction(model_find_and_add_construction(model, climate_zone_set, 'GroundContactWall', data['ground_contact_wall_standards_construction_type'], data['ground_contact_wall_building_category'])) end if data['ground_contact_ceiling_standards_construction_type'] && data['ground_contact_ceiling_building_category'] ground_surfaces.setRoofCeilingConstruction(model_find_and_add_construction(model, climate_zone_set, 'GroundContactRoof', data['ground_contact_ceiling_standards_construction_type'], data['ground_contact_ceiling_building_category'])) end # Exterior sub surfaces constructions exterior_subsurfaces = OpenStudio::Model::DefaultSubSurfaceConstructions.new(model) construction_set.setDefaultExteriorSubSurfaceConstructions(exterior_subsurfaces) if data['exterior_fixed_window_standards_construction_type'] && data['exterior_fixed_window_building_category'] exterior_subsurfaces.setFixedWindowConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorWindow', data['exterior_fixed_window_standards_construction_type'], data['exterior_fixed_window_building_category'])) end if data['exterior_operable_window_standards_construction_type'] && data['exterior_operable_window_building_category'] exterior_subsurfaces.setOperableWindowConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorWindow', data['exterior_operable_window_standards_construction_type'], data['exterior_operable_window_building_category'])) end if data['exterior_door_standards_construction_type'] && data['exterior_door_building_category'] exterior_subsurfaces.setDoorConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorDoor', data['exterior_door_standards_construction_type'], data['exterior_door_building_category'])) end construction_name = data['exterior_glass_doors'] unless construction_name.nil? exterior_subsurfaces.setGlassDoorConstruction(model_add_construction(model, construction_name)) end if data['exterior_overhead_door_standards_construction_type'] && data['exterior_overhead_door_building_category'] exterior_subsurfaces.setOverheadDoorConstruction(model_find_and_add_construction(model, climate_zone_set, 'ExteriorDoor', data['exterior_overhead_door_standards_construction_type'], data['exterior_overhead_door_building_category'])) end if data['exterior_skylight_standards_construction_type'] && data['exterior_skylight_building_category'] exterior_subsurfaces.setSkylightConstruction(model_find_and_add_construction(model, climate_zone_set, 'Skylight', data['exterior_skylight_standards_construction_type'], data['exterior_skylight_building_category'])) end if (construction_name = data['tubular_daylight_domes']) exterior_subsurfaces.setTubularDaylightDomeConstruction(model_add_construction(model, construction_name)) end if (construction_name = data['tubular_daylight_diffusers']) exterior_subsurfaces.setTubularDaylightDiffuserConstruction(model_add_construction(model, construction_name)) end # Interior sub surfaces constructions interior_subsurfaces = OpenStudio::Model::DefaultSubSurfaceConstructions.new(model) construction_set.setDefaultInteriorSubSurfaceConstructions(interior_subsurfaces) if (construction_name = data['interior_fixed_windows']) interior_subsurfaces.setFixedWindowConstruction(model_add_construction(model, construction_name)) end if (construction_name = data['interior_operable_windows']) interior_subsurfaces.setOperableWindowConstruction(model_add_construction(model, construction_name)) end if (construction_name = data['interior_doors']) interior_subsurfaces.setDoorConstruction(model_add_construction(model, construction_name)) end # Other constructions if (construction_name = data['interior_partitions']) construction_set.setInteriorPartitionConstruction(model_add_construction(model, construction_name)) end if (construction_name = data['space_shading']) construction_set.setSpaceShadingConstruction(model_add_construction(model, construction_name)) end if (construction_name = data['building_shading']) construction_set.setBuildingShadingConstruction(model_add_construction(model, construction_name)) end if (construction_name = data['site_shading']) construction_set.setSiteShadingConstruction(model_add_construction(model, construction_name)) end # componentize the construction set # construction_set_component = construction_set.createComponent # Return the construction set return OpenStudio::Model::OptionalDefaultConstructionSet.new(construction_set) end |
#model_add_constructions(model, building_type, climate_zone) ⇒ Bool
Adds code-minimum constructions based on the building type as defined in the OpenStudio_Standards_construction_sets.json file. Where there is a separate construction set specified for the individual space type, this construction set will be created and applied to this space type, overriding the whole-building construction set.
406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 406 def model_add_constructions(model, building_type, climate_zone) OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started applying constructions') # Assign construction to adiabatic construction # Assign a material to all internal mass objects assign_contruction_to_adiabatic_surfaces(model) # The constructions lookup table uses a slightly different list of # building types. apply_building_default_constructionset(building_type, climate_zone, model) # Make a construction set for each space type, if one is specified #apply_default_constructionsets_to_spacetypes(climate_zone, model) OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished applying constructions') return true end |
#model_add_hvac(model, epw_file) ⇒ Object
2 3 4 5 6 7 8 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2 def model_add_hvac(model, epw_file) OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started Adding HVAC') system_fuel_defaults = self.get_canadian_system_defaults_by_weatherfile_name(model) necb_autozone_and_autosystem(model, nil, false, system_fuel_defaults) OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished adding HVAC') return true end |
#model_add_schedule(model, schedule_name) ⇒ ScheduleRuleset
make return an OptionalScheduleRuleset
Create a schedule from the openstudio standards dataset and add it to the model.
51 52 53 54 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 51 def model_add_schedule(model, schedule_name) super(model, schedule_name) end |
#model_add_swh(model, building_type, climate_zone, prototype_input, epw_file) ⇒ Object
2 3 4 5 6 7 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 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/service_water_heating.rb', line 2 def model_add_swh(model, building_type, climate_zone, prototype_input, epw_file) OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started Adding Service Water Heating') # Add the main service water heating loop, if specified unless prototype_input['main_water_heater_volume'].nil? swh_fueltype = self.get_canadian_system_defaults_by_weatherfile_name(model)['swh_fueltype'] # Add the main service water loop unless building_type == 'RetailStripmall' && ( template != 'NECB2011' && template != 'NECB2015') main_swh_loop = model_add_swh_loop(model, 'Main Service Water Loop', nil, OpenStudio.convert(prototype_input['main_service_water_temperature'], 'F', 'C').get, prototype_input['main_service_water_pump_head'], prototype_input['main_service_water_pump_motor_efficiency'], OpenStudio.convert(prototype_input['main_water_heater_capacity'], 'Btu/hr', 'W').get, OpenStudio.convert(prototype_input['main_water_heater_volume'], 'gal', 'm^3').get, swh_fueltype, OpenStudio.convert(prototype_input['main_service_water_parasitic_fuel_consumption_rate'], 'Btu/hr', 'W').get, building_type) end # Attach the end uses if specified in prototype inputs # TODO remove special logic for large office SWH end uses # TODO remove special logic for stripmall SWH end uses and service water loops # TODO remove special logic for large hotel SWH end uses if prototype_input['main_service_water_peak_flowrate'] # Attaches the end uses if specified as a lump value in the prototype_input model_add_swh_end_uses(model, 'Main', main_swh_loop, OpenStudio.convert(prototype_input['main_service_water_peak_flowrate'], 'gal/min', 'm^3/s').get, prototype_input['main_service_water_flowrate_schedule'], OpenStudio.convert(prototype_input['main_water_use_temperature'], 'F', 'C').get, nil, building_type) else # Attaches the end uses if specified by space type space_type_map = @space_type_map building_type = 'Space Function' puts space_type_map space_type_map.sort.each do |space_type_name, space_names| search_criteria = { 'template' => template, 'building_type' => model_get_lookup_name(building_type), 'space_type' => space_type_name } data = model_find_object(standards_data['space_types'], search_criteria) # Skip space types with no data next if data.nil? # Skip space types with no water use, unless it is a NECB archetype (these do not have peak flow rates defined) # Add a service water use for each space space_names.sort.each do |space_name| space = model.getSpaceByName(space_name).get space_multiplier = nil # Added this to prevent double counting of zone multipliers.. space multipliers are never used in NECB archtypes. space_multiplier = 1 model_add_swh_end_uses_by_space(model, model_get_lookup_name(building_type), climate_zone, main_swh_loop, space_type_name, space_name, space_multiplier) end end end end # Add the booster water heater, if specified unless prototype_input['booster_water_heater_volume'].nil? # Add the booster water loop swh_booster_loop = model_add_swh_booster(model, main_swh_loop, OpenStudio.convert(prototype_input['booster_water_heater_capacity'], 'Btu/hr', 'W').get, OpenStudio.convert(prototype_input['booster_water_heater_volume'], 'gal', 'm^3').get, prototype_input['booster_water_heater_fuel'], OpenStudio.convert(prototype_input['booster_water_temperature'], 'F', 'C').get, 0, nil, building_type) # Attach the end uses model_add_booster_swh_end_uses(model, swh_booster_loop, OpenStudio.convert(prototype_input['booster_service_water_peak_flowrate'], 'gal/min', 'm^3/s').get, prototype_input['booster_service_water_flowrate_schedule'], OpenStudio.convert(prototype_input['booster_water_use_temperature'], 'F', 'C').get, building_type) end # Add the laundry water heater, if specified unless prototype_input['laundry_water_heater_volume'].nil? # Add the laundry service water heating loop laundry_swh_loop = model_add_swh_loop(model, 'Laundry Service Water Loop', nil, OpenStudio.convert(prototype_input['laundry_service_water_temperature'], 'F', 'C').get, prototype_input['laundry_service_water_pump_head'], prototype_input['laundry_service_water_pump_motor_efficiency'], OpenStudio.convert(prototype_input['laundry_water_heater_capacity'], 'Btu/hr', 'W').get, OpenStudio.convert(prototype_input['laundry_water_heater_volume'], 'gal', 'm^3').get, prototype_input['laundry_water_heater_fuel'], OpenStudio.convert(prototype_input['laundry_service_water_parasitic_fuel_consumption_rate'], 'Btu/hr', 'W').get, building_type) # Attach the end uses if specified in prototype inputs model_add_swh_end_uses(model, 'Laundry', laundry_swh_loop, OpenStudio.convert(prototype_input['laundry_service_water_peak_flowrate'], 'gal/min', 'm^3/s').get, prototype_input['laundry_service_water_flowrate_schedule'], OpenStudio.convert(prototype_input['laundry_water_use_temperature'], 'F', 'C').get, nil, building_type) end OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished adding Service Water Heating') return true end |
#model_apply_sizing_parameters(model) ⇒ Object
1070 1071 1072 1073 1074 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1070 def model_apply_sizing_parameters(model) model.getSizingParameters.setHeatingSizingFactor(self.get_standards_constant('sizing_factor_max_heating')) model.getSizingParameters.setCoolingSizingFactor(self.get_standards_constant('sizing_factor_max_cooling')) OpenStudio.logFree(OpenStudio::Info, 'openstudio.prototype.Model', "Set sizing factors to #{self.get_standards_constant('sizing_factor_max_heating')} for heating and #{self.get_standards_constant('sizing_factor_max_heating')} for cooling.") end |
#model_attach_water_fixtures_to_spaces?(model) ⇒ Boolean
Determine whether or not water fixtures are attached to spaces
327 328 329 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 327 def model_attach_water_fixtures_to_spaces?(model) return true end |
#model_create_prototype_model(climate_zone, epw_file, sizing_run_dir = Dir.pwd, debug = false, measure_model = nil) ⇒ Object
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 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 145 def model_create_prototype_model(climate_zone, epw_file, sizing_run_dir = Dir.pwd, debug = false, measure_model = nil) building_type = @instvarbuilding_type raise 'no building_type!' if @instvarbuilding_type.nil? model = nil # prototype generation. model = load_geometry_osm(@geometry_file) # standard candidate model.getThermostatSetpointDualSetpoints(&:remove) model.yearDescription.get.setDayofWeekforStartDay('Sunday') model_add_design_days_and_weather_file(model, climate_zone, epw_file) # Standards model_add_ground_temperatures(model, @instvarbuilding_type, climate_zone) # prototype candidate model.getBuilding.setName(self.class.to_s) model.getBuilding.setName("-#{@instvarbuilding_type}-#{climate_zone}-#{epw_file} created: #{Time.new}") set_occ_sensor_spacetypes(model, @space_type_map) model_add_loads(model) # standards candidate model_apply_infiltration_standard(model) # standards candidate model_modify_surface_convection_algorithm(model) # standards model_add_constructions(model, @instvarbuilding_type, climate_zone) # prototype candidate apply_standard_construction_properties(model) # standards candidate apply_standard_window_to_wall_ratio(model) # standards candidate apply_standard_skylight_to_roof_ratio(model) # standards candidate model_create_thermal_zones(model, @space_multiplier_map) # standards candidate # For some building types, stories are defined explicitly if model_run_sizing_run(model, "#{sizing_run_dir}/SR0") == false raise("sizing run 0 failed!") end # Create Reference HVAC Systems. model_add_hvac(model, epw_file) # standards for NECB Prototype for NREL candidate model_add_swh(model, @instvarbuilding_type, climate_zone, @prototype_input, epw_file) model_apply_sizing_parameters(model) # set a larger tolerance for unmet hours from default 0.2 to 1.0C model.getOutputControlReportingTolerances.setToleranceforTimeHeatingSetpointNotMet(1.0) model.getOutputControlReportingTolerances.setToleranceforTimeCoolingSetpointNotMet(1.0) if model_run_sizing_run(model, "#{sizing_run_dir}/SR1") == false raise("sizing run 1 failed!") end # This is needed for NECB2011 as a workaround for sizing the reheat boxes model.getAirTerminalSingleDuctVAVReheats.each {|iobj| air_terminal_single_duct_vav_reheat_set_heating_cap(iobj)} # Apply the prototype HVAC assumptions # which include sizing the fan pressure rises based # on the flow rate of the system. model_apply_prototype_hvac_assumptions(model, building_type, climate_zone) # for 90.1-2010 Outpatient, AHU2 set minimum outdoor air flow rate as 0 # AHU1 doesn't have economizer model_modify_oa_controller(model) # For operating room 1&2 in 2010 and 2013, VAV minimum air flow is set by schedule model_reset_or_room_vav_minimum_damper(@prototype_input, model) model_modify_oa_controller(model) # Apply the HVAC efficiency standard model_apply_hvac_efficiency_standard(model, climate_zone) # Fix EMS references. # Temporary workaround for OS issue #2598 model_temp_fix_ems_references(model) # Add daylighting controls per standard # only four zones in large hotel have daylighting controls # todo: YXC to merge to the main function model_add_daylighting_controls(model) # to be removed after refactor. # Add output variables for debugging model_request_timeseries_outputs(model) if debug # If measure model is passed, then replace measure model with new model created here. if measure_model.nil? return model else model_replace_model(measure_model, model) return measure_model end end |
#model_create_thermal_zones(model, space_multiplier_map = nil) ⇒ Bool
Creates thermal zones to contain each space, as defined for each building in the system_to_space_map inside the Prototype.building_name e.g. (Prototype.secondary_school.rb) file.
2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2938 def model_create_thermal_zones(model, space_multiplier_map = nil) OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started creating thermal zones') space_multiplier_map = {} if space_multiplier_map.nil? # Remove any Thermal zones assigned model.getThermalZones.each(&:remove) # Create a thermal zone for each space in the self model.getSpaces.sort.each do |space| zone = OpenStudio::Model::ThermalZone.new(model) zone.setName("#{space.name} ZN") unless space_multiplier_map[space.name.to_s].nil? || (space_multiplier_map[space.name.to_s] == 1) zone.setMultiplier(space_multiplier_map[space.name.to_s]) end space.setThermalZone(zone) # Skip thermostat for spaces with no space type next if space.spaceType.empty? # Add a thermostat space_type_name = space.spaceType.get.name.get thermostat_name = space_type_name + ' Thermostat' thermostat = model.getThermostatSetpointDualSetpointByName(thermostat_name) if thermostat.empty? OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "Thermostat #{thermostat_name} not found for space name: #{space.name}") else thermostat_clone = thermostat.get.clone(model).to_ThermostatSetpointDualSetpoint.get zone.setThermostatSetpointDualSetpoint(thermostat_clone) # Set Ideal loads to thermal zone for sizing for NECB needs. We need this for sizing. ideal_loads = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model) ideal_loads.addToThermalZone(zone) end end OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished creating thermal zones') end |
#model_find_and_add_construction(model, climate_zone_set, intended_surface_type, standards_construction_type, building_category) ⇒ Object
Helper method to find a particular construction and add it to the model after modifying the insulation value if necessary.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 658 def model_find_and_add_construction(model, climate_zone_set, intended_surface_type, standards_construction_type, building_category) # Get the construction properties, # which specifies properties by construction category by climate zone set. # AKA the info in Tables 5.5-1-5.5-8 props = model_find_object(standards_data['construction_properties'], 'template' => template, 'climate_zone_set' => climate_zone_set, 'intended_surface_type' => intended_surface_type, 'standards_construction_type' => standards_construction_type, 'building_category' => building_category) if !props OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Could not find construction properties for: #{template}-#{climate_zone_set}-#{intended_surface_type}-#{standards_construction_type}-#{building_category}.") # Return an empty construction construction = OpenStudio::Model::Construction.new(model) construction.setName('Could not find construction properties set to Adiabatic ') almost_adiabatic = OpenStudio::Model::MasslessOpaqueMaterial.new(model, 'Smooth', 500) construction.insertLayer(0, almost_adiabatic) return construction else OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "Construction properties for: #{template}-#{climate_zone_set}-#{intended_surface_type}-#{standards_construction_type}-#{building_category} = #{props}.") end # Make sure that a construction is specified if props['construction'].nil? OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No typical construction is specified for construction properties of: #{template}-#{climate_zone_set}-#{intended_surface_type}-#{standards_construction_type}-#{building_category}. Make sure it is entered in the spreadsheet.") # Return an empty construction construction = OpenStudio::Model::Construction.new(model) construction.setName('No typical construction was specified') return construction end # Add the construction, modifying properties as necessary construction = model_add_construction(model, props['construction'], props) return construction end |
#model_find_climate_zone_set(model, clim) ⇒ Object
Helper method to find out which climate zone set contains a specific climate zone. Returns climate zone set name as String if success, nil if not found.
1185 1186 1187 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1185 def model_find_climate_zone_set(model, clim) return "NECB-CNEB ClimatZone 4-8" end |
#necb_autozone_and_autosystem(model = nil, runner = nil, use_ideal_air_loads = false, system_fuel_defaults) ⇒ String
This method will take a model that uses NECB2011 spacetypes , and..
-
Create a building story schema.
-
Remove all existing Thermal Zone defintions.
-
Create new thermal zones based on the following definitions.
Rule1 all zones must contain only the same schedule / occupancy schedule. Rule2 zones must cater to similar solar gains (N,E,S,W) Rule3 zones must not pass from floor to floor. They must be contained to a single floor or level. Rule4 Wildcard spaces will be associated with the nearest zone of similar schedule type in which is shared most of it’s internal surface with. Rule5 For NECB zones must contain spaces of similar system type only. Rule6 Residential / dwelling units must not share systems with other space types.
2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2689 def necb_autozone_and_autosystem( model = nil, runner = nil, use_ideal_air_loads = false, system_fuel_defaults ) # Create a data struct for the space to system to placement information. # system assignment. unless ['NaturalGas', 'Electricity', 'PropaneGas', 'FuelOil#1', 'FuelOil#2', 'Coal', 'Diesel', 'Gasoline', 'OtherFuel1'].include?(system_fuel_defaults['boiler_fueltype']) BTAP.runner_register('ERROR', "boiler_fueltype = #{system_fuel_defaults['boiler_fueltype']}", runner) return end unless [true, false].include?(system_fuel_defaults['mau_type']) BTAP.runner_register('ERROR', "mau_type = #{system_fuel_defaults['mau_type']}", runner) return end unless ['Hot Water', 'Electric'].include?(system_fuel_defaults['mau_heating_coil_type']) BTAP.runner_register('ERROR', "mau_heating_coil_type = #{system_fuel_defaults['mau_heating_coil_type']}", runner) return false end unless ['Hot Water', 'Electric'].include?(system_fuel_defaults['baseboard_type']) BTAP.runner_register('ERROR', "baseboard_type = #{system_fuel_defaults['baseboard_type']}", runner) return false end unless ['Scroll', 'Centrifugal', 'Rotary Screw', 'Reciprocating'].include?(system_fuel_defaults['chiller_type']) BTAP.runner_register('ERROR', "chiller_type = #{system_fuel_defaults['chiller_type']}", runner) return false end unless ['DX', 'Hydronic'].include?(system_fuel_defaults['mau_cooling_type']) BTAP.runner_register('ERROR', "mau_cooling_type = #{system_fuel_defaults['mau_cooling_type']}", runner) return false end unless ['Electric', 'Gas', 'DX'].include?(system_fuel_defaults['heating_coil_type_sys3']) BTAP.runner_register('ERROR', "heating_coil_type_sys3 = #{system_fuel_defaults['heating_coil_type_sys3']}", runner) return false end unless ['Electric', 'Gas', 'DX'].include?(system_fuel_defaults['heating_coil_type_sys4']) BTAP.runner_register('ERROR', "heating_coil_type_sys4 = #{system_fuel_defaults['heating_coil_type_sys4']}", runner) return false end unless ['Hot Water', 'Electric'].include?(system_fuel_defaults['heating_coil_type_sys6']) BTAP.runner_register('ERROR', "heating_coil_type_sys6 = #{system_fuel_defaults['heating_coil_type_sys6']}", runner) return false end unless ['AF_or_BI_rdg_fancurve', 'AF_or_BI_inletvanes', 'fc_inletvanes', 'var_speed_drive'].include?(system_fuel_defaults['fan_type']) BTAP.runner_register('ERROR', "fan_type = #{system_fuel_defaults['fan_type']}", runner) return false end # REPEATED CODE!! unless ['Electric', 'Hot Water'].include?(system_fuel_defaults['heating_coil_type_sys6']) BTAP.runner_register('ERROR', "heating_coil_type_sys6 = #{system_fuel_defaults['heating_coil_type_sys6']}", runner) return false end # REPEATED CODE!! unless ['Electric', 'Gas'].include?(system_fuel_defaults['heating_coil_type_sys4']) BTAP.runner_register('ERROR', "heating_coil_type_sys4 = #{system_fuel_defaults['heating_coil_type_sys4']}", runner) return false end # Ensure that floors have been assigned by user. raise('No building stories have been defined.. User must define building stories and spaces in model.') if model.getBuildingStorys.empty? # BTAP::Geometry::BuildingStoreys::auto_assign_stories(model) # this method will determine the spaces that should be set to each system schedule_type_array, space_zoning_data_array = necb_spacetype_system_selection(model, nil, nil) # Deal with Wildcard spaces. Might wish to have logic to do coridors first. space_zoning_data_array.sort_by(&:space_name).each do |space_zone_data| # If it is a wildcard space. if space_zone_data.system_number.nil? # iterate through all adjacent spaces from largest shared wall area to smallest. # Set system type to match first space system that is not nil. adj_spaces = space_get_adjacent_spaces_with_shared_wall_areas(space_zone_data.space, true) if adj_spaces.nil? puts "Warning: No adjacent spaces for #{space_zone_data.space.name} on same floor, looking for others above and below to set system" adj_spaces = space_get_adjacent_spaces_with_shared_wall_areas(space_zone_data.space, false) end adj_spaces.sort.each do |adj_space| # if there are no adjacent spaces. Raise an error. raise "Could not determine adj space to space #{space_zone_data.space.name.get}" if adj_space.nil? adj_space_data = space_zoning_data_array.find {|data| data.space == adj_space[0]} if adj_space_data.system_number.nil? next else space_zone_data.system_number = adj_space_data.system_number puts space_zone_data.space.name.get.to_s break end end raise "Could not determine adj space system to space #{space_zone_data.space.name.get}" if space_zone_data.system_number.nil? end end # remove any thermal zones used for sizing to start fresh. Should only do this after the above system selection method. model.getThermalZones.sort.each(&:remove) # now lets apply the rules. # Rule1 all zones must contain only the same schedule / occupancy schedule. # Rule2 zones must cater to similar solar gains (N,E,S,W) # Rule3 zones must not pass from floor to floor. They must be contained to a single floor or level. # Rule4 Wildcard spaces will be associated with the nearest zone of similar schedule type in which is shared most of it's internal surface with. # Rule5 NECB zones must contain spaces of similar system type only. # Rule6 Multiplier zone will be part of the floor and orientation of the base space. # Rule7 Residential / dwelling units must not share systems with other space types. # Array of system types of Array of Spaces system_zone_array = [] # Lets iterate by system (0..7).each do |system_number| system_zone_array[system_number] = [] # iterate by story story_counter = 0 model.getBuildingStorys.sort.each do |story| # puts "Story:#{story}" story_counter += 1 # iterate by operation schedule type. schedule_type_array.each do |schedule_type| # iterate by horizontal location ['north', 'east', 'west', 'south', 'core'].each do |horizontal_placement| # puts "horizontal_placement:#{horizontal_placement}" [true, false].each do |is_dwelling_unit| space_array = [] space_zoning_data_array.each do |space_info| # puts "Spacename: #{space_info.space.name}:#{space_info.space.spaceType.get.name}" if (space_info.system_number == system_number) && (space_info.space.buildingStory.get == story) && (determine_necb_schedule_type(space_info.space).to_s == schedule_type) && (space_info.horizontal_placement == horizontal_placement) && (space_info.is_dwelling_unit == is_dwelling_unit) space_array << space_info.space end end # create Thermal Zone if space_array is not empty. unless space_array.empty? # Process spaces that have multipliers associated with them first. # This map define the multipliers for spaces with multipliers not equals to 1 space_multiplier_map = @space_multiplier_map # create new zone and add the spaces to it. space_array.each do |space| # Create thermalzone for each space. thermal_zone = OpenStudio::Model::ThermalZone.new(model) # Create a more informative space name. thermal_zone.setName("Sp-#{space.name} Sys-#{system_number} Flr-#{story_counter} Sch-#{schedule_type} HPlcmt-#{horizontal_placement} ZN") # Add zone mulitplier if required. thermal_zone.setMultiplier(space_multiplier_map[space.name.to_s]) unless space_multiplier_map[space.name.to_s].nil? # Space to thermal zone. (for archetype work it is one to one) space.setThermalZone(thermal_zone) # Get thermostat for space type if it already exists. space_type_name = space.spaceType.get.name.get thermostat_name = space_type_name + ' Thermostat' thermostat = model.getThermostatSetpointDualSetpointByName(thermostat_name) if thermostat.empty? OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "Thermostat #{thermostat_name} not found for space name: #{space.name} ZN") raise " Thermostat #{thermostat_name} not found for space name: #{space.name}" else thermostat_clone = thermostat.get.clone(model).to_ThermostatSetpointDualSetpoint.get thermal_zone.setThermostatSetpointDualSetpoint(thermostat_clone) end # Add thermal to zone system number. system_zone_array[system_number] << thermal_zone end end end end end end end # system iteration # Create and assign the zones to the systems. if use_ideal_air_loads == true # otherwise use ideal loads. model.getThermalZones.sort.each do |thermal_zone| thermal_zone_ideal_loads = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model) thermal_zone_ideal_loads.addToThermalZone(thermal_zone) end else hw_loop_needed = false system_zone_array.each_with_index do |zones, system_index| next if zones.empty? if system_index == 1 && (system_fuel_defaults['mau_heating_coil_type'] == 'Hot Water' || system_fuel_defaults['baseboard_type'] == 'Hot Water') hw_loop_needed = true elsif system_index == 2 || system_index == 5 || system_index == 7 hw_loop_needed = true elsif (system_index == 3 || system_index == 4) && system_fuel_defaults['baseboard_type'] == 'Hot Water' hw_loop_needed = true elsif system_index == 6 && (system_fuel_defaults['mau_heating_coil_type'] == 'Hot Water' || system_fuel_defaults['baseboard_type'] == 'Hot Water') hw_loop_needed = true end if hw_loop_needed break end end if hw_loop_needed hw_loop = OpenStudio::Model::PlantLoop.new(model) always_on = model.alwaysOnDiscreteSchedule setup_hw_loop_with_components( model, hw_loop, system_fuel_defaults['boiler_fueltype'], always_on ) end system_zone_array.each_with_index do |zones, system_index| # skip if no thermal zones for this system. next if zones.empty? case system_index when 0, nil # Do nothing no system assigned to zone. Used for Unconditioned spaces when 1 add_sys1_unitary_ac_baseboard_heating(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['mau_type'], system_fuel_defaults['mau_heating_coil_type'], system_fuel_defaults['baseboard_type'], hw_loop) when 2 add_sys2_FPFC_sys5_TPFC(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['chiller_type'], 'FPFC', system_fuel_defaults['mau_cooling_type'], hw_loop) when 3 add_sys3and8_single_zone_packaged_rooftop_unit_with_baseboard_heating_single_speed(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['heating_coil_type_sys3'], system_fuel_defaults['baseboard_type'], hw_loop) when 4 add_sys4_single_zone_make_up_air_unit_with_baseboard_heating(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['heating_coil_type_sys4'], system_fuel_defaults['baseboard_type'], hw_loop) when 5 add_sys2_FPFC_sys5_TPFC(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['chiller_type'], 'TPFC', system_fuel_defaults['mau_cooling_type'], hw_loop) when 6 add_sys6_multi_zone_built_up_system_with_baseboard_heating(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['heating_coil_type_sys6'], system_fuel_defaults['baseboard_type'], system_fuel_defaults['chiller_type'], system_fuel_defaults['fan_type'], hw_loop) when 7 add_sys2_FPFC_sys5_TPFC(model, zones, system_fuel_defaults['boiler_fueltype'], system_fuel_defaults['chiller_type'], 'FPFC', system_fuel_defaults['mau_cooling_type'], hw_loop) end end end # Check to ensure that all spaces are assigned to zones except undefined ones. errors = [] model.getSpaces.sort.each do |space| if space.thermalZone.empty? && (space.spaceType.get.name.get != 'Space Function - undefined -') errors << "space #{space.name} with spacetype #{space.spaceType.get.name.get} was not assigned a thermalzone." end end unless errors.empty? raise(" #{errors}") end end |
#necb_spacetype_system_selection(model, heating_design_load = nil, cooling_design_load = nil) ⇒ Object
2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2520 def necb_spacetype_system_selection(model, heating_design_load = nil, cooling_design_load = nil) spacezoning_data = Struct.new( :space, # the space object :space_name, # the space name :building_type_name, # space type name :space_type_name, # space type name :necb_hvac_system_selection_type, # :system_number, # the necb system type :number_of_stories, # number of stories :horizontal_placement, # the horizontal placement (norht, south, east, west, core) :vertical_placment, # the vertical placement ( ground, top, both, middle ) :people_obj, # Spacetype people object :heating_capacity, :cooling_capacity, :is_dwelling_unit, # Checks if it is a dwelling unit. :is_wildcard ) # Array to store schedule objects schedule_type_array = [] # find the number of stories in the model this include multipliers. number_of_stories = model.getBuilding.standardsNumberOfAboveGroundStories if number_of_stories.empty? raise 'Number of above ground stories not present in geometry model. Please ensure this is defined in your Building Object' else number_of_stories = number_of_stories.get end # set up system array containers. These will contain the spaces associated with the system types. space_zoning_data_array = [] # First pass of spaces to collect information into the space_zoning_data_array . model.getSpaces.sort.each do |space| # this will get the spacetype system index 8.4.4.8A from the SpaceTypeData and BuildingTypeData in (1-12) space_system_index = nil if space.spaceType.empty? space_system_index = nil else # gets row information from standards spreadsheet. space_type_property = model_find_object(standards_data['space_types'], 'template' => @template, 'space_type' => space.spaceType.get.standardsSpaceType.get, 'building_type' => space.spaceType.get.standardsBuildingType.get) raise("could not find necb system selection type for space: #{space.name} and spacetype #{space.spaceType.get.standardsSpaceType.get}") if space_type_property.nil? # stores the Building or SpaceType System type name. necb_hvac_system_selection_type = space_type_property['necb_hvac_system_selection_type'] end # Get the heating and cooling load for the space. Only Zones with a defined thermostat will have a load. # Make sure we don't have sideeffects by changing the argument variables. cooling_load = cooling_design_load heating_load = heating_design_load if space.spaceType.get.standardsSpaceType.get == '- undefined -' cooling_load = 0.0 heating_load = 0.0 else cooling_load = space.thermalZone.get.coolingDesignLoad.get * space.floorArea * space.multiplier / 1000.0 if cooling_load.nil? heating_load = space.thermalZone.get.heatingDesignLoad.get * space.floorArea * space.multiplier / 1000.0 if heating_load.nil? end # identify space-system_index and assign the right NECB system type 1-7. system = nil is_dwelling_unit = false case necb_hvac_system_selection_type when nil raise "#{space.name} does not have an NECB system association. Please define a NECB HVAC System Selection Type in the google docs standards database." when 0, '- undefined -' # These are spaces are undefined...so they are unconditioned and have no loads other than infiltration and no systems system = 0 when 'Assembly Area' # Assembly Area. system = if number_of_stories <= 4 3 else 6 end when 'Automotive Area' system = 4 when 'Data Processing Area' system = if cooling_design_load > 20 # KW...need a sizing run. 2 else 1 end when 'General Area' # [3,6] system = if number_of_stories <= 2 3 else 6 end when 'Historical Collections Area' # [2], system = 2 when 'Hospital Area' # [3], system = 3 when 'Indoor Arena' # ,[7], system = 7 when 'Industrial Area' # [3] this need some thought. system = 3 when 'Residential/Accomodation Area' # ,[1], this needs some thought. system = 1 is_dwelling_unit = true when 'Sleeping Area' # [3], system = 3 is_dwelling_unit = true when 'Supermarket/Food Services Area' # [3,4], system = 3 when 'Supermarket/Food Services Area - vented' system = 4 when 'Warehouse Area' system = 4 when 'Warehouse Area - refrigerated' system = 5 when 'Wildcard' system = nil is_wildcard = true else raise "NECB HVAC System Selection Type #{necb_hvac_system_selection_type} not valid" end # get placement on floor, core or perimeter and if a top, bottom, middle or single story. horizontal_placement, vertical_placement = BTAP::Geometry::Spaces.get_space_placement(space) # dump all info into an array for debugging and iteration. unless space.spaceType.empty? space_type_name = space.spaceType.get.standardsSpaceType.get building_type_name = space.spaceType.get.standardsBuildingType.get space_zoning_data_array << spacezoning_data.new(space, space.name.get, building_type_name, space_type_name, necb_hvac_system_selection_type, system, number_of_stories, horizontal_placement, vertical_placement, space.spaceType.get.people, heating_load, cooling_load, is_dwelling_unit, is_wildcard) schedule_type_array << determine_necb_schedule_type(space).to_s end end return schedule_type_array.uniq!, space_zoning_data_array end |
#set_construction_set_to_necb!(model, default_surface_construction_set, runner = nil, scale_wall = 1.0, scale_floor = 1.0, scale_roof = 1.0, scale_ground_wall = 1.0, scale_ground_floor = 1.0, scale_ground_roof = 1.0, scale_door = 1.0, scale_window = 1.0) ⇒ Boolean
this will create a copy and convert all construction sets to NECB reference conductances.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 289 def set_construction_set_to_necb!(model, default_surface_construction_set, runner = nil, scale_wall = 1.0, scale_floor = 1.0, scale_roof = 1.0, scale_ground_wall = 1.0, scale_ground_floor = 1.0, scale_ground_roof = 1.0, scale_door = 1.0, scale_window = 1.0) BTAP.runner_register('Info', 'set_construction_set_to_necb!', runner) if model.weatherFile.empty? || model.weatherFile.get.path.empty? || !File.exist?(model.weatherFile.get.path.get.to_s) BTAP.runner_register('Error', 'Weather file is not defined. Please ensure the weather file is defined and exists.', runner) return false end #Note:hdd needs to be defined for eval to work on table eval below. hdd = self.get_necb_hdd18(model) old_name = default_surface_construction_set.name.get.to_s new_name = "#{old_name} at hdd = #{hdd}" # convert conductance values to rsi values. (Note: we should really be only using conductances in) wall_rsi = 1.0 / (scale_wall * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Outdoors', 'surface' => 'Wall'})[0]['formula'])) floor_rsi = 1.0 / (scale_floor * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Outdoors', 'surface' => 'Floor'})[0]['formula'])) roof_rsi = 1.0 / (scale_roof * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Outdoors', 'surface' => 'RoofCeiling'})[0]['formula'])) ground_wall_rsi = 1.0 / (scale_ground_wall * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Ground', 'surface' => 'Wall'})[0]['formula'])) ground_floor_rsi = 1.0 / (scale_ground_floor * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Ground', 'surface' => 'Floor'})[0]['formula'])) ground_roof_rsi = 1.0 / (scale_ground_roof * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Ground', 'surface' => 'RoofCeiling'})[0]['formula'])) door_rsi = 1.0 / (scale_door * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Outdoors', 'surface' => 'Door'})[0]['formula'])) window_rsi = 1.0 / (scale_window * eval(self.get_standards_table('surface_thermal_transmittance', {'boundary_condition' => 'Outdoors', 'surface' => 'Window'})[0]['formula'])) BTAP::Resources::Envelope::ConstructionSets.customize_default_surface_construction_set_rsi!(model, new_name, default_surface_construction_set, wall_rsi, floor_rsi, roof_rsi, ground_wall_rsi, ground_floor_rsi, ground_roof_rsi, window_rsi, nil, nil, window_rsi, nil, nil, door_rsi, door_rsi, nil, nil, door_rsi, window_rsi, nil, nil, window_rsi, nil, nil, window_rsi, nil, nil) BTAP.runner_register('Info', 'set_construction_set_to_necb! was sucessful.', runner) return true end |
#set_necb_external_subsurface_conductance(subsurface, hdd) ⇒ Object
Set all external subsurfaces (doors, windows, skylights) to NECB values.
382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 382 def set_necb_external_subsurface_conductance(subsurface, hdd) conductance_value = 0 if subsurface.outsideBoundaryCondition.downcase.match('outdoors') case subsurface.subSurfaceType.downcase when /window/ conductance_value = @standards_data['conductances']['Window'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor when /door/ conductance_value = @standards_data['conductances']['Door'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor end subsurface.setRSI(1 / conductance_value) end end |
#set_necb_external_surface_conductance(surface, hdd, is_radiant = false, scaling_factor = 1.0) ⇒ String
Set all external surface conductances to NECB values.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb', line 343 def set_necb_external_surface_conductance(surface, hdd, is_radiant = false, scaling_factor = 1.0) conductance_value = 0 if surface.outsideBoundaryCondition.casecmp('outdoors').zero? case surface.surfaceType.downcase when 'wall' conductance_value = @standards_data['conductances']['Wall'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor when 'floor' conductance_value = @standards_data['conductances']['Floor'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor when 'roofceiling' conductance_value = @standards_data['conductances']['Roof'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor end if is_radiant conductance_value *= 0.80 end return BTAP::Geometry::Surfaces.set_surfaces_construction_conductance([surface], conductance_value) end if surface.outsideBoundaryCondition.downcase =~ /ground/ case surface.surfaceType.downcase when 'wall' conductance_value = @standards_data['conductances']['GroundWall'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor when 'floor' conductance_value = @standards_data['conductances']['GroundFloor'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor when 'roofceiling' conductance_value = @standards_data['conductances']['GroundRoof'].find {|i| i['hdd'] > hdd}['thermal_transmittance'] * scaling_factor end if is_radiant conductance_value *= 0.80 end return BTAP::Geometry::Surfaces.set_surfaces_construction_conductance([surface], conductance_value) end end |
#set_occ_sensor_spacetypes(model, space_type_map) ⇒ Bool
Returns true if successful, false if not
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 434 435 436 437 438 439 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 401 def set_occ_sensor_spacetypes(model, space_type_map) building_type = 'Space Function' space_type_map.each do |space_type_name, space_names| space_names.sort.each do |space_name| space = model.getSpaceByName(space_name) next if space.empty? space = space.get # Check if space type for this space matches NECB2011 specific space type # for occupancy sensor that is area dependent. Note: space.floorArea in m2. if (space_type_name == 'Storage area' && space.floorArea < 100) || (space_type_name == 'Storage area - refrigerated' && space.floorArea < 100) || (space_type_name == 'Hospital - medical supply' && space.floorArea < 100) || (space_type_name == 'Office - enclosed' && space.floorArea < 25) # If there is only one space assigned to this space type, then reassign this stub # to the @@template duplicate with appendage " - occsens", otherwise create a new stub # for this space. Required to use reduced LPD by NECB2011 0.9 factor. space_type_name_occsens = space_type_name + ' - occsens' stub_space_type_occsens = model.getSpaceTypeByName("#{building_type} #{space_type_name_occsens}") if stub_space_type_occsens.empty? # create a new space type just once for space_type_name appended with " - occsens" stub_space_type_occsens = OpenStudio::Model::SpaceType.new(model) stub_space_type_occsens.setStandardsBuildingType(building_type) stub_space_type_occsens.setStandardsSpaceType(space_type_name_occsens) stub_space_type_occsens.setName("#{building_type} #{space_type_name_occsens}") space_type_apply_rendering_color(stub_space_type_occsens) space.setSpaceType(stub_space_type_occsens) else # reassign occsens space type stub already created... stub_space_type_occsens = stub_space_type_occsens.get space.setSpaceType(stub_space_type_occsens) end end end end return true end |
#set_wildcard_schedules_to_dominant_building_schedule(model, runner = nil) ⇒ Object
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 215 def set_wildcard_schedules_to_dominant_building_schedule(model, runner = nil) new_sched_ruleset = OpenStudio::Model::DefaultScheduleSet.new(model) # initialize BTAP.runner_register('Info', 'set_wildcard_schedules_to_dominant_building_schedule', runner) # Set wildcard schedules based on dominant schedule type in building. dominant_sched_type = determine_dominant_necb_schedule_type(model) # puts "dominant_sched_type = #{dominant_sched_type}" # find schedule set that corresponds to dominant schedule type model.getDefaultScheduleSets.sort.each do |sched_ruleset| # just check people schedule # TO DO: should make this smarter: check all schedules people_sched = sched_ruleset.numberofPeopleSchedule people_sched_name = people_sched.get.name.to_s unless people_sched.empty? search_string = "NECB-#{dominant_sched_type}" if people_sched.empty? == false if people_sched_name.include? search_string new_sched_ruleset = sched_ruleset end end end # replace the default schedule set for the space type with * to schedule ruleset with dominant schedule type model.getSpaces.sort.each do |space| # check to see if space space type has a "*" wildcard schedule. spacetype_name = space.spaceType.get.name.to_s unless space.spaceType.empty? if determine_necb_schedule_type(space).to_s == '*'.to_s new_sched = spacetype_name.to_s optional_spacetype = model.getSpaceTypeByName(new_sched) if optional_spacetype.empty? BTAP.runner_register('Error', "Cannot find NECB spacetype #{new_sched}", runner) else BTAP.runner_register('Info', "Setting wildcard spacetype #{spacetype_name} default schedule set to #{new_sched_ruleset.name}", runner) optional_spacetype.get.setDefaultScheduleSet(new_sched_ruleset) # this works! end end end # end of do |space| return true end |
#set_zones_thermostat_schedule_based_on_space_type_schedules(model, runner = nil) ⇒ Object
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1123 def set_zones_thermostat_schedule_based_on_space_type_schedules(model, runner = nil) puts 'in set_zones_thermostat_schedule_based_on_space_type_schedules' BTAP.runner_register('DEBUG', 'Start-set_zones_thermostat_schedule_based_on_space_type_schedules', runner) model.getThermalZones.sort.each do |zone| BTAP.runner_register('DEBUG', "Zone = #{zone.name} Spaces =#{zone.spaces.size} ", runner) array = [] zone.spaces.sort.each do |space| schedule_type = determine_necb_schedule_type(space).to_s BTAP.runner_register('DEBUG', "space name/type:#{space.name}/#{schedule_type}", runner) # if wildcard space type, need to get dominant schedule type if '*'.to_s == schedule_type dominant_sched_type = determine_dominant_necb_schedule_type(model) schedule_type = dominant_sched_type end array << schedule_type end array.uniq! if array.size > 1 BTAP.runner_register('Error', "#{zone.name} has spaces with different schedule types. Please ensure that all the spaces are of the same schedule type A to I.", runner) return false end htg_search_string = "NECB-#{array[0]}-Thermostat Setpoint-Heating" clg_search_string = "NECB-#{array[0]}-Thermostat Setpoint-Cooling" if model.getScheduleRulesetByName(htg_search_string).empty? == false htg_sched = model.getScheduleRulesetByName(htg_search_string).get else BTAP.runner_register('ERROR', "heating_thermostat_setpoint_schedule NECB-#{array[0]} does not exist", runner) return false end if model.getScheduleRulesetByName(clg_search_string).empty? == false clg_sched = model.getScheduleRulesetByName(clg_search_string).get else BTAP.runner_register('ERROR', "cooling_thermostat_setpoint_schedule NECB-#{array[0]} does not exist", runner) return false end name = "NECB-#{array[0]}-Thermostat Dual Setpoint Schedule" # If dual setpoint already exists, use that one, else create one ds = if model.getThermostatSetpointDualSetpointByName(name).empty? == false model.getThermostatSetpointDualSetpointByName(name).get else BTAP::Resources::Schedules.create_annual_thermostat_setpoint_dual_setpoint(model, name, htg_sched, clg_sched) end thermostat_clone = ds.clone.to_ThermostatSetpointDualSetpoint.get zone.setThermostatSetpointDualSetpoint(thermostat_clone) BTAP.runner_register('Info', "ThermalZone #{zone.name} set to DualSetpoint Schedule NECB-#{array[0]}", runner) end BTAP.runner_register('DEBUG', 'END-set_zones_thermostat_schedule_based_on_space_type_schedules', runner) return true end |
#setup_chw_loop_with_components(model, chw_loop, chiller_type) ⇒ Object
of setup_hw_loop_with_components
2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2439 def setup_chw_loop_with_components(model, chw_loop, chiller_type) chw_loop.setName('Chilled Water Loop') sizing_plant = chw_loop.sizingPlant sizing_plant.setLoopType('Cooling') sizing_plant.setDesignLoopExitTemperature(7.0) sizing_plant.setLoopDesignTemperatureDifference(6.0) # pump = OpenStudio::Model::PumpConstantSpeed.new(model) chw_pump = OpenStudio::Model::PumpConstantSpeed.new(model) chiller1 = OpenStudio::Model::ChillerElectricEIR.new(model) chiller2 = OpenStudio::Model::ChillerElectricEIR.new(model) chiller1.setCondenserType('WaterCooled') chiller2.setCondenserType('WaterCooled') chiller1_name = "Primary Chiller WaterCooled #{chiller_type}" chiller1.setName(chiller1_name) chiller2_name = "Secondary Chiller WaterCooled #{chiller_type}" chiller2.setName(chiller2_name) chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model) chw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model) # Add the components to the chilled water loop chw_supply_inlet_node = chw_loop.supplyInletNode chw_supply_outlet_node = chw_loop.supplyOutletNode chw_pump.addToNode(chw_supply_inlet_node) chw_loop.addSupplyBranchForComponent(chiller1) chw_loop.addSupplyBranchForComponent(chiller2) chw_loop.addSupplyBranchForComponent(chiller_bypass_pipe) chw_supply_outlet_pipe.addToNode(chw_supply_outlet_node) # Add a setpoint manager to control the # chilled water to a constant temperature chw_t_c = 7.0 chw_t_sch = BTAP::Resources::Schedules.create_annual_constant_ruleset_schedule(model, 'CHW Temp', 'Temperature', chw_t_c) chw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, chw_t_sch) chw_t_stpt_manager.addToNode(chw_supply_outlet_node) return chiller1, chiller2 end |
#setup_cw_loop_with_components(model, cw_loop, chiller1, chiller2) ⇒ Object
of setup_chw_loop_with_components
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2483 def setup_cw_loop_with_components(model, cw_loop, chiller1, chiller2) cw_loop.setName('Condenser Water Loop') cw_sizing_plant = cw_loop.sizingPlant cw_sizing_plant.setLoopType('Condenser') cw_sizing_plant.setDesignLoopExitTemperature(29.0) cw_sizing_plant.setLoopDesignTemperatureDifference(6.0) cw_pump = OpenStudio::Model::PumpConstantSpeed.new(model) clg_tower = OpenStudio::Model::CoolingTowerSingleSpeed.new(model) # TO DO: Need to define and set cooling tower curves clg_tower_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model) cw_supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model) # Add the components to the condenser water loop cw_supply_inlet_node = cw_loop.supplyInletNode cw_supply_outlet_node = cw_loop.supplyOutletNode cw_pump.addToNode(cw_supply_inlet_node) cw_loop.addSupplyBranchForComponent(clg_tower) cw_loop.addSupplyBranchForComponent(clg_tower_bypass_pipe) cw_supply_outlet_pipe.addToNode(cw_supply_outlet_node) cw_loop.addDemandBranchForComponent(chiller1) cw_loop.addDemandBranchForComponent(chiller2) # Add a setpoint manager to control the # condenser water to constant temperature cw_t_c = 29.0 cw_t_sch = BTAP::Resources::Schedules.create_annual_constant_ruleset_schedule(model, 'CW Temp', 'Temperature', cw_t_c) cw_t_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, cw_t_sch) cw_t_stpt_manager.addToNode(cw_supply_outlet_node) return clg_tower end |
#setup_hw_loop_with_components(model, hw_loop, boiler_fueltype, pump_flow_sch) ⇒ Object
2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 2385 def setup_hw_loop_with_components(model, hw_loop, boiler_fueltype, pump_flow_sch) hw_loop.setName('Hot Water Loop') sizing_plant = hw_loop.sizingPlant sizing_plant.setLoopType('Heating') sizing_plant.setDesignLoopExitTemperature(82.0) # TODO: units sizing_plant.setLoopDesignTemperatureDifference(16.0) # pump (set to variable speed for now till fix to run away plant temperature is found) # pump = OpenStudio::Model::PumpConstantSpeed.new(model) pump = OpenStudio::Model::PumpVariableSpeed.new(model) # TODO: the keyword "setPumpFlowRateSchedule" does not seem to work. A message # was sent to NREL to let them know about this. Once there is a fix for this, # use the proper pump schedule depending on whether we have two-pipe or four-pipe # fan coils. # pump.resetPumpFlowRateSchedule() # pump.setPumpFlowRateSchedule(pump_flow_sch) # boiler boiler1 = OpenStudio::Model::BoilerHotWater.new(model) boiler2 = OpenStudio::Model::BoilerHotWater.new(model) boiler1.setFuelType(boiler_fueltype) boiler2.setFuelType(boiler_fueltype) boiler1.setName('Primary Boiler') boiler2.setName('Secondary Boiler') # boiler_bypass_pipe boiler_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model) # supply_outlet_pipe supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model) # Add the components to the hot water loop hw_supply_inlet_node = hw_loop.supplyInletNode hw_supply_outlet_node = hw_loop.supplyOutletNode pump.addToNode(hw_supply_inlet_node) hw_loop.addSupplyBranchForComponent(boiler1) hw_loop.addSupplyBranchForComponent(boiler2) hw_loop.addSupplyBranchForComponent(boiler_bypass_pipe) supply_outlet_pipe.addToNode(hw_supply_outlet_node) # Add a setpoint manager to control the # hot water based on outdoor temperature hw_oareset_stpt_manager = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model) hw_oareset_stpt_manager.setControlVariable('Temperature') hw_oareset_stpt_manager.setSetpointatOutdoorLowTemperature(82.0) hw_oareset_stpt_manager.setOutdoorLowTemperature(-16.0) hw_oareset_stpt_manager.setSetpointatOutdoorHighTemperature(60.0) hw_oareset_stpt_manager.setOutdoorHighTemperature(0.0) hw_oareset_stpt_manager.addToNode(hw_supply_outlet_node) end |
#space_apply_infiltration_rate(space) ⇒ Double
handle doors and vestibules
Set the infiltration rate for this space to include the impact of air leakage requirements in the standard.
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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb', line 336 def space_apply_infiltration_rate(space) # Remove infiltration rates set at the space type. infiltration_data = @standards_data['infiltration'] unless space.spaceType.empty? space.spaceType.get.spaceInfiltrationDesignFlowRates.each(&:remove) end # Remove infiltration rates set at the space object. space.spaceInfiltrationDesignFlowRates.each(&:remove) exterior_wall_and_roof_and_subsurface_area = space_exterior_wall_and_roof_and_subsurface_area(space) # To do # Don't create an object if there is no exterior wall area if exterior_wall_and_roof_and_subsurface_area <= 0.0 OpenStudio.logFree(OpenStudio::Info, 'openstudio.Standards.Model', "For #{template}, no exterior wall area was found, no infiltration will be added.") return true end # Calculate the total infiltration, assuming # that it only occurs through exterior walls and roofs (not floors as # explicit stated in the NECB2011 so overhang/cantilevered floors will # have no effective infiltration) tot_infil_m3_per_s = self.get_standards_constant('infiltration_rate_m3_per_s_per_m2') * exterior_wall_and_roof_and_subsurface_area # Now spread the total infiltration rate over all # exterior surface area (for the E+ input field) this will include the exterior floor if present. all_ext_infil_m3_per_s_per_m2 = tot_infil_m3_per_s / space.exteriorArea OpenStudio.logFree(OpenStudio::Debug, 'openstudio.Standards.Space', "For #{space.name}, adj infil = #{all_ext_infil_m3_per_s_per_m2.round(8)} m^3/s*m^2.") # Get any infiltration schedule already assigned to this space or its space type # If not, the always on schedule will be applied. infil_sch = nil unless space.spaceInfiltrationDesignFlowRates.empty? old_infil = space.spaceInfiltrationDesignFlowRates[0] if old_infil.schedule.is_initialized infil_sch = old_infil.schedule.get end end if infil_sch.nil? && space.spaceType.is_initialized space_type = space.spaceType.get unless space_type.spaceInfiltrationDesignFlowRates.empty? old_infil = space_type.spaceInfiltrationDesignFlowRates[0] if old_infil.schedule.is_initialized infil_sch = old_infil.schedule.get end end end if infil_sch.nil? infil_sch = space.model.alwaysOnDiscreteSchedule end # Create an infiltration rate object for this space infiltration = OpenStudio::Model::SpaceInfiltrationDesignFlowRate.new(space.model) infiltration.setName("#{space.name} Infiltration") infiltration.setFlowperExteriorSurfaceArea(all_ext_infil_m3_per_s_per_m2) infiltration.setSchedule(infil_sch) infiltration.setConstantTermCoefficient(self.get_standards_constant('infiltration_constant_term_coefficient')) infiltration.setTemperatureTermCoefficient(self.get_standards_constant('infiltration_constant_term_coefficient')) infiltration.setVelocityTermCoefficient(self.get_standards_constant('infiltration_velocity_term_coefficient')) infiltration.setVelocitySquaredTermCoefficient(self.get_standards_constant('infiltration_velocity_squared_term_coefficient')) infiltration.setSpace(space) return true end |
#space_type_apply_internal_loads(space_type, set_people, set_lights, set_electric_equipment, set_gas_equipment, set_ventilation, set_infiltration) ⇒ Bool
Sets the selected internal loads to standards-based or typical values. For each category that is selected get all load instances. Remove all but the first instance if multiple instances. Add a new instance/definition if no instance exists. Modify the definition for the remaining instance to have the specified values. This method does not alter any loads directly assigned to spaces. This method skips plenums.
Also, assign reasonable clothing, air velocity, and work efficiency inputs to allow reasonable thermal comfort metrics to be calculated. to return air, fraction radiant, and fraction visible.
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 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 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 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/beps_compliance_path.rb', line 19 def space_type_apply_internal_loads(space_type, set_people, set_lights, set_electric_equipment, set_gas_equipment, set_ventilation, set_infiltration) # Skip plenums # Check if the space type name # contains the word plenum. if space_type.name.get.to_s.downcase.include?('plenum') return false end if space_type.standardsSpaceType.is_initialized if space_type.standardsSpaceType.get.downcase.include?('plenum') return false end end # Get the space Type data from @standards data spacetype_data = nil if @standards_data['space_types'].is_a?(Hash) == true spacetype_data = @standards_data['space_types']['table'] else spacetype_data = @standards_data['space_types'] end standards_building_type = space_type.standardsBuildingType.is_initialized ? space_type.standardsBuildingType.get : nil standards_space_type = space_type.standardsSpaceType.is_initialized ? space_type.standardsSpaceType.get : nil space_type_properties = spacetype_data.select { |s| (s['building_type'] == standards_building_type) && (s['space_type'] == standards_space_type) }[0] # Need to add a check, or it'll crash on space_type_properties['occupancy_per_area'].to_f below if space_type_properties.nil? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} was not found in the standards data.") return false end # People people_have_info = false occupancy_per_area = space_type_properties['occupancy_per_area'].to_f people_have_info = true unless occupancy_per_area.zero? if set_people && people_have_info # Remove all but the first instance instances = space_type.people.sort if instances.size.zero? # Create a new definition and instance definition = OpenStudio::Model::PeopleDefinition.new(space_type.model) definition.setName("#{space_type.name} People Definition") instance = OpenStudio::Model::People.new(definition) instance.setName("#{space_type.name} People") instance.setSpaceType(space_type) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no people, one has been created.") instances << instance elsif instances.size > 1 instances.each_with_index do |inst, i| next if i.zero? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "Removed #{inst.name} from #{space_type.name}.") inst.remove end end # Modify the definition of the instance space_type.people.sort.each do |inst| definition = inst.peopleDefinition unless occupancy_per_area.zero? definition.setPeopleperSpaceFloorArea(OpenStudio.convert(occupancy_per_area / 1000, 'people/ft^2', 'people/m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set occupancy to #{occupancy_per_area} people/1000 ft^2.") end # set fraction radiant ## definition.setFractionRadiant(0.3) # Clothing schedule for thermal comfort metrics clothing_sch = space_type.model.getScheduleRulesetByName('Clothing Schedule') if clothing_sch.is_initialized clothing_sch = clothing_sch.get else clothing_sch = OpenStudio::Model::ScheduleRuleset.new(space_type.model) clothing_sch.setName('Clothing Schedule') clothing_sch.defaultDaySchedule.setName('Clothing Schedule Default Winter Clothes') clothing_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0) sch_rule = OpenStudio::Model::ScheduleRule.new(clothing_sch) sch_rule.daySchedule.setName('Clothing Schedule Summer Clothes') sch_rule.daySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.5) sch_rule.setStartDate(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(5), 1)) sch_rule.setEndDate(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(9), 30)) end inst.setClothingInsulationSchedule(clothing_sch) # Air velocity schedule for thermal comfort metrics air_velo_sch = space_type.model.getScheduleRulesetByName('Air Velocity Schedule') if air_velo_sch.is_initialized air_velo_sch = air_velo_sch.get else air_velo_sch = OpenStudio::Model::ScheduleRuleset.new(space_type.model) air_velo_sch.setName('Air Velocity Schedule') air_velo_sch.defaultDaySchedule.setName('Air Velocity Schedule Default') air_velo_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.2) end inst.setAirVelocitySchedule(air_velo_sch) # Work efficiency schedule for thermal comfort metrics work_efficiency_sch = space_type.model.getScheduleRulesetByName('Work Efficiency Schedule') if work_efficiency_sch.is_initialized work_efficiency_sch = work_efficiency_sch.get else work_efficiency_sch = OpenStudio::Model::ScheduleRuleset.new(space_type.model) work_efficiency_sch.setName('Work Efficiency Schedule') work_efficiency_sch.defaultDaySchedule.setName('Work Efficiency Schedule Default') work_efficiency_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0) end inst.setWorkEfficiencySchedule(work_efficiency_sch) end end # Lights apply_standard_lights(set_lights, space_type, space_type_properties) # Electric Equipment elec_equip_have_info = false elec_equip_per_area = space_type_properties['electric_equipment_per_area'].to_f elec_equip_frac_latent = space_type_properties['electric_equipment_fraction_latent'].to_f elec_equip_frac_radiant = space_type_properties['electric_equipment_fraction_radiant'].to_f elec_equip_frac_lost = space_type_properties['electric_equipment_fraction_lost'].to_f elec_equip_have_info = true unless elec_equip_per_area.zero? if set_electric_equipment && elec_equip_have_info # Remove all but the first instance instances = space_type.electricEquipment.sort if instances.size.zero? definition = OpenStudio::Model::ElectricEquipmentDefinition.new(space_type.model) definition.setName("#{space_type.name} Elec Equip Definition") instance = OpenStudio::Model::ElectricEquipment.new(definition) instance.setName("#{space_type.name} Elec Equip") instance.setSpaceType(space_type) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no electric equipment, one has been created.") instances << instance elsif instances.size > 1 instances.each_with_index do |inst, i| next if i.zero? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "Removed #{inst.name} from #{space_type.name}.") inst.remove end end # Modify the definition of the instance space_type.electricEquipment.sort.each do |inst| definition = inst.electricEquipmentDefinition unless elec_equip_per_area.zero? definition.setWattsperSpaceFloorArea(OpenStudio.convert(elec_equip_per_area.to_f, 'W/ft^2', 'W/m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set electric EPD to #{elec_equip_per_area} W/ft^2.") end unless elec_equip_frac_latent.zero? definition.setFractionLatent(elec_equip_frac_latent) end unless elec_equip_frac_radiant.zero? definition.setFractionRadiant(elec_equip_frac_radiant) end unless elec_equip_frac_lost.zero? definition.setFractionLost(elec_equip_frac_lost) end end end # Gas Equipment gas_equip_have_info = false gas_equip_per_area = space_type_properties['gas_equipment_per_area'].to_f gas_equip_frac_latent = space_type_properties['gas_equipment_fraction_latent'].to_f gas_equip_frac_radiant = space_type_properties['gas_equipment_fraction_radiant'].to_f gas_equip_frac_lost = space_type_properties['gas_equipment_fraction_lost'].to_f gas_equip_have_info = true unless gas_equip_per_area.zero? if set_gas_equipment && gas_equip_have_info # Remove all but the first instance instances = space_type.gasEquipment.sort if instances.size.zero? definition = OpenStudio::Model::GasEquipmentDefinition.new(space_type.model) definition.setName("#{space_type.name} Gas Equip Definition") instance = OpenStudio::Model::GasEquipment.new(definition) instance.setName("#{space_type.name} Gas Equip") instance.setSpaceType(space_type) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no gas equipment, one has been created.") instances << instance elsif instances.size > 1 instances.each_with_index do |inst, i| next if i.zero? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "Removed #{inst.name} from #{space_type.name}.") inst.remove end end # Modify the definition of the instance space_type.gasEquipment.sort.each do |inst| definition = inst.gasEquipmentDefinition unless gas_equip_per_area.zero? definition.setWattsperSpaceFloorArea(OpenStudio.convert(gas_equip_per_area.to_f, 'Btu/hr*ft^2', 'W/m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set gas EPD to #{elec_equip_per_area} Btu/hr*ft^2.") end unless gas_equip_frac_latent.zero? definition.setFractionLatent(gas_equip_frac_latent) end unless gas_equip_frac_radiant.zero? definition.setFractionRadiant(gas_equip_frac_radiant) end unless gas_equip_frac_lost.zero? definition.setFractionLost(gas_equip_frac_lost) end end end # Ventilation ventilation_have_info = false ventilation_per_area = space_type_properties['ventilation_per_area'].to_f ventilation_per_person = space_type_properties['ventilation_per_person'].to_f ventilation_ach = space_type_properties['ventilation_air_changes'].to_f ventilation_have_info = true unless ventilation_per_area.zero? ventilation_have_info = true unless ventilation_per_person.zero? ventilation_have_info = true unless ventilation_ach.zero? # Get the design OA or create a new one if none exists ventilation = space_type.designSpecificationOutdoorAir if ventilation.is_initialized ventilation = ventilation.get else ventilation = OpenStudio::Model::DesignSpecificationOutdoorAir.new(space_type.model) ventilation.setName("#{space_type.name} Ventilation") space_type.setDesignSpecificationOutdoorAir(ventilation) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no ventilation specification, one has been created.") end if set_ventilation && ventilation_have_info # Modify the ventilation properties ventilation.setOutdoorAirMethod('Sum') unless ventilation_per_area.zero? ventilation.setOutdoorAirFlowperFloorArea(OpenStudio.convert(ventilation_per_area.to_f, 'ft^3/min*ft^2', 'm^3/s*m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set ventilation per area to #{ventilation_per_area} cfm/ft^2.") end unless ventilation_per_person.zero? ventilation.setOutdoorAirFlowperPerson(OpenStudio.convert(ventilation_per_person.to_f, 'ft^3/min*person', 'm^3/s*person').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set ventilation per person to #{ventilation_per_person} cfm/person.") end unless ventilation_ach.zero? ventilation.setOutdoorAirFlowAirChangesperHour(ventilation_ach) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set ventilation to #{ventilation_ach} ACH.") end elsif set_ventilation && !ventilation_have_info # All space types must have a design spec OA # object for ventilation controls to work correctly, # even if the values are all zero. ventilation.setOutdoorAirFlowperFloorArea(0) ventilation.setOutdoorAirFlowperPerson(0) ventilation.setOutdoorAirFlowAirChangesperHour(0) end # Infiltration infiltration_have_info = false infiltration_per_area_ext = space_type_properties['infiltration_per_exterior_area'].to_f infiltration_per_area_ext_wall = space_type_properties['infiltration_per_exterior_wall_area'].to_f infiltration_ach = space_type_properties['infiltration_air_changes'].to_f unless infiltration_per_area_ext.zero? && infiltration_per_area_ext_wall.zero? && infiltration_ach.zero? infiltration_have_info = true end if set_infiltration && infiltration_have_info # Remove all but the first instance instances = space_type.spaceInfiltrationDesignFlowRates.sort if instances.size.zero? instance = OpenStudio::Model::SpaceInfiltrationDesignFlowRate.new(space_type.model) instance.setName("#{space_type.name} Infiltration") instance.setSpaceType(space_type) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} had no infiltration objects, one has been created.") instances << instance elsif instances.size > 1 instances.each_with_index do |inst, i| next if i.zero? OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "Removed #{inst.name} from #{space_type.name}.") inst.remove end end # Modify each instance space_type.spaceInfiltrationDesignFlowRates.sort.each do |inst| unless infiltration_per_area_ext.zero? inst.setFlowperExteriorSurfaceArea(OpenStudio.convert(infiltration_per_area_ext.to_f, 'ft^3/min*ft^2', 'm^3/s*m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set infiltration to #{ventilation_ach} per ft^2 exterior surface area.") end unless infiltration_per_area_ext_wall.zero? inst.setFlowperExteriorWallArea(OpenStudio.convert(infiltration_per_area_ext_wall.to_f, 'ft^3/min*ft^2', 'm^3/s*m^2').get) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set infiltration to #{infiltration_per_area_ext_wall} per ft^2 exterior wall area.") end unless infiltration_ach.zero? inst.setAirChangesperHour(infiltration_ach) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.SpaceType', "#{space_type.name} set infiltration to #{ventilation_ach} ACH.") end end end end |
#thermal_zone_demand_control_ventilation_required?(thermal_zone, climate_zone) ⇒ Bool
Add exception logic for 90.1-2013 for cells, sickrooms, labs, barbers, salons, and bowling alleys
Determine if demand control ventilation (DCV) is required for this zone based on area and occupant density. Does not account for System requirements like ERV, economizer, etc. Those are accounted for in the AirLoopHVAC method of the same name.
1066 1067 1068 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/hvac_systems.rb', line 1066 def thermal_zone_demand_control_ventilation_required?(thermal_zone, climate_zone) return false end |
#water_heater_mixed_apply_efficiency(water_heater_mixed) ⇒ Bool
Applies the standard efficiency ratings and typical losses and paraisitic loads to this object. Efficiency and skin loss coefficient (UA) Per PNNL www.energycodes.gov/sites/default/files/documents/PrototypeModelEnhancements_2014_0.pdf Appendix A: Service Water Heating
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 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 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/openstudio-standards/standards/necb/necb_2011/service_water_heating.rb', line 148 def water_heater_mixed_apply_efficiency(water_heater_mixed) # Get the capacity of the water heater # TODO add capability to pull autosized water heater capacity # if the Sizing:WaterHeater object is ever implemented in OpenStudio. capacity_w = water_heater_mixed.heaterMaximumCapacity if capacity_w.empty? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.WaterHeaterMixed', "For #{water_heater_mixed.name}, cannot find capacity, standard will not be applied.") return false else capacity_w = capacity_w.get end capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get # Get the volume of the water heater # TODO add capability to pull autosized water heater volume # if the Sizing:WaterHeater object is ever implemented in OpenStudio. volume_m3 = water_heater_mixed.tankVolume if volume_m3.empty? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.WaterHeaterMixed', "For #{water_heater_mixed.name}, cannot find volume, standard will not be applied.") return false else volume_m3 = volume_m3.get end volume_gal = OpenStudio.convert(volume_m3, 'm^3', 'gal').get # Get the heater fuel type fuel_type = water_heater_mixed.heaterFuelType unless fuel_type == 'NaturalGas' || fuel_type == 'Electricity' OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.WaterHeaterMixed', "For #{water_heater_mixed.name}, fuel type of #{fuel_type} is not yet supported, standard will not be applied.") end # Calculate the water heater efficiency and # skin loss coefficient (UA) # Calculate the energy factor (EF) # From PNNL http://www.energycodes.gov/sites/default/files/documents/PrototypeModelEnhancements_2014_0.pdf # Appendix A: Service Water Heating water_heater_eff = nil ua_btu_per_hr_per_f = nil sl_btu_per_hr = nil case fuel_type when 'Electricity' volume_l_per_s = volume_m3 * 1000 if capacity_btu_per_hr <= OpenStudio.convert(12, 'kW', 'Btu/hr').get # Fixed water heater efficiency per PNNL water_heater_eff = 1 # Calculate the max allowable standby loss (SL) sl_w = if volume_l_per_s < 270 40 + 0.2 * volume_l_per_s # assume bottom inlet else 0.472 * volume_l_per_s - 33.5 end # assume bottom inlet sl_btu_per_hr = OpenStudio.convert(sl_w, 'W', 'Btu/hr').get else # Fixed water heater efficiency per PNNL water_heater_eff = 1 # Calculate the max allowable standby loss (SL) # use this - NECB does not give SL calculation for cap > 12 kW sl_btu_per_hr = 20 + (35 * Math.sqrt(volume_gal)) end # Calculate the skin loss coefficient (UA) ua_btu_per_hr_per_f = sl_btu_per_hr / 70 when 'NaturalGas' if capacity_btu_per_hr <= 75_000 # Fixed water heater thermal efficiency per PNNL water_heater_eff = 0.82 # Calculate the minimum Energy Factor (EF) base_ef = 0.67 vol_drt = 0.0019 ef = base_ef - (vol_drt * volume_gal) # Calculate the Recovery Efficiency (RE) # based on a fixed capacity of 75,000 Btu/hr # and a fixed volume of 40 gallons by solving # this system of equations: # ua = (1/.95-1/re)/(67.5*(24/41094-1/(re*cap))) # 0.82 = (ua*67.5+cap*re)/cap cap = 75_000.0 re = (Math.sqrt(6724 * ef**2 * cap**2 + 40_409_100 * ef**2 * cap - 28_080_900 * ef * cap + 29_318_000_625 * ef**2 - 58_636_001_250 * ef + 29_318_000_625) + 82 * ef * cap + 171_225 * ef - 171_225) / (200 * ef * cap) # Calculate the skin loss coefficient (UA) # based on the actual capacity. ua_btu_per_hr_per_f = (water_heater_eff - re) * capacity_btu_per_hr / 67.5 else # Thermal efficiency requirement from 90.1 et = 0.8 # Calculate the max allowable standby loss (SL) cap_adj = 800 vol_drt = 110 sl_btu_per_hr = (capacity_btu_per_hr / cap_adj + vol_drt * Math.sqrt(volume_gal)) # Calculate the skin loss coefficient (UA) ua_btu_per_hr_per_f = (sl_btu_per_hr * et) / 70 # Calculate water heater efficiency water_heater_eff = (ua_btu_per_hr_per_f * 70 + capacity_btu_per_hr * et) / capacity_btu_per_hr end end # Convert to SI ua_btu_per_hr_per_c = OpenStudio.convert(ua_btu_per_hr_per_f, 'Btu/hr*R', 'W/K').get # Set the water heater properties # Efficiency water_heater_mixed.setHeaterThermalEfficiency(water_heater_eff) # Skin loss water_heater_mixed.setOffCycleLossCoefficienttoAmbientTemperature(ua_btu_per_hr_per_c) water_heater_mixed.setOnCycleLossCoefficienttoAmbientTemperature(ua_btu_per_hr_per_c) # TODO: Parasitic loss (pilot light) # PNNL document says pilot lights were removed, but IDFs # still have the on/off cycle parasitic fuel consumptions filled in water_heater_mixed.setOnCycleParasiticFuelType(fuel_type) # self.setOffCycleParasiticFuelConsumptionRate(??) water_heater_mixed.setOnCycleParasiticHeatFractiontoTank(0) water_heater_mixed.setOffCycleParasiticFuelType(fuel_type) # self.setOffCycleParasiticFuelConsumptionRate(??) water_heater_mixed.setOffCycleParasiticHeatFractiontoTank(0.8) # set part-load performance curve if fuel_type == 'NaturalGas' plf_vs_plr_curve = model_add_curve(water_heater_mixed.model, 'SWH-EFFFPLR-NECB2011') water_heater_mixed.setPartLoadFactorCurve(plf_vs_plr_curve) end # Append the name with standards information water_heater_mixed.setName("#{water_heater_mixed.name} #{water_heater_eff.round(3)} Therm Eff") OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.WaterHeaterMixed', "For #{template}: #{water_heater_mixed.name}; thermal efficiency = #{water_heater_eff.round(3)}, skin-loss UA = #{ua_btu_per_hr_per_f.round}Btu/hr") return true end |