Class: BuildingSync::WorkflowMaker

Inherits:
WorkflowMakerBase show all
Defined in:
lib/buildingsync/makers/workflow_maker.rb

Overview

base class for objects that will configure workflows based on building sync files

Direct Known Subclasses

Translator

Instance Method Summary collapse

Methods inherited from WorkflowMakerBase

#add_measure_path, #add_new_measure, #clear_all_measures, #get_prefix, #save_xml, #set_measure_argument, #set_measure_path, #set_measure_paths

Constructor Details

#initialize(doc, ns) ⇒ WorkflowMaker

initialize - load workflow json file and add necessary measure paths

Parameters:

  • doc (REXML::Document)
  • ns (String)


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/buildingsync/makers/workflow_maker.rb', line 57

def initialize(doc, ns)
  super(doc, ns)

  @facility_xml = nil
  @facility = nil

  # TODO: Be consistent in symbolizing names in hashes or not
  File.open(PHASE_0_BASE_OSW_FILE_PATH, 'r') do |file|
    @workflow = JSON.parse(file.read)
  end

  File.open(WORKFLOW_MAKER_JSON_FILE_PATH, 'r') do |file|
    @workflow_maker_json = JSON.parse(file.read, symbolize_names: true)
  end

  # Add all of the measure directories from the extension gems
  # into the @workflow, then check they exist
  set_measure_paths(get_measure_directories_array)
  measures_exist?
  read_xml
end

Instance Method Details

#cleanup_larger_files(osw_dir) ⇒ Object

cleanup larger files

Parameters:

  • osw_dir (String)


547
548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'lib/buildingsync/makers/workflow_maker.rb', line 547

def cleanup_larger_files(osw_dir)
  path = File.join(osw_dir, 'eplusout.sql')
  FileUtils.rm_f(path) if File.exist?(path)
  path = File.join(osw_dir, 'data_point.zip')
  FileUtils.rm_f(path) if File.exist?(path)
  path = File.join(osw_dir, 'eplusout.eso')
  FileUtils.rm_f(path) if File.exist?(path)
  Dir.glob(File.join(osw_dir, '*create_typical_building_from_model*')).each do |path|
    FileUtils.rm_rf(path) if File.exist?(path)
  end
  Dir.glob(File.join(osw_dir, '*create_typical_building_from_model*')).each do |path|
    FileUtils.rm_rf(path) if File.exist?(path)
  end
end

#configure_workflow_for_scenario(base_workflow, scenario) ⇒ Object

Based on the MeasureIDs defined by the Scenario, configure the workflow provided using the default measure arguments defined by the lib/buildingsync/makers/workflow_maker.json

Parameters:

  • base_workflow (Hash)

    a Hash map of the @workflow. DO NOT use @workflow directly, should be a deep clone

  • scenario (BuildingSync::Scenario)

    a Scenario object



283
284
285
286
287
288
289
290
291
292
293
294
295
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
351
352
353
354
355
356
357
358
# File 'lib/buildingsync/makers/workflow_maker.rb', line 283

def configure_workflow_for_scenario(base_workflow, scenario)
  successful = true

  num_measures = 0
  scenario.get_measure_ids.each do |measure_id|
    measure = @facility.measures.find { |m| m.xget_id == measure_id }
    current_num_measure = num_measures

    sym_to_find = measure.xget_text('SystemCategoryAffected')
    if sym_to_find.nil? || sym_to_find.empty?
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "Measure ID: #{measure.xget_id} does not define a SystemCategoryAffected.")
      successful = false
    else
      sym_to_find = sym_to_find.to_s.to_sym
    end

    # 'Other HVAC' or 'Cooling System' as examples
    categories_found = @workflow_maker_json.key?(sym_to_find)
    if categories_found
      m_name = measure.xget_name

      if m_name.nil? || m_name.empty?
        OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "Measure ID: #{measure.xget_id} does not have a MeasureName defined.")
        successful = false
      else
        m_name = m_name.to_sym
      end

      # Where standardized measure names have not been adopted as enumerations
      # in the BuildingSync Schema, a <MeasureName>Other</MeasureName> is used
      # and the actual measure name added
      if m_name == :Other
        m_name = measure.xget_text('CustomMeasureName')
        if m_name.nil? || m_name.empty?
          OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "Measure ID: #{measure.xget_id} has a MeasureName of 'Other' but does not have a CustomMeasureName defined.")
          successful = false
        else
          m_name = m_name.to_sym
        end
      end
      measure_found = false
      @workflow_maker_json[sym_to_find].each do |category|
        # m_name is, for example: 'Replace HVAC system type to VRF'

        if !category[m_name].nil?
          measure_found = true
          measure_dir_name = category[m_name][:measure_dir_name]
          num_measures += 1
          category[m_name][:arguments].each do |argument|
            # Certain arguments are only applied under specific conditions
            #
            if !argument[:condition].nil? && !argument[:condition].empty?
              set_argument_detail(base_workflow, argument, measure_dir_name, m_name.to_s)
            else
              set_measure_argument(base_workflow, measure_dir_name, argument[:name], argument[:value])
            end
          end
        end
      end
      if !measure_found
        OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "Could not find measure '#{m_name}' under category #{sym_to_find} in workflow_maker.json.")
      end
    else
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "Category: #{measure.xget_text('SystemCategoryAffected')} not found in workflow_maker.json.")
    end

    if current_num_measure == num_measures
      OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "Measure ID: #{measure.xget_id} could not be processed!")
      successful = false
    end
  end

  # ensure that we didn't miss any measures by accident
  OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.configure_workflow_for_scenario', "#{scenario.get_measure_ids.size} measures expected, #{num_measures} resolved,  expected measure_ids = #{scenario.get_measure_ids}") if num_measures != scenario.get_measure_ids.size
  return successful
end

#deep_copy_workflowHash

Creates a deep copy of the @workflow be serializing and reloading with JSON

Returns:

  • (Hash)

    a new workflow object



514
515
516
# File 'lib/buildingsync/makers/workflow_maker.rb', line 514

def deep_copy_workflow
  return JSON.load(JSON.generate(@workflow))
end

#gather_results(year_val = Date.today.year, baseline_only = false) ⇒ Boolean

gather results for all CB Modeled and POM Scenarios, including both annual and monthly results

  • ResourceUse and AllResourceTotal elements are added to the Scenario as part of this process

  • ResourceUse - holds consumption information about a specific resource / fuel (Electricity, Natural gas, etc.)

  • AllResourceTotal - holds total site and source energy consumption information

Parameters:

  • year_val (Integer) (defaults to: Date.today.year)
  • baseline_only (Boolean) (defaults to: false)

Returns:

  • (Boolean)


569
570
571
572
573
574
575
576
577
578
579
# File 'lib/buildingsync/makers/workflow_maker.rb', line 569

def gather_results(year_val = Date.today.year, baseline_only = false)
  # Gather results for the Current Building Modeled (Baseline) Scenario
  @facility.report.cb_modeled.os_gather_results(year_val)

  if !baseline_only
    # Gather results for the Package of Measures scenarios
    @facility.report.poms.each do |scenario|
      scenario.os_gather_results(year_val)
    end
  end
end

#get_available_measures_hashhash

gets all available measures across all measure directories

Returns:

  • (hash)

    Looks as follows [measure_name1, mn2, etc.], path_to_measure_dir_2: […]



184
185
186
187
188
189
190
191
192
# File 'lib/buildingsync/makers/workflow_maker.rb', line 184

def get_available_measures_hash
  measures_hash = {}
  get_measure_directories_array.each do |potential_measure_path|
    Dir.chdir(potential_measure_path) do
      measures_hash[potential_measure_path] = Dir.glob('*').select { |f| File.directory? f }
    end
  end
  return measures_hash
end

#get_facilityBuildingSync::Facility

get the facility object from this workflow

Returns:



101
102
103
# File 'lib/buildingsync/makers/workflow_maker.rb', line 101

def get_facility
  return @facility
end

#get_failed_scenariosArray<BuildingSync::Scenario>

get failed scenarios

Returns:



537
538
539
540
541
542
543
# File 'lib/buildingsync/makers/workflow_maker.rb', line 537

def get_failed_scenarios
  failed = []
  @facility.report.scenarios.each do |scenario|
    failed << scenario if !scenario.simulation_success?
  end
  return failed
end

#get_measure_directories_arrayarray

collect all measure directories that contain measures needed for BldgSync

Returns:

  • (array)

    of measure dirs



196
197
198
199
200
201
202
# File 'lib/buildingsync/makers/workflow_maker.rb', line 196

def get_measure_directories_array
  common_measures_instance = OpenStudio::CommonMeasures::Extension.new
  model_articulation_instance = OpenStudio::ModelArticulation::Extension.new
  ee_measures_instance = OpenStudio::EeMeasures::Extension.new
  bldg_sync_instance = BuildingSync::Extension.new
  return [common_measures_instance.measures_dir, model_articulation_instance.measures_dir, bldg_sync_instance.measures_dir, ee_measures_instance.measures_dir]
end

#get_measure_type(measure_dir_name) ⇒ String

gets the measure type of a measure given its directory - looking up the measure type in the measure.xml file

Parameters:

Returns:

  • (String)


259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/buildingsync/makers/workflow_maker.rb', line 259

def get_measure_type(measure_dir_name)
  measure_type = nil
  get_measure_directories_array.each do |potential_measure_path|
    measure_dir_full_path = "#{potential_measure_path}/#{measure_dir_name}"
    if Dir.exist?(measure_dir_full_path)
      measure_xml_doc = nil
      File.open(measure_dir_full_path + '/measure.xml', 'r') do |file|
        measure_xml_doc = REXML::Document.new(file)
      end
      measure_xml_doc.elements.each('/measure/attributes/attribute') do |attribute|
        attribute_name = attribute.elements['name'].text
        if attribute_name == 'Measure Type'
          measure_type = attribute.elements['value'].text
        end
      end
    end
  end
  return measure_type
end

#get_modelOpenStudio::Model

get model

Returns:

  • (OpenStudio::Model)

    model



113
114
115
# File 'lib/buildingsync/makers/workflow_maker.rb', line 113

def get_model
  return @facility.get_model
end

#get_scenariosArray<BuildingSync::Scenario>

get scenario elements

Returns:



125
126
127
# File 'lib/buildingsync/makers/workflow_maker.rb', line 125

def get_scenarios
  return @facility.report.scenarios
end

#get_space_typesVector<OpenStudio::Model::SpaceType>

get the space types of the facility

Returns:

  • (Vector<OpenStudio::Model::SpaceType>)

    vector of space types



107
108
109
# File 'lib/buildingsync/makers/workflow_maker.rb', line 107

def get_space_types
  return @facility.get_space_types
end

#get_workflowHash

get the current workflow

Returns:

  • (Hash)


119
120
121
# File 'lib/buildingsync/makers/workflow_maker.rb', line 119

def get_workflow
  return @workflow
end

#insert_measure_into_workflow(measure_goal_type, measure_dir_name, relative_position = 0, args_hash = {}) ⇒ Object

inserts any measure. traverses through the measures available in the included extensions (common measures, model articulation, etc.) to find the lib/measures/ specified. It is inserted at the relative position according to its type

Parameters:

  • measure_goal_type (String)

    one of: ‘EnergyPlusMeasure’, ‘ReportingMeasure’, or ‘ModelMeasure’

  • measure_dir_name (String)

    the directory name for the measure, as it appears in any of the gems, i.e. openstudio-common-measures-gem/lib/measures/

  • relative_position (Integer) (defaults to: 0)

    the position where the measure should be inserted with respect to the measure_goal_type

  • args_hash (hash) (defaults to: {})


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/buildingsync/makers/workflow_maker.rb', line 212

def insert_measure_into_workflow(measure_goal_type, measure_dir_name, relative_position = 0, args_hash = {})
  successfully_added = false
  count = 0 # count for all of the measures, regardless of the type
  measure_type_count = 0 # count of measures specific to the measure_goal_type
  measure_type_found = false
  new_step = {}
  new_step['measure_dir_name'] = measure_dir_name
  new_step['arguments'] = args_hash
  if @workflow['steps'].empty?
    @workflow['steps'].insert(count, new_step)
    successfully_added = true
  else
    @workflow['steps'].each do |step|
      measure_dir_name = step['measure_dir_name']
      measure_type = get_measure_type(measure_dir_name)
      OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.insert_measure_into_workflow', "measure: #{measure_dir_name} with type: #{measure_type} found")
      if measure_type == measure_goal_type
        measure_type_found = true
        if measure_type_count == relative_position
          # insert measure here
          OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.insert_measure_into_workflow', "inserting measure with type (#{measure_goal_type}) at position #{count} and dir: #{measure_dir_name} and type: #{get_measure_type(measure_dir_name)}")
          puts "inserting measure with type (#{measure_goal_type}) at position #{count} and dir: #{measure_dir_name} and type: #{get_measure_type(measure_dir_name)}"
          @workflow['steps'].insert(count, new_step)
          successfully_added = true
          break
        end
        measure_type_count += 1
      elsif measure_type_found
        OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.insert_measure_into_workflow', "inserting measure with type (#{measure_goal_type})at position #{count} and dir: #{measure_dir_name} and type: #{get_measure_type(measure_dir_name)}")
        puts "inserting measure with type (#{measure_goal_type}) at position #{count} and dir: #{measure_dir_name} and type: #{get_measure_type(measure_dir_name)}"
        @workflow['steps'].insert(count - 1, new_step)
        successfully_added = true
        break
      end
      count += 1
    end
  end
  if !successfully_added
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMakerPhaseZero.insert_measure_into_workflow', "CANNOT insert measure with type (#{measure_goal_type}) at position #{count} and dir: #{measure_dir_name} and type: #{get_measure_type(measure_dir_name)}")
  end
  return successfully_added
end

#measures_exist?Boolean

iterate over the current measure list in the workflow and check if they are available at the referenced measure directories

Returns:

  • (Boolean)


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
# File 'lib/buildingsync/makers/workflow_maker.rb', line 155

def measures_exist?
  all_measures_found = true
  number_measures_found = 0
  @workflow['steps'].each do |step|
    measure_is_valid = false
    measure_dir_name = step['measure_dir_name']
    get_measure_directories_array.each do |potential_measure_path|
      measure_dir_full_path = "#{potential_measure_path}/#{measure_dir_name}"
      if Dir.exist?(measure_dir_full_path)
        measure_is_valid = true
        OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.measures_exist?', "Measure: #{measure_dir_name} found at: #{measure_dir_full_path}")
        number_measures_found += 1
        break
      end
    end
    if !measure_is_valid
      all_measures_found = false
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.measures_exist?', "CANNOT find measure with name (#{measure_dir_name}) in any of the measure paths  ")
    end
  end
  if all_measures_found
    OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.measures_exist?', "Total measures found: #{number_measures_found}. All measures defined by @workflow found.")
    puts "Total measures found: #{number_measures_found}. All measures defined by @workflow found."
  end
  return all_measures_found
end

#prepare_final_xmlObject

writes the parameters determined during processing back to the BldgSync XML file



143
144
145
# File 'lib/buildingsync/makers/workflow_maker.rb', line 143

def prepare_final_xml
  @facility.prepare_final_xml
end

#purge_skipped_from_workflow(workflow) ⇒ Object

Removes unused measures from a workflow, where __SKIP__ == true copy is made and the measures are configured for the specific scenario

Parameters:

  • workflow (Hash)

    a hash of the openstudio workflow, typically after a deep



521
522
523
524
525
526
527
528
529
530
531
532
533
# File 'lib/buildingsync/makers/workflow_maker.rb', line 521

def purge_skipped_from_workflow(workflow)
  non_skipped = []
  if !workflow.nil? && !workflow['steps'].nil? && workflow.key?('steps')
    workflow['steps'].each do |step|
      if !step.nil? && step.key?('arguments') && !step['arguments'].nil?
        if step['arguments'].key?('__SKIP__') && step['arguments']['__SKIP__'] == false
          non_skipped << step
        end
      end
    end
    workflow['steps'] = non_skipped
  end
end

#read_xmlObject



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/buildingsync/makers/workflow_maker.rb', line 79

def read_xml
  facility_xml_temp = @doc.get_elements("#{get_prefix}BuildingSync/#{get_prefix}Facilities/#{get_prefix}Facility")

  # Raise errors for zero or multiple Facilities.  Not supported at this time.
  if facility_xml_temp.nil? || facility_xml_temp.empty?
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.populate_facility_report_and_scenarios', 'There are no Facility elements in your BuildingSync file.')
    raise StandardError, 'There are no Facility elements in your BuildingSync file.'
  elsif facility_xml_temp.size > 1
    @facility_xml = facility_xml_temp.first
    OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.populate_facility_report_and_scenarios', "There are more than one (#{facility_xml_temp.size}) Facility elements in your BuildingSync file. Only the first Facility will be considered (ID: #{@facility_xml.attributes['ID']}")
  else
    @facility_xml = facility_xml_temp.first
  end

  OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.read_xml', "Setting up workflow for Facility ID: #{@facility_xml.attributes['ID']}")

  # Initialize Facility object
  @facility = BuildingSync::Facility.new(@facility_xml, @ns)
end

#run_osws(output_dir, only_cb_modeled = false, runner_options = { run_simulations: true, verbose: false, num_parallel: 7, max_to_run: Float::INFINITY }) ⇒ Object

run osws - running all scenario simulations

Parameters:

  • only_cb_modeled (Boolean) (defaults to: false)

    used to only run the simulations for the cb_modeled (baseline) scenario

  • runner_options (hash) (defaults to: { run_simulations: true, verbose: false, num_parallel: 7, max_to_run: Float::INFINITY })


496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
# File 'lib/buildingsync/makers/workflow_maker.rb', line 496

def run_osws(output_dir, only_cb_modeled = false, runner_options = { run_simulations: true, verbose: false, num_parallel: 7, max_to_run: Float::INFINITY })
  osw_files = []
  osw_sr_files = []
  if only_cb_modeled
    osw_files << "#{@facility.report.cb_modeled.get_osw_dir}/in.osw"
  else
    Dir.glob("#{output_dir}/**/in.osw") { |osw| osw_files << osw }
  end
  Dir.glob("#{output_dir}/SR/in.osw") { |osw| osw_sr_files << osw }

  runner = OpenStudio::Extension::Runner.new(dirname = Dir.pwd, bundle_without = [], options = runner_options)

  # This doesn't run the workflow defined by the Sizing Run
  return runner.run_osws(osw_files - osw_sr_files)
end

#set_argument_detail(workflow, argument, measure_dir_name, measure_name) ⇒ Object

TODO: Update this as I believe no longer will work as expected, keys being searched for

by the @facility_xml['key'] don't make sense.

set argument details, used when the condition

Parameters:

  • workflow (Hash)

    a hash of the openstudio workflow

  • argument (Hash)
  • measure_dir_name (String)

    the directory name for the measure, as it appears in any of the gems, i.e. openstudio-common-measures-gem/lib/measures/

  • measure_name (String)


368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/buildingsync/makers/workflow_maker.rb', line 368

def set_argument_detail(workflow, argument, measure_dir_name, measure_name)
  argument_name = ''
  argument_value = ''

  if measure_name == 'Add daylight controls' || measure_name == 'Replace HVAC system type to PZHP'
    # For these measures, the condition is based on the standards building type determined
    if argument[:condition] == @facility.site.get_building_type
      argument_name = argument[:name]

      # This is a really terrible way to do this.  It fails
      # in many scenarios
      argument_value = "#{argument[:value]} #{@facility.site.get_standard_template}"
    end
  elsif measure_name == 'Replace burner'
    if argument[:condition] == @facility.site.get_system_type
      argument_name = argument[:name]
      argument_value = argument[:value]
    end
  elsif measure_name == 'Replace boiler'
    if argument[:condition] == @facility.site.get_system_type
      argument_name = argument[:name]
      argument_value = argument[:value]
    end
  elsif measure_name == 'Replace package units'
    if argument[:condition] == @facility.site.get_system_type
      argument_name = argument[:name]
      argument_value = argument[:value]
    end
  elsif measure_name == 'Replace HVAC system type to VRF' || measure_name == 'Replace HVAC with GSHP and DOAS' || measure_name == 'Replace AC and heating units with ground coupled heat pump systems'
    if argument[:condition] == @facility.site.get_building_type
      argument_name = (argument[:name]).to_s
      argument_value = argument[:value]
    end
  else
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.set_argument_detail', "measure dir name not found #{measure_name}.")
    puts "BuildingSync.WorkflowMaker.set_argument_detail: Measure dir name not found #{measure_name}."
  end

  set_measure_argument(workflow, measure_dir_name, argument_name, argument_value) if !argument_name.nil? && !argument_name.empty?
end

#setup_and_sizing_run(dir, epw_file_path, standard_to_be_used, ddy_file = nil) ⇒ Object

generate the baseline model as osm model

Parameters:

  • dir (String)
  • epw_file_path (String)
  • standard_to_be_used (String)

    ‘ASHRAE90.1’ or ‘CaliforniaTitle24’ are supported options

  • ddy_file (String) (defaults to: nil)

    path to the ddy file

Returns:

  • @see BuildingSync::Facility.write_osm



135
136
137
138
139
140
# File 'lib/buildingsync/makers/workflow_maker.rb', line 135

def setup_and_sizing_run(dir, epw_file_path, standard_to_be_used, ddy_file = nil)
  @facility.set_all
  @facility.determine_open_studio_standard(standard_to_be_used)
  @facility.generate_baseline_osm(epw_file_path, dir, standard_to_be_used, ddy_file)
  @facility.write_osm(dir)
end

#write_osw(main_output_dir, scenario) ⇒ Boolean

Write an OSW for the provided scenario

Parameters:

  • main_output_dir (String)

    main output path, not scenario specific. i.e. SR should be a subdirectory

  • (BuildingSync::Scenario)

Returns:

  • (Boolean)

    whether the writing was successful



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

def write_osw(main_output_dir, scenario)
  successful = true
  # deep clone
  base_workflow = deep_copy_workflow

  # configure the workflow based on measures in this scenario
  begin
    # The workflow is updated by configure_workflow, put with pass by reference
    # we are ok to use it later without returning
    if !configure_workflow_for_scenario(base_workflow, scenario)
      successful = false
      OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.write_osw', "Could not configure workflow for scenario #{scenario.xget_name}")
    else
      purge_skipped_from_workflow(base_workflow)
      scenario.set_workflow(base_workflow)
      scenario.write_osw(main_output_dir)
    end
  rescue StandardError => e
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.write_osw', "Could not configure for scenario #{scenario.xget_name}. Error: #{e}")
    puts "Could not configure for scenario #{scenario.xget_name}"
    puts e.backtrace.join("\n\t")
    successful = false
  end
  return successful
end

#write_osws(main_output_dir, only_cb_modeled = false) ⇒ Boolean

write workflows for scenarios into osw files. This includes:

- Package of Measure Scenarios
- Current Building Modeled (Baseline) Scenario

Parameters:

  • main_output_dir (String)

    main output path, not scenario specific. i.e. SR should be a subdirectory

Returns:

  • (Boolean)

    whether writing of all the new workflows was successful



414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
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
# File 'lib/buildingsync/makers/workflow_maker.rb', line 414

def write_osws(main_output_dir, only_cb_modeled = false)
  # make sure paths exist
  FileUtils.mkdir_p(main_output_dir)

  if @facility.report.cb_modeled.nil?
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.write_osws', 'OSW cannot be written since no current building modeled scenario is defined. One can be added after file import using the add_cb_modeled method')
    raise StandardError, 'BuildingSync.WorkflowMaker.write_osws: OSW cannot be written since no current building modeled scenario is defined. One can be added after file import using the add_cb_modeled method'
  end

  # Write a workflow for the current building modeled scenario
  cb_modeled_success = write_osw(main_output_dir, @facility.report.cb_modeled)

  if !cb_modeled_success
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.write_osws', 'A workflow was not successfully written for the cb_modeled (Current Building Modeled) Scenario.')
    raise StandardError, 'BuildingSync.WorkflowMaker.write_osws: A workflow was not successfully written for the cb_modeled (Current Building Modeled) Scenario.'
  end

  number_successful = cb_modeled_success ? 1 : 0

  if !only_cb_modeled
    # write an osw for each Package Of Measures scenario
    @facility.report.poms.each do |scenario|
      successful = write_osw(main_output_dir, scenario)
      if successful
        number_successful += 1
      else
        OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.write_osws', "Scenario ID: #{scenario.xget_id}. Unsuccessful write_osw")
      end
    end
  end

  # Compare the total number of potential successes to the number of actual successes
  if only_cb_modeled
    # In this case we should have only 1 success
    expected_successes = 1
    really_successful = number_successful == expected_successes
  else
    # In this case, all pom scenarios should be run + the cb_modeled scenario
    expected_successes = @facility.report.poms.size + 1
    really_successful = number_successful == expected_successes
  end

  if !really_successful
    OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.WorkflowMaker.write_osws', "Facility ID: #{@facility.xget_id}. Expected #{expected_successes}, Got #{number_successful} OSWs")
  end

  return really_successful
end