問題()を解くためのプログラムである。
(これから載せるプログラムを実行するには、以上取ることが
お勧めである。それ以下だと波動はギザギザになる。)
/* * move1d-e.c -- 1次元波動方程式の初期値境界値問題を解く。 * コンパイル: ccx move1d-e.c */ #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int i, j, Jmax, skip, N; double tau, h, lambda, dt, Tmax; double *u, *newu, *v, *newv, *w, *neww; double f(double), g(double), fx(double); /* N, λ を入力する */ printf("区間の分割数 N = "); scanf("%d", &N); printf(" λ= "); scanf("%lf", &lambda); /* hを計算する */ h = 1.0 / N; tau = lambda * h; printf("τ=%f\n", tau); printf(" dt= "); scanf("%lf", &dt); skip = dt / tau; /* 最終時刻を入力する */ printf("最終時刻 Tmax = "); scanf("%lf", &Tmax); /* ベクトル u, newu, v, newv, w, neww を用意する */ u = malloc(sizeof(double) * (N+1)); newu = malloc(sizeof(double) * (N+1)); v= malloc(sizeof(double) * (N+1)); newv = malloc(sizeof(double) * (N+1)); w= malloc(sizeof(double) * (N+1)); neww = malloc(sizeof(double) * (N+1)); for (i = 0; i <= N; i++) u[i] = f(i * h); for (i = 0; i <=N; i++) v[i] = g(i * h); for (i = 0; i <=N; i++) w[i] = fx(i * h); /* ウィンドウを出す */ openpl(); fspace2(-0.1, -1.1, 1.1, 1.1); /* t=0 の状態を表示する */ fmove(0.0, u[0]); for (i = 1; i <= N; i++) fcont(i * h, u[i]); /* ループを何回まわるか計算する */ Jmax = Tmax / tau + 0.5; /* Dirichlet 境界条件 */ u[0] = u[N] = 0.0; v[0] = v[N] = 0.0; for (j = 0; j <= Jmax; j++) { /* 差分方程式 (j -> j+1) */ for (i = 1; i < N; i++){ newv[i]= (v[i+1] + lambda* w[i+1])/ 2.0 +(v[i-1] - lambda* w[i-1])/ 2.0; neww[i]=( lambda * v[i+1] + w[i+1])/ 2.0 +( -lambda * v[i-1] + w[i-1])/ 2.0; newu[i]=( u[i+1] + u[i-1])/ 2.0 + tau * v[i]; } neww[0] = lambda * v[1] + w[1]; neww[N] = -lambda * v[N-1] + w[N-1]; for (i = 1; i < N; i++){ u[i] = newu[i]; v[i] = newv[i]; w[i] = neww[i]; } w[0] = neww[0]; w[N] = neww[N]; if (j % skip == 0) { /* この時刻 (t=(j+1)τ) の状態を表示する */ erase(); fmove(0.0, u[0]); for (i = 1; i <= N; i++) fcont(i * h, u[i]); } } printf("終りました。ウィンドウをクリックして下さい。\n"); closepl(); } double f(double x) { if (x < 0.4) return 0.0; if (x > 0.6) return 0.0; else return sin(5.0 * M_PI * x); } double g(double x) { return 0.0; } double fx(double x) { if (x < 0.4) return 0.0; if (x > 0.6) return 0.0; else return 5.0 * M_PI * cos(5.0 * M_PI * x); }
問題()を解くためのプログラムである。
/* move1d-e.c -- 1次元波動方程式の初期値境界値問題を解く。 * コンパイル: ccx move1d-e.c * du/dx = 0 ( x= 0.0 ) * du/dx = 0 ( x= 1.0 ) * の条件で解く。 */ #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int i, j, Jmax, skip, N; double tau, h, lambda, dt, Tmax, a, b, q, s; double *u, *newu, *v, *newv, *w, *neww; double f(double), g(double), fx(double); /* N, λ を入力する */ printf("区間の分割数 N = "); scanf("%d", &N); printf(" λ= "); scanf("%lf", &lambda); /* hを計算する */ h = 1.0 / N; tau = lambda * h; printf("τ=%f\n", tau); printf(" dt= "); scanf("%lf", &dt); skip = dt / tau; /* 最終時刻を入力する */ printf("最終時刻 Tmax = "); scanf("%lf", &Tmax); /* ベクトル u, newu, v, newv, w, neww を用意する */ u = (double *)malloc(sizeof(double) * (N+1)); newu = (double *)malloc(sizeof(double) * (N+1)); v= (double *)malloc(sizeof(double) * (N+1)); newv = (double *)malloc(sizeof(double) * (N+1)); w= (double *)malloc(sizeof(double) * (N+1)); neww = (double *)malloc(sizeof(double) * (N+1)); for (i = 0; i <= N; i++) u[i] = f(i * h); for (i = 0; i <=N; i++) v[i] = g(i * h); for (i = 0; i <=N; i++) w[i] = fx(i * h); /* ウィンドウを出す */ openpl(); fspace2(-0.1, -1.1, 1.1, 1.1); /* t=0 の状態を表示する */ fmove(0.0, u[0]); for (i = 1; i <= N; i++) fcont(i * h, u[i]); /* ループを何回まわるか計算する */ Jmax = (int)rint(Tmax / tau); /* Dirichlet 境界条件 */ w[0] = 0.0; w[N] = 0.0; for (j = 0; j <= Jmax; j++) { /* 差分方程式 (j -> j+1) */ for (i = 1; i < N; i++){ newv[i]= (v[i+1] + lambda* w[i+1])/ 2.0 +(v[i-1] - lambda* w[i-1])/ 2.0; neww[i]=( lambda * v[i+1] + w[i+1])/ 2.0 +( -lambda * v[i-1] + w[i-1])/ 2.0; newu[i]=( u[i+1] + u[i-1])/ 2.0 + tau * v[i]; } newv[0]= lambda * w[1] + v[1]; newu[0]= u[1] + tau * v[0]; newv[N]= -lambda * w[N-1] + v[N-1]; newu[N]= u[N+1] + tau * v[N]; neww[0]= w[0]; neww[N]= w[N]; for (i = 0; i <= N; i++){ u[i] = newu[i]; v[i] = newv[i]; w[i] = neww[i]; } if (j % skip == 0) { /* この時刻 (t=(j+1)τ) の状態を表示する */ erase(); fmove(0.0, u[0]); for (i = 1; i <= N; i++) fcont(i * h, u[i]); } } printf("終りました。ウィンドウをクリックして下さい。\n"); closepl(); } double f(double x) { if (x < 0.2) return 0.0; if (x > 0.6) return 0.0; else return sin(5.0 * M_PI * x); } double g(double x) { return 0.0; } double fx(double x) { if (x < 0.2) return 0.0; if (x > 0.6) return 0.0; else return 5.0 * M_PI * cos(5.0 * M_PI * x); }