openstudio-common-measures 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +6 -3
  4. data/Rakefile +17 -3
  5. data/lib/measures/AddDaylightSensors/LICENSE.md +27 -0
  6. data/lib/measures/AddDaylightSensors/README.md +136 -0
  7. data/lib/measures/AddDaylightSensors/README.md.erb +42 -0
  8. data/lib/measures/AddDaylightSensors/measure.rb +521 -0
  9. data/lib/measures/AddDaylightSensors/measure.xml +233 -0
  10. data/lib/measures/EnableDemandControlledVentilation/LICENSE.md +27 -0
  11. data/lib/measures/EnableDemandControlledVentilation/README.md +32 -0
  12. data/lib/measures/EnableDemandControlledVentilation/README.md.erb +42 -0
  13. data/lib/measures/EnableDemandControlledVentilation/measure.rb +154 -0
  14. data/lib/measures/EnableDemandControlledVentilation/measure.xml +99 -0
  15. data/lib/measures/EnableEconomizerControl/LICENSE.md +27 -0
  16. data/lib/measures/EnableEconomizerControl/README.md +48 -0
  17. data/lib/measures/EnableEconomizerControl/README.md.erb +42 -0
  18. data/lib/measures/EnableEconomizerControl/measure.rb +172 -0
  19. data/lib/measures/EnableEconomizerControl/measure.xml +124 -0
  20. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/LICENSE.md +27 -0
  21. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/README.md +64 -0
  22. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/README.md.erb +42 -0
  23. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/measure.rb +422 -0
  24. data/lib/measures/IncreaseInsulationRValueForExteriorWalls/measure.xml +150 -0
  25. data/lib/measures/IncreaseInsulationRValueForRoofs/LICENSE.md +27 -0
  26. data/lib/measures/IncreaseInsulationRValueForRoofs/README.md +64 -0
  27. data/lib/measures/IncreaseInsulationRValueForRoofs/README.md.erb +42 -0
  28. data/lib/measures/IncreaseInsulationRValueForRoofs/measure.rb +422 -0
  29. data/lib/measures/IncreaseInsulationRValueForRoofs/measure.xml +143 -0
  30. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/LICENSE.md +27 -0
  31. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/README.md +97 -0
  32. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/README.md.erb +42 -0
  33. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/measure.rb +450 -0
  34. data/lib/measures/ReduceElectricEquipmentLoadsByPercentage/measure.xml +186 -0
  35. data/lib/measures/ReduceLightingLoadsByPercentage/LICENSE.md +27 -0
  36. data/lib/measures/ReduceLightingLoadsByPercentage/README.md +96 -0
  37. data/lib/measures/ReduceLightingLoadsByPercentage/README.md.erb +42 -0
  38. data/lib/measures/ReduceLightingLoadsByPercentage/measure.rb +513 -0
  39. data/lib/measures/ReduceLightingLoadsByPercentage/measure.xml +191 -0
  40. data/lib/measures/ReduceSpaceInfiltrationByPercentage/LICENSE.md +27 -0
  41. data/lib/measures/ReduceSpaceInfiltrationByPercentage/README.md +104 -0
  42. data/lib/measures/ReduceSpaceInfiltrationByPercentage/README.md.erb +42 -0
  43. data/lib/measures/ReduceSpaceInfiltrationByPercentage/measure.rb +349 -0
  44. data/lib/measures/ReduceSpaceInfiltrationByPercentage/measure.xml +181 -0
  45. data/lib/measures/ReduceVentilationByPercentage/LICENSE.md +27 -0
  46. data/lib/measures/ReduceVentilationByPercentage/README.md +40 -0
  47. data/lib/measures/ReduceVentilationByPercentage/README.md.erb +42 -0
  48. data/lib/measures/ReduceVentilationByPercentage/measure.rb +291 -0
  49. data/lib/measures/ReduceVentilationByPercentage/measure.xml +96 -0
  50. data/lib/measures/add_ems_to_control_ev_charging/{ReadMe.MD → README.md} +0 -0
  51. data/lib/measures/add_ev_load/{ReadMe.MD → README.md} +0 -0
  52. data/lib/measures/create_variable_speed_rtu/LICENSE.md +27 -0
  53. data/lib/measures/create_variable_speed_rtu/README.md +120 -0
  54. data/lib/measures/create_variable_speed_rtu/README.md.erb +42 -0
  55. data/lib/measures/create_variable_speed_rtu/measure.rb +539 -0
  56. data/lib/measures/create_variable_speed_rtu/measure.xml +207 -0
  57. data/lib/measures/generic_qaqc/measure.xml +14 -14
  58. data/lib/measures/generic_qaqc/resources/check_envelope_conductance.rb +7 -1
  59. data/lib/measures/generic_qaqc/resources/check_eui_by_end_use.rb +10 -11
  60. data/lib/measures/openstudio_results/README.md +5 -1
  61. data/lib/measures/openstudio_results/measure.rb +12 -8
  62. data/lib/measures/openstudio_results/measure.xml +56 -36
  63. data/lib/measures/openstudio_results/resources/os_lib_reporting.rb +115 -37
  64. data/lib/measures/openstudio_results/resources/os_lib_schedules.rb +27 -25
  65. data/lib/measures/set_exterior_walls_and_floors_to_adiabatic/README.md +16 -0
  66. data/lib/measures/set_exterior_walls_and_floors_to_adiabatic/measure.rb +32 -1
  67. data/lib/measures/set_exterior_walls_and_floors_to_adiabatic/measure.xml +31 -12
  68. data/lib/measures/view_data/measure.xml +8 -8
  69. data/lib/measures/view_data/resources/va3c.rb +50 -46
  70. data/lib/measures/view_model/resources/va3c.rb +50 -46
  71. data/lib/openstudio/common_measures/version.rb +1 -1
  72. data/openstudio-common-measures.gemspec +2 -2
  73. metadata +59 -9
@@ -0,0 +1,186 @@
1
+ <measure>
2
+ <schema_version>3.0</schema_version>
3
+ <name>reduce_electric_equipment_loads_by_percentage</name>
4
+ <uid>0902e302-70db-4339-99b0-17f08bc93629</uid>
5
+ <version_id>3edc28aa-ab1d-4495-affa-d8e5873431b1</version_id>
6
+ <version_modified>20200229T024319Z</version_modified>
7
+ <xml_checksum>F9A5B8F0</xml_checksum>
8
+ <class_name>ReduceElectricEquipmentLoadsByPercentage</class_name>
9
+ <display_name>Reduce Electric Equipment Loads by Percentage</display_name>
10
+ <description>Reduce Electric Equipment Loads by Percentage&lt;/display_name>
11
+ &lt;description>Reduce electric equipment loads. This will affect equipment that have a, power, power per area (LPD), or power per person value. This can be applied to the entire building or a specific space type. A positive percentage represents an increase electric equipment power, while a negative percentage can be used for an increase in electric equipment power.</description>
12
+ <modeler_description>Loop through all electric equipment objects in the specified space type or the entire building. Clone the definition if it has not already been cloned, rename and adjust the power based on the specified percentage. Link the new definition to the existing electric equipment instance. Loop through objects first in space types and then in spaces, but only for spaces that are in the specified space type, unless entire building has been chosen.</modeler_description>
13
+ <arguments>
14
+ <argument>
15
+ <name>space_type</name>
16
+ <display_name>Apply the Measure to a Specific Space Type or to the Entire Model</display_name>
17
+ <type>Choice</type>
18
+ <required>true</required>
19
+ <model_dependent>false</model_dependent>
20
+ <default_value>*Entire Building*</default_value>
21
+ <choices>
22
+ <choice>
23
+ <value>{56e1135b-dc93-4378-8702-058b66cecd23}</value>
24
+ <display_name>*Entire Building*</display_name>
25
+ </choice>
26
+ </choices>
27
+ </argument>
28
+ <argument>
29
+ <name>elecequip_power_reduction_percent</name>
30
+ <display_name>Electric Equipment Power Reduction</display_name>
31
+ <type>Double</type>
32
+ <units>%</units>
33
+ <required>true</required>
34
+ <model_dependent>false</model_dependent>
35
+ <default_value>30</default_value>
36
+ </argument>
37
+ <argument>
38
+ <name>material_and_installation_cost</name>
39
+ <display_name>Increase in Material and Installation Cost for Electric Equipment per Floor Area</display_name>
40
+ <type>Double</type>
41
+ <units>%</units>
42
+ <required>true</required>
43
+ <model_dependent>false</model_dependent>
44
+ <default_value>0</default_value>
45
+ </argument>
46
+ <argument>
47
+ <name>demolition_cost</name>
48
+ <display_name>Increase in Demolition Costs for Electric Equipment per Floor Area</display_name>
49
+ <type>Double</type>
50
+ <units>%</units>
51
+ <required>true</required>
52
+ <model_dependent>false</model_dependent>
53
+ <default_value>0</default_value>
54
+ </argument>
55
+ <argument>
56
+ <name>years_until_costs_start</name>
57
+ <display_name>Years Until Costs Start</display_name>
58
+ <type>Integer</type>
59
+ <units>whole years</units>
60
+ <required>true</required>
61
+ <model_dependent>false</model_dependent>
62
+ <default_value>0</default_value>
63
+ </argument>
64
+ <argument>
65
+ <name>demo_cost_initial_const</name>
66
+ <display_name>Demolition Costs Occur During Initial Construction</display_name>
67
+ <type>Boolean</type>
68
+ <required>true</required>
69
+ <model_dependent>false</model_dependent>
70
+ <default_value>false</default_value>
71
+ <choices>
72
+ <choice>
73
+ <value>true</value>
74
+ <display_name>true</display_name>
75
+ </choice>
76
+ <choice>
77
+ <value>false</value>
78
+ <display_name>false</display_name>
79
+ </choice>
80
+ </choices>
81
+ </argument>
82
+ <argument>
83
+ <name>expected_life</name>
84
+ <display_name>Expected Life</display_name>
85
+ <type>Integer</type>
86
+ <units>whole years</units>
87
+ <required>true</required>
88
+ <model_dependent>false</model_dependent>
89
+ <default_value>15</default_value>
90
+ </argument>
91
+ <argument>
92
+ <name>om_cost</name>
93
+ <display_name>Increase O &amp; M Costs for Electric Equipment per Floor Area</display_name>
94
+ <type>Double</type>
95
+ <units>%</units>
96
+ <required>true</required>
97
+ <model_dependent>false</model_dependent>
98
+ <default_value>0</default_value>
99
+ </argument>
100
+ <argument>
101
+ <name>om_frequency</name>
102
+ <display_name>O &amp; M Frequency</display_name>
103
+ <type>Integer</type>
104
+ <units>whole years</units>
105
+ <required>true</required>
106
+ <model_dependent>false</model_dependent>
107
+ <default_value>1</default_value>
108
+ </argument>
109
+ </arguments>
110
+ <outputs/>
111
+ <provenances/>
112
+ <tags>
113
+ <tag>Equipment.Electric Equipment</tag>
114
+ </tags>
115
+ <attributes>
116
+ <attribute>
117
+ <name>Measure Type</name>
118
+ <value>ModelMeasure</value>
119
+ <datatype>string</datatype>
120
+ </attribute>
121
+ <attribute>
122
+ <name>Measure Function</name>
123
+ <value>Measure</value>
124
+ <datatype>string</datatype>
125
+ </attribute>
126
+ <attribute>
127
+ <name>Requires EnergyPlus Results</name>
128
+ <value>false</value>
129
+ <datatype>boolean</datatype>
130
+ </attribute>
131
+ <attribute>
132
+ <name>Uses SketchUp API</name>
133
+ <value>false</value>
134
+ <datatype>boolean</datatype>
135
+ </attribute>
136
+ </attributes>
137
+ <files>
138
+ <file>
139
+ <filename>EnvelopeAndLoadTestModel_01.osm</filename>
140
+ <filetype>osm</filetype>
141
+ <usage_type>test</usage_type>
142
+ <checksum>138E2AAC</checksum>
143
+ </file>
144
+ <file>
145
+ <filename>EnvelopeAndLoadTestModel_01_FullyCosted.osm</filename>
146
+ <filetype>osm</filetype>
147
+ <usage_type>test</usage_type>
148
+ <checksum>38E06CA8</checksum>
149
+ </file>
150
+ <file>
151
+ <filename>README.md.erb</filename>
152
+ <filetype>erb</filetype>
153
+ <usage_type>readmeerb</usage_type>
154
+ <checksum>703C9964</checksum>
155
+ </file>
156
+ <file>
157
+ <filename>README.md</filename>
158
+ <filetype>md</filetype>
159
+ <usage_type>readme</usage_type>
160
+ <checksum>4FC6A4A7</checksum>
161
+ </file>
162
+ <file>
163
+ <filename>ReduceElectricEquipmentLoadsByPercentage_Test.rb</filename>
164
+ <filetype>rb</filetype>
165
+ <usage_type>test</usage_type>
166
+ <checksum>CE00BAC9</checksum>
167
+ </file>
168
+ <file>
169
+ <filename>LICENSE.md</filename>
170
+ <filetype>md</filetype>
171
+ <usage_type>license</usage_type>
172
+ <checksum>E0468DD6</checksum>
173
+ </file>
174
+ <file>
175
+ <version>
176
+ <software_program>OpenStudio</software_program>
177
+ <identifier>2.0.0</identifier>
178
+ <min_compatible>2.0.0</min_compatible>
179
+ </version>
180
+ <filename>measure.rb</filename>
181
+ <filetype>rb</filetype>
182
+ <usage_type>script</usage_type>
183
+ <checksum>0BB19691</checksum>
184
+ </file>
185
+ </files>
186
+ </measure>
@@ -0,0 +1,27 @@
1
+ OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted
4
+ provided that the following conditions are met:
5
+
6
+ (1) Redistributions of source code must retain the above copyright notice, this list of conditions
7
+ and the following disclaimer.
8
+
9
+ (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+
12
+ (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
13
+ or promote products derived from this software without specific prior written permission from the
14
+ respective party.
15
+
16
+ (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
17
+ derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
18
+ designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
21
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
23
+ OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,96 @@
1
+
2
+
3
+ ###### (Automatically generated documentation)
4
+
5
+ # Reduce Lighting Loads by Percentage
6
+
7
+ ## Description
8
+ The lighting system in this building uses more power per area than is required with the latest lighting technologies. Replace the lighting system with a newer, more efficient lighting technology. Newer technologies provide the same amount of light but use less energy in the process.
9
+
10
+ ## Modeler Description
11
+ This measure supports models which have a mixture of lighting assigned to spaces and space types. The lighting may be specified as individual luminaires, lighting equipment level, lighting power per area, or lighting power per person. Loop through all lights and luminaires in the specified space type or the entire building. Clone the definition if it is shared by other lights, rename and adjust the power based on the specified percentage. Link the new definition to the existing lights or luminaire instance. Adjust the power for lighting equipment assigned to a particular space but only if that space is part of the selected space type by looping through the objects first in space types and then in spaces, but again only for spaces that are in the specified space type (unless the entire building has been chosen). Material and installation cost increases will be applied to all costs related to both the definition and instance of the lighting object. If this measure includes baseline costs, then the material and installation costs of the lighting objects in the baseline model will be summed together and added as a capital cost on the building object.
12
+
13
+ ## Measure Type
14
+ ModelMeasure
15
+
16
+ ## Taxonomy
17
+
18
+
19
+ ## Arguments
20
+
21
+
22
+ ### Apply the Measure to a Specific Space Type or to the Entire Model
23
+
24
+ **Name:** space_type,
25
+ **Type:** Choice,
26
+ **Units:** ,
27
+ **Required:** true,
28
+ **Model Dependent:** false
29
+
30
+ ### Lighting Power Reduction
31
+
32
+ **Name:** lighting_power_reduction_percent,
33
+ **Type:** Double,
34
+ **Units:** %,
35
+ **Required:** true,
36
+ **Model Dependent:** false
37
+
38
+ ### Increase in Material and Installation Cost for Lighting per Floor Area
39
+
40
+ **Name:** material_and_installation_cost,
41
+ **Type:** Double,
42
+ **Units:** %,
43
+ **Required:** true,
44
+ **Model Dependent:** false
45
+
46
+ ### Increase in Demolition Costs for Lighting per Floor Area
47
+
48
+ **Name:** demolition_cost,
49
+ **Type:** Double,
50
+ **Units:** %,
51
+ **Required:** true,
52
+ **Model Dependent:** false
53
+
54
+ ### Years Until Costs Start
55
+
56
+ **Name:** years_until_costs_start,
57
+ **Type:** Integer,
58
+ **Units:** whole years,
59
+ **Required:** true,
60
+ **Model Dependent:** false
61
+
62
+ ### Demolition Costs Occur During Initial Construction
63
+
64
+ **Name:** demo_cost_initial_const,
65
+ **Type:** Boolean,
66
+ **Units:** ,
67
+ **Required:** true,
68
+ **Model Dependent:** false
69
+
70
+ ### Expected Life
71
+
72
+ **Name:** expected_life,
73
+ **Type:** Integer,
74
+ **Units:** whole years,
75
+ **Required:** true,
76
+ **Model Dependent:** false
77
+
78
+ ### Increase O & M Costs for Lighting per Floor Area
79
+
80
+ **Name:** om_cost,
81
+ **Type:** Double,
82
+ **Units:** %,
83
+ **Required:** true,
84
+ **Model Dependent:** false
85
+
86
+ ### O & M Frequency
87
+
88
+ **Name:** om_frequency,
89
+ **Type:** Integer,
90
+ **Units:** whole years,
91
+ **Required:** true,
92
+ **Model Dependent:** false
93
+
94
+
95
+
96
+
@@ -0,0 +1,42 @@
1
+ <%#= README.md.erb is used to auto-generate README.md. %>
2
+ <%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
3
+ ###### (Automatically generated documentation)
4
+
5
+ # <%= name %>
6
+
7
+ ## Description
8
+ <%= description %>
9
+
10
+ ## Modeler Description
11
+ <%= modelerDescription %>
12
+
13
+ ## Measure Type
14
+ <%= measureType %>
15
+
16
+ ## Taxonomy
17
+ <%= taxonomy %>
18
+
19
+ ## Arguments
20
+
21
+ <% arguments.each do |argument| %>
22
+ ### <%= argument[:display_name] %>
23
+ <%= argument[:description] %>
24
+ **Name:** <%= argument[:name] %>,
25
+ **Type:** <%= argument[:type] %>,
26
+ **Units:** <%= argument[:units] %>,
27
+ **Required:** <%= argument[:required] %>,
28
+ **Model Dependent:** <%= argument[:model_dependent] %>
29
+ <% end %>
30
+
31
+ <% if arguments.size == 0 %>
32
+ <%= "This measure does not have any user arguments" %>
33
+ <% end %>
34
+
35
+ <% if outputs.size > 0 %>
36
+ ## Outputs
37
+ <% output_names = [] %>
38
+ <% outputs.each do |output| %>
39
+ <% output_names << output[:display_name] %>
40
+ <% end %>
41
+ <%= output_names.join(", ") %>
42
+ <% end %>
@@ -0,0 +1,513 @@
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 ReduceLightingLoadsByPercentage < OpenStudio::Measure::ModelMeasure
38
+ # define the name that a user will see
39
+ def name
40
+ return 'Reduce Lighting Loads by Percentage'
41
+ end
42
+
43
+ # human readable description
44
+ def description
45
+ return 'The lighting system in this building uses more power per area than is required with the latest lighting technologies. Replace the lighting system with a newer, more efficient lighting technology. Newer technologies provide the same amount of light but use less energy in the process.'
46
+ end
47
+
48
+ # human readable description of modeling approach
49
+ def modeler_description
50
+ return 'This measure supports models which have a mixture of lighting assigned to spaces and space types. The lighting may be specified as individual luminaires, lighting equipment level, lighting power per area, or lighting power per person. Loop through all lights and luminaires in the specified space type or the entire building. Clone the definition if it is shared by other lights, rename and adjust the power based on the specified percentage. Link the new definition to the existing lights or luminaire instance. Adjust the power for lighting equipment assigned to a particular space but only if that space is part of the selected space type by looping through the objects first in space types and then in spaces, but again only for spaces that are in the specified space type (unless the entire building has been chosen). Material and installation cost increases will be applied to all costs related to both the definition and instance of the lighting object. If this measure includes baseline costs, then the material and installation costs of the lighting objects in the baseline model will be summed together and added as a capital cost on the building object.'
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
83
+ space_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('space_type', space_type_handles, space_type_display_names)
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 for reduction percentage
89
+ lighting_power_reduction_percent = OpenStudio::Measure::OSArgument.makeDoubleArgument('lighting_power_reduction_percent', true)
90
+ lighting_power_reduction_percent.setDisplayName('Lighting Power Reduction')
91
+ lighting_power_reduction_percent.setDefaultValue(30.0)
92
+ lighting_power_reduction_percent.setUnits('%')
93
+ args << lighting_power_reduction_percent
94
+
95
+ # make an argument for material and installation cost
96
+ material_and_installation_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('material_and_installation_cost', true)
97
+ material_and_installation_cost.setDisplayName('Increase in Material and Installation Cost for Lighting per Floor Area')
98
+ material_and_installation_cost.setDefaultValue(0.0)
99
+ material_and_installation_cost.setUnits('%')
100
+ args << material_and_installation_cost
101
+
102
+ # make an argument for demolition cost
103
+ demolition_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('demolition_cost', true)
104
+ demolition_cost.setDisplayName('Increase in Demolition Costs for Lighting per Floor Area')
105
+ demolition_cost.setDefaultValue(0.0)
106
+ demolition_cost.setUnits('%')
107
+ args << demolition_cost
108
+
109
+ # make an argument for years until costs start
110
+ years_until_costs_start = OpenStudio::Measure::OSArgument.makeIntegerArgument('years_until_costs_start', true)
111
+ years_until_costs_start.setDisplayName('Years Until Costs Start')
112
+ years_until_costs_start.setDefaultValue(0)
113
+ years_until_costs_start.setUnits('whole years')
114
+ args << years_until_costs_start
115
+
116
+ # make a choice argument for when demo costs occur
117
+ demo_cost_initial_const = OpenStudio::Measure::OSArgument.makeBoolArgument('demo_cost_initial_const', true)
118
+ demo_cost_initial_const.setDisplayName('Demolition Costs Occur During Initial Construction')
119
+ demo_cost_initial_const.setDefaultValue(false)
120
+ args << demo_cost_initial_const
121
+
122
+ # make an argument for expected life
123
+ expected_life = OpenStudio::Measure::OSArgument.makeIntegerArgument('expected_life', true)
124
+ expected_life.setDisplayName('Expected Life')
125
+ expected_life.setDefaultValue(15)
126
+ expected_life.setUnits('whole years')
127
+ args << expected_life
128
+
129
+ # make an argument for O & M cost
130
+ om_cost = OpenStudio::Measure::OSArgument.makeDoubleArgument('om_cost', true)
131
+ om_cost.setDisplayName('Increase O & M Costs for Lighting per Floor Area')
132
+ om_cost.setDefaultValue(0.0)
133
+ om_cost.setUnits('%')
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')
139
+ om_frequency.setDefaultValue(1)
140
+ om_frequency.setUnits('whole years')
141
+ args << om_frequency
142
+
143
+ return args
144
+ end
145
+
146
+ # define what happens when the measure is run
147
+ def run(model, runner, user_arguments)
148
+ super(model, runner, user_arguments)
149
+
150
+ # use the built-in error checking
151
+ if !runner.validateUserArguments(arguments(model), user_arguments)
152
+ return false
153
+ end
154
+
155
+ # assign the user inputs to variables
156
+ object = runner.getOptionalWorkspaceObjectChoiceValue('space_type', user_arguments, model)
157
+ lighting_power_reduction_percent = runner.getDoubleArgumentValue('lighting_power_reduction_percent', user_arguments)
158
+ material_and_installation_cost = runner.getDoubleArgumentValue('material_and_installation_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 space type 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
+ else
183
+ runner.registerError('Script Error - argument not showing up as space type or building.')
184
+ return false
185
+ end
186
+ end
187
+
188
+ # check the lighting_power_reduction_percent and for reasonableness
189
+ if lighting_power_reduction_percent > 100
190
+ runner.registerError('Please Enter a Value less than or equal to 100 for the Lighting Power Reduction Percentage.')
191
+ return false
192
+ elsif lighting_power_reduction_percent == 0
193
+ runner.registerInfo('No lighting power adjustment requested, but some life cycle costs may still be affected.')
194
+ elsif (lighting_power_reduction_percent < 1) && (lighting_power_reduction_percent > -1)
195
+ runner.registerWarning("A Lighting Power Reduction Percentage of #{lighting_power_reduction_percent} percent is abnormally low.")
196
+ elsif lighting_power_reduction_percent > 90
197
+ runner.registerWarning("A Lighting Power Reduction Percentage of #{lighting_power_reduction_percent} percent is abnormally high.")
198
+ elsif lighting_power_reduction_percent < 0
199
+ runner.registerInfo('The requested value for lighting power reduction percentage was negative. This will result in an increase in lighting power.')
200
+ end
201
+
202
+ # check lifecycle cost arguments for reasonableness
203
+ if material_and_installation_cost < -100
204
+ runner.registerError("Material and Installation Cost percentage increase can't be less than -100.")
205
+ return false
206
+ end
207
+
208
+ if demolition_cost < -100
209
+ runner.registerError("Demolition Cost percentage increase can't be less than -100.")
210
+ return false
211
+ end
212
+
213
+ if years_until_costs_start < 0
214
+ runner.registerError('Enter an integer greater than or equal to 0 for Years Until Costs Start.')
215
+ return false
216
+ end
217
+
218
+ if expected_life < 1
219
+ runner.registerError('Enter an integer greater than or equal to 1 for Expected Life.')
220
+ return false
221
+ end
222
+
223
+ if om_cost < -100
224
+ runner.registerError("O & M Cost percentage increase can't be less than -100.")
225
+ return false
226
+ end
227
+
228
+ if om_frequency < 1
229
+ runner.registerError('Choose an integer greater than 0 for O & M Frequency.')
230
+ end
231
+
232
+ # helper to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001). The definition be called through this measure.
233
+ def neat_numbers(number, roundto = 2) # round to 0 or 2)
234
+ if roundto == 2
235
+ number = format '%.2f', number
236
+ else
237
+ number = number.round
238
+ end
239
+ # regex to add commas
240
+ number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
241
+ end
242
+
243
+ # helper to make it easier to do unit conversions on the fly. The definition be called through this measure.
244
+ def unit_helper(number, from_unit_string, to_unit_string)
245
+ converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value
246
+ end
247
+
248
+ # helper that loops through lifecycle costs getting total costs under "Construction" or "Salvage" category and add to counter if occurs during year 0
249
+ def get_total_costs_for_objects(objects)
250
+ counter = 0
251
+ objects.each do |object|
252
+ object_LCCs = object.lifeCycleCosts
253
+ object_LCCs.each do |object_LCC|
254
+ if (object_LCC.category == 'Construction') || (object_LCC.category == 'Salvage')
255
+ if object_LCC.yearsFromStart == 0
256
+ counter += object_LCC.totalCost
257
+ end
258
+ end
259
+ end
260
+ end
261
+ return counter
262
+ end
263
+
264
+ # counter for demo cost of baseline objects
265
+ demo_costs_of_baseline_objects = 0
266
+
267
+ # counter for year 0 capital costs
268
+ yr0_capital_totalCosts = 0
269
+
270
+ # get initial light and luminaire costs and multiply by -1
271
+ yr0_capital_totalCosts += get_total_costs_for_objects(model.getLightsDefinitions) * -1
272
+ yr0_capital_totalCosts += get_total_costs_for_objects(model.getLuminaireDefinitions) * -1
273
+
274
+ # report initial condition
275
+ building = model.getBuilding
276
+ building_lighting_power = building.lightingPower
277
+
278
+ # method should always return double but this is work around for when it is nan because of 0 floor area
279
+ if building.floorArea > 0.0
280
+ building_LPD = unit_helper(building.lightingPowerPerFloorArea, 'W/m^2', 'W/ft^2')
281
+ runner.registerInitialCondition("The model's initial building lighting power was #{neat_numbers(building_lighting_power, 0)} watts, a lighting power density of #{neat_numbers(building_LPD)} w/ft^2.")
282
+ else
283
+ runner.registerInitialCondition("The model's initial building lighting power was #{neat_numbers(building_lighting_power, 0)} watts. Building Area is not greater than 0 so an LPD can't be calculated.")
284
+ end
285
+
286
+ # get space types in model
287
+ if apply_to_building
288
+ space_types = model.getSpaceTypes
289
+ else
290
+ space_types = []
291
+ space_types << space_type # only run on a single space type
292
+ end
293
+
294
+ # helper def to add to demo cost related to baseline objects
295
+ def add_to_baseline_demo_cost_counter(baseline_object, demo_cost_initial_const)
296
+ counter = 0
297
+ if demo_cost_initial_const == true
298
+ baseline_object_LCCs = baseline_object.lifeCycleCosts
299
+ baseline_object_LCCs.each do |baseline_object_LCC|
300
+ if baseline_object_LCC.category == 'Salvage'
301
+ counter += baseline_object_LCC.totalCost
302
+ end
303
+ end
304
+ end
305
+ return counter
306
+ end
307
+
308
+ # def to alter performance and life cycle costs of objects
309
+ def alter_performance_and_lcc(object, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
310
+ # edit clone based on percentage reduction
311
+ new_def = object
312
+ if !new_def.lightingLevel.empty?
313
+ new_lighting_level = new_def.setLightingLevel(new_def.lightingLevel.get - new_def.lightingLevel.get * lighting_power_reduction_percent * 0.01)
314
+ elsif !new_def.wattsperSpaceFloorArea.empty?
315
+ new_lighting_per_area = new_def.setWattsperSpaceFloorArea(new_def.wattsperSpaceFloorArea.get - new_def.wattsperSpaceFloorArea.get * lighting_power_reduction_percent * 0.01)
316
+ elsif !new_def.wattsperPerson.empty?
317
+ new_lighting_per_person = new_def.setWattsperPerson(new_def.wattsperPerson.get - new_def.wattsperPerson.get * lighting_power_reduction_percent * 0.01)
318
+ else
319
+ runner.registerWarning("'#{new_def.name}' is used by one or more instances and has no load values. Its performance was not altered.")
320
+ end
321
+
322
+ new_def_LCCs = new_def.lifeCycleCosts
323
+ if new_def_LCCs.empty?
324
+ if material_and_installation_cost.abs + demolition_cost.abs + om_cost.abs != 0
325
+ runner.registerWarning("'#{new_def.name}' had no life cycle cost objects. No cost was added for it.")
326
+ end
327
+ else
328
+ new_def_LCCs.each do |new_def_LCC|
329
+ if new_def_LCC.category == 'Construction'
330
+ new_def_LCC.setCost(new_def_LCC.cost * (1 + material_and_installation_cost / 100))
331
+ new_def_LCC.setYearsFromStart(years_until_costs_start) # just uses argument value, does not need existing value
332
+ new_def_LCC.setRepeatPeriodYears(expected_life) # just uses argument value, does not need existing value
333
+ elsif new_def_LCC.category == 'Salvage'
334
+ new_def_LCC.setCost(new_def_LCC.cost * (1 + demolition_cost / 100))
335
+ new_def_LCC.setYearsFromStart(years_until_costs_start + expected_life) # just uses argument value, does not need existing value
336
+ new_def_LCC.setRepeatPeriodYears(expected_life) # just uses argument value, does not need existing value
337
+ elsif new_def_LCC.category == 'Maintenance'
338
+ new_def_LCC.setCost(new_def_LCC.cost * (1 + om_cost / 100))
339
+ new_def_LCC.setRepeatPeriodYears(om_frequency) # just uses argument value, does not need existing value
340
+ end
341
+
342
+ # reset any month durations
343
+ new_def_LCC.resetRepeatPeriodMonths
344
+ new_def_LCC.resetMonthsFromStart
345
+ end
346
+
347
+ end
348
+ end
349
+
350
+ # make a hash of old defs and new lights and luminaire defs
351
+ cloned_lights_defs = {}
352
+ cloned_luminaire_defs = {}
353
+
354
+ # loop through space types
355
+ space_types.each do |space_type|
356
+ next if space_type.spaces.size <= 0
357
+ space_type_lights = space_type.lights
358
+ space_type_lights.each do |space_type_light|
359
+ # clone def if it has not already been cloned
360
+ exist_def = space_type_light.lightsDefinition
361
+ if cloned_lights_defs.any? { |k, v| k.to_s == exist_def.name.to_s }
362
+ new_def = cloned_lights_defs[exist_def.name.to_s]
363
+ else
364
+ # clone rename and add to hash
365
+ new_def = exist_def.clone(model)
366
+ new_def_name = new_def.setName("#{exist_def.name} - #{lighting_power_reduction_percent} percent reduction")
367
+ cloned_lights_defs[exist_def.name.to_s] = new_def
368
+ new_def = new_def.to_LightsDefinition.get
369
+
370
+ # add demo cost of object being removed to one counter for one time demo cost for baseline objects
371
+ demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
372
+
373
+ # call def to alter performance and life cycle costs
374
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
375
+
376
+ end
377
+
378
+ # link instance with clone and rename
379
+ updated_instance = space_type_light.setLightsDefinition(new_def.to_LightsDefinition.get)
380
+ updated_instance_name = space_type_light.setName("#{space_type_light.name} #{lighting_power_reduction_percent} percent reduction")
381
+ end
382
+
383
+ space_type_luminaires = space_type.luminaires
384
+ space_type_luminaires.each do |space_type_luminaire|
385
+ # clone def if it has not already been cloned
386
+ exist_def = space_type_luminaire.luminaireDefinition
387
+ if cloned_luminaire_defs.any? { |k, v| k.to_s == exist_def.name }
388
+ new_def = cloned_luminaire_defs[exist_def.name]
389
+ else
390
+ # clone rename and add to hash
391
+ new_def = exist_def.clone(model)
392
+ new_def_name = new_def.setName("#{new_def.name} - #{lighting_power_reduction_percent} percent reduction")
393
+ cloned_luminaire_defs[exist_def.name] = new_def
394
+ new_def = new_def.to_LightsDefinition.get
395
+
396
+ # add demo cost of object being removed to one counter for one time demo cost for baseline objects
397
+ demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
398
+
399
+ # call def to alter performance and life cycle costs
400
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
401
+
402
+ end
403
+
404
+ # link instance with clone and rename
405
+ updated_instance = space_type_light.setLightsDefinition(new_def.to_LightsDefinition.get)
406
+ updated_instance_name = space_type_light.setName("#{space_type_light.name} #{lighting_power_reduction_percent} percent reduction")
407
+ end
408
+ end
409
+
410
+ # getting spaces in the model
411
+ spaces = model.getSpaces
412
+
413
+ # get space types in model
414
+ if apply_to_building
415
+ spaces = model.getSpaces
416
+ else
417
+ if !space_type.spaces.empty?
418
+ spaces = space_type.spaces # only run on a single space type
419
+ end
420
+ end
421
+
422
+ spaces.each do |space|
423
+ space_lights = space.lights
424
+ space_lights.each do |space_light|
425
+ # clone def if it has not already been cloned
426
+ exist_def = space_light.lightsDefinition
427
+ if cloned_lights_defs.any? { |k, v| k.to_s == exist_def.name.to_s }
428
+ new_def = cloned_lights_defs[exist_def.name.to_s]
429
+ else
430
+ # clone rename and add to hash
431
+ new_def = exist_def.clone(model)
432
+ new_def_name = new_def.setName("#{new_def.name} - #{lighting_power_reduction_percent} percent reduction")
433
+ cloned_lights_defs[exist_def.name.to_s] = new_def
434
+ new_def = new_def.to_LightsDefinition.get
435
+
436
+ # add demo cost of object being removed to one counter for one time demo cost for baseline objects
437
+ demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
438
+
439
+ # call def to alter performance and life cycle costs
440
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
441
+
442
+ end
443
+
444
+ # link instance with clone and rename
445
+ updated_instance = space_light.setLightsDefinition(new_def.to_LightsDefinition.get)
446
+ updated_instance_name = space_light.setName("#{space_light.name} #{lighting_power_reduction_percent} percent reduction")
447
+ end
448
+
449
+ space_luminaires = space.luminaires
450
+ space_luminaires.each do |space_luminaire|
451
+ # clone def if it has not already been cloned
452
+ exist_def = space_luminaire.luminaireDefinition
453
+ if cloned_luminaire_defs.any? { |k, v| k.to_s == exist_def.name }
454
+ new_def = cloned_luminaire_defs[exist_def.name]
455
+ else
456
+ # clone rename and add to hash
457
+ new_def = exist_def.clone(model)
458
+ new_def_name = new_def.setName("#{new_def.name} - #{lighting_power_reduction_percent} percent reduction")
459
+ cloned_luminaire_defs[exist_def.name] = new_def
460
+ new_def = new_def.to_LightsDefinition.get
461
+
462
+ # add demo cost of object being removed to one counter for one time demo cost for baseline objects
463
+ demo_costs_of_baseline_objects += add_to_baseline_demo_cost_counter(exist_def, demo_cost_initial_const)
464
+
465
+ # call def to alter performance and life cycle costs
466
+ alter_performance_and_lcc(new_def, lighting_power_reduction_percent, material_and_installation_cost, demolition_cost, om_cost, years_until_costs_start, expected_life, om_frequency, runner)
467
+
468
+ end
469
+
470
+ # link instance with clone and rename
471
+ updated_instance = space_light.setLightsDefinition(new_def)
472
+ updated_instance_name = space_light.setName("#{space_light.name} - #{lighting_power_reduction_percent} percent reduction")
473
+ end
474
+ end
475
+
476
+ if cloned_lights_defs.empty? && cloned_luminaire_defs.empty?
477
+ runner.registerAsNotApplicable('No lighting or luminaire objects were found in the specified space type(s).')
478
+ end
479
+
480
+ # get final light and luminaire costs to use in final condition
481
+ yr0_capital_totalCosts += get_total_costs_for_objects(model.getLightsDefinitions)
482
+ yr0_capital_totalCosts += get_total_costs_for_objects(model.getLuminaireDefinitions)
483
+
484
+ # add one time demo cost of removed lights and luminaires if appropriate
485
+ if demo_cost_initial_const == true
486
+ building = model.getBuilding
487
+ 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.
488
+ runner.registerInfo("Adding one time cost of $#{neat_numbers(lcc_baseline_demo.totalCost, 0)} related to demolition of baseline objects.")
489
+
490
+ # if demo occurs on year 0 then add to initial capital cost counter
491
+ if lcc_baseline_demo.yearsFromStart == 0
492
+ yr0_capital_totalCosts += lcc_baseline_demo.totalCost
493
+ end
494
+ end
495
+
496
+ # report final condition
497
+ final_building = model.getBuilding
498
+ final_building_lighting_power = final_building.lightingPower
499
+
500
+ # method should always return double but this is work around for when it is nan because of 0 floor area
501
+ if building.floorArea > 0.0
502
+ final_building_LPD = unit_helper(final_building.lightingPowerPerFloorArea, 'W/m^2', 'W/ft^2')
503
+ runner.registerFinalCondition("The model's final final lighting power was #{neat_numbers(final_building_lighting_power, 0)} watts, a lighting power density of #{neat_numbers(final_building_LPD)} w/ft^2. Initial capital costs associated with the improvements are $#{neat_numbers(yr0_capital_totalCosts, 0)}.")
504
+ else
505
+ runner.registerFinalCondition("The model's final final lighting power was #{neat_numbers(final_building_lighting_power, 0)} wattsBuilding Area is not greater than 0 so an LPD can't be calculated.")
506
+ end
507
+
508
+ return true
509
+ end
510
+ end
511
+
512
+ # this allows the measure to be used by the application
513
+ ReduceLightingLoadsByPercentage.new.registerWithApplication