Class: XcelEDAReportingandQAQC

Inherits:
OpenStudio::Measure::ReportingMeasure
  • Object
show all
Includes:
OsLib_CreateResults
Defined in:
lib/measures/XcelEDAReportingandQAQC/measure.rb,
lib/measures/XcelEDAReportingandQAQC/resources/EUI.rb,
lib/measures/XcelEDAReportingandQAQC/resources/UnmetHrs.rb,
lib/measures/XcelEDAReportingandQAQC/resources/EndUseBreakdown.rb,
lib/measures/XcelEDAReportingandQAQC/resources/PeakHeatCoolMonth.rb

Overview

******************************************************************************* OpenStudio®, Copyright © Alliance for Sustainable Energy, LLC. See also openstudio.net/license *******************************************************************************

Instance Method Summary collapse

Methods included from OsLib_CreateResults

#create_results

Instance Method Details

#arguments(model = nil) ⇒ Object

define the arguments that the user will input



21
22
23
24
25
# File 'lib/measures/XcelEDAReportingandQAQC/measure.rb', line 21

def arguments(model = nil)
  args = OpenStudio::Measure::OSArgumentVector.new

  return args
end

#enduse_pcts_checkObject

energy use for cooling and heating as percentage of total energy



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
# File 'lib/measures/XcelEDAReportingandQAQC/resources/EndUseBreakdown.rb', line 11

def enduse_pcts_check
  # summary of the check
  check_elems = OpenStudio::AttributeVector.new
  check_elems << OpenStudio::Attribute.new('name', 'Energy Enduses Check')
  check_elems << OpenStudio::Attribute.new('category', 'Xcel EDA')
  check_elems << OpenStudio::Attribute.new('description', 'Check that heating and cooling energy make up the expected percentage of total energy consumption')

  # aggregators to hold the values
  electricity_cooling = 0
  natural_gas_cooling = 0
  other_fuel_cooling = 0
  total_site_energy = 0
  electricity_heating = 0
  natural_gas_heating = 0
  other_fuel_heating = 0

  # make sure all required data are available
  if @sql.electricityCooling.is_initialized
    electricity_cooling = @sql.electricityCooling.get
  end
  if @sql.naturalGasCooling.is_initialized
    natural_gas_cooling = @sql.naturalGasCooling.get
  end
  if @sql.totalSiteEnergy.is_initialized
    total_site_energy = @sql.totalSiteEnergy.get
  end
  if @sql.electricityHeating.is_initialized
    electricity_heating = @sql.electricityHeating.get
  end
  if @sql.naturalGasHeating.is_initialized
    natural_gas_heating = @sql.naturalGasHeating.get
  end

  other_fuels = ['gasoline', 'diesel', 'coal', 'fuelOilNo1', 'fuelOilNo2', 'propane', 'otherFuel1', 'otherFuel2']
  other_fuel_cooling = 0.0
  other_fuels.each do |fuel|
    other_energy = @sql.instance_eval(fuel + 'Cooling')
    if other_energy.is_initialized
      # sum up all of the "other" fuels
      other_fuel_cooling += other_energy.get
    end
  end
  other_fuel_heating = 0.0
  other_fuels.each do |fuel|
    other_energy = @sql.instance_eval(fuel + 'Heating')
    if other_energy.is_initialized
      # sum up all of the "other" fuels
      other_fuel_heating += other_energy.get
    end
  end

  # if @sql.otherFuelCooling.is_initialized
    # other_fuel_cooling = @sql.otherFuelCooling.get
  # end
  # if @sql.otherFuelHeating.is_initialized
    # other_fuel_heating = @sql.otherFuelHeating.get
  # end

  pct_cooling = (electricity_cooling + natural_gas_cooling + other_fuel_cooling) / total_site_energy
  pct_heating = (electricity_heating + natural_gas_heating + other_fuel_heating) / total_site_energy

  # flag if 0% < pct_cooling < 20%
  if (pct_cooling < 0.0) || (pct_cooling > 0.2)
    check_elems << OpenStudio::Attribute.new('flag', "Cooling energy = #{pct_cooling} of total energy use;  outside of 0%-20% range expected by Xcel EDA")
    @runner.registerWarning("Cooling energy = #{pct_cooling} of total energy use;  outside of 0%-20% range expected by Xcel EDA")
  end

  # flag if 30% < pct_heating < 50%
  if (pct_heating < 0.30) || (pct_heating > 0.50)
    check_elems << OpenStudio::Attribute.new('flag', "Heating energy = #{pct_heating} of total energy use; outside the 30%-50% range expected by Xcel EDA")
    @runner.registerWarning("Heating energy = #{pct_heating} of total energy use; outside the 30%-50% range expected by Xcel EDA")
  end

  check_elem = OpenStudio::Attribute.new('check', check_elems)

  return check_elem
end

#energyPlusOutputRequests(runner, user_arguments) ⇒ Object

return a vector of IdfObject’s to request EnergyPlus objects needed by the run method



28
29
30
31
32
33
34
35
36
37
# File 'lib/measures/XcelEDAReportingandQAQC/measure.rb', line 28

def energyPlusOutputRequests(runner, user_arguments)
  super(runner, user_arguments)

  result = OpenStudio::IdfObjectVector.new

  # Request the day type to use in the peak demand window checks.
  result << OpenStudio::IdfObject.load('Output:Variable,*,Site Day Type Index,timestep;').get

  return result
end

#eui_checkObject

checks the EUI for the whole building



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
# File 'lib/measures/XcelEDAReportingandQAQC/resources/EUI.rb', line 12

def eui_check
  # summary of the check
  check_elems = OpenStudio::AttributeVector.new
  check_elems << OpenStudio::Attribute.new('name', 'EUI Check')
  check_elems << OpenStudio::Attribute.new('category', 'General')
  check_elems << OpenStudio::Attribute.new('description', 'Check that the EUI of the building is reasonable')

  building = @model.getBuilding

  # make sure all required data are available
  if @sql.totalSiteEnergy.empty?
    check_elems << OpenStudio::Attribute.new('flag', 'Site energy data unavailable; check not run')
    @runner.registerWarning('Site energy data unavailable; check not run')
  end

  total_site_energy_kBtu = OpenStudio.convert(@sql.totalSiteEnergy.get, 'GJ', 'kBtu').get
  if total_site_energy_kBtu == 0
    check_elems << OpenStudio::Attribute.new('flag', 'Model site energy use = 0; likely a problem with the model')
    @runner.registerWarning('Model site energy use = 0; likely a problem with the model')
  end

  floor_area_ft2 = OpenStudio.convert(building.floorArea, 'm^2', 'ft^2').get
  if floor_area_ft2 == 0
    check_elems << OpenStudio::Attribute.new('flag', 'The building has 0 floor area')
    @runner.registerWarning('The building has 0 floor area')
  end

  site_EUI = total_site_energy_kBtu / floor_area_ft2
  if site_EUI > 200
    check_elems << OpenStudio::Attribute.new('flag', "Site EUI of #{site_EUI} looks high.  A hospital or lab (high energy buildings) are around 200 kBtu/ft^2")
    @runner.registerWarning("Site EUI of #{site_EUI} looks high.  A hospital or lab (high energy buildings) are around 200 kBtu/ft^2")
  end
  if site_EUI < 30
    check_elems << OpenStudio::Attribute.new('flag', "Site EUI of #{site_EUI} looks low.  A high efficiency office building is around 50 kBtu/ft^2")
    @runner.registerWarning("Site EUI of #{site_EUI} looks low.  A high efficiency office building is around 50 kBtu/ft^2")
  end

  check_elem = OpenStudio::Attribute.new('check', check_elems)

  return check_elem
end

#nameObject

define the name that a user will see, this method may be deprecated as the display name in PAT comes from the name field in measure.xml



16
17
18
# File 'lib/measures/XcelEDAReportingandQAQC/measure.rb', line 16

def name
  return 'XcelEDAReportingandQAQC'
end

#peak_heat_cool_mo_checkObject

peak heating and cooling months



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
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
# File 'lib/measures/XcelEDAReportingandQAQC/resources/PeakHeatCoolMonth.rb', line 11

def peak_heat_cool_mo_check
  # summary of the check
  check_elems = OpenStudio::AttributeVector.new
  check_elems << OpenStudio::Attribute.new('name', 'Peak Heating and Cooling Month Check')
  check_elems << OpenStudio::Attribute.new('category', 'Xcel EDA')
  check_elems << OpenStudio::Attribute.new('description', 'Check that the heating and cooling energy peak during the expected time of year')

  # heating
  heating_electricity_peak_energy = 0
  heating_gas_peak_energy = 0
  heating_other_fuel_peak_energy = 0
  heating_district_cooling_peak_energy = 0
  heating_district_heating_peak_energy = 0
  # cooling
  cooling_electricity_peak_energy = 0
  cooling_gas_peak_energy = 0
  cooling_other_fuel_peak_energy = 0
  cooling_district_cooling_peak_energy = 0
  cooling_district_heating_peak_energy = 0

  # heating
  heating_electricity_peak_mo = 'NotAMonth'.to_MonthOfYear
  heating_gas_peak_mo = 'NotAMonth'.to_MonthOfYear
  heating_other_fuel_peak_mo = 'NotAMonth'.to_MonthOfYear
  heating_district_cooling_peak_mo = 'NotAMonth'.to_MonthOfYear
  heating_district_heating_peak_mo = 'NotAMonth'.to_MonthOfYear
  # cooling
  cooling_electricity_peak_mo = 'NotAMonth'.to_MonthOfYear
  cooling_gas_peak_mo = 'NotAMonth'.to_MonthOfYear
  cooling_other_fuel_peak_mo = 'NotAMonth'.to_MonthOfYear
  cooling_district_cooling_peak_mo = 'NotAMonth'.to_MonthOfYear
  cooling_district_heating_peak_mo = 'NotAMonth'.to_MonthOfYear

  # loop through all of the months, finding the peak month for
  # heating and cooling for each fuel type
  (1..12).each do |month|
    month = OpenStudio::MonthOfYear.new(month)
    heating = 'Heating'.to_EndUseCategoryType
    cooling = 'Cooling'.to_EndUseCategoryType
    electricity = 'Electricity'.to_EndUseFuelType
    gas = 'Gas'.to_EndUseFuelType
    other_fuel = 'OtherFuel_1'.to_EndUseFuelType
    district_cooling = 'DistrictCooling'.to_EndUseFuelType
    district_heating = 'DistrictHeating'.to_EndUseFuelType

    # heating
    if @sql.energyConsumptionByMonth(electricity, heating, month).is_initialized
      if @sql.energyConsumptionByMonth(electricity, heating, month).get > heating_electricity_peak_energy
        heating_electricity_peak_energy = @sql.energyConsumptionByMonth(electricity, heating, month).get
        heating_electricity_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(gas, heating, month).is_initialized
      if @sql.energyConsumptionByMonth(gas, heating, month).get > heating_gas_peak_energy
        heating_gas_peak_energy = @sql.energyConsumptionByMonth(gas, heating, month).get
        heating_gas_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(other_fuel, heating, month).is_initialized
      if @sql.energyConsumptionByMonth(other_fuel, heating, month).get > heating_other_fuel_peak_energy
        heating_other_fuel_peak_energy = @sql.energyConsumptionByMonth(other_fuel, heating, month).get
        heating_other_fuel_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(district_cooling, heating, month).is_initialized
      if @sql.energyConsumptionByMonth(district_cooling, heating, month).get > heating_district_cooling_peak_energy
        heating_district_cooling_peak_energy = @sql.energyConsumptionByMonth(district_cooling, heating, month).get
        heating_district_cooling_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(district_heating, heating, month).is_initialized
      if @sql.energyConsumptionByMonth(district_heating, heating, month).get > heating_district_heating_peak_energy
        heating_district_heating_peak_energy = @sql.energyConsumptionByMonth(district_heating, heating, month).get
        heating_district_heating_peak_mo = month
      end
    end

    # cooling
    if @sql.energyConsumptionByMonth(electricity, cooling, month).is_initialized
      if @sql.energyConsumptionByMonth(electricity, cooling, month).get > cooling_electricity_peak_energy
        cooling_electricity_peak_energy = @sql.energyConsumptionByMonth(electricity, cooling, month).get
        cooling_electricity_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(gas, cooling, month).is_initialized
      if @sql.energyConsumptionByMonth(gas, cooling, month).get > cooling_gas_peak_energy
        cooling_gas_peak_energy = @sql.energyConsumptionByMonth(gas, cooling, month).get
        cooling_gas_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(other_fuel, cooling, month).is_initialized
      if @sql.energyConsumptionByMonth(other_fuel, cooling, month).get > cooling_other_fuel_peak_energy
        cooling_other_fuel_peak_energy = @sql.energyConsumptionByMonth(other_fuel, cooling, month).get
        cooling_other_fuel_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(district_cooling, cooling, month).is_initialized
      if @sql.energyConsumptionByMonth(district_cooling, cooling, month).get > cooling_district_cooling_peak_energy
        cooling_district_cooling_peak_energy = @sql.energyConsumptionByMonth(district_cooling, cooling, month).get
        cooling_district_cooling_peak_mo = month
      end
    end

    if @sql.energyConsumptionByMonth(district_heating, cooling, month).is_initialized
      if @sql.energyConsumptionByMonth(district_heating, cooling, month).get > cooling_district_heating_peak_energy
        cooling_district_heating_peak_energy = @sql.energyConsumptionByMonth(district_heating, cooling, month).get
        cooling_district_heating_peak_mo = month
      end
    end
  end

  # define winter
  winter = ['Dec', 'Jan', 'Feb', 'Mar', 'NotAMonth']

  # define summer
  summer = ['Jun', 'Jul', 'Aug', 'NotAMonth']

  # peak heating should occur during winter for all fuel types
  unless winter.include?(heating_electricity_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak electricity consumption for heating does not occur in winter as expected; it occurs in #{heating_electricity_peak_mo.valueName}")
    @runner.registerWarning("Peak electricity consumption for heating does not occur in winter as expected; it occurs in #{heating_electricity_peak_mo.valueName}")
  end

  unless winter.include?(heating_gas_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak gas consumption for heating does not occur in winter as expected; it occurs in #{heating_gas_peak_mo.valueName}")
    @runner.registerWarning("Peak gas consumption for heating does not occur in winter as expected; it occurs in #{heating_gas_peak_mo.valueName}")
  end

  unless winter.include?(heating_other_fuel_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak other fuel consumption for heating does not occur in winter as expected; it occurs in #{heating_other_fuel_peak_mo.valueName}")
    @runner.registerWarning("Peak other fuel consumption for heating does not occur in winter as expected; it occurs in #{heating_other_fuel_peak_mo.valueName}")
  end

  unless winter.include?(heating_district_cooling_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak district cooling consumption for heating does not occur in winter as expected; it occurs in #{heating_district_cooling_peak_mo.valueName}")
    @runner.registerWarning("Peak district cooling consumption for heating does not occur in winter as expected; it occurs in #{heating_district_cooling_peak_mo.valueName}")
  end

  unless winter.include?(heating_district_heating_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak district heating consumption for heating does not occur in winter as expected; it occurs in #{heating_district_heating_peak_mo.valueName}")
    @runner.registerWarning("Peak district heating consumption for heating does not occur in winter as expected; it occurs in #{heating_district_heating_peak_mo.valueName}")
  end

  # peak cooling should occur during summer for all fuel types
  unless summer.include?(cooling_electricity_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak electricity consumption for cooling does not occur in summer as expected; it occurs in #{cooling_electricity_peak_mo.valueName}")
    @runner.registerWarning("Peak electricity consumption for cooling does not occur in summer as expected; it occurs in #{cooling_electricity_peak_mo.valueName}")
  end

  unless summer.include?(cooling_gas_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak gas consumption for cooling does not occur in summer as expected; it occurs in #{cooling_gas_peak_mo.valueName}")
    @runner.registerWarning("Peak gas consumption for cooling does not occur in summer as expected; it occurs in #{cooling_gas_peak_mo.valueName}")
  end

  unless summer.include?(cooling_other_fuel_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak other fuel consumption for cooling does not occur in summer as expected; it occurs in #{cooling_other_fuel_peak_mo.valueName}")
    @runner.registerWarning("Peak other fuel consumption for cooling does not occur in summer as expected; it occurs in #{cooling_other_fuel_peak_mo.valueName}")
  end

  unless summer.include?(cooling_district_cooling_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak district cooling consumption for cooling does not occur in summer as expected; it occurs in #{cooling_district_cooling_peak_mo.valueName}")
    @runner.registerWarning("Peak district cooling consumption for cooling does not occur in summer as expected; it occurs in #{cooling_district_cooling_peak_mo.valueName}")
  end

  unless summer.include?(cooling_district_heating_peak_mo.valueName)
    check_elems << OpenStudio::Attribute.new('flag', "Peak district heating consumption for cooling does not occur in summer as expected; it occurs in #{cooling_district_heating_peak_mo.valueName}")
    @runner.registerWarning("Peak district heating consumption for cooling does not occur in summer as expected; it occurs in #{cooling_district_heating_peak_mo.valueName}")
  end

  check_elem = OpenStudio::Attribute.new('check', check_elems)

  return check_elem
end

#run(runner, user_arguments) ⇒ Object

define what happens when the measure is run



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
# File 'lib/measures/XcelEDAReportingandQAQC/measure.rb', line 40

def run(runner, user_arguments)
  super(runner, user_arguments)

  # make the runner a class variable
  @runner = runner

  # use the built-in error checking
  if !runner.validateUserArguments(arguments, user_arguments)
    return false
  end

  runner.registerInitialCondition('Starting QAQC report generation')

  # get the last model and sql file
  @model = runner.lastOpenStudioModel
  if @model.is_initialized
    @model = @model.get
  else
    runner.registerError('Cannot find last model.')
    return false
  end

  @sql = runner.lastEnergyPlusSqlFile
  if @sql.is_initialized
    @sql = @sql.get
  else
    runner.registerError('Cannot find last sql file.')
    return false
  end

  # define the time-of-use periods for electricity consumption
  electricity_consumption_tou_periods = [
    {
      'tou_name' => 'system_peak',
      'tou_id' => 1,
      'skip_weekends' => true,
      'skip_holidays' => true,
      'start_mo' => 'June',
      'start_day' => 1,
      'start_hr' => 14,
      'end_mo' => 'September',
      'end_day' => 30,
      'end_hr' => 18
    },
    {
      'tou_name' => 'peak',
      'tou_id' => 2,
      'skip_weekends' => true,
      'skip_holidays' => true,
      'start_mo' => 'January',
      'start_day' => 1,
      'start_hr' => 7,
      'end_mo' => 'December',
      'end_day' => 31,
      'end_hr' => 22
    },
    {
      'tou_name' => 'low_value_spring',
      'tou_id' => 4,
      'skip_weekends' => false,
      'skip_holidays' => false,
      'start_mo' => 'February',
      'start_day' => 1,
      'start_hr' => 0,
      'end_mo' => 'April',
      'end_day' => 30,
      'end_hr' => 6
    },
    {
      'tou_name' => 'low_value_fall',
      'tou_id' => 4,
      'skip_weekends' => false,
      'skip_holidays' => false,
      'start_mo' => 'November',
      'start_day' => 1,
      'start_hr' => 0,
      'end_mo' => 'November',
      'end_day' => 30,
      'end_hr' => 6
    },
    {
      'tou_name' => 'average',
      'tou_id' => 3,
      'skip_weekends' => false,
      'skip_holidays' => false,
      'start_mo' => 'January',
      'start_day' => 1,
      'start_hr' => 0,
      'end_mo' => 'December',
      'end_day' => 31,
      'end_hr' => 24
    }
  ]

  # vector to store the results and checks
  report_elems = OpenStudio::AttributeVector.new
  report_elems << create_results(skip_weekends = true,
                                 skip_holidays = true,
                                 start_mo = 'June',
                                 start_day = 1,
                                 start_hr = 14,
                                 end_mo = 'September',
                                 end_day = 30,
                                 end_hr = 18,
                                 electricity_consumption_tou_periods)

  # create an attribute vector to hold the checks
  check_elems = OpenStudio::AttributeVector.new

  # unmet hours check
  check_elems << unmet_hrs_check

  # energy use for cooling and heating as percentage of total energy check
  check_elems << enduse_pcts_check

  # peak heating and cooling months check
  check_elems << peak_heat_cool_mo_check

  # EUI check
  check_elems << eui_check

  # Register Values for all of the checks
  check_elems.each do |check|
    check_uid = OpenStudio.removeBraces(OpenStudio.createUUID)
    # loop through attributes (name,category,description,then optionally one or more flag attributes)
    check.valueAsAttributeVector.each_with_index do |value, index|
      if index == 0 # name
        runner.registerValue("qaqc_name_#{check_uid}", value.valueAsString)
      elsif index == 1 # category
        runner.registerValue("qaqc_cat_#{check_uid}", value.valueAsString)
      elsif index == 2 # description
        runner.registerValue("qaqc_desc_#{check_uid}", value.valueAsString)
      else # flag
        flag_uid = OpenStudio.removeBraces(OpenStudio.createUUID)
        runner.registerValue("qaqc_flag_#{check_uid}_#{flag_uid}", value.valueAsString)
      end
    end
  end

  # end checks
  report_elems << OpenStudio::Attribute.new('checks', check_elems)

  # create an extra layer of report.  the first level gets thrown away.
  top_level_elems = OpenStudio::AttributeVector.new
  top_level_elems << OpenStudio::Attribute.new('report', report_elems)

  # create the report
  result = OpenStudio::Attribute.new('summary_report', top_level_elems)
  result.saveToXml(OpenStudio::Path.new('report.xml'))

  # closing the sql file
  @sql.close

  # reporting final condition
  runner.registerFinalCondition('Finished generating report.xml.')

  return true
end

#unmet_hrs_checkObject

checks the number of unmet hours in the model



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
# File 'lib/measures/XcelEDAReportingandQAQC/resources/UnmetHrs.rb', line 12

def unmet_hrs_check
  # summary of the check
  check_elems = OpenStudio::AttributeVector.new
  check_elems << OpenStudio::Attribute.new('name', 'Unmet Hours Check')
  check_elems << OpenStudio::Attribute.new('category', 'General')
  check_elems << OpenStudio::Attribute.new('description', 'Check that the heating and cooling systems are meeting their setpoints for the entire simulation period')

  # setup the queries
  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 = @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? || cooling_setpoint_unmet.empty?
    check_elems << OpenStudio::Attribute.new('flag', 'Hours heating or cooling unmet data unavailable; check not run')
    @runner.registerWarning('Hours heating or cooling unmet data unavailable; check not run')
  end

  # aggregate heating and cooling hrs
  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
    check_elems << OpenStudio::Attribute.new('flag', "Hours heating or cooling unmet is #{heating_or_cooling_setpoint_unmet}; > the Xcel EDA limit of 300 hrs")
    @runner.registerWarning("Hours heating or cooling unmet is #{heating_or_cooling_setpoint_unmet}; > the Xcel EDA limit of 300 hrs")
  end

  check_elem = OpenStudio::Attribute.new('check', check_elems)

  return check_elem
end