urbanopt-reporting 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|