> restart; > # CRANK-NICOLSON ALGORITHM 12.3 > # > # To approximate the solution of the parabolic partial-differential > # equation subject to the boundary conditions > # u(0,t) = u(l,t) = 0, 0 < t < T = max t > # and the initial conditions > # u(x,0) = F(x), 0 <= x <= l: > # > # INPUT: endpoint l; maximum time T; constant ALPHA; integers m, N: > # > # OUTPUT: approximations W(I,J) to u(x(I),t(J)) for each > # I = 1,..., m-1 and J = 1,..., N. > alg123 := proc() local F, OK, FX, FT, ALPHA, M, N, M1, M2, H, K, VV, V, I, L, U, J, T, Z, I1, FLAG, NAME, OUP, X; > printf(`This is the Crank-Nicolson Method.\n`); > printf(`Input the function F(X) in terms of x.\n`); > printf(`For example: sin(3.141592654*x)\n`); > F := scanf(`%a`)[1]; > F := unapply(F,x); > printf(`The lefthand endpoint on the X-axis is 0.\n`); > OK :=FALSE; > while OK = FALSE do > printf(`Input the righthand endpoint on the X-axis.\n`); > FX := scanf(`%f`)[1]; > if FX <= 0 then > printf(`Must be positive number.\n`); > else > OK := TRUE; > fi; > od; > OK := FALSE; > while OK = FALSE do > printf(`Input the maximum value of the time variable T.\n`); > FT := scanf(`%f`)[1]; > if FT <= 0 then > printf(`Must be positive number.\n`); > else > OK := TRUE; > fi; > od; > printf(`Input the constant alpha.\n`); > ALPHA := scanf(`%f`)[1]; > OK := FALSE; > while OK = FALSE do > printf(`Input integer m = number of intervals on X-axis\n`); > printf(`and N = number of time intervals - separated by a blank.\n`); > printf(`Note that m must be 3 or larger.\n`); > M := scanf(`%d`)[1]; > N := scanf(`%d`)[1]; > if M <= 2 or N <= 0 then > printf(`Numbers are not within correct range.\n`); > else > OK := TRUE; > fi; > od; > if OK = TRUE then > M1 := M-1; > M2 := M-2; > # Step 1 > H := FX/M; > K := FT/N; > # VV is used in place of lambda > VV := ALPHA^2*K/(H^2); > # Set V(M) to zero > V[M-1] := 0; > # Step 3 > for I from 1 to M1 do > V[I-1] := evalf(F(I*H)); > od; > # Step 3 > # Steps 3 - 11 solve a tridiagonal linear system using Algorithm 6.7 > L[0] := 1+VV; > U[0] := -VV/(2*L[0]); > # Step 4 > for I from 2 to M2 do > L[I-1] := 1+VV+VV*U[I-2]/2; > U[I-1] := -VV/(2*L[I-1]); > od; > # Step 5 > L[M1-1] := 1+VV+0.5*VV*U[M2-1]; > # Step 6 > for J from 1 to N do > # Step 7 > # Current t > T := J*K; > Z[0] := ((1-VV)*V[0]+VV*V[1]/2)/L[0]; > # Step 8 > for I from 2 to M1 do > Z[I-1] := ((1-VV)*V[I-1]+0.5*VV*(V[I]+V[I-2]+Z[I-2]))/L[I-1]; > od; > # Step 9 > V[M1-1] := Z[M1-1]; > # Step 10 > for I1 from 1 to M2 do > I := M2-I1+1; > V[I-1] := Z[I-1]-U[I-1]*V[I]; > od; > od; > # Step 11 > printf(`Choice of output method:\n`); > printf(`1. Output to screen\n`); > printf(`2. Output to text file\n`); > printf(`Please enter 1 or 2.\n`); > FLAG := scanf(`%d`)[1]; > if FLAG = 2 then > printf(`Input the file name in the form - drive:\\name.ext\n`); > printf(`for example: A:\\OUTPUT.DTA\n`); > NAME := scanf(`%s`)[1]; > OUP := fopen(NAME,WRITE,TEXT); > else > OUP := default; > fi; > fprintf(OUP, `CRANK-NICOLSON METHOD\n\n`); > fprintf(OUP, ` I X(I) W(X(I),%12.6e)\n`, FT); > for I from 1 to M1 do > X := I*H; > fprintf(OUP, `%3d %11.8f %13.8f\n`, I, X, V[I-1]); > od; > if OUP <> default then > fclose(OUP): > printf(`Output file %s created successfully`,NAME); > fi; > fi; > # Step 12 > RETURN(0); > end; > alg123();