Nglib is usually worse that Netgen, see this surface mesh picture for comparison. The elements along the inside radius of the bend are too big in Nglib's mesh and sometimes they're too bent to be useful for FEA, but using the Netgen UI it's very good.
I'm having trouble finding the relevant code in Netgen to compare to Nglib, any pointers on which source files to look in?
Same thing happens with both 4.9.13 and 5.0.0
The problem appears at the edge mesh stage. Nglib's edge mesh is too coarse along curved surfaces. This picture shows edge meshes generated using 5 elements per edge and 5 elements per curvature radius. I used this large number to exaggerate the difference.
You can see that nglib respects the number of elements per edge even when it's not appropriate, but Netgen somehow decides to refine along the edge of the curve so the element size all the way along matches the element size at the curved edges, and that leads to a proper mesh.
From looking at OCCGenerateMesh and OCCSetLocalMeshSize I can't spot the difference from Nglib's Ng_OCC_SetLocalMeshSize
I guess I'm talking to myself :P
Anyway it turns out this is a known bug: 3584774
I just posted a quick fix for it as a comment in that bug.
It's a pretty serious bug that would wreck the quality of just about every OCC mesh made with nglib or batchmode.
I will help you stop talking to yourself… I think this is the same bug that affected me when I first tried to integrate Netgen into one of my applications. Luckily, the workaround is simple enough.
What Nglib does not do that Netgen does is to build a surface mesh for visualization purposes (I guess Netgen uses this mesh to display the geometry in the GUI). This mesh itself is built by OCC (a BRepMesh_IncrementalMesh object) and stored inside the topological faces (TopoDS_Face).
Anyhow, it turns out that this surface mesh is used by Netgen to compute surface element sizes. This happens in occgenmesh.cpp, where you can find these lines of code:
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);
if (triangulation.IsNull()) continue;
What this code does is access the visualization mesh stored in the face. However, if the mesh has not been created, as is the case in Nglib, then triangulation.IsNull() returns true and a portion of the sizing code does not get executed. Therefore, the surface elements end up being bigger.
Now the fix: In nglib.cpp, you need to add the call to build the visualization mesh in Ng_OCC_SetLocalMeshSize(). For version 4.9.13, this translates to adding the following on line 722 of nglib.cpp:
The parameter 0.01 controls the deflection of the mesh i.e. how accurate it is at approximating the actual curved surfaces (the smaller, the more accurate the visualization mesh is). 0.01 is the value used by the GUI.
Hope it helps…
Cheers. Exactly matches what I worked out too. Though I used 0.001 which felt a bit safer - it corresponds to a slightly higher visualization quality setting in the Netgen UI. It can be slow but that's not really a problem in my application.