Actual source code: ex18f90.F90

  1: !
  2: ! Example usage of Fortran 2003/2008 classes (extended derived types) as
  3: ! user-defined contexts in PETSc. Example contributed by Glenn Hammond.
  4: !
  5: module ex18f90base_module
  6: #include "petsc/finclude/petscsnes.h"
  7:       implicit none
  8:   private

 10:   type, public :: base_type
 11:     PetscInt :: A  ! junk
 12:     PetscReal :: I ! junk
 13:   contains
 14:     procedure, public :: Print => BasePrint
 15:   end type base_type
 16: contains
 17: subroutine BasePrint(this)
 18:   implicit none
 19:   class(base_type) :: this
 20:   print *
 21:   print *, 'Base printout'
 22:   print *
 23: end subroutine BasePrint
 24: end module ex18f90base_module

 26: module ex18f90extended_module
 27:   use ex18f90base_module
 28:   implicit none
 29:   private
 30:   type, public, extends(base_type) :: extended_type
 31:     PetscInt :: B  ! junk
 32:     PetscReal :: J ! junk
 33:   contains
 34:     procedure, public :: Print =>  ExtendedPrint
 35:   end type extended_type
 36: contains
 37: subroutine ExtendedPrint(this)
 38:   implicit none
 39:   class(extended_type) :: this
 40:   print *
 41:   print *, 'Extended printout'
 42:   print *
 43: end subroutine ExtendedPrint
 44: end module ex18f90extended_module

 46: module ex18f90function_module
 47:   use petscsnes
 48:   implicit none
 49:   public :: TestFunction
 50:   contains
 51: subroutine TestFunction(snes,xx,r,ctx,ierr)
 52:   use ex18f90base_module
 53:   implicit none
 54:   SNES :: snes
 55:   Vec :: xx
 56:   Vec :: r
 57:   class(base_type) :: ctx ! yes, this should be base_type in order to handle all
 58:   PetscErrorCode :: ierr  ! polymorphic extensions
 59:   call ctx%Print()
 60: end subroutine TestFunction
 61: end module ex18f90function_module

 63: program ex18f90

 65:   use ex18f90base_module
 66:   use ex18f90extended_module
 67:   use ex18f90function_module
 68:   implicit none

 70: !
 71: ! Since class(base_type) has a bound function (method), Print, one must
 72: ! provide an interface definition as below and use SNESSetFunctionNoInterface()
 73: ! instead of SNESSetFunction()
 74: !
 75:   interface
 76:   subroutine SNESSetFunctionNoInterface(snes_base,x,TestFunction,base,ierr)
 77:     use ex18f90base_module
 78:     use petscsnes
 79:     SNES snes_base
 80:     Vec x
 81:     external TestFunction
 82:     class(base_type) :: base
 83:     PetscErrorCode ierr
 84:   end subroutine
 85:   end interface

 87:   PetscMPIInt :: size
 88:   PetscMPIInt :: rank

 90:   SNES :: snes_base, snes_extended
 91:   Vec :: x
 92:   class(base_type), pointer :: base
 93:   class(extended_type), pointer :: extended
 94:   PetscErrorCode :: ierr

 96:   print *, 'Start of Fortran2003 test program'

 98:   nullify(base)
 99:   nullify(extended)
100:   allocate(base)
101:   allocate(extended)
102:   PetscCallA(PetscInitialize(ierr))
103:   PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
104:   PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))

106:   PetscCallA(VecCreate(PETSC_COMM_WORLD,x,ierr))

108:   ! use the base class as the context
109:   print *
110:   print *, 'the base class will succeed by printing out Base printout below'
111:   PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes_base,ierr))
112:   PetscCallA(SNESSetFunctionNoInterface(snes_base,x,TestFunction,base,ierr))
113:   PetscCallA(SNESComputeFunction(snes_base,x,x,ierr))
114:   PetscCallA(SNESDestroy(snes_base,ierr))

116:   ! use the extended class as the context
117:   print *, 'the extended class will succeed by printing out Extended printout below'
118:   PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes_extended,ierr))
119:   PetscCallA(SNESSetFunctionNoInterface(snes_extended,x,TestFunction,extended,ierr))
120:   PetscCallA(SNESComputeFunction(snes_extended,x,x,ierr))
121:   PetscCallA(VecDestroy(x,ierr))
122:   PetscCallA(SNESDestroy(snes_extended,ierr))
123:   if (associated(base)) deallocate(base)
124:   if (associated(extended)) deallocate(extended)
125:   PetscCallA(PetscFinalize(ierr))

127:   print *, 'End of Fortran2003 test program'
128: end program ex18f90

130: !/*TEST
131: !
132: !   build:
133: !      requires: defined(PETSC_USING_F2003) defined(PETSC_USING_F90FREEFORM)
134: !   test:
135: !     requires: !pgf90_compiler
136: !
137: !TEST*/