urbanopt-cli 0.6.0 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +2 -2
  4. data/CHANGELOG.md +38 -0
  5. data/CMakeLists.txt +13 -13
  6. data/FindOpenStudioSDK.cmake +11 -6
  7. data/Gemfile +11 -5
  8. data/example_files/Gemfile +6 -3
  9. data/example_files/base_workflow_res.osw +10 -0
  10. data/example_files/example_project_combined.json +13 -3
  11. data/example_files/example_project_with_PV.json +751 -0
  12. data/example_files/example_project_with_streets.json +826 -0
  13. data/example_files/mappers/Baseline.rb +69 -14
  14. data/example_files/mappers/CreateBar.rb +31 -1
  15. data/example_files/mappers/FlexibleHotWater.rb +69 -0
  16. data/example_files/mappers/Floorspace.rb +31 -1
  17. data/example_files/mappers/HighEfficiency.rb +20 -8
  18. data/example_files/mappers/HighEfficiencyCreateBar.rb +3 -2
  19. data/example_files/mappers/HighEfficiencyFloorspace.rb +3 -2
  20. data/example_files/mappers/base_workflow.osw +5 -0
  21. data/example_files/mappers/createbar_workflow.osw +3 -1
  22. data/example_files/mappers/floorspace_workflow.osw +2 -1
  23. data/example_files/osm_building/7.osm +0 -307
  24. data/example_files/osm_building/8.osm +0 -419
  25. data/example_files/osm_building/9.osm +0 -664
  26. data/example_files/reopt/base_assumptions.json +3 -3
  27. data/example_files/reopt/multiPV_assumptions.json +2 -2
  28. data/example_files/resources/hpxml-measures/Gemfile +1 -1
  29. data/example_files/resources/hpxml-measures/Gemfile.lock +6 -25
  30. data/example_files/visualization/input_visualization_feature.html +15 -16
  31. data/example_files/visualization/input_visualization_scenario.html +16 -11
  32. data/lib/uo_cli/version.rb +1 -1
  33. data/lib/uo_cli.rb +158 -26
  34. data/scripts/setup-env-gitbash.sh +4 -4
  35. data/scripts/setup-env-unix.sh +4 -4
  36. data/scripts/setup-env.bat +3 -3
  37. data/scripts/setup-env.ps1 +3 -3
  38. data/uo_cli.gemspec +8 -5
  39. metadata +59 -14
@@ -22,8 +22,8 @@
22
22
  "net_metering_limit_kw": 0,
23
23
  "interconnection_limit_kw": 100000000.0,
24
24
  "blended_monthly_demand_charges_us_dollars_per_kw": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
25
- "blended_monthly_rates_us_dollars_per_kwh": [0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
26
- },
25
+ "blended_monthly_rates_us_dollars_per_kwh": [0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
26
+ },
27
27
  "Wind": {
28
28
  "min_kw": 0,
29
29
  "max_kw": 0,
@@ -77,7 +77,7 @@
77
77
  "losses": 0.14,
78
78
  "array_type": 1,
79
79
  "module_type": 0,
80
- "gcr": 0.4,
80
+ "gcr": 0.99,
81
81
  "dc_ac_ratio": 1.2,
82
82
  "inv_eff": 0.96,
83
83
  "radius": 0,
@@ -77,7 +77,7 @@
77
77
  "losses": 0.14,
78
78
  "array_type": 1,
79
79
  "module_type": 0,
80
- "gcr": 0.4,
80
+ "gcr": 0.99,
81
81
  "dc_ac_ratio": 1.2,
82
82
  "inv_eff": 0.96,
83
83
  "radius": 0,
@@ -113,7 +113,7 @@
113
113
  "losses": 0.14,
114
114
  "array_type": 0,
115
115
  "module_type": 0,
116
- "gcr": 0.4,
116
+ "gcr": 0.99,
117
117
  "dc_ac_ratio": 1.2,
118
118
  "inv_eff": 0.96,
119
119
  "radius": 0,
@@ -2,7 +2,7 @@
2
2
 
3
3
  source 'http://rubygems.org'
4
4
 
5
- gem 'nokogiri', '~> 1.10'
5
+ gem 'nokogiri', '~> 1.12'
6
6
  gem 'oga'
7
7
  gem 'schematron-nokogiri'
8
8
  gem 'rake'
@@ -4,27 +4,17 @@ GEM
4
4
  ansi (1.5.0)
5
5
  ast (2.4.2)
6
6
  builder (3.2.4)
7
- ci_reporter (2.0.0)
8
- builder (>= 2.1.2)
9
- ci_reporter_minitest (1.0.0)
10
- ci_reporter (~> 2.0)
11
- minitest (~> 5.0)
12
- codecov (0.2.12)
13
- json
14
- simplecov
15
- docile (1.3.5)
16
- json (2.5.1)
17
- mini_portile2 (2.5.0)
7
+ mini_portile2 (2.6.1)
18
8
  minitest (5.14.4)
19
9
  minitest-reporters (1.4.3)
20
10
  ansi
21
11
  builder
22
12
  minitest (>= 5.0)
23
13
  ruby-progressbar
24
- nokogiri (1.11.2)
25
- mini_portile2 (~> 2.5.0)
14
+ nokogiri (1.12.5)
15
+ mini_portile2 (~> 2.6.1)
26
16
  racc (~> 1.4)
27
- nokogiri (1.11.2-x64-mingw32)
17
+ nokogiri (1.12.5-x64-mingw32)
28
18
  racc (~> 1.4)
29
19
  oga (3.3)
30
20
  ast
@@ -38,28 +28,19 @@ GEM
38
28
  ruby-progressbar (1.11.0)
39
29
  schematron-nokogiri (0.0.3)
40
30
  nokogiri (~> 1.6)
41
- simplecov (0.21.2)
42
- docile (~> 1.1)
43
- simplecov-html (~> 0.11)
44
- simplecov_json_formatter (~> 0.1)
45
- simplecov-html (0.12.3)
46
- simplecov_json_formatter (0.1.2)
47
31
 
48
32
  PLATFORMS
49
33
  ruby
50
34
  x64-mingw32
51
35
 
52
36
  DEPENDENCIES
53
- ci_reporter_minitest (~> 1.0.0)
54
- codecov (= 0.2.12)
55
37
  minitest (~> 5.9)
56
38
  minitest-reporters
57
- nokogiri (~> 1.10)
39
+ nokogiri (~> 1.12)
58
40
  oga
59
41
  parallel
60
42
  rake
61
43
  schematron-nokogiri
62
- simplecov
63
44
 
64
45
  BUNDLED WITH
65
- 2.2.11
46
+ 2.2.11
@@ -383,10 +383,13 @@
383
383
 
384
384
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
385
385
 
386
- var datasets = ['Electricity:Facility', 'ElectricityProduced:Facility', 'NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
386
+ var datasets = ['Electricity:Facility', 'REopt:ElectricityProduced:Total', 'NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
387
387
 
388
388
  var endUseKeys = ['Heating:Electricity', 'Cooling:Electricity', 'InteriorLights:Electricity', 'ExteriorLights:Electricity', 'ExteriorEquipment:Electricity', 'InteriorEquipment:Electricity', 'Fans:Electricity', 'Pumps:Electricity', 'HeatRejection:Electricity', 'WaterSystems:Electricity'];
389
389
 
390
+ var kbtu_datasets = ['NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
391
+ var changeToKbtu = false;
392
+
390
393
 
391
394
  var applicableEndUseKeys = [];
392
395
 
@@ -449,8 +452,7 @@
449
452
 
450
453
  // monthly fuel use
451
454
  $scope.monthlyFuelChartData[feature.name] = [];
452
- var changeToKbtu = false;
453
- var kbtu_datasets = ['NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
455
+
454
456
  // first iterate through all kbtu datasets to see if you'll need to change to kBtu units
455
457
  _.forEach(kbtu_datasets, function (kbtu_dataset) {
456
458
  var values = feature.monthly_values[kbtu_dataset];
@@ -481,7 +483,7 @@
481
483
  datasetUnit = 'Electricity:Facility(kWh)';
482
484
  }
483
485
  }
484
- } else if (dataset == 'ElectricityProduced:Facility') {
486
+ } else if (dataset == 'REopt:ElectricityProduced:Total') {
485
487
  // first check if there is data to include
486
488
  if (!(values.every(item => item === 0))) {
487
489
  if (changeToKbtu) {
@@ -530,29 +532,26 @@
530
532
  // monthly net use
531
533
  if(feature['complete_simulation'] == true){
532
534
  $scope.monthlyNetChartData[feature.name] = [];
533
- var values = feature.monthly_values['NaturalGas:Facility'];
534
- var changeToKbtu = false;
535
- if (!(values.every(item => item === 0))) {
536
- changeToKbtu = true
537
- }
535
+ var unit = ' (kWh)'
538
536
  if (changeToKbtu){
539
- var unit = ' (kBtu)'
540
- }
541
- else {
542
- var unit = ' (kWh)'
537
+ unit = ' (kBtu)'
543
538
  }
544
539
 
545
540
  $scope.annualNetChartData[feature.name] = 0;
546
541
  $scope.monthlyNetChartData[feature.name].push({
547
542
  key: 'Net Energy Use' + unit,
548
543
  values: _.map(months, function (month, i) {
544
+ var value = 0;
549
545
  if (changeToKbtu){
550
- var value = feature.monthly_values['Electricity:Facility'][i]*3.41 - feature.monthly_values['ElectricityProduced:Facility'][i]*3.41 + feature.monthly_values['NaturalGas:Facility'][i]; //Values are in kBtu
546
+ value = feature.monthly_values['Electricity:Facility'][i]*3.41 - feature.monthly_values['REopt:ElectricityProduced:Total'][i]*3.41;
547
+ _.forEach(kbtu_datasets, function(ds){
548
+ value += feature.monthly_values[ds][i];
549
+ });
551
550
  }
552
551
  else {
553
- var value = feature.monthly_values['Electricity:Facility'][i] - feature.monthly_values['ElectricityProduced:Facility'][i]; //Values are in kWh
552
+ value = feature.monthly_values['Electricity:Facility'][i] - feature.monthly_values['REopt:ElectricityProduced:Total'][i]; //Values are in kWh
554
553
  }
555
- value;
554
+
556
555
  $scope.annualNetChartData[feature.name] += value;
557
556
  // global
558
557
  monthlyNetYMin = _.min([monthlyNetYMin, value]);
@@ -373,10 +373,13 @@
373
373
 
374
374
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
375
375
 
376
- var datasets = ['Electricity:Facility', 'ElectricityProduced:Facility', 'NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
376
+ var datasets = ['Electricity:Facility', 'REopt:ElectricityProduced:Total', 'NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
377
377
 
378
378
  var endUseKeys = ['Heating:Electricity', 'Cooling:Electricity', 'InteriorLights:Electricity', 'ExteriorLights:Electricity', 'InteriorEquipment:Electricity', 'ExteriorEquipment:Electricity', 'Fans:Electricity', 'Pumps:Electricity', 'HeatRejection:Electricity', 'WaterSystems:Electricity'];
379
379
 
380
+ var kbtu_datasets = ['NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
381
+ var changeToKbtu = false;
382
+
380
383
  var applicableEndUseKeys = [];
381
384
 
382
385
  $scope.monthlyFuelChartData = {};
@@ -422,8 +425,7 @@
422
425
 
423
426
  // monthly fuel use
424
427
  $scope.monthlyFuelChartData[scenario.name] = [];
425
- var changeToKbtu = false;
426
- var kbtu_datasets = ['NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
428
+
427
429
  // first iterate through all kbtu datasets to see if you'll need to change to kBtu units
428
430
  _.forEach(kbtu_datasets, function (kbtu_dataset) {
429
431
  var values = scenario.monthly_values[kbtu_dataset];
@@ -454,7 +456,7 @@
454
456
  datasetUnit = 'Electricity:Facility(kWh)';
455
457
  }
456
458
  }
457
- } else if (dataset == 'ElectricityProduced:Facility') {
459
+ } else if (dataset == 'REopt:ElectricityProduced:Total') {
458
460
  // first check if there is data to include
459
461
  if (!(values.every(item => item === 0))) {
460
462
  if (changeToKbtu) {
@@ -502,24 +504,27 @@
502
504
  if (!(values.every(item => item === 0))) {
503
505
  changeToKbtu = true
504
506
  }
507
+ var unit = ' (kWh)'
505
508
  if (changeToKbtu){
506
- var unit = ' (kBtu)'
507
- }
508
- else {
509
- var unit = ' (kWh)'
509
+ unit = ' (kBtu)'
510
510
  }
511
511
 
512
512
  $scope.annualNetChartData[scenario.name] = 0;
513
513
  $scope.monthlyNetChartData[scenario.name].push({
514
514
  key: 'Net Energy Use' + unit,
515
515
  values: _.map(months, function (month, i) {
516
+ var value = 0;
516
517
  if (changeToKbtu){
517
- var value = scenario.monthly_values['Electricity:Facility'][i]*3.41 - scenario.monthly_values['ElectricityProduced:Facility'][i]*3.41 + scenario.monthly_values['NaturalGas:Facility'][i]; //Values are in kBtu
518
+ value = scenario.monthly_values['Electricity:Facility'][i]*3.41 - scenario.monthly_values['REopt:ElectricityProduced:Total'][i]*3.41 + scenario.monthly_values['NaturalGas:Facility'][i]; //Values are in kBtu
519
+
520
+ _.forEach(kbtu_datasets, function(ds){
521
+ value += scenario.monthly_values[ds][i];
522
+ });
518
523
  }
519
524
  else {
520
- var value = scenario.monthly_values['Electricity:Facility'][i] - scenario.monthly_values['ElectricityProduced:Facility'][i]; //Values are in kWh
525
+ value = scenario.monthly_values['Electricity:Facility'][i] - scenario.monthly_values['REopt:ElectricityProduced:Total'][i]; //Values are in kWh
521
526
  }
522
- value;
527
+ // value;
523
528
  $scope.annualNetChartData[scenario.name] += value;
524
529
  monthlyNetYMin = _.min([monthlyNetYMin, value]);
525
530
  monthlyNetYMax = _.max([monthlyNetYMax, value]);
@@ -40,6 +40,6 @@
40
40
 
41
41
  module URBANopt
42
42
  module CLI
43
- VERSION = '0.6.0'.freeze
43
+ VERSION = '0.6.4'.freeze
44
44
  end
45
45
  end
data/lib/uo_cli.rb CHANGED
@@ -46,6 +46,7 @@ require 'urbanopt/geojson'
46
46
  require 'urbanopt/scenario'
47
47
  require 'urbanopt/reopt'
48
48
  require 'urbanopt/reopt_scenario'
49
+ require 'urbanopt/rnm'
49
50
  require 'csv'
50
51
  require 'fileutils'
51
52
  require 'json'
@@ -59,10 +60,11 @@ module URBANopt
59
60
  COMMAND_MAP = {
60
61
  'create' => 'Make new things - project directory or files',
61
62
  'run' => 'Use files in your directory to simulate district energy use',
62
- 'opendss' => 'Run OpenDSS simulation',
63
63
  'process' => 'Post-process URBANopt simulations for additional insights',
64
64
  'visualize' => 'Visualize and compare results for features and scenarios',
65
65
  'validate' => 'Validate results with custom rules',
66
+ 'opendss' => 'Run OpenDSS simulation',
67
+ 'rnm' => 'Run RNM simulation',
66
68
  'delete' => 'Delete simulations for a specified scenario',
67
69
  'des_params' => 'Make a DES system parameters config file',
68
70
  'des_create' => 'Create a Modelica model',
@@ -106,9 +108,6 @@ module URBANopt
106
108
  "Add additional tags to specify the method for creating geometry, or use the default urban geometry creation method to create building geometry from geojson coordinates with core and perimeter zoning\n" \
107
109
  'Example: uo create --project-folder urbanopt_example_project', type: String, short: :p
108
110
 
109
- opt :electric, "\nCreate default project with FeatureFile containing electrical network\n" \
110
- "Example: uo create --project-folder urbanopt_example_project --electric", short: :l
111
-
112
111
  opt :create_bar, "\nCreate building geometry and add space types using the create bar from building type ratios measure\n" \
113
112
  "Refer to https://docs.urbanopt.net/ for more details about the workflow\n" \
114
113
  "Used with --project-folder\n" \
@@ -123,6 +122,15 @@ module URBANopt
123
122
  "This functionality has not been exhaustively tested and currently supports the Single-Family Detached building type and the Baseline Scenario only\n" \
124
123
  "Used with --project-folder\n" \
125
124
  "Example: uo create --project-folder urbanopt_example_project --combined\n", short: :d
125
+
126
+ opt :electric, "\nCreate default project with FeatureFile containing electrical network, used for OpenDSS analysis\n" \
127
+ "Example: uo create --project-folder urbanopt_example_project --electric", short: :l
128
+
129
+ opt :streets, "\nCreate default project wiht FeatureFile containing streets, used for RNM analysis\n" \
130
+ "Example: uo create --project-folder urbanopt_example_project --streets", short: :t
131
+
132
+ opt :photovoltaic, "\nCreate default project with FeatureFile containing community photovoltaic for the district and ground-mount photovoltaic associated with buildings, used for REopt analysis \n" \
133
+ "Example: uo create --project-folder urbanopt_example_project --photovoltaic", short: :v
126
134
 
127
135
  opt :empty, "\nUse with --project-folder argument to create an empty project folder\n" \
128
136
  "Then add your own Feature file in the project directory you created,\n" \
@@ -173,11 +181,11 @@ module URBANopt
173
181
 
174
182
  opt :scenario, "\nRun OpenDSS simulations for <scenario>\n" \
175
183
  "Requires --feature also be specified\n" \
176
- 'Example: uo opendss --scenario baseline_scenario-2.csv --feature example_project.json', default: 'baseline_scenario.csv', short: :s
184
+ 'Example: uo opendss --scenario baseline_scenario-2.csv --feature example_project.json', default: 'baseline_scenario.csv', required: true, short: :s
177
185
 
178
186
  opt :feature, "\nRun OpenDSS simulations according to <featurefile>\n" \
179
187
  "Requires --scenario also be specified\n" \
180
- 'Example: uo opendss --scenario baseline_scenario.csv --feature example_project.json', default: 'example_project_with_electric_network.json', short: :f
188
+ 'Example: uo opendss --scenario baseline_scenario.csv --feature example_project.json', default: 'example_project_with_electric_network.json', required: true, short: :f
181
189
 
182
190
  opt :equipment, "\nRun OpenDSS simulations using <equipmentfile>. If not specified, the electrical_database.json from urbanopt-ditto-reader will be used.\n" \
183
191
  'Example: uo opendss --scenario baseline_scenario.csv --feature example_project.json', type: String, short: :e
@@ -204,6 +212,33 @@ module URBANopt
204
212
  end
205
213
  end
206
214
 
215
+ # Define RNM commands
216
+ def opt_rnm
217
+ @subopts = Optimist.options do
218
+ banner "\nURBANopt #{@command}:\n\n"
219
+
220
+ opt :scenario, "\nRun RNM simulation for <scenario>. Scenario must be run and post-processed prior to calling the rnm command.\n" \
221
+ "Requires --feature also be specified\n" \
222
+ 'Example: uo rnm --scenario baseline_scenario-2.csv --feature example_project.json', default: 'baseline_scenario.csv', required: true, short: :s
223
+
224
+ opt :feature, "\nRun RNM simulation according to <featurefile>\n" \
225
+ "Requires --scenario also be specified\n" \
226
+ 'Example: uo rnm --scenario baseline_scenario.csv --feature example_project.json', default: 'example_project_with_streets.json', required: true, short: :f
227
+
228
+ opt :reopt, "\nInclude processed REopt optimization results in the simulation.\n" \
229
+ "Example: uo rnm --scenario baseline_scenario.csv --feature example_project.json --reopt", short: :r
230
+
231
+ opt :extended_catalog, "\nUse this option to specify the extended electrical catalog path.\n" \
232
+ "If this option is not included, the default catalog will be used", type: String, short: :c
233
+
234
+ opt :average_peak_catalog, "\nUse this option to specify the average peak catalog path.\n" \
235
+ "If this option is not included, the default catalog will be used", type: String, short: :a
236
+
237
+ opt :opendss, "\n If this option is specified, an OpenDSS-compatible electrical database will be created \n" \
238
+ "Example: uo rnm --scenario baseline_scenario.csv --feature example_project_with_streets.json --opendss", short: :o
239
+ end
240
+ end
241
+
207
242
  # Define post-processing commands
208
243
  def opt_process
209
244
  @subopts = Optimist.options do
@@ -219,10 +254,16 @@ module URBANopt
219
254
  opt :reopt_feature, "\nOptimize for each building individually with REopt\n" \
220
255
  'Example: uo process --reopt-feature'
221
256
 
257
+ opt :reopt_resilience, "\nInclude resilience reporting in REopt optimization\n" \
258
+ 'Example: uo process --reopt-scenario --reopt-resilience'
259
+
260
+ opt :reopt_keep_existing, "\nKeep existing reopt feature optimizations instead of rerunning them to avoid rate limit issues.\n" \
261
+ 'Example: uo process --reopt-feature --reopt-keep-existing', short: :k
262
+
222
263
  opt :with_database, "\nInclude a sql database output of post-processed results\n" \
223
264
  'Example: uo process --default --with-database'
224
265
 
225
- opt :reopt_scenario_assumptions_file, "\nPath to the scenario REopt assumptions JSON file you want to use. Use with the --reopt-scenario post-processor. " \
266
+ opt :reopt_scenario_assumptions_file, "\nPath to the scenario REopt assumptions JSON file you want to use. Use with the --reopt-scenario post-processor.\n" \
226
267
  "If not specified, the reopt/base_assumptions.json file will be used", type: String, short: :a
227
268
 
228
269
  opt :scenario, "\nSelect which scenario to optimize", default: 'baseline_scenario.csv', required: true, short: :s
@@ -344,7 +385,7 @@ module URBANopt
344
385
  @scenario_name = File.basename(@scenario_file_name, File.extname(@scenario_file_name))
345
386
  end
346
387
 
347
- # Simulate energy usage as defined by ScenarioCSV\
388
+ # Simulate energy usage as defined by ScenarioCSV
348
389
  def self.run_func
349
390
  run_dir = File.join(@root_dir, 'run', @scenario_name.downcase)
350
391
  csv_file = File.join(@root_dir, @scenario_file_name)
@@ -493,11 +534,15 @@ module URBANopt
493
534
 
494
535
  if @opthash.subopts[:electric] == true
495
536
  FileUtils.cp(File.join(path_item, 'example_project_with_electric_network.json'), dir_name)
537
+ elsif @opthash.subopts[:streets] == true
538
+ FileUtils.cp(File.join(path_item, 'example_project_with_streets.json'), dir_name)
539
+ elsif @opthash.subopts[:photovoltaic] == true
540
+ FileUtils.cp(File.join(path_item, 'example_project_with_PV.json'), dir_name)
496
541
  end
497
542
 
498
543
  if @opthash.subopts[:floorspace] == false
499
544
 
500
- if @opthash.subopts[:electric] != true
545
+ if @opthash.subopts[:electric] != true && @opthash.subopts[:streets] != true && @opthash.subopts[:photovoltaic] != true
501
546
  # copy feature file
502
547
  FileUtils.cp(File.join(path_item, 'example_project.json'), dir_name)
503
548
  end
@@ -514,6 +559,7 @@ module URBANopt
514
559
  FileUtils.cp(File.join(path_item, 'mappers/HighEfficiency.rb'), File.join(dir_name, 'mappers'))
515
560
  FileUtils.cp(File.join(path_item, 'mappers/ThermalStorage.rb'), File.join(dir_name, 'mappers'))
516
561
  FileUtils.cp(File.join(path_item, 'mappers/EvCharging.rb'), File.join(dir_name, 'mappers'))
562
+ FileUtils.cp(File.join(path_item, 'mappers/FlexibleHotWater.rb'), File.join(dir_name, 'mappers'))
517
563
 
518
564
  # copy osw file
519
565
  FileUtils.cp(File.join(path_item, 'mappers/base_workflow.osw'), File.join(dir_name, 'mappers'))
@@ -728,6 +774,7 @@ module URBANopt
728
774
  puts "\nDone\n"
729
775
  end
730
776
 
777
+ # Run OpenDSS simulation
731
778
  if @opthash.command == 'opendss'
732
779
 
733
780
  # first check python
@@ -797,11 +844,45 @@ module URBANopt
797
844
  begin
798
845
  system(ditto_cli_root + ditto_cli_addition)
799
846
  rescue FileNotFoundError
800
- abort("\nMust post-process results before running opendss. We recommend 'process --default'." \
801
- "Once opendss is run, you may then 'process --opendss'")
847
+ abort("\nMust post-process results before running OpenDSS. We recommend 'process --default'." \
848
+ "Once OpenDSS is run, you may then 'process --opendss'")
802
849
  end
803
850
  end
804
851
 
852
+ # Run RNM Simulation
853
+ if @opthash.command == 'rnm'
854
+
855
+ run_dir = File.join(@root_dir, 'run', @scenario_name.downcase)
856
+ # check if project has been post-processed appropriately
857
+ if !File.exist?(File.join(run_dir, 'default_scenario_report.json'))
858
+ abort("\nYou must first post-process the scenario before running RNM. We recommend 'process --default'.")
859
+ end
860
+
861
+ puts 'Preparing RNM inputs'
862
+ # prep arguments
863
+ reopt = @opthash.subopts[:reopt] ? true : false
864
+ opendss_catalog = @opthash.subopts[:opendss] ? true : false
865
+
866
+ # if paths below are nil, default paths will be used
867
+ extended_catalog_path = @opthash.subopts[:extended_catalog] ? @opthash.subopts[:extended_catalog] : nil
868
+ average_peak_catalog_path = @opthash.subopts[:average_peak_catalog] ? @opthash.subopts[:average_peak_catalog] : nil
869
+
870
+ # create inputs, run sim and get results
871
+ begin
872
+ runner = URBANopt::RNM::Runner.new(@scenario_name, run_dir, @opthash.subopts[:scenario], @opthash.subopts[:feature], extended_catalog_path:extended_catalog_path, average_peak_catalog_path:average_peak_catalog_path, reopt:reopt, opendss_catalog:opendss_catalog)
873
+ runner.create_simulation_files
874
+ runner.run
875
+ runner.post_process
876
+ rescue => error
877
+ abort("\nError: #{error.message}")
878
+ end
879
+
880
+ # TODO: aggregate back into scenario reports and geojson file
881
+ puts "\nRNM Results saved to: #{File.join(run_dir, 'rnm-us', 'results')}"
882
+ puts "\nDone\n"
883
+
884
+ end
885
+
805
886
  # Post-process the scenario
806
887
  if @opthash.command == 'process'
807
888
  if @opthash.subopts[:default] == false && @opthash.subopts[:opendss] == false && @opthash.subopts[:reopt_scenario] == false && @opthash.subopts[:reopt_feature] == false
@@ -829,7 +910,7 @@ module URBANopt
829
910
  results << { "process_type": 'default', "status": 'Complete', "timestamp": Time.now.strftime('%Y-%m-%dT%k:%M:%S.%L') }
830
911
  elsif @opthash.subopts[:opendss] == true
831
912
  puts "\nPost-processing OpenDSS results\n"
832
- opendss_folder = File.join(@root_dir, 'run', @scenario_name, 'opendss')
913
+ opendss_folder = File.join(@root_dir, 'run', @scenario_name.downcase, 'opendss')
833
914
  if File.directory?(opendss_folder)
834
915
  opendss_folder_name = File.basename(opendss_folder)
835
916
  opendss_post_processor = URBANopt::Scenario::OpenDSSPostProcessor.new(scenario_report, opendss_results_dir_name = opendss_folder_name)
@@ -848,15 +929,58 @@ module URBANopt
848
929
  scenario_assumptions = File.expand_path(@opthash.subopts[:reopt_scenario_assumptions_file]).to_s
849
930
  end
850
931
  puts "\nRunning the REopt Scenario post-processor with scenario assumptions file: #{scenario_assumptions}\n"
851
- reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(scenario_report, scenario_assumptions, scenario_base.reopt_feature_assumptions, DEVELOPER_NREL_KEY)
932
+ # Add community photovoltaic if present in the Feature File
933
+ community_photovoltaic = []
934
+ feature_file = JSON.parse(File.read(File.expand_path(@opthash.subopts[:feature])), symbolize_names: true)
935
+ feature_file[:features].each do |feature|
936
+ begin
937
+ if feature[:properties][:district_system_type]
938
+ if feature[:properties][:district_system_type] == 'Community Photovoltaic'
939
+ community_photovoltaic << feature
940
+ end
941
+ end
942
+ rescue
943
+ end
944
+ end
945
+ reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(
946
+ scenario_report,
947
+ scenario_assumptions,
948
+ scenario_base.reopt_feature_assumptions,
949
+ DEVELOPER_NREL_KEY,false
950
+ )
852
951
  if @opthash.subopts[:reopt_scenario] == true
853
952
  puts "\nPost-processing entire scenario with REopt\n"
854
- scenario_report_scenario = reopt_post_processor.run_scenario_report(scenario_report: scenario_report, save_name: 'scenario_optimization')
953
+ scenario_report_scenario = reopt_post_processor.run_scenario_report(
954
+ scenario_report: scenario_report,
955
+ save_name: 'scenario_optimization',
956
+ run_resilience: @opthash.subopts[:reopt_resilience],
957
+ community_photovoltaic: community_photovoltaic
958
+ )
855
959
  results << { "process_type": 'reopt_scenario', "status": 'Complete', "timestamp": Time.now.strftime('%Y-%m-%dT%k:%M:%S.%L') }
856
960
  puts "\nDone\n"
857
961
  elsif @opthash.subopts[:reopt_feature] == true
858
962
  puts "\nPost-processing each building individually with REopt\n"
859
- scenario_report_features = reopt_post_processor.run_scenario_report_features(scenario_report: scenario_report, save_names_feature_reports: ['feature_optimization'] * scenario_report.feature_reports.length, save_name_scenario_report: 'feature_optimization')
963
+ # Add groundmount photovoltaic if present in the Feature File
964
+ groundmount_photovoltaic = {}
965
+ feature_file = JSON.parse(File.read(File.expand_path(@opthash.subopts[:feature])), symbolize_names: true)
966
+ feature_file[:features].each do |feature|
967
+ begin
968
+ if feature[:properties][:district_system_type]
969
+ if feature[:properties][:district_system_type] == 'Ground Mount Photovoltaic'
970
+ groundmount_photovoltaic[feature[:properties][:associated_building_id]] = feature[:properties][:footprint_area]
971
+ end
972
+ end
973
+ rescue
974
+ end
975
+ end
976
+ scenario_report_features = reopt_post_processor.run_scenario_report_features(
977
+ scenario_report: scenario_report,
978
+ save_names_feature_reports: ['feature_optimization'] * scenario_report.feature_reports.length,
979
+ save_name_scenario_report: 'feature_optimization',
980
+ run_resilience: @opthash.subopts[:reopt_resilience],
981
+ keep_existing_output: @opthash.subopts[:reopt_keep_existing],
982
+ groundmount_photovoltaic: groundmount_photovoltaic
983
+ )
860
984
  results << { "process_type": 'reopt_feature', "status": 'Complete', "timestamp": Time.now.strftime('%Y-%m-%dT%k:%M:%S.%L') }
861
985
  puts "\nDone\n"
862
986
  end
@@ -881,11 +1005,16 @@ module URBANopt
881
1005
  scenario_folders = []
882
1006
  scenario_report_exists = false
883
1007
  Dir.glob(File.join(run_dir, '/*_scenario')) do |scenario_folder|
884
- scenario_report = File.join(scenario_folder, 'default_scenario_report.csv')
885
- if File.exist?(scenario_report)
886
- scenario_folders << scenario_folder
1008
+ scenario_report = File.join(scenario_folder, 'scenario_optimization.csv')
1009
+ # Check if Scenario Optimization REopt file exists and add that
1010
+ if File.exist?(File.join(scenario_folder, 'scenario_optimization.csv'))
1011
+ scenario_folders << File.join(scenario_folder, 'scenario_optimization.csv')
887
1012
  scenario_report_exists = true
888
- else
1013
+ # Check if Default Feature Report exists and add that
1014
+ elsif File.exist?(File.join(scenario_folder, 'default_scenario_report.csv'))
1015
+ scenario_folders << File.join(scenario_folder, 'default_scenario_report.csv')
1016
+ scenario_report_exists = true
1017
+ elsif
889
1018
  puts "\nERROR: Default reports not created for #{scenario_folder}. Please use 'process --default' to create default post processing reports for all scenarios first. Visualization not generated for #{scenario_folder}.\n"
890
1019
  end
891
1020
  end
@@ -921,11 +1050,14 @@ module URBANopt
921
1050
  feature_folders = []
922
1051
  # loop through building feature ids from scenario csv
923
1052
  csv['Feature Id'].each do |feature|
924
- feature_report = File.join(run_dir, feature, 'feature_reports')
925
- if File.exist?(feature_report)
1053
+ # Check if Feature Optimization REopt file exists and add that
1054
+ if File.exist?(File.join(run_dir, feature, 'feature_reports/feature_optimization.csv'))
926
1055
  feature_report_exists = true
927
- feature_folders << File.join(run_dir, feature)
928
- else
1056
+ feature_folders << File.join(run_dir, feature, 'feature_reports/feature_optimization.csv')
1057
+ elsif File.exist?(File.join(run_dir, feature, 'feature_reports/default_feature_report.csv'))
1058
+ feature_report_exists = true
1059
+ feature_folders << File.join(run_dir, feature, 'feature_reports/default_feature_report.csv')
1060
+ elsif
929
1061
  puts "\nERROR: Default reports not created for #{feature}. Please use 'process --default' to create default post processing reports for all features first. Visualization not generated for #{feature}.\n"
930
1062
  end
931
1063
  end
@@ -944,7 +1076,7 @@ module URBANopt
944
1076
  end
945
1077
  end
946
1078
  end
947
- html_out_path = File.join(@root_dir, 'run', @scenario_name, 'feature_comparison.html')
1079
+ html_out_path = File.join(@root_dir, 'run', @scenario_name.downcase, 'feature_comparison.html')
948
1080
  FileUtils.cp(html_in_path, html_out_path)
949
1081
  puts "\nDone\n"
950
1082
  end
@@ -966,8 +1098,8 @@ module URBANopt
966
1098
  feature_ids = CSV.read(@opthash.subopts[:scenario], headers: true)
967
1099
  feature_list = []
968
1100
  feature_ids['Feature Id'].each do |feature|
969
- if Dir.exist?(File.join(@root_dir, 'run', @scenario_name, feature))
970
- feature_list << File.join(@root_dir, 'run', @scenario_name, feature)
1101
+ if Dir.exist?(File.join(@root_dir, 'run', @scenario_name.downcase, feature))
1102
+ feature_list << File.join(@root_dir, 'run', @scenario_name.downcase, feature)
971
1103
  else
972
1104
  puts "Warning: did not find a directory for FeatureID: #{feature} ...skipping"
973
1105
  end
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/bin/bash
2
2
  # This is a simple setup script that generates an enviroment file that
3
3
  # is used to setup the ruby enviroment to run the urbanopt-cli tool.
4
4
  # To use, just run this script in bash (e.g. ./setup-env.sh)
@@ -8,9 +8,9 @@
8
8
 
9
9
  BASE_DIR_NAME=$(dirname `which $0`)
10
10
 
11
- GEM_HOME=${BASE_DIR_NAME}/gems/ruby/2.5.0
12
- GEM_PATH=${BASE_DIR_NAME}/gems/ruby/2.5.0
13
- PATH=${BASE_DIR_NAME}/ruby/bin:${BASE_DIR_NAME}/gems/ruby/2.5.0/bin:$PATH
11
+ GEM_HOME=${BASE_DIR_NAME}/gems/ruby/2.7.0
12
+ GEM_PATH=${BASE_DIR_NAME}/gems/ruby/2.7.0
13
+ PATH=${BASE_DIR_NAME}/ruby/bin:${BASE_DIR_NAME}/gems/ruby/2.7.0/bin:$PATH
14
14
  RUBYLIB=${BASE_DIR_NAME}/OpenStudio/Ruby
15
15
  RUBY_DLL_PATH=${BASE_DIR_NAME}/OpenStudio/Ruby
16
16
 
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/bin/bash
2
2
  # This is a simple setup script that generates an enviroment file that
3
3
  # is used to setup the ruby enviroment to run the urbanopt-cli tool.
4
4
  # To use, just run this script in bash (e.g. ./setup-env.sh)
@@ -7,9 +7,9 @@
7
7
 
8
8
  BASE_DIR_NAME="$(cd "$(dirname "$0")" && pwd)"
9
9
 
10
- GEM_HOME=${BASE_DIR_NAME}/gems/ruby/2.5.0
11
- GEM_PATH=${BASE_DIR_NAME}/gems/ruby/2.5.0
12
- PATH=${BASE_DIR_NAME}/ruby/bin:${BASE_DIR_NAME}/gems/ruby/2.5.0/bin:$PATH
10
+ GEM_HOME=${BASE_DIR_NAME}/gems/ruby/2.7.0
11
+ GEM_PATH=${BASE_DIR_NAME}/gems/ruby/2.7.0
12
+ PATH=${BASE_DIR_NAME}/ruby/bin:${BASE_DIR_NAME}/gems/ruby/2.7.0/bin:$PATH
13
13
  RUBYLIB=${BASE_DIR_NAME}/OpenStudio/Ruby
14
14
  RUBY_DLL_PATH=${BASE_DIR_NAME}/OpenStudio/Ruby
15
15
 
@@ -3,9 +3,9 @@ IF "%HOMEPATH%"=="" exit /B
3
3
 
4
4
  SET BASE_DIR_NAME=%~d0%~p0
5
5
 
6
- SET GEM_HOME=%BASE_DIR_NAME%\gems\ruby\2.5.0
7
- SET GEM_PATH=%BASE_DIR_NAME%\gems\ruby\2.5.0
8
- SET PATH=%BASE_DIR_NAME%\ruby\bin;%BASE_DIR_NAME%\gems\ruby\2.5.0\bin;%PATH%
6
+ SET GEM_HOME=%BASE_DIR_NAME%\gems\ruby\2.7.0
7
+ SET GEM_PATH=%BASE_DIR_NAME%\gems\ruby\2.7.0
8
+ SET PATH=%BASE_DIR_NAME%\ruby\bin;%BASE_DIR_NAME%\gems\ruby\2.7.0\bin;%PATH%
9
9
  SET RUBYLIB=%BASE_DIR_NAME%\OpenStudio\Ruby
10
10
  SET RUBY_DLL_PATH=%BASE_DIR_NAME%\OpenStudio\Ruby
11
11