Research Article

High-Performance Design Patterns for Modern Fortran

Listing 12

function df_dx(this)
implicit none
class(tensor), intent(in):: this
type(tensor):: df_dx
integer(ikind):: i, nx
real(c_double):: dx, left_image, right_image
real(c_double), dimension(:), allocatable, save:: local_tensor_data
  nx = local_grid_resolution
  if (.not.allocated(local_tensor_data)) allocate(local_tensor_data(nx))
  dx = 2. pi/(real(nx, c_double) num_procs)
  if (num_procs > 1) then
   call MPI_SENDRECV(this%global_f(), 1,
    MPI_DOUBLE_PRECISION, left_id, 0, right_image, 1,
    MPI_DOUBLE_PRECISION, right_id, 0, MPI_COMM_CART,
    status, ierr)
   call MPI_SENDRECV(this%global_f(nx), 1,
    MPI_DOUBLE_PRECISION, right_id, 0, left_image, 1,
    MPI_DOUBLE_PRECISION, left_id, 0, MPI_COMM_CART,
    status, ierr)
  else
   left_image = this%global_f(nx)
   right_image = this%global_f()
  end if
  local_tensor_data() = 0.5 (this%global_f() − left_image)/dx
  local_tensor_data(nx) = 0.5 (right_image − this%global_f(nx − 1))/dx
  do concurrent(i = 2 : nx − 1)
  local_tensor_data(i) = 0.5 (this%global_f(i + 1) − this%global_f(i − 1))/dx
  end do
  df_dx%global_f = local_tensor_data
end function