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/petscsys.h>
7: #include "petsc/finclude/petscsnes.h"
8: use PetscSys
9: use PetscSnes
10: implicit none
11: private
13: type, public :: base_type
14: PetscInt :: A ! junk
15: PetscReal :: I ! junk
16: contains
17: procedure, public :: Print => BasePrint
18: end type base_type
19: contains
20: subroutine BasePrint(this)
21: implicit none
22: class(base_type) :: this
23: print *
24: print *, 'Base printout'
25: print *
26: end subroutine BasePrint
27: end module ex18f90base_module
29: module ex18f90extended_module
30: use ex18f90base_module
31: #include <petsc/finclude/petscsys.h>
32: use PetscSys
33: implicit none
34: private
35: type, public, extends(base_type) :: extended_type
36: PetscInt :: B ! junk
37: PetscReal :: J ! junk
38: contains
39: procedure, public :: Print => ExtendedPrint
40: end type extended_type
41: contains
42: subroutine ExtendedPrint(this)
43: implicit none
44: class(extended_type) :: this
45: print *
46: print *, 'Extended printout'
47: print *
48: end subroutine ExtendedPrint
49: end module ex18f90extended_module
51: module ex18f90function_module
52: use petscsnes
53: implicit none
54: public :: TestFunction
55: contains
56: subroutine TestFunction(snes,xx,r,ctx,ierr)
57: use ex18f90base_module
58: implicit none
59: SNES :: snes
60: Vec :: xx
61: Vec :: r
62: class(base_type) :: ctx ! yes, this should be base_type in order to handle all
63: PetscErrorCode :: ierr ! polymorphic extensions
64: call ctx%Print()
65: end subroutine TestFunction
66: end module ex18f90function_module
68: program ex18f90
70: use ex18f90base_module
71: use ex18f90extended_module
72: use ex18f90function_module
73: implicit none
75: !
76: ! Since class(base_type) has a bound function (method), Print, one must
77: ! provide an interface definition as below and use SNESSetFunctionNoInterface()
78: ! instead of SNESSetFunction()
79: !
80: interface
81: subroutine SNESSetFunctionNoInterface(snes_base,x,TestFunction,base,ierr)
82: use ex18f90base_module
83: use petscsnes
84: SNES snes_base
85: Vec x
86: external TestFunction
87: class(base_type) :: base
88: PetscErrorCode ierr
89: end subroutine
90: end interface
92: PetscMPIInt :: size
93: PetscMPIInt :: rank
95: SNES :: snes_base, snes_extended
96: Vec :: x
97: class(base_type), pointer :: base
98: class(extended_type), pointer :: extended
99: PetscErrorCode :: ierr
101: print *, 'Start of Fortran2003 test program'
103: nullify(base)
104: nullify(extended)
105: allocate(base)
106: allocate(extended)
107: PetscCallA(PetscInitialize(ierr))
108: PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
109: PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))
111: PetscCallA(VecCreate(PETSC_COMM_WORLD,x,ierr))
113: ! use the base class as the context
114: print *
115: print *, 'the base class will succeed by printing out Base printout below'
116: PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes_base,ierr))
117: PetscCallA(SNESSetFunctionNoInterface(snes_base,x,TestFunction,base,ierr))
118: PetscCallA(SNESComputeFunction(snes_base,x,x,ierr))
119: PetscCallA(SNESDestroy(snes_base,ierr))
121: ! use the extended class as the context
122: print *, 'the extended class will succeed by printing out Extended printout below'
123: PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes_extended,ierr))
124: PetscCallA(SNESSetFunctionNoInterface(snes_extended,x,TestFunction,extended,ierr))
125: PetscCallA(SNESComputeFunction(snes_extended,x,x,ierr))
126: PetscCallA(VecDestroy(x,ierr))
127: PetscCallA(SNESDestroy(snes_extended,ierr))
128: if (associated(base)) deallocate(base)
129: if (associated(extended)) deallocate(extended)
130: PetscCallA(PetscFinalize(ierr))
132: print *, 'End of Fortran2003 test program'
133: end program ex18f90
135: !/*TEST
136: !
137: ! build:
138: ! requires: defined(PETSC_USING_F2003) defined(PETSC_USING_F90FREEFORM)
139: ! test:
140: ! requires: !pgf90_compiler
141: !
142: !TEST*/