Coverage for teaser/logic/archetypebuildings/bmvbs/singlefamilydwelling.py: 98%
245 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 June 2015
2# by TEASER4 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.thermalzone import ThermalZone
14import teaser.data.utilities as datahandling
16class SingleFamilyDwelling(Residential):
17 """Archetype Residential Building according
19 Subclass from Residential archetype class to represent
20 SingleFamilyDwelling according to IWU :cite:`KurzverfahrenIWU`.
22 The SingleFamilyDwelling module contains a single zone building. It has 4
23 outer walls, 4 windows, a flat roof and a ground floor. Interior wall
24 areas are assigned related to typical width and depth of zones according to
25 :cite:`SwissSocietyofEngineersandArchitects.March2006`. It makes
26 number_of_floors and height_of_floors mandatory parameters.
27 Additional information can be passed
28 to the archetype (e.g. floor layout and number of neighbors).
30 Default values are given according to IWU.
32 In detail the net leased area is divided into the following thermal zone
33 area:
35 #. Single dwelling (100% of net leased area)
37 Parameters
38 ----------
40 parent: Project()
41 The parent class of this object, the Project the Building belongs to.
42 Allows for better control of hierarchical structures. If not None it
43 adds this Building instance to Project.buildings.
44 (default: None)
45 name : str
46 Individual name
47 year_of_construction : int
48 Year of first construction
49 height_of_floors : float [m]
50 Average height of the buildings' floors
51 number_of_floors : int
52 Number of building's floors above ground
53 net_leased_area : float [m2]
54 Total net leased area of building. This is area is NOT the footprint
55 of a building
56 with_ahu : Boolean
57 If set to True, an empty instance of BuildingAHU is instantiated and
58 assigned to attribute central_ahu. This instance holds information for
59 central Air Handling units. Default is False.
60 internal_gains_mode: int [1, 2, 3]
61 mode for the internal gains calculation done in AixLib:
63 1. Temperature and activity degree dependent heat flux calculation. The
64 calculation is based on SIA 2024 (default)
65 2. Temperature and activity degree independent heat flux calculation, the max.
66 heatflowrate is prescribed by the parameter
67 fixed_heat_flow_rate_persons.
68 3. Temperature and activity degree dependent calculation with
69 consideration of moisture and co2. The moisture calculation is
70 based on SIA 2024 (2015), the co2 calculation is based on
71 Engineering ToolBox (2004)
72 inner_wall_approximation_approach : str
73 'teaser_default' (default) sets length of inner walls = typical
74 length * height of floors + 2 * typical width * height of floors
75 'typical_minus_outer' sets length of inner walls = 2 * typical
76 length * height of floors + 2 * typical width * height of floors
77 - length of outer or interzonal walls
78 'typical_minus_outer_extended' like 'typical_minus_outer', but also
79 considers that
80 a) a non-complete "average room" reduces its circumference
81 proportional to the square root of the area
82 b) rooftops, windows and ground floors (= walls with border to
83 soil) may have a vertical share
84 residential_layout : int
85 Structure of floor plan (default = 0)
87 0. compact
88 1. elongated/complex
90 neighbour_buildings : int
91 Number of neighbour buildings. CAUTION: this will not change
92 the orientation of the buildings wall, but just the overall
93 exterior wall and window area(!) (default = 0)
95 0. no neighbour
96 1. one neighbour
97 2. two neighbours
99 attic : int
100 Design of the attic. CAUTION: this will not change the orientation or
101 tilt of the roof instances, but just adapt the roof area(!) (default
102 = 0)
104 0. flat roof
105 1. non heated attic
106 2. partly heated attic
107 3. heated attic
109 cellar : int
110 Design of the of cellar CAUTION: this will not change the
111 orientation, tilt of GroundFloor instances, nor the number or area of
112 ThermalZones, but will change GroundFloor area(!) (default = 0)
114 0. no cellar
115 1. non heated cellar
116 2. partly heated cellar
117 3. heated cellar
119 dormer : str
120 Is a dormer attached to the roof? CAUTION: this will not
121 change roof or window orientation or tilt, but just adapt the roof
122 area(!) (default = 0)
124 0. no dormer
125 1. dormer
127 construction_data : str
128 Construction type of used wall constructions default is "iwu_heavy"
130 - iwu_heavy: heavy construction
131 - iwu_light: light construction
132 - kfw_40, kfw_55, kfw_70, kfw_85, kfw_100: KfW efficiency building standards
134 Notes
135 -----
136 The listed attributes are just the ones that are set by the user
137 calculated values are not included in this list. Changing these values is
138 expert mode.
141 Attributes
142 ----------
144 zone_area_factors : dict
145 This dictionary contains the name of the zone (str), the
146 zone area factor (float), the zone usage from BoundaryConditions json
147 (str) (Default see doc string above), and may contain a dictionary with
148 keyword-attribute-like changes to zone parameters that are usually
149 inherited from parent: 'number_of_floors', 'height_of_floors'
150 outer_wall_names : dict
151 This dictionary contains a random name for the outer walls,
152 their orientation and tilt. Default is a building in north-south
153 orientation)
154 roof_names : dict
155 This dictionary contains the name of the roofs, their orientation
156 and tilt. Default is one flat roof.
157 ground_floor_names : dict
158 This dictionary contains the name of the ground floors, their
159 orientation and tilt. Default is one ground floor.
160 window_names : dict
161 This dictionary contains the name of the window, their
162 orientation and tilt. Default is a building in north-south
163 orientation)
164 inner_wall_names : dict
165 This dictionary contains the name of the inner walls, their
166 orientation and tilt. Default is one cumulated inner wall.
167 ceiling_names : dict
168 This dictionary contains the name of the ceilings, their
169 orientation and tilt. Default is one cumulated ceiling.
170 floor_names : dict
171 This dictionary contains the name of the floors, their
172 orientation and tilt. Default is one cumulated floor.
173 est_living_area_factor : float
174 Estimation factor for calculation of number of heated floors
175 est_bottom_building_closure : float
176 Estimation factor to calculate ground floor area
177 est_upper_building_closure : float
178 Estimation factor to calculate attic area
179 est_factor_win_area : float
180 Estimation factor to calculate window area
181 est_factor_cellar_area : float
182 Estimation factor to calculate heated cellar area
183 """
185 def __init__(
186 self,
187 parent,
188 name=None,
189 year_of_construction=None,
190 number_of_floors=None,
191 height_of_floors=None,
192 net_leased_area=None,
193 with_ahu=False,
194 inner_wall_approximation_approach='teaser_default',
195 internal_gains_mode=1,
196 residential_layout=None,
197 neighbour_buildings=None,
198 attic=None,
199 cellar=None,
200 dormer=None,
201 construction_data=None,
202 ):
203 """Constructor of SingleFamilyDwelling
204 """
206 super(SingleFamilyDwelling, self).__init__(
207 parent,
208 name,
209 year_of_construction,
210 net_leased_area,
211 with_ahu,
212 internal_gains_mode,
213 inner_wall_approximation_approach
214 )
216 self.residential_layout = residential_layout
217 self.neighbour_buildings = neighbour_buildings
218 self.attic = attic
219 self.cellar = cellar
220 self.dormer = dormer
221 self.construction_data = construction_data
222 self.number_of_floors = number_of_floors
223 self.height_of_floors = height_of_floors
225 # Parameters are default values for current calculation following IWU
227 # [area factor, usage type(has to be set)]
228 self.zone_area_factors = {"SingleDwelling": [1, "Living"]}
230 self.outer_wall_names = {
231 "Exterior Facade North": [90.0, 0.0],
232 "Exterior Facade East": [90.0, 90.0],
233 "Exterior Facade South": [90.0, 180.0],
234 "Exterior Facade West": [90.0, 270.0],
235 }
236 # [tilt, orientation]
238 self.roof_names = {"Rooftop": [0, -1]} # [0, -1]
240 self.ground_floor_names = {"Ground Floor": [0, -2]} # [0, -2]
242 self.window_names = {
243 "Window Facade North": [90.0, 0.0],
244 "Window Facade East": [90.0, 90.0],
245 "Window Facade South": [90.0, 180.0],
246 "Window Facade West": [90.0, 270.0],
247 }
248 # [tilt, orientation]
250 self.inner_wall_names = {"InnerWall": [90.0, 0.0]}
252 self.ceiling_names = {"Ceiling": [0.0, -1]}
254 self.floor_names = {"Floor": [0.0, -2]}
256 self.est_living_area_factor = 0.75 # fW
257 self.est_bottom_building_closure = 1.33 # p_FB
258 self.est_upper_building_closure = 1.0
259 self.est_factor_win_area = 0.2
260 self.est_factor_cellar_area = 0.5
262 self.nr_of_orientation = len(self.outer_wall_names)
264 # estimated intermediate calculated values
265 self._living_area_per_floor = 0
266 self._number_of_heated_floors = 0
267 self._est_factor_heated_cellar = 0
268 self._est_factor_heated_attic = 0
269 self._est_roof_area = 0
270 self._est_ground_floor_area = 0.0
271 self._est_win_area = 0
272 self._est_outer_wall_area = 0.0
273 self._est_cellar_wall_area = 0
274 self._est_factor_volume = 0.0
276 self.est_factor_neighbour = 0.0 # n_Nachbar
277 self.est_extra_floor_area = 0.0 # q_Fa
279 if self.neighbour_buildings == 0:
280 self._est_factor_neighbour = 0.0
281 self._est_extra_floor_area = 50.0
282 elif self.neighbour_buildings == 1:
283 self._est_factor_neighbour = 1.0
284 self._est_extra_floor_area = 30.0
285 elif self.neighbour_buildings == 2:
286 self._est_factor_neighbour = 2.0
287 self._est_extra_floor_area = 10.0
289 self._est_facade_to_floor_area = 0.0 # p_Fa
291 if self.residential_layout == 0:
292 self._est_facade_to_floor_area = 0.66
293 elif self.residential_layout == 1:
294 self._est_facade_to_floor_area = 0.8
296 self._est_factor_heated_attic = 0.0 # f_TB_DG
297 self._est_area_per_floor = 0.0 # p_DA
298 self._est_area_per_roof = 0.0 # p_OG
300 if self.attic == 0:
301 self._est_factor_heated_attic = 0.0
302 self._est_area_per_floor = 1.33
303 self._est_area_per_roof = 0.0
304 elif self.attic == 1:
305 self._est_factor_heated_attic = 0.0
306 self._est_area_per_floor = 0.0
307 self._est_area_per_roof = 1.33
308 elif self.attic == 2:
309 self._est_factor_heated_attic = 0.5
310 self._est_area_per_floor = 0.75
311 self._est_area_per_roof = 0.67
312 elif self.attic == 3:
313 self._est_factor_heated_attic = 1.0
314 self._est_area_per_floor = 1.5
315 self._est_area_per_roof = 0.0
317 self._est_factor_heated_cellar = 0.0 # f_TB_KG
319 if self.cellar == 0:
320 self._est_factor_heated_cellar = 0.0
321 elif self.cellar == 1:
322 self._est_factor_heated_cellar = 0.0
323 elif self.cellar == 2:
324 self._est_factor_heated_cellar = 0.5
325 elif self.cellar == 3:
326 self._est_factor_heated_cellar = 1.0
328 self._est_factor_dormer = 0.0
330 if self.dormer == 0:
331 self._est_factor_dormer = 1.0
332 elif self.dormer == 1:
333 self._est_factor_dormer = 1.3
335 if self.with_ahu is True:
336 self.central_ahu.temperature_profile = (
337 7 * [293.15] + 12 * [295.15] + 5 * [293.15]
338 )
339 # according to :cite:`DeutschesInstitutfurNormung.2016`
340 self.central_ahu.min_relative_humidity_profile = 24 * [0.45]
341 # according to :cite:`DeutschesInstitutfurNormung.2016b` and
342 # :cite:`DeutschesInstitutfurNormung.2016`
343 self.central_ahu.max_relative_humidity_profile = 24 * [0.65]
344 self.central_ahu.v_flow_profile = (
345 7 * [0.0] + 12 * [1.0] + 5 * [0.0]
346 ) # according to user #
347 # profile in :cite:`DeutschesInstitutfurNormung.2016`
349 def generate_archetype(self):
350 """Generates a SingleFamilyDwelling building.
352 With given values, this class generates a archetype building for
353 single family dwellings according to TEASER requirements
354 """
355 # help area for the correct building area setting while using typeBldgs
356 self.thermal_zones = None
357 type_bldg_area = self.net_leased_area
358 self.net_leased_area = 0.0
360 self._number_of_heated_floors = (
361 self._est_factor_heated_cellar
362 + self.number_of_floors
363 + self.est_living_area_factor * self._est_factor_heated_attic
364 )
366 self._living_area_per_floor = type_bldg_area / self._number_of_heated_floors
368 self._est_ground_floor_area = (
369 self.est_bottom_building_closure * self._living_area_per_floor
370 )
372 self._est_roof_area = (
373 self.est_upper_building_closure
374 * self._est_factor_dormer
375 * self._est_area_per_floor
376 * self._living_area_per_floor
377 )
379 self._top_floor_area = self._est_area_per_roof * self._living_area_per_floor
381 if self._est_roof_area == 0:
382 self._est_roof_area = self._top_floor_area
384 self._est_facade_area = self._est_facade_to_floor_area * (
385 self._living_area_per_floor + self._est_extra_floor_area
386 )
388 self._est_win_area = self.est_factor_win_area * type_bldg_area
390 self._est_cellar_wall_area = (
391 self.est_factor_cellar_area
392 * self._est_factor_heated_cellar
393 * self._est_facade_area
394 )
396 self._est_outer_wall_area = (
397 (self._number_of_heated_floors * self._est_facade_area)
398 - self._est_cellar_wall_area
399 - self._est_win_area
400 )
402 # self._est_factor_volume = type_bldg_area * 2.5
404 for key, value in self.zone_area_factors.items():
405 zone = ThermalZone(self)
406 zone.name = key
407 zone.area = type_bldg_area * value[0]
408 try:
409 zone.number_of_floors = value[2]['number_of_floors']
410 except (KeyError, IndexError):
411 pass
412 try:
413 zone.height_of_floors = value[2]['height_of_floors']
414 except (KeyError, IndexError):
415 pass
416 use_cond = UseCond(zone)
417 use_cond.load_use_conditions(value[1], data_class=self.parent.data)
419 zone.use_conditions = use_cond
420 zone.use_conditions.with_ahu = False
422 for key, value in self.outer_wall_names.items():
423 # North and South
425 if value[1] == 0 or value[1] == 180.0:
426 self.outer_area[value[1]] = (
427 self._est_outer_wall_area / self.nr_of_orientation
428 )
429 # East and West
430 elif value[1] == 90 or value[1] == 270:
432 self.outer_area[value[1]] = (
433 self._est_outer_wall_area / self.nr_of_orientation
434 )
436 for zone in self.thermal_zones:
437 # create wall and set building elements
438 outer_wall = OuterWall(zone)
439 outer_wall.load_type_element(
440 year=self.year_of_construction,
441 construction=self.construction_data.value,
442 data_class=self.parent.data,
443 )
444 outer_wall.name = key
445 outer_wall.tilt = value[0]
446 outer_wall.orientation = value[1]
448 for key, value in self.window_names.items():
450 if value[1] == 0 or value[1] == 180:
452 self.window_area[value[1]] = self._est_win_area / self.nr_of_orientation
454 elif value[1] == 90 or value[1] == 270:
456 self.window_area[value[1]] = self._est_win_area / self.nr_of_orientation
458 """
459 There is no real classification for windows, so this is a bit hard
460 code - will be fixed sometime
461 """
462 for zone in self.thermal_zones:
463 window = Window(zone)
464 construction = (
465 "Waermeschutzverglasung, dreifach"
466 if self.construction_data.is_kfw()
467 else "Kunststofffenster, " "Isolierverglasung"
468 )
469 window.load_type_element(
470 self.year_of_construction,
471 construction=construction,
472 data_class=self.parent.data,
473 )
474 window.name = key
475 window.tilt = value[0]
476 window.orientation = value[1]
478 for key, value in self.roof_names.items():
480 self.outer_area[value[1]] = self._est_roof_area
482 for zone in self.thermal_zones:
483 roof = Rooftop(zone)
484 roof.load_type_element(
485 year=self.year_of_construction,
486 construction=self.construction_data.value,
487 data_class=self.parent.data,
488 )
489 roof.name = key
490 roof.tilt = value[0]
491 roof.orientation = value[1]
493 for key, value in self.ground_floor_names.items():
495 self.outer_area[value[1]] = self._est_ground_floor_area
497 for zone in self.thermal_zones:
498 ground_floor = GroundFloor(zone)
499 ground_floor.load_type_element(
500 year=self.year_of_construction,
501 construction=self.construction_data.value,
502 data_class=self.parent.data,
503 )
504 ground_floor.name = key
505 ground_floor.tilt = value[0]
506 ground_floor.orientation = value[1]
508 for key, value in self.inner_wall_names.items():
510 for zone in self.thermal_zones:
511 inner_wall = InnerWall(zone)
512 inner_wall.load_type_element(
513 year=self.year_of_construction,
514 construction=self.construction_data.value,
515 data_class=self.parent.data,
516 )
517 inner_wall.name = key
518 inner_wall.tilt = value[0]
519 inner_wall.orientation = value[1]
520 # zone.inner_walls.append(inner_wall)
522 if self.number_of_floors > 1:
524 for key, value in self.ceiling_names.items():
526 for zone in self.thermal_zones:
527 ceiling = Ceiling(zone)
528 ceiling.load_type_element(
529 year=self.year_of_construction,
530 construction=self.construction_data.value,
531 data_class=self.parent.data,
532 )
533 ceiling.name = key
534 ceiling.tilt = value[0]
535 ceiling.orientation = value[1]
536 # zone.inner_walls.append(ceiling)
538 for key, value in self.floor_names.items():
540 for zone in self.thermal_zones:
541 floor = Floor(zone)
542 floor.load_type_element(
543 year=self.year_of_construction,
544 construction=self.construction_data.value,
545 data_class=self.parent.data,
546 )
547 floor.name = key
548 floor.tilt = value[0]
549 floor.orientation = value[1]
550 # zone.inner_walls.append(floor)
551 else:
552 pass
554 for key, value in self.outer_area.items():
555 self.set_outer_wall_area(value, key)
556 for key, value in self.window_area.items():
557 self.set_window_area(value, key)
559 for zone in self.thermal_zones:
560 zone.set_inner_wall_area()
561 zone.set_volume_zone()
563 @property
564 def residential_layout(self):
565 return self._residential_layout
567 @residential_layout.setter
568 def residential_layout(self, value):
569 if value is not None:
570 self._residential_layout = value
571 else:
572 self._residential_layout = 0
574 @property
575 def neighbour_buildings(self):
576 return self._neighbour_buildings
578 @neighbour_buildings.setter
579 def neighbour_buildings(self, value):
580 if value is not None:
581 self._neighbour_buildings = value
582 else:
583 self._neighbour_buildings = 0
585 @property
586 def attic(self):
587 return self._attic
589 @attic.setter
590 def attic(self, value):
591 if value is not None:
592 self._attic = value
593 else:
594 self._attic = 0
596 @property
597 def cellar(self):
598 return self._cellar
600 @cellar.setter
601 def cellar(self, value):
602 if value is not None:
603 self._cellar = value
604 else:
605 self._cellar = 0
607 @property
608 def dormer(self):
609 return self._dormer
611 @dormer.setter
612 def dormer(self, value):
613 if value is not None:
614 self._dormer = value
615 else:
616 self._dormer = 0
618 @property
619 def construction_data(self):
620 return self._construction_data
621 @construction_data.setter
622 def construction_data(self, value):
623 self._construction_data = datahandling.check_construction_data_setter_iwu(value)