-
Notifications
You must be signed in to change notification settings - Fork 27
Mech Vent Preconditioning - Loads #753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 12 commits
40b37b2
6f9515d
9359dd4
f1a399c
822bbd6
136c413
a47f8e5
598e235
515e062
d6abdde
ac6c95f
fa5c6eb
735f44d
f08f747
87d7574
d32a3e5
216b73d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2121,7 +2121,7 @@ def self.add_total_loads_output(runner, model, living_zone) | |
| tot_load_sensors[:clg] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Cooling:EnergyTransfer') | ||
| tot_load_sensors[:clg].setName('clg_load_tot') | ||
|
|
||
| # Need to adjusted E+ EnergyTransfer meters for dehumidifiers | ||
| # Need to adjust E+ EnergyTransfer meters for dehumidifiers | ||
| intgain_dehumidifier = nil | ||
| model.getZoneHVACDehumidifierDXs.each do |e| | ||
| next unless e.thermalZone.get.name.to_s == living_zone.name.to_s | ||
|
|
@@ -2138,14 +2138,25 @@ def self.add_total_loads_output(runner, model, living_zone) | |
| program.setName(Constants.ObjectNameTotalLoadsProgram) | ||
| program.addLine('Set loads_htg_tot = 0') | ||
| program.addLine('Set loads_clg_tot = 0') | ||
| # Need to adjust E+ EnergyTransfer meters for mech vent preconditioning | ||
| # Fixme: is it possible to have cooling in hvac but heating in mech vent preconditioning? How to report load in that case? | ||
| # Fixme: Proceed reporting both | ||
| model.getEnergyManagementSystemGlobalVariables.sort.each do |ems_var| | ||
| next unless ems_var.name.to_s.start_with? 'Precond_' | ||
| if ems_var.name.to_s.start_with? 'Precond_HeatingLoad' | ||
| program.addLine("Set loads_htg_tot = loads_htg_tot + #{ems_var.name.get}") | ||
| else | ||
| program.addLine("Set loads_clg_tot = loads_clg_tot + #{ems_var.name.get}") | ||
| end | ||
| end | ||
| program.addLine("If #{liv_load_sensors[:htg].name} > 0") | ||
| s = " Set loads_htg_tot = #{tot_load_sensors[:htg].name} - #{tot_load_sensors[:clg].name}" | ||
| s = " Set loads_htg_tot = loads_htg_tot + #{tot_load_sensors[:htg].name} - #{tot_load_sensors[:clg].name}" | ||
| if not intgain_dehumidifier.nil? | ||
| s += " - #{intgain_dehumidifier.name}" | ||
| end | ||
| program.addLine(s) | ||
| program.addLine("ElseIf #{liv_load_sensors[:clg].name} > 0") | ||
| s = " Set loads_clg_tot = #{tot_load_sensors[:clg].name} - #{tot_load_sensors[:htg].name}" | ||
| s = " Set loads_clg_tot = loads_clg_tot + #{tot_load_sensors[:clg].name} - #{tot_load_sensors[:htg].name}" | ||
| if not intgain_dehumidifier.nil? | ||
| s += " + #{intgain_dehumidifier.name}" | ||
| end | ||
|
|
@@ -2516,6 +2527,15 @@ def self.add_component_loads_output(runner, model, living_zone, liv_load_sensors | |
| mechvent_sensors.each do |sensor| | ||
| program.addLine("Set hr_mechvent = hr_mechvent - #{sensor.name}") | ||
| end | ||
| # Adjust component load reporting for preconditioning | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjust component loads read from equipment objects (add preconditioning loads to mechvent subitem). |
||
| model.getEnergyManagementSystemGlobalVariables.sort.each do |ems_var| | ||
| next unless ems_var.name.to_s.start_with? 'Precond_' | ||
| if ems_var.name.to_s.start_with? 'Precond_HeatingLoad' | ||
| program.addLine("Set hr_mechvent = hr_mechvent + #{ems_var.name.get}") | ||
| else | ||
| program.addLine("Set hr_mechvent = hr_mechvent - #{ems_var.name.get}") | ||
| end | ||
| end | ||
| program.addLine('Set hr_ducts = 0') | ||
| ducts_sensors.each do |duct_sensors| | ||
| s = 'Set hr_ducts = hr_ducts' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
|
|
||
| class Airflow | ||
| def self.apply(model, runner, weather, spaces, hpxml, cfa, nbeds, | ||
| ncfl_ag, duct_systems, nv_clg_ssn_sensor, hvac_map, eri_version, | ||
| ncfl_ag, duct_systems, clg_ssn_sensor, hvac_map, eri_version, | ||
| frac_windows_operable, apply_ashrae140_assumptions) | ||
|
|
||
| # Global variables | ||
|
|
@@ -106,10 +106,10 @@ def self.apply(model, runner, weather, spaces, hpxml, cfa, nbeds, | |
| vented_crawl = foundation | ||
| end | ||
|
|
||
| apply_natural_ventilation_and_whole_house_fan(model, weather, hpxml.site, vent_fans_whf, open_window_area, nv_clg_ssn_sensor) | ||
| apply_natural_ventilation_and_whole_house_fan(model, weather, hpxml.site, vent_fans_whf, open_window_area, clg_ssn_sensor) | ||
| apply_infiltration_and_ventilation_fans(model, weather, hpxml.site, vent_fans_mech, vent_fans_kitchen, vent_fans_bath, vented_dryers, | ||
| hpxml.building_construction.has_flue_or_chimney, hpxml.air_infiltration_measurements, | ||
| vented_attic, vented_crawl, hvac_map) | ||
| vented_attic, vented_crawl, hvac_map, clg_ssn_sensor) | ||
| end | ||
|
|
||
| def self.get_default_fraction_of_windows_operable() | ||
|
|
@@ -1486,6 +1486,8 @@ def self.calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_er | |
| # Calculate mass flow rate based on outdoor air density | ||
| # Address load with flow-weighted combined effectiveness | ||
| infil_program.addLine("Set Fan_MFR = #{q_var} * OASupRho") | ||
| infil_program.addLine('Set ZoneInEnth = OASupInEnth') | ||
| infil_program.addLine('Set ZoneInTemp = OASupInTemp') | ||
| if not vent_mech_erv_hrv_tot.empty? | ||
| # ERV/HRV EMS load model | ||
| # E+ ERV model is using standard density for MFR calculation, caused discrepancy with other system types. | ||
|
|
@@ -1502,14 +1504,12 @@ def self.calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_er | |
| infil_program.addLine('Set ERVTotalHeatTrans = Fan_MFR * (ERVSupOutEnth - OASupInEnth)') | ||
| infil_program.addLine('Set ERVLatHeatTrans = ERVTotalHeatTrans - ERVSensHeatTrans') | ||
| # ERV/HRV Load calculation | ||
| infil_program.addLine('Set FanTotalToLv = Fan_MFR * (ERVSupOutEnth - ZoneAirEnth)') | ||
| infil_program.addLine('Set FanSensToLv = Fan_MFR * ZoneCp * (ERVSupOutTemp - ZoneTemp)') | ||
| infil_program.addLine('Set FanLatToLv = FanTotalToLv - FanSensToLv') | ||
| else | ||
| infil_program.addLine('Set FanTotalToLv = Fan_MFR * (OASupInEnth - ZoneAirEnth)') | ||
| infil_program.addLine('Set FanSensToLv = Fan_MFR * ZoneCp * (OASupInTemp - ZoneTemp)') | ||
| infil_program.addLine('Set FanLatToLv = FanTotalToLv - FanSensToLv') | ||
|
||
| infil_program.addLine('Set ZoneInEnth = ERVSupOutEnth') | ||
| infil_program.addLine('Set ZoneInTemp = ERVSupOutTemp') | ||
| end | ||
| infil_program.addLine('Set FanTotalToLv = Fan_MFR * (ZoneInEnth - ZoneAirEnth)') | ||
| infil_program.addLine('Set FanSensToLv = Fan_MFR * ZoneCp * (ZoneInTemp - ZoneTemp)') | ||
| infil_program.addLine('Set FanLatToLv = FanTotalToLv - FanSensToLv') | ||
|
|
||
| # Actuator, | ||
| # If preconditioned, handle actuators later in calculate_precond_loads | ||
|
|
@@ -1519,12 +1519,25 @@ def self.calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_er | |
| end | ||
| end | ||
|
|
||
| def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map) | ||
| def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map, clg_ssn_sensor) | ||
| # Preconditioning | ||
| # Assume introducing no sensible loads to zone if preconditioned | ||
| if not vent_mech_preheat.empty? | ||
| htg_stp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Thermostat Heating Setpoint Temperature') | ||
| htg_stp_sensor.setName("#{Constants.ObjectNameAirflow} htg stp s") | ||
| htg_stp_sensor.setKeyName(@living_zone.name.to_s) | ||
| infil_program.addLine("Set HtgStp = #{htg_stp_sensor.name}") # heating thermostat setpoint | ||
| end | ||
| if not vent_mech_precool.empty? | ||
| clg_stp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Thermostat Cooling Setpoint Temperature') | ||
| clg_stp_sensor.setName("#{Constants.ObjectNameAirflow} clg stp s") | ||
| clg_stp_sensor.setKeyName(@living_zone.name.to_s) | ||
| infil_program.addLine("Set ClgStp = #{clg_stp_sensor.name}") # cooling thermostat setpoint | ||
| end | ||
| vent_mech_preheat.each_with_index do |f_preheat, i| | ||
| infil_program.addLine('If OASupInTemp < ZoneTemp') | ||
| infil_program.addLine("If (OASupInTemp < HtgStp) && (#{clg_ssn_sensor.name} < 1)") | ||
| htg_energy_actuator = create_other_equipment_object_and_actuator(model: model, name: "shared mech vent preheating energy #{i}", space: @living_space, frac_lat: 0.0, frac_lost: 1.0, hpxml_fuel_type: f_preheat.preheating_fuel, end_use: Constants.ObjectNameMechanicalVentilationPreconditioning) | ||
| htg_load_var = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "Precond_HeatingLoad_#{i}") | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Global variables created here for load reporting. |
||
| hvac_map["#{f_preheat.id}_preheat"] = [htg_energy_actuator.actuatedComponent.get] | ||
| infil_program.addLine(" Set Qpreheat = #{UnitConversions.convert(f_preheat.average_oa_unit_flow_rate, 'cfm', 'm^3/s').round(4)}") | ||
| if [HPXML::MechVentTypeERV, HPXML::MechVentTypeHRV].include? f_preheat.fan_type | ||
|
|
@@ -1534,17 +1547,24 @@ def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_m | |
| end | ||
| calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, 'Qpreheat', true) | ||
|
|
||
| infil_program.addLine(" Set PreHeatingEnergy = (-FanSensToLv) * #{f_preheat.preheating_fraction_load_served}") | ||
| infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} + PreHeatingEnergy") | ||
| infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv") | ||
| infil_program.addLine(" Set #{htg_energy_actuator.name} = PreHeatingEnergy / #{f_preheat.preheating_efficiency_cop}") | ||
| infil_program.addLine(' If ZoneInTemp < HtgStp') | ||
| infil_program.addLine(' Set FanSensToSpt = Fan_MFR * ZoneCp * (ZoneInTemp - HtgStp)') | ||
| infil_program.addLine(" Set PreHeatingWatt = (-FanSensToSpt) * #{f_preheat.preheating_fraction_load_served}") | ||
| infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} + PreHeatingWatt") | ||
| infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv") # Fixme:Does this assumption still apply? | ||
| infil_program.addLine(' Else') | ||
| infil_program.addLine(' Set PreHeatingWatt = 0.0') | ||
| infil_program.addLine(' EndIf') | ||
| infil_program.addLine('Else') | ||
| infil_program.addLine(" Set #{htg_energy_actuator.name} = 0.0") | ||
| infil_program.addLine(' Set PreHeatingWatt = 0.0') | ||
| infil_program.addLine('EndIf') | ||
| infil_program.addLine("Set #{htg_load_var.name.get} = PreHeatingWatt * ZoneTimeStep*3600") | ||
| infil_program.addLine("Set #{htg_energy_actuator.name} = PreHeatingWatt / #{f_preheat.preheating_efficiency_cop}") | ||
| end | ||
| vent_mech_precool.each_with_index do |f_precool, i| | ||
| infil_program.addLine('If OASupInTemp > ZoneTemp') | ||
| infil_program.addLine("If (OASupInTemp > ClgStp) && (#{clg_ssn_sensor.name} > 0)") | ||
| clg_energy_actuator = create_other_equipment_object_and_actuator(model: model, name: "shared mech vent precooling energy #{i}", space: @living_space, frac_lat: 0.0, frac_lost: 1.0, hpxml_fuel_type: f_precool.precooling_fuel, end_use: Constants.ObjectNameMechanicalVentilationPreconditioning) | ||
| clg_load_var = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "Precond_CoolingLoad_#{i}") | ||
| hvac_map["#{f_precool.id}_precool"] = [clg_energy_actuator.actuatedComponent.get] | ||
| infil_program.addLine(" Set Qprecool = #{UnitConversions.convert(f_precool.average_oa_unit_flow_rate, 'cfm', 'm^3/s').round(4)}") | ||
| if [HPXML::MechVentTypeERV, HPXML::MechVentTypeHRV].include? f_precool.fan_type | ||
|
|
@@ -1554,18 +1574,24 @@ def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_m | |
| end | ||
| calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, 'Qprecool', true) | ||
|
|
||
| infil_program.addLine(" Set PreCoolingEnergy = FanSensToLv * #{f_precool.precooling_fraction_load_served}") | ||
| infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} - PreCoolingEnergy") | ||
| infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv") | ||
| infil_program.addLine(" Set #{clg_energy_actuator.name} = PreCoolingEnergy / #{f_precool.precooling_efficiency_cop}") | ||
| infil_program.addLine(' If ZoneInTemp > ClgStp') | ||
| infil_program.addLine(' Set FanSensToSpt = Fan_MFR * ZoneCp * (ZoneInTemp - ClgStp)') | ||
| infil_program.addLine(" Set PreCoolingWatt = FanSensToSpt * #{f_precool.precooling_fraction_load_served}") | ||
| infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} - PreCoolingWatt") | ||
| infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv") # Fixme:Does this assumption still apply? | ||
| infil_program.addLine(' Else') | ||
| infil_program.addLine(' Set PreCoolingWatt = 0.0') | ||
| infil_program.addLine(' EndIf') | ||
| infil_program.addLine('Else') | ||
| infil_program.addLine(" Set #{clg_energy_actuator.name} = 0.0") | ||
| infil_program.addLine(' Set PreCoolingWatt = 0.0') | ||
| infil_program.addLine('EndIf') | ||
| infil_program.addLine("Set #{clg_load_var.name.get} = PreCoolingWatt * ZoneTimeStep*3600") | ||
| infil_program.addLine("Set #{clg_energy_actuator.name} = PreCoolingWatt / #{f_precool.precooling_efficiency_cop}") | ||
| end | ||
| end | ||
|
|
||
| def self.apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_mech, living_ach50, living_const_ach, weather, vent_fans_kitchen, vent_fans_bath, vented_dryers, | ||
| range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map) | ||
| range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map, clg_ssn_sensor) | ||
| # Categorize fans into different types | ||
| vent_mech_preheat = vent_fans_mech.select { |vent_mech| (not vent_mech.preheating_efficiency_cop.nil?) } | ||
| vent_mech_precool = vent_fans_mech.select { |vent_mech| (not vent_mech.precooling_efficiency_cop.nil?) } | ||
|
|
@@ -1640,7 +1666,7 @@ def self.apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_me | |
| calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, 'Qload') | ||
|
|
||
| # Address preconditioning | ||
| calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map) | ||
| calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map, clg_ssn_sensor) | ||
|
|
||
| program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model) | ||
| program_calling_manager.setName("#{infil_program.name} calling manager") | ||
|
|
@@ -1649,7 +1675,7 @@ def self.apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_me | |
| end | ||
|
|
||
| def self.apply_infiltration_and_ventilation_fans(model, weather, site, vent_fans_mech, vent_fans_kitchen, vent_fans_bath, vented_dryers, | ||
| has_flue_chimney, air_infils, vented_attic, vented_crawl, hvac_map) | ||
| has_flue_chimney, air_infils, vented_attic, vented_crawl, hvac_map, clg_ssn_sensor) | ||
| # Get living space infiltration | ||
| living_ach50 = nil | ||
| living_const_ach = nil | ||
|
|
@@ -1687,7 +1713,7 @@ def self.apply_infiltration_and_ventilation_fans(model, weather, site, vent_fans | |
|
|
||
| # Get mechanical ventilation | ||
| apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_mech, living_ach50, living_const_ach, weather, vent_fans_kitchen, vent_fans_bath, vented_dryers, | ||
| range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map) | ||
| range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map, clg_ssn_sensor) | ||
| end | ||
|
|
||
| def self.apply_infiltration_to_living(site, living_ach50, living_const_ach, infil_program, weather, has_flue_chimney) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjust total loads read from E+ output meter