Actual source code: ex20f.F90

  1: !
  2: !     Demonstrates use of MatDuplicate() for a shell matrix with a context
  3: !
  4: #include "petsc/finclude/petscmat.h"
  5: module ex20fmodule
  6:   use petscmat
  7:   implicit none
  8:   type :: MatCtx
  9:     PetscReal :: lambda
 10:   end type MatCtx

 12:   interface
 13:     subroutine MatCreateShell(comm, mloc, nloc, m, n, ctx, mat, ierr)
 14:       use petscmat
 15:       import MatCtx
 16:       implicit none
 17:       MPI_Comm :: comm
 18:       PetscInt :: mloc, nloc, m, n
 19:       type(MatCtx) :: ctx
 20:       Mat :: mat
 21:       PetscErrorCode :: ierr
 22:     end subroutine MatCreateShell

 24:     subroutine MatShellSetContext(mat, ctx, ierr)
 25:       use petscmat
 26:       import MatCtx
 27:       implicit none
 28:       Mat :: mat
 29:       type(MatCtx) :: ctx
 30:       PetscErrorCode :: ierr
 31:     end subroutine MatShellSetContext

 33:     subroutine MatShellGetContext(mat, ctx, ierr)
 34:       use petscmat
 35:       import MatCtx
 36:       implicit none
 37:       Mat :: mat
 38:       type(MatCtx), pointer :: ctx
 39:       PetscErrorCode :: ierr
 40:     end subroutine MatShellGetContext
 41:   end interface

 43: contains
 44:   subroutine MatDuplicate_F(F, opt, M, ierr)

 46:     Mat                  :: F, M
 47:     MatDuplicateOption   :: opt
 48:     PetscErrorCode       :: ierr
 49:     PetscInt             :: ml, nl
 50:     type(MatCtx), pointer :: ctxM, ctxF_pt

 52:     PetscCall(MatGetLocalSize(F, ml, nl, ierr))
 53:     PetscCall(MatShellGetContext(F, ctxF_pt, ierr))
 54:     allocate (ctxM)
 55:     ctxM%lambda = ctxF_pt%lambda
 56:     PetscCall(MatCreateShell(PETSC_COMM_WORLD, ml, nl, PETSC_DETERMINE, PETSC_DETERMINE, ctxM, M, ierr))
 57: !        PetscCall(MatShellSetOperation(M,MATOP_DUPLICATE,MatDuplicate_F,ierr))
 58:     PetscCall(MatShellSetOperation(M, MATOP_DESTROY, MatDestroy_F, ierr))
 59:   end subroutine MatDuplicate_F

 61:   subroutine MatDestroy_F(F, ierr)

 63:     Mat                  :: F
 64:     PetscErrorCode       :: ierr
 65:     type(MatCtx), pointer :: ctxF_pt
 66:     PetscCall(MatShellGetContext(F, ctxF_pt, ierr))
 67:     deallocate (ctxF_pt)
 68:   end subroutine MatDestroy_F

 70: end module ex20fmodule

 72: ! ----------------------------------------------------
 73: !                    main program
 74: ! ----------------------------------------------------
 75: program main
 76:   use ex20fmodule
 77:   implicit none
 78:   Mat                  :: F, Fcopy
 79:   type(MatCtx)         :: ctxF
 80:   type(MatCtx), pointer :: ctxF_pt, ctxFcopy_pt
 81:   PetscErrorCode       :: ierr
 82:   PetscInt             :: n = 128

 84:   PetscCallA(PetscInitialize(ierr))
 85:   ctxF%lambda = 3.14d0
 86:   PetscCallA(MatCreateShell(PETSC_COMM_WORLD, PETSC_DECIDE, PETSC_DECIDE, n, n, ctxF, F, ierr))
 87:   PetscCallA(MatShellSetOperation(F, MATOP_DUPLICATE, MatDuplicate_F, ierr))
 88:   print *, 'ctxF%lambda = ', ctxF%lambda

 90:   PetscCallA(MatShellGetContext(F, ctxF_pt, ierr))
 91:   print *, 'ctxF_pt%lambda = ', ctxF_pt%lambda

 93:   PetscCallA(MatDuplicate(F, MAT_DO_NOT_COPY_VALUES, Fcopy, ierr))
 94:   PetscCallA(MatShellGetContext(Fcopy, ctxFcopy_pt, ierr))
 95:   print *, 'ctxFcopy_pt%lambda = ', ctxFcopy_pt%lambda

 97:   PetscCallA(MatDestroy(F, ierr))
 98:   PetscCallA(MatDestroy(Fcopy, ierr))
 99:   PetscCallA(PetscFinalize(ierr))
100: end program main

102: !/*TEST
103: !
104: !     build:
105: !       requires: double
106: !
107: !     test:
108: !
109: !TEST*/