Coverage for teaser/logic/retrofit.py: 92%

37 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-04-29 16:01 +0000

1import itertools 

2 

3from teaser.logic.buildingobjects.building import Building 

4import teaser.data.utilities as datahandling 

5 

6 

7def generate_buildings_for_all_element_combinations( 

8 project_add_building_function: callable, 

9 add_building_function_kwargs: dict, 

10 elements: list = None, 

11 retrofit_choices: list = None 

12): 

13 """ 

14 Generate buildings for all possible combinations of 

15 retrofit statuses for specified building elements. 

16 

17 This function creates multiple variations of a building based 

18 on different retrofit options for specified building elements. 

19 It's designed to work with TABULA archetypes. 

20 

21 Parameters 

22 ---------- 

23 project_add_building_function : callable 

24 Function to add a building to the project. 

25 add_building_function_kwargs : dict 

26 Keyword arguments for the add_building function. 

27 elements : list, optional 

28 List of building elements to consider for retrofit. 

29 Defaults to ['outer_walls', 'windows', 'rooftops', 'ground_floors']. 

30 retrofit_choices : list, optional 

31 List of retrofit options to consider. 

32 Defaults to ['standard', 'retrofit', 'adv_retrofit']. 

33 

34 Returns 

35 ------- 

36 list: A list of names of the generated buildings. 

37 

38 Raises 

39 ------ 

40 ValueError: If unsupported elements or retrofit choices are provided, or if the 

41 construction data is not from TABULA DE or DK. 

42 

43 Note 

44 ---- 

45 This function only works with TABULA DE or DK construction data. 

46 """ 

47 construction_data = datahandling.ConstructionData( 

48 add_building_function_kwargs["construction_data"] 

49 ) 

50 if not construction_data.is_tabula_de() and not construction_data.is_tabula_dk(): 

51 raise ValueError( 

52 "Given option to retrofit all combinations " 

53 "is only implemented for TABULA archetypes." 

54 ) 

55 

56 # Define mapping for later naming 

57 retrofit_dict = {'standard': 0, 'retrofit': 1, 'adv_retrofit': 2} 

58 possible_elements = ['outer_walls', 'windows', 'rooftops', "ground_floors"] 

59 

60 if elements is None: 

61 elements = ['outer_walls', 'windows', 'rooftops', "ground_floors"] 

62 if retrofit_choices is None: 

63 retrofit_choices = list(retrofit_dict.keys()) 

64 unsupported_elements = set(elements).difference(possible_elements) 

65 if unsupported_elements: 

66 raise ValueError( 

67 "The following elements are not supported: " + ", ".join(unsupported_elements) 

68 ) 

69 unsupported_choices = set(retrofit_choices).difference(retrofit_dict.keys()) 

70 if unsupported_choices: 

71 raise ValueError( 

72 "The following retrofit_choices are not supported: " + ", ".join(unsupported_choices) 

73 ) 

74 

75 # Generate all possible combinations of retrofit statuses for each element 

76 combinations = itertools.product(retrofit_choices, repeat=len(elements)) 

77 

78 # Create a list to store the resulting dictionaries 

79 combinations = [ 

80 { 

81 element: status 

82 for element, status in zip(elements, combo) 

83 } 

84 for combo in combinations 

85 ] 

86 

87 generated_building_names = [] 

88 for element_retrofit_stats in combinations: 

89 # Code for retrofit status OiWiRiGi with i from 0 to 2 

90 retrofit_code = ''.join( 

91 f"{element[0]}{retrofit_dict[retrofit_option]}" 

92 for element, retrofit_option in element_retrofit_stats.items() 

93 ) 

94 modified_function_kwargs = add_building_function_kwargs.copy() 

95 modified_function_kwargs["name"] += f"_{retrofit_code}" 

96 building = project_add_building_function(**modified_function_kwargs) 

97 component_based_retrofit(building=building, element_retrofit_stats=element_retrofit_stats) 

98 generated_building_names.append(modified_function_kwargs["name"]) 

99 return generated_building_names 

100 

101 

102def component_based_retrofit(building: Building, element_retrofit_stats: dict): 

103 """ 

104 Apply component-based retrofits to a building based on specified retrofit statuses. 

105 

106 This function applies retrofits to specific building elements (e.g., walls, windows) 

107 based on the provided retrofit statuses. 

108 

109 Parameters 

110 ---------- 

111 building : Building 

112 The building object to be retrofitted. 

113 element_retrofit_stats : dict 

114 A dictionary specifying the retrofit status for each 

115 building element. Keys are element names (e.g., 'outer_walls'), 

116 and values are retrofit options (e.g., 'standard', 'retrofit'). 

117 

118 Note 

119 ---- 

120 This function modifies the building object in-place. 

121 Only elements with 'standard' retrofit option are processed. 

122 """ 

123 for zone in building.thermal_zones: 

124 for element, retrofit_option in element_retrofit_stats.items(): 

125 if retrofit_option == "standard": 

126 continue 

127 for wall_count in getattr(zone, element): 

128 wall_count.load_type_element( 

129 year=building.year_of_construction, 

130 construction=wall_count.construction_data.replace( 

131 "standard", 

132 retrofit_option 

133 ) 

134 )