Actual source code: ex83f.F90

  1: !
  2: !     Creates a tridiagonal sparse matrix explicitly in Fortran and solves a linear system with it
  3: !
  4: !     The matrix is provided in two three ways
  5: !       Compressed sparse row: ia(), ja(), and a()
  6: !     Entry triples:  rows(), cols(), and a()
  7: !     Entry triples in a way that supports new nonzero values with the same nonzero structure
  8: !
  9: #include <petsc/finclude/petscksp.h>
 10: program main
 11:   use petscksp
 12:   implicit none

 14:   PetscInt i, n
 15:   PetscCount nz
 16:   PetscBool flg, equal
 17:   PetscErrorCode ierr
 18:   PetscInt, allocatable, dimension(:) :: ia, ja, rows, cols
 19:   PetscScalar, allocatable, dimension(:) :: a, x, b

 21:   Mat J, Jt, Jr
 22:   Vec rhs, solution
 23:   KSP ksp
 24:   PC pc

 26:   PetscCallA(PetscInitialize(ierr))
 27:   n = 3
 28:   PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-n', n, flg, ierr))
 29:   nz = 3*n - 4

 31:   allocate (b(n), x(n))

 33: !     Fill the sparse matrix representation
 34:   allocate (ia(n + 1), ja(nz), a(nz))
 35:   allocate (rows(nz), cols(nz))

 37:   b(1:n) = 1.0

 39: !     PETSc ia() and ja() values begin at 0, not 1, you may need to shift the indices used in your code
 40:   ia(1) = 0
 41:   ia(2) = 1
 42:   do i = 3, n
 43:     ia(i) = ia(i - 1) + 3
 44:   end do
 45:   ia(n + 1) = ia(n) + 1

 47:   ja(1) = 0
 48:   rows(1) = 0; cols(1) = 0
 49:   a(1) = 1.0
 50:   do i = 2, n - 1
 51:     ja(2 + 3*(i - 2)) = i - 2
 52:     rows(2 + 3*(i - 2)) = i - 1; cols(2 + 3*(i - 2)) = i - 2
 53:     a(2 + 3*(i - 2)) = -1.0
 54:     ja(2 + 3*(i - 2) + 1) = i - 1
 55:     rows(2 + 3*(i - 2) + 1) = i - 1; cols(2 + 3*(i - 2) + 1) = i - 1
 56:     a(2 + 3*(i - 2) + 1) = 2.0
 57:     ja(2 + 3*(i - 2) + 2) = i
 58:     rows(2 + 3*(i - 2) + 2) = i - 1; cols(2 + 3*(i - 2) + 2) = i
 59:     a(2 + 3*(i - 2) + 2) = -1.0
 60:   end do
 61:   ja(nz) = n - 1
 62:   rows(nz) = n - 1; cols(nz) = n - 1
 63:   a(nz) = 1.0

 65:   PetscCallA(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n, n, ia, ja, a, J, ierr))
 66:   PetscCallA(MatCreateSeqAIJFromTriple(PETSC_COMM_SELF, n, n, rows, cols, a, Jt, nz, PETSC_FALSE, ierr))
 67:   PetscCallA(MatEqual(J, Jt, equal, ierr))
 68:   PetscCheckA(equal .eqv. PETSC_TRUE, PETSC_COMM_SELF, PETSC_ERR_PLIB, 'Matrices J and Jt must be equal')
 69:   PetscCallA(MatDestroy(Jt, ierr))
 70:   PetscCallA(MatCreate(PETSC_COMM_SELF, Jr, ierr))
 71:   PetscCallA(MatSetSizes(Jr, n, n, n, n, ierr))
 72:   PetscCallA(MatSetType(Jr, MATSEQAIJ, ierr))
 73:   PetscCallA(MatSetPreallocationCOO(Jr, nz, rows, cols, ierr))
 74:   PetscCallA(MatSetValuesCOO(Jr, a, INSERT_VALUES, ierr))
 75:   PetscCallA(MatEqual(J, Jr, equal, ierr))
 76:   PetscCheckA(equal .eqv. PETSC_TRUE, PETSC_COMM_SELF, PETSC_ERR_PLIB, 'Matrices J and Jr must be equal')

 78:   PetscCallA(VecCreateSeqWithArray(PETSC_COMM_SELF, 1_PETSC_INT_KIND, n, b, rhs, ierr))
 79:   PetscCallA(VecCreateSeqWithArray(PETSC_COMM_SELF, 1_PETSC_INT_KIND, n, x, solution, ierr))

 81:   PetscCallA(KSPCreate(PETSC_COMM_SELF, ksp, ierr))
 82:   PetscCallA(KSPSetErrorIfNotConverged(ksp, PETSC_TRUE, ierr))
 83: ! Default to a direct sparse LU solver for robustness
 84:   PetscCallA(KSPGetPC(ksp, pc, ierr))
 85:   PetscCallA(PCSetType(pc, PCLU, ierr))
 86:   PetscCallA(KSPSetFromOptions(ksp, ierr))
 87:   PetscCallA(KSPSetOperators(ksp, J, J, ierr))

 89:   PetscCallA(KSPSolve(ksp, rhs, solution, ierr))

 91: ! Keep the same size and nonzero structure of the matrix but change its numerical entries
 92:   do i = 2, n - 1
 93:     a(2 + 3*(i - 2) + 1) = 4.0
 94:   end do
 95:   PetscCallA(PetscObjectStateIncrease(J, ierr))
 96:   PetscCallA(MatSetValuesCOO(Jr, a, INSERT_VALUES, ierr))
 97:   PetscCallA(MatEqual(J, Jr, equal, ierr))
 98:   PetscCheckA(equal .eqv. PETSC_TRUE, PETSC_COMM_SELF, PETSC_ERR_PLIB, 'Matrices J and Jr should be equal')
 99:   PetscCallA(MatDestroy(Jr, ierr))

101:   PetscCallA(KSPSolve(ksp, rhs, solution, ierr))

103:   PetscCallA(KSPDestroy(ksp, ierr))
104:   PetscCallA(VecDestroy(rhs, ierr))
105:   PetscCallA(VecDestroy(solution, ierr))
106:   PetscCallA(MatDestroy(J, ierr))

108:   deallocate (b, x)
109:   deallocate (ia, ja, a)
110:   deallocate (rows, cols)

112:   PetscCallA(PetscFinalize(ierr))
113: end

115: !/*TEST
116: !
117: !     test:
118: !       args: -ksp_monitor -ksp_view
119: !
120: !TEST*/