#if defined(_OPENACC) || defined(_OPENMP)
!=====================================================================
! Transfer wrappers for copy or update if present
!=====================================================================
module gpu_utils
  implicit none

  private
  public :: copy_or_update, copy_or_update_pointer, copy_or_update_alloc

  ! Adjust this as needed

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Generic interface for arrays and scalars (non-pointer, non-allocatable)
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  interface copy_or_update
     module procedure copy_or_update_double_nonpointer_r1
     module procedure copy_or_update_double_nonpointer_r2
     module procedure copy_or_update_double_nonpointer_r3
     module procedure copy_or_update_double_nonpointer_r4
     module procedure copy_or_update_double_nonpointer_r5
     module procedure copy_or_update_double_nonpointer_r6
     module procedure copy_or_update_logical_nonpointer_r1
     module procedure copy_or_update_logical_nonpointer_r2
     module procedure copy_or_update_logical_nonpointer_r3
     module procedure copy_or_update_logical_nonpointer_r4
     module procedure copy_or_update_logical_nonpointer_r5
     module procedure copy_or_update_logical_nonpointer_r6
     module procedure copy_or_update_integer_nonpointer_r1
     module procedure copy_or_update_integer_nonpointer_r2
     module procedure copy_or_update_integer_nonpointer_r3
     module procedure copy_or_update_integer_nonpointer_r4
     module procedure copy_or_update_integer_nonpointer_r5
     module procedure copy_or_update_integer_nonpointer_r6

    module procedure copy_or_update_double_nonpointer
    module procedure copy_or_update_logical_nonpointer
    module procedure copy_or_update_integer_nonpointer
  end interface copy_or_update
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Generic interface for data with pointer attribute
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  interface copy_or_update_pointer
     module procedure copy_or_update_double_pointer_r1
     module procedure copy_or_update_double_pointer_r2
     module procedure copy_or_update_double_pointer_r3
     module procedure copy_or_update_double_pointer_r4
     module procedure copy_or_update_double_pointer_r5
     module procedure copy_or_update_double_pointer_r6
     module procedure copy_or_update_logical_pointer_r1
     module procedure copy_or_update_logical_pointer_r2
     module procedure copy_or_update_logical_pointer_r3
     module procedure copy_or_update_logical_pointer_r4
     module procedure copy_or_update_logical_pointer_r5
     module procedure copy_or_update_logical_pointer_r6
     module procedure copy_or_update_integer_pointer_r1
     module procedure copy_or_update_integer_pointer_r2
     module procedure copy_or_update_integer_pointer_r3
     module procedure copy_or_update_integer_pointer_r4
     module procedure copy_or_update_integer_pointer_r5
     module procedure copy_or_update_integer_pointer_r6

    module procedure copy_or_update_double_pointer
    module procedure copy_or_update_logical_pointer
    module procedure copy_or_update_integer_pointer
  end interface copy_or_update_pointer
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! Generic interface for arrays with allocatable attribute
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  interface copy_or_update_alloc
     module procedure copy_or_update_double_alloc_r1
     module procedure copy_or_update_double_alloc_r2
     module procedure copy_or_update_double_alloc_r3
     module procedure copy_or_update_double_alloc_r4
     module procedure copy_or_update_double_alloc_r5
     module procedure copy_or_update_double_alloc_r6
     module procedure copy_or_update_logical_alloc_r1
     module procedure copy_or_update_logical_alloc_r2
     module procedure copy_or_update_logical_alloc_r3
     module procedure copy_or_update_logical_alloc_r4
     module procedure copy_or_update_logical_alloc_r5
     module procedure copy_or_update_logical_alloc_r6
     module procedure copy_or_update_integer_alloc_r1
     module procedure copy_or_update_integer_alloc_r2
     module procedure copy_or_update_integer_alloc_r3
     module procedure copy_or_update_integer_alloc_r4
     module procedure copy_or_update_integer_alloc_r5
     module procedure copy_or_update_integer_alloc_r6
  end interface copy_or_update_alloc

contains

  ! Versions for scalars, pointers

  subroutine copy_or_update_double_pointer(scalar, no_update)
    implicit none
    double precision, pointer, intent(inout) :: scalar
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(scalar)) then
       print *, 'copy_or_update: null-pointer encountered'
       return
    end if


  end subroutine copy_or_update_double_pointer

  ! Versions for scalars, non-pointers
  subroutine copy_or_update_double_nonpointer(scalar, no_update)
    implicit none
    double precision, intent(inout) :: scalar
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer


  subroutine copy_or_update_logical_pointer(scalar, no_update)
    implicit none
    logical, pointer, intent(inout) :: scalar
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(scalar)) then
       print *, 'copy_or_update: null-pointer encountered'
       return
    end if


  end subroutine copy_or_update_logical_pointer

  ! Versions for scalars, non-pointers
  subroutine copy_or_update_logical_nonpointer(scalar, no_update)
    implicit none
    logical, intent(inout) :: scalar
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer


  subroutine copy_or_update_integer_pointer(scalar, no_update)
    implicit none
    integer, pointer, intent(inout) :: scalar
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(scalar)) then
       print *, 'copy_or_update: null-pointer encountered'
       return
    end if


  end subroutine copy_or_update_integer_pointer

  ! Versions for scalars, non-pointers
  subroutine copy_or_update_integer_nonpointer(scalar, no_update)
    implicit none
    integer, intent(inout) :: scalar
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer


  ! Versions for various array ranks

  ! Generate non-pointer and pointer versions for ranks 1..MAXRANK

  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_double_nonpointer_r1(array, no_update)
    implicit none
    double precision, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer_r1

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_double_pointer_r1(array, no_update)
    implicit none
    double precision, pointer, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 1)'
       return
    end if


  end subroutine copy_or_update_double_pointer_r1

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_double_alloc_r1(array, no_update)
    implicit none
    double precision, allocatable, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 1)'
       return
    end if


  end subroutine copy_or_update_double_alloc_r1


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_double_nonpointer_r2(array, no_update)
    implicit none
    double precision, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer_r2

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_double_pointer_r2(array, no_update)
    implicit none
    double precision, pointer, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 2)'
       return
    end if


  end subroutine copy_or_update_double_pointer_r2

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_double_alloc_r2(array, no_update)
    implicit none
    double precision, allocatable, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 2)'
       return
    end if


  end subroutine copy_or_update_double_alloc_r2


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_double_nonpointer_r3(array, no_update)
    implicit none
    double precision, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer_r3

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_double_pointer_r3(array, no_update)
    implicit none
    double precision, pointer, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 3)'
       return
    end if


  end subroutine copy_or_update_double_pointer_r3

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_double_alloc_r3(array, no_update)
    implicit none
    double precision, allocatable, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 3)'
       return
    end if


  end subroutine copy_or_update_double_alloc_r3


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_double_nonpointer_r4(array, no_update)
    implicit none
    double precision, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer_r4

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_double_pointer_r4(array, no_update)
    implicit none
    double precision, pointer, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 4)'
       return
    end if


  end subroutine copy_or_update_double_pointer_r4

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_double_alloc_r4(array, no_update)
    implicit none
    double precision, allocatable, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 4)'
       return
    end if


  end subroutine copy_or_update_double_alloc_r4


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_double_nonpointer_r5(array, no_update)
    implicit none
    double precision, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer_r5

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_double_pointer_r5(array, no_update)
    implicit none
    double precision, pointer, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 5)'
       return
    end if


  end subroutine copy_or_update_double_pointer_r5

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_double_alloc_r5(array, no_update)
    implicit none
    double precision, allocatable, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 5)'
       return
    end if


  end subroutine copy_or_update_double_alloc_r5


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_double_nonpointer_r6(array, no_update)
    implicit none
    double precision, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_double_nonpointer_r6

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_double_pointer_r6(array, no_update)
    implicit none
    double precision, pointer, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 6)'
       return
    end if


  end subroutine copy_or_update_double_pointer_r6

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_double_alloc_r6(array, no_update)
    implicit none
    double precision, allocatable, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 6)'
       return
    end if


  end subroutine copy_or_update_double_alloc_r6

  ! Generate non-pointer and pointer versions for ranks 1..MAXRANK

  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_logical_nonpointer_r1(array, no_update)
    implicit none
    logical, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer_r1

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_logical_pointer_r1(array, no_update)
    implicit none
    logical, pointer, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 1)'
       return
    end if


  end subroutine copy_or_update_logical_pointer_r1

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_logical_alloc_r1(array, no_update)
    implicit none
    logical, allocatable, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 1)'
       return
    end if


  end subroutine copy_or_update_logical_alloc_r1


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_logical_nonpointer_r2(array, no_update)
    implicit none
    logical, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer_r2

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_logical_pointer_r2(array, no_update)
    implicit none
    logical, pointer, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 2)'
       return
    end if


  end subroutine copy_or_update_logical_pointer_r2

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_logical_alloc_r2(array, no_update)
    implicit none
    logical, allocatable, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 2)'
       return
    end if


  end subroutine copy_or_update_logical_alloc_r2


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_logical_nonpointer_r3(array, no_update)
    implicit none
    logical, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer_r3

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_logical_pointer_r3(array, no_update)
    implicit none
    logical, pointer, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 3)'
       return
    end if


  end subroutine copy_or_update_logical_pointer_r3

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_logical_alloc_r3(array, no_update)
    implicit none
    logical, allocatable, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 3)'
       return
    end if


  end subroutine copy_or_update_logical_alloc_r3


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_logical_nonpointer_r4(array, no_update)
    implicit none
    logical, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer_r4

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_logical_pointer_r4(array, no_update)
    implicit none
    logical, pointer, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 4)'
       return
    end if


  end subroutine copy_or_update_logical_pointer_r4

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_logical_alloc_r4(array, no_update)
    implicit none
    logical, allocatable, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 4)'
       return
    end if


  end subroutine copy_or_update_logical_alloc_r4


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_logical_nonpointer_r5(array, no_update)
    implicit none
    logical, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer_r5

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_logical_pointer_r5(array, no_update)
    implicit none
    logical, pointer, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 5)'
       return
    end if


  end subroutine copy_or_update_logical_pointer_r5

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_logical_alloc_r5(array, no_update)
    implicit none
    logical, allocatable, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 5)'
       return
    end if


  end subroutine copy_or_update_logical_alloc_r5


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_logical_nonpointer_r6(array, no_update)
    implicit none
    logical, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_logical_nonpointer_r6

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_logical_pointer_r6(array, no_update)
    implicit none
    logical, pointer, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 6)'
       return
    end if


  end subroutine copy_or_update_logical_pointer_r6

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_logical_alloc_r6(array, no_update)
    implicit none
    logical, allocatable, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 6)'
       return
    end if


  end subroutine copy_or_update_logical_alloc_r6

  ! Generate non-pointer and pointer versions for ranks 1..MAXRANK

  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_integer_nonpointer_r1(array, no_update)
    implicit none
    integer, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer_r1

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_integer_pointer_r1(array, no_update)
    implicit none
    integer, pointer, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 1)'
       return
    end if


  end subroutine copy_or_update_integer_pointer_r1

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_integer_alloc_r1(array, no_update)
    implicit none
    integer, allocatable, intent(inout) :: array(:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 1)'
       return
    end if


  end subroutine copy_or_update_integer_alloc_r1


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_integer_nonpointer_r2(array, no_update)
    implicit none
    integer, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer_r2

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_integer_pointer_r2(array, no_update)
    implicit none
    integer, pointer, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 2)'
       return
    end if


  end subroutine copy_or_update_integer_pointer_r2

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_integer_alloc_r2(array, no_update)
    implicit none
    integer, allocatable, intent(inout) :: array(:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 2)'
       return
    end if


  end subroutine copy_or_update_integer_alloc_r2


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_integer_nonpointer_r3(array, no_update)
    implicit none
    integer, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer_r3

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_integer_pointer_r3(array, no_update)
    implicit none
    integer, pointer, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 3)'
       return
    end if


  end subroutine copy_or_update_integer_pointer_r3

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_integer_alloc_r3(array, no_update)
    implicit none
    integer, allocatable, intent(inout) :: array(:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 3)'
       return
    end if


  end subroutine copy_or_update_integer_alloc_r3


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_integer_nonpointer_r4(array, no_update)
    implicit none
    integer, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer_r4

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_integer_pointer_r4(array, no_update)
    implicit none
    integer, pointer, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 4)'
       return
    end if


  end subroutine copy_or_update_integer_pointer_r4

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_integer_alloc_r4(array, no_update)
    implicit none
    integer, allocatable, intent(inout) :: array(:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 4)'
       return
    end if


  end subroutine copy_or_update_integer_alloc_r4


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_integer_nonpointer_r5(array, no_update)
    implicit none
    integer, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer_r5

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_integer_pointer_r5(array, no_update)
    implicit none
    integer, pointer, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 5)'
       return
    end if


  end subroutine copy_or_update_integer_pointer_r5

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_integer_alloc_r5(array, no_update)
    implicit none
    integer, allocatable, intent(inout) :: array(:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 5)'
       return
    end if


  end subroutine copy_or_update_integer_alloc_r5


  !------------------------------
  ! Non-pointer, non-allocatable
  !------------------------------
  subroutine copy_or_update_integer_nonpointer_r6(array, no_update)
    implicit none
    integer, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if


  end subroutine copy_or_update_integer_nonpointer_r6

  !-------------
  ! Pointer case
  !-------------
  subroutine copy_or_update_integer_pointer_r6(array, no_update)
    implicit none
    integer, pointer, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. associated(array)) then
       print *, 'copy_or_update: null-pointer encountered (rank 6)'
       return
    end if


  end subroutine copy_or_update_integer_pointer_r6

  !----------------
  ! Allocatable case
  !----------------
  subroutine copy_or_update_integer_alloc_r6(array, no_update)
    implicit none
    integer, allocatable, intent(inout) :: array(:,:,:,:,:,:)
    logical, optional, intent(in)     :: no_update

    logical                           :: no_update_

    if (present(no_update)) then
       no_update_ = no_update
    else
       no_update_ = .false.
    end if

    if (.not. allocated(array)) then
       print *, 'copy_or_update: unallocated allocatable (rank 6)'
       return
    end if


  end subroutine copy_or_update_integer_alloc_r6


end module gpu_utils
#endif
