From d4cde66a1b3c189adfabc0b2ebcc7e1febf2d337 Mon Sep 17 00:00:00 2001 From: Jeremy Wright Date: Wed, 29 Jan 2025 06:51:53 -0500 Subject: [PATCH 1/5] Broke the methods apart to make it cleaner if the user wants more meshing control --- assembly_mesh_plugin/plugin.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/assembly_mesh_plugin/plugin.py b/assembly_mesh_plugin/plugin.py index d578079..5bd5583 100644 --- a/assembly_mesh_plugin/plugin.py +++ b/assembly_mesh_plugin/plugin.py @@ -5,12 +5,11 @@ import gmsh -def assembly_to_gmsh(self, mesh_path="tagged_mesh.msh"): +def get_tagged_gmesh(self): """ - Pack the assembly into a gmsh object, respecting assembly part names and face tags when creating - the physical groups. + Allows the user to get a gmsh object from the assembly, respecting assembly part names and face + tags, but have more control over how it is meshed. """ - gmsh.initialize() gmsh.option.setNumber("General.Terminal", 0) gmsh.model.add("coil_assembly") @@ -126,6 +125,18 @@ def assembly_to_gmsh(self, mesh_path="tagged_mesh.msh"): gmsh.model.occ.synchronize() + return gmsh + + +def assembly_to_gmsh(self, mesh_path="tagged_mesh.msh"): + """ + Pack the assembly into a gmsh object, respecting assembly part names and face tags when creating + the physical groups. + """ + + # Turn this assembly with potentially tagged faces into a gmsh object + gmsh = get_tagged_gmesh(self) + gmsh.model.mesh.field.setAsBackgroundMesh(2) gmsh.model.mesh.generate(3) @@ -136,3 +147,5 @@ def assembly_to_gmsh(self, mesh_path="tagged_mesh.msh"): # Patch the new assembly functions into CadQuery's importers package cq.Assembly.assemblyToGmsh = assembly_to_gmsh +cq.Assembly.saveToGmsh = assembly_to_gmsh # Alias name that works better on cq.Assembly +cq.Assembly.getTaggedGmesh = get_tagged_gmesh From c01e9d8f6d2bafe31b07ebfc54786c7e5b946a71 Mon Sep 17 00:00:00 2001 From: Jeremy Wright Date: Wed, 29 Jan 2025 07:41:50 -0500 Subject: [PATCH 2/5] Update assembly_mesh_plugin/plugin.py Fix gmsh name Co-authored-by: Jonathan Shimwell --- assembly_mesh_plugin/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assembly_mesh_plugin/plugin.py b/assembly_mesh_plugin/plugin.py index 5bd5583..8b8fbe1 100644 --- a/assembly_mesh_plugin/plugin.py +++ b/assembly_mesh_plugin/plugin.py @@ -5,7 +5,7 @@ import gmsh -def get_tagged_gmesh(self): +def get_tagged_gmsh(self): """ Allows the user to get a gmsh object from the assembly, respecting assembly part names and face tags, but have more control over how it is meshed. From 932c3463744536e4d229e560dbdfc1951274952f Mon Sep 17 00:00:00 2001 From: Jeremy Wright Date: Wed, 29 Jan 2025 07:42:13 -0500 Subject: [PATCH 3/5] Fix gmsh name Co-authored-by: Jonathan Shimwell --- assembly_mesh_plugin/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assembly_mesh_plugin/plugin.py b/assembly_mesh_plugin/plugin.py index 8b8fbe1..29ddd86 100644 --- a/assembly_mesh_plugin/plugin.py +++ b/assembly_mesh_plugin/plugin.py @@ -135,7 +135,7 @@ def assembly_to_gmsh(self, mesh_path="tagged_mesh.msh"): """ # Turn this assembly with potentially tagged faces into a gmsh object - gmsh = get_tagged_gmesh(self) + gmsh = get_tagged_gmsh(self) gmsh.model.mesh.field.setAsBackgroundMesh(2) From 6fb0ecd5e87ea852271115f7a7ec2ab93907344f Mon Sep 17 00:00:00 2001 From: Jeremy Wright Date: Wed, 29 Jan 2025 07:42:33 -0500 Subject: [PATCH 4/5] Fix gmsh name Co-authored-by: Jonathan Shimwell --- assembly_mesh_plugin/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assembly_mesh_plugin/plugin.py b/assembly_mesh_plugin/plugin.py index 29ddd86..df9d95d 100644 --- a/assembly_mesh_plugin/plugin.py +++ b/assembly_mesh_plugin/plugin.py @@ -148,4 +148,4 @@ def assembly_to_gmsh(self, mesh_path="tagged_mesh.msh"): # Patch the new assembly functions into CadQuery's importers package cq.Assembly.assemblyToGmsh = assembly_to_gmsh cq.Assembly.saveToGmsh = assembly_to_gmsh # Alias name that works better on cq.Assembly -cq.Assembly.getTaggedGmesh = get_tagged_gmesh +cq.Assembly.getTaggedGmsh = get_tagged_gmsh From 3595878e0890d8a4f4671eb7fdbad4fe5537b2cc Mon Sep 17 00:00:00 2001 From: Jeremy Wright Date: Wed, 29 Jan 2025 08:09:07 -0500 Subject: [PATCH 5/5] Switched the method names in the test and added a getTaggedGmsh example in the readme --- README.md | 35 +++++++++++++++++++++++++++++++++-- tests/smoke_test.py | 6 +++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 83bf795..4d13763 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ import cadquery_assembly_mesh_plugin.plugin You can then tag faces in each of the assembly parts and create your asembly. To export the assembly to a mesh file, you do the following. ```python -your_assembly.assemblyToGmsh(mesh_path="tagged_mesh.msh") +your_assembly.saveToGmsh(mesh_path="tagged_mesh.msh") ``` Normal tag names lead to a physical group with the assembly part name prefixed. So a tag name of `inner-bottom` on an assembly part with the name `steel_plate` will be `steel_plate_inner-bottom` @@ -54,11 +54,42 @@ assy = cq.Assembly() assy.add(shell, name="shell", loc=cq.Location(cq.Vector(0, 0, 0)), color=cq.Color("red")) assy.add(insert, name="insert", loc=cq.Location(cq.Vector(0, 0, 0)), color=cq.Color("blue")) -assy.assemblyToGmsh(mesh_path="tagged_mesh.msh") +assy.saveToGmsh(mesh_path="tagged_mesh.msh") ``` The resulting `.msh` file should have three physical groups named for tags in it. The `in_contact` group should include the faces from both the shell and the insert. +If you want more control over the mesh generation and export, you can use the `getTaggedGmsh` method and then finalize the mesh yourself. + +```python +import cadquery as cq +import cadquery_assembly_mesh_plugin.plugin +import gmsh + +shell = cq.Workplane("XY").box(50, 50, 50) +shell = shell.faces(">Z").workplane().rect(21, 21).cutThruAll() +shell.faces(">X[-2]").tag("inner-right") +shell.faces("X").tag("outer-right") + +assy = cq.Assembly() +assy.add(shell, name="shell", loc=cq.Location(cq.Vector(0, 0, 0)), color=cq.Color("red")) +assy.add(insert, name="insert", loc=cq.Location(cq.Vector(0, 0, 0)), color=cq.Color("blue")) + +# Get a Gmsh object back with all the tagged faces as physical groups +gmsh = assy.getTaggedGmsh() + +# Generate the mesh and write it to the file +gmsh.model.mesh.field.setAsBackgroundMesh(2) +gmsh.model.mesh.generate(3) +gmsh.write(mesh_path) +gmsh.finalize() +``` + ## Tests These tests are also run in Github Actions, and the meshes which are generated can be viewed as artifacts on the successful `tests` Actions there. diff --git a/tests/smoke_test.py b/tests/smoke_test.py index 8d70b47..eb36f75 100644 --- a/tests/smoke_test.py +++ b/tests/smoke_test.py @@ -15,7 +15,7 @@ def test_basic_assembly(): assy = generate_simple_nested_boxes() # Create a mesh that has all the faces tagged as physical groups - assy.assemblyToGmsh(mesh_path="tagged_mesh.msh") + assy.saveToGmsh(mesh_path="tagged_mesh.msh") def test_basic_cross_section(): @@ -27,7 +27,7 @@ def test_basic_cross_section(): assy = generate_test_cross_section() # Create a mesh that has all the faces in the correct physical groups - assy.assemblyToGmsh(mesh_path="tagged_cross_section.msh") + assy.saveToGmsh(mesh_path="tagged_cross_section.msh") def test_planar_coil(): @@ -39,4 +39,4 @@ def test_planar_coil(): assy = generate_assembly() # Create a mesh that has all the faces in the correct physical groups - assy.assemblyToGmsh(mesh_path="tagged_planar_coil.msh") + assy.saveToGmsh(mesh_path="tagged_planar_coil.msh")