35
35
from pathlib import Path
36
36
37
37
import gmsh
38
- from ceasiompy .CPACS2GMSH .func .generategmesh import (
39
- # duplicate_disk_actuator_surfaces,
40
- # control_disk_actuator_normal,
41
- # get_entities_from_volume,
38
+ from ceasiompy .CPACS2GMSH .func .generategmesh import ( # duplicate_disk_actuator_surfaces,; control_disk_actuator_normal,; get_entities_from_volume,
42
39
ModelPart ,
43
40
add_disk_actuator ,
44
- fuselage_size ,
45
41
process_gmsh_log ,
46
42
)
43
+ from ceasiompy .CPACS2GMSH .func .gmsh_utils import MESH_COLORS
47
44
from ceasiompy .utils .ceasiomlogger import get_logger
48
45
49
46
# from ceasiompy.utils.commonnames import (
53
50
# GMSH_ENGINE_CONFIG_NAME,
54
51
# )
55
52
from ceasiompy .utils .ceasiompyutils import get_part_type
56
-
57
- # from ceasiompy.utils.commonxpath import GMSH_MESH_SIZE_WINGS_XPATH
53
+ from ceasiompy .utils .commonxpath import GMSH_MESH_SIZE_FUSELAGE_XPATH , GMSH_MESH_SIZE_WINGS_XPATH
58
54
from ceasiompy .utils .configfiles import ConfigFile
55
+ from cpacspy .cpacsfunctions import create_branch
56
+
57
+ from ceasiompy .CPACS2GMSH .func .mesh_sizing import fuselage_size , wings_size
58
+
59
59
60
60
log = get_logger ()
61
61
66
66
67
67
68
68
def generate_2d_mesh_for_pentagrow (
69
- cpacs , cpacs_path , brep_dir , results_dir , open_gmsh , min_max_mesh_factor , symmetry = False
69
+ cpacs ,
70
+ cpacs_path ,
71
+ brep_dir ,
72
+ results_dir ,
73
+ open_gmsh ,
74
+ min_max_mesh_factor ,
75
+ symmetry = False ,
76
+ fuselage_mesh_size_factor = 1 ,
77
+ wing_mesh_size_factor = 1.5 ,
70
78
):
71
79
"""
72
80
Function to generate a mesh from brep files forming an airplane
@@ -133,18 +141,22 @@ def generate_2d_mesh_for_pentagrow(
133
141
gmsh .option .setNumber ("General.Terminal" , 0 )
134
142
# Log complexity
135
143
gmsh .option .setNumber ("General.Verbosity" , 5 )
144
+ # Tollerance for boolean
145
+ gmsh .option .setNumber ("Geometry.ToleranceBoolean" , 1e-5 )
136
146
137
147
# Import each aircraft original parts / parent parts
138
- fuselage_volume_dimtags = []
139
- wings_volume_dimtags = []
140
- enginePylons_enginePylon_volume_dimtags = []
141
- engine_nacelle_fanCowl_volume_dimtags = []
142
- engine_nacelle_coreCowl_volume_dimtags = []
143
- vehicles_engines_engine_volume_dimtags = []
144
- vehicles_rotorcraft_model_rotors_rotor_volume_dimtags = []
145
-
146
- fuselage_surface = []
147
- wing_surface = []
148
+ # fuselage_volume_dimtags = []
149
+ # wings_volume_dimtags = []
150
+ # enginePylons_enginePylon_volume_dimtags = []
151
+ # engine_nacelle_fanCowl_volume_dimtags = []
152
+ # engine_nacelle_coreCowl_volume_dimtags = []
153
+ # vehicles_engines_engine_volume_dimtags = []
154
+ # vehicles_rotorcraft_model_rotors_rotor_volume_dimtags = []
155
+
156
+ # fuselage_surface = []
157
+ # wing_surface = []
158
+ aircraft_parts = []
159
+ parts_parent_dimtag = []
148
160
149
161
log .info (f"Importing files from { brep_dir } " )
150
162
@@ -153,121 +165,22 @@ def generate_2d_mesh_for_pentagrow(
153
165
part_entities = gmsh .model .occ .importShapes (str (brep_file ), highestDimOnly = False )
154
166
gmsh .model .occ .synchronize ()
155
167
156
- # Create the aircraft part object
157
168
part_obj = ModelPart (uid = brep_file .stem )
158
- # maybe to cut off -->
159
169
part_obj .part_type = get_part_type (cpacs .tixi , part_obj .uid )
160
170
161
- if part_obj .part_type == "fuselage" :
162
- fuselage_volume_dimtags .append (part_entities [0 ])
163
- model_bb = gmsh .model .get_bounding_box (
164
- fuselage_volume_dimtags [0 ][0 ], fuselage_volume_dimtags [0 ][1 ]
165
- )
166
- fuselage_surface_dimtags = gmsh .model .get_entities (2 )
167
- print (f"fuselage_surface_dimtags{ fuselage_surface_dimtags } " )
168
-
169
- elif part_obj .part_type == "wing" :
170
- wings_volume_dimtags .append (part_entities [0 ])
171
- # return wings_volume_dimtags
172
- wing_surface_dimtags = gmsh .model .get_entities (2 )
173
- wing_surface_dimtags = [
174
- tag for tag in wing_surface_dimtags if tag not in fuselage_surface_dimtags
175
- ]
176
-
177
- print (f"wing_surface_dimtags{ wing_surface_dimtags } " )
178
-
179
- elif part_obj .part_type == "enginePylons/enginePylon" :
180
- enginePylons_enginePylon_volume_dimtags .append (part_entities [0 ])
181
- # return enginePylons_enginePylon_volume_dimtags
182
-
183
- elif part_obj .part_type == "engine/nacelle/fanCowl" :
184
- engine_nacelle_fanCowl_volume_dimtags .append (part_entities [0 ])
185
-
186
- elif part_obj .part_type == "engine/nacelle/coreCowl" :
187
- engine_nacelle_coreCowl_volume_dimtags .append (part_entities [0 ])
188
-
189
- elif part_obj .part_type == "vehicles/engines/engine" :
190
- vehicles_engines_engine_volume_dimtags .append (part_entities [0 ])
171
+ part_surfaces = [e for e in part_entities if e [0 ] == 2 ]
172
+ part_obj .surfaces_tags = [tag for dim , tag in part_surfaces ]
191
173
192
- elif part_obj .part_type == "vehicles/rotorcraft/model/rotors/rotor" :
193
- vehicles_rotorcraft_model_rotors_rotor_volume_dimtags .append (part_entities [0 ])
194
- else :
195
- log .warning (f"'{ brep_file } ' cannot be categorized!" )
196
- return None
174
+ # Add to the list of aircraft parts
175
+ aircraft_parts .append (part_obj )
176
+ parts_parent_dimtag .append (part_entities [0 ])
197
177
198
- for fuselage_surface_dimtag in fuselage_surface_dimtags :
199
- fuselage_tags = fuselage_surface_dimtag [1 ]
200
- fuselage_surface .append (fuselage_tags )
201
-
202
- for wing_surface_dimtag in wing_surface_dimtags :
203
- wing_tags = wing_surface_dimtag [1 ]
204
- wing_surface .append (wing_tags )
205
-
206
- # gmsh.model.add_physical_group(2, surface, -1, name="aircraft_surface")
207
-
208
- gmsh .model .add_physical_group (2 , fuselage_surface , - 1 , name = "fuselage_surface" )
209
- gmsh .model .add_physical_group (2 , wing_surface , - 1 , name = "wing_surface" )
210
-
211
- gmsh .model .occ .synchronize ()
212
-
213
- log .info ("Start manipulation to obtain a watertight volume" )
214
- log .info ("Cutting parts..." )
215
- # we have to obtain a wathertight volume
216
-
217
- # gmsh.model.occ.fragment(
218
- # wings_volume_dimtags,
219
- # fuselage_volume_dimtags,
220
- # )
221
- gmsh .model .occ .fuse (wings_volume_dimtags , wings_volume_dimtags , - 1 , False , False )
222
- log .info ("Removing parts..." )
223
- # gmsh.model.occ.cut(wings_volume_dimtags, fuselage_volume_dimtags, -1, False, False)
224
-
225
- volume_inner_part = gmsh .model .occ .cut (
226
- wings_volume_dimtags , fuselage_volume_dimtags , - 1 , False , False
227
- )
228
- volume_inner_part = volume_inner_part [:- 1 ]
229
- print (f"inner part={ volume_inner_part } " )
230
- volume_inner_part = [(3 , 4 ), (3 , 5 )]
231
-
232
- surface_inner_part = gmsh .model .occ .cut (
233
- wing_surface_dimtags , fuselage_surface_dimtags , - 1 , False , False
234
- )
235
- surface_inner_part = surface_inner_part [:- 1 ]
236
- print (f"inner part={ surface_inner_part } " )
237
- surface_inner_part = [
238
- (2 , 15 ),
239
- (2 , 20 ),
240
- (2 , 3 ),
241
- (2 , 4 ),
242
- (2 , 5 ),
243
- (2 , 34 ),
244
- (2 , 35 ),
245
- (2 , 36 ),
246
- (2 , 37 ),
247
- (2 , 38 ),
248
- (2 , 39 ),
249
- (2 , 40 ),
250
- (2 , 41 ),
251
- (2 , 42 ),
252
- (2 , 43 ),
253
- (2 , 44 ),
254
- (2 , 45 ),
255
- (2 , 46 ),
256
- ]
178
+ log .info (f"Part : { part_obj .uid } imported" )
257
179
258
180
gmsh .model .occ .synchronize ()
259
181
260
- gmsh .model .occ .remove (volume_inner_part )
261
- gmsh .model .occ .remove (surface_inner_part )
262
- gmsh .model .occ .synchronize ()
263
- gmsh .fltk .run ()
264
- log .info ("Fusing parts..." )
265
- # gmsh.model.occ.fuse(wings_volume_dimtags, fuselage_volume_dimtags, -1, False, False)
266
- gmsh .model .occ .fuse (wings_volume_dimtags , fuselage_volume_dimtags , - 1 , False , False )
267
- gmsh .model .occ .synchronize ()
268
-
269
- gmsh .fltk .run ()
270
-
182
+ # Create external domain for the farfield
183
+ model_bb = gmsh .model .getBoundingBox (- 1 , - 1 )
271
184
model_dimensions = [
272
185
abs (model_bb [0 ] - model_bb [3 ]),
273
186
abs (model_bb [1 ] - model_bb [4 ]),
@@ -280,7 +193,66 @@ def generate_2d_mesh_for_pentagrow(
280
193
model_bb [2 ] + model_dimensions [2 ] / 2 ,
281
194
]
282
195
283
- fuselage_maxlen , _ = fuselage_size (cpacs_path )
196
+ log .info ("Start manipulation to obtain a watertight volume" )
197
+ log .info ("Fusing parts..." )
198
+
199
+ # Ciclo di fusione
200
+ while len (parts_parent_dimtag ) > 1 :
201
+ fused_entities , mapping = gmsh .model .occ .fuse (
202
+ [parts_parent_dimtag [0 ]], [parts_parent_dimtag [1 ]]
203
+ )
204
+
205
+ gmsh .model .occ .synchronize ()
206
+
207
+ # Aggiorna la lista delle entità fuse
208
+ new_fused = fused_entities [0 ]
209
+ parts_parent_dimtag = [new_fused ] + parts_parent_dimtag [2 :]
210
+
211
+ # Verifica le entità nel modello
212
+ final_volume_numbers = gmsh .model .getEntities (3 )
213
+
214
+ if len (final_volume_numbers ) != 1 or final_volume_numbers [0 ][1 ] != 1 :
215
+ log .error (f"There are { len (final_volume_numbers )} , fusion not successful" )
216
+ log .error ("You should have just one volume" )
217
+
218
+ gmsh .model .occ .synchronize ()
219
+
220
+ aircraft = ModelPart ("aircraft" )
221
+
222
+ for part in aircraft_parts :
223
+ aircraft .points .extend (part .points )
224
+ aircraft .lines .extend (part .lines )
225
+ aircraft .surfaces .extend (part .surfaces )
226
+ aircraft .volume .extend (part .volume )
227
+ aircraft .points_tags .extend (part .points_tags )
228
+ aircraft .lines_tags .extend (part .lines_tags )
229
+ aircraft .surfaces_tags .extend (part .surfaces_tags )
230
+ aircraft .volume_tag .extend (part .volume_tag )
231
+
232
+ print (part .surfaces_tags )
233
+
234
+ surfaces_group = gmsh .model .addPhysicalGroup (2 , part .surfaces_tags )
235
+ print (f"surfaces_group ={ surfaces_group } " )
236
+ gmsh .model .setPhysicalName (2 , surfaces_group , f"{ part .uid } " )
237
+ part .physical_groups .append (surfaces_group )
238
+
239
+ # Set surface BC for each part of the aircraft
240
+ # if part.part_type == "engine":
241
+ # define_engine_bc(part, brep_dir)
242
+ # else:
243
+ # surfaces_group = gmsh.model.addPhysicalGroup(2, part.surfaces_tags)
244
+ # if part.part_type == "rotor":
245
+ # gmsh.model.setPhysicalName(
246
+ # 2, surfaces_group, f"{part.uid}{ACTUATOR_DISK_INLET_SUFFIX}"
247
+ # )
248
+ # else:
249
+ # gmsh.model.setPhysicalName(2, surfaces_group, f"{part.uid}")
250
+ # part.physical_groups.append(surfaces_group)
251
+ gmsh .model .occ .synchronize ()
252
+
253
+ # gmsh.fltk.run()
254
+
255
+ fuselage_maxlen , fuselage_minlen = fuselage_size (cpacs_path )
284
256
285
257
# gmsh.model.occ.translate(
286
258
# [(3, 1)],
@@ -290,17 +262,49 @@ def generate_2d_mesh_for_pentagrow(
290
262
# )
291
263
292
264
gmsh .model .occ .synchronize ()
293
- log .info ("Manipulation finished" )
265
+ log .info ("Geometry has been fused" )
266
+
267
+ mesh_size_fuselage = ((fuselage_maxlen + fuselage_minlen ) / 2 ) / fuselage_mesh_size_factor
268
+ log .info (f"Mesh size fuselage={ mesh_size_fuselage :.3f} m" )
269
+
270
+ create_branch (cpacs .tixi , GMSH_MESH_SIZE_FUSELAGE_XPATH )
271
+ cpacs .tixi .updateDoubleElement (GMSH_MESH_SIZE_FUSELAGE_XPATH , mesh_size_fuselage , "%.3f" )
272
+
273
+ wing_maxlen , wing_minlen = wings_size (cpacs_path )
274
+ mesh_size_wing = ((wing_maxlen * 0.8 + wing_minlen ) / 2 ) / wing_mesh_size_factor
275
+ log .info (f"Mesh size wing={ mesh_size_wing :.3f} m" )
276
+
277
+ create_branch (cpacs .tixi , GMSH_MESH_SIZE_WINGS_XPATH )
278
+ cpacs .tixi .updateDoubleElement (GMSH_MESH_SIZE_WINGS_XPATH , mesh_size_wing , "%.3f" )
279
+
280
+ for part in aircraft_parts :
281
+ print (part .part_type )
282
+ if part .part_type == "fuselage" :
283
+ part .mesh_size = mesh_size_fuselage
284
+ gmsh .model .mesh .setSize (part .points , part .mesh_size )
285
+ gmsh .model .setColor (part .surfaces , * MESH_COLORS [part .part_type ], recursive = False )
286
+ elif part .part_type in ["wing" , "pylon" ]:
287
+ part .mesh_size = mesh_size_wing
288
+ gmsh .model .mesh .setSize (part .points , part .mesh_size )
289
+ gmsh .model .setColor (part .surfaces , * MESH_COLORS [part .part_type ], recursive = False )
290
+ # elif part.part_type == "engine":
291
+ # part.mesh_size = mesh_size_engines
292
+ # gmsh.model.mesh.setSize(part.points, part.mesh_size)
293
+ # gmsh.model.setColor(part.surfaces, *MESH_COLORS[part.part_type], recursive=False)
294
+ # elif part.part_type == "rotor":
295
+ # part.mesh_size = mesh_size_propellers
296
+ # gmsh.model.mesh.setSize(part.points, part.mesh_size)
297
+ # gmsh.model.setColor(part.surfaces, *MESH_COLORS[part.part_type], recursive=False)
298
+
299
+ # mesh_size = model_dimensions[0] * float(min_max_mesh_factor) * (10**-3)
300
+ # gmsh.option.set_number("Mesh.MeshSizeMin", mesh_size)
301
+ # gmsh.option.set_number("Mesh.MeshSizeMax", mesh_size)
302
+ # gmsh.option.setNumber("Mesh.StlOneSolidPerSurface", 2)
294
303
295
- # Mesh generation
296
304
log .info ("Start of gmsh 2D surface meshing process" )
297
305
298
306
gmsh .option .setNumber ("Mesh.Algorithm" , 6 )
299
307
gmsh .option .setNumber ("Mesh.LcIntegrationPrecision" , 1e-6 )
300
- mesh_size = model_dimensions [0 ] * float (min_max_mesh_factor ) * (10 ** - 3 )
301
- gmsh .option .set_number ("Mesh.MeshSizeMin" , mesh_size )
302
- gmsh .option .set_number ("Mesh.MeshSizeMax" , mesh_size )
303
- gmsh .option .setNumber ("Mesh.StlOneSolidPerSurface" , 2 )
304
308
305
309
gmsh .model .occ .synchronize ()
306
310
gmsh .logger .start ()
0 commit comments