# Smooth refinement for a merged 2D mesh

Thanks to @user21 response and FEMAddOns I have been able to create a multi-region mesh. I am trying to make a smooth transitional mesh refinement with respect to a certain subregion. I plan to do this for certain polygons inside the mesh domain later, but for now I tried it on a simple test case:

<< NDSolveFEM
<< FEMAddOns

rmid = ImplicitRegion[
Sin[x] - 0.5 x <= y && y <= Sin [x] - 0.25 x + 0.2 && x >= 0 &&
x <= 3 && y >= -1, {x, y}];

rup = ImplicitRegion[
Sin [x] - 0.25 x + 0.2 <= y && y <= 1.5 && x >= 0 && x <= 3, {x, y}];

rdown = ImplicitRegion[
Sin[x] - 0.5 x >= y && y >= -1 && x >= 0 && x <= 3, {x, y}];

uniondomain = RegionUnion[rup, rdown, rmid];
ndomain = ToNumericalRegion@uniondomain;
symbounds = RegionBounds[uniondomain];
bm1 = ToBoundaryMesh[rmid, symbounds];
bm2 = ToBoundaryMesh[rup, symbounds];
bm3 = ToBoundaryMesh[rdown, symbounds];
bm = BoundaryElementMeshJoin[bm1, bm2, bm3];

mesh1 = ToElementMesh[bm,
"RegionMarker" -> {{{1.45, 1.1}, 1, 0.05}, {{1.5, 0.6}, 2,
0.003}, {{1.54, -0.38}, 3, 0.05}}];
mesh1["Wireframe"[
"MeshElementStyle" -> {FaceForm[Red], FaceForm[LightBlue],
FaceForm[Yellow]}, ImageSize -> Medium]]


which is good so far: However, I can't get the refinement function to work as function of distance from the middle high-resolution region.

f = Function[{vertices, area}, Block[{x, y}, {x, y} = Mean[vertices];
If[RegionMember[rmid, {x, y}], area > 0.003,
area > 0.003 + 20*(RegionDistance[rmid])^2[{x, y}]]]];
mesh2 = ToElementMesh[bm,
"RegionMarker" -> {{{1.45, 1.1}, 1, 0.05}, {{1.5, 0.6}, 2,
0.003}, {{1.54, -0.38}, 3, 0.05}},
MeshRefinementFunction -> f];
mesh2["Wireframe"[
"MeshElementStyle" -> {FaceForm[Red], FaceForm[LightBlue],
FaceForm[Yellow]}, ImageSize -> Medium]]


I've been playing with various functions with no luck. I also used the DistMeshgenerator, but that one was even harder because I didn't know how to get it to work for a multi-region mesh. Is there a better way than RegionDistance to do this or it is my refinement function that needs to be somewhat more effective?

Just to clarify, I know for this case the boundaries have function definitions and a simple distance can be obtained based on those, but I am looking for a more general solution that can be used on arbitrary regions defined by polygons etc.

For this to be efficient you'd need to use discretized versions of rmid. Note that I used SignedRegionDistance - RegionDistance should also work, but the given region distance function did not provide a refinement (too coarse, I believe). Here is an example:

f = With[{rmf = RegionMember[DiscretizeRegion[rmid]],
rdf = SignedRegionDistance[DiscretizeRegion[rmid]]},
Function[{vertices, area}, Block[{x, y}, {x, y} = Mean[vertices];
If[rmf[{x, y}], area > 0.0005, area > rdf[{x, y}]/200]]]];
mesh2 = ToElementMesh[bm,
"RegionMarker" -> {{{1.45, 1.1}, 1, 0.05}, {{1.5, 0.6}, 2,
0.003}, {{1.54, -0.38}, 3, 0.05}},
MeshRefinementFunction -> f];
mesh2["Wireframe"[
"MeshElementStyle" -> {FaceForm[Red], FaceForm[LightBlue],
FaceForm[Yellow]}, ImageSize -> Medium]] • As always, you solved it very nice and elegant! This actually works pretty well, especially if the boundaries are required to be more finely resolved in some applications. For my application, I want them to be gradually from the middle region and larger, so f = With[{rmf = RegionMember[DiscretizeRegion[rmid]], rdf = SignedRegionDistance[DiscretizeRegion[rmid]]}, Function[{vertices, area}, Block[{x, y}, {x, y} = Mean[vertices]; If[rmf[{x, y}], area > 0.0005, area > 0.0005 + rdf[{x, y}]/200]]]]` gives a nice transition with your solution. (since distances are zero on boundaries) Feb 21, 2022 at 15:00