3
$\begingroup$

I am trying to create FE meshes from vector or bitmap images and have come across the following issue. This is best shown using the following simplified code.

Needs["NDSolve`FEM`"]
coords = {{0., 0.}, {0., 1.}, {1., 1.}, {1., 0.}, {0.5, 0.25}, {1.0, 0.25}, {1.0, 0.75}, {0.5, 0.75}};
ellist = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {5, 6}, {6, 7}, {7, 8}, {8,5}};
labels = {1, 1, 1, 1, 2, 2, 2, 2};
meshtest = ToBoundaryMesh["Coordinates" -> coords, "BoundaryElements" -> {LineElement[ellist, labels]}];

Ideally I would like to have the inner rectangles boundary labeled with one value and the outer one with another value. However when the elements are co-linear (or rather one is found within another), then the labelling does not work.

meshtest["Wireframe"["MeshElement" -> "BoundaryElements", "MeshElementMarkerStyle" -> Blue]] 

image of mesh

I think this is probably still a desired feature in the boundary meshing algorithm, but is there anyway to find (and solve) these problems automatically, when I don't know a priori whether there is an overlap in the different regions? The images that I am meshing are rather complex and therefore it is difficult to know whether lines overlap or not.

$\endgroup$
4
$\begingroup$

In principle you'd like an input where the overlap is split and specify the markers at the edges like so:

Needs["NDSolve`FEM`"]
coords = {{0., 0.}, {0., 1.}, {1., 1.}, {1., 0.}, {0.5, 0.25}, {1.0, 
    0.25}, {1.0, 0.75}, {0.5, 0.75}};
ellist = {{1, 2}, {2, 3}, {3, 7}, {6, 4}, {4, 1}, {5, 6}, {6, 7}, {7, 
    8}, {8, 5}};
labels = {1, 1, 1, 1, 1, 2, 2, 2, 2};
meshtest = 
  ToBoundaryMesh["Coordinates" -> coords, 
   "BoundaryElements" -> {LineElement[ellist, labels]}];
meshtest["Wireframe"["MeshElement" -> "BoundaryElements", 
  "MeshElementMarkerStyle" -> Blue]]

enter image description here

Now, that may not always be easily possible. In that case you can use the boundary marker function to specify what you want:

(* original data *)
coords = {{0., 0.}, {0., 1.}, {1., 1.}, {1., 0.}, {0.5, 0.25}, {1.0, 
    0.25}, {1.0, 0.75}, {0.5, 0.75}};
ellist = {{1, 2}, {2, 3}, {3, 4}, {4, 1}, {5, 6}, {6, 7}, {7, 8}, {8, 
    5}};
labels = {1, 1, 1, 1, 2, 2, 2, 2};

You'd then specify a boundary marker function (see Options section in ToBoundaryMesh ref page)

boundaryMarkerFunction = 
  Compile[{{boundaryElementCoords, _Real, 
     3}, {pointMarkers, _Integer, 2}},
   MapThread[Module[{pt1 = #[[1]], pt2 = #[[2]]},
      Print[" boundary element coords: ", #1, "  Point markers: ", #2];
      Which[
       pt1[[1]] > 0.9 && pt2[[1]] > 0.9, 2,
       pt1[[1]] < 0.1 && pt2[[1]] < 0.1, 3,
       True, 4 ]] &, {boundaryElementCoords, pointMarkers}]];

Generating the boundary mesh then gives:

meshtest = 
  ToBoundaryMesh["Coordinates" -> coords, 
   "BoundaryElements" -> {LineElement[ellist, labels]}
   , "BoundaryMarkerFunction" -> boundaryMarkerFunction
   ];
SequenceForm[" boundary element coords: ", {{0., 0.}, {0., 1.}}, "  \
Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{0., 1.}, {1., 1.}}, "  \
Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{1., 1.}, {1., 0.75}}, "  \
Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{1., 0.75}, {1., 0.25}}, \
"  Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{1., 0.25}, {1., 0.}}, "  \
Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{1., 0.}, {0., 0.}}, "  \
Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{0.5, 0.25}, {1., 0.25}}, \
"  Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{1., 0.25}, {1., 0.75}}, \
"  Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{1., 0.75}, {0.5, 0.75}}, \
"  Point markers: ", {0, 0}]
SequenceForm[" boundary element coords: ", {{0.5, 0.75}, {0.5, \
0.25}}, "  Point markers: ", {0, 0}]

Looking at the mesh:

meshtest["Wireframe"["MeshElement" -> "BoundaryElements", 
  "MeshElementMarkerStyle" -> Blue]]

enter image description here

With this approach very general marker distributions should be possible.

$\endgroup$
  • $\begingroup$ This is great. Many thanks and exactly what I am trying to achieve. I hope this is also useful for others. $\endgroup$ – Dunlop Nov 5 '18 at 13:42

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.