Skip to content
core.F90 4.52 KiB
Newer Older
! Main solver routines for heat equation solver
module core
  use heat

contains

  ! Exchange the boundary data between MPI tasks
  subroutine exchange_init(field0, parallel)
    use mpi

    implicit none

    type(field), intent(inout) :: field0
    type(parallel_data), intent(in) :: parallel

    integer :: ierr

    ! Send to left, receive from right
    call mpi_isend(field0%data(0, 1), 1, parallel%columntype, &
         & parallel%nleft, 11, parallel%comm, parallel%requests(1), ierr)
    call mpi_irecv(field0%data(0, field0%ny + 1), 1, parallel%columntype, &
         & parallel%nright, 11, &
         & parallel%comm, parallel%requests(2), ierr)
    
    ! Send to right, receive from left
    call mpi_isend(field0%data(0, field0%ny), 1, parallel%columntype, &
         & parallel%nright, 12, parallel%comm, parallel%requests(3), ierr)
    call mpi_irecv(field0%data(0, 0), 1, parallel%columntype, &
         & parallel%nleft, 12, &
         & parallel%comm, parallel%requests(4), ierr)

    ! Send to up receive from down
    call mpi_isend(field0%data(1, 0), 1, parallel%rowtype, &
         & parallel%nup, 13, parallel%comm, parallel%requests(5), ierr)
    call mpi_irecv(field0%data(field0%nx+1, 0), 1, parallel%rowtype, &
         & parallel%ndown, 13, parallel%comm, parallel%requests(6), ierr)

    ! Send to the down, receive from up
    call mpi_isend(field0%data(field0%nx, 0), 1, parallel%rowtype, &
         & parallel%ndown, 14, parallel%comm, parallel%requests(7), ierr)
    call mpi_irecv(field0%data(0, 0), 1, parallel%rowtype, &
         & parallel%nup, 14, parallel%comm, parallel%requests(8), ierr)

  end subroutine exchange_init

  ! Finalize the non-blocking communication
  subroutine exchange_finalize(parallel)
    use mpi
    implicit none
    type(parallel_data), intent(inout) :: parallel
    integer :: ierr

    call mpi_waitall(8, parallel%requests, mpi_statuses_ignore, ierr)
  end subroutine exchange_finalize

  ! Compute one time step of temperature evolution
  ! Arguments:
  !   curr (type(field)): current temperature values
  !   prev (type(field)): values from previous time step
  !   a (real(dp)): update equation constant
  !   dt (real(dp)): time step value
  subroutine evolve_interior(curr, prev, a, dt)

    implicit none

    type(field), intent(inout) :: curr, prev
    real(dp) :: a, dt
    integer :: i, j, nx, ny

    nx = curr%nx
    ny = curr%ny

    do j = 2, ny - 1
       do i = 2, nx - 1
          curr%data(i, j) = prev%data(i, j) + a * dt * &
               & ((prev%data(i-1, j) - 2.0 * prev%data(i, j) + &
               &   prev%data(i+1, j)) / curr%dx**2 + &
               &  (prev%data(i, j-1) - 2.0 * prev%data(i, j) + &
               &   prev%data(i, j+1)) / curr%dy**2)
       end do
    end do
  end subroutine evolve_interior

  ! Compute one time step of temperature evolution
  ! Arguments:
  !   curr (type(field)): current temperature values
  !   prev (type(field)): values from previous time step
  !   a (real(dp)): update equation constant
  !   dt (real(dp)): time step value
  ! Update only the border-dependent part
  subroutine evolve_edges(curr, prev, a, dt)

    implicit none

    type(field), intent(inout) :: curr, prev
    real(dp) :: a, dt
    integer :: i, j, nx, ny

    nx = curr%nx
    ny = curr%ny

    j = 1
    do i = 1, nx
       curr%data(i, j) = prev%data(i, j) + a * dt * &
            & ((prev%data(i-1, j) - 2.0 * prev%data(i, j) + &
            &   prev%data(i+1, j)) / curr%dx**2 + &
            &  (prev%data(i, j-1) - 2.0 * prev%data(i, j) + &
            &   prev%data(i, j+1)) / curr%dy**2)
    end do
    j = ny
    do i = 1, nx
       curr%data(i, j) = prev%data(i, j) + a * dt * &
            & ((prev%data(i-1, j) - 2.0 * prev%data(i, j) + &
            &   prev%data(i+1, j)) / curr%dx**2 + &
            &  (prev%data(i, j-1) - 2.0 * prev%data(i, j) + &
            &   prev%data(i, j+1)) / curr%dy**2)
    end do
    i = 1
    do j = 1, ny
       curr%data(i, j) = prev%data(i, j) + a * dt * &
            & ((prev%data(i-1, j) - 2.0 * prev%data(i, j) + &
            &   prev%data(i+1, j)) / curr%dx**2 + &
            &  (prev%data(i, j-1) - 2.0 * prev%data(i, j) + &
            &   prev%data(i, j+1)) / curr%dy**2)
    end do
    i = nx
    do j = 1, ny
       curr%data(i, j) = prev%data(i, j) + a * dt * &
            & ((prev%data(i-1, j) - 2.0 * prev%data(i, j) + &
            &   prev%data(i+1, j)) / curr%dx**2 + &
            &  (prev%data(i, j-1) - 2.0 * prev%data(i, j) + &
            &   prev%data(i, j+1)) / curr%dy**2)
    end do

  end subroutine evolve_edges


end module core