pycphy 0.1.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 +24 -0
- pycphy/foamCaseDeveloper/__init__.py +41 -0
- pycphy/foamCaseDeveloper/config/__init__.py +26 -0
- pycphy/foamCaseDeveloper/config/block_mesh_config.py +90 -0
- pycphy/foamCaseDeveloper/config/control_config.py +168 -0
- pycphy/foamCaseDeveloper/config/global_config.py +83 -0
- pycphy/foamCaseDeveloper/config/turbulence_config.py +187 -0
- pycphy/foamCaseDeveloper/core/__init__.py +18 -0
- pycphy/foamCaseDeveloper/core/block_mesh_developer.py +101 -0
- pycphy/foamCaseDeveloper/core/control_dict_writer.py +55 -0
- pycphy/foamCaseDeveloper/core/foam_case_manager.py +195 -0
- pycphy/foamCaseDeveloper/core/turbulence_properties_writer.py +68 -0
- pycphy/foamCaseDeveloper/main.py +260 -0
- pycphy/foamCaseDeveloper/writers/__init__.py +18 -0
- pycphy/foamCaseDeveloper/writers/block_mesh_writer.py +113 -0
- pycphy/foamCaseDeveloper/writers/control_dict_writer.py +54 -0
- pycphy/foamCaseDeveloper/writers/foam_writer.py +73 -0
- pycphy/foamCaseDeveloper/writers/turbulence_properties_writer.py +78 -0
- pycphy-0.1.0.dist-info/METADATA +335 -0
- pycphy-0.1.0.dist-info/RECORD +24 -0
- pycphy-0.1.0.dist-info/WHEEL +5 -0
- pycphy-0.1.0.dist-info/entry_points.txt +2 -0
- pycphy-0.1.0.dist-info/licenses/LICENSE +21 -0
- pycphy-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
# block_mesh_developer.py
|
2
|
+
|
3
|
+
from ..writers.block_mesh_writer import BlockMeshWriter
|
4
|
+
|
5
|
+
class BlockMeshDeveloper:
|
6
|
+
"""
|
7
|
+
A high-level class to generate data for simple geometries and write
|
8
|
+
a blockMeshDict file. It now accepts custom patch names.
|
9
|
+
"""
|
10
|
+
def __init__(self, p0, p1, cells, patch_names, scale=1.0):
|
11
|
+
"""
|
12
|
+
Initializes the developer for a simple cuboid.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
p0 (tuple): The minimum corner of the cube (x0, y0, z0).
|
16
|
+
p1 (tuple): The maximum corner of the cube (x1, y1, z1).
|
17
|
+
cells (tuple): Number of cells in each direction (nx, ny, nz).
|
18
|
+
patch_names (dict): A dictionary mapping face identifiers to custom names.
|
19
|
+
e.g., {'minX': 'inlet', 'maxX': 'outlet', ...}
|
20
|
+
scale (float): The scaling factor for the mesh.
|
21
|
+
"""
|
22
|
+
self.p0 = p0
|
23
|
+
self.p1 = p1
|
24
|
+
self.cells = cells
|
25
|
+
self.patch_names = patch_names
|
26
|
+
self.scale = scale
|
27
|
+
|
28
|
+
# Data structures for the writer
|
29
|
+
self.vertices = []
|
30
|
+
self.blocks = []
|
31
|
+
self.boundary = []
|
32
|
+
self.edges = [] # Empty for a simple cube
|
33
|
+
|
34
|
+
def _generate_data(self):
|
35
|
+
"""Generates the vertex, block, and boundary data for the cube."""
|
36
|
+
x0, y0, z0 = self.p0
|
37
|
+
x1, y1, z1 = self.p1
|
38
|
+
|
39
|
+
# 1. Generate Vertices (OpenFOAM ordering)
|
40
|
+
self.vertices = [
|
41
|
+
(x0, y0, z0), # 0
|
42
|
+
(x1, y0, z0), # 1
|
43
|
+
(x1, y1, z0), # 2
|
44
|
+
(x0, y1, z0), # 3
|
45
|
+
(x0, y0, z1), # 4
|
46
|
+
(x1, y0, z1), # 5
|
47
|
+
(x1, y1, z1), # 6
|
48
|
+
(x0, y1, z1) # 7
|
49
|
+
]
|
50
|
+
|
51
|
+
# 2. Generate Blocks (only one for a simple cube)
|
52
|
+
self.blocks = [
|
53
|
+
('hex', [0, 1, 2, 3, 4, 5, 6, 7], self.cells, 'simpleGrading', [1, 1, 1])
|
54
|
+
]
|
55
|
+
|
56
|
+
# 3. Generate Boundary Patches using custom names
|
57
|
+
self.boundary = [
|
58
|
+
{
|
59
|
+
'name': self.patch_names.get('minX', 'minX_default'), 'type': 'patch',
|
60
|
+
'faces': [[0, 4, 7, 3]]
|
61
|
+
},
|
62
|
+
{
|
63
|
+
'name': self.patch_names.get('maxX', 'maxX_default'), 'type': 'patch',
|
64
|
+
'faces': [[1, 2, 6, 5]]
|
65
|
+
},
|
66
|
+
{
|
67
|
+
'name': self.patch_names.get('minY', 'minY_default'), 'type': 'patch',
|
68
|
+
'faces': [[0, 1, 5, 4]]
|
69
|
+
},
|
70
|
+
{
|
71
|
+
'name': self.patch_names.get('maxY', 'maxY_default'), 'type': 'patch',
|
72
|
+
'faces': [[2, 3, 7, 6]]
|
73
|
+
},
|
74
|
+
{
|
75
|
+
'name': self.patch_names.get('minZ', 'minZ_default'), 'type': 'patch',
|
76
|
+
'faces': [[0, 3, 2, 1]]
|
77
|
+
},
|
78
|
+
{
|
79
|
+
'name': self.patch_names.get('maxZ', 'maxZ_default'), 'type': 'patch',
|
80
|
+
'faces': [[4, 5, 6, 7]]
|
81
|
+
}
|
82
|
+
]
|
83
|
+
|
84
|
+
def create_blockmesh_dict(self, file_path):
|
85
|
+
"""
|
86
|
+
Generates the geometry data and writes the blockMeshDict file.
|
87
|
+
|
88
|
+
Args:
|
89
|
+
file_path (str): The location to save the blockMeshDict file.
|
90
|
+
"""
|
91
|
+
self._generate_data()
|
92
|
+
|
93
|
+
writer = BlockMeshWriter(
|
94
|
+
file_path=file_path,
|
95
|
+
scale=1.0, # Scale is typically 1 when specifying absolute coords
|
96
|
+
vertices=self.vertices,
|
97
|
+
blocks=self.blocks,
|
98
|
+
edges=self.edges,
|
99
|
+
boundary=self.boundary
|
100
|
+
)
|
101
|
+
writer.write()
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# control_dict_writer.py
|
2
|
+
|
3
|
+
from ..writers.control_dict_writer import ControlDictWriter as BaseControlDictWriter
|
4
|
+
|
5
|
+
class ControlDictWriter(BaseControlDictWriter):
|
6
|
+
"""
|
7
|
+
Extended ControlDictWriter with additional functionality for case management.
|
8
|
+
"""
|
9
|
+
|
10
|
+
def __init__(self, file_path, params):
|
11
|
+
"""
|
12
|
+
Initializes the ControlDictWriter.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
file_path (str): The full path to the output file 'controlDict'.
|
16
|
+
params (dict): A dictionary containing the key-value pairs for the controlDict.
|
17
|
+
e.g., {'application': 'icoFoam', 'deltaT': 0.001}
|
18
|
+
"""
|
19
|
+
super().__init__(file_path, params)
|
20
|
+
|
21
|
+
def validate_params(self):
|
22
|
+
"""
|
23
|
+
Validates the control parameters for common issues.
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
bool: True if validation passes, False otherwise.
|
27
|
+
"""
|
28
|
+
required_params = ['application', 'startFrom', 'stopAt']
|
29
|
+
|
30
|
+
for param in required_params:
|
31
|
+
if param not in self.params:
|
32
|
+
print(f"Warning: Required parameter '{param}' is missing from control parameters.")
|
33
|
+
return False
|
34
|
+
|
35
|
+
# Validate application
|
36
|
+
valid_applications = [
|
37
|
+
'icoFoam', 'simpleFoam', 'pimpleFoam', 'interFoam',
|
38
|
+
'rhoSimpleFoam', 'rhoPimpleFoam', 'buoyantFoam'
|
39
|
+
]
|
40
|
+
|
41
|
+
if self.params.get('application') not in valid_applications:
|
42
|
+
print(f"Warning: Application '{self.params.get('application')}' may not be a valid OpenFOAM solver.")
|
43
|
+
|
44
|
+
# Validate time step
|
45
|
+
if 'deltaT' in self.params:
|
46
|
+
try:
|
47
|
+
delta_t = float(self.params['deltaT'])
|
48
|
+
if delta_t <= 0:
|
49
|
+
print("Warning: deltaT should be positive.")
|
50
|
+
return False
|
51
|
+
except (ValueError, TypeError):
|
52
|
+
print("Warning: deltaT should be a valid number.")
|
53
|
+
return False
|
54
|
+
|
55
|
+
return True
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# foam_case_manager.py
|
2
|
+
|
3
|
+
import os
|
4
|
+
from .block_mesh_developer import BlockMeshDeveloper
|
5
|
+
from .control_dict_writer import ControlDictWriter
|
6
|
+
from .turbulence_properties_writer import TurbulencePropertiesWriter
|
7
|
+
|
8
|
+
class FoamCaseManager:
|
9
|
+
"""
|
10
|
+
A comprehensive manager for creating and setting up OpenFOAM cases.
|
11
|
+
|
12
|
+
This class provides a high-level interface for creating complete OpenFOAM
|
13
|
+
case directories with all necessary configuration files.
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self, case_name):
|
17
|
+
"""
|
18
|
+
Initialize the FoamCaseManager.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
case_name (str): The name of the OpenFOAM case directory.
|
22
|
+
"""
|
23
|
+
self.case_name = case_name
|
24
|
+
self.system_dir = os.path.join(case_name, "system")
|
25
|
+
self.constant_dir = os.path.join(case_name, "constant")
|
26
|
+
|
27
|
+
# Ensure directories exist
|
28
|
+
os.makedirs(self.system_dir, exist_ok=True)
|
29
|
+
os.makedirs(self.constant_dir, exist_ok=True)
|
30
|
+
|
31
|
+
def setup_geometry(self, p0, p1, cells, patch_names, scale=1.0):
|
32
|
+
"""
|
33
|
+
Set up the geometry and mesh configuration.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
p0 (tuple): The minimum corner of the cube (x0, y0, z0).
|
37
|
+
p1 (tuple): The maximum corner of the cube (x1, y1, z1).
|
38
|
+
cells (tuple): Number of cells in each direction (nx, ny, nz).
|
39
|
+
patch_names (dict): A dictionary mapping face identifiers to custom names.
|
40
|
+
scale (float): The scaling factor for the mesh.
|
41
|
+
"""
|
42
|
+
self.geometry_config = {
|
43
|
+
'p0': p0,
|
44
|
+
'p1': p1,
|
45
|
+
'cells': cells,
|
46
|
+
'patch_names': patch_names,
|
47
|
+
'scale': scale
|
48
|
+
}
|
49
|
+
|
50
|
+
def setup_control(self, control_params):
|
51
|
+
"""
|
52
|
+
Set up the control dictionary parameters.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
control_params (dict): Dictionary containing control parameters.
|
56
|
+
"""
|
57
|
+
self.control_config = control_params
|
58
|
+
|
59
|
+
def setup_turbulence(self, simulation_type, model_properties):
|
60
|
+
"""
|
61
|
+
Set up the turbulence model configuration.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
simulation_type (str): The simulation type ('RAS', 'LES', 'laminar').
|
65
|
+
model_properties (dict): Properties for the turbulence model.
|
66
|
+
"""
|
67
|
+
self.turbulence_config = {
|
68
|
+
'simulation_type': simulation_type,
|
69
|
+
'model_properties': model_properties
|
70
|
+
}
|
71
|
+
|
72
|
+
def create_blockmesh_dict(self):
|
73
|
+
"""
|
74
|
+
Create the blockMeshDict file.
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
bool: True if successful, False otherwise.
|
78
|
+
"""
|
79
|
+
if not hasattr(self, 'geometry_config'):
|
80
|
+
print("Error: Geometry configuration not set. Call setup_geometry() first.")
|
81
|
+
return False
|
82
|
+
|
83
|
+
try:
|
84
|
+
developer = BlockMeshDeveloper(
|
85
|
+
p0=self.geometry_config['p0'],
|
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
|
95
|
+
|
96
|
+
except Exception as e:
|
97
|
+
print(f"Error creating blockMeshDict: {e}")
|
98
|
+
return False
|
99
|
+
|
100
|
+
def create_control_dict(self):
|
101
|
+
"""
|
102
|
+
Create the controlDict file.
|
103
|
+
|
104
|
+
Returns:
|
105
|
+
bool: True if successful, False otherwise.
|
106
|
+
"""
|
107
|
+
if not hasattr(self, 'control_config'):
|
108
|
+
print("Error: Control configuration not set. Call setup_control() first.")
|
109
|
+
return False
|
110
|
+
|
111
|
+
try:
|
112
|
+
cd_path = os.path.join(self.system_dir, "controlDict")
|
113
|
+
control_dict = ControlDictWriter(file_path=cd_path, params=self.control_config)
|
114
|
+
|
115
|
+
# Validate parameters before writing
|
116
|
+
if not control_dict.validate_params():
|
117
|
+
print("Warning: Control parameters validation failed, but proceeding anyway.")
|
118
|
+
|
119
|
+
control_dict.write()
|
120
|
+
return True
|
121
|
+
|
122
|
+
except Exception as e:
|
123
|
+
print(f"Error creating controlDict: {e}")
|
124
|
+
return False
|
125
|
+
|
126
|
+
def create_turbulence_properties(self):
|
127
|
+
"""
|
128
|
+
Create the turbulenceProperties file.
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
bool: True if successful, False otherwise.
|
132
|
+
"""
|
133
|
+
if not hasattr(self, 'turbulence_config'):
|
134
|
+
print("Error: Turbulence configuration not set. Call setup_turbulence() first.")
|
135
|
+
return False
|
136
|
+
|
137
|
+
try:
|
138
|
+
tp_path = os.path.join(self.constant_dir, "turbulenceProperties")
|
139
|
+
turbulence_writer = TurbulencePropertiesWriter(
|
140
|
+
file_path=tp_path,
|
141
|
+
simulation_type=self.turbulence_config['simulation_type'],
|
142
|
+
model_properties=self.turbulence_config['model_properties']
|
143
|
+
)
|
144
|
+
|
145
|
+
# Validate configuration before writing
|
146
|
+
if not turbulence_writer.validate_simulation_type():
|
147
|
+
print("Warning: Simulation type validation failed, but proceeding anyway.")
|
148
|
+
|
149
|
+
if not turbulence_writer.validate_model_properties():
|
150
|
+
print("Warning: Model properties validation failed, but proceeding anyway.")
|
151
|
+
|
152
|
+
turbulence_writer.write()
|
153
|
+
return True
|
154
|
+
|
155
|
+
except Exception as e:
|
156
|
+
print(f"Error creating turbulenceProperties: {e}")
|
157
|
+
return False
|
158
|
+
|
159
|
+
def create_full_case(self):
|
160
|
+
"""
|
161
|
+
Create a complete OpenFOAM case with all configuration files.
|
162
|
+
|
163
|
+
Returns:
|
164
|
+
bool: True if all files created successfully, False otherwise.
|
165
|
+
"""
|
166
|
+
print(f"--- Starting full OpenFOAM case setup for '{self.case_name}' ---")
|
167
|
+
|
168
|
+
success = True
|
169
|
+
|
170
|
+
# Create blockMeshDict
|
171
|
+
print("\n[Step 1/3] Creating blockMeshDict...")
|
172
|
+
if not self.create_blockmesh_dict():
|
173
|
+
success = False
|
174
|
+
|
175
|
+
# Create controlDict
|
176
|
+
print("\n[Step 2/3] Creating controlDict...")
|
177
|
+
if not self.create_control_dict():
|
178
|
+
success = False
|
179
|
+
|
180
|
+
# Create turbulenceProperties
|
181
|
+
print("\n[Step 3/3] Creating turbulenceProperties...")
|
182
|
+
if not self.create_turbulence_properties():
|
183
|
+
success = False
|
184
|
+
|
185
|
+
if success:
|
186
|
+
print(f"\n--- Case setup complete! ---")
|
187
|
+
print(f"Files written in '{self.case_name}'")
|
188
|
+
print(f" - {os.path.join(self.case_name, 'system', 'blockMeshDict')}")
|
189
|
+
print(f" - {os.path.join(self.case_name, 'system', 'controlDict')}")
|
190
|
+
print(f" - {os.path.join(self.case_name, 'constant', 'turbulenceProperties')}")
|
191
|
+
else:
|
192
|
+
print(f"\n--- Case setup failed! ---")
|
193
|
+
print("Some files could not be created. Check error messages above.")
|
194
|
+
|
195
|
+
return success
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# turbulence_properties_writer.py
|
2
|
+
|
3
|
+
from ..writers.turbulence_properties_writer import TurbulencePropertiesWriter as BaseTurbulencePropertiesWriter
|
4
|
+
|
5
|
+
class TurbulencePropertiesWriter(BaseTurbulencePropertiesWriter):
|
6
|
+
"""
|
7
|
+
Extended TurbulencePropertiesWriter with additional functionality for case management.
|
8
|
+
"""
|
9
|
+
|
10
|
+
def __init__(self, file_path, simulation_type, model_properties):
|
11
|
+
"""
|
12
|
+
Initializes the TurbulencePropertiesWriter.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
file_path (str): The full path to the output file 'turbulenceProperties'.
|
16
|
+
simulation_type (str): The top-level simulation type (e.g., 'RAS', 'LES', 'laminar').
|
17
|
+
model_properties (dict): A dictionary containing the properties for the chosen model.
|
18
|
+
This dictionary can be nested.
|
19
|
+
"""
|
20
|
+
super().__init__(file_path, simulation_type, model_properties)
|
21
|
+
|
22
|
+
def validate_simulation_type(self):
|
23
|
+
"""
|
24
|
+
Validates the simulation type.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
bool: True if validation passes, False otherwise.
|
28
|
+
"""
|
29
|
+
valid_types = ['RAS', 'LES', 'laminar']
|
30
|
+
|
31
|
+
if self.simulation_type not in valid_types:
|
32
|
+
print(f"Warning: Invalid simulation type '{self.simulation_type}'. Valid types: {valid_types}")
|
33
|
+
return False
|
34
|
+
|
35
|
+
return True
|
36
|
+
|
37
|
+
def validate_model_properties(self):
|
38
|
+
"""
|
39
|
+
Validates the model properties based on simulation type.
|
40
|
+
|
41
|
+
Returns:
|
42
|
+
bool: True if validation passes, False otherwise.
|
43
|
+
"""
|
44
|
+
if self.simulation_type == 'RAS':
|
45
|
+
required_keys = ['RASModel', 'turbulence']
|
46
|
+
for key in required_keys:
|
47
|
+
if key not in self.model_properties:
|
48
|
+
print(f"Warning: Required RAS parameter '{key}' is missing.")
|
49
|
+
return False
|
50
|
+
|
51
|
+
# Validate RAS model
|
52
|
+
valid_ras_models = ['kEpsilon', 'realizableKE', 'kOmegaSST', 'SpalartAllmaras']
|
53
|
+
if self.model_properties.get('RASModel') not in valid_ras_models:
|
54
|
+
print(f"Warning: Unknown RAS model '{self.model_properties.get('RASModel')}'.")
|
55
|
+
|
56
|
+
elif self.simulation_type == 'LES':
|
57
|
+
required_keys = ['LESModel', 'turbulence']
|
58
|
+
for key in required_keys:
|
59
|
+
if key not in self.model_properties:
|
60
|
+
print(f"Warning: Required LES parameter '{key}' is missing.")
|
61
|
+
return False
|
62
|
+
|
63
|
+
# Validate LES model
|
64
|
+
valid_les_models = ['Smagorinsky', 'kEqn', 'WALE', 'dynamicKEqn']
|
65
|
+
if self.model_properties.get('LESModel') not in valid_les_models:
|
66
|
+
print(f"Warning: Unknown LES model '{self.model_properties.get('LESModel')}'.")
|
67
|
+
|
68
|
+
return True
|
@@ -0,0 +1,260 @@
|
|
1
|
+
# main.py
|
2
|
+
|
3
|
+
"""
|
4
|
+
Main entry point for the foamCaseDeveloper module.
|
5
|
+
|
6
|
+
This script provides a command-line interface for creating OpenFOAM cases
|
7
|
+
using the foamCaseDeveloper tools.
|
8
|
+
"""
|
9
|
+
|
10
|
+
import argparse
|
11
|
+
import sys
|
12
|
+
import os
|
13
|
+
|
14
|
+
from .core import FoamCaseManager
|
15
|
+
from .config import global_config, block_mesh_config, control_config, turbulence_config
|
16
|
+
|
17
|
+
def create_example_case():
|
18
|
+
"""
|
19
|
+
Create an example OpenFOAM case with default settings from config files.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
bool: True if successful, False otherwise.
|
23
|
+
"""
|
24
|
+
print("Creating example OpenFOAM case from config files...")
|
25
|
+
|
26
|
+
# Initialize case manager with global config
|
27
|
+
case_manager = FoamCaseManager(global_config.case_name)
|
28
|
+
|
29
|
+
# Set up geometry from config file
|
30
|
+
case_manager.setup_geometry(
|
31
|
+
p0=block_mesh_config.p0,
|
32
|
+
p1=block_mesh_config.p1,
|
33
|
+
cells=block_mesh_config.cells,
|
34
|
+
patch_names=block_mesh_config.patch_names,
|
35
|
+
scale=block_mesh_config.scale
|
36
|
+
)
|
37
|
+
|
38
|
+
# Set up control from config file
|
39
|
+
case_manager.setup_control(control_config.control_params)
|
40
|
+
|
41
|
+
# Set up turbulence from config file
|
42
|
+
sim_type = turbulence_config.SIMULATION_TYPE
|
43
|
+
if sim_type == "RAS":
|
44
|
+
model_props = turbulence_config.RAS_PROPERTIES
|
45
|
+
elif sim_type == "LES":
|
46
|
+
model_props = turbulence_config.LES_PROPERTIES
|
47
|
+
elif sim_type == "laminar":
|
48
|
+
model_props = turbulence_config.LAMINAR_PROPERTIES
|
49
|
+
else:
|
50
|
+
print(f"Warning: Unknown simulation type '{sim_type}'. Using laminar.")
|
51
|
+
sim_type = "laminar"
|
52
|
+
model_props = {}
|
53
|
+
|
54
|
+
case_manager.setup_turbulence(
|
55
|
+
simulation_type=sim_type,
|
56
|
+
model_properties=model_props
|
57
|
+
)
|
58
|
+
|
59
|
+
# Create the complete case
|
60
|
+
return case_manager.create_full_case()
|
61
|
+
|
62
|
+
def create_custom_case(case_name, geometry_file=None, control_file=None, turbulence_file=None):
|
63
|
+
"""
|
64
|
+
Create a custom OpenFOAM case from configuration files.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
case_name (str): Name of the case directory.
|
68
|
+
geometry_file (str): Path to geometry configuration file.
|
69
|
+
control_file (str): Path to control configuration file.
|
70
|
+
turbulence_file (str): Path to turbulence configuration file.
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
bool: True if successful, False otherwise.
|
74
|
+
"""
|
75
|
+
print(f"Creating custom OpenFOAM case '{case_name}'...")
|
76
|
+
|
77
|
+
# Initialize case manager
|
78
|
+
case_manager = FoamCaseManager(case_name)
|
79
|
+
|
80
|
+
# Load geometry configuration
|
81
|
+
if geometry_file and os.path.exists(geometry_file):
|
82
|
+
try:
|
83
|
+
# Import the geometry configuration
|
84
|
+
import importlib.util
|
85
|
+
spec = importlib.util.spec_from_file_location("geometry_config", geometry_file)
|
86
|
+
geometry_module = importlib.util.module_from_spec(spec)
|
87
|
+
spec.loader.exec_module(geometry_module)
|
88
|
+
|
89
|
+
geometry_config = BlockMeshConfig(
|
90
|
+
p0=geometry_module.p0,
|
91
|
+
p1=geometry_module.p1,
|
92
|
+
cells=geometry_module.cells,
|
93
|
+
patch_names=geometry_module.patch_names,
|
94
|
+
scale=getattr(geometry_module, 'scale', 1.0)
|
95
|
+
)
|
96
|
+
|
97
|
+
case_manager.setup_geometry(
|
98
|
+
p0=geometry_config.p0,
|
99
|
+
p1=geometry_config.p1,
|
100
|
+
cells=geometry_config.cells,
|
101
|
+
patch_names=geometry_config.patch_names,
|
102
|
+
scale=geometry_config.scale
|
103
|
+
)
|
104
|
+
|
105
|
+
except Exception as e:
|
106
|
+
print(f"Error loading geometry configuration: {e}")
|
107
|
+
return False
|
108
|
+
else:
|
109
|
+
print("No geometry configuration file provided, using defaults.")
|
110
|
+
geometry_config = BlockMeshConfig()
|
111
|
+
case_manager.setup_geometry(
|
112
|
+
p0=geometry_config.p0,
|
113
|
+
p1=geometry_config.p1,
|
114
|
+
cells=geometry_config.cells,
|
115
|
+
patch_names=geometry_config.patch_names,
|
116
|
+
scale=geometry_config.scale
|
117
|
+
)
|
118
|
+
|
119
|
+
# Load control configuration
|
120
|
+
if control_file and os.path.exists(control_file):
|
121
|
+
try:
|
122
|
+
# Import the control configuration
|
123
|
+
import importlib.util
|
124
|
+
spec = importlib.util.spec_from_file_location("control_config", control_file)
|
125
|
+
control_module = importlib.util.module_from_spec(spec)
|
126
|
+
spec.loader.exec_module(control_module)
|
127
|
+
|
128
|
+
case_manager.setup_control(control_module.control_params)
|
129
|
+
|
130
|
+
except Exception as e:
|
131
|
+
print(f"Error loading control configuration: {e}")
|
132
|
+
return False
|
133
|
+
else:
|
134
|
+
print("No control configuration file provided, using defaults.")
|
135
|
+
control_config = ControlConfig()
|
136
|
+
case_manager.setup_control(control_config.get_parameters())
|
137
|
+
|
138
|
+
# Load turbulence configuration
|
139
|
+
if turbulence_file and os.path.exists(turbulence_file):
|
140
|
+
try:
|
141
|
+
# Import the turbulence configuration
|
142
|
+
import importlib.util
|
143
|
+
spec = importlib.util.spec_from_file_location("turbulence_config", turbulence_file)
|
144
|
+
turbulence_module = importlib.util.module_from_spec(spec)
|
145
|
+
spec.loader.exec_module(turbulence_module)
|
146
|
+
|
147
|
+
sim_type = turbulence_module.SIMULATION_TYPE
|
148
|
+
if sim_type == "RAS":
|
149
|
+
model_props = turbulence_module.RAS_PROPERTIES
|
150
|
+
elif sim_type == "LES":
|
151
|
+
model_props = turbulence_module.LES_PROPERTIES
|
152
|
+
elif sim_type == "laminar":
|
153
|
+
model_props = turbulence_module.LAMINAR_PROPERTIES
|
154
|
+
else:
|
155
|
+
print(f"Warning: Unknown simulation type '{sim_type}'. Using laminar.")
|
156
|
+
sim_type = "laminar"
|
157
|
+
model_props = {}
|
158
|
+
|
159
|
+
case_manager.setup_turbulence(
|
160
|
+
simulation_type=sim_type,
|
161
|
+
model_properties=model_props
|
162
|
+
)
|
163
|
+
|
164
|
+
except Exception as e:
|
165
|
+
print(f"Error loading turbulence configuration: {e}")
|
166
|
+
return False
|
167
|
+
else:
|
168
|
+
print("No turbulence configuration file provided, using defaults.")
|
169
|
+
turbulence_config = TurbulenceConfig()
|
170
|
+
case_manager.setup_turbulence(
|
171
|
+
simulation_type=turbulence_config.get_simulation_type(),
|
172
|
+
model_properties=turbulence_config.get_model_properties()
|
173
|
+
)
|
174
|
+
|
175
|
+
# Create the complete case
|
176
|
+
return case_manager.create_full_case()
|
177
|
+
|
178
|
+
def main():
|
179
|
+
"""
|
180
|
+
Main entry point for the command-line interface.
|
181
|
+
"""
|
182
|
+
parser = argparse.ArgumentParser(
|
183
|
+
description="OpenFOAM Case Developer - Create OpenFOAM cases with Python",
|
184
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
185
|
+
epilog="""
|
186
|
+
Examples:
|
187
|
+
# Create an example case
|
188
|
+
pycphy-foam --example
|
189
|
+
|
190
|
+
# Create a custom case from configuration files
|
191
|
+
pycphy-foam --case myCase --geometry configBlockMesh.py --control configControl.py --turbulence configTurbulence.py
|
192
|
+
|
193
|
+
# Create a case with just geometry configuration
|
194
|
+
pycphy-foam --case myCase --geometry configBlockMesh.py
|
195
|
+
"""
|
196
|
+
)
|
197
|
+
|
198
|
+
parser.add_argument(
|
199
|
+
"--example",
|
200
|
+
action="store_true",
|
201
|
+
help="Create an example OpenFOAM case with default settings"
|
202
|
+
)
|
203
|
+
|
204
|
+
parser.add_argument(
|
205
|
+
"--case",
|
206
|
+
type=str,
|
207
|
+
help="Name of the OpenFOAM case directory to create"
|
208
|
+
)
|
209
|
+
|
210
|
+
parser.add_argument(
|
211
|
+
"--geometry",
|
212
|
+
type=str,
|
213
|
+
help="Path to geometry configuration file (Python module)"
|
214
|
+
)
|
215
|
+
|
216
|
+
parser.add_argument(
|
217
|
+
"--control",
|
218
|
+
type=str,
|
219
|
+
help="Path to control configuration file (Python module)"
|
220
|
+
)
|
221
|
+
|
222
|
+
parser.add_argument(
|
223
|
+
"--turbulence",
|
224
|
+
type=str,
|
225
|
+
help="Path to turbulence configuration file (Python module)"
|
226
|
+
)
|
227
|
+
|
228
|
+
args = parser.parse_args()
|
229
|
+
|
230
|
+
# Validate arguments
|
231
|
+
if args.example and args.case:
|
232
|
+
print("Error: Cannot specify both --example and --case options.")
|
233
|
+
sys.exit(1)
|
234
|
+
|
235
|
+
if not args.example and not args.case:
|
236
|
+
print("Error: Must specify either --example or --case option.")
|
237
|
+
sys.exit(1)
|
238
|
+
|
239
|
+
# Create the case
|
240
|
+
success = False
|
241
|
+
|
242
|
+
if args.example:
|
243
|
+
success = create_example_case()
|
244
|
+
else:
|
245
|
+
success = create_custom_case(
|
246
|
+
case_name=args.case,
|
247
|
+
geometry_file=args.geometry,
|
248
|
+
control_file=args.control,
|
249
|
+
turbulence_file=args.turbulence
|
250
|
+
)
|
251
|
+
|
252
|
+
if success:
|
253
|
+
print("\nOpenFOAM case creation completed successfully!")
|
254
|
+
sys.exit(0)
|
255
|
+
else:
|
256
|
+
print("\nOpenFOAM case creation failed!")
|
257
|
+
sys.exit(1)
|
258
|
+
|
259
|
+
if __name__ == "__main__":
|
260
|
+
main()
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
OpenFOAM dictionary writers for various file types.
|
3
|
+
|
4
|
+
This module contains the base FoamWriter class and specific writers
|
5
|
+
for different OpenFOAM dictionary files.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from .foam_writer import FoamWriter
|
9
|
+
from .block_mesh_writer import BlockMeshWriter
|
10
|
+
from .control_dict_writer import ControlDictWriter
|
11
|
+
from .turbulence_properties_writer import TurbulencePropertiesWriter
|
12
|
+
|
13
|
+
__all__ = [
|
14
|
+
"FoamWriter",
|
15
|
+
"BlockMeshWriter",
|
16
|
+
"ControlDictWriter",
|
17
|
+
"TurbulencePropertiesWriter",
|
18
|
+
]
|