5
$\begingroup$

I am having trouble generating a mesh of a rectangle inside another rectangle. I have been following the steps on this article: https://reference.wolfram.com/language/PDEModels/tutorial/HeatTransfer/ModelCollection/ShrinkFitting.html

However, I have been getting an error that I cannot combine the inner rectangle to the outer rectangle with a hole in it. It says "Coordinate Skeleton[2] should be a pair of numbers, or a Scaled or Offset form." in the debugger. Here is my code, it is more or less what the tutorial does.

bathx = 30;
bathy = 30;
plastic = Rectangle[{10, 10}, {20, 20}];
waterbath = 
  RegionDifference[Rectangle[{0, 0}, {bathx, bathy}], plastic]; 
\[CapitalOmega] = RegionUnion[plastic, waterbath]; 
bounds = 1.1*{{0, bathx}, {0, bathy}};
mesh = ToElementMesh[\[CapitalOmega], bounds];

Show[mesh["Wireframe"]]

Subscript[bm, w] = ToBoundaryMesh[waterbath]; 
Subscript[bm, p] = ToBoundaryMesh[plastic];
ResourceFunction["FEMAddOnsInstall"][]
Needs["FEMAddOns`"]
bmesh = FEMUtils`BoundaryElementMeshJoin[Subscript[bm, w], 
  Subscript[bm, p]]

waterbathCoordinate = {1, 1};
plasticCoordinate = {15, 15};
markerColors = {Blue, Orange};
markerCoordinates = {{waterbathCoordinate}, {plasticCoordinate}};

Show[{bmesh["Wireframe"], 
  Graphics[MapThread[{PointSize[0.02], #1, 
      Point /@ #2} &, {markerColors, markerCoordinates}]]}]  

markerSpecification = {{plasticCoordinate, 1}, {waterbathCoordinate, 
    2}};

mesh2 = ToElementMesh[bmesh, "RegionMarker" -> markerSpecification, 
   "MaxCellMeasure" -> 5*10^-6];
GraphicsRow[{mesh2[
   "Wireframe"[
    "MeshElementStyle" -> 
     Map[Directive[FaceForm[#], EdgeForm[]] &, markerColors]]], 
  mesh2["Wireframe"[
    Sequence[PlotRange -> {bounds}, 
     "MeshElementStyle" -> Map[FaceForm[#] &, markerColors]]]]}]

Show[{mesh2["Wireframe"]}]
```
$\endgroup$
1
  • 1
    $\begingroup$ Your MaxCellMeasure on mesh2 is tiny and it crashed my kernel. Try something more like "MaxCellMeasure" -> 1. $\endgroup$
    – Tim Laska
    Jul 24 '20 at 0:08
7
$\begingroup$

The linked example was for a much smaller domain and hence too small of a mesh size specification. The following code should accomplish what you need.

(* Uncomment if not installed *)
(*ResourceFunction["FEMAddOnsInstall"][]*)
Needs["FEMAddOns`"]
bathx = 30;
bathy = 30;
bounds = 1.1*{{0, bathx}, {0, bathy}};
plastic = Rectangle[{10, 10}, {20, 20}];
waterbath = Rectangle[{0, 0}, {bathx, bathy}];

bmw = ToBoundaryMesh[waterbath];
bmp = ToBoundaryMesh[plastic];
bmesh = BoundaryElementMeshJoin[bmw, bmp];

waterbathCoordinate = {1, 1};
plasticCoordinate = {15, 15};
markerColors = {Blue, Orange};
markerCoordinates = {{waterbathCoordinate}, {plasticCoordinate}};

Show[{bmesh["Wireframe"], 
  Graphics[MapThread[{PointSize[0.02], #1, 
      Point /@ #2} &, {markerColors, markerCoordinates}]]}]

markerSpecification = {{plasticCoordinate, 1}, {waterbathCoordinate, 
    2}};

mesh2 = ToElementMesh[bmesh, "RegionMarker" -> markerSpecification, 
   "MaxCellMeasure" -> {"Length" -> 1}];
GraphicsRow[{mesh2[
   "Wireframe"[
    "MeshElementStyle" -> 
     Map[Directive[FaceForm[#], EdgeForm[]] &, markerColors]]], 
  mesh2["Wireframe"[
    Sequence[PlotRange -> {bounds}, 
     "MeshElementStyle" -> Map[FaceForm[#] &, markerColors]]]]}]
mesh2["Wireframe"]

Output

$\endgroup$
6
$\begingroup$

Tim's answer is spot on. Here is a slightly different approach that uses a trick. The idea is to use the waterbath as the region and tell ToElementMesh to also mesh the interior region (the plastic). If this approach is applicable in your case then you can reduce the amount of code somewhat.

Needs["NDSolve`FEM`"]
bathx = 30;
bathy = 30;
plastic = Rectangle[{10, 10}, {20, 20}];
waterbath = 
  RegionDifference[Rectangle[{0, 0}, {bathx, bathy}], plastic];
waterbathCoordinate = {1, 1};
plasticCoordinate = {15, 15};
markerColors = {Blue, Orange};
markerSpecification = {{plasticCoordinate, 1, 
    0.25}, {waterbathCoordinate, 2, 1.}};
mesh = ToElementMesh[waterbath, "RegionHoles" -> None, 
  "RegionMarker" -> markerSpecification]
GraphicsRow[{mesh[
   "Wireframe"[
    "MeshElementStyle" -> 
     Map[Directive[FaceForm[#], EdgeForm[]] &, markerColors]]], 
  mesh["Wireframe"[
    "MeshElementStyle" -> Map[FaceForm[#] &, markerColors]]]}]

enter image description here

Also, note that I used a different granularity in the subsections of the mesh.

$\endgroup$

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.