urbanopt-reporting 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/measures/default_feature_reports/measure.rb +73 -7
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +7 -1
- data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +3 -1
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +22 -3
- data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +111 -0
- data/lib/urbanopt/reporting/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eae158ffc7f5239454037c578719bc38263a2991b0597ea1654ff682c875dbf0
|
4
|
+
data.tar.gz: 83f93741c0f85426fd02132cc57c245b1f38967f1e4f02712447c8c0ad8e4ca6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffcc7a5f81d1bc56569a74cfecfc14593125faacede9f5e52256a568392eec8cb0a8e02d0ba2ce4ae3f9d4d52f7d00cf60720f30d7d66b2a8d38dcef898e0cac
|
7
|
+
data.tar.gz: 685fcf61b239616865a48b4cdf1f3179f246b07fceeed4be9f240dee44eefba3fac32b4b52afeb564675873a5bef5eb72a60a3b64b411e151b21eb7b5423ba5b
|
data/CHANGELOG.md
CHANGED
@@ -71,6 +71,11 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
71
71
|
feature_type.setDefaultValue('Building')
|
72
72
|
args << feature_type
|
73
73
|
|
74
|
+
feature_location = OpenStudio::Measure::OSArgument.makeStringArgument('feature_location', false)
|
75
|
+
feature_location.setDisplayName('URBANopt Feature Location')
|
76
|
+
feature_location.setDefaultValue('0')
|
77
|
+
args << feature_location
|
78
|
+
|
74
79
|
# make an argument for the frequency
|
75
80
|
reporting_frequency_chs = OpenStudio::StringVector.new
|
76
81
|
reporting_frequency_chs << 'Detailed'
|
@@ -193,6 +198,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
193
198
|
'District Heating Inlet Temperature', 'District Heating Outlet Temperature', 'Cooling Coil Total Cooling Rate',
|
194
199
|
'Heating Coil Heating Rate']
|
195
200
|
|
201
|
+
tes_timeseries_data = ['Ice Thermal Storage End Fraction', 'Cooling coil Ice Thermal Storage End Fraction']
|
202
|
+
timeseries_data += tes_timeseries_data
|
203
|
+
|
196
204
|
timeseries_data.each do |ts|
|
197
205
|
result << OpenStudio::IdfObject.load("Output:Variable,*,#{ts},#{reporting_frequency};").get
|
198
206
|
end
|
@@ -254,6 +262,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
254
262
|
feature_id = runner.getStringArgumentValue('feature_id', user_arguments)
|
255
263
|
feature_name = runner.getStringArgumentValue('feature_name', user_arguments)
|
256
264
|
feature_type = runner.getStringArgumentValue('feature_type', user_arguments)
|
265
|
+
feature_location = runner.getStringArgumentValue('feature_location', user_arguments)
|
257
266
|
|
258
267
|
# Assign the user inputs to variables
|
259
268
|
reporting_frequency = runner.getStringArgumentValue('reporting_frequency', user_arguments)
|
@@ -318,13 +327,16 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
318
327
|
# Get Location information and store in the feature_report
|
319
328
|
##
|
320
329
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
330
|
+
if feature_location.include? '['
|
331
|
+
# get latitude from feature_location
|
332
|
+
latitude = (feature_location.split(',')[0].delete! '[]').to_f
|
333
|
+
# get longitude from feature_location
|
334
|
+
longitude = (feature_location.split(',')[1].delete! '[]').to_f
|
335
|
+
# latitude
|
336
|
+
feature_report.location.latitude = latitude
|
337
|
+
# longitude
|
338
|
+
feature_report.location.longitude = longitude
|
339
|
+
end
|
328
340
|
|
329
341
|
# surface_elevation
|
330
342
|
elev = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='General' AND RowName='Elevation' AND ColumnName='Value'")
|
@@ -332,6 +344,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
332
344
|
|
333
345
|
##########################################################################
|
334
346
|
##
|
347
|
+
|
335
348
|
# Get program information and store in the feature_report
|
336
349
|
##
|
337
350
|
|
@@ -475,6 +488,39 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
475
488
|
total_construction_cost = sql_query(runner, sql_file, 'Life-Cycle Cost Report', "TableName='Present Value for Recurring, Nonrecurring and Energy Costs (Before Tax)' AND RowName='LCC_MAT - BUILDING - LIFE CYCLE COSTS' AND ColumnName='Cost'")
|
476
489
|
feature_report.program.total_construction_cost = total_construction_cost
|
477
490
|
|
491
|
+
# packaged thermal storage capacities by cooling coil
|
492
|
+
ptes_keys = sql_file.availableKeyValues('RUN Period 1', 'Zone Timestep', 'Cooling Coil Ice Thermal Storage End Fraction')
|
493
|
+
if ptes_keys.empty?
|
494
|
+
ptes_size = nil
|
495
|
+
runner.registerWarning('Query failed for Packaged Ice Thermal Storage Capacity')
|
496
|
+
else
|
497
|
+
begin
|
498
|
+
ptes_size = 0
|
499
|
+
ptes_keys.each do |pk|
|
500
|
+
ptes_size += sql_query(runner, sql_file, 'ComponentSizingSummary', "TableName='Coil:Cooling:DX:SingleSpeed:ThermalStorage' AND RowName='#{pk}' AND ColumnName='Ice Storage Capacity'").to_f
|
501
|
+
end
|
502
|
+
ptes_size = convert_units(ptes_size, 'GJ', 'kWh')
|
503
|
+
rescue StandardError
|
504
|
+
runner.registerWarning('Query ptes_size.get failed')
|
505
|
+
end
|
506
|
+
end
|
507
|
+
feature_report.thermal_storage.ptes_size = ptes_size
|
508
|
+
|
509
|
+
# get the central tank thermal storage capacity
|
510
|
+
its_size = nil
|
511
|
+
its_size_index = sql_file.execAndReturnFirstDouble("SELECT ReportVariableDataDictionaryIndex FROM ReportVariableDataDictionary WHERE VariableName='Ice Thermal Storage Capacity'")
|
512
|
+
if its_size_index.empty?
|
513
|
+
runner.registerWarning('Query failed for Ice Thermal Storage Capacity')
|
514
|
+
else
|
515
|
+
begin
|
516
|
+
its_size = sql_file.execAndReturnFirstDouble("SELECT VariableValue FROM ReportVariableData WHERE ReportVariableDataDictionaryIndex=#{its_size_index}").get
|
517
|
+
its_size = convert_units(its_size.to_f, 'GJ', 'kWh')
|
518
|
+
rescue StandardError
|
519
|
+
runner.registerWarning('Query its_size.get failed')
|
520
|
+
end
|
521
|
+
end
|
522
|
+
feature_report.thermal_storage.its_size = its_size
|
523
|
+
|
478
524
|
############################################################################
|
479
525
|
##
|
480
526
|
# Get Reporting Periods information and store in the feature_report
|
@@ -669,6 +715,10 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
669
715
|
powerTimeseries = ['Net Electric Energy', 'Electricity:Facility Power', 'ElectricityProduced:Facility Power', 'Electricity:Facility Apparent Power', 'ElectricityProduced:Facility Apparent Power', 'Net Power', 'Net Apparent Power']
|
670
716
|
requested_timeseries_names += powerTimeseries
|
671
717
|
|
718
|
+
# add additional thermal storage timeseries
|
719
|
+
tesTimeseries = ['Ice Thermal Storage End Fraction', 'Cooling Coil Ice Thermal Storage End Fraction']
|
720
|
+
requested_timeseries_names += tesTimeseries
|
721
|
+
|
672
722
|
# register info all timeseries
|
673
723
|
runner.registerInfo("All timeseries: #{requested_timeseries_names}")
|
674
724
|
|
@@ -870,6 +920,22 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
870
920
|
# puts "units = #{new_unit}"
|
871
921
|
# end
|
872
922
|
|
923
|
+
# thermal storage ice end fractions have multiple timeseries, aggregate into a single series with consistent name and use the average value at each timestep
|
924
|
+
if tesTimeseries.include? timeseries_name
|
925
|
+
|
926
|
+
# set up array if 1st key_value
|
927
|
+
if key_i == 0
|
928
|
+
runner.registerInfo("SETTING UP NEW ARRAY FOR: #{timeseries_name}")
|
929
|
+
tmpArray = Array.new(n, 1)
|
930
|
+
end
|
931
|
+
|
932
|
+
# add to array (keep min value at each timestep)
|
933
|
+
(0..(n - 1)).each do |ind|
|
934
|
+
tVal = values[key_cnt][ind].to_f
|
935
|
+
tmpArray[ind] = [tVal, tmpArray[ind]].min
|
936
|
+
end
|
937
|
+
end
|
938
|
+
|
873
939
|
# comfort results usually have multiple timeseries (per zone), aggregate into a single series with consistent name and use worst value at each timestep
|
874
940
|
if comfortTimeseries.include? timeseries_name
|
875
941
|
|
@@ -36,6 +36,7 @@ require_relative 'timeseries_csv'
|
|
36
36
|
require_relative 'distributed_generation'
|
37
37
|
require_relative 'power_distribution'
|
38
38
|
require_relative 'validator'
|
39
|
+
require_relative 'thermal_storage'
|
39
40
|
|
40
41
|
require 'json-schema'
|
41
42
|
require 'json'
|
@@ -52,7 +53,7 @@ module URBANopt
|
|
52
53
|
##
|
53
54
|
class FeatureReport
|
54
55
|
attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
|
55
|
-
:timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution # :nodoc:
|
56
|
+
:timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution, :thermal_storage # :nodoc:
|
56
57
|
##
|
57
58
|
# Each FeatureReport object corresponds to a single Feature.
|
58
59
|
##
|
@@ -88,6 +89,8 @@ module URBANopt
|
|
88
89
|
|
89
90
|
@power_distribution = PowerDistribution.new(hash[:power_distribution])
|
90
91
|
|
92
|
+
@thermal_storage = ThermalStorage.new(hash[:thermal_storage])
|
93
|
+
|
91
94
|
# initialize class variables @@validator and @@schema
|
92
95
|
@@validator ||= Validator.new
|
93
96
|
@@schema ||= @@validator.schema
|
@@ -108,6 +111,7 @@ module URBANopt
|
|
108
111
|
hash[:reporting_periods] = []
|
109
112
|
hash[:distributed_generation] = {}
|
110
113
|
hash[:power_distribution] = {}
|
114
|
+
hash[:thermal_storage] = {}
|
111
115
|
return hash
|
112
116
|
end
|
113
117
|
|
@@ -209,6 +213,8 @@ module URBANopt
|
|
209
213
|
|
210
214
|
result[:power_distribution] = @power_distribution.to_hash if @power_distribution
|
211
215
|
|
216
|
+
result[:thermal_storage] = @thermal_storage.to_hash if @thermal_storage
|
217
|
+
|
212
218
|
# validate feature_report properties against schema
|
213
219
|
if @@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result).any?
|
214
220
|
raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result)}"
|
@@ -63,6 +63,9 @@
|
|
63
63
|
},
|
64
64
|
"distributed_generation": {
|
65
65
|
"$ref": "#/definitions/DistributedGeneration"
|
66
|
+
},
|
67
|
+
"thermal_storage": {
|
68
|
+
"$ref": "#/definitions/ThermalStorage"
|
66
69
|
}
|
67
70
|
},
|
68
71
|
"required": [
|
@@ -216,6 +219,9 @@
|
|
216
219
|
},
|
217
220
|
"power_distribution": {
|
218
221
|
"$ref": "#/definitions/PowerDistribution"
|
222
|
+
},
|
223
|
+
"thermal_storage": {
|
224
|
+
"$ref": "#/definitions/ThermalStorage"
|
219
225
|
}
|
220
226
|
},
|
221
227
|
"required": [
|
@@ -541,11 +547,11 @@
|
|
541
547
|
"type": "object",
|
542
548
|
"properties": {
|
543
549
|
"latitude": {
|
544
|
-
"description": "(deg)",
|
550
|
+
"description": "latitude for the centroid of the feature (deg)",
|
545
551
|
"type": "number"
|
546
552
|
},
|
547
553
|
"longitude": {
|
548
|
-
"description": "(deg)",
|
554
|
+
"description": "longitude for the centroid of the feature (deg)",
|
549
555
|
"type": "number"
|
550
556
|
},
|
551
557
|
"surface_elevation": {
|
@@ -852,6 +858,19 @@
|
|
852
858
|
"type": "number"
|
853
859
|
}
|
854
860
|
}
|
861
|
+
},
|
862
|
+
"ThermalStorage": {
|
863
|
+
"type": "object",
|
864
|
+
"properties": {
|
865
|
+
"its_size": {
|
866
|
+
"description": "Total central plant TES capacity in kWh",
|
867
|
+
"type": "number"
|
868
|
+
},
|
869
|
+
"ptes_size": {
|
870
|
+
"description": "Total distributed/packaged TES capacity in kWh",
|
871
|
+
"type": "number"
|
872
|
+
}
|
873
|
+
}
|
855
874
|
}
|
856
875
|
}
|
857
|
-
}
|
876
|
+
}
|
@@ -0,0 +1,111 @@
|
|
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 'json'
|
32
|
+
require 'urbanopt/reporting/default_reports/validator'
|
33
|
+
require 'json-schema'
|
34
|
+
|
35
|
+
module URBANopt
|
36
|
+
module Reporting
|
37
|
+
module DefaultReports
|
38
|
+
##
|
39
|
+
# Ice Thermal Storage Systems
|
40
|
+
##
|
41
|
+
class ThermalStorage
|
42
|
+
##
|
43
|
+
# _Float_ - Total ice storage capacity on central plant loop in kWh
|
44
|
+
#
|
45
|
+
attr_accessor :its_size
|
46
|
+
|
47
|
+
# _Float_ - Total ice storage capacity distributed to packaged systems in kWh
|
48
|
+
#
|
49
|
+
attr_accessor :ptes_size
|
50
|
+
|
51
|
+
def initialize(hash = {})
|
52
|
+
hash.delete_if { |k, v| v.nil? }
|
53
|
+
|
54
|
+
@its_size = hash[:its_size]
|
55
|
+
@ptes_size = hash[:ptes_size]
|
56
|
+
|
57
|
+
# initialize class variables @@validator and @@schema
|
58
|
+
@@validator ||= Validator.new
|
59
|
+
@@schema ||= @@validator.schema
|
60
|
+
|
61
|
+
# initialize @@logger
|
62
|
+
@@logger ||= URBANopt::Reporting::DefaultReports.logger
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Assigns default values if attribute values do not exist.
|
67
|
+
##
|
68
|
+
def defaults
|
69
|
+
hash = {}
|
70
|
+
hash[:its_size] = nil
|
71
|
+
hash[:ptes_size] = nil
|
72
|
+
|
73
|
+
return hash
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Convert to hash equivalent for JSON serialization
|
78
|
+
##
|
79
|
+
def to_hash
|
80
|
+
result = {}
|
81
|
+
result[:its_size] = @its_size if @its_size
|
82
|
+
result[:ptes_size] = @ptes_size if @ptes_size
|
83
|
+
|
84
|
+
return result
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Add up old and new values
|
89
|
+
##
|
90
|
+
def self.add_values(existing_value, new_value) #:nodoc:
|
91
|
+
if existing_value && new_value
|
92
|
+
existing_value += new_value
|
93
|
+
elsif new_value
|
94
|
+
existing_value = new_value
|
95
|
+
end
|
96
|
+
return existing_value
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Merge thermal storage
|
101
|
+
##
|
102
|
+
def self.merge_thermal_storage(existing_tes, new_tes)
|
103
|
+
existing_tes.its_size = add_values(existing_tes.its_size, new_tes.its_size)
|
104
|
+
existing_tes.ptes_size = add_values(existing_tes.ptes_size, new_tes.ptes_size)
|
105
|
+
|
106
|
+
return existing_tes
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: urbanopt-reporting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rawad El Kontar
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-08-
|
12
|
+
date: 2020-08-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -144,6 +144,7 @@ files:
|
|
144
144
|
- lib/urbanopt/reporting/default_reports/schema/scenario_schema.json
|
145
145
|
- lib/urbanopt/reporting/default_reports/solar_pv.rb
|
146
146
|
- lib/urbanopt/reporting/default_reports/storage.rb
|
147
|
+
- lib/urbanopt/reporting/default_reports/thermal_storage.rb
|
147
148
|
- lib/urbanopt/reporting/default_reports/timeseries_csv.rb
|
148
149
|
- lib/urbanopt/reporting/default_reports/validator.rb
|
149
150
|
- lib/urbanopt/reporting/default_reports/wind.rb
|
@@ -168,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
169
|
- !ruby/object:Gem::Version
|
169
170
|
version: '0'
|
170
171
|
requirements: []
|
171
|
-
|
172
|
-
rubygems_version: 2.7.6
|
172
|
+
rubygems_version: 3.1.4
|
173
173
|
signing_key:
|
174
174
|
specification_version: 4
|
175
175
|
summary: Library to report URBANopt results
|