!
!
!   This program demonstrates use of PETSc dense matrices.
!
      program main
#include <petsc/finclude/petscsys.h>
      use petscsys
      implicit none

      PetscErrorCode ierr

      PetscCallA(PetscInitialize(ierr))

!  Demo of PETSc-allocated dense matrix storage
      call Demo1()

!  Demo of user-allocated dense matrix storage
      call Demo2()

      PetscCallA(PetscFinalize(ierr))
      end

! -----------------------------------------------------------------
!
!  Demo1 -  This subroutine demonstrates the use of PETSc-allocated dense
!  matrix storage.  Here MatDenseGetArray() is used for direct access to the
!  array that stores the dense matrix.
!
!  Note the use of PETSC_NULL_SCALAR_ARRAY in MatCreateSeqDense() to indicate that no
!  storage is being provided by the user. (Do NOT pass a zero in that
!  location.)
!
      subroutine Demo1()
#include <petsc/finclude/petscmat.h>
      use petscmat
      implicit none

      Mat         A
      PetscInt   n,m
      PetscErrorCode ierr
      PetscScalar,pointer :: aa(:,:)

      n = 4
      m = 5

!  Create matrix

      PetscCall(MatCreate(PETSC_COMM_SELF,A,ierr))
      PetscCall(MatSetSizes(A,m,n,m,n,ierr))
      PetscCall(MatSetType(A,MATSEQDENSE,ierr))
      PetscCall(MatSetUp(A,ierr))

!  Access array storage
      PetscCall(MatDenseGetArray(A,aa,ierr))

!  Set matrix values directly
      PetscCall(FillUpMatrix(m,n,aa))

      PetscCall(MatDenseRestoreArray(A,aa,ierr))

!  Finalize matrix assembly
      PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY,ierr))
      PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY,ierr))

!  View matrix
      PetscCall(MatView(A,PETSC_VIEWER_STDOUT_SELF,ierr))

!  Clean up
      PetscCall(MatDestroy(A,ierr))
      end

! -----------------------------------------------------------------
!
!  Demo2 -  This subroutine demonstrates the use of user-allocated dense
!  matrix storage.
!
      subroutine Demo2()
#include <petsc/finclude/petscmat.h>
      use petscmat
      implicit none

      PetscInt   n,m
      PetscErrorCode ierr
      parameter (m=5,n=4)
      Mat       A
      PetscScalar    aa(m,n)

!  Create matrix
      PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,m,n,aa,A,ierr))

!  Set matrix values directly
      PetscCall(FillUpMatrix(m,n,aa))

!  Finalize matrix assembly
      PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY,ierr))
      PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY,ierr))

!  View matrix
      PetscCall(MatView(A,PETSC_VIEWER_STDOUT_SELF,ierr))

!  Clean up
      PetscCall(MatDestroy(A,ierr))
      end

! -----------------------------------------------------------------

      subroutine FillUpMatrix(m,n,X)
      PetscInt          m,n,i,j
      PetscScalar      X(m,n)

      do 10, j=1,n
        do 20, i=1,m
          X(i,j) = 1.0/real(i+j-1)
 20     continue
 10   continue
      end
