buildingsync 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|