1 /* This example (Ascher et al, 1995, Example 9.2) solves a numerically
2 difficult boundary value problem using continuation.
5 Uri M. Ascher, Robert M. M. Mattheij and Robert D. Russell.
6 Numerical Solution of Boundary Value Problems for Ordinary
7 Differential Equations. Classics in Applied Mathematics 13, SIAM, (1995),
10 The linear differential equation is
12 e u''(x) + x u'(x) = -e %pi^2* cos(%pi x) - (%pi x) sin(%pi x)
14 with -1 < x < 1 and 0 < e <= 1
16 and boundary conditions u(-1)=-2 and u(1)=0
19 u(x) = cos(%pi x) + erf(x/sqrt(2 e))/erf(1/sqrt(2 e))
21 When e is small the solution has a rapid transition near x=0
22 and is difficult to solve numerically. COLNEW is able to solve the
23 problem for directly for e=1.0e-6, but here we will use
24 continuation to solve it successively for e=[1e-2,1e-3,1e-4,1e-5,1e-6].
26 The mesh and solution from the previous step is used as the initial
27 estimates for the next step.
36 exact(x):=cos(%pi*x)+erf(x/sqrt(2*e))/erf(1/sqrt(2*e))$
38 /* Define the equations. Do this before e is defined */
39 f: [-(x/e)*z2 - %pi^2*cos(%pi*x) - (%pi*x/e)*sin(%pi*x)];
40 define(fsub(x,z1,z2),f);
41 df: jacobian(f,[z1,z2]);
42 define(dfsub(x,z1,z2),df);
44 /* Build the functions gsub and dgsub
45 Use define and buildq to remove dependence on g and dg */
47 define(gsub(i,z1,z2),buildq([g],g[i]));
48 dg: jacobian(g,[z1,z2]);
51 buildq([val:makelist(dg[i],i,1,length(dg))],block([dg:val],dg[i])));
53 /* Define constant epsilon */
56 /* Number of differential equations */
65 /* Locations of side conditions */
66 zeta : float([-1, 1])$
67 /* Set up parameter array. */
68 ipar : makelist(0,k,1,11)$
71 /* 5 collocation points per subinterval */
73 /* Initial uniform mesh of 1 subintervals */
76 /* Size of fspace, ispace */
81 /* No initial guess is provided */
85 /* No fixed points in mesh */
87 /* Tolerances on two components */
90 /* Two error tolerances (on u and its derivative)
91 Relatively large tolerances to keep the example small */
95 fspace : makelist(0e0, k, 1, ipar[5])$
96 ispace : makelist(0, k, 1, ipar[6])$
99 /* First run with default initial guess.
100 Returns iflag. 1 = success */
101 ([iflag, fspace, ispace] :
102 colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol,
103 fixpnt, ispace, fspace,
104 0, fsub, dfsub, gsub, dgsub, dummy), iflag);
106 /* iflag=1 on success */
107 if (iflag#1) then error("On return from colnew_expert: iflag # 1");
109 /* Function to generate equally spaced list of values */
110 xlist(xmin,xmax,n):=block([dx:(xmax-xmin)/n],makelist(i,i,0,n)*dx+xmin)$
112 /* x values for solution. Cluster around x=0 */
113 X: xlist(aleft,aright,500)$
115 /* Generate solution values for z1=u(x) */
116 ans:colnew_appsln(X,2,fspace,ispace)$
117 z:maplist(first,ans)$
120 /* Compare with exact solution and report */
121 y:float(map(exact,X))$
122 maxerror:apply(max,abs(y-z));
123 printf(true," e: ~8,3e iflag ~3d Mesh size ~3d max error ~8,3e~%",
124 e,iflag,ispace[1],maxerror);
126 /* Now use continuation to solve for progressively smaller e
127 Use previous solution as initial guess and every second point
128 from previous mesh as initial mesh */
131 /* Run COLNEW using continuation for new value of e
132 Set new mesh size ipar[3] from previous size ispace[1]
133 Push list of values of z1=u(x) on to list Z */
137 [iflag, fspace, ispace]:
138 colnew_expert(ncomp,m,aleft,aright,zeta,ipar,ltol,tol,fixpnt,
139 ispace,fspace,0,fsub,dfsub,gsub,dgsub,dummy),
140 if (iflag#1) then error("On return from colnew_expert: iflag # 1"),
141 ans:colnew_appsln(X,2,fspace,ispace),
142 z:maplist(first,ans),
144 y:float(map(exact,X)),
145 maxerror:apply(max,abs(y-z)),
146 printf(true," e: ~8,3e iflag ~3d Mesh size ~3d max error ~8,3e~%",
147 e,iflag,ispace[1],maxerror),
151 for e_ in [1e-3,1e-4,1e-5,1e-6] do run_it(e_);
153 /* Z is list of solutions z1 = u(x). Restore order. */
156 /* Plot z1=u(x) for each value of e*/
159 [discrete,X,Z[1]], [discrete,X,Z[2]], [discrete,X,Z[3]],
160 [discrete,X,Z[4]], [discrete,X,Z[5]]],
161 [legend,"e=1e-2","e=1e-3","e=1e-4","e=1e-5","e=1e-6"],
162 [xlabel,"x"],[ylabel,"u(x)"],
163 [png_file,"./colnew-ex5.png"]);