Repository navigation
feat(palace): expose the Gmsh 3D algorithm and thread counts - #290
Merged
Merged
Conversation
Alisama20
requested review from
cdaunt,
flaport,
joamatab,
nikosavola and
vvahidd
as code owners
September 29, 2026 19:20
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #290 +/- ##
==========================================
+ Coverage 65.54% 65.89% +0.35%
==========================================
Files 110 110
Lines 16836 16934 +98
Branches 3323 3342 +19
==========================================
+ Hits 11035 11159 +124
+ Misses 4743 4728 -15
+ Partials 1058 1047 -11 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The mesh stats could not tell whether two meshes were the same: the tetrahedron count is not enough, and a hash of the .msh file changes with Gmsh's node and element numbering. Add gmsh_utils.mesh_hash(), a hash of node positions, element connectivity and physical groups by name that does not depend on numbering or element order, and record it in collect_mesh_stats() with the gsim and Gmsh versions and the effective Gmsh options that shape the mesh. Show them in print_mesh_stats() and in the SimulationResult summary. They also reach metadata.json, which exports the mesh stats. Part of gdsfactory#283.
gsim left Gmsh at its defaults, so there was no way to choose the 3D algorithm or the number of threads, both of which decide which mesh comes out. Add algorithm_3d, threads and surface_threads to MeshConfig, sim.mesh(), sim.preview() and generate_mesh(), applied right after Gmsh is initialized. The defaults, Delaunay and one thread, are what Gmsh did already. Log a warning for the two combinations that do not keep the mesh (parallel surface meshing, and HXT with several threads), and document which ones do. Part of gdsfactory#283.
Alisama20
force-pushed
the
feat/mesher-controls
branch
from
September 30, 2026 14:27
9eacb2e to
9a84d03
Compare
vvahidd
approved these changes
Oct 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #287: the first commit of this branch is that PR, and only the second one,
feat(palace): expose the Gmsh 3D algorithm and thread counts, is new here. Its tests use the mesh hash and the recorded Gmsh options of #287.#283 asks for the Gmsh thread and algorithm controls to be exposed separately from the Palace solver settings, for a way to keep the mesh identical when that matters, and for the limits to be documented. gsim set none of them: Gmsh ran single-threaded with its default 3D algorithm, and there was no way to change either.
This adds three options to
MeshConfig,sim.mesh(),sim.preview()andgenerate_mesh():algorithm_3d("delaunay"or"hxt")Mesh.Algorithm3D= 1 or 10"delaunay"threadsGeneral.NumThreads,Mesh.MaxNumThreads3Dsurface_threadsMesh.MaxNumThreads1D,Mesh.MaxNumThreads2DThey need a Gmsh with per-dimension thread limits (
Mesh.MaxNumThreads1D/2D/3D, which the 4.11.1 manual already lists; I did not check earlier versions, andgmshis not pinned inpyproject.toml). They are applied right aftergenerate_mesh()initializes Gmsh, and the effective values are recorded with the mesh hash from #287, so the settings behind a hash can be read next to it. A simulation that already has amesh_configkeeps its values unlesssim.mesh()overrides them, like the curve-fit and high-order settings.Defaults change nothing. They are what Gmsh did already, one thread and Delaunay, now set explicitly. On the lumped CPW of the notebooks (135,380 tetrahedra) and on the 800 µm CPW of #283 (90,055), the mesh hash is identical with and without this change.
Which combinations keep the mesh. From the runs behind #283 (Windows 10, Intel i7-9750H, Gmsh 4.15.2; the Apple M4 in the issue shows the same for Delaunay, which is the only algorithm it varied threads for beyond one HXT run):
algorithm_3dthreads/surface_threadsSo the way to get the same mesh whatever the thread count is Delaunay with
surface_threads=1, which is the default; it does not make meshing faster. That HXT repeats itself at a fixed thread count was seen on the Windows machine only, in every repeat there; it is worth confirming on another host before relying on it. Parallel surface meshing is the only combination that sped meshing up with Delaunay, and it gives a different mesh each time, also withMesh.Reproducible=1and a fixed seed. gsim logs a warning for the two combinations that lose the mesh (surface_threads > 1, and HXT with several threads); the same guidance is in theMeshConfigandgenerate_meshdocstrings, which the API docs render.Part of #283.
Test Plan
New
tests/palace/test_mesher_controls.py, 18 tests:threads=0,surface_threads=0and an unknown algorithm;apply_mesher_optionssets every Gmsh option it should, for both algorithms;surface_threads=4and one for HXT with 4 threads;sim.mesh()applies the options and records them in the mesh stats, defaults to one thread, and a simulation with amesh_configkeeps its controls unlesssim.mesh()overrides them;sim.preview()forwards the options togenerate_mesh();gmshthatgenerate_mesh()itself uses. A first version put this ingmsh_utils, which uses the real Gmsh, and it broketest_generate_mesh_forwards_curve_fit_and_decimationwhenever an earlier test had not left Gmsh initialized, because that test replacesgenerator.gmshwith a fake. It only showed up with all the branches merged, so the helper lives ingenerator.pynow.I broke each link on purpose (not calling
apply_mesher_options, not keeping the previous config, applying the surface count to 3D, not passingthreadsthrough, dropping the HXT warning, a wrong HXT code,preview()not forwarding, and using the real Gmsh instead of the generator's) and in every case the matching test failed.On the real 800 µm CPW of #283, run through
sim.mesh()itself:db3edef2cdc04142db3edef2cdc04142db3edef2cdc04142db3edef2cdc0414203d9de97…and73b45d15…86335bafc65c9623both37a3afd023a65c05bothThe classes are the same as in the earlier runs that patched Gmsh directly. The meshes have 90,055 (Delaunay) and 73,007 (HXT) tetrahedra because gsim samples the distance field at 200 points by default, not the 1600 of the recipe in #283, which gives 98,112 and 79,230.
Full suite: 1476 passed, 6 skipped, 4 xpassed (the 1434 that pass on
mainplus the 24 of #287 and the 18 new tests). pre-commit: all hooks pass.