Crea mesh graduata

Oct 11 2020

Voglio creare una maglia graduata all'interno di un cubo, con una maglia più fine nella metà sinistra e una maglia più grossolana nella metà destra. Il mio piano era di partizionare il cubo con un piano 2D e quindi generare la mesh di confine con ToBoundaryMesh(era inteso creare una mesh di confine anche sulla partizione) e quindi applicare ToElementMeshcon diversi MaxCellMeasurea sinistra ea destra della partizione. Ecco il mio codice:

reg = RegionUnion[Cuboid[], 
  ImplicitRegion[x == 0.5 && 0 <= y <= 1 && 0 <= z <= 1, {x, y, z}]];
ToBoundaryMesh[reg]

che dà il seguente errore:

BoundaryDiscretizeRegion::brepl: There are components in RegionUnion[Cuboid[{0,0,0}],ImplicitRegion[x==0.5&&0<=y<=1&&0<=z<=1,{x,y,z}]] having dimension lower than the embedding dimension 3 that will not be included in the boundary representation.

Come posso ottenere una mesh graduata? Ogni aiuto è molto apprezzato.

modificare

Ho provato quanto segue. Ho creato due cuboidi con un confine comune e li ho uniti con Or. Quindi ho creato una mesh mentre contrassegno le due regioni cuboidi (etichette 10 e 20) utilizzando RegionMarker, in cui ho anche specificato che MaxCellMeasurele due regioni siano 1 e 0,01. Ecco il codice:

reg = ImplicitRegion[Or[0 <= x <= 0.5 && 0 <= y <= 1 && 0 <= z <= 1,
0.5 <= x <= 1 && 0 <= y <= 1 && 0 <= z <= 1], {x, y, z}];
mesh = ToElementMesh[reg, 
   "RegionMarker" -> {{{0.1, 0.5, 0.5}, 10, 1}, {{0.6, 0.5, 0.5}, 20, 0.01}}];

Ma crea comunque una maglia di dimensioni uniformi nelle due regioni. Qualche idea su come superare il problema?

Risposte

3 TimLaska Oct 13 2020 at 14:14

Ecco un metodo per costruire una mesh esaedro anisotropa, sebbene non soddisfi il desiderio dell'OP di una soluzione "semplice".

L'ispirazione viene dall'esempio della griglia del prodotto tensoriale . L'idea è di creare una serie di segmenti di mesh 1D lungo ciascuna direzione e costruire la mesh usando RegionProduct.

Di seguito è riportato un esempio di una mesh graduata collegata a una mesh uniforme lungo la direzione x. Un esempio pratico di questo tipo di mesh sarebbe il trasferimento di calore coniugato in cui il fluido ha uno strato limite o una mesh graduata per catturare i gradienti termici sulla parete e il solido può essere mesh uniformemente.

Alcune funzioni di supporto per costruire mesh classificate:

(* Import required package *)
Needs["NDSolve`FEM`"];
(* Define Some Helper Functions For Structured Quad Mesh*)
pointsToMesh[data_] :=
  MeshRegion[Transpose[{data}], 
   Line@Table[{i, i + 1}, {i, Length[data] - 1}]];
unitMeshGrowth[n_, r_] := 
 Table[(r^(j/(-1 + n)) - 1.)/(r - 1.), {j, 0, n - 1}]
meshGrowth[x0_, xf_, n_, r_] := (xf - x0) unitMeshGrowth[n, r] + x0
firstElmHeight[x0_, xf_, n_, r_] := 
 Abs@First@Differences@meshGrowth[x0, xf, n, r]
lastElmHeight[x0_, xf_, n_, r_] := 
 Abs@Last@Differences@meshGrowth[x0, xf, n, r]
findGrowthRate[x0_, xf_, n_, fElm_] := 
 Quiet@Abs@
   FindRoot[firstElmHeight[x0, xf, n, r] - fElm, {r, 1.0001, 100000}, 
     Method -> "Brent"][[1, 2]]
meshGrowthByElm[x0_, xf_, n_, fElm_] := 
 N@Sort@Chop@meshGrowth[x0, xf, n, findGrowthRate[x0, xf, n, fElm]]
meshGrowthByElm0[len_, n_, fElm_] := meshGrowthByElm[0, len, n, fElm]
flipSegment[l_] := (#1 - #2) & @@ {First[#], #} &@Reverse[l];
extendMesh[mesh_, newmesh_] := Union[mesh, Max@mesh + newmesh]

Un flusso di lavoro commentato per creare una mesh graduata:

(*Define parameters*)
(*Lengths*)
(*2 horizontal segments*)
h1 = 0.5;
h2 = 0.5;
v = 1;(*Vertical*)
d = 1;(*Depth*)
(*Number of elements per segment*)
nh1 = 15;
nh2 = 10;
nv = 20;
nd = 5;
(*Association for Clearer Region Assignment*)
reg = <|"left" -> 1, "right" -> 2|>;
(*Create mesh segments*)
(*Horizontal segments*)
(* left segment *)
(*First element is 1/50th of seg length*)
(*Flip segment so smallest elm at interface *)
sh1 = flipSegment@meshGrowthByElm0[h1, nh1, h1/50];
(*Make right segment uniform mesh size*)
sh2 = Subdivide[h2, nh2];
(*Glue segments together*)
segh = extendMesh[sh1, sh2];
(*View individual horizontal segments*)
Print["Horizontal segments"]
pointsToMesh /@ {sh1, sh2}
(*View combined segments*)
Print["Combined horizontal segments"]
rh = pointsToMesh@segh
(*Vertical Segment*)
Print["Vertical segment"]
rv = pointsToMesh@Subdivide[v, nv]
(*View Region Product of horiz and vert segs*)
Print["2D Region via RegionProduct"]
RegionProduct[rh, rv]
(*Depth Segment*)
Print["Depth segment"]
rd = pointsToMesh@Subdivide[d, nd]
(*Create a tensor product grid from h,v,and d segments*)
rp = RegionProduct[rh, rv, rd];
(*View mesh*)
Print["Full Extruded 3D Region via RegionProduct"]
HighlightMesh[rp, Style[1, Orange]]
(*Extract Coords from RegionProduct*)
crd = MeshCoordinates[rp];
(*grab hexa element incidents RegionProduct mesh*)
inc = Delete[0] /@ MeshCells[rp, 3];
mesh = ToElementMesh["Coordinates" -> crd, 
   "MeshElements" -> {HexahedronElement[inc]}];
(*Extract bmesh*)
bmesh = ToBoundaryMesh[mesh];
(*Iron RegionMember Function*)
Ω3Diron = Cuboid[{0, 0, 0}, {h1, v, d}];
rmf = RegionMember[Ω3Diron];
regmarkerfn = If[rmf[#], reg["left"], reg["right"]] &;
(*Get mean coordinate of each hexa for region marker assignment*)
mean = Mean /@ GetElementCoordinates[mesh["Coordinates"], #] & /@ 
    ElementIncidents[mesh["MeshElements"]] // First;
regmarkers = regmarkerfn /@ mean;
(*Create and view element mesh*)
Print["Converted Hexa Element Mesh"]
mesh = ToElementMesh["Coordinates" -> mesh["Coordinates"], 
   "MeshElements" -> {HexahedronElement[inc, regmarkers]}];
Graphics3D[
 ElementMeshToGraphicsComplex[bmesh, 
  VertexColors -> (ColorData["BrightBands"] /@ 
     Rescale[regmarkerfn /@ bmesh["Coordinates"]])], Boxed -> False]