urbanopt-reopt 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee9ebcdfb84f8014a57ba10b922de59989801a03
4
- data.tar.gz: f382a27f0219f10d01b20d09b2cfdd41d48cd223
3
+ metadata.gz: a833a15c613e58704915acea2d8a31cfd2ded2f9
4
+ data.tar.gz: 4aa9285353fb46787c73b12d7d6b4e47da0e4098
5
5
  SHA512:
6
- metadata.gz: 0edee439c2cc7bff0cc349de7511ab20c163c3ba803a0dbb4bca4291a6a6439aa2737e5c91077ea10316d23c32a80d5ed37dbe4138c0d992c7b08baddfe7db68
7
- data.tar.gz: 28026ba4c576ece08adb4a1084eb64e36ce533400c5b2b66ab0b8290fa8de76c39b8d0aaa5afe7591463db93fd23392144f32167e97fd72ab32b8ef5783bdaf7
6
+ metadata.gz: 364198ba99ef78bc954f94519717abb17d7e24a9d1c46c08eee4b05c4881f6b510d1557e451f64ee8e42cf00c30c4892ddf018d1b5040d88f68c31456060fb46
7
+ data.tar.gz: 5040b4fdbee705eabd026c0139d76857b53fcd325aa6e0730f58eba29b5107c86d0bb8eb77c3fb064dc2173b60ed8077cb578e270305ef36ebdf09560aa1212a
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ **Expected behavior**
10
+ _A clear and concise description of what you expected to happen._
11
+
12
+ **Actual behavior**
13
+ _A clear and concise description of what actually happens._
14
+
15
+ **To Reproduce**
16
+ Steps to reproduce the behavior:
17
+
18
+ 1. Go to '...'
19
+ 1. Enter '...'
20
+ 1. Enter '...'
21
+
22
+ ### Additional context
23
+
24
+ _E.g.: Windows, Mac, Linux? Are you behind a firewall? Do you have additional security constraints?_
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ **Is your feature request related to a problem?**
10
+ A clear and concise description of what the problem is: _I'm frustrated when [...]_
11
+
12
+ **Describe the solution you'd like**
13
+ A clear and concise description of what you want to happen
14
+
15
+ **Alternatives you've considered**
16
+ A clear and concise description of any alternative solutions or features you've considered
17
+
18
+ **Additional context**
19
+ Add any other context or screenshots about the feature request here
@@ -0,0 +1,13 @@
1
+ ### Addresses #[issue number here]
2
+
3
+ ### Pull Request Description
4
+
5
+ [description here]
6
+
7
+ ### Checklist (Delete lines that don't apply)
8
+
9
+ - [ ] Unit tests have been added or updated
10
+ - [ ] Documentation has been modified appropriately
11
+ - [ ] All ci tests pass (green)
12
+ - [ ] An [ISSUE](https://github.com/urbanopt/urbanopt-cli/issues) has been created that this is addressing. Issues will get added to the Change Log when the change_log.rb script is run
13
+ - [ ] This branch is up-to-date with develop
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
+ *.DS_Store
2
+ /vendor/
1
3
  /.bundle/
2
4
  /.yardoc
3
5
  /.ruby-version
@@ -24,4 +26,4 @@ developer_nrel_key.rb
24
26
  # measures tests
25
27
  lib/measures/.rubocop.yml
26
28
  lib/measures/test_results/*
27
- lib/measures/*/tests/output/*
29
+ lib/measures/*/tests/output/*
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # URBANopt REopt Gem
2
2
 
3
+ ## Version 0.2.0
4
+
5
+ * Handles multiple PV systems in the REopt Lite assumptions
6
+ * Changes REoptPostProcessor run_scenario and run_scenario_features methods to save feature and scenario reports with custom names
7
+ * Parses date from timeseries CSV when creating load profile for REopt job and when parsing optimized results
8
+ * Renames REopt timeseries CSV columns to include 'REopt' and units
9
+
10
+
3
11
  ## Version 0.1.0
4
12
 
5
13
  * Initial release of URBANopt REopt Gem.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,58 @@
1
+ # URBANopt Contribution Policy
2
+
3
+ ## Version 1.0
4
+
5
+ The URBANopt team welcomes your contribution to the project. You can contribute to the URBANopt project in several ways: by using the software, reporting issues, contributing documentation, or contributing code back to the project. The GitHub [Contributing to Open Source](https://opensource.guide/how-to-contribute/) guide provides a good overview. If you contribute code, you agree that your contribution may be incorporated into the URBANopt Software Development Kit (SDK) and made available under the URBANopt SDK license.
6
+
7
+ The contribution process for URBANopt is composed of three steps:
8
+
9
+ ## 1. Send consent email
10
+
11
+ In order for us to distribute your code as part of URBANopt under the URBANopt SDK [license](https://github.com/urbanopt/urbanopt-scenario-gem/blob/develop/LICENSE.md), we’ll need your consent. An email acknowledging your understanding of these terms and agreeing to them is all that will be asked of any contributor. Send an email to the URBANopt project manager ([see below](#documentation) for the address) including the following text and a list of co-contributors (if any):
12
+
13
+ *I agree to contribute to the URBANopt SDK. I agree to the following terms and conditions for my contributions: First, I agree that I am licensing the copyright to my contributions under the terms of the current URBANopt SDK license. Second, I hereby grant to Alliance for Sustainable Energy, LLC, to any successor manager and distributor of URBANopt SDK appointed by the U.S. Department of Energy, and to all recipients of a version of URBANopt SDK that includes my contributions, a non-exclusive, worldwide, royalty-free, irrevocable patent license under any patent claims owned by me, or owned by my employer and known to me, that are or will be,necessarily infringed upon by my contributions alone, or by combination of my contributions with the version of URBANopt SDK to which they are contributed, to make, have made, use, offer to sell, sell, import, and otherwise transfer any version of URBANopt SDK that includes my contributions, in source code and object code form. Third, I represent and warrant that I am authorized to make the contributions and grant the foregoing license(s). Additionally, if, to my knowledge, my employer has rights to intellectual property that covers my contributions, I represent and warrant that I have received permission to make these contributions and grant the foregoing license(s) on behalf of my employer.*
14
+
15
+ Once we have your consent on file, you’ll only need to redo it if conditions change (e.g. a change of employer).
16
+
17
+ ## 2. Scope agreement and timeline commitment
18
+
19
+ If your contribution is small (e.g. a bug fix), simply submit your contribution via GitHub. If you find a bug, first make sure it is not an already known issue, then report it in the GitHub [issue tracker](https://github.com/urbanopt/urbanopt-scenario-gem/issues) for this repository. If your contribution is larger (e.g. a new feature or new functionality/capability), we’ll need to evaluate your proposed contribution first. We may ask you to revise your materials and make changes to it, which we will then re-review.
20
+
21
+ ## 3. Technical contribution process
22
+
23
+ We want URBANopt to adhere to our established quality standards. Smaller, non-code contributions may not require as much review as code contributions, but all contributions will be reviewed. Code contributions will initially be in a source control branch, and then will be merged into the official URBANopt repository after review and approval. Any bugs, either discovered by you, us, or any users will be tracked in our issue tracker. We request that you take full responsibility for correcting bugs. Be aware that, unless notified otherwise, the correction of bugs takes precedence over the submission or creation of new code.
24
+
25
+ ### Release Schedule
26
+
27
+ Contributions should be aligned with the URBANopt release schedule. The URBANopt SDK is currently released publicly two times each year (approximately on the last workday of March and October). There are cutoff dates for when new contributions are allowed for the upcoming release (approximately two weeks before release date). If your contribution is incomplete or comes in past the cutoff date for a release, we reserve the right to hold your code for a later release.
28
+
29
+ ### Coding Standards
30
+
31
+ Make sure you read and follow the coding standards when writing URBANopt SDK code. Although these standards are not complete or very detailed, they should give you an idea of the style that we would like you to adopt. New additions to the URBANopt SDK must be written using object-oriented programming techniques and practices. Please also look at the URBANopt SDK code itself as an example of the preferred coding style.
32
+
33
+ ### Code Reviews
34
+
35
+ You will be working and testing your code in a source control branch. When a piece of functionality is complete, tested and working, let us know and we will review your code. If the functionality that you contributed is complex, we may ask you for a written design document as well. We want your code to follow coding standards, be clear, readable, and maintainable, and of course it should do what it is supposed to do. We will look for errors, style issues, comments (or lack thereof), and any other issues in your code. We will inform you of our comments and we expect you to make the recommended changes. New re-reviews may be expected until the code complies with our required processes.
36
+
37
+ ### Unit Tests
38
+
39
+ We ask that you supply unit tests along with the code that you have written. A unit test is a program that exercises your code in isolation to verify that it does what it is supposed to do. Your unit tests are very important to us. First, they give an indication that your code works according to its intended functionality. Second, we execute your unit tests automatically along with our unit tests to verify that the overall URBANopt SDK code continues to work.
40
+
41
+ ### Code Coverage
42
+
43
+ We require that your unit tests provide an adequate coverage of the source code you are submitting. You will need to design your unit tests in such a way that all critical parts of the code (at least) are tested and verified.
44
+
45
+ ### Documentation
46
+
47
+ Proper documentation is crucial for our users, without it users will not know how to use your contribution. We require that you create user documentation so that end users know how to use your new functionality.
48
+
49
+ For further questions or information:
50
+
51
+ - Ben Polly\
52
+ URBANopt Project Management\
53
+ ben.polly@nrel.gov\
54
+ (303) 384-7429
55
+
56
+ URBANopt is funded by the U.S. Department of Energy (DOE) and managed by the National Renewable Energy Laboratory (NREL).
57
+
58
+ URBANopt is developed in collaboration with NREL, LBNL, and private firms.
data/Gemfile CHANGED
@@ -44,18 +44,17 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
44
44
  if allow_local && File.exist?('../urbanopt-scenario-gem')
45
45
  gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
46
46
  elsif allow_local
47
- gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'post_process'
47
+ gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
48
48
  else
49
- gem 'urbanopt-scenario', '0.1.1'
49
+ gem 'urbanopt-scenario', '0.2.0'
50
50
  end
51
51
 
52
52
  if allow_local && File.exists?('../urbanopt-geojson-gem')
53
- # gem 'openstudio-extension', github: 'NREL/OpenStudio-extension-gem', branch: 'develop'
54
53
  gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
55
54
  elsif allow_local
56
55
  gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
57
56
  else
58
- gem 'urbanopt-geojson', '0.1.0'
57
+ gem 'urbanopt-geojson', '0.2.0'
59
58
  end
60
59
 
61
60
  # simplecov has an unnecessary dependency on native json gem, use fork that does not require this
@@ -32,6 +32,7 @@ require 'urbanopt/scenario/default_reports'
32
32
  require 'urbanopt/reopt/reopt_logger'
33
33
  require 'csv'
34
34
  require 'matrix'
35
+ require 'time'
35
36
 
36
37
  module URBANopt # :nodoc:
37
38
  module REopt # :nodoc:
@@ -74,7 +75,7 @@ module URBANopt # :nodoc:
74
75
  requireds.each_with_index do |i, x|
75
76
  if [nil, 0].include? x
76
77
  n = requireds_names[i]
77
- p 'a' # @@logger.error("Missing value for #{n} - this is a required input")
78
+ # @@logger.error("Missing value for #{n} - this is a required input")
78
79
  raise "Missing value for #{n} - this is a required input"
79
80
  end
80
81
  end
@@ -95,20 +96,25 @@ module URBANopt # :nodoc:
95
96
  reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area * 1.0 / 43560 # acres/sqft
96
97
  end
97
98
 
99
+ unless feature_report.timesteps_per_hour.nil?
100
+ reopt_inputs[:Scenario][:time_steps_per_hour] = feature_report.timesteps_per_hour
101
+ end
102
+
98
103
  # Parse Load Profile
99
104
  begin
100
- col_num = feature_report.timeseries_csv.column_names.index('Electricity:Facility')
105
+ col_num = feature_report.timeseries_csv.column_names.index('Electricity:Facility(kWh)')
101
106
  t = CSV.read(feature_report.timeseries_csv.path, headers: true, converters: :numeric)
102
- energy_timeseries_kwh = t.by_col[col_num].map { |e| ((e || 0) * 0.293071) } # convert kBTU to KWH
103
- if (feature_report.timesteps_per_hour || 1) > 1
104
- energy_timeseries_kwh = energy_timeseries_kwh.each_slice(feature_report.timesteps_per_hour).to_a.map { |x| x.inject(0, :+) / x.length.to_f }
105
- end
106
-
107
- if energy_timeseries_kwh.length < feature_report.timesteps_per_hour * 8760
108
- energy_timeseries_kwh += [0] * ((feature_report.timesteps_per_hour * 8760) - energy_timeseries_kwh.length)
109
- @@logger.info("Assuming load profile for Feature Report #{feature_report.name} #{feature_report.id} starts January 1 - filling in rest with zeros")
107
+ energy_timeseries_kwh = t.by_col[col_num].map { |e| ((e || 0) ) }
108
+ if energy_timeseries_kwh.length < (feature_report.timesteps_per_hour * 8760)
109
+ start_date = Time.parse(t.by_col["Datetime"][0])
110
+ 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) /
111
+ (( 60 / feature_report.timesteps_per_hour ) * 60)).to_int
112
+ end_date = Time.parse(t.by_col["Datetime"][-1])
113
+ 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
+ (( 60 / feature_report.timesteps_per_hour ) * 60)).to_int
115
+ energy_timeseries_kwh = [0.0]*(start_ts-1) + energy_timeseries_kwh + [0.0]*((feature_report.timesteps_per_hour * 8760) - end_ts)
110
116
  end
111
- reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kwh.map { |e| e ? e : 0 }
117
+ reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kwh.map { |e| e ? e : 0 }[0,(feature_report.timesteps_per_hour * 8760)]
112
118
  rescue StandardError
113
119
  @@logger.error("Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}")
114
120
  raise "Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}"
@@ -133,6 +139,26 @@ module URBANopt # :nodoc:
133
139
  @@logger.info("Warning cannot Feature Report #{feature_report.name} #{feature_report.id} - REopt optimization was non-optimal")
134
140
  return feature_report
135
141
  end
142
+
143
+ $ts_per_hour = feature_report.timesteps_per_hour
144
+ def scale_timeseries(input, ts_per_hr=$ts_per_hour)
145
+ if input.nil?
146
+ return nil
147
+ end
148
+ if input.length ==0
149
+ return nil
150
+ end
151
+ if input.length == (8760 * ts_per_hr)
152
+ return input
153
+ end
154
+ result = []
155
+ input.each do |val|
156
+ (1..ts_per_hr).each do |x|
157
+ result.push(val/ts_per_hr.to_f)
158
+ end
159
+ end
160
+ return result
161
+ end
136
162
 
137
163
  # Update location
138
164
  feature_report.location.latitude = reopt_output['inputs']['Scenario']['Site']['latitude']
@@ -142,36 +168,57 @@ module URBANopt # :nodoc:
142
168
  feature_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
143
169
 
144
170
  # Update distributed generation sizing and financials
145
- (feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars']) || 0
146
- (feature_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars']) || 0
147
- (feature_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars']) || 0
148
- (feature_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars']) || 0
149
- (feature_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars']) || 0
150
- (feature_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars']) || 0
151
-
152
- (feature_report.distributed_generation.solar_pv.size_kw = reopt_output['outputs']['Scenario']['Site']['PV']['size_kw']) || 0
153
- (feature_report.distributed_generation.wind.size_kw = reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw']) || 0
154
- (feature_report.distributed_generation.generator.size_kw = reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw']) || 0
155
- (feature_report.distributed_generation.storage.size_kw = reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw']) || 0
156
- (feature_report.distributed_generation.storage.size_kwh = reopt_output['outputs']['Scenario']['Site']['Storage']['size_kwh']) || 0
171
+ feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
172
+ feature_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
173
+ feature_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
174
+ feature_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
175
+ feature_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
176
+ feature_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
177
+
178
+ if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
179
+ reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
180
+ elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
181
+ reopt_output['outputs']['Scenario']['Site']['PV'] = []
182
+ 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::Scenario::DefaultReports::SolarPV.new( {size_kw: (pv['size_kw'] || 0), id: i })
186
+ end
187
+
188
+ wind = reopt_output['outputs']['Scenario']['Site']['Wind']
189
+ if !wind['size_kw'].nil? and wind['size_kw'] != 0
190
+ feature_report.distributed_generation.add_tech 'wind', URBANopt::Scenario::DefaultReports::Wind.new( {size_kw: (wind['size_kw'] || 0) })
191
+ end
157
192
 
193
+ generator = reopt_output['outputs']['Scenario']['Site']['Generator']
194
+ if !generator['size_kw'].nil? and generator['size_kw'] != 0
195
+ feature_report.distributed_generation.add_tech 'generator', URBANopt::Scenario::DefaultReports::Generator.new( {size_kw: (generator['size_kw'] || 0) })
196
+ end
197
+
198
+ storage = reopt_output['outputs']['Scenario']['Site']['Storage']
199
+ if !storage['size_kw'].nil? and storage['size_kw'] != 0
200
+ feature_report.distributed_generation.add_tech 'storage', URBANopt::Scenario::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
201
+ end
202
+
158
203
  generation_timeseries_kwh = Matrix[[0] * 8760]
159
204
 
160
205
  unless reopt_output['outputs']['Scenario']['Site']['PV'].nil?
161
- if (reopt_output['outputs']['Scenario']['Site']['PV']['size_kw'] || 0) > 0
162
- if !reopt_output['outputs']['Scenario']['Site']['PV']['year_one_power_production_series_kw'].nil?
163
- generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['PV']['year_one_power_production_series_kw']]
206
+ reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
207
+ if (pv['size_kw'] || 0) > 0
208
+ if !pv['year_one_power_production_series_kw'].nil?
209
+ generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
210
+ end
164
211
  end
165
- end
212
+ end
166
213
  end
167
214
 
168
- # unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
169
- # if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
170
- # if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
171
- # generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
172
- # end
173
- # end
174
- # end
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
175
222
 
176
223
  unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
177
224
  if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
@@ -190,136 +237,152 @@ module URBANopt # :nodoc:
190
237
  end
191
238
 
192
239
  $generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * 8760
193
- $generation_timeseries_kwh_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Total')
240
+ $generation_timeseries_kwh_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Total(kw)')
194
241
  if $generation_timeseries_kwh_col.nil?
195
242
  $generation_timeseries_kwh_col = feature_report.timeseries_csv.column_names.length
196
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Total')
243
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
197
244
  end
198
245
 
199
- $load = reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'] || [0] * 8760
200
- $load_col = feature_report.timeseries_csv.column_names.index('Electricity:Load:Total')
246
+ $load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
247
+ $load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
201
248
  if $load_col.nil?
202
249
  $load_col = feature_report.timeseries_csv.column_names.length
203
- feature_report.timeseries_csv.column_names.push('Electricity:Load:Total')
250
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
204
251
  end
205
252
 
206
- $utility_to_load = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'] || [0] * 8760
207
- $utility_to_load_col = feature_report.timeseries_csv.column_names.index('Electricity:Grid:ToLoad')
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)
254
+ $utility_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
208
255
  if $utility_to_load_col.nil?
209
256
  $utility_to_load_col = feature_report.timeseries_csv.column_names.length
210
- feature_report.timeseries_csv.column_names.push('Electricity:Grid:ToLoad')
257
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
211
258
  end
212
259
 
213
- $utility_to_battery = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'] || [0] * 8760
214
- $utility_to_battery_col = feature_report.timeseries_csv.column_names.index('Electricity:Grid:ToBattery')
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)
261
+ $utility_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
215
262
  if $utility_to_battery_col.nil?
216
263
  $utility_to_battery_col = feature_report.timeseries_csv.column_names.length
217
- feature_report.timeseries_csv.column_names.push('Electricity:Grid:ToBattery')
264
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
218
265
  end
219
266
 
220
- $storage_to_load = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'] || [0] * 8760
221
- $storage_to_load_col = feature_report.timeseries_csv.column_names.index('Electricity:Storage:ToLoad')
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)
268
+ $storage_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
222
269
  if $storage_to_load_col.nil?
223
270
  $storage_to_load_col = feature_report.timeseries_csv.column_names.length
224
- feature_report.timeseries_csv.column_names.push('Electricity:Storage:ToLoad')
271
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
225
272
  end
226
273
 
227
- $storage_to_grid = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'] || [0] * 8760
228
- $storage_to_grid_col = feature_report.timeseries_csv.column_names.index('Electricity:Storage:ToGrid')
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)
275
+ $storage_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
229
276
  if $storage_to_grid_col.nil?
230
277
  $storage_to_grid_col = feature_report.timeseries_csv.column_names.length
231
- feature_report.timeseries_csv.column_names.push('Electricity:Storage:ToGrid')
278
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
232
279
  end
233
280
 
234
- $storage_soc = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'] || [0] * 8760
235
- $storage_soc_col = feature_report.timeseries_csv.column_names.index('Electricity:Storage:StateOfCharge')
281
+ $storage_soc = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct']) || [0] * (8760 * feature_report.timesteps_per_hour)
282
+ $storage_soc_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
236
283
  if $storage_soc_col.nil?
237
284
  $storage_soc_col = feature_report.timeseries_csv.column_names.length
238
- feature_report.timeseries_csv.column_names.push('Electricity:Storage:StateOfCharge')
285
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
239
286
  end
240
287
 
241
- $generator_total = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'] || [0] * 8760
242
- $generator_total_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:Total')
288
+ $generator_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
289
+ $generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
243
290
  if $generator_total_col.nil?
244
291
  $generator_total_col = feature_report.timeseries_csv.column_names.length
245
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:Total')
292
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
246
293
  end
247
294
 
248
- $generator_to_battery = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'] || [0] * 8760
249
- $generator_to_battery_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToBattery')
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)
296
+ $generator_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
250
297
  if $generator_to_battery_col.nil?
251
298
  $generator_to_battery_col = feature_report.timeseries_csv.column_names.length
252
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToBattery')
299
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
253
300
  end
254
301
 
255
- $generator_to_load = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'] || [0] * 8760
256
- $generator_to_load_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToLoad')
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)
303
+ $generator_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
257
304
  if $generator_to_load_col.nil?
258
305
  $generator_to_load_col = feature_report.timeseries_csv.column_names.length
259
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToLoad')
306
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
260
307
  end
261
308
 
262
- $generator_to_grid = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'] || [0] * 8760
263
- $generator_to_grid_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToGrid')
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)
310
+ $generator_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
264
311
  if $generator_to_grid_col.nil?
265
312
  $generator_to_grid_col = feature_report.timeseries_csv.column_names.length
266
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToGrid')
313
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
267
314
  end
268
315
 
269
- $pv_total = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_power_production_series_kw'] || [0] * 8760
270
- $pv_total_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:PV:Total')
316
+ $pv_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
271
317
  if $pv_total_col.nil?
272
318
  $pv_total_col = feature_report.timeseries_csv.column_names.length
273
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:PV:Total')
319
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
274
320
  end
275
321
 
276
- $pv_to_battery = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_to_battery_series_kw'] || [0] * 8760
277
- $pv_to_battery_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToBattery')
322
+ $pv_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
278
323
  if $pv_to_battery_col.nil?
279
324
  $pv_to_battery_col = feature_report.timeseries_csv.column_names.length
280
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToBattery')
325
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
281
326
  end
282
327
 
283
- $pv_to_load = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_to_load_series_kw'] || [0] * 8760
284
- $pv_to_load_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToLoad')
328
+ $pv_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
285
329
  if $pv_to_load_col.nil?
286
330
  $pv_to_load_col = feature_report.timeseries_csv.column_names.length
287
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToLoad')
331
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
288
332
  end
289
333
 
290
- $pv_to_grid = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_to_grid_series_kw'] || [0] * 8760
291
- $pv_to_grid_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToGrid')
334
+
335
+ $pv_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
292
336
  if $pv_to_grid_col.nil?
293
337
  $pv_to_grid_col = feature_report.timeseries_csv.column_names.length
294
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToGrid')
338
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
339
+ end
340
+
341
+ $pv_total = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
342
+ $pv_to_battery = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
343
+ $pv_to_load = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
344
+ $pv_to_grid = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
345
+
346
+ reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
347
+ 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)]
352
+ end
295
353
  end
296
354
 
297
- $wind_total = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'] || [0] * 8760
298
- $wind_total_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:Total')
355
+ $pv_total = $pv_total.to_a[0]
356
+ $pv_to_battery = $pv_to_battery.to_a[0]
357
+ $pv_to_load = $pv_to_load.to_a[0]
358
+ $pv_to_grid = $pv_to_grid.to_a[0]
359
+
360
+ $wind_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
361
+ $wind_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
299
362
  if $wind_total_col.nil?
300
363
  $wind_total_col = feature_report.timeseries_csv.column_names.length
301
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:Total')
364
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
302
365
  end
303
366
 
304
- $wind_to_battery = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'] || [0] * 8760
305
- $wind_to_battery_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToBattery')
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)
368
+ $wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
306
369
  if $wind_to_battery_col.nil?
307
370
  $wind_to_battery_col = feature_report.timeseries_csv.column_names.length
308
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToBattery')
371
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
309
372
  end
310
373
 
311
- $wind_to_load = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'] || [0] * 8760
312
- $wind_to_load_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToLoad')
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)
375
+ $wind_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
313
376
  if $wind_to_load_col.nil?
314
377
  $wind_to_load_col = feature_report.timeseries_csv.column_names.length
315
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToLoad')
378
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
316
379
  end
317
380
 
318
- $wind_to_grid = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'] || [0] * 8760
319
- $wind_to_grid_col = feature_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToGrid')
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)
382
+ $wind_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
320
383
  if $wind_to_grid_col.nil?
321
384
  $wind_to_grid_col = feature_report.timeseries_csv.column_names.length
322
- feature_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToGrid')
385
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
323
386
  end
324
387
 
325
388
  def modrow(x, i) # :nodoc:
@@ -346,9 +409,12 @@ module URBANopt # :nodoc:
346
409
  end
347
410
 
348
411
  old_data = CSV.open(feature_report.timeseries_csv.path).read
412
+ start_date = Time.parse(old_data[1][0])
413
+ 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) / (( 60 / feature_report.timesteps_per_hour ) * 60)).to_int
414
+
349
415
  mod_data = old_data.map.with_index do |x, i|
350
416
  if i > 0
351
- modrow(x, i)
417
+ modrow(x, start_ts + i -2)
352
418
  else
353
419
  x
354
420
  end
@@ -70,11 +70,18 @@ module URBANopt # :nodoc:
70
70
  if !scenario_report.nil?
71
71
  @scenario_report = scenario_report
72
72
 
73
- @scenario_reopt_default_output_file = File.join(@scenario_report.directory_name, "scenario_report_#{@scenario_report.id}_reopt_run.json")
73
+ if !Dir.exist?(File.join(@scenario_report.directory_name, "reopt"))
74
+ Dir.mkdir(File.join(@scenario_report.directory_name, "reopt"))
75
+ end
76
+
77
+ @scenario_reopt_default_output_file = File.join(@scenario_report.directory_name, "reopt/scenario_report_#{@scenario_report.id}_reopt_run.json")
74
78
  @scenario_timeseries_default_output_file = File.join(@scenario_report.directory_name, "scenario_report_#{@scenario_report.id}_timeseries.csv")
75
79
 
76
80
  @scenario_report.feature_reports.each do |fr|
77
- @feature_reports_reopt_default_output_files << File.join(fr.directory_name, "feature_report_#{fr.id}_reopt_run.json")
81
+ if !Dir.exist?(File.join(fr.directory_name, "reopt"))
82
+ Dir.mkdir(File.join(fr.directory_name, "reopt"))
83
+ end
84
+ @feature_reports_reopt_default_output_files << File.join(fr.directory_name, "reopt/feature_report_#{fr.id}_reopt_run.json")
78
85
  end
79
86
 
80
87
  @scenario_report.feature_reports.each do |fr|
@@ -111,7 +118,7 @@ module URBANopt # :nodoc:
111
118
  #
112
119
  # [*return:*] _URBANopt::Scenario::DefaultReports::FeatureReport_ - Returns an updated FeatureReport
113
120
  ##
114
- def run_feature_report(feature_report, reopt_assumptions_hash = nil, reopt_output_file = nil, timeseries_csv_path = nil)
121
+ def run_feature_report(feature_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil)
115
122
  api = URBANopt::REopt::REoptLiteAPI.new(@nrel_developer_key, @localhost)
116
123
  adapter = URBANopt::REopt::FeatureReportAdapter.new
117
124
 
@@ -120,7 +127,11 @@ module URBANopt # :nodoc:
120
127
  reopt_output_file = feature_report.directory_name
121
128
  end
122
129
  reopt_output = api.reopt_request(reopt_input, reopt_output_file)
123
- return adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path)
130
+ result = adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path)
131
+ if !save_name.nil?
132
+ result.save_feature_report save_name
133
+ end
134
+ return result
124
135
  end
125
136
 
126
137
  ##
@@ -135,7 +146,7 @@ module URBANopt # :nodoc:
135
146
  # * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the ScenarioReport will be saved.
136
147
  #
137
148
  # [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ Returns an updated ScenarioReport
138
- def run_scenario_report(scenario_report, reopt_assumptions_hash = nil, reopt_output_file = nil, timeseries_csv_path = nil)
149
+ def run_scenario_report(scenario_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil)
139
150
  if !reopt_assumptions_hash.nil?
140
151
  @scenario_reopt_default_assumptions_hash = reopt_assumptions_hash
141
152
  end
@@ -153,7 +164,11 @@ module URBANopt # :nodoc:
153
164
 
154
165
  reopt_output = api.reopt_request(reopt_input, @scenario_reopt_default_output_file)
155
166
 
156
- return adapter.update_scenario_report(scenario_report, reopt_output, @scenario_timeseries_default_output_file)
167
+ result = adapter.update_scenario_report(scenario_report, reopt_output, @scenario_timeseries_default_output_file)
168
+ if !save_name.nil?
169
+ result.save save_name
170
+ end
171
+ return result
157
172
  end
158
173
 
159
174
  # Updates a set of FeatureReports based on an optional set of \REopt Lite optimization assumptions.
@@ -167,7 +182,8 @@ module URBANopt # :nodoc:
167
182
  # * +timeseries_csv_path+ - _Array_ - Optional. A array of paths to files at which the new timeseries CSV for the FeatureReports will be saved. The number and order of the paths should match the feature_reports array.
168
183
  #
169
184
  # [*return:*] _Array_ Returns an array of updated _URBANopt::Scenario::DefaultReports::FeatureReport_ objects
170
- def run_feature_reports(feature_reports, reopt_assumptions_hashes = [], reopt_output_files = [], timeseries_csv_paths = [])
185
+ def run_feature_reports(feature_reports:, reopt_assumptions_hashes:[], reopt_output_files:[], timeseries_csv_paths:[], save_names:nil)
186
+
171
187
  if !reopt_assumptions_hashes.empty?
172
188
  @feature_reports_reopt_default_assumption_hashes = reopt_assumptions_hashes
173
189
  end
@@ -182,7 +198,7 @@ module URBANopt # :nodoc:
182
198
 
183
199
  if @feature_reports_reopt_default_output_files.empty?
184
200
  feature_reports.each do |fr|
185
- @feature_reports_reopt_default_output_files << File.join(fr.directory_name, "feature_report_#{fr.id}_reopt_run.json")
201
+ @feature_reports_reopt_default_output_files << File.join(fr.directory_name, "reopt/feature_report_#{fr.id}_reopt_run.json")
186
202
  end
187
203
  end
188
204
 
@@ -198,17 +214,21 @@ module URBANopt # :nodoc:
198
214
  feature_reports.each_with_index do |feature_report, idx|
199
215
  begin
200
216
  reopt_input = feature_adapter.reopt_json_from_feature_report(feature_report, @feature_reports_reopt_default_assumption_hashes[idx])
201
- if reopt_output_files[idx].nil?
202
- reopt_output_files[idx] = feature_report.directory_name
203
- end
204
217
  reopt_output = api.reopt_request(reopt_input, @feature_reports_reopt_default_output_files[idx])
205
218
  new_feature_report = feature_adapter.update_feature_report(feature_report, reopt_output, @feature_reports_timeseries_default_output_files[idx])
206
219
  new_feature_reports.push(new_feature_report)
220
+ if !save_names.nil?
221
+ if save_names.length == feature_reports.length
222
+ new_feature_report.save_feature_report save_names[idx]
223
+ else
224
+ warn "Could not save feature reports - the number of save names provided did not match the number of feature reports"
225
+ end
226
+ end
207
227
  rescue StandardError
208
228
  @@logger.info("Could not optimize Feature Report #{feature_report.name} #{feature_report.id}")
209
229
  end
210
230
  end
211
-
231
+
212
232
  return new_feature_reports
213
233
  end
214
234
 
@@ -223,8 +243,8 @@ module URBANopt # :nodoc:
223
243
  # * +feature_report_timeseries_csv_paths+ - _Array_ - Optional. An array of paths to files at which the new timeseries CSV for the FeatureReports will be saved. The number and order of the paths should match the array in ScenarioReport.feature_reports.
224
244
  #
225
245
  # [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
226
- def run_scenario_report_features(scenario_report, reopt_assumptions_hashes = [], reopt_output_files = [], feature_report_timeseries_csv_paths = [])
227
- new_feature_reports = run_feature_reports(scenario_report.feature_reports, reopt_assumptions_hashes, reopt_output_files, feature_report_timeseries_csv_paths)
246
+ 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)
247
+ 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)
228
248
 
229
249
  new_scenario_report = URBANopt::Scenario::DefaultReports::ScenarioReport.new
230
250
  new_scenario_report.id = scenario_report.id
@@ -237,7 +257,9 @@ module URBANopt # :nodoc:
237
257
  new_feature_reports.each do |feature_report|
238
258
  new_scenario_report.add_feature_report(feature_report)
239
259
  end
240
-
260
+ if !save_name_scenario_report.nil?
261
+ new_scenario_report.save save_name_scenario_report
262
+ end
241
263
  return new_scenario_report
242
264
  end
243
265
  end
@@ -30,8 +30,9 @@
30
30
 
31
31
  require 'urbanopt/scenario/default_reports'
32
32
  require 'urbanopt/reopt/reopt_logger'
33
-
33
+ require 'matrix'
34
34
  require 'csv'
35
+ require 'time'
35
36
 
36
37
  module URBANopt # :nodoc:
37
38
  module REopt # :nodoc:
@@ -116,23 +117,23 @@ module URBANopt # :nodoc:
116
117
 
117
118
  # Update load profile info
118
119
  begin
119
- col_num = scenario_report.timeseries_csv.column_names.index('Electricity:Facility')
120
+ col_num = scenario_report.timeseries_csv.column_names.index('Electricity:Facility(kWh)')
120
121
  t = CSV.read(scenario_report.timeseries_csv.path, headers: true, converters: :numeric)
121
- energy_timeseries_kwh = t.by_col[col_num].map { |e| ((e || 0) * 0.293071) } # convert kBTU to KWH
122
-
123
- if (scenario_report.timesteps_per_hour || 1) > 1
124
- energy_timeseries_kwh = energy_timeseries_kwh.each_slice(scenario_report.timesteps_per_hour).to_a.map { |x| x.inject(0, :+) / x.length.to_f }
125
- end
126
-
127
- if energy_timeseries_kwh.length < scenario_report.timesteps_per_hour * 8760
128
- energy_timeseries_kwh += [0] * ((scenario_report.timesteps_per_hour * 8760) - energy_timeseries_kwh.length)
129
- @@logger.info("Assuming load profile for Scenario Report #{scenario_report.name} #{scenario_report.id} starts January 1 - filling in rest with zeros")
122
+ energy_timeseries_kwh = t.by_col[col_num].map { |e| ((e || 0) ) }
123
+ if energy_timeseries_kwh.length < (scenario_report.timesteps_per_hour * 8760)
124
+ start_date = Time.parse(t.by_col["Datetime"][0])
125
+ 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) /
126
+ (( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
127
+ end_date = Time.parse(t.by_col["Datetime"][-1])
128
+ 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) /
129
+ (( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
130
+ energy_timeseries_kwh = [0.0]*(start_ts-1) + energy_timeseries_kwh + [0.0]*((scenario_report.timesteps_per_hour * 8760) - end_ts)
130
131
  end
131
- reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kwh
132
+ reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kwh.map { |e| e ? e : 0 }[0,(scenario_report.timesteps_per_hour * 8760)]
132
133
  rescue StandardError
134
+ @@logger.error("Could not parse the annual electric load from the timeseries csv - #{scenario_report.timeseries_csv.path}")
133
135
  raise "Could not parse the annual electric load from the timeseries csv - #{scenario_report.timeseries_csv.path}"
134
136
  end
135
-
136
137
  return reopt_inputs
137
138
  end
138
139
 
@@ -174,6 +175,26 @@ module URBANopt # :nodoc:
174
175
  @@logger.info("Warning cannot Feature Report #{scenario_report.name} #{scenario_report.id} - REopt optimization was non-optimal")
175
176
  return scenario_report
176
177
  end
178
+
179
+ $ts_per_hour = scenario_report.timesteps_per_hour
180
+ def scale_timeseries(input, ts_per_hr=$ts_per_hour)
181
+ if input.nil?
182
+ return nil
183
+ end
184
+ if input.length ==0
185
+ return nil
186
+ end
187
+ if input.length == (8760 * ts_per_hr)
188
+ return input
189
+ end
190
+ result = []
191
+ input.each do |val|
192
+ (1..ts_per_hr).each do |x|
193
+ result.push(val/ts_per_hr.to_f)
194
+ end
195
+ end
196
+ return result
197
+ end
177
198
 
178
199
  # Update location
179
200
  scenario_report.location.latitude = reopt_output['inputs']['Scenario']['Site']['latitude']
@@ -183,36 +204,57 @@ module URBANopt # :nodoc:
183
204
  scenario_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
184
205
 
185
206
  # Update distributed generation sizing and financials
186
- (scenario_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars']) || 0
187
- (scenario_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars']) || 0
188
- (scenario_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars']) || 0
189
- (scenario_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars']) || 0
190
- (scenario_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars']) || 0
191
- (scenario_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars']) || 0
192
-
193
- (scenario_report.distributed_generation.solar_pv.size_kw = reopt_output['outputs']['Scenario']['Site']['PV']['size_kw']) || 0
194
- (scenario_report.distributed_generation.wind.size_kw = reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw']) || 0
195
- (scenario_report.distributed_generation.generator.size_kw = reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw']) || 0
196
- (scenario_report.distributed_generation.storage.size_kw = reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw']) || 0
197
- (scenario_report.distributed_generation.storage.size_kwh = reopt_output['outputs']['Scenario']['Site']['Storage']['size_kwh']) || 0
198
-
199
- # Update dispatch
207
+
208
+ scenario_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
209
+ scenario_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
210
+ scenario_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
211
+ scenario_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
212
+ scenario_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
213
+ scenario_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
214
+
215
+ if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
216
+ reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
217
+ elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
218
+ reopt_output['outputs']['Scenario']['Site']['PV'] = []
219
+ end
220
+
221
+ reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
222
+ scenario_report.distributed_generation.add_tech 'solar_pv', URBANopt::Scenario::DefaultReports::SolarPV.new( {size_kw: (pv['size_kw'] || 0), id: i })
223
+ end
224
+
225
+ wind = reopt_output['outputs']['Scenario']['Site']['Wind']
226
+ if !wind['size_kw'].nil? and wind['size_kw'] != 0
227
+ scenario_report.distributed_generation.add_tech 'wind', URBANopt::Scenario::DefaultReports::Wind.new( {size_kw: (wind['size_kw'] || 0) })
228
+ end
229
+
230
+ generator = reopt_output['outputs']['Scenario']['Site']['Generator']
231
+ if !generator['size_kw'].nil? and generator['size_kw'] != 0
232
+ scenario_report.distributed_generation.add_tech 'generator', URBANopt::Scenario::DefaultReports::Generator.new( {size_kw: (generator['size_kw'] || 0) })
233
+ end
234
+
235
+ storage = reopt_output['outputs']['Scenario']['Site']['Storage']
236
+ if !storage['size_kw'].nil? and storage['size_kw'] != 0
237
+ scenario_report.distributed_generation.add_tech 'storage', URBANopt::Scenario::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
238
+ end
239
+
200
240
  generation_timeseries_kwh = Matrix[[0] * 8760]
201
- unless reopt_output['outputs']['Scenario']['Site']['PV'].nil?
202
- if (reopt_output['outputs']['Scenario']['Site']['PV']['size_kw'] || 0) > 0
203
- if !reopt_output['outputs']['Scenario']['Site']['PV']['year_one_power_production_series_kw'].nil?
204
- generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['PV']['year_one_power_production_series_kw']]
241
+
242
+
243
+ reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
244
+ if (pv['size_kw'] || 0) > 0
245
+ if !pv['year_one_power_production_series_kw'].nil?
246
+ generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
205
247
  end
206
248
  end
207
- end
249
+ end
208
250
 
209
- # unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
210
- # if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
211
- # if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
212
- # generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
213
- # end
214
- # end
215
- # end
251
+ unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
252
+ if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
253
+ if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
254
+ generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
255
+ end
256
+ end
257
+ end
216
258
 
217
259
  unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
218
260
  if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
@@ -231,136 +273,151 @@ module URBANopt # :nodoc:
231
273
  end
232
274
 
233
275
  $generation_timeseries_kwh = generation_timeseries_kwh.to_a[0]
234
- $generation_timeseries_kwh_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Total')
276
+ $generation_timeseries_kwh_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Total(kw)')
235
277
  if $generation_timeseries_kwh_col.nil?
236
278
  $generation_timeseries_kwh_col = scenario_report.timeseries_csv.column_names.length
237
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Total')
279
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
238
280
  end
239
281
 
240
- $load = reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'] || [0] * 8760
241
- $load_col = scenario_report.timeseries_csv.column_names.index('Electricity:Load:Total')
282
+ $load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
283
+ $load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
242
284
  if $load_col.nil?
243
285
  $load_col = scenario_report.timeseries_csv.column_names.length
244
- scenario_report.timeseries_csv.column_names.push('Electricity:Load:Total')
286
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
245
287
  end
246
288
 
247
- $utility_to_load = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'] || [0] * 8760
248
- $utility_to_load_col = scenario_report.timeseries_csv.column_names.index('Electricity:Grid:ToLoad')
289
+ $utility_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
290
+ $utility_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
249
291
  if $utility_to_load_col.nil?
250
292
  $utility_to_load_col = scenario_report.timeseries_csv.column_names.length
251
- scenario_report.timeseries_csv.column_names.push('Electricity:Grid:ToLoad')
293
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
252
294
  end
253
295
 
254
- $utility_to_battery = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'] || [0] * 8760
255
- $utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('Electricity:Grid:ToBattery')
296
+ $utility_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
297
+ $utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
256
298
  if $utility_to_battery_col.nil?
257
299
  $utility_to_battery_col = scenario_report.timeseries_csv.column_names.length
258
- scenario_report.timeseries_csv.column_names.push('Electricity:Grid:ToBattery')
300
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
259
301
  end
260
302
 
261
- $storage_to_load = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'] || [0] * 8760
262
- $storage_to_load_col = scenario_report.timeseries_csv.column_names.index('Electricity:Storage:ToLoad')
303
+ $storage_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
304
+ $storage_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
263
305
  if $storage_to_load_col.nil?
264
306
  $storage_to_load_col = scenario_report.timeseries_csv.column_names.length
265
- scenario_report.timeseries_csv.column_names.push('Electricity:Storage:ToLoad')
307
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
266
308
  end
267
309
 
268
- $storage_to_grid = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'] || [0] * 8760
269
- $storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('Electricity:Storage:ToGrid')
310
+ $storage_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
311
+ $storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
270
312
  if $storage_to_grid_col.nil?
271
313
  $storage_to_grid_col = scenario_report.timeseries_csv.column_names.length
272
- scenario_report.timeseries_csv.column_names.push('Electricity:Storage:ToGrid')
314
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
273
315
  end
274
316
 
275
- $storage_soc = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'] || [0] * 8760
276
- $storage_soc_col = scenario_report.timeseries_csv.column_names.index('Electricity:Storage:StateOfCharge')
317
+ $storage_soc = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct']) || [0] * (8760 * scenario_report.timesteps_per_hour)
318
+ $storage_soc_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
277
319
  if $storage_soc_col.nil?
278
320
  $storage_soc_col = scenario_report.timeseries_csv.column_names.length
279
- scenario_report.timeseries_csv.column_names.push('Electricity:Storage:StateOfCharge')
321
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
280
322
  end
281
323
 
282
- $generator_total = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'] || [0] * 8760
283
- $generator_total_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:Total')
324
+ $generator_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
325
+ $generator_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
284
326
  if $generator_total_col.nil?
285
327
  $generator_total_col = scenario_report.timeseries_csv.column_names.length
286
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:Total')
328
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
287
329
  end
288
330
 
289
- $generator_to_battery = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'] || [0] * 8760
290
- $generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToBattery')
331
+ $generator_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
332
+ $generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
291
333
  if $generator_to_battery_col.nil?
292
334
  $generator_to_battery_col = scenario_report.timeseries_csv.column_names.length
293
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToBattery')
335
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
294
336
  end
295
337
 
296
- $generator_to_load = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'] || [0] * 8760
297
- $generator_to_load_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToLoad')
338
+ $generator_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
339
+ $generator_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
298
340
  if $generator_to_load_col.nil?
299
341
  $generator_to_load_col = scenario_report.timeseries_csv.column_names.length
300
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToLoad')
342
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
301
343
  end
302
344
 
303
- $generator_to_grid = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'] || [0] * 8760
304
- $generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToGrid')
345
+ $generator_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
346
+ $generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
305
347
  if $generator_to_grid_col.nil?
306
348
  $generator_to_grid_col = scenario_report.timeseries_csv.column_names.length
307
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToGrid')
349
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
308
350
  end
309
351
 
310
- $pv_total = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_power_production_series_kw'] || [0] * 8760
311
- $pv_total_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:Total')
352
+ $pv_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
312
353
  if $pv_total_col.nil?
313
354
  $pv_total_col = scenario_report.timeseries_csv.column_names.length
314
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:Total')
355
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
315
356
  end
316
357
 
317
- $pv_to_battery = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_to_battery_series_kw'] || [0] * 8760
318
- $pv_to_battery_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToBattery')
358
+ $pv_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
319
359
  if $pv_to_battery_col.nil?
320
360
  $pv_to_battery_col = scenario_report.timeseries_csv.column_names.length
321
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToBattery')
361
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
322
362
  end
323
363
 
324
- $pv_to_load = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_to_load_series_kw'] || [0] * 8760
325
- $pv_to_load_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToLoad')
364
+ $pv_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
326
365
  if $pv_to_load_col.nil?
327
366
  $pv_to_load_col = scenario_report.timeseries_csv.column_names.length
328
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToLoad')
367
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
329
368
  end
330
369
 
331
- $pv_to_grid = reopt_output['outputs']['Scenario']['Site']['PV']['year_one_to_grid_series_kw'] || [0] * 8760
332
- $pv_to_grid_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToGrid')
370
+ $pv_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
333
371
  if $pv_to_grid_col.nil?
334
372
  $pv_to_grid_col = scenario_report.timeseries_csv.column_names.length
335
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToGrid')
373
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
336
374
  end
337
375
 
338
- $wind_total = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'] || [0] * 8760
339
- $wind_total_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:Total')
376
+ $pv_total = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
377
+ $pv_to_battery = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
378
+ $pv_to_load = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
379
+ $pv_to_grid = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
380
+
381
+ reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
382
+ if (pv['size_kw'] || 0) > 0
383
+ $pv_total += Matrix[scale_timeseries(pv['year_one_power_production_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
384
+ $pv_to_battery += Matrix[scale_timeseries(pv['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
385
+ $pv_to_load += Matrix[scale_timeseries(pv['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
386
+ $pv_to_grid += Matrix[scale_timeseries(pv['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
387
+ end
388
+ end
389
+
390
+ $pv_total = $pv_total.to_a[0]
391
+ $pv_to_battery = $pv_to_battery.to_a[0]
392
+ $pv_to_load = $pv_to_load.to_a[0]
393
+ $pv_to_grid = $pv_to_grid.to_a[0]
394
+
395
+ $wind_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
396
+ $wind_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
340
397
  if $wind_total_col.nil?
341
398
  $wind_total_col = scenario_report.timeseries_csv.column_names.length
342
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:Total')
399
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
343
400
  end
344
401
 
345
- $wind_to_battery = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'] || [0] * 8760
346
- $wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToBattery')
402
+ $wind_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
403
+ $wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
347
404
  if $wind_to_battery_col.nil?
348
405
  $wind_to_battery_col = scenario_report.timeseries_csv.column_names.length
349
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToBattery')
406
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
350
407
  end
351
408
 
352
- $wind_to_load = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'] || [0] * 8760
353
- $wind_to_load_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToLoad')
409
+ $wind_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
410
+ $wind_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
354
411
  if $wind_to_load_col.nil?
355
412
  $wind_to_load_col = scenario_report.timeseries_csv.column_names.length
356
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToLoad')
413
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
357
414
  end
358
415
 
359
- $wind_to_grid = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'] || [0] * 8760
360
- $wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToGrid')
416
+ $wind_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
417
+ $wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
361
418
  if $wind_to_grid_col.nil?
362
419
  $wind_to_grid_col = scenario_report.timeseries_csv.column_names.length
363
- scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToGrid')
420
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
364
421
  end
365
422
 
366
423
  def modrow(x, i) # :nodoc:
@@ -387,9 +444,11 @@ module URBANopt # :nodoc:
387
444
  end
388
445
 
389
446
  old_data = CSV.open(scenario_report.timeseries_csv.path).read
447
+ start_date = Time.parse(old_data[1][0])
448
+ 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) / (( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
390
449
  mod_data = old_data.map.with_index do |x, i|
391
450
  if i > 0
392
- modrow(x, i)
451
+ modrow(x, start_ts + i -2)
393
452
  else
394
453
  x
395
454
  end
@@ -30,6 +30,6 @@
30
30
 
31
31
  module URBANopt # :nodoc:
32
32
  module REopt # :nodoc:
33
- VERSION = '0.1.0'.freeze
33
+ VERSION = '0.2.0'.freeze
34
34
  end
35
35
  end
@@ -29,5 +29,5 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_dependency 'certified'
31
31
  spec.add_dependency 'json_pure'
32
- spec.add_dependency 'urbanopt-scenario', '0.1.1'
32
+ #spec.add_dependency 'urbanopt-scenario', '0.1.1'
33
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanopt-reopt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-16 00:00:00.000000000 Z
11
+ date: 2020-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,20 +94,6 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: urbanopt-scenario
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - '='
102
- - !ruby/object:Gem::Version
103
- version: 0.1.1
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - '='
109
- - !ruby/object:Gem::Version
110
- version: 0.1.1
111
97
  description: Classes and measures for utilizing the REopt Lite API within OpenStudio
112
98
  workflows.
113
99
  email:
@@ -116,6 +102,9 @@ executables: []
116
102
  extensions: []
117
103
  extra_rdoc_files: []
118
104
  files:
105
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
106
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
107
+ - ".github/pull_request_template.md"
119
108
  - ".gitignore"
120
109
  - ".rakeTasks"
121
110
  - ".rdoc_options"
@@ -123,6 +112,7 @@ files:
123
112
  - ".rubocop.yml"
124
113
  - ".travis.yml"
125
114
  - CHANGELOG.md
115
+ - CONTRIBUTING.md
126
116
  - Gemfile
127
117
  - Jenkinsfile
128
118
  - LICENSE.md