V3FIT
All Classes Namespaces Files Functions Variables Enumerations Macros Pages
gmresr.f
1  SUBROUTINE gmresr(oktest,n,j,mgmres,b,x,work,eps,stc,
2  & maxits,resid,matvec,iflag)
3 C*********************************************************
4 C GMRESR algorithm to solve linear system Ax = b
5 C
6 C author:
7 C m.botchev, utrecht university, december 1996
8 C report bugs to botchev@cwi.nl or botchev@excite.com
9 C
10 C Copyright (c) 1996 by M.A.Botchev
11 C Permission to copy all or part of this work is granted,
12 C provided that the copies are not made or distributed
13 C for resale, and that the copyright notice and this
14 C notice are retained.
15 C
16 C Details to the algorithm may be found in
17 C H.A. van der Vorst, C. Vuik, "GMRESR: a Family of Nested GMRES
18 C Methods", Num. Lin. Alg. Appl., vol. 1(4), 369--386 (1994)
19 C
20 C parameter list:
21 C oktest is TRUE if intermediate residuals should be printed
22 C n == INTEGER size of problem
23 C j == INTEGER truncation parameter (work with j last vectors)
24 C mgmres == INTEGER dimension of the invoked GMRES
25 C if mgmres.eq.0 then we get GCR algorithm, the simplest
26 C version of GMRESR
27 C b == real*8 righthand side vector
28 C x == real*8 initial guess on input,
29 C (approximate) solution on output
30 C work == real*8 work space 1 of size n x (2*j+mgmres+2)
31 C eps == real*8 tolerance of stopping criterion.
32 C process is stopped as soon as
33 C (1) residual norm has been decreased by factor eps,
34 C i.e. ||res|| / ||res0|| <= eps OR
35 C (2) maximum number of iterations maxit has been performed
36 C stc == CHARACTER*3
37 C Determine stopping criterion (||.|| denotes the 2-norm):
38 C stc='rel' -- relative stopping crit.: ||res|| < eps*||res0||
39 C stc='abs' -- absolute stopping crit.: ||res|| < eps
40 C maxits == INTEGER max. no. outer_iterative_steps/truncation_length on input
41 C on output it is the actual number of total iterative steps
42 C resid == real*8 residual measure (depends on stopping criterion)
43 C achieved on output
44 C iflag == INTEGER on output 0 - solution found within tolerance
45 C 1 - no convergence within maxits
46 C ----------------------------------------------------------
47 C subroutines used
48 C matvec == matrix-vector product y <- A*x
49 C blas subroutines:
50 C dscal
51 C daxpy
52 C blas functions:
53 C ddot
54 C dnrm2
55 C**********************************************************
56 
57  external matvec
58 
59 C list of variables: arrays in alphabetical order,
60 C then other variables in alphabetical order
61 
62  logical oktest
63  character*3 stc
64 
65  integer i,iflag,its,nits,itsinn,j,k,maxits,mgmres,n
66 
67  real*8 b(n),x(n),work(n,0:(2*j+mgmres+2-1)),
68  & alpha,alphai,cknorm,ckres,ddot,dnrm2,eps,epsinn,
69  & res0,resnor,resid
70 
71 C distribute work space work(n,*) among some virtual variables;
72 C namely, we think of columns of work as being occupied by
73 C c(n,0:j-1), u(n,0:j-1), resid(n), workgmr(n,mgmres+1)
74 C therefore we define "shifts"
75 
76  integer c, u, workres, workgmre
77 C ----------------------------------------------------------------------------
78 
79  if((stc.NE.'rel').and.(stc.NE.'abs'))then
80  print *,'Error in VACGMRESR:'
81  print *,'PARAMETER STC=',stc,' SHOULD BE rel OR abs.'
82  stop
83  endif
84 
85 C c occupies j columns 0...j-1:
86  c = 0
87 C u occupies j columns j...2*j-1:
88  u = j
89 C resid occupies 1 column No. 2*j:
90  workres = 2*j
91 C workgmre occupies mgmres+1 columns 2*j+1...2*j+mgmres+1:
92  workgmre = 2*j+1
93 C so that we can access, say, to the (k)th column of the virtual
94 C array c(n,0:j-1) as work(1,c+k),
95 C virtual residual vector resid(n) is work(1,workres) and so on ...
96 
97 C ***Furthermore, we build sequences c_k and u_k, k = 0,...,m-1
98 C but we store only the last j vectors in the following way:
99 C Assume j=3, then
100 C --------------------------------------------------------------
101 C k | number of column of work | columns of work which are vectors
102 C | in which we store c_k | we actually store and use
103 C 0 | 0 | c_0 u_0 ...
104 C 1 | 1 | c_0 c_1 u_0 u_1 ...
105 C 2 | 2 | c_0 c_1 c_2 u_0 u_1 u_2 ...
106 C 3 | 0 | c_3 c_1 c_2 u_3 u_1 u_2 ...
107 C 4 | 1 | c_3 c_4 c_2 u_3 u_4 u_2 ...
108 C 5 | 2 | c_3 c_4 c_5 u_3 u_4 u_5 ...
109 C 6 | 0 | c_6 c_4 c_5 u_6 u_4 u_5 ...
110 C ... | ... | ... ...
111 C This mapping is performed by function mod(k,j)
112 
113 C Reset iteration counter
114  nits= 0
115  its = 0
116 
117 C Calculate (initial) residual norm
118  call matvec(x,work(1,workres),n)
119  alpha = -1
120  call daxpy(n,alpha,b,1,work(1,workres),1)
121  call dscal(n,alpha,work(1,workres),1)
122 
123 C Calculate residual norm and quit if it is zero
124  res0 = dnrm2(n,work(1,workres),1)
125  resnor = res0
126  resid = 0
127 
128  if ( res0 .eq. 0.0d0 ) then
129  iflag = 0
130  maxits = 0
131  return
132  end if
133 
134  if (stc.eq.'abs') then
135  resid=resnor
136  else
137  resid=resnor/res0
138  endif
139 
140  if ( resid .le. eps ) then
141  iflag = 0
142  maxits = 0
143  return
144  end if
145 
146 C Main iterative loop ============================
147  k = -1
148  do while (.true.)
149 
150  if(oktest)write(*,199)its,resid
151  199 format(' its =', i4, ' resid =', d20.6)
152 
153 C Loop to increment dimension of projection subspace
154  k=k+1
155 
156 C Number of step (not restart) to be done
157  its = its + 1
158 C write(*,'(A,i3)') '+++++++++++++++++ its ',its
159 
160 C - - - - - - - - - - - - - - - - - - - - - - - - -
161 C This part should deliver
162 C u(1,k) <-- invA * resid
163 C where u(1,k) is the k-th column of array u(1:n,0:m) and
164 C invA is some reasonable approximation to the inverse of A
165 C
166 C If mgmres=0 then no inner iterations are performed
167 C to get invA, so that invA is just the identity matrix.
168 C In this case algorithm GMRESR is nothing but GCR
169 C
170 C Otherwise for inner iterations we perform ONE restart of GMRES
171 C ATTN: for this implementation it is crucial to perform only
172 C ONE restart of GMRES
173  if (mgmres.eq.0) then
174 C u(1,k) := resid
175  call dcopy(n,work(1,workres),1,work(1,u+mod(k,j)),1)
176  call matvec(work(1,u+mod(k,j)),work(1,c+mod(k,j)),n)
177  nits=nits+1
178  else
179 C Solve linear system A*u(1,k)=resid by GMRES
180 C The stopping criterion for inner iterations is
181 C always absolute but it is automatically adjusted
182 C not to be stricter than the stopping criterion for the
183 C outer iterations. For example, if stop.criterion for
184 C the outer iterations is relative than absolute stop.
185 C criterion for the inner iterations is (eps*res0)
186 C Accuracy for inner iteration:
187 
188  if(stc.eq.'abs')then
189  epsinn = eps
190  else
191  epsinn = eps*res0
192  endif
193 
194 C After envoking gmres0 epsinn and itsinn contain actual achieved
195 C accuracy and number of performed iterations respectively
196 
197  itsinn=mgmres
198 
199  call gmres0(oktest,n,mgmres,
200  & work(1,workres),work(1,u+mod(k,j)),
201  & work(1,c+mod(k,j)),work(1,workgmre),
202  & epsinn,itsinn,matvec)
203 
204  nits=nits+itsinn
205  end if
206 C - - - - - - - - - - - - - - - - - - - - - - - -
207 
208 C Inner loop to orthogonalize
209 C c(1,k) with respect to c(1,k-j),...,c(1,k-1)
210 C and to update correspondingly
211 C u(1,k) with respect to u(1,k-j),...,u(1,k-1)
212 C parameter j is used only here
213  do i = max0(0,k-j),k-1
214  alphai = ddot(n,work(1,c+mod(i,j)),1,work(1,c+mod(k,j)),1)
215  call daxpy(n,-alphai,work(1,c+mod(i,j)),1,
216  & work(1,c+mod(k,j)),1)
217  call daxpy(n,-alphai,work(1,u+mod(i,j)),1,
218  & work(1,u+mod(k,j)),1)
219  end do
220 
221 C Normalize c(1,k) and "normalize" u(1,k)
222  cknorm = dnrm2(n,work(1,c+mod(k,j)),1)
223  cknorm = 1 / cknorm
224  call dscal(n,cknorm,work(1,c+mod(k,j)),1)
225  call dscal(n,cknorm,work(1,u+mod(k,j)),1)
226 
227 C Update current solution and residual
228  ckres = ddot(n,work(1,c+mod(k,j)),1,work(1,workres),1)
229  call daxpy(n, ckres,work(1,u+mod(k,j)),1,x, 1)
230  call daxpy(n,-ckres,work(1,c+mod(k,j)),1,work(1,workres),1)
231 
232 C call show(n,10,x,'GMRESR ')
233 
234 C Calculate residual norm, check convergence
235  resnor = dnrm2(n,work(1,workres),1)
236 
237  if (stc.eq.'abs') then
238  resid=resnor
239  else
240  resid=resnor/res0
241  endif
242 
243  if ( resid .le. eps ) then
244  iflag = 0
245  maxits = nits
246  return
247  end if
248  if (its .ge. maxits*j) then
249  iflag = 1
250  maxits = nits
251  return
252  end if
253 
254 C print 11, ' ||res|| = ',resnor
255 C 11 format(A,d)
256 C 13 format(i4,A,d)
257 
258  end do
259 C End of infinite iterative loop =================
260 C End of GMRESR subroutine
261  end
262 
263 C=============================================================================
264  subroutine gmres0(oktest,n,im,rhs,uu,cc,work0,eps,maxits,matvec)
265 
266 C This is the modified GMRES routine gmres0 adapted for GMRESR by
267 C Mike Botchev, Utrecht University, Dec. 1996
268 C For detail on how to make GMRES (for GMRESR) cheaper see
269 C the above-mentioned paper on GMRESR
270 c*************************************************************
271 C This code was initially written by Youcef Saad
272 C then revised by Henk A. van der Vorst
273 C and Mike Botchev (oct. 1996)
274 C ************************************************************
275 c gmres algorithm . simple version . (may 23, 1985)
276 c parameter list:
277 c oktest == TRUE for printing intermediate results
278 c n == size of problem
279 c im == size of krylov subspace: should not exceed 50 in this
280 c version (can be reset in code. looking at comment below)
281 c rhs == right hand side
282 c uu == initial guess for vector u (see above-mentioned paper on GMRESR)
283 c on input, approximate solution on output
284 c cc == initial guess for vector c (see above-mentioned paper on GMRESR)
285 c on input, approximate solution on output
286 c work0 == work space of size n x (im+1)
287 c eps == tolerance for stopping criterion. process is stopped
288 c as soon as ( ||.|| is the euclidean norm):
289 c || current residual || <= eps
290 c maxits == maximum number of iterations allowed
291 c on OUTPUT: actual number of iterations performed
292 c ----------------------------------------------------------------
293 c subroutines
294 c matvec == matrix vector multiplication y <- A*x
295 c
296 c BLAS:
297 c dcopy == y <-- x routine
298 c ddot == dot product function
299 c dnrm2 == euclidean norm function
300 c daxpy == y <-- y+ax routine
301 c dscal == x <-- ax routine
302 c dtsrv == to solve linear system with a triangular matrix
303 c*************************************************************
304 c-------------------------------------------------------------
305 c arnoldi size should not exceed 10 in this version..
306 c to reset modify maxdim. BUT: ----------------
307 c maxdim was set to 10 because of two reasons:
308 c (1) it is assumed in this implementation that it is cheaper to
309 c make maxdim vector updates than to make 1 matrix-vector
310 c multiplication;
311 c (2) for large maxdim we may lose the orthogonality property
312 c on which this cheap implementation is based.
313 c Please keep it in mind changing maxdim
314 c-------------------------------------------------------------
315  integer maxdim,maxd1,md1max
316  parameter(maxdim=10, maxd1=maxdim+1, md1max=maxdim*maxd1)
317  external matvec
318 
319  logical oktest
320  integer jjj,jj1
321  integer i,i1,im,its,j,k,k1,maxits,n
322  real*8 cc,coeff,coef1,dabs,ddot,dnrm2,dsqrt,eps,epsmac,
323  & gam,rhs(n),ro,uu(n),work0(n,im+1),t
324 
325  real*8 hh(maxd1,maxdim),hh1(maxd1,maxdim),c(maxdim),
326  & s(maxdim),rs(maxd1),rs1(maxd1)
327 
328  data (( hh(jj1,jjj), jj1=1,maxd1), jjj=1,maxdim) / md1max*0.0 / ,
329  & epsmac / 1.d-16 /
330 C-----------------------------------------------------------------------------
331 
332  if (im .gt. maxdim) then
333  im = maxdim
334  write (*,'(A,i2)') 'GMRES0: dimension has been reduced to ',im
335  write (*,'(A)') ' =&gt; reset MAXDIM if you want it to be more'
336  write (*,'(A)') ' BUT read comments near MAXDIM before'
337  end if
338 
339  its = 0
340 
341 C ----------------------------
342 C Outer loop starts here..
343 C BUT here (for GMRESR) only 1 outer loop is allowed
344 C Compute initial residual vector
345 C ----------------------------
346  10 continue
347 C do not calculate initial residual first restart because
348 C initial guess is always zero.
349 C make initial guess zero:
350  coeff = 0.0
351  call dscal(n,coeff,uu,1)
352 C make initial residual right-hand side:
353  call dcopy(n,rhs,1,work0,1)
354 
355  ro = dnrm2(n, work0, 1)
356  if ((ro .eq. 0.0d0).or.(ro .le. eps)) then
357  call matvec(uu, cc, n)
358  eps = ro
359  maxits = its
360  return
361  end if
362 
363  coeff = 1 / ro
364  call dscal(n,coeff,work0,1)
365 
366  if (oktest) write(*, 199) its, ro
367 
368 c initialize 1-st term of rhs of hessenberg system..
369  rs(1) = ro
370  i = 0
371 
372  4 continue
373  i=i+1
374  its = its + 1
375  i1 = i + 1
376  call matvec(work0(1,i), work0(1,i1), n)
377 c -----------------------------------------
378 c modified gram - schmidt...
379 c -----------------------------------------
380  do j=1, i
381  t = ddot(n, work0(1,j),1,work0(1,i1),1)
382  hh(j,i) = t
383  call daxpy(n, -t, work0(1,j), 1, work0(1,i1), 1)
384  end do
385  t = dnrm2(n, work0(1,i1), 1)
386  hh(i1,i) = t
387  if (t .ne. 0.0d0)then
388  t = 1 / t
389  call dscal(n, t, work0(1,i1), 1)
390 C save new column of hh in hh1 to reproduce vector cc later on
391  call dcopy(maxd1,hh(1,i),1,hh1(1,i),1)
392  endif
393 c done with modified gram schmidt and arnoldi step..
394 
395 c now update factorization of hh
396  if (i .ne. 1) then
397 c perform previous transformations on i-th column of h
398  do k=2,i
399  k1 = k-1
400  t = hh(k1,i)
401  hh(k1,i) = c(k1)*t + s(k1)*hh(k,i)
402  hh(k,i) = -s(k1)*t + c(k1)*hh(k,i)
403  end do
404  endif
405  gam = dsqrt(hh(i,i)**2 + hh(i1,i)**2)
406  if (gam .eq. 0.0d0) gam = epsmac
407 
408 c determine next plane rotation
409  c(i) = hh(i,i)/gam
410  s(i) = hh(i1,i)/gam
411  rs(i1) = -s(i)*rs(i)
412  rs(i) = c(i)*rs(i)
413 
414 c determine residual norm and test for convergence-
415  hh(i,i) = c(i)*hh(i,i) + s(i)*hh(i1,i)
416  ro = dabs(rs(i1))
417  if (oktest) write(*, 199) its, ro
418  if ((i .lt. im) .and. (ro .gt. eps)) goto 4
419 c
420 c now compute solution. first solve upper triangular system.
421 c
422 C rs := hh(1:i,1:i) ^-1 * rs
423 
424  call dtrsv('U','N','N',i,hh,maxd1,rs,1)
425 c done with back substitution..
426 
427 c now form linear combination to get vector uu
428  do j=1, i
429  t = rs(j)
430  call daxpy(n, t, work0(1,j), 1, uu,1)
431  end do
432 C DO NOT restart outer loop EVEN when necessary (that is crucial
433 C for this implementation of GMRESR): NEVER goto 10 !
434 C if (ro .gt. eps .and. its .lt. maxits) goto 10
435 
436 C Finally, reproduce vector cc as cc = A*uu = work0*hh1*rs:
437 C rs := hh1(1:i1,1:i) * rs
438  coeff = 1
439  coef1 = 0
440  call dgemv('N',i1,i,coeff,hh1,maxd1,rs,1,coef1,rs1,1)
441 
442 C now multiply Krylov basis vectors work0 by rs:
443 C cc := work0*rs
444  call dscal(n,coef1,cc,1)
445  do j=1, i1
446  t = rs1(j)
447  call daxpy(n, t, work0(1,j), 1, cc,1)
448  end do
449 
450  199 format('itsinn =', i4, ' res. norm =', d20.6)
451 
452  maxits=its
453  eps=ro
454  return
455 c------------------------------- end of gmres0 ----------------------
456  end