Coverage for teaser/logic/archetypebuildings/tabula/dk/singlefamilyhouse.py: 84%
181 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# created April 2017
2# by TEASER Development Team
4from teaser.logic.archetypebuildings.residential import Residential
5from teaser.logic.buildingobjects.useconditions import UseConditions as UseCond
6from teaser.logic.buildingobjects.buildingphysics.ceiling import Ceiling
7from teaser.logic.buildingobjects.buildingphysics.floor import Floor
8from teaser.logic.buildingobjects.buildingphysics.groundfloor import GroundFloor
9from teaser.logic.buildingobjects.buildingphysics.innerwall import InnerWall
10from teaser.logic.buildingobjects.buildingphysics.outerwall import OuterWall
11from teaser.logic.buildingobjects.buildingphysics.rooftop import Rooftop
12from teaser.logic.buildingobjects.buildingphysics.window import Window
13from teaser.logic.buildingobjects.buildingphysics.door import Door
14from teaser.logic.buildingobjects.thermalzone import ThermalZone
15import teaser.data.utilities as datahandling
18class SingleFamilyHouse(Residential):
19 """Archetype for Danish TABULA Single Family House.
21 This is an archetype building for danish single family house according to
22 TABULA building typology (http://webtool.building-typology.eu/#bm). As
23 TABULA defines one reference building, whereas TEASER wants to provide a
24 methodology to generate individual building information, this archetype
25 underlies some assumptions. The made assumptions are explained in the
26 following:
28 Each building has four orientations for outer walls and windows (north,
29 east, south and west), two orientations for rooftops (south and north), with
30 tilt of 35 degree and one orientation for ground floors and one door (
31 default
32 orientation is west). The area of each surface is calculated using the
33 product of the given net_leased_area and specific estimation factors. These
34 estimation factors where build by dividing the given 'surface area' by the
35 'reference floor area' in TABULA. The estimation factors are calculated for
36 each building period ('construction year class'). Please note that the
37 number and height of the floors given in TEASER does not have any effect on
38 the surface area for heat transmission, but is only used to calculate the
39 interior wall area, which is not specified in TABULA at all. Further, TABULA
40 does not specify any specific user profile, by default the SingleFamilyHouse
41 class has exactly one usage zone, which is 'Living'. TABULA also does not
42 always specify the exact construction of building elements, but always
43 provides a prescribed U-Value. We used the U-Value and the given material
44 information to determine thickness of each layer and implemented it into
45 elements json ('teaser.data.input.inputdata.TypeElements_TABULA_DK.json'). The
46 material properties have been assumed from the "Handbook for Energy
47 Consultants - HB2016" (http://www.hbemo.dk/). As there might be some
48 differences in the assumptions for material properties from TABULA and
49 HB2016 the U-Value might not always be exactly the same as in TABULA but is
50 always in an acceptable range. The U-Value has been calculated using
51 combined constant values for interior and exterior heat transmission, we
52 used a resistance of 0.17 (m2*K)/W for outer walls, windows, flat roofs and
53 doors; 0.34 (m2*K)/W for ground floors to unheated cellars and 0.17 (m2*K)/W
54 to direct ground coupled floors, 0.21 (m2*K)/W was taken for pitched roofs.
56 Parameters
57 ----------
59 parent: Project()
60 The parent class of this object, the Project the Building belongs to.
61 Allows for better control of hierarchical structures. If not None it
62 adds this Building instance to Project.buildings.
63 (default: None)
64 name : str
65 Individual name
66 year_of_construction : int
67 Year of first construction
68 height_of_floors : float [m]
69 Average height of the buildings' floors
70 number_of_floors : int
71 Number of building's floors above ground
72 net_leased_area : float [m2]
73 Total net leased area of building. This is area is NOT the footprint
74 of a building
75 with_ahu : Boolean
76 If set to True, an empty instance of BuildingAHU is instantiated and
77 assigned to attribute central_ahu. This instance holds information for
78 central Air Handling units. Default is False.
79 internal_gains_mode: int [1, 2, 3]
80 mode for the internal gains calculation done in AixLib:
82 1. Temperature and activity degree dependent heat flux calculation for persons. The
83 calculation is based on SIA 2024 (default)
84 2. Temperature and activity degree independent heat flux calculation for persons, the max.
85 heatflowrate is prescribed by the parameter
86 fixed_heat_flow_rate_persons.
87 3. Temperature and activity degree dependent calculation with
88 consideration of moisture and co2. The moisture calculation is
89 based on SIA 2024 (2015) and regards persons and non-persons, the co2 calculation is based on
90 Engineering ToolBox (2004) and regards only persons.
91 inner_wall_approximation_approach : str
92 'teaser_default' (default) sets length of inner walls = typical
93 length * height of floors + 2 * typical width * height of floors
94 'typical_minus_outer' sets length of inner walls = 2 * typical
95 length * height of floors + 2 * typical width * height of floors
96 - length of outer or interzonal walls
97 'typical_minus_outer_extended' like 'typical_minus_outer', but also
98 considers that
99 a) a non-complete "average room" reduces its circumference
100 proportional to the square root of the area
101 b) rooftops, windows and ground floors (= walls with border to
102 soil) may have a vertical share
103 construction_data : str
104 Construction type of used wall constructions default is "existing
105 state"
107 - existing state:
108 construction of walls according to existing state in TABULA
109 - usual refurbishment:
110 construction of walls according to usual refurbishment in
111 TABULA
112 - advanced refurbishment:
113 construction of walls according to advanced refurbishment in
114 TABULA
116 """
118 def __init__(
119 self,
120 parent,
121 name=None,
122 year_of_construction=None,
123 number_of_floors=None,
124 height_of_floors=None,
125 net_leased_area=None,
126 with_ahu=False,
127 internal_gains_mode=1,
128 inner_wall_approximation_approach='teaser_default',
129 construction_data=None,
130 ):
132 super(SingleFamilyHouse, self).__init__(
133 parent,
134 name,
135 year_of_construction,
136 net_leased_area,
137 with_ahu,
138 internal_gains_mode,
139 inner_wall_approximation_approach
140 )
142 self.construction_data = construction_data
143 self.number_of_floors = number_of_floors
144 self.height_of_floors = height_of_floors
146 self._construction_data_1 = self.construction_data.value + "_1_SFH"
147 self._construction_data_2 = self.construction_data.value + "_2_SFH"
149 self.zone_area_factors = {"SingleDwelling": [1, "Living"]}
151 self._outer_wall_names_1 = {
152 "ExteriorFacadeNorth_1": [90.0, 0.0],
153 "ExteriorFacadeEast_1": [90.0, 90.0],
154 "ExteriorFacadeSouth_1": [90.0, 180.0],
155 "ExteriorFacadeWest_1": [90.0, 270.0],
156 }
158 self._outer_wall_names_2 = {
159 "ExteriorFacadeNorth_2": [90.0, 0.0],
160 "ExteriorFacadeEast_2": [90.0, 90.0],
161 "ExteriorFacadeSouth_2": [90.0, 180.0],
162 "ExteriorFacadeWest_2": [90.0, 270.0],
163 }
165 self.roof_names_1 = {
166 "RooftopNorth_1": [35.0, 0.0],
167 "RooftopSouth_1": [35.0, 90.0],
168 }
170 self.roof_names_2 = {
171 "RooftopNorth_2": [35.0, 0.0],
172 "RooftopSouth_2": [35.0, 90.0],
173 }
175 self.ground_floor_names_1 = {"GroundFloor_1": [0, -2]}
177 self.ground_floor_names_2 = {"GroundFloor_2": [0, -2]}
179 self.door_names = {"Door": [90.0, 270]}
181 self.window_names_1 = {
182 "WindowFacadeNorth_1": [90.0, 0.0],
183 "WindowFacadeEast_1": [90.0, 90.0],
184 "WindowFacadeSouth_1": [90.0, 180.0],
185 "WindowFacadeWest_1": [90.0, 270.0],
186 }
187 self.window_names_2 = {
188 "WindowFacadeNorth_2": [90.0, 0.0],
189 "WindowFacadeEast_2": [90.0, 90.0],
190 "WindowFacadeSouth_2": [90.0, 180.0],
191 "WindowFacadeWest_2": [90.0, 270.0],
192 }
194 # [tilt, orientation]
196 self.inner_wall_names = {"InnerWall": [90.0, 0.0]}
198 self.ceiling_names = {"Ceiling": [0.0, -1]}
200 self.floor_names = {"Floor": [0.0, -2]}
202 # Rooftop1, Rooftop2, Wall1, Wall2, GroundFloor1, GroundFloor2,
203 # Window1, Window2, Door
204 # Area/ReferenceFloorArea
205 self.facade_estimation_factors = {
206 (2007, 2010): {
207 "rt1": 1.179,
208 "rt2": 0.0,
209 "ow1": 1.0345,
210 "ow2": 0.0,
211 "gf1": 1.0276,
212 "gf2": 0.0,
213 "win1": 0.17,
214 "win2": 0.0,
215 "door": 0.009,
216 },
217 (1999, 2006): {
218 "rt1": 0.8054,
219 "rt2": 0.0,
220 "ow1": 0.7852,
221 "ow2": 0.0,
222 "gf1": 0.6040,
223 "gf2": 0.0,
224 "win1": 0.1839,
225 "win2": 0.0,
226 "door": 0.009,
227 },
228 (1979, 1998): {
229 "rt1": 1.1721,
230 "rt2": 0.0,
231 "ow1": 1.0164,
232 "ow2": 0.0,
233 "gf1": 1.0000,
234 "gf2": 0.0,
235 "win1": 0.2025,
236 "win2": 0.0,
237 "door": 0.009,
238 },
239 (1973, 1978): {
240 "rt1": 1.1197,
241 "rt2": 0.0,
242 "ow1": 0.6154,
243 "ow2": 0.2137,
244 "gf1": 1.0085,
245 "gf2": 0.0,
246 "win1": 0.1906,
247 "win2": 0.0,
248 "door": 0.009,
249 },
250 (1961, 1972): {
251 "rt1": 1.1765,
252 "rt2": 0.0,
253 "ow1": 0.7908,
254 "ow2": 0.0,
255 "gf1": 1.0458,
256 "gf2": 0.0,
257 "win1": 0.2203,
258 "win2": 0.0,
259 "door": 0.009,
260 },
261 (1951, 1960): {
262 "rt1": 1.1778,
263 "rt2": 0.0,
264 "ow1": 1.1222,
265 "ow2": 0.0,
266 "gf1": 1.1778,
267 "gf2": 0.0,
268 "win1": 0.3133,
269 "win2": 0.0,
270 "door": 0.009,
271 },
272 (1931, 1950): {
273 "rt1": 0.7479,
274 "rt2": 0.0,
275 "ow1": 0.6891,
276 "ow2": 0.2269,
277 "gf1": 0.7395,
278 "gf2": 0.0,
279 "win1": 0.1824,
280 "win2": 0.0,
281 "door": 0.009,
282 },
283 (1851, 1930): {
284 "rt1": 0.9895,
285 "rt2": 0.0,
286 "ow1": 1.0316,
287 "ow2": 0.0,
288 "gf1": 0.6947,
289 "gf2": 0.0,
290 "win1": 0.1589,
291 "win2": 0.0,
292 "door": 0.009,
293 },
294 (0, 1850): {
295 "rt1": 1.1742,
296 "rt2": 0.0,
297 "ow1": 1.1061,
298 "ow2": 0.0,
299 "gf1": 0.9621,
300 "gf2": 0.0,
301 "win1": 0.2045,
302 "win2": 0.0,
303 "door": 0.009,
304 },
305 }
307 self.building_age_group = None
309 if self.with_ahu is True:
310 self.central_ahu.profile_temperature = (
311 7 * [293.15] + 12 * [295.15] + 5 * [293.15]
312 )
313 self.central_ahu.profile_min_relative_humidity = 24 * [0.45]
314 self.central_ahu.profile_max_relative_humidity = 24 * [0.55]
315 self.central_ahu.profile_v_flow = 7 * [0.0] + 12 * [1.0] + 5 * [0.0]
317 def _check_year_of_construction(self):
318 """Assigns the bldg age group according to year of construction"""
320 for key in self.facade_estimation_factors:
321 if (
322 self.year_of_construction in range(key[0], key[1])
323 or self.year_of_construction == key[1]
324 ):
325 self.building_age_group = (key[0], key[1])
327 if self.building_age_group is None:
328 raise RuntimeError(
329 "Year of construction not supported for this archetype" "building"
330 )
332 def generate_archetype(self):
333 """Generates a SingleFamilyHouse archetype buildings
335 With given values, this function generates an archetype building for
336 Tabula Single Family House.
337 """
338 self.thermal_zones = None
339 self._check_year_of_construction()
340 # help area for the correct building area setting while using typeBldgs
341 type_bldg_area = self.net_leased_area
342 self.net_leased_area = 0.0
344 for key, value in self.zone_area_factors.items():
345 zone = ThermalZone(parent=self)
346 zone.name = key
347 zone.area = type_bldg_area * value[0]
348 try:
349 zone.number_of_floors = value[2]['number_of_floors']
350 except (KeyError, IndexError):
351 pass
352 try:
353 zone.height_of_floors = value[2]['height_of_floors']
354 except (KeyError, IndexError):
355 pass
356 use_cond = UseCond(parent=zone)
357 use_cond.load_use_conditions(zone_usage=value[1])
358 zone.use_conditions = use_cond
360 zone.use_conditions.with_ahu = False
361 zone.use_conditions.persons *= zone.area * 0.01
362 zone.use_conditions.machines *= zone.area * 0.01
364 if self.facade_estimation_factors[self.building_age_group]["ow1"] != 0:
365 for key, value in self._outer_wall_names_1.items():
366 for zone in self.thermal_zones:
367 outer_wall = OuterWall(zone)
368 outer_wall.load_type_element(
369 year=self.year_of_construction,
370 construction=self._construction_data_1,
371 data_class=self.parent.data,
372 )
373 outer_wall.name = key
374 outer_wall.tilt = value[0]
375 outer_wall.orientation = value[1]
376 outer_wall.area = (
377 self.facade_estimation_factors[self.building_age_group]["ow1"]
378 * zone.area
379 ) / len(self._outer_wall_names_1)
381 if self.facade_estimation_factors[self.building_age_group]["ow2"] != 0:
382 for key, value in self._outer_wall_names_2.items():
383 for zone in self.thermal_zones:
384 outer_wall = OuterWall(zone)
385 outer_wall.load_type_element(
386 year=self.year_of_construction,
387 construction=self._construction_data_2,
388 data_class=self.parent.data,
389 )
390 outer_wall.name = key
391 outer_wall.tilt = value[0]
392 outer_wall.orientation = value[1]
393 outer_wall.area = (
394 self.facade_estimation_factors[self.building_age_group]["ow2"]
395 * zone.area
396 ) / len(self._outer_wall_names_2)
398 if self.facade_estimation_factors[self.building_age_group]["win1"] != 0:
399 for key, value in self.window_names_1.items():
400 for zone in self.thermal_zones:
401 window = Window(zone)
402 window.load_type_element(
403 self.year_of_construction,
404 construction=self._construction_data_1,
405 data_class=self.parent.data,
406 )
407 window.name = key
408 window.tilt = value[0]
409 window.orientation = value[1]
410 window.area = (
411 self.facade_estimation_factors[self.building_age_group]["win1"]
412 * zone.area
413 ) / len(self.window_names_1)
415 if self.facade_estimation_factors[self.building_age_group]["win2"] != 0:
416 for key, value in self.window_names_2.items():
417 for zone in self.thermal_zones:
418 window = Window(zone)
419 window.load_type_element(
420 self.year_of_construction,
421 construction=self._construction_data_2,
422 data_class=self.parent.data,
423 )
424 window.name = key
425 window.tilt = value[0]
426 window.orientation = value[1]
427 window.area = (
428 self.facade_estimation_factors[self.building_age_group]["win2"]
429 * zone.area
430 ) / len(self.window_names_2)
432 if self.facade_estimation_factors[self.building_age_group]["gf1"] != 0:
433 for key, value in self.ground_floor_names_1.items():
435 for zone in self.thermal_zones:
436 gf = GroundFloor(zone)
437 gf.load_type_element(
438 year=self.year_of_construction,
439 construction=self._construction_data_1,
440 data_class=self.parent.data,
441 )
442 gf.name = key
443 gf.tilt = value[0]
444 gf.orientation = value[1]
445 gf.area = (
446 self.facade_estimation_factors[self.building_age_group]["gf1"]
447 * zone.area
448 ) / len(self.ground_floor_names_1)
450 if self.facade_estimation_factors[self.building_age_group]["gf2"] != 0:
451 for key, value in self.ground_floor_names_2.items():
453 for zone in self.thermal_zones:
454 gf = GroundFloor(zone)
455 gf.load_type_element(
456 year=self.year_of_construction,
457 construction=self._construction_data_2,
458 data_class=self.parent.data,
459 )
460 gf.name = key
461 gf.tilt = value[0]
462 gf.orientation = value[1]
463 gf.area = (
464 self.facade_estimation_factors[self.building_age_group]["gf2"]
465 * zone.area
466 ) / len(self.ground_floor_names_2)
468 if self.facade_estimation_factors[self.building_age_group]["rt1"] != 0:
469 for key, value in self.roof_names_1.items():
471 for zone in self.thermal_zones:
472 rt = Rooftop(zone)
473 rt.load_type_element(
474 year=self.year_of_construction,
475 construction=self._construction_data_1,
476 data_class=self.parent.data,
477 )
478 rt.name = key
479 rt.tilt = value[0]
480 rt.orientation = value[1]
481 rt.area = (
482 self.facade_estimation_factors[self.building_age_group]["rt1"]
483 * zone.area
484 ) / len(self.roof_names_1)
486 if self.facade_estimation_factors[self.building_age_group]["rt2"] != 0:
487 for key, value in self.roof_names_2.items():
489 for zone in self.thermal_zones:
490 rt = Rooftop(zone)
491 rt.load_type_element(
492 year=self.year_of_construction,
493 construction=self._construction_data_2,
494 data_class=self.parent.data,
495 )
496 rt.name = key
497 rt.tilt = value[0]
498 rt.orientation = value[1]
499 rt.area = (
500 self.facade_estimation_factors[self.building_age_group]["rt2"]
501 * zone.area
502 ) / len(self.roof_names_2)
504 if self.facade_estimation_factors[self.building_age_group]["door"] != 0:
505 for key, value in self.door_names.items():
507 for zone in self.thermal_zones:
508 door = Door(zone)
509 door.load_type_element(
510 year=self.year_of_construction,
511 construction=self._construction_data_1,
512 data_class=self.parent.data,
513 )
514 door.name = key
515 door.tilt = value[0]
516 door.orientation = value[1]
517 door.area = (
518 self.facade_estimation_factors[self.building_age_group]["door"]
519 * zone.area
520 ) / len(self.door_names)
522 for key, value in self.inner_wall_names.items():
524 for zone in self.thermal_zones:
525 inner_wall = InnerWall(zone)
526 inner_wall.load_type_element(
527 year=self.year_of_construction,
528 construction="tabula_dk_standard",
529 data_class=self.parent.data,
530 )
531 inner_wall.name = key
532 inner_wall.tilt = value[0]
533 inner_wall.orientation = value[1]
535 if self.number_of_floors > 1:
537 for key, value in self.ceiling_names.items():
539 for zone in self.thermal_zones:
540 ceiling = Ceiling(zone)
541 ceiling.load_type_element(
542 year=self.year_of_construction,
543 construction="tabula_dk_standard",
544 data_class=self.parent.data,
545 )
546 ceiling.name = key
547 ceiling.tilt = value[0]
548 ceiling.orientation = value[1]
550 for key, value in self.floor_names.items():
552 for zone in self.thermal_zones:
553 floor = Floor(zone)
554 floor.load_type_element(
555 year=self.year_of_construction,
556 construction="tabula_dk_standard",
557 data_class=self.parent.data,
558 )
559 floor.name = key
560 floor.tilt = value[0]
561 floor.orientation = value[1]
563 for zone in self.thermal_zones:
564 zone.set_inner_wall_area()
565 zone.set_volume_zone()
567 @property
568 def construction_data(self):
569 return self._construction_data
571 @construction_data.setter
572 def construction_data(self, value):
573 self._construction_data = datahandling.check_construction_data_setter_tabula_dk(value)