MA 625: Full Multigrid V Cycle (McCormick)

Below is a complete nested iteration V cycle multigrid code. It appears in S. F. McCormick, Multigrid Methods, Frontiers in Applied Mathematics, vol. 3, SIAM Books, Philadelphia, 1987.

        program fmv
        implicit real*8 (a-h,o-z)
        dimension u(8000), f(8000), ks(10), ex(8000)
        do 500 i = 1,8000
          u(i) = 0.
          f(i) = 0.
          ex(i) = 0.
500     continue
        h = .5
        kst = 1
        nlev = 6
        n = 2 ** nlev
        write (*,5) n
5       format (// ' One FMV cycle for n = ', i3 // )
        do 10 k = 1,nlev
          ks(k) = kst
          n = 2 ** k + 1
          call fset ( f(kst), ex(kst), n, h )
          kst = kst + n*n
          h = h * .5
10      continue
        do 300 n = 1,nlev
          if ( n.gt.1 ) then
            do 100 k = n,2,-1
              kst = ks(k)
              kstc = ks(k-1)
              nf = 2 ** k + 1
              nc = 2 ** (k-1) + 1
              call relax ( u(kst), f(kst), nf )
              call relax ( u(kst), f(kst), nf )
              call resinj ( u(kst), f(kst), f(kstc), nf, nc )
100         continue
          endif
          do 200 k = 1,n
            kst = ks(k)
            kstf = ks(k+1)
            nc = 2 ** k + 1
            nf = 2 ** (k+1) + 1
c           call relax ( u(kst), f(kst), nc )
            call relax ( u(kst), f(kst), nc )
            if ( k.eq.n ) call err ( u(kst), ex(kst), f(kst), nc )
            if ( k.lt.nlev ) call intadd ( u(kst), u(kstf), nc, nf )
200       continue
300     continue
        end

        subroutine err ( u, ex, f, n )
        implicit real*8 (a-h,o-z)
        dimension u(n,n), f(n,n), ex(n,n)
        data once / 0 /
        h = 1. / (n-1)
        emax = 0.
        esum = 0.
        rmax = 0.
        rsum = 0.
        n1 = n - 1
        do 10 i = 2,n1
          do 10 j = 2,n1
            er = abs( u(i,j) - ex(i,j) )
            if ( er.gt.emax ) emax = er
            r = abs ( f(i,j) + u(i+1,j) + u(i-1,j) + u(i,j+1) +
     *                u(i,j-1) - 4. * u(i,j) )
            if ( r.gt.rmax ) rmax = r
            esum = esum + er*er
            rsum = rsum + r*r
10      continue
        eh = (h * esum) ** .5
        rh = (h * rsum) ** .5
        if ( once.eq.0 ) write (*,19) 'n', 'rmax', 'rh', 'emax', 'eh'
        once = 1
        write (*,20) n, rmax, rh, emax, eh
19      format ( 1x, a3, 4a12 /)
20      format ( 1x, i3, 4e12.3 )
        return
        end

        subroutine fset ( g, ex, n, h )
        implicit real*8 (a-h,o-z)
        dimension g(n,n), ex(n,n)
        h2 = h * h
        n1 = n - 1
        do 10 i = 2,n1
          x = h * (i - 1)
          x2 = x * x
          xx = x2 * (x2 - 1.)
          x6 = 6.*x2 - 1.
          do 10 j = 2,n1
            y = h * (j - 1)
            y2 = y * y
            yy = y2 * (y2 - 1.)
            ex(i,j) = xx * yy
            g(i,j)  = -2. * h2 * (x6 * yy + (6. * y2 - 1.) * xx)
10      continue
        return
        end

        subroutine relax ( v, g, n )
        implicit real*8 (a-h,o-z)
        dimension v(n,n), g(n,n)
        n1 = n - 1
        irb = 1
        do 10 krb = 1,2
          do 20 i = 2,n1
            irb = 1 - irb
            do 20 j = irb+2,n1,2
              v(i,j) = (g(i,j) + v(i+1,j) + v(i-1,j) + v(i,j+1) +
     *                  v(i,j-1)) * .25
20        continue
10      continue
        return
        end

        subroutine resinj ( v, f, g, n, nc )
        implicit real*8 (a-h,o-z)
        dimension f(n,n), v(n,n), g(nc,nc)
        n1 = nc - 1
        do 10 i = 2,n1
          i2 = 2*i - 1
          do 10 j = 2,n1
            j2 = 2*j - 1
            t = f(i2,j2) + v(i2+1,j2) + v(i2-1,j2) + v(i2,j2+1) +
     *          v(i2,j2-1)
            g(i,j) = 2.0 * t - 8.0 * v(i2,j2)
10      continue
        return
        end

        subroutine intadd ( v, w, n, nf )
        implicit real*8 (a-h,o-z)
        dimension v(n,n), w(nf,nf)
        do 10 i = 2,n
          i2 = 2*i - 1
          do 10 j = 2,n
            j2 = 2*j - 1
            w(i2,j2-1) = w(i2,j2-1) + (v(i,j)+v(i,j1-1)) * .5
            w(i2-1,j2) = w(i2-1,j2) + (v(i,j)+v(i-1,j1)) * .5
10      continue
        do 20 i = 1,n
          do 20 j = 1,n
            v(i,j) = 0.
20      continue
        return
        end