""" lca_carbon_workflow module Returns the summarize of envelope and energy systems SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2024 Concordia CERC group Code contributors: Alireza Adli alireza.adli@concordia.ca Mohammad Reza Seyedabadi mohammad.seyedabadi@mail.concordia.ca """ from pathlib import Path from hub.imports.geometry_factory import GeometryFactory from hub.imports.construction_factory import ConstructionFactory from hub.helpers.dictionaries import Dictionaries from city_model_structure.life_cycle_assessment.access_nrcan_catalogue \ import AccessNrcanCatalog from city_model_structure.life_cycle_assessment.opening_emission \ import OpeningEmission from city_model_structure.life_cycle_assessment.envelope_emission \ import EnvelopeEmission class LCACarbonWorkflow: def __init__( self, city_path, archetypes_catalog_file_name, constructions_catalog_file, catalog='nrcan', building_parameters=('height', 'year_of_construction', 'function')): self.file_path = (Path(__file__).parent / 'input_files' / city_path) self.catalogs_path = (Path(__file__).parent / 'input_files') self.archetypes_catalog_file_name = archetypes_catalog_file_name self.constructions_catalog_file = constructions_catalog_file self.nrcan_catalogs = AccessNrcanCatalog( self.catalogs_path, archetypes=self.archetypes_catalog_file_name, constructions=self.constructions_catalog_file) self.out_path = (Path(__file__).parent / 'out_files') self.handler = catalog self.height, self.year_of_construction, self.function = \ building_parameters print('[simulation start]') self.city = GeometryFactory( 'geojson', path=self.file_path, height_field=self.height, year_of_construction_field=self.year_of_construction, function_field=self.function, function_to_hub=Dictionaries().montreal_function_to_hub_function).city print(f'city created from {self.file_path}') ConstructionFactory(self.handler, self.city).enrich() self.building_envelope_emission = [] self.building_opening_emission = [] self.building_component_emission = [] def calculate_building_component_emission(self, building): surface_envelope_emission = [] surface_opening_emission = [] period_of_construction = self.nrcan_catalogs.year_to_period_of_construction(building.year_of_construction) opaque_surface_code = self.nrcan_catalogs.find_opaque_surface( self.nrcan_catalogs.hub_to_nrcan_function(building.function), self.nrcan_catalogs.year_to_period_of_construction( building.year_of_construction), '6') for surface in building.surfaces: boundary_envelope_emission = [] boundary_opening_emission = [] for boundary in surface.associated_thermal_boundaries: opening_emission = None layer_emission = self._calculate_envelope_emission(boundary) boundary_envelope_emission += layer_emission if boundary.window_ratio: opening_emission = self._calculate_opening_emission( building, surface, boundary, opaque_surface_code) if opening_emission: boundary_opening_emission += opening_emission if boundary_opening_emission: surface_opening_emission += boundary_opening_emission surface_envelope_emission += boundary_envelope_emission building_envelope_emission = sum(surface_envelope_emission) building_opening_emission = sum(surface_opening_emission) building_component_emission = \ building_envelope_emission + building_opening_emission return building_envelope_emission, building_opening_emission, \ building_component_emission def _calculate_envelope_emission(self, boundary): layer_emission = [] for layer in boundary.layers: if not layer.no_mass: layer_emission.append(EnvelopeEmission( self.nrcan_catalogs.search_materials( layer.material_name)['embodied_carbon'], boundary.opaque_area, layer.thickness).calculate_envelope_emission()) return layer_emission def _calculate_opening_emission( self, building, surface, boundary, opaque_surface_code): opening_emission = [] for opening in boundary.thermal_openings: transparent_surface_type = 'Window' if building.year_of_construction >= 2020 and \ surface.type == 'Roof': transparent_surface_type = 'Skylight' opening_emission.append(OpeningEmission( self.nrcan_catalogs.search_transparent_surfaces( transparent_surface_type, opaque_surface_code)['embodied_carbon'], opening.area).calculate_opening_emission()) return opening_emission def calculate_emission(self): for building in self.city.buildings: envelope, opening, building_component = \ self.calculate_building_component_emission(building) self.building_envelope_emission.append(envelope) self.building_opening_emission.append(opening) self.building_component_emission.append(building_component)