Skip to main content

Project Logo

CadQuery plugin to create a mesh of an assembly with corresponding data.

This plugin makes use of CadQuery tags to collect surfaces into Gmsh physical groups. The tagged faces are matched to their corresponding surfaces in the mesh via their position in the CadQuery solid(s) vs the Gmsh surface ID. There are a few challenges with mapping tags to surfaces to be aware of.

  1. Each tag can select multiple faces/surfaces at once, and this has to be accounted for when mapping tags to surfaces.
  2. Tags are present at the higher level of the Workplane class, but are do not propagate to lower-level classes like Face.
  3. OpenCASCADE does not provide a built-in mechanism for tagging low-level entities without the use of an external data structure or framework.

Installation

You can install via PyPI

pip install assembly-mesh-plugin

Usage

PLEASE NOTE: This plugin currently needs to be run in an Anaconda/Mamba environment because of a crash with the PyPI packages when passing OpenCASCADE objects to Gmesh in memory.

The plugin needs to be imported in order to monkey-patch its method into CadQuery:

import assembly_mesh_plugin

You can then tag faces in each of the assembly parts and create your assembly. To export the assembly to a mesh file, you do the following.

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

By prefixing a tag with the ~ character, the part name is ignored, which allows for tagging of a multi-material physical group. For instance, tagging multiple faces with ~contact-with-casing will produce a physical group with the name contact-with-casing that includes all those faces, even if they belong to different parts/solids.

Below is a simple example.

import cadquery as cq
import assembly_mesh_plugin

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[-2]").tag("~in_contact")

# Create the insert
insert = cq.Workplane("XY").box(20, 20, 50)
insert.faces("<X").tag("~in_contact")
insert.faces(">X").tag("outer-right")

assy = cq.Assembly()
assy.add(shell, name="shell")
assy.add(insert, name="insert")

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.

import cadquery as cq
import assembly_mesh_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[-2]").tag("~in_contact")

# Create the insert
insert = cq.Workplane("XY").box(20, 20, 50)
insert.faces("<X").tag("~in_contact")
insert.faces(">X").tag("outer-right")

assy = cq.Assembly()
assy.add(shell, name="shell")
assy.add(insert, name="insert")

# Get a Gmsh object back with all the tagged faces as physical groups
gmsh_object = assy.getTaggedGmsh()

# Generate the mesh and write it to the file
gmsh_object.model.mesh.field.setAsBackgroundMesh(2)
gmsh_object.model.mesh.generate(3)
gmsh_object.write("tagged_mesh.msh")
gmsh_object.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.

  • sample_coils.py contains generators for sample assemblies for use in testing the basic operation of this plugin. This file also contains the code to tag all faces of interest.
  • smoke_test.py runs two tests currently. The first is for a simple cross-section of a coil (image below), which makes it easier to verify basic operation. The second is for a planar coil, which forces the use of more advanced selectors, but is not as complex as a coil with a non-planar sweep path. This planar-coil test is not complete yet.

Once the test has been run (using the pytest command), two mesh files (.msh extension) be created in the root of the repository.

  • tagged_cross_section.msh
  • tagged_planar_coil.msh

These mesh files will have many physical groups since each surface gets its own physical group, but it should also contain physical groups corresponding to the tags that were created for the faces in the assembly parts.

Metadata

Release files for assembly-mesh-plugin 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for assembly-mesh-plugin 0.2.0
File Size Uploaded
assembly_mesh_plugin-0.2.0.tar.gz 435.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for assembly-mesh-plugin 0.2.0
File Interpreter ABI Platform
assembly_mesh_plugin-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 449.6 kB

Release files / assembly_mesh_plugin-0.2.0.tar.gz

Download URL assembly_mesh_plugin-0.2.0.tar.gz
Size 435.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9b0e80e0e6ec62598107a3301151ab896ad96e758bbdc6bb8c22026c61fc0994
BLAKE2b-256 checksum
How to use checksums
4c2359e4d0560da9219df6e557850d5acc148ad890af78c0babd590f0d0cf282
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.

Transparency log

Release files / assembly_mesh_plugin-0.2.0-py3-none-any.whl

Download URL assembly_mesh_plugin-0.2.0-py3-none-any.whl
Size 14.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
31d647be2a3e2ffef812b28fac95ce1503442bf4aab7922716b2bf08a11fbcc0
BLAKE2b-256 checksum
How to use checksums
938bbcd26727edaf0e4350828484a72baa1a7ad59272ccb49396a1c1d27b000f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page