要素メッシュの可視化
要素メッシュのワイヤフレームの可視化は,ElementMeshの近似の可視化を作成する効率よい方法である.可視化は,線形要素を使ってメッシュを可視化する.メッシュをより完全に可視化するためには,ElementMeshはMeshRegionに変換されなければならない.より高度な可視化には,HighlightMeshを使うことができる.
ElementMeshは通常ToBoundaryMeshかToElementMeshを使って作成される.
パッケージを使うには,有限要素法のコンテキストがロードされなければならない.
Needs["NDSolve`FEM`"]ワイヤフレーム
要素メッシュを調べるためには,そのワイヤフレームを見ると便利である.
| mesh["Wireframe"] | ワイヤフレームを形成するエッジを表示する |
| mesh["Wireframe"[pos]] | 位置 pos のリストに対応する位置を持つ要素を示す |
| mesh["Wirefame"[ElementMarker m]] | マーカー m に対応するElementMarkerを持つ要素を示す |
ElementMeshワイヤフレームのコマンド.
埋込み次元によっては,ワイヤフレームの可視化はデフォルトではメッシュ要素を2Dのメッシュ要素で,そして境界要素を3Dで表示する.メッシュ要素を3Dで表示すると有用なこともあり,可能ではあるが,この可視化は境界要素を3Dで表示することほど有用ではないことが多い.
mesh = ToElementMesh["Coordinates" -> {{1.293, 0.228}, {1., 0.}, {0.94, 0.342}, {1.293, 0.}, {1.215, 0.442}, {2., 0.}, {1.879, 0.684}}, "MeshElements" -> {TriangleElement[{{1, 3, 2}, {1, 2, 4}, {1, 4, 6}, {1, 6, 7}, {1, 7, 5}, {1, 5, 3}}, {66, 66, 66, 44, 44, 44}]}]mesh["Wireframe"]このワイヤフレームはデフォルトではメッシュ要素を要素メッシュで表示することに注意する.
MeshRegion[mesh]mesh["Wireframe"["MeshElementStyle" -> EdgeForm[Green]]]mesh["Wireframe"["MeshElementStyle" -> FaceForm[Green]]]mesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[Green], EdgeForm[Red]]]]mesh["Wireframe"["MeshElementIDStyle" -> Red]]mesh["Wireframe"["MeshElementMarkerStyle" -> Blue]]pos = Position[mesh["Quality"], _ ? (# ≤ 0.9&)]メッシュ品質についての詳細は,要素メッシュの生成のチュートリアルを参照するとよい.
mesh["Wireframe"[pos]]mesh["Wireframe"[pos, "MeshElementMarkerStyle" -> Blue]]pos = Position[ElementMarkers[mesh["MeshElements"]], 44]mesh["Wireframe"[pos]]mesh["Wireframe"[ElementMarker == 44]]ここまで示したオプションは,"MeshElements","BoundaryElements","PointElements"というすべてのメッシュ要素に使える.この詳細は,ElementMeshのドキュメントを参照されたい.
2Dでは,デフォルトのワイヤフレームの可視化は,メッシュ要素を表示する.境界要素の可視化も可能である.
mesh["Wireframe"["MeshElement" -> "BoundaryElements"]]異なるメッシュ要素マーカー間のインターフェースは内部境界を形成することに注意する.
mesh["Wireframe"["MeshElement" -> "BoundaryElements", "MeshElementMarkerStyle" -> Blue]]mesh["Wireframe"["MeshElement" -> "PointElements"]]Show[mesh["Wireframe"], mesh["Wireframe"["MeshElement" -> "PointElements", "MeshElementIDStyle" -> Red]]]点要素については,境界インシデントのみが可視化されることに注意する.点要素が明示的に与えられない場合には,点要素は境界要素のインシデントから導き出される.
mesh["BoundaryElements"]mesh["PointElements"]メッシュを可視化するもう一つの方法に,MeshRegionを使う方法がある.
HighlightMesh[MeshRegion[mesh], Labeled[0, "Index"]]mesh = ToElementMesh["Coordinates" -> {{1.293, 0.228}, {1., 0.}, {0.94, 0.342}, {1.293, 0.}, {1.215, 0.442}, {2., 0.}, {1.879, 0.684}}, "MeshElements" -> {TriangleElement[{{1, 3, 2}, {1, 2, 4}, {1, 4, 6}, {1, 6, 7}, {1, 7, 5}, {1, 5, 3}}]},
"BoundaryElements" -> {LineElement[{{3, 2}, {2, 4}, {4, 6}, {6, 7}, {7, 5}, {5, 3}}]},
"PointElements" -> {PointElement[{{1}, {2}, {3}, {4}, {5}, {6}, {7}}]}]Show[mesh["Wireframe"], mesh["Wireframe"["MeshElement" -> "PointElements", "MeshElementIDStyle" -> Red]]]複合タイプの要素あるいは複数要素の場合には,要素の番号付けは,リスト内の位置に従って行われる.
coordinates = {{0., 0.}, {1., 0.}, {2., 0.}, {2.5, 0.5}, {0., 1.}, {1., 1.}, {2., 1.}, {3., 1.}, {2.5, 1.5}, {0., 2.}, {1., 2.}, {2., 2.}};e1 = QuadElement[{{1, 2, 6, 5}, {2, 3, 7, 6}, {5, 6, 11, 10}, {6, 7, 12, 11}}, {5, 5, 7, 7}];
e2 = TriangleElement[{{3, 4, 7}, {4, 8, 7}, {7, 9, 12}, {7, 8, 9}}, {5, 5, 7, 7}];mesh = ToElementMesh["Coordinates" -> coordinates, "MeshElements" -> {e1, e2}]mesh["Wireframe"["MeshElementIDStyle" -> Red]]mesh["Wireframe"["MeshElementIDStyle" -> Red, "ContinuousElementID" -> True]]mesh["Wireframe"["MeshElementStyle" -> {FaceForm[Green], FaceForm[Red]}]]要素メッシュに色付けを行う場合には,"MeshElementStyle"成分の数がマーカーの数にマッチしなければならない.
Note that in the above input the QuadElement instances were specified before the TriangleElement. The elements have been sorted for performance reasons. The automatic sorting can be switched off.
mesh = ToElementMesh["Coordinates" -> coordinates, "MeshElements" -> {QuadElement[{{1, 2, 6, 5}, {2, 3, 7, 6}, {5, 6, 11, 10}, {6, 7, 12, 11}}], TriangleElement[{{3, 4, 7}, {4, 8, 7}, {7, 9, 12}, {7, 8, 9}}]}, "SortElements" -> False]mesh["Wireframe"["MeshElementIDStyle" -> Red, "ContinuousElementID" -> True]]diskCenters = Table[3 / 4{Sin[θ], Cos[θ]}, {θ, 0, 2 Pi, Pi / 5}];
region = Fold[RegionDifference, Rectangle[{-1, -1}, {1, 1}], Disk[#, 1 / 10]& /@ diskCenters];mesh = ToElementMesh[region, "RegionHoles" -> None, "RegionMarker" -> Join[
MapThread[{#1, #2, 0.001}&, {diskCenters, Range[Length[diskCenters]]}], {{{0, 0}, Length[diskCenters] + 1, 0.01}}]];
temp = Most[Range[0, 1, 1 / (Length[diskCenters] + 1)]];
colors = ColorData["BrightBands"][#]& /@ temp;
mesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]bmesh = ToBoundaryMesh["Coordinates" -> {{1., 0.}, {0.94, 0.342}, {1.293, 0.}, {1.215, 0.442}, {2., 0.}, {1.879, 0.684}}, "BoundaryElements" -> {LineElement[{{2, 1}, {1, 3}, {3, 5}, {5, 6}, {6, 4}, {4, 2}}, {1, 3, 3, 2, 3, 3}]}, "PointElements" -> {PointElement[{{1}, {2}, {3}, {4}, {5}, {6}}, {1, 1, 3, 3, 2, 2}]}]Show[
bmesh["Wireframe"["MeshElement" -> "BoundaryElements", "MeshElementIDStyle" -> Blue, "MeshElementMarkerStyle" -> Purple]],
bmesh["Wireframe"["MeshElement" -> "PointElements", "MeshElementStyle" -> PointSize[0.015], "MeshElementIDStyle" -> Red, "MeshElementMarkerStyle" -> Orange]]]bmesh["Wireframe"[Or@@(ElementMarker == #& /@ {1, 2})]]mesh = ToElementMesh[bmesh]mesh["Wireframe"["MeshElement" -> "BoundaryElements", "MeshElementMarkerStyle" -> Purple, "MeshElementStyle" -> {Blue, Red, DarkGreen}]]3Dでは,描くデフォルトのワイヤフレームは,境界メッシュである.
nx = 8;ny = 4;nz = 5;
coordinates = Flatten[ Table[{r Cos[θ], r Sin[θ], h}, {h, -1., 1., 2 / (nz - 1)}, {r, 1., 2., 1 / (ny - 1)}, {θ, 0., 2 Pi / 3., (2 Pi / 3.) / (nx - 1)}], 2];incidents = Flatten[Table[Block[{p1 = (j - 1) * nx + i, p2 = j * nx + i, p3 = p2 + 1, p4 = p1 + 1, p5, p6, p7, p8},
{p5, p6, p7, p8} = {p1, p2, p3, p4} + k * nx * ny;
{p1, p2, p3, p4} += (k - 1) * nx * ny;
{p1, p2, p3, p4, p5, p6, p7, p8}], {i, 1, nx - 1}, {j, 1, ny - 1}, {k, 1, nz - 1}], 2];mesh = ToElementMesh["Coordinates" -> coordinates, "MeshElements" -> {HexahedronElement[incidents]}]3Dでは,デフォルトでは境界要素が表示される.これは,デフォルトでメッシュ要素が表示される2Dの場合とは対照的である.
mesh["Wireframe"]mesh["Wireframe"["MeshElement" -> "MeshElements"]]| "ContinuousElementID" | 連続番号とともに要素を表示する |
| "MeshElement" | どのメッシュ要素を描くべきかを指定する |
| "MeshElementIDStyle" | メッシュ要素の識別番号をどのスタイルで描くべきかを指定する |
| "MeshElementMarkerStyle" | メッシュ要素マーカーをどのスタイルで描くべきかを指定する |
| "MeshElementStyle" | メッシュ要素をどのスタイルで描くべきかを指定する |
ElementMeshの"Wireframe"可視化のオプション.
STLファイルは,境界要素メッシュとしてインポートすることができる.
bmesh = ToBoundaryMesh[Import["http://exampledata.wolfram.com/gear.1", {"STL"}]];bmesh["Wireframe"]3Dのワイヤフレームは,デフォルトですべての境界要素を表示する.境界メッシュの成分が細かく分解されている場合には,ワイヤフレームメッシュがその部分であまりにも密になりすぎるということもある.その対処法として,エッジフレームメッシュを3Dで使う方法がある.主要なエッジは,近傍の曲面が異なる法線を持つエッジである.
bmesh["Edgeframe"]bmesh["Edgeframe"["BoundaryGroupingThreshold" -> 0.2, "EdgeframeDirective" -> Red]]"Edgeframe"はGraphics3Dと同じオプションに加えて,以下のオプションを持つ.
ElementMeshの"Edgeframe"可視化のオプション.
境界マーカーも自動作成される.マーカーは,それぞれに別の色を割り当てることによって可視化できる.
box = Cuboid[{0, 0, 0}, {1, 1, 1}];
holes = Thread@Ball[{{1., 0.5, 0.5}, {1., 1., 0.5}, {1., 1., 1.}}, 0.2];
region = Fold[RegionDifference, box, holes]bmesh = ToBoundaryMesh[region]groups = bmesh["BoundaryElementMarkerUnion"];
temp = Most[Range[0, 1, 1 / (Length[groups])]];
colors = ColorData["BrightBands"][#]& /@ temp;
bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors, ViewPoint -> {2, 2, 1}]]ときには,境界マーカーあるいは点マーカーをスクロールして,境界条件を適用する特定の曲面あるいは境界点を見付けたい場合がある.
reg = RegionDifference[RegionDifference[
RegionDifference[
RegionUnion[Cylinder[{{0, 0, 0}, {0, 0, 3}}, 1], Cuboid[{-1 / 2, 0, 1}, {2, 1 + 1 / 4, 3}]],
Cuboid[{1, 0, 0}, {2, 1 - 1 / 4, 2}]],
Cylinder[{{0, 0, 0}, {0, 0, 3}}, 1 - 1 / 4]
],
Cylinder[{{3 / 2, 0, 3 - 1 / 2}, {3 / 2, 2, 3 - 1 / 2}}, 1 / 4]
];
bmesh = ToBoundaryMesh[reg]bIDs = bmesh["BoundaryElementMarkerUnion"];
edgeframe = bmesh["Edgeframe"];
outline = bmesh["Wireframe"["MeshElementStyle" ->
Directive[Opacity[0.2], FaceForm[LightBlue], EdgeForm[]]]];
Manipulate[Show[
outline,
edgeframe,
bmesh["Wireframe"[ElementMarker == bIDs[[id]], "MeshElementStyle" -> Directive[FaceForm[LightGray], EdgeForm[]]]]
], {{id, 1, "ElementMarker ID"}, 1, Length[bIDs], 1, Appearance -> "Open"}, SaveDefinitions -> True]pIDs = bmesh["PointElementMarkerUnion"];
edgeframe = bmesh["Edgeframe"];
outline = bmesh["Wireframe"["MeshElementStyle" ->
Directive[Opacity[0.2], FaceForm[LightBlue], EdgeForm[]]]];
Manipulate[
Show[
outline,
edgeframe,
bmesh["Wireframe"[ElementMarker == pIDs[[id]], "MeshElement" -> "PointElements", "MeshElementStyle" -> Red]]
], {{id, 1, "ElementMarker ID"}, 1, Length[pIDs], 1, Appearance -> "Open"}, SaveDefinitions -> True]mesh = ToElementMesh[bmesh]完全な要素メッシュにおいて点マーカーをより制御したい場合には,オプション"PointMarkers""BoundaryDeduced"をToElementMeshに指定するとよい.
pIDs = mesh["PointElementMarkerUnion"];
outline = mesh["Wireframe"["MeshElementStyle" -> Directive[Opacity[0.2], FaceForm[LightBlue], EdgeForm[]]]];
edgeframe = mesh["Edgeframe"];
Manipulate[
Show[
outline,
edgeframe,
mesh["Wireframe"[ElementMarker == pIDs[[id]], "MeshElement" -> "PointElements", "MeshElementStyle" -> Red]]
], {{id, 1, "ElementMarker ID"}, 1, Length[pIDs], 1, Appearance -> "Open"}, SaveDefinitions -> True]もう一つのオプションとして,すべての曲面を表示し,凡例を加えることもできる.
groups = bmesh["BoundaryElementMarkerUnion"];
temp = Most[Range[0, 1, 1 / (Length[groups])]];
colors = ColorData["BrightBands"][#]& /@ tempShow[
bmesh["Edgeframe"],
bmesh["Wireframe"["MeshElement" -> "BoundaryElements", "MeshElementStyle" -> (Directive[EdgeForm[], FaceForm[#]]& /@ colors)]]
, Epilog -> Inset[LineLegend[colors, groups], Scaled[{0.85, 0.8}]]
]3Dで複数の材料領域を作成し表示する例については,OpenCascadeLinkのドキュメントを参照されたい.
問題
ワイヤフレームの可視化の目的は,ElementMeshの近似の可視化を与えることにある.可視化は,線形要素を使ってメッシュを可視化する.
mesh = ToElementMesh[Disk[], MaxCellMeasure -> {"Area" -> Infinity}, "MaxBoundaryCellMeasure" -> 0.5, "BoundaryMeshGenerator" -> "RegionPlot"]Show[
mesh["Wireframe"],
mesh["Wireframe"["MeshElement" -> "PointElements", "MeshElementStyle" -> Red]], PlotRange -> {{.7, 1.1}, {-.4, .4}}]中間のノードはDiskの曲線上にあるが,ワイヤフレームの可視化は線形のみであるので,ノードが外側にあるように見えることに注意する.
変形の可視化
NDSolveを使って構造力学を解析する場合には,負荷のもとでのオブジェクトの変形が領域上で計算される.領域を負荷で変形されたかのように可視化すると便利なこともある.
この例における厳密な物理学は重要ではないが,NDSolveを使って有限要素法で計算された構造力学アプリケーションについては,従属変数の数が変形関数の数を指定する.
op = {Inactive[Div][{{0, -((Y*ν)/(1 - ν^2))}, {-((Y*(1 - ν))/(2*(1 - ν^2))), 0}} .
Inactive[Grad][v[x, y], {x, y}], {x, y}] + Inactive[Div][{{-(Y/(1 - ν^2)), 0}, {0, -((Y*(1 - ν))/(2*(1 - ν^2)))}} .
Inactive[Grad][u[x, y], {x, y}], {x, y}], Inactive[Div][{{0, -((Y*(1 - ν))/(2*(1 - ν^2)))}, {-((Y*ν)/(1 - ν^2)), 0}} .
Inactive[Grad][u[x, y], {x, y}], {x, y}] + Inactive[Div][{{-((Y*(1 - ν))/(2*(1 - ν^2))), 0}, {0, -(Y/(1 - ν^2))}} .
Inactive[Grad][v[x, y], {x, y}], {x, y}]} /. {Y -> 10 ^ 3, ν -> 33 / 100};Subscript[Γ, D] = DirichletCondition[{u[x, y] == 0., v[x, y] == 0.}, x == 0];{uif, vif} = NDSolveValue[{op == {0, NeumannValue[-1, x == 5]}, Subscript[Γ, D]}, {u, v}, {x, 0, 5}, {y, 0, 1}]NDSolveが2つの補間関数を返す.1つは,
方向の変形であり,もう一つは,
方向の変形である.変形された梁を示すためには,停止状態の梁の要素メッシュを作成しなければならない.この梁は,与えられた補間関数によって変形される.
mesh = uif["ElementMesh"];
ElementMeshDeformation[mesh, {uif, vif}]["Wireframe"]変形の量が小さいために変形が見た目では分からないような場合には,スケーリング因数を指定することができる.
ElementMeshDeformation[mesh, {uif, vif}, "ScalingFactor" -> 5]["Wireframe"]スケーリング因数が1であるとスケールしない.デフォルトではAutomaticスケーリングが使われる.自動スケーリング因数の計算には最小のよく使われる長さと最大の変形の間の関係が使われる.
maxDeformation = Max[Abs[Subtract@@@(MinMax /@ (#["ValuesOnGrid"]& /@ {uif, vif}))]];
minSize = Min[Abs[Subtract@@@(MinMax /@ Transpose[mesh["Coordinates"]])]];
minSize / maxDeformationElementMeshのElementMeshDeformation可視化のオプション.
ElementMeshDeformationは2Dと3Dの両方で使える.
ElementMeshの変換
可視化のために,ElementMeshをさまざまな形式に変換することが可能である.MeshRegionへの変換は以下のように行われる.
mesh = ToElementMesh[Rectangle[{0, 0}, {5, 1}]];
MeshRegion[mesh]ElementMeshをGraphicsComplexに変換することも可能である.
Graphics[ElementMeshToGraphicsComplex[mesh]]Graphics[{Directive[EdgeForm[Red], FaceForm[]], ElementMeshToGraphicsComplex[mesh]}]GraphicsComplexのオプションを指定することができる.
u = Function[{x, y}, x (y - 0.5) / 25];
v = Function[{x, y}, -x ^ 2 / 50];
Graphics[ElementMeshToGraphicsComplex[mesh, VertexColors -> (ColorData["Rainbow"] /@ Rescale[Norm[{u@@#, v@@#}]& /@ mesh["Coordinates"]])]]