(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) 関数が微分の形の形で表されているときの積分値を求める
(一般的に数値積分をする意味は、関数自体が変化の式(例えば速度の関数)などで表されているとき
ある時刻から時刻までの距離を求めたいときなどで使用される。
もちろんその変化の式が、手計算によって計算可能ならば積分によって時間と距離の関係を導出し
その時間を入れることで直接距離を導いたほうが早い。
しかし、一般的に時間と距離の関係のような式自体が導出することが不可能な場合が世の中には多く
時間と速度の関係のような変化の式を見つけ出すことの方が容易なのだが、これを手計算で積分すること
は非常に難しいため数値積分が提案された)
(注目!) n階の常微分方程式とn連立常微分方程式を解く方法は同じである。
(1-1)
(1-2)
(1-3)
(1-4)
(1-5)
ここで、を外に出すと
(1-1)
(1-2)
(1-3)
(1-4)
(1-5)
ここでは、2元連立常微分方程式を解いてみる。
ここで、ルンゲクッタの公式(1-5)を適用すると、
(2-3)
(2-3a)
(2-3b)
(2-3c)
(2-3d)
(2-4)
(2-4a)
(2-4b)
(2-4c)
(2-4d)
#include "stdafx.h" #include<iostream> #include<fstream> #include<io.h> #include<math.h> #include "ComplexC++.h" #define PI 3.1415926 const static double Em=1.0; //電圧源 const static double R1=1.0; //抵抗 const static double R2=1.0; //抵抗 const static double C1=1.0; //コイル const static double C2=1.0; //コイル const static double freq=0.1; //周波数0.1Hz const static double omega=2*PI*freq; //角周波数 const static double dh=(1/freq)/30.; //1周期の30分割 static double K3[3]={0,0,0}; static double L3[3]={0,0,0}; static double K4[4]={0,0,0,0}; static double L4[4]={0,0,0,0}; void rungeKutta3ziK(double t,double V1,double V2); void rungeKutta3ziL(double t,double V1,double V2); void rungeKutta4ziK(double t,double V1,double V2); void rungeKutta4ziL(double t,double V1,double V2); double v1_func(double t,double V1,double V2); double v2_func(double t,double V1,double V2); ///////// 理論計算 /////////////// Complex c1(double t); Complex c2(double t); const static double lamda1=(-3-sqrt(5.))/2; const static double lamda2=(-3+sqrt(5.))/2; int _tmain(int argc, _TCHAR* argv[]) { errno_t err; FILE *fp_output; //変数 double t=0; //実時間 double v0=0; //初期電圧 double V1=0.0; double V2=0.0; double V111=0.0; double V222=0.0; Complex V11; Complex V22; if( err = fopen_s(&fp_output,"renritu_bibun_kekka.txt","w") != 0){ exit(2);} t=0; for(int n=1; n< 3*(int)((1/freq)/dh); n++){ //3次ルンゲクッタ係数の計算 rungeKutta3ziK(t,V1,V2); rungeKutta3ziL(t,V1,V2); //4次ルンゲクッタ係数の計算 rungeKutta4ziK(t,V111,V222); rungeKutta4ziL(t,V111,V222); //3次ルンゲクッタの計算 V1=V1+(1./6.)*(K3[0]+4*K3[1]+K3[2])*dh; V2=V2+(1./6.)*(L3[0]+4*L3[1]+L3[2])*dh; //4次ルンゲクッタの計算 V111=V111+(1./6.)*(K4[0]+2*K4[1]+2*K4[2]+K4[3]); V222=V222+(1./6.)*(L4[0]+2*L4[1]+2*L4[2]+L4[3]); //n=1から始まるから t=n*dh(n=1,2,3...) t=(double)n*dh; //電源電圧 v0=1.+sin(omega*t); V11=c1(t)*2.*exp(lamda1*t)+c2(t)*2.*exp(lamda2*t); V22=c1(t)*(1-sqrt(5.))*exp(lamda1*t)+c2(t)*(1+sqrt(5.))*exp(lamda2*t); //printf("t = %f e=%f v1 = %f v2 = %f V11 = %f V22= %f\n",t,v0,V1,V2,cabs(V11),Real(V22)); //fprintf_s(fp_output,"%f %f %f %f %f %f %f\n",t,v0,V1,V2,cabs(V11),Real(V22)); printf("t = %f e=%f v1 = %f v2 = %f V111 = %f V222= %f V1real = %f V2real = %f\n",t,v0,V1,V2,V111,V222,Real(V11),Real(V22)); fprintf_s(fp_output,"%f %f %f %f %f %f %f %f %f\n",t,v0,V1,V2,V111,V222,Real(V11),Real(V22)); } if(fp_output != NULL) fclose(fp_output); getchar(); return 0; } void rungeKutta3ziK(double t,double V1,double V2){ //これは t=n*dh(n=1,2,3,...)の計算となる K3[0]=v1_func(t,V1,V2); K3[1]=v1_func(t+dh/2,V1+K3[0]/2.0,V2+L3[0]/2.0); K3[2]=v1_func(t+dh,V1-K3[0]+2.0*K3[1],V2-L3[0]+2.0*L3[1]); } void rungeKutta3ziL(double t,double V1,double V2){ //これは t=n*dh(n=1,2,3,...)の計算となる L3[0]=v2_func(t,V1,V2); L3[1]=v2_func(t+dh/2,V1+K3[0]/2.0,V2+L3[0]/2.0); L3[2]=v2_func(t+dh,V1-K3[0]+2.0*K3[1],V2-L3[0]+2.0*L3[1]); } void rungeKutta4ziK(double t,double V1,double V2){ //これは t=n*dh(n=1,2,3,...)の計算となる K4[0]=dh*v1_func(t,V1,V2); K4[1]=dh*v1_func(t+dh/2,V1+K4[0]/2.0,V2+L4[0]/2.0); K4[2]=dh*v1_func(t+dh/2,V1+K4[1]/2.0,V2+L4[1]/2.0); K4[3]=dh*v1_func(t+dh,V1+K4[2],V2+L4[2]); } void rungeKutta4ziL(double t,double V1,double V2){ //これは t=n*dh(n=1,2,3,...)の計算となる L4[0]=dh*v2_func(t,V1,V2); L4[1]=dh*v2_func(t+dh/2,V1+K4[0]/2.0,V2+L4[0]/2.0); L4[2]=dh*v2_func(t+dh/2,V1+K4[1]/2.0,V2+L4[1]/2.0); L4[3]=dh*v2_func(t+dh,V1+K4[2],V2+L4[2]); }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 連立のルンゲクッタ法 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% echo off clear all close all load 'renritu_bibun_kekka.txt' t=renritu_bibun_kekka(:,1); e=renritu_bibun_kekka(:,2); V1=renritu_bibun_kekka(:,3); V2=renritu_bibun_kekka(:,4); V111=renritu_bibun_kekka(:,5); V222=renritu_bibun_kekka(:,6); V11=renritu_bibun_kekka(:,7); V22=renritu_bibun_kekka(:,8); plot(t,e,'r-','linewidth',2); hold on plot(t,V1,'bo','linewidth',2); hold on plot(t,V111,'b+','linewidth',2); hold on plot(t,V11,'b-','linewidth',2); hold on plot(t,V2,'mo','linewidth',2); hold on plot(t,V222,'m+','linewidth',2); hold on plot(t,V22,'m-','linewidth',2); hold on grid on xlabel('時間(sec)','Fontsize',18) ylabel('電流(A)','Fontsize',18) h=legend('電圧',..., 'V1(3次ルンゲクッタ)',..., 'V111(4次ルンゲクッタ)',..., 'V11(厳密解)',..., 'V2(3次ルンゲクッタ)',..., 'V222(4次ルンゲクッタ)',..., 'V22(厳密解)',..., 1); set(h,'FontSize',15) axis([0 Inf -Inf Inf]); h=gca get(h) set(h,'LineWidth',2,..., 'FontSize',18) print -djpeg renritu_method_byouga.jpg
(3-1)
(3-1a)
(3-1b)
(3-1c)
(3-2)
(3-2a)
(3-2b)
(3-2c)