数値シミュレーション:2階の微分方程式 (シラバス10・11...

16
C言語第 6 1 数値シミュレーション:2階の微分方程式 (シラバス10・11回目) 【1】2階の微分方程式と差分方程式 微分方程式を、 2 2 (,) dx dx c fxt dt dt + = とする。これを2つの1階の微分方程式に変更する。 2 2 2 2 (,) (,) (,) (, ,) dx y dx dx dx dx dt c fxt c fxt dy dt dt dt dt cy fxt Fxyt dt ì = ï ï + = Þ =- + Þ í ï =- + = ï î それぞれの1階の微分方程式に Runge Kutta 法を適用する。それぞれ、差分に直して 1 1 , n n n n x x y y dx dy dt t dt t + + - - Þ Þ D D より 1 2 3 4 1 1 2 3 4 1 2 2 6 2 2 6 n n n n k k k k x x k k k k y y t t + + + + + - = ´ + + + D - ´D = を用いる。ここで、 1 ( , , ) n n n k fx y t = 1 1 2 ( , , ) 2 2 2 n n n k t k t k fx y t t ´D ´ + + D D = + 2 2 3 ( , , ) 2 2 2 n n n k t k t k fx y t t ´D ´ + + D D = + 4 3 3 ( , , ) n n n k fx k ty k tt t = + ´D + ´D +D 【2】RLC回路のシミュレーション R E C S x L R E C S x L

Upload: others

Post on 04-Sep-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 1

数値シミュレーション:2階の微分方程式

(シラバス10・11回目)【1】2階の微分方程式と差分方程式

微分方程式を、2

2 ( , )d x dxc f x tdt dt

+ =

とする。これを2つの1階の微分方程式に変更する。

2 2

2 2( , ) ( , )( , ) ( , , )

dx yd x dx d x dx dtc f x t c f x t

dydt dt dt dt cy f x t F x y tdt

ì =ïï+ = Þ = - + Þ íï = - + =ïî

それぞれの1階の微分方程式に Runge Kutta 法を適用する。それぞれ、差分に直して

1 1, n n n nx x y ydx dydt t dt t

+ +- -Þ Þ

D D

より

1 2 3 41

1 2 3 41

2 26

2 26

n n

n n

k k k kx x

k k k ky y

t

t

+

+

+ + +- = ´

+ + +

D

- ´D=

を用いる。ここで、

1 ( , , )n n nk f x y t=

1 12 ( , , )

2 2 2n n nk t k tk f x y t t´D ´

+ +DD

= +

2 23 ( , , )

2 2 2n n nk t k tk f x y t t´D ´

+ +DD

= +

4 3 3( , , )n n nk f x k t y k t t t= + ´D + ´D + D

【2】RLC回路のシミュレーション

RE C

S

xL

RE C

S

xL

Page 2: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 2

図のようなRC回路にコイル(L)が入っている。スイッチSで端子を電池(E)側から切り替えると、コンデンサ

に生じた電位が徐々に消滅していく。そのときのコンデンサの電圧変化 x は、時間とともに変化する。電

流の向きを、RからLの方向にとると、2

2 0d x dxLC RC xdt dt

+ + =

となる。これを2つの1階の方程式にするには、

( )

2 2

2 20,

Rcd x dx d x R dx x LLC RC xxdt dt dt L dt LC f x tLC

ì =ïï+ + = Þ + = - Þ íï = -ïî

なので

( )

( )

1

2

,

1( , ) ,

dx y f x ydtdy dy R RCy xcy f x t y x f x ydt dt L LC LC

= =

+= - + Þ = - - = - =

になる。初期条件として

( )( )0

0 0

x E

y

=

=

にする。

【3】数値計算に必要な工夫

微分方程式は

dx ydtdy RCy xdt LC

ì =ïïí +ï = -ïî

になる。ただし、dy RCy xdt LC

+= - は、このまま数値計算すると、例えば、

●R=0.025(kΩ)

●C=0.25 (μF)

●L=10(mH)

のとき、3 6

3 6

3 9 96 4

9

0.025 0.25 F 0.025 10 0.25 10 F10mH 0.25 F 10 10 H 0.25 10 F

0.025 0.25 10 10 10 0.0025 10 0.25 102.5 10 2.5 2.5

dy RCy x k y x y xdt LC

y x y x y x

mm

-

- -

-

-

+ W´ ´ + ´ W´ ´ ´ += - = - = -

´ ´ ´ ´

´ ´ += = ´ + = ´ +

´となり、係数が非常に大きな値となり、数値計算には不適である。このようなときには、時間変数 tは秒で計測するのであるが、この

●計測時間の単位を ms(1 s

1000= )や m s(

1 s1000,000

= )のように短くする

Page 3: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 3

とよい。このことを見るために、実際に数値を用いて

9 2 94 4

210 100.25 10 0.25 102.5 2.5

dxydtdy d x dxy x x

dt dt dt

=æ ö æ ö= - ´ + Þ = - ´ +ç ÷ ç ÷

è ø è ø

なので、大きな数が現れる。そこで

● 810 (後で使うため ( )4210 を見越している)で両辺を割る

2 9 2 4 94

2 8 2 8 8

4

10 0.25 10 100.25 10 2.5 10 10 10 2.5

0.25 10 10 2.5

d x dx d x dxx xdt dt dtdt

dx xdt

æ öæ ö ´= - ´ + Þ = - +ç ÷ç ÷ ç ÷è ø è ø

æ ö= - +ç ÷è ø

になる。分母の大きな数を、時間 tに含めると

( ) ( )2 2

28 2 4 44

0.25 10 10.2510 10 2.5 41010

d x dx d x dxx xdt dt d td t

æ öæ ö ç ÷= - + Þ = - +ç ÷ ç ÷è ø ç ÷

è ø

そこで、新しい変数として、410T t=

をとれば、もとの微分方程式は

( )2

42

10.25 104

d x dx x T tdT dT

æ ö= - - + =ç ÷è ø

になり、

●大きな数は姿を消す

ことがわかる。その結果、プログラムでは、 410T t= について、0 秒から 60 秒間計測するとすれば、 tによる実際の計測時間は

( )4: 60s 100s1 60s 60s s 6ms

10000 1000

T T tTt t

ì = == ü ïÞý í= þ = ´ = =ïî

プログラムでの経過時間

計測時間:

になる。従って、

●計測時間は、msで表示

で表示するとよい。

この変換を系統的に行うには、2

21dy RCy x d x R dx x

dt LC dt L dt LC+ æ ö= - Þ = - +ç ÷

è øにおいて 80.3 10LC -= ´ なので、 810 のかわりに、1 LC を用いて、

●両辺を1LC

で割る=両辺に LC を掛ける

Page 4: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 4

2 2

2 2

2

2

1

d x R dx d x dxx LC RC xdt L dt LC dt dt

d x RC dx C dxx R xt tLLCt d dd LC LCLC

æ ö æ ö= - + Þ = - +ç ÷ ç ÷è ø è ø

æ ö æ öç ÷ ç ÷

Þ = - + = - +ç ÷ ç ÷ç ÷ ç ÷æ ö ç ÷ ç ÷ç ÷ è ø è øè ø

そこで、新しい変数として、

tTLC

=

をとれば、もとの微分方程式は

2

2 3 : [ ]

ms 10

t LCTd x C dx tR x T sdT L dT LC LCT

æ ö =æ ö= - + = Þç ÷ ç ÷ç ÷ è ø ´è ø

計測時間プログラムでの経過時間

で表示:

になる。従ってプログラムで用いる微分方程式は

( )

( )

1

2

,

,

dx y f x ydTdy CR y x f x ydT L

= =

æ ö= - + =ç ÷ç ÷

è øになる。

【4】プログラム

1) ( ) ( )( )

( )( )

1

1 1 next 1

next 1

,, , ,

,x

x f x y tdx xy f x y f x y x x f x y tdt t x x f x y t

D

ìD = DD ï= = Þ = Þ Þ = + DíD ï - = Dî

プログラムでは

( )STEP

next 1 , calculate nextx , ,x x f x t t x y tæ ö

= + D = Dç ÷ç ÷è ø

2) ( ) ( )( )

( )

2

2 2

next 2

,, ,

,y

y f x y tdy C yR y x f x y f x ydt L t y y f x y t

D

D = Dìæ ö D ï= - + = Þ = Þç ÷ íç ÷ Dè ø ï - = Dî

( )next 2 ,y y f x y tÞ = + D

プログラムでは

( )STEP

next 2 , calculate nexty , ,y y f x y t x y tæ ö

= + D = Dç ÷ç ÷è ø

repo1.c#include <stdio.h>#include <math.h>

#define R (0.025*1000.0)#define C (0.25/1000000.0)#define L (10.0/1000.0)

Page 5: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 5

#define INITIAL_TIME 0.0#define LAST_TIME 10.0#define INITIAL_X 1.0#define INITIAL_Y 0.0#define STEP 0.04

double f1(double x, double y){

double fy;

fy = y;

return fy;}

double f2(double x, double y){

double fx;

fx = -(R*sqrt(C/L)*y+x);

return fx;}

double calclate_nextx(double x, double y, double step){

double k1, k2, k3, k4;double next_x;

k1 = f1(x, y);k2 = f1(x+k1*step/2.0, y+k1*step/2.0);k3 = f1(x+k2*step/2.0, y+k2*step/2.0);k4 = f1(x+k3*step, y+k3*step);

next_x = x + (k1+2.0*k2+2.0*k3+k4) *step/6.0;

return next_x;}

double calclate_nexty (double x, double y, double step){

double k1, k2, k3, k4;double next_y;

k1 = f2(x, y);k2 = f2(x+k1*step/2.0, y+k1*step/2.0);k3 = f2(x+k2*step/2.0, y+k2*step/2.0);k4 = f2(x+k3*step, y+k3*step);

next_y = y + (k1+2.0*k2+2.0*k3+k4)*step/6.0;

return next_y;}

void writedata(double t, double x){

// msで表示するため、1.0E3を掛けておくprintf("%7.4f,%10.3e\n", sqrt(L*C)*t*1.0E3, x);

}

int main(void){

Page 6: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 6

double t, last_t;double x, next_x, y, next_y;

x = INITIAL_X;y = INITIAL_Y;t = INITIAL_TIME;last_t = LAST_TIME*(1.0+STEP);

while(t < last_t){writedata(t, x);next_x = calclate_nextx(x, y, STEP);next_y = calclate_nexty(x, y, STEP);x = next_x;y = next_y;t = t+STEP;

}

return 0;}

になる。

【5】表計算ソフトの自動立ち上げ(Windows用のみ)

計算結果を画面表示と同時にファイルを作成し、作成したファイルを自動的に表計算ソフトで表にして

表示するようにする。

1)csv ファイルを作成:fopen 関数

fopen(番地, 決まった文字列);

fopen(csv ファイル名の格納番地, "wt");

FILE * file_open;

file_open= fopen(filename, "wt");

file_open の数値が零(NULL)だと作成に失敗

2)csv ファイルへの書き込み:fprintf 関数

fprintf(FILE * 型番地, ...);

printf("%5.2f %10.3e\n", t, x);

fprintf(file_open, "%5.2f, %10.3e\n", t, x);

3)書き込み終了後csv ファイルを閉じる:fclose 関数

fclose(FILE * 型番地)

fclose(file_open)

4)表計算ソフトでcsv ファイルを開く:ShellExecute 関数

ShellExecute((HWND)0, "open", 番地, NULL, NULL, SW_SHOWNORMAL)

ShellExecute((HWND)0, "open", csv ファイル名の格納番地, NULL, NULL, SW_SHOWNORMAL)

戻り値は特別で HWND 型になっている。戻り値が32以下だと csv ファイル用表計算ソフトの起動に失敗

Page 7: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 7

の関数を使用する。ShellExecute 関数を使用するために

windows.h を#include する

こと。

メニュー[プロジェクト]-[プロパティー]の

[文字セット] マルチバイト文字セットを使用するを選択

プログラムは repo1.c に太文字部を追加や変更します。

repo2.c#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>#include <stdio.h>#include <math.h>

#define R (0.025*1000.0)#define C (0.25/1000000.0)#define L (10.0/1000.0)

#define INITIAL_TIME 0.0#define LAST_TIME 50.0#define INITIAL_X 1.0#define INITIAL_Y 0.0#define STEP 0.0025

double f1(double x, double y){

double fy;

fy = y;

return fy;}

double f2(double x, double y){

double fx;

fx = -(R*sqrt(C/L)*y+x);

return fx;}

double calclate_nextx(double x, double y, double step){

double k1, k2, k3, k4;double next_x;

Page 8: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 8

k1 = f1(x, y);k2 = f1(x+k1*step/2.0, y+k1*step/2.0);k3 = f1(x+k2*step/2.0, y+k2*step/2.0);k4 = f1(x+k3*step, y+k3*step);

next_x = x + (k1+2.0*k2+2.0*k3+k4)*step/6.0;

return next_x;}

double calclate_nexty (double x, double y, double step){

double k1, k2, k3, k4;double next_y;

k1 = f2(x, y);k2 = f2(x+k1*step/2.0, y+k1*step/2.0);k3 = f2(x+k2*step/2.0, y+k2*step/2.0);k4 = f2(x+k3*step, y+k3*step);

next_y = y + (k1+2.0*k2+2.0*k3+k4)*step/6.0;

return next_y;}

void writedata(FILE *file_open, double t, double x){

// msで表示するため、1.0E3を掛けておくprintf("%7.4f,%10.3e\n", sqrt(L*C)*t*1.0E3, x);if(file_open != NULL){

fprintf(file_open, "%7.4f, %10.3e\n", sqrt(L*C)*t*1.0E3, x);}

}

int main(void){

// 作成ファイル名はexample2.csvchar filename[] = "example2.csv";// 作成ファイル追尾用変数FILE * file_open = NULL;double t, last_t;double x, next_x, y, next_y;

x = INITIAL_X;y = INITIAL_Y;t = INITIAL_TIME;last_t = LAST_TIME*(1.0+STEP);

// ファイルの作成に失敗すると数値(file_open=NULL)を返すfile_open = fopen(filename, "wt");

writedata(file_open, t, x);

while(t < last_t){next_x = calclate_nextx(x, y, STEP);next_y = calclate_nexty(x, y, STEP);x = next_x;y = next_y;t = t+STEP;writedata(file_open, t, x);

}

// NULLのときにファイル作成失敗

Page 9: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 9

if(file_open == NULL){printf("\n====>ファイル(%s)の作成に失敗しています。\n====>既にファイルが開か

れているかもしれません。", filename);

getchar();}else{

HINSTANCE hinst;

fclose(file_open);

hinst = ShellExecute((HWND)0, "open", filename, NULL, NULL, SW_SHOWNORMAL);

if(hinst <= (HINSTANCE)32){printf("\n====>表計算ソフトの自動起動に失敗しました。");

getchar();}

}

return 0;}

エクセルからグラフ作成方法

散布図-散布図(平滑線)

Page 10: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 10

グラフの移動

新しいシート

Page 11: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 11

完了

Page 12: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 12

第6回目レポート

レポートの回数(6回目)、学生証番号と氏名を明記すること

必ず表紙を付け、最後のページ(の添付用)を表紙の次に入れる

(A4レポート用紙使用のこと)

1) RLC 回路において、

● コンデンサー電圧の満たす方程式2

2 0d x dxLC RC xdt dt

+ + = を導け。

キルヒホッフの第Ⅱ法則を用いる

コンデンサーに蓄えられる電荷をQとすると・・・

コンデンサの電圧 ( )V x= は・・・Qを使って書ける

電流は・・・Qを使って書ける

Qの微分方程式をコンデンサの電圧 ( )V x= の微分方程式に変えて・・・

●初期条件 ( )0 0y = は何を意味するか。物理の言葉で説明せよ。

の2点を提出。

2) repo.2 のプログラムを作成し、t-x グラフを作成せよ。

●プログラム

● t-x グラフ(散布図を選択)ができるが、数値などの見栄えを美しくする事)

●グラフが示すように振動しながら減衰してゆくが、方程式を元にして何故かの説明

の3点を提出。

3) 0.1 kgm = の質点を先端にもつバネの減衰振動の方程式2

2d x dxm kx bdt dt

= - -

を、2

2 0d x dxLC RC xdt dt

+ + = のプログラムを参考にして作成し、数値

A)0.10.01

kb=ì

í =î

Page 13: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 13

B)0.10.4

kb=ì

í =îを用いて、t-x グラフを作成せよ。

●プログラム:A)と B)共通で1点

時間間隔は「0.0025 秒=5ms」に

#define STEP 0.0025

ただし、データの表示時間は、t でよい:

printf("%5.2f,%10.3e\n", t, x);

●t-x グラフ:A)と B)の 2 点

の3点を提出。

A)のグラフ

B)のグラフ

Page 14: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 14

提出例(使える表紙は次のページ)

作成する解答など

1ページ目 2ページ目 3ページ目以降

次ページの添付用

コンピュータ物理学演習Ⅱ

第 6回目

月 日

学籍番号

氏名

Page 15: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 15

コンピュータ物理学演習Ⅱ

第 6 回目

月 日提出

学籍番号

氏名

Page 16: 数値シミュレーション:2階の微分方程式 (シラバス10・11 …yasue/ffn/c6-new.pdfC言語第6回 3 とよい。このことを見るために、実際に数値を用いて

C言語第 6回 16

第6回目レポート(添付用)

1) RLC 回路のコンデンサー電圧の満たす方程式2

2 0d x dxLC RC xdt dt

+ + = を導け。

2) repo.1c/repo.2 のどちらかのプログラムを作成し、t-x グラフを作成せよ。

●プログラム

●実行結果

●t-x グラフ

●グラフが示すように振動しながら減衰してゆくが、方程式を元にして何故かの

説明

の4点を提出。

3) 0.1 kgm = の質点を先端にもつバネの減衰振動の方程式2

2d x dxm kx bdt dt

= - -

を、2

2 0d x dxLC RC xdt dt

+ + = のプログラムを参考にして作成し、数値

A)0.050.02

kb=ì

í =î

B)0.10.4

kb=ì

í =îを用いて、t-x グラフを作成せよ。#define STEP 0.1 とし、50 秒間計測する。

●プログラム:A)と B)共通で1点

●実行結果:A)と B)の 2 点

●t-x グラフ:A)と B)の 2 点

の5点を提出。