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

!
!  This example is the Fortran version of ex6.c.  The program reads a PETSc matrix
!  and vector from a file and solves a linear system.  Input arguments are:
!        -f <input_file> : file to load.  For example see $PETSC_DIR/share/petsc/datafiles/matrices
!

  PetscErrorCode ierr
  PetscInt its, m, n, mlocal, nlocal
  PetscBool flg
  PetscScalar, parameter :: none = -1.0
  PetscReal norm
  Vec x, b, u
  Mat A
  character(len=128) f
  PetscViewer fd
  MatInfo info
  KSP ksp

  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))

! Get information about matrix
  PetscCallA(MatGetSize(A, m, n, ierr))
  PetscCallA(MatGetLocalSize(A, mlocal, nlocal, ierr))
  PetscCallA(MatGetInfo(A, MAT_GLOBAL_SUM, info, ierr))
  write (*, 100) m, &
    n, &
    mlocal, nlocal, &
    info%BLOCK_SIZE, info%NZ_ALLOCATED, &
    info%NZ_USED, info%NZ_UNNEEDED, &
    info%MEMORY, info%ASSEMBLIES, &
    info%MALLOCS

100 format(4(i4, 1x), 7(1pe9.2, 1x))
  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
  PetscCallA(KSPCreate(PETSC_COMM_WORLD, ksp, ierr))
  PetscCallA(KSPSetOperators(ksp, A, A, ierr))
  PetscCallA(KSPSetFromOptions(ksp, ierr))
  PetscCallA(KSPSolve(ksp, 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(ksp, its, ierr))
  write (6, 101) norm, its
101 format('Residual norm ', 1pe9.2, ' iterations ', i5)

! Cleanup
  PetscCallA(KSPDestroy(ksp, ierr))
  PetscCallA(VecDestroy(b, ierr))
  PetscCallA(VecDestroy(x, ierr))
  PetscCallA(VecDestroy(u, ierr))
  PetscCallA(MatDestroy(A, 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*/
