buildingsync 0.2.0
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 +7 -0
- data/.github/workflows/continuous_integration.yml +146 -0
- data/.gitignore +33 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +50 -0
- data/Gemfile +31 -0
- data/Jenkinsfile +10 -0
- data/LICENSE.md +29 -0
- data/README.md +105 -0
- data/Rakefile +77 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/buildingsync.gemspec +37 -0
- data/config.rb.in +26 -0
- data/doc_templates/LICENSE.md +29 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +38 -0
- data/doc_templates/copyright_js.txt +5 -0
- data/doc_templates/copyright_ruby.txt +36 -0
- data/lib/buildingsync.rb +43 -0
- data/lib/buildingsync/all_resource_total.rb +54 -0
- data/lib/buildingsync/audit_date.rb +54 -0
- data/lib/buildingsync/constants.rb +49 -0
- data/lib/buildingsync/contact.rb +54 -0
- data/lib/buildingsync/extension.rb +57 -0
- data/lib/buildingsync/generator.rb +584 -0
- data/lib/buildingsync/get_bcl_weather_file.rb +326 -0
- data/lib/buildingsync/helpers/Model.hvac.rb +216 -0
- data/lib/buildingsync/helpers/helper.rb +494 -0
- data/lib/buildingsync/helpers/xml_get_set.rb +215 -0
- data/lib/buildingsync/makers/phase_zero_base.osw +178 -0
- data/lib/buildingsync/makers/workflow_maker.json +811 -0
- data/lib/buildingsync/makers/workflow_maker.rb +581 -0
- data/lib/buildingsync/makers/workflow_maker_base.rb +167 -0
- data/lib/buildingsync/model_articulation/building.rb +1119 -0
- data/lib/buildingsync/model_articulation/building_and_system_types.json +121 -0
- data/lib/buildingsync/model_articulation/building_section.rb +190 -0
- data/lib/buildingsync/model_articulation/building_system.rb +49 -0
- data/lib/buildingsync/model_articulation/envelope_system.rb +102 -0
- data/lib/buildingsync/model_articulation/exterior_floor_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/facility.rb +439 -0
- data/lib/buildingsync/model_articulation/foundation_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/hvac_system.rb +395 -0
- data/lib/buildingsync/model_articulation/lighting_system.rb +102 -0
- data/lib/buildingsync/model_articulation/loads_system.rb +287 -0
- data/lib/buildingsync/model_articulation/location_element.rb +129 -0
- data/lib/buildingsync/model_articulation/measure.rb +57 -0
- data/lib/buildingsync/model_articulation/roof_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/service_hot_water_system.rb +87 -0
- data/lib/buildingsync/model_articulation/site.rb +242 -0
- data/lib/buildingsync/model_articulation/spatial_element.rb +343 -0
- data/lib/buildingsync/model_articulation/wall_system_type.rb +64 -0
- data/lib/buildingsync/report.rb +217 -0
- data/lib/buildingsync/resource_use.rb +55 -0
- data/lib/buildingsync/scenario.rb +622 -0
- data/lib/buildingsync/selection_tool.rb +98 -0
- data/lib/buildingsync/time_series.rb +85 -0
- data/lib/buildingsync/translator.rb +167 -0
- data/lib/buildingsync/utility.rb +67 -0
- data/lib/buildingsync/version.rb +45 -0
- metadata +223 -0
@@ -0,0 +1,343 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
require 'openstudio'
|
40
|
+
require 'fileutils'
|
41
|
+
require 'json'
|
42
|
+
require 'openstudio/extension/core/os_lib_model_generation'
|
43
|
+
|
44
|
+
require 'buildingsync/helpers/helper'
|
45
|
+
require 'buildingsync/helpers/xml_get_set'
|
46
|
+
|
47
|
+
module BuildingSync
|
48
|
+
# base class for objects that will configure workflows based on building sync files
|
49
|
+
class SpatialElement
|
50
|
+
include OsLib_ModelGeneration
|
51
|
+
include BuildingSync::Helper
|
52
|
+
include BuildingSync::XmlGetSet
|
53
|
+
# initialize SpatialElement class
|
54
|
+
# @param base_xml [REXML::Element] an element corresponding to a spatial element,
|
55
|
+
# either an auc:Site, auc:Building, auc:Section
|
56
|
+
# @param ns [String] namespace, likely 'auc'
|
57
|
+
def initialize(base_xml, ns)
|
58
|
+
@base_xml = base_xml
|
59
|
+
@ns = ns
|
60
|
+
|
61
|
+
@total_floor_area = nil
|
62
|
+
@standards_building_type = nil
|
63
|
+
@system_type = nil
|
64
|
+
@bar_division_method = nil
|
65
|
+
@space_types = {}
|
66
|
+
@fraction_area = nil
|
67
|
+
@space_types_floor_area = nil
|
68
|
+
@conditioned_floor_area_heated_only = nil
|
69
|
+
@conditioned_floor_area_cooled_only = nil
|
70
|
+
@conditioned_floor_area_heated_cooled = nil
|
71
|
+
@custom_conditioned_above_grade_floor_area = nil
|
72
|
+
@custom_conditioned_below_grade_floor_area = nil
|
73
|
+
|
74
|
+
@user_defined_fields = REXML::Element.new("#{@ns}:UserDefinedFields")
|
75
|
+
end
|
76
|
+
|
77
|
+
# read floor areas
|
78
|
+
# @param parent_total_floor_area [Float]
|
79
|
+
def read_floor_areas(parent_total_floor_area)
|
80
|
+
@base_xml.elements.each("#{@ns}:FloorAreas/#{@ns}:FloorArea") do |floor_area_element|
|
81
|
+
next if !floor_area_element.elements["#{@ns}:FloorAreaValue"]
|
82
|
+
floor_area = floor_area_element.elements["#{@ns}:FloorAreaValue"].text.to_f
|
83
|
+
next if floor_area.nil?
|
84
|
+
|
85
|
+
floor_area_type = floor_area_element.elements["#{@ns}:FloorAreaType"].text
|
86
|
+
if floor_area_type == 'Gross'
|
87
|
+
@total_floor_area = OpenStudio.convert(validate_positive_number_excluding_zero('gross_floor_area', floor_area), 'ft^2', 'm^2').get
|
88
|
+
elsif floor_area_type == 'Heated and Cooled'
|
89
|
+
@conditioned_floor_area_heated_cooled = OpenStudio.convert(validate_positive_number_excluding_zero('@heated_and_cooled_floor_area', floor_area), 'ft^2', 'm^2').get
|
90
|
+
elsif floor_area_type == 'Footprint'
|
91
|
+
@footprint_floor_area = OpenStudio.convert(validate_positive_number_excluding_zero('@footprint_floor_area', floor_area), 'ft^2', 'm^2').get
|
92
|
+
elsif floor_area_type == 'Conditioned'
|
93
|
+
@conditioned_floor_area_heated_cooled = OpenStudio.convert(validate_positive_number_excluding_zero('@conditioned_floor_area_heated_cooled', floor_area), 'ft^2', 'm^2').get
|
94
|
+
elsif floor_area_type == 'Heated Only'
|
95
|
+
@conditioned_floor_area_heated_only = OpenStudio.convert(validate_positive_number_excluding_zero('@heated_only_floor_area', floor_area), 'ft^2', 'm^2').get
|
96
|
+
elsif floor_area_type == 'Cooled Only'
|
97
|
+
@conditioned_floor_area_cooled_only = OpenStudio.convert(validate_positive_number_excluding_zero('@cooled_only_floor_area', floor_area), 'ft^2', 'm^2').get
|
98
|
+
elsif floor_area_type == 'Custom'
|
99
|
+
if floor_area_element.elements["#{@ns}:FloorAreaCustomName"].text == 'Conditioned above grade'
|
100
|
+
@custom_conditioned_above_grade_floor_area = OpenStudio.convert(validate_positive_number_excluding_zero('@custom_conditioned_above_grade_floor_area', floor_area), 'ft^2', 'm^2').get
|
101
|
+
elsif floor_area_element.elements["#{@ns}:FloorAreaCustomName"].text == 'Conditioned below grade'
|
102
|
+
@custom_conditioned_below_grade_floor_area = OpenStudio.convert(validate_positive_number_excluding_zero('@custom_conditioned_below_grade_floor_area', floor_area), 'ft^2', 'm^2').get
|
103
|
+
end
|
104
|
+
else
|
105
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.SpatialElement.generate_baseline_osm', "Unsupported floor area type found: #{floor_area_type}")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if @total_floor_area.nil? || @total_floor_area == 0
|
110
|
+
# if the total floor area is null, we try to calculate the total area, from various conditioned areas
|
111
|
+
running_floor_area = 0
|
112
|
+
if !@conditioned_floor_area_cooled_only.nil? && @conditioned_floor_area_cooled_only > 0
|
113
|
+
running_floor_area += @conditioned_floor_area_cooled_only
|
114
|
+
end
|
115
|
+
if !@conditioned_floor_area_heated_only.nil? && @conditioned_floor_area_heated_only > 0
|
116
|
+
running_floor_area += @conditioned_floor_area_heated_only
|
117
|
+
end
|
118
|
+
if !@conditioned_floor_area_heated_cooled.nil? && @conditioned_floor_area_heated_cooled > 0
|
119
|
+
running_floor_area += @conditioned_floor_area_heated_cooled
|
120
|
+
end
|
121
|
+
if running_floor_area > 0
|
122
|
+
@total_floor_area = running_floor_area
|
123
|
+
else
|
124
|
+
# if the conditions floor areas are null, we look at the conditioned above and below grade areas
|
125
|
+
if !@custom_conditioned_above_grade_floor_area.nil? && @custom_conditioned_above_grade_floor_area > 0
|
126
|
+
running_floor_area += @custom_conditioned_above_grade_floor_area
|
127
|
+
end
|
128
|
+
if !@custom_conditioned_below_grade_floor_area.nil? && @custom_conditioned_below_grade_floor_area > 0
|
129
|
+
running_floor_area += @custom_conditioned_below_grade_floor_area
|
130
|
+
end
|
131
|
+
if running_floor_area > 0
|
132
|
+
@total_floor_area = running_floor_area
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# if we did not find any area we get the parent one
|
138
|
+
if @total_floor_area.nil? || @total_floor_area == 0
|
139
|
+
return parent_total_floor_area
|
140
|
+
else
|
141
|
+
return @total_floor_area
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# set building and system type
|
146
|
+
# @param occupancy_classification [String]
|
147
|
+
# @param total_floor_area [Float]
|
148
|
+
# @param total_number_floors [Integer]
|
149
|
+
# @param raise_exception [Boolean]
|
150
|
+
def set_bldg_and_system_type(occupancy_classification, total_floor_area, total_number_floors, raise_exception)
|
151
|
+
# DOE Prototype building types:from openstudio-standards/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb
|
152
|
+
# SmallOffice, MediumOffice, LargeOffice, RetailStandalone, RetailStripmall, PrimarySchool, SecondarySchool, Outpatient
|
153
|
+
# Hospital, SmallHotel, LargeHotel, QuickServiceRestaurant, FullServiceRestaurant, MidriseApartment, HighriseApartment, Warehouse
|
154
|
+
|
155
|
+
if !occupancy_classification.nil? && !total_floor_area.nil?
|
156
|
+
|
157
|
+
building_and_system_types = eval(File.read(BUILDING_AND_SYSTEMS_FILE_PATH))
|
158
|
+
|
159
|
+
process_bldg_and_system_type(building_and_system_types, occupancy_classification, total_floor_area, total_number_floors)
|
160
|
+
|
161
|
+
if @standards_building_type == ''
|
162
|
+
raise "Building type '#{occupancy_classification}' is beyond BuildingSync scope"
|
163
|
+
end
|
164
|
+
elsif raise_exception
|
165
|
+
if occupancy_classification.nil? && !total_floor_area.nil?
|
166
|
+
raise "ID: #{xget_id} occupancy classification '#{occupancy_classification}' is nil"
|
167
|
+
elsif !occupancy_classification.nil? && total_floor_area.nil?
|
168
|
+
raise "ID: #{xget_id} Building total floor area '#{total_floor_area}' is nil"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# gets the standards occupancy type from the building type or the potential overwrite occupancy type
|
174
|
+
# @param occ_type [Hash]
|
175
|
+
# @return [Boolean]
|
176
|
+
def sets_occupancy_bldg_system_types(occ_type)
|
177
|
+
@standards_building_type = occ_type[:standards_building_type]
|
178
|
+
@bar_division_method = occ_type[:bar_division_method]
|
179
|
+
@system_type = occ_type[:system_type]
|
180
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.SpatialElement.sets_occupancy_bldg_system_types', "Element ID: #{xget_id} @standards_building_type #{@standards_building_type}, @bar_division_method #{@bar_division_method} and @system_type: #{@system_type}")
|
181
|
+
return true
|
182
|
+
end
|
183
|
+
|
184
|
+
# Determine the standards_building_type, bar_division_method, and system_type given:
|
185
|
+
# - occupancy_classification, total_floor_area, total_number_floors
|
186
|
+
# @param building_and_system_types [Hash] a read in of the building_and_system_types.json file
|
187
|
+
# @param occupancy_classification [String] value of OccupancyClassification element
|
188
|
+
# @param total_floor_area [Float]
|
189
|
+
# @param total_number_floors [Integer]
|
190
|
+
# @return [Boolean]
|
191
|
+
def process_bldg_and_system_type(building_and_system_types, occupancy_classification, total_floor_area, total_number_floors)
|
192
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.SpatialElement.process_bldg_and_system_type', "Element ID: #{xget_id} started with occupancy_classification #{occupancy_classification} and total floor area: #{total_floor_area}")
|
193
|
+
puts "Element ID: #{xget_id} started with occupancy_classification #{occupancy_classification} and total floor area: #{total_floor_area}"
|
194
|
+
min_floor_area_correct = false
|
195
|
+
max_floor_area_correct = false
|
196
|
+
building_and_system_types[:"#{occupancy_classification}"]&.each do |occ_type|
|
197
|
+
if !occ_type[:standards_building_type].nil?
|
198
|
+
if occ_type[:min_floor_area] || occ_type[:max_floor_area]
|
199
|
+
if occ_type[:min_floor_area] && occ_type[:min_floor_area].to_f < total_floor_area
|
200
|
+
min_floor_area_correct = true
|
201
|
+
end
|
202
|
+
if occ_type[:max_floor_area] && occ_type[:max_floor_area].to_f > total_floor_area
|
203
|
+
max_floor_area_correct = true
|
204
|
+
end
|
205
|
+
if (min_floor_area_correct && max_floor_area_correct) || (!occ_type[:min_floor_area] && max_floor_area_correct) || (min_floor_area_correct && !occ_type[:max_floor_area])
|
206
|
+
puts "selected the following standards_building_type: #{occ_type[:standards_building_type]}"
|
207
|
+
return sets_occupancy_bldg_system_types(occ_type)
|
208
|
+
end
|
209
|
+
elsif occ_type[:min_number_floors] || occ_type[:max_number_floors]
|
210
|
+
if occ_type[:min_number_floors] && occ_type[:min_number_floors].to_i <= total_number_floors
|
211
|
+
puts "selected the following standards_building_type: #{occ_type[:standards_building_type]}"
|
212
|
+
return sets_occupancy_bldg_system_types(occ_type)
|
213
|
+
elsif occ_type[:max_number_floors] && occ_type[:max_number_floors].to_i > total_number_floors
|
214
|
+
puts "selected the following standards_building_type: #{occ_type[:standards_building_type]}"
|
215
|
+
return sets_occupancy_bldg_system_types(occ_type)
|
216
|
+
end
|
217
|
+
else
|
218
|
+
# otherwise we assume the first one is correct and we select this
|
219
|
+
puts "selected the following standards_building_type: #{occ_type[:standards_building_type]}"
|
220
|
+
return sets_occupancy_bldg_system_types(occ_type)
|
221
|
+
end
|
222
|
+
else
|
223
|
+
# otherwise we assume the first one is correct and we select this
|
224
|
+
return sets_occupancy_bldg_system_types(occ_type)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
raise "BuildingSync Occupancy type #{occupancy_classification} is not available in the building_and_system_types.json dictionary"
|
228
|
+
return false
|
229
|
+
end
|
230
|
+
|
231
|
+
# validate positive number excluding zero
|
232
|
+
# @param name [String]
|
233
|
+
# @param value [Float]
|
234
|
+
# @return float
|
235
|
+
def validate_positive_number_excluding_zero(name, value)
|
236
|
+
puts "Error: parameter #{name} must be positive and not zero." if value <= 0
|
237
|
+
return value
|
238
|
+
end
|
239
|
+
|
240
|
+
# validate positive number including zero
|
241
|
+
# @param name [String]
|
242
|
+
# @param value [Float]
|
243
|
+
# @return float
|
244
|
+
def validate_positive_number_including_zero(name, value)
|
245
|
+
puts "Error: parameter #{name} must be positive or zero." if value < 0
|
246
|
+
return value
|
247
|
+
end
|
248
|
+
|
249
|
+
# create space types
|
250
|
+
# @param model [OpenStudio::Model]
|
251
|
+
# @param total_bldg_floor_area [Float]
|
252
|
+
# @param total_number_floors [Integer]
|
253
|
+
# @param standard_template [String]
|
254
|
+
# @param open_studio_standard [Standard]
|
255
|
+
# @return hash
|
256
|
+
def create_space_types(model, total_bldg_floor_area, total_number_floors, standard_template, open_studio_standard)
|
257
|
+
# create space types from section type
|
258
|
+
# mapping lookup_name name is needed for a few methods
|
259
|
+
set_bldg_and_system_type(xget_text('OccupancyClassification'), total_bldg_floor_area, total_number_floors, false) if @standards_building_type.nil?
|
260
|
+
if open_studio_standard.nil?
|
261
|
+
begin
|
262
|
+
open_studio_standard = Standard.build("#{standard_template}_#{@standards_building_type}")
|
263
|
+
rescue StandardError => e
|
264
|
+
# if the combination of standard type and bldg type fails we try the standard type alone.
|
265
|
+
puts "could not find open studio standard for template #{standard_template} and bldg type: #{@standards_building_type}, trying the standard type alone"
|
266
|
+
open_studio_standard = Standard.build(standard_template)
|
267
|
+
raise(e)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
@space_types = get_space_types_from_building_type(@standards_building_type, standard_template, true)
|
272
|
+
puts "BuildingSync.SpatialElement.create_space_types - Space types: #{@space_types} selected for building type: #{@standards_building_type} and standard template: #{standard_template}"
|
273
|
+
# create space_type_map from array
|
274
|
+
sum_of_ratios = 0.0
|
275
|
+
|
276
|
+
@space_types.each do |space_type_name, hash|
|
277
|
+
# create space type
|
278
|
+
space_type = OpenStudio::Model::SpaceType.new(model)
|
279
|
+
space_type.setStandardsBuildingType(@standards_building_type)
|
280
|
+
space_type.setStandardsSpaceType(space_type_name)
|
281
|
+
space_type.setName("#{@standards_building_type} #{space_type_name}")
|
282
|
+
|
283
|
+
# set color
|
284
|
+
test = open_studio_standard.space_type_apply_rendering_color(space_type) # this uses openstudio-standards
|
285
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.SpatialElement.create_space_types', "Warning: Could not find color for #{space_type.name}") if !test
|
286
|
+
# extend hash to hold new space type object
|
287
|
+
hash[:space_type] = space_type
|
288
|
+
|
289
|
+
# add to sum_of_ratios counter for adjustment multiplier
|
290
|
+
sum_of_ratios += hash[:ratio]
|
291
|
+
end
|
292
|
+
|
293
|
+
# store multiplier needed to adjust sum of ratios to equal 1.0
|
294
|
+
@ratio_adjustment_multiplier = 1.0 / sum_of_ratios
|
295
|
+
|
296
|
+
@space_types_floor_area = {}
|
297
|
+
@space_types.each do |space_type_name, hash|
|
298
|
+
ratio_of_bldg_total = hash[:ratio] * @ratio_adjustment_multiplier * @fraction_area
|
299
|
+
final_floor_area = ratio_of_bldg_total * total_bldg_floor_area # I think I can just pass ratio but passing in area is cleaner
|
300
|
+
@space_types_floor_area[hash[:space_type]] = { floor_area: final_floor_area }
|
301
|
+
end
|
302
|
+
puts 'BuildingSync.SpatialElement.create_space_types'
|
303
|
+
return @space_types_floor_area
|
304
|
+
end
|
305
|
+
|
306
|
+
# add user defined field to xml file
|
307
|
+
# @param field_name [String]
|
308
|
+
# @param field_value [String]
|
309
|
+
def add_user_defined_field_to_xml_file(field_name, field_value)
|
310
|
+
user_defined_field = REXML::Element.new("#{@ns}:UserDefinedField")
|
311
|
+
field_name_element = REXML::Element.new("#{@ns}:FieldName")
|
312
|
+
field_value_element = REXML::Element.new("#{@ns}:FieldValue")
|
313
|
+
|
314
|
+
if !field_value.nil?
|
315
|
+
@user_defined_fields.add_element(user_defined_field)
|
316
|
+
user_defined_field.add_element(field_name_element)
|
317
|
+
user_defined_field.add_element(field_value_element)
|
318
|
+
|
319
|
+
field_name_element.text = field_name
|
320
|
+
field_value_element.text = field_value
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
# write parameters to xml for spatial element
|
325
|
+
def prepare_final_xml_for_spatial_element
|
326
|
+
add_user_defined_field_to_xml_file('StandardsBuildingType', @standards_building_type)
|
327
|
+
add_user_defined_field_to_xml_file('SystemType', @system_type)
|
328
|
+
add_user_defined_field_to_xml_file('BarDivisionMethod', @bar_division_method)
|
329
|
+
add_user_defined_field_to_xml_file('FractionArea', @fraction_area)
|
330
|
+
add_user_defined_field_to_xml_file('SpaceTypesFloorArea', @space_types_floor_area)
|
331
|
+
add_user_defined_field_to_xml_file('TotalFloorArea(m^2)', @total_floor_area)
|
332
|
+
add_user_defined_field_to_xml_file('ConditionedFloorArea(m^2)', @conditioned_floor_area_heated_cooled) if !@conditioned_floor_area_heated_cooled.nil?
|
333
|
+
add_user_defined_field_to_xml_file('HeatedFloorArea(m^2)', @conditioned_floor_area_heated_only) if !@conditioned_floor_area_heated_only.nil?
|
334
|
+
add_user_defined_field_to_xml_file('CooledFloorArea(m^2)', @conditioned_floor_area_cooled_only) if !@conditioned_floor_area_cooled_only.nil?
|
335
|
+
add_user_defined_field_to_xml_file('ConditionedAboveGradeFloorArea(m^2)', @custom_conditioned_above_grade_floor_area) if !@custom_conditioned_above_grade_floor_area.nil?
|
336
|
+
add_user_defined_field_to_xml_file('ConditionedBelowGradeFloorArea(m^2)', @custom_conditioned_below_grade_floor_area) if !@custom_conditioned_below_grade_floor_area.nil?
|
337
|
+
|
338
|
+
@base_xml.add_element(@user_defined_fields)
|
339
|
+
end
|
340
|
+
|
341
|
+
attr_reader :total_floor_area, :standards_building_type, :system_type, :space_types
|
342
|
+
end
|
343
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
|
40
|
+
module BuildingSync
|
41
|
+
# Wall System Type
|
42
|
+
class WallSystemType
|
43
|
+
# initialize a specific floor system type given a ref
|
44
|
+
# @param doc [REXML::Document]
|
45
|
+
# @param ns [String]
|
46
|
+
# @param ref [String]
|
47
|
+
def initialize(doc, ns, ref)
|
48
|
+
@id = nil
|
49
|
+
doc.elements.each("#{ns}:Systems/#{ns}:WallSystems/#{ns}:WallSystem") do |wall_system|
|
50
|
+
if wall_system.attributes['ID'] == ref
|
51
|
+
read(wall_system, ns)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# read
|
57
|
+
# @param wall_system [REXML:Element]
|
58
|
+
# @param ns [String]
|
59
|
+
def read(wall_system, ns)
|
60
|
+
# ID
|
61
|
+
@id = wall_system.attributes['ID'] if wall_system.attributes['ID']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
|
40
|
+
require 'buildingsync/audit_date'
|
41
|
+
require 'buildingsync/scenario'
|
42
|
+
require 'buildingsync/utility'
|
43
|
+
|
44
|
+
module BuildingSync
|
45
|
+
# Report class
|
46
|
+
class Report
|
47
|
+
include BuildingSync::Helper
|
48
|
+
include BuildingSync::XmlGetSet
|
49
|
+
# @param base_xml [REXML::Element]
|
50
|
+
# @param ns [String]
|
51
|
+
def initialize(base_xml, ns)
|
52
|
+
@base_xml = base_xml
|
53
|
+
@ns = ns
|
54
|
+
help_element_class_type_check(base_xml, 'Report')
|
55
|
+
|
56
|
+
@scenarios = []
|
57
|
+
@audit_dates = []
|
58
|
+
@utilities = []
|
59
|
+
|
60
|
+
# Special scenarios
|
61
|
+
@cb_modeled = nil
|
62
|
+
@cb_measured = []
|
63
|
+
@poms = []
|
64
|
+
|
65
|
+
read_xml
|
66
|
+
end
|
67
|
+
|
68
|
+
def read_xml
|
69
|
+
read_scenarios
|
70
|
+
|
71
|
+
# Audit dates
|
72
|
+
@base_xml.elements.each("#{@ns}:AuditDates/#{@ns}:AuditDate") do |audit_date|
|
73
|
+
@audit_dates << BuildingSync::AuditDate.new(audit_date, @ns)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Utilities
|
77
|
+
@base_xml.elements.each("#{@ns}:Utilities/#{@ns}:Utility") do |utility|
|
78
|
+
@utilities << BuildingSync::Utility.new(utility, @ns)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def read_scenarios
|
83
|
+
# Scenarios - create and checks
|
84
|
+
scenarios_xml_temp = @base_xml.get_elements("#{@ns}:Scenarios/#{@ns}:Scenario")
|
85
|
+
cb_modeled = []
|
86
|
+
scenarios_xml_temp&.each do |scenario_xml|
|
87
|
+
if scenario_xml.is_a? REXML::Element
|
88
|
+
sc = BuildingSync::Scenario.new(scenario_xml, @ns)
|
89
|
+
@scenarios.push(sc)
|
90
|
+
cb_modeled << sc if sc.cb_modeled?
|
91
|
+
@cb_measured << sc if sc.cb_measured?
|
92
|
+
@poms << sc if sc.pom?
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# -- Issue warnings for undesirable situations
|
97
|
+
if @scenarios.empty?
|
98
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.read_xml', 'No Scenario elements found')
|
99
|
+
end
|
100
|
+
|
101
|
+
# -- Logging for Scenarios
|
102
|
+
if cb_modeled.empty?
|
103
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.read_xml', 'A Current Building Modeled Scenario is required.')
|
104
|
+
elsif cb_modeled.size > 1
|
105
|
+
@cb_modeled = cb_modeled[0]
|
106
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.read_xml', "Only 1 Current Building Modeled Scenario is supported. Using Scenario with ID: #{@cb_modeled.xget_id}")
|
107
|
+
else
|
108
|
+
@cb_modeled = cb_modeled[0]
|
109
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.read_xml', "Current Building Modeled Scenario has ID: #{@cb_modeled.xget_id}")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_all_utility_meter_numbers
|
114
|
+
all = []
|
115
|
+
@utilities.each do |utility|
|
116
|
+
all += utility.get_utility_meter_numbers
|
117
|
+
end
|
118
|
+
return all
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_all_utility_names
|
122
|
+
all = []
|
123
|
+
@utilities.each do |utility|
|
124
|
+
all += utility.get_utility_meter_numbers
|
125
|
+
end
|
126
|
+
return all
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_auditor_contact_id
|
130
|
+
return xget_attribute_for_element('AuditorContactID', 'IDref')
|
131
|
+
end
|
132
|
+
|
133
|
+
def get_newest_audit_date
|
134
|
+
dates = []
|
135
|
+
@audit_dates.each do |date|
|
136
|
+
dates << date.xget_text_as_date('Date')
|
137
|
+
end
|
138
|
+
return dates.max
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_oldest_audit_date
|
142
|
+
dates = []
|
143
|
+
@audit_dates.each do |date|
|
144
|
+
dates << date.xget_text_as_date('Date')
|
145
|
+
end
|
146
|
+
return dates.min
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get the SiteEnergyUseIntensity for the benchmark scenario.
|
150
|
+
# Where multiple benchmark scenarios exist, the value from the first is returned
|
151
|
+
# @see get_scenario_site_eui
|
152
|
+
def get_first_benchmark_site_eui
|
153
|
+
eui = []
|
154
|
+
ids = []
|
155
|
+
@scenarios.each do |scenario|
|
156
|
+
if scenario.benchmark?
|
157
|
+
eui << get_first_scenario_site_eui(scenario)
|
158
|
+
ids << scenario.xget_id
|
159
|
+
end
|
160
|
+
end
|
161
|
+
if eui.size == 1
|
162
|
+
return eui[0]
|
163
|
+
elsif eui.empty?
|
164
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.get_benchmark_site_eui', 'No Benchmark Scenarios exist with SiteEnergyUseIntensity defined')
|
165
|
+
return nil
|
166
|
+
elsif eui.size > 1
|
167
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.get_benchmark_site_eui', "Multiple Benchmark Scenarios exist with SiteEnergyUseIntensity defined. Returning the value for Scenario ID: #{ids[0]}")
|
168
|
+
return eui[0]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Get the SiteEnergyUseIntensity for the cb_modeled scenario.
|
173
|
+
# @see get_scenario_site_eui
|
174
|
+
def get_first_cb_modeled_site_eui
|
175
|
+
return get_first_scenario_site_eui(@cb_modeled)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Get the AllResourceTotal/SiteEnergyUseIntensity value as a float.
|
179
|
+
# Where multiple AllResourceTotals exist with the value defined, the first is returned.
|
180
|
+
# @param scenario [BuildingSync::Scenario] the scenario
|
181
|
+
# @return [Float] if atleast one value is found
|
182
|
+
# @return [nil] if no value is found
|
183
|
+
def get_first_scenario_site_eui(scenario)
|
184
|
+
eui = []
|
185
|
+
scenario.get_all_resource_totals.each do |art|
|
186
|
+
eui << art.xget_text_as_float('SiteEnergyUseIntensity')
|
187
|
+
end
|
188
|
+
if eui.size == 1
|
189
|
+
return eui[0]
|
190
|
+
elsif eui.empty?
|
191
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.get_scenario_site_eui', "Scenario ID: #{@cb_modeled.xget_id} does not have a SiteEnergyUseIntensity defined in any of the AllResourceTotal elements.")
|
192
|
+
return nil
|
193
|
+
elsif eui.size > 1
|
194
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.Facility.get_scenario_site_eui', "Scenario ID: #{@cb_modeled.xget_id} has more thant 1 (#{eui.size}) SiteEnergyUseIntensity defined in the AllResourceTotal elements. Returning the first.")
|
195
|
+
return eui[0]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# add a current building modeled scenario and set the @cb_modeled attribute
|
200
|
+
# @param id [String] id to use for the scenario
|
201
|
+
# @return [NilClass]
|
202
|
+
def add_cb_modeled(id = 'Scenario-Baseline')
|
203
|
+
if @cb_modeled.nil? || @cb_modeled.empty?
|
204
|
+
g = BuildingSync::Generator.new
|
205
|
+
scenario_xml = g.add_scenario_to_report(@base_xml, 'CBModeled', id)
|
206
|
+
scenario = BuildingSync::Scenario.new(scenario_xml, @ns)
|
207
|
+
@scenarios.push(scenario)
|
208
|
+
@cb_modeled = scenario
|
209
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.WorkflowMaker.add_cb_modeled', "A Current Building Modeled scenario was added (Scenario ID: #{@cb_modeled.xget_id}).")
|
210
|
+
else
|
211
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.WorkflowMaker.add_cb_modeled', "A Current Building Modeled scenario already exists (Scenario ID: #{@cb_modeled.xget_id}). A new one was not added.")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
attr_reader :scenarios, :cb_modeled, :cb_measured, :poms, :utilities
|
216
|
+
end
|
217
|
+
end
|