14
$\begingroup$

In my project, I am importing a complex geometry from an STL file into Mathematica as a MeshRegion. I would like to edit this mesh significantly: For instance, drastically reduce or increase the number of elements (for finite element analysis) or make boolean operations. But I am not sure if Mathematica can re-mesh a MeshRegion that is obtained from discrete data.

Let me illustrate. When I work with an ImplicitRegion, I seem to have full control, I can make a mesh with very many or few elements, and apply boolean operations too:

IR = ImplicitRegion[
   x^6 - 5 x^4 y + 3 x^4 y^2 + 10 x^2 y^3 + 3 x^2 y^4 - y^5 + y^6 + 
     z^2 <= 1, {x, y, z}];
<< NDSolve`FEM`
ToElementMesh[IR, MaxCellMeasure -> Infinity, 
  AccuracyGoal -> 0]["Wireframe"]
ToElementMesh[RegionDifference[IR, Cuboid[]], 
  MaxCellMeasure -> 0.001]["Wireframe"]

enter image description here

Next, I create a MeshRegion by applying DiscretizeRegion. This leaves me in basically the same situation as importing some STL mesh into Mathematica as MeshRegion:

MR = DiscretizeRegion[IR]; (* same as MR = Import["filename.stl", "MeshRegion"] *)

Now I can no longer downsample:

ToElementMesh[MR, MaxCellMeasure -> Infinity, AccuracyGoal -> 0]
ToElementMesh[MR]

enter image description here

Same thing! No downsampling appears to have happened. Possibly no re-meshing whatsoever. Mathematica returns basically the same number of elements (TetrahedronElement["<" 16793 ">"] vs TetrahedronElement["<" 16841 ">"], respectively).

Also I can no longer apply boolean operations:

RegionDifference[MR, Cuboid[]] // DiscretizeRegion

returns an error

enter image description here

Is there some way I could gain control of the DiscretizeRegion in the same way as ImplicitRegion? In practice, I am presented with discrete data (STL file) and I would like to be able to re-mesh it, do boolean operations, and run FEM in full control of my mesh. Is that possible?

EDIT:

You can brute force Mathematica to re-mesh using this hack:

    MR2 = DiscretizeGraphics[
      RegionPlot3D[
       RegionMember[MR, {x, y, z}] == True && 
        RegionMember[Cuboid[], {x, y, z}] == False, {x, -2, 2}, {y, -2, 
        2}, {z, -2, 2}, PlotPoints -> 20]]
ToElementMesh[MR2, MaxCellMeasure -> Infinity, AccuracyGoal -> 0]

enter image description here

However, converting the MeshRegion (picture above, left) with ToElementMesh hopelessly overmeshes things (picture above, right). I get about 500k tetrahedral elements. Once again I don't know how to control my mesh for finite element analysis.


Cross-posted to Wolfram Community.

$\endgroup$
  • $\begingroup$ DiscretizeRegion can also take MaxCellMeasure. Similarly you can recover an ElementMesh by simply calling it on the MeshRegion. E.g. NDSolve`FEM`ElementMesh[MR]. $\endgroup$ – b3m2a1 Sep 13 '17 at 16:20
  • 2
    $\begingroup$ @b3m2a1 OP is importing the mesh from an STL file, i.e. it has already been discretized, so DiscretizeRegion is never used. It is used in the question only to create an example of an imported mesh. $\endgroup$ – C. E. Sep 14 '17 at 10:00
  • 2
    $\begingroup$ Note that you can directly import an STL as an ElementMesh: Needs["NDSolve`FEM`"]; bmesh = Import["~/gear.stl", "ElementMesh"] but you need to do this in a fresh session. Also, you can find a lot of information in the ElementMesh generation tutorial $\endgroup$ – user21 Sep 14 '17 at 13:02
11
+100
$\begingroup$

Is it possible to re-mesh, downsample & upsample a DiscretizeRegion object?

I believe the answer to all of those questions is yes, but just the body of the mesh and not the boundary – with a caveat which is described towards the end of this post.

First, let's deal with the question of re-meshing the body of the mesh.

bmesh = ToBoundaryMesh[MR];
ToElementMesh[bmesh, MaxCellMeasure -> Infinity, MeshQualityGoal -> "Minimal"]
(* Out: ElementMesh[{{-1.22416, 1.22416}, {-1.06605, 1.2848}, {-1.03294, 
   1.03294}}, {TetrahedronElement["<" 7292 ">"]}] *)

In this example, we discarded the discretization of the body of the mesh and then re-meshed it using the boundary. This results in a considerable downsampling compared to the original mesh:

emesh = ToElementMesh[MR]
(* Out: ElementMesh[{{-1.22416, 1.22416}, {-1.06605, 1.2848}, {-1.03294, 
   1.03294}}, {TetrahedronElement["<" 13449 ">"]}] *)

i.e. the re-meshed mesh has 7292 elements and the original mesh has 13449 elements. Similarly, we can also upsample it in this way:

bmesh = ToBoundaryMesh[MR];
ToElementMesh[bmesh, MaxCellMeasure -> 0.0001]
(* Out: ElementMesh[{{-1.22416, 1.22416}, {-1.06605, 1.2848}, {-1.03294, 
   1.03294}}, {TetrahedronElement["<" 98265 ">"]}] *)

This re-meshed mesh has 98265 elements.

Re-meshing the boundary is not possible without a symbolic representation. This is probably for a good reason. If you discretize the boundary (i.e. the surface in the 3D case) then you know what's happening at those points, but you don't know what's happening in between those points. Adding more points in between without knowing what those points are supposed to be is not going to make your result more exact. Allowing users to do it might trick them (us) into believing that they (we) are creating a better mesh, when in fact the new mesh is no better than the original at all.

This is how you can add a symbolic description to a mesh:

bmesh = ToBoundaryMesh[MR];
nr = ToNumericalRegion[IR];
SetNumericalRegionElementMesh[nr, bmesh];

bmesh = ToElementMesh[nr, MaxCellMeasure -> 0.00001];
Length@Flatten[ElementIncidents[bmesh["BoundaryElements"]], 1]
(* Out: 16782 *)

Compare with the number of boundary elements in the original mesh:

bmesh = ToBoundaryMesh[MR, MaxCellMeasure -> Infinity];
Length@Flatten[ElementIncidents[bmesh["BoundaryElements"]], 1]
(* Out: 4446 *)

This is an example of an upsampling. In other words, it is possible to re-mesh, upsample, and downsample the mesh if you can provide a symbolic description which will guide ToElementMesh to selecting the additional points.

As for your question about performing boolean operations on discretized regions, the answer is a no. That code is for symbolic regions.

Finally, note that the wireframes in your question show the boundary elements only. It is better to count the number of elements to get an idea of how well upsampling/downsampling works.

$\endgroup$
  • 3
    $\begingroup$ (+1) That's a good answer. $\endgroup$ – user21 Sep 14 '17 at 14:32
  • $\begingroup$ @user21 Thanks, and thank you for the bounty :) $\endgroup$ – C. E. Sep 18 '17 at 5:26
  • 1
    $\begingroup$ It's a good answer and it deserved more attention, so no worries :) $\endgroup$ – user21 Sep 18 '17 at 6:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.