urbanopt-cli 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/CHANGELOG.md +20 -0
- data/CMakeLists.txt +10 -10
- data/FindOpenStudioSDK.cmake +6 -6
- data/Gemfile +9 -9
- data/example_files/Gemfile +3 -3
- data/example_files/example_project.json +35 -20
- data/example_files/example_project_with_electric_network.json +2116 -0
- data/example_files/mappers/Baseline.rb +4 -1
- data/example_files/mappers/EvCharging.rb +131 -0
- data/example_files/mappers/base_workflow.osw +26 -1
- data/example_files/validation_schema.yaml +149 -0
- data/example_files/visualization/input_visualization_feature.html +213 -56
- data/example_files/visualization/input_visualization_scenario.html +92 -30
- data/lib/uo_cli.rb +204 -90
- data/lib/uo_cli/version.rb +1 -1
- data/uo_cli.gemspec +4 -6
- metadata +15 -27
- data/developer_nrel_key.rb +0 -31
@@ -0,0 +1,131 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt™, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
require 'urbanopt/reporting'
|
32
|
+
require 'openstudio/common_measures'
|
33
|
+
require 'openstudio/model_articulation'
|
34
|
+
|
35
|
+
require_relative 'HighEfficiency'
|
36
|
+
|
37
|
+
require 'json'
|
38
|
+
|
39
|
+
module URBANopt
|
40
|
+
module Scenario
|
41
|
+
class EvChargingMapper < HighEfficiencyMapper
|
42
|
+
def create_osw(scenario, features, feature_names)
|
43
|
+
osw = super(scenario, features, feature_names)
|
44
|
+
|
45
|
+
feature = features[0]
|
46
|
+
|
47
|
+
def ev_charging_type(building_type)
|
48
|
+
typical_home = ['Single-Family', 'Multifamily (2 to 4 units)', 'Multifamily (5 or more units)', 'Lodging']
|
49
|
+
typical_public = ['Public assembly', 'Strip shopping mall', 'Enclosed mall', 'Retail other than mall', 'Food service', 'Nonrefrigerated warehouse', 'Food sales', 'Refrigerated warehouse', 'Religious worship', 'Service', 'Public order and safety', 'Uncovered Parking', 'Covered Parking']
|
50
|
+
typical_work = ['Office', 'Laboratory', 'Education', 'Inpatient health care', 'Outpatient health care', 'Nursing']
|
51
|
+
|
52
|
+
if typical_home.include? building_type
|
53
|
+
return 'Typical Home'
|
54
|
+
elsif typical_public.include? building_type
|
55
|
+
return 'Typical Public'
|
56
|
+
elsif typical_work.include? building_type
|
57
|
+
return 'Typical Work'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# add EV loads
|
62
|
+
ev_charging = nil
|
63
|
+
|
64
|
+
begin
|
65
|
+
ev_charging = feature.ev_charging
|
66
|
+
rescue
|
67
|
+
end
|
68
|
+
|
69
|
+
if ev_charging != true
|
70
|
+
puts "Please set ev_charging to true to add EV loads."
|
71
|
+
elsif ev_charging == true
|
72
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ev_load', '__SKIP__', false)
|
73
|
+
begin
|
74
|
+
ev_charging_station_type = feature.ev_charging_station_type
|
75
|
+
rescue
|
76
|
+
end
|
77
|
+
if !ev_charging_station_type.nil? && !ev_charging_station_type.empty?
|
78
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ev_load', 'chg_station_type', ev_charging_station_type)
|
79
|
+
else
|
80
|
+
building_type = feature.building_type
|
81
|
+
# For mixed use building ev_charging_station_type must be specified
|
82
|
+
if building_type == 'Mixed use'
|
83
|
+
puts "Specify the ev_charging_station_type for the Feature, add_ev_load measure not applied."
|
84
|
+
else
|
85
|
+
ev_charging_station_type = ev_charging_type(building_type)
|
86
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ev_load', 'chg_station_type', ev_charging_station_type)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
begin
|
91
|
+
if ev_charging_station_type == 'Typical Work'
|
92
|
+
delay_type = feature.delay_type
|
93
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ev_load', 'delay_type', delay_type)
|
94
|
+
end
|
95
|
+
rescue
|
96
|
+
end
|
97
|
+
|
98
|
+
begin
|
99
|
+
ev_charging_behavior = feature.ev_charging_behavior
|
100
|
+
if !ev_charging_behavior.nil? && !ev_charging_behavior.empty?
|
101
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ev_load', 'charge_behavior', ev_charging_behavior)
|
102
|
+
end
|
103
|
+
rescue
|
104
|
+
end
|
105
|
+
|
106
|
+
begin
|
107
|
+
ev_percent = feature.ev_percent
|
108
|
+
if !ev_percent.nil? && !ev_percent.empty?
|
109
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ev_load', 'ev_percent', ev_percent)
|
110
|
+
end
|
111
|
+
rescue
|
112
|
+
end
|
113
|
+
|
114
|
+
#Add EMS Control to EV charging only if ev_charging is true
|
115
|
+
begin
|
116
|
+
ev_curtailment_frac = feature.ev_curtailment_frac
|
117
|
+
rescue
|
118
|
+
end
|
119
|
+
|
120
|
+
if !ev_curtailment_frac.nil?
|
121
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ems_to_control_ev_charging', '__SKIP__', false)
|
122
|
+
OpenStudio::Extension.set_measure_argument(osw, 'add_ems_to_control_ev_charging', 'curtailment_frac', ev_curtailment_frac)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
return osw
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -60,6 +60,21 @@
|
|
60
60
|
"__SKIP__":true,
|
61
61
|
"blend_method":"Building Story"
|
62
62
|
}
|
63
|
+
},{
|
64
|
+
"measure_dir_name": "add_ev_load",
|
65
|
+
"arguments": {
|
66
|
+
"__SKIP__": true,
|
67
|
+
"chg_station_type": "Typical Public",
|
68
|
+
"delay_type": "Min Delay",
|
69
|
+
"charge_behavior": "Business as Usual",
|
70
|
+
"ev_percent": 100
|
71
|
+
}
|
72
|
+
},{
|
73
|
+
"measure_dir_name": "add_ems_to_control_ev_charging",
|
74
|
+
"arguments": {
|
75
|
+
"__SKIP__": true,
|
76
|
+
"curtailment_frac": 0.5
|
77
|
+
}
|
63
78
|
},{
|
64
79
|
"measure_dir_name":"urban_geometry_creation_zoning",
|
65
80
|
"arguments":{
|
@@ -130,6 +145,16 @@
|
|
130
145
|
"size_mult":"0.75",
|
131
146
|
"charge_start":"23:00"
|
132
147
|
}
|
148
|
+
},{
|
149
|
+
"measure_dir_name":"export_time_series_modelica",
|
150
|
+
"arguments":{
|
151
|
+
"__SKIP__":false
|
152
|
+
}
|
153
|
+
},{
|
154
|
+
"measure_dir_name":"export_modelica_loads",
|
155
|
+
"arguments":{
|
156
|
+
"__SKIP__":false
|
157
|
+
}
|
133
158
|
},{
|
134
159
|
"measure_dir_name":"default_feature_reports",
|
135
160
|
"arguments":{
|
@@ -142,4 +167,4 @@
|
|
142
167
|
],
|
143
168
|
"name":null,
|
144
169
|
"description":null
|
145
|
-
}
|
170
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# General bounds for expected EUI values
|
2
|
+
# Commercial building reference: https://portfoliomanager.energystar.gov/pdf/reference/US%20National%20Median%20Table.pdf
|
3
|
+
# Residential building reference: https://www.eia.gov/consumption/residential/data/2015/c&e/pdf/ce1.1.pdf
|
4
|
+
# Converting between SI & Imperial EUI units: https://eddysantosa.com/eui/
|
5
|
+
# You may adjust these values for the <building_type>s in your FeatureFile. The references above may be useful guidelines
|
6
|
+
EUI:
|
7
|
+
IP:
|
8
|
+
Units: "kBtu/ft2/yr"
|
9
|
+
Single-Family Detached:
|
10
|
+
min: 10
|
11
|
+
max: 60
|
12
|
+
Single-Family Attached:
|
13
|
+
min: 10
|
14
|
+
max: 60
|
15
|
+
Multifamily (2 to 4 units):
|
16
|
+
min: 20
|
17
|
+
max: 75
|
18
|
+
Multifamily (5 or more units):
|
19
|
+
min: 10
|
20
|
+
max: 60
|
21
|
+
Office:
|
22
|
+
min: 40
|
23
|
+
max: 75
|
24
|
+
Laboratory:
|
25
|
+
min: 100
|
26
|
+
max: 150
|
27
|
+
Nonrefrigerated warehouse:
|
28
|
+
min: 10
|
29
|
+
max: 40
|
30
|
+
Food sales:
|
31
|
+
min: 50
|
32
|
+
max: 250
|
33
|
+
Public order and safety:
|
34
|
+
min: 40
|
35
|
+
max: 75
|
36
|
+
Outpatient health care:
|
37
|
+
min: 50
|
38
|
+
max: 100
|
39
|
+
Refrigerated warehouse:
|
40
|
+
min: 75
|
41
|
+
max: 100
|
42
|
+
Religious worship:
|
43
|
+
min: 20
|
44
|
+
max: 40
|
45
|
+
Public assembly:
|
46
|
+
min: 40
|
47
|
+
max: 60
|
48
|
+
Education:
|
49
|
+
min: 40
|
50
|
+
max: 100
|
51
|
+
Food service:
|
52
|
+
min: 200
|
53
|
+
max: 500
|
54
|
+
Inpatient health care:
|
55
|
+
min: 200
|
56
|
+
max: 300
|
57
|
+
Nursing:
|
58
|
+
min: 50
|
59
|
+
max: 100
|
60
|
+
Lodging:
|
61
|
+
min: 50
|
62
|
+
max: 100
|
63
|
+
Strip shopping mall:
|
64
|
+
min: 80
|
65
|
+
max: 120
|
66
|
+
Enclosed mall:
|
67
|
+
min: 50
|
68
|
+
max: 75
|
69
|
+
Retail other than mall:
|
70
|
+
min: 40
|
71
|
+
max: 75
|
72
|
+
Service:
|
73
|
+
min: 30
|
74
|
+
max: 75
|
75
|
+
Mixed use:
|
76
|
+
min: 10
|
77
|
+
max: 75
|
78
|
+
|
79
|
+
SI:
|
80
|
+
Units: "kWh/m2/yr"
|
81
|
+
Single-Family Detached:
|
82
|
+
min: 30
|
83
|
+
max: 200
|
84
|
+
Single-Family Attached:
|
85
|
+
min: 30
|
86
|
+
max: 200
|
87
|
+
Multifamily (2 to 4 units):
|
88
|
+
min: 63
|
89
|
+
max: 237
|
90
|
+
Multifamily (5 or more units):
|
91
|
+
min: 30
|
92
|
+
max: 200
|
93
|
+
Office:
|
94
|
+
min: 126
|
95
|
+
max: 237
|
96
|
+
Laboratory:
|
97
|
+
min: 315
|
98
|
+
max: 475
|
99
|
+
Nonrefrigerated warehouse:
|
100
|
+
min: 31
|
101
|
+
max: 126
|
102
|
+
Food sales:
|
103
|
+
min: 157
|
104
|
+
max: 789
|
105
|
+
Public order and safety:
|
106
|
+
min: 126
|
107
|
+
max: 237
|
108
|
+
Outpatient health care:
|
109
|
+
min: 157
|
110
|
+
max: 315
|
111
|
+
Refrigerated warehouse:
|
112
|
+
min: 236
|
113
|
+
max: 315
|
114
|
+
Religious worship:
|
115
|
+
min: 63
|
116
|
+
max: 126
|
117
|
+
Public assembly:
|
118
|
+
min: 126
|
119
|
+
max: 190
|
120
|
+
Education:
|
121
|
+
min: 126
|
122
|
+
max: 315
|
123
|
+
Food service:
|
124
|
+
min: 630
|
125
|
+
max: 1577
|
126
|
+
Inpatient health care:
|
127
|
+
min: 630
|
128
|
+
max: 946
|
129
|
+
Nursing:
|
130
|
+
min: 157
|
131
|
+
max: 315
|
132
|
+
Lodging:
|
133
|
+
min: 157
|
134
|
+
max: 315
|
135
|
+
Strip shopping mall:
|
136
|
+
min: 252
|
137
|
+
max: 379
|
138
|
+
Enclosed mall:
|
139
|
+
min: 157
|
140
|
+
max: 237
|
141
|
+
Retail other than mall:
|
142
|
+
min: 126
|
143
|
+
max: 237
|
144
|
+
Service:
|
145
|
+
min: 94
|
146
|
+
max: 237
|
147
|
+
Mixed use:
|
148
|
+
min: 31
|
149
|
+
max: 789
|
@@ -32,6 +32,10 @@
|
|
32
32
|
color: red;
|
33
33
|
}
|
34
34
|
|
35
|
+
.button-pad {
|
36
|
+
padding:5px 15px;
|
37
|
+
}
|
38
|
+
|
35
39
|
nvd3 {
|
36
40
|
display: block;
|
37
41
|
width: 100%;
|
@@ -154,6 +158,7 @@
|
|
154
158
|
<div ng-controller="MyAppCtrl" class="container">
|
155
159
|
|
156
160
|
<h1>Features</h1>
|
161
|
+
<md-button class="button-pad md-raised md-primary" ng-click="toggleAxes()">Toggle Y-Axis Ranges</md-button>
|
157
162
|
|
158
163
|
<h2>Monthly Fuel Use</h2>
|
159
164
|
<md-content class="md-padding" layout-sm="column" layout="row" layout-wrap>
|
@@ -167,7 +172,7 @@
|
|
167
172
|
</md-card-title-text>
|
168
173
|
</md-card-title>
|
169
174
|
<md-card-content>
|
170
|
-
<nvd3 class="h-320 remove-x-lines" options="monthlyFuelChartOptions" data="monthlyFuelChartData[feature.name]"></nvd3>
|
175
|
+
<nvd3 class="h-320 remove-x-lines" options="monthlyFuelChartOptions[feature.name]" data="monthlyFuelChartData[feature.name]"></nvd3>
|
171
176
|
</md-card-content>
|
172
177
|
</md-card>
|
173
178
|
</div>
|
@@ -181,13 +186,14 @@
|
|
181
186
|
<md-card-title-text>
|
182
187
|
<span class="md-headline">{{ feature.name }}</span>
|
183
188
|
<span class="md-subhead">Annual Net Energy - {{
|
184
|
-
annualNetChartData[feature.name] }}
|
185
|
-
|
189
|
+
annualNetChartData[feature.name] }}
|
190
|
+
</span>
|
191
|
+
<span class="md-subhead">Monthly Net Energy </span>
|
186
192
|
<span ng-if="feature.complete_simulation!=true" class="md-subhead error">{{errorText}}</span>
|
187
193
|
</md-card-title-text>
|
188
194
|
</md-card-title>
|
189
195
|
<md-card-content>
|
190
|
-
<nvd3 class="h-320 remove-x-lines" options="monthlyNetChartOptions" data="monthlyNetChartData[feature.name]"></nvd3>
|
196
|
+
<nvd3 class="h-320 remove-x-lines" options="monthlyNetChartOptions[feature.name]" data="monthlyNetChartData[feature.name]"></nvd3>
|
191
197
|
</md-card-content>
|
192
198
|
</md-card>
|
193
199
|
</div>
|
@@ -205,7 +211,7 @@
|
|
205
211
|
</md-card-title-text>
|
206
212
|
</md-card-title>
|
207
213
|
<md-card-content>
|
208
|
-
<nvd3 class="h-420 remove-x-lines" options="annualEndUseChartOptions" data="annualEndUseChartData[feature.name]"></nvd3>
|
214
|
+
<nvd3 class="h-420 remove-x-lines" options="annualEndUseChartOptions[feature.name]" data="annualEndUseChartData[feature.name]"></nvd3>
|
209
215
|
</md-card-content>
|
210
216
|
</md-card>
|
211
217
|
</div>
|
@@ -225,10 +231,10 @@
|
|
225
231
|
myApp.controller('MyAppCtrl', function ($scope) {
|
226
232
|
$scope.features = scenarioData;
|
227
233
|
|
228
|
-
$scope.
|
234
|
+
$scope.defaultMonthlyFuelChartOptions = {
|
229
235
|
chart: {
|
230
236
|
type: 'multiBarChart',
|
231
|
-
color: ['#187C7C', '#8CC025', '#CE2828'],
|
237
|
+
color: ['#187C7C', '#8CC025', '#CE2828', '#AFECE7', '#F19953'],
|
232
238
|
height: 320,
|
233
239
|
margin: {
|
234
240
|
top: 45,
|
@@ -272,7 +278,7 @@
|
|
272
278
|
}
|
273
279
|
};
|
274
280
|
|
275
|
-
$scope.
|
281
|
+
$scope.defaultMonthlyNetChartOptions = {
|
276
282
|
chart: {
|
277
283
|
type: 'multiBarChart',
|
278
284
|
color: ['#014D4D'],
|
@@ -319,7 +325,7 @@
|
|
319
325
|
}
|
320
326
|
};
|
321
327
|
|
322
|
-
$scope.
|
328
|
+
$scope.defaultAnnualEndUseChartOptions = {
|
323
329
|
chart: {
|
324
330
|
type: 'multiBarChart',
|
325
331
|
// color: ['#014D4D'],
|
@@ -370,11 +376,17 @@
|
|
370
376
|
}
|
371
377
|
};
|
372
378
|
|
379
|
+
// use different options for each feature
|
380
|
+
$scope.monthlyFuelChartOptions = {};
|
381
|
+
$scope.monthlyNetChartOptions = {};
|
382
|
+
$scope.annualEndUseChartOptions = {};
|
383
|
+
|
373
384
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
374
385
|
|
375
|
-
var datasets = ['Electricity:Facility', 'ElectricityProduced:Facility', '
|
386
|
+
var datasets = ['Electricity:Facility', 'ElectricityProduced:Facility', 'NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
|
387
|
+
|
388
|
+
var endUseKeys = ['Heating:Electricity', 'Cooling:Electricity', 'InteriorLights:Electricity', 'ExteriorLights:Electricity', 'ExteriorEquipment:Electricity', 'InteriorEquipment:Electricity', 'Fans:Electricity', 'Pumps:Electricity', 'HeatRejection:Electricity', 'WaterSystems:Electricity'];
|
376
389
|
|
377
|
-
var endUseKeys = ['Heating:Electricity', 'Cooling:Electricity', 'InteriorLights:Electricity', 'ExteriorLights:Electricity', 'InteriorEquipment:Electricity', 'Fans:Electricity', 'Pumps:Electricity', 'HeatRejection:Electricity', 'WaterSystems:Electricity'];
|
378
390
|
|
379
391
|
var applicableEndUseKeys = [];
|
380
392
|
|
@@ -383,12 +395,18 @@
|
|
383
395
|
$scope.annualNetChartData = {};
|
384
396
|
|
385
397
|
$scope.annualEndUseChartData = {};
|
386
|
-
|
398
|
+
|
399
|
+
// calculate global maximums across features
|
387
400
|
var monthlyFuelYMax = 0;
|
388
401
|
var monthlyNetYMin = 0;
|
389
402
|
var monthlyNetYMax = 0;
|
390
|
-
|
391
403
|
var annualTotalYMax = 0;
|
404
|
+
|
405
|
+
// also record totals per feature
|
406
|
+
$scope.annualEndUseTotals = {};
|
407
|
+
$scope.monthlyFuelTotals = {};
|
408
|
+
$scope.monthlyNetTotals = {};
|
409
|
+
|
392
410
|
$scope.errorText = "No data. This feature either did not complete successfully or did not include an annual simulation ranging from January 1 to December 31.";
|
393
411
|
|
394
412
|
// figure out max total energy use and applicable end uses
|
@@ -398,65 +416,150 @@
|
|
398
416
|
|
399
417
|
_.forEach(endUseKeys, function (endUseKey) {
|
400
418
|
var endUseValue = feature.annual_values[endUseKey];
|
401
|
-
//console.log("endUseKey: ", endUseKey, "endUseValue: ", endUseValue);
|
419
|
+
// console.log("endUseKey: ", endUseKey, "endUseValue: ", endUseValue);
|
402
420
|
|
403
421
|
if (endUseValue == 0 || !endUseValue) {
|
404
422
|
console.log("no data found for: ", endUseKey);
|
405
423
|
}
|
406
424
|
else {
|
407
425
|
applicableEndUseKeys.push(endUseKey);
|
408
|
-
total_value += endUseValue
|
426
|
+
total_value += endUseValue;
|
409
427
|
}
|
410
428
|
});
|
429
|
+
// global maximum
|
411
430
|
annualTotalYMax = _.max([annualTotalYMax, total_value]);
|
431
|
+
|
412
432
|
});
|
413
433
|
|
414
434
|
applicableEndUseKeys = _.uniq(applicableEndUseKeys).sort();
|
415
435
|
|
416
|
-
|
436
|
+
// store global default
|
437
|
+
$scope.defaultAnnualEndUseChartOptions.chart['yDomain'] = [0, _.round(annualTotalYMax)];
|
438
|
+
|
417
439
|
// gather data for each feature
|
418
440
|
_.forEach($scope.features, function (feature) {
|
419
441
|
|
442
|
+
// calculate local maximums per feature
|
443
|
+
var localFuelYMax = 0;
|
444
|
+
var localNetYMax = 0;
|
445
|
+
var localNetYMin = 100000000;
|
446
|
+
var localEndUseMax = 0;
|
447
|
+
|
420
448
|
if(feature['complete_simulation'] == true){
|
449
|
+
|
421
450
|
// monthly fuel use
|
422
451
|
$scope.monthlyFuelChartData[feature.name] = [];
|
452
|
+
var changeToKbtu = false;
|
453
|
+
var kbtu_datasets = ['NaturalGas:Facility', 'Propane:Facility', 'FuelOilNo2:Facility', 'OtherFuels:Facility'];
|
454
|
+
// first iterate through all kbtu datasets to see if you'll need to change to kBtu units
|
455
|
+
_.forEach(kbtu_datasets, function (kbtu_dataset) {
|
456
|
+
var values = feature.monthly_values[kbtu_dataset];
|
457
|
+
if (!(values.every(item => item === 0))) {
|
458
|
+
changeToKbtu = true;
|
459
|
+
}
|
460
|
+
});
|
461
|
+
|
423
462
|
_.forEach(datasets, function (dataset) {
|
463
|
+
|
424
464
|
var values = feature.monthly_values[dataset];
|
465
|
+
var datasetUnit = "";
|
466
|
+
|
425
467
|
if (dataset == 'Electricity:Facility') {
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
}
|
441
|
-
}
|
442
|
-
})
|
468
|
+
// first check if there is data to include
|
469
|
+
if (!(values.every(item => item === 0))) {
|
470
|
+
console.log(changeToKbtu);
|
471
|
+
if (changeToKbtu) {
|
472
|
+
var kBtuValues = [];
|
473
|
+
var kwhValues = feature.monthly_values[dataset]
|
474
|
+
_.forEach(kwhValues, function (kwhValue) {
|
475
|
+
new_value = kwhValue*3.4121416; //convert kwh to kbtu
|
476
|
+
kBtuValues.push(new_value);
|
477
|
+
})
|
478
|
+
values = kBtuValues;
|
479
|
+
datasetUnit = 'Electricity:Facility(kBtu)';
|
480
|
+
} else {
|
481
|
+
datasetUnit = 'Electricity:Facility(kWh)';
|
482
|
+
}
|
483
|
+
}
|
484
|
+
} else if (dataset == 'ElectricityProduced:Facility') {
|
485
|
+
// first check if there is data to include
|
486
|
+
if (!(values.every(item => item === 0))) {
|
487
|
+
if (changeToKbtu) {
|
488
|
+
var kBtuValues = [];
|
489
|
+
var kwhValues = feature.monthly_values[dataset];
|
490
|
+
_.forEach(kwhValues, function (kwhValue) {
|
491
|
+
new_value = kwhValue*3.4121416; //convert kwh to kbtu
|
492
|
+
kBtuValues.push(new_value);
|
493
|
+
})
|
494
|
+
values = kBtuValues;
|
495
|
+
datasetUnit = 'ElectricityProduced:Facility(kBtu)';
|
496
|
+
|
497
|
+
} else {
|
498
|
+
datasetUnit = 'ElectricityProduced:Facility(kWh)'
|
499
|
+
}
|
500
|
+
}
|
501
|
+
} else {
|
502
|
+
// everything else gets kBtu for now
|
503
|
+
if (!(values.every(item => item === 0))) {
|
504
|
+
datasetUnit = dataset + '(kBtu)';
|
505
|
+
}
|
506
|
+
};
|
507
|
+
// if datasetUnit is empty string, there is no data so don't push it in the array
|
508
|
+
if (datasetUnit != ""){
|
509
|
+
$scope.monthlyFuelChartData[feature.name].push({
|
510
|
+
key: datasetUnit,
|
511
|
+
values: _.map(values, function (value, i) {
|
512
|
+
value;
|
513
|
+
// global
|
514
|
+
monthlyFuelYMax = _.max([monthlyFuelYMax, value]);
|
515
|
+
// local
|
516
|
+
localFuelYMax = _.max([localFuelYMax, value]);
|
517
|
+
return {
|
518
|
+
x: months[i],
|
519
|
+
y: value
|
520
|
+
};
|
521
|
+
})
|
522
|
+
});
|
523
|
+
}
|
443
524
|
});
|
444
|
-
|
525
|
+
// calculate both the global (default) max and the per-feature max
|
526
|
+
$scope.monthlyFuelTotals[feature.name] = _.round(localFuelYMax);
|
527
|
+
$scope.defaultMonthlyFuelChartOptions.chart['yDomain'] = [0, _.round(monthlyFuelYMax)];
|
445
528
|
}
|
446
529
|
|
447
530
|
// monthly net use
|
448
|
-
|
449
531
|
if(feature['complete_simulation'] == true){
|
450
532
|
$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
|
+
}
|
538
|
+
if (changeToKbtu){
|
539
|
+
var unit = ' (kBtu)'
|
540
|
+
}
|
541
|
+
else {
|
542
|
+
var unit = ' (kWh)'
|
543
|
+
}
|
544
|
+
|
451
545
|
$scope.annualNetChartData[feature.name] = 0;
|
452
546
|
$scope.monthlyNetChartData[feature.name].push({
|
453
|
-
key: 'Net Energy Use',
|
547
|
+
key: 'Net Energy Use' + unit,
|
454
548
|
values: _.map(months, function (month, i) {
|
455
|
-
|
549
|
+
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
|
551
|
+
}
|
552
|
+
else {
|
553
|
+
var value = feature.monthly_values['Electricity:Facility'][i] - feature.monthly_values['ElectricityProduced:Facility'][i]; //Values are in kWh
|
554
|
+
}
|
456
555
|
value;
|
457
556
|
$scope.annualNetChartData[feature.name] += value;
|
557
|
+
// global
|
458
558
|
monthlyNetYMin = _.min([monthlyNetYMin, value]);
|
459
559
|
monthlyNetYMax = _.max([monthlyNetYMax, value]);
|
560
|
+
// local
|
561
|
+
localNetYMax = _.max([localNetYMax, value]);
|
562
|
+
localNetYMin = _.min([localNetYMin, value]);
|
460
563
|
return {
|
461
564
|
x: month,
|
462
565
|
y: value
|
@@ -464,32 +567,86 @@
|
|
464
567
|
})
|
465
568
|
});
|
466
569
|
$scope.annualNetChartData[feature.name] = _.round($scope.annualNetChartData[feature.name]);
|
467
|
-
|
570
|
+
// calculate global range and local range
|
571
|
+
$scope.monthlyNetTotals[feature.name] = [_.round(localNetYMin), _.round(localNetYMax)];
|
572
|
+
$scope.defaultMonthlyNetChartOptions.chart['yDomain'] = [_.round(monthlyNetYMin), _.round(monthlyNetYMax)];
|
468
573
|
}
|
469
574
|
|
470
575
|
// annual end use
|
471
|
-
if(feature['complete_simulation'] == true){
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
576
|
+
if(feature['complete_simulation'] == true) {
|
577
|
+
$scope.annualEndUseChartData[feature.name] = [];
|
578
|
+
// Find all applicable end uses
|
579
|
+
_.forEach(applicableEndUseKeys, function (endUseKey){
|
580
|
+
var endUseValue = feature.annual_values[endUseKey]
|
581
|
+
|
582
|
+
localEndUseMax += endUseValue
|
583
|
+
// console.log("endUseKey: ", endUseKey, " endUseValue: ", endUseValue);
|
584
|
+
|
585
|
+
$scope.annualEndUseChartData[feature.name].push({
|
586
|
+
key: endUseKey,
|
587
|
+
values: [{
|
588
|
+
x: 'End Use',
|
589
|
+
y: endUseValue
|
590
|
+
}]
|
591
|
+
});
|
592
|
+
|
485
593
|
});
|
486
|
-
|
487
|
-
|
488
|
-
|
594
|
+
|
595
|
+
// also store local maximum for each feature
|
596
|
+
$scope.annualEndUseTotals[feature.name] = _.round(localEndUseMax);
|
597
|
+
|
489
598
|
}
|
490
599
|
});
|
600
|
+
|
601
|
+
// assign chart options for each feature. assign global maximum to start
|
602
|
+
_.forEach($scope.features, function (feature) {
|
603
|
+
$scope.monthlyFuelChartOptions[feature.name] = _.cloneDeep($scope.defaultMonthlyFuelChartOptions);
|
604
|
+
$scope.monthlyNetChartOptions[feature.name] = _.cloneDeep($scope.defaultMonthlyNetChartOptions);
|
605
|
+
$scope.annualEndUseChartOptions[feature.name] = _.cloneDeep($scope.defaultAnnualEndUseChartOptions);
|
606
|
+
|
491
607
|
});
|
492
|
-
|
608
|
+
|
609
|
+
// console.log("LOCAL MAXES:");
|
610
|
+
// console.log($scope.annualEndUseTotals);
|
611
|
+
// console.log($scope.monthlyFuelTotals);
|
612
|
+
// console.log($scope.monthlyNetTotals);
|
613
|
+
// console.log("GLOBAL MAXES:");
|
614
|
+
// console.log(annualTotalYMax);
|
615
|
+
// console.log(monthlyNetYMin, monthlyNetYMax);
|
616
|
+
// console.log(monthlyFuelYMax);
|
617
|
+
// console.log("OPTIONS:")
|
618
|
+
// console.log($scope.annualEndUseChartOptions);
|
619
|
+
// console.log($scope.monthlyFuelChartOptions);
|
620
|
+
// console.log($scope.monthlyNetChartOptions);
|
621
|
+
|
622
|
+
// change Y axes from global maximum to local maximum
|
623
|
+
$scope.axes = 0;
|
624
|
+
|
625
|
+
$scope.toggleAxes = function () {
|
626
|
+
|
627
|
+
if ($scope.axes == 0) {
|
628
|
+
|
629
|
+
// change axis
|
630
|
+
_.forEach($scope.features, function (feature) {
|
631
|
+
$scope.monthlyFuelChartOptions[feature.name].chart['yDomain'] = [0, $scope.monthlyFuelTotals[feature.name]];
|
632
|
+
$scope.monthlyNetChartOptions[feature.name].chart['yDomain'] = $scope.monthlyNetTotals[feature.name];
|
633
|
+
$scope.annualEndUseChartOptions[feature.name].chart['yDomain'] = [0, $scope.annualEndUseTotals[feature.name]];
|
634
|
+
});
|
635
|
+
|
636
|
+
$scope.axes = 1;
|
637
|
+
|
638
|
+
} else {
|
639
|
+
|
640
|
+
_.forEach($scope.features, function (feature) {
|
641
|
+
$scope.monthlyFuelChartOptions[feature.name].chart['yDomain'] = _.cloneDeep($scope.defaultMonthlyFuelChartOptions.chart['yDomain']);
|
642
|
+
$scope.monthlyNetChartOptions[feature.name].chart['yDomain'] = _.cloneDeep($scope.defaultMonthlyNetChartOptions.chart['yDomain']);
|
643
|
+
$scope.annualEndUseChartOptions[feature.name].chart['yDomain'] = _.cloneDeep($scope.defaultAnnualEndUseChartOptions.chart['yDomain']);
|
644
|
+
});
|
645
|
+
$scope.axes = 0;
|
646
|
+
}
|
647
|
+
};
|
648
|
+
|
649
|
+
});
|
493
650
|
|
494
651
|
_.delay(function () {
|
495
652
|
window.dispatchEvent(new Event('resize'));
|