Class: BuildingSync::Scenario

Inherits:
Object
  • Object
show all
Includes:
Helper, XmlGetSet
Defined in:
lib/buildingsync/scenario.rb

Overview

Scenario class

Instance Method Summary collapse

Methods included from XmlGetSet

#get_prefix, #xget_attribute_for_element, #xget_element, #xget_id, #xget_idrefs, #xget_linked_premises, #xget_name, #xget_or_create, #xget_plurals_text_value, #xget_text, #xget_text_as_bool, #xget_text_as_date, #xget_text_as_dt, #xget_text_as_float, #xget_text_as_integer, #xset_or_create, #xset_text

Methods included from Helper

#help_calculate_hours, #help_convert, #help_count_number_of_days, #help_element_class_type_check, #help_get_attribute_value, #help_get_default_schedule_set, #help_get_duration, #help_get_end_time, #help_get_end_time_sat, #help_get_end_time_sun, #help_get_end_time_weekday, #help_get_or_create, #help_get_schedule_rule_set_from_schedule, #help_get_start_time, #help_get_start_time_sat, #help_get_start_time_sun, #help_get_start_time_weekday, #help_get_text_value, #help_get_text_value_as_bool, #help_get_text_value_as_date, #help_get_text_value_as_datetime, #help_get_text_value_as_float, #help_get_text_value_as_integer, #help_get_zone_name_list, #help_load_doc, #help_print_all_schedules, #help_print_schedule, #help_write_profile

Constructor Details

#initialize(base_xml, ns) ⇒ Scenario

Returns a new instance of Scenario.



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
# File 'lib/buildingsync/scenario.rb', line 54

def initialize(base_xml, ns)
  @base_xml = base_xml
  @ns = ns

  help_element_class_type_check(base_xml, 'Scenario')

  # Helpful
  @site_eui_xpath = "#{@ns}:AllResourceTotals/#{@ns}:AllResourceTotal/#{@ns}:SiteEnergyUseIntensity"
  @g = BuildingSync::Generator.new(@ns)

  # linked fields
  @resource_uses = [] # Array[<BuildingSync::ResourceUse>]
  @time_series_data = [] # Array[<BuildingSync::TimeSeries]
  @all_resource_totals = [] # Array[<REXML::Element>] of AllResourceTotal

  # Simulation relevant fields
  @main_output_dir = nil
  @osw_dir = nil
  @workflow = {} # Hash to hold the workflow, see set_workflow
  @results_file_name = 'results.json' # holds annual and monthly results
  @eplustbl_file_name = 'eplustbl.htm' # holds source energy results
  @out_osw_file_name = 'out.osw' # holds the completion status of the simulation
  @out_osw_json = nil # Hash to hold the read in of out.osw
  @results_json = nil # Hash to hold the read in of results.json

  # Define mappings for native units by Resource Use
  @native_units_map = {
    'Electricity' => 'kWh',
    'Natural gas' => 'kBtu'
  }

  # Define a mapping between BuildingSync concepts to openstudio concepts
  # available in the results.json file
  @bsync_openstudio_resources_map = {
    'IP' => {
      'ResourceUse' => [
        {
          'EnergyResource' => 'Electricity',
          'EndUse' => 'All end uses',
          'fields' => [
            {
              # AnnualFuelUseConsistentUnits is in MMBtu/yr
              'bsync_element_name' => 'AnnualFuelUseConsistentUnits',
              'bsync_element_units' => 'MMBtu',
              'os_results_key' => 'fuel_electricity',
              'os_results_unit' => 'kBtu'
            },
            {
              'bsync_element_name' => 'AnnualPeakConsistentUnits',
              'bsync_element_units' => 'kW',
              'os_results_key' => 'annual_peak_electric_demand',
              'os_results_unit' => 'kW'
            }
          ],
          'monthly' => {
            # [bracket text] is replaced when processed
            'text' => 'electricity_ip_[month]',
            'os_results_unit' => 'kWh'
          }
        },
        {
          'EnergyResource' => 'Natural gas',
          'EndUse' => 'All end uses',
          'fields' => [
            {
              # AnnualFuelUseConsistentUnits is in MMBtu/yr
              'bsync_element_name' => 'AnnualFuelUseConsistentUnits',
              'bsync_element_units' => 'MMBtu',
              'os_results_key' => 'fuel_natural_gas',
              'os_results_unit' => 'kBtu'
            }
          ],
          'monthly' => {
            # [bracket text] is replaced when processed
            'text' => 'natural_gas_ip_[month]',
            'os_results_unit' => 'MMBtu'
          }
        }
      ],
      'AllResourceTotal' => [
        {
          'EndUse' => 'All end uses',
          'fields' => [
            {
              'bsync_element_name' => 'SiteEnergyUse',
              'bsync_element_units' => 'kBtu',
              'os_results_key' => 'total_site_energy',
              'os_results_unit' => 'kBtu'
            },
            {
              'bsync_element_name' => 'SiteEnergyUseIntensity',
              'bsync_element_units' => 'kBtu/ft^2',
              'os_results_key' => 'total_site_eui',
              'os_results_unit' => 'kBtu/ft^2'
            }
          ]
        }
      ]
    }
  }

  read_xml

  # Removes data from POM and CB Modeled on import
  if !get_scenario_type_child_element.nil? && (pom? || cb_modeled?)
    delete_previous_results
  end
end

Instance Method Details

#add_fields_from_map(fields, os_results, parent_xml) ⇒ Object



530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
# File 'lib/buildingsync/scenario.rb', line 530

def add_fields_from_map(fields, os_results, parent_xml)
  fields.each do |field|
    os_results_val = os_results[field['os_results_key']]
    if os_results_val.nil?
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.parse_annual_results', "Scenario ID: #{xget_id}.  Unable to find result for #{field['os_results_key']}")
    else
      if field['os_results_unit'] == field['bsync_element_units']
        # Parent element
        new_element = REXML::Element.new("#{@ns}:#{field['bsync_element_name']}", parent_xml)
        new_element.text = os_results_val
      else
        converted = help_convert(os_results_val, field['os_results_unit'], field['bsync_element_units'])
        if !converted.nil?
          new_element = REXML::Element.new("#{@ns}:#{field['bsync_element_name']}", parent_xml)
          new_element.text = converted
        end
      end
    end
  end
end

#add_source_energy(all_resource_total_xml) ⇒ Object



494
495
496
497
498
499
500
501
502
503
504
505
# File 'lib/buildingsync/scenario.rb', line 494

def add_source_energy(all_resource_total_xml)
  eplustbl_file = File.join(get_osw_dir, @eplustbl_file_name)
  if !File.exist?(eplustbl_file)
    OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Scenario.add_source_energy', "Scenario ID: #{xget_id}.  #{@eplustbl_file_name} does not exist, cannot add source energy results")
  else
    source_energy, source_eui = get_source_energy_array(eplustbl_file)
    source_energy_xml = REXML::Element.new("#{@ns}:SourceEnergyUse", all_resource_total_xml)
    source_energy_xml.text = source_energy
    source_eui_xml = REXML::Element.new("#{@ns}:SourceEnergyUseIntensity", all_resource_total_xml)
    source_eui_xml.text = source_eui
  end
end

#benchmark?Boolean

Returns:

  • (Boolean)


615
616
617
618
619
620
# File 'lib/buildingsync/scenario.rb', line 615

def benchmark?
  if xget_element('ScenarioType').nil?
    return false
  end
  return check_scenario_type("./#{@ns}:Benchmark")
end

#cb_measured?Boolean

Returns:

  • (Boolean)


587
588
589
590
591
592
# File 'lib/buildingsync/scenario.rb', line 587

def cb_measured?
  if xget_element('ScenarioType').nil?
    return false
  end
  return check_scenario_type("./#{@ns}:CurrentBuilding/#{@ns}:CalculationMethod/#{@ns}:Measured")
end

#cb_modeled?Boolean

Returns:

  • (Boolean)


594
595
596
597
598
599
# File 'lib/buildingsync/scenario.rb', line 594

def cb_modeled?
  if xget_element('ScenarioType').nil?
    return false
  end
  return check_scenario_type("./#{@ns}:CurrentBuilding/#{@ns}:CalculationMethod/#{@ns}:Modeled")
end

#check_scenario_type(path) ⇒ Object



578
579
580
581
582
583
584
585
# File 'lib/buildingsync/scenario.rb', line 578

def check_scenario_type(path)
  to_check = xget_element('ScenarioType').get_elements(path)
  if !to_check.nil? && !to_check.empty?
    return true
  else
    return false
  end
end

#delete_previous_results(all = false) ⇒ Object

delete previous results from the Scenario. This only affects POM or cb_modeled scenarios, unless all = true is passed



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/buildingsync/scenario.rb', line 274

def delete_previous_results(all = false)
  if pom?
    get_scenario_type_child_element.elements.delete("#{@ns}:AnnualSavingsSiteEnergy")
    get_scenario_type_child_element.elements.delete("#{@ns}:AnnualSavingsCost")
    get_scenario_type_child_element.elements.delete("#{@ns}:CalculationMethod")
    get_scenario_type_child_element.elements.delete("#{@ns}AnnualSavingsByFuels")
  end

  # Delete elements from the xml and reset the attributes to empty
  if pom? || cb_modeled? || all
    get_scenario_type_child_element.elements.delete("#{@ns}AllResourceTotals")
    get_scenario_type_child_element.elements.delete("#{@ns}ResourceUses")
    @resource_uses = []
    @all_resource_totals = []
  end
end

#get_all_end_use_resource_usesObject



188
189
190
# File 'lib/buildingsync/scenario.rb', line 188

def get_all_end_use_resource_uses
  return @resource_uses.each.select { |ru| ru.xget_text('EndUse') == 'All end uses' }
end

#get_all_resource_totalsArray<REXML::Element>

Returns:

  • (Array<REXML::Element>)


193
194
195
# File 'lib/buildingsync/scenario.rb', line 193

def get_all_resource_totals
  return @all_resource_totals
end

#get_benchmark_toolObject



218
219
220
221
# File 'lib/buildingsync/scenario.rb', line 218

def get_benchmark_tool
  child = get_scenario_type_child_element
  return help_get_text_value(child.elements["#{@ns}:BenchmarkTool"])
end

#get_main_output_dirString

Returns:

  • (String)


208
209
210
# File 'lib/buildingsync/scenario.rb', line 208

def get_main_output_dir
  return @main_output_dir
end

#get_measure_idsArray<String>

Returns:

  • (Array<String>)


179
180
181
# File 'lib/buildingsync/scenario.rb', line 179

def get_measure_ids
  return xget_idrefs('MeasureID')
end

#get_osw_dirString

get osw dir

Returns:

  • (String)

    directory to the new osw_dir



214
215
216
# File 'lib/buildingsync/scenario.rb', line 214

def get_osw_dir
  return @osw_dir
end

#get_resource_usesArray<BuildingSync::ResourceUse>

Returns:



184
185
186
# File 'lib/buildingsync/scenario.rb', line 184

def get_resource_uses
  return @resource_uses
end

#get_scenario_type_child_elementREXML::Element

Returns:

  • (REXML::Element)


171
172
173
174
175
176
# File 'lib/buildingsync/scenario.rb', line 171

def get_scenario_type_child_element
  scenario_type = xget_element('ScenarioType')
  if !scenario_type.nil?
    scenario_type.get_elements('*')[0]
  end
end

#get_source_energy_array(eplustbl_path) ⇒ Array

Get source energy and source EUI from

Parameters:

  • eplustbl_path (String)

Returns:

  • (Array)
    total_source_energy_kbtu, total_source_eui_kbtu_ft2


510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'lib/buildingsync/scenario.rb', line 510

def get_source_energy_array(eplustbl_path)
  # DLM: total hack because these are not reported in the out.osw
  # output is array of [source_energy, source_eui] in kBtu and kBtu/ft2
  result = []
  File.open(eplustbl_path, 'r') do |f|
    while line = f.gets
      if /\<td align=\"right\"\>Total Source Energy\<\/td\>/.match?(line)
        result << /\<td align=\"right\"\>(.*?)<\/td\>/.match(f.gets)[1].to_f
        result << /\<td align=\"right\"\>(.*?)<\/td\>/.match(f.gets)[1].to_f
        break
      end
    end
  end

  result[0] = result[0] * 947.8171203133 # GJ to kBtu
  result[1] = result[1] * 0.947817120313 * 0.092903 # MJ/m2 to kBtu/ft2

  return result[0], result[1]
end

#get_time_series_dataArray<BuildingSync::TimeSeries>

Returns:



198
199
200
# File 'lib/buildingsync/scenario.rb', line 198

def get_time_series_data
  return @time_series_data
end

#get_workflowHash

Returns:

  • (Hash)


203
204
205
# File 'lib/buildingsync/scenario.rb', line 203

def get_workflow
  return @workflow
end

#os_add_all_resource_totals(results) ⇒ Object



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
# File 'lib/buildingsync/scenario.rb', line 467

def os_add_all_resource_totals(results)
  ip_map = @bsync_openstudio_resources_map['IP']
  os_results = results['OpenStudioResults']

  # Loop through ResourceUses in the resource_use_map
  ip_map['AllResourceTotal'].each do |map|
    end_use = map['EndUse']

    # Check if an AllResourceTotal of the desired type already exists
    element = @base_xml.get_elements("./#{@ns}:AllResourceTotals/#{@ns}:AllResourceTotal[#{@ns}:EndUse/text() = '#{end_use}']")

    # Add a new ResourceUse xml to the Scenario
    if element.nil? || element.empty?
      art_id = "#{xget_id}-AllResourceTotal-#{end_use.split.map(&:capitalize).join('')}"
      all_resource_total_xml = @g.add_all_resource_total_to_scenario(@base_xml, end_use, art_id)
    else
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Scenario.parse_annual_results', "Scenario ID: #{xget_id}.  Resource Use of type: #{ru_type} and end use: #{end_use} already exists")
      all_resource_total_xml = element.first
    end

    add_fields_from_map(map['fields'], os_results, all_resource_total_xml)
    # add_source_energy(all_resource_total_xml)

    @all_resource_totals << BuildingSync::AllResourceTotal.new(all_resource_total_xml, @ns)
  end
end

#os_add_resource_uses(results) ⇒ Object

Use the bsync to openstudio resources map to add results from the openstudio simulations as new ResourceUse elements and objects

Parameters:

  • results (Hash)

    a hash of the results as directly read in from a results.json file



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/buildingsync/scenario.rb', line 436

def os_add_resource_uses(results)
  @results_json = results
  ip_map = @bsync_openstudio_resources_map['IP']
  os_results = @results_json['OpenStudioResults']

  # Loop through ResourceUses in the resource_use_map
  ip_map['ResourceUse'].each do |resource_use_map|
    ru_type = resource_use_map['EnergyResource']
    end_use = resource_use_map['EndUse']
    native_units = @native_units_map[ru_type]

    # Check if a ResourceUse of the desired type already exists
    resource_use_element = @base_xml.get_elements("./#{@ns}:ResourceUses/#{@ns}:ResourceUse[#{@ns}:EnergyResource/text() = '#{ru_type}' and #{@ns}:EndUse/text() = '#{end_use}']")

    # Add a new ResourceUse xml to the Scenario.  This also adds ResourceUses if not defined
    if resource_use_element.nil? || resource_use_element.empty?
      ru_id = "#{xget_id}-ResourceUse-#{ru_type.split.map(&:capitalize).join('')}-#{end_use.split.map(&:capitalize).join('')}"
      resource_use_xml = @g.add_energy_resource_use_to_scenario(@base_xml, ru_type, end_use, ru_id, native_units)
    else
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Scenario.parse_annual_results', "Scenario ID: #{xget_id}.  Resource Use of type: #{ru_type} and end use: #{end_use} already exists")
      resource_use_xml = resource_use_element.first
    end

    # Map in the fields for each ResourceUse element into the xml
    add_fields_from_map(resource_use_map['fields'], os_results, resource_use_xml)

    # Add ResourceUse to array
    @resource_uses << BuildingSync::ResourceUse.new(resource_use_xml, @ns)
  end
end

#os_gather_results(year_val) ⇒ Object



376
377
378
379
380
381
382
383
384
385
# File 'lib/buildingsync/scenario.rb', line 376

def os_gather_results(year_val)
  if simulation_success? && results_available_and_correct_units?
    os_parse_annual_results
    os_parse_monthly_all_end_uses_results(year_val)
  elsif !simulation_success?
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.os_gather_results', "Scenario ID: #{xget_id}. Unable to gather results as simulation was unsuccessful.")
  elsif !results_available_and_correct_units?
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.os_gather_results', "Scenario ID: #{xget_id}. Unable to gather results as results are not available.")
  end
end

#os_parse_annual_results(results = @results_json) ⇒ Object



387
388
389
390
# File 'lib/buildingsync/scenario.rb', line 387

def os_parse_annual_results(results = @results_json)
  os_add_resource_uses(results)
  os_add_all_resource_totals(results)
end

#os_parse_monthly_all_end_uses_results(year_val = Date.today.year, results = @results_json) ⇒ Object



392
393
394
395
396
397
398
399
400
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
# File 'lib/buildingsync/scenario.rb', line 392

def os_parse_monthly_all_end_uses_results(year_val = Date.today.year, results = @results_json)
  if results_available_and_correct_units?(results)
    time_series_data_xml = xget_or_create('TimeSeriesData')
    resource_use_map = @bsync_openstudio_resources_map['IP']['ResourceUse']
    os_results = results['OpenStudioResults']
    get_all_end_use_resource_uses.each do |resource_use|
      resource_use_hash = resource_use_map.each.find { |h| h['EnergyResource'] == resource_use.xget_text('EnergyResource') && h['EndUse'] == 'All end uses' }
      if resource_use_hash.nil?
        OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.os_parse_monthly_all_end_uses_results', "Scenario ID: #{xget_id}: Unable to find mapping for ResourceUse: #{resource_use.xget_id} and 'All end uses'. Cannot parse monthly results")
      else
        monthly_text = resource_use_hash['monthly']['text']
        monthly_units = resource_use_hash['monthly']['os_results_unit']
        native_units = @native_units_map[resource_use.xget_text('EnergyResource')]
        (1..12).each do |month|
          start_date_time = DateTime.new(year_val, month, 1)

          # substitues [month] with oct, for example, so we get electricity_ip_oct
          key_to_find = monthly_text.gsub('[month]', start_date_time.strftime('%b').downcase)
          if os_results.key?(key_to_find)
            # We always use the first day of the month as the start day
            time_series_xml = REXML::Element.new("#{@ns}:TimeSeries", time_series_data_xml)
            time_series_xml.add_attribute('ID', "TS-#{start_date_time.strftime('%b').upcase}-#{resource_use.xget_id}")

            # Convert value to correct units
            interval_reading_value = help_convert(os_results[key_to_find], monthly_units, native_units)

            # Create new TimeSeries element
            ts = BuildingSync::TimeSeries.new(time_series_xml, @ns)
            ts.set_monthly_energy_reading(start_date_time.dup, interval_reading_value, resource_use.xget_id)

          else
            OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.os_parse_monthly_all_end_uses_results', "Scenario ID: #{xget_id}: Key #{key_to_find} not found in results['OpenStudioResults'].  Make sure monthly data is being output by os_results measure")
          end
        end
      end
    end
  else
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.get_timeseries_element', 'Cannot add monthly report values to the BldgSync file since it is missing.')
  end
end

#osw_mkdir_pObject

Create the @osw_dir



249
250
251
252
253
254
255
256
# File 'lib/buildingsync/scenario.rb', line 249

def osw_mkdir_p
  if !@osw_dir.nil?
    FileUtils.mkdir_p(@osw_dir)
  else
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.osw_mkdir_p', "Scenario ID: #{xget_id}.  @osw_dir must be set first")
    raise StandardError, "BuildingSync.Scenario.osw_mkdir_p Scenario ID: #{xget_id}.  @osw_dir must be set first"
  end
end

#pom?Boolean

Returns:

  • (Boolean)


601
602
603
604
605
606
# File 'lib/buildingsync/scenario.rb', line 601

def pom?
  if xget_element('ScenarioType').nil?
    return false
  end
  return check_scenario_type("./#{@ns}:PackageOfMeasures")
end

#read_all_resource_totalsObject



560
561
562
563
564
565
566
567
# File 'lib/buildingsync/scenario.rb', line 560

def read_all_resource_totals
  all_resource_total = @base_xml.get_elements("./#{@ns}:AllResourceTotals/#{@ns}:AllResourceTotal")
  if !all_resource_total.nil? && !all_resource_total.empty?
    all_resource_total.each do |art|
      @all_resource_totals << BuildingSync::AllResourceTotal.new(art, @ns)
    end
  end
end

#read_resource_usesObject



551
552
553
554
555
556
557
558
# File 'lib/buildingsync/scenario.rb', line 551

def read_resource_uses
  resource_use = @base_xml.get_elements("./#{@ns}:ResourceUses/#{@ns}:ResourceUse")
  if !resource_use.nil? && !resource_use.empty?
    resource_use.each do |ru|
      @resource_uses << BuildingSync::ResourceUse.new(ru, @ns)
    end
  end
end

#read_time_series_dataObject



569
570
571
572
573
574
575
576
# File 'lib/buildingsync/scenario.rb', line 569

def read_time_series_data
  time_series = @base_xml.get_elements("./#{@ns}:TimeSeriesData/#{@ns}:TimeSeries")
  if !time_series.nil? && !time_series.empty?
    time_series.each do |ts|
      @time_series_data << BuildingSync::TimeSeries.new(ts, @ns)
    end
  end
end

#read_xmlObject



163
164
165
166
167
168
# File 'lib/buildingsync/scenario.rb', line 163

def read_xml
  # Read in data about ResourceUses, AllResourceTotals, and TimeSeriesData
  read_resource_uses
  read_all_resource_totals
  read_time_series_data
end

#results_available_and_correct_units?(results = @results_json) ⇒ Boolean

Returns:

  • (Boolean)


352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/buildingsync/scenario.rb', line 352

def results_available_and_correct_units?(results = @results_json)
  results_available = true

  if !results.nil?
    if @results_json['units'] == 'SI'
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.results_available_and_correct_units?', "Scenario ID: #{xget_id}. Only able to process IP results.")
      results_available = false
    end
  elsif !File.exist?(File.join(get_osw_dir, @results_file_name))
    results_available = false
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.results_available_and_correct_units?', "Scenario ID: #{xget_id}.  Unable to gather results: #{results_file} does not exist.")
  else
    results_file = File.join(get_osw_dir, @results_file_name)
    File.open(results_file, 'r') do |file|
      @results_json = JSON.parse(file.read)
    end
    if @results_json['units'] == 'SI'
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.results_available_and_correct_units?', "Scenario ID: #{xget_id}. Only able to process IP results.")
      results_available = false
    end
  end
  return results_available
end

#set_main_output_dir(main_output_dir) ⇒ Object



233
234
235
236
# File 'lib/buildingsync/scenario.rb', line 233

def set_main_output_dir(main_output_dir)
  @main_output_dir = main_output_dir
  return @main_output_dir
end

#set_osw_dir(main_output_dir = @main_output_dir) ⇒ Object



238
239
240
241
242
243
244
245
246
# File 'lib/buildingsync/scenario.rb', line 238

def set_osw_dir(main_output_dir = @main_output_dir)
  if !xget_name.nil?
    to_use = xget_name
  elsif !xget_id.nil?
    to_use = xget_id
  end
  @osw_dir = File.join(main_output_dir, to_use)
  return @osw_dir
end

#set_workflow(workflow) ⇒ Object

Parameters:

  • workflow (Hash)

    a hash of the openstudio workflow



224
225
226
227
228
229
230
231
# File 'lib/buildingsync/scenario.rb', line 224

def set_workflow(workflow)
  if !workflow.is_a?(Hash)
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.set_workflow', "Scenario ID: #{xget_id}.  Cannot set_workflow, argument must be a Hash.")
    raise StandardError, "BuildingSync.Scenario.set_workflow Scenario ID: #{xget_id}.  Cannot set_workflow, argument must be a Hash, not a #{workflow.class}"
  else
    @workflow = workflow
  end
end

#simulation_success?Boolean

Check that the simulation was completed successfully. We check:

  • out.osw completed_status == 'Success'

  • finished.job file exists

  • failed.job file doesn't exist

  • eplusout.end and eplusout.err files

Returns:

  • (Boolean)


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
350
# File 'lib/buildingsync/scenario.rb', line 296

def simulation_success?
  success = true

  # Check out.osw
  out_osw_file = File.join(get_osw_dir, @out_osw_file_name)
  if !File.exist?(out_osw_file)
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id}.  #{out_osw_file} does not exist.")
  else
    File.open(out_osw_file, 'r') do |file|
      @out_osw_json = JSON.parse(file.read)
    end
    if @out_osw_json['completed_status'] == 'Success'
      OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id} successfully completed.")
    else
      success = false
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id} unsuccessful.")
    end

  end

  # Check for finished.job
  finished_job = File.join(get_osw_dir, 'finished.job')
  if !File.exist?(finished_job)
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id}: finished.job does not exist, simulation unsuccessful.")
    success = false
  end

  # Check for failed.job
  failed_job = File.join(get_osw_dir, 'failed.job')
  if File.exist?(failed_job)
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id}: failed.job exists, simulation unsuccessful.")
    success = false
  end

  # Check eplusout.end and eplusout.err files
  end_file = File.join(get_osw_dir, 'eplusout.end')
  if File.exist?(end_file)
    # we open the .end file to determine if EnergyPlus was successful or not
    energy_plus_string = File.open(end_file, &:readline)
    if energy_plus_string.include? 'Fatal Error Detected'
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id}: eplusout.end detected error, simulation unsuccessful: #{energy_plus_string}")
      success = false
      # if we found out that there was a fatal error we search the err file for the first error.
      File.open(File.join(scenario.get_osw_dir, 'eplusout.err')).each do |line|
        if line.include? '** Severe  **'
          OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id}: Severe error occurred! #{line}")
        elsif line.include? '**  Fatal  **'
          OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.Scenario.simulation_success?', "Scenario ID: #{xget_id}: Fatal error occurred! #{line}")
        end
      end
    end
  end

  return success
end

#target?Boolean

Returns:

  • (Boolean)


608
609
610
611
612
613
# File 'lib/buildingsync/scenario.rb', line 608

def target?
  if xget_element('ScenarioType').nil?
    return false
  end
  return check_scenario_type("./#{@ns}:Target")
end

#write_osw(main_output_dir = @main_output_dir) ⇒ Object

Use the @workflow definition to write a new ' in.osw ' file. The main_output_dir and osw_dir are set and created if not existing.

Parameters:

  • main_output_dir (String) (defaults to: @main_output_dir)

    path to the main output directory to use



261
262
263
264
265
266
267
268
269
270
# File 'lib/buildingsync/scenario.rb', line 261

def write_osw(main_output_dir = @main_output_dir)
  set_main_output_dir(main_output_dir)
  set_osw_dir(main_output_dir)
  osw_mkdir_p
  # write the osw
  path = File.join(@osw_dir, 'in.osw')
  File.open(path, 'w') do |file|
    file << JSON.pretty_generate(@workflow)
  end
end