Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/urbanopt/reopt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
require 'urbanopt/reopt/reopt_post_processor'
require 'urbanopt/reopt/version'
require 'urbanopt/reopt/reopt_ghp_post_processor'
require 'urbanopt/reopt/reopt_ghp_adapter'
require 'urbanopt/reopt/reopt_ghp_adapter_ghp'
require 'urbanopt/reopt/reopt_ghp_api'
require 'urbanopt/reopt/reopt_ghp_result'

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions lib/urbanopt/reopt/reopt_ghp_post_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'bundler/setup'
require 'urbanopt/reopt/reopt_logger'
require 'urbanopt/reopt/reopt_ghp_api'
require 'urbanopt/reopt/reopt_ghp_result'
require 'csv'
require 'json'
require 'fileutils'
Expand Down Expand Up @@ -115,12 +116,14 @@ def run_reopt_lcca(system_parameter_hash: nil, reopt_ghp_assumptions_hash: nil,
end

building_ids.each do |building_id|
# create REopt building input file for all buildings in loop order list
reopt_input_building = adapter.create_reopt_input_building(@run_dir, @system_parameter_input_hash, @reopt_ghp_assumptions_input_hash, building_id, @modelica_result_input)
# create REopt building input file for all buildings in loop order list in GHP scenario
reopt_input_building = adapter.create_reopt_input_building_ghp(@run_dir, @system_parameter_input_hash, @reopt_ghp_assumptions_input_hash, building_id, @modelica_result_input)
#create REopt building input file for all buildings in loop order list in BAU scenario
reopt_input_building_bau = adapter.create_reopt_input_building_bau(@run_dir, @system_parameter_input_hash, @reopt_ghp_assumptions_input_hash, building_id, @modelica_result_input)
end
ghp_ids.each do |ghp_id|
# create REopt district input file
reopt_input_district = adapter.create_reopt_input_district(@run_dir, @system_parameter_input_hash, @reopt_ghp_assumptions_input_hash, ghp_id, @modelica_result_input)
reopt_input_district = adapter.create_reopt_input_district_ghp(@run_dir, @system_parameter_input_hash, @reopt_ghp_assumptions_input_hash, ghp_id, @modelica_result_input)
end

Dir.foreach(reopt_ghp_input) do |input_file|
Expand All @@ -142,8 +145,14 @@ def run_reopt_lcca(system_parameter_hash: nil, reopt_ghp_assumptions_hash: nil,
# call the REopt API
api = URBANopt::REopt::REoptLiteGHPAPI.new(reopt_input_data, DEVELOPER_NREL_KEY, reopt_output_file, @localhost)
api.get_api_results

end

## POST PROCESS RESULTS
ghp_results = URBANopt::REopt::REoptGHPResult.new
results = ghp_results.result_calculate(reopt_ghp_dir)
end

end # REoptGHPPostProcessor
end # REopt
end # URBANopt
117 changes: 117 additions & 0 deletions lib/urbanopt/reopt/reopt_ghp_result.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# *********************************************************************************
# URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
# See also https://github.com/urbanopt/urbanopt-reopt-gem/blob/develop/LICENSE.md
# *********************************************************************************

module URBANopt # :nodoc:
module REopt # :nodoc:
class REoptGHPResult

def initialize
# initialize @@logger
@@logger ||= URBANopt::REopt.reopt_logger
end

def result_calculate(reopt_ghp_dir)
bau_output_dict = {}
ghp_output_dict = {}
reopt_output = File.join(reopt_ghp_dir, 'reopt_ghp_outputs')
bau_outputs = []
ghp_outputs = []
Dir.glob(File.join(reopt_output, '*')) do |file|
next unless File.file?(file)

prefix = File.basename(file).split('_').first
bau_outputs << file if prefix == 'BAU'
ghp_outputs << file if prefix == 'GHP'
ghp_outputs << file if prefix == 'GHX'
end

# Initialize variables
lcc_bau = 0
lcc_ghp = 0
lcc_net = 0
lifecycle_capital_costs_bau = 0
lifecycle_capital_costs_ghp = 0
lifecycle_capital_costs_net = 0
initial_capital_costs_bau = 0
initial_capital_costs_ghp = 0
initial_capital_costs_net = 0
initial_capital_costs_after_incentives_bau = 0
initial_capital_costs_after_incentives_ghp = 0
initial_capital_costs_after_incentives_net = 0
lifecycle_elecbill_after_tax_bau = 0
lifecycle_elecbill_after_tax_ghp = 0
lifecycle_elecbill_after_tax_net = 0
npv_bau = 0
npv_ghp = 0
npv_net = 0

unless bau_outputs.empty?
bau_outputs.each do |file|
bau_file = JSON.parse(File.read(file), symbolize_names: true)
financial = bau_file.dig(:outputs, :Financial) || {}

lcc_bau += financial[:lcc] || 0
initial_capital_costs_bau += financial[:initial_capital_costs] || 0
initial_capital_costs_after_incentives_bau += financial[:initial_capital_costs_after_incentives] || 0
lifecycle_capital_costs_bau += financial[:lifecycle_capital_costs] || 0
lifecycle_elecbill_after_tax_bau += financial[:lifecycle_elecbill_after_tax_bau] || 0
npv_bau += financial[:npv] || 0
end
end

unless ghp_outputs.empty?
ghp_outputs.each do |file|
ghp_file = JSON.parse(File.read(file), symbolize_names: true)
financial = ghp_file.dig(:outputs, :Financial) || {}

lcc_ghp += financial[:lcc] || 0
initial_capital_costs_ghp += financial[:initial_capital_costs] || 0
initial_capital_costs_after_incentives_ghp += financial[:initial_capital_costs_after_incentives] || 0
lifecycle_capital_costs_ghp += financial[:lifecycle_capital_costs] || 0
lifecycle_elecbill_after_tax_ghp += financial[:lifecycle_elecbill_after_tax] || 0
npv_ghp += financial[:npv] || 0
end
end

# Net calculations
lcc_net = lcc_ghp - lcc_bau
initial_capital_costs_net = initial_capital_costs_ghp - initial_capital_costs_bau
initial_capital_costs_after_incentives_net = initial_capital_costs_after_incentives_ghp - initial_capital_costs_after_incentives_bau
lifecycle_capital_costs_net = lifecycle_capital_costs_ghp - lifecycle_capital_costs_bau
lifecycle_elecbill_after_tax_net = lifecycle_elecbill_after_tax_ghp - lifecycle_elecbill_after_tax_bau
npv_net = npv_ghp - npv_bau

# Write output JSON
result_data = {
lcc_bau: lcc_bau,
lcc_ghp: lcc_ghp,
lcc_net: lcc_net,
initial_capital_costs_bau: initial_capital_costs_bau,
initial_capital_costs_ghp: initial_capital_costs_ghp,
initial_capital_costs_net: initial_capital_costs_net,
initial_capital_costs_after_incentives_bau: initial_capital_costs_after_incentives_bau,
initial_capital_costs_after_incentives_ghp: initial_capital_costs_after_incentives_ghp,
initial_capital_costs_after_incentives_net: initial_capital_costs_after_incentives_net,
lifecycle_capital_costs_bau: lifecycle_capital_costs_bau,
lifecycle_capital_costs_ghp: lifecycle_capital_costs_ghp,
lifecycle_capital_costs_net: lifecycle_capital_costs_net,
lifecycle_elecbill_after_tax_bau: lifecycle_elecbill_after_tax_bau,
lifecycle_elecbill_after_tax_ghp: lifecycle_elecbill_after_tax_ghp,
lifecycle_elecbill_after_tax_net: lifecycle_elecbill_after_tax_net,
npv_bau: npv_bau,
npv_ghp: npv_ghp,
npv_net: npv_net
}

File.open(File.join(reopt_ghp_dir, "reopt_ghp_result_summary.json"), "w") do |file|
file.write(JSON.pretty_generate(result_data))
end


end

end
end
end
95 changes: 95 additions & 0 deletions lib/urbanopt/reopt/reopt_schema/REopt-BAU-input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"Site": {
"latitude": {
"type": "float",
"min": -90,
"max": 90,
"description": "The approximate latitude of the site in decimal degrees.",
"required": true
},
"longitude": {
"type": "float",
"min": -180,
"max": 180,
"description": "The approximate longitude of the site in decimal degrees.",
"required": true
}
},
"SpaceHeatingLoad": {
"fuel_loads_mmbtu_per_hour": {
"type": "array",
"required": true,
"description": "This is the fuel energy consumption for space heating at the individual building level. This is used in the business as usual (BAU) LCCA analysis in the GHP module to calculate BAU bills. These are 8760 hourly timeseries values.",
"note": "This parameter is required to run REopt's BAU for GHP module. If there is no fuel based heating in BAU, add values close to 0."
}
},
"DomesticHotWaterLoad": {
"fuel_loads_mmbtu_per_hour": {
"type": "array",
"required": false,
"description": "This is the fuel enegry consumption for providing domestic hot water at the individual building level. This is used in the business as usual (BAU) LCCA analysis in the GHP module. These are 8760 hourly timeseries values.",
"note": "Only required if BAU system has DHW load and uses fuel for this load. If BAU system has no DHW load, or does not use fuel for DHW heating, set to values close to zeros. If BAU system uses electricity for DHW, please add this electric DHW load to ElectricLoad"

}
},
"CoolingLoad":{
"fuel_loads_mmbtu_per_hour": {
"type": "array",
"required": true,
"description": "This is the fuel energy consumption for space cooling at the individual building level. This is used in the business as usual (BAU) LCCA analysis in the GHP module to calculate BAU bills. These are 8760 hourly timeseries values.",
"note": "Only required if BAU system uses fuel for cooling. If BAU system uses electricity for cooling (AC), please add this load to ElectricLoad defined below. If BAU system has no cooling load, set to values close to zeros."
}
},
"ElectricLoad": {
"load_kw": {
"type": "array",
"required": true,
"description": "8760 timeseries",
"note": "This is the electric load profile for heating and cooling in the BAU scenario (kW). It is an hourly timeseries load profile with 8760 values. If there is no electricity based heating or cooling in BAU, set these values close to 0."
}
},
"ElectricTarriff": {
"urdb_label": "string",
"required": true,
"description": "Label attribute of utility rate structure from https://openei.org/services/doc/rest/util_rates/?version=3."
},
"ExistingBoiler": {
"fuel_cost_per_mmbtu": {
"type": "float",
"required": false,
"description": "Only required if BAU system use fuel for heating. In this case, fuel cost needs to be specified"
},
"installed_cost_per_mmbtu_per_hour": {
"type": "float",
"required": false,
"description": "Capital cost of ExistingBoiler. Include if counting the capital cost of upgrading ExistingBoiler in the BAU system in NPV calculation. Default is $56,000/MMBtu (EIA). The peak heating load is considered to be the size of the system and is multiplied by this field to get total capital cost. Note: this option can only be called from the API after July 2, 2025"
}
},
"ElectricHeater": {
"installed_cost_per_mmbtu_per_hour": {
"type": "float",
"required": false,
"description": "Capital cost of ElectricHeater/Electric furnace. Include if BAU system use electric heater/electric furnace for heating and if counting capital cost of upgrading electric heater/furnace in the BAU system in NPV calculation. Default value is $59,412/MMBtu (EIA)"
},
"min_mmbtu_per_hour":{
"type": "float",
"required": false,
"description": "User defined input for the size of electric heater system. This value should be the same in min_mmbtu_per_hour and max_mmbtu_per_hour."
},
"max_mmbtu_per_hour":{
"type": "float",
"required": false,
"description": "User defined input for the size of electric heater system. This value should be the same in min_mmbtu_per_hour and max_mmbtu_per_hour."
},
"can_serve_space_heating": {
"type": "bool",
"required": false,
"description": "true if electric heater can serve space heating load in the BAU system"
},
"can_serve_dhw": {
"type": "bool",
"required": false,
"description": "true if electric heater can serve water heating load in the BAU system"
}
}
}
Loading