ソフトウェア開発 趣味

科学技術計算向けプログラミング言語「Julia」を使った構造解析(1) 固有値解析を実装してみる

更新日:

Juliaとは?

プログラミング言語「Julia」とは、主に科学技術計算のために開発された比較的新しいプログラミング言語です。公式ホームページから抜粋すると、以下のような特徴を持ちます。

Juliaは、R、MATLABおよびPythonなどの言語と同様に、 高いレベルの計算処理における手軽さと見やすさを提供し、また一般的な プログラミングにも対応が可能です。

Julia公式ページ https://hshindo.github.io/julia-doc-ja-v0.6/manual/introduction.html

つまり、現在非常に世界的に人気の高い言語であるPythonのような書きやすさを持ちながら、行列演算で非常に強力な言語であるMATLABのような高度な行列演算機能を有する言語ということになります。加えて、以下のような特徴があることが個人的には非常に魅力的に感じました。

  • コンパイル言語並みに高速に動作する。
  • Pythonのライブラリを簡単に扱える。

つまり、言語としての使いやすさを追求するだけでなく高速な演算能力も両立し、豊富なライブラリによって人気を博しているPythonの資産も活用できる、まさに良いとこどりといえる言語です。

ただし、プログラミング言語は実際に使ってみないと真価はわかりません。そこで今回はまず固有値解析を題材にJuliaを使ってみたいと思います。

インストールする

インストールは公式サイトからインストーラをダウンロードできます。

公式サイト : https://julialang.org/

なお、インストールが自由にできる環境にない、もっと気軽に試したい、という方のために、ブラウザ上でコードを記述、実行、保存できるサービス「JuliaBox.com」が公式に用意されています。

JuliaBox : https://www.juliabox.com/

今回は上記のJuliaBoxを使ってみました。

行列演算を試してみる

まずはどの程度簡単に行列が使えるか試してみます。

まずは剛性マトリクス、外力ベクトルを用意して静的応力解析を行ってみます。以下のようなモデルを定義します。ソースコードは下記です。

using LinearAlgebra
 
# 剛性マトリクス
K = [
     15.0   -15.0
    -15.0    30.0    
]
 
# 外力ベクトル
P = [ 50.0, 30.0 ]
 
# K * d = P から変形ベクトルdを求める
d = K \ P

JuliaBoxでの実行結果は以下です。非常に簡単なコードで解が求まりました。特筆すべきは行列の可読性です。人間にも読みやすい形で記述することができます。

固有値解析を試してみる

もう少しだけ高度な解析として質点系振動モデルの固有値解析を例に固有値解析を行います。

固有値解析とは以下のような関係が成り立つ{u}≠{0}の解を求める計算になります。

\( ( -ω^2[M]+[K] ) \{u\} = \{0\} \)

ω : 固有円振動数, [M] : 質量マトリクス, [K] : 剛性マトリクス

まずは質点系振動モデルを作るための関数群を定義します。

 
# 線形代数ライブラリ
using LinearAlgebra
 
# 質点系の構造体
mutable struct LumpedMassModel
    size::Int64
    m::Array{Float64, 1}
    c::Array{Float64, 1}
    k::Array{Float64, 1}
 
    LumpedMassModel() = new()
end
 
# 全体マトリクスに部分マトリクスを加算する
# full : 全体マトリクス
# part : 部分マトリクス
# row, clm : 加算する位置(左上の行、列)
function addToFullMatrix(full, part, row, clm)
    row_length = length(full[1, :])
    clm_length = length(full[:, 1])
 
    # rowが全体剛性マトリクスに含まれるか
    if 0 < row <= row_length 
        # clmが全体剛性マトリクスに含まれるか
        if 0 < clm <= clm_length
            full[row, clm] += part[1, 1]
        end
        # clm + 1が全体剛性マトリクスに含まれるか
        if 0 < clm + 1 <= clm_length 
            full[row, clm + 1] += part[1, 2]
        end
    end
 
    # row + 1が全体剛性マトリクスに含まれるか
    if 0 < row + 1 <= row_length
        # clmが全体剛性マトリクスに含まれるか
        if 0 < clm <= clm_length
            full[row + 1, clm] += part[2, 1]
        end
        # clm + 1が全体剛性マトリクスに含まれるか
        if 0 < clm + 1 <= clm_length 
            full[row + 1, clm + 1] += part[2, 2]
        end
    end
end
 
# 質量マトリクスを作成する関数
function buildMassMatrix(model)::Array{Float64, 2}
    size = model.size
    mat  = zeros(Float64, size, size)
    for index in 1:size
        mat[index, index] = model.m[index] 
    end
    return mat
end
 
# 剛性マトリクスを作成する関数
function buildStiffnessMatrix(model)::Array{Float64, 2}
    size = model.size
    mat = zeros(Float64, size, size)
    for story_index in 1:size
        # 階のばね値を取得
        k = model.k[story_index]
 
        # ばねの剛性マトリクスを構築
        part = [
             k  -k
            -k   k
        ]
 
        # 全体剛性マトリクスに加算
        # 層間に配置するため、story_index - 1 ~ story_index の間
        addToFullMatrix(mat, part, story_index - 1, story_index - 1)
    end
    return mat
end

つづいて、これを使って5質点系モデルを作るコードです。

sample = LumpedMassModel()
sample.size  = 5
sample.m     = [200.0, 200.0, 200.0, 200.0, 200.0]
sample.k     = [8000.0, 7000.0, 6000.0, 5000.0, 4000.0]
mmat         = buildMassMatrix(sample)
kmat         = buildStiffnessMatrix(sample)    
amat         = kmat/mmat
eigen_values = eigvals(amat)
eigen_vector = eigvecs(amat)
 
# 固有値はω^2なので、固有周期に変換する
map(eigen_values) do omega2 2.0 * pi / (omega2 ^ 0.5) end

以下に実行結果を示します。固有周期が算出できました。

固有周期のほかに固有ベクトルも求まっています。Juliaには可視化ライブラリも用意されていますので、固有ベクトルを可視化してみます。ソースコードは以下です。

Pkg.add("Plots")
using Plots
 
function mode_values(eigen_vector, mode_index)
    eigvec1 = eigen_vector[:, mode_index]
    size = length(eigvec1)
    heights = []
    push!(heights, 0.0)
    insert!(eigvec1, 1, 0.0)
    for index in 1:size
       push!(heights, float(index)) 
    end
    return (eigvec1, heights)
end
 
function view_mode(eigen_vector, mode_index)
    (eigvec, heights) = mode_values(eigen_vector, mode_index)
    plot(eigvec, heights)
end
function view_modes(eigen_vector)
    size = length(eigen_vector[1, :])
 
    mat_x = []
    mat_y = []
    for mode_index in 1:size
        (eigvec, heights) = mode_values(eigen_vector, mode_index)
        push!(mat_x, eigvec)
        push!(mat_y, heights)
    end
    plot(mat_x, mat_y)
 
end
 
 
view_modes(eigen_vector)

実行結果は以下です。

このように、行列の演算、可視化まで非常にスムーズに行うことができました。

まとめ

Juliaは科学技術計算向けプログラミング言語と称するだけあって、今回紹介した機能のほかにも多様な機能があります。その2では応用として、複素固有値解析の実装について書きたいと思います。

参考になった! (まだ評価がありません)
読み込み中...

問い合わせ先

各種ご相談は下記連絡先でお受けしております。

  • 解析コンサルティングのご依頼
  • ソフトウェアのご購入、レンタルのご相談
  • プログラム、システム受託開発のご相談

株式会社構造計画研究所 エンジニアリング営業部


クリックすると、お問い合わせフォームが別ウィンドウで開きます。

-ソフトウェア開発, 趣味

Copyright Ⓒ 2019 KOZO KEIKAKU ENGINEERING Inc. All Rights Reserved.