Skip to content

Commit

Permalink
Merging QAQC changes [#46624917]
Browse files Browse the repository at this point in the history
  • Loading branch information
axelstudios committed Jun 28, 2013
1 parent 3dfa117 commit 2bdcbdd
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 151 deletions.
10 changes: 5 additions & 5 deletions openstudiocore/ruby/openstudio/qaqc/CreateQAQCXML.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@
o_model = proj.get.seedModel
else
o_model = dp.model
end
end

#get the optional sql file
o_sql = dp.sqlFile

#perform the check if the model and sql file exist
if not o_model.empty? and not o_sql.empty?

#get the model
model = o_model.get

Expand All @@ -103,7 +103,7 @@

#make a new qaqc report for this model and add it to the overall report
single_qaqc = SingleModelQAQCReport.new
single_qaqc.model_id = "#{dp.uuid.to_s.gsub('{','').gsub('}','')}"
single_qaqc.model_id = "#{dp.name.gsub(/\W/,' ')}"
qaqc_report.add_single_model_qaqc_report(single_qaqc)

#TODO make the selection of env periods more intelligent
Expand Down Expand Up @@ -173,8 +173,8 @@
qaqc_report.add_two_model_comparison_qaqc_report(comparison)

#record uuids of models being compared
comparison.baseline_model_id = "#{base.uuid.to_s.gsub('{','').gsub('}','')}"
comparison.proposed_model_id = "#{dp.uuid.to_s.gsub('{','').gsub('}','')}"
comparison.baseline_model_id = "#{base.name.gsub(/\W/,' ')}"
comparison.proposed_model_id = "#{dp.name.gsub(/\W/,' ')}"

#heating & cooling primary fuel swap
comparison.add_check(heat_cool_fuel_swap_check(base_model,base_sql,dp_model,dp_sql))
Expand Down
19 changes: 17 additions & 2 deletions openstudiocore/ruby/openstudio/qaqc/checks/EUI.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,31 @@ def eui_check(model,sql)
eui_check.category = "General"
eui_check.description = "Check that the EUI of the building is reasonable."
building = model.getBuilding

#make sure all required data are available
if sql.totalSiteEnergy.empty?
eui_check.add_flag(Flag.new($eda,"Site energy data unavailable; check not run"))
return eui_check
end

total_site_energy_GJ = OpenStudio::Quantity.new(sql.totalSiteEnergy.get, $GJ_unit)
total_site_energy_kBtu = OpenStudio::convert(total_site_energy_GJ, $kBtu_unit).get
if total_site_energy_kBtu.value == 0
eui_check.add_flag(Flag.new($eda,"No site energy use was found"))
return eui_check
end
floor_area_m2 = OpenStudio::Quantity.new(building.floorArea, $m2_unit)
floor_area_ft2 = OpenStudio::convert(floor_area_m2, $ft2_unit).get
if floor_area_ft2.value == 0
eui_check.add_flag(Flag.new($eda,"The building has 0 floor area"))
return eui_check
end
site_EUI = total_site_energy_kBtu / floor_area_ft2
if site_EUI.value > 200
eui_check.add_flag(Flag.new($gen_mod,"Site EUI of #{site_EUI} looks high. A hospital or lab (high energy buildings) are around 200 kBtu/ft^2"))
eui_check.add_flag(Flag.new($eda,"Site EUI of #{site_EUI} looks high. A hospital or lab (high energy buildings) are around 200 kBtu/ft^2"))
end
if site_EUI.value < 30
eui_check.add_flag(Flag.new($gen_mod,"Site EUI of #{site_EUI} looks low. A high efficiency office building is around 50 kBtu/ft^2"))
eui_check.add_flag(Flag.new($eda,"Site EUI of #{site_EUI} looks low. A high efficiency office building is around 50 kBtu/ft^2"))
end
debug_puts eui_check.flags.inspect

Expand Down
7 changes: 7 additions & 0 deletions openstudiocore/ruby/openstudio/qaqc/checks/EndUseBreakdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ def enduse_pcts_check(model,sql)
enduse_pcts_check.name = "Energy Enduses Check"
enduse_pcts_check.category = "Xcel EDA"
enduse_pcts_check.description = "Check that heating and cooling energy make up the expected percentage of total energy consumption."

#make sure all required data are available
if sql.electricityCooling.empty? or sql.naturalGasCooling.empty? or sql.otherFuelCooling.empty? or sql.totalSiteEnergy.empty? or sql.electricityHeating.empty? or sql.naturalGasHeating.empty? or sql.otherFuelHeating.empty?
enduse_pcts_check.add_flag(Flag.new($eda,"Enduse energy data unavailable; check not run"))
return enduse_pcts_check
end

pct_cooling = (sql.electricityCooling.get + sql.naturalGasCooling.get + sql.otherFuelCooling.get) / sql.totalSiteEnergy.get
pct_heating = (sql.electricityHeating.get + sql.naturalGasHeating.get + sql.otherFuelHeating.get) / sql.totalSiteEnergy.get
#flag if 0% < pct_cooling < 20%
Expand Down
13 changes: 10 additions & 3 deletions openstudiocore/ruby/openstudio/qaqc/checks/UnmetHrs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ def unmet_hrs_check(model,sql)
heating_setpoint_unmet_query = "SELECT Value FROM TabularDataWithStrings WHERE (ReportName='SystemSummary') AND (ReportForString='Entire Facility') AND (TableName='Time Setpoint Not Met') AND (RowName = 'Facility') AND (ColumnName='During Heating')"
cooling_setpoint_unmet_query = "SELECT Value FROM TabularDataWithStrings WHERE (ReportName='SystemSummary') AND (ReportForString='Entire Facility') AND (TableName='Time Setpoint Not Met') AND (RowName = 'Facility') AND (ColumnName='During Cooling')"
#get the info
heating_setpoint_unmet = get_double(sql, heating_setpoint_unmet_query)
cooling_setpoint_unmet = get_double(sql, cooling_setpoint_unmet_query)
heating_setpoint_unmet = sql.execAndReturnFirstDouble(heating_setpoint_unmet_query)
cooling_setpoint_unmet = sql.execAndReturnFirstDouble(cooling_setpoint_unmet_query)

#make sure all the data are availalbe
if heating_setpoint_unmet.empty? or cooling_setpoint_unmet.empty?
unmet_hrs_check.add_flag(Flag.new($eda,"Hours heating or cooling unmet data unavailable; check not run"))
return unmet_hrs_check
end

#aggregate heating and cooling hrs
heating_or_cooling_setpoint_unmet = heating_setpoint_unmet + cooling_setpoint_unmet
heating_or_cooling_setpoint_unmet = heating_setpoint_unmet.get + cooling_setpoint_unmet.get
#flag if heating + cooling unmet hours > 300
if heating_or_cooling_setpoint_unmet > 300
unmet_hrs_check.add_flag(Flag.new($eda,"Hours heating or cooling unmet is #{heating_or_cooling_setpoint_unmet}; > the Xcel EDA limit of 300 hrs"))
Expand Down
270 changes: 129 additions & 141 deletions openstudiocore/ruby/openstudio/qaqc/utilities/QAQCUtilities.rb
Original file line number Diff line number Diff line change
@@ -1,141 +1,129 @@
#This file defines a bunch of ruby helper methods that make certain openstudio calls simpler in ruby

#load a model into OS & version translates, exiting and erroring if a problem is found
def safe_load_model(model_path_string)
model_path = OpenStudio::Path.new(model_path_string)
if OpenStudio::exists(model_path)
versionTranslator = OpenStudio::OSVersion::VersionTranslator.new
model = versionTranslator.loadModel(model_path)
if model.empty?
puts "Version translation failed for #{model_path_string}"
exit
else
model = model.get
end
else
puts "#{model_path_string} couldn't be found"
exit
end
return model
end

#load a sql file, exiting and erroring if a problem is found
def safe_load_sql(sql_path_string)
sql_path = OpenStudio::Path.new(sql_path_string)
if OpenStudio::exists(sql_path)
sql = OpenStudio::SqlFile.new(sql_path)
else
puts "#{sql_path} couldn't be found"
exit
end
return sql
end

#function to wrap debug == true puts
def debug_puts(puts_text)
if Debug_Mode == true
puts "#{puts_text}"
end
end

#gets a time series data vector from the sql file and puts the values into a standard array of numbers
def get_timeseries_array(openstudio_sql_file, env_period, timestep, variable_name, key_value)
#puts openstudio_sql_file.class
#puts env_period.class
#puts timestep.class
#puts variable_name.class
#puts key_value.class
key_value = key_value.upcase #upper cases the key_value b/c it is always uppercased in the sql file.
#timestep = timestep.capitalize #capitalize the timestep b/c it is always capitalized in the sql file
#timestep = timestep.split(" ").each{|word| word.capitalize!}.join(" ")
#returns an array of all keyValues matching the variable name, envPeriod, and reportingFrequency
#we'll use this to check if the query will work before we send it.
puts "*#{env_period}*#{timestep}*#{variable_name}"
time_series_array = []
puts env_period.class
if env_period.nil?
puts "here"
time_series_array = [nil]
return time_series_array
end
possible_env_periods = openstudio_sql_file.availableEnvPeriods()
if possible_env_periods.nil?
time_series_array = [nil]
return time_series_array
end
possible_timesteps = openstudio_sql_file.availableReportingFrequencies(env_period)
if possible_timesteps.nil?
time_series_array = [nil]
return time_series_array
end
possible_variable_names = openstudio_sql_file.availableVariableNames(env_period,timestep)
if possible_variable_names.nil?
time_series_array = [nil]
return time_series_array
end
possible_key_values = openstudio_sql_file.availableKeyValues(env_period,timestep,variable_name)
if possible_key_values.nil?
time_series_array = [nil]
return time_series_array
end

if possible_key_values.include? key_value and
possible_variable_names.include? variable_name and
possible_env_periods.include? env_period and
possible_timesteps.include? timestep
#the query is valid
time_series = openstudio_sql_file.timeSeries(env_period, timestep, variable_name, key_value)
if time_series #checks to see if time_series exists
time_series = time_series.get.values
debug_puts " #{key_value} time series length = #{time_series.size}"
for i in 0..(time_series.size - 1)
#puts "#{i.to_s} -- #{time_series[i]}"
time_series_array << time_series[i]
end
end
else
#do this if the query is not valid. The comments might help troubleshoot.
time_series_array = [nil]
debug_puts "***The pieces below do NOT make a valid query***"
debug_puts " *#{key_value}* - this key value might not exist for the variable you are looking for"
debug_puts " *#{timestep}* - this value should be Hourly, Monthly, Zone Timestep, HVAC System Timestep, etc"
debug_puts " *#{variable_name}* - every word should be capitalized EG: Refrigeration System Total Compressor Electric Consumption "
debug_puts " *#{env_period}* - you can get an array of all the valid env periods by using the sql_file.availableEnvPeriods() method "
debug_puts " Possible key values: #{possible_key_values}"
debug_puts " Possible Variable Names: #{possible_variable_names}"
debug_puts " Possible run periods: #{possible_env_periods}"
debug_puts " Possible timesteps: #{possible_timesteps}"
end
return time_series_array
end

#gets the average of the numbers in an array
def non_zero_array_average(arr)
debug_puts "average of the entire array = #{arr.inject{ |sum, el| sum + el }.to_f / arr.size}"
arr.delete(0)
debug_puts "average of the non-zero numbers in the array = #{arr.inject{ |sum, el| sum + el }.to_f / arr.size}"
return arr.inject{ |sum, el| sum + el }.to_f / arr.size
end

#method for converting from IP to SI if you know the strings of the input and the output
def ip_to_si(number, ip_unit_string, si_unit_string)
ip_unit = OpenStudio::createUnit(ip_unit_string, "IP".to_UnitSystem).get
si_unit = OpenStudio::createUnit(si_unit_string, "SI".to_UnitSystem).get
#puts "#{ip_unit} --> #{si_unit}"
ip_quantity = OpenStudio::Quantity.new(number, ip_unit)
si_quantity = OpenStudio::convert(ip_quantity, si_unit).get
#puts "#{ip_quantity} = #{si_quantity}"
return si_quantity.value
end

#get a double from the sql file
def get_double(openstudio_sql_file,query)
value = openstudio_sql_file.execAndReturnFirstDouble(query)
if value.empty?
value = "data not found"
puts "***Invalid Query: #{query}"
else
value = value.get
end
return value
end
#This file defines a bunch of ruby helper methods that make certain openstudio calls simpler in ruby

#load a model into OS & version translates, exiting and erroring if a problem is found
def safe_load_model(model_path_string)
model_path = OpenStudio::Path.new(model_path_string)
if OpenStudio::exists(model_path)
versionTranslator = OpenStudio::OSVersion::VersionTranslator.new
model = versionTranslator.loadModel(model_path)
if model.empty?
puts "Version translation failed for #{model_path_string}"
exit
else
model = model.get
end
else
puts "#{model_path_string} couldn't be found"
exit
end
return model
end

#load a sql file, exiting and erroring if a problem is found
def safe_load_sql(sql_path_string)
sql_path = OpenStudio::Path.new(sql_path_string)
if OpenStudio::exists(sql_path)
sql = OpenStudio::SqlFile.new(sql_path)
else
puts "#{sql_path} couldn't be found"
exit
end
return sql
end

#function to wrap debug == true puts
def debug_puts(puts_text)
if Debug_Mode == true
puts "#{puts_text}"
end
end

#gets a time series data vector from the sql file and puts the values into a standard array of numbers
def get_timeseries_array(openstudio_sql_file, env_period, timestep, variable_name, key_value)
#puts openstudio_sql_file.class
#puts env_period.class
#puts timestep.class
#puts variable_name.class
#puts key_value.class
key_value = key_value.upcase #upper cases the key_value b/c it is always uppercased in the sql file.
#timestep = timestep.capitalize #capitalize the timestep b/c it is always capitalized in the sql file
#timestep = timestep.split(" ").each{|word| word.capitalize!}.join(" ")
#returns an array of all keyValues matching the variable name, envPeriod, and reportingFrequency
#we'll use this to check if the query will work before we send it.
puts "*#{env_period}*#{timestep}*#{variable_name}"
time_series_array = []
puts env_period.class
if env_period.nil?
puts "here"
time_series_array = [nil]
return time_series_array
end
possible_env_periods = openstudio_sql_file.availableEnvPeriods()
if possible_env_periods.nil?
time_series_array = [nil]
return time_series_array
end
possible_timesteps = openstudio_sql_file.availableReportingFrequencies(env_period)
if possible_timesteps.nil?
time_series_array = [nil]
return time_series_array
end
possible_variable_names = openstudio_sql_file.availableVariableNames(env_period,timestep)
if possible_variable_names.nil?
time_series_array = [nil]
return time_series_array
end
possible_key_values = openstudio_sql_file.availableKeyValues(env_period,timestep,variable_name)
if possible_key_values.nil?
time_series_array = [nil]
return time_series_array
end

if possible_key_values.include? key_value and
possible_variable_names.include? variable_name and
possible_env_periods.include? env_period and
possible_timesteps.include? timestep
#the query is valid
time_series = openstudio_sql_file.timeSeries(env_period, timestep, variable_name, key_value)
if time_series #checks to see if time_series exists
time_series = time_series.get.values
debug_puts " #{key_value} time series length = #{time_series.size}"
for i in 0..(time_series.size - 1)
#puts "#{i.to_s} -- #{time_series[i]}"
time_series_array << time_series[i]
end
end
else
#do this if the query is not valid. The comments might help troubleshoot.
time_series_array = [nil]
debug_puts "***The pieces below do NOT make a valid query***"
debug_puts " *#{key_value}* - this key value might not exist for the variable you are looking for"
debug_puts " *#{timestep}* - this value should be Hourly, Monthly, Zone Timestep, HVAC System Timestep, etc"
debug_puts " *#{variable_name}* - every word should be capitalized EG: Refrigeration System Total Compressor Electric Consumption "
debug_puts " *#{env_period}* - you can get an array of all the valid env periods by using the sql_file.availableEnvPeriods() method "
debug_puts " Possible key values: #{possible_key_values}"
debug_puts " Possible Variable Names: #{possible_variable_names}"
debug_puts " Possible run periods: #{possible_env_periods}"
debug_puts " Possible timesteps: #{possible_timesteps}"
end
return time_series_array
end

#gets the average of the numbers in an array
def non_zero_array_average(arr)
debug_puts "average of the entire array = #{arr.inject{ |sum, el| sum + el }.to_f / arr.size}"
arr.delete(0)
debug_puts "average of the non-zero numbers in the array = #{arr.inject{ |sum, el| sum + el }.to_f / arr.size}"
return arr.inject{ |sum, el| sum + el }.to_f / arr.size
end

#method for converting from IP to SI if you know the strings of the input and the output
def ip_to_si(number, ip_unit_string, si_unit_string)
ip_unit = OpenStudio::createUnit(ip_unit_string, "IP".to_UnitSystem).get
si_unit = OpenStudio::createUnit(si_unit_string, "SI".to_UnitSystem).get
#puts "#{ip_unit} --> #{si_unit}"
ip_quantity = OpenStudio::Quantity.new(number, ip_unit)
si_quantity = OpenStudio::convert(ip_quantity, si_unit).get
#puts "#{ip_quantity} = #{si_quantity}"
return si_quantity.value
end

0 comments on commit 2bdcbdd

Please sign in to comment.