Coverage for bim2sim/plugins/PluginOpenFOAM/bim2sim_openfoam/openfoam_elements/stlbound.py: 0%
75 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-01 10:24 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-01 10:24 +0000
1import logging
3from bim2sim.elements.base_elements import Element
4from bim2sim.plugins.PluginOpenFOAM.bim2sim_openfoam.openfoam_elements.openfoam_base_boundary_conditions import \
5 OpenFOAMBaseBoundaryFields
6from bim2sim.plugins.PluginOpenFOAM.bim2sim_openfoam.openfoam_elements.openfoam_base_element import \
7 OpenFOAMBaseElement
8from bim2sim.utilities.pyocc_tools import PyOCCTools
9from bim2sim.utilities.types import BoundaryOrientation
11logger = logging.getLogger(__name__)
14class StlBound(OpenFOAMBaseBoundaryFields, OpenFOAMBaseElement):
15 def __init__(self, bound, radiation_model):
16 super().__init__()
17 self.radiation_model = radiation_model
18 self.bound = bound
19 self.guid = bound.guid
20 self.bound_element_type = (
21 bound.bound_element.__class__.__name__.replace('Disaggregated', ''))
22 if (self.bound_element_type in ['Floor', 'InnerFloor'] and
23 bound.top_bottom == 'TOP'):
24 self.bound_element_type = 'Ceiling'
25 # hotfix for incorrectly assigned floors and roofs in bim2sim elements
26 # todo: test and remove?
27 if self.bound_element_type in ['InnerFloor']:
28 if bound.top_bottom == BoundaryOrientation.top:
29 self.bound_element_type = 'Ceiling'
30 self.solid_name = self.bound_element_type + '_' + bound.guid.replace(
31 '$', '___')
32 if not hasattr(bound, 'cfd_face'):
33 bound.cfd_face = bound.bound_shape
34 opening_shapes = []
35 if bound.opening_bounds:
36 opening_shapes = [s.bound_shape for s in bound.opening_bounds]
37 self.tri_geom = PyOCCTools.triangulate_bound_shape(bound.cfd_face,
38 opening_shapes)
39 self.temperature = 293.15
40 self.heat_flux = 0
41 self.power = 0
42 self.bound_area = PyOCCTools.get_shape_area(self.tri_geom)
43 self.set_default_refinement_level()
44 self.set_patch_info_type()
46 def set_default_refinement_level(self):
47 self.refinement_level = [2, 3]
48 if self.bound_element_type in ['OuterWall', 'Window', 'Door',
49 'InnerFloor', 'Floor', 'Roof',
50 'GroundFloor', 'OuterDoor', 'Ceiling']:
51 self.refinement_level = [2, 3]
52 elif self.bound_element_type in ['InnerWall', 'Wall', 'InnerDoor']:
53 self.refinement_level = [2, 3]
54 else:
55 logger.warning(f"{self.bound_element_type} bound_element_type is "
56 f"unknown")
58 def set_patch_info_type(self):
59 # AirTerminal, SpaceHeater
60 self.patch_info_type = 'wall'
61 if self.bound_element_type == 'SpaceHeater':
62 self.patch_info_type = 'wall'
63 elif self.bound_element_type == 'AirTerminal':
64 # todo: implement distinction for inlet (Zuluft) and outlet (
65 # Abluft), for the surface itself and the surrounding boxes.
66 pass
67 else:
68 pass
70 def read_boundary_conditions(self, timestep_df, default_temp):
71 res_key = self.guid.upper() + ':'
72 if not self.bound.physical:
73 self.heat_flux = 0
74 self.power = 0
75 self.temperature = default_temp - 273.15
76 try:
77 self.temperature = timestep_df[
78 res_key + 'Surface Inside Face Temperature [C](Hourly)']
79 except KeyError:
80 logger.warning(f"the boundary with guid %s does not provide a "
81 f"surface inside face temperature and is set to adiabatic.", self.guid)
82 self.heat_flux = 0
83 self.power = 0
84 self.temperature = default_temp - 273.15
85 return
86 if not self.bound_element_type == 'Window':
87 self.power = timestep_df[res_key + ('Surface Inside Face '
88 'Conduction Heat Transfer '
89 'Rate [W](Hourly)')]
90 prev_heat_flux = timestep_df[res_key + ('Surface Inside Face '
91 'Conduction Heat Transfer '
92 'Rate per Area [W/m2]('
93 'Hourly)')]
94 self.heat_flux = prev_heat_flux
95 else:
96 self.heat_flux = (timestep_df[res_key + (
97 'Surface Window Net Heat Transfer '
98 'Rate [W](Hourly)')] /
99 self.bound_area)
100 self.power = timestep_df[res_key + (
101 'Surface Window Net Heat Transfer '
102 'Rate [W](Hourly)')]
104 def set_boundary_conditions(self, no_heatloss=False):
105 if self.radiation_model == 'none':
106 qr = 'none'
107 else:
108 qr = 'qr'
109 if no_heatloss:
110 pass
111 elif any(i for i in ["INNER", "FLOOR"] if i in self.solid_name.upper()):
112 # else: #
113 self.T = {
114 'type': 'fixedValue',
115 'value': f'uniform {self.temperature + 273.15}'
116 }
117 else:
118 self.T = {'type': 'externalWallHeatFluxTemperature',
119 'mode': 'power',
120 'qr': f"{qr}",
121 'Q': f'uniform {self.power}',
122 'qrRelaxation': 0.003,
123 'relaxation': 1.0,
124 'kappaMethod': 'fluidThermo',
125 'kappa': 'fluidThermo',
126 'value': f'uniform {self.temperature + 273.15}'
127 }