Parallel OCCT Meshing : how to identify the bad face?

Hi Friends,

I’m using python to mesh an OCCT TopoDS_Solid.
Code is simple :

brep = OCCGeometry(...) with pyngcore.TaskManager(): mesh = brep.GenerateMesh(...)

When NetGen is in the “surface meshing” phase, the Face number is output to the console.
Because the Faces meshing is done in parallel, the Face number displayed has nothing to do with the original Face index in the OCCT Solid.
So, if the meshing fails, I have nothing in the output to know what Face is guilty.

Do you know how I could have access to this info ?
Thanks :slight_smile:

Hi Oliver,
You can set the MeshingParameter nthreads=1 to mesh sequentially. Anyway, the surface meshing is not parallel yet, just the mesh optimization afterwards.
The face numbers should match the numbering in the IGES/Step topology explorer in the netgen GUI.


Thanks Matthiash,

According to this post Netgen parallelization, parallelization is somehow impacting 2D meshing (i.e. the Blue graph is smaller when parallelized).
Moreover, if the 2D phase was purely iterative, why would be the face numbers wrong in the output ?
And finally, during the 2D phase, I’m seeing all my CPU @100%, proving that a parallel process is running.

Disabling multithreading would be a very bad news, because I’m seeing real benefits in the final processing time.

I was hoping to be able to somehow “tag” each face, and retrieve this tag after the failure.
I guess I’ll have to make some DIY cooking inside the code …

Thanks again Matt !

Thats quite a few questions, I will try to answer them one by one:
The post you mentioned is about the CSG Geometry Kernel (built-in in Netgen). OCC Surface meshing is not parallelized because we had issues with thread-safety in OpenCascade. Thus, only the surface optimization afterwards is running in parallel.

The face numbering has nothing to do with the parallelization, Netgen builds a face map, iterating over all compounds/solids and their faces, see here: netgen/occgeom.cpp at master · NGSolve/netgen · GitHub

The 100% CPU usage is due to the busy loop in the TaskManager (which has the benefit that even small loops profit from parallelization with low task distribution overhead). I agree that we should throttle this in sequential parts of the code (this is done when calling external direct solvers in NGSolve for instance)

Disabling multithreading was just a suggestion for debugging your meshing issue, not a recommendation in general.

For tagging the bad face, you could set the surface color at occgeom.cpp, line 247:

We will think about a more general solution. Note that there is the debugparam setting “write_mesh_on_error”, which is set from Python with

netgen.meshing.debugparam.write_mesh_on_error = True

But this flag is only handled during volume meshing at this moment.


Thanks a lot Matt for your fast and accurate answer.

If the number displayed during Face meshing, for exemple :
Face 2013 / 3474 (parameter space projection)
If this number is the real index in the Face MAP, this is perfectly OK for my purposes.

Back Matthias,

I was wondering what problem you have faced with OCCT, preventing you from activating parallel 2D meshing ?

As far as I can remember there was a problem that some occ routines are not thread safe. They store some caching info in global variables for faster projection or so…


In my spare time I would like to try to parallelize the 2D part of NetGen, as far as possible.
After some quick investigations into the code, it seams that several elements are obviously not suitable for parallelization.
Appart from OCCT itself, I’m quite sure the Mesh class is not ThreadSafe.

Do you have / can you share the last codebase version of parallelized 2D+3D (the very last one that was not working because of OCCT) ?
I do not want to reinvent the wheel :slight_smile:
Thanks !

I am happy to hear you like to help with optimization of parallel meshing.

First step is profiling, you can easily use vite-tracer also for meshing, (see
1.9 Parallel computing with TaskManager — NGS-Py 6.2.2302 documentation) to detect non-parallel or badly scaling regions.


Thanks for pointers Joachim.

My purpose in not (yet) to optimize the already parallised parts.
My intention is mainly to investigate parallelization of the OCCT surface meshing part in NetGen.
Your team has previously attempted to do such thing, and according to Matthias:

Being a long time user of OCCT myself, I would like to evaluate where the “thread-safety issues” of OCCT are, and possibly find workarounds, as far as my capabilities go.

The problem is that the current public GitHub version of NetGen, is obviously not the one your team was using when investigating OCCT parallelized surface meshing.
There are indeed several statements in the code, that are only valid in a mono-thread environment (Console outputs, Mesh updates, …).