aboutsummaryrefslogtreecommitdiff
path: root/math/deboor/colloc_io.f
blob: 023612f2890ccd1147900d611171fb88ae9d277a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
subroutine colloc(aleft,aright,lbegin,iorder,ntimes,addbrk,relerr,ier)
c  from  * a practical guide to splines *  by c. de boor
chapter xv, example. solution of an ode by collocation.
calls colpnt, difequ(ppvalu(interv)), knots, eqblok(putit(difequ*,
c     bsplvd(bsplvb)))), slvblk(various subprograms), bsplpp(bsplvb*),
c     newnot
c
c******  i n p u t  ******
c  aleft, aright  endpoints of interval of approximation
c  lbegin   initial number of polynomial pieces in the approximation.
c	    a uniform breakpoint sequence is chosen.
c  iorder   order of polynomial pieces in the approximation
c  ntimes   number of passes through  n e w n o t  to be made
c  addbrk   the number (possibly fractional) of breaks to be added per
c	    pass through newnot. e.g., if addbrk = .33334, then a break-
c	    point will be added at every third pass through newnot.
c  relerr   a tolerance. newton iteration is stopped if the difference
c	    between the b-coeffs of two successive iterates is no more
c	    than  relerr*(absol.largest b-coefficient).
c
c******  p r i n t e d	 o u t p u t  ******
c     consists of the pp-representation of the approximate solution,
c     and of the error at selected points.
c
c******  m e t h o d  ******
c  the m-th order ordinary differential equation with  m  side condit-
c  ions, to be specified in subroutine	d i f e q u , is solved approx-
c  imately by collocation.
c  the approximation  f  to the solution  g  is pp of order  k+m  with
c  l  pieces and  m-1 continuous derivatives.  f  is determined by the
c  requirement that it satisfy the d.e. at  k  points per interval (to
c  be specified in  c o l p n t ) and the  m  side conditions.
c     this usually nonlinear system of equations for  f  is solved by
c  newton's method. the resulting linear system for the b-coeffs of an
c  iterate is constructed appropriately in  e q b l o k  and then solved
c  in  s l v b l k , a program designed to solve  a l m o s t  b l o c k
c  d i a g o n a l  linear systems efficiently.
c     there is an opportunity to attempt improvement of the breakpoint
c  sequence (both in number and location) through use of  n e w n o t .
c
c     parameter npiece=100, ndim=200, ncoef=2000, lenblk=2000
c     integer iorder,lbegin,ntimes,   i,iflag,ii,integs(3,npiece),iside
c    *			,iter,itermx,k,kpm,l,lnew,m,n,nbloks,nncoef,nt
      integer iorder,lbegin,ntimes,   i,iflag,ii,integs(3,100),iside
     *		  ,iter,itermx,k,kpm,l,lnew,m,n,nbloks,ncoef,nncoef,nt
c     real addbrk,aleft,aright,relerr,	 a(ndim),amax,asave(ndim)
c    *	   ,b(ndim),bloks(lenblk),break,coef,dx,err,rho,t(ndim)
c    *	   ,templ(lenblk),temps(ndim),xside
      real addbrk,aleft,aright,relerr,	 a(200),amax,asave(200)
     *	   ,b(200),bloks(2000),break,coef,dx,err,rho,t(200)
     *	   ,templ(2000),temps(200),xside
      equivalence (bloks,templ)
c     common /approx/ break(npiece), coef(ncoef), l,kpm
      common /approx/ break(100), coef(2000), l,kpm
      common /side/ m, iside, xside(10)
      common /other/ itermx,k,rho(19)
      data ncoef,lenblk / 2000,2000 /
c
      ier = 0
      kpm = iorder
      if (lbegin*kpm .gt. ncoef)	go to 999
c  *** set the various parameters concerning the particular dif.equ.
c     including a first approx. in case the de is to be solved by
c     iteration ( itermx .gt. 0) .
      call difequ (1, temps(1), temps )
c  *** obtain the  k  collocation points for the standard interval.
      k = kpm - m
      call colpnt ( k, rho )
c  *** the following five statements could be replaced by a read in or-
c     der to obtain a specific (nonuniform) spacing of the breakpnts.
      dx = (aright - aleft)/float(lbegin)
      temps(1) = aleft
      do 4 i=2,lbegin
    4	 temps(i) = temps(i-1) + dx
      temps(lbegin+1) = aright
c  *** generate, in knots, the required knots t(1),...,t(n+kpm).
      call knots ( temps, lbegin, kpm, t, n )
      nt = 1
c  *** generate the almost block diagonal coefficient matrix  bloks  and
c     right side  b  from collocation equations and side conditions.
c     then solve via  slvblk , obtaining the b-representation of the ap-
c     proximation in  t , a ,  n  , kpm  .
   10	 call eqblok(t,n,kpm,temps,a,bloks,lenblk,integs,nbloks,b)
	 call slvblk(bloks,integs,nbloks,b,temps,a,iflag)
	 iter = 1
	 if (itermx .le. 1)		go to 30
c  *** save b-spline coeff. of current approx. in  asave , then get new
c     approx. and compare with old. if coeff. are more than  relerr
c     apart (relatively) or if no. of iterations is less than  itermx ,
c     continue iterating.
   20	    call bsplpp(t,a,n,kpm,templ,break,coef,l)
	    do 25 i=1,n
   25	       asave(i) = a(i)
	    call eqblok(t,n,kpm,temps,a,bloks,lenblk,integs,nbloks,b)
	    call slvblk(bloks,integs,nbloks,b,temps,a,iflag)
	    err = 0.
	    amax = 0.
	    do 26 i=1,n
	       amax = amax1(amax,abs(a(i)))
   26	       err = amax1(err,abs(a(i)-asave(i)))
	    if (err .le. relerr*amax)	go to 30
	    iter = iter+1
	    if (iter .lt. itermx)	go to 20
c  *** iteration (if any) completed. print out approx. based on current
c     breakpoint sequence, then try to improve the sequence.
   30	 print 630,kpm,l,n,(break(i),i=2,l)
  630	 format(47h approximation from a space of splines of order,i3
     *	       ,4h on ,i3,11h intervals,/13h of dimension,i4
     *	       ,16h.  breakpoints -/(5e20.10))
 	 if (itermx .gt. 0)  print 635,iter,itermx
  635	 format(6h after,i3,3h of,i3,20h allowed iterations,)
	 call bsplpp(t,a,n,kpm,templ,break,coef,l)
 	 print 637
  637	 format(46h the pp representation of the approximation is)
 	 do 38 i=1,l
 	    ii = (i-1)*kpm
   38	    print 638, break(i),(coef(ii+j),j=1,kpm)
  638	 format(f9.3,e13.6,10e11.3)
c  *** the following call is provided here for possible further analysis
c     of the approximation specific to the problem being solved.
c     it is, of course, easily omitted.
 	 call difequ ( 4, temps(1), temps )
c
	 if (nt .gt. ntimes)		return
c  *** from the pp-rep. of the current approx., obtain in  newnot  a new
c     (and possibly better) sequence of breakpoints, adding (on the ave-
c     rage)  a d d b r k  breakpoints per pass through newnot.
	 lnew = lbegin + int(float(nt)*addbrk)
	 if (lnew*kpm .gt. ncoef)	go to 999
	 call newnot(break,coef,l,kpm,temps,lnew,templ)
	 call knots(temps,lnew,kpm,t,n)
	 nt = nt + 1
					go to 10
  999 nncoef = ncoef
      print 699,nncoef
  699 format(11h **********/23h the assigned dimension,i5
     *	    ,25h for  coef  is too small.)
 					return
      end