pycphy 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pycphy/__init__.py +11 -0
- pycphy/cli.py +145 -0
- pycphy/config_manager.py +373 -0
- pycphy/foamCaseDeveloper/__init__.py +60 -41
- pycphy/foamCaseDeveloper/config/__init__.py +69 -26
- pycphy/foamCaseDeveloper/config/cad_mesh_config.py +62 -0
- pycphy/foamCaseDeveloper/config/config_hfdibdem.py +193 -0
- pycphy/foamCaseDeveloper/config/constant/__init__.py +23 -0
- pycphy/foamCaseDeveloper/config/constant/dynamic_mesh_config.py +208 -0
- pycphy/foamCaseDeveloper/config/constant/gravity_field_config.py +379 -0
- pycphy/foamCaseDeveloper/config/constant/transport_properties_config.py +225 -0
- pycphy/foamCaseDeveloper/config/constant/turbulence_config.py +617 -0
- pycphy/foamCaseDeveloper/config/csv_boundary_reader.py +219 -0
- pycphy/foamCaseDeveloper/config/system/__init__.py +31 -0
- pycphy/foamCaseDeveloper/config/system/block_mesh_config.py +184 -0
- pycphy/foamCaseDeveloper/config/{control_config.py → system/control_config.py} +113 -1
- pycphy/foamCaseDeveloper/config/system/decompose_par_config.py +525 -0
- pycphy/foamCaseDeveloper/config/system/fv_options_config.py +575 -0
- pycphy/foamCaseDeveloper/config/system/fv_schemes_config.py +363 -0
- pycphy/foamCaseDeveloper/config/system/set_fields_config.py +640 -0
- pycphy/foamCaseDeveloper/config/system/snappy_hex_mesh_config.py +241 -0
- pycphy/foamCaseDeveloper/config/zero/U_config.py +135 -0
- pycphy/foamCaseDeveloper/config/zero/__init__.py +22 -0
- pycphy/foamCaseDeveloper/config/zero/f_config.py +140 -0
- pycphy/foamCaseDeveloper/config/zero/lambda_config.py +157 -0
- pycphy/foamCaseDeveloper/config/zero/p_config.py +97 -0
- pycphy/foamCaseDeveloper/core/__init__.py +30 -18
- pycphy/foamCaseDeveloper/core/block_mesh_developer.py +1 -1
- pycphy/foamCaseDeveloper/core/cad_block_mesh_developer.py +463 -0
- pycphy/foamCaseDeveloper/core/case_builder.py +1217 -0
- pycphy/foamCaseDeveloper/core/foam_case_manager.py +370 -111
- pycphy/foamCaseDeveloper/develop_case.py +640 -0
- pycphy/foamCaseDeveloper/main.py +260 -260
- pycphy/foamCaseDeveloper/utils/myAutoCAD.py +418 -0
- pycphy/foamCaseDeveloper/writers/__init__.py +37 -4
- pycphy/foamCaseDeveloper/writers/constant/__init__.py +25 -0
- pycphy/foamCaseDeveloper/writers/constant/dynamic_mesh_dict_writer.py +75 -0
- pycphy/foamCaseDeveloper/writers/constant/gravity_field_writer.py +88 -0
- pycphy/foamCaseDeveloper/writers/constant/hfdibdem_dict_writer.py +81 -0
- pycphy/foamCaseDeveloper/writers/constant/transport_properties_writer.py +202 -0
- pycphy/foamCaseDeveloper/writers/{turbulence_properties_writer.py → constant/turbulence_properties_writer.py} +49 -1
- pycphy/foamCaseDeveloper/writers/system/__init__.py +31 -0
- pycphy/foamCaseDeveloper/writers/{block_mesh_writer.py → system/block_mesh_writer.py} +1 -1
- pycphy/foamCaseDeveloper/writers/{control_dict_writer.py → system/control_dict_writer.py} +37 -1
- pycphy/foamCaseDeveloper/writers/system/decompose_par_writer.py +228 -0
- pycphy/foamCaseDeveloper/writers/system/fv_options_writer.py +188 -0
- pycphy/foamCaseDeveloper/writers/system/fv_schemes_writer.py +155 -0
- pycphy/foamCaseDeveloper/writers/system/set_fields_writer.py +191 -0
- pycphy/foamCaseDeveloper/writers/system/snappy_hex_mesh_writer.py +123 -0
- pycphy/foamCaseDeveloper/writers/zero/__init__.py +24 -0
- pycphy/foamCaseDeveloper/writers/zero/f_field_writer.py +89 -0
- pycphy/foamCaseDeveloper/writers/zero/lambda_field_writer.py +84 -0
- pycphy/foamCaseDeveloper/writers/zero/p_field_writer.py +89 -0
- pycphy/foamCaseDeveloper/writers/zero/u_field_writer.py +96 -0
- pycphy/foamCaseDeveloper/writers/zero/zero_field_factory.py +388 -0
- {pycphy-0.1.0.dist-info → pycphy-0.2.0.dist-info}/METADATA +154 -6
- pycphy-0.2.0.dist-info/RECORD +63 -0
- pycphy-0.2.0.dist-info/entry_points.txt +3 -0
- pycphy/foamCaseDeveloper/config/block_mesh_config.py +0 -90
- pycphy/foamCaseDeveloper/config/turbulence_config.py +0 -187
- pycphy/foamCaseDeveloper/core/control_dict_writer.py +0 -55
- pycphy/foamCaseDeveloper/core/turbulence_properties_writer.py +0 -68
- pycphy-0.1.0.dist-info/RECORD +0 -24
- pycphy-0.1.0.dist-info/entry_points.txt +0 -2
- {pycphy-0.1.0.dist-info → pycphy-0.2.0.dist-info}/WHEEL +0 -0
- {pycphy-0.1.0.dist-info → pycphy-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {pycphy-0.1.0.dist-info → pycphy-0.2.0.dist-info}/top_level.txt +0 -0
@@ -1,19 +1,36 @@
|
|
1
1
|
# foam_case_manager.py
|
2
2
|
|
3
3
|
import os
|
4
|
-
from
|
5
|
-
from .
|
6
|
-
|
4
|
+
from typing import Dict, Any
|
5
|
+
from .case_builder import (
|
6
|
+
GeometryComponent,
|
7
|
+
ControlComponent,
|
8
|
+
TurbulenceComponent,
|
9
|
+
DynamicMeshComponent,
|
10
|
+
HFDIBDEMComponent,
|
11
|
+
TransportPropertiesComponent,
|
12
|
+
FvSchemesComponent,
|
13
|
+
FvOptionsComponent,
|
14
|
+
GravityFieldComponent,
|
15
|
+
SetFieldsComponent,
|
16
|
+
DecomposeParComponent,
|
17
|
+
SnappyHexMeshComponent,
|
18
|
+
PFieldComponent,
|
19
|
+
UFieldComponent,
|
20
|
+
FFieldComponent,
|
21
|
+
LambdaFieldComponent
|
22
|
+
)
|
7
23
|
|
8
24
|
class FoamCaseManager:
|
9
25
|
"""
|
10
26
|
A comprehensive manager for creating and setting up OpenFOAM cases.
|
11
27
|
|
12
28
|
This class provides a high-level interface for creating complete OpenFOAM
|
13
|
-
case directories with all necessary configuration files
|
29
|
+
case directories with all necessary configuration files using a modular
|
30
|
+
component-based approach.
|
14
31
|
"""
|
15
32
|
|
16
|
-
def __init__(self, case_name):
|
33
|
+
def __init__(self, case_name: str):
|
17
34
|
"""
|
18
35
|
Initialize the FoamCaseManager.
|
19
36
|
|
@@ -24,11 +41,50 @@ class FoamCaseManager:
|
|
24
41
|
self.system_dir = os.path.join(case_name, "system")
|
25
42
|
self.constant_dir = os.path.join(case_name, "constant")
|
26
43
|
|
44
|
+
# Initialize components
|
45
|
+
self.geometry = GeometryComponent()
|
46
|
+
self.control = ControlComponent()
|
47
|
+
self.turbulence = TurbulenceComponent()
|
48
|
+
self.dynamic_mesh = DynamicMeshComponent()
|
49
|
+
self.hfdibdem = HFDIBDEMComponent()
|
50
|
+
self.transport_properties = TransportPropertiesComponent()
|
51
|
+
self.fv_schemes = FvSchemesComponent()
|
52
|
+
self.fv_options = FvOptionsComponent()
|
53
|
+
self.gravity_field = GravityFieldComponent()
|
54
|
+
self.set_fields = SetFieldsComponent()
|
55
|
+
self.decompose_par = DecomposeParComponent()
|
56
|
+
self.snappy_hex_mesh = SnappyHexMeshComponent()
|
57
|
+
self.p_field = PFieldComponent()
|
58
|
+
self.u_field = UFieldComponent()
|
59
|
+
self.f_field = FFieldComponent()
|
60
|
+
self.lambda_field = LambdaFieldComponent()
|
61
|
+
|
62
|
+
# List of all components for easy iteration
|
63
|
+
self.components = [
|
64
|
+
self.geometry,
|
65
|
+
self.control,
|
66
|
+
self.turbulence,
|
67
|
+
self.dynamic_mesh,
|
68
|
+
self.hfdibdem,
|
69
|
+
self.transport_properties,
|
70
|
+
self.fv_schemes,
|
71
|
+
self.fv_options,
|
72
|
+
self.gravity_field,
|
73
|
+
self.set_fields,
|
74
|
+
self.decompose_par,
|
75
|
+
self.snappy_hex_mesh,
|
76
|
+
self.p_field,
|
77
|
+
self.u_field,
|
78
|
+
self.f_field,
|
79
|
+
self.lambda_field
|
80
|
+
]
|
81
|
+
|
27
82
|
# Ensure directories exist
|
28
83
|
os.makedirs(self.system_dir, exist_ok=True)
|
29
84
|
os.makedirs(self.constant_dir, exist_ok=True)
|
30
85
|
|
31
|
-
def setup_geometry(self, p0, p1, cells
|
86
|
+
def setup_geometry(self, p0: tuple, p1: tuple, cells: tuple,
|
87
|
+
patch_names: Dict[str, str], scale: float = 1.0) -> bool:
|
32
88
|
"""
|
33
89
|
Set up the geometry and mesh configuration.
|
34
90
|
|
@@ -36,127 +92,282 @@ class FoamCaseManager:
|
|
36
92
|
p0 (tuple): The minimum corner of the cube (x0, y0, z0).
|
37
93
|
p1 (tuple): The maximum corner of the cube (x1, y1, z1).
|
38
94
|
cells (tuple): Number of cells in each direction (nx, ny, nz).
|
39
|
-
patch_names (
|
95
|
+
patch_names (Dict): A dictionary mapping face identifiers to custom names.
|
40
96
|
scale (float): The scaling factor for the mesh.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
bool: True if setup successful, False otherwise.
|
100
|
+
"""
|
101
|
+
return self.geometry.configure(p0=p0, p1=p1, cells=cells,
|
102
|
+
patch_names=patch_names, scale=scale)
|
103
|
+
|
104
|
+
def mark_geometry_ready(self, mesh_summary: Dict[str, Any] = None) -> bool:
|
105
|
+
"""
|
106
|
+
Mark the geometry as configured when using CAD-based or external mesh generation.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
mesh_summary (Dict): Optional summary of mesh information
|
110
|
+
|
111
|
+
Returns:
|
112
|
+
bool: True if successful, False otherwise.
|
41
113
|
"""
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
114
|
+
try:
|
115
|
+
# Mark geometry as configured
|
116
|
+
self.geometry.is_configured = True
|
117
|
+
|
118
|
+
# Store mesh summary if provided
|
119
|
+
if mesh_summary:
|
120
|
+
self.geometry.geometry_config = mesh_summary
|
121
|
+
|
122
|
+
return True
|
123
|
+
except Exception as e:
|
124
|
+
print(f"Error marking geometry as ready: {e}")
|
125
|
+
return False
|
49
126
|
|
50
|
-
def setup_control(self, control_params):
|
127
|
+
def setup_control(self, control_params: Dict[str, Any]) -> bool:
|
51
128
|
"""
|
52
129
|
Set up the control dictionary parameters.
|
53
130
|
|
54
131
|
Args:
|
55
|
-
control_params (
|
132
|
+
control_params (Dict): Dictionary containing control parameters.
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
bool: True if setup successful, False otherwise.
|
56
136
|
"""
|
57
|
-
self.
|
137
|
+
return self.control.configure(control_params=control_params)
|
58
138
|
|
59
|
-
def setup_turbulence(self, simulation_type, model_properties):
|
139
|
+
def setup_turbulence(self, simulation_type: str, model_properties: Dict[str, Any]) -> bool:
|
60
140
|
"""
|
61
141
|
Set up the turbulence model configuration.
|
62
142
|
|
63
143
|
Args:
|
64
144
|
simulation_type (str): The simulation type ('RAS', 'LES', 'laminar').
|
65
|
-
model_properties (
|
145
|
+
model_properties (Dict): Properties for the turbulence model.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
bool: True if setup successful, False otherwise.
|
66
149
|
"""
|
67
|
-
self.
|
68
|
-
|
69
|
-
'model_properties': model_properties
|
70
|
-
}
|
150
|
+
return self.turbulence.configure(simulation_type=simulation_type,
|
151
|
+
model_properties=model_properties)
|
71
152
|
|
72
|
-
def
|
153
|
+
def setup_dynamic_mesh(self, write_dynamic_mesh_dict: bool, mesh_type: str,
|
154
|
+
mesh_properties: Dict[str, Any]) -> bool:
|
73
155
|
"""
|
74
|
-
|
156
|
+
Set up the dynamic mesh configuration.
|
75
157
|
|
158
|
+
Args:
|
159
|
+
write_dynamic_mesh_dict (bool): Whether to write dynamicMeshDict.
|
160
|
+
mesh_type (str): The type of dynamic mesh ('solidBodyMotion', 'multiBodyOverset', etc.).
|
161
|
+
mesh_properties (Dict): Properties for the dynamic mesh configuration.
|
162
|
+
|
76
163
|
Returns:
|
77
|
-
bool: True if successful, False otherwise.
|
164
|
+
bool: True if setup successful, False otherwise.
|
78
165
|
"""
|
79
|
-
|
80
|
-
|
81
|
-
|
166
|
+
return self.dynamic_mesh.configure(write_dynamic_mesh_dict=write_dynamic_mesh_dict,
|
167
|
+
mesh_type=mesh_type, mesh_properties=mesh_properties)
|
168
|
+
|
169
|
+
def setup_hfdibdem(self, write_hfdibdem_dict: bool,
|
170
|
+
hfdibdem_properties: Dict[str, Any]) -> bool:
|
171
|
+
"""
|
172
|
+
Set up the HFDIBDEM configuration.
|
82
173
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
p1=self.geometry_config['p1'],
|
87
|
-
cells=self.geometry_config['cells'],
|
88
|
-
patch_names=self.geometry_config['patch_names'],
|
89
|
-
scale=self.geometry_config.get('scale', 1.0)
|
90
|
-
)
|
91
|
-
|
92
|
-
bmd_path = os.path.join(self.system_dir, "blockMeshDict")
|
93
|
-
developer.create_blockmesh_dict(file_path=bmd_path)
|
94
|
-
return True
|
174
|
+
Args:
|
175
|
+
write_hfdibdem_dict (bool): Whether to write HFDIBDEMDict.
|
176
|
+
hfdibdem_properties (Dict): Properties for the HFDIBDEM configuration.
|
95
177
|
|
96
|
-
|
97
|
-
|
98
|
-
|
178
|
+
Returns:
|
179
|
+
bool: True if setup successful, False otherwise.
|
180
|
+
"""
|
181
|
+
return self.hfdibdem.configure(write_hfdibdem_dict=write_hfdibdem_dict,
|
182
|
+
hfdibdem_properties=hfdibdem_properties)
|
99
183
|
|
100
|
-
def
|
184
|
+
def validate_all_components(self) -> bool:
|
101
185
|
"""
|
102
|
-
|
186
|
+
Validate all configured components.
|
103
187
|
|
104
188
|
Returns:
|
105
|
-
bool: True if
|
189
|
+
bool: True if all required components are valid, False otherwise.
|
106
190
|
"""
|
107
|
-
|
108
|
-
print("Error: Control configuration not set. Call setup_control() first.")
|
109
|
-
return False
|
191
|
+
all_valid = True
|
110
192
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
print("
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
except Exception as e:
|
123
|
-
print(f"Error creating controlDict: {e}")
|
124
|
-
return False
|
193
|
+
for component in self.components:
|
194
|
+
if component.is_required and component.is_configured:
|
195
|
+
if not component.validate():
|
196
|
+
print(f"Validation failed for {component.name}")
|
197
|
+
all_valid = False
|
198
|
+
elif component.is_required and not component.is_configured:
|
199
|
+
print(f"Required component {component.name} is not configured")
|
200
|
+
all_valid = False
|
201
|
+
|
202
|
+
return all_valid
|
125
203
|
|
126
|
-
def
|
204
|
+
def get_component_status(self) -> Dict[str, Dict[str, Any]]:
|
127
205
|
"""
|
128
|
-
|
206
|
+
Get the status of all components.
|
129
207
|
|
130
208
|
Returns:
|
131
|
-
|
209
|
+
Dict containing status information for each component.
|
132
210
|
"""
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
if
|
147
|
-
print("
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
211
|
+
status = {}
|
212
|
+
for component in self.components:
|
213
|
+
status[component.name] = component.get_status()
|
214
|
+
return status
|
215
|
+
|
216
|
+
def print_component_status(self):
|
217
|
+
"""Print the status of all components."""
|
218
|
+
print(f"\n=== Component Status for '{self.case_name}' ===")
|
219
|
+
for component in self.components:
|
220
|
+
status = component.get_status()
|
221
|
+
status_icon = "✓" if status['is_valid'] else "✗" if status['is_configured'] else "-"
|
222
|
+
required_icon = "!" if status['is_required'] else ""
|
223
|
+
print(f"{status_icon}{required_icon} {component.name}: {component.description}")
|
224
|
+
if component.is_configured:
|
225
|
+
print(f" Configured: {status['is_configured']}, Valid: {status['is_valid']}")
|
226
|
+
else:
|
227
|
+
print(f" Configured: {status['is_configured']}")
|
228
|
+
print("=" * 50)
|
229
|
+
|
230
|
+
def setup_transport_properties(self, write_transport_properties: bool, transport_model: str,
|
231
|
+
model_properties: Dict[str, Any], thermal_properties: Dict[str, Any] = None,
|
232
|
+
species_properties: Dict[str, Any] = None, advanced_properties: Dict[str, Any] = None) -> bool:
|
233
|
+
"""Set up transport properties configuration."""
|
234
|
+
return self.transport_properties.configure(
|
235
|
+
write_transport_properties=write_transport_properties,
|
236
|
+
transport_model=transport_model,
|
237
|
+
model_properties=model_properties,
|
238
|
+
thermal_properties=thermal_properties,
|
239
|
+
species_properties=species_properties,
|
240
|
+
advanced_properties=advanced_properties
|
241
|
+
)
|
158
242
|
|
159
|
-
def
|
243
|
+
def setup_fv_schemes(self, write_fv_schemes: bool, ddt_schemes: Dict[str, Any],
|
244
|
+
grad_schemes: Dict[str, Any], div_schemes: Dict[str, Any],
|
245
|
+
laplacian_schemes: Dict[str, Any], interpolation_schemes: Dict[str, Any],
|
246
|
+
sn_grad_schemes: Dict[str, Any], flux_required: Dict[str, Any] = None) -> bool:
|
247
|
+
"""Set up finite volume schemes configuration."""
|
248
|
+
return self.fv_schemes.configure(
|
249
|
+
write_fv_schemes=write_fv_schemes,
|
250
|
+
ddt_schemes=ddt_schemes,
|
251
|
+
grad_schemes=grad_schemes,
|
252
|
+
div_schemes=div_schemes,
|
253
|
+
laplacian_schemes=laplacian_schemes,
|
254
|
+
interpolation_schemes=interpolation_schemes,
|
255
|
+
sn_grad_schemes=sn_grad_schemes,
|
256
|
+
flux_required=flux_required
|
257
|
+
)
|
258
|
+
|
259
|
+
def setup_fv_options(self, write_fv_options: bool, momentum_sources: Dict[str, Any] = None,
|
260
|
+
thermal_sources: Dict[str, Any] = None, species_sources: Dict[str, Any] = None,
|
261
|
+
turbulence_sources: Dict[str, Any] = None, pressure_sources: Dict[str, Any] = None,
|
262
|
+
volume_fraction_sources: Dict[str, Any] = None, advanced_sources: Dict[str, Any] = None) -> bool:
|
263
|
+
"""Set up finite volume options configuration."""
|
264
|
+
return self.fv_options.configure(
|
265
|
+
write_fv_options=write_fv_options,
|
266
|
+
momentum_sources=momentum_sources,
|
267
|
+
thermal_sources=thermal_sources,
|
268
|
+
species_sources=species_sources,
|
269
|
+
turbulence_sources=turbulence_sources,
|
270
|
+
pressure_sources=pressure_sources,
|
271
|
+
volume_fraction_sources=volume_fraction_sources,
|
272
|
+
advanced_sources=advanced_sources
|
273
|
+
)
|
274
|
+
|
275
|
+
def setup_gravity_field(self, write_gravity_field: bool, gravity_value: tuple,
|
276
|
+
dimensions: list = None) -> bool:
|
277
|
+
"""Set up gravity field configuration."""
|
278
|
+
return self.gravity_field.configure(
|
279
|
+
write_gravity_field=write_gravity_field,
|
280
|
+
gravity_value=gravity_value,
|
281
|
+
dimensions=dimensions
|
282
|
+
)
|
283
|
+
|
284
|
+
def setup_set_fields(self, write_set_fields_dict: bool, default_field_values: Dict[str, Any] = None,
|
285
|
+
regions: Dict[str, Any] = None) -> bool:
|
286
|
+
"""Set up setFields configuration."""
|
287
|
+
return self.set_fields.configure(
|
288
|
+
write_set_fields_dict=write_set_fields_dict,
|
289
|
+
default_field_values=default_field_values,
|
290
|
+
regions=regions
|
291
|
+
)
|
292
|
+
|
293
|
+
def setup_decompose_par(self, write_decompose_par_dict: bool, number_of_subdomains: int,
|
294
|
+
method: str, coeffs: Dict[str, Any] = None, options: Dict[str, Any] = None,
|
295
|
+
fields: list = None, preserve_patches: list = None, preserve_cell_zones: list = None,
|
296
|
+
preserve_face_zones: list = None, preserve_point_zones: list = None) -> bool:
|
297
|
+
"""Set up decomposePar configuration."""
|
298
|
+
return self.decompose_par.configure(
|
299
|
+
write_decompose_par_dict=write_decompose_par_dict,
|
300
|
+
number_of_subdomains=number_of_subdomains,
|
301
|
+
method=method,
|
302
|
+
coeffs=coeffs,
|
303
|
+
options=options,
|
304
|
+
fields=fields,
|
305
|
+
preserve_patches=preserve_patches,
|
306
|
+
preserve_cell_zones=preserve_cell_zones,
|
307
|
+
preserve_face_zones=preserve_face_zones,
|
308
|
+
preserve_point_zones=preserve_point_zones
|
309
|
+
)
|
310
|
+
|
311
|
+
def setup_snappy_hex_mesh(self, write_snappy_hex_mesh_dict: bool, geometry: Dict[str, Any],
|
312
|
+
castellated_mesh_controls: Dict[str, Any], snap_controls: Dict[str, Any],
|
313
|
+
add_layers_controls: Dict[str, Any] = None, mesh_quality_controls: Dict[str, Any] = None,
|
314
|
+
merged_patches: list = None, write_flags: Dict[str, Any] = None) -> bool:
|
315
|
+
"""Set up snappyHexMesh configuration."""
|
316
|
+
return self.snappy_hex_mesh.configure(
|
317
|
+
write_snappy_hex_mesh_dict=write_snappy_hex_mesh_dict,
|
318
|
+
geometry=geometry,
|
319
|
+
castellated_mesh_controls=castellated_mesh_controls,
|
320
|
+
snap_controls=snap_controls,
|
321
|
+
add_layers_controls=add_layers_controls,
|
322
|
+
mesh_quality_controls=mesh_quality_controls,
|
323
|
+
merged_patches=merged_patches,
|
324
|
+
write_flags=write_flags
|
325
|
+
)
|
326
|
+
|
327
|
+
def setup_p_field(self, write_p_field: bool, internal_pressure: float,
|
328
|
+
boundary_conditions: Dict[str, Any], ref_pressure_cell: int = 0,
|
329
|
+
ref_pressure_value: float = 0.0, pressure_dimensions: list = None) -> bool:
|
330
|
+
"""Set up pressure field configuration."""
|
331
|
+
return self.p_field.configure(
|
332
|
+
write_p_field=write_p_field,
|
333
|
+
internal_pressure=internal_pressure,
|
334
|
+
boundary_conditions=boundary_conditions,
|
335
|
+
ref_pressure_cell=ref_pressure_cell,
|
336
|
+
ref_pressure_value=ref_pressure_value,
|
337
|
+
pressure_dimensions=pressure_dimensions
|
338
|
+
)
|
339
|
+
|
340
|
+
def setup_u_field(self, write_u_field: bool, internal_velocity: tuple,
|
341
|
+
boundary_conditions: Dict[str, Any], velocity_dimensions: list = None) -> bool:
|
342
|
+
"""Set up velocity field configuration."""
|
343
|
+
return self.u_field.configure(
|
344
|
+
write_u_field=write_u_field,
|
345
|
+
internal_velocity=internal_velocity,
|
346
|
+
boundary_conditions=boundary_conditions,
|
347
|
+
velocity_dimensions=velocity_dimensions
|
348
|
+
)
|
349
|
+
|
350
|
+
def setup_f_field(self, write_f_field: bool, internal_force: tuple,
|
351
|
+
boundary_conditions: Dict[str, Any], force_dimensions: list = None) -> bool:
|
352
|
+
"""Set up force field configuration."""
|
353
|
+
return self.f_field.configure(
|
354
|
+
write_f_field=write_f_field,
|
355
|
+
internal_force=internal_force,
|
356
|
+
boundary_conditions=boundary_conditions,
|
357
|
+
force_dimensions=force_dimensions
|
358
|
+
)
|
359
|
+
|
360
|
+
def setup_lambda_field(self, write_lambda_field: bool, internal_lambda: float,
|
361
|
+
boundary_conditions: Dict[str, Any], lambda_dimensions: list = None) -> bool:
|
362
|
+
"""Set up lambda field configuration."""
|
363
|
+
return self.lambda_field.configure(
|
364
|
+
write_lambda_field=write_lambda_field,
|
365
|
+
internal_lambda=internal_lambda,
|
366
|
+
boundary_conditions=boundary_conditions,
|
367
|
+
lambda_dimensions=lambda_dimensions
|
368
|
+
)
|
369
|
+
|
370
|
+
def create_full_case(self) -> bool:
|
160
371
|
"""
|
161
372
|
Create a complete OpenFOAM case with all configuration files.
|
162
373
|
|
@@ -165,31 +376,79 @@ class FoamCaseManager:
|
|
165
376
|
"""
|
166
377
|
print(f"--- Starting full OpenFOAM case setup for '{self.case_name}' ---")
|
167
378
|
|
168
|
-
|
379
|
+
# Validate all components first
|
380
|
+
if not self.validate_all_components():
|
381
|
+
print("Component validation failed. Cannot proceed with case creation.")
|
382
|
+
self.print_component_status()
|
383
|
+
return False
|
169
384
|
|
170
|
-
|
171
|
-
print("\n[Step 1/3] Creating blockMeshDict...")
|
172
|
-
if not self.create_blockmesh_dict():
|
173
|
-
success = False
|
385
|
+
print("\nAll components validated successfully. Proceeding with case creation...")
|
174
386
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
success = False
|
387
|
+
success = True
|
388
|
+
step = 1
|
389
|
+
total_steps = len([c for c in self.components if c.is_configured])
|
179
390
|
|
180
|
-
#
|
181
|
-
|
182
|
-
|
183
|
-
|
391
|
+
# Build each configured component
|
392
|
+
for component in self.components:
|
393
|
+
if component.is_configured:
|
394
|
+
print(f"\n[Step {step}/{total_steps}] Creating {component.name}...")
|
395
|
+
if not component.build(self.case_name):
|
396
|
+
print(f"Failed to build {component.name}")
|
397
|
+
success = False
|
398
|
+
step += 1
|
184
399
|
|
185
400
|
if success:
|
186
401
|
print(f"\n--- Case setup complete! ---")
|
187
|
-
print(f"Files written in '{self.case_name}'")
|
188
|
-
|
189
|
-
|
190
|
-
|
402
|
+
print(f"Files written in '{self.case_name}':")
|
403
|
+
|
404
|
+
# List all created files
|
405
|
+
created_files = []
|
406
|
+
|
407
|
+
# System files
|
408
|
+
if self.geometry.is_configured:
|
409
|
+
created_files.append(os.path.join(self.case_name, 'system', 'blockMeshDict'))
|
410
|
+
if self.control.is_configured:
|
411
|
+
created_files.append(os.path.join(self.case_name, 'system', 'controlDict'))
|
412
|
+
|
413
|
+
# Constant files
|
414
|
+
if self.turbulence.is_configured:
|
415
|
+
created_files.append(os.path.join(self.case_name, 'constant', 'turbulenceProperties'))
|
416
|
+
if self.dynamic_mesh.is_configured and self.dynamic_mesh.write_dynamic_mesh_dict:
|
417
|
+
created_files.append(os.path.join(self.case_name, 'constant', 'dynamicMeshDict'))
|
418
|
+
if self.hfdibdem.is_configured and self.hfdibdem.write_hfdibdem_dict:
|
419
|
+
created_files.append(os.path.join(self.case_name, 'constant', 'HFDIBDEMDict'))
|
420
|
+
if self.transport_properties.is_configured and self.transport_properties.write_transport_properties:
|
421
|
+
created_files.append(os.path.join(self.case_name, 'constant', 'transportProperties'))
|
422
|
+
if self.gravity_field.is_configured and self.gravity_field.write_gravity_field:
|
423
|
+
created_files.append(os.path.join(self.case_name, 'constant', 'g'))
|
424
|
+
|
425
|
+
# Additional system files
|
426
|
+
if self.fv_schemes.is_configured and self.fv_schemes.write_fv_schemes:
|
427
|
+
created_files.append(os.path.join(self.case_name, 'system', 'fvSchemes'))
|
428
|
+
if self.fv_options.is_configured and self.fv_options.write_fv_options:
|
429
|
+
created_files.append(os.path.join(self.case_name, 'system', 'fvOptions'))
|
430
|
+
if self.set_fields.is_configured and self.set_fields.write_set_fields_dict:
|
431
|
+
created_files.append(os.path.join(self.case_name, 'system', 'setFieldsDict'))
|
432
|
+
if self.decompose_par.is_configured and self.decompose_par.write_decompose_par_dict:
|
433
|
+
created_files.append(os.path.join(self.case_name, 'system', 'decomposeParDict'))
|
434
|
+
if self.snappy_hex_mesh.is_configured and self.snappy_hex_mesh.write_snappy_hex_mesh_dict:
|
435
|
+
created_files.append(os.path.join(self.case_name, 'system', 'snappyHexMeshDict'))
|
436
|
+
|
437
|
+
# Zero directory files
|
438
|
+
if self.p_field.is_configured and self.p_field.write_p_field:
|
439
|
+
created_files.append(os.path.join(self.case_name, '0', 'p'))
|
440
|
+
if self.u_field.is_configured and self.u_field.write_u_field:
|
441
|
+
created_files.append(os.path.join(self.case_name, '0', 'U'))
|
442
|
+
if self.f_field.is_configured and self.f_field.write_f_field:
|
443
|
+
created_files.append(os.path.join(self.case_name, '0', 'f'))
|
444
|
+
if self.lambda_field.is_configured and self.lambda_field.write_lambda_field:
|
445
|
+
created_files.append(os.path.join(self.case_name, '0', 'lambda'))
|
446
|
+
|
447
|
+
for file_path in created_files:
|
448
|
+
print(f" - {file_path}")
|
449
|
+
|
191
450
|
else:
|
192
451
|
print(f"\n--- Case setup failed! ---")
|
193
|
-
print("Some
|
452
|
+
print("Some components could not be built. Check error messages above.")
|
194
453
|
|
195
454
|
return success
|