xref: /petsc/src/snes/tests/ex18f90.F90 (revision 76be6f4ff3bd4e251c19fc00ebbebfd58b6e7589)
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!
5module Base_module
6#include "petsc/finclude/petscsnes.h"
7      implicit none
8  private
9
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
16contains
17subroutine BasePrint(this)
18  implicit none
19  class(base_type) :: this
20  print *
21  print *, 'Base printout'
22  print *
23end subroutine BasePrint
24end module Base_module
25
26module Extended_module
27  use Base_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
36contains
37subroutine ExtendedPrint(this)
38  implicit none
39  class(extended_type) :: this
40  print *
41  print *, 'Extended printout'
42  print *
43end subroutine ExtendedPrint
44end module Extended_module
45
46module Function_module
47  use petscsnes
48  implicit none
49  public :: TestFunction
50  contains
51subroutine TestFunction(snes,xx,r,ctx,ierr)
52  use Base_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()
60end subroutine TestFunction
61end module Function_module
62
63program ex18f90
64
65  use Base_module
66  use Extended_module
67  use Function_module
68  implicit none
69
70! ifort on windows requires this interface definition
71interface
72  subroutine SNESSetFunction(snes_base,x,TestFunction,base,ierr)
73    use Base_module
74    use petscsnes
75    SNES snes_base
76    Vec x
77    external TestFunction
78    class(base_type) :: base
79    PetscErrorCode ierr
80  end subroutine
81end interface
82
83  PetscMPIInt :: size
84  PetscMPIInt :: rank
85
86  SNES :: snes_base, snes_extended
87  Vec :: x
88  class(base_type), pointer :: base
89  class(extended_type), pointer :: extended
90  PetscErrorCode :: ierr
91
92  print *, 'Start of Fortran2003 test program'
93
94  nullify(base)
95  nullify(extended)
96  allocate(base)
97  allocate(extended)
98  PetscCallA(PetscInitialize(ierr))
99  PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
100  PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))
101
102  PetscCallA(VecCreate(PETSC_COMM_WORLD,x,ierr))
103
104  ! use the base class as the context
105  print *
106  print *, 'the base class will succeed by printing out Base printout below'
107  PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes_base,ierr))
108  PetscCallA(SNESSetFunction(snes_base,x,TestFunction,base,ierr))
109  PetscCallA(SNESComputeFunction(snes_base,x,x,ierr))
110  PetscCallA(SNESDestroy(snes_base,ierr))
111
112  ! use the extended class as the context
113  print *, 'the extended class will succeed by printing out Extended printout below'
114  PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes_extended,ierr))
115  PetscCallA(SNESSetFunction(snes_extended,x,TestFunction,extended,ierr))
116  PetscCallA(SNESComputeFunction(snes_extended,x,x,ierr))
117  PetscCallA(VecDestroy(x,ierr))
118  PetscCallA(SNESDestroy(snes_extended,ierr))
119  if (associated(base)) deallocate(base)
120  if (associated(extended)) deallocate(extended)
121  PetscCallA(PetscFinalize(ierr))
122
123  print *, 'End of Fortran2003 test program'
124end program ex18f90
125
126!/*TEST
127!
128!   build:
129!      requires: defined(PETSC_USING_F2003) defined(PETSC_USING_F90FREEFORM)
130!   test:
131!     requires: !pgf90_compiler
132!
133!TEST*/
134