lib/openstudio-standards/qaqc/hvac.rb in openstudio-standards-0.6.0.rc2 vs lib/openstudio-standards/qaqc/hvac.rb in openstudio-standards-0.6.3

- old
+ new

@@ -31,15 +31,13 @@ # get the weather file run period (as opposed to design day run period) ann_env_pd = nil @sql = @model.sqlFile.get @sql.availableEnvPeriods.each do |env_pd| env_type = @sql.environmentType(env_pd) - if env_type.is_initialized - if env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod') - ann_env_pd = env_pd - break - end + if env_type.is_initialized && (env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod')) + ann_env_pd = env_pd + break end end # only try to get the annual timeseries if an annual simulation was run if ann_env_pd.nil? @@ -96,19 +94,15 @@ end end end # check setpoint manager temperatures against design temperatures - if spm_min_temp_f - if (spm_min_temp_f - design_cooling_sat).abs > max_sizing_temp_delta - check_elems << OpenStudio::Attribute.new('flag', "Minor Error: Air loop '#{air_loop.name}' sizing uses a #{design_cooling_sat.round(1)}F design cooling supply air temperature, but the setpoint manager operates down to #{spm_min_temp_f.round(1)}F.") - end + if spm_min_temp_f && ((spm_min_temp_f - design_cooling_sat).abs > max_sizing_temp_delta) + check_elems << OpenStudio::Attribute.new('flag', "Minor Error: Air loop '#{air_loop.name}' sizing uses a #{design_cooling_sat.round(1)}F design cooling supply air temperature, but the setpoint manager operates down to #{spm_min_temp_f.round(1)}F.") end - if spm_max_temp_f - if (spm_max_temp_f - design_heating_sat).abs > max_sizing_temp_delta - check_elems << OpenStudio::Attribute.new('flag', "Minor Error: Air loop '#{air_loop.name}' sizing uses a #{design_heating_sat.round(1)}F design heating supply air temperature, but the setpoint manager operates up to #{spm_max_temp_f.round(1)}F.") - end + if spm_max_temp_f && ((spm_max_temp_f - design_heating_sat).abs > max_sizing_temp_delta) + check_elems << OpenStudio::Attribute.new('flag', "Minor Error: Air loop '#{air_loop.name}' sizing uses a #{design_heating_sat.round(1)}F design heating supply air temperature, but the setpoint manager operates up to #{spm_max_temp_f.round(1)}F.") end # set expected minimums for operating temperatures expected_min = spm_min_temp_f.nil? ? design_cooling_sat : [design_cooling_sat, spm_min_temp_f].min expected_max = spm_max_temp_f.nil? ? design_heating_sat : [design_heating_sat, spm_max_temp_f].max @@ -131,16 +125,13 @@ reheat_zone = true when 'OS_AirTerminal_SingleDuct_VAV_Reheat' term = equipment.to_AirTerminalSingleDuctVAVReheat.get reheat_op_f = OpenStudio.convert(term.maximumReheatAirTemperature, 'C', 'F').get reheat_zone = true - when 'OS_AirTerminal_SingleDuct_ParallelPIU_Reheat' + when 'OS_AirTerminal_SingleDuct_ParallelPIU_Reheat', 'OS_AirTerminal_SingleDuct_SeriesPIU_Reheat' # reheat_op_f = # Not an OpenStudio input reheat_zone = true - when 'OS_AirTerminal_SingleDuct_SeriesPIU_Reheat' - # reheat_op_f = # Not an OpenStudio input - reheat_zone = true end end # get the zone heating and cooling SAT for sizing sizing_zone = zone.sizingZone @@ -193,11 +184,11 @@ end end # check reasonableness of supply air temperatures when supply air flow rate is operating flow_tolerance = OpenStudio.convert(10.0, 'cfm', 'm^3/s').get operating_temperatures = temperatures.select.with_index { |_t, k| flowrates[k] > flow_tolerance } - operating_temperatures = operating_temperatures.map { |t| (t * 1.8 + 32.0) } + operating_temperatures = operating_temperatures.map { |t| ((t * 1.8) + 32.0) } next if operating_temperatures.empty? runtime_fraction = operating_temperatures.size.to_f / temperatures.size temps_out_of_bounds = operating_temperatures.select { |t| ((t < 40.0) || (t > 110.0) || ((t + max_operating_temp_delta) < expected_min) || ((t - max_operating_temp_delta) > expected_max)) } @@ -492,14 +483,13 @@ elsif model_normalized_flow_rate_ip > air_loop_max_flow_rate_max_warning check_elems << OpenStudio::Attribute.new('flag', "Warning: Flow Rate of #{model_normalized_flow_rate_ip.round(2)} #{air_loop_max_flow_rate_units_ip} for #{air_loop.name.get} is above #{air_loop_max_flow_rate_max_warning.round(2)} #{air_loop_max_flow_rate_units_ip}.") elsif model_normalized_flow_rate_ip > air_loop_max_flow_rate_max_error check_elems << OpenStudio::Attribute.new('flag', "Error: Flow Rate of #{model_normalized_flow_rate_ip.round(2)} #{air_loop_max_flow_rate_units_ip} for #{air_loop.name.get} is above #{air_loop_max_flow_rate_max_error.round(2)} #{air_loop_max_flow_rate_units_ip}.") end - end - # loop through air loops to get max flow rate and cooling capacity. - @model.getAirLoopHVACs.sort.each do |air_loop| + # loop through air loops to get max flow rate and cooling capacity. + # check if DOAS, don't check airflow or cooling capacity if it is sizing_system = air_loop.sizingSystem next if sizing_system.typeofLoadtoSizeOn.to_s == 'VentilationRequirement' # gather argument options for air_loop_cooling_capacity checks @@ -538,11 +528,11 @@ max_error = sizing_benchmarks['zone_heating_capacity']['max_error'] units_ip = sizing_benchmarks['zone_heating_capacity']['units'] @model.getThermalZones.sort.each do |thermal_zone| next if thermal_zone.canBePlenum - next if thermal_zone.exteriorSurfaceArea == 0.0 + next if thermal_zone.exteriorSurfaceArea < 0.01 # check actual against target query = "SELECT Value FROM tabulardatawithstrings WHERE ReportName='#{report_name}' and TableName='#{table_name}' and RowName= '#{thermal_zone.name.get.upcase}' and ColumnName= '#{column_name}'" results = @sql.execAndReturnFirstDouble(query) model_zone_heating_capacity_ip = OpenStudio.convert(results.to_f, 'W/m^2', units_ip).get @@ -746,11 +736,11 @@ # eff values from model motor_eff = component.motorEfficiency # get eff values from standards motor_bhp = std.pump_brake_horsepower(component) - next if motor_bhp == 0.0 + next if motor_bhp < 0.0001 # less than 1 watt standard_minimum_motor_efficiency_and_size = std.pump_standard_minimum_motor_efficiency_and_size(component, motor_bhp)[0] # check actual against target if standard_minimum_motor_efficiency_and_size.nil? @@ -767,11 +757,11 @@ # eff values from model motor_eff = component.motorEfficiency # get eff values from standards motor_bhp = std.pump_brake_horsepower(component) - next if motor_bhp == 0.0 + next if motor_bhp < 0.0001 # less than 1 watt standard_minimum_motor_efficiency_and_size = std.pump_standard_minimum_motor_efficiency_and_size(component, motor_bhp)[0] # check actual against target if standard_minimum_motor_efficiency_and_size.nil? @@ -855,29 +845,27 @@ search_criteria['condenser_type'] = condenser_type next end end # if no match and also no absorption_type then issue warning - if !search_criteria.key?('condenser_type') || search_criteria['condenser_type'].nil? - if !search_criteria.key?('absorption_type') || search_criteria['absorption_type'].nil? - check_elems << OpenStudio::Attribute.new('flag', "Can't find unique search criteria for #{component.name}. #{search_criteria}") - next # don't go past here - end + if (!search_criteria.key?('condenser_type') || search_criteria['condenser_type'].nil?) && + (!search_criteria.key?('absorption_type') || search_criteria['absorption_type'].nil?) + check_elems << OpenStudio::Attribute.new('flag', "Can't find unique search criteria for #{component.name}. #{search_criteria}") + next # don't go past here end elsif search_criteria['cooling_type'] == 'WaterCooled' chiller_air_cooled_condenser_types.each do |compressor_type| if component.name.to_s.include?(compressor_type) search_criteria['compressor_type'] = compressor_type next end end # if no match and also no absorption_type then issue warning - if !search_criteria.key?('compressor_type') || search_criteria['compressor_type'].nil? - if !search_criteria.key?('absorption_type') || search_criteria['absorption_type'].nil? - check_elems << OpenStudio::Attribute.new('flag', "Can't find unique search criteria for #{component.name}. #{search_criteria}") - next # don't go past here - end + if (!search_criteria.key?('compressor_type') || search_criteria['compressor_type'].nil?) && + (!search_criteria.key?('absorption_type') || search_criteria['absorption_type'].nil?) + check_elems << OpenStudio::Attribute.new('flag', "Can't find unique search criteria for #{component.name}. #{search_criteria}") + next # don't go past here end end # lookup chiller capacity_w = std.chiller_electric_eir_find_capacity(component) @@ -1055,11 +1043,11 @@ next unless airloop.thermalZones.size > 1.0 end # skip of brake horsepower is 0 - next if std.fan_brake_horsepower(component) == 0.0 + next if std.fan_brake_horsepower(component) < 0.0001 # less than 1 wat # temp model for use by temp model and target curve model_temp = OpenStudio::Model::Model.new # get coeficents for fan @@ -1283,20 +1271,16 @@ end # check setpoint manager temperatures against design temperatures case plant_loop.sizingPlant.loopType when 'Heating' - if spm_max_temp_f - if (spm_max_temp_f - design_supply_temperature).abs > max_sizing_temp_delta - check_elems << OpenStudio::Attribute.new('flag', "Minor Error: #{plant_loop.name} sizing uses a #{design_supply_temperature.round(1)}F supply water temperature, but the setpoint manager operates up to #{spm_max_temp_f.round(1)}F.") - end + if spm_max_temp_f && ((spm_max_temp_f - design_supply_temperature).abs > max_sizing_temp_delta) + check_elems << OpenStudio::Attribute.new('flag', "Minor Error: #{plant_loop.name} sizing uses a #{design_supply_temperature.round(1)}F supply water temperature, but the setpoint manager operates up to #{spm_max_temp_f.round(1)}F.") end when 'Cooling' - if spm_min_temp_f - if (spm_min_temp_f - design_supply_temperature).abs > max_sizing_temp_delta - check_elems << OpenStudio::Attribute.new('flag', "Minor Error: #{plant_loop.name} sizing uses a #{design_supply_temperature.round(1)}F supply water temperature, but the setpoint manager operates down to #{spm_min_temp_f.round(1)}F.") - end + if spm_min_temp_f && ((spm_min_temp_f - design_supply_temperature).abs > max_sizing_temp_delta) + check_elems << OpenStudio::Attribute.new('flag', "Minor Error: #{plant_loop.name} sizing uses a #{design_supply_temperature.round(1)}F supply water temperature, but the setpoint manager operates down to #{spm_min_temp_f.round(1)}F.") end end # get supply water temperatures for supply outlet node supply_temp_timeseries = @sql.timeSeries(ann_env_pd, 'Timestep', 'System Node Temperature', supply_outlet_node_name) @@ -1326,18 +1310,18 @@ end end # check reasonableness of supply water temperatures when supply water flow rate is operating operating_temperatures = temperatures.select.with_index { |_t, k| flowrates[k] > 1e-8 } - operating_temperatures = operating_temperatures.map { |t| (t * 1.8 + 32.0) } + operating_temperatures = operating_temperatures.map { |t| ((t * 1.8) + 32.0) } if operating_temperatures.empty? check_elems << OpenStudio::Attribute.new('flag', "Warning: Flowrates are all zero in supply node timeseries for '#{plant_loop.name}'") next end - runtime_fraction = operating_temperatures.size.to_f / temperatures.size.to_f + runtime_fraction = operating_temperatures.size / temperatures.size.to_f temps_out_of_bounds = [] case plant_loop.sizingPlant.loopType when 'Heating' design_return_temperature = design_supply_temperature - design_temperature_difference expected_max = spm_max_temp_f.nil? ? design_supply_temperature : [design_supply_temperature, spm_max_temp_f].max @@ -1418,16 +1402,14 @@ # Check each plant loop @model.getPlantLoops.sort.each do |plant_loop| # Set the expected/typical W/gpm loop_type = plant_loop.sizingPlant.loopType case loop_type - when 'Heating' + when 'Heating', 'Condenser' expected_w_per_gpm = 19.0 when 'Cooling' expected_w_per_gpm = 22.0 - when 'Condenser' - expected_w_per_gpm = 19.0 end # Check the W/gpm for each pump on each plant loop plant_loop.supplyComponents.each do |component| # Get the W/gpm for the pump @@ -1495,15 +1477,13 @@ begin # get the weather file run period (as opposed to design day run period) ann_env_pd = nil @sql.availableEnvPeriods.each do |env_pd| env_type = @sql.environmentType(env_pd) - if env_type.is_initialized - if env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod') - ann_env_pd = env_pd - break - end + if env_type.is_initialized && (env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod')) + ann_env_pd = env_pd + break end end # only try to get the annual timeseries if an annual simulation was run if ann_env_pd.nil? @@ -1661,11 +1641,11 @@ # Convert to array ts = ts.get.values plrs = [] for i in 0..(ts.size - 1) - plrs << ts[i] / design_power.to_f + plrs << (ts[i] / design_power.to_f) end # Bin part load ratios bins = OpenstudioStandards::HVAC.hourly_part_load_ratio_bins(plrs) frac_hrs_above_90 = bins[10] @@ -1725,14 +1705,12 @@ # get the weather file run period (as opposed to design day run period) ann_env_pd = nil @sql.availableEnvPeriods.each do |env_pd| env_type = @sql.environmentType(env_pd) - if env_type.is_initialized - if env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod') - ann_env_pd = env_pd - break - end + if env_type.is_initialized && (env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod')) + ann_env_pd = env_pd + break end end # only try to get the annual timeseries if an annual simulation was run if ann_env_pd.nil?