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.
- honeybee_energy/__init__.py +24 -0
- honeybee_energy/__main__.py +4 -0
- honeybee_energy/_extend_honeybee.py +145 -0
- honeybee_energy/altnumber.py +21 -0
- honeybee_energy/baseline/__init__.py +2 -0
- honeybee_energy/baseline/create.py +608 -0
- honeybee_energy/baseline/data/__init__.py +1 -0
- honeybee_energy/baseline/data/constructions.csv +64 -0
- honeybee_energy/baseline/data/fen_ratios.csv +15 -0
- honeybee_energy/baseline/data/lpd_building.csv +21 -0
- honeybee_energy/baseline/data/pci_2016.csv +22 -0
- honeybee_energy/baseline/data/pci_2019.csv +22 -0
- honeybee_energy/baseline/data/pci_2022.csv +22 -0
- honeybee_energy/baseline/data/shw.csv +21 -0
- honeybee_energy/baseline/pci.py +512 -0
- honeybee_energy/baseline/result.py +371 -0
- honeybee_energy/boundarycondition.py +128 -0
- honeybee_energy/cli/__init__.py +69 -0
- honeybee_energy/cli/baseline.py +475 -0
- honeybee_energy/cli/edit.py +327 -0
- honeybee_energy/cli/lib.py +1154 -0
- honeybee_energy/cli/result.py +810 -0
- honeybee_energy/cli/setconfig.py +124 -0
- honeybee_energy/cli/settings.py +569 -0
- honeybee_energy/cli/simulate.py +380 -0
- honeybee_energy/cli/translate.py +1714 -0
- honeybee_energy/cli/validate.py +224 -0
- honeybee_energy/config.json +11 -0
- honeybee_energy/config.py +842 -0
- honeybee_energy/construction/__init__.py +1 -0
- honeybee_energy/construction/_base.py +374 -0
- honeybee_energy/construction/air.py +325 -0
- honeybee_energy/construction/dictutil.py +89 -0
- honeybee_energy/construction/dynamic.py +607 -0
- honeybee_energy/construction/opaque.py +460 -0
- honeybee_energy/construction/shade.py +319 -0
- honeybee_energy/construction/window.py +1096 -0
- honeybee_energy/construction/windowshade.py +847 -0
- honeybee_energy/constructionset.py +1655 -0
- honeybee_energy/dictutil.py +56 -0
- honeybee_energy/generator/__init__.py +5 -0
- honeybee_energy/generator/loadcenter.py +204 -0
- honeybee_energy/generator/pv.py +535 -0
- honeybee_energy/hvac/__init__.py +21 -0
- honeybee_energy/hvac/_base.py +124 -0
- honeybee_energy/hvac/_template.py +270 -0
- honeybee_energy/hvac/allair/__init__.py +22 -0
- honeybee_energy/hvac/allair/_base.py +349 -0
- honeybee_energy/hvac/allair/furnace.py +168 -0
- honeybee_energy/hvac/allair/psz.py +131 -0
- honeybee_energy/hvac/allair/ptac.py +163 -0
- honeybee_energy/hvac/allair/pvav.py +109 -0
- honeybee_energy/hvac/allair/vav.py +128 -0
- honeybee_energy/hvac/detailed.py +337 -0
- honeybee_energy/hvac/doas/__init__.py +28 -0
- honeybee_energy/hvac/doas/_base.py +345 -0
- honeybee_energy/hvac/doas/fcu.py +127 -0
- honeybee_energy/hvac/doas/radiant.py +329 -0
- honeybee_energy/hvac/doas/vrf.py +81 -0
- honeybee_energy/hvac/doas/wshp.py +91 -0
- honeybee_energy/hvac/heatcool/__init__.py +23 -0
- honeybee_energy/hvac/heatcool/_base.py +177 -0
- honeybee_energy/hvac/heatcool/baseboard.py +61 -0
- honeybee_energy/hvac/heatcool/evapcool.py +72 -0
- honeybee_energy/hvac/heatcool/fcu.py +92 -0
- honeybee_energy/hvac/heatcool/gasunit.py +53 -0
- honeybee_energy/hvac/heatcool/radiant.py +269 -0
- honeybee_energy/hvac/heatcool/residential.py +77 -0
- honeybee_energy/hvac/heatcool/vrf.py +54 -0
- honeybee_energy/hvac/heatcool/windowac.py +70 -0
- honeybee_energy/hvac/heatcool/wshp.py +62 -0
- honeybee_energy/hvac/idealair.py +699 -0
- honeybee_energy/internalmass.py +310 -0
- honeybee_energy/lib/__init__.py +1 -0
- honeybee_energy/lib/_loadconstructions.py +194 -0
- honeybee_energy/lib/_loadconstructionsets.py +117 -0
- honeybee_energy/lib/_loadmaterials.py +83 -0
- honeybee_energy/lib/_loadprogramtypes.py +125 -0
- honeybee_energy/lib/_loadschedules.py +87 -0
- honeybee_energy/lib/_loadtypelimits.py +64 -0
- honeybee_energy/lib/constructions.py +207 -0
- honeybee_energy/lib/constructionsets.py +95 -0
- honeybee_energy/lib/materials.py +67 -0
- honeybee_energy/lib/programtypes.py +125 -0
- honeybee_energy/lib/schedules.py +61 -0
- honeybee_energy/lib/scheduletypelimits.py +31 -0
- honeybee_energy/load/__init__.py +1 -0
- honeybee_energy/load/_base.py +190 -0
- honeybee_energy/load/daylight.py +397 -0
- honeybee_energy/load/dictutil.py +47 -0
- honeybee_energy/load/equipment.py +771 -0
- honeybee_energy/load/hotwater.py +543 -0
- honeybee_energy/load/infiltration.py +460 -0
- honeybee_energy/load/lighting.py +480 -0
- honeybee_energy/load/people.py +497 -0
- honeybee_energy/load/process.py +472 -0
- honeybee_energy/load/setpoint.py +816 -0
- honeybee_energy/load/ventilation.py +550 -0
- honeybee_energy/material/__init__.py +1 -0
- honeybee_energy/material/_base.py +166 -0
- honeybee_energy/material/dictutil.py +59 -0
- honeybee_energy/material/frame.py +367 -0
- honeybee_energy/material/gas.py +1087 -0
- honeybee_energy/material/glazing.py +854 -0
- honeybee_energy/material/opaque.py +1351 -0
- honeybee_energy/material/shade.py +1360 -0
- honeybee_energy/measure.py +472 -0
- honeybee_energy/programtype.py +723 -0
- honeybee_energy/properties/__init__.py +1 -0
- honeybee_energy/properties/aperture.py +333 -0
- honeybee_energy/properties/door.py +342 -0
- honeybee_energy/properties/extension.py +244 -0
- honeybee_energy/properties/face.py +274 -0
- honeybee_energy/properties/model.py +2640 -0
- honeybee_energy/properties/room.py +1747 -0
- honeybee_energy/properties/shade.py +314 -0
- honeybee_energy/properties/shademesh.py +262 -0
- honeybee_energy/reader.py +48 -0
- honeybee_energy/result/__init__.py +1 -0
- honeybee_energy/result/colorobj.py +648 -0
- honeybee_energy/result/emissions.py +290 -0
- honeybee_energy/result/err.py +101 -0
- honeybee_energy/result/eui.py +100 -0
- honeybee_energy/result/generation.py +160 -0
- honeybee_energy/result/loadbalance.py +890 -0
- honeybee_energy/result/match.py +202 -0
- honeybee_energy/result/osw.py +90 -0
- honeybee_energy/result/rdd.py +59 -0
- honeybee_energy/result/zsz.py +190 -0
- honeybee_energy/run.py +1577 -0
- honeybee_energy/schedule/__init__.py +1 -0
- honeybee_energy/schedule/day.py +626 -0
- honeybee_energy/schedule/dictutil.py +59 -0
- honeybee_energy/schedule/fixedinterval.py +1012 -0
- honeybee_energy/schedule/rule.py +619 -0
- honeybee_energy/schedule/ruleset.py +1867 -0
- honeybee_energy/schedule/typelimit.py +310 -0
- honeybee_energy/shw.py +315 -0
- honeybee_energy/simulation/__init__.py +1 -0
- honeybee_energy/simulation/control.py +214 -0
- honeybee_energy/simulation/daylightsaving.py +185 -0
- honeybee_energy/simulation/dictutil.py +51 -0
- honeybee_energy/simulation/output.py +646 -0
- honeybee_energy/simulation/parameter.py +606 -0
- honeybee_energy/simulation/runperiod.py +443 -0
- honeybee_energy/simulation/shadowcalculation.py +295 -0
- honeybee_energy/simulation/sizing.py +546 -0
- honeybee_energy/ventcool/__init__.py +5 -0
- honeybee_energy/ventcool/_crack_data.py +91 -0
- honeybee_energy/ventcool/afn.py +289 -0
- honeybee_energy/ventcool/control.py +269 -0
- honeybee_energy/ventcool/crack.py +126 -0
- honeybee_energy/ventcool/fan.py +493 -0
- honeybee_energy/ventcool/opening.py +365 -0
- honeybee_energy/ventcool/simulation.py +314 -0
- honeybee_energy/writer.py +1078 -0
- honeybee_energy-1.116.106.dist-info/METADATA +113 -0
- honeybee_energy-1.116.106.dist-info/RECORD +162 -0
- honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
- honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
- honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
- honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""Settings for the EnergyPlus Shadow Calculation."""
|
|
3
|
+
from __future__ import division
|
|
4
|
+
|
|
5
|
+
from ..reader import parse_idf_string
|
|
6
|
+
from ..writer import generate_idf_string
|
|
7
|
+
|
|
8
|
+
from honeybee.typing import valid_string, int_in_range
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ShadowCalculation(object):
|
|
12
|
+
"""Settings for the EnergyPlus Shadow Calculation.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
solar_distribution: Text desribing how EnergyPlus should treat beam solar
|
|
17
|
+
radiation and reflectances from surfaces that strike the building
|
|
18
|
+
surfaces. (Default: FullExteriorWithReflections). Choose from the following:
|
|
19
|
+
|
|
20
|
+
* MinimalShadowing
|
|
21
|
+
* FullExterior
|
|
22
|
+
* FullInteriorAndExterior
|
|
23
|
+
* FullExteriorWithReflections
|
|
24
|
+
* FullInteriorAndExteriorWithReflections
|
|
25
|
+
|
|
26
|
+
calculation_method: Text noting whether CPU-based polygon clipping method or
|
|
27
|
+
GPU-based pixel counting method should be used. For low numbers of shading
|
|
28
|
+
surfaces (less than ~200), PolygonClipping requires less runtime than
|
|
29
|
+
PixelCounting. However, PixelCounting runtime scales significantly
|
|
30
|
+
better at higher numbers of shading surfaces. PixelCounting also has
|
|
31
|
+
no limitations related to zone concavity when used with any
|
|
32
|
+
“FullInterior” solar distribution options. (Default: PolygonClipping).
|
|
33
|
+
Choose from the following:
|
|
34
|
+
|
|
35
|
+
* PolygonClipping
|
|
36
|
+
* PixelCounting
|
|
37
|
+
|
|
38
|
+
calculation_update_method: Text describing how often the solar and shading
|
|
39
|
+
calculations are updated with respect to the flow of time in the
|
|
40
|
+
simulation. (Default: Periodic). Choose from the following:
|
|
41
|
+
|
|
42
|
+
* Periodic
|
|
43
|
+
* Timestep
|
|
44
|
+
|
|
45
|
+
calculation_frequency: Integer for the number of days in each period for
|
|
46
|
+
which a unique shadow calculation will be performed. This field is only
|
|
47
|
+
used if the Periodic method is used in the previous field. (Default: 30).
|
|
48
|
+
maximum_figures: Integer for the number of figures used in shadow overlaps.
|
|
49
|
+
(Default: 15000).
|
|
50
|
+
|
|
51
|
+
Properties:
|
|
52
|
+
* solar_distribution
|
|
53
|
+
* calculation_method
|
|
54
|
+
* calculation_update_method
|
|
55
|
+
* calculation_frequency
|
|
56
|
+
* maximum_figures
|
|
57
|
+
"""
|
|
58
|
+
__slots__ = (
|
|
59
|
+
'_solar_distribution', '_calculation_method', '_calculation_update_method',
|
|
60
|
+
'_calculation_frequency', '_maximum_figures')
|
|
61
|
+
SOLAR_DISTRIBUTIONS = (
|
|
62
|
+
'MinimalShadowing', 'FullExterior', 'FullInteriorAndExterior',
|
|
63
|
+
'FullExteriorWithReflections', 'FullInteriorAndExteriorWithReflections')
|
|
64
|
+
CALCULATION_METHODS = ('PolygonClipping', 'PixelCounting')
|
|
65
|
+
CALCULATION_UPDATE_METHODS = ('Periodic', 'Timestep')
|
|
66
|
+
|
|
67
|
+
def __init__(self, solar_distribution='FullExteriorWithReflections',
|
|
68
|
+
calculation_method='PolygonClipping',
|
|
69
|
+
calculation_update_method='Periodic',
|
|
70
|
+
calculation_frequency=30, maximum_figures=15000):
|
|
71
|
+
"""Initialize ShadowCalculation."""
|
|
72
|
+
self.solar_distribution = solar_distribution
|
|
73
|
+
self.calculation_method = calculation_method
|
|
74
|
+
self.calculation_update_method = calculation_update_method
|
|
75
|
+
self.calculation_frequency = calculation_frequency
|
|
76
|
+
self.maximum_figures = maximum_figures
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def solar_distribution(self):
|
|
80
|
+
"""Get or set text for how solar reflectances from surfaces should be treated.
|
|
81
|
+
|
|
82
|
+
Choose from the options below:
|
|
83
|
+
|
|
84
|
+
* MinimalShadowing
|
|
85
|
+
* FullExterior
|
|
86
|
+
* FullInteriorAndExterior
|
|
87
|
+
* FullExteriorWithReflections
|
|
88
|
+
* FullInteriorAndExteriorWithReflections
|
|
89
|
+
"""
|
|
90
|
+
return self._solar_distribution
|
|
91
|
+
|
|
92
|
+
@solar_distribution.setter
|
|
93
|
+
def solar_distribution(self, value):
|
|
94
|
+
clean_input = valid_string(value).lower()
|
|
95
|
+
for key in self.SOLAR_DISTRIBUTIONS:
|
|
96
|
+
if key.lower() == clean_input:
|
|
97
|
+
value = key
|
|
98
|
+
break
|
|
99
|
+
else:
|
|
100
|
+
raise ValueError(
|
|
101
|
+
'solar_distribution {} is not recognized.\nChoose from the '
|
|
102
|
+
'following:\n{}'.format(value, self.SOLAR_DISTRIBUTIONS))
|
|
103
|
+
self._solar_distribution = value
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def calculation_method(self):
|
|
107
|
+
"""Get or set text for whether CPU-based or GPU-based methods should be used.
|
|
108
|
+
|
|
109
|
+
Choose from the options below:
|
|
110
|
+
|
|
111
|
+
* PolygonClipping
|
|
112
|
+
* PixelCounting
|
|
113
|
+
"""
|
|
114
|
+
return self._calculation_method
|
|
115
|
+
|
|
116
|
+
@calculation_method.setter
|
|
117
|
+
def calculation_method(self, value):
|
|
118
|
+
clean_input = valid_string(value).lower()
|
|
119
|
+
for key in self.CALCULATION_METHODS:
|
|
120
|
+
if key.lower() == clean_input:
|
|
121
|
+
value = key
|
|
122
|
+
break
|
|
123
|
+
else:
|
|
124
|
+
raise ValueError(
|
|
125
|
+
'calculation_method "{}" is not recognized.\nChoose from the '
|
|
126
|
+
'following:\n{}'.format(value, self.CALCULATION_METHODS))
|
|
127
|
+
self._calculation_method = value
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def calculation_update_method(self):
|
|
131
|
+
"""Get or set text for how often the solar and shading calculations are updated.
|
|
132
|
+
|
|
133
|
+
Choose from the options below:
|
|
134
|
+
|
|
135
|
+
* Periodic
|
|
136
|
+
* Timestep
|
|
137
|
+
"""
|
|
138
|
+
return self._calculation_update_method
|
|
139
|
+
|
|
140
|
+
@calculation_update_method.setter
|
|
141
|
+
def calculation_update_method(self, value):
|
|
142
|
+
clean_input = valid_string(value).lower()
|
|
143
|
+
for key in self.CALCULATION_UPDATE_METHODS:
|
|
144
|
+
if key.lower() == clean_input:
|
|
145
|
+
value = key
|
|
146
|
+
break
|
|
147
|
+
else:
|
|
148
|
+
raise ValueError(
|
|
149
|
+
'calculation_update_method "{}" is not recognized.\nChoose from the '
|
|
150
|
+
'following:\n{}'.format(value, self.CALCULATION_UPDATE_METHODS))
|
|
151
|
+
self._calculation_update_method = value
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def calculation_frequency(self):
|
|
155
|
+
"""Get or set a integer for the number of days with unique shadow calculations.
|
|
156
|
+
"""
|
|
157
|
+
return self._calculation_frequency
|
|
158
|
+
|
|
159
|
+
@calculation_frequency.setter
|
|
160
|
+
def calculation_frequency(self, value):
|
|
161
|
+
self._calculation_frequency = int_in_range(
|
|
162
|
+
value, 1, input_name='shadow calculation calculation frequency')
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def maximum_figures(self):
|
|
166
|
+
"""Get or set a integer for the number of figures used in shadow overlaps."""
|
|
167
|
+
return self._maximum_figures
|
|
168
|
+
|
|
169
|
+
@maximum_figures.setter
|
|
170
|
+
def maximum_figures(self, value):
|
|
171
|
+
self._maximum_figures = int_in_range(
|
|
172
|
+
value, 200, input_name='shadow calculation maximum figures')
|
|
173
|
+
|
|
174
|
+
@classmethod
|
|
175
|
+
def from_idf(cls, idf_string, solar_distribution='FullExteriorWithReflections'):
|
|
176
|
+
"""Create a ShadowCalculation object from an EnergyPlus IDF text string.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
idf_string: A text string fully describing an EnergyPlus
|
|
180
|
+
ShadowCalculation definition.
|
|
181
|
+
solar_distribution: Text desribing how EnergyPlus should treat beam
|
|
182
|
+
solar radiation and reflectances from surfaces that strike the
|
|
183
|
+
building surfaces.
|
|
184
|
+
"""
|
|
185
|
+
# check the inputs
|
|
186
|
+
ep_strs = parse_idf_string(idf_string, 'ShadowCalculation,')
|
|
187
|
+
|
|
188
|
+
# extract the properties from the string
|
|
189
|
+
calc_method = 'PolygonClipping'
|
|
190
|
+
update_method = 'Periodic'
|
|
191
|
+
calculation_frequency = 20
|
|
192
|
+
maximum_figures = 15000
|
|
193
|
+
try:
|
|
194
|
+
calc_method = ep_strs[0] if ep_strs[0] != '' else update_method
|
|
195
|
+
update_method = ep_strs[1] if ep_strs[1] != '' else update_method
|
|
196
|
+
calculation_frequency = ep_strs[2] if ep_strs[2] != '' else 20
|
|
197
|
+
maximum_figures = ep_strs[3] if ep_strs[3] != '' else 15000
|
|
198
|
+
except IndexError:
|
|
199
|
+
pass # shorter ShadowCalculation definition
|
|
200
|
+
|
|
201
|
+
return cls(solar_distribution, calc_method, update_method,
|
|
202
|
+
calculation_frequency, maximum_figures)
|
|
203
|
+
|
|
204
|
+
@classmethod
|
|
205
|
+
def from_dict(cls, data):
|
|
206
|
+
"""Create a ShadowCalculation object from a dictionary.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
data: A ShadowCalculation dictionary in following the format below.
|
|
210
|
+
|
|
211
|
+
.. code-block:: python
|
|
212
|
+
|
|
213
|
+
{
|
|
214
|
+
"type": "ShadowCalculation",
|
|
215
|
+
"solar_distribution": 'FullInteriorAndExteriorWithReflections',
|
|
216
|
+
"calculation_method": 'PolygonClipping',
|
|
217
|
+
"calculation_update_method": 'Periodic',
|
|
218
|
+
"calculation_frequency": 30,
|
|
219
|
+
"maximum_figures": 15000
|
|
220
|
+
}
|
|
221
|
+
"""
|
|
222
|
+
assert data['type'] == 'ShadowCalculation', \
|
|
223
|
+
'Expected ShadowCalculation dictionary. Got {}.'.format(data['type'])
|
|
224
|
+
solar_distribution = data['solar_distribution'] if \
|
|
225
|
+
'solar_distribution' in data else 'FullExteriorWithReflections'
|
|
226
|
+
calculation_method = data['calculation_method'] if \
|
|
227
|
+
'calculation_method' in data else 'PolygonClipping'
|
|
228
|
+
update_method = data['calculation_update_method'] if \
|
|
229
|
+
'calculation_update_method' in data else 'Periodic'
|
|
230
|
+
calculation_frequency = data['calculation_frequency'] if \
|
|
231
|
+
'calculation_frequency' in data else 30
|
|
232
|
+
maximum_figures = data['maximum_figures'] if \
|
|
233
|
+
'maximum_figures' in data else 15000
|
|
234
|
+
return cls(solar_distribution, calculation_method, update_method,
|
|
235
|
+
calculation_frequency, maximum_figures)
|
|
236
|
+
|
|
237
|
+
def to_idf(self):
|
|
238
|
+
"""Get an EnergyPlus string representation of the ShadowCalculation.
|
|
239
|
+
|
|
240
|
+
.. code-block:: shell
|
|
241
|
+
|
|
242
|
+
ShadowCalculation,
|
|
243
|
+
PolygonClipping, !- calculation method
|
|
244
|
+
Periodic, !- calculation update method
|
|
245
|
+
30, !- calculation frequency
|
|
246
|
+
15000; !- maximum figures
|
|
247
|
+
"""
|
|
248
|
+
values = (self.calculation_method, self.calculation_update_method,
|
|
249
|
+
self.calculation_frequency, self.maximum_figures)
|
|
250
|
+
comments = ('calculation method', 'calculation update method',
|
|
251
|
+
'calculation frequency', 'maximum figures')
|
|
252
|
+
return generate_idf_string('ShadowCalculation', values, comments)
|
|
253
|
+
|
|
254
|
+
def to_dict(self):
|
|
255
|
+
"""ShadowCalculation dictionary representation."""
|
|
256
|
+
return {
|
|
257
|
+
'type': 'ShadowCalculation',
|
|
258
|
+
'solar_distribution': self.solar_distribution,
|
|
259
|
+
'calculation_method': self.calculation_method,
|
|
260
|
+
'calculation_update_method': self.calculation_update_method,
|
|
261
|
+
'calculation_frequency': self.calculation_frequency,
|
|
262
|
+
'maximum_figures': self.maximum_figures
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
def duplicate(self):
|
|
266
|
+
"""Get a copy of this object."""
|
|
267
|
+
return self.__copy__()
|
|
268
|
+
|
|
269
|
+
def ToString(self):
|
|
270
|
+
"""Overwrite .NET ToString."""
|
|
271
|
+
return self.__repr__()
|
|
272
|
+
|
|
273
|
+
def __copy__(self):
|
|
274
|
+
return ShadowCalculation(
|
|
275
|
+
self.solar_distribution, self.calculation_method,
|
|
276
|
+
self.calculation_update_method, self.calculation_frequency,
|
|
277
|
+
self.maximum_figures)
|
|
278
|
+
|
|
279
|
+
def __key(self):
|
|
280
|
+
"""A tuple based on the object properties, useful for hashing."""
|
|
281
|
+
return (self.solar_distribution, self.calculation_method,
|
|
282
|
+
self.calculation_update_method, self.calculation_frequency,
|
|
283
|
+
self.maximum_figures)
|
|
284
|
+
|
|
285
|
+
def __hash__(self):
|
|
286
|
+
return hash(self.__key())
|
|
287
|
+
|
|
288
|
+
def __eq__(self, other):
|
|
289
|
+
return isinstance(other, ShadowCalculation) and self.__key() == other.__key()
|
|
290
|
+
|
|
291
|
+
def __ne__(self, other):
|
|
292
|
+
return not self.__eq__(other)
|
|
293
|
+
|
|
294
|
+
def __repr__(self):
|
|
295
|
+
return self.to_idf()
|