# Assigning Element Markers to 3D FEM Mesh

I have created a 3D graphic using GraphicsComplex and then use ToElementMesh to generate a 3D Mesh that I want to solve a PDE on, but I cannot figure out how to apply ElementMarkers to the Boundaries. I am aware of the boundaryMarkerFunction but cannot seem to apply it correctly. Nice would be to apply the ElementMarkers to the faces of the 3D Graphic which is then Discretized using DiscretizeGraphics. Most examples of the boundaryMarkerFunction floating around seem to be for 2D meshes. In particular I would like to assign different boundary conditions to the base and fins of the object, therefore need appropriate ElementMarkers.

My Code is

Needs["NDSolveFEM"]

ft = 0.002;
fb = 0.005;
fh = 0.04;
bt = 0.005;
fins = 8;
w = 0.1;
l = 0.1;

g = (w - (fins*fb))/(fins - 1);
dfx = (fb - ft)/2;
dx = 2*dfx + ft + g;
nodes = 4*fins + 2;

base = {{0, y, 0}, {w, y, 0}, {w, y, bt}};
lastfin = {{dfx + ft, y, bt + fh}, {dfx, y, bt + fh}, {0, y, bt}};

restfins =
Flatten[Table[{{w - dfx - i*dx, y, bt + fh}, {w - dfx - ft - i*dx,
y, bt + fh}, {w - 2*dfx - ft - i*dx, y,
bt}, {w - 2*dfx - ft - g - i*dx, y, bt}}, {i, 0, fins - 2}], 1];

face1 = Join[base, restfins, lastfin] /. y -> 0;
face2 = Join[base, restfins, lastfin] /. y -> l;
fintops =
Table[{4 + 4 i, 4 + nodes + 4 i, 5 + nodes + 4 i, 5 + 4 i}, {i, 0,
fins - 1}];
basetops =
Table[{6 + 4 i, 6 + nodes + 4 i, 7 + nodes + 4 i, 7 + 4 i}, {i, 0,
fins - 2}];
finsidesright =
Table[{5 + 4 i, 5 + nodes + 4 i, 6 + nodes + 4 i, 6 + 4 i}, {i, 0,
fins - 2}];
finsidesleft =
Table[{7 + 4 i, 7 + nodes + 4 i, 8 + nodes + 4 i, 8 + 4 i}, {i, 0,
fins - 2}];

heatsink =
Graphics3D[
GraphicsComplex[Join[face1, face2],
Polygon[Join[{Table[i, {i, 1, nodes}],
Table[i, {i, nodes + 1, 2*nodes}], {1, 2, 2 + nodes,
1 + nodes}, {2, 2 + nodes, 3 + nodes, 3}, {3, 3 + nodes,
4 + nodes, 4}, {1, 1 + nodes, nodes + nodes, nodes}, {nodes,
2*nodes, 2*nodes - 1, nodes - 1}}, fintops, basetops,
finsidesright, finsidesleft]]]]


DiscretizeGraphics[heatsink] looks a bit strange:

Fortunately, however, ToElementMesh looks okay

mesh = ToElementMesh[DiscretizeGraphics[heatsink]]["Wireframe"]


Any tips on how I can assign the faces / boundaries "ElementMarkers" would be most appreciated.

Note at first I used Regions to create the object but it seemed to get distorted during meshing unless a very fine mesh was used.

• Sorry, but I don't understand why you need markers to define different boundary conditions. Neumann conditions can be applied as functions of position on the whole boundary and you can define one Dirichlet condition to each face independently. If the material is homogeneous I don't see the need for region markers. Nice geometry btw. Apr 24, 2016 at 21:25
• Is this what you want: bmesh = ToBoundaryMesh[DiscretizeGraphics[heatsink], "BoundaryMarkerFunction" -> (2 & /@ # &)]; emesh = ToElementMesh[bmesh] -- there might be other ways, but it's a little unclear whether you want different markers on the bound. Apr 24, 2016 at 21:39
• @tsuresuregusa, markers have several advantages over predicates: 1 they decouple the PDE from the geometry. 2 Since node and boundary markers are inserted during the boundary generation and then propagated and filled out during the mesh generation phase they is no inexactness in the matching the region bound. With a predicate, due to numerical error there may be the need for a pred <= epsilon. - Markers match on the element regardless how accurate the boundary is. And there are more advantages... Apr 24, 2016 at 23:04
• I filed the BoundaryDiscretizeGraphics issue as a bug. Apr 24, 2016 at 23:24
• @user21 that makes a lot of sense actually. Thanks a lot for the explanation. Apr 24, 2016 at 23:52

A bit long for a comment: What I'd do is split all polygons into quad elements and use those directly. Roughly like this:

sidesback1 = Partition[Table[i, {i, 1, nodes}][[3 ;; -1]], 4];
sidesfront1 =
Partition[Table[i, {i, nodes + 1, 2*nodes}][[3 ;; -1]], 4];
bmesh = ToBoundaryMesh["Coordinates" -> Join[face1, face2],
"BoundaryElements" -> {
QuadElement[{{1, 2, 2 + nodes, 1 + nodes}, {2, 2 + nodes,
3 + nodes, 3}, {3, 3 + nodes, 4 + nodes, 4}, {1, 1 + nodes,
nodes + nodes, nodes}, {nodes, 2*nodes, 2*nodes - 1,
nodes - 1}}]
}]


What is missing here is that you still need to split the former {1,2,3,34} polygon and add nodes on the {1,2} edge such that this polygon can be split down. This has the advantage that you could address every face or collection of faces with markers. I may do it later, but I need to attend to other things first.

Thanks to those that responded. Applying the boundary in the pde as a formula is okay for simple geometries but for more complicated ones it is cumbersome. I have tried user21's first suggestion:

bmesh = ToBoundaryMesh[DiscretizeGraphics[heatsink],
"BoundaryMarkerFunction" -> (2 & /@ # &)];

emesh = ToElementMesh[bmesh];
emesh["Wireframe"["MeshElement" -> "BoundaryElements",
"MeshElementMarkerStyle" -> Red]]


and get the following as required - Marker "2" on the boundary. Thats certainly a step for me in the right direction. Now I just need to work out how to apply that to specific regions on the boundary, i.e. EM = 1 on say the base. The other answer looks promising regarding this so I will try that and get back.