Coverage for teaser/logic/buildingobjects/calculation/aixlib.py: 96%
101 statements
« prev ^ index » next coverage.py v7.4.4, created at 2025-04-29 16:01 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2025-04-29 16:01 +0000
1"""This module includes AixLib calculation class."""
3import teaser.logic.utilities as utilities
4from itertools import cycle, islice
5import os
6import pandas as pd
9class AixLib(object):
10 """Class to calculate parameters for AixLib output.
12 This class holds functions to sort and partly rewrite zone and building
13 attributes specific for AixLib MultizoneEquipped
14 simulation. This includes the export of boundary conditions and AHU
15 operation values.
17 Parameters
18 ----------
19 parent: Building()
20 The parent class of this object, the Building the attributes are
21 calculated for. (default: None)
24 Attributes
25 ----------
26 file_set_t : str
27 Filename for set temperature file
28 file_ahu : str
29 Filename for AHU boundary conditions file
30 file_internal_gains : str
31 Filename for internal gains file
32 version : str
33 Used AixLib version, default should always be current main version
34 of GitHub
35 besmod_version : str
36 Used BESMod version vor export_besmod, default should always be current main version
37 of GitHub
38 total_surface_area : float [m2]
39 This is the total surface area of the building for interior and
40 exterior surfaces. That includes: OuterWalls, Rooftops, GroundFloors,
41 Windows for exterior surfaces, and InnerWalls, Ceilings, Floors for
42 interior walls.
43 consider_heat_capacity : bool
44 decides whether air capacity is considered or not for all thermal
45 zones in the building. Default is True, you need to export your
46 model again if changing this value
47 use_set_back : bool
48 True if night set back should be used. In this case the function
49 considers heating_time and temp_set_back defined in
50 use_conditions of zone. Default is True, you need to export your
51 model again if changing this value
52 use_set_point_temperature_profile_heating : bool
53 Standard is False. True if the set_point temperature profile heating
54 should be used for the export. Then, the night set back and everything
55 except the set point profile will be ignored.
57 """
59 def __init__(self, parent):
60 """Construct AixLib."""
61 self.parent = parent
63 self.file_set_t_heat = "TsetHeat_" + self.parent.name + ".txt"
64 self.file_set_t_cool = "TsetCool_" + self.parent.name + ".txt"
65 self.file_ahu = "AHU_" + self.parent.name + ".txt"
66 self.file_internal_gains = "InternalGains_" + self.parent.name + ".txt"
67 self.version = "2.1.1"
68 self.besmod_version = "0.6.0"
69 self.total_surface_area = None
70 self.consider_heat_capacity = True
71 self.use_set_back = True
72 self.use_set_point_temperature_profile_heating = False
73 self.use_set_back_cool = False
75 def calc_auxiliary_attr(self):
76 """Call function to calculate all auxiliary attributes for AixLib."""
77 self._calc_surface_area()
79 def _calc_surface_area(self):
80 """Calculate the total surface area of all surfaces."""
81 surf_area_temp = 0.0
82 for zone in self.parent.thermal_zones:
83 if type(zone.model_attr).__name__ == "OneElement":
84 surf_area_temp += zone.model_attr.area_ow + zone.model_attr.area_win
85 elif type(zone.model_attr).__name__ == "TwoElement":
86 surf_area_temp += (
87 zone.model_attr.area_ow
88 + zone.model_attr.area_iw
89 + zone.model_attr.area_win
90 )
91 elif type(zone.model_attr).__name__ == "ThreeElement":
92 surf_area_temp += (
93 zone.model_attr.area_ow
94 + zone.model_attr.area_iw
95 + zone.model_attr.area_gf
96 + zone.model_attr.area_win
97 )
98 elif type(zone.model_attr).__name__ == "FourElement":
99 surf_area_temp += (
100 zone.model_attr.area_ow
101 + zone.model_attr.area_iw
102 + zone.model_attr.area_gf
103 + zone.model_attr.area_rt
104 + zone.model_attr.area_win
105 )
106 elif type(zone.model_attr).__name__ == "FiveElement":
107 surf_area_temp += (
108 zone.model_attr.area_ow
109 + zone.model_attr.area_iw
110 + zone.model_attr.area_gf
111 + zone.model_attr.area_rt
112 + zone.model_attr.area_win
113 + sum(zone.model_attr.area_nzb)
114 )
116 self.total_surface_area = surf_area_temp
118 def modelica_set_temp(self, path=None):
119 """Create .txt file for set temperatures for heating.
121 This function creates a txt for set temperatures of each
122 zone, that are all saved into one matrix.
124 Parameters
125 ----------
126 path : str
127 optional path, when matfile is exported separately
129 """
130 if path is None:
131 path = utilities.get_default_path()
132 else:
133 pass
135 utilities.create_path(path)
136 path = os.path.join(path, self.file_set_t_heat)
138 export = pd.DataFrame(
139 index=pd.date_range("2019-01-01 00:00:00", periods=8760, freq="h")
140 .to_series()
141 .dt.strftime("%m-%d %H:%M:%S"),
142 columns=[zone.name for zone in self.parent.thermal_zones],
143 )
145 for zone_count in self.parent.thermal_zones:
146 export[zone_count.name] = zone_count.use_conditions.schedules[
147 "heating_profile"
148 ]
150 export.index = [(i + 1) * 3600 for i in range(8760)]
151 self._delete_file(path=path)
152 with open(path, "a") as f:
153 f.write("#1\n")
154 f.write(
155 "double Tset({}, {})\n".format(8760, len(self.parent.thermal_zones) + 1)
156 )
157 export.to_csv(f, sep="\t", header=False, index_label=False)
159 def modelica_set_temp_cool(self, path=None):
160 """Create .txt file for set temperatures cooling.
162 This function creates a txt for set temperatures for cooling
163 of each zone, that are all saved into one matrix.
166 Parameters
167 ----------
168 path : str
169 optional path, when matfile is exported separately
171 """
172 if path is None:
173 path = utilities.get_default_path()
174 else:
175 pass
177 utilities.create_path(path)
178 path = os.path.join(path, self.file_set_t_cool)
180 export = pd.DataFrame(
181 index=pd.date_range("2019-01-01 00:00:00", periods=8760, freq="h")
182 .to_series()
183 .dt.strftime("%m-%d %H:%M:%S"),
184 columns=[zone.name for zone in self.parent.thermal_zones],
185 )
187 for zone_count in self.parent.thermal_zones:
188 export[zone_count.name] = zone_count.use_conditions.schedules[
189 "cooling_profile"
190 ]
192 export.index = [(i + 1) * 3600 for i in range(8760)]
193 self._delete_file(path=path)
194 with open(path, "a") as f:
195 f.write("#1\n")
196 f.write(
197 "double Tset({}, {})\n".format(8760, len(self.parent.thermal_zones) + 1)
198 )
199 export.to_csv(f, sep="\t", header=False, index_label=False)
201 def modelica_AHU_boundary(self, path=None):
202 """Create .txt file for AHU boundary conditions (building).
204 This function creates a txt for building AHU boundary
205 conditions
207 1. Column : time step
208 2. Column : desired AHU profile temperature
209 3. Column : Desired minimal relative humidity
210 4. Column : desired maximal relative humidity
211 5. Column : AHU status (On/Off)
213 Parameters
214 ----------
215 path : str
216 optional path, when matfile is exported separately
218 Attributes
219 ----------
220 temperature_profile : [float]
221 timeline of temperatures requirements for AHU simulation
222 min_relative_humidity_profile : [float]
223 timeline of relative humidity requirements for AHU simulation
224 max_relative_humidity_profile : [float]
225 timeline of relative humidity requirements for AHU simulation
226 v_flow_profile : [int]
227 timeline of desired relative v_flow of the AHU simulation (0..1)
229 """
230 if path is None:
231 path = utilities.get_default_path()
232 else:
233 pass
235 utilities.create_path(path)
236 path = os.path.join(path, self.file_ahu)
238 if self.parent.with_ahu is True:
239 export = self.parent.central_ahu.schedules
240 else: # Dummy values for Input Table
241 export = pd.DataFrame(
242 index=pd.date_range("2019-01-01 00:00:00", periods=8760, freq="h")
243 .to_series()
244 .dt.strftime("%m-%d %H:%M:%S")
245 )
247 export["temperature_profile"] = list(islice(cycle([293.15, 293.15]), 8760))
248 export["min_relative_humidity_profile"] = list(islice(cycle([0, 0]), 8760))
249 export["max_relative_humidity_profile"] = list(islice(cycle([1, 1]), 8760))
250 export["v_flow_profile"] = list(islice(cycle([0, 1]), 8760))
252 export.index = [(i + 1) * 3600 for i in range(8760)]
253 self._delete_file(path=path)
254 with open(path, "a") as f:
255 f.write("#1\n")
256 f.write("double AHU({}, {})\n".format(8760, 5))
257 export.to_csv(f, sep="\t", header=False, index_label=False)
259 def modelica_gains_boundary(self, path=None):
260 """Create .txt file for internal gains boundary conditions.
262 This function creates a matfile (-v4) for building internal gains
263 boundary conditions. It collects all internal gain profiles of the
264 zones and stores them into one file. The file is extended for each
265 zone. Only applicable if zones are defined
267 1. Column : time step
268 2,5,8,... Column : profile_persons
269 3,6,9,... Column : profile_machines
270 4,7,10,... Column : profile_lighting
272 Notes
273 -----
274 When time line is created, we need to add a 0 to first element of
275 all boundaries. This is due to to expected format in Modelica.
277 Parameters
278 ----------
279 path : str
280 optional path, when matfile is exported separately
282 """
283 if path is None:
284 path = utilities.get_default_path()
285 else:
286 pass
288 utilities.create_path(path)
289 path = os.path.join(path, self.file_internal_gains)
291 export = pd.DataFrame(
292 index=pd.date_range("2019-01-01 00:00:00", periods=8760, freq="h")
293 .to_series()
294 .dt.strftime("%m-%d %H:%M:%S")
295 )
297 for zone_count in self.parent.thermal_zones:
298 export[
299 "person_{}".format(zone_count.name)
300 ] = zone_count.use_conditions.schedules["persons_profile"]
301 export[
302 "machines_{}".format(zone_count.name)
303 ] = zone_count.use_conditions.schedules["machines_profile"]
304 export[
305 "lighting_{}".format(zone_count.name)
306 ] = zone_count.use_conditions.schedules["lighting_profile"]
308 export.index = [(i + 1) * 3600 for i in range(8760)]
309 self._delete_file(path=path)
310 with open(path, "a") as f:
311 f.write("#1\n")
312 f.write(
313 "double Internals({}, {})\n".format(
314 8760, (len(self.parent.thermal_zones) * 3 + 1)
315 )
316 )
317 export.to_csv(f, sep="\t", header=False, index_label=False)
319 def _delete_file(self, path):
320 """Delete a file before new information is written to it.
322 If a building with the exact name and project name is generated, we need to make
323 sure to delete the old information in the text files. This helper function is a
324 wrapper to delete a file with given filepath.
326 Parameters:
327 -----------
328 path : str
329 Absolute path to the file to be deleted.
331 """
332 try:
333 os.remove(path)
334 except OSError:
335 pass