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,102 @@
|
|
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 'buildingsync/helpers/helper'
|
40
|
+
require 'buildingsync/helpers/xml_get_set'
|
41
|
+
|
42
|
+
module BuildingSync
|
43
|
+
# LightingSystemType class
|
44
|
+
class LightingSystemType
|
45
|
+
include BuildingSync::Helper
|
46
|
+
include BuildingSync::XmlGetSet
|
47
|
+
# initialize
|
48
|
+
# @param doc [REXML::Document]
|
49
|
+
# @param ns [String]
|
50
|
+
def initialize(base_xml, ns)
|
51
|
+
@base_xml = base_xml
|
52
|
+
@ns = ns
|
53
|
+
|
54
|
+
help_element_class_type_check(@base_xml, 'LightingSystem')
|
55
|
+
|
56
|
+
read_xml
|
57
|
+
end
|
58
|
+
|
59
|
+
# read
|
60
|
+
def read_xml; end
|
61
|
+
|
62
|
+
# add exterior lights
|
63
|
+
# @param model [OpenStudio::Model]
|
64
|
+
# @param standard [Standard]
|
65
|
+
# @param onsite_parking_fraction [Float]
|
66
|
+
# @param exterior_lighting_zone [String]
|
67
|
+
# @param remove_objects [Boolean]
|
68
|
+
# @return boolean
|
69
|
+
def add_exterior_lights(model, standard, onsite_parking_fraction, exterior_lighting_zone, remove_objects)
|
70
|
+
if remove_objects
|
71
|
+
model.getExteriorLightss.each do |ext_light|
|
72
|
+
next if ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
|
73
|
+
|
74
|
+
ext_light.remove
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
exterior_lights = standard.model_add_typical_exterior_lights(model, exterior_lighting_zone.chars[0].to_i, onsite_parking_fraction)
|
79
|
+
exterior_lights.each do |k, v|
|
80
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.LightingSystem.add_exterior_lights', "Adding Exterior Lights named #{v.exteriorLightsDefinition.name} with design level of #{v.exteriorLightsDefinition.designLevel} * #{OpenStudio.toNeatString(v.multiplier, 0, true)}.")
|
81
|
+
end
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
|
85
|
+
# add daylighting controls
|
86
|
+
# @param model [OpenStudio::Model]
|
87
|
+
# @param standard [Standard]
|
88
|
+
# @param template [String]
|
89
|
+
# @param main_output_dir [String] main output path, not scenario specific. i.e. SR should be a subdirectory
|
90
|
+
# @return boolean
|
91
|
+
def add_daylighting_controls(model, standard, template, main_output_dir)
|
92
|
+
# add daylight controls, need to perform a sizing run for 2010
|
93
|
+
if template == '90.1-2010'
|
94
|
+
if standard.model_run_sizing_run(model, "#{main_output_dir}/SRvt") == false
|
95
|
+
return false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
standard.model_add_daylighting_controls(model)
|
99
|
+
return true
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,287 @@
|
|
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/extension/core/os_lib_schedules.rb'
|
40
|
+
|
41
|
+
require 'buildingsync/helpers/helper'
|
42
|
+
require_relative 'building_system'
|
43
|
+
|
44
|
+
module BuildingSync
|
45
|
+
# LoadsSystem class that manages internal and external loads
|
46
|
+
class LoadsSystem < BuildingSystem
|
47
|
+
include BuildingSync::Helper
|
48
|
+
# initialize
|
49
|
+
# @param system_element [REXML::Element]
|
50
|
+
# @param ns [String]
|
51
|
+
def initialize(system_element = '', ns = '')
|
52
|
+
# code to initialize
|
53
|
+
end
|
54
|
+
|
55
|
+
# add internal loads from standard definitions
|
56
|
+
# @param model [OpenStudio::Model]
|
57
|
+
# @param standard [Standard]
|
58
|
+
# @param template [String]
|
59
|
+
# @param building_sections [REXML:Element]
|
60
|
+
# @param remove_objects [Boolean]
|
61
|
+
# @return [Boolean]
|
62
|
+
def add_internal_loads(model, standard, template, building_sections, remove_objects)
|
63
|
+
# remove internal loads
|
64
|
+
if remove_objects
|
65
|
+
model.getSpaceLoads.each do |instance|
|
66
|
+
next if instance.name.to_s.include?('Elevator') # most prototype building types model exterior elevators with name Elevator
|
67
|
+
next if instance.to_InternalMass.is_initialized
|
68
|
+
next if instance.to_WaterUseEquipment.is_initialized
|
69
|
+
|
70
|
+
instance.remove
|
71
|
+
end
|
72
|
+
model.getDesignSpecificationOutdoorAirs.each(&:remove)
|
73
|
+
model.getDefaultScheduleSets.each(&:remove)
|
74
|
+
end
|
75
|
+
|
76
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', 'Adding internal loads')
|
77
|
+
count_not_found = 0
|
78
|
+
model.getSpaceTypes.each do |space_type|
|
79
|
+
data = standard.space_type_get_standards_data(space_type)
|
80
|
+
if data.empty?
|
81
|
+
original_building_type = space_type.standardsBuildingType.get
|
82
|
+
alternate_building_type = standard.model_get_lookup_name(original_building_type)
|
83
|
+
if alternate_building_type != original_building_type
|
84
|
+
space_type.setStandardsBuildingType(alternate_building_type)
|
85
|
+
data = standard.space_type_get_standards_data(space_type)
|
86
|
+
if data.empty?
|
87
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "Unable to get standards data for Space Type: #{space_type.name}. Tried standards building type: #{original_building_type} and #{alternate_building_type} with standards space type: #{space_type.standardsSpaceType.get}")
|
88
|
+
count_not_found += 1
|
89
|
+
next
|
90
|
+
else
|
91
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "Space Type: #{space_type.name}. Standards building type changed from #{original_building_type} to #{alternate_building_type} with standards space type: #{space_type.standardsSpaceType.get}")
|
92
|
+
end
|
93
|
+
else
|
94
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "Unable to get standards data for Space Type: #{space_type.name}. Standards building type: #{space_type.standardsBuildingType.get}, space type: #{space_type.standardsSpaceType.get}")
|
95
|
+
count_not_found += 1
|
96
|
+
next
|
97
|
+
end
|
98
|
+
end
|
99
|
+
# Don't add infiltration here; will be added later in the script
|
100
|
+
test = standard.space_type_apply_internal_loads(space_type, true, true, true, true, true, false)
|
101
|
+
if test == false
|
102
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "Could not add loads for #{space_type.name}. Not expected for #{template}")
|
103
|
+
next
|
104
|
+
end
|
105
|
+
|
106
|
+
# apply internal load schedules
|
107
|
+
# the last bool test it to make thermostat schedules. They are now added in HVAC section instead of here
|
108
|
+
success = standard.space_type_apply_internal_load_schedules(space_type, true, true, true, true, true, true, false)
|
109
|
+
if !success
|
110
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "space_type_apply_internal_load_schedules unsuccessful for #{space_type.name}")
|
111
|
+
end
|
112
|
+
|
113
|
+
# here we adjust the people schedules according to user input of hours per week and weeks per year
|
114
|
+
if !building_sections.empty?
|
115
|
+
adjust_schedules(standard, space_type, get_building_occupancy_hours(building_sections), model)
|
116
|
+
end
|
117
|
+
# extend space type name to include the template. Consider this as well for load defs
|
118
|
+
space_type.setName("#{space_type.name} - #{template}")
|
119
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.LoadsSystem.add_internal_loads', "Adding loads to space type named #{space_type.name}")
|
120
|
+
end
|
121
|
+
|
122
|
+
if count_not_found > 0
|
123
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "#{count_not_found} of #{model.getSpaceTypes.size} Space Types have no internal loads")
|
124
|
+
end
|
125
|
+
|
126
|
+
# warn if spaces in model without space type
|
127
|
+
spaces_without_space_types = []
|
128
|
+
model.getSpaces.each do |space|
|
129
|
+
next if space.spaceType.is_initialized
|
130
|
+
|
131
|
+
spaces_without_space_types << space
|
132
|
+
end
|
133
|
+
if !spaces_without_space_types.empty?
|
134
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LoadsSystem.add_internal_loads', "#{spaces_without_space_types.size} spaces do not have space types assigned, and wont' receive internal loads from standards space type lookups.")
|
135
|
+
end
|
136
|
+
return true
|
137
|
+
end
|
138
|
+
|
139
|
+
# add occupancy peak
|
140
|
+
# @param model [OpenStudio::Model]
|
141
|
+
# @param new_occupancy_peak [String]
|
142
|
+
# @param area [String]
|
143
|
+
# @param space_types [REXML:Element]
|
144
|
+
def adjust_occupancy_peak(model, new_occupancy_peak, area, space_types)
|
145
|
+
# we assume that the standard always generate people per area
|
146
|
+
sum_of_people_per_area = 0.0
|
147
|
+
count = 0
|
148
|
+
if !space_types.nil?
|
149
|
+
sorted_space_types = model.getSpaceTypes.sort
|
150
|
+
sorted_space_types.each do |space_type|
|
151
|
+
if space_types.include? space_type
|
152
|
+
peoples = space_type.people
|
153
|
+
peoples.each do |people|
|
154
|
+
sum_of_people_per_area += people.peoplePerFloorArea.get
|
155
|
+
count += 1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
average_people_per_area = sum_of_people_per_area / count
|
160
|
+
puts "existing occupancy: #{average_people_per_area} new target value: #{new_occupancy_peak.to_f / area.to_f}"
|
161
|
+
new_sum_of_people_per_area = 0.0
|
162
|
+
sorted_space_types.each do |space_type|
|
163
|
+
if space_types.include? space_type
|
164
|
+
peoples = space_type.people
|
165
|
+
peoples.each do |people|
|
166
|
+
ratio = people.peoplePerFloorArea.get.to_f / average_people_per_area.to_f
|
167
|
+
new_value = ratio * new_occupancy_peak.to_f / area.to_f
|
168
|
+
puts "adjusting occupancy per area value from: #{people.peoplePerFloorArea.get} by ratio #{ratio} to #{new_value}"
|
169
|
+
people.peopleDefinition.setPeopleperSpaceFloorArea(new_value)
|
170
|
+
new_sum_of_people_per_area += new_value
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
puts "resulting total absolute occupancy value: #{new_sum_of_people_per_area * area.to_f} occupancy per area value: #{new_sum_of_people_per_area / count}"
|
175
|
+
else
|
176
|
+
puts 'space types are empty'
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# get building occupancy hours
|
181
|
+
# @param building_sections [array]
|
182
|
+
# @return [Float]
|
183
|
+
def get_building_occupancy_hours(building_sections)
|
184
|
+
if building_sections.count == 1
|
185
|
+
return building_sections[0].typical_occupant_usage_value_hours.to_f
|
186
|
+
end
|
187
|
+
occupancy_hours = nil
|
188
|
+
count = 0.0
|
189
|
+
building_sections.each do |section|
|
190
|
+
occupancy_hours = 0.0 if occupancy_hours.nil?
|
191
|
+
occupancy_hours += section.typical_occupant_usage_value_hours.to_f if section.typical_occupant_usage_value_hours.nil?
|
192
|
+
count += 1 if section.typical_occupant_usage_value_hours.nil?
|
193
|
+
end
|
194
|
+
return nil if occupancy_hours.nil?
|
195
|
+
return occupancy_hours / count
|
196
|
+
end
|
197
|
+
|
198
|
+
# adjust schedules
|
199
|
+
# @param standard [Standard]
|
200
|
+
# @param space_type [OpenStudio::Model::SpaceType]
|
201
|
+
# @param building_occupant_hours_per_week [Float]
|
202
|
+
# @param model [OpenStudio::Model]
|
203
|
+
# @return boolean
|
204
|
+
def adjust_schedules(standard, space_type, building_occupant_hours_per_week, model)
|
205
|
+
# this uses code from https://github.com/NREL/openstudio-extension-gem/blob/6f8f7a46de496c3ab95ed9c72d4d543bd4b67740/lib/openstudio/extension/core/os_lib_model_generation.rb#L3007
|
206
|
+
#
|
207
|
+
# currently this works for all schedules in the model
|
208
|
+
# in the future we would want to make this more flexible to adjusted based on space_types or building sections
|
209
|
+
return unless !building_occupant_hours_per_week.nil?
|
210
|
+
hours_per_week = building_occupant_hours_per_week
|
211
|
+
|
212
|
+
default_schedule_set = help_get_default_schedule_set(model)
|
213
|
+
existing_number_of_people_sched = help_get_schedule_rule_set_from_schedule(default_schedule_set.numberofPeopleSchedule)
|
214
|
+
return false if existing_number_of_people_sched.nil?
|
215
|
+
calc_hours_per_week = help_calculate_hours(existing_number_of_people_sched)
|
216
|
+
ratio_hours_per_week = hours_per_week / calc_hours_per_week
|
217
|
+
|
218
|
+
wkdy_start_time = help_get_start_time_weekday(existing_number_of_people_sched)
|
219
|
+
wkdy_end_time = help_get_end_time_weekday(existing_number_of_people_sched)
|
220
|
+
wkdy_hours = wkdy_end_time - wkdy_start_time
|
221
|
+
|
222
|
+
sat_start_time = help_get_start_time_sat(existing_number_of_people_sched)
|
223
|
+
sat_end_time = help_get_end_time_sat(existing_number_of_people_sched)
|
224
|
+
sat_hours = sat_end_time - sat_start_time
|
225
|
+
|
226
|
+
sun_start_time = help_get_start_time_sun(existing_number_of_people_sched)
|
227
|
+
sun_end_time = help_get_end_time_sun(existing_number_of_people_sched)
|
228
|
+
sun_hours = sun_end_time - sun_start_time
|
229
|
+
|
230
|
+
# determine new end times via ratios
|
231
|
+
wkdy_end_time = wkdy_start_time + OpenStudio::Time.new(ratio_hours_per_week * wkdy_hours.totalDays)
|
232
|
+
sat_end_time = sat_start_time + OpenStudio::Time.new(ratio_hours_per_week * sat_hours.totalDays)
|
233
|
+
sun_end_time = sun_start_time + OpenStudio::Time.new(ratio_hours_per_week * sun_hours.totalDays)
|
234
|
+
|
235
|
+
# Infer the current hours of operation schedule for the building
|
236
|
+
op_sch = standard.model_infer_hours_of_operation_building(model)
|
237
|
+
default_schedule_set.setHoursofOperationSchedule(op_sch)
|
238
|
+
|
239
|
+
# help_print_all_schedules("org_schedules-#{space_type.name}.csv", default_schedule_set)
|
240
|
+
|
241
|
+
# Convert existing schedules in the model to parametric schedules based on current hours of operation
|
242
|
+
standard.model_setup_parametric_schedules(model)
|
243
|
+
|
244
|
+
# Modify hours of operation, using weekdays values for all weekdays and weekend values for Saturday and Sunday
|
245
|
+
standard.schedule_ruleset_set_hours_of_operation(op_sch,
|
246
|
+
wkdy_start_time: wkdy_start_time,
|
247
|
+
wkdy_end_time: wkdy_end_time,
|
248
|
+
sat_start_time: sat_start_time,
|
249
|
+
sat_end_time: sat_end_time,
|
250
|
+
sun_start_time: sun_start_time,
|
251
|
+
sun_end_time: sun_end_time)
|
252
|
+
|
253
|
+
# Apply new operating hours to parametric schedules to make schedules in model reflect modified hours of operation
|
254
|
+
parametric_schedules = standard.model_apply_parametric_schedules(model, error_on_out_of_order: false)
|
255
|
+
puts "Updated #{parametric_schedules.size} schedules with new hours of operation."
|
256
|
+
return true
|
257
|
+
end
|
258
|
+
|
259
|
+
# add elevator
|
260
|
+
# @param model [OpenStudio::Model]
|
261
|
+
# @param standard [Standard]
|
262
|
+
# @return boolean
|
263
|
+
def add_elevator(model, standard)
|
264
|
+
# remove elevators as spaceLoads or exteriorLights
|
265
|
+
model.getSpaceLoads.each do |instance|
|
266
|
+
next if !instance.name.to_s.include?('Elevator') # most prototype building types model exterior elevators with name Elevator
|
267
|
+
|
268
|
+
instance.remove
|
269
|
+
end
|
270
|
+
model.getExteriorLightss.each do |ext_light|
|
271
|
+
next if !ext_light.name.to_s.include?('Fuel equipment') # some prototype building types model exterior elevators by this name
|
272
|
+
|
273
|
+
ext_light.remove
|
274
|
+
end
|
275
|
+
|
276
|
+
elevators = standard.model_add_elevators(model)
|
277
|
+
if elevators.nil?
|
278
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.LoadsSystem.add_elevator', 'No elevators added to the building.')
|
279
|
+
else
|
280
|
+
elevator_def = elevators.electricEquipmentDefinition
|
281
|
+
design_level = elevator_def.designLevel.get
|
282
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.LoadsSystem.add_elevator', "Adding #{elevators.multiplier.round(1)} elevators each with power of #{OpenStudio.toNeatString(design_level, 0, true)} (W), plus lights and fans.")
|
283
|
+
end
|
284
|
+
return true
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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
|
+
# base class for objects that will configure workflows based on building sync files
|
42
|
+
class LocationElement < SpatialElement
|
43
|
+
# initialize LocationElement class
|
44
|
+
# @param base_xml [REXML::Element] an element corresponding to a locational element
|
45
|
+
# either an auc:Site or auc:Building
|
46
|
+
# @param ns [String] namespace, likely 'auc'
|
47
|
+
def initialize(base_xml, ns)
|
48
|
+
super(base_xml, ns)
|
49
|
+
@base_xml = base_xml
|
50
|
+
@ns = ns
|
51
|
+
|
52
|
+
@climate_zone = nil
|
53
|
+
@climate_zone_ashrae = nil
|
54
|
+
@climate_zone_ca_t24 = nil
|
55
|
+
@city_name = nil
|
56
|
+
@state_name = nil
|
57
|
+
|
58
|
+
read_location_values
|
59
|
+
end
|
60
|
+
|
61
|
+
# read location values
|
62
|
+
def read_location_values
|
63
|
+
# read in the ASHRAE climate zone
|
64
|
+
read_climate_zone
|
65
|
+
|
66
|
+
# read city and state name
|
67
|
+
read_city_and_state_name
|
68
|
+
end
|
69
|
+
|
70
|
+
def determine_climate_zone(standard_to_be_used = nil)
|
71
|
+
if standard_to_be_used == ASHRAE90_1
|
72
|
+
if !@climate_zone_ashrae.nil?
|
73
|
+
@climate_zone = @climate_zone_ashrae
|
74
|
+
elsif @climate_zone.nil? && !@climate_zone_ca_t24.nil?
|
75
|
+
@climate_zone = @climate_zone_ca_t24
|
76
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LocationElement.determine_climate_zone', "Element ID: #{xget_id} - Standard to use is #{standard_to_be_used} but ASHRAE Climate Zone is nil. Using CA T24: #{@climate_zone}")
|
77
|
+
end
|
78
|
+
elsif standard_to_be_used == CA_TITLE24
|
79
|
+
if !@climate_zone_ca_t24.nil?
|
80
|
+
@climate_zone = @climate_zone_ca_t24
|
81
|
+
elsif @climate_zone.nil? && !@climate_zone_ashrae.nil?
|
82
|
+
@climate_zone = @climate_zone_ashrae
|
83
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LocationElement.determine_climate_zone', "Element ID: #{xget_id} - Standard to use is #{standard_to_be_used} but CA T24 Climate Zone is nil. Using ASHRAE: #{@climate_zone}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# get climate zone
|
89
|
+
# @param standard_to_be_used [String]
|
90
|
+
# @return [String]
|
91
|
+
def get_climate_zone
|
92
|
+
return @climate_zone
|
93
|
+
end
|
94
|
+
|
95
|
+
# read climate zone
|
96
|
+
def read_climate_zone
|
97
|
+
if @base_xml.elements["#{@ns}:ClimateZoneType/#{@ns}:ASHRAE"]
|
98
|
+
@climate_zone_ashrae = @base_xml.elements["#{@ns}:ClimateZoneType/#{@ns}:ASHRAE/#{@ns}:ClimateZone"].text
|
99
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.LocationElement.read_climate_zone', "Element ID: #{xget_id} - ASHRAE Climate Zone: #{@climate_zone_ashrae}")
|
100
|
+
else
|
101
|
+
@climate_zone_ashrae = nil
|
102
|
+
end
|
103
|
+
if @base_xml.elements["#{@ns}:ClimateZoneType/#{@ns}:CaliforniaTitle24"]
|
104
|
+
@climate_zone_ca_t24 = @base_xml.elements["#{@ns}:ClimateZoneType/#{@ns}:CaliforniaTitle24/#{@ns}:ClimateZone"].text
|
105
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.LocationElement.read_climate_zone', "Element ID: #{xget_id} - Title24 Climate Zone: #{@climate_zone_ca_t24}")
|
106
|
+
else
|
107
|
+
@climate_zone_ca_t24 = nil
|
108
|
+
end
|
109
|
+
|
110
|
+
if @climate_zone_ashrae.nil? && @climate_zone_ca_t24.nil?
|
111
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.LocationElement.read_climate_zone', "Element ID: #{xget_id} - Title24 Climate Zone and ASHRAE Climate Zone not found")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# read city and state name
|
116
|
+
def read_city_and_state_name
|
117
|
+
if @base_xml.elements["#{@ns}:Address/#{@ns}:City"]
|
118
|
+
@city_name = @base_xml.elements["#{@ns}:Address/#{@ns}:City"].text
|
119
|
+
else
|
120
|
+
@city_name = nil
|
121
|
+
end
|
122
|
+
if @base_xml.elements["#{@ns}:Address/#{@ns}:State"]
|
123
|
+
@state_name = @base_xml.elements["#{@ns}:Address/#{@ns}:State"].text
|
124
|
+
else
|
125
|
+
@state_name = nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|