urbanopt-reopt 0.3.0.pre1 → 0.5.4
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/pull_request_template.md +2 -2
- data/.gitignore +3 -0
- data/CHANGELOG.md +69 -3
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +2 -5
- data/LICENSE.md +1 -1
- data/RDOC_MAIN.md +13 -13
- data/README.md +15 -15
- data/Rakefile +30 -0
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/docs/README.md +16 -16
- data/docs/package-lock.json +10084 -151
- data/docs/package.json +8 -4
- data/index.md +13 -13
- data/lib/urbanopt-reopt.rb +1 -1
- data/lib/urbanopt/reopt.rb +1 -1
- data/lib/urbanopt/reopt/extension.rb +1 -1
- data/lib/urbanopt/reopt/feature_report_adapter.rb +102 -64
- data/lib/urbanopt/reopt/reopt_lite_api.rb +117 -12
- data/lib/urbanopt/reopt/reopt_logger.rb +1 -1
- data/lib/urbanopt/reopt/reopt_post_processor.rb +57 -24
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +1 -1
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +106 -72
- data/lib/urbanopt/reopt/utilities.rb +107 -0
- data/lib/urbanopt/reopt/version.rb +2 -2
- data/lib/urbanopt/reopt_scenario.rb +1 -1
- data/urbanopt-reopt.gemspec +8 -5
- metadata +35 -20
- data/.travis.yml +0 -22
data/docs/package.json
CHANGED
@@ -10,13 +10,17 @@
|
|
10
10
|
},
|
11
11
|
"author": "NREL",
|
12
12
|
"dependencies": {
|
13
|
-
"
|
13
|
+
"braces": "^3.0.2",
|
14
|
+
"highlight.js": "^10.4.1",
|
14
15
|
"json-schema-ref-parser": "^6.1.0",
|
15
16
|
"json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
|
16
|
-
"
|
17
|
-
"
|
17
|
+
"serialize-javascript": "^5.0.1",
|
18
|
+
"vuepress": "^1.6.0",
|
19
|
+
"webpack-dev-middleware": "^3.6.0",
|
20
|
+
"yargs-parser": "^18.1.1"
|
18
21
|
},
|
19
22
|
"devDependencies": {
|
20
|
-
"gh-pages": "^2.0.1"
|
23
|
+
"gh-pages": "^2.0.1",
|
24
|
+
"ini": "^2.0.0"
|
21
25
|
}
|
22
26
|
}
|
data/index.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# **URBANopt REopt Gem**
|
2
2
|
|
3
|
-
The **URBANopt REopt Gem** extends **URBANopt::
|
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-v1/](https://developer.nrel.gov/docs/energy-optimization/reopt-v1/) for more detailed information on input parameters and default assumptions.
|
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-v1/](https://developer.nrel.gov/docs/energy-optimization/reopt-v1/) 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
|
|
@@ -9,7 +9,7 @@ See the [example project](https://github.com/urbanopt/urbanopt-example-reopt-pro
|
|
9
9
|
|
10
10
|
## Installation
|
11
11
|
|
12
|
-
See [https://docs.urbanopt.net/installation/installation.html](https://docs.urbanopt.net/installation/installation.html) for instructions on prerequiste software, including:
|
12
|
+
See [https://docs.urbanopt.net/installation/installation.html](https://docs.urbanopt.net/installation/installation.html) for instructions on prerequiste software, including:
|
13
13
|
- Ruby 2.2.6
|
14
14
|
- Bundler 1.17.0
|
15
15
|
- OpenStudio 2.8.1
|
@@ -31,7 +31,7 @@ Or install it yourself as:
|
|
31
31
|
|
32
32
|
## Functionality
|
33
33
|
|
34
|
-
This gem is used to call the REopt Lite API on a Scenario Report or Feature Report to update the object's Distributed Generation attributes (including system financial and sizing metrics) as shown in an example below:
|
34
|
+
This gem is used to call the REopt Lite API on a Scenario Report or Feature Report to update the object's Distributed Generation attributes (including system financial and sizing metrics) as shown in an example below:
|
35
35
|
|
36
36
|
```
|
37
37
|
"distributed_generation": {
|
@@ -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-v1/](https://developer.nrel.gov/docs/energy-optimization/reopt-v1/) for more detailed information on input parameters and default assumptions.
|
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-v1/](https://developer.nrel.gov/docs/energy-optimization/reopt-v1/) 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
|
|
@@ -99,7 +99,7 @@ require 'urbanopt/reopt'
|
|
99
99
|
feature_reports_hash = {} # <insert a Feature Report hash here>
|
100
100
|
|
101
101
|
#Create a Feature Report
|
102
|
-
feature_report = URBANopt::
|
102
|
+
feature_report = URBANopt::Reporting::DefaultReports::FeatureReport.new(feature_reports_hash)
|
103
103
|
|
104
104
|
#Specify a file name where REopt Lite results will be written in JSON format
|
105
105
|
reopt_output_file = File.join(feature_report.directory_name, 'feature_report_reopt_run1.json')
|
@@ -115,7 +115,7 @@ reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(nil, nil, nil, DE
|
|
115
115
|
|
116
116
|
#Call REopt Lite with the post processor to update the feature's distributed generation attributes and timeseries CSV.
|
117
117
|
updated_feature_report = reopt_post_processor.run_feature_report(feature_report,reopt_assumptions_file,reopt_output_file,timeseries_output_file)
|
118
|
-
|
118
|
+
|
119
119
|
```
|
120
120
|
|
121
121
|
More commonly, this gem can be used to run REopt a collection of features stored in a Scenario Report as show here:
|
@@ -123,9 +123,9 @@ More commonly, this gem can be used to run REopt a collection of features stored
|
|
123
123
|
```ruby
|
124
124
|
require 'urbanopt/reopt'
|
125
125
|
#Create a Scenario Report
|
126
|
-
scenario_report = URBANopt::
|
126
|
+
scenario_report = URBANopt::Reporting::DefaultReports::ScenarioReport.new({:directory_name => File.join(File.dirname(__FILE__), '../run/example_scenario'), :timeseries_csv => {:path => File.join(File.dirname(__FILE__), '../run/example_scenario/timeseries.csv') }})
|
127
127
|
|
128
|
-
#Load Feature Reports into the Scenario Report
|
128
|
+
#Load Feature Reports into the Scenario Report
|
129
129
|
(1..2).each do |i|
|
130
130
|
feature_reports_path = File.join(File.dirname(__FILE__), "../run/example_scenario/#{i}/010_default_feature_reports/default_feature_reports.json")
|
131
131
|
|
@@ -134,8 +134,8 @@ scenario_report = URBANopt::Scenario::DefaultReports::ScenarioReport.new({:direc
|
|
134
134
|
feature_reports_hash = JSON.parse(file.read, symbolize_names: true)
|
135
135
|
end
|
136
136
|
|
137
|
-
feature_report = URBANopt::
|
138
|
-
|
137
|
+
feature_report = URBANopt::Reporting::DefaultReports::FeatureReport.new(feature_reports_hash)
|
138
|
+
|
139
139
|
feature_report_dir = File.join(File.dirname(__FILE__), "../run/example_scenario/#{i}")
|
140
140
|
feature_report.directory_name = feature_report_dir
|
141
141
|
|
@@ -150,7 +150,7 @@ reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(scenario_report,
|
|
150
150
|
|
151
151
|
#Call REopt Lite with the post processor once on the sceanrio's aggregated load to update the scenario's distributed generation attributes and timeseries CSV.
|
152
152
|
updated_scenario_report = reopt_post_processor.run_scenario_report(scenario_report)
|
153
|
-
|
153
|
+
|
154
154
|
```
|
155
155
|
|
156
156
|
## Testing
|
@@ -164,7 +164,7 @@ Next, obtain a developer.nrel.gov API key from the [NREL Developer Network](http
|
|
164
164
|
Finally, execute:
|
165
165
|
|
166
166
|
$ bundle install
|
167
|
-
$ bundle update
|
167
|
+
$ bundle update
|
168
168
|
$ bundle exec rake
|
169
169
|
|
170
170
|
|
data/lib/urbanopt-reopt.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, 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,
|
data/lib/urbanopt/reopt.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, 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,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, 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,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, 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,
|
@@ -28,17 +28,18 @@
|
|
28
28
|
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
# *********************************************************************************
|
30
30
|
|
31
|
-
require 'urbanopt/
|
31
|
+
require 'urbanopt/reporting/default_reports'
|
32
32
|
require 'urbanopt/reopt/reopt_logger'
|
33
33
|
require 'csv'
|
34
34
|
require 'matrix'
|
35
|
+
require_relative 'utilities'
|
35
36
|
require 'time'
|
36
37
|
|
37
38
|
module URBANopt # :nodoc:
|
38
39
|
module REopt # :nodoc:
|
39
40
|
class FeatureReportAdapter
|
40
41
|
##
|
41
|
-
# FeatureReportAdapter can convert a URBANopt::
|
42
|
+
# FeatureReportAdapter can convert a URBANopt::Reporting::DefaultReports::FeatureReport into a \REopt Lite posts or update a URBANopt::Reporting::DefaultReports::FeatureReport from a \REopt Lite response.
|
42
43
|
##
|
43
44
|
# [*parameters:*]
|
44
45
|
##
|
@@ -52,7 +53,7 @@ module URBANopt # :nodoc:
|
|
52
53
|
#
|
53
54
|
# [*parameters:*]
|
54
55
|
#
|
55
|
-
# * +feature_report+ - _URBANopt::
|
56
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport to use in converting the optional +reopt_assumptions_hash+ to a \REopt Lite post. If a +reopt_assumptions_hash+ is not provided, a default post will be updated from this FeatureReport and submitted to the \REopt Lite API.
|
56
57
|
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt Lite API containing default values. Values will be overwritten from the FeatureReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API.
|
57
58
|
#
|
58
59
|
# [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt Lite API
|
@@ -69,11 +70,11 @@ module URBANopt # :nodoc:
|
|
69
70
|
|
70
71
|
# Check FeatureReport has required data
|
71
72
|
requireds_names = ['latitude', 'longitude']
|
72
|
-
requireds = [feature_report.location.
|
73
|
+
requireds = [feature_report.location.latitude_deg, feature_report.location.longitude_deg]
|
73
74
|
|
74
75
|
if requireds.include?(nil) || requireds.include?(0)
|
75
76
|
requireds.each_with_index do |i, x|
|
76
|
-
if [nil
|
77
|
+
if [nil].include? x
|
77
78
|
n = requireds_names[i]
|
78
79
|
# @@logger.error("Missing value for #{n} - this is a required input")
|
79
80
|
raise "Missing value for #{n} - this is a required input"
|
@@ -84,27 +85,33 @@ module URBANopt # :nodoc:
|
|
84
85
|
reopt_inputs[:Scenario][:description] = description
|
85
86
|
|
86
87
|
# Parse Location
|
87
|
-
reopt_inputs[:Scenario][:Site][:latitude] = feature_report.location.
|
88
|
-
reopt_inputs[:Scenario][:Site][:longitude] = feature_report.location.
|
88
|
+
reopt_inputs[:Scenario][:Site][:latitude] = feature_report.location.latitude_deg
|
89
|
+
reopt_inputs[:Scenario][:Site][:longitude] = feature_report.location.longitude_deg
|
89
90
|
|
90
|
-
# Parse Optional FeatureReport metrics
|
91
|
-
|
92
|
-
|
91
|
+
# Parse Optional FeatureReport metrics - do not overwrite from assumptions file
|
92
|
+
if reopt_inputs[:Scenario][:Site][:roof_squarefeet].nil?
|
93
|
+
unless feature_report.program.roof_area_sqft.nil?
|
94
|
+
reopt_inputs[:Scenario][:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area_sqft]
|
95
|
+
end
|
93
96
|
end
|
94
97
|
|
95
|
-
|
96
|
-
|
98
|
+
if reopt_inputs[:Scenario][:Site][:land_acres].nil?
|
99
|
+
unless feature_report.program.site_area_sqft.nil?
|
100
|
+
reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
|
101
|
+
end
|
97
102
|
end
|
98
103
|
|
99
|
-
|
100
|
-
reopt_inputs[:Scenario][:time_steps_per_hour] =
|
104
|
+
if reopt_inputs[:Scenario][:time_steps_per_hour].nil?
|
105
|
+
reopt_inputs[:Scenario][:time_steps_per_hour] = 1
|
101
106
|
end
|
102
107
|
|
103
108
|
# Parse Load Profile
|
104
109
|
begin
|
110
|
+
#Convert kWh values in the timeseries CSV to kW
|
105
111
|
col_num = feature_report.timeseries_csv.column_names.index('Electricity:Facility(kWh)')
|
106
112
|
t = CSV.read(feature_report.timeseries_csv.path, headers: true, converters: :numeric)
|
107
113
|
energy_timeseries_kw = t.by_col[col_num].map { |e| ((e * feature_report.timesteps_per_hour || 0) ) }
|
114
|
+
#Fill in missing timestep values with 0 if a full year is not provided
|
108
115
|
if energy_timeseries_kw.length < (feature_report.timesteps_per_hour * 8760)
|
109
116
|
start_date = Time.parse(t.by_col["Datetime"][0])
|
110
117
|
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) /
|
@@ -113,33 +120,60 @@ module URBANopt # :nodoc:
|
|
113
120
|
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) /
|
114
121
|
(( 60 / feature_report.timesteps_per_hour ) * 60)).to_int
|
115
122
|
energy_timeseries_kw = [0.0]*(start_ts-1) + energy_timeseries_kw + [0.0]*((feature_report.timesteps_per_hour * 8760) - end_ts)
|
116
|
-
end
|
117
|
-
|
123
|
+
end
|
124
|
+
#Clip to one non-leap year's worth of data
|
125
|
+
energy_timeseries_kw = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(feature_report.timesteps_per_hour * 8760)]
|
126
|
+
#Convert from the OpenDSS resolution to the REopt Lite resolution, if necessary
|
118
127
|
rescue StandardError
|
119
128
|
@@logger.error("Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}")
|
120
129
|
raise "Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}"
|
121
130
|
end
|
131
|
+
|
132
|
+
# Convert load to REopt Resolution
|
133
|
+
begin
|
134
|
+
reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, feature_report.timesteps_per_hour, reopt_inputs[:Scenario][:time_steps_per_hour])
|
135
|
+
|
136
|
+
rescue
|
137
|
+
@@logger.error("Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}")
|
138
|
+
raise "Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}"
|
139
|
+
end
|
140
|
+
|
141
|
+
if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps].nil?
|
142
|
+
n_top_values = 100
|
143
|
+
tmp1 = reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw]
|
144
|
+
tmp2 = tmp1.each_index.max_by(n_top_values*reopt_inputs[:Scenario][:time_steps_per_hour]){|i| tmp1[i]}
|
145
|
+
for i in (0...tmp2.count)
|
146
|
+
tmp2[i] += 1
|
147
|
+
end
|
148
|
+
reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps] = tmp2
|
149
|
+
end
|
150
|
+
|
151
|
+
if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw].nil?
|
152
|
+
reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw] = 0
|
153
|
+
end
|
154
|
+
|
122
155
|
return reopt_inputs
|
123
156
|
end
|
124
157
|
|
158
|
+
|
125
159
|
##
|
126
160
|
# Update a FeatureReport from a \REopt Lite response
|
127
161
|
#
|
128
162
|
# [*parameters:*]
|
129
163
|
#
|
130
|
-
# * +feature_report+ - _URBANopt::
|
164
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport to update from a \REopt Lite reponse hash.
|
131
165
|
# * +reopt_output+ - _Hash_ - A reponse hash from the \REopt Lite API to use in overwriting FeatureReport technology sizes, costs and dispatch strategies.
|
132
166
|
# * +timeseries_csv_path+ - _String_ - Optional. The path to a file at which a new timeseries CSV will be written. If not provided a file is created based on the run_uuid of the \REopt Lite optimization task.
|
133
167
|
#
|
134
|
-
# [*return:*] _URBANopt::
|
168
|
+
# [*return:*] _URBANopt::Reporting::DefaultReports::FeatureReport_ - Returns an updated FeatureReport.
|
135
169
|
##
|
136
|
-
def update_feature_report(feature_report, reopt_output, timeseries_csv_path =
|
170
|
+
def update_feature_report(feature_report, reopt_output, timeseries_csv_path=nil, resilience_stats=nil)
|
137
171
|
# Check if the \REopt Lite response is valid
|
138
172
|
if reopt_output['outputs']['Scenario']['status'] != 'optimal'
|
139
173
|
@@logger.info("Warning cannot Feature Report #{feature_report.name} #{feature_report.id} - REopt optimization was non-optimal")
|
140
174
|
return feature_report
|
141
175
|
end
|
142
|
-
|
176
|
+
|
143
177
|
$ts_per_hour = feature_report.timesteps_per_hour
|
144
178
|
def scale_timeseries(input, ts_per_hr=$ts_per_hour)
|
145
179
|
if input.nil?
|
@@ -152,7 +186,7 @@ module URBANopt # :nodoc:
|
|
152
186
|
return input
|
153
187
|
end
|
154
188
|
result = []
|
155
|
-
input.each do |val|
|
189
|
+
input.each do |val|
|
156
190
|
(1..ts_per_hr).each do |x|
|
157
191
|
result.push(val/ts_per_hr.to_f)
|
158
192
|
end
|
@@ -161,11 +195,8 @@ module URBANopt # :nodoc:
|
|
161
195
|
end
|
162
196
|
|
163
197
|
# Update location
|
164
|
-
feature_report.location.
|
165
|
-
feature_report.location.
|
166
|
-
|
167
|
-
# Update timeseries csv from \REopt Lite dispatch data
|
168
|
-
feature_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
|
198
|
+
feature_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
|
199
|
+
feature_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
|
169
200
|
|
170
201
|
# Update distributed generation sizing and financials
|
171
202
|
feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
|
@@ -174,56 +205,63 @@ module URBANopt # :nodoc:
|
|
174
205
|
feature_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
|
175
206
|
feature_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
|
176
207
|
feature_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
|
208
|
+
feature_report.distributed_generation.total_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_us_dollars'] || 0
|
209
|
+
feature_report.distributed_generation.year_one_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_bau_us_dollars'] || 0
|
210
|
+
feature_report.distributed_generation.year_one_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_bau_us_dollars'] || 0
|
211
|
+
feature_report.distributed_generation.year_one_bill_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_bau_us_dollars'] || 0
|
212
|
+
feature_report.distributed_generation.total_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_bau_us_dollars'] || 0
|
213
|
+
feature_report.distributed_generation.total_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_bau_us_dollars'] || 0
|
214
|
+
if !resilience_stats.nil?
|
215
|
+
feature_report.distributed_generation.resilience_hours_min = resilience_stats['resilience_hours_min']
|
216
|
+
feature_report.distributed_generation.resilience_hours_max = resilience_stats['resilience_hours_max']
|
217
|
+
feature_report.distributed_generation.resilience_hours_avg = resilience_stats['resilience_hours_avg']
|
218
|
+
feature_report.distributed_generation.probs_of_surviving = resilience_stats['probs_of_surviving']
|
219
|
+
feature_report.distributed_generation.probs_of_surviving_by_month = resilience_stats['probs_of_surviving_by_month']
|
220
|
+
feature_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
|
221
|
+
end
|
177
222
|
|
178
223
|
if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
|
179
224
|
reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
|
180
225
|
elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
|
181
226
|
reopt_output['outputs']['Scenario']['Site']['PV'] = []
|
182
227
|
end
|
183
|
-
|
184
|
-
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
185
|
-
feature_report.distributed_generation.add_tech 'solar_pv', URBANopt::
|
228
|
+
|
229
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
230
|
+
feature_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new( {size_kw: (pv['size_kw'] || 0), id: i })
|
186
231
|
end
|
187
232
|
|
188
233
|
wind = reopt_output['outputs']['Scenario']['Site']['Wind']
|
189
234
|
if !wind['size_kw'].nil? and wind['size_kw'] != 0
|
190
|
-
feature_report.distributed_generation.add_tech 'wind', URBANopt::
|
235
|
+
feature_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new( {size_kw: (wind['size_kw'] || 0) })
|
191
236
|
end
|
192
237
|
|
193
238
|
generator = reopt_output['outputs']['Scenario']['Site']['Generator']
|
194
239
|
if !generator['size_kw'].nil? and generator['size_kw'] != 0
|
195
|
-
feature_report.distributed_generation.add_tech 'generator', URBANopt::
|
240
|
+
feature_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new( {size_kw: (generator['size_kw'] || 0) })
|
196
241
|
end
|
197
242
|
|
198
243
|
storage = reopt_output['outputs']['Scenario']['Site']['Storage']
|
199
244
|
if !storage['size_kw'].nil? and storage['size_kw'] != 0
|
200
|
-
feature_report.distributed_generation.add_tech 'storage', URBANopt::
|
245
|
+
feature_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
|
201
246
|
end
|
202
|
-
|
247
|
+
|
203
248
|
generation_timeseries_kwh = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
|
249
|
+
reopt_resolution = reopt_output['inputs']['Scenario']['time_steps_per_hour']
|
204
250
|
|
205
251
|
unless reopt_output['outputs']['Scenario']['Site']['PV'].nil?
|
206
|
-
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
|
252
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
|
207
253
|
if (pv['size_kw'] || 0) > 0
|
208
254
|
if !pv['year_one_power_production_series_kw'].nil?
|
209
|
-
generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
|
255
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
|
210
256
|
end
|
211
257
|
end
|
212
258
|
end
|
213
259
|
end
|
214
260
|
|
215
|
-
unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
|
216
|
-
if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
|
217
|
-
if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
|
218
|
-
generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
261
|
unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
|
224
262
|
if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
|
225
263
|
if !reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'].nil?
|
226
|
-
generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']]
|
264
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
|
227
265
|
end
|
228
266
|
end
|
229
267
|
end
|
@@ -231,7 +269,7 @@ module URBANopt # :nodoc:
|
|
231
269
|
unless reopt_output['outputs']['Scenario']['Site']['Generator'].nil?
|
232
270
|
if (reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0) > 0
|
233
271
|
if !reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'].nil?
|
234
|
-
generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']]
|
272
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
|
235
273
|
end
|
236
274
|
end
|
237
275
|
end
|
@@ -243,70 +281,70 @@ module URBANopt # :nodoc:
|
|
243
281
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
|
244
282
|
end
|
245
283
|
|
246
|
-
$load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
284
|
+
$load = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
247
285
|
$load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
|
248
286
|
if $load_col.nil?
|
249
287
|
$load_col = feature_report.timeseries_csv.column_names.length
|
250
288
|
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
|
251
289
|
end
|
252
290
|
|
253
|
-
$utility_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
291
|
+
$utility_to_load = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
254
292
|
$utility_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
|
255
293
|
if $utility_to_load_col.nil?
|
256
294
|
$utility_to_load_col = feature_report.timeseries_csv.column_names.length
|
257
295
|
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
|
258
296
|
end
|
259
297
|
|
260
|
-
$utility_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
298
|
+
$utility_to_battery = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
261
299
|
$utility_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
|
262
300
|
if $utility_to_battery_col.nil?
|
263
301
|
$utility_to_battery_col = feature_report.timeseries_csv.column_names.length
|
264
302
|
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
|
265
303
|
end
|
266
304
|
|
267
|
-
$storage_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
305
|
+
$storage_to_load = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
268
306
|
$storage_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
|
269
307
|
if $storage_to_load_col.nil?
|
270
308
|
$storage_to_load_col = feature_report.timeseries_csv.column_names.length
|
271
309
|
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
|
272
310
|
end
|
273
311
|
|
274
|
-
$storage_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
312
|
+
$storage_to_grid = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
275
313
|
$storage_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
|
276
314
|
if $storage_to_grid_col.nil?
|
277
315
|
$storage_to_grid_col = feature_report.timeseries_csv.column_names.length
|
278
316
|
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
|
279
317
|
end
|
280
318
|
|
281
|
-
$storage_soc = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
319
|
+
$storage_soc = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
282
320
|
$storage_soc_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
|
283
321
|
if $storage_soc_col.nil?
|
284
322
|
$storage_soc_col = feature_report.timeseries_csv.column_names.length
|
285
323
|
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
|
286
324
|
end
|
287
325
|
|
288
|
-
$generator_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
326
|
+
$generator_total = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
289
327
|
$generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
|
290
328
|
if $generator_total_col.nil?
|
291
329
|
$generator_total_col = feature_report.timeseries_csv.column_names.length
|
292
330
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
|
293
331
|
end
|
294
332
|
|
295
|
-
$generator_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
333
|
+
$generator_to_battery = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
296
334
|
$generator_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
|
297
335
|
if $generator_to_battery_col.nil?
|
298
336
|
$generator_to_battery_col = feature_report.timeseries_csv.column_names.length
|
299
337
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
|
300
338
|
end
|
301
339
|
|
302
|
-
$generator_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
340
|
+
$generator_to_load = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
303
341
|
$generator_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
|
304
342
|
if $generator_to_load_col.nil?
|
305
343
|
$generator_to_load_col = feature_report.timeseries_csv.column_names.length
|
306
344
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
|
307
345
|
end
|
308
346
|
|
309
|
-
$generator_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
347
|
+
$generator_to_grid = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
310
348
|
$generator_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
|
311
349
|
if $generator_to_grid_col.nil?
|
312
350
|
$generator_to_grid_col = feature_report.timeseries_csv.column_names.length
|
@@ -345,10 +383,10 @@ module URBANopt # :nodoc:
|
|
345
383
|
|
346
384
|
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
347
385
|
if (pv['size_kw'] || 0) > 0
|
348
|
-
$pv_total += Matrix[scale_timeseries(pv['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
349
|
-
$pv_to_battery += Matrix[scale_timeseries(pv['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
350
|
-
$pv_to_load += Matrix[scale_timeseries(pv['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
351
|
-
$pv_to_grid += Matrix[scale_timeseries(pv['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
386
|
+
$pv_total += Matrix[scale_timeseries(convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
387
|
+
$pv_to_battery += Matrix[scale_timeseries(convert_powerflow_resolution(pv['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
388
|
+
$pv_to_load += Matrix[scale_timeseries(convert_powerflow_resolution(pv['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
389
|
+
$pv_to_grid += Matrix[scale_timeseries(convert_powerflow_resolution(pv['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
352
390
|
end
|
353
391
|
end
|
354
392
|
|
@@ -357,28 +395,28 @@ module URBANopt # :nodoc:
|
|
357
395
|
$pv_to_load = $pv_to_load.to_a[0]
|
358
396
|
$pv_to_grid = $pv_to_grid.to_a[0]
|
359
397
|
|
360
|
-
$wind_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
398
|
+
$wind_total = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
361
399
|
$wind_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
|
362
400
|
if $wind_total_col.nil?
|
363
401
|
$wind_total_col = feature_report.timeseries_csv.column_names.length
|
364
402
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
|
365
403
|
end
|
366
404
|
|
367
|
-
$wind_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
405
|
+
$wind_to_battery = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
368
406
|
$wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
369
407
|
if $wind_to_battery_col.nil?
|
370
408
|
$wind_to_battery_col = feature_report.timeseries_csv.column_names.length
|
371
409
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
372
410
|
end
|
373
411
|
|
374
|
-
$wind_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
412
|
+
$wind_to_load = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
375
413
|
$wind_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
|
376
414
|
if $wind_to_load_col.nil?
|
377
415
|
$wind_to_load_col = feature_report.timeseries_csv.column_names.length
|
378
416
|
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
|
379
417
|
end
|
380
418
|
|
381
|
-
$wind_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
|
419
|
+
$wind_to_grid = scale_timeseries(convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)) || [0] * (8760 * feature_report.timesteps_per_hour)
|
382
420
|
$wind_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
|
383
421
|
if $wind_to_grid_col.nil?
|
384
422
|
$wind_to_grid_col = feature_report.timeseries_csv.column_names.length
|