(1)「電気・電子工学のための数値計算法入門」橋本修著 総合電子出版社
(2)「ディジタル信号処理技術」玉井徳みち、長島厚、藤田泰弘、若井修造著 日経BP社
(3)「よくわかる有限要素法」福森栄次著 Ohmsha
http://szksrv.isc.chubu.ac.jp/java/physics/rlc/rlc0.html
http://www.asahi-net.or.jp/~jk2m-mrt/kiso_RLC.htm
http://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0
http://www.cmplx.cse.nagoya-u.ac.jp/~furuhashi/education/CircuitMaker/chap1.pdf
http://www.akita-nct.ac.jp/~yamamoto/lecture/2003/5E/lecture_5E/diff_eq/node2.html
http://chemeng.on.coocan.jp/cemath/cemath08.html
http://homepage3.nifty.com/skomo/f6/hp6_3.htm
http://homepage1.nifty.com/gfk/rungekutta.htm
(a) 微分の説明
微分方程式の解を求める
(b) 微分方程式の解を数値計算で求める
(c) 積分の説明
(d) 関数が微分の形の形で表されているときの積分値を求める
(一般的に数値積分をする意味は、関数自体が変化の式(例えば速度の関数)などで表されているとき
ある時刻から時刻までの距離を求めたいときなどで使用される。
もちろんその変化の式が、手計算によって計算可能ならば積分によって時間と距離の関係を導出し
その時間を入れることで直接距離を導いたほうが早い。
しかし、一般的に時間と距離の関係のような式自体が導出することが不可能な場合が世の中には多く
時間と速度の関係のような変化の式を見つけ出すことの方が容易なのだが、これを手計算で積分すること
は非常に難しいため数値積分が提案された)
微分方程式の初期解を求める方法として、オイラー法を説明する。
1階の常微分方程式は、一般に
(1-1)
という形で表すことができる(微分が が、
と同じ意味になるのだが、
違和感があるが仕方がない!)。
いま、と
の区間内でテイラー展開すると、先に示したように
の範囲で
(1-2)
ここで、を十分小さくすると
(1-3)
となり、
(1-4)
を得る。
ここで、初期条件 のとき
とすると、
(1-4)式から
(1-5)
次にとし、それに対して
とすると
(1-6)
この考えを繰り返すと
(1-7)
この刻み幅を極めて小さくすると解の精度は向上する。
このようにテイラー展開の1次の項のみ使用して解を求めるとき
1次の精度をもつアルゴリズムと呼ぶ。
増分をでの微分の平均を取ることで表してみる
(1-8)
たとえば、から始まる場合
この時点で、右辺のは求められていないので、
この場合は、
この考え方を一般形に変形すると、
さらにこれを簡単に表すと、
(1-1)
この微分方程式の一般解は、
特解(定常解@過度状態が終わった状態)のときの
(1-2)
と
式(1)でとおいた場合の一般解(過渡解@過度状態のときの解)
(1-3)
の和で表される。
(1-4)
定常解を以下のようにしてもとめる。
は定数であるため、
は定数となる。
そのため時間変化がないから
となるため(1)は、
(1-5)
次に過渡解は、
両辺を積分すると
(1-6)
初期条件は、t=0のときなので、
ゆえに
つまり
(1-7)
時定数 を代入して
(1-7b)
この式は時間の経過とともに過度状態が終わり電流は、に収束することを示している。
(1-8)
(1-7)式にを代入したものと(1-8)式に
を代入したものは等しいので
(1-9)
となる。
ゆえに (1-8)式は、
時定数 を代入して
(1-10)
となる。
(1)SW1を入れたときのオイラー法
(2)SW2を入れたときのオイラー法
(注意)
(1)から(2)に以降する時間は、
(1)で十分に安定してからなので
if( t <= sw )
の状態を持つ。
#include "stdafx.h" #include<iostream> #include<fstream> #include<io.h> #include<math.h> double f(double x); double kai(int in); int _tmain(int argc, _TCHAR* argv[]) { errno_t err; FILE *fp_output; double I=0; //電流 const static double E=1.0; //電圧源 const static double R=1.0; //抵抗 const static double L=1.0; //コイル const static double tau = L/R; //時定数 const static double dh=1.0e-1; //微小時間0.1 const static double sw=1.0; //両スイッチ切換え時刻 //変数 double t=0; //実時間 double i1=0.0; //初期電流(厳密解) double i2=0.0; //初期電流(オイラー法) double i3=0.0; //初期電流(修正オイラー法) if( err = fopen_s(&fp_output,"data.txt","w") != 0){ exit(2);} for(int n=1; n< 5*(int)(sw/dh);n++){ t=(double)n*dh; // 0 <= t <= s の場合 if( t <= sw ){ i1=(E/R)*(1.0-exp(-t/tau)); i2=i2+dh*((E-R*i2)/L); i3=i3+dh*(((E-R*i3)/L)+((E-R*i2)/L))/2.0; }else{ i1=(E/R)*( exp(-(t-sw)/tau) - exp(-t/tau) ); i2=i2+dh*(-R*i2/L); i3=i3+dh*((-R*i3/L)+(-R*i2/L))/2.0; } printf("t = %f i1 = %f i2 = %f i3 = %f\n",t,i1,i2,i3); fprintf_s(fp_output,"%f %f %f %f\n",t,i1,i2,i3); } if(fp_output != NULL) fclose(fp_output); getchar(); return 0; }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.2 オイラー法 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% echo off clear all close all load 'data.txt' t=data(:,1); i1=data(:,2); i2=data(:,3); i3=data(:,4); plot(t,i1,'r-','linewidth',2); hold on plot(t,i2,'b+-','linewidth',2); hold on plot(t,i3,'g+-','linewidth',2); hold on grid on xlabel('時間(sec)','Fontsize',18) ylabel('電流(A)','Fontsize',18) h=legend('厳密解',..., 'オイラー法',..., '修正オイラー法',..., 1); set(h,'FontSize',15) axis([0 5.0 -Inf 0.8]); h=gca get(h) set(h,'LineWidth',2,..., 'FontSize',18) print -djpeg euler_method.jpg