IBM Books

Parallel Engineering and Scientific Subroutine Library for AIX Version 2 Release 3: Guide and Reference

Example--Using the Fortran 90 Sparse Subroutines

This example finds the solution to the linear system Ax = b. It also contains an application program that shows how you can use the Fortran 90 sparse linear algebraic equation subroutines and their utilities to solve this example.

The following is the general sparse matrix A:

          *                                                   *
          | 2.0  0.0   0.0  0.0   0.0   0.0   0.0   0.0   0.0 |
          | 0.0  2.0  -1.0  0.0   0.0   0.0   0.0   0.0   0.0 |
          | 0.0  1.0   2.0  0.0   0.0   0.0   0.0   0.0   0.0 |
          | 1.0  0.0   0.0  2.0  -1.0   0.0   0.0   0.0   0.0 |
          | 0.0  0.0   0.0  1.0   2.0  -1.0   0.0   0.0   0.0 |
          | 0.0  0.0   0.0  0.0   1.0   2.0  -1.0   0.0   0.0 |
          | 0.0  0.0   0.0  0.0   0.0   1.0   2.0  -1.0   0.0 |
          | 0.0  0.0   0.0  0.0   0.0   0.0   1.0   2.0  -1.0 |
          | 0.0  0.0   0.0  0.0   0.0   0.0   0.0   1.0   2.0 |
          *                                                   *

The following is the dense vector b, containing the right-hand side:

    *     *
    | 2.0 |
    | 1.0 |
    | 3.0 |
    | 2.0 |
    | 2.0 |
    | 2.0 |
    | 2.0 |
    | 2.0 |
    | 3.0 |
    *     *

The following is the dense vector x, containing the initial guess to the solution:

    *     *
    | 0.0 |
    | 0.0 |
    | 0.0 |
    | 0.0 |
    | 0.0 |
    | 0.0 |
    | 0.0 |
    | 0.0 |
    | 0.0 |
    *     *

Output

Global vector x:

 B,D    0
    *     *
    | 1.0 |
 0  | 1.0 |
    | 1.0 |
    | --- |
    | 1.0 |
 1  | 1.0 |
    | 1.0 |
    | --- |
    | 1.0 |
 2  | 1.0 |
    | 1.0 |
    *     *

The following is the 3 × 1 process grid:

B,D  |    0    
-----| -------  
0    |   P00
-----| -------  
1    |   P10
-----| -------  
2    |   P20

Local vector x:

   p,q |   0
------|------
      |  1.0
   0  |  1.0
      |  1.0
------|------
      |  1.0
   1  |  1.0
      |  1.0
------|------
      |  1.0
   2  |  1.0
      |  1.0

ITER = 4

ERR = 0.4071D-15

The value of info is 0 on all processes.

Application Program

This application program illustrates how to use the Fortran 90 sparse linear algebraic equation subroutines and their utilities.

@process init(f90ptr)
!
! This program illustrates how to use the PESSL F90 Sparse Iterative
! Solver and its supporting utility subroutines.  A very simple problem
! (DSRIS Example 1 from the ESSL Guide and Reference) using an
! HPF BLOCK data distribution is solved.
!
      PROGRAM EXAMPLE90
 
! Interface module required to use the PESSL F90 Sparse Iterative Solver
 
      USE F90SPARSE
      IMPLICIT NONE
 
! Interface definition for the PARTS subroutine PART_BLOCK
 
      INTERFACE PART_BLOCK
       SUBROUTINE PART_BLOCK(GLOBAL_INDX,N,NP,PV,NV)
       IMPLICIT NONE
       INTEGER, INTENT(IN)  :: GLOBAL_INDX, N, NP
       INTEGER, INTENT(OUT) :: NV
       INTEGER, INTENT(OUT) :: PV(*)
 
       END SUBROUTINE PART_BLOCK
      END INTERFACE
 
! Parameters
      CHARACTER, PARAMETER          :: ORDER='R'
      INTEGER, PARAMETER            :: IZERO=0, IONE=1
 
! Sparse Matrices
      TYPE(D_SPMAT)                 :: A, BLCK
! Preconditioner Data Structure
      TYPE(D_PRECN)                 :: PRC
 
! Dense Vectors
      REAL(KIND(1.D0)), POINTER     :: B(:), X(:)
 
! Communications data structure
      TYPE(DESC_TYPE)               :: DESC_A
 
! BLACS parameters
      INTEGER            :: NPROW, NPCOL, ICTXT, IAM, NP, MYROW, MYCOL
 
! Solver parameters
      INTEGER            :: ITER, ITMAX, IERR, ITRACE,
     &                      IPREC, METHD, ISTOPC, IPARM(20)
      REAL(KIND(1.D0))   :: ERR, EPS, RPARM(20)
 
! Other variables
      CHARACTER*5        :: AFMT, ATYPE
      INTEGER            :: IRCODE, IRCODE1, IRCODE2, IRCODE3
      INTEGER            :: I,J
      INTEGER            :: N,NNZERO
      INTEGER, POINTER   :: PV(:)
      INTEGER            :: LPROCS, NROW, NCOL
      INTEGER            :: GLOBAL_INDX, NV_COUNT
      INTEGER            :: GLOBAL_INDX_OWNER, NV
      INTEGER            :: LOCAL_INDX
!
!     Global Problem
!      DSRIS Example 1 from the ESSL Guide and Reference
!
      REAL*8          :: A_GLOBAL(22),B_GLOBAL(9),XINIT_GLOBAL(9)
      INTEGER         :: JA(22),IA(10)
      DATA A_GLOBAL     /2.D0,2.D0,-1.D0,1.D0,2.D0,1.D0,2.D0,-1.D0,
     $                   1.D0,2.D0,-1.D0,1.D0,2.D0,-1.D0,1.D0,2.D0,
     $                  -1.D0,1.D0,2.D0,-1.D0,1.D0,2.D0/
      DATA JA           /1,2,3,2,3,1,4,5,4,5,6,5,6,7,6,7,8,
     $                   7,8,9,8,9/
      DATA IA           /1,2,4,6,9,12,15,18,21,23/
 
      DATA B_GLOBAL     /2.D0,1.D0,3.D0,2.D0,2.D0,2.D0,2.D0,2.D0,
     $                   3.D0/
      DATA XINIT_GLOBAL /0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,0.D0,
     $                   0.D0/
 
! Initialize BLACS
! Define a NP x 1 Process Grid
 
      CALL BLACS_PINFO(IAM, NP)
      CALL BLACS_GET(IZERO, IZERO, ICTXT)
      CALL BLACS_GRIDINIT(ICTXT, ORDER, NP, IONE)
      CALL BLACS_GRIDINFO(ICTXT, NPROW, NPCOL, MYROW, MYCOL)
 
!
! Initialize the global problem size
!
      N = SIZE(IA)-1
 
!
! Guess for the local number of nonzeros
!
      NNZERO = SIZE(A_GLOBAL)
 
!
! Allocate and initialize some elements of the sparse matrix A
! its descriptor vector, DESC_A, the rhs vector B, and the
! solution vector X.
!
      CALL PADALL(N,PART_BLOCK,DESC_A,ICTXT)
      CALL PSPALL(A,DESC_A,NNZ=NNZERO)
      CALL PGEALL(B,DESC_A)
      CALL PGEALL(X,DESC_A)
 
!
! Allocate an integer work area to be used as an argument for
! the PART_BLOCK PARTS subroutine
!
      NROW   = N
      NCOL   = NROW
      LPROCS = MAX(NPROW, NROW + NCOL)
      ALLOCATE(PV(LPROCS), STAT = IRCODE)
      IF (IRCODE /= 0) THEN
       WRITE(6,*) 'PV Allocation failed'
       CALL BLACS_ABORT(ICTXT,-1)
       STOP
      ENDIF
 
 
! SETUP BLCK
 
      BLCK%M  = 1
      BLCK%N  = NCOL
      BLCK%FIDA = 'CSR'
 
      ALLOCATE(BLCK%AS(BLCK%N),STAT=IRCODE1)
      ALLOCATE(BLCK%IA1(BLCK%N),STAT=IRCODE2)
      ALLOCATE(BLCK%IA2(BLCK%M+1),STAT=IRCODE3)
      IRCODE = IRCODE1 + IRCODE2 + IRCODE3
      IF (IRCODE /= 0) THEN
       WRITE(6,*) 'Error allocating BLCK'
       CALL BLACS_ABORT(ICTXT,-1)
       STOP
      ENDIF
 
!
! In this simple example, all processes have a copy of
! the global sparse matrix, A, the global rhs vector, B,
! and the global initial guess vector, X.
!
! Each process will call PSPINS as many times as necessary
! to insert the local rows it owns.
!
! Each process will call PGEINS as many times as necessary
! to insert the local elements it owns.
!
      DO GLOBAL_INDX = 1, NROW
       CALL PART_BLOCK(GLOBAL_INDX,N,NP,PV,NV)
!
! In this simple example, NV will always be 1
! since there will not be duplicate coefficients
!
       DO NV_COUNT = 1, NV
        GLOBAL_INDX_OWNER = PV(NV_COUNT)
        IF (GLOBAL_INDX_OWNER == MYROW) THEN
         BLCK%IA2(1) = 1
         BLCK%IA2(2) = 1
         DO J = IA(GLOBAL_INDX), IA(GLOBAL_INDX+1)-1
          BLCK%AS(BLCK%IA2(2)) = A_GLOBAL(J)
          BLCK%IA1(BLCK%IA2(2)) = JA(J)
          BLCK%IA2(2) =BLCK%IA2(2) + 1
         ENDDO
         CALL PSPINS(A,GLOBAL_INDX,1,BLCK,DESC_A)
         CALL PGEINS(B,B_GLOBAL(GLOBAL_INDX:GLOBAL_INDX),
     &               DESC_A,GLOBAL_INDX)
         CALL PGEINS(X,XINIT_GLOBAL(GLOBAL_INDX:GLOBAL_INDX),
     &               DESC_A,GLOBAL_INDX)
        ENDIF
       END DO
      END DO
 
! Assemble A and DESC_A
      AFMT = 'DEF'
      ATYPE = 'GEN'
      CALL PSPASB(A,DESC_A,MTYPE=ATYPE,
     &            STOR=AFMT,DUPFLAG=2,INFO=IERR)
 
      IF (IERR /= 0) THEN
       IF (IAM.EQ.0) THEN
        WRITE(6,*) 'Error in assembly :',IERR
        CALL BLACS_ABORT(ICTXT,-1)
        STOP
       END IF
      END IF
 
! Assemble B and X
 
      CALL PGEASB(B,DESC_A)
      CALL PGEASB(X,DESC_A)
 
!
! Deallocate BLCK
!
 
      IF (ASSOCIATED(BLCK%AS))    DEALLOCATE(BLCK%AS)
      IF (ASSOCIATED(BLCK%IA1))   DEALLOCATE(BLCK%IA1)
      IF (ASSOCIATED(BLCK%IA2))   DEALLOCATE(BLCK%IA2)
!
! Deallocate Work vector
!
      IF (ASSOCIATED(PV))      DEALLOCATE(PV)
 
!
!  Preconditioning
!
!  We are using ILU for the preconditioner; PESSL
!  will allocate PRC.
!
      IPREC = 2
      CALL PSPGPR(IPREC,A,PRC,DESC_A,INFO=IERR)
 
      IF (IERR /= 0) THEN
       IF (IAM.EQ.0) THEN
        WRITE(6,*) 'Error in preconditioner :',IERR
        CALL BLACS_ABORT(ICTXT,-1)
        STOP
       END IF
      END IF
 
!
!  Iterative Solver - use the BICGSTAB method
!
      ITMAX = 1000
      EPS   = 1.D-8
      METHD = 1
      ISTOPC = 1
      ITRACE = 0
      IPARM    = 0
      IPARM(1) = METHD
      IPARM(2) = ISTOPC
      IPARM(3) = ITMAX
      IPARM(4) = ITRACE
      RPARM    = 0.0D0
      RPARM(1) = EPS
 
      CALL PSPGIS(A,B,X,PRC,DESC_A,IPARM=IPARM,RPARM=RPARM,
     &            INFO=IERR)
 
 
      IF (IERR /= 0) THEN
       IF (IAM.EQ.0) THEN
        WRITE(6,*) 'Error in solver :',IERR
        CALL BLACS_ABORT(ICTXT,-1)
        STOP
       END IF
      END IF
 
      ITER = IPARM(5)
      ERR  = RPARM(2)
      IF (IAM.EQ.0) THEN
       WRITE(6,*) 'Number of iterations : ',ITER
       WRITE(6,*) 'Error on exit        : ',ERR
      END IF
 
!
!  Each process prints their local piece of the solution vector
!
      IF (IAM.EQ.0) THEN
       Write(6,*) 'Solution Vector X'
      END IF
 
      LOCAL_INDX = 1
      Do GLOBAL_INDX = 1, NROW
       CALL PART_BLOCK(GLOBAL_INDX,N,NP,PV,NV)
!
! In this simple example, NV will always be 1
! since there will not be duplicate coefficients
!
       DO NV_COUNT = 1, NV
        GLOBAL_INDX_OWNER = PV(NV_COUNT)
        IF (GLOBAL_INDX_OWNER == MYROW) THEN
         Write(6,*) GLOBAL_INDX, X(LOCAL_INDX)
         LOCAL_INDX = LOCAL_INDX +1
        ENDIF
       END DO
      END DO
 
!
!  Deallocate the vectors, the sparse matrix, and
!  the preconditioner data structure.
!  Finally, deallocate the descriptor vector
!
       CALL PGEFREE(B, DESC_A)
       CALL PGEFREE(X, DESC_A)
       CALL PSPFREE(A, DESC_A)
       CALL PSPFREE(PRC, DESC_A)
       CALL PADFREE(DESC_A)
 
!
!  Terminate the process grid and the BLACS
!
       CALL BLACS_GRIDEXIT(ICTXT)
       CALL BLACS_EXIT(0)
 
       END PROGRAM EXAMPLE90


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]