逆行列、行列式とできたので、連立一次方程式を解かせる。有限要素法のいわゆる「solve」というやつで、解析の手順として、
- pre : 構造を設定、要素に分割
- solve : 連立一次方程式を解く(それだけじゃない?)
- post : ひずみの結果を表示する
という手順になっている。
Gauss の消去法を使って直接的に解くわけだが、これって、そのまんま LU 分解なわけで。なので、solve 自体は反復法なども含めた意味で使わないとダメっぽい。
let solve (A' : matrix) (F': vector) = let A = A'.Copy() let F = F'.Copy() let n = A.NumCols-1 // 前進消去 for i in 0..n-1 do for j in i+1..n do let p = A.[j,i]/A.[i,i] F.[j] <- F.[j] - p * F.[i] for k in 0..n do A.[j,k] <- A.[j,k] - p * A.[i,k] // 後退代入 F.[n] <- F.[n]/A.[n,n] for i in n-1..-1..0 do for j in i+1..n do F.[i] <- F.[i] - A.[i,j]*F.[j] F.[i] <- F.[i]/A.[i,i] F [/code] <p> 「有限要素法概説」にあった前進消去「上三角化」したあとに後退代入でひとつずつ計算する。 </p> [code lang="csharp"] // 2x -y = 2 // -x +2y= 5 を解く let M = matrix[[2.;-1.]; [-1.;2.]] let F = vector[2.0;5.0] solve M F
こんな風にいれておいて、実行すると
val it : Vector<float> = vector [|3.0; 4.0|]
こんな風に結果が出る。
実は、F# MathProvider にも同じものがあって、
let M = matrix[[2.;-1.]; [-1.;2.]] let F = vector[2.0;5.0] let sol = MathProvider.LinearAlgebra.solve M F
として解くと同じ事ができる。
有限要素法の場合、ひとつの節点の自由度は6になるので、節点の数の6倍の計算量になる。さらに、要素が持つ節点(頂点)は三角形二次要素場合は6点になるので、要素数の36倍の計算量なる。が、計算量が多くなるといっても、多くなっても2桁増えるぐらいだから大したことはない?ことはないか。前進消去で、n^3/2 ぐらいのオーダーになるので、n が 100倍になると、100万倍ぐらいの計算量が増える。となると、この素直な方法で解いてしまうと、メッシュ数を2倍細かくすると約8倍の計算量が必要になる。確かに、高速化が必要な分野であるかも。
このあたりは後で実測して試してみよう。
あらためて線形代数を読み直したのだが、行列式自体は余因子展開で解けるので、逆行列自体は必要ない。が、有限要素法の連立一次方程式を解くには必要…という訳もなく、後でわかったんだけど、逆行列を使うよりもLU分解したほうが計算量は少なくて済む。ここのあたりは、きっちりとやらないと。