Skip to content

Commit

Permalink
Updates to handle breaking changes from REopt v3.11 (#157)
Browse files Browse the repository at this point in the history
* use released versions of gems

* bump to v1.0.0

* add year to district input for ElectricLoad

* add year to ElectricLoad for GHP assumptions

* add year to ElectricLoad test assumption files

* use `v3` in ghp test api url instead of `stable`

* rubocop formatting

* remove unused variable

* less action & more assertion in 15-minute-interval test
  • Loading branch information
vtnate authored Jan 27, 2025
1 parent 9af5f52 commit c81d59b
Show file tree
Hide file tree
Showing 14 changed files with 59 additions and 63 deletions.
24 changes: 12 additions & 12 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
# if allow_local && File.exist?('../OpenStudio-extension-gem')
# gem 'openstudio-extension', path: '../OpenStudio-extension-gem'
# elsif allow_local
# gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'bundler-hack'
# gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
# else
# gem 'openstudio-extension', '~> 0.8.1'
# end
Expand All @@ -43,17 +43,17 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
# gem 'openstudio-model-articulation', '0.1.0'
# end

# if allow_local && File.exist?('../urbanopt-scenario-gem')
# gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
# elsif allow_local
gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'os39'
# end
if allow_local && File.exist?('../urbanopt-scenario-gem')
gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
elsif allow_local
gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
end

# Temporary! Remove this once reporting-gem is merged/released
gem 'urbanopt-reporting', github: 'URBANopt/urbanopt-reporting-gem', branch: 'os39'
# gem 'urbanopt-reporting', github: 'URBANopt/urbanopt-reporting-gem', branch: 'develop'

# if allow_local && File.exists?('../urbanopt-geojson-gem')
# gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
# elsif allow_local
# gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
# end
if allow_local && File.exist?('../urbanopt-geojson-gem')
gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
elsif allow_local
gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
end
9 changes: 4 additions & 5 deletions lib/urbanopt/reopt/feature_report_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ def reopt_json_from_feature_report(feature_report, reopt_assumptions_hash = nil,
else
@@logger.info('Using default REopt assumptions')
reopt_inputs = {
Settings:{},
Settings: {},
Site: {},
Financial:{},
Financial: {},
ElectricTariff: {
monthly_demand_rates: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
monthly_energy_rates: [0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
Expand Down Expand Up @@ -158,7 +158,6 @@ def reopt_json_from_feature_report(feature_report, reopt_assumptions_hash = nil,
# [*return:*] _URBANopt::Reporting::DefaultReports::FeatureReport_ - Returns an updated FeatureReport.
##
def update_feature_report(feature_report, reopt_output, timeseries_csv_path = nil, resilience_stats = nil)

# Check if the \REopt response is valid
if reopt_output['status'] != 'optimal'
@@logger.error("ERROR cannot update Feature Report #{feature_report.name} #{feature_report.id} - REopt optimization was non-optimal")
Expand Down Expand Up @@ -439,15 +438,15 @@ def modrow(x, i) # :nodoc:
x[$storage_to_grid_col] = $storage_to_grid[i] || 0 if defined?(storage)
x[$storage_soc_col] = $storage_soc[i] || 0 if defined?(storage)
x[$generator_total_col] = $generator_total[i] || 0 if defined?(generator)
x[$generator_to_battery_col] = $generator_to_battery[i] || 0 if (defined?(generator) && defined?(storage))
x[$generator_to_battery_col] = $generator_to_battery[i] || 0 if defined?(generator) && defined?(storage)
x[$generator_to_load_col] = $generator_to_load[i] || 0 if defined?(generator)
x[$generator_to_grid_col] = $generator_to_grid[i] || 0 if defined?(generator)
x[$pv_total_col] = $pv_total[i] || 0
x[$pv_to_battery_col] = $pv_to_battery[i] || 0 if defined?(storage)
x[$pv_to_load_col] = $pv_to_load[i] || 0
x[$pv_to_grid_col] = $pv_to_grid[i] || 0
x[$wind_total_col] = $wind_total[i] || 0 if defined?(wind)
x[$wind_to_battery_col] = $wind_to_battery[i] || 0 if (defined?(wind) && defined?(storage))
x[$wind_to_battery_col] = $wind_to_battery[i] || 0 if defined?(wind) && defined?(storage)
x[$wind_to_load_col] = $wind_to_load[i] || 0 if defined?(wind)
x[$wind_to_grid_col] = $wind_to_grid[i] || 0 if defined?(wind)
return x
Expand Down
5 changes: 3 additions & 2 deletions lib/urbanopt/reopt/reopt_ghp_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class REoptGHPAdapter
def initialize
# initialize @@logger
@@logger ||= URBANopt::REopt.reopt_logger
# Define class variable
# Define class variable
@@hours_in_year = 8760
end

Expand Down Expand Up @@ -247,7 +247,8 @@ def create_reopt_input_district(run_dir, system_parameter_hash, reopt_ghp_assump
# This is not used in REopt calculation but required for formatting.
reopt_inputs_district[:DomesticHotWaterLoad][:fuel_loads_mmbtu_per_hour] = [0.0000001]*@@hours_in_year

reopt_inputs_district[:ElectricLoad] = {}
# Adding year for ElectricLoad so district electric load can be calculated with REopt API v3.11
reopt_inputs_district[:ElectricLoad] = {:year => 2017}
#required for reopt formatting
reopt_inputs_district[:ElectricLoad][:loads_kw] = [0.00001]*@@hours_in_year

Expand Down
9 changes: 5 additions & 4 deletions lib/urbanopt/reopt/reopt_ghp_files/reopt_ghp_assumption.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
},
"SpaceHeatingLoad": {
},
"DomesticHotWaterLoad": {
"DomesticHotWaterLoad": {
},
"ElectricLoad": {
"ElectricLoad": {
"year": 2017
},
"ElectricTariff": {
"urdb_label": "594976725457a37b1175d089"
"urdb_label": "594976725457a37b1175d089"
},
"GHP":{
"installed_cost_heatpump_per_ton": 1075,
"installed_cost_ghx_per_ft": 14,
"installed_cost_building_hydronic_loop_per_sqft": 1.7,
"om_cost_per_sqft_year": 0,
"macrs_bonus_fraction": 0.6,
"macrs_bonus_fraction": 0.6,
"macrs_itc_reduction": 0.5,
"federal_itc_fraction": 0.3
},
Expand Down
28 changes: 11 additions & 17 deletions lib/urbanopt/reopt/reopt_ghp_post_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
module URBANopt # :nodoc:
module REopt # :nodoc:
class REoptGHPPostProcessor

def initialize(run_dir, system_parameter, modelica_result, reopt_ghp_assumptions = nil, nrel_developer_key = nil, localhost)
# initialize @@logger
@@logger ||= URBANopt::REopt.reopt_logger
Expand Down Expand Up @@ -42,11 +41,11 @@ def initialize(run_dir, system_parameter, modelica_result, reopt_ghp_assumptions
File.open(system_parameter, 'r') do |file|
@system_parameter_input_hash = JSON.parse(file.read, symbolize_names: true)
end
#Determine loop order
# Determine loop order
loop_order = File.join(File.dirname(system_parameter), '_loop_order.json')
if File.exist?(loop_order)
File.open(loop_order, 'r') do |file|
loop_order_input= JSON.parse(file.read, symbolize_names: true)
loop_order_input = JSON.parse(file.read, symbolize_names: true)
# Check the type of the parsed data
if loop_order_input.is_a?(Array)
@loop_order_input_hash = loop_order_input
Expand All @@ -61,7 +60,7 @@ def initialize(run_dir, system_parameter, modelica_result, reopt_ghp_assumptions
puts "GHE IDs in group: #{item[:list_ghe_ids_in_group].inspect}"
end
else
puts "Unexpected JSON structure"
puts 'Unexpected JSON structure'
end
end
end
Expand All @@ -77,7 +76,6 @@ def initialize(run_dir, system_parameter, modelica_result, reopt_ghp_assumptions

# # Create REopt input and output building report
def run_reopt_lcca(system_parameter_hash: nil, reopt_ghp_assumptions_hash: nil, modelica_result: nil)

adapter = URBANopt::REopt::REoptGHPAdapter.new

# if these arguments are specified, use them
Expand All @@ -89,22 +87,21 @@ def run_reopt_lcca(system_parameter_hash: nil, reopt_ghp_assumptions_hash: nil,
@reopt_ghp_assumptions_input_hash = reopt_ghp_assumptions_hash
end


if !modelica_result.nil?
@modelica_result_input = modelica_result
end

# Create folder for REopt input files only if they dont exist
reopt_ghp_dir = File.join(@run_dir, "reopt_ghp")
reopt_ghp_input = File.join(reopt_ghp_dir, "reopt_ghp_inputs")
reopt_ghp_dir = File.join(@run_dir, 'reopt_ghp')
reopt_ghp_input = File.join(reopt_ghp_dir, 'reopt_ghp_inputs')
unless Dir.exist?(reopt_ghp_dir)
FileUtils.mkdir_p(reopt_ghp_dir)
end
unless Dir.exist?(reopt_ghp_input)
FileUtils.mkdir_p(reopt_ghp_input)
end

reopt_ghp_output = File.join(reopt_ghp_dir, "reopt_ghp_outputs")
reopt_ghp_output = File.join(reopt_ghp_dir, 'reopt_ghp_outputs')
unless Dir.exist?(reopt_ghp_output)
FileUtils.mkdir_p(reopt_ghp_output)
end
Expand Down Expand Up @@ -142,14 +139,11 @@ def run_reopt_lcca(system_parameter_hash: nil, reopt_ghp_assumptions_hash: nil,

# reopt_ghp_output_file
reopt_output_file = File.join(reopt_ghp_output, "#{base_name}_output.json")
#call the REopt API
# call the REopt API
api = URBANopt::REopt::REoptLiteGHPAPI.new(reopt_input_data, DEVELOPER_NREL_KEY, reopt_output_file, @localhost)
api.get_api_results()

api.get_api_results
end

end

end #REoptGHPPostProcessor
end #REopt
end #URBANopt
end # REoptGHPPostProcessor
end # REopt
end # URBANopt
1 change: 0 additions & 1 deletion lib/urbanopt/reopt/reopt_post_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def initialize(scenario_report, scenario_reopt_assumptions_file = nil, reopt_fea
end
@nrel_developer_key = nrel_developer_key
@localhost = localhost
@reopt_base_post = { ElectricTariff: {}, ElectricLoad: {}, Wind: { max_kw: 0 } }

@scenario_reopt_default_output_file = nil
@scenario_timeseries_default_output_file = nil
Expand Down
5 changes: 2 additions & 3 deletions lib/urbanopt/reopt/reopt_schema/REopt-GHP-input.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
"building_sqft": {
"type": "float",
"requierd": true,
"required": true,
"description": "to calculate cost of hydronic loop",
"note": "for the GHX iteration, set building_sqft to a number close to 0 but not exactly 0"
},
Expand All @@ -69,7 +69,7 @@
"number_of_boreholes": {
"type": "int",
"required": true,
"note": "in the GHP iteration, set this value to 0"
"note": "in the GHP iteration, set this value to 0"
},
"length_boreholes_ft": {
"type": "float",
Expand Down Expand Up @@ -146,4 +146,3 @@
}
}
}

16 changes: 6 additions & 10 deletions lib/urbanopt/reopt/scenario_report_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ def reopt_json_from_scenario_report(scenario_report, reopt_assumptions_json = ni
else
@@logger.info('Using default REopt assumptions')
reopt_inputs = {
Settings:{},
Settings: {},
Site: {},
Financial:{},
Financial: {},
ElectricTariff: {
monthly_demand_rates: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
monthly_energy_rates: [0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
Expand Down Expand Up @@ -277,12 +277,8 @@ def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path =
wind = reopt_output['outputs']['Wind']
# find size_class
size_class = nil
if reopt_output['inputs']['Wind']['size_class']
size_class = reopt_output['inputs']['Wind']['size_class']
else
size_class = 'commercial' # default
end
scenario_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new({ size_kw: (wind['size_kw'] || 0), size_class: size_class, average_yearly_energy_produced_kwh: (wind['average_yearly_energy_produced_kwh'] || 0) })
size_class = reopt_output['inputs']['Wind']['size_class'] || 'commercial'
scenario_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new({ size_kw: (wind['size_kw'] || 0), size_class:, average_yearly_energy_produced_kwh: (wind['average_yearly_energy_produced_kwh'] || 0) })
end

if reopt_output['outputs'].key?('Generator')
Expand Down Expand Up @@ -491,15 +487,15 @@ def modrow(data, idx) # :nodoc:
data[$storage_to_grid_col] = $storage_to_grid[idx] || 0 if defined?(storage)
data[$storage_soc_col] = $storage_soc[idx] || 0 if defined?(storage)
data[$generator_total_col] = $generator_total[idx] || 0 if defined?(generator)
data[$generator_to_battery_col] = $generator_to_battery[idx] || 0 if (defined?(generator) && defined?(storage))
data[$generator_to_battery_col] = $generator_to_battery[idx] || 0 if defined?(generator) && defined?(storage)
data[$generator_to_load_col] = $generator_to_load[idx] || 0 if defined?(generator)
data[$generator_to_grid_col] = $generator_to_grid[idx] || 0 if defined?(generator)
data[$pv_total_col] = $pv_total[idx] || 0
data[$pv_to_battery_col] = $pv_to_battery[idx] || 0 if defined?(storage)
data[$pv_to_load_col] = $pv_to_load[idx] || 0
data[$pv_to_grid_col] = $pv_to_grid[idx] || 0
data[$wind_total_col] = $wind_total[idx] || 0 if defined?(wind)
data[$wind_to_battery_col] = $wind_to_battery[idx] || 0 if (defined?(wind) && defined?(storage))
data[$wind_to_battery_col] = $wind_to_battery[idx] || 0 if defined?(wind) && defined?(storage)
data[$wind_to_load_col] = $wind_to_load[idx] || 0 if defined?(wind)
data[$wind_to_grid_col] = $wind_to_grid[idx] || 0 if defined?(wind)
return data
Expand Down
2 changes: 1 addition & 1 deletion lib/urbanopt/reopt/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

module URBANopt # :nodoc:
module REopt # :nodoc:
VERSION = '0.13.0'.freeze
VERSION = '1.0.0'.freeze
end
end
3 changes: 2 additions & 1 deletion spec/files/reopt_assumptions_4tsperhour_v3.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"ElectricLoad": {
"critical_loads_kw_is_net": false,
"critical_load_fraction": 0,
"loads_kw_is_net": true
"loads_kw_is_net": true,
"year": 2017
},
"PV": {
"name": "Roof - South Face",
Expand Down
3 changes: 2 additions & 1 deletion spec/files/reopt_assumptions_with_wind_v3.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"ElectricLoad": {
"critical_loads_kw_is_net": false,
"critical_load_fraction": 0,
"loads_kw_is_net": true
"loads_kw_is_net": true,
"year": 2017
},
"PV": {
"name": "Roof - South Face",
Expand Down
3 changes: 2 additions & 1 deletion spec/tests/urbanopt_reopt_ghp_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
building_4_data = JSON.parse(File.read(@building_4_path), symbolize_names: true)

expect(building_4_data[:Site][:latitude]).to_not be_nil
expect(building_4_data[:ElectricLoad][:year]).to_not be_nil
expect(building_4_data[:ElectricLoad][:loads_kw]).to_not be_empty
expect(building_4_data[:ElectricLoad][:loads_kw].size).to eq(8760)
expect(building_4_data[:ElectricTariff][:urdb_label]).to_not be_nil
Expand All @@ -83,7 +84,7 @@
File.open(reopt_input_file_path, 'r') do |f|
reopt_input_data = JSON.parse(f.read)
end
post_url = "https://developer.nrel.gov/api/reopt/stable/job/?api_key=#{DEVELOPER_NREL_KEY}"
post_url = "https://developer.nrel.gov/api/reopt/v3/job/?api_key=#{DEVELOPER_NREL_KEY}"

# Parse the URL and prepare the HTTP request
uri = URI.parse(post_url)
Expand Down
10 changes: 7 additions & 3 deletions spec/tests/urbanopt_reopt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,15 @@
reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(nil, nil, nil, DEVELOPER_NREL_KEY)

# Act
feature_report = reopt_post_processor.run_feature_report(feature_report: feature_report, reopt_assumptions_hash: reopt_assumptions, reopt_output_file: reopt_output_file, timeseries_csv_path: timeseries_output_file, save_name: 'feature_report_reopt')
feature_report = reopt_post_processor.run_feature_report(feature_report: feature_report, reopt_output_file: reopt_output_file, timeseries_csv_path: timeseries_output_file, save_name: 'feature_report_reopt1')
feature_report = reopt_post_processor.run_feature_report(feature_report: feature_report, reopt_assumptions_hash: reopt_assumptions, reopt_output_file: reopt_output_file, timeseries_csv_path: timeseries_output_file, save_name: 'feature_report_reopt1')
feature_report = reopt_post_processor.run_feature_report(feature_report: feature_report, reopt_assumptions_hash: reopt_assumptions, timeseries_csv_path: timeseries_output_file, save_name: 'feature_report_reopt2')
feature_report = reopt_post_processor.run_feature_report(feature_report: feature_report, reopt_assumptions_hash: reopt_assumptions, reopt_output_file: reopt_output_file, save_name: 'feature_report_reopt3')
feature_report = reopt_post_processor.run_feature_report(feature_report: feature_report, save_name: 'feature_report_reopt4')

# Assert
# Assume that file size over 7kb means data was written correctly. Test file is expected to be about 10kb
expect((File.size(feature_report_dir / 'feature_reports' / 'feature_report_reopt1.json').to_f / 1024) > 7)
expect((File.size(feature_report_dir / 'feature_reports' / 'feature_report_reopt2.json').to_f / 1024) > 7)
expect((File.size(feature_report_dir / 'feature_reports' / 'feature_report_reopt3.json').to_f / 1024) > 7)

# Cleanup
FileUtils.rm_rf(scenario_dir / '1' / 'reopt')
Expand Down
4 changes: 2 additions & 2 deletions urbanopt-reopt.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ Gem::Specification.new do |spec|
# It would be nice to be able to use newer patches of Ruby 3.2, which would require os-extension to relax its dependency on bundler.
spec.required_ruby_version = '3.2.2'

# spec.add_dependency 'openstudio-extension', '~> 0.8.2'
spec.add_dependency 'openstudio-extension', '~> 0.8.3'
# Matrix is in stdlib, but needs to be specifically added here for compatibility with Ruby 3.2
spec.add_dependency 'matrix', '~> 0.4.2'
# spec.add_dependency 'urbanopt-scenario', '~> 0.12.0'
spec.add_dependency 'urbanopt-scenario', '~> 1.0.0'

spec.add_development_dependency 'rspec', '~> 3.13'
spec.add_development_dependency 'simplecov', '~> 0.22.0'
Expand Down

0 comments on commit c81d59b

Please sign in to comment.