Top Level Namespace

Defined Under Namespace

Modules: OpenStudio, OsLib_HelperMethods, OsLib_Reporting Classes: AddCeilingFan, AddCeilingFanTest, AddChilledWaterStorageTank, AddChilledWaterStorageTankTest, AddElectricVehicleChargingLoad, AddElectricVehicleChargingLoadTest, AddElectrochromicWindow, AddElectrochromicWindowTest, AddExteriorBlindsAndControl, AddExteriorBlindsAndControlTest, AddFanAssistNightVentilationWithHybridControl, AddFanAssistNightVentilationWithHybridControlTest, AddHpwh, AddHpwhTest, AddInteriorBlindsAndControl, AddNaturalVentilationWithHybridControl, AddNaturalVentilationWithHybridControlTest, AddOutputVariable, AddOutputVariable_Test, AddRooftopPV, AddRooftopPVTest, AdjustDHWSetpoint, AdjustDHWSetpointTest, AdjustThermostatSetpointsByDegreesForPeakHours, AdjustThermostatSetpointsByDegreesForPeakHours_Test, ApplyDynamicCoatingToRoofWall, ApplyDynamicCoatingToRoofWallTest, AverageVentilationForPeakHours, AverageVentilationForPeakHoursTest, EnableDemandControlledVentilation, EnableDemandControlledVentilation_Test, EnableOccupancyDrivenLighting, EnableOccupancyDrivenLightingTest, GEBMetricsReport, GEBMetricsReportTest, Precooling, Preheating, ReduceDomesticHotWaterUseForPeakHours, ReduceDomesticHotWaterUseForPeakHoursTest, ReduceEPDByPercentageForPeakHours, ReduceEPDByPercentageForPeakHoursTest, ReduceExteriorLightingLoads, ReduceExteriorLightingLoadsTest, ReduceLPDByPercentageForPeakHours, ReduceLPDByPercentageForPeakHoursTest

Instance Method Summary collapse

Instance Method Details

#get_logs(log_type = OpenStudio::Error) ⇒ Object

Get an array of all messages of a given type in the log



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
# File 'lib/openstudio/geb/logging.rb', line 91

def get_logs(log_type = OpenStudio::Error)
  errors = []

  $OPENSTUDIO_LOG.logMessages.each do |msg|
    if /openstudio.*/ =~ msg.logChannel
      # Skip certain messages that are irrelevant/misleading
      next if msg.logMessage.include?('UseWeatherFile') || # 'UseWeatherFile' is not yet a supported option for YearDescription
        msg.logMessage.include?('Skipping layer') || # Annoying/bogus "Skipping layer" warnings
        msg.logChannel.include?('runmanager') || # RunManager messages
        msg.logChannel.include?('setFileExtension') || # .ddy extension unexpected
        msg.logChannel.include?('Translator') || # Forward translator and geometry translator
        msg.logMessage.include?('Successive data points') || # Successive data points (2004-Jan-31 to 2001-Feb-01, ending on line 753) are greater than 1 day apart in EPW file
        msg.logMessage.include?('has multiple parents') || # Bogus errors about curves having multiple parents
        msg.logMessage.include?('does not have an Output') || # Warning from EMS translation
        msg.logMessage.include?('Prior to OpenStudio 2.6.2, this field was returning a double, it now returns an Optional double') # Warning about OS API change

      # Only fail on the errors
      if msg.logLevel == log_type
        errors << "[#{msg.logChannel}] #{msg.logMessage}"
      end
    end
  end

  return errors
end

#get_run_envObject

for parallel runs under Ruby 2.2.4



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/openstudio/geb/utilities.rb', line 87

def get_run_env
  new_env = {}
  new_env['BUNDLER_ORIG_MANPATH'] = nil
  new_env['BUNDLER_ORIG_PATH'] = nil
  new_env['BUNDLER_VERSION'] = nil
  new_env['BUNDLE_BIN_PATH'] = nil
  new_env['RUBYLIB'] = nil
  new_env['RUBYOPT'] = nil
  new_env['GEM_PATH'] = nil
  new_env['GEM_HOME'] = nil
  new_env['BUNDLE_GEMFILE'] = nil
  new_env['BUNDLE_PATH'] = nil
  new_env['BUNDLE_WITHOUT'] = nil

  return new_env
end

#list_all_geb_measuresObject

get the list of available GEB measures in json format



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
# File 'lib/openstudio/geb/utilities.rb', line 29

def list_all_geb_measures
  measure_list = {}

  # get the absolute path of measures folder
  measures_dir = File.expand_path("../../../measures/", __FILE__ )

  # use partial codes from function list_measures in OS Extension Runner to get the list of measures
  # this is a temporary solution for the geb gem to be adopted by URBANopt workflow due to gem complexity
  # (previously use nokogiri/oga as dependency and it didn't work in the integration process)
  if measures_dir.nil? || measures_dir.empty?
    puts 'Measures dir is nil or empty'
    return true
  end

  # this is to accommodate a single measures dir (like most gems)
  # or a repo with multiple directories fo measures (like OpenStudio-measures)
  measures = Dir.glob(File.join(measures_dir, '**/measure.rb'))
  if measures.empty?
    # also try nested 2-deep to support openstudio-measures
    measures = Dir.glob(File.join(measures_dir, '**/**/measure.rb'))
  end
  puts "#{measures.length} MEASURES FOUND"
  puts measures.inspect
  measures.each do |measure|
    measure_name = measure.split('/')[-2]
    measure_list[measure_name] = {}
    # now measure_dir_name uses folder name rather than absolute path, adding "measure_paths" to the osw file
    measure_list[measure_name]['measure_dir_name'] = File.basename(File.dirname(measure))  # get just this folder name
  end

=begin
  measure_folders_name = Dir.entries(measures_path).select {|entry| File.directory? File.join(measures_path,entry) and !(entry =='.' || entry == '..') }
  measure_folders_name.each do |measure_folder|
    # read the measure.xml file, get measure's metadata
    measure_xml = File.join(measures_path,measure_folder,'measure.xml')
    handle = File.open(measure_xml)
    data = Oga.parse_xml(handle)

    # get measure's display name
    measure_name = data.xpath("//display_name").first.text
    # get measure's ruby class name
    class_name = data.xpath("//class_name").first.text
    # get parameter name list
    para_names = []
    data.xpath("measure//arguments//argument//name").each{|ele| para_names << ele.text}
    measure_list[measure_name] = {}
    measure_list[measure_name]['measure_dir_name'] = File.join(measures_path, measure_folder)
    measure_list[measure_name]['class_name'] = class_name
    measure_list[measure_name]['para_names'] = para_names
    # puts JSON.pretty_generate(measure_list)
  end
=end

  return measure_list
end

#log_messages_to_file(file_path, debug = false) ⇒ Array<String>

Log the info, warning, and error messages to a file. runner @param [file_path] The path to the log file debug @param [Boolean] If true, include the debug messages in the log

Returns:

  • (Array<String>)

    The array of messages, which can be used elsewhere.



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
# File 'lib/openstudio/geb/logging.rb', line 47

def log_messages_to_file(file_path, debug = false)
  messages = []

  File.open(file_path, 'w') do |file|
    $OPENSTUDIO_LOG.logMessages.each do |msg|
      # DLM: you can filter on log channel here for now
      if /openstudio.*/ =~ msg.logChannel # /openstudio\.model\..*/
        # Skip certain messages that are irrelevant/misleading
        next if msg.logMessage.include?('UseWeatherFile') || # 'UseWeatherFile' is not yet a supported option for YearDescription
          msg.logMessage.include?('Skipping layer') || # Annoying/bogus "Skipping layer" warnings
          msg.logChannel.include?('runmanager') || # RunManager messages
          msg.logChannel.include?('setFileExtension') || # .ddy extension unexpected
          msg.logChannel.include?('Translator') || # Forward translator and geometry translator
          msg.logMessage.include?('Successive data points') || # Successive data points (2004-Jan-31 to 2001-Feb-01, ending on line 753) are greater than 1 day apart in EPW file
          msg.logMessage.include?('has multiple parents') || # Bogus errors about curves having multiple parents
          msg.logMessage.include?('does not have an Output') || # Warning from EMS translation
          msg.logMessage.include?('Prior to OpenStudio 2.6.2, this field was returning a double, it now returns an Optional double') # Warning about OS API change

        # Report the message in the correct way
        if msg.logLevel == OpenStudio::Info
          s = "INFO  #{msg.logMessage}"
          file.puts(s)
          messages << s
        elsif msg.logLevel == OpenStudio::Warn
          s = "WARN  #{msg.logMessage}"
          file.puts(s)
          messages << s
        elsif msg.logLevel == OpenStudio::Error
          s = "ERROR #{msg.logMessage}"
          file.puts(s)
          messages << s
        elsif msg.logLevel == OpenStudio::Debug && debug
          s = "DEBUG #{msg.logMessage}"
          file.puts(s)
          messages << s
        end
      end
    end
  end

  return messages
end

#log_messages_to_runner(runner, debug = false) ⇒ Runner

Log the info, warning, and error messages to a runner. runner @param [Runner] The Measure runner to add the messages to debug @param [Boolean] If true, include the debug messages in the log

Returns:

  • (Runner)

    The same Measure runner, with messages from the openstudio-standards library added



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
# File 'lib/openstudio/geb/logging.rb', line 14

def log_messages_to_runner(runner, debug = false)
  $OPENSTUDIO_LOG.logMessages.each do |msg|
    # DLM: you can filter on log channel here for now
    if /openstudio.*/ =~ msg.logChannel # /openstudio\.model\..*/
      # Skip certain messages that are irrelevant/misleading
      next if msg.logMessage.include?('UseWeatherFile') || # 'UseWeatherFile' is not yet a supported option for YearDescription
        msg.logMessage.include?('Skipping layer') || # Annoying/bogus "Skipping layer" warnings
        msg.logChannel.include?('runmanager') || # RunManager messages
        msg.logChannel.include?('setFileExtension') || # .ddy extension unexpected
        msg.logChannel.include?('Translator') || # Forward translator and geometry translator
        msg.logMessage.include?('Successive data points') || # Successive data points (2004-Jan-31 to 2001-Feb-01, ending on line 753) are greater than 1 day apart in EPW file
        msg.logMessage.include?('has multiple parents') || # Bogus errors about curves having multiple parents
        msg.logMessage.include?('does not have an Output') || # Warning from EMS translation
        msg.logMessage.include?('Prior to OpenStudio 2.6.2, this field was returning a double, it now returns an Optional double') # Warning about OS API change

      # Report the message in the correct way
      if msg.logLevel == OpenStudio::Info
        runner.registerInfo(msg.logMessage)
      elsif msg.logLevel == OpenStudio::Warn
        runner.registerWarning("[#{msg.logChannel}] #{msg.logMessage}")
      elsif msg.logLevel == OpenStudio::Error
        runner.registerError("[#{msg.logChannel}] #{msg.logMessage}")
      elsif msg.logLevel == OpenStudio::Debug && debug
        runner.registerInfo("DEBUG - #{msg.logMessage}")
      end
    end
  end
end

#postprocess_out_osw(outdir) ⇒ Object



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
# File 'lib/openstudio/geb/utilities.rb', line 115

def postprocess_out_osw(outdir)

  out_osw = File.join(outdir, 'out.osw')
  raise "Cannot find file #{out_osw}" if !File.exist?(out_osw)

  result_osw = nil
  File.open(out_osw, 'r') do |f|
    result_osw = JSON::parse(f.read, :symbolize_names=>true)
  end

  if !result_osw.nil?
    if result_osw.keys.include?(:eplusout_err)
      result_osw[:eplusout_err].gsub!(/YMD=.*?,/, '')
      result_osw[:eplusout_err].gsub!(/Elapsed Time=.*?\n/, '')
      # Replace eplusout_err by a list of lines instead of a big string
      # Will make git diffing easier
      result_osw[:eplusout_err] = result_osw[:eplusout_err].split("\n")
    end

    result_osw.delete(:completed_at)
    result_osw.delete(:hash)
    result_osw.delete(:started_at)
    result_osw.delete(:updated_at)

    # Should always be true
    if (result_osw[:steps].size == 1) && (result_osw[:steps].select{|s| s[:measure_dir_name] == 'openstudio_results'}.size == 1)
      # If something went wrong, there wouldn't be results
      if result_osw[:steps][0].keys.include?(:result)
        result_osw[:steps][0][:result].delete(:completed_at)
        result_osw[:steps][0][:result].delete(:started_at)
        result_osw[:steps][0][:result].delete(:step_files)

        # Round all numbers to 2 digits to avoid excessive diffs
        # result_osw[:steps][0][:result][:step_values].each_with_index do |h, i|
        result_osw[:steps][0][:result][:step_values].each_with_index do |h, i|
          if h[:value].is_a? Float
            result_osw[:steps][0][:result][:step_values][i][:value] = h[:value].round(2)
          end
        end
      end
    end

    # The fuel cell tests produce out.osw files that are about 800 MB
    # because E+ throws a warning in the Regula Falsi routine (an E+ bug)
    # which results in about 7.5 Million times the same warning
    # So if the file size is bigger than 100 KiB, we throw out the eplusout_err
    if File.size(out_osw) > 100000
      result_osw.delete(:eplusout_err)
    end
  end

  return result_osw
end

#reset_logObject



117
118
119
# File 'lib/openstudio/geb/logging.rb', line 117

def reset_log
  $OPENSTUDIO_LOG.resetStringStream
end

#rm_old_folder_and_create_new(folder_path) ⇒ Object



104
105
106
107
108
109
110
111
112
113
# File 'lib/openstudio/geb/utilities.rb', line 104

def rm_old_folder_and_create_new(folder_path)
  if File.exist? folder_path
    FileUtils.rm_rf(folder_path)
    sleep(0.1)
  end

  unless File.directory?(folder_path)
    FileUtils.mkdir_p(folder_path)
  end
end

#safe_load_osm(model_path_string) ⇒ Object

load openstudio model



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/openstudio/geb/utilities.rb', line 10

def safe_load_osm(model_path_string)
  model_path = OpenStudio::Path.new(model_path_string)
  if OpenStudio.exists(model_path)
    version_translator = OpenStudio::OSVersion::VersionTranslator.new
    model = version_translator.loadModel(model_path)
    if model.empty?
      OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "Version translation failed for #{model_path_string}")
      return false
    else
      model = model.get
    end
  else
    OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "#{model_path_string} couldn't be found")
    return false
  end
  return model
end