colloc Subroutine

subroutine colloc(aleft, aright, lbegin, iorder, ntimes, addbrk, relerr)

************80

! COLLOC solves an ordinary differential equation by collocation.

Method:

The M-th order ordinary differential equation with M side
conditions, to be specified in subroutine DIFEQU, is solved
approximately by collocation.

The approximation F to the solution G is piecewise polynomial of order
K+M with L pieces and M-1 continuous derivatives.   F is determined by
the requirement that it satisfy the differential equation at K points
per interval (to be specified in COLPNT ) and the M side conditions.

This usually nonlinear system of equations for F is solved by
Newton's method. the resulting linear system for the B-coefficients of an
iterate is constructed appropriately in EQBLOK and then solved
in SLVBLK, a program designed to solve almost block
diagonal linear systems efficiently.

There is an opportunity to attempt improvement of the breakpoint
sequence, both in number and location, through the use of NEWNOT.

Printed output consists of the piecewise polynomial representation
of the approximate solution, and of the error at selected points.

Modified:

14 February 2007

Author:

Carl DeBoor

Reference:

Carl DeBoor,
A Practical Guide to Splines,
Springer, 2001,
ISBN: 0387953663,
LC: QA1.A647.v27.

Parameters:

Input, real ( kind = 8 ) ALEFT, ARIGHT, the endpoints of the interval.

Input, integer ( kind = 4 ) LBEGIN, the initial number of polynomial
pieces in the approximation.  A uniform breakpoint sequence will be chosen.

Input, integer ( kind = 4 ) IORDER, the order of the polynomial pieces
to be used in the approximation

Input, integer ( kind = 4 ) NTIMES, the number of passes to be made
through NEWNOT.

Input, real ( kind = 8 ) ADDBRK, the number, possibly fractional, of
breaks to be added per pass through NEWNOT.  For instance, if
ADDBRK = 0.33334, then a breakpoint will be added at every third pass
through NEWNOT.

Input, real ( kind = 8 ) RELERR, a tolerance.  Newton iteration is
stopped if the difference between the B-coefficients of two successive
iterates is no more than RELERR*(absolute largest B-coefficient).

Arguments

Type IntentOptional Attributes Name
real(kind=8) :: aleft
real(kind=8) :: aright
integer(kind=4) :: lbegin
integer(kind=4) :: iorder
integer(kind=4) :: ntimes
real(kind=8) :: addbrk
real(kind=8) :: relerr

Calls

proc~~colloc~~CallsGraph proc~colloc colloc bsplpp bsplpp proc~colloc->bsplpp colpnt colpnt proc~colloc->colpnt difequ difequ proc~colloc->difequ eqblok eqblok proc~colloc->eqblok knots knots proc~colloc->knots newnot newnot proc~colloc->newnot slvblk slvblk proc~colloc->slvblk

Common Blocks

difequ (subroutine)
l2err (subroutine)
colloc (subroutine)
difequ (subroutine)
l2err (subroutine)
"> common /approx/

Type Attributes Name Initial
real :: break(npiece)
real :: coef(ncoef)
integer(kind=4) :: l
integer(kind=4) :: kpm

difequ (subroutine)
eqblok (subroutine)
putit (subroutine)
colloc (subroutine)
difequ (subroutine)
eqblok (subroutine)
putit (subroutine)
"> common /other/

Type Attributes Name Initial
integer(kind=4) :: itermx
integer(kind=4) :: k
real :: rho(19)

difequ (subroutine)
eqblok (subroutine)
putit (subroutine)
colloc (subroutine)
difequ (subroutine)
eqblok (subroutine)
putit (subroutine)
"> common /side/

Type Attributes Name Initial
integer(kind=4) :: m
integer(kind=4) :: iside
real :: xside(10)

Source Code

subroutine colloc ( aleft, aright, lbegin, iorder, ntimes, addbrk, relerr )

  !*****************************************************************************80
  !
  !! COLLOC solves an ordinary differential equation by collocation.
  !
  !  Method:
  !
  !    The M-th order ordinary differential equation with M side 
  !    conditions, to be specified in subroutine DIFEQU, is solved 
  !    approximately by collocation.
  !
  !    The approximation F to the solution G is piecewise polynomial of order 
  !    K+M with L pieces and M-1 continuous derivatives.   F is determined by 
  !    the requirement that it satisfy the differential equation at K points 
  !    per interval (to be specified in COLPNT ) and the M side conditions.
  !
  !    This usually nonlinear system of equations for F is solved by
  !    Newton's method. the resulting linear system for the B-coefficients of an
  !    iterate is constructed appropriately in EQBLOK and then solved
  !    in SLVBLK, a program designed to solve almost block
  !    diagonal linear systems efficiently.
  !
  !    There is an opportunity to attempt improvement of the breakpoint
  !    sequence, both in number and location, through the use of NEWNOT.
  !
  !    Printed output consists of the piecewise polynomial representation 
  !    of the approximate solution, and of the error at selected points.
  !
  !  Modified:
  !
  !    14 February 2007
  !
  !  Author:
  !
  !    Carl DeBoor
  !
  !  Reference:
  !
  !    Carl DeBoor,
  !    A Practical Guide to Splines,
  !    Springer, 2001,
  !    ISBN: 0387953663,
  !    LC: QA1.A647.v27.
  !
  !  Parameters: 
  !
  !    Input, real ( kind = 8 ) ALEFT, ARIGHT, the endpoints of the interval.
  !
  !    Input, integer ( kind = 4 ) LBEGIN, the initial number of polynomial 
  !    pieces in the approximation.  A uniform breakpoint sequence will be chosen.
  !
  !    Input, integer ( kind = 4 ) IORDER, the order of the polynomial pieces 
  !    to be used in the approximation
  !
  !    Input, integer ( kind = 4 ) NTIMES, the number of passes to be made 
  !    through NEWNOT.
  !
  !    Input, real ( kind = 8 ) ADDBRK, the number, possibly fractional, of 
  !    breaks to be added per pass through NEWNOT.  For instance, if 
  !    ADDBRK = 0.33334, then a breakpoint will be added at every third pass 
  !    through NEWNOT.
  !
  !    Input, real ( kind = 8 ) RELERR, a tolerance.  Newton iteration is 
  !    stopped if the difference between the B-coefficients of two successive 
  !    iterates is no more than RELERR*(absolute largest B-coefficient).
  !
  implicit none

  integer ( kind = 4 ), parameter :: npiece = 100
  integer ( kind = 4 ), parameter :: ndim = 200
  integer ( kind = 4 ), parameter :: ncoef = 2000
  integer ( kind = 4 ), parameter :: lenblk = 2000

  real ( kind = 8 ) a(ndim)
  real ( kind = 8 ) addbrk
  real ( kind = 8 ) aleft
  real ( kind = 8 ) amax
  real ( kind = 8 ) aright
  real ( kind = 8 ) asave(ndim)
  real ( kind = 8 ) b(ndim)
  real ( kind = 8 ) bloks(lenblk)
  real ( kind = 8 ) break
  real ( kind = 8 ) coef
  real ( kind = 8 ) dx
  real ( kind = 8 ) err
  integer ( kind = 4 ) i
  integer ( kind = 4 ) iflag
  integer ( kind = 4 ) ii
  integer ( kind = 4 ) integs(3,npiece)
  integer ( kind = 4 ) iorder
  integer ( kind = 4 ) iside
  integer ( kind = 4 ) itemps(ndim)
  integer ( kind = 4 ) iter
  integer ( kind = 4 ) itermx
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kpm
  integer ( kind = 4 ) l
  integer ( kind = 4 ) lbegin
  integer ( kind = 4 ) lnew
  integer ( kind = 4 ) m
  integer ( kind = 4 ) n
  integer ( kind = 4 ) nbloks
  integer ( kind = 4 ) nt
  integer ( kind = 4 ) ntimes
  real ( kind = 8 ) relerr
  real ( kind = 8 ) rho
  real ( kind = 8 ) t(ndim)
  real ( kind = 8 ) templ(lenblk)
  real ( kind = 8 ) temps(ndim)
  real ( kind = 8 ) xside

  equivalence ( bloks, templ )

  save / approx /
  save / other /
  save / side /

  common / approx / break(npiece), coef(ncoef), l, kpm
  common / other / itermx, k, rho(19)
  common / side / m, iside, xside(10)

  kpm = iorder

  if ( ncoef < lbegin * kpm ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'COLLOC - Fatal error!'
     write ( *, '(a)' ) '  The assigned dimension for COEF is too small.'
     stop
  end if
  !
  !  Set the various parameters concerning the particular differential
  !  equation, including a first approximation in case the differential
  !  equation is to be solved by iteration ( 0 < ITERMX ).
  !
  call difequ ( 1, temps(1), temps )
  !
  !  Obtain the K collocation points for the standard interval.
  !
  k = kpm - m
  call colpnt ( k, rho )
  !
  !  The following five statements could be replaced by a read in
  !  order to obtain a nonuniform spacing of the breakpoints.
  !
  dx = ( aright - aleft ) / real ( lbegin, kind = 8 )

  temps(1) = aleft
  do i = 2, lbegin
     temps(i) = temps(i-1) + dx
  end do
  temps(lbegin+1) = aright
  !
  !  Generate the required knots T(1:N+KPM).
  !
  call knots ( temps, lbegin, kpm, m, t, n )
  nt = 1
  !
  !  Generate the almost block diagonal coefficient matrix BLOKS and
  !  right hand side B from collocation equations and side conditions.
  !
  !  Then solve via SLVBLK, obtaining the B-representation of the 
  !  approximation in T, A, N, KPM.
  !
  do

     call eqblok ( t, n, kpm, temps, a, bloks, lenblk, integs, nbloks, b )

     call slvblk ( bloks, integs, nbloks, b, itemps, a, iflag )
     !
     !  Save B-spline coefficients of current approximation in ASAVE, then 
     !  get new approximation and compare with old. 
     !
     !  If coefficients are more than RELERR apart (relatively) or if number 
     !  of iterations is less than ITERMX, continue iterating.
     !
     do iter = 1, itermx

        call bsplpp ( t, a, n, kpm, templ, break, coef, l )

        asave(1:n) = a(1:n)

        call eqblok ( t, n, kpm, temps, a, bloks, lenblk, integs, nbloks, b )

        call slvblk ( bloks, integs, nbloks, b, itemps, a, iflag )

        amax = maxval ( abs ( a(1:n) ) )
        err = maxval ( abs ( a(1:n) - asave(1:n) ) )

        if ( err <= relerr * amax ) then
           exit
        end if

     end do
     !
     !  Iteration (if any) completed.  Print out approximation based on current
     !  breakpoint sequence, then try to improve the sequence.
     !
     write ( *, '(a)' ) ' '
     write ( *,'(a,i3,a,i3,a)' ) &
          '  Approximation from a space of splines of order ', kpm, &
          ' on ', l, ' intervals'
     write ( *, '(a,i4)' ) '  of dimension ', n
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) '  Breakpoints:'
     write ( *, '(a)' ) ' '
     write ( *, '(5g14.6)' ) break(2:l)

     if ( 0 < itermx ) then
        write ( *, '(a)' ) ' '
        write ( *, '(a,i8)' ) '  Results on interation ', iter
     end if

     call bsplpp ( t, a, n, kpm, templ, break, coef, l )

     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) &
          '  The piecewise polynomial representation of the approximation:'
     write ( *, '(a)' ) ' '

     do i = 1, l
        ii = ( i - 1 ) * kpm
        write ( *, '(f9.3,2x,e12.4,10e11.3)' ) break(i), coef(ii+1:ii+kpm)
     end do
     !
     !  The following call is provided here for possible further analysis
     !  of the approximation specific to the problem being solved.
     !  It is, of course, easily omitted.
     !
     call difequ ( 4, temps(1), temps )

     if ( ntimes < nt ) then
        exit
     end if
     !
     !  From the piecewise polynomial representation of the current approximation, 
     !  obtain in NEWNOT a new, and possibly better, sequence of breakpoints, 
     !  adding, on average, ADDBRK breakpoints per pass through NEWNOT.
     !
     lnew = lbegin + int ( real ( nt, kind = 8 ) * addbrk )

     if ( ncoef < lnew * kpm ) then
        write ( *, '(a)' ) ' '
        write ( *, '(a)' ) 'COLLOC - Fatal error!'
        write ( *, '(a)' ) '  The assigned dimension for COEF is too small.'
        stop
     end if

     call newnot ( break, coef, l, kpm, temps, lnew, templ )

     call knots ( temps, lnew, kpm, m, t, n )
     nt = nt + 1

  end do

  return  
end subroutine colloc