微分方程式の解法 とその可視化 Part2 14年11月5日水曜日 常微分方程式の数値解法 前回までの復習 オイラー法とは 微分を1次の差分で近似する. 近似の微分 本当の微分 14年11月5日水曜日 常微分方程式の数値解法 ルンゲ・クッタ法では微分を幾つかの項の和として近似する. 数値解析において常微分方程式の近似解を求める 一連の方法で,以下の方法だけを指す言葉ではない. 14年11月5日水曜日 常微分方程式の数値解法 4段4次ルンゲ・クッタ法 現時点の値からk1を求める. 14年11月5日水曜日 常微分方程式の数値解法 4段4次ルンゲ・クッタ法 k1をdt/2の地点まで延長し,そこから k2を求める. 14年11月5日水曜日 常微分方程式の数値解法 4段4次ルンゲ・クッタ法 k2を最初の地点に戻し,そこから k3を求める. 14年11月5日水曜日 常微分方程式の数値解法 4段4次ルンゲ・クッタ法 k3を最初の地点に戻し,そこから dt離れたk4を求める. 14年11月5日水曜日 常微分方程式の数値解法 4段4次ルンゲ・クッタ法 得られたk1~k4を重み付きで足し合 わせる. 公式完成! 14年11月5日水曜日 常微分方程式の数値解法 オイラー法 V.S. 4段4次ルンゲ・クッタ法 オイラー法 4段4次ルンゲ・クッタ法 直感的でわかりやすい公式 やや複雑な公式 誤差は1次のオーダー プログラミングも楽 初心者向き 誤差は4次のオーダー (力のある人は証明してみよ.) 常微分方程式の解法としては 様々な意味で最優秀な公式 余分に4つの記憶領域を使う 14年11月5日水曜日 常微分方程式の数値解法 4段4次ルンゲ・クッタ法の適用例 こんな感じ 問題 4段4次ルンゲ・クッタ法 Exercise! 上記の問題をRK法を用いて解き, 可視化せよ.(ヒント:オイラー法 のプログラムを少し直すだけで完成 できるはず) 14年11月5日水曜日 常微分方程式の数値解法 #include <stdio.h> #include <math.h> int main(void) { int i; double dt = 0.01; double xN,xN_new; double k1,k2,k3,k4; 4段4次ルンゲ・クッタ法の適用例 FILE *gp; gp = popen("gnuplot -persist","w"); fprintf(gp, "plot '-' with lines \n"); xN = 0.01; for (i = 0; i < 1000; i++) { fprintf(gp,"%f %f\n", i * dt, xN);// データの書き込み k1 = xN; k2 = xN + dt / 2 * k1; k3 = xN + dt / 2 * k2; k4 = xN + dt * k3; xN_new = xN + dt * (k1 + 2 * k2 + 2 * k3 + k4) /6;//計算 ひみつ xN = xN_new; } fprintf(gp,"e\n"); fflush(gp); pclose(gp); return 0; } 14年11月5日水曜日 常微分方程式の数値解法 Exercise!RK法で計算&可視化をせよ.また厳密解と比較せよ. scanf関数 main2.c main3.c main4.c で読み込 めるよう に. 14年11月5日水曜日 常微分方程式の数値解法 2変数の場合 問題 Exercise! 上記の問題をRK法を用いて解き,可視化せよ. 計算の順番に気をつけること! 14年11月5日水曜日 常微分方程式の数値解法 #include <stdio.h> #include <math.h> int main(void) { int i; double double double double double 多変数の場合 dt = 0.01; xN,xN_new; yN,yN_new; kx1,kx2,kx3,kx4; ky1,ky2,ky3,ky4; xN = 1.0; yN = 0.0; for (i = 0; i < 10000; i++) { printf("%f %f %f\n",i * dt, xN, yN); //printf("%f\n", xN * xN + yN * yN); kx1 kx2 kx3 kx4 = = = = -yN; -(yN + dt / 2 * ky1); -(yN + dt / 2 * ky2); -(yN + dt * ky3); ky1 ky2 ky3 ky4 = = = = xN; xN + dt / 2 * kx1; xN + dt / 2 * kx2; xN + dt * kx3; xN_new = xN + dt * (kx1 + 2 * kx2 + 2 * kx3 + kx4) / 6; yN_new = yN + dt * (ky1 + 2 * ky2 + 2 * ky3 + ky4) / 6; xN = xN_new; yN = yN_new; } return 0; } 14年11月5日水曜日 main5.c cf: Euler cf: Euler 常微分方程式の数値解法 オイラー法 V.S. 4段4次ルンゲ・クッタ法 (誤差対決) オイラー法が真の解からどれほど離れているかを表す指標 RK法が真の解からどれほど離れているかを表す指標 どちらの方法も の時0に近づくはず! オイラー法 V.S. 4段4次ルンゲ・クッタ法 (誤差対決) 14年11月5日水曜日 常微分方程式の数値解法 オイラー法 V.S. 4段4次ルンゲ・クッタ法 (誤差対決) #include <stdio.h> #include <math.h> #define N (100) int main(void) { int i; double T = 3.14159265358979 * 10; double dt = T / N; double xN_Euler,xN_Euler_new; double yN_Euler,yN_Euler_new; double xN,xN_new,yN,yN_new; double kx1,kx2,kx3,kx4; double ky1,ky2,ky3,ky4; double xs,ys,err_Euler = 0,err_RK = 0; xN = 1.0; xN_Euler = 1.0; yN = 0.0; yN_Euler = 0.0; for (i = 0; i < N; i++) { //Exact Solution xs = cos(i * dt); ys = sin(i * dt); //RK err_RK = err_RK + dt * (fabs(xN - xs) + fabs(yN - ys));//Calc Sa kx1 = -yN; ky1 = xN; kx2 = -(yN + dt / 2 * ky1); ky2 = xN + dt / 2 * kx1; kx3 = -(yN + dt / 2 * ky2); ky3 = xN + dt / 2 * kx2; kx4 = -(yN + dt * ky3); ky4 = xN + dt * kx3; xN_new = xN + dt * (kx1 + 2 * kx2 + 2 * kx3 + kx4) / 6; yN_new = yN + dt * (ky1 + 2 * ky2 + 2 * ky3 + ky4) / 6; xN = xN_new; yN = yN_new; //Euler err_Euler = err_Euler + dt * (fabs(xN_Euler - xs) + fabs(yN_Euler - ys)); xN_Euler_new = xN_Euler + dt * (-yN_Euler); yN_Euler_new = yN_Euler + dt * (xN_Euler); xN_Euler = xN_Euler_new; yN_Euler = yN_Euler_new; } err_RK = err_RK / T; err_Euler = err_Euler / T; printf("err_RK = %15.15f,dt = % 15.15f\n",err_RK,dt); printf("err_Euler = %15.15f,dt = % 15.15f\n",err_Euler,dt); return 0; } main6.c 14年11月5日水曜日 厳密解を計算 RK法にて差を計算 オイラー法にて差を計算 常微分方程式の数値解法 オイラー法 V.S. 4段4次ルンゲ・クッタ法 (誤差対決) Exercise! main6-1.c main6.cにおいて 1 155.434715579091460 8720.135117209718373 14年11月5日水曜日 155.434715579091460 常微分方程式の数値解法 オイラー法 V.S. 4段4次ルンゲ・クッタ法 (誤差対決) Exercise! main6.cにおいて とし,誤差がどのようになるか調べ,下記の表を完成させよ 155.434715579091460 x10 x10 x10 14年11月5日水曜日 8720.135117209718373 155.434715579091460 27.716996517146850 0.001606408974007 0.372568841218112 0.000000162268631 0.031937429963379 0.000000000016235 0.003146750675461 0.000000000000019 常微分方程式の数値解法 バネ・ダンパ系の運動方程式 壁 玉 床 14年11月5日水曜日 壁 常微分方程式の数値解法 バネ・ダンパ系の運動方程式 玉 壁 壁 床 玉はバネの伸び に比例して力を受ける.(比例定数は ) 玉はダンパから速度 に比例して抵抗力を受ける.(比例定数は ) 14年11月5日水曜日 常微分方程式の数値解法 バネ・ダンパ系の運動方程式 玉 壁 壁 床 2 d x dx + 2 + dt2 dt 14年11月5日水曜日 2 0x =0 常微分方程式の数値解法 バネ・ダンパ系の運動方程式 Exercise! 以下のバネ・ダンパ系の運動方程式をRK法を用いて解き, main7.c 可視化せよ. 2 d x dx + 2 + 2 dt dt 2 0x =0 ← そっと手を離すという条件 ← 時刻0でちょっと右にあるという条件 (条件さえ満たせば何でも良いが,例えば など) 14年11月5日水曜日 レポート Aコース. 授業で扱ったバネ・ダンパ系の運動方程式をRK法を解く プログラムにおいて,厳密解と近似解を比較せよ. ヒント:厳密解は導出することもできるが,図書館(or参考書)な どで調べることもできる. O Bコース. 2重振り子の運動方程式をRK法を 用いて可視化せよ.(初期条件などは適宜決 l0 定すること)また厳密解を明示的に与えるこ シミュレーション とができるか考察せよ. ✓000 = ✓100 = g(2m0 + m1 ) sin ✓0 + gm1 sin(✓0 2✓1 ) + 2m1 sin(✓0 ✓1 ) l0 ✓002 cos(✓0 2l0 (m0 m1 cos2 (✓0 ✓1 ) + m1 ) sin(✓0 ✓1 ) (m0 + m1 ) g cos ✓0 + l0 ✓002 + l1 m1 ✓102 cos(✓0 l1 (m0 m1 cos2 (✓0 ✓1 ) + m1 ) ✓1 ) + l1 ✓102 l1 ✓1 ) m1 14年11月5日水曜日 m0 ✓1 ✓0
© Copyright 2024 ExpyDoc