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