## 48 Package colnew ¶

### 48.1 Introduction to colnew ¶

colnew solves mixed-order systems of boundary-value problems (BVPs) in ordinary differential equations(ODEs). It is a Common Lisp translation (via f2cl) of the Fortran routine COLNEW (see Bader&Ascher 1987).

The method uses collocation at Gaussian points and interpolation using basis functions. Approximate solutions are computed on a sequence of automatically selected meshes until a user-specified set of tolerances is satisfied. A damped Newton’s method is used for the nonlinear iteration.

COLNEW has some advanced features:

- Continuation: Most iterative numerical solvers require an initial guess. There are parameter dependent problems that have an obvious solution for a special value of the parameter (for example a coupling constant vanishes). One can then slowly vary the parameter, solving the problem numerically using as a guess the previous solution, until one gets into a strong coupling regime, hence the name continuation. Sometimes an artificial parameter is introduced to allow the use of continuation.
- Singularities: Another interesting feature of COLNEW is that one can manage singularities in the differential equation by setting interior "boundary points" on the singularities. This is because the differential equation is only imposed in the interior of the intervals, but the solution is checked for continuity and continuity of the derivative on the boundary of the intervals.
- Stiff differential equations: COLNEW can be used for solving some stiff differential equations due to the use of adaptive meshes.

The maxima interface to COLNEW exposes the full power and complexity of the Fortran 77 implementation.

COLNEW is a modification of the package COLSYS (see Ascher 1981a and Ascher 1981b). It incorporates a new basis representation replacing B-splines, and improvements for the linear and nonlinear algebraic equation solvers. The package can be referenced as either COLNEW or COLSYS.

Many practical problems that are not in the standard form accepted by COLNEW can be converted into this form. See Asher&Russell 1981.

Categories: Numerical methods · Differential equations · Share packages · Package colnew ·

### 48.2 Functions and Variables for colnew ¶

Function: colnew_expert
colnew_expert (ncomp, m, aleft, aright, zeta, ipar, ltol, tol, fixpnt, ispace, fspace, iflag, fsub, dfsub, gsub, dgsub, guess) ¶

  colnew_expert solves mixed-order systems of boundary-value problems (BVPs) in ordinary differential equations (ODEs) using a numerical collocation method.

  colnew_expert returns the list [iflag, fspace, ispace]. iflag is an error flag. Lists fspace and ispace contain the state of the solution and can be: used by `colnew_appsln` to calculate solution values at arbitrary points in the solution domain; and passed back to colnew_expert to restart the solution process with different arguments.

  The function arguments are:

  `ncomp`

    Number of differential equations (ncomp ≤ 20)

  `m`

    Integer list of length ncomp. \(m_j\) is the order of the \(j\)-th differential equation, with \(1 \le m_j \le 4\) and \(m^* = \sum_j m_j \le 40.\)

  `aleft`

    Left end of interval

  `aright`

    Right end of interval

  `zeta`

    zeta \((\zeta)\) is a real list of length \(m^*.\) \(\zeta_j\) is the \(j\)-th boundary or side condition point. The list \(\zeta\) must be ordered, with \(\zeta_j \le \zeta_{j+1}.\) All side condition points must be mesh points in all meshes used, see description of ipar[11] and fixpnt below.

  `ipar`

    A integer list of length 11. The parameters in ipar are:

    - ipar[1]
      - 0, if the problem is linear
      - 1, if the problem is nonlinear
    - ipar[2] ( = \(k\) )
      Number of collocation points per subinterval , where \(\max_j m_j \le k \le 7.\) If ipar[2]=0 then colnew sets \(k = \max\left(\max_i m_i + 5, 5 - \max_i m_i\right).\)
    - ipar[3] ( = \(n\) )
      Number of subintervals in the initial mesh.
      If ipar[3] = 0 then colnew arbitrarily sets \(n = 5\).
    - ipar[4] ( = ntol )
      Number of solution and derivative tolerances.
      Require \(0 < {\rm ntol} < m^*.\)
    - ipar[5] ( = ndimf )
      The length of list fspace. Its size provides a constraint on nmax. Choose ipar[5] according to the formula \({\rm ipar[5]} \ge {\rm nmax} \cdot {\rm nsizef}\) where \({\rm nsizef} = 4 + 3m^* + (5 + {\rm kd})\times{\rm kdm} + (2m^* - {\rm nrec})\times 2 m^*.\)
    - ipar[6] ( = ndimi )
      The length of list ispace. Its size provides a constraint on nmax, the maximum number of subintervals. Choose ipar[6] according to the formula \({\rm ipar[6]} = {\rm nmax}\times {\rm nsizei}\) where \({\rm nsizei} = 3 + {\rm kdm}\) with

          \[\eqalign{
              {\rm kdm} &= {\rm kd} + m^* \cr
              {\rm kd} &= k + {\rm ncomp} \cr
              {\rm nrec} &= {\it number\, of\, right\, end\, boundary\, conditions} \cr
            }
          \]

      .
    - ipar[7] ( = iprint )
      output control
      - -1, for full diagnostic printout
      - 0, for selected printout
      - 1, for no printout
    - ipar[8] ( = iread )
      - 0, causes colnew to generate a uniform initial mesh.
      - 1, if the initial mesh is provided by the user. it is defined in fspace as follows: the mesh aleft=x[1]<x[2]< ... <x[n]<x[n+1]=aright will occupy fspace[1], ..., fspace[n+1]. the user needs to supply only the interior mesh points fspace[j] = x[j], j = 2, ..., n.
      - 2, if the initial mesh is supplied by the user as with ipar[8]=1, and in addition no adaptive mesh selection is to be done.
    - ipar[9] ( = iguess )
      - 0, if no initial guess for the solution is provided
      - 1, if an initial guess is provided by the user in subroutine guess.
      - 2, if an initial mesh and approximate solution coefficients are provided by the user in fspace. (the former and new mesh are the same).
      - 3, if a former mesh and approximate solution coefficients are provided by the user in fspace, and the new mesh is to be taken twice as coarse; i.e.,every second point from the former mesh.
      - 4, if in addition to a former initial mesh and approximate solution coefficients, a new mesh is provided in fspace as well. (see description of output for further details on iguess = 2, 3, and 4.)
    - ipar[10]
      - 0, if the problem is regular
      - 1, if the first relax factor is =rstart, and the nonlinear iteration does not rely on past convergence (use for an extra sensitive nonlinear problem only).
      - 2, if we are to return immediately upon (a) two successive nonconvergences, or (b) after obtaining error estimate for the first time.
    - ipar[11] ( = nfxpnt , the dimension of fixpnt)
      The number of fixed points in the mesh other than aleft and aright. The code requires that all side condition points other than aleft and aright (see description of zeta) must be included as fixed points in fixpnt.
  `ltol`

    A list of length ntol=ipar[4]. ltol[j]=k specifies that the j-th tolerance in tol controls the error in the k-th component of z(u).

    The list ltol must be ordered with \(1 ≤ ltol[1] < ltol[2] < ... < ltol[ntol] ≤ mstar\).

  `tol`

    An list of length ntol=ipar[4]. tol[j] is the error tolerance on the ltol[j]-th component of z(u).

    Thus, the code attempts to satisfy for j=1,...,ntol on each subinterval \(abs(z(v)-z(u))[k] ≤ tol(j)*abs(z(u))[k]+tol(j)\) if v(x) is the approximate solution vector.

  `fixpnt`

    An list of length ipar[11]. It contains the points, other than aleft and aright, which are to be included in every mesh. All side condition points other than aleft and aright (see zeta) be included as fixed points in fixpnt.

  `ispace`

    An integer work list of length ipar[6].

  `fspace`

    A real work list of length ipar[5].

  `fsub`

    fsub is a function f(x,z1,...,z[mstar]) which realizes the system of ODEs.

    It returns a list of ncomp values, one for each ODE. Each value is the highest order derivative in each ode in terms of of x,z1,...,z[mstar] .

  `dfsub`

    dfsub is a function df(x,z1,...,z[mstar]) for evaluating the Jacobian of f.

  `gsub`

    Name of subroutine gsub(i,z1,z2,...,z[mstar]) for evaluating the i-th component of the boundary value function g(z1,...,z[mstar]). The independent variable x is not an argument of g. The value x=zeta[i] must be substituted in advance.

  `dgsub`

    Name of subroutine dgsub(i,z1,...,z[mstar]) for evaluating the i-th row of the Jacobian of g(z1,...,z[mstar]).

  `guess`

    Name of subroutine to evaluate the initial approximation for (u(x)) and for dmval(u(x))= vector of the mj-th derivatives of u(x). This subroutine is needed only if using ipar(9) = 1.

  The return value of colnew_expert is the list [iflag, fspace, ispace], where:

  `iflag`

    The mode of return from colnew_expert.

    - = 1 for normal return
    - = 0 if the collocation matrix is singular.
    - = -1 if the expected no. of subintervals exceeds storage specifications.
    - = -2 if the nonlinear iteration has not converged.
    - = -3 if there is an input data error.
  `fspace`

    A list of floats of length ipar[5].

  `ispace`

    A list of integers of length ipar[6].

  `colnew_appsln` uses fspace and ispace to calculate solution values at arbitrary points. The lists can also be used to restart the solution process with modified meshes and parameters.

  Categories: Numerical methods · Differential equations · Package colnew ·

Function: colnew_appsln
colnew_appsln (x, zlen, fspace, ispace) ¶

  Return a list of solution values from `colnew_expert` results.

  The function arguments are:

  `x`

    List of x-coordinates to calculate solution.

  `zlen`

    mstar, the length of the solution list z

  `fspace`

    List fspace returned from colnew_expert.

  `ispace`

    List ispace returned from colnew_expert.

  Categories: Numerical methods · Differential equations · Package colnew ·

### 48.3 Examples for colnew ¶

COLNEW is best learned by example.

#### 48.3.1 Example 1: A uniformly loaded beam of variable stiffness ¶

The problem describes a uniformly loaded beam of variable stiffness, simply supported at both ends.

The problem from Gawain&Ball 1978 and is Example 1 from Ascher 1981a. The maxima code is in file share/colnew/prob1.mac and a Fortran implementation is in share/colnew/ex1.

The differential equation is

    \[(x^3 u'')'' = x^3u'''' + 6x^2u''' + 6xu'' = 1 \quad {\rm over} \quad 1 \le x \le 2
    \]

with boundary conditions

    \[\eqalign{
    u(1) &= 0 \cr
    u''(1) &= 0 \cr
    u(2) &= 0 \cr
    u''(2) &= 0}
    \]

The exact solution is

    \[u(x) = {{10\log 2 - 3}\over 4}(1-x) + {1\over 2}\left({1\over x} + (3+x)\log x - x\right)
    \]

There is nconc = 1 differential equation of fourth order. The list of orders \(m = [4]\) and \(m^* = \sum_j m_j = 4.\)

The unknown vector of length \(m^*\) is

    \[
    \eqalign{
    z(x) &= [z_1(x),z_2(x),z_3(x),z_4(x)] \cr
         &= [u(x),u'(x),u''(x),u'''(x)]
    }
    \]

The differential equation is expressed as

    \[
    u''''(x) = F(x,z_1,z_2,z_3,z_4) = 1 - 6 x^2 z_3 - 6x z_2
    \]

There are \(m^* = 4\) boundary conditions. They are given by a function \(G(z_1,z_2,z_3,z_4)\) that returns a list of length \(m^*.\) The \(j\)-th boundary condition applies at \(x = \zeta_j\) and is satisfied when \(g[j] = 0\). We have

j | zeta[j] | Condition | g[j]
--- | --- | --- | ---
1 | 1.0 | \(u=0\) | \(z_1\)
2 | 1.0 | \(u'\hbox{}'=0\) | \(z_3\)
3 | 2.0 | \(u=0\) | \(z_1\)
4 | 2.0 | \(u'\hbox{}'=0\) | \(z_3\)

giving \(\zeta = [1.0,1,0,2.0,2.0]\) and \(G(z_1,z_2,z_3,z_4) = [z_1, z_3, z_1, z_3]\).

The Jacobians df and dg of f and g respectively are determined symbolically.

The solution uses the default five collocation points per subinterval and the first mesh contains only one subinterval. The maximum error magnitude in the approximate solution is evaluated at 100 equidistant points by function `colnew_appsln` using the results returned by COLNEW and compared to the estimates from the code.

    (%i1) load("colnew")$

    (%i2) /* One differential equation of order 4 */
     m : [4];

    (%o2)                          [4]

    (%i3) /* Location of boundary conditions */
     zeta : float([1,1,2,2]);

    (%o3)                 [1.0, 1.0, 2.0, 2.0]

    (%i4) /* Set up parameter array.  Use defaults for all except as shown */
     ipar : makelist(0,k,1,11);
    (%o4)           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    (%i5) /* initial mesh size */
     ipar[3] : 1$

    (%i6) /* number of tolerances */
     ipar[4] : 2$

    (%i7) /* size of real work array */
     ipar[5] : 2000$

    (%i8) /* size of integer work array */
     ipar[6] : 200$

    (%i9) /* Two error tolerances (on u and its second derivative) */
     ltol : [1, 3];
    (%o9)                        [1, 3]

    (%i10) tol : [1d-7, 1d-7];

    (%o10)                  [1.0e-7, 1.0e-7]

    (%i11) /* Real work array */
     fspace : makelist(0d0, k, 1, ipar[5])$

    (%i12) /* Integer work array */
     ispace : makelist(0, k, 1, ipar[6])$

    (%i13) /* no internal fixed points */
     fixpnt : []$

    (%i14) /* Define the equations */
     fsub(x, z1, z2, z3, z4) := [(1-6*x^2*z4-6*x*z3)/x^3];
                                              2
                                       1 - 6 x  z4 + (- 6) x z3
    (%o14) fsub(x, z1, z2, z3, z4) := [------------------------]
                                                   3
                                                  x

    (%i15) df : jacobian(fsub(x,z1, z2, z3, z4),[z1,z2,z3,z4]);
                           [         6     6 ]
    (%o15)                 [ 0  0  - --  - - ]
                           [          2    x ]
                           [         x       ]

    (%i16) define(dfsub(x, z1, z2, z3, z4), df);

                                         [         6     6 ]
    (%o16)   dfsub(x, z1, z2, z3, z4) := [ 0  0  - --  - - ]
                                         [          2    x ]
                                         [         x       ]

    (%i17) g(z1, z2, z3, z4) := [z1, z3, z1, z3];
    (%o17)        g(z1, z2, z3, z4) := [z1, z3, z1, z3]

    (%i18) gsub(i, z1, z2, z3, z4) :=
     subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], g(z1, z2, z3, z4)[i]);

    (%o18) gsub(i, z1, z2, z3, z4) :=
    subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4],
    g(z1, z2, z3, z4) )
                     i

    (%i19) dg:jacobian(g(z1, z2, z3, z4), [z1,z2,z3,z4]);
                             [ 1  0  0  0 ]
                             [            ]
                             [ 0  0  1  0 ]
    (%o19)                   [            ]
                             [ 1  0  0  0 ]
                             [            ]
                             [ 0  0  1  0 ]

    (%i20) dgsub(i, z1, z2, z3, z4) :=
     subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], row(dg, i)[1]);

    (%o20) dgsub(i, z1, z2, z3, z4) :=
         subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4], row(dg, i) )
                                                                   1

    (%i21) /* Exact solution */
      exact(x) := [.25*(10.*log(2.)-3.)*(1.-x) + .5*(1./x+(3.+x)*log(x)-x),
                 -.25*(10.*log(2.)-3.) + .5*(-1./x/x+log(x)+(3.+x)/x-1.),
                 .5*(2./x**3+1./x-3./x/x),
                 .5*(-6./x**4-1./x/x+6./x**3)]$

    (%i22) [iflag, fspace, ispace] :
     colnew_expert(1, m, 1d0, 2d0, zeta, ipar, ltol, tol, fixpnt, ispace, fspace,
                 0, fsub, dfsub, gsub, dgsub, dummy)$

     VERSION *COLNEW* OF COLSYS .

     THE MAXIMUM NUMBER OF SUBINTERVALS IS MIN (  12 (ALLOWED FROM FSPACE),  16 (ALLOWED FROM ISPACE) )

     THE NEW MESH (OF    1 SUBINTERVALS),
        1.000000    2.000000

     THE NEW MESH (OF    2 SUBINTERVALS),
        1.000000    1.500000    2.000000

     THE NEW MESH (OF    4 SUBINTERVALS),
        1.000000    1.250000    1.500000    1.750000    2.000000

    (%i23) /* Calculate the error at 101 points using the known exact solution */
     block([x : 1,
           err : makelist(0d0, k, 1, 4),
           j],
      for j : 1 thru 101 do
        block([],
          zval : colnew_appsln([x], 4, fspace, ispace)[1],
          u : float(exact(x)),
          err : map(lambda([a,b], max(a,b)), err, abs(u-zval)),
          x : x + 0.01),
      print("The exact errors are:"),
      printf(true, "   ~{ ~11,4e~}~%", err));
    The exact errors are:
         1.7389e-10   6.2679e-9   2.1843e-7   9.5743e-6
    (%o23)                        false

#### 48.3.2 Example 2: Deformation of a spherical cap ¶

These equations describe the small finite deformation of a thin shallow spherical cap of constant thickness subject to a quadratically varying axisymmetric external pressure distribution superimposed on a uniform internal pressure distribution. The problem is described in Parker&Wan 1984 and is Example 2 from Ascher 1981a. The maxima code is in file share/colnew/prob2.mac and a Fortran implementation is in share/colnew/ex2.

There are two nonlinear differential equations for \(φ\) and \(ψ\) over \(0 < x < 1\).

    \[\eqalign{
    {ε^4 \over μ}\left[φ'' + {1 \over x}φ' - {1\over x^2}φ\right] + ψ \left(1-{1\over x}φ\right) - φ &= - γ x\left(1-{x^2\over 2}\right) \cr
    \mu \left[ψ'\hbox{}' + {1\over x} ψ' - {1 \over x^2}ψ\right] - φ\left(1-{φ \over {2x}}\right) &= 0
    }
    \]

subject to boundary conditions \(φ = 0\) and \(x ψ' - 0.3 ψ + 0.7 x = 0\) at \(x=0\) and \(x=1\).

For \(ε = μ = 0.01\), two solutions exists. These are obtained by starting the nonlinear iteration from two different guesses to the solution: initially with the default initial guess; and secondly, with the initial conditions given by the function solutn.

There are nconc = 2 differential equations of second order. The list of orders \(m = [2,2]\) and \(m^* = \sum_i m_i = 4.\)

The vector of unknowns of length \(m^* = 4\) is \(z(x) = [ φ(x), φ'(x), ψ(x), ψ'(x)]\).

The differential equation is expressed as

    \[\eqalign{
    F(x,z_1,z_2,z_3,z_4)
      &= \left[
           \matrix{
             \phi''(x) \cr
             \psi''(x)
           }
         \right]
         \cr
      &= \left[
           \matrix{
             \displaystyle{z_1 \over x^2} - {z_2 \over x} + \left[z_1-z_3 \left(1-{z_1\over x}\right) - γ x \left(1-{x^2 \over 2}\right)\right] {\mu \over \epsilon^4}
             \cr
             \displaystyle{z_3 \over x^2} - {z_4 \over x} + {z_1 \over μ} \left(1-{z_1\over {2x}}\right)
           }
         \right]
    }
    \]

There are four boundary conditions given by list \(zeta\) and function \(G(z_1,z_2,z_3,z_4)\).

j | zeta[j] | Condition | g[j]
--- | --- | --- | ---
1 | 0.0 | \(φ = 0\) | \(z_1\)
2 | 0.0 | \(x ψ' - 0.3 ψ + 0.7 x = 0\) | \(z_3\)
3 | 1.0 | \(φ = 0\) | \(z_1\)
4 | 1.0 | \(x ψ' - 0.3 ψ + 0.7 x = 0\) | \(z_4 - 0.3\ {}z_3 + 0.7\)

giving \(\zeta=[0.0,0.0,1.0,1.0]\) and \(G(z_1,z_2,z_3,z_4)=[z_1, z_3, z_1, z_4-0.3 z_3+0.7]\).

Note that \(x\) is not an argument of function \(G\). The value of \(x = \zeta_j\) must be substituted.

    (%i1) load("colnew")$

    (%i2) /* Define constants */
     gamma : 1.1;
    (%o2)                          1.1

    (%i3) eps : 0.01;
    (%o3)                         0.01

    (%i4) dmu : eps;
    (%o4)                         0.01

    (%i5) eps4mu : eps^4/dmu;
    (%o5)                        1.0e-6

    (%i6) xt : sqrt(2*(gamma-1)/gamma);
    (%o6)                  0.42640143271122105

    (%i7) /* Number of differential equations */
     ncomp : 2;
    (%o7)                           2

    (%i8) /* Orders */
     m : [2, 2];

    (%o8)                        [2, 2]

    (%i9) /* Interval ends */
     aleft : 0.0;
    (%o9)                          0.0

    (%i10) aright : 1.0;

    (%o10)                         1.0

    (%i11) /* Locations of side conditions */
     zeta : float([0, 0, 1, 1])$

    (%i12) /* Set up parameter array.  */
     ipar : makelist(0,k,1,11);
    (%o12)          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    (%i13) /* Non-linear prob */
     ipar[1] : 1;
    (%o13)                          1

    (%i14) /* 4 collocation points per subinterval */
     ipar[2] : 4;
    (%o14)                          4

    (%i15) /* Initial uniform mesh of 10 subintervals */
     ipar[3] : 10;
    (%o15)                         10

    (%i16) ipar[8] : 0;
    (%o16)                          0

    (%i17) /* Size of fspace, ispace */
     ipar[5] : 40000;
    (%o17)                        40000

    (%i18) ipar[6] : 2500;
    (%o18)                        2500

    (%i19) /* No output */
     ipar[7] : 1;
    (%o19)                          1

    (%i20) /* No initial approx is provided */
     ipar[9] : 0;
    (%o20)                          0

    (%i21) /* Regular problem */
     ipar[10] : 0;
    (%o21)                          0

    (%i22) /* No fixed points in mesh */
     ipar[11] : 0;
    (%o22)                          0

    (%i23) /* Tolerances on all components */
     ipar[4] : 4;

    (%o23)                          4

    (%i24) /* Tolerances on all four components */
     ltol : [1, 2, 3, 4];
    (%o24)                    [1, 2, 3, 4]

    (%i25) tol : [1d-5, 1d-5, 1d-5, 1d-5];

    (%o25)          [1.0e-5, 1.0e-5, 1.0e-5, 1.0e-5]

    (%i26) fspace : makelist(0d0, k, 1, ipar[5])$
    (%i27) ispace : makelist(0, k, 1, ipar[6])$

    (%i28) fixpnt : []$

    (%i29) /* Define the equations */
     fsub(x, z1, z2, z3, z4) :=
     [z1/x/x - z2/x + (z1-z3*(1-z1/x) - gamma*x*(1-x*x/2))/eps4mu,
      z3/x/x - z4/x + z1*(1-z1/2/x)/dmu];

    (%o29) fsub(x, z1, z2, z3, z4) :=
     z1                     z1                     x x
     --        z1 - z3 (1 - --) + (- gamma) x (1 - ---)
     x    z2                x                       2
    [-- - -- + ----------------------------------------,
     x    x                     eps4mu
                      z1
                      --
    z3                2
    --        z1 (1 - --)
    x    z4           x
    -- - -- + -----------]
    x    x        dmu

    (%i30) df : jacobian(fsub(x,z1, z2, z3, z4),[z1,z2,z3,z4]);
    (%o30)
          [             z3        1      1             z1           ]
          [  1000000.0 (-- + 1) + --   - -  1000000.0 (-- - 1)   0  ]
          [             x          2     x             x            ]
          [                       x                                 ]
          [                                                         ]
          [            z1     50.0 z1               1             1 ]
          [ 100.0 (1 - ---) - -------   0           --          - - ]
          [            2 x       x                   2            x ]
          [                                         x               ]

    (%i31) dfsub(x, z1, z2, z3, z4) :=
      subst(['x=x,'z1=z1,'z2=z2,'z3=z3,'z4=z4], df);

    (%o31) dfsub(x, z1, z2, z3, z4) :=
          subst(['x = x, 'z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4], df)

    (%i32) g(z1, z2, z3, z4) := [z1, z3, z1, z4 - 0.3*z3 + .7];
    (%o32) g(z1, z2, z3, z4) := [z1, z3, z1, z4 - 0.3 z3 + 0.7]

    (%i33) gsub(i, z1, z2, z3, z4) :=
        subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], g(z1, z2, z3, z4)[i]);

    (%o33) gsub(i, z1, z2, z3, z4) :=
    subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4],
    g(z1, z2, z3, z4) )
                     i

    (%i34) dg:jacobian(g(z1, z2, z3, z4), [z1,z2,z3,z4]);
                           [ 1  0    0    0 ]
                           [                ]
                           [ 0  0    1    0 ]
    (%o34)                 [                ]
                           [ 1  0    0    0 ]
                           [                ]
                           [ 0  0  - 0.3  1 ]

    (%i35) dgsub(i, z1, z2, z3, z4) := subst(['z1=z1,'z2=z2,'z3=z3,'z4=z4], row(dg, i)[1]);

    (%o35) dgsub(i, z1, z2, z3, z4) :=
         subst(['z1 = z1, 'z2 = z2, 'z3 = z3, 'z4 = z4], row(dg, i) )
                                                                   1

    (%i36) /* Initial approximation function for second run */
     solutn(x) :=
     block([cons : gamma*x*(1-0.5*x*x),
           dcons : gamma*(1-1.5*x*x),
           d2cons : -3*gamma*x],
      if is(x > xt) then
        [[0, 0, -cons, -dcons],
         [0, -d2cons]]
      else
        [[2*x, 2, -2*x + cons, -2 + dcons],
         [0, d2cons]]);

    (%o36) solutn(x) := block([cons : gamma x (1 - 0.5 x x),
    dcons : gamma (1 - 1.5 x x), d2cons : - 3 gamma x],
    if is(x > xt) then [[0, 0, - cons, - dcons], [0, - d2cons]]
     else [[2 x, 2, - 2 x + cons, - 2 + dcons], [0, d2cons]])

    (%i37) /* First run with default initial guess */
     [iflag, fspace, ispace] :
     colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol, fixpnt, ispace, fspace,
     0, fsub, dfsub, gsub, dgsub, dummy)$

    (%i38) /* Check return status iflag, 1 = success */
     iflag;

    (%o38)                          1

    (%i39) /* Print values of solution at x = 0,.05,...,1 */
     x : 0;
    (%o39)                          0

    (%i40) for j : 1 thru 21 do
     block([],
       zval : colnew_appsln([x], 4, fspace, ispace)[1],
       printf(true, "~5,2f  ~{~15,5e~}~%", x, zval),
       x : x + 0.05);

     0.00       0.00000e+0     4.73042e-2   -2.72134e-31    -1.10497e+0
     0.05       2.36520e-3     4.73037e-2    -5.51761e-2    -1.10064e+0
     0.10       4.73037e-3     4.73030e-2    -1.09919e-1    -1.08765e+0
     0.15       7.09551e-3     4.73030e-2    -1.63796e-1    -1.06600e+0
     0.20       9.46069e-3     4.73039e-2    -2.16375e-1    -1.03569e+0
     0.25       1.18259e-2     4.73040e-2    -2.67221e-1    -9.96720e-1
     0.30       1.41911e-2     4.73020e-2    -3.15902e-1    -9.49092e-1
     0.35       1.65562e-2     4.72980e-2    -3.61986e-1    -8.92804e-1
     0.40       1.89215e-2     4.72993e-2    -4.05038e-1    -8.27857e-1
     0.45       2.12850e-2     4.72138e-2    -4.44627e-1    -7.54252e-1
     0.50       2.36370e-2     4.67629e-2    -4.80320e-1    -6.72014e-1
     0.55       2.59431e-2     4.51902e-2    -5.11686e-1    -5.81260e-1
     0.60       2.81093e-2     4.07535e-2    -5.38310e-1    -4.82374e-1
     0.65       2.99126e-2     2.98538e-2    -5.59805e-1    -3.76416e-1
     0.70       3.08743e-2     5.53985e-3    -5.75875e-1    -2.65952e-1
     0.75       3.00326e-2    -4.51680e-2    -5.86417e-1    -1.56670e-1
     0.80       2.55239e-2    -1.46617e-1    -5.91753e-1    -6.04539e-2
     0.85       1.37512e-2    -3.46952e-1    -5.93069e-1    -1.40102e-3
     0.90      -1.25155e-2    -7.52826e-1    -5.93303e-1    -2.86234e-2
     0.95      -6.94274e-2    -1.65084e+0    -5.99062e-1    -2.48115e-1
     1.00      2.63400e-14     1.19263e+2    -6.25420e-1    -8.87626e-1
    (%o40)                        done

    (%i41) /* Second run with initial guess */
     ipar[9] : 1;
    (%o41)                          1

    (%i42) [iflag, fspace, ispace] :
     colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol, fixpnt, ispace, fspace,
     0, fsub, dfsub, gsub, dgsub, solutn)$

    (%i43) /* Check return status iflag, 1 = success */
     iflag;

    (%o43)                          1

    (%i44) /* Print values of solution at x = 0,.05,...,1 */
     x : 0;
    (%o44)                          0

    (%i45) for j : 1 thru 21 do
     block([],
       zval : colnew_appsln([x], 4, fspace, ispace)[1],
       printf(true, "~5,2f  ~{~15,5e~}~%", x, zval),
       x : x + 0.05);
     0.00       0.00000e+0     2.04139e+0    5.11228e-33    -9.03975e-1
     0.05       1.02070e-1     2.04139e+0    -4.52648e-2    -9.07936e-1
     0.10       2.04139e-1     2.04139e+0    -9.09256e-2    -9.19819e-1
     0.15       3.06209e-1     2.04140e+0    -1.37379e-1    -9.39624e-1
     0.20       4.08279e-1     2.04141e+0    -1.85020e-1    -9.67352e-1
     0.25       5.10351e-1     2.04152e+0    -2.34246e-1    -1.00301e+0
     0.30       6.12448e-1     2.04303e+0    -2.85454e-1    -1.04663e+0
     0.35       7.15276e-1     2.10661e+0    -3.39053e-1    -1.09916e+0
     0.40       8.32131e-1    -2.45181e-1    -3.96124e-1    -1.20544e+0
     0.45       1.77510e-2    -3.57554e+0    -4.45400e-1    -7.13543e-1
     0.50       2.25122e-2     1.23608e-1    -4.80360e-1    -6.70074e-1
     0.55       2.58693e-2     4.85257e-2    -5.11692e-1    -5.81075e-1
     0.60       2.80994e-2     4.11112e-2    -5.38311e-1    -4.82343e-1
     0.65       2.99107e-2     2.99116e-2    -5.59805e-1    -3.76409e-1
     0.70       3.08739e-2     5.55200e-3    -5.75875e-1    -2.65950e-1
     0.75       3.00325e-2    -4.51649e-2    -5.86417e-1    -1.56669e-1
     0.80       2.55239e-2    -1.46616e-1    -5.91753e-1    -6.04538e-2
     0.85       1.37512e-2    -3.46952e-1    -5.93069e-1    -1.40094e-3
     0.90      -1.25155e-2    -7.52826e-1    -5.93303e-1    -2.86233e-2
     0.95      -6.94274e-2    -1.65084e+0    -5.99062e-1    -2.48115e-1
     1.00      2.64996e-14     1.19263e+2    -6.25420e-1    -8.87626e-1
    (%o45)                        done

Columns 1 (x) and 2 (\(φ\)) of the two sets of results above, and the figure below, can be compared with Figure 1 in Ascher 1981a.

#### 48.3.3 Example 3: Rotating flow of viscous incompressible fluid ¶

Example 3 from Ascher 1981a describes the velocities in the boundary layer produced by the rotating flow of a viscous incompressible fluid over a stationary infinite disk (see Gawain&Ball 1978).

The differential equations are:

    \[\eqalign{
    G'' + {3-n\over 2} HG' + (n-1)H'G - s(G-1) &= 0 \cr
    H''' + {3-n\over 2} HH'' + n\left(H'\right)^2 - 1 + G^2 -sH' &= 0
    }
    \]

with the boundary conditions

    \[\eqalign{
    G(0) &= H(0) = H'(0) = 0 \cr
    G(\infty) &= 1 \cr
    H'(\infty) &= 0
    }
    \]

The solution uses a number of techniques to obtain convergence. Refer to Ascher 1981a for details.

The maxima code is in file share/colnew/prob3.mac. The reference Fortran implementation is in share/colnew/ex3.

#### 48.3.4 Example 4: Quantum Neumann equation ¶

A more sophisticated example is Bellon&Talon 2005, which deals with singularities in the solution domain, provides an initial guess to the solution and uses continuation to solve the system of non-linear differential equations.

The maxima code is in file share/colnew/prob4.mac. The Fortran implementation is in share/colnew/ex4.

#### 48.3.5 Example 5: Simple example of continuation ¶

This example (see Ascher et al, 1995, Example 9.2) solves a numerically difficult boundary value problem using continuation. The maxima code is in file share/colnew/prob5.mac and a Fortran implementation is in share/colnew/ex5. The linear differential equation is

    \[
    \epsilon u'' + x u' = -\epsilon \pi^2 \cos \pi x - \pi x\sin \pi x \quad -1 < x < 1

    \]

with boundary conditions

    \[\eqalign{
    u(-1) &= -2 \cr
    u(1) &= 0
    }
    \]

The exact solution is

    \[
    u(x) = \cos \pi x + {{\rm erf}\left(\displaystyle{x \over \sqrt{2\epsilon}}\right) \over
    {\rm erf}\left(\displaystyle{1 \over \sqrt{2\epsilon}}\right)}

    \]

When \(ε\) is small the solution has a rapid transition near \(x=0\) and is difficult to solve numerically. COLNEW is able to solve the problem for directly for \(\epsilon = 10^{-6},\) but here we will use continuation to solve it succesively for \(\epsilon = [10^{-2}, 10^{-3}, 10^{-4}, 10^{-5}, 10^{-6}].\)

There is nconc = 1 differential equation of second order. The list of orders \(m = [2]\) and \(m^* = \sum_j m[j] = 2.\)

The unknown vector of length \(m^*\) is \(z(x) = [z_1(x),z_2(x)] = [u(x),u'(x)]\).

The differential equation is expressed as

    \[
    [u''(x)] = F(x,z_1,z_2) = \left[-{x\over \epsilon}z_2 - \pi^2\cos \pi x - {\pi x \over \epsilon}\sin \pi x\right]

    \]

There are \(m^*=2\) boundary conditions. They are given by a function \(G(z_1,z_2)\) that returns a list of length \(m^*.\) The \(j\)-th boundary condition applies at \(x = \zeta_j\) and is satisfied when \(g[j] = 0\). We have

j | zeta[j] | Condition | g[j]
--- | --- | --- | ---
1 | -1.0 | \(u=-2\) | \(z_1+2\)
2 | 1.0 | \(u=0\) | \(z_1\)

giving \(\zeta = [-1.0,1,0]\) and \(G(z_1,z_2) = [z_1+2, z_1]\).

The Jacobians df and dg of f and g respectively are determined symbolically.

The ODE will be solved for multiple values of \(ε\). The functions fsub, dfsub, gsub and dgsub are defined before e is set, so that it can be changed in the program.

    (%i1) load("colnew")$
    (%i2) kill(e,x,z1,z2)$

    (%i3) /* Exact solution */
     exact(x):=cos(%pi*x)+erf(x/sqrt(2*e))/erf(1/sqrt(2*e))$

    (%i4) /* Define the equations.  Do this before e is defined */
     f: [-(x/e)*z2 - %pi^2*cos(%pi*x) - (%pi*x/e)*sin(%pi*x)];
                 x z2   %pi x sin(%pi x)      2
    (%o4)     [- ---- - ---------------- - %pi  cos(%pi x)]
                  e            e

    (%i5) define(fsub(x,z1,z2),f);
                                x z2   %pi x sin(%pi x)
    (%o5) fsub(x, z1, z2) := [- ---- - ----------------
                                 e            e
                                                        2
                                                   - %pi  cos(%pi x)]

    (%i6) df: jacobian(f,[z1,z2]);
                               [      x ]
    (%o6)                      [ 0  - - ]
                               [      e ]

    (%i7) define(dfsub(x,z1,z2),df);
                                         [      x ]
    (%o7)            dfsub(x, z1, z2) := [ 0  - - ]
                                         [      e ]

    (%i8) /* Build the functions gsub and dgsub
       Use define and buildq to remove dependence on g and dg */
     g: [z1+2,z1];
    (%o8)                     [z1 + 2, z1]

    (%i9) define(gsub(i,z1,z2),buildq([g],g[i]));
    (%o9)           gsub(i, z1, z2) := [z1 + 2, z1]
                                                   i

    (%i10) dg: jacobian(g,[z1,z2]);
                                [ 1  0 ]
    (%o10)                      [      ]
                                [ 1  0 ]

    (%i11) define(
     dgsub(i,z1,z2),
     buildq([val:makelist(dg[i],i,1,length(dg))],block([dg:val],dg[i])));
    (%o11) dgsub(i, z1, z2) := block([dg : [[1, 0], [1, 0]]], dg )
                                                                i

    (%i12) /* Define constant epsilon */
     e : 0.01$

    (%i13) /* Number of differential equations */
     ncomp : 1$

    (%i14) /* Orders */
     m : [2]$

    (%i15) /* Interval ends */
     aleft:-1.0$

    (%i16) aright:1.0$

    (%i17) /* Locations of side conditions */
     zeta : float([-1, 1])$

    (%i18) /* Set up parameter array.  */
     ipar : makelist(0,k,1,11)$

    (%i19) /* linear prob */
     ipar[1] : 0$

    (%i20) /* 5 collocation points per subinterval */
     ipar[2] : 5$

    (%i21) /* Initial uniform mesh of 1 subintervals */
     ipar[3] : 1$

    (%i22) ipar[8] : 0$

    (%i23) /* Size of fspace, ispace */
     ipar[5] : 10000$

    (%i24) ipar[6] :  1000$

    (%i25) /* No output.  Don't do this for development. */
     ipar[7]:1$

    (%i26) /* No initial guess is provided */
     ipar[9] : 0$

    (%i27) /* Regular problem */
     ipar[10] : 0$

    (%i28) /* No fixed points in mesh */
     ipar[11] : 0$

    (%i29) /* Tolerances on two components */
     ipar[4] : 2$

    (%i30) /* Two error tolerances (on u and its derivative)
       Relatively large tolerances to keep the example small */
     ltol : [1, 2]$

    (%i31) tol : [1e-4, 1e-4]$
    (%i32) fspace : makelist(0e0, k, 1, ipar[5])$
    (%i33) ispace : makelist(0, k, 1, ipar[6])$
    (%i34) fixpnt : []$

    (%i35) /* First run with default initial guess.
       Returns iflag. 1 = success */
     ([iflag, fspace, ispace] :
      colnew_expert(ncomp, m, aleft, aright, zeta, ipar, ltol, tol,
      fixpnt, ispace, fspace,
      0, fsub, dfsub, gsub, dgsub, dummy),
      if (iflag#1) then error("On return from colnew_expert: iflag = ",iflag),
      iflag);
    (%o35)                          1

    (%i36) /* Function to generate equally spaced list of values */
     xlist(xmin,xmax,n):=block([dx:(xmax-xmin)/n],makelist(i,i,0,n)*dx+xmin)$

    (%i37) /* x values for solution.  Cluster around x=0 */
     X: xlist(aleft,aright,500)$

    (%i38) /* Generate solution values for z1=u(x) */
     ans:colnew_appsln(X,2,fspace,ispace)$

    (%i39) z:maplist(first,ans)$
    (%i40) Z:[z]$

    (%i41) /* Compare with exact solution and report */
     y:float(map(exact,X))$

    (%i42) maxerror:apply(max,abs(y-z));
    (%o42)                6.881499912125832e-7

    (%i43) printf(true," e: ~8,3e  iflag ~3d  Mesh size ~3d  max error ~8,3e~%",
      e,iflag,ispace[1],maxerror);
     e: 1.000e-2  iflag   1  Mesh size  16  max error 6.881e-7
    (%o43)                        false

    (%i44) /* Now use continuation to solve for progressively smaller e
       Use previous solution as initial guess and every second point
       from previous mesh as initial mesh */
     ipar[9] : 3$

    (%i45) /* Run COLNEW using continuation for new value of e
       Set new mesh size ipar[3] from previous size ispace[1]
       Push list of values of z1=u(x) on to list Z */
     run_it(e_):=block(
      e:e_,
      ipar[3]:ispace[1],
      [iflag, fspace, ispace]:
         colnew_expert(ncomp,m,aleft,aright,zeta,ipar,ltol,tol,fixpnt,
         ispace,fspace,0,fsub,dfsub,gsub,dgsub,dummy),
      if (iflag#1) then error("On return from colnew_expert: iflag =",iflag),
      ans:colnew_appsln(X,2,fspace,ispace),
      z:maplist(first,ans),
      push(z,Z),
      y:float(map(exact,X)),
      maxerror:apply(max,abs(y-z)),
      printf(true," e: ~8,3e  iflag ~3d  Mesh size ~3d  max error ~8,3e~%",
        e,iflag,ispace[1],maxerror),
      iflag
     )$

    (%i46) for e_ in [1e-3,1e-4,1e-5,1e-6] do run_it(e_)$
     e: 1.000e-3  iflag   1  Mesh size  20  max error 3.217e-7
     e: 1.000e-4  iflag   1  Mesh size  40  max error 3.835e-7
     e: 1.000e-5  iflag   1  Mesh size  38  max error 8.689e-9
     e: 1.000e-6  iflag   1  Mesh size  60  max error 6.333e-7

    (%i47) /* Z is list of solutions z1 = u(x).  Restore order. */
     Z:reverse(Z)$

    (%i48) /* Plot z1=u(x) for each value of e */
     plot2d([
      [discrete,X,Z[1]], [discrete,X,Z[2]], [discrete,X,Z[3]],
      [discrete,X,Z[4]], [discrete,X,Z[5]]],
      [legend,"e=1e-2","e=1e-3","e=1e-4","e=1e-5","e=1e-6"],
      [xlabel,"x"],[ylabel,"u(x)"],
      [png_file,"./colnew-ex5.png"]); */
     done$
    (%o48)  [/tmp/5zscumjmw4lichu2.gnuplot, ./colnew-ex5.png]

The figure below shows the solution for \(ε=[10^{-2},10^{-3},10^{-4},10^{-5},10^{-6}]\).

### 48.4 References for colnew ¶

- (Gawain&Ball 1978) T. H. Gawain and R. E. Ball, Improved Finite Difference Formulas for Boundary Value Problems, International Journal for Numerical Methods in Engineering 12, no. 7 (1978) 1151–60. doi:10.1002/nme.1620120706
- (Ascher 1979a) U. Ascher, J. Christiansen and R. D. Russell, A collocation solver for mixed order systems of boundary value problems, Math. Comp. 33 (1979), 659-679, doi:10.1090/S0025-5718-1979-0521281-7
- (Ascher 1979b) U. Ascher, J. Christiansen and R. D. Russell, COLSYS - a collocation code for boundary value problems, in Codes for boundary-value problems in ordinary differential equations, Lecture Notes in Computer Science 76, Springer Verlag, B. Childs et. al. (eds.) (1979), 164-185, ISBN 978-3-540-09554-5
- (Ascher 1981a) U. Ascher, J. Christiansen and R. D. Russell, Collocation software for boundary-value odes, ACM Trans. Math Software 7 (1981), 209-222. doi:10.1145/355945.355950
- (Ascher 1981b) U. Ascher, U., J. Christiansen, and R. D. Russell. ‘Algorithm 569: COLSYS: Collocation Software for Boundary-Value ODEs [D2]’. ACM Transactions on Mathematical Software 7, no. 2 (June 1981): 223–29. doi:10.1145/355945.355951
- (Ascher&Russell 1981) U. Ascher and R. D. Russell. ‘Reformulation of Boundary Value Problems into “Standard” Form’. SIAM Review 23, no. 2 (April 1981), 238–54, doi:10.1137/1023039
- (Parker&Wan 1984) David F. Parker and Frederic Y. M. Wan, ‘Finite Polar Dimpling of Shallow Caps Under Sub-Buckling Axisymmetric Pressure Distributions’. SIAM Journal on Applied Mathematics 44, no. 2 (April 1984): 301–26, doi:10.1137/0144022
- (Bader&Ascher 1987) G. Bader and U. Ascher, A new basis implementation for a mixed order boundary value ode solver, SIAM J. Scient. Stat. Comput. (1987), 483-500, doi:10.1137/0908047
- (Ascher et al, 1995) Uri M. Ascher, Robert M. M. Mattheij, and Robert D. Russell. Numerical Solution of Boundary Value Problems for Ordinary Differential Equations. Classics in Applied Mathematics 13, SIAM, (1995), ISBN 978-0-89871-354-1
- (Bellon&Talon 2005) M. Bellon, M. Talon, Spectrum of the quantum Neumann model, Physics Letters A, Volume 337, Issues 4–6, pp 360-368, doi:10.1016/j.physleta.2005.02.002 arXiv:hep-th/0407005

JavaScript license information