urbanopt-reopt 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/nightly_build.yml +36 -0
- data/CHANGELOG.md +32 -0
- data/Gemfile +1 -3
- data/LICENSE.md +1 -13
- data/RDOC_MAIN.md +2 -2
- data/README.md +4 -2
- data/Rakefile +1 -1
- data/developer_nrel_key.rb +1 -1
- data/doc_templates/LICENSE.md +17 -17
- data/doc_templates/copyright_erb.txt +2 -2
- data/doc_templates/copyright_js.txt +2 -2
- data/doc_templates/copyright_ruby.txt +2 -2
- data/docs/README.md +2 -2
- data/docs/package-lock.json +6199 -4852
- data/index.md +2 -2
- data/lib/urbanopt/reopt/extension.rb +6 -16
- data/lib/urbanopt/reopt/feature_report_adapter.rb +23 -19
- data/lib/urbanopt/reopt/reopt_lite_api.rb +26 -32
- data/lib/urbanopt/reopt/reopt_logger.rb +9 -16
- data/lib/urbanopt/reopt/reopt_post_processor.rb +25 -25
- data/lib/urbanopt/reopt/reopt_schema/reopt_input_schema.json +1 -2
- data/lib/urbanopt/reopt/reopt_schema/reopt_output_schema.json +6 -1
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +7 -17
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +74 -47
- data/lib/urbanopt/reopt/utilities.rb +30 -0
- data/lib/urbanopt/reopt/version.rb +7 -17
- data/lib/urbanopt/reopt.rb +6 -16
- data/lib/urbanopt/reopt_scenario.rb +6 -16
- data/lib/urbanopt-reopt.rb +6 -16
- data/urbanopt-reopt.gemspec +3 -2
- metadata +25 -10
data/index.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# **URBANopt REopt Gem**
|
2
2
|
|
3
3
|
The **URBANopt<sup>™</sup> REopt Gem** extends **URBANopt::Reporting::DefaultReports::ScenarioReport** and **URBANopt::Reporting::DefaultReports::FeatureReport** with the ability to derive cost-optimal distributed energy resource (DER) technology sizes and annual dispatch strageties via the [REopt Lite](https://reopt.nrel.gov/tool) decision support platform.
|
4
|
-
REopt Lite is a technoeconomic model which leverages mixed integer linear programming to identify the cost-optimal sizing of solar PV, Wind, Storage and/or diesel generation given an electric load profile, a utility rate tariff and other technoeconomic parameters. See [https://developer.nrel.gov/docs/energy-optimization/reopt
|
4
|
+
REopt Lite is a technoeconomic model which leverages mixed integer linear programming to identify the cost-optimal sizing of solar PV, Wind, Storage and/or diesel generation given an electric load profile, a utility rate tariff and other technoeconomic parameters. See [https://developer.nrel.gov/docs/energy-optimization/reopt/v2/](https://developer.nrel.gov/docs/energy-optimization/reopt/v2/) for more detailed information on input parameters and default assumptions.
|
5
5
|
|
6
6
|
See the [example project](https://github.com/urbanopt/urbanopt-example-reopt-project.git) for more infomation about usage of this gem.
|
7
7
|
|
@@ -83,7 +83,7 @@ Moreover, the following optimal dispatch fields are added to its timeseries CSV.
|
|
83
83
|
| ElectricityProduced:Wind:ToGrid | kWh |
|
84
84
|
```
|
85
85
|
|
86
|
-
The REopt Lite has default values for all non-required input parameters that are used unless the user specifies custom assumptions. See [https://developer.nrel.gov/docs/energy-optimization/reopt
|
86
|
+
The REopt Lite has default values for all non-required input parameters that are used unless the user specifies custom assumptions. See [https://developer.nrel.gov/docs/energy-optimization/reopt/v2/](https://developer.nrel.gov/docs/energy-optimization/reopt/v2/) for more detailed information on input parameters and default assumptions.
|
87
87
|
|
88
88
|
<b>Note:</b> Required attributes for a REopt run include latitude and longitude. If no utility rate is specified in your REopt Lite assumption settings, then a constant default rate of $0.13 is assumed without demand charges. Also, by default, only solar PV and storage are considered in the analysis (i.e. Wind and Generators are excluded from consideration).
|
89
89
|
|
@@ -1,31 +1,21 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
|
4
|
+
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
#
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
#
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
#
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
19
|
-
# Redistribution of this software, without modification, must refer to the software
|
20
|
-
# by the same designation. Redistribution of a modified version of this software
|
21
|
-
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
-
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
-
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
-
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
-
# refer to any modified version of this software or any modified version of the
|
26
|
-
# underlying software originally provided by Alliance without the prior written
|
27
|
-
# consent of Alliance.
|
28
|
-
|
18
|
+
#
|
29
19
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
20
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
21
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -1,31 +1,21 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
|
4
|
+
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
#
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
#
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
#
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
19
|
-
# Redistribution of this software, without modification, must refer to the software
|
20
|
-
# by the same designation. Redistribution of a modified version of this software
|
21
|
-
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
-
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
-
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
-
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
-
# refer to any modified version of this software or any modified version of the
|
26
|
-
# underlying software originally provided by Alliance without the prior written
|
27
|
-
# consent of Alliance.
|
28
|
-
|
18
|
+
#
|
29
19
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
20
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
21
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -130,10 +120,10 @@ module URBANopt # :nodoc:
|
|
130
120
|
# Fill in missing timestep values with 0 if a full year is not provided
|
131
121
|
if energy_timeseries_kw.length < (feature_report.timesteps_per_hour * 8760)
|
132
122
|
start_date = Time.parse(t.by_col['Datetime'][0])
|
133
|
-
start_ts = (((start_date.yday * 60.0 * 60.0 * 24) + (start_date.hour * 60.0 * 60.0) + (start_date.min * 60.0) + start_date.sec) /
|
123
|
+
start_ts = (((start_date.yday * 60.0 * 60.0 * 24) + (start_date.hour * 60.0 * 60.0) + (start_date.min * 60.0) + start_date.sec) / \
|
134
124
|
((60 / feature_report.timesteps_per_hour) * 60)).to_int
|
135
125
|
end_date = Time.parse(t.by_col['Datetime'][-1])
|
136
|
-
end_ts = (((end_date.yday * 60.0 * 60.0 * 24) + (end_date.hour * 60.0 * 60.0) + (end_date.min * 60.0) + end_date.sec) /
|
126
|
+
end_ts = (((end_date.yday * 60.0 * 60.0 * 24) + (end_date.hour * 60.0 * 60.0) + (end_date.min * 60.0) + end_date.sec) / \
|
137
127
|
((60 / feature_report.timesteps_per_hour) * 60)).to_int
|
138
128
|
energy_timeseries_kw = [0.0] * (start_ts - 1) + energy_timeseries_kw + [0.0] * ((feature_report.timesteps_per_hour * 8760) - end_ts)
|
139
129
|
end
|
@@ -193,6 +183,7 @@ module URBANopt # :nodoc:
|
|
193
183
|
feature_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
|
194
184
|
|
195
185
|
# Update distributed generation sizing and financials
|
186
|
+
feature_report.distributed_generation.annual_renewable_electricity_pct = reopt_output['outputs']['Scenario']['Site']['annual_renewable_electricity_pct'] || 0
|
196
187
|
feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
|
197
188
|
feature_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
|
198
189
|
feature_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
|
@@ -222,17 +213,30 @@ module URBANopt # :nodoc:
|
|
222
213
|
|
223
214
|
# Store the PV name and location in a hash
|
224
215
|
location = {}
|
216
|
+
azimuth = {}
|
217
|
+
tilt = {}
|
218
|
+
module_type = {}
|
219
|
+
gcr = {}
|
220
|
+
|
225
221
|
# Check whether multi PV assumption input file is used or single PV
|
226
222
|
if reopt_output['inputs']['Scenario']['Site']['PV'].is_a?(Array)
|
227
223
|
reopt_output['inputs']['Scenario']['Site']['PV'].each do |pv|
|
228
224
|
location[pv['pv_name']] = pv['location']
|
225
|
+
azimuth[pv['pv_name']] = pv['azimuth']
|
226
|
+
tilt[pv['pv_name']] = pv['tilt']
|
227
|
+
module_type[pv['pv_name']] = pv['module_type']
|
228
|
+
gcr[pv['pv_name']] = pv['gcr']
|
229
229
|
end
|
230
230
|
else
|
231
231
|
location[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['location']
|
232
|
+
azimuth[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['azimuth']
|
233
|
+
tilt[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['tilt']
|
234
|
+
module_type[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['module_type']
|
235
|
+
gcr[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['gcr']
|
232
236
|
end
|
233
237
|
|
234
238
|
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
235
|
-
feature_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new({ size_kw: (pv['size_kw'] || 0), id: i, location: location[pv['pv_name']] })
|
239
|
+
feature_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new({ size_kw: (pv['size_kw'] || 0), id: i, location: location[pv['pv_name']], average_yearly_energy_produced_kwh: pv['average_yearly_energy_produced_kwh'], azimuth: azimuth[pv['pv_name']], tilt: tilt[pv['pv_name']], module_type: module_type[pv['pv_name']], gcr: gcr[pv['pv_name']] })
|
236
240
|
end
|
237
241
|
|
238
242
|
wind = reopt_output['outputs']['Scenario']['Site']['Wind']
|
@@ -1,31 +1,21 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
|
4
|
+
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
#
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
#
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
#
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
19
|
-
# Redistribution of this software, without modification, must refer to the software
|
20
|
-
# by the same designation. Redistribution of a modified version of this software
|
21
|
-
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
-
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
-
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
-
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
-
# refer to any modified version of this software or any modified version of the
|
26
|
-
# underlying software originally provided by Alliance without the prior written
|
27
|
-
# consent of Alliance.
|
28
|
-
|
18
|
+
#
|
29
19
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
20
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
21
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -41,7 +31,6 @@
|
|
41
31
|
require 'net/https'
|
42
32
|
require 'openssl'
|
43
33
|
require 'uri'
|
44
|
-
require 'uri'
|
45
34
|
require 'json'
|
46
35
|
require 'securerandom'
|
47
36
|
require 'certified'
|
@@ -65,8 +54,8 @@ module URBANopt # :nodoc:
|
|
65
54
|
def initialize(nrel_developer_key = nil, use_localhost = false)
|
66
55
|
@use_localhost = use_localhost
|
67
56
|
if @use_localhost
|
68
|
-
@uri_submit = URI.parse('http//:127.0.0.1:8000/
|
69
|
-
@uri_submit_outagesimjob = URI.parse('http//:127.0.0.1:8000/
|
57
|
+
@uri_submit = URI.parse('http//:127.0.0.1:8000/v2/job/')
|
58
|
+
@uri_submit_outagesimjob = URI.parse('http//:127.0.0.1:8000/v2/outagesimjob/')
|
70
59
|
else
|
71
60
|
if [nil, '', '<insert your key here>'].include? nrel_developer_key
|
72
61
|
if [nil, '', '<insert your key here>'].include? DEVELOPER_NREL_KEY
|
@@ -76,8 +65,8 @@ module URBANopt # :nodoc:
|
|
76
65
|
end
|
77
66
|
end
|
78
67
|
@nrel_developer_key = nrel_developer_key
|
79
|
-
@uri_submit = URI.parse("https://developer.nrel.gov/api/reopt/
|
80
|
-
@uri_submit_outagesimjob = URI.parse("https://developer.nrel.gov/api/reopt/
|
68
|
+
@uri_submit = URI.parse("https://developer.nrel.gov/api/reopt/v2/job?api_key=#{@nrel_developer_key}")
|
69
|
+
@uri_submit_outagesimjob = URI.parse("https://developer.nrel.gov/api/reopt/v2/outagesimjob?api_key=#{@nrel_developer_key}")
|
81
70
|
# initialize @@logger
|
82
71
|
@@logger ||= URBANopt::REopt.reopt_logger
|
83
72
|
end
|
@@ -95,10 +84,10 @@ module URBANopt # :nodoc:
|
|
95
84
|
##
|
96
85
|
def uri_results(run_uuid) # :nodoc:
|
97
86
|
if @use_localhost
|
98
|
-
return URI.parse("http://127.0.0.1:8000/
|
87
|
+
return URI.parse("http://127.0.0.1:8000/v2/job/#{run_uuid}/results")
|
99
88
|
end
|
100
89
|
|
101
|
-
return URI.parse("https://developer.nrel.gov/api/reopt/
|
90
|
+
return URI.parse("https://developer.nrel.gov/api/reopt/v2/job/#{run_uuid}/results?api_key=#{@nrel_developer_key}")
|
102
91
|
end
|
103
92
|
|
104
93
|
##
|
@@ -113,26 +102,31 @@ module URBANopt # :nodoc:
|
|
113
102
|
##
|
114
103
|
def uri_resilience(run_uuid) # :nodoc:
|
115
104
|
if @use_localhost
|
116
|
-
return URI.parse("http://127.0.0.1:8000/
|
105
|
+
return URI.parse("http://127.0.0.1:8000/v2/job/#{run_uuid}/resilience_stats")
|
117
106
|
end
|
118
107
|
|
119
|
-
return URI.parse("https://developer.nrel.gov/api/reopt/
|
108
|
+
return URI.parse("https://developer.nrel.gov/api/reopt/v2/job/#{run_uuid}/resilience_stats?api_key=#{@nrel_developer_key}")
|
120
109
|
end
|
121
110
|
|
122
|
-
def make_request(http,
|
111
|
+
def make_request(http, req, max_tries = 3)
|
123
112
|
result = nil
|
124
113
|
tries = 0
|
125
114
|
while tries < max_tries
|
126
115
|
begin
|
127
|
-
result = http.request(
|
116
|
+
result = http.request(req)
|
128
117
|
# Result codes sourced from https://developer.nrel.gov/docs/errors/
|
129
118
|
if result.code == '429'
|
130
119
|
@@logger.fatal('Exceeded the REopt-Lite API limit of 300 requests per hour')
|
131
120
|
puts 'Using the URBANopt CLI to submit a Scenario optimization counts as one request per scenario'
|
132
121
|
puts 'Using the URBANopt CLI to submit a Feature optimization counts as one request per feature'
|
133
122
|
abort('Please wait and try again once the time period has elapsed. The URBANopt CLI flag --reopt-keep-existing can be used to resume the optimization')
|
123
|
+
elsif result.code == '404'
|
124
|
+
@@logger.info("REOpt is still calculating. We'll give it a moment and check again")
|
125
|
+
sleep 15
|
126
|
+
tries += 1
|
127
|
+
next
|
134
128
|
elsif (result.code != '201') && (result.code != '200') # Anything in the 200s is success
|
135
|
-
@@logger.
|
129
|
+
@@logger.warn("REopt-Lite has returned a '#{result.code}' status code. Visit https://developer.nrel.gov/docs/errors/ for more status code information")
|
136
130
|
# display error messages
|
137
131
|
json_res = JSON.parse(result.body, allow_nan: true)
|
138
132
|
json_res['messages'].delete('warnings') if json_res['messages']['warnings']
|
@@ -351,10 +345,10 @@ module URBANopt # :nodoc:
|
|
351
345
|
sleep 5
|
352
346
|
end
|
353
347
|
|
354
|
-
|
355
|
-
|
348
|
+
max_retry = 5
|
349
|
+
tries = 0
|
356
350
|
(check_complete = sizes == 0) && ((data['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0) > 0)
|
357
|
-
while (
|
351
|
+
while (tries < max_retry) && check_complete
|
358
352
|
sleep 3
|
359
353
|
response = make_request(http, get_request)
|
360
354
|
data = JSON.parse(response.body, allow_nan: true)
|
@@ -368,7 +362,7 @@ module URBANopt # :nodoc:
|
|
368
362
|
end
|
369
363
|
sizes = pv_sizes + (data['outputs']['Scenario']['Site']['Storage']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0)
|
370
364
|
(check_complete = sizes == 0) && ((data['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0) > 0)
|
371
|
-
|
365
|
+
tries += 1
|
372
366
|
end
|
373
367
|
|
374
368
|
data = JSON.parse(response.body, allow_nan: true)
|
@@ -1,31 +1,21 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
|
4
|
+
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
#
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
#
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
#
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
19
|
-
# Redistribution of this software, without modification, must refer to the software
|
20
|
-
# by the same designation. Redistribution of a modified version of this software
|
21
|
-
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
-
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
-
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
-
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
-
# refer to any modified version of this software or any modified version of the
|
26
|
-
# underlying software originally provided by Alliance without the prior written
|
27
|
-
# consent of Alliance.
|
28
|
-
|
18
|
+
#
|
29
19
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
20
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
21
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -43,6 +33,9 @@ require 'logger'
|
|
43
33
|
module URBANopt
|
44
34
|
module REopt
|
45
35
|
@@reopt_logger = Logger.new($stdout)
|
36
|
+
|
37
|
+
# Set Logger::DEBUG for development
|
38
|
+
@@reopt_logger.level = Logger::WARN
|
46
39
|
##
|
47
40
|
# Definining class variable "@@logger" to log errors, info and warning messages.
|
48
41
|
def self.reopt_logger
|
@@ -1,31 +1,21 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
|
4
|
+
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
#
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
#
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
#
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
19
|
-
# Redistribution of this software, without modification, must refer to the software
|
20
|
-
# by the same designation. Redistribution of a modified version of this software
|
21
|
-
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
-
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
-
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
-
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
-
# refer to any modified version of this software or any modified version of the
|
26
|
-
# underlying software originally provided by Alliance without the prior written
|
27
|
-
# consent of Alliance.
|
28
|
-
|
18
|
+
#
|
29
19
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
20
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
21
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -93,20 +83,19 @@ module URBANopt # :nodoc:
|
|
93
83
|
@@logger.info("Created directory: #{File.join(fr.directory_name, 'reopt')}")
|
94
84
|
end
|
95
85
|
@feature_reports_reopt_default_output_files << File.join(fr.directory_name, "reopt/feature_report_#{fr.id}_reopt_run.json")
|
96
|
-
end
|
97
|
-
|
98
|
-
@scenario_report.feature_reports.each do |fr|
|
99
86
|
@feature_reports_timeseries_default_output_files << File.join(fr.directory_name, "feature_report_#{fr.id}_timeseries.csv")
|
100
87
|
end
|
101
88
|
end
|
102
89
|
|
103
90
|
if !scenario_reopt_assumptions_file.nil?
|
91
|
+
@scenario_reopt_assumptions_file = scenario_reopt_assumptions_file
|
104
92
|
File.open(scenario_reopt_assumptions_file, 'r') do |file|
|
105
93
|
@scenario_reopt_default_assumptions_hash = JSON.parse(file.read, symbolize_names: true)
|
106
94
|
end
|
107
95
|
end
|
108
96
|
|
109
97
|
if !reopt_feature_assumptions.empty?
|
98
|
+
@reopt_feature_assumptions = reopt_feature_assumptions
|
110
99
|
reopt_feature_assumptions.each do |file|
|
111
100
|
@feature_reports_reopt_default_assumption_hashes << JSON.parse(File.open(file, 'r').read, symbolize_names: true)
|
112
101
|
end
|
@@ -137,12 +126,13 @@ module URBANopt # :nodoc:
|
|
137
126
|
reopt_output_file = File.join(feature_report.directory_name, 'reopt')
|
138
127
|
end
|
139
128
|
reopt_output = api.reopt_request(reopt_input, reopt_output_file)
|
129
|
+
@@logger.debug("REOpt output file: #{reopt_output_file}")
|
140
130
|
if run_resilience
|
141
131
|
run_uuid = reopt_output['outputs']['Scenario']['run_uuid']
|
142
132
|
if File.directory? reopt_output_file
|
143
133
|
resilience_stats = api.resilience_request(run_uuid, reopt_output_file)
|
144
134
|
else
|
145
|
-
resilience_stats = api.resilience_request(run_uuid, reopt_output_file.sub
|
135
|
+
resilience_stats = api.resilience_request(run_uuid, reopt_output_file.sub('.json', '_resilience.json'))
|
146
136
|
end
|
147
137
|
else
|
148
138
|
resilience_stats = nil
|
@@ -167,8 +157,12 @@ module URBANopt # :nodoc:
|
|
167
157
|
#
|
168
158
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ Returns an updated ScenarioReport
|
169
159
|
def run_scenario_report(scenario_report:, reopt_assumptions_hash: nil, reopt_output_file: nil, timeseries_csv_path: nil, save_name: nil, run_resilience: true, community_photovoltaic: nil)
|
160
|
+
puts 'run scenario report'
|
161
|
+
@save_assumptions_filepath = false
|
170
162
|
if !reopt_assumptions_hash.nil?
|
171
163
|
@scenario_reopt_default_assumptions_hash = reopt_assumptions_hash
|
164
|
+
else
|
165
|
+
@save_assumptions_filepath = true
|
172
166
|
end
|
173
167
|
if !reopt_output_file.nil?
|
174
168
|
@scenario_reopt_default_output_file = reopt_output_file
|
@@ -188,15 +182,21 @@ module URBANopt # :nodoc:
|
|
188
182
|
if File.directory? @scenario_reopt_default_output_file
|
189
183
|
resilience_stats = api.resilience_request(run_uuid, @scenario_reopt_default_output_file)
|
190
184
|
else
|
191
|
-
resilience_stats = api.resilience_request(run_uuid, @scenario_reopt_default_output_file.sub
|
185
|
+
resilience_stats = api.resilience_request(run_uuid, @scenario_reopt_default_output_file.sub('.json', '_resilience.json'))
|
192
186
|
end
|
193
187
|
else
|
194
188
|
resilience_stats = nil
|
195
189
|
end
|
196
190
|
|
197
191
|
result = adapter.update_scenario_report(scenario_report, reopt_output, @scenario_timeseries_default_output_file, resilience_stats)
|
192
|
+
# can you save the assumptions file path that was used?
|
193
|
+
if @save_assumptions_filepath && @scenario_reopt_assumptions_file
|
194
|
+
result.distributed_generation.reopt_assumptions_file_path = @scenario_reopt_assumptions_file
|
195
|
+
end
|
196
|
+
|
198
197
|
if !save_name.nil?
|
199
|
-
|
198
|
+
# don't save individual feature reports when doing the scenario optimization!
|
199
|
+
result.save(save_name, false)
|
200
200
|
end
|
201
201
|
return result
|
202
202
|
end
|
@@ -251,7 +251,7 @@ module URBANopt # :nodoc:
|
|
251
251
|
if File.directory? @feature_reports_reopt_default_output_files[idx]
|
252
252
|
resilience_stats = api.resilience_request(run_uuid, @feature_reports_reopt_default_output_files[idx])
|
253
253
|
else
|
254
|
-
resilience_stats = api.resilience_request(run_uuid, @feature_reports_reopt_default_output_files[idx].sub
|
254
|
+
resilience_stats = api.resilience_request(run_uuid, @feature_reports_reopt_default_output_files[idx].sub('.json', '_resilience.json'))
|
255
255
|
end
|
256
256
|
else
|
257
257
|
resilience_stats = nil
|
@@ -270,7 +270,7 @@ module URBANopt # :nodoc:
|
|
270
270
|
@@logger.error("ERROR: #{e}")
|
271
271
|
end
|
272
272
|
else
|
273
|
-
|
273
|
+
@@logger.info('Output file already exists...skipping')
|
274
274
|
end
|
275
275
|
end
|
276
276
|
|
@@ -308,7 +308,7 @@ module URBANopt # :nodoc:
|
|
308
308
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
|
309
309
|
def run_scenario_report_features(scenario_report:, reopt_assumptions_hashes: [], reopt_output_files: [], feature_report_timeseries_csv_paths: [], save_names_feature_reports: nil, save_name_scenario_report: nil, run_resilience: true, keep_existing_output: false, groundmount_photovoltaic: nil)
|
310
310
|
new_feature_reports = run_feature_reports(feature_reports: scenario_report.feature_reports, reopt_assumptions_hashes: reopt_assumptions_hashes, reopt_output_files: reopt_output_files, timeseries_csv_paths: feature_report_timeseries_csv_paths, save_names: save_names_feature_reports, run_resilience: run_resilience, keep_existing_output: keep_existing_output, groundmount_photovoltaic: groundmount_photovoltaic)
|
311
|
-
|
311
|
+
|
312
312
|
# only do this if you have run feature reports
|
313
313
|
new_scenario_report = URBANopt::Reporting::DefaultReports::ScenarioReport.new
|
314
314
|
if !new_feature_reports.empty?
|
@@ -71,6 +71,11 @@
|
|
71
71
|
"Site": {
|
72
72
|
"type": "object",
|
73
73
|
"properties": {
|
74
|
+
"annual_renewable_electricity_pct": {
|
75
|
+
"type": "float",
|
76
|
+
"description": "Fraction of annual renewable electricity - 0 for none, 1 for all, over 1 for more generated than consumed",
|
77
|
+
"units": "none"
|
78
|
+
},
|
74
79
|
"LoadProfile": {
|
75
80
|
"type": "object",
|
76
81
|
"properties": {
|
@@ -540,4 +545,4 @@
|
|
540
545
|
}
|
541
546
|
}
|
542
547
|
}
|
543
|
-
}
|
548
|
+
}
|
@@ -1,31 +1,21 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
|
-
|
4
|
+
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
#
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
#
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
#
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
19
|
-
# Redistribution of this software, without modification, must refer to the software
|
20
|
-
# by the same designation. Redistribution of a modified version of this software
|
21
|
-
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
-
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
-
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
-
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
-
# refer to any modified version of this software or any modified version of the
|
26
|
-
# underlying software originally provided by Alliance without the prior written
|
27
|
-
# consent of Alliance.
|
28
|
-
|
18
|
+
#
|
29
19
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
20
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
21
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -106,7 +96,7 @@ module URBANopt
|
|
106
96
|
if row.length > 3 && !@reopt_files_dir.nil?
|
107
97
|
@reopt_feature_assumptions[idx - 1] = File.join(@reopt_files_dir, row[3].chomp)
|
108
98
|
end
|
109
|
-
|
99
|
+
|
110
100
|
# gets +features+ from the feature_file.
|
111
101
|
features = []
|
112
102
|
feature = feature_file.get_feature_by_id(feature_id)
|