!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include <petsc/finclude/petscsys.h>
      subroutine F90Array1dCreateScalar(array, start, len1, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start, len1
        PetscScalar, target ::                                                      &
       &     array(start:start + len1 - 1)
        PetscScalar, pointer :: ptr(:)

        ptr => array
      end subroutine

      subroutine F90Array1dCreateReal(array, start, len1, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start, len1
        PetscReal, target ::                                                        &
       &     array(start:start + len1 - 1)
        PetscReal, pointer :: ptr(:)

        ptr => array
      end subroutine

      subroutine F90Array1dCreateInt(array, start, len1, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start, len1
        PetscInt, target ::                                                         &
       &     array(start:start + len1 - 1)
        PetscInt, pointer :: ptr(:)

        ptr => array
      end subroutine

      subroutine F90Array1dCreateMPIInt(array, start, len1, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start, len1
        PetscMPIInt, target ::                                                      &
        &     array(start:start + len1 - 1)
        PetscMPIInt, pointer :: ptr(:)

        ptr => array
      end subroutine

      subroutine F90Array1dCreateFortranAddr(array, start, len1, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start, len1
        PetscFortranAddr, target ::                                                 &
       &     array(start:start + len1 - 1)
        PetscFortranAddr, pointer :: ptr(:)

        ptr => array
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array1dAccessScalar(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:)
        PetscFortranAddr address
        PetscInt start

        if (associated(ptr) .eqv. .false.) then
          address = 0
        else
          start = lbound(ptr, 1)
          call F90Array1dGetAddrScalar(ptr(start), address)
        end if
      end subroutine

      subroutine F90Array1dAccessReal(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:)
        PetscFortranAddr address
        PetscInt start

        if (associated(ptr) .eqv. .false.) then
          address = 0
        else
          start = lbound(ptr, 1)
          call F90Array1dGetAddrReal(ptr(start), address)
        end if
      end subroutine

      subroutine F90Array1dAccessInt(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:)
        PetscFortranAddr address
        PetscInt start

        if (associated(ptr) .eqv. .false.) then
          address = 0
        else
          start = lbound(ptr, 1)
          call F90Array1dGetAddrInt(ptr(start), address)
        end if
      end subroutine

      subroutine F90Array1dAccessMPIInt(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscMPIInt, pointer :: ptr(:)
        PetscFortranAddr address
        PetscInt start

        if (associated(ptr) .eqv. .false.) then
          address = 0
        else
          start = lbound(ptr, 1)
          call F90Array1dGetAddrMPIInt(ptr(start), address)
        end if
      end subroutine

      subroutine F90Array1dAccessFortranAddr(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:)
        PetscFortranAddr address
        PetscInt start

        if (associated(ptr) .eqv. .false.) then
          address = 0
        else
          start = lbound(ptr, 1)
          call F90Array1dGetAddrFortranAddr(ptr(start), address)
        end if
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array1dDestroyScalar(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:)

        nullify (ptr)
      end subroutine

      subroutine F90Array1dDestroyReal(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:)

        nullify (ptr)
      end subroutine

      subroutine F90Array1dDestroyInt(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:)

        nullify (ptr)
      end subroutine

      subroutine F90Array1dDestroyMPIInt(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscMPIInt, pointer :: ptr(:)

        nullify (ptr)
      end subroutine

      subroutine F90Array1dDestroyFortranAddr(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:)

        nullify (ptr)
      end subroutine
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array2dCreateScalar(array, start1, len1,                        &
     &     start2, len2, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscScalar, target ::                                                      &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1)
        PetscScalar, pointer :: ptr(:, :)

        ptr => array
      end subroutine

      subroutine F90Array2dCreateReal(array, start1, len1,                          &
     &     start2, len2, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscReal, target ::                                                        &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1)
        PetscReal, pointer :: ptr(:, :)

        ptr => array
      end subroutine

      subroutine F90Array2dCreateInt(array, start1, len1,                           &
     &     start2, len2, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt, target ::                                                         &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1)
        PetscInt, pointer :: ptr(:, :)

        ptr => array
      end subroutine

      subroutine F90Array2dCreateFortranAddr(array, start1, len1,                   &
     &     start2, len2, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscFortranAddr, target ::                                                 &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1)
        PetscFortranAddr, pointer :: ptr(:, :)

        ptr => array
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array2dAccessScalar(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :)
        PetscFortranAddr address
        PetscInt start1, start2

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        call F90Array2dGetAddrScalar(ptr(start1, start2), address)
      end subroutine

      subroutine F90Array2dAccessReal(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:, :)
        PetscFortranAddr address
        PetscInt start1, start2

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        call F90Array2dGetAddrReal(ptr(start1, start2), address)
      end subroutine

      subroutine F90Array2dAccessInt(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:, :)
        PetscFortranAddr address
        PetscInt start1, start2

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        call F90Array2dGetAddrInt(ptr(start1, start2), address)
      end subroutine

      subroutine F90Array2dAccessFortranAddr(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:, :)
        PetscFortranAddr address
        PetscInt start1, start2

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        call F90Array2dGetAddrFortranAddr(ptr(start1, start2), address)
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array2dDestroyScalar(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array2dDestroyReal(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array2dDestroyInt(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array2dDestroyFortranAddr(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:, :)

        nullify (ptr)
      end subroutine
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array3dCreateScalar(array, start1, len1,                        &
     &     start2, len2, start3, len3, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscScalar, target ::                                                      &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1)
        PetscScalar, pointer :: ptr(:, :, :)

        ptr => array
      end subroutine

      subroutine F90Array3dCreateReal(array, start1, len1,                          &
     &     start2, len2, start3, len3, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscReal, target ::                                                        &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1)
        PetscReal, pointer :: ptr(:, :, :)

        ptr => array
      end subroutine

      subroutine F90Array3dCreateInt(array, start1, len1,                           &
     &     start2, len2, start3, len3, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscInt, target ::                                                         &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1)
        PetscInt, pointer :: ptr(:, :, :)

        ptr => array
      end subroutine

      subroutine F90Array3dCreateFortranAddr(array, start1, len1,                   &
     &     start2, len2, start3, len3, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscFortranAddr, target ::                                                 &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1)
        PetscFortranAddr, pointer :: ptr(:, :, :)

        ptr => array
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array3dAccessScalar(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        call F90Array3dGetAddrScalar(ptr(start1, start2, start3), address)
      end subroutine

      subroutine F90Array3dAccessReal(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        call F90Array3dGetAddrReal(ptr(start1, start2, start3), address)
      end subroutine

      subroutine F90Array3dAccessInt(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        call F90Array3dGetAddrInt(ptr(start1, start2, start3), address)
      end subroutine

      subroutine F90Array3dAccessFortranAddr(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        call F90Array3dGetAddrFortranAddr(ptr(start1, start2, start3),        &
       &                                  address)
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array3dDestroyScalar(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array3dDestroyReal(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:, :, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array3dDestroyInt(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:, :, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array3dDestroyFortranAddr(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:, :, :)

        nullify (ptr)
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      subroutine F90Array4dCreateScalar(array, start1, len1,                        &
     &     start2, len2, start3, len3, start4, len4, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscInt start4, len4
        PetscScalar, target ::                                                      &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1, start4:start4 + len4 - 1)
        PetscScalar, pointer :: ptr(:, :, :, :)

        ptr => array
      end subroutine

      subroutine F90Array4dCreateReal(array, start1, len1,                          &
     &     start2, len2, start3, len3, start4, len4, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscInt start4, len4
        PetscReal, target ::                                                        &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1, start4:start4 + len4 - 1)
        PetscReal, pointer :: ptr(:, :, :, :)

        ptr => array
      end subroutine

      subroutine F90Array4dCreateInt(array, start1, len1,                           &
     &     start2, len2, start3, len3, start4, len4, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscInt start4, len4
        PetscInt, target ::                                                         &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1, start4:start4 + len4 - 1)
        PetscInt, pointer :: ptr(:, :, :, :)

        ptr => array
      end subroutine

      subroutine F90Array4dCreateFortranAddr(array, start1, len1,                   &
     &     start2, len2, start3, len3, start4, len4, ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt start1, len1
        PetscInt start2, len2
        PetscInt start3, len3
        PetscInt start4, len4
        PetscFortranAddr, target ::                                                 &
       &     array(start1:start1 + len1 - 1, start2:start2 + len2 - 1,                       &
       &           start3:start3 + len3 - 1, start4:start4 + len4 - 1)
        PetscFortranAddr, pointer :: ptr(:, :, :, :)

        ptr => array
      end subroutine

      subroutine F90Array4dAccessScalar(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3, start4

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        start4 = lbound(ptr, 4)
        call F90Array4dGetAddrScalar(ptr(start1, start2, start3, start4),              &
       &                             address)
      end subroutine

      subroutine F90Array4dAccessReal(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:, :, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3, start4

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        start4 = lbound(ptr, 4)
        call F90Array4dGetAddrReal(ptr(start1, start2, start3, start4),                &
       &                             address)
      end subroutine

      subroutine F90Array4dAccessInt(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:, :, :, :)
        PetscFortranAddr address
        PetscInt start1, start2, start3, start4

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        start4 = lbound(ptr, 4)
        call F90Array4dGetAddrInt(ptr(start1, start2, start3, start4),                 &
       &                             address)
      end subroutine

      subroutine F90Array4dAccessFortranAddr(ptr, address)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :, :, :)
        PetscFortranAddr address
        PetscFortranAddr start1, start2, start3, start4

        start1 = lbound(ptr, 1)
        start2 = lbound(ptr, 2)
        start3 = lbound(ptr, 3)
        start4 = lbound(ptr, 4)
        call F90Array4dGetAddrFortranAddr(ptr(start1, start2, start3,                 &
       &                                      start4), address)
      end subroutine

      subroutine F90Array4dDestroyScalar(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscScalar, pointer :: ptr(:, :, :, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array4dDestroyReal(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscReal, pointer :: ptr(:, :, :, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array4dDestroyInt(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscInt, pointer :: ptr(:, :, :, :)

        nullify (ptr)
      end subroutine

      subroutine F90Array4dDestroyFortranAddr(ptr)
        use, intrinsic :: ISO_C_binding
        implicit none
        PetscFortranAddr, pointer :: ptr(:, :, :, :)

        nullify (ptr)
      end subroutine

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
