!### macro's ##################################################### ! #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if ! #include "tm5.inc" ! !################################################################# module OMP_ParTools use GO , only : gol, goPr, goErr public :: TM5_OMP_Init public :: my_omp_max, my_omp_sum, my_omp_domain ! --- const -------------------------------------- character(len=*), parameter :: mname = 'OMP_ParTools' ! --- var -------------------------------------- ! OMP variables : integer :: omp_mytask, omp_ntasks, omp_mode logical :: omp_master !$OMP THREADPRIVATE (omp_mytask, omp_ntasks, omp_mode, omp_master) integer, parameter :: mx_omp_wrk = 32, mx_omp_ntasks = 64 real :: wrk(mx_omp_wrk,0:1,0:mx_omp_ntasks-1) contains ! =================================================== ! ----------------------------------------------------------------- ! OMP subroutines, originally written by r. richter, sgi, july 2008 ! adapted for TM5-structure and conventions by Vincent Huijnen, september 2008 ! ----------------------------------------------------------------- subroutine TM5_OMP_Init ( status ) ! Written : r. richter, sgi, july 2008 implicit none !vh #if defined (MPI) !vh #include !vh #endif ! --- in/out ---------------------------------- integer, intent(out) :: status ! --- const ------------------------------ ! Local parameter integer :: i, j, mype, npes, info ! Functions integer :: omp_get_thread_num, omp_get_num_threads logical :: omp_in_parallel !vh #if defined (_OPENMP) #ifdef _OPENMP if (omp_in_parallel()) & stop 'CALL my_omp_init () in parrallel region is not allowed' #endif !vh#if defined (MPI) !vh call mpi_comm_rank (mpi_comm_world, mype, info) !vh call mpi_comm_size (mpi_comm_world, npes, info) !vh call mpi_barrier (mpi_comm_world, info) !vh do i = 0, npes - 1 !vh if (i == mype) then !vh#endif !$OMP PARALLEL & !$OMP default (none) & !$OMP shared (wrk) & !$OMP private (j) #ifdef _OPENMP j = omp_get_thread_num() omp_mytask = omp_get_thread_num() omp_ntasks = omp_get_num_threads() write(*,*)'OMP. ntasks: ',omp_ntasks,', my_task: ',omp_mytask #else j = 0 omp_mytask = 0 omp_ntasks = 1 write(*,*)'No openmp parallelization used' #endif if (omp_ntasks > mx_omp_ntasks) then print *, 'ERROR : Increase mx_omp_ntasks to', omp_ntasks stop end if omp_mode = 0 omp_master = omp_mytask == 0 wrk(1:mx_omp_wrk,0:1,j) = 0.0 !$OMP END PARALLEL !vh#if defined (MPI) !vh end if !vh call mpi_barrier (mpi_comm_world, info) !vh end do !vh#endif ! ok status = 0 return end subroutine TM5_OMP_Init ! subroutine my_omp_domain (std_start, std_end, dom_start, dom_end) ! Written : r. richter, sgi, july 2008 implicit none ! Input/output parameters integer :: std_start, std_end, dom_start, dom_end ! Local parameters real (8) :: x_len, x_mytask, x_ntasks ! Functions logical :: omp_in_parallel !vh #if defined (_OPENMP) #ifdef _OPENMP if (omp_in_parallel()) then x_mytask = real (omp_mytask, 8) x_ntasks = real (omp_ntasks, 8) else x_mytask = 0.0_8 x_ntasks = 1.0_8 end if #else x_mytask = real (omp_mytask, 8) x_ntasks = real (omp_ntasks, 8) #endif x_len = real (std_end - std_start + 1, 8) dom_start = std_start + floor ((x_mytask * x_len + 0.5_8) / & x_ntasks, 4) dom_end = std_start - 1 + floor ((x_mytask * x_len + x_len + & 0.5_8) / x_ntasks, 4) return end subroutine my_omp_domain ! subroutine my_omp_sum (lvec, gvec) ! Written : r. richter, sgi, july 2008 implicit none ! Input/output parameters real :: lvec, gvec ! Local parameters logical :: do_parallel ! Functions logical (4) :: omp_in_parallel !#if defined (_OPENMP) #ifdef _OPENMP do_parallel = omp_in_parallel() #else do_parallel = .false. #endif if (do_parallel) then omp_mode = mod (omp_mode + 1, 2) wrk(1,omp_mode,omp_mytask) = lvec !$OMP BARRIER if (omp_master) gvec = sum (wrk(1,omp_mode,0:omp_ntasks-1)) !$OMP BARRIER else gvec = lvec end if return end subroutine my_omp_sum ! subroutine my_omp_max (lvec, gvec) ! Written : r. richter, sgi, july 2008 implicit none ! Input/output parameters real :: lvec, gvec ! Local parameters logical :: do_parallel ! Functions logical (4) :: omp_in_parallel !#if defined (_OPENMP) #ifdef _OPENMP do_parallel = omp_in_parallel() #else do_parallel = .false. #endif if (do_parallel) then omp_mode = mod (omp_mode + 1, 2) wrk(1,omp_mode,omp_mytask) = lvec !$OMP BARRIER if (omp_master) gvec = maxval (wrk(1,omp_mode,0:omp_ntasks-1)) !$OMP BARRIER else gvec = lvec end if return end subroutine my_omp_max end module OMP_ParTools