array_utils.fpp Source File


Contents

Source Code


Source Code

!> Provides wrappers to some simple array operations. We use this
!> indirection in order to be able to consistently treat performance
!> concerns. Currently this is limited to adding OpenMP, although in
!> the future it might allow different approaches as appropriate.
module array_utils
  implicit none

  private

  public :: copy, gs2_maxval, gs2_abs, gs2_max_abs
  public :: zero_array

  !> Interface to helper subroutines for copying one array into another.
  interface copy
     module procedure copy_real_array_3
     module procedure copy_real_array_4
     module procedure copy_complex_array_3
     module procedure copy_complex_array_4
  end interface copy

  !> Interface to helper functions for finding the maximum in an array
  interface gs2_maxval
     module procedure gs2_maxval_real_array_2
     module procedure gs2_maxval_real_array_3
  end interface gs2_maxval

  !> Interface to helper functions for finding magnitude of an array
  interface gs2_abs
     module procedure gs2_abs_real_array_2
     module procedure gs2_abs_real_array_3
     module procedure gs2_abs_complex_array_2
     module procedure gs2_abs_complex_array_3
  end interface gs2_abs

  !> Interface to helper functions for finding maxval of magnitude of an array
  interface gs2_max_abs
     module procedure gs2_max_abs_real_array_2
     module procedure gs2_max_abs_real_array_3
     module procedure gs2_max_abs_complex_array_2
     module procedure gs2_max_abs_complex_array_3
  end interface gs2_max_abs

  !> Interface to helper functions to zero an array
  interface zero_array
     module procedure zero_array_real_array_1
     module procedure zero_array_real_array_2
     module procedure zero_array_real_array_3
     module procedure zero_array_real_array_4
     module procedure zero_array_real_array_5
     module procedure zero_array_complex_array_1
     module procedure zero_array_complex_array_2
     module procedure zero_array_complex_array_3
     module procedure zero_array_complex_array_4
     module procedure zero_array_complex_array_5
  end interface zero_array

contains

  !> Copy 3D real arrays
  subroutine copy_real_array_3(array_in, array_out)
    implicit none
    real, dimension(:, :, :), intent(in) :: array_in
    real, dimension(:, :, :), intent(out) :: array_out
    integer :: counter, start, end
    ! In a debug build we might want to add a check here that the arrays have
    ! compatible shape.

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_out, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, :, counter) = array_in(:, :, counter)
    end do
    !$OMP END PARALLEL DO
  end subroutine copy_real_array_3

  !> Copy 4D real arrays
  subroutine copy_real_array_4(array_in, array_out)
    implicit none
    real, dimension(:, :, :, :), intent(in) :: array_in
    real, dimension(:, :, :, :), intent(out) :: array_out
    integer :: counter, start, end
    ! In a debug build we might want to add a check here that the arrays have
    ! compatible shape.

    start = lbound(array_in, dim = 4)
    end = ubound(array_in, dim = 4)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_out, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, :, :, counter) = array_in(:, :, :, counter)
    end do
    !$OMP END PARALLEL DO
  end subroutine copy_real_array_4

  !> Copy 3D complex arrays
  subroutine copy_complex_array_3(array_in, array_out)
    implicit none
    complex, dimension(:, :, :), intent(in) :: array_in
    complex, dimension(:, :, :), intent(out) :: array_out
    integer :: counter, start, end
    ! In a debug build we might want to add a check here that the arrays have
    ! compatible shape.

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_out, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, :, counter) = array_in(:, :, counter)
    end do
    !$OMP END PARALLEL DO
  end subroutine copy_complex_array_3

  !> Copy 4D complex arrays
  subroutine copy_complex_array_4(array_in, array_out)
    implicit none
    complex, dimension(:, :, :, :), intent(in) :: array_in
    complex, dimension(:, :, :, :), intent(out) :: array_out
    integer :: counter, start, end
    ! In a debug build we might want to add a check here that the arrays have
    ! compatible shape.

    start = lbound(array_in, dim = 4)
    end = ubound(array_in, dim = 4)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_out, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, :, :, counter) = array_in(:, :, :, counter)
    end do
    !$OMP END PARALLEL DO
  end subroutine copy_complex_array_4

  !> Find maximum in 2D array
  real function gs2_maxval_real_array_2(array_in) result(the_max)
    implicit none
    real, dimension(:, :), intent(in) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)
    the_max = 0.0
    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP REDUCTION(max: the_max) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       the_max = max(maxval(array_in(:, counter)), the_max)
    end do
    !$OMP END PARALLEL DO
  end function gs2_maxval_real_array_2

  !> Find maximum in 3D array
  real function gs2_maxval_real_array_3(array_in) result(the_max)
    implicit none
    real, dimension(:, :, :), intent(in) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)
    the_max = 0.0
    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP REDUCTION(max: the_max) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       the_max = max(maxval(array_in(:, :, counter)), the_max)
    end do
    !$OMP END PARALLEL DO
  end function gs2_maxval_real_array_3

  !> Return absolute of 2D array
  function gs2_abs_real_array_2(array_in) result(array_out)
    implicit none
    real, dimension(:, :), intent(in) :: array_in
    real, dimension(:, :), allocatable :: array_out
    integer :: counter, start, end

    allocate(array_out, mold = array_in)
    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in, array_out) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, counter) = abs(array_in(:, counter))
    end do
    !$OMP END PARALLEL DO
  end function gs2_abs_real_array_2

  !> Return absolute of 3D array
  function gs2_abs_real_array_3(array_in) result(array_out)
    implicit none
    real, dimension(:, :, :), intent(in) :: array_in
    real, dimension(:, :, :), allocatable :: array_out
    integer :: counter, start, end

    allocate(array_out, mold = array_in)
    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in, array_out) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, :, counter) = abs(array_in(:, :, counter))
    end do
    !$OMP END PARALLEL DO
  end function gs2_abs_real_array_3

  !> Return absolute of 2D array
  function gs2_abs_complex_array_2(array_in) result(array_out)
    implicit none
    complex, dimension(:, :), intent(in) :: array_in
    real, dimension(:, :), allocatable :: array_out
    integer :: counter, start, end

    allocate(array_out(size(array_in, dim=1),size(array_in, dim=2)))
    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in, array_out) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, counter) = abs(array_in(:, counter))
    end do
    !$OMP END PARALLEL DO
  end function gs2_abs_complex_array_2

  !> Return absolute of 3D array
  function gs2_abs_complex_array_3(array_in) result(array_out)
    implicit none
    complex, dimension(:, :, :), intent(in) :: array_in
    real, dimension(:, :, :), allocatable :: array_out
    integer :: counter, start, end

    allocate(array_out(size(array_in, dim=1),size(array_in, dim=2),size(array_in, dim=3)))
    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in, array_out) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_out(:, :, counter) = abs(array_in(:, :, counter))
    end do
    !$OMP END PARALLEL DO
  end function gs2_abs_complex_array_3

  !> Find maximum of abs 2D array
  real function gs2_max_abs_real_array_2(array_in) result(the_max)
    implicit none
    real, dimension(:, :), intent(in) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)
    the_max = 0.0
    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP REDUCTION(max: the_max) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       the_max = max(maxval(abs(array_in(:, counter))), the_max)
    end do
    !$OMP END PARALLEL DO
  end function gs2_max_abs_real_array_2

  !> Find maximum of abs 3D array
  real function gs2_max_abs_real_array_3(array_in) result(the_max)
    implicit none
    real, dimension(:, :, :), intent(in) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)
    the_max = 0.0
    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP REDUCTION(max: the_max) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       the_max = max(maxval(abs(array_in(:, :, counter))), the_max)
    end do
    !$OMP END PARALLEL DO
  end function gs2_max_abs_real_array_3

  !> Find maximum of abs 2D array
  real function gs2_max_abs_complex_array_2(array_in) result(the_max)
    implicit none
    complex, dimension(:, :), intent(in) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)
    the_max = 0.0
    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP REDUCTION(max: the_max) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       the_max = max(maxval(abs(array_in(:, counter))), the_max)
    end do
    !$OMP END PARALLEL DO
  end function gs2_max_abs_complex_array_2

  !> Find maximum of abs 3D array
  real function gs2_max_abs_complex_array_3(array_in) result(the_max)
    implicit none
    complex, dimension(:, :, :), intent(in) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)
    the_max = 0.0
    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP REDUCTION(max: the_max) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       the_max = max(maxval(abs(array_in(:, :, counter))), the_max)
    end do
    !$OMP END PARALLEL DO
  end function gs2_max_abs_complex_array_3

  !> Zero out a 1D array
  subroutine zero_array_real_array_1(array_in)
    implicit none
    real, dimension(:), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 1)
    end = ubound(array_in, dim = 1)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_real_array_1

  !> Zero out a 2D array
  subroutine zero_array_real_array_2(array_in)
    implicit none
    real, dimension(:, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_real_array_2

  !> Zero out a 3D array
  subroutine zero_array_real_array_3(array_in)
    implicit none
    real, dimension(:, :, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, :, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_real_array_3

  !> Zero out a 4D array
  subroutine zero_array_real_array_4(array_in)
    implicit none
    real, dimension(:, :, :, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 4)
    end = ubound(array_in, dim = 4)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, :, :, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_real_array_4

  !> Zero out a 5D array
  subroutine zero_array_real_array_5(array_in)
    implicit none
    real, dimension(:, :, :, :, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 5)
    end = ubound(array_in, dim = 5)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, :, :, :, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_real_array_5

  !> Zero out a 1D array
  subroutine zero_array_complex_array_1(array_in)
    implicit none
    complex, dimension(:), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 1)
    end = ubound(array_in, dim = 1)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_complex_array_1

  !> Zero out a 2D array
  subroutine zero_array_complex_array_2(array_in)
    implicit none
    complex, dimension(:, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 2)
    end = ubound(array_in, dim = 2)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_complex_array_2

  !> Zero out a 3D array
  subroutine zero_array_complex_array_3(array_in)
    implicit none
    complex, dimension(:, :, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 3)
    end = ubound(array_in, dim = 3)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, :, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_complex_array_3

  !> Zero out a 4D array
  subroutine zero_array_complex_array_4(array_in)
    implicit none
    complex, dimension(:, :, :, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 4)
    end = ubound(array_in, dim = 4)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, :, :, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_complex_array_4

  !> Zero out a 5D array
  subroutine zero_array_complex_array_5(array_in)
    implicit none
    complex, dimension(:, :, :, :, :), intent(in out) :: array_in
    integer :: counter, start, end

    start = lbound(array_in, dim = 5)
    end = ubound(array_in, dim = 5)

    !$OMP PARALLEL DO DEFAULT(none) &
    !$OMP SHARED(start, end, array_in) &
    !$OMP SCHEDULE(static)
    do counter = start, end
       array_in(:, :, :, :, counter) = 0.0
    end do
    !$OMP END PARALLEL DO
  end subroutine zero_array_complex_array_5

end module array_utils