meshql
Query-based meshing on top of GMSH
About
meshql is a declarative, query-based tool for parametric mesh generation built on top of GMSH. It provides an intuitive API for creating structured and unstructured meshes with support for:
- Query-based selection: Use CadQuery-like selectors to target specific geometry entities
- Boundary layers: Automatic boundary layer generation for both 2D and 3D meshes
- Transfinite meshing: Automated structured meshing with intelligent edge/face grouping
- Physical groups: Easy boundary condition assignment with named groups
- Preprocessing: Advanced geometry splitting and partitioning for complex workflows
- Multiple formats: Export to GMSH, SU2, VTK, and other mesh formats
- Visualization: Built-in mesh and geometry visualization tools
Installation
Prerequisites
meshql requires GMSH and CadQuery. Install them first:
# Install GMSH (required)
conda install -c conda-forge gmsh python-gmsh
# Install CadQuery (required for CAD geometry support)
conda install -c conda-forge -c cadquery cadquery=master
From PyPI
pip install git+https://github.com/OpenOrion/meshql.git#egg=meshql
From Source
git clone https://github.com/OpenOrion/meshql.git
cd meshql
pip install -e ".[gmsh]"
Quick Start
Basic Example: NACA Airfoil with Boundary Layer
import cadquery as cq
from meshql import GeometryQL
from meshql.utils.shapes import generate_naca4_airfoil
# Generate NACA 0012 airfoil coordinates
airfoil_coords = generate_naca4_airfoil("0012", num_points=40)
with GeometryQL.gmsh() as geo:
mesh = (
geo
.load(
cq.Workplane("XY")
.circle(20)
.polyline(airfoil_coords)
.close()
)
# Configure airfoil surface
.edges(type="interior")
.addPhysicalGroup("airfoil")
.addBoundaryLayer(
ratio=2,
size=0.00001,
num_layers=40,
)
.setMeshSize(0.01)
.end()
# Configure farfield
.edges(type="exterior")
.addPhysicalGroup("farfield")
.setMeshSize(3.0)
.end()
.generate(2)
.show("mesh")
)
Structured Mesh with Preprocessing
import cadquery as cq
from meshql import GeometryQL, Split
with GeometryQL.gmsh() as geo:
(
geo
.load(
cq.Workplane("XY").box(10, 10, 10).rect(2, 2).cutThruAll(),
preprocess=(Split, lambda split: (
split
.from_plane(angle=(90, 90, 0))
.from_plane(angle=(-90, 90, 0))
)),
)
.setTransfiniteAuto(max_nodes=50)
.generate(3)
.show("mesh", only_surface=True)
)
3D Wing with Interior Faces
import cadquery as cq
import numpy as np
from meshql import GeometryQL
from meshql.utils.shapes import generate_naca4_airfoil
airfoil_coords = generate_naca4_airfoil("0012", num_points=40) * 5 - np.array([2.5, 0])
with GeometryQL.gmsh() as geo:
(
geo
.load(
cq.Workplane("XY")
.box(10, 10, 10)
.faces(">Z")
.workplane(centerOption="CenterOfMass")
.polyline(airfoil_coords)
.close()
.cutThruAll()
)
.faces(type="interior")
.addPhysicalGroup("wing")
.addBoundaryLayer(size=0.001, ratio=1.5, num_layers=3)
.end()
.generate(2)
.show("mesh")
)
Key Features
Selection System
Use intuitive CadQuery-style selectors to target geometry entities:
.faces(">Z") # Top faces
.edges(type="interior") # Interior edges
.solids() # All solids
.vertices() # All vertices
Meshing Operations
Boundary Layers
Automatic boundary layer generation for viscous flow simulations:
.addBoundaryLayer(
size=0.001, # First cell height
ratio=1.5, # Growth ratio
num_layers=10, # Number of layers
)
Transfinite Meshing
Automated structured meshing with intelligent parameter selection:
.setTransfiniteAuto(
max_nodes=50, # Maximum nodes per edge
min_nodes=2, # Minimum nodes per edge
auto_recombine=True, # Recombine to quads/hexes
)
Physical Groups
Assign boundary conditions with named groups:
.faces(">Z")
.addPhysicalGroup("top_wall")
.end()
.faces("<Z")
.addPhysicalGroup("bottom_wall")
.end()
Mesh Refinement
Control mesh size and algorithms:
.setMeshSize(0.1) # Set mesh size
.setMeshAlgorithm2D("Delaunay") # 2D algorithm
.setMeshAlgorithm3D("Delaunay") # 3D algorithm
.refine() # Refine mesh
.recombine() # Recombine elements
Preprocessing
Geometry Splitting
Split complex geometries for structured meshing:
preprocess=(Split, lambda split: (
split
.from_plane(angle=(90, 90, 0)) # Split by plane
.from_ratios([0.25, 0.5, 0.75]) # Split by ratios
.from_normals([(1, 0, 0), (0, 1, 0)]) # Split by normals
.from_edge(selector=">Z") # Split from edge
))
Mesh Import
Load existing meshes from various formats:
import meshly
mesh = meshly.Mesh(
vertices=vertices_array,
indices=indices_array,
markers={"boundary": [face_indices]}
)
geo.load(mesh)
Output Formats
Export to multiple mesh formats:
.write("output.msh", dim=2) # GMSH format
.write("output.su2", dim=2) # SU2 format
.write("output.vtk", dim=2) # VTK format
Visualization
Built-in visualization tools:
.show("mesh") # Show mesh
.show("mesh", only_surface=True) # Show surface only
.show("gmsh") # Open in GMSH GUI
Examples
More examples available in the examples directory:
- cube.ipynb: Basic structured meshing with boundary layers
- naca0012.ipynb: Airfoil meshing with boundary layers
- inviscid_wedge.ipynb: Inviscid flow simulation setup
- turbo.ipynb: Turbomachinery example with STEP import
- progression.ipynb: Mesh refinement progression
Documentation
- Changelog: Version history and feature releases
Development Setup
Quick Start
git clone https://github.com/OpenOrion/meshql.git
cd meshql
make install
Available Make Commands
# Install package in development mode with GMSH support
make install
# Build Python package
make build-package
# Run tests
make test
# Clean build artifacts
make clean
# Quick local build (for testing)
make build
Manual Installation
git clone https://github.com/OpenOrion/meshql.git
cd meshql
pip install -e ".[gmsh]"
Contributing
We welcome contributions! Please check out the Discord for discussions and collaboration.
Support
- Discord: Join our community
- Issues: Report bugs or request features
Tutorial
Video tutorial available:
latest: https://www.youtube.com/watch?v=7skc6wjwoTk
v1: https://www.youtube.com/watch?v=ltbxRsuvaLw
License
MIT License - see LICENSE file for details.
Metadata
Release files for meshql 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| meshql-2.0.0.tar.gz | 42.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| meshql-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.2 kB
Release files / meshql-2.0.0.tar.gz
| Download URL | meshql-2.0.0.tar.gz |
|---|---|
| Size | 42.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
93d303048570d2e1e9562124d3acd556f76a19263254379cc54ad24995ec0ab6
|
|
BLAKE2b-256 checksum How to use checksums |
fe818cfdbf431ea11a3978a23b2e4c9ed5ecb6f7623694b6b9241ff6a6b68da4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / meshql-2.0.0-py3-none-any.whl
| Download URL | meshql-2.0.0-py3-none-any.whl |
|---|---|
| Size | 48.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
46d4820e57eaf673390994a57b8088fa40831184228e5f1638e59dbec49f928a
|
|
BLAKE2b-256 checksum How to use checksums |
223acaac9b82929f35c5ded18113d8ba2723a4b8b8e75489669bb89701e41d6a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for meshql 2.0.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.