From ff6b340772d7e565dbe866ea0c82308e09ecd8c0 Mon Sep 17 00:00:00 2001 From: krande Date: Tue, 22 Oct 2024 20:32:11 +0200 Subject: [PATCH] make meshing temporarily more tolerant --- .../scripts/meshing/gmsh_maintaining_names.py | 73 +++++++++++++++++++ src/ada/fem/meshing/concepts.py | 6 +- .../meshing/partitioning/partition_beams.py | 8 +- .../meshing/partitioning/partition_plates.py | 13 ++-- src/ada/fem/meshing/utils.py | 6 +- src/ada/occ/tessellating.py | 4 +- 6 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 examples/scripts/meshing/gmsh_maintaining_names.py diff --git a/examples/scripts/meshing/gmsh_maintaining_names.py b/examples/scripts/meshing/gmsh_maintaining_names.py new file mode 100644 index 00000000..a70d5953 --- /dev/null +++ b/examples/scripts/meshing/gmsh_maintaining_names.py @@ -0,0 +1,73 @@ +import gmsh + +# Initialize Gmsh +gmsh.initialize() +gmsh.model.add("OCC example") + +# Enable the OpenCASCADE kernel +gmsh.option.setNumber("Geometry.OCCBooleanPreserveNumbering", 1) + +# Create a basic geometry using the OCC kernel +# Define points +p1 = gmsh.model.occ.addPoint(0, 0, 0) +p2 = gmsh.model.occ.addPoint(1, 0, 0) +p3 = gmsh.model.occ.addPoint(1, 1, 0) +p4 = gmsh.model.occ.addPoint(0, 1, 0) + +# Create lines +l1 = gmsh.model.occ.addLine(p1, p2) +l2 = gmsh.model.occ.addLine(p2, p3) +l3 = gmsh.model.occ.addLine(p3, p4) +l4 = gmsh.model.occ.addLine(p4, p1) + +# Create a surface +cl = gmsh.model.occ.addCurveLoop([l1, l2, l3, l4]) +surface = gmsh.model.occ.addPlaneSurface([cl]) + +# Synchronize to update the model +gmsh.model.occ.synchronize() + +# Assign physical groups with names before fragmentation +gmsh.model.addPhysicalGroup(1, [l1, l2, l3, l4], tag=1) +gmsh.model.setPhysicalName(1, 1, "Boundary") +gmsh.model.addPhysicalGroup(2, [surface], tag=2) +gmsh.model.setPhysicalName(2, 2, "Original Surface") + +# Create another shape to fragment the original surface with +# Example: A circle intersecting the original surface +circle_center = gmsh.model.occ.addPoint(0.5, 0.5, 0) +circle = gmsh.model.occ.addCircle(0.5, 0.5, 0, 0.3) +circle_loop = gmsh.model.occ.addCurveLoop([circle]) +circle_surface = gmsh.model.occ.addPlaneSurface([circle_loop]) + +# Perform the fragmentation operation +# This will return the mapping of original to new entities +dim_tags_out, map_out = gmsh.model.occ.fragment([(2, surface)], [(2, circle_surface)]) + +# Synchronize the model after the operation +gmsh.model.occ.synchronize() + +# Update physical groups based on the mapping from the fragmentation +for entity_map in map_out: + original_entity = entity_map[0] + new_entities = entity_map[1:] + + # Assign physical groups to new entities based on the original entity's dimension and tag + if original_entity[0] == 1: # Line (1D entity) + for new_entity in new_entities: + gmsh.model.addPhysicalGroup(1, [new_entity[1]], tag=original_entity[1]) + gmsh.model.setPhysicalName(1, original_entity[1], f"Boundary Fragment {new_entity[1]}") + elif original_entity[0] == 2: # Surface (2D entity) + for new_entity in new_entities: + gmsh.model.addPhysicalGroup(2, [new_entity[1]], tag=original_entity[1]) + gmsh.model.setPhysicalName(2, original_entity[1], f"Surface Fragment {new_entity[1]}") + +gmsh.fltk.run() +# Optionally, you can mesh the geometry +gmsh.model.mesh.generate(2) + +# Save the modified model +gmsh.write("occ_example_with_fragmentation.msh") + +# Finalize Gmsh +gmsh.finalize() diff --git a/src/ada/fem/meshing/concepts.py b/src/ada/fem/meshing/concepts.py index 8a2d8e99..322a8c20 100644 --- a/src/ada/fem/meshing/concepts.py +++ b/src/ada/fem/meshing/concepts.py @@ -248,8 +248,12 @@ def make_quads(self): partition_objects_with_holes(model, self) else: for dim, tag in model.entities: + try: + self.model.mesh.set_transfinite_surface(tag) + except Exception as e: + logger.error(f"Error while setting transfinite surface: {e}") + continue ents.append(tag) - self.model.mesh.set_transfinite_surface(tag) self.model.mesh.setRecombine(dim, tag) def make_hex(self): diff --git a/src/ada/fem/meshing/partitioning/partition_beams.py b/src/ada/fem/meshing/partitioning/partition_beams.py index dcf1fe50..6c919150 100644 --- a/src/ada/fem/meshing/partitioning/partition_beams.py +++ b/src/ada/fem/meshing/partitioning/partition_beams.py @@ -1,4 +1,4 @@ -from ada.config import Config +from ada.config import Config, logger from ada.fem.meshing import GmshSession @@ -61,7 +61,11 @@ def split_intersecting_beams(gmsh_session: GmshSession, margins=5e-5, out_of_pla continue # entities_1 = gmsh_session.model.occ.get_entities(1) - res, res_map = gmsh_session.model.occ.fragment(bm_gmsh_obj.entities, [(0, split_point)]) + try: + res, res_map = gmsh_session.model.occ.fragment(bm_gmsh_obj.entities, [(0, split_point)]) + except Exception as e: + logger.error(f"Error while fragmenting beam: {bm.name} using {n} {e}") + continue bm_gmsh_obj.entities = [x for x in res_map[0] if x[0] == 1] gmsh_session.model.occ.synchronize() diff --git a/src/ada/fem/meshing/partitioning/partition_plates.py b/src/ada/fem/meshing/partitioning/partition_plates.py index ebcef580..196e62e0 100644 --- a/src/ada/fem/meshing/partitioning/partition_plates.py +++ b/src/ada/fem/meshing/partitioning/partition_plates.py @@ -1,6 +1,6 @@ from __future__ import annotations -from ada.config import Config +from ada.config import Config, logger from ada.core.clash_check import PlateConnections, filter_away_beams_along_plate_edges, find_beams_connected_to_plate from ada.fem.meshing import GmshSession @@ -39,10 +39,13 @@ def partition_intersected_plates(plate_con: PlateConnections, gmsh_session: Gmsh for pl2_dim, pl2_ent in pl2_gmsh_obj.entities: intersecting_plates.add((pl2_dim, pl2_ent)) - - res, res_map = gmsh_session.model.occ.fragment( - list(intersecting_plates), [(pl1_dim, pl1_ent)], removeTool=False - ) + try: + res, res_map = gmsh_session.model.occ.fragment( + list(intersecting_plates), [(pl1_dim, pl1_ent)], removeTool=False + ) + except Exception as e: + logger.error(f"Error while fragmenting plate: {pl1.name} using {pl2.name} {e}") + continue replaced_pl_entities += [(dim, r) for dim, r in res if dim == 2] pl1_gmsh_obj.entities = replaced_pl_entities diff --git a/src/ada/fem/meshing/utils.py b/src/ada/fem/meshing/utils.py index 9274e853..6fd7aa06 100644 --- a/src/ada/fem/meshing/utils.py +++ b/src/ada/fem/meshing/utils.py @@ -102,7 +102,11 @@ def get_sh_sections_for_shape_obj(model: gmsh.model, model_obj: Shape, gmsh_data def get_sh_sections_for_plate_obj(model: gmsh.model, model_obj: Plate, gmsh_data: GmshData, fem: FEM): tags = [] for dim, ent in gmsh_data.entities: - _, tag, _ = model.mesh.getElements(2, ent) + try: + _, tag, _ = model.mesh.getElements(2, ent) + except BaseException as e: + logger.error(e) + continue tags += tag elements = [fem.elements.from_id(x) for x in chain.from_iterable(tags)] diff --git a/src/ada/occ/tessellating.py b/src/ada/occ/tessellating.py index 7c6b83ce..bb57f65d 100644 --- a/src/ada/occ/tessellating.py +++ b/src/ada/occ/tessellating.py @@ -317,4 +317,6 @@ def ifc_to_trimesh_scene(self, ifc_store: IfcStore, merge_meshes=True) -> trimes shapes_tess_iter = self.iter_ifc_store(ifc_store) graph = ifc_store.assembly.get_graph_store() - return self.meshes_to_trimesh(shapes_tess_iter, graph, merge_meshes=merge_meshes) + scene = self.meshes_to_trimesh(shapes_tess_iter, graph, merge_meshes=merge_meshes) + scene.metadata.update(graph.create_meta()) + return scene