!
#include <petsc/finclude/petscksp.h>
program main
  use petscksp
  implicit none

!
!  This example is a modified Fortran version of ex6.c.  It tests the use of
!  options prefixes in PETSc. Two linear problems are solved in this program.
!  The first problem is read from a file. The second problem is constructed
!  from the first, by eliminating some of the entries of the linear matrix 'A'.

!  Each solve is distinguished by a unique prefix - 'a' for the first, 'b'
!  for the second.  With the prefix the user can distinguish between the various
!  options (command line, from .petscrc file, etc.) for each of the solvers.
!  Input arguments are:
!     -f <input_file> : file to load.  For a 5X5 example of the 5-pt. stencil
!                       use the file petsc/src/mat/examples/mat.ex.binary

  PetscErrorCode ierr
  PetscInt its
  PetscBool flg
  PetscScalar, parameter :: none = -1.0, five = 5.0
  PetscReal norm
  Vec x, b, u
  Mat A
  KSP ksp1, ksp2
  character(len=PETSC_MAX_PATH_LEN) f
  PetscViewer fd
  IS isrow

  PetscCallA(PetscInitialize(ierr))

!     Read in matrix and RHS
  PetscCallA(PetscOptionsGetString(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-f', f, flg, ierr))
  PetscCallA(PetscViewerBinaryOpen(PETSC_COMM_WORLD, f, FILE_MODE_READ, fd, ierr))

  PetscCallA(MatCreate(PETSC_COMM_WORLD, A, ierr))
  PetscCallA(MatSetType(A, MATSEQAIJ, ierr))
  PetscCallA(MatLoad(A, fd, ierr))

  PetscCallA(VecCreate(PETSC_COMM_WORLD, b, ierr))
  PetscCallA(VecLoad(b, fd, ierr))
  PetscCallA(PetscViewerDestroy(fd, ierr))

! Set up solution
  PetscCallA(VecDuplicate(b, x, ierr))
  PetscCallA(VecDuplicate(b, u, ierr))

! Solve system-1
  PetscCallA(KSPCreate(PETSC_COMM_WORLD, ksp1, ierr))
  PetscCallA(KSPSetOptionsPrefix(ksp1, 'a', ierr))
  PetscCallA(KSPAppendOptionsPrefix(ksp1, '_', ierr))
  PetscCallA(KSPSetOperators(ksp1, A, A, ierr))
  PetscCallA(KSPSetFromOptions(ksp1, ierr))
  PetscCallA(KSPSolve(ksp1, b, x, ierr))

! Show result
  PetscCallA(MatMult(A, x, u, ierr))
  PetscCallA(VecAXPY(u, none, b, ierr))
  PetscCallA(VecNorm(u, NORM_2, norm, ierr))
  PetscCallA(KSPGetIterationNumber(ksp1, its, ierr))

  write (6, 100) norm, its
100 format('Residual norm ', e11.4, ' iterations ', i5)

! Create system 2 by striping off some rows of the matrix
  PetscCallA(ISCreateStride(PETSC_COMM_SELF, 5_PETSC_INT_KIND, 0_PETSC_INT_KIND, 1_PETSC_INT_KIND, isrow, ierr))
  PetscCallA(MatZeroRowsIS(A, isrow, five, PETSC_NULL_VEC, PETSC_NULL_VEC, ierr))

! Solve system-2
  PetscCallA(KSPCreate(PETSC_COMM_WORLD, ksp2, ierr))
  PetscCallA(KSPSetOptionsPrefix(ksp2, 'b', ierr))
  PetscCallA(KSPAppendOptionsPrefix(ksp2, '_', ierr))
  PetscCallA(KSPSetOperators(ksp2, A, A, ierr))
  PetscCallA(KSPSetFromOptions(ksp2, ierr))
  PetscCallA(KSPSolve(ksp2, b, x, ierr))

! Show result
  PetscCallA(MatMult(A, x, u, ierr))
  PetscCallA(VecAXPY(u, none, b, ierr))
  PetscCallA(VecNorm(u, NORM_2, norm, ierr))
  PetscCallA(KSPGetIterationNumber(ksp2, its, ierr))
  write (6, 100) norm, its

! Cleanup
  PetscCallA(KSPDestroy(ksp1, ierr))
  PetscCallA(KSPDestroy(ksp2, ierr))
  PetscCallA(VecDestroy(b, ierr))
  PetscCallA(VecDestroy(x, ierr))
  PetscCallA(VecDestroy(u, ierr))
  PetscCallA(MatDestroy(A, ierr))
  PetscCallA(ISDestroy(isrow, ierr))

  PetscCallA(PetscFinalize(ierr))
end

!/*TEST
!
!    test:
!      args: -f ${DATAFILESPATH}/matrices/arco1 -options_left no
!      requires: datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES)
!
!TEST*/
