Scilabで二重積分

Scilabを利用すると1変数の数値積分が簡単に計算できます。

\begin{equation}
\int_{x_0}^{x_1}f(x)\mathrm{d}x
\end{equation}

このブログでも数値積分タグにいくつかの例を見つけることができます。しかしながら、2変数の数値積分はこれまで行ってきませんでした。

\begin{equation}
\int\int f(x,y) \mathrm{d}x\mathrm{d}y
\end{equation}

Scilabには二重積分を計算することが可能な int2d が存在します。今回は高校数学の美しい物語で解析的に解かれている二重積分を数値的に計算してみます。


積分範囲が長方形領域の場合


積分範囲が長方形の領域の場合、すなわち以下のような式で表すことができる場合は、簡単に数値積分できます。

\begin{equation}
\int_{x_0}^{x_1}\int_{y_0}^{y_1}f(x,y)\mathrm{d}x\mathrm{d}y
\end{equation}

Scilabの int2d では長方形領域を2つの三角形のパッチワークとして与えます。
積分範囲を int2d に渡すために行列XとYを用意します。それぞれ2つの三角形の頂点のx座標とy座標を与えます。

\begin{equation}
X =
\begin{pmatrix}
x_{0} & x_{0} \\
x_{1} & x_{1} \\
x_{1} & x_{0} \\
\end{pmatrix},
Y =
\begin{pmatrix}
y_{0} & y_{0} \\
y_{0} & y_{1} \\
y_{1} & y_{1} \\
\end{pmatrix}
\end{equation}

001_20170423145553b2b.png
Fig.1: Scilabのint2dへの積分範囲の与え方


実際に以下の積分を計算して見ます。

\begin{equation}
\int_{0}^{\pi}\int_{0}^{R}x^4 \sin(y)\mathrm{d}x\mathrm{d}y
\end{equation}

clear;

r = 1;

// *** 積分する関数の定義 ***
function z = func(x,y)
z = (x .^ 4) * sin(y)
endfunction
// 積分範囲
x0 = 0; x1 = r;
y0 = 0; y1 = %pi;

// *** 二重積分 ***
X = [x0, x0;
x1, x1;
x1, x0];
Y = [y0, y0;
y0, y1;
y1, y1];
// 数値解
I = int2d(X, Y, func)
// 解析解
A = 2*(r^5)/5


数値化解と解析解が同じ値になることが確認できます。

積分範囲が三角形の組み合わせで表せる場合


積分範囲が長方形の場合は2つの三角形の組み合わせで表現されますが、より複雑な形状の場合も任意の個数の三角形の組み合わせで表現できるはずです。今回は逆に簡単になってしまいますが、1個の三角形で表現できる例を計算します。

\begin{equation}
\int \int_D xy^2 \mathrm{d}x\mathrm{y}
\end{equation}

jusekibun.png
Fig.2: 積分領域Dが三角形ひとつ分の例


積分領域が三角形ひとつ分なので、与える行列は3行1列になります。

\begin{equation}
X =
\begin{pmatrix}
x_{0} \\
x_{1} \\
x_{1} \\
\end{pmatrix},
Y =
\begin{pmatrix}
y_{1} \\
y_{0} \\
y_{1} \\
\end{pmatrix}
\end{equation}

この計算を行うScilabスクリプトは以下のようになります。

clear;

// *** 積分する関数の定義 ***
function z = func(x,y)
z = x .* (y .^ 2)
endfunction

// *** 二重積分 ***
X = [0;
1;
1];
Y = [1;
0;
1];
// 数値解
I = int2d(X, Y, func)
// 解析解
A = 3/20


このスクリプトも数値解と解析解が同じに値になることが分かります。

同様にしてN個の三角形の組み合わせで表現される積分範囲の場合3行N列の行列で指定することができます。

更に複雑な積分領域の場合


どんなに複雑な積分領域の形状であっても三角形のパッチワークで表現できるはずですが、現実的には大変です。そこでOctaveの精義―フリーの高機能数値計算ツールを使いこなすで紹介されている方法を試してみましたが、現状うまく行っていません。上手く行っていませんがとりあえず方法だけは紹介します。
具体的にはScilabの論理演算で条件分岐の考え方を使って積分領域外では値がゼロになるように被積分関数の定義を行います。

\begin{equation}
\int\int_D -\frac{1}{(2x + y + 1)^2}\mathrm{d}x\mathrm{d}y
\end{equation}

jusekibun2.png
Fig.3: 複雑な積分領域の例


clear;

// *** 積分する関数の定義 ***
function z = func(x,y)
region = y >= x .^ 2
z = - 1 ./ ((2 * x + y + 1) .^ 2) .* region
endfunction

// *** 二重積分 ***
X = [0;
1;
1];
Y = [0;
0;
1];
// 数値解
I = int2d(X, Y, func)
// 解析解
A = (1/3) * log(4) - 1/2


原理的にはこのスクリプトでよいはずですが、実際には正しく計算してくれません。Scilab 6.0ではエラーで停止します。Scilab 5.5.2ではそれっぽい値を返しますが、解析解の値とはかなりずれた値となっており、不正確です。

関連エントリ




参考URL




付録


このエントリで使用したファイルを添付します。ファイル名末尾の".txt"を削除して、"_"を"."に変更すれば使えるはずです。(参考:ねがてぃぶろぐの付録)


参考文献/使用機器




フィードバック



にほんブログ村 その他趣味ブログ 電子工作へ

 ↑ 電子工作ブログランキング参加中です。1クリックお願いします。


コメント・トラックバックも歓迎です。 ↓      


 ↓ この記事が面白かった方は「拍手」をお願いします。

tag: Scilab 数値積分 重積分 

Scilabで数値積分:地球深部の密度と圧力

Scilabで数値積分: 固体の比熱ではintegrate関数を用いてデバイモデルから結晶固体の比熱を計算しました。
またScilabで乱数による関数の積分ではモンテカルロ法を用いて関数の積分を行いました。

これらはいずれも既知の関数f(x)について具体的な積分範囲、たとえばa≦x≦bでの積分値

\int_a^b f(x)\mathrm{d}x

を求める手法でした。

これらの方法では関数f(x)の形が式として分かっている必要があります。
しかしながら、離散的な数値データに対する積分値が計算したい場合もあります。

001_201311020335151bb.png

Fig.1: 地球の内部構造(世界初!地球中心部の超高圧高温状態を実現 ~ようやく手が届いた地球コア~より)


今回は地球内部の密度を表す数値表から、数値積分を使って重力加速度と圧力の深さ依存性を計算します。



標準地球モデル:PREM


地球内部の構造は、地震波観測からfig.1のような層構造をしていることが知られています。
もっとも有名な地球内部構造のモデルはDziewonski and Anderson (1981)によるPREM(Preliminary Reference Earth Model)と呼ばれるものです。

002_20131102033515160.png

Fig.2: 地球内部の地震波速度分布と密度分布。横軸は地球の中心からの距離(半径)。


PREMにはP波速度、S波速度、密度の深さごとの値、及びこれら3つの数値から計算できる重力加速度、圧力などが表として掲載されています。(参考:PREMの表地球を貫通するトンネル内の落下運動)

今回はPREMの密度から重力加速度と圧力を計算し、PREMの論文の中の値と比較して計算結果のチェックを行います。

重力加速度の計算


高校物理では重力加速度は約9.8[m/s]として計算をすると思います。
重力加速度はは大きな質量を持つ地球から万有引力によって引っ張られる力に起因しているため、地球内部では重力加速度の値が地球表面の値とは異なります。

地球の中心からr[m]での密度をρ(r)[g/m3]とするとr[m]より深い部分の質量M(r)[g]は

M(r) = 4 \pi \int_0^r u^2 \rho(u) \mathrm{d}u

重力加速度は、万有引力の法則より

g(r) = G\frac{M(r)}{r} = \frac{4\pi G}{r}\int_{0}^{r}u^2\rho(u)\mathrm{d}u

ここでGは万有引力定数G=6.67259×10-14[m3/s2/g]です。
PREMの数値データはPREM.txtに保存しfscanfMat等を用いてScilabから読み出しを行います。離散データの数値積分にはinttrapを用いました。

重力加速度計算の積分のところだけ抜き出すと、以下のようになります。

// *** 重力加速度の計算 ***
Gravity_num = zeros(Radius);
for i = 2:length(Gravity_num)
Gravity_num(i) = 4 * %pi * grav / (Radius(i) ^ 2) * inttrap(Radius(1:i), Radius(1:i) .^ 2 .* RHO(1:i));
end


圧力の計算


地球内部では非常に長い地質学的時間のなかで静水圧平衡が成り立っていると考えることが出来るため、圧力の計算が出来ます。

\frac{\mathrm{d}P}{\mathrm{d}r} = - \rho(r)g(r)

これを素直に積分すると以下の式が得られます。

\int\mathrm{d}P = - \int\rho(r)g(r)\mathrm{d}r

文字を置き換えて

\int\mathrm{d}Q = - \int\rho(u)g(u)\mathrm{d}u

地球表面rsでの圧力Ps(つまり大気圧)から地球深部rの圧力Pまで積分すると

\int_{P_s}^{P}\mathrm{d}Q = - \int_{r_s}^r\rho(u)g(u)\mathrm{d}u

大気圧はPs=1013.25[hPa]ですが、これは地球内部の圧力である数[GPa](数万気圧)と比べて充分小さいので左辺はほぼ地球深部の圧力Pと考えることが出来ます。

\int_{P_s}^{P}\mathrm{d}Q = P - P_s \simeq P

したがって圧力は以下のような積分で計算することが出来ます。

P = \int_{r}^{r_s}\rho(u)g(u)\mathrm{d}u

この積分を行う部分をScilabのプログラムから抜粋すると以下のようになります。

// *** 圧力の計算 ***
Pressure_num = zeros(Radius);
for i = 1:length(Pressure_num)-1
Pressure_num(i) = inttrap(Radius(i:$), RHO(i:$) .* Gravity_num(i:$));
end


計算結果


重力加速度と圧力の計算結果をFig.3に示します。

003_20131102033515738.png

Fig.3: 地球内部の重力加速度(上)と圧力(下)


赤の実線で示されたのがPREMの表にある値で、青の破線で示したのが今回積分から計算された値です。多少の誤差が発生しているようですが、おおよそ上手く計算できています。

全ソースコードはDeepEarth_sce.txtです。

clear;

// *** 物理定数 ***
grav = 6.67259e-14; // 万有引力定数 (m^3/s^2 g)

// *** PREMのテーブルを読み出し ***
X = fscanfMat('PREM.txt');
Radius = 1E3 * X(:,1); // 半径 (m)
Vp = X(:,2); // P波速度 (m/s)
Vs = X(:,3); // S波速度 (m/s)
RHO = 1E3 * X(:,4); // 密度 (g/m^3)
Ks = 1E12 * X(:,5); // 断熱体積弾性率(Pa)
Mu = 1E12 * X(:,6); // 剛性率(Pa)
Nu = 1E12 * X(:,7); //
Pressure = 1E12 * X(:,8); // 圧力(Pa)
Gravity = X(:,9); // 重力加速度 (m/s^2)

// *** 重力加速度の計算 ***
Gravity_num = zeros(Radius);
for i = 2:length(Gravity_num)
Gravity_num(i) = 4 * %pi * grav / (Radius(i) ^ 2) * inttrap(Radius(1:i), Radius(1:i) .^ 2 .* RHO(1:i));
end

// *** 圧力の計算 ***
Pressure_num = zeros(Radius);
for i = 1:length(Pressure_num)-1
Pressure_num(i) = inttrap(Radius(i:$), RHO(i:$) .* Gravity_num(i:$));
end

// *** 地震波速度と密度のプロット ***
scf(0)
// 地震波速度
xsetech([0,0,1,0.45]);
plot(1E-3 * Radius, 1E-3 * Vp,'-r');
plot(1E-3 * Radius, 1E-3 * Vs,'-b');
legend(["Vp","Vs"],1);
ylabel("Velocity (km/s)");
xlabel("Radius (km)");
// 密度
xsetech([0,0.45,1,0.45]);
plot(1E-3 * Radius, 1E-3 * RHO,'-r');
ylabel("Density (kg/s^3)");
xlabel("Radius (km)");

// *** 重力加速度と圧力のプロット ***
scf(1)
// 重力加速度
xsetech([0,0,1,0.45]);
plot(1E-3 * Radius,Gravity,'-r');
plot(1E-3 * Radius,Gravity_num,'--b');
legend(["Table","Numerical"],4);
ylabel("Acceleration of gravity (m/s^2)");
xlabel("Radius (km)");
// 圧力
xsetech([0,0.45,1,0.45]);
plot(1E-3 * Radius,1E-12 * Pressure,'-r');
plot(1E-3 * Radius,1E-12 * Pressure_num,'--b');
legend(["Table","Numerical"],1);
ylabel("Pressure (GPa)");
xlabel("Radius (km)");


台形積分とスプライン積分


今回使用したinttrapは、データ店の間を直線で補完する(要するに台形の面積を計算する)台形積分です。
もう少し高度な計算をするスプライン積分もintsplinを使って計算することが出来ます。
入力するパラメータも同じなので、多くの場合そのまま置き換えることが出来るでしょう。

ただし今回のPREMのようにデータが不連続となる点で複数の値を持っているような表の積分を行うときにはintsplinでは下記のようなエラーが出ます。

!--error 999 
splin: 入力引数 #1 の値が間違っています: (厳密に)昇順ではありません, もしくは +-inf を検出しました.


このような場合は、今回のように台形積分inttrapを使います。

関連エントリ




参考URL




付録


このエントリで使用したScilabのシミュレーション用ファイルを添付します。ファイル名末尾の".txt"を削除して、"_"を"."に変更すれば使えるはずです。(参考:ねがてぃぶろぐの付録)


参考文献/使用機器




フィードバック



にほんブログ村 その他趣味ブログ 電子工作へ

 ↑ 電子工作ブログランキング参加中です。1クリックお願いします。


コメント・トラックバックも歓迎です。 ↓      


 ↓ この記事が面白かった方は「拍手」をお願いします。

tag: Scilab 数値積分  マントル 

Scilabで乱数による関数の積分

Scilabには関数の積分の計算を行うintegrateがあるため簡単な関数の積分には必要が無いのですが、乱数を使った積分の方法について書きます。
[0,1]の範囲で一様分布な乱数列を{Xk}k=1,2...nとすると関数f(x)の積分は以下のようにして計算することが出来ます。

\begin{eqnarray}\int_a^b f(x) \mathrm{d}x & = & \int_0^1 f(a+(b-a)r)(b-a)\mathrm{d}r \\ & = & \lim_{n \to \infty} \frac{1}{n}\sum_{k=1}^{n}f(a+(b-a)X_k)(b-a) \end{eqnarray}


乱数による積分の考え方


[0,1]の範囲の一様分布な乱数列{Xk}k=1,2...nはScilabを使うと簡単に得られます。(参考:Scilabで乱数の生成,Scilabでコイン投げ)

このとき関数f(x)の積分は、f(Xk)の平均から求めることが出来るでしょう。

\int_{0}^{1}f(x)\mathrm{d}x = \lim_{n \to \infty} \frac{1}{n} \sum_{k=1}^{n}f(X_k)

例として、以下に挙げる具体的な関数f(x)に対して積分の計算をします。

f(x) = \exp(-x^2)

関数f(x)のグラフはFig.1のような形になります。積分は0≦x≦1の範囲の面積を求めることと同じです。


001_20130926022100898.png
Fig.1: 関数f(x)=exp(-x2)のグラフ


Scilabで楽しむ確率論(PDF)では、本文中に書いてある数式と実際にScilabで計算している数式が異なっています。本エントリではプログラムの方にあわせることにします。

モンテカルロ法以外の計算法


実際のところ、この程度の関数なら乱数を用いたモンテカルロ法を使うよりも、素直に数値積分をするほうがはるかに良い結果が得られます。

Scilabではintegrateをつかって簡単に数値積分が出来ます。(参考:Scilabで数値積分: 固体の比熱)
また、もっと基本的な方法として、解析的に原始関数を決められないか考えるという方法もあります。Maximaを使って不定積分を行うと以下のような結果が得られました。

\int f(x)\mathrm{d}x = \frac{\sqrt{\pi} \mathrm{erf}(x)}{2} + C(C: 積分定数)

まあこの場合は誤差関数erfが入っているので数値積分から逃れられてはいないというのも事実ではありますが。

数値積分、解析的な積分、乱数を使った積分のそれぞれの方法で積分値を計算するScilabのプログラムがfunc_sce.txtです。
数値積分と解析的な積分の両方の方法で、積分の値は0.7468241となりました。モンテカルロ法で求めた値もおおよそ同じくらいになります。

clear;

// *** 関数の定義 ***
// 関数f(x)
deff('y = f(x)','y = exp(- x .^ 2)');
// 原始関数F(x)
deff('y = F(x)','y = sqrt(%pi) .* erf(x) ./ 2');

X = linspace(0,5);

// *** グラフの描画 ***
plot(X,f(X));
xlabel("x");
ylabel("f(x)");

// *** 積分の計算 ***
// 解析的な積分
F(1) - F(0)
// 数値積分
integrate('f(x)','x',0,1)
// モンテカルロ積分
n = 1000;
mean(f(rand(1,n)))


ヒストグラム


このモンテカルロ法による積分を複数回行ったときのヒストグラムをFig.2へ示します。
確かにintegrateで求めた値を中心にばらついていることが分かります。


002_20130926022059bb7.png
Fig.2: 積分結果のばらつきを示すヒストグラム


積分範囲の変更


次に積分範囲がa≦x≦bの場合へ拡張します。方法は単純モンテカルロ積分 (2)の通りです。

a \leq x \leq b
0 \leq x - a \leq b - a
0 \leq \frac{x - a}{b - a} \leq 1

\frac{x-a}{b-a} = r

とおくと0≦r≦1となるので、置換積分を考えればよいことになります。

x = a+(b-a)r
\frac{\mathrm{d}x}{\mathrm{d}r} = b-a
\mathrm{d}x=(b-a)\mathrm{d}r

したがって

\begin{eqnarray}\int_a^b f(x) \mathrm{d}x & = & \int_0^1 f(a+(b-a)r)(b-a)\mathrm{d}r \\ & = & \lim_{n \to \infty} \frac{1}{n}\sum_{k=1}^{n}f(a+(b-a)X_k)(b-a) \end{eqnarray}

となります。

関連エントリ




参考URL




付録


このエントリで使用したScilabのシミュレーション用ファイルを添付します。ファイル名末尾の".txt"を削除して、"_"を"."に変更すれば使えるはずです。(参考:ねがてぃぶろぐの付録)


参考文献/使用機器




フィードバック



にほんブログ村 その他趣味ブログ 電子工作へ

 ↑ 電子工作ブログランキング参加中です。1クリックお願いします。


コメント・トラックバックも歓迎です。 ↓      


 ↓ この記事が面白かった方は「拍手」をお願いします。

tag: Scilab 数値積分 乱数 モンテカルロ解析 Maxima 

Scilabで二酸化炭素の状態方程式 その2

Scilabで二酸化炭素の状態方程式 その1では、Scilabを用いてファンデルワールスの状態方程式を解くプログラムを作成しました。

\left(P + \frac{a^2}{V} \right) (V-b)=RT

(P: 圧力, V: モル体積, R: 気体定数, T: 絶対温度, a, b: ファンデルワールス定数)

実はファンデルワールスの状態方程式は気体の体積だけでなく、液体や気体・液体共存のときのP,V,Tも計算することが出来ます。
この計算を行う際にMaxwellの規則を利用します(参考:ファン・デル・ワールスの状態方程式 (クラウジウス=クラペイロンの式、ジュール=トムソン効果)3.液体・気体共存領域)。Maxwellの規則ではグラフの面積が等しくなる条件を用いますが、こういった条件を探すのは、解析的には難しく、数値計算の出番となります。

004_20130811163805e0f.png

Fig.1: T = 250 (K)のときの二酸化炭素の圧力Pとモル体積Vの関係。グラフ中の赤の水平線の部分が液体・気体の共存領域、それよりも右側が気体の安定領域で左側が液体の安定領域。赤の水平線は、赤の水平線と赤の点線で囲まれた二つの領域の面積が等しくなる条件から引かれる。(Maxwellの規則)



二酸化炭素の相図


常温・常圧の二酸化炭素は気体ですが、固体の二酸化炭素といえばドライアイスです。ドライアイスは室温においておくと液体にならずに気体になりますが、5.1×105(Pa)つまり5気圧以上では水などと同様に液体になります。
以下に示すのは、ファン・デル・ワールスの状態方程式 (クラウジウス=クラペイロンの式、ジュール=トムソン効果)から引用した二酸化炭素の相図です。相図(Phase diagram, 状態図とも)は物質の状態(固体,液体,気体)と温度・圧力・化学組成の関係性を表した図です。



液体・気体共存領域


ファンデルワールスの状態方程式の1つの特徴として気体と液体の相転移を表すことができる点が挙げられます。
このときの液体、気体のそれぞれのモル体積は、Fig.1に示したとおりファンデルワールスの状態方程式と水平線の一番左の交点と一番右の交点として表されます。
またこの水平線は、水平線と状態方程式の作る二つの領域の面積が等しくなる条件から引くことが出来ます。
これをMaxwellの規則と呼び、数式で表すと以下のようになります。

\int_{V_l}^{V_g}P_{vdw}\mathrm{d}V - \int_{V_l}^{V_g}P_k \mathrm{d}V = 0

ただしPvdwがファンデルワールスの状態方程式で計算した圧力、Pkが水平線の圧力です。これらの交点のうち一番左の物が液体の体積Vlで一番右のものが気体の体積Vgです。

数値計算


色々な教科書に水平線Pkは面積が等しくなる条件から決定することが出来ると簡単に書かれていますが、Pkを決めないと交点Vg,Vlが決まらないため、Pkを決めるためには数値計算が必要です。

この計算にはScilabで金属の化学ポテンシャルScilabでおもりの吊り下げで利用した非線形方程式ソルバfsolveが使えます。

まずPkとPvdw(V)が与えられているとして3つの交点の値を求めます。
交点の値は、ファンデルワールスの状態方程式を変形して得られる以下の三次方程式の解です。

P_k V^3 - (b P_k + RT) V^2 + aV - ab = 0

Scilabでは多項式の解はrootsを用いて簡単に計算できます。解は複素数の要素を持つ縦ベクトルになります。Scilab言語には(C言語のような)型の宣言が無いのでミスを犯しやすいのですが、解の全ての要素が実部しか持たなかったとしても、変数の型としては複素数なので、realをつかって実数型へ変換する必要があります。

数値積分にはScilabで数値積分: 固体の比熱Scilabで関数フィッティング: 金属の電気抵抗で使ったintegrateを利用します。

最終的なプログラムはCO2-subcritical_sce.txtです。

clear;

// *** 入力パラメータ ***
// 物理定数
r = 8.31 // 気体定数 (J/K/mol)

// 二酸化炭素のファンデルワールス状態方程式
a = 3.65E-1; // Pa m^6 / mol^2
b = 4.28E-5; // m^3 / mol
// 温度 (K)
t = 250;

// *** ファンデルワールスの状態方程式 **
function p = pvdw(v)
p = r .* t ./ (v - b) - a ./ v ./ v
endfunction

// *** 解くべき方程式 ***
function e = func(pk)
Vx = roots([pk, -1 * (b * pk + r * t), a, - a * b]);
vg = max(real(Vx));
vl = min(real(Vx));
s1 = integrate('pvdw(v)','v',vl,vg);
s2 = (vg - vl) * pk;
e = s1 - s2;
endfunction

// *** 非線形方程式の数値解 ***
pk0 = %eps;
pk = fsolve(pk0,func);

Vx = roots([pk, -1 * (b * pk + r * t), a, - a * b]);
vg = max(real(Vx));
vl = min(real(Vx));

// *** 圧力の計算とプロット ***
// モル体積ベクトル
Vl = linspace(b,vl,1000) + %eps; // (m^3 / mol)
Vm = linspace(vl,vg,1000); // (m^3 / mol)
Vg = linspace(vg,1e-3,1000); // (m^3 / mol)
// 温度
plot(Vl,pvdw(Vl),'-r');
plot(Vm,pk,'-r');
plot(Vm,pvdw(Vm),'--r');
plot(Vg,pvdw(Vg),'-r');
// *** グラフの装飾 ***
xlabel("Molar volume (m^3/mol)");
ylabel("Pressure (Pa)");
plot([b,b],[-1E8,2E7],'--k');
plot([0,0.001],[0,0],'--k');
zoom_rect([0,-2E6,1E-3,2E7]);


関連エントリ




参考URL




付録


このエントリで使用したScilabのシミュレーション用ファイルを添付します。ファイル名末尾の".txt"を削除して、"_"を"."に変更すれば使えるはずです。(参考:ねがてぃぶろぐの付録)


参考文献/使用機器




フィードバック



にほんブログ村 その他趣味ブログ 電子工作へ

 ↑ 電子工作ブログランキング参加中です。1クリックお願いします。


コメント・トラックバックも歓迎です。 ↓      


 ↓ この記事が面白かった方は「拍手」をお願いします。

tag: Scilab 非線形方程式ソルバ 数値積分 状態方程式 熱力学 

Scilabで単振り子 その1 解析解との比較

これまで微分方程式による物理現象のモデル化(PDF)から運動学の章で紹介されている微分方程式をScilabを用いて計算してきました。
今回から4回は単振り子の微分方程式をScilabで計算します。

001_20130720182725.png

Fig.1: 単振り子の問題設定



単振り子の微分方程式と解析解


導出は次回に回しますが、単振り子の運動を表す微分方程式は、以下のように書くことが出来ます。

\frac{\mathrm{d}\theta}{\mathrm{d}t} = q
\frac{\mathrm{d}^2\theta}{\mathrm{d}t^2} = - \frac{g}{L}\sin\theta

(θ: 振れ角, t: 時間, q: 角速度, g: 重力加速度, L: 糸の長さ)

この微分方程式は、解析的に解を求めることが出来ます。
例えば、初角度θ0から初角速度q0=0で振動を開始したとすると下記のようになります。

t(\theta) = - \sqrt{\frac{L}{2g}}\int^{\theta}_{\theta_0}\frac{\mathrm{d}\theta}{\sqrt{\cos\theta - \cos\theta_0}}

しかしながら、この積分は初等関数で表せる形に出来ないので、結局は数値積分をせざるを得ません。

今回は、これまでと同様にScilabの常微分方程式ソルバodeを用いて振りこの運動をシミュレーションするとともに、解析解に対する数値積分も行い、これら二つを比較します。

プログラミング


常微分方程式ソルバはode関数を使います。(参考:常微分方程式のタグが付いたエントリ)

解析解のほうの数値積分はintegrate関数を用いました。(参考:Scilabで数値積分: 固体の比熱,integrate - 求積法による積分)

// *** 解析解とソルバ解の共通部分 ***
// 初期振幅の入力
g = 9.8; // 重力加速度
l = g / (2 * %pi) ^ 2; // 糸の長さ
// 初期条件
th0 = input("th0 = "); // 初角度
q0 = 0; // 初角速度
X0 = [th0; q0];

// *** 常微分方程式ソルバによる解 ***
// 解くべき微分方程式の定義
function dx = pend(t,x)
dx(1) = x(2);
dx(2) = - g / l * sin(x(1));
endfunction
T = linspace(0,2,200); // 時間ベクトル
TH = ode(X0, 0, T, pend); // 常微分方程式ソルバ
plot(T,TH(1,:),'-r'); // プロット

// *** 解析解 ***
THanaly = linspace(- th0, th0, 20);
Tanaly = - sqrt(l / (2 * g)) * integrate('1 ./ sqrt(cos(th) - cos(th0))','th',th0,THanaly);
plot(Tanaly,THanaly,'og');

// *** グラフの体裁 ***
legend("o.d.e","integration",1);
xlabel("t[s]");
ylabel("$\theta \mathrm{[rad]}$");


計算結果


以下に、初角速度q0=0で初角度θ0を0.1ラジアン、2.9ラジアンの2通りの値で計算した結果を示します。

002_20130720182725.png

003_20130720182724.png

Fig.2-3: 厳密な単振り子の解。sinθ≒θの近似が成り立つときの周期が1秒となるように糸の長さLを調整している。振幅(初角度)が小さいとき(θ0=0.1; グラフ上)は周期が1秒となっているが、振幅(初角度)が大きいとき(θ0=2.9; グラフ下)は周期が1秒を大きく超えている。


関連エントリ




参考URL




付録


このエントリで使用したLTspiceのシミュレーション用ファイルを添付します。ファイル名末尾の".txt"を削除して、"_"を"."に変更すれば使えるはずです。(参考:ねがてぃぶろぐの付録)


参考文献/使用機器




フィードバック



にほんブログ村 その他趣味ブログ 電子工作へ

 ↑ 電子工作ブログランキング参加中です。1クリックお願いします。


コメント・トラックバックも歓迎です。 ↓      


 ↓ この記事が面白かった方は「拍手」をお願いします。

tag: Scilab 常微分方程式 ode 数値積分 単振り子 

FC2カウンター
カテゴリ
ユーザータグ

LTspiceAkaiKKRmachikaneyamaScilabKKRPSoCCPAOPアンプPIC強磁性常微分方程式モンテカルロ解析トランジスタode状態密度DOSインターフェースecaljスイッチング回路定電流PDS5022半導体シェルスクリプト乱数レベルシフトHP6632A温度解析可変抵抗I2Cブレッドボード分散関係トランジスタ技術R6452A数値積分反強磁性バンドギャップ確率論セミナー絶縁偏微分方程式非線形方程式ソルババンド構造熱設計カオスA/DコンバータISO-I2Cフォトカプラ三端子レギュレータシュミットトリガLEDGW近似LM358アナログスイッチ数値微分TL43174HC4053マフィンティン半径発振回路サーボ直流動作点解析カレントミラーPC817CUSB単振り子bzqlty開発環境BSch2ちゃんねる電子負荷イジング模型LDAチョッパアンプ量子力学補間アセンブラFFTブラべ格子標準ロジックパラメトリック解析基本並進ベクトルewidthキュリー温度QSGWGGA失敗談MaximaSMPTLP621スイッチト・キャパシタ熱伝導コバルト相対論スピン軌道相互作用六方最密充填構造繰り返しFETランダムウォークcygwingfortran不規則合金状態方程式ラプラス方程式抵抗スレーターポーリング曲線位相図格子比熱マントルデータロガー自動計測ダイヤモンドガイガー管QNAPUPS固有値問題条件分岐井戸型ポテンシャルシュレディンガー方程式詰め回路MCU第一原理計算起電力熱力学スーパーセルVCALM555仮想結晶近似awkTLP521NE555ubuntufsolveブラウン運動OpenMPVESTA最大値テスタ差し込みグラフFXA-7020ZRWriter509三角波TLP552平均場近似最適化最小値過渡解析LMC662トランスPIC16F785CapSenseMBEナイキスト線図CK1026フィルタP-10負帰還安定性EAGLEAACircuit2SC1815OPA2277PGAノコギリ波縮退非線型方程式ソルバL10構造fcc面心立方構造結晶磁気異方性TeX全エネルギー固定スピンモーメントFSMウィグナーザイツ胞interp1ヒストグラム確率論マテリアルデザインspecx.fジバニャン方程式等高線初期値フェルミ面正規分布c/agnuplotBaO岩塩構造ルチル構造ウルツ鉱構造ZnO重積分SIC二相共存スワップ領域リジッドバンド模型半金属合金multiplotハーフメタルデバイ模型edeltquantumESPRESSOフォノンifortUbuntuマンデルブロ集合キーボードRealforce関数フィッティングフラクタルクーロン散乱CIF化学反応三次元最小二乗法日本語直流解析PCトラックボールExcelTS-110パラメータ・モデル等価回路モデルTS-112疎行列文字列HiLAPW両対数グラフ片対数グラフ熱拡散方程式陰解法境界条件連立一次方程式Crank-Nicolson法グラフの分割軸ラベルヒストグラム不規則局所モーメント入出力円周率Gimp凡例線種シンボルMAS830L

最新コメント
リンク

にほんブログ村 その他趣味ブログ 電子工作へ