「有限要素法・アルゴリズム」の編集履歴(バックアップ)一覧はこちら

有限要素法・アルゴリズム」(2015/07/02 (木) 18:29:06) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

六面体要素の例でアルゴリズム処理の並びを整理する。 プログラム上での便宜のために導出で用いなかった記号を用いる。 *定数行列の準備 $${\cal C}_{ijkl} = \lambda \delta_{ij}\delta_{kl} + \mu (\delta_{ik}\delta_{jl} + \delta_{il}\delta_{jk}) $$ $$ S_{kn} = \left[ \begin{array}{cccccccc} 1 & -1 & -1 & 1& 1& -1& -1& 1 \\ 1 & 1 & -1 & -1& 1& 1& -1& -1 \\ 1 & 1 & 1 & 1& -1& -1& -1& -1 \end{array} \right]$$ *メッシュ 以下のように作成済みとする。 $$ x_{ip} = \left[ \begin{array}{ccc} x_1 & & x_p\\ y_1 & \cdots & y_p \\ z_1 & & z_p \end{array} \right] ,\ e_{nq} = \left[ \begin{array}{ccc} p_{11} & & p_{1q}\\ \vdots & \cdots & \vdots \\ p_{n1} & & p_{nq} \end{array} \right] $$ //添字の連続を避けるため、ある要素qにおけるn番節点のi座標座標を指定するときは $$ x_i(e_{nq}) $$と呼ぶものとする。 *自由度・荷重 拘束・外力込みで定義しておく、このページでは節点における自由度を先にカウントする。 自由度に対する時間微分などあれば同様。 $$ u = ^t\left[ \begin{array}{ccc} u_{x1}, u_{y1}, u_{z1}, & \cdots, & u_{zp} \end{array} \right]$$ $$ f = ^t\left[ \begin{array}{ccc} f_{x1}, f_{y1}, f_{z1}, & \cdots, & f_{zp} \end{array} \right]$$ 全自由度の配列サイズは$$L_D = L_p L_d$$ (配列pのサイズを $$L_p$$ = length(p) とする)。 *要素内M,K行列の作成 結構重たい処理のため、並列化ができる今の御時世最低smpで同時処理するのが望ましい。 parfor: は並列化推奨ループを示す。 **&bold(){parfor q = 1..q}(各要素に対するループ) -$$N^q(n, s), D^{q\prime}(d,n,s), G(d,d,s), detJ(s)$$: メモリの動的確保 **&bold(){parfor s = 1..n}(数値積分各要素に関するループ) +$$\xi_{ks} = S_{ks}/\sqrt{3} $$   +$$N_n = \prod_k \frac{1 + S_{kn} \xi_{ks}}{2} $$ +$$D^\prime_{jn} = \frac{\partial N_n}{\partial \xi_j} = S_{nj} \prod_k \frac{1 + \bar{\delta}_{jk} S_{nk} \xi_{ks}}{2}$$ +$$J_{ij} = x_{in} D^\prime_{jn} $$   [loop: n] +$$G_{ij} = J_{ij}^{-1} $$ +$$dV = det J_{ij} $$ **&bold(){end }(index s) **&bold(){end }(要素 q) 並列化パラメータの関係で一旦要素ループをここで切る。 **&bold(){parfor q = 1..q}(各要素に対するループ) -$$M^q(n,n), K^q(n,n), {\cal M}^q(d,d,n,n), {\cal K}^q(d,d,n,n)$$行列のメモリの動的確保・0フィル **&bold(){parfor m = 1..Σn, n = 1..Σn}(K行列等各要素に対するループ) -$$D^{n,m}(d), {\cal B}^{n,m}(d,d,d)$$行列のメモリ確保 -&bold(){for s = 1..n}(数値積分): リダクション(1メモリへの複数回アクセス)が噛むので並列化しないのが安泰 +$$D_{im}, D_{in} = N_{n,i} = D^\prime_{jn} G_{ij} $$  [loop: j] +$${\cal B}_{uvjm}, {\cal B}_{klin} = \frac{1}{2} \left[ \delta_{ik} D_{ln} + \delta_{il} D_{kn} \right]$$ +$$K^q_{mn} += D_{im} D_{in} dV$$  [loop: i] +$${\cal K}^q_{ijmn} += {\cal B}_{uvjm} {\cal C}_{uvkl} {\cal B}_{klin} dV $$ [loop: k,l,u,v ] +$$M^q_{mn} += N_m N_n dV$$ +(意図してN行列ベースの質量行列を作成したければ)$${\cal M}^q_{ijmn} += \rho \delta_{ij} N_m N_n dV$$ -&bold(){end } (index s) **&bold(){end }(index m, n) **&bold(){end }(要素 q) -$$N^q(n, s), D^{q\prime}(d,n,s), G(d,d,s), detJ(s)$$: は以後使わないので解放する。 *拘束・非ゼロ情報の登録 陰解法など全体行列が必要な場合には、合間に(CPUなど)単プロセスで自由度IDに関する整備をしておく。 メッシュ登録の段階くらいで、前もって隣接節点状況を登録しておくこと。 free = int[L_D], free_count = 0 メモリ節約のため、密自由度座標を疎行列インデックスへの変換を記録するidxは帯行列とする。 $$idx = \textrm{int}\left\{ L_D \times L_d\max[L_{p,a}] \right\}$$, idx_count = 0; **&bold(){for m = 1..Lp}(各節点に対するループ) **&bold(){for i = 1..Ld}(節点mの自由度) -$$r = i + L_d m$$ -if free(m,i) then   free(r) = free_count   free_count++ -else   free(r) = -1 -end -&bold(){for a = 1..max L(p,a)}(隣接節点に対するループ, $$a > L(p,a)$$ ならリターン ) -&bold(){for j = 1..Ld}(節点aの自由度) -$$n = m.adjacent(a)$$ : 隣接節点の番号 -$$c = j + L_d a$$ -if free(m,i) and free(n,j) then   idx(r,c) = idx_count   idx_count++ -else   idx(r,c) = -1 -end -&bold(){end }(index j) -&bold(){end }(隣接節点 a) **&bold(){end }(index i) **&bold(){end }(節点 m) *全体疎行列 拘束自由度を除いた全体行列を作成する。 メモリの確保は $$(K,M)$$ = double [idx_count] $$(row, col)$$ =int [idx_count] 及び $$\tilde{f} =$$ double [free_count] **&bold(){parfor m = 1..Lp}(各節点に対するループ) **&bold(){parfor i = 1..Ld}(節点mの自由度) +$$r = i + L_d m$$ +$$l = free(r)$$ +$$\tilde{f}(idx_f) = f(r) \hspace{2em} if\ l \neq -1$$ -&bold(){for a = 1..max L(p,a)}(隣接節点に対するループ, $$a > L(p,a)$$ ならリターン ) -&bold(){for j = 1..Ld}(節点aの自由度) +$$n = m.adjacent(a)$$ : 隣接節点の番号 +$$qlist =m.elem(a)$$ : 共有要素リスト +$$c = j + L_d a$$ +$$k = idx(r,c)$$ +$$row(k) = r \hspace{2em} if\ k \neq -1$$ +$$col(k) = j + L_d n \hspace{2em} if\ k \neq -1 $$ -&bold(){for q = 1..qlist}(各要素に対するループ) +$$ K(k) += {\cal K}^q_{ijmn} \hspace{2em} if\ k \neq -1$$ +必要なら $$M(k) += {\cal M}^q_{ijmn} \hspace{2em} if\ k \neq -1 $$ +$$\tilde{f}(l) -= {\cal K}^q_{ijmn} u( j + L_d n) \hspace{2em} if\ l \neq -1 $$ -&bold(){end }(要素 q) -&bold(){end }(index j) -&bold(){end }(隣接節点 a) **&bold(){end }(index i) **&bold(){end }(節点 m) **最終的な連立方程式に $$ A = K - \omega^2 M $$など *連立方程式を解く $$ \tilde{\bf u} = A^{-1} \tilde{\bf f} $$ 直接法(dgesv_やmatlabならバックスラッシュ)・反復法(CG法他)など適切なルーチンで。 $$free$$を利用して$$\tilde{\bf u}$$を配り直して、出力しておしまい。 #javascript(){{ <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-22313036-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> }}
六面体要素の例でアルゴリズム処理の並びを整理する。 プログラム上での便宜のために導出で用いなかった記号を用いる。 *定数行列の準備 ${\cal C}_{ijkl} = \lambda \delta_{ij}\delta_{kl} + \mu (\delta_{ik}\delta_{jl} + \delta_{il}\delta_{jk}) $ $ S_{kn} = \left[ \begin{array}{cccccccc} 1 & -1 & -1 & 1& 1& -1& -1& 1 \\ 1 & 1 & -1 & -1& 1& 1& -1& -1 \\ 1 & 1 & 1 & 1& -1& -1& -1& -1 \end{array} \right]$ *メッシュ 以下のように作成済みとする。 $ x_{ip} = \left[ \begin{array}{ccc} x_1 & & x_p\\ y_1 & \cdots & y_p \\ z_1 & & z_p \end{array} \right] ,\ e_{nq} = \left[ \begin{array}{ccc} p_{11} & & p_{1q}\\ \vdots & \cdots & \vdots \\ p_{n1} & & p_{nq} \end{array} \right] $ //添字の連続を避けるため、ある要素qにおけるn番節点のi座標座標を指定するときは $ x_i(e_{nq}) $と呼ぶものとする。 *自由度・荷重 拘束・外力込みで定義しておく、このページでは節点における自由度を先にカウントする。 自由度に対する時間微分などあれば同様。 $ u = ^t\left[ \begin{array}{ccc} u_{x1}, u_{y1}, u_{z1}, & \cdots, & u_{zp} \end{array} \right]$ $ f = ^t\left[ \begin{array}{ccc} f_{x1}, f_{y1}, f_{z1}, & \cdots, & f_{zp} \end{array} \right]$ 全自由度の配列サイズは$L_D = L_p L_d$ (配列pのサイズを $L_p$ = length(p) とする)。 *要素内M,K行列の作成 結構重たい処理のため、並列化ができる今の御時世最低smpで同時処理するのが望ましい。 parfor: は並列化推奨ループを示す。 **&bold(){parfor q = 1..q}(各要素に対するループ) -$N^q(n, s), D^{q\prime}(d,n,s), G(d,d,s), detJ(s)$: メモリの動的確保 **&bold(){parfor s = 1..n}(数値積分各要素に関するループ) +$\xi_{ks} = S_{ks}/\sqrt{3} $   +$N_n = \prod_k \frac{1 + S_{kn} \xi_{ks}}{2} $ +$D^\prime_{jn} = \frac{\partial N_n}{\partial \xi_j} = S_{nj} \prod_k \frac{1 + \bar{\delta}_{jk} S_{nk} \xi_{ks}}{2}$ +$J_{ij} = x_{in} D^\prime_{jn} $   [loop: n] +$G_{ij} = J_{ij}^{-1} $ +$dV = det J_{ij} $ **&bold(){end }(index s) **&bold(){end }(要素 q) 並列化パラメータの関係で一旦要素ループをここで切る。 **&bold(){parfor q = 1..q}(各要素に対するループ) -$M^q(n,n), K^q(n,n), {\cal M}^q(d,d,n,n), {\cal K}^q(d,d,n,n)$行列のメモリの動的確保・0フィル **&bold(){parfor m = 1..Σn, n = 1..Σn}(K行列等各要素に対するループ) -$D^{n,m}(d), {\cal B}^{n,m}(d,d,d)$行列のメモリ確保 -&bold(){for s = 1..n}(数値積分): リダクション(1メモリへの複数回アクセス)が噛むので並列化しないのが安泰 +$D_{im}, D_{in} = N_{n,i} = D^\prime_{jn} G_{ij} $  [loop: j] +${\cal B}_{uvjm}, {\cal B}_{klin} = \frac{1}{2} \left[ \delta_{ik} D_{ln} + \delta_{il} D_{kn} \right]$ +$K^q_{mn} += D_{im} D_{in} dV$  [loop: i] +${\cal K}^q_{ijmn} += {\cal B}_{uvjm} {\cal C}_{uvkl} {\cal B}_{klin} dV $ [loop: k,l,u,v ] +$M^q_{mn} += N_m N_n dV$ +(意図してN行列ベースの質量行列を作成したければ)${\cal M}^q_{ijmn} += \rho \delta_{ij} N_m N_n dV$ -&bold(){end } (index s) **&bold(){end }(index m, n) **&bold(){end }(要素 q) -$N^q(n, s), D^{q\prime}(d,n,s), G(d,d,s), detJ(s)$: は以後使わないので解放する。 *拘束・非ゼロ情報の登録 陰解法など全体行列が必要な場合には、合間に(CPUなど)単プロセスで自由度IDに関する整備をしておく。 メッシュ登録の段階くらいで、前もって隣接節点状況を登録しておくこと。 free = int[L_D], free_count = 0 メモリ節約のため、密自由度座標を疎行列インデックスへの変換を記録するidxは帯行列とする。 $idx = \textrm{int}\left\{ L_D \times L_d\max[L_{p,a}] \right\}$, idx_count = 0; **&bold(){for m = 1..Lp}(各節点に対するループ) **&bold(){for i = 1..Ld}(節点mの自由度) -$r = i + L_d m$ -if free(m,i) then   free(r) = free_count   free_count++ -else   free(r) = -1 -end -&bold(){for a = 1..max L(p,a)}(隣接節点に対するループ, $a > L(p,a)$ ならリターン ) -&bold(){for j = 1..Ld}(節点aの自由度) -$n = m.adjacent(a)$ : 隣接節点の番号 -$c = j + L_d a$ -if free(m,i) and free(n,j) then   idx(r,c) = idx_count   idx_count++ -else   idx(r,c) = -1 -end -&bold(){end }(index j) -&bold(){end }(隣接節点 a) **&bold(){end }(index i) **&bold(){end }(節点 m) *全体疎行列 拘束自由度を除いた全体行列を作成する。 メモリの確保は $(K,M)$ = double [idx_count] $(row, col)$ =int [idx_count] 及び $\tilde{f} =$ double [free_count] **&bold(){parfor m = 1..Lp}(各節点に対するループ) **&bold(){parfor i = 1..Ld}(節点mの自由度) +$r = i + L_d m$ +$l = free(r)$ +$\tilde{f}(idx_f) = f(r) \hspace{2em} if\ l \neq -1$ -&bold(){for a = 1..max L(p,a)}(隣接節点に対するループ, $a > L(p,a)$ ならリターン ) -&bold(){for j = 1..Ld}(節点aの自由度) +$n = m.adjacent(a)$ : 隣接節点の番号 +$qlist =m.elem(a)$ : 共有要素リスト +$c = j + L_d a$ +$k = idx(r,c)$ +$row(k) = r \hspace{2em} if\ k \neq -1$ +$col(k) = j + L_d n \hspace{2em} if\ k \neq -1 $ -&bold(){for q = 1..qlist}(各要素に対するループ) +$ K(k) += {\cal K}^q_{ijmn} \hspace{2em} if\ k \neq -1$ +必要なら $M(k) += {\cal M}^q_{ijmn} \hspace{2em} if\ k \neq -1 $ +$\tilde{f}(l) -= {\cal K}^q_{ijmn} u( j + L_d n) \hspace{2em} if\ l \neq -1 $ -&bold(){end }(要素 q) -&bold(){end }(index j) -&bold(){end }(隣接節点 a) **&bold(){end }(index i) **&bold(){end }(節点 m) **最終的な連立方程式に $ A = K - \omega^2 M $など *連立方程式を解く $ \tilde{\bf u} = A^{-1} \tilde{\bf f} $ 直接法(dgesv_やmatlabならバックスラッシュ)・反復法(CG法他)など適切なルーチンで。 $free$を利用して$\tilde{\bf u}$を配り直して、出力しておしまい。 #javascript(){{ <script type="text/x-mathjax-config"> MathJax.Hub.Config({ tex2jax: {inlineMath: [ ['$','$'], ["\\(","\\)"] ], processEscapes: true }, TeX: { Macros: {L: '\\Large\\displaystyle'}}}); </script> <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script> }} #javascript(){{ <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-22313036-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> }}

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー