honeybee-energy 1.116.106__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. honeybee_energy/__init__.py +24 -0
  2. honeybee_energy/__main__.py +4 -0
  3. honeybee_energy/_extend_honeybee.py +145 -0
  4. honeybee_energy/altnumber.py +21 -0
  5. honeybee_energy/baseline/__init__.py +2 -0
  6. honeybee_energy/baseline/create.py +608 -0
  7. honeybee_energy/baseline/data/__init__.py +1 -0
  8. honeybee_energy/baseline/data/constructions.csv +64 -0
  9. honeybee_energy/baseline/data/fen_ratios.csv +15 -0
  10. honeybee_energy/baseline/data/lpd_building.csv +21 -0
  11. honeybee_energy/baseline/data/pci_2016.csv +22 -0
  12. honeybee_energy/baseline/data/pci_2019.csv +22 -0
  13. honeybee_energy/baseline/data/pci_2022.csv +22 -0
  14. honeybee_energy/baseline/data/shw.csv +21 -0
  15. honeybee_energy/baseline/pci.py +512 -0
  16. honeybee_energy/baseline/result.py +371 -0
  17. honeybee_energy/boundarycondition.py +128 -0
  18. honeybee_energy/cli/__init__.py +69 -0
  19. honeybee_energy/cli/baseline.py +475 -0
  20. honeybee_energy/cli/edit.py +327 -0
  21. honeybee_energy/cli/lib.py +1154 -0
  22. honeybee_energy/cli/result.py +810 -0
  23. honeybee_energy/cli/setconfig.py +124 -0
  24. honeybee_energy/cli/settings.py +569 -0
  25. honeybee_energy/cli/simulate.py +380 -0
  26. honeybee_energy/cli/translate.py +1714 -0
  27. honeybee_energy/cli/validate.py +224 -0
  28. honeybee_energy/config.json +11 -0
  29. honeybee_energy/config.py +842 -0
  30. honeybee_energy/construction/__init__.py +1 -0
  31. honeybee_energy/construction/_base.py +374 -0
  32. honeybee_energy/construction/air.py +325 -0
  33. honeybee_energy/construction/dictutil.py +89 -0
  34. honeybee_energy/construction/dynamic.py +607 -0
  35. honeybee_energy/construction/opaque.py +460 -0
  36. honeybee_energy/construction/shade.py +319 -0
  37. honeybee_energy/construction/window.py +1096 -0
  38. honeybee_energy/construction/windowshade.py +847 -0
  39. honeybee_energy/constructionset.py +1655 -0
  40. honeybee_energy/dictutil.py +56 -0
  41. honeybee_energy/generator/__init__.py +5 -0
  42. honeybee_energy/generator/loadcenter.py +204 -0
  43. honeybee_energy/generator/pv.py +535 -0
  44. honeybee_energy/hvac/__init__.py +21 -0
  45. honeybee_energy/hvac/_base.py +124 -0
  46. honeybee_energy/hvac/_template.py +270 -0
  47. honeybee_energy/hvac/allair/__init__.py +22 -0
  48. honeybee_energy/hvac/allair/_base.py +349 -0
  49. honeybee_energy/hvac/allair/furnace.py +168 -0
  50. honeybee_energy/hvac/allair/psz.py +131 -0
  51. honeybee_energy/hvac/allair/ptac.py +163 -0
  52. honeybee_energy/hvac/allair/pvav.py +109 -0
  53. honeybee_energy/hvac/allair/vav.py +128 -0
  54. honeybee_energy/hvac/detailed.py +337 -0
  55. honeybee_energy/hvac/doas/__init__.py +28 -0
  56. honeybee_energy/hvac/doas/_base.py +345 -0
  57. honeybee_energy/hvac/doas/fcu.py +127 -0
  58. honeybee_energy/hvac/doas/radiant.py +329 -0
  59. honeybee_energy/hvac/doas/vrf.py +81 -0
  60. honeybee_energy/hvac/doas/wshp.py +91 -0
  61. honeybee_energy/hvac/heatcool/__init__.py +23 -0
  62. honeybee_energy/hvac/heatcool/_base.py +177 -0
  63. honeybee_energy/hvac/heatcool/baseboard.py +61 -0
  64. honeybee_energy/hvac/heatcool/evapcool.py +72 -0
  65. honeybee_energy/hvac/heatcool/fcu.py +92 -0
  66. honeybee_energy/hvac/heatcool/gasunit.py +53 -0
  67. honeybee_energy/hvac/heatcool/radiant.py +269 -0
  68. honeybee_energy/hvac/heatcool/residential.py +77 -0
  69. honeybee_energy/hvac/heatcool/vrf.py +54 -0
  70. honeybee_energy/hvac/heatcool/windowac.py +70 -0
  71. honeybee_energy/hvac/heatcool/wshp.py +62 -0
  72. honeybee_energy/hvac/idealair.py +699 -0
  73. honeybee_energy/internalmass.py +310 -0
  74. honeybee_energy/lib/__init__.py +1 -0
  75. honeybee_energy/lib/_loadconstructions.py +194 -0
  76. honeybee_energy/lib/_loadconstructionsets.py +117 -0
  77. honeybee_energy/lib/_loadmaterials.py +83 -0
  78. honeybee_energy/lib/_loadprogramtypes.py +125 -0
  79. honeybee_energy/lib/_loadschedules.py +87 -0
  80. honeybee_energy/lib/_loadtypelimits.py +64 -0
  81. honeybee_energy/lib/constructions.py +207 -0
  82. honeybee_energy/lib/constructionsets.py +95 -0
  83. honeybee_energy/lib/materials.py +67 -0
  84. honeybee_energy/lib/programtypes.py +125 -0
  85. honeybee_energy/lib/schedules.py +61 -0
  86. honeybee_energy/lib/scheduletypelimits.py +31 -0
  87. honeybee_energy/load/__init__.py +1 -0
  88. honeybee_energy/load/_base.py +190 -0
  89. honeybee_energy/load/daylight.py +397 -0
  90. honeybee_energy/load/dictutil.py +47 -0
  91. honeybee_energy/load/equipment.py +771 -0
  92. honeybee_energy/load/hotwater.py +543 -0
  93. honeybee_energy/load/infiltration.py +460 -0
  94. honeybee_energy/load/lighting.py +480 -0
  95. honeybee_energy/load/people.py +497 -0
  96. honeybee_energy/load/process.py +472 -0
  97. honeybee_energy/load/setpoint.py +816 -0
  98. honeybee_energy/load/ventilation.py +550 -0
  99. honeybee_energy/material/__init__.py +1 -0
  100. honeybee_energy/material/_base.py +166 -0
  101. honeybee_energy/material/dictutil.py +59 -0
  102. honeybee_energy/material/frame.py +367 -0
  103. honeybee_energy/material/gas.py +1087 -0
  104. honeybee_energy/material/glazing.py +854 -0
  105. honeybee_energy/material/opaque.py +1351 -0
  106. honeybee_energy/material/shade.py +1360 -0
  107. honeybee_energy/measure.py +472 -0
  108. honeybee_energy/programtype.py +723 -0
  109. honeybee_energy/properties/__init__.py +1 -0
  110. honeybee_energy/properties/aperture.py +333 -0
  111. honeybee_energy/properties/door.py +342 -0
  112. honeybee_energy/properties/extension.py +244 -0
  113. honeybee_energy/properties/face.py +274 -0
  114. honeybee_energy/properties/model.py +2640 -0
  115. honeybee_energy/properties/room.py +1747 -0
  116. honeybee_energy/properties/shade.py +314 -0
  117. honeybee_energy/properties/shademesh.py +262 -0
  118. honeybee_energy/reader.py +48 -0
  119. honeybee_energy/result/__init__.py +1 -0
  120. honeybee_energy/result/colorobj.py +648 -0
  121. honeybee_energy/result/emissions.py +290 -0
  122. honeybee_energy/result/err.py +101 -0
  123. honeybee_energy/result/eui.py +100 -0
  124. honeybee_energy/result/generation.py +160 -0
  125. honeybee_energy/result/loadbalance.py +890 -0
  126. honeybee_energy/result/match.py +202 -0
  127. honeybee_energy/result/osw.py +90 -0
  128. honeybee_energy/result/rdd.py +59 -0
  129. honeybee_energy/result/zsz.py +190 -0
  130. honeybee_energy/run.py +1577 -0
  131. honeybee_energy/schedule/__init__.py +1 -0
  132. honeybee_energy/schedule/day.py +626 -0
  133. honeybee_energy/schedule/dictutil.py +59 -0
  134. honeybee_energy/schedule/fixedinterval.py +1012 -0
  135. honeybee_energy/schedule/rule.py +619 -0
  136. honeybee_energy/schedule/ruleset.py +1867 -0
  137. honeybee_energy/schedule/typelimit.py +310 -0
  138. honeybee_energy/shw.py +315 -0
  139. honeybee_energy/simulation/__init__.py +1 -0
  140. honeybee_energy/simulation/control.py +214 -0
  141. honeybee_energy/simulation/daylightsaving.py +185 -0
  142. honeybee_energy/simulation/dictutil.py +51 -0
  143. honeybee_energy/simulation/output.py +646 -0
  144. honeybee_energy/simulation/parameter.py +606 -0
  145. honeybee_energy/simulation/runperiod.py +443 -0
  146. honeybee_energy/simulation/shadowcalculation.py +295 -0
  147. honeybee_energy/simulation/sizing.py +546 -0
  148. honeybee_energy/ventcool/__init__.py +5 -0
  149. honeybee_energy/ventcool/_crack_data.py +91 -0
  150. honeybee_energy/ventcool/afn.py +289 -0
  151. honeybee_energy/ventcool/control.py +269 -0
  152. honeybee_energy/ventcool/crack.py +126 -0
  153. honeybee_energy/ventcool/fan.py +493 -0
  154. honeybee_energy/ventcool/opening.py +365 -0
  155. honeybee_energy/ventcool/simulation.py +314 -0
  156. honeybee_energy/writer.py +1078 -0
  157. honeybee_energy-1.116.106.dist-info/METADATA +113 -0
  158. honeybee_energy-1.116.106.dist-info/RECORD +162 -0
  159. honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
  160. honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
  161. honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
  162. honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
@@ -0,0 +1,569 @@
1
+ """commands to generate honeybee energy simulation settings."""
2
+ import click
3
+ import sys
4
+ import logging
5
+ import json
6
+ import os
7
+
8
+ from ladybug.futil import preparedir
9
+ from ladybug.analysisperiod import AnalysisPeriod
10
+ from ladybug.dt import Date
11
+ from honeybee.config import folders
12
+ from honeybee.model import Model
13
+
14
+ from honeybee_energy.simulation.parameter import SimulationParameter
15
+ from honeybee_energy.simulation.runperiod import RunPeriod
16
+ from honeybee_energy.simulation.control import SimulationControl
17
+ from honeybee_energy.construction.windowshade import WindowConstructionShade
18
+ from honeybee_energy.construction.dynamic import WindowConstructionDynamic
19
+
20
+
21
+ _logger = logging.getLogger(__name__)
22
+
23
+
24
+ @click.group(help='Commands for simulating Honeybee JSON files in EnergyPlus.')
25
+ def settings():
26
+ pass
27
+
28
+
29
+ @settings.command('default-sim-par')
30
+ @click.argument('ddy-file', type=click.Path(
31
+ file_okay=True, dir_okay=False, resolve_path=True))
32
+ @click.option(
33
+ '--reporting-frequency', '-rf', help='Text for the frequency at which '
34
+ 'the outputs are reported. (Default: Hourly). Choose from the following: '
35
+ 'Annual, Monthly, Daily, Hourly, Timestep', default='Hourly', type=str)
36
+ @click.option(
37
+ '--run-period', '-rp', help='An AnalysisPeriod or RunPeriod string '
38
+ 'to dictate the start and end of the simulation '
39
+ '(eg. "6/21 to 9/21 between 0 and 23 @1"). If unspecified, the '
40
+ 'simulation will be for the whole year.', default=None, type=str)
41
+ @click.option(
42
+ '--north', '-n', default=0, type=float, show_default=True,
43
+ help='Number from -360 to 360 for the counterclockwise difference between '
44
+ 'North and the positive Y-axis in degrees. 90 is west; 270 is east')
45
+ @click.option(
46
+ '--filter-des-days/--all-des-days', ' /-all', help='Flag to note whether '
47
+ 'the design days in the ddy-file should be filtered to only include 99.6 '
48
+ 'and 0.4 design days.', default=True, show_default=True)
49
+ @click.option(
50
+ '--efficiency-standard', '-es', help='Text to set the efficiency standard, which '
51
+ 'will automatically set the efficiencies of all HVAC equipment when provided. '
52
+ 'Note that providing a standard here will cause the OpenStudio translation '
53
+ 'process to perform an additional sizing calculation with EnergyPlus, '
54
+ 'which is needed since the default efficiencies of equipment vary depending '
55
+ 'on their size. THIS WILL SIGNIFICANTLY INCREASE TRANSLATION TIME. '
56
+ 'However, it is often worthwhile when the goal is to match the '
57
+ 'HVAC specification with a particular standard.Choose from the following: '
58
+ 'DOE_Ref_Pre_1980, DOE_Ref_1980_2004, ASHRAE_2004, ASHRAE_2007, ASHRAE_2010, '
59
+ 'ASHRAE_2013, ASHRAE_2016, ASHRAE_2019', default=None, type=str)
60
+ @click.option(
61
+ '--climate-zone', '-cz', help='Text indicating the ASHRAE climate zone to be '
62
+ 'used with the efficiency_standard. When unspecified, the climate zone will be '
63
+ 'inferred from the design days. This input can be a single integer (in which '
64
+ 'case it is interpreted as A) or it can include the A, B, or C qualifier '
65
+ '(eg. 3C).', default=None, type=str)
66
+ @click.option(
67
+ '--building-type', '-bt', help='Text for the building type to be used in '
68
+ 'the efficiency_standard. If the type is not recognized or is None, it will '
69
+ 'be assumed that the building is a generic NonResidential.',
70
+ default=None, type=str)
71
+ @click.option(
72
+ '--output-file', '-f', help='Optional file to output the JSON string of '
73
+ 'the simulation parameters. By default, it will be printed to stdout.',
74
+ type=click.File('w'), default='-', show_default=True)
75
+ def default_sim_par(
76
+ ddy_file, reporting_frequency, run_period, north, filter_des_days,
77
+ efficiency_standard, climate_zone, building_type, output_file):
78
+ """Get a SimulationParameter JSON with default outputs for energy use only.
79
+
80
+ \b
81
+ Args:
82
+ ddy_file: Full path to a DDY file that will be used to specify design days
83
+ within the simulation parameter.
84
+ """
85
+ try:
86
+ sim_par = SimulationParameter()
87
+ sim_par.output.add_zone_energy_use()
88
+ sim_par.output.add_hvac_energy_use()
89
+ sim_par.output.add_electricity_generation()
90
+ sim_par.output.reporting_frequency = reporting_frequency
91
+ _apply_run_period(run_period, sim_par)
92
+ sim_par.north_angle = north
93
+ if os.path.isfile(ddy_file):
94
+ _apply_design_days(ddy_file, filter_des_days, sim_par)
95
+ if efficiency_standard is not None and efficiency_standard != '':
96
+ sim_par.sizing_parameter.efficiency_standard = efficiency_standard
97
+ if climate_zone is not None and climate_zone != '':
98
+ sim_par.sizing_parameter.climate_zone = climate_zone
99
+ if building_type is not None and building_type != '':
100
+ sim_par.sizing_parameter.building_type = building_type
101
+ output_file.write(json.dumps(sim_par.to_dict()))
102
+ except Exception as e:
103
+ _logger.exception('Failed to generate simulation parameter.\n{}'.format(e))
104
+ sys.exit(1)
105
+ else:
106
+ sys.exit(0)
107
+
108
+
109
+ @settings.command('load-balance-sim-par')
110
+ @click.argument('ddy-file', type=click.Path(
111
+ file_okay=True, dir_okay=False, resolve_path=True))
112
+ @click.option('--load-type', '-lt', help='A text value to set the type of load outputs '
113
+ 'requested. Choose from the following:\nAll - all energy use '
114
+ 'including heat lost from the zone\nTotal - the total load added to the '
115
+ 'zone (both sensible and latent)\nSensible - the sensible load added to '
116
+ 'the zone\nLatent - the latent load added to the zone.',
117
+ type=str, default='Total', show_default=True)
118
+ @click.option('--reporting-frequency', '-rf', help='Text for the frequency at which '
119
+ 'the outputs are reported. (Default: Hourly). Choose from the following: '
120
+ 'Annual, Monthly, Daily, Hourly Timestep', default='Hourly', type=str)
121
+ @click.option('--run-period', '-rp', help='An AnalysisPeriod or RunPeriod string '
122
+ 'to dictate the start and end of the simulation '
123
+ '(eg. "6/21 to 9/21 between 0 and 23 @1"). If unspecified, the '
124
+ 'simulation will be for the whole year.', default=None, type=str)
125
+ @click.option('--north', '-n', default=0, type=float, show_default=True,
126
+ help='Number from -360 to 360 for the counterclockwise difference between '
127
+ 'North and the positive Y-axis in degrees. 90 is west; 270 is east')
128
+ @click.option('--filter-des-days/--all-des-days', ' /-all', help='Flag to note whether '
129
+ 'the design days in the ddy-file should be filtered to only include 99.6 '
130
+ 'and 0.4 design days.', default=True, show_default=True)
131
+ @click.option('--output-file', '-f', help='Optional file to output the JSON string of '
132
+ 'the simulation parameters. By default, it will be printed to stdout.',
133
+ type=click.File('w'), default='-', show_default=True)
134
+ def load_balance_sim_par(ddy_file, load_type, reporting_frequency, run_period, north,
135
+ filter_des_days, output_file):
136
+ """Get a SimulationParameter JSON with outputs for thermal load balances.
137
+
138
+ \b
139
+ Args:
140
+ ddy_file: Full path to a DDY file that will be used to specify design days
141
+ within the simulation parameter.
142
+ """
143
+ try:
144
+ sim_par = SimulationParameter()
145
+ sim_par.output.add_zone_energy_use(load_type)
146
+ gl_load_type = load_type if load_type != 'All' else 'Total'
147
+ sim_par.output.add_gains_and_losses(gl_load_type)
148
+ sim_par.output.add_surface_energy_flow()
149
+ sim_par.output.reporting_frequency = reporting_frequency
150
+ _apply_run_period(run_period, sim_par)
151
+ sim_par.north_angle = north
152
+ if os.path.isfile(ddy_file):
153
+ _apply_design_days(ddy_file, filter_des_days, sim_par)
154
+ output_file.write(json.dumps(sim_par.to_dict()))
155
+ except Exception as e:
156
+ _logger.exception('Failed to generate simulation parameter.\n{}'.format(e))
157
+ sys.exit(1)
158
+ else:
159
+ sys.exit(0)
160
+
161
+
162
+ @settings.command('comfort-sim-par')
163
+ @click.argument('ddy-file', type=click.Path(
164
+ file_okay=True, dir_okay=False, resolve_path=True))
165
+ @click.option('--run-period', '-rp', help='An AnalysisPeriod or RunPeriod string '
166
+ 'to dictate the start and end of the simulation '
167
+ '(eg. "6/21 to 9/21 between 0 and 23 @1"). If unspecified, the '
168
+ 'simulation will be for the whole year.', default=None, type=str)
169
+ @click.option('--north', '-n', default=0, type=float, show_default=True,
170
+ help='Number from -360 to 360 for the counterclockwise difference between '
171
+ 'North and the positive Y-axis in degrees. 90 is west; 270 is east')
172
+ @click.option('--filter-des-days/--all-des-days', ' /-all', help='Flag to note whether '
173
+ 'the design days in the ddy-file should be filtered to only include 99.6 '
174
+ 'and 0.4 design days.', default=True, show_default=True)
175
+ @click.option('--output-file', '-f', help='Optional file to output the JSON string of '
176
+ 'the simulation parameters. By default, it will be printed to stdout.',
177
+ type=click.File('w'), default='-', show_default=True)
178
+ def comfort_sim_par(ddy_file, run_period, north, filter_des_days, output_file):
179
+ """Get a SimulationParameter JSON with outputs for thermal comfort mapping.
180
+
181
+ \b
182
+ Args:
183
+ ddy_file: Full path to a DDY file that will be used to specify design days
184
+ within the simulation parameter.
185
+ """
186
+ try:
187
+ sim_par = SimulationParameter()
188
+ sim_par.shadow_calculation.solar_distribution = \
189
+ 'FullInteriorAndExteriorWithReflections'
190
+ sim_par.output.add_comfort_metrics()
191
+ sim_par.output.add_surface_temperature()
192
+ _apply_run_period(run_period, sim_par)
193
+ sim_par.north_angle = north
194
+ if os.path.isfile(ddy_file):
195
+ _apply_design_days(ddy_file, filter_des_days, sim_par)
196
+ output_file.write(json.dumps(sim_par.to_dict()))
197
+ except Exception as e:
198
+ _logger.exception('Failed to generate simulation parameter.\n{}'.format(e))
199
+ sys.exit(1)
200
+ else:
201
+ sys.exit(0)
202
+
203
+
204
+ @settings.command('sizing-sim-par')
205
+ @click.argument('ddy-file', type=click.Path(
206
+ file_okay=True, dir_okay=False, resolve_path=True))
207
+ @click.option('--load-type', '-lt', help='A text value to set the type of load outputs '
208
+ 'requested. Choose from the following:\nAll - all energy use '
209
+ 'including heat lost from the zone\nTotal - the total load added to the '
210
+ 'zone (both sensible and latent)\nSensible - the sensible load added to '
211
+ 'the zone\nLatent - the latent load added to the zone.',
212
+ type=str, default='Total', show_default=True)
213
+ @click.option('--north', '-n', default=0, type=float, show_default=True,
214
+ help='Number from -360 to 360 for the counterclockwise difference between '
215
+ 'North and the positive Y-axis in degrees. 90 is west; 270 is east')
216
+ @click.option('--filter-des-days/--all-des-days', ' /-all', help='Flag to note whether '
217
+ 'the design days in the ddy-file should be filtered to only include 99.6 '
218
+ 'and 0.4 design days.', default=True, show_default=True)
219
+ @click.option('--output-file', '-f', help='Optional file to output the JSON string of '
220
+ 'the simulation parameters. By default, it will be printed to stdout.',
221
+ type=click.File('w'), default='-', show_default=True)
222
+ def sizing_sim_par(ddy_file, load_type, north, filter_des_days, output_file):
223
+ """Get a SimulationParameter JSON with outputs and run period for HVAC sizing.
224
+
225
+ \b
226
+ Args:
227
+ ddy_file: Full path to a DDY file that will be used to specify design days
228
+ within the simulation parameter.
229
+ """
230
+ try:
231
+ sim_par = SimulationParameter()
232
+ sim_par.output.add_zone_energy_use(load_type)
233
+ gl_load_type = load_type if load_type != 'All' else 'Total'
234
+ sim_par.output.add_gains_and_losses(gl_load_type)
235
+ sim_par.output.add_surface_energy_flow()
236
+ sim_par.simulation_control = SimulationControl(True, True, True, True, False)
237
+ sim_par.north_angle = north
238
+ if os.path.isfile(ddy_file):
239
+ _apply_design_days(ddy_file, filter_des_days, sim_par)
240
+ output_file.write(json.dumps(sim_par.to_dict()))
241
+ except Exception as e:
242
+ _logger.exception('Failed to generate simulation parameter.\n{}'.format(e))
243
+ sys.exit(1)
244
+ else:
245
+ sys.exit(0)
246
+
247
+
248
+ @settings.command('custom-sim-par')
249
+ @click.argument('ddy-file', type=click.Path(
250
+ file_okay=True, dir_okay=False, resolve_path=True))
251
+ @click.argument('output-names', nargs=-1)
252
+ @click.option('--reporting-frequency', '-rf', help='Text for the frequency at which '
253
+ 'the outputs are reported. (Default: Hourly). Choose from the following: '
254
+ 'Annual, Monthly, Daily, Hourly Timestep', default='Hourly', type=str)
255
+ @click.option('--run-period', '-rp', help='An AnalysisPeriod or RunPeriod string '
256
+ 'to dictate the start and end of the simulation '
257
+ '(eg. "6/21 to 9/21 between 0 and 23 @1"). If unspecified, the '
258
+ 'simulation will be for the whole year.', default=None, type=str)
259
+ @click.option('--north', '-n', default=0, type=float, show_default=True,
260
+ help='Number from -360 to 360 for the counterclockwise difference between '
261
+ 'North and the positive Y-axis in degrees. 90 is west; 270 is east')
262
+ @click.option('--filter-des-days/--all-des-days', ' /-all', help='Flag to note whether '
263
+ 'the design days in the ddy-file should be filtered to only include 99.6 '
264
+ 'and 0.4 design days.', default=True, show_default=True)
265
+ @click.option('--output-file', '-f', help='Optional file to output the JSON string of '
266
+ 'the simulation parameters. By default, it will be printed to stdout.',
267
+ type=click.File('w'), default='-', show_default=True)
268
+ def custom_sim_par(ddy_file, output_names, reporting_frequency, run_period, north,
269
+ filter_des_days, output_file):
270
+ """Get a SimulationParameter JSON with an option for custom outputs.
271
+
272
+ \b
273
+ Args:
274
+ ddy_file: Full path to a DDY file that will be used to specify design days
275
+ within the simulation parameter.
276
+ output_names: Any number of EnergyPlus output names as strings (eg.
277
+ 'Surface Window System Solar Transmittance'. These outputs will be
278
+ requested from the simulation.
279
+ """
280
+ try:
281
+ sim_par = SimulationParameter()
282
+ for output_name in output_names:
283
+ sim_par.output.add_output(output_name)
284
+ sim_par.output.reporting_frequency = reporting_frequency
285
+ _apply_run_period(run_period, sim_par)
286
+ sim_par.north_angle = north
287
+ if os.path.isfile(ddy_file):
288
+ _apply_design_days(ddy_file, filter_des_days, sim_par)
289
+ output_file.write(json.dumps(sim_par.to_dict()))
290
+ except Exception as e:
291
+ _logger.exception('Failed to generate simulation parameter.\n{}'.format(e))
292
+ sys.exit(1)
293
+ else:
294
+ sys.exit(0)
295
+
296
+
297
+ @settings.command('orientation-sim-pars')
298
+ @click.argument('ddy-file', type=click.Path(
299
+ file_okay=True, dir_okay=False, resolve_path=True))
300
+ @click.argument('north-angles', nargs=-1, type=float)
301
+ @click.option('--default-outputs/--no-default-outputs', ' /-nd', help='Flag to note '
302
+ 'whether the default outputs for energy usage should be included in '
303
+ 'the simulation parameters or no outputs should be requested except '
304
+ 'for those explicitly listed with --output-name.',
305
+ default=True, show_default=True)
306
+ @click.option('--output-name', '-o', help='Any number of EnergyPlus output names as '
307
+ 'strings (eg. Surface Window System Solar Transmittance). These outputs '
308
+ 'will be requested from the simulation.',
309
+ type=click.STRING, multiple=True, default=None, show_default=True)
310
+ @click.option('--reporting-frequency', '-rf', help='Text for the frequency at which '
311
+ 'the outputs are reported. (Default: Hourly). Choose from the following: '
312
+ 'Annual, Monthly, Daily, Hourly Timestep', default='Hourly', type=str)
313
+ @click.option('--run-period', '-rp', help='An AnalysisPeriod or RunPeriod string '
314
+ 'to dictate the start and end of the simulation '
315
+ '(eg. "6/21 to 9/21 between 0 and 23 @1"). If unspecified, the '
316
+ 'simulation will be for the whole year.', default=None, type=str)
317
+ @click.option('--start-north', '-n', default=0, type=float, show_default=True,
318
+ help='Number from -360 to 360 for the starting north angle. This will be '
319
+ 'added to the north-angles in order to shift all norths.')
320
+ @click.option('--filter-des-days/--all-des-days', ' /-all', help='Flag to note whether '
321
+ 'the design days in the ddy-file should be filtered to only include 99.6 '
322
+ 'and 0.4 design days.', default=True, show_default=True)
323
+ @click.option(
324
+ '--efficiency-standard', '-es', help='Text to set the efficiency standard, which '
325
+ 'will automatically set the efficiencies of all HVAC equipment when provided. '
326
+ 'Note that providing a standard here will cause the OpenStudio translation '
327
+ 'process to perform an additional sizing calculation with EnergyPlus, '
328
+ 'which is needed since the default efficiencies of equipment vary depending '
329
+ 'on their size. THIS WILL SIGNIFICANTLY INCREASE TRANSLATION TIME. '
330
+ 'However, it is often worthwhile when the goal is to match the '
331
+ 'HVAC specification with a particular standard.Choose from the following: '
332
+ 'DOE_Ref_Pre_1980, DOE_Ref_1980_2004, ASHRAE_2004, ASHRAE_2007, ASHRAE_2010, '
333
+ 'ASHRAE_2013, ASHRAE_2016, ASHRAE_2019', default=None, type=str)
334
+ @click.option(
335
+ '--climate-zone', '-cz', help='Text indicating the ASHRAE climate zone to be '
336
+ 'used with the efficiency_standard. When unspecified, the climate zone will be '
337
+ 'inferred from the design days. This input can be a single integer (in which '
338
+ 'case it is interpreted as A) or it can include the A, B, or C qualifier '
339
+ '(eg. 3C).', default=None, type=str)
340
+ @click.option(
341
+ '--building-type', '-bt', help='Text for the building type to be used in '
342
+ 'the efficiency_standard. If the type is not recognized or is None, it will '
343
+ 'be assumed that the building is a generic NonResidential.', default=None, type=str)
344
+ @click.option('--folder', '-f', help='Output folder for the simulation parameter JSONS.',
345
+ default=None, show_default=True,
346
+ type=click.Path(file_okay=False, dir_okay=True, resolve_path=True))
347
+ @click.option('--log-file', '-log', help='Optional log file to output the paths of the '
348
+ 'simulation parameters. By default the list will be printed out to '
349
+ 'stdout.', type=click.File('w'), default='-')
350
+ def orientation_sim_pars(
351
+ ddy_file, north_angles, default_outputs, output_name, reporting_frequency,
352
+ run_period, start_north, filter_des_days,
353
+ efficiency_standard, climate_zone, building_type, folder, log_file):
354
+ """Get SimulationParameter JSONs with different north angles for orientation studies.
355
+
356
+ \b
357
+ Args:
358
+ ddy_file: Full path to a DDY file that will be used to specify design days
359
+ within the simulation parameter.
360
+ north_angles: Any number of values between -360 and 360 for the counterclockwise
361
+ difference between the North and the positive Y-axis in degrees. 90 is
362
+ West and 270 is East.
363
+ """
364
+ try:
365
+ # get a default folder if none was specified
366
+ if folder is None:
367
+ folder = os.path.join(folders.default_simulation_folder, 'orientation_study')
368
+ preparedir(folder, remove_content=False)
369
+
370
+ # create a base set of simulation parameters to be edited parametrically
371
+ sim_par = SimulationParameter()
372
+ if default_outputs:
373
+ sim_par.output.add_zone_energy_use()
374
+ sim_par.output.add_hvac_energy_use()
375
+ sim_par.output.add_electricity_generation()
376
+ for out_name in output_name:
377
+ sim_par.output.add_output(out_name)
378
+ sim_par.output.reporting_frequency = reporting_frequency
379
+ _apply_run_period(run_period, sim_par)
380
+ if os.path.isfile(ddy_file):
381
+ _apply_design_days(ddy_file, filter_des_days, sim_par)
382
+
383
+ # set the sizing parameters if specified
384
+ if efficiency_standard is not None and efficiency_standard != '':
385
+ sim_par.sizing_parameter.efficiency_standard = efficiency_standard
386
+ if climate_zone is not None and climate_zone != '':
387
+ sim_par.sizing_parameter.climate_zone = climate_zone
388
+ if building_type is not None and building_type != '':
389
+ sim_par.sizing_parameter.building_type = building_type
390
+
391
+ # shift all of the north angles by the start_north if specified
392
+ if start_north != 0:
393
+ north_angles = [angle + start_north for angle in north_angles]
394
+ for i, angle in enumerate(north_angles):
395
+ angle = angle - 360 if angle > 360 else angle
396
+ angle = angle + 360 if angle < -360 else angle
397
+ north_angles[i] = angle
398
+
399
+ # loop through the north angles and write a simulation parameter for each
400
+ json_files = []
401
+ for angle in north_angles:
402
+ sim_par.north_angle = angle
403
+ base_name = 'sim_par_north_{}'.format(int(angle))
404
+ file_name = '{}.json'.format(base_name)
405
+ file_path = os.path.join(folder, file_name)
406
+ with open(file_path, 'w') as fp:
407
+ json.dump(sim_par.to_dict(), fp)
408
+ sp_info = {
409
+ 'id': base_name,
410
+ 'path': file_name,
411
+ 'full_path': os.path.abspath(file_path)
412
+ }
413
+ json_files.append(sp_info)
414
+ log_file.write(json.dumps(json_files))
415
+ except Exception as e:
416
+ _logger.exception('Failed to generate simulation parameters.\n{}'.format(e))
417
+ sys.exit(1)
418
+ else:
419
+ sys.exit(0)
420
+
421
+
422
+ @settings.command('run-period')
423
+ @click.argument('start-month', type=int)
424
+ @click.argument('start-day', type=int)
425
+ @click.argument('end-month', type=int)
426
+ @click.argument('end-day', type=int)
427
+ @click.option('--start-day-of-week', '-dow', help='Text for the day of the week '
428
+ 'on which the simulation starts.', type=str, default='Sunday',
429
+ show_default=True)
430
+ @click.option('--holidays', '-h', help='Text for the holidays within the simulation. '
431
+ 'Dates should be formatted as follows: "[day int] [month text]" '
432
+ '(eg. "25 Dec"). If not specified, no holidays are applied.',
433
+ type=str, default=None, show_default=True, multiple=True)
434
+ @click.option('--output-file', '-f', help='Optional file to output the JSON string of '
435
+ 'the run period. By default, it will be printed to stdout.',
436
+ type=click.File('w'), default='-', show_default=True)
437
+ def run_period(start_month, start_day, end_month, end_day, start_day_of_week,
438
+ holidays, output_file):
439
+ """Get a RunPeriod string that can be used to set the simulation run period.
440
+
441
+ \b
442
+ Args:
443
+ start_month: Start month (1-12).
444
+ start_day: Start day (1-31).
445
+ end_month: End month (1-12).
446
+ end_day: End day (1-31).
447
+ """
448
+ try:
449
+ # create the run period
450
+ a_period = AnalysisPeriod(start_month, start_day, 0, end_month, end_day, 23)
451
+ run_period = RunPeriod.from_analysis_period(a_period)
452
+ # set the start day of the week if it is input
453
+ if start_day_of_week is not None:
454
+ run_period.start_day_of_week = start_day_of_week.title()
455
+ # set the holidays if requested.
456
+ if holidays:
457
+ dates = tuple(Date.from_date_string(date) for date in holidays)
458
+ run_period.holidays = dates
459
+ output_file.write(str(run_period))
460
+ except Exception as e:
461
+ _logger.exception('Failed to generate run period.\n{}'.format(e))
462
+ sys.exit(1)
463
+ else:
464
+ sys.exit(0)
465
+
466
+
467
+ @settings.command('dynamic-window-outputs')
468
+ @click.argument('model-file', type=click.Path(
469
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
470
+ @click.option(
471
+ '--base-idf', '-i', help='An optional base IDF file to which the outputs '
472
+ 'for dynamic windows will be appended.', default=None, show_default=True,
473
+ type=click.Path(exists=False, file_okay=True, dir_okay=False, resolve_path=True))
474
+ @click.option(
475
+ '--output-file', '-f', help='Optional IDF file to output the list of outputs to '
476
+ 'add to the EnergyPlus simulation. By default this will be printed out to '
477
+ 'stdout', type=click.File('w'), default='-', show_default=True)
478
+ def dynamic_window_outputs(model_file, base_idf, output_file):
479
+ """Get an IDF string that requests transmittance outputs for dynamic windows.
480
+
481
+ This should be used within comfort mapping workflows to request transmittance
482
+ outputs for dynamic windows. Note that the output is just an IDF text string
483
+ that should be incorporated in the energy simulation by means of additional
484
+ strings or additional IDF.
485
+
486
+ \b
487
+ Args:
488
+ model_file: Full path to a Model JSON or Pkl file to be analyzed for
489
+ dynamic window constructions.
490
+ """
491
+ try:
492
+ # define templates to be reused for each dynamic window
493
+ out_vars = [
494
+ 'Surface Window Transmitted Beam to Beam Solar Radiation Rate',
495
+ 'Surface Window Transmitted Beam to Diffuse Solar Radiation Rate',
496
+ 'Surface Window Transmitted Diffuse Solar Radiation Rate',
497
+ 'Surface Outside Face Incident Solar Radiation Rate per Area',
498
+ ]
499
+ out_per_win = ['Output:Variable, {}, ' + var + ', Timestep;' for var in out_vars]
500
+
501
+ # define dynamic constructions and re-serialize the Model to Python
502
+ dyn_con = (WindowConstructionShade, WindowConstructionDynamic)
503
+ model = Model.from_file(model_file)
504
+
505
+ # load up the contents of the base IDF file if it exists
506
+ out_strs = []
507
+ if base_idf is not None and os.path.isfile(base_idf):
508
+ with open(base_idf, "r") as add_idf_file:
509
+ out_strs.append(add_idf_file.read())
510
+
511
+ # loop through the apertures and add outputs to be requested
512
+ for room in model.rooms:
513
+ for face in room.faces:
514
+ for ap in face.apertures:
515
+ if isinstance(ap.properties.energy.construction, dyn_con):
516
+ for op in out_per_win:
517
+ out_strs.append(op.format(ap.identifier))
518
+
519
+ # write the IDF string
520
+ output_file.write('\n'.join(out_strs))
521
+ except Exception as e:
522
+ _logger.exception('Model baseline geometry creation failed.\n{}'.format(e))
523
+ sys.exit(1)
524
+ else:
525
+ sys.exit(0)
526
+
527
+
528
+ def _load_run_period_str(run_period_str):
529
+ """Load a RunPeriod from a string of a run period or analysis period.
530
+
531
+ Args:
532
+ run_period_str: A string of a RunPeriod or AnalysisPeriod to be loaded.
533
+ """
534
+ if run_period_str is not None and run_period_str != '' \
535
+ and run_period_str != 'None':
536
+ if run_period_str.startswith('RunPeriod'):
537
+ return RunPeriod.from_string(run_period_str)
538
+ else:
539
+ return RunPeriod.from_analysis_period(
540
+ AnalysisPeriod.from_string(run_period_str))
541
+
542
+
543
+ def _apply_run_period(run_period_json, sim_par):
544
+ """Helper function to apply a RunPeriod from a JSON to simulation parameters.
545
+
546
+ Args:
547
+ run_period_json: A JSON file of a RunPeriod or AnalysisPeriod to be loaded.
548
+ sim_par: A SimulationParameter object.
549
+ """
550
+ run_period = _load_run_period_str(run_period_json)
551
+ if run_period is not None:
552
+ sim_par.run_period = run_period
553
+
554
+
555
+ def _apply_design_days(ddy_file, filter_des_days, sim_par):
556
+ """Apply design days from a DDY file to simulation parameters.
557
+
558
+ Args:
559
+ ddy_file: Path to a .ddy file.
560
+ filter_des_days: Boolean for whether design days should be filtered.
561
+ sim_par: A SimulationPArameter object.
562
+ """
563
+ try:
564
+ if filter_des_days:
565
+ sim_par.sizing_parameter.add_from_ddy_996_004(ddy_file)
566
+ else:
567
+ sim_par.sizing_parameter.add_from_ddy(ddy_file)
568
+ except AssertionError: # no design days in the DDY file
569
+ pass