Skip to content

Commit

Permalink
Merge pull request #775 from RWTH-EBC/774_retrofit_combos
Browse files Browse the repository at this point in the history
774 retrofit combos
  • Loading branch information
Nico-yf authored Nov 12, 2024
2 parents b83d754 + bc90f70 commit 0673d23
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 1 deletion.
2 changes: 1 addition & 1 deletion teaser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sys
import os

__version__ = "1.0.0"
__version__ = "1.0.1"


new_path = os.path.join(os.path.expanduser('~'), ("TEASEROutput"))
Expand Down
134 changes: 134 additions & 0 deletions teaser/logic/retrofit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import itertools

from teaser.logic.buildingobjects.building import Building
import teaser.data.utilities as datahandling


def generate_buildings_for_all_element_combinations(
project_add_building_function: callable,
add_building_function_kwargs: dict,
elements: list = None,
retrofit_choices: list = None
):
"""
Generate buildings for all possible combinations of
retrofit statuses for specified building elements.
This function creates multiple variations of a building based
on different retrofit options for specified building elements.
It's designed to work with TABULA archetypes.
Parameters
----------
project_add_building_function : callable
Function to add a building to the project.
add_building_function_kwargs : dict
Keyword arguments for the add_building function.
elements : list, optional
List of building elements to consider for retrofit.
Defaults to ['outer_walls', 'windows', 'rooftops', 'ground_floors'].
retrofit_choices : list, optional
List of retrofit options to consider.
Defaults to ['standard', 'retrofit', 'adv_retrofit'].
Returns
-------
list: A list of names of the generated buildings.
Raises
------
ValueError: If unsupported elements or retrofit choices are provided, or if the
construction data is not from TABULA DE or DK.
Note
----
This function only works with TABULA DE or DK construction data.
"""
construction_data = datahandling.ConstructionData(
add_building_function_kwargs["construction_data"]
)
if not construction_data.is_tabula_de() and not construction_data.is_tabula_dk():
raise ValueError(
"Given option to retrofit all combinations "
"is only implemented for TABULA archetypes."
)

# Define mapping for later naming
retrofit_dict = {'standard': 0, 'retrofit': 1, 'adv_retrofit': 2}
possible_elements = ['outer_walls', 'windows', 'rooftops', "ground_floors"]

if elements is None:
elements = ['outer_walls', 'windows', 'rooftops', "ground_floors"]
if retrofit_choices is None:
retrofit_choices = list(retrofit_dict.keys())
unsupported_elements = set(elements).difference(possible_elements)
if unsupported_elements:
raise ValueError(
"The following elements are not supported: " + ", ".join(unsupported_elements)
)
unsupported_choices = set(retrofit_choices).difference(retrofit_dict.keys())
if unsupported_choices:
raise ValueError(
"The following retrofit_choices are not supported: " + ", ".join(unsupported_choices)
)

# Generate all possible combinations of retrofit statuses for each element
combinations = itertools.product(retrofit_choices, repeat=len(elements))

# Create a list to store the resulting dictionaries
combinations = [
{
element: status
for element, status in zip(elements, combo)
}
for combo in combinations
]

generated_building_names = []
for element_retrofit_stats in combinations:
# Code for retrofit status OiWiRiGi with i from 0 to 2
retrofit_code = ''.join(
f"{element[0]}{retrofit_dict[retrofit_option]}"
for element, retrofit_option in element_retrofit_stats.items()
)
modified_function_kwargs = add_building_function_kwargs.copy()
modified_function_kwargs["name"] += f"_{retrofit_code}"
building = project_add_building_function(**modified_function_kwargs)
component_based_retrofit(building=building, element_retrofit_stats=element_retrofit_stats)
generated_building_names.append(modified_function_kwargs["name"])
return generated_building_names


def component_based_retrofit(building: Building, element_retrofit_stats: dict):
"""
Apply component-based retrofits to a building based on specified retrofit statuses.
This function applies retrofits to specific building elements (e.g., walls, windows)
based on the provided retrofit statuses.
Parameters
----------
building : Building
The building object to be retrofitted.
element_retrofit_stats : dict
A dictionary specifying the retrofit status for each
building element. Keys are element names (e.g., 'outer_walls'),
and values are retrofit options (e.g., 'standard', 'retrofit').
Note
----
This function modifies the building object in-place.
Only elements with 'standard' retrofit option are processed.
"""
for zone in building.thermal_zones:
for element, retrofit_option in element_retrofit_stats.items():
if retrofit_option == "standard":
continue
for wall_count in getattr(zone, element):
wall_count.load_type_element(
year=building.year_of_construction,
construction=wall_count.construction_data.replace(
"standard",
retrofit_option
)
)
46 changes: 46 additions & 0 deletions teaser/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from teaser.data.dataclass import DataClass
from teaser.logic.archetypebuildings.tabula.de.singlefamilyhouse import SingleFamilyHouse
from teaser.logic.simulation.modelicainfo import ModelicaInfo
from teaser.logic.retrofit import generate_buildings_for_all_element_combinations


class Project(object):
Expand Down Expand Up @@ -598,6 +599,51 @@ def add_residential(
)
return type_bldg

def add_residential_retrofit_combinations(
self,
elements: list = None,
retrofit_choices: list = None,
**add_residential_kwargs: dict
):
"""
Generate residential buildings for all possible combinations of
retrofit statuses for specified building elements.
This function creates multiple variations of a residential building based
on different retrofit options for specified building elements.
It's designed to work with TABULA archetypes.
Parameters
----------
add_residential_kwargs : dict
Keyword arguments for the function add_residential.
elements : list, optional
List of building elements to consider for retrofit.
Defaults to ['outer_walls', 'windows', 'rooftops', 'ground_floors'].
retrofit_choices : list, optional
List of retrofit options to consider.
Defaults to ['standard', 'retrofit', 'adv_retrofit'].
Returns
-------
list: A list of names of the generated buildings.
Raises
------
ValueError: If unsupported elements or retrofit choices are provided, or if the
construction data is not from TABULA DE or DK.
Note
----
This function only works with TABULA DE or DK construction data.
"""
return generate_buildings_for_all_element_combinations(
project_add_building_function=self.add_residential,
add_building_function_kwargs=add_residential_kwargs,
elements=elements,
retrofit_choices=retrofit_choices,
)

def save_project(self, file_name=None, path=None):
"""Saves the project to a JSON file
Expand Down
39 changes: 39 additions & 0 deletions tests/test_partial_retrofit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import itertools

from teaser.project import Project


class Test_tabula_sfh(object):

def test_tabula_de_sfh_area_1859(self):
"""
Test for area estimation of tabula sfh
"""
for elements, retrofit_choices in itertools.product(
[
None,
["outer_walls", "windows", "rooftops", "ground_floors"],
["outer_walls", "windows"]
],
[
None,
["standard", "retrofit", "adv_retrofit"],
["standard", "retrofit"]
]
):
prj = Project(False)
prj.add_residential_retrofit_combinations(
elements=elements,
retrofit_choices=retrofit_choices,
construction_data='tabula_de_standard',
geometry_data='tabula_de_single_family_house',
name="ResidentialBuilding",
year_of_construction=1858,
number_of_floors=2,
height_of_floors=3.2,
net_leased_area=219
)
len_elements = len(elements) if elements is not None else 4
len_choices = len(retrofit_choices) if retrofit_choices is not None else 3
assert len(prj.buildings) == len_choices ** len_elements, \
"Number of generated buildings does not match expectation"

0 comments on commit 0673d23

Please sign in to comment.