Actual source code: ex21f90.F90

  1: !
  2: !
  3: !    Demonstrates how one may access entries of a PETSc Vec as if it was an array of Fortran derived types
  4: !
  5: !
  6: ! -----------------------------------------------------------------------
  7: #include <petsc/finclude/petscvec.h>
  8: module ex21module
  9:   use petscsys
 10:   implicit none
 11:   type MyStruct
 12:     sequence
 13:     PetscScalar :: a, b, c
 14:   end type MyStruct
 15: !
 16: !
 17: !   These two routines are defined in ex21.c they create the Fortran pointer to the derived type
 18: !
 19:   interface
 20:     subroutine VecGetArrayMyStruct(v, array, ierr)
 21:       use petscvec
 22:       import MyStruct
 23:       type(MyStruct), pointer :: array(:)
 24:       PetscErrorCode ierr
 25:       Vec v
 26:     end subroutine

 28:     subroutine VecRestoreArrayMyStruct(v, array, ierr)
 29:       use petscvec
 30:       import MyStruct
 31:       type(MyStruct), pointer :: array(:)
 32:       PetscErrorCode ierr
 33:       Vec v
 34:     end subroutine
 35:   end interface
 36: end module

 38: !  These routines are used internally by the C functions VecGetArrayMyStruct() and VecRestoreArrayMyStruct()
 39: !  Because Fortran requires "knowing" exactly what derived types the pointers to point too, these have to be
 40: !  customized for exactly the derived type in question
 41: !
 42: subroutine F90Array1dCreateMyStruct(array, start, len, ptr)
 43:   use petscsys
 44:   use ex21module
 45:   implicit none
 46:   PetscInt start, len
 47:   type(MyStruct), target :: array(start:start + len - 1)
 48:   type(MyStruct), pointer :: ptr(:)

 50:   ptr => array
 51: end subroutine

 53: subroutine F90Array1dAccessMyStruct(ptr, address)
 54:   use petscsys
 55:   use ex21module
 56:   implicit none
 57:   type(MyStruct), pointer :: ptr(:)
 58:   PetscFortranAddr address
 59:   PetscInt start

 61:   start = lbound(ptr, 1)
 62:   call F90Array1dGetAddrMyStruct(ptr(start), address)
 63: end subroutine

 65: subroutine F90Array1dDestroyMyStruct(ptr)
 66:   use ex21module
 67:   implicit none
 68:   type(MyStruct), pointer :: ptr(:)

 70:   nullify (ptr)
 71: end subroutine

 73: program main
 74:   use petscvec
 75:   use ex21module
 76:   implicit none

 78: !
 79: ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 80: !                   Variable declarations
 81: ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 82: !
 83: !  Variables:
 84: !     x, y, w - vectors
 85: !     z       - array of vectors
 86: !
 87:   Vec x, y
 88:   type(MyStruct), pointer :: xarray(:)
 89:   PetscInt n
 90:   PetscErrorCode ierr
 91:   PetscBool flg
 92:   integer i

 94: ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 95: !                 Beginning of program
 96: ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 98:   PetscCallA(PetscInitialize(ierr))

100:   n = 30
101:   PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-n', n, flg, ierr))
102:   PetscCallA(VecCreate(PETSC_COMM_WORLD, x, ierr))
103:   PetscCallA(VecSetSizes(x, PETSC_DECIDE, n, ierr))
104:   PetscCallA(VecSetFromOptions(x, ierr))
105:   PetscCallA(VecDuplicate(x, y, ierr))

107:   PetscCallA(VecGetArrayMyStruct(x, xarray, ierr))
108:   do i = 1, 10
109:     xarray(i)%a = i
110:     xarray(i)%b = 100*i
111:     xarray(i)%c = 10000*i
112:   end do

114:   PetscCallA(VecRestoreArrayMyStruct(x, xarray, ierr))
115:   PetscCallA(VecView(x, PETSC_VIEWER_STDOUT_SELF, ierr))
116:   PetscCallA(VecGetArrayMyStruct(x, xarray, ierr))
117:   do i = 1, 10
118:     write (*, *) abs(xarray(i)%a), abs(xarray(i)%b), abs(xarray(i)%c)
119:   end do
120:   PetscCallA(VecRestoreArrayMyStruct(x, xarray, ierr))

122:   PetscCallA(VecDestroy(x, ierr))
123:   PetscCallA(VecDestroy(y, ierr))
124:   PetscCallA(PetscFinalize(ierr))

126: end

128: !/*TEST
129: !
130: !   build:
131: !     depends: ex21.c
132: !
133: !   test:
134: !
135: !TEST*/