// heat1d-i-freefem.edp // 実行: FreeFem++ heat1d-i-freefem.edp // N, x が大域的な識別子を隠すと警告が出る (つまり名前が衝突する)。 int i, N, n,n2, nMax,nfunc,nm1; real pi=4.0*atan(1.0); real a = 0.0, b = 1.0; real lambda,Tmax,theta,c1,c2,c3,c4,dt,t; int skip; cout << "input nfunc= "; cin >> nfunc; cout << "input theta= "; cin >> theta; cout << "input N= "; cin >> N; cout << "input lambda= "; cin >> lambda; cout << "input Tmax= "; cin >> Tmax; cout << "input dt= "; cin >> dt; real h = (b-a) / N; real tau = lambda * h^2; real[int] x(N+1); real[int] u(N+1); real[int] AL(N),AD(N),AU(N),ff(N); real[int] al(N),ad(N),au(N); real[int] al2(N),ad2(N),au2(N),b2(N); skip = rint(dt / tau); cout << "h= " << h << endl; cout << "lambda= " << lambda << endl; cout << "tau= " << tau << endl; c1 = - theta*lambda; c2 = 1.0 + 2.0*theta*lambda; c3 = 1.0 - 2.0*(1.0-theta)*lambda; c4 = (1.0 -theta)*lambda; for (i = 1; i <N;i++){ AL[i] = AU[i] = -theta*lambda; AD[i] = 1 +2*theta*lambda; } func real f(real x) { if (nfunc ==1) if (x < 0.5) return x; else return 1 - x; else if (nfunc == 2) return 1.0; else if (nfunc == 3) return sin(pi*x); else if (nfunc == 4) if (x <=0.1) return 5*x; else if (x <= 0.3) return -2*x + 0.7; else if (x <= 0.5) return 4.5*x - 1.25; else if (x <= 0.7) return -x + 1.5; else if (x <= 0.9) return x + 0.1; else return -10*x + 10.0; else if (nfunc == 5) if (x <= 0.2) return -x + 0.8; else if (x <= 0.3) return 4*x - 0.2; else if (x <= 0.4) return -4*x + 2.2; else if (x <= 0.7) return -x + 1.0; else if (x <= 0.8) return 4*x - 2.6; else return -x +1.5; else return 0; } for (i = 0; i <= N; i++) { x[i] = a + i * h; u[i] = f(x[i]); } plot([x,u], bb=[[-0.1,-0.1],[1.1,1.1]],aspectratio=true); n2 = N-1; for (i = 1; i <N;i++){ al[i] = AL[i]+1; ad[i] = AD[i]+1; au[i] = AU[i]+1; } for (i = 1; i <N;i++){ al2[i] = AL[i]+1; ad2[i] = AD[i]+1; au2[i] = AU[i]+1; } //係数行列の LU 分解 nm1 = n2 -1; for (i=0; i < nm1; i++){ al[i+1] /= au[i]; ad[i+1] -= au[i]*al[i+1]; } nMax = rint(Tmax / tau); cout << "nMax =" << nMax << endl; for (n = 1; n <= nMax; n++) { //連立1次方程式を作って解く for (i = 1; i < N; i++){ ff[i] = c3*u[i] +c4*(u[i-1] +u[i+1]); } // LU 分解済みの三重対角行列を係数に持つ三項方程式を解く for(i=0; i < nm1;i++){ b2[i] = ff[i]+1; b2[i+1] -= b2[i] * al2[i+1]; } b2[nm1]/=ad2[nm1]; for(i=n2-2; i >= 0 ;i-1){ b2[i] = (b2[i] - au2[i]*b2[i+1])/ad2[i]; } for(i=1;i<N;i++){ u[i] =b2[i]; } u[0]=0.0; u[N]=0.0; t=n*tau; if(n%skip ==0){ plot([x, u], bb=[[-0.1,-0.1],[1.1,1.1]],aspectratio=true); } }