// 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);
}
}