openstudio-calibration 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE.md +1 -1
  5. data/Rakefile +1 -1
  6. data/doc_templates/LICENSE.md +1 -1
  7. data/doc_templates/copyright_erb.txt +1 -1
  8. data/doc_templates/copyright_js.txt +1 -1
  9. data/doc_templates/copyright_ruby.txt +1 -1
  10. data/lib/measures/AddMonthlyJSONUtilityData/LICENSE.md +1 -1
  11. data/lib/measures/AddMonthlyJSONUtilityData/measure.rb +1 -1
  12. data/lib/measures/AddMonthlyJSONUtilityData/measure.xml +12 -11
  13. data/lib/measures/AddMonthlyUtilityData/LICENSE.md +1 -1
  14. data/lib/measures/AddMonthlyUtilityData/measure.rb +1 -1
  15. data/lib/measures/AddMonthlyUtilityData/measure.xml +13 -12
  16. data/lib/measures/CalibrationReports/LICENSE.md +1 -1
  17. data/lib/measures/CalibrationReports/README.md +2 -2
  18. data/lib/measures/CalibrationReports/measure.rb +1 -1
  19. data/lib/measures/CalibrationReports/measure.xml +12 -11
  20. data/lib/measures/CalibrationReportsEnhanced/LICENSE.md +1 -1
  21. data/lib/measures/CalibrationReportsEnhanced/measure.rb +2 -2
  22. data/lib/measures/CalibrationReportsEnhanced/measure.xml +18 -17
  23. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/LICENSE.md +1 -1
  24. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/measure.rb +1 -1
  25. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/measure.xml +14 -13
  26. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/LICENSE.md +1 -1
  27. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/measure.rb +1 -1
  28. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/measure.xml +14 -13
  29. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/LICENSE.md +1 -1
  30. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/measure.rb +1 -1
  31. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/measure.xml +14 -13
  32. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/LICENSE.md +1 -1
  33. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/measure.rb +1 -1
  34. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/measure.xml +14 -13
  35. data/lib/measures/CoilCoolingWaterMultiplier/LICENSE.md +1 -1
  36. data/lib/measures/CoilCoolingWaterMultiplier/measure.rb +1 -1
  37. data/lib/measures/CoilCoolingWaterMultiplier/measure.xml +14 -13
  38. data/lib/measures/CoilCoolingWaterPercentChange/LICENSE.md +1 -1
  39. data/lib/measures/CoilCoolingWaterPercentChange/measure.rb +1 -1
  40. data/lib/measures/CoilCoolingWaterPercentChange/measure.xml +14 -13
  41. data/lib/measures/CoilHeatingElectricMultiplier/LICENSE.md +1 -1
  42. data/lib/measures/CoilHeatingElectricMultiplier/measure.rb +1 -1
  43. data/lib/measures/CoilHeatingElectricMultiplier/measure.xml +14 -13
  44. data/lib/measures/CoilHeatingElectricPercentChange/LICENSE.md +1 -1
  45. data/lib/measures/CoilHeatingElectricPercentChange/measure.rb +1 -1
  46. data/lib/measures/CoilHeatingElectricPercentChange/measure.xml +14 -13
  47. data/lib/measures/CoilHeatingGasMultiplier/LICENSE.md +1 -1
  48. data/lib/measures/CoilHeatingGasMultiplier/measure.rb +1 -1
  49. data/lib/measures/CoilHeatingGasMultiplier/measure.xml +14 -13
  50. data/lib/measures/CoilHeatingGasPercentChange/LICENSE.md +1 -1
  51. data/lib/measures/CoilHeatingGasPercentChange/measure.rb +1 -1
  52. data/lib/measures/CoilHeatingGasPercentChange/measure.xml +14 -13
  53. data/lib/measures/CoilHeatingWaterMultiplier/LICENSE.md +1 -1
  54. data/lib/measures/CoilHeatingWaterMultiplier/measure.rb +1 -1
  55. data/lib/measures/CoilHeatingWaterMultiplier/measure.xml +14 -13
  56. data/lib/measures/CoilHeatingWaterPercentChange/LICENSE.md +1 -1
  57. data/lib/measures/CoilHeatingWaterPercentChange/measure.rb +1 -1
  58. data/lib/measures/CoilHeatingWaterPercentChange/measure.xml +14 -13
  59. data/lib/measures/ConstructionLayerZeroMaterialProperties/LICENSE.md +1 -1
  60. data/lib/measures/ConstructionLayerZeroMaterialProperties/measure.rb +1 -1
  61. data/lib/measures/ConstructionLayerZeroMaterialProperties/measure.xml +12 -11
  62. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/LICENSE.md +1 -1
  63. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/measure.rb +1 -1
  64. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/measure.xml +12 -11
  65. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/LICENSE.md +1 -1
  66. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/measure.rb +3 -3
  67. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/measure.xml +24 -11
  68. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/LICENSE.md +1 -1
  69. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/measure.rb +3 -3
  70. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/measure.xml +24 -11
  71. data/lib/measures/FansMultiplier/LICENSE.md +1 -1
  72. data/lib/measures/FansMultiplier/measure.rb +1 -1
  73. data/lib/measures/FansMultiplier/measure.xml +14 -13
  74. data/lib/measures/FansPercentChange/LICENSE.md +1 -1
  75. data/lib/measures/FansPercentChange/measure.rb +1 -1
  76. data/lib/measures/FansPercentChange/measure.xml +14 -13
  77. data/lib/measures/GeneralCalibrationMeasureMultiplier/LICENSE.md +1 -1
  78. data/lib/measures/GeneralCalibrationMeasureMultiplier/measure.rb +1 -1
  79. data/lib/measures/GeneralCalibrationMeasureMultiplier/measure.xml +16 -15
  80. data/lib/measures/GeneralCalibrationMeasurePercentChange/LICENSE.md +1 -1
  81. data/lib/measures/GeneralCalibrationMeasurePercentChange/measure.rb +1 -1
  82. data/lib/measures/GeneralCalibrationMeasurePercentChange/measure.xml +16 -15
  83. data/lib/measures/HardSizeHvac/LICENSE.md +1 -1
  84. data/lib/measures/HardSizeHvac/measure.rb +1 -1
  85. data/lib/measures/HardSizeHvac/measure.xml +13 -12
  86. data/lib/measures/RValueOfInsulationForConstructionMultiplier/LICENSE.md +1 -1
  87. data/lib/measures/RValueOfInsulationForConstructionMultiplier/measure.rb +1 -1
  88. data/lib/measures/RValueOfInsulationForConstructionMultiplier/measure.xml +12 -11
  89. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/LICENSE.md +1 -1
  90. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/measure.rb +1 -1
  91. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/measure.xml +12 -11
  92. data/lib/measures/RoofThermalPropertiesMultiplier/LICENSE.md +1 -1
  93. data/lib/measures/RoofThermalPropertiesMultiplier/measure.rb +3 -3
  94. data/lib/measures/RoofThermalPropertiesMultiplier/measure.xml +24 -11
  95. data/lib/measures/RoofThermalPropertiesPercentChange/LICENSE.md +1 -1
  96. data/lib/measures/RoofThermalPropertiesPercentChange/measure.rb +3 -3
  97. data/lib/measures/RoofThermalPropertiesPercentChange/measure.xml +24 -11
  98. data/lib/measures/TimeseriesObjectiveFunction/LICENSE.md +1 -1
  99. data/lib/measures/TimeseriesObjectiveFunction/measure.rb +1 -1
  100. data/lib/measures/TimeseriesObjectiveFunction/measure.xml +12 -12
  101. data/lib/measures/TimeseriesObjectiveFunction/resources/report.html.erb +4 -1
  102. data/lib/measures/TimeseriesPlot/LICENSE.md +1 -1
  103. data/lib/measures/TimeseriesPlot/measure.rb +1 -1
  104. data/lib/measures/TimeseriesPlot/measure.xml +17 -17
  105. data/lib/measures/TimeseriesPlot/resources/report.html.erb +4 -1
  106. data/lib/measures/WaterHeaterMixedMultiplier/LICENSE.md +1 -1
  107. data/lib/measures/WaterHeaterMixedMultiplier/measure.rb +1 -1
  108. data/lib/measures/WaterHeaterMixedMultiplier/measure.xml +14 -13
  109. data/lib/measures/WaterHeaterMixedPercentChange/LICENSE.md +1 -1
  110. data/lib/measures/WaterHeaterMixedPercentChange/measure.rb +1 -1
  111. data/lib/measures/WaterHeaterMixedPercentChange/measure.xml +14 -13
  112. data/lib/measures/{zone_report → inspect_and_edit_parametric_schedules}/LICENSE.md +1 -1
  113. data/lib/measures/inspect_and_edit_parametric_schedules/README.md +41 -0
  114. data/lib/measures/inspect_and_edit_parametric_schedules/README.md.erb +53 -0
  115. data/lib/measures/inspect_and_edit_parametric_schedules/docs/.gitkeep +0 -0
  116. data/lib/measures/inspect_and_edit_parametric_schedules/docs/apply_measures_now.png +0 -0
  117. data/lib/measures/inspect_and_edit_parametric_schedules/measure.rb +224 -0
  118. data/lib/measures/inspect_and_edit_parametric_schedules/measure.xml +131 -0
  119. data/lib/measures/shift_hours_of_operation/LICENSE.md +27 -0
  120. data/lib/measures/shift_hours_of_operation/README.md +134 -0
  121. data/lib/measures/{zone_report → shift_hours_of_operation}/README.md.erb +5 -0
  122. data/lib/measures/shift_hours_of_operation/docs/.gitkeep +0 -0
  123. data/lib/measures/shift_hours_of_operation/measure.rb +513 -0
  124. data/lib/measures/shift_hours_of_operation/measure.xml +261 -0
  125. data/lib/openstudio-calibration.rb +1 -1
  126. data/lib/openstudio/calibration.rb +1 -1
  127. data/lib/openstudio/calibration/extension.rb +1 -1
  128. data/lib/openstudio/calibration/version.rb +2 -2
  129. data/openstudio-calibration.gemspec +3 -3
  130. metadata +21 -14
  131. data/lib/measures/zone_report/README.md +0 -26
  132. data/lib/measures/zone_report/measure.rb +0 -706
  133. data/lib/measures/zone_report/measure.xml +0 -69
  134. data/lib/measures/zone_report/resources/report.html.in +0 -342
@@ -0,0 +1,27 @@
1
+ OpenStudio(R), Copyright (c) 2008-2021, 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,134 @@
1
+
2
+
3
+ ###### (Automatically generated documentation)
4
+
5
+ # Shift Hours of Operation
6
+
7
+ ## Description
8
+ This measure will infer the hours of operation for the building and then will shift the start of the hours of operation and change the duration of the hours of operation. In an alternate workflow you can directly pass in target start and duration rather than a shift and delta. Inputs can vary for weekday, Saturday, and Sunday. if a day does not have any hours of operation to start with increasing hours of operation may not have any impact as the auto generated data may not know what to do during operating hours. Future version may be able to borrow a profile formula but would probably require additional user arguments.
9
+
10
+ ## Modeler Description
11
+ This will only impact schedule rulesets. It will use methods in openstudio-standards to infer hours of operation, develop a parametric formula for all of the ruleset schedules, alter the hours of operation inputs to that formula and then re-apply the schedules. Input is expose to set ramp frequency of the resulting schedules. If inputs are such that no changes are requested, bypass the measure with NA so that it will not be parameterized. An advanced option for this measure would be bool to use hours of operation from OSM schedule ruleset hours of operation instead of inferring from standards. This should allow different parts of the building to have different hours of operation in the seed model.
12
+
13
+ ## Measure Type
14
+ ModelMeasure
15
+
16
+ ## Taxonomy
17
+
18
+
19
+ ## Arguments
20
+
21
+
22
+ ### Shift the weekday start of hours of operation.
23
+ Use decimal hours so an 1 hour and 15 minute shift would be 1.25. Positive value moves the hour of operation later
24
+ **Name:** hoo_start_weekday,
25
+ **Type:** Double,
26
+ **Units:** Hours,
27
+ **Required:** true,
28
+ **Model Dependent:** false
29
+
30
+
31
+
32
+
33
+ ### Extend the weekday of hours of operation.
34
+ Use decimal hours so an 1 hour and 15 minute would be 1.25. Positive value makes the hour of operation longer.
35
+ **Name:** hoo_dur_weekday,
36
+ **Type:** Double,
37
+ **Units:** Hours,
38
+ **Required:** true,
39
+ **Model Dependent:** false
40
+
41
+
42
+
43
+
44
+ ### Shift the saturday start of hours of operation.
45
+ Use decimal hours so an 1 hour and 15 minute shift would be 1.25. Positive value moves the hour of operation later
46
+ **Name:** hoo_start_saturday,
47
+ **Type:** Double,
48
+ **Units:** Hours,
49
+ **Required:** true,
50
+ **Model Dependent:** false
51
+
52
+
53
+
54
+
55
+ ### Extend the saturday of hours of operation.
56
+ Use decimal hours so an 1 hour and 15 minute would be 1.25. Positive value makes the hour of operation longer.
57
+ **Name:** hoo_dur_saturday,
58
+ **Type:** Double,
59
+ **Units:** Hours,
60
+ **Required:** true,
61
+ **Model Dependent:** false
62
+
63
+
64
+
65
+
66
+ ### Shift the sunday start of hours of operation.
67
+ Use decimal hours so an 1 hour and 15 minute shift would be 1.25. Positive value moves the hour of operation later
68
+ **Name:** hoo_start_sunday,
69
+ **Type:** Double,
70
+ **Units:** Hours,
71
+ **Required:** true,
72
+ **Model Dependent:** false
73
+
74
+
75
+
76
+
77
+ ### Extend the sunday of hours of operation.
78
+ Use decimal hours so an 1 hour and 15 minute would be 1.25. Positive value makes the hour of operation longer.
79
+ **Name:** hoo_dur_sunday,
80
+ **Type:** Double,
81
+ **Units:** Hours,
82
+ **Required:** true,
83
+ **Model Dependent:** false
84
+
85
+
86
+
87
+
88
+ ### Hours of operation values treated as deltas
89
+ When this is true the hours of operation start and duration represent a delta from the original model values. When switched to false they represent absolute values.
90
+ **Name:** delta_values,
91
+ **Type:** Boolean,
92
+ **Units:** ,
93
+ **Required:** true,
94
+ **Model Dependent:** false
95
+
96
+
97
+
98
+
99
+ ### Dynamically generate parametric schedules from current ruleset schedules.
100
+ When this is true the parametric schedule formulas and hours of operation will be generated from the existing model schedules. When false it expects the model already has parametric formulas stored.
101
+ **Name:** infer_parametric_schedules,
102
+ **Type:** Boolean,
103
+ **Units:** ,
104
+ **Required:** true,
105
+ **Model Dependent:** false
106
+
107
+
108
+
109
+
110
+ ### Fraction of Daily Occupancy Range.
111
+ This determine what fraction of occupancy be considered operating conditions. This fraction is normalized to expanded to range seen over the full year and does not necessary equal fraction of design occupancy. This value should be between 0 and 1.0 and is only used if dynamically generated parametric schedules are used.
112
+ **Name:** fraction_of_daily_occ_range,
113
+ **Type:** Double,
114
+ **Units:** Hours,
115
+ **Required:** true,
116
+ **Model Dependent:** false
117
+
118
+
119
+
120
+
121
+ ### Use model hours of operation as target
122
+ The default behavior is for this to be false. This can not be used unless Dynamically generate parametric schedules from current ruleset schedules is set to false and if the schedules in the model already have parametric profiles. When changed to true all of the hours of operation start and duration values will be ignored as the bool to treat those values as relative or absolute. Instead the hours of operation schedules for the model will be used.
123
+ **Name:** target_hoo_from_model,
124
+ **Type:** Boolean,
125
+ **Units:** ,
126
+ **Required:** true,
127
+ **Model Dependent:** false
128
+
129
+
130
+
131
+
132
+
133
+
134
+
@@ -26,6 +26,11 @@
26
26
  **Units:** <%= argument[:units] %>,
27
27
  **Required:** <%= argument[:required] %>,
28
28
  **Model Dependent:** <%= argument[:model_dependent] %>
29
+
30
+ <% if argument[:type] == "Choice" && !argument[:model_dependent]%>
31
+ **Choice Display Names** <%= argument[:choice_display_names] %>
32
+ <% end %>
33
+
29
34
  <% end %>
30
35
 
31
36
  <% if arguments.size == 0 %>
@@ -0,0 +1,513 @@
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2021, 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
+ # insert your copyright here
37
+
38
+ # see the URL below for information on how to write OpenStudio measures
39
+ # http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/
40
+
41
+ require 'openstudio-standards'
42
+
43
+ # load OpenStudio measure libraries from openstudio-extension gem
44
+ require 'openstudio-extension'
45
+ require 'openstudio/extension/core/os_lib_helper_methods'
46
+
47
+ # start the measure
48
+ class ShiftHoursOfOperation < OpenStudio::Measure::ModelMeasure
49
+ # resource file modules
50
+ include OsLib_HelperMethods
51
+
52
+ # human readable name
53
+ def name
54
+ # Measure name should be the title case of the class name.
55
+ return 'Shift Hours of Operation'
56
+ end
57
+
58
+ # human readable description
59
+ def description
60
+ return 'This measure will infer the hours of operation for the building and then will shift the start of the hours of operation and change the duration of the hours of operation. In an alternate workflow you can directly pass in target start and duration rather than a shift and delta. Inputs can vary for weekday, Saturday, and Sunday. if a day does not have any hours of operation to start with increasing hours of operation may not have any impact as the auto generated data may not know what to do during operating hours. Future version may be able to borrow a profile formula but would probably require additional user arguments.'
61
+ end
62
+
63
+ # human readable description of modeling approach
64
+ def modeler_description
65
+ return 'This will only impact schedule rulesets. It will use methods in openstudio-standards to infer hours of operation, develop a parametric formula for all of the ruleset schedules, alter the hours of operation inputs to that formula and then re-apply the schedules. Input is expose to set ramp frequency of the resulting schedules. If inputs are such that no changes are requested, bypass the measure with NA so that it will not be parameterized. An advanced option for this measure would be bool to use hours of operation from OSM schedule ruleset hours of operation instead of inferring from standards. This should allow different parts of the building to have different hours of operation in the seed model.'
66
+ end
67
+
68
+ # define the arguments that the user will input
69
+ def arguments(model)
70
+ args = OpenStudio::Measure::OSArgumentVector.new
71
+
72
+ # delta hoo_start for weekdays
73
+ hoo_start_weekday = OpenStudio::Measure::OSArgument.makeDoubleArgument('hoo_start_weekday', true)
74
+ hoo_start_weekday.setDisplayName('Shift the weekday start of hours of operation.')
75
+ hoo_start_weekday.setDescription('Use decimal hours so an 1 hour and 15 minute shift would be 1.25. Positive value moves the hour of operation later')
76
+ hoo_start_weekday.setDefaultValue(0.0)
77
+ hoo_start_weekday.setUnits('Hours')
78
+ args << hoo_start_weekday
79
+
80
+ # delta hoo_dur for weekday
81
+ hoo_dur_weekday = OpenStudio::Measure::OSArgument.makeDoubleArgument('hoo_dur_weekday', true)
82
+ hoo_dur_weekday.setDisplayName('Extend the weekday of hours of operation.')
83
+ hoo_dur_weekday.setDescription('Use decimal hours so an 1 hour and 15 minute would be 1.25. Positive value makes the hour of operation longer.')
84
+ hoo_dur_weekday .setDefaultValue(0.0)
85
+ hoo_dur_weekday.setUnits('Hours')
86
+ args << hoo_dur_weekday
87
+
88
+ # TODO: - could include every day of the week
89
+
90
+ # delta hoo_start for saturdays
91
+ hoo_start_saturday = OpenStudio::Measure::OSArgument.makeDoubleArgument('hoo_start_saturday', true)
92
+ hoo_start_saturday.setDisplayName('Shift the saturday start of hours of operation.')
93
+ hoo_start_saturday.setDescription('Use decimal hours so an 1 hour and 15 minute shift would be 1.25. Positive value moves the hour of operation later')
94
+ hoo_start_saturday.setDefaultValue(0.0)
95
+ hoo_start_saturday.setUnits('Hours')
96
+ args << hoo_start_saturday
97
+
98
+ # delta hoo_dur for saturday
99
+ hoo_dur_saturday = OpenStudio::Measure::OSArgument.makeDoubleArgument('hoo_dur_saturday', true)
100
+ hoo_dur_saturday.setDisplayName('Extend the saturday of hours of operation.')
101
+ hoo_dur_saturday.setDescription('Use decimal hours so an 1 hour and 15 minute would be 1.25. Positive value makes the hour of operation longer.')
102
+ hoo_dur_saturday.setDefaultValue(0.0)
103
+ hoo_dur_saturday.setUnits('Hours')
104
+ args << hoo_dur_saturday
105
+
106
+ # delta hoo_start for sundays
107
+ hoo_start_sunday = OpenStudio::Measure::OSArgument.makeDoubleArgument('hoo_start_sunday', true)
108
+ hoo_start_sunday.setDisplayName('Shift the sunday start of hours of operation.')
109
+ hoo_start_sunday.setDescription('Use decimal hours so an 1 hour and 15 minute shift would be 1.25. Positive value moves the hour of operation later')
110
+ hoo_start_sunday.setDefaultValue(0.0)
111
+ hoo_start_sunday.setUnits('Hours')
112
+ args << hoo_start_sunday
113
+
114
+ # delta hoo_dur for sunday
115
+ hoo_dur_sunday = OpenStudio::Measure::OSArgument.makeDoubleArgument('hoo_dur_sunday', true)
116
+ hoo_dur_sunday.setDisplayName('Extend the sunday of hours of operation.')
117
+ hoo_dur_sunday.setDescription('Use decimal hours so an 1 hour and 15 minute would be 1.25. Positive value makes the hour of operation longer.')
118
+ hoo_dur_sunday.setDefaultValue(0.0)
119
+ hoo_dur_sunday.setUnits('Hours')
120
+ args << hoo_dur_sunday
121
+
122
+ # TODO: - could include start and end days to have delta or absolute values applied to. (maybe decimal between 1.0 and 13.0 month where 3.50 would be March 15th)
123
+
124
+ # make an argument for delta_values
125
+ delta_values = OpenStudio::Measure::OSArgument.makeBoolArgument('delta_values', true)
126
+ delta_values.setDisplayName('Hours of operation values treated as deltas')
127
+ delta_values.setDescription('When this is true the hours of operation start and duration represent a delta from the original model values. When switched to false they represent absolute values.')
128
+ delta_values.setDefaultValue(true)
129
+ args << delta_values
130
+
131
+ # make an argument for infer_parametric_schedules
132
+ infer_parametric_schedules = OpenStudio::Measure::OSArgument.makeBoolArgument('infer_parametric_schedules', true)
133
+ infer_parametric_schedules.setDisplayName('Dynamically generate parametric schedules from current ruleset schedules.')
134
+ infer_parametric_schedules.setDescription('When this is true the parametric schedule formulas and hours of operation will be generated from the existing model schedules. When false it expects the model already has parametric formulas stored.')
135
+ infer_parametric_schedules.setDefaultValue(true)
136
+ args << infer_parametric_schedules
137
+
138
+ # delta hoo_start for sundays
139
+ fraction_of_daily_occ_range = OpenStudio::Measure::OSArgument.makeDoubleArgument('fraction_of_daily_occ_range', true)
140
+ fraction_of_daily_occ_range.setDisplayName('Fraction of Daily Occupancy Range.')
141
+ fraction_of_daily_occ_range.setDescription('This determine what fraction of occupancy be considered operating conditions. This fraction is normalized to expanded to range seen over the full year and does not necessary equal fraction of design occupancy. This value should be between 0 and 1.0 and is only used if dynamically generated parametric schedules are used.')
142
+ fraction_of_daily_occ_range.setDefaultValue(0.25)
143
+ fraction_of_daily_occ_range.setUnits('Hours')
144
+ args << fraction_of_daily_occ_range
145
+
146
+ # make an argument for target_hoo_from_model
147
+ # Should only be true when infer_parametric_schedules is false
148
+ target_hoo_from_model = OpenStudio::Measure::OSArgument.makeBoolArgument('target_hoo_from_model', true)
149
+ target_hoo_from_model.setDisplayName('Use model hours of operation as target')
150
+ target_hoo_from_model.setDescription('The default behavior is for this to be false. This can not be used unless Dynamically generate parametric schedules from current ruleset schedules is set to false and if the schedules in the model already have parametric profiles. When changed to true all of the hours of operation start and duration values will be ignored as the bool to treat those values as relative or absolute. Instead the hours of operation schedules for the model will be used.')
151
+ target_hoo_from_model.setDefaultValue(false)
152
+ args << target_hoo_from_model
153
+
154
+ # TODO: - add argument for step frequency, which is hours per step (should be fractional 1 or less generally).
155
+ # For now it defaults to simulation timestep
156
+
157
+ return args
158
+ end
159
+
160
+ # get model hoo info
161
+ def hoo_summary(model, runner, standard)
162
+ hoo_summary_hash = {}
163
+ hoo_summary_hash[:zero_hoo] = []
164
+ hoo_summary_hash[:final_hoo_start_range] = []
165
+ hoo_summary_hash[:final_hoo_dur_range] = []
166
+ model.getSpaces.sort.each do |space|
167
+ default_sch_type = OpenStudio::Model::DefaultScheduleType.new('HoursofOperationSchedule')
168
+ hours_of_operation = space.getDefaultSchedule(default_sch_type)
169
+ if !hours_of_operation.is_initialized
170
+ runner.registerWarning("Hours of Operation Schedule is not set for #{space.name}.")
171
+ next
172
+ end
173
+ hours_of_operation_hash = standard.space_hours_of_operation(space)
174
+ hours_of_operation_hash.each do |hoo_key, val|
175
+ if val[:hoo_hours] == 0.0
176
+ hoo_summary_hash[:zero_hoo] << val[:hoo_hours]
177
+ else
178
+ hoo_summary_hash[:final_hoo_dur_range] << val[:hoo_hours]
179
+ hoo_summary_hash[:final_hoo_start_range] << val[:hoo_start]
180
+ end
181
+ end
182
+ end
183
+
184
+ return hoo_summary_hash
185
+ end
186
+
187
+ # process hoo schedules for various days of the week
188
+ # todo - when date range arg is used and not full year will never want to change default profile
189
+ def process_hoo(used_hoo_sch_sets, model, runner, args, days_of_week, hoo_start_dows, hoo_dur_dows)
190
+ # profiles added to this will be processed
191
+ altered_schedule_days = {} # key is profile value is original index position defined in used_hoo_sch_sets
192
+
193
+ # loop through horus of operation schedules
194
+ used_hoo_sch_sets.uniq.each do |hoo_sch, hours_of_operation_hash|
195
+ if !hoo_sch.to_ScheduleRuleset.is_initialized
196
+ runner.registerWarning("#{hoo_sch.name} is not schedule schedule ruleset, will not be altered by this method.")
197
+ next
198
+ end
199
+ hoo_sch = hoo_sch.to_ScheduleRuleset.get
200
+
201
+ year_description = hoo_sch.model.yearDescription.get
202
+ year = year_description.assumedYear
203
+ year_start_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('January'), 1, year)
204
+ year_end_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('December'), 31, year)
205
+
206
+ orig_profile_indexes_used = hoo_sch.getActiveRuleIndices(year_start_date, year_end_date)
207
+ orig_num_days_default_used = orig_profile_indexes_used.count(-1)
208
+ if orig_num_days_default_used > 0
209
+ default_prof = hoo_sch.defaultDaySchedule
210
+
211
+ # clone default profile as rule that sits above it so it can be evauluated and used if needed
212
+ new_prof = default_prof.clone(model).to_ScheduleDay.get
213
+ new_rule = OpenStudio::Model::ScheduleRule.new(hoo_sch, new_prof)
214
+ hoo_sch.setScheduleRuleIndex(new_rule, hoo_sch.scheduleRules.size - 1)
215
+
216
+ # set days of week for clone to match days of week passed into the method
217
+ if days_of_week.include?('mon')
218
+ new_rule.setApplyMonday(true)
219
+ end
220
+ if days_of_week.include?('tue')
221
+ new_rule.setApplyTuesday(true)
222
+ end
223
+ if days_of_week.include?('wed')
224
+ new_rule.setApplyWednesday(true)
225
+ end
226
+ if days_of_week.include?('thur')
227
+ new_rule.setApplyThursday(true)
228
+ end
229
+ if days_of_week.include?('fri')
230
+ new_rule.setApplyFriday(true)
231
+ end
232
+ if days_of_week.include?('sat')
233
+ new_rule.setApplySaturday(true)
234
+ end
235
+ if days_of_week.include?('sun')
236
+ new_rule.setApplySunday(true)
237
+ end
238
+
239
+ # check if default days are used at all
240
+ profile_indexes_used = hoo_sch.getActiveRuleIndices(year_start_date, year_end_date)
241
+ num_days_new_profile_used = profile_indexes_used.count(hoo_sch.scheduleRules.size - 1)
242
+ if !profile_indexes_used.uniq.include?(-1) && num_days_new_profile_used > 0
243
+ # don't need new profile, can use default
244
+ new_rule.remove
245
+ altered_schedule_days[hoo_sch.defaultDaySchedule] = -1
246
+ elsif num_days_new_profile_used == 0.0
247
+ # can remove cloned rule and skip the default profile (don't pass into array)
248
+ new_rule.remove
249
+ else
250
+ altered_schedule_days[new_rule.daySchedule] = -1 # use hoo that was applicable to the default before it was cloned
251
+ end
252
+ end
253
+
254
+ # use this to link to hoo from hours_of_operation_hash
255
+ counter_of_orig_index = hours_of_operation_hash.size - 2 # this is not impacted by cloning that may have happened above
256
+
257
+ hoo_sch.scheduleRules.reverse.each do |rule|
258
+ # inspect days of the week
259
+ actual_days_of_week_for_profile = []
260
+ if rule.applyMonday then actual_days_of_week_for_profile << 'mon' end
261
+ if rule.applyTuesday then actual_days_of_week_for_profile << 'tue' end
262
+ if rule.applyWednesday then actual_days_of_week_for_profile << 'wed' end
263
+ if rule.applyThursday then actual_days_of_week_for_profile << 'thur' end
264
+ if rule.applyFriday then actual_days_of_week_for_profile << 'fri' end
265
+ if rule.applySaturday then actual_days_of_week_for_profile << 'sat' end
266
+ if rule.applySunday then actual_days_of_week_for_profile << 'sun' end
267
+
268
+ # if an exact match for the rules passed in are met, this rule can be edited in place (update later for date range)
269
+ day_of_week_intersect = days_of_week & actual_days_of_week_for_profile
270
+ current_rule_index = rule.ruleIndex
271
+ if days_of_week == actual_days_of_week_for_profile
272
+ altered_schedule_days[rule.daySchedule] = counter_of_orig_index
273
+
274
+ # if this rule contains the requested days of the week and another then a clone should be made above this with only the requested days of the week that are also already on for this rule
275
+ elsif !day_of_week_intersect.empty?
276
+
277
+ # clone default profile as rule that sits above it so it can be evaluated and used if needed
278
+ new_rule = rule.clone(model).to_ScheduleRule.get
279
+ hoo_sch.setScheduleRuleIndex(new_rule, current_rule_index) # the cloned rule should be just above what was cloned
280
+
281
+ # update days of week for rule
282
+ if day_of_week_intersect.include?('mon')
283
+ new_rule.setApplyMonday(true)
284
+ else
285
+ new_rule.setApplyMonday(false)
286
+ end
287
+ if day_of_week_intersect.include?('tue')
288
+ new_rule.setApplyTuesday(true)
289
+ else
290
+ new_rule.setApplyTuesday(false)
291
+ end
292
+ if day_of_week_intersect.include?('wed')
293
+ new_rule.setApplyWednesday(true)
294
+ else
295
+ new_rule.setApplyWednesday(false)
296
+ end
297
+ if day_of_week_intersect.include?('thur')
298
+ new_rule.setApplyThursday(true)
299
+ else
300
+ new_rule.setApplyThursday(false)
301
+ end
302
+ if day_of_week_intersect.include?('fri')
303
+ new_rule.setApplyFriday(true)
304
+ else
305
+ new_rule.setApplyFriday(false)
306
+ end
307
+ if day_of_week_intersect.include?('sat')
308
+ new_rule.setApplySaturday(true)
309
+ else
310
+ new_rule.setApplySaturday(false)
311
+ end
312
+ if day_of_week_intersect.include?('sun')
313
+ new_rule.setApplySunday(true)
314
+ else
315
+ new_rule.setApplySunday(false)
316
+ end
317
+
318
+ # add to array
319
+ altered_schedule_days[new_rule.daySchedule] = counter_of_orig_index
320
+ end
321
+
322
+ # adjust the count used to find hoo from hours_of_operation_hash
323
+ counter_of_orig_index -= 1
324
+ end
325
+ runner.registerInfo("For #{hoo_sch.name} #{days_of_week.inspect} #{altered_schedule_days.size} profiles will be processed.")
326
+
327
+ # convert altered_schedule_days to hash where key is profile and value is key of index in hours_of_operation_hash
328
+
329
+ # loop through profiles to changes
330
+ altered_schedule_days.each do |new_profile, hoo_hash_index|
331
+ # gather info and edit selected profile
332
+ if args['delta_values']
333
+ orig_hoo_start = hours_of_operation_hash[hoo_hash_index][:hoo_start]
334
+ orig_hoo_dur = hours_of_operation_hash[hoo_hash_index][:hoo_hours]
335
+
336
+ # check for duration grater than 24 or lower than 0
337
+ max_dur_delta = 24 - orig_hoo_dur
338
+ min_dur_delta = orig_hoo_dur * -1.0
339
+ if hoo_dur_dows > max_dur_delta
340
+ target_dur = 24.0
341
+ runner.registerWarning("For profile in #{hoo_sch.name} duration is being capped at 24 hours.")
342
+ elsif hoo_dur_dows < min_dur_delta
343
+ target_dur = 0.0
344
+ runner.registerWarning("For profile in #{hoo_sch.name} duration is being limited to a low of 0 hours.")
345
+ else
346
+ target_dur = hoo_dur_dows + orig_hoo_dur
347
+ end
348
+
349
+ # setup new hoo values with delta
350
+ if orig_hoo_start + hoo_start_dows <= 24.0
351
+ new_hoo_start = orig_hoo_start + hoo_start_dows
352
+ else
353
+ new_hoo_start = orig_hoo_start + hoo_start_dows - 24.0
354
+ end
355
+ if new_hoo_start + hoo_dur_dows + orig_hoo_dur <= 24.0
356
+ new_hoo_end = new_hoo_start + target_dur
357
+ else
358
+ new_hoo_end = new_hoo_start + target_dur - 24.0
359
+ end
360
+ else
361
+ new_hoo_start = hoo_start_dows
362
+ if hoo_start_dows + hoo_dur_dows <= 24.0
363
+ new_hoo_end = hoo_start_dows + hoo_dur_dows
364
+ else
365
+ new_hoo_end = hoo_start_dows + hoo_dur_dows - 24.0
366
+ end
367
+ end
368
+
369
+ # setup hoo start time
370
+ target_start_hr = new_hoo_start.truncate
371
+ target_start_min = ((new_hoo_start - target_start_hr) * 60.0).truncate
372
+ target_start_time = OpenStudio::Time.new(0, target_start_hr, target_start_min, 0)
373
+
374
+ # setup hoo end time
375
+ target_end_hr = new_hoo_end.truncate
376
+ target_end_min = ((new_hoo_end - target_end_hr) * 60.0).truncate
377
+ target_end_time = OpenStudio::Time.new(0, target_end_hr, target_end_min, 0)
378
+
379
+ # adding new values
380
+ new_profile.clearValues
381
+ if target_dur < 24
382
+ new_profile.addValue(target_start_time, 0)
383
+ end
384
+ if target_dur > 0
385
+ new_profile.addValue(target_end_time, 1)
386
+ end
387
+ os_time_24 = OpenStudio::Time.new(0, 24, 0, 0)
388
+ if target_end_time > target_start_time || target_start_time == os_time_24
389
+ new_profile.addValue(os_time_24, 0)
390
+ elsif target_end_time < target_start_time
391
+ new_profile.addValue(os_time_24, 1)
392
+ else # they are equal
393
+ if target_dur == 24.0
394
+ new_profile.addValue(os_time_24, 1)
395
+ else
396
+ new_profile.addValue(os_time_24, 0)
397
+ end
398
+ end
399
+ end
400
+ end
401
+
402
+ return altered_schedule_days
403
+ end
404
+
405
+ # define what happens when the measure is run
406
+ def run(model, runner, user_arguments)
407
+ super(model, runner, user_arguments)
408
+
409
+ # assign the user inputs to variables
410
+ args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
411
+ if !args then return false end
412
+
413
+ # check expected values of double arguments
414
+ fraction = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => 0.0, 'max' => 1.0, 'min_eq_bool' => true, 'max_eq_bool' => true, 'arg_array' => ['fraction_of_daily_occ_range'])
415
+
416
+ neg_24__24 = ['hoo_start_weekday',
417
+ 'hoo_dur_weekday',
418
+ 'hoo_start_saturday',
419
+ 'hoo_dur_saturday',
420
+ 'hoo_start_sunday',
421
+ 'hoo_dur_sunday']
422
+ time_hours = OsLib_HelperMethods.checkDoubleAndIntegerArguments(runner, user_arguments, 'min' => -24.0, 'max' => 24.0, 'min_eq_bool' => true, 'max_eq_bool' => true, 'arg_array' => neg_24__24)
423
+
424
+ # setup log messages that will come from standards
425
+ OsLib_HelperMethods.setup_log_msgs(runner, true) # bool is debug
426
+
427
+ # load standards
428
+ standard = Standard.build('90.1-2004') # selected template doesn't matter
429
+
430
+ if args['infer_parametric_schedules']
431
+ # infer hours of operation for the building
432
+ # @param fraction_of_daily_occ_range [Double] fraction above/below daily min range required to start and end hours of operation
433
+ occ_fraction = args['fraction_of_daily_occ_range']
434
+ standard.model_infer_hours_of_operation_building(model, fraction_of_daily_occ_range: occ_fraction, gen_occ_profile: true)
435
+ runner.registerInfo('Inferring initial hours of operation for the building and generating parametric profile formulas.')
436
+
437
+ # report back hours of operation
438
+ initial_hoo_range = []
439
+ hours_of_operation_hash_test = standard.space_hours_of_operation(model.getSpaces.first)
440
+ hours_of_operation_hash_test.each do |hoo_key, val|
441
+ initial_hoo_range << val[:hoo_hours]
442
+ runner.registerInfo("For Profile Index #{hoo_key} hours of operation run for #{val[:hoo_hours]} hours, from #{val[:hoo_start]} to #{val[:hoo_end]} and is used for #{val[:days_used].size} days of the year.")
443
+ end
444
+
445
+ # model_setup_parametric_schedules
446
+ # todo - there should be arg here that can have formula based on fraction of day and no hours is argument to gather_inputs_parametric_schedules method. need to update high level methods in standards to support input for this
447
+ standard.model_setup_parametric_schedules(model, gather_data_only: false)
448
+ end
449
+
450
+ # report final condition of model
451
+ hoo_summary_hash = hoo_summary(model, runner, standard)
452
+ if !hoo_summary_hash[:zero_hoo].empty?
453
+ runner.registerInitialCondition("Across the building the non-zero hours of operation range from #{hoo_summary_hash[:final_hoo_dur_range].min} hours to #{hoo_summary_hash[:final_hoo_dur_range].max} hours. Start of hours of operation range from #{hoo_summary_hash[:final_hoo_start_range].min} to #{hoo_summary_hash[:final_hoo_start_range].max}. One or more hours of operation schedules used contain a profile with 0 hours of operation.")
454
+ else
455
+ runner.registerInitialCondition("Across the building the hours of operation range from #{hoo_summary_hash[:final_hoo_dur_range].min} hours to #{hoo_summary_hash[:final_hoo_dur_range].max} hours. Start of hours of operation range from #{hoo_summary_hash[:final_hoo_start_range].min} to #{hoo_summary_hash[:final_hoo_start_range].max}.")
456
+ end
457
+
458
+ # gather hours of operation schedules used by this model
459
+ used_hoo_sch_sets = {}
460
+ model.getSpaces.sort.each do |space|
461
+ default_sch_type = OpenStudio::Model::DefaultScheduleType.new('HoursofOperationSchedule')
462
+ hours_of_operation = space.getDefaultSchedule(default_sch_type)
463
+ if !hours_of_operation.is_initialized
464
+ runner.registerWarning("Hours of Operation Schedule is not set for #{space.name}.")
465
+ next
466
+ end
467
+ hours_of_operation_hash = standard.space_hours_of_operation(space)
468
+ used_hoo_sch_sets[hours_of_operation.get] = hours_of_operation_hash
469
+ end
470
+
471
+ # loop through and alter hours of operation schedules
472
+ runner.registerInfo("There are #{used_hoo_sch_sets.uniq.size} hours of operation schedules in the model to alter.")
473
+
474
+ # process weekday profiles
475
+ runner.registerInfo('Altering hours of operation schedules for weekday profiles')
476
+ weekday = process_hoo(used_hoo_sch_sets, model, runner, args, ['mon', 'tue', 'wed', 'thur', 'fri'], args['hoo_start_weekday'], args['hoo_dur_weekday'])
477
+
478
+ # process saturday profiles
479
+ runner.registerInfo('Altering hours of operation schedules for saturday profiles')
480
+ saturday = process_hoo(used_hoo_sch_sets, model, runner, args, ['sat'], args['hoo_start_saturday'], args['hoo_dur_saturday'])
481
+
482
+ # process sunday profiles
483
+ runner.registerInfo('Altering hours of operation schedules for sunday profiles')
484
+ sunday = process_hoo(used_hoo_sch_sets, model, runner, args, ['sun'], args['hoo_start_sunday'], args['hoo_dur_sunday'])
485
+
486
+ # TODO: - need to address this error when manipulating schedules
487
+ # [openstudio.standards.ScheduleRuleset] <1> Pre-interpolated processed hash for Large Office Bldg Equip Default Schedule has one or more out of order conflicts: [[3.5, 0.8], [4.5, 0.6], [5.0, 0.6], [7.0, 0.5], [9.0, 0.4], [6.0, 0.4], [10.0, 0.9], [16.5, 0.9], [17.5, 0.8], [18.5, 0.9], [21.5, 0.9]]. Method will stop because Error on Out of Order was set to true.
488
+ # model_build_parametric_schedules
489
+ parametric_schedules = standard.model_apply_parametric_schedules(model, ramp_frequency: nil, infer_hoo_for_non_assigned_objects: true, error_on_out_of_order: true)
490
+ runner.registerInfo("Created #{parametric_schedules.size} parametric schedules.")
491
+
492
+ # report final condition of model
493
+ hoo_summary_hash = hoo_summary(model, runner, standard)
494
+ if !hoo_summary_hash[:zero_hoo].empty?
495
+ runner.registerFinalCondition("Across the building the non-zero hours of operation range from #{hoo_summary_hash[:final_hoo_dur_range].min} hours to #{hoo_summary_hash[:final_hoo_dur_range].max} hours. Start of hours of operation range from #{hoo_summary_hash[:final_hoo_start_range].min} to #{hoo_summary_hash[:final_hoo_start_range].max}. One or more hours of operation schedules used contain a profile with 0 hours of operation.")
496
+ else
497
+ runner.registerFinalCondition("Across the building the hours of operation range from #{hoo_summary_hash[:final_hoo_dur_range].min} hours to #{hoo_summary_hash[:final_hoo_dur_range].max} hours. Start of hours of operation range from #{hoo_summary_hash[:final_hoo_start_range].min} to #{hoo_summary_hash[:final_hoo_start_range].max}.")
498
+ end
499
+
500
+ # get log messages (if debut in setup is true this will fail for error)
501
+ OsLib_HelperMethods.log_msgs
502
+
503
+ # TODO: - adding hours of operation to a schedule that doesn't have them to start with, like a sunday, can be problematic
504
+ # todo - start of day may not be reliable and there may not be formula inputs to show what occupied behavior is
505
+ # todo - in a situation like that it could be good to get formula from day that was non-zero to start with like weekday or saturday.
506
+ # todo - maybe standards can do something like this when making the formulas in the first place.
507
+
508
+ return true
509
+ end
510
+ end
511
+
512
+ # register the measure to be used by the application
513
+ ShiftHoursOfOperation.new.registerWithApplication