Coverage for teaser/logic/archetypebuildings/tabula/de/singlefamilyhouse.py: 97%
191 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
3import teaser.data.utilities as datahandling
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
17class SingleFamilyHouse(Residential):
18 """Archetype for German TABULA Single Family House.
20 This is an archetype building for german single family house according to
21 TABULA building typology (http://webtool.building-typology.eu/#bm). As
22 TABULA defines one reference building, whereas TEASER wants to provide a
23 methodology to generate individual building information, this archetype
24 underlies some assumptions. The made assumptions are explained in the
25 following:
27 Each building has four orientations for outer walls and windows (north,
28 east, south and west), two orientations for rooftops (south and north), with
29 tilt of 35 degree and one orientation for ground floors and one door (
30 default
31 orientation is west). The area of each surface is calculated using the
32 product of the given net_leased_area and specific estimation factors. These
33 estimation factors where build by dividing the given 'surface area' by the
34 'reference floor area' in TABULA. The estimation factors are calculated for
35 each building period ('construction year class'). Please note that the
36 number and height of the floors given in TEASER does not have any effect on
37 the surface area for heat transmission, but is only used to calculate the
38 interior wall area, which is not specified in TABULA at all. Further, TABULA
39 does not specify any specific user profile, by default the SingleFamilyHouse
40 class has exactly one usage zone, which is 'Living'. TABULA also does not
41 always specify the exact construction of building elements, but always
42 provides a prescribed U-Value. We used the U-Value and the given material
43 information to determine thickness of each layer and implemented it into
44 elements json ('teaser.data.input.inputdata.TypeElements_TABULA_DE.json'). The
45 material properties have been taken from MASEA Material data base
46 (http://www.masea-ensan.de/). As there might be some differences in the
47 assumptions for material properties from TABULA and MASEA the U-Value might
48 not always be exactly the same as in TABULA but is always in an acceptable
49 range. The U-Value has been calculated using combined constant values for
50 interior and exterior heat transmission, we used a resistance of 0.17
51 (m2*K)/W for outer walls, windows, flat roofs and doors; 0.34 (m2*K)/W for
52 ground floors to unheated cellars and 0.17 (m2*K)/W to direct ground
53 coupled floors, 0.21 (m2*K)/W was taken for pitched roofs.
55 Parameters
56 ----------
58 parent: Project()
59 The parent class of this object, the Project the Building belongs to.
60 Allows for better control of hierarchical structures. If not None it
61 adds this Building instance to Project.buildings.
62 (default: None)
63 name : str
64 Individual name
65 year_of_construction : int
66 Year of first construction
67 height_of_floors : float [m]
68 Average height of the buildings' floors
69 number_of_floors : int
70 Number of building's floors above ground
71 net_leased_area : float [m2]
72 Total net leased area of building. This is area is NOT the footprint
73 of a building
74 with_ahu : Boolean
75 If set to True, an empty instance of BuildingAHU is instantiated and
76 assigned to attribute central_ahu. This instance holds information for
77 central Air Handling units. Default is False.
78 internal_gains_mode: int [1, 2, 3]
79 mode for the internal gains calculation done in AixLib:
81 1. Temperature and activity degree dependent heat flux calculation for persons. The
82 calculation is based on SIA 2024 (default)
83 2. Temperature and activity degree independent heat flux calculation for persons, the max.
84 heatflowrate is prescribed by the parameter
85 fixed_heat_flow_rate_persons.
86 3. Temperature and activity degree dependent calculation with
87 consideration of moisture and co2. The moisture calculation is
88 based on SIA 2024 (2015) and regards persons and non-persons, the co2 calculation is based on
89 Engineering ToolBox (2004) and regards only persons.
90 inner_wall_approximation_approach : str
91 'teaser_default' (default) sets length of inner walls = typical
92 length * height of floors + 2 * typical width * height of floors
93 'typical_minus_outer' sets length of inner walls = 2 * typical
94 length * height of floors + 2 * typical width * height of floors
95 - length of outer or interzonal walls
96 'typical_minus_outer_extended' like 'typical_minus_outer', but also
97 considers that
98 a) a non-complete "average room" reduces its circumference
99 proportional to the square root of the area
100 b) rooftops, windows and ground floors (= walls with border to
101 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 TABULA
111 - advanced refurbishment:
112 construction of walls according to advanced refurbishment in
113 TABULA
115"""
117 def __init__(
118 self,
119 parent,
120 name=None,
121 year_of_construction=None,
122 number_of_floors=None,
123 height_of_floors=None,
124 net_leased_area=None,
125 with_ahu=False,
126 internal_gains_mode=1,
127 inner_wall_approximation_approach='teaser_default',
128 construction_data=None,
129 ):
131 super(SingleFamilyHouse, self).__init__(
132 parent,
133 name,
134 year_of_construction,
135 net_leased_area,
136 with_ahu,
137 internal_gains_mode,
138 inner_wall_approximation_approach
139 )
141 self.construction_data = construction_data
142 self.number_of_floors = number_of_floors
143 self.height_of_floors = height_of_floors
145 if self.construction_data.is_kfw():
146 self._construction_data_1 = self.construction_data.value
147 self._construction_data_2 = self.construction_data.value
148 else:
149 self._construction_data_1 = self.construction_data.value + "_1_SFH"
150 self._construction_data_2 = self.construction_data.value + "_2_SFH"
152 self.zone_area_factors = {"SingleDwelling": [1, "Living"]}
154 self._outer_wall_names_1 = {
155 "ExteriorFacadeNorth_1": [90.0, 0.0],
156 "ExteriorFacadeEast_1": [90.0, 90.0],
157 "ExteriorFacadeSouth_1": [90.0, 180.0],
158 "ExteriorFacadeWest_1": [90.0, 270.0],
159 }
161 self._outer_wall_names_2 = {
162 "ExteriorFacadeNorth_2": [90.0, 0.0],
163 "ExteriorFacadeEast_2": [90.0, 90.0],
164 "ExteriorFacadeSouth_2": [90.0, 180.0],
165 "ExteriorFacadeWest_2": [90.0, 270.0],
166 }
168 self.roof_names_1 = {
169 "RooftopNorth_1": [35.0, 0.0],
170 "RooftopSouth_1": [35.0, 90.0],
171 }
173 self.roof_names_2 = {
174 "RooftopNorth_2": [35.0, 0.0],
175 "RooftopSouth_2": [35.0, 90.0],
176 }
178 self.ground_floor_names_1 = {"GroundFloor_1": [0, -2]}
180 self.ground_floor_names_2 = {"GroundFloor_2": [0, -2]}
182 self.door_names = {"Door": [90.0, 270]}
184 self.window_names_1 = {
185 "WindowFacadeNorth_1": [90.0, 0.0],
186 "WindowFacadeEast_1": [90.0, 90.0],
187 "WindowFacadeSouth_1": [90.0, 180.0],
188 "WindowFacadeWest_1": [90.0, 270.0],
189 }
190 self.window_names_2 = {
191 "WindowFacadeNorth_2": [90.0, 0.0],
192 "WindowFacadeEast_2": [90.0, 90.0],
193 "WindowFacadeSouth_2": [90.0, 180.0],
194 "WindowFacadeWest_2": [90.0, 270.0],
195 }
197 # [tilt, orientation]
199 self.inner_wall_names = {"InnerWall": [90.0, 0.0]}
201 self.ceiling_names = {"Ceiling": [0.0, -1]}
203 self.floor_names = {"Floor": [0.0, -2]}
205 # Rooftop1, Rooftop2, Wall1, Wall2, GroundFloor1, GroundFloor2,
206 # Window1, Window2, Door
207 # Area/ReferenceFloorArea
208 self.facade_estimation_factors = {
209 (0, 1859): {
210 "rt1": 0.613,
211 "rt2": 0.0,
212 "ow1": 0.7753,
213 "ow2": 0.0,
214 "gf1": 0.0,
215 "gf2": 0.3904,
216 "win1": 0.1315,
217 "win2": 0.0,
218 "door": 0.009,
219 },
220 (1860, 1918): {
221 "rt1": 0.585,
222 "rt2": 0.0,
223 "ow1": 1.366,
224 "ow2": 0.0,
225 "gf1": 0.3211,
226 "gf2": 0.2303,
227 "win1": 0.157,
228 "win2": 0.0,
229 "door": 0.014,
230 },
231 (1919, 1948): {
232 "rt1": 0.7063,
233 "rt2": 0.0,
234 "ow1": 0.7766,
235 "ow2": 0.0,
236 "gf1": 0.47822,
237 "gf2": 0.0,
238 "win1": 0.173,
239 "win2": 0.0,
240 "door": 0.0066,
241 },
242 (1949, 1957): {
243 "rt1": 1.13,
244 "rt2": 0.0,
245 "ow1": 1.0613,
246 "ow2": 0.0,
247 "gf1": 0.559,
248 "gf2": 0.161,
249 "win1": 0.166,
250 "win2": 0.0,
251 "door": 0.018,
252 },
253 (1958, 1968): {
254 "rt1": 1.396,
255 "rt2": 0.0,
256 "ow1": 1.167,
257 "ow2": 0.072,
258 "gf1": 0.957,
259 "gf2": 0.0,
260 "win1": 0.224,
261 "win2": 0.0,
262 "door": 0.017,
263 },
264 (1969, 1978): {
265 "rt1": 1.05838,
266 "rt2": 0.0,
267 "ow1": 1.0266,
268 "ow2": 0.0,
269 "gf1": 0.4526,
270 "gf2": 0.4277,
271 "win1": 0.1977,
272 "win2": 0.0,
273 "door": 0.01156,
274 },
275 (1979, 1983): {
276 "rt1": 0.46667,
277 "rt2": 0.0,
278 "ow1": 0.738,
279 "ow2": 0.0,
280 "gf1": 0.386,
281 "gf2": 0.0,
282 "win1": 0.125,
283 "win2": 0.0,
284 "door": 0.00926,
285 },
286 (1984, 1994): {
287 "rt1": 0.8213,
288 "rt2": 0.0,
289 "ow1": 1.409,
290 "ow2": 0.0,
291 "gf1": 0.502,
292 "gf2": 0.0,
293 "win1": 0.198,
294 "win2": 0.0,
295 "door": 0.01333,
296 },
297 (1995, 2001): {
298 "rt1": 0.947,
299 "rt2": 0.0,
300 "ow1": 1.038,
301 "ow2": 0.0,
302 "gf1": 0.691,
303 "gf2": 0.0,
304 "win1": 0.266,
305 "win2": 0.0,
306 "door": 0.016,
307 },
308 (2002, 2009): {
309 "rt1": 0.58435,
310 "rt2": 0.0,
311 "ow1": 1.285,
312 "ow2": 0.0,
313 "gf1": 0.543,
314 "gf2": 0.0,
315 "win1": 0.1925,
316 "win2": 0.0,
317 "door": 0.0136,
318 },
319 (2010, 2015): {
320 "rt1": 0.70535,
321 "rt2": 0.0,
322 "ow1": 1.217,
323 "ow2": 0.0,
324 "gf1": 0.57647,
325 "gf2": 0.0,
326 "win1": 0.2246,
327 "win2": 0.0,
328 "door": 0.014,
329 },
330 (2016, 2100): {
331 "rt1": 0.70535,
332 "rt2": 0.0,
333 "ow1": 1.217,
334 "ow2": 0.0,
335 "gf1": 0.57647,
336 "gf2": 0.0,
337 "win1": 0.2246,
338 "win2": 0.0,
339 "door": 0.014,
340 },
341 }
343 self.building_age_group = None
345 if self.with_ahu is True:
346 self.central_ahu.temperature_profile = (
347 7 * [293.15] + 12 * [295.15] + 5 * [293.15]
348 )
349 self.central_ahu.min_relative_humidity_profile = 24 * [0.45]
350 self.central_ahu.max_relative_humidity_profile = 24 * [0.55]
351 self.central_ahu.v_flow_profile = 7 * [0.0] + 12 * [1.0] + 5 * [0.0]
353 self.internal_gains_mode = internal_gains_mode
355 def _check_year_of_construction(self):
356 """Assigns the bldg age group according to year of construction"""
358 for key in self.facade_estimation_factors:
359 if (
360 self.year_of_construction in range(key[0], key[1])
361 or self.year_of_construction == key[1]
362 ):
363 self.building_age_group = (key[0], key[1])
365 if self.building_age_group is None:
366 raise RuntimeError(
367 "Year of construction not supported for this archetype" "building"
368 )
370 def generate_archetype(self):
371 """Generates a SingleFamilyHouse archetype buildings
373 With given values, this function generates an archetype building for
374 Tabula Single Family House.
375 """
376 self.thermal_zones = None
377 self._check_year_of_construction()
378 # help area for the correct building area setting while using typeBldgs
379 type_bldg_area = self.net_leased_area
380 self.net_leased_area = 0.0
382 for key, value in self.zone_area_factors.items():
383 zone = ThermalZone(parent=self)
384 zone.name = key
385 zone.area = type_bldg_area * value[0]
386 try:
387 zone.number_of_floors = value[2]['number_of_floors']
388 except (KeyError, IndexError):
389 pass
390 try:
391 zone.height_of_floors = value[2]['height_of_floors']
392 except (KeyError, IndexError):
393 pass
394 use_cond = UseCond(parent=zone)
395 use_cond.load_use_conditions(zone_usage=value[1])
396 zone.use_conditions = use_cond
398 zone.use_conditions.with_ahu = False
400 if self.facade_estimation_factors[self.building_age_group]["ow1"] != 0:
401 for key, value in self._outer_wall_names_1.items():
402 for zone in self.thermal_zones:
403 outer_wall = OuterWall(zone)
404 outer_wall.load_type_element(
405 year=self.year_of_construction,
406 construction=self._construction_data_1,
407 data_class=self.parent.data,
408 )
409 outer_wall.name = key
410 outer_wall.tilt = value[0]
411 outer_wall.orientation = value[1]
412 outer_wall.area = (
413 self.facade_estimation_factors[self.building_age_group]["ow1"]
414 * zone.area
415 ) / len(self._outer_wall_names_1)
417 if self.facade_estimation_factors[self.building_age_group]["ow2"] != 0:
418 for key, value in self._outer_wall_names_2.items():
419 for zone in self.thermal_zones:
420 outer_wall = OuterWall(zone)
421 outer_wall.load_type_element(
422 year=self.year_of_construction,
423 construction=self._construction_data_2,
424 data_class=self.parent.data,
425 )
426 outer_wall.name = key
427 outer_wall.tilt = value[0]
428 outer_wall.orientation = value[1]
429 outer_wall.area = (
430 self.facade_estimation_factors[self.building_age_group]["ow2"]
431 * zone.area
432 ) / len(self._outer_wall_names_2)
434 if self.facade_estimation_factors[self.building_age_group]["win1"] != 0:
435 for key, value in self.window_names_1.items():
436 for zone in self.thermal_zones:
437 window = Window(zone)
438 construction = (
439 "Waermeschutzverglasung, dreifach"
440 if self.construction_data.is_kfw()
441 else self._construction_data_1
442 )
443 window.load_type_element(
444 self.year_of_construction,
445 construction=construction,
446 data_class=self.parent.data,
447 )
448 window.name = key
449 window.tilt = value[0]
450 window.orientation = value[1]
451 window.area = (
452 self.facade_estimation_factors[self.building_age_group]["win1"]
453 * zone.area
454 ) / len(self.window_names_1)
456 if self.facade_estimation_factors[self.building_age_group]["win2"] != 0:
457 for key, value in self.window_names_2.items():
458 for zone in self.thermal_zones:
459 window = Window(zone)
460 construction = (
461 "Waermeschutzverglasung, dreifach"
462 if self.construction_data.is_kfw()
463 else self._construction_data_2
464 )
465 window.load_type_element(
466 self.year_of_construction,
467 construction=construction,
468 data_class=self.parent.data,
469 )
470 window.name = key
471 window.tilt = value[0]
472 window.orientation = value[1]
473 window.area = (
474 self.facade_estimation_factors[self.building_age_group]["win2"]
475 * zone.area
476 ) / len(self.window_names_2)
478 if self.facade_estimation_factors[self.building_age_group]["gf1"] != 0:
479 for key, value in self.ground_floor_names_1.items():
481 for zone in self.thermal_zones:
482 gf = GroundFloor(zone)
483 gf.load_type_element(
484 year=self.year_of_construction,
485 construction=self._construction_data_1,
486 data_class=self.parent.data,
487 )
488 gf.name = key
489 gf.tilt = value[0]
490 gf.orientation = value[1]
491 gf.area = (
492 self.facade_estimation_factors[self.building_age_group]["gf1"]
493 * zone.area
494 ) / len(self.ground_floor_names_1)
496 if self.facade_estimation_factors[self.building_age_group]["gf2"] != 0:
497 for key, value in self.ground_floor_names_2.items():
499 for zone in self.thermal_zones:
500 gf = GroundFloor(zone)
501 gf.load_type_element(
502 year=self.year_of_construction,
503 construction=self._construction_data_2,
504 data_class=self.parent.data,
505 )
506 gf.name = key
507 gf.tilt = value[0]
508 gf.orientation = value[1]
509 gf.area = (
510 self.facade_estimation_factors[self.building_age_group]["gf2"]
511 * zone.area
512 ) / len(self.ground_floor_names_2)
514 if self.facade_estimation_factors[self.building_age_group]["rt1"] != 0:
515 for key, value in self.roof_names_1.items():
517 for zone in self.thermal_zones:
518 rt = Rooftop(zone)
519 rt.load_type_element(
520 year=self.year_of_construction,
521 construction=self._construction_data_1,
522 data_class=self.parent.data,
523 )
524 rt.name = key
525 rt.tilt = value[0]
526 rt.orientation = value[1]
527 rt.area = (
528 self.facade_estimation_factors[self.building_age_group]["rt1"]
529 * zone.area
530 ) / len(self.roof_names_1)
532 if self.facade_estimation_factors[self.building_age_group]["rt2"] != 0:
533 for key, value in self.roof_names_2.items():
535 for zone in self.thermal_zones:
536 rt = Rooftop(zone)
537 rt.load_type_element(
538 year=self.year_of_construction,
539 construction=self._construction_data_2,
540 data_class=self.parent.data,
541 )
542 rt.name = key
543 rt.tilt = value[0]
544 rt.orientation = value[1]
545 rt.area = (
546 self.facade_estimation_factors[self.building_age_group]["rt2"]
547 * zone.area
548 ) / len(self.roof_names_2)
550 if self.facade_estimation_factors[self.building_age_group]["door"] != 0:
551 for key, value in self.door_names.items():
553 for zone in self.thermal_zones:
554 door = Door(zone)
555 door.load_type_element(
556 year=self.year_of_construction,
557 construction=self._construction_data_1,
558 data_class=self.parent.data,
559 )
560 door.name = key
561 door.tilt = value[0]
562 door.orientation = value[1]
563 door.area = (
564 self.facade_estimation_factors[self.building_age_group]["door"]
565 * zone.area
566 ) / len(self.door_names)
568 for key, value in self.inner_wall_names.items():
570 for zone in self.thermal_zones:
571 inner_wall = InnerWall(zone)
572 if self.construction_data.is_tabula_de():
573 inner_wall.load_type_element(
574 year=self.year_of_construction,
575 construction="tabula_de_standard",
576 data_class=self.parent.data,
577 )
578 else:
579 inner_wall.load_type_element(
580 year=self.year_of_construction,
581 construction=self.construction_data.value,
582 data_class=self.parent.data,
583 )
584 inner_wall.name = key
585 inner_wall.tilt = value[0]
586 inner_wall.orientation = value[1]
588 if self.number_of_floors > 1:
590 for key, value in self.ceiling_names.items():
592 for zone in self.thermal_zones:
593 ceiling = Ceiling(zone)
594 if self.construction_data.is_tabula_de():
595 ceiling.load_type_element(
596 year=self.year_of_construction,
597 construction="tabula_de_standard",
598 data_class=self.parent.data,
599 )
600 else:
601 ceiling.load_type_element(
602 year=self.year_of_construction,
603 construction=self.construction_data.value,
604 data_class=self.parent.data,
605 )
606 ceiling.name = key
607 ceiling.tilt = value[0]
608 ceiling.orientation = value[1]
610 for key, value in self.floor_names.items():
612 for zone in self.thermal_zones:
613 floor = Floor(zone)
614 if self.construction_data.is_tabula_de():
615 floor.load_type_element(
616 year=self.year_of_construction,
617 construction="tabula_de_standard",
618 data_class=self.parent.data,
619 )
620 else:
621 floor.load_type_element(
622 year=self.year_of_construction,
623 construction=self.construction_data.value,
624 data_class=self.parent.data,
625 )
626 floor.name = key
627 floor.tilt = value[0]
628 floor.orientation = value[1]
630 for zone in self.thermal_zones:
631 zone.set_inner_wall_area()
632 zone.set_volume_zone()
634 @property
635 def construction_data(self):
636 return self._construction_data
638 @construction_data.setter
639 def construction_data(self, value):
640 self._construction_data = datahandling.check_construction_data_setter_tabula_de(value)