/* * wave1d.c --- 1次元波動方程式 (Dirichlet 境界条件) * * ccx wave1d.c -I/usr/local/include -lmatrix * ノートパソコンでは * ccx wave1d.c -I/usr/local/include -L/usr/local/lib -lmatrix */ #include <stdio.h> #include <math.h> #include <matrix.h> void copy_vector(int, vector, vector); double pi; int main() { /* N は区間の分割数 */ int N; int i, n, nmax, nfunc; /* lambda はλ, tau はτ */ double lambda, Tmax, h, tau, lambda2; /* u1[i]=u_{i,n-1} * u2[i]=u_{i,n} * u3[i]=u_{i,n+1] */ vector u1, u2, u3; double phi(double, int), psi(double, int); pi = 4.0 * atan(1.0); /* N は 100 とか 1000 とか */ printf("N="); scanf("%d", &N); u1 = new_vector(N+1); u2 = new_vector(N+1); u3 = new_vector(N+1); /* λについては本に詳しいが、λ=1 が良い結果を出す */ printf("λ="); scanf("%lf", &lambda); /* Tmax は最終時刻だから、長く計算したければ大きな値を入れる */ printf("Tmax="); scanf("%lf", &Tmax); lambda2 = lambda * lambda; h = 1.0 / N; tau = lambda * h; /* 初期値を選ぶ */ printf("nfunc(初期値の種類 1..2)="); scanf("%d", &nfunc); /* 初期値 */ /* u_{i,0}=φi */ for (i = 0; i <= N; i++) u1[i] = phi(i * h, nfunc); /* u_{i,1}=(1-λ2)... */ for (i = 1; i < N; i++) u2[i] = (1-lambda2) * u1[i] + 0.5 * lambda2 * (u1[i-1] + u1[i+1]) + tau * psi(i * h, nfunc); u2[0] = u2[N] = 0.0; /* グラフを描くための準備 */ openpl(); fspace2(-0.2, -1.2, 1.2, 1.2); /* t=0 でのグラフ */ fmove(0.0, u1[0]); for (i = 1; i <= N; i++) fcont(i * h, u1[i]); /* t=t1=τ でのグラフ */ erase(); fmove(0.0, u1[0]); for (i = 1; i <= N; i++) fcont(i * h, u2[i]); nmax = (int)rint(Tmax / tau); /* 時間に関するループ */ for (n = 1; n <= nmax; n++) { for (i = 1; i < N; i++) u3[i] = 2 * (1 - lambda2) * u2[i] + lambda2 * (u2[i-1] + u2[i+1]) - u1[i]; u3[0] = u3[N] = 0.0; /* t=t_{n+1}=(n+1)τ でのグラフ */ erase(); fmove(0.0, u3[0]); for (i = 1; i <= N; i++) fcont(i * h, u3[i]); /* u1 <- u2, u2 <- u3 */ copy_vector(N + 1, u1, u2); copy_vector(N + 1, u2, u3); } closepl(); return 0.0; } /* φ */ double phi(double x, int nfunc) { if (nfunc == 1) { return sin(pi * x); } else if (nfunc == 2) { if (x > 0.375 && x <= 0.5) return 8.0 * x - 3.0; else if (x > 0.5 && x < 0.625) return - 8.0 * x + 5.0; else return 0.0; } else return 0.0; } /* ψ */ double psi(double x, int nfunc) { if (nfunc == 1) { return 0.0; } else if (nfunc == 2) { return 0.0; } else return 0.0; } /* * ベクトル b をベクトル a にコピー */ void copy_vector(int N, vector a, vector b) { int i; for (i = 0; i < N; i++) a[i] = b[i]; return; }