openstudio-geb 0.0.1 → 0.0.3r

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/measure.rb +1 -1
  4. data/lib/measures/add_chilled_water_storage_tank/measure.rb +167 -36
  5. data/lib/measures/add_chilled_water_storage_tank/tests/restaurant.osm +12189 -0
  6. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/LICENSE.md +0 -0
  7. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/README.md +0 -0
  8. data/lib/measures/{Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation → add_rooftop_pv_simple}/README.md.erb +0 -0
  9. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/measure.rb +0 -0
  10. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/measure.xml +0 -0
  11. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/tests/CZ06RV2.epw +0 -0
  12. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/tests/add_rooftop_pv_test.rb +0 -0
  13. data/lib/measures/{add_rooftop_pv → add_rooftop_pv_simple}/tests/pv_test_input.osm +0 -0
  14. data/lib/measures/average_ventilation_for_peak_hours/measure.rb +22 -11
  15. data/lib/measures/average_ventilation_for_peak_hours/tests/LargeOffice-90.1-2013-ASHRAE 169-2013-5A.osm +21863 -0
  16. data/lib/measures/reduce_epd_by_percentage_for_peak_hours/measure.rb +94 -95
  17. data/lib/openstudio/geb/utilities.rb +34 -6
  18. data/lib/openstudio/geb/version.rb +1 -1
  19. data/openstudio-geb.gemspec +1 -1
  20. metadata +15 -129
  21. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/files/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw +0 -8768
  22. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/files/USA_NY_Buffalo.Niagara.Intl.AP.725280_TMY3.epw +0 -8768
  23. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation/LICENSE.md +0 -27
  24. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation/README.md +0 -32
  25. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation/measure.rb +0 -156
  26. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation/measure.xml +0 -117
  27. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation/tests/0320_ModelWithHVAC_01.osm +0 -22223
  28. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Enable Demand Controlled Ventilation/tests/EnableDemandControlledVentilation_Test.rb +0 -123
  29. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/LICENSE.md +0 -27
  30. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/README.md +0 -136
  31. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/README.md.erb +0 -47
  32. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/measure.rb +0 -586
  33. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/measure.xml +0 -200
  34. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/tests/EnvelopeAndLoadTestModel_01.osm +0 -14352
  35. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/tests/EnvelopeAndLoadTestModel_01_Costed.osm +0 -14438
  36. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/tests/HasSpaceWithNoLightsOrElec.osm +0 -16531
  37. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/measures/Set Electric Equipment loads by EPD/tests/ReplaceElectricEquipmentWithEPD_Test.rb +0 -592
  38. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/out.osw +0 -68
  39. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/reports/eplustbl.html +0 -27183
  40. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/data_point.zip +0 -0
  41. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/data_point_out.json +0 -6
  42. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.audit +0 -49
  43. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.bnd +0 -1103
  44. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.eio +0 -630
  45. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.end +0 -1
  46. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.err +0 -331
  47. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.eso +0 -158559
  48. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.mdd +0 -336
  49. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.mtd +0 -2519
  50. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.rdd +0 -638
  51. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.shd +0 -902
  52. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusout.sql +0 -0
  53. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplusssz.csv +0 -147
  54. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/eplustbl.htm +0 -27183
  55. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/epluszsz.csv +0 -148
  56. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/finished.job +0 -1
  57. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/in.idf +0 -10384
  58. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/in.osm +0 -13809
  59. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/measure_attributes.json +0 -6
  60. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/objectives.json +0 -2
  61. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/pre-preprocess.idf +0 -10134
  62. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/results.json +0 -6
  63. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/run.log +0 -0
  64. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/sqlite.err +0 -1
  65. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/started.job +0 -1
  66. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/stdout-energyplus +0 -271
  67. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/run/stdout-expandobject +0 -3
  68. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/stderr +0 -0
  69. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/stdout +0 -0
  70. data/lib/measures/Enable Demand Controlled Ventilation/tests/MediumOffice-90.1-2010-ASHRAE 169-2013-5A_dcv/workflow.osw +0 -19
  71. data/lib/measures/add_rooftop_pv/README.md.erb +0 -42
  72. data/lib/measures/average_ventilation_for_peak_hours/tests/example_model.osm +0 -8077
@@ -1,586 +0,0 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
3
- # All rights reserved.
4
- # Redistribution and use in source and binary forms, with or without
5
- # modification, are permitted provided that the following conditions are met:
6
- #
7
- # (1) Redistributions of source code must retain the above copyright notice,
8
- # this list of conditions and the following disclaimer.
9
- #
10
- # (2) Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- #
14
- # (3) Neither the name of the copyright holder nor the names of any contributors
15
- # may be used to endorse or promote products derived from this software without
16
- # specific prior written permission from the respective party.
17
- #
18
- # (4) Other than as required in clauses (1) and (2), distributions in any form
19
- # of modifications or other derivative works may not use the "OpenStudio"
20
- # trademark, "OS", "os", or any other confusingly similar designation without
21
- # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
- #
23
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
24
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25
- # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
27
- # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
28
- # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32
- # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
- # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- # *******************************************************************************
35
-
36
- # start the measure
37
- class SetElectricEquipmentLoadsByEPD < OpenStudio::Measure::ModelMeasure
38
- # define the name that a user will see
39
- def name
40
- return 'Set Electric Equipment loads by EPD'
41
- end
42
-
43
- # human readable description
44
- def description
45
- return 'Set the electric equipment power density (W/ft^2) in the to a specified value for all spaces that have electric equipment. This can be applied to the entire building or a specific space type. Cost can be added per floor area'
46
- end
47
-
48
- # human readable description of modeling approach
49
- def modeler_description
50
- return 'Delete all of the existing electric equipment in the model. Add electric equipment with the user defined electric equipment power density to all spaces that initially had electric equipment, using the schedule from the original electric equipment. If multiple electric equipment existed the schedule will be pulled from the one with the highest electric equipment power density value. Demolition costs from electric equipment removed by this measure can be included in the analysis.'
51
- end
52
-
53
- # define the arguments that the user will input
54
- def arguments(model)
55
- args = OpenStudio::Measure::OSArgumentVector.new
56
-
57
- # make a choice argument for model objects
58
- space_type_handles = OpenStudio::StringVector.new
59
- space_type_display_names = OpenStudio::StringVector.new
60
-
61
- # putting model object and names into hash
62
- space_type_args = model.getSpaceTypes
63
- space_type_args_hash = {}
64
- space_type_args.each do |space_type_arg|
65
- space_type_args_hash[space_type_arg.name.to_s] = space_type_arg
66
- end
67
-
68
- # looping through sorted hash of model objects
69
- space_type_args_hash.sort.map do |key, value|
70
- # only include if space type is used in the model
71
- if !value.spaces.empty?
72
- space_type_handles << value.handle.to_s
73
- space_type_display_names << key
74
- end
75
- end
76
-
77
- # add building to string vector with space type
78
- building = model.getBuilding
79
- space_type_handles << building.handle.to_s
80
- space_type_display_names << '*Entire Building*'
81
-
82
- # make a choice argument for space type or entire building
83
- space_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('space_type', space_type_handles, space_type_display_names, true)
84
- space_type.setDisplayName('Apply the Measure to a Specific Space Type or to the Entire Model')
85
- space_type.setDefaultValue('*Entire Building*') # if no space type is chosen this will run on the entire building
86
- args << space_type
87
-
88
- # make an argument EPD
89
- epd = OpenStudio::Measure::OSArgument.makeDoubleArgument('epd', true)
90
- epd.setDisplayName('Lighting Power Density (W/ft^2)')
91
- epd.setDefaultValue(1.0)
92
- args << epd
93
-
94
- # add in argument to add electric equipment to all spaces that are included in building floor area even if original space didn't have electric equipment
95
- add_instance_all_spaces = OpenStudio::Measure::OSArgument.makeBoolArgument('add_instance_all_spaces', true)
96
- add_instance_all_spaces.setDisplayName('Add electric equipment to all spaces included in floor area, including spaces that did not originally include electric equipment')
97
- add_instance_all_spaces.setDefaultValue(false)
98
- args << add_instance_all_spaces
99
-
100
- # make an argument for material and installation cost
101
- material_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('material_cost', true)
102
- material_cost.setDisplayName('Material and Installation Costs for Lights per Floor Area ($/ft^2).')
103
- material_cost.setDefaultValue(0.0)
104
- args << material_cost
105
-
106
- # make an argument for demolition cost
107
- demolition_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('demolition_cost', true)
108
- demolition_cost.setDisplayName('Demolition Costs for Lights per Floor Area ($/ft^2).')
109
- demolition_cost.setDefaultValue(0.0)
110
- args << demolition_cost
111
-
112
- # make an argument for duration in years until costs start
113
- years_until_costs_start = OpenStudio::Measure::OSArgument.makeIntegerArgument('years_until_costs_start', true)
114
- years_until_costs_start.setDisplayName('Years Until Costs Start (whole years).')
115
- years_until_costs_start.setDefaultValue(0)
116
- args << years_until_costs_start
117
-
118
- # make an argument to determine if demolition costs should be included in initial construction
119
- demo_cost_initial_const = OpenStudio::Measure::OSArgument.makeBoolArgument('demo_cost_initial_const', true)
120
- demo_cost_initial_const.setDisplayName('Demolition Costs Occur During Initial Construction?')
121
- demo_cost_initial_const.setDefaultValue(false)
122
- args << demo_cost_initial_const
123
-
124
- # make an argument for expected life
125
- expected_life = OpenStudio::Measure::OSArgument.makeIntegerArgument('expected_life', true)
126
- expected_life.setDisplayName('Expected Life (whole years).')
127
- expected_life.setDefaultValue(20)
128
- args << expected_life
129
-
130
- # make an argument for o&m cost
131
- om_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('om_cost', true)
132
- om_cost.setDisplayName('O & M Costs for Lights per Floor Area ($/ft^2).')
133
- om_cost.setDefaultValue(0.0)
134
- args << om_cost
135
-
136
- # make an argument for o&m frequency
137
- om_frequency = OpenStudio::Measure::OSArgument.makeIntegerArgument('om_frequency', true)
138
- om_frequency.setDisplayName('O & M Frequency (whole years).')
139
- om_frequency.setDefaultValue(1)
140
- args << om_frequency
141
-
142
- return args
143
- end
144
-
145
- # define what happens when the measure is run
146
- def run(model, runner, user_arguments)
147
- super(model, runner, user_arguments)
148
-
149
- # use the built-in error checking
150
- if !runner.validateUserArguments(arguments(model), user_arguments)
151
- return false
152
- end
153
-
154
- # assign the user inputs to variables
155
- object = runner.getOptionalWorkspaceObjectChoiceValue('space_type', user_arguments, model)
156
- epd = runner.getDoubleArgumentValue('epd', user_arguments)
157
- add_instance_all_spaces = runner.getBoolArgumentValue('add_instance_all_spaces', user_arguments)
158
- material_cost = runner.getDoubleArgumentValue('material_cost', user_arguments)
159
- demolition_cost = runner.getDoubleArgumentValue('demolition_cost', user_arguments)
160
- years_until_costs_start = runner.getIntegerArgumentValue('years_until_costs_start', user_arguments)
161
- demo_cost_initial_const = runner.getBoolArgumentValue('demo_cost_initial_const', user_arguments)
162
- expected_life = runner.getIntegerArgumentValue('expected_life', user_arguments)
163
- om_cost = runner.getDoubleArgumentValue('om_cost', user_arguments)
164
- om_frequency = runner.getIntegerArgumentValue('om_frequency', user_arguments)
165
-
166
- # check the space_type for reasonableness and see if measure should run on space type or on the entire building
167
- apply_to_building = false
168
- space_type = nil
169
- if object.empty?
170
- handle = runner.getStringArgumentValue('space_type', user_arguments)
171
- if handle.empty?
172
- runner.registerError('No SpaceType was chosen.')
173
- else
174
- runner.registerError("The selected space type with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
175
- end
176
- return false
177
- else
178
- if !object.get.to_SpaceType.empty?
179
- space_type = object.get.to_SpaceType.get
180
- elsif !object.get.to_Building.empty?
181
- apply_to_building = true
182
- # space_type = model.getSpaceTypes
183
- else
184
- runner.registerError('Script Error - argument not showing up as space type or building.')
185
- return false
186
- end
187
- end
188
-
189
- # check the epd for reasonableness
190
- if (epd < 0) || (epd > 50)
191
- runner.registerError("A Lighting Power Density of #{epd} W/ft^2 is above the measure limit.")
192
- return false
193
- elsif epd > 21
194
- runner.registerWarning("A Lighting Power Density of #{epd} W/ft^2 is abnormally high.")
195
- end
196
-
197
- # set flags to use later
198
- costs_requested = false
199
-
200
- # check costs for reasonableness
201
- if material_cost.abs + demolition_cost.abs + om_cost.abs == 0
202
- runner.registerInfo('No costs were requested for Exterior Lights.')
203
- else
204
- costs_requested = true
205
- end
206
-
207
- # check lifecycle arguments for reasonableness
208
- if (years_until_costs_start < 0) && (years_until_costs_start > expected_life)
209
- runner.registerError('Years until costs start should be a non-negative integer less than Expected Life.')
210
- end
211
- if (expected_life < 1) && (expected_life > 100)
212
- runner.registerError('Choose an integer greater than 0 and less than or equal to 100 for Expected Life.')
213
- end
214
- if om_frequency < 1
215
- runner.registerError('Choose an integer greater than 0 for O & M Frequency.')
216
- end
217
-
218
- # helper to make it easier to do unit conversions on the fly. The definition be called through this measure.
219
- def unit_helper(number, from_unit_string, to_unit_string)
220
- converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value
221
- end
222
-
223
- # short def to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001). The definition be called through this measure
224
- def neat_numbers(number, roundto = 2) # round to 0 or 2)
225
- if roundto == 2
226
- number = format '%.2f', number
227
- else
228
- number = number.round
229
- end
230
- # regex to add commas
231
- number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
232
- end
233
-
234
- # helper that loops through lifecycle costs getting total costs under "Construction" or "Salvage" category and add to counter if occurs during year 0
235
- def get_total_costs_for_objects(objects)
236
- counter = 0
237
- objects.each do |object|
238
- object_LCCs = object.lifeCycleCosts
239
- object_LCCs.each do |object_LCC|
240
- if (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
241
- if object_LCC.yearsFromStart == 0
242
- counter += object_LCC.totalCost
243
- end
244
- end
245
- end
246
- end
247
- return counter
248
- end
249
-
250
- # helper def to add to demo cost related to baseline objects
251
- def add_to_baseline_demo_cost_counter(baseline_object) # removed if statement from def
252
- counter = 0
253
- baseline_object_LCCs = baseline_object.lifeCycleCosts
254
- baseline_object_LCCs.each do |baseline_object_LCC|
255
- if baseline_object_LCC.category == 'Salvage'
256
- counter += baseline_object_LCC.totalCost
257
- end
258
- end
259
- return counter
260
- end
261
-
262
- # setup OpenStudio units that we will need
263
- unit_epd_ip = OpenStudio.createUnit('W/ft^2').get
264
- unit_epd_si = OpenStudio.createUnit('W/m^2').get
265
-
266
- # define starting units
267
- epd_ip = OpenStudio::Quantity.new(epd, unit_epd_ip)
268
-
269
- # unit conversion of epd from IP units (W/ft^2) to SI units (W/m^2)
270
- epd_si = OpenStudio.convert(epd_ip, unit_epd_si).get
271
-
272
- # calculate the initial electric equipment
273
- elec_equip_defs = model.getElectricEquipmentDefinitions
274
- initial_electric_equipment_cost = 0
275
- initial_electric_equipment_cost += get_total_costs_for_objects(elec_equip_defs)
276
-
277
- # counter for demo cost of baseline objects
278
- demo_costs_of_baseline_objects = 0
279
-
280
- # get demo cost if all existing electric equipment
281
- if demo_cost_initial_const
282
- elec_equip_defs.each do |elec_equip_def|
283
- demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(elec_equip_def)
284
- end
285
- end
286
-
287
- # find most common electric equipment schedule for use in spaces that do not have electric equipment
288
- elec_equip_sch_hash = {}
289
- # add schedules or electric equipment directly assigned to space
290
- model.getSpaces.each do |space|
291
- space.electricEquipment.each do |elec_equip|
292
- if elec_equip.schedule.is_initialized
293
- sch = elec_equip.schedule.get
294
- if elec_equip_sch_hash.key?(sch)
295
- elec_equip_sch_hash[sch] += 1
296
- else
297
- elec_equip_sch_hash[sch] = 1
298
- end
299
- end
300
- end
301
- # add schedule for electric equipment assigned to space types
302
- if space.spaceType.is_initialized
303
- space.spaceType.get.electricEquipment.each do |elec_equip|
304
- if elec_equip.schedule.is_initialized
305
- sch = elec_equip.schedule.get
306
- if elec_equip_sch_hash.key?(sch)
307
- elec_equip_sch_hash[sch] += 1
308
- else
309
- elec_equip_sch_hash[sch] = 1
310
- end
311
- end
312
- end
313
- end
314
- end
315
- most_comm_sch = elec_equip_sch_hash.key(elec_equip_sch_hash.values.max)
316
-
317
- # report initial condition
318
- building = model.getBuilding
319
- building_start_epd_si = OpenStudio::Quantity.new(building.electricEquipmentPowerPerFloorArea, unit_epd_si)
320
- building_start_epd_ip = OpenStudio.convert(building_start_epd_si, unit_epd_ip).get
321
- runner.registerInitialCondition("The model's initial EPD is #{building_start_epd_ip}. Initial Year 0 cost for building electric equipment is $#{neat_numbers(initial_electric_equipment_cost, 0)}.")
322
-
323
- # add if statement for NA if EPD = 0
324
- if building_start_epd_ip.value <= 0
325
- runner.registerAsNotApplicable('The model has no electric equipment, nothing will be changed.')
326
- end
327
-
328
- # create a new ElectricEquipmentDefinition and new Lights object to use with setLightingPowerPerFloorArea
329
- template_elec_equip_def = OpenStudio::Model::ElectricEquipmentDefinition.new(model)
330
- template_elec_equip_def.setName("EPD #{epd_ip} - ElecEquipDef")
331
- template_elec_equip_def.setWattsperSpaceFloorArea(epd_si.value)
332
-
333
- template_elec_equip_inst = OpenStudio::Model::ElectricEquipment.new(template_elec_equip_def)
334
- template_elec_equip_inst.setName("EPD #{epd_ip} - ElecEquipInstance")
335
-
336
- # add lifeCycleCost objects if there is a non-zero value in one of the cost arguments
337
- if costs_requested == true
338
-
339
- starting_lcc_counter = template_elec_equip_def.lifeCycleCosts.size
340
-
341
- # get si input values for lcc objects
342
- material_cost_si = unit_helper(material_cost, '1/ft^2', '1/m^2')
343
- demolition_cost_si = unit_helper(demolition_cost, '1/ft^2', '1/m^2')
344
- om_cost_si = unit_helper(om_cost, '1/ft^2', '1/m^2')
345
-
346
- # adding new cost items
347
- lcc_mat = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Mat - #{template_elec_equip_def.name}", template_elec_equip_def, material_cost_si, 'CostPerArea', 'Construction', expected_life, years_until_costs_start)
348
- lcc_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_Demo - #{template_elec_equip_def.name}", template_elec_equip_def, demolition_cost_si, 'CostPerArea', 'Salvage', expected_life, years_until_costs_start + expected_life)
349
- lcc_om = OpenStudio::Model::LifeCycleCost.createLifeCycleCost("LCC_OM - #{template_elec_equip_def.name}", template_elec_equip_def, om_cost_si, 'CostPerArea', 'Maintenance', om_frequency, 0)
350
-
351
- if template_elec_equip_def.lifeCycleCosts.size - starting_lcc_counter != 3
352
- runner.registerWarning("The measure did not function as expected. #{template_elec_equip_def.lifeCycleCosts.size - starting_lcc_counter} LifeCycleCost objects were made, 3 were expected.")
353
- end
354
-
355
- end
356
-
357
- # show as not applicable if no cost requested
358
- if costs_requested == false
359
- runner.registerAsNotApplicable('No new lifecycle costs objects were requested.')
360
- end
361
-
362
- # get space types in model
363
- if apply_to_building
364
- space_types = model.getSpaceTypes
365
- else
366
- space_types = []
367
- space_types << space_type # only run on a single space type
368
- end
369
-
370
- # loop through space types
371
- space_types.each do |space_type|
372
- space_type_electric_equipment = space_type.electricEquipment
373
- space_type_spaces = space_type.spaces
374
- multiple_schedules = false
375
-
376
- space_type_electric_equipment_array = []
377
-
378
- # if space type has electric equipment and is used in the model
379
- if !space_type_electric_equipment.empty? && !space_type_spaces.empty?
380
- electric_equipment_schedules = []
381
- space_type_electric_equipment.each do |space_type_elec_equip|
382
- electric_equipment_data_for_array = []
383
- if !space_type_elec_equip.schedule.empty?
384
- space_type_elec_equip_new_schedule = space_type_elec_equip.schedule
385
- if !space_type_elec_equip_new_schedule.empty?
386
- electric_equipment_schedules << space_type_elec_equip.powerPerFloorArea
387
- if !space_type_elec_equip.powerPerFloorArea.empty?
388
- electric_equipment_data_for_array << space_type_elec_equip.powerPerFloorArea.get
389
- else
390
- electric_equipment_data_for_array << 0.0
391
- end
392
- electric_equipment_data_for_array << space_type_elec_equip_new_schedule.get
393
- electric_equipment_data_for_array << space_type_elec_equip.isScheduleDefaulted
394
- space_type_electric_equipment_array << electric_equipment_data_for_array
395
- end
396
- end
397
- end
398
-
399
- # pick schedule to use and see if it is defaulted
400
- space_type_electric_equipment_array = space_type_electric_equipment_array.sort.reverse[0]
401
- if !space_type_electric_equipment_array.nil? # this is need if schedule is empty but also not defaulted
402
- if space_type_electric_equipment_array[2] != true # if not schedule defaulted
403
- preferred_schedule = space_type_electric_equipment_array[1]
404
- else
405
- # leave schedule blank, it is defaulted
406
- end
407
- end
408
-
409
- # flag if electric_equipment_schedules has more than one unique object
410
- if electric_equipment_schedules.uniq.size > 1
411
- multiple_schedules = true
412
- end
413
-
414
- # delete electric equipment and add in new electric equipment.
415
- space_type_electric_equipment = space_type.electricEquipment
416
- space_type_electric_equipment.each(&:remove)
417
- space_type_elec_equip_new = template_elec_equip_inst.clone(model)
418
- space_type_elec_equip_new = space_type_elec_equip_new.to_ElectricEquipment.get
419
- space_type_elec_equip_new.setSpaceType(space_type)
420
-
421
- # assign preferred schedule to new electric equipment object
422
- if defined? space_type_electric_equipment_array
423
- if !space_type_elec_equip_new.schedule.empty? && (space_type_electric_equipment_array[2] != true)
424
- space_type_elec_equip_new.setSchedule(preferred_schedule)
425
- end
426
- else
427
- runner.registerWarning("Not adding schedule for electric equipment in #{space_type.name}, no original electric equipment to harvest schedule from.")
428
- end
429
-
430
- # if schedules had to be removed due to multiple electric equipment add warning
431
- if !space_type_elec_equip_new.schedule.empty? && (multiple_schedules == true)
432
- space_type_elec_equip_new_schedule = space_type_elec_equip_new.schedule
433
- runner.registerWarning("The space type named '#{space_type.name}' had more than one electric equipment object with unique schedules. The schedule named '#{space_type_elec_equip_new_schedule.get.name}' was used for the new EPD electric equipment object.")
434
- end
435
-
436
- elsif space_type_electric_equipment.empty? && !space_type_spaces.empty?
437
- runner.registerInfo("The space type named '#{space_type.name}' doesn't have any electric equipment, none will be added.")
438
- end
439
- end
440
-
441
- # getting spaces in the model
442
- spaces = model.getSpaces
443
-
444
- # get space types in model
445
- if apply_to_building
446
- spaces = model.getSpaces
447
- else
448
- if !space_type.spaces.empty?
449
- spaces = space_type.spaces # only run on a single space type
450
- end
451
- end
452
-
453
- spaces.each do |space|
454
- space_electric_equipment = space.electricEquipment
455
- space_space_type = space.spaceType
456
- if !space_space_type.empty?
457
- space_space_type_electric_equipment = space_space_type.get.electricEquipment
458
- else
459
- space_space_type_electric_equipment = []
460
- end
461
-
462
- # array to manage electric equipment schedules within a space
463
- space_electric_equipment_array = []
464
-
465
- # if space has electric equipment and space type also has electric equipment
466
- if !space_electric_equipment.empty? && !space_space_type_electric_equipment.empty?
467
-
468
- # loop through and remove all electric equipment
469
- space_electric_equipment.each(&:remove)
470
- runner.registerWarning("The space named '#{space.name}' had one or more electric equipment objects. These were deleted and a new EPD electric equipment object was added to the parent space type named '#{space_space_type.get.name}'.")
471
-
472
- elsif !space_electric_equipment.empty? && space_space_type_electric_equipment.empty?
473
-
474
- # inspect schedules for electric equipment objects
475
- multiple_schedules = false
476
- electric_equipment_schedules = []
477
- space_electric_equipment.each do |space_elec_equip|
478
- electric_equipment_data_for_array = []
479
- if !space_elec_equip.schedule.empty?
480
- space_elec_equip_new_schedule = space_elec_equip.schedule
481
- if !space_elec_equip_new_schedule.empty?
482
- electric_equipment_schedules << space_elec_equip.powerPerFloorArea
483
- if !space_elec_equip.powerPerFloorArea.empty?
484
- electric_equipment_data_for_array << space_elec_equip.powerPerFloorArea.get
485
- else
486
- electric_equipment_data_for_array << 0.0
487
- end
488
- electric_equipment_data_for_array << space_elec_equip_new_schedule.get
489
- electric_equipment_data_for_array << space_elec_equip.isScheduleDefaulted
490
- space_electric_equipment_array << electric_equipment_data_for_array
491
- end
492
- end
493
- end
494
-
495
- # pick schedule to use and see if it is defaulted
496
- space_electric_equipment_array = space_electric_equipment_array.sort.reverse[0]
497
- if !space_electric_equipment_array.nil?
498
- if space_electric_equipment_array[2] != true
499
- preferred_schedule = space_electric_equipment_array[1]
500
- else
501
- # leave schedule blank, it is defaulted
502
- end
503
- end
504
-
505
- # flag if electric_equipment_schedules has more than one unique object
506
- if electric_equipment_schedules.uniq.size > 1
507
- multiple_schedules = true
508
- end
509
-
510
- # delete electric equipment and add in new electric equipment
511
- space_electric_equipment.each(&:remove)
512
- space_elec_equip_new = template_elec_equip_inst.clone(model)
513
- space_elec_equip_new = space_elec_equip_new.to_ElectricEquipment.get
514
- space_elec_equip_new.setSpace(space)
515
-
516
- # assign preferred schedule to new electric equipment object
517
- if defined? space_type_electric_equipment_array
518
- if !space_elec_equip_new.schedule.empty? && (space_type_electric_equipment_array[2] != true)
519
- space_elec_equip_new.setSchedule(preferred_schedule)
520
- end
521
- else
522
- runner.registerWarning("Not adding schedule for electric equipment in #{space.name}, no original electric equipment to harvest schedule from.")
523
- end
524
-
525
- # if schedules had to be removed due to multiple electric equipment add warning here
526
- if !space_elec_equip_new.schedule.empty? && (multiple_schedules == true)
527
- space_elec_equip_new_schedule = space_elec_equip_new.schedule
528
- runner.registerWarning("The space type named '#{space.name}' had more than one electric equipment object with unique schedules. The schedule named '#{space_elec_equip_new_schedule.get.name}' was used for the new EPD electric equipment object.")
529
- end
530
-
531
- elsif space_electric_equipment.empty? && space_space_type_electric_equipment.empty?
532
-
533
- # add in electric equipment for spaces that do not have any with most common schedule
534
- if add_instance_all_spaces && space.partofTotalFloorArea
535
- space_elec_equip_new = template_elec_equip_inst.clone(model)
536
- space_elec_equip_new = space_elec_equip_new.to_ElectricEquipment.get
537
- space_elec_equip_new.setSpace(space)
538
- space_elec_equip_new.setSchedule(most_comm_sch)
539
- runner.registerInfo("Adding electric equipment to #{space.name} using #{most_comm_sch.name} as fractional schedule.")
540
- else
541
- # issue warning that the space does not have any direct or inherited electric equipment.
542
- runner.registerInfo("The space named '#{space.name}' does not have any direct or inherited electric equipment. No electric equipment object was added")
543
- end
544
-
545
- end
546
- end
547
-
548
- # subtract demo cost of electric equipment that were not deleted so the demo costs are not counted
549
- if demo_cost_initial_const
550
- elec_equip_defs.each do |elec_equip_def| # this does not loop through the new def (which is the desired behavior)
551
- demo_costs_of_baseline_objects += -1 * add_to_baseline_demo_cost_counter(elec_equip_def)
552
- puts "#{elec_equip_def.name},#{add_to_baseline_demo_cost_counter(elec_equip_def)}"
553
- end
554
- end
555
-
556
- # clean up template electric equipment instance. Will EnergyPlus will fail if you have an instance that isn't associated with a space or space type
557
- template_elec_equip_inst.remove
558
-
559
- # calculate the final electric equipment and cost for initial condition.
560
- elec_equip_defs = model.getElectricEquipmentDefinitions # this is done again to get the new def made by the measure
561
- final_electric_equipment_cost = 0
562
- final_electric_equipment_cost += get_total_costs_for_objects(elec_equip_defs)
563
-
564
- # add one time demo cost of removed electric equipment if appropriate
565
- if demo_cost_initial_const == true
566
- building = model.getBuilding
567
- lcc_baseline_demo = OpenStudio::Model::LifeCycleCost.createLifeCycleCost('LCC_baseline_demo', building, demo_costs_of_baseline_objects, 'CostPerEach', 'Salvage', 0, years_until_costs_start).get # using 0 for repeat period since one time cost.
568
- runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost, 0)} related to demolition of baseline objects.")
569
-
570
- # if demo occurs on year 0 then add to initial capital cost counter
571
- if lcc_baseline_demo.yearsFromStart == 0
572
- final_electric_equipment_cost += lcc_baseline_demo.totalCost
573
- end
574
- end
575
-
576
- # report final condition
577
- building_final_epd_si = OpenStudio::Quantity.new(building.electricEquipmentPowerPerFloorArea, unit_epd_si)
578
- building_final_epd_ip = OpenStudio.convert(building_final_epd_si, unit_epd_ip).get
579
- runner.registerFinalCondition("Your model's final EPD is #{building_final_epd_ip}. Final Year 0 cost for building electric equipment is $#{neat_numbers(final_electric_equipment_cost, 0)}.")
580
-
581
- return true
582
- end
583
- end
584
-
585
- # this allows the measure to be used by the application
586
- SetElectricEquipmentLoadsByEPD.new.registerWithApplication