LCOV - code coverage report
Current view: | top level - dynamics/se/dycore - hybrid_mod.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 116 | 186 | 62.4 %
Date: | 2024-12-17 17:57:11 |  | Functions: | 7 | 12 | 58.3 %

              Line data    Source code
           1             : ! ===========================================
           2             : ! Module to support hybrid programming model
           3             : ! hybrid_t is assumed to be a private struct
           4             : ! ===========================================
           5             : module hybrid_mod
           6             :
           7             : use parallel_mod  , only : parallel_t, copy_par
           8             : use thread_mod    , only : omp_set_num_threads, omp_get_thread_num
           9             : use thread_mod    , only : horz_num_threads, vert_num_threads, tracer_num_threads
          10             : use dimensions_mod, only : nlev, qsize, ntrac, use_cslam
          11             :
          12             : implicit none
          13             : private
          14             :
          15             :   type, private :: hybrid_p
          16             :      integer :: ibeg, iend
          17             :      integer :: kbeg, kend
          18             :      integer :: qbeg, qend
          19             :   end type
          20             :
          21             :   type, public :: hybrid_t
          22             :      type (parallel_t) :: par
          23             :      integer           :: ithr
          24             :      integer           :: nthreads
          25             :      integer           :: ibeg, iend
          26             :      integer           :: kbeg, kend
          27             :      integer           :: qbeg, qend
          28             :      logical           :: masterthread
          29             :   end type
          30             :
          31             :   integer, allocatable :: work_pool_horz(:,:)
          32             :   integer, allocatable :: work_pool_vert(:,:)
          33             :   integer, allocatable :: work_pool_trac(:,:)
          34             :   integer, allocatable :: work_pool_ctrac(:,:)
          35             :
          36             :   integer :: nelemd_save
          37             :   logical :: init_ranges = .true.
          38             :   integer :: region_num_threads
          39             :   character(len=64) :: region_name
          40             :
          41             :   public :: PrintHybrid
          42             :   public :: set_region_num_threads
          43             :   private :: set_loop_ranges
          44             :   public :: get_loop_ranges
          45             :   public :: init_loop_ranges
          46             :   public :: threadOwnsTracer, threadOwnsVertlevel
          47             :   public :: config_thread_region
          48             :
          49             :   interface config_thread_region
          50             :       module procedure config_thread_region_par
          51             :       module procedure config_thread_region_hybrid
          52             :   end interface
          53             :   interface PrintHybrid
          54             :       module procedure PrintHybridnew
          55             :   end interface
          56             :
          57             : contains
          58             :
          59           0 :   subroutine PrintHybridnew(hybt,vname)
          60             :     type (hybrid_t) :: hybt
          61             :     character(len=*) :: vname
          62             :
          63           0 :     write(*,21) vname, hybt%par%rank, hybt%ithr, hybt%nthreads, &
          64           0 :                 hybt%ibeg, hybt%iend,hybt%kbeg,hybt%kend, &
          65           0 :                 hybt%qbeg, hybt%qend
          66             : 21  format('PrintHybrid: (',a, ', rank: ',i8, ', ithrd: ',i4,',  nthreads: ',i4, &
          67             :            ', i{beg,end}: ',2(i4),', k{beg,end}: ',2(i4),', q{beg,end}: ',2(i4),')')
          68             :
          69           0 :   end subroutine PrintHybridnew
          70             :
          71             :
          72     5933616 :   function config_thread_region_hybrid(old,region_name) result(new)
          73             :      type (hybrid_t), intent(in) :: old
          74             :      character(len=*), intent(in) :: region_name
          75             :      type (hybrid_t) :: new
          76             :
          77             :      integer :: ithr
          78             :      integer :: kbeg_range, kend_range, qbeg_range, qend_range
          79             :
          80             :
          81     5933616 :      ithr = omp_get_thread_num()
          82             :
          83     5933616 :      if ( TRIM(region_name) == 'serial') then
          84           0 :          region_num_threads = 1
          85           0 :          new%ibeg = old%ibeg;      new%iend = old%iend
          86           0 :          new%kbeg = old%kbeg;      new%kend = old%kend
          87           0 :          new%qbeg = old%qbeg;      new%qend = old%qend
          88             :      endif
          89     5933616 :      if ( TRIM(region_name) == 'vertical') then
          90      738816 :          region_num_threads = vert_num_threads
          91      738816 :          call set_thread_ranges_1D ( work_pool_vert, kbeg_range, kend_range, ithr )
          92      738816 :          new%ibeg = old%ibeg;      new%iend = old%iend
          93      738816 :          new%kbeg = kbeg_range;    new%kend = kend_range
          94      738816 :          new%qbeg = old%qbeg;      new%qend = old%qend
          95             :       endif
          96             :
          97     5933616 :       if ( TRIM(region_name) == 'tracer' ) then
          98           0 :          region_num_threads = tracer_num_threads
          99           0 :          call set_thread_ranges_1D ( work_pool_trac, qbeg_range, qend_range, ithr)
         100           0 :          new%ibeg = old%ibeg;      new%iend = old%iend
         101           0 :          new%kbeg = old%kbeg;      new%kend = old%kend
         102           0 :          new%qbeg = qbeg_range;    new%qend = qend_range
         103             :       endif
         104             :
         105     5933616 :       if ( TRIM(region_name) == 'ctracer' ) then
         106     5194800 :          region_num_threads = tracer_num_threads
         107     5194800 :          call set_thread_ranges_1D ( work_pool_ctrac, qbeg_range, qend_range, ithr)
         108     5194800 :          new%ibeg = old%ibeg;      new%iend = old%iend
         109     5194800 :          new%kbeg = old%kbeg;      new%kend = old%kend
         110     5194800 :          new%qbeg = qbeg_range;    new%qend = qend_range
         111             :       endif
         112             :
         113     5933616 :       if ( TRIM(region_name) == 'vertical_and_tracer' ) then
         114           0 :          region_num_threads = vert_num_threads*tracer_num_threads
         115             :          call set_thread_ranges_2D ( work_pool_vert, work_pool_trac, kbeg_range, kend_range, &
         116           0 :                                                        qbeg_range, qend_range, ithr )
         117           0 :          new%ibeg = old%ibeg;      new%iend = old%iend
         118           0 :          new%kbeg = kbeg_range;    new%kend = kend_range
         119           0 :          new%qbeg = qbeg_range;    new%qend = qend_range
         120             :       endif
         121             :
         122             :
         123     5933616 :       new%par          = old%par      ! relies on parallel_mod copy constructor
         124     5933616 :       new%nthreads     = old%nthreads * region_num_threads
         125     5933616 :       if( region_num_threads .ne. 1 ) then
         126           0 :           new%ithr         = old%ithr * region_num_threads + ithr
         127             :       else
         128     5933616 :           new%ithr         = old%ithr
         129             :       endif
         130     5933616 :       new%masterthread = old%masterthread
         131             : !  Do we want to make this following call?
         132             : !      call omp_set_num_threads(new%nthreads)
         133             :
         134     5933616 :   end function config_thread_region_hybrid
         135             :
         136     1113600 :   function config_thread_region_par(par,region_name) result(hybrid)
         137             :       type (parallel_t) , intent(in) :: par
         138             :       character(len=*), intent(in) :: region_name
         139             :       type (hybrid_t)                :: hybrid
         140             :       ! local
         141             :       integer    :: ithr
         142             :       integer    :: ibeg_range, iend_range
         143             :       integer    :: kbeg_range, kend_range
         144             :       integer    :: qbeg_range, qend_range
         145             :       integer    :: nthreads
         146             :
         147     1113600 :       ithr            = omp_get_thread_num()
         148             :
         149     1113600 :       if ( TRIM(region_name) == 'serial') then
         150      742656 :          region_num_threads = 1
         151      742656 :          if ( .NOT. allocated(work_pool_horz) ) allocate(work_pool_horz(horz_num_threads,2))
         152      742656 :          call set_thread_ranges_1D ( work_pool_horz, ibeg_range, iend_range, ithr )
         153      742656 :          hybrid%ibeg = 1;          hybrid%iend = nelemd_save
         154      742656 :          hybrid%kbeg = 1;          hybrid%kend = nlev
         155      742656 :          hybrid%qbeg = 1;          hybrid%qend = qsize
         156             :       endif
         157             :
         158     1113600 :       if ( TRIM(region_name) == 'horizontal') then
         159      370944 :          region_num_threads = horz_num_threads
         160      370944 :          call set_thread_ranges_1D ( work_pool_horz, ibeg_range, iend_range, ithr )
         161      370944 :          hybrid%ibeg = ibeg_range; hybrid%iend = iend_range
         162      370944 :          hybrid%kbeg = 1;          hybrid%kend = nlev
         163      370944 :          hybrid%qbeg = 1;          hybrid%qend = qsize
         164             :       endif
         165             :
         166     1113600 :       if ( TRIM(region_name) == 'vertical') then
         167           0 :          region_num_threads = vert_num_threads
         168           0 :          call set_thread_ranges_1D ( work_pool_vert, kbeg_range, kend_range, ithr )
         169           0 :          hybrid%ibeg = 1;          hybrid%iend = nelemd_save
         170           0 :          hybrid%kbeg = kbeg_range; hybrid%kend = kend_range
         171           0 :          hybrid%qbeg = 1;          hybrid%qend = qsize
         172             :       endif
         173             :
         174     1113600 :       if ( TRIM(region_name) == 'tracer' ) then
         175           0 :          region_num_threads = tracer_num_threads
         176           0 :          call set_thread_ranges_1D ( work_pool_trac, qbeg_range, qend_range, ithr)
         177           0 :          hybrid%ibeg = 1;          hybrid%iend = nelemd_save
         178           0 :          hybrid%kbeg = 1;          hybrid%kend = nlev
         179           0 :          hybrid%qbeg = qbeg_range; hybrid%qend = qend_range
         180             :       endif
         181             :
         182     1113600 :       if ( TRIM(region_name) == 'ctracer' ) then
         183           0 :          region_num_threads = tracer_num_threads
         184           0 :          call set_thread_ranges_1D ( work_pool_ctrac, qbeg_range, qend_range, ithr)
         185           0 :          hybrid%ibeg = 1;          hybrid%iend = nelemd_save
         186           0 :          hybrid%kbeg = 1;          hybrid%kend = nlev
         187           0 :          hybrid%qbeg = qbeg_range; hybrid%qend = qend_range
         188             :       endif
         189             :
         190     1113600 :       if ( TRIM(region_name) == 'vertical_and_tracer' ) then
         191           0 :          region_num_threads = vert_num_threads*tracer_num_threads
         192             :          call set_thread_ranges_2D ( work_pool_vert, work_pool_trac, kbeg_range, kend_range, &
         193           0 :                                                        qbeg_range, qend_range, ithr )
         194           0 :          hybrid%ibeg = 1;          hybrid%iend = nelemd_save
         195           0 :          hybrid%kbeg = kbeg_range; hybrid%kend = kend_range
         196           0 :          hybrid%qbeg = qbeg_range; hybrid%qend = qend_range
         197             :       endif
         198     1113600 :       call omp_set_num_threads(region_num_threads)
         199             :
         200             : !      hybrid%par          = par      ! relies on parallel_mod copy constructor
         201     1113600 :       call copy_par(hybrid%par,par)
         202     1113600 :       hybrid%nthreads     = region_num_threads
         203     1113600 :       hybrid%ithr         = ithr
         204     1113600 :       hybrid%masterthread = (par%masterproc .and. ithr==0)
         205             :
         206     1113600 :   end function config_thread_region_par
         207             :
         208        1536 :   subroutine init_loop_ranges(nelemd)
         209             :
         210             :       integer, intent(in) :: nelemd
         211             :       integer :: ith, beg_index, end_index
         212             :
         213             :
         214        1536 :       if ( init_ranges ) then
         215        1536 :         nelemd_save=nelemd
         216        4608 :         if ( .NOT. allocated(work_pool_horz) ) allocate(work_pool_horz(horz_num_threads,2))
         217        1536 :         if(nelemd<horz_num_threads) &
         218           0 :           print *,'WARNING: insufficient horizontal parallelism to support ',horz_num_threads,' horizontal threads'
         219             :
         220        3072 :         do ith=0,horz_num_threads-1
         221        1536 :           call create_work_pool( 1, nelemd, horz_num_threads, ith, beg_index, end_index )
         222        1536 :           work_pool_horz(ith+1,1) = beg_index
         223        3072 :           work_pool_horz(ith+1,2) = end_index
         224             :         end do
         225             :
         226        1536 :         if(nlev<vert_num_threads) &
         227           0 :           print *,'WARNING: insufficient vertical parallelism to support ',vert_num_threads,' vertical threads'
         228        4608 :         if ( .NOT. allocated(work_pool_vert) ) allocate(work_pool_vert(vert_num_threads,2))
         229        3072 :         do ith=0,vert_num_threads-1
         230        1536 :           call create_work_pool( 1, nlev, vert_num_threads, ith, beg_index, end_index )
         231        1536 :           work_pool_vert(ith+1,1) = beg_index
         232        3072 :           work_pool_vert(ith+1,2) = end_index
         233             :         end do
         234             :
         235        1536 :         if(qsize<tracer_num_threads) &
         236           0 :           print *,'WARNING: insufficient tracer parallelism to support ',tracer_num_threads,' tracer threads'
         237        4608 :         if ( .NOT. allocated(work_pool_trac) ) allocate(work_pool_trac(tracer_num_threads,2))
         238        3072 :         do ith=0,tracer_num_threads-1
         239        1536 :           call create_work_pool( 1, qsize, tracer_num_threads, ith, beg_index, end_index )
         240        1536 :           work_pool_trac(ith+1,1) = beg_index
         241        3072 :           work_pool_trac(ith+1,2) = end_index
         242             :         end do
         243             :
         244        1536 :         if(use_cslam .and. ntrac<tracer_num_threads) &
         245           0 :           print *,'WARNING: insufficient CSLAM tracer parallelism to support ',tracer_num_threads,' tracer threads'
         246        4608 :         if ( .NOT. allocated(work_pool_ctrac) ) allocate(work_pool_ctrac(tracer_num_threads,2))
         247        3072 :         do ith=0,tracer_num_threads-1
         248        1536 :           call create_work_pool( 1, ntrac, tracer_num_threads, ith, beg_index, end_index )
         249        1536 :           work_pool_ctrac(ith+1,1) = beg_index
         250        3072 :           work_pool_ctrac(ith+1,2) = end_index
         251             :         end do
         252             :
         253        1536 :         init_ranges = .false.
         254             :       endif
         255             :
         256        1536 :   end subroutine init_loop_ranges
         257             :
         258           0 :  subroutine set_region_num_threads( local_name )
         259             :
         260             :   character(len=*), intent(in) :: local_name
         261             :
         262           0 :   region_name = local_name
         263             :
         264             : #ifdef _OPENMP
         265             :
         266             :   if ( TRIM(region_name) == 'horizontal') then
         267             :     region_num_threads = horz_num_threads
         268             :     call omp_set_num_threads(region_num_threads)
         269             :     return
         270             :   endif
         271             :
         272             :   if ( TRIM(region_name) == 'vertical') then
         273             :     region_num_threads = vert_num_threads
         274             :     call omp_set_num_threads(region_num_threads)
         275             :     return
         276             :   endif
         277             :
         278             :   if ( TRIM(region_name) == 'tracer' ) then
         279             :     region_num_threads = tracer_num_threads
         280             :     call omp_set_num_threads(region_num_threads)
         281             :     return
         282             :   endif
         283             :
         284             :   if ( TRIM(region_name) == 'vertical_and_tracer' ) then
         285             :     region_num_threads = vert_num_threads*tracer_num_threads
         286             :     call omp_set_num_threads(region_num_threads)
         287             :     return
         288             :   endif
         289             :
         290             : #endif
         291             :
         292           0 :   end subroutine set_region_num_threads
         293             :
         294             :   subroutine set_loop_ranges (pybrid)
         295             :
         296             :   type (hybrid_p) :: pybrid
         297             :
         298             :   integer :: ibeg_range, iend_range
         299             :   integer :: kbeg_range, kend_range
         300             :   integer :: qbeg_range, qend_range
         301             :   integer :: idthread
         302             :
         303             : #ifdef _OPENMP
         304             :   idthread = omp_get_thread_num()
         305             :
         306             :   if ( TRIM(region_name) == 'horizontal' ) then
         307             :     call set_thread_ranges_1D ( work_pool_horz, ibeg_range, iend_range, idthread )
         308             :     pybrid%ibeg = ibeg_range; pybrid%iend = iend_range
         309             :     pybrid%kbeg = 1;          pybrid%kend = nlev
         310             :     pybrid%qbeg = 1;          pybrid%qend = qsize
         311             :   endif
         312             :
         313             :   if ( TRIM(region_name) == 'vertical' ) then
         314             :     call set_thread_ranges_1D ( work_pool_vert, kbeg_range, kend_range, idthread )
         315             :     !FIXME: need to set ibeg, iend as well
         316             :     pybrid%kbeg = kbeg_range; pybrid%kend = kend_range
         317             :     pybrid%qbeg = 1;          pybrid%qend = qsize
         318             :   endif
         319             :
         320             :   if ( TRIM(region_name) == 'tracer' ) then
         321             :     call set_thread_ranges_1D ( work_pool_trac, qbeg_range, qend_range, idthread )
         322             :     !FIXME: need to set ibeg, iend as well
         323             :     pybrid%kbeg = 1;          pybrid%kend = nlev
         324             :     pybrid%qbeg = qbeg_range; pybrid%qend = qend_range
         325             :   endif
         326             :
         327             :   if ( TRIM(region_name) == 'ctracer' ) then
         328             :     call set_thread_ranges_1D ( work_pool_ctrac, qbeg_range, qend_range, idthread )
         329             :     !FIXME: need to set ibeg, iend as well
         330             :     pybrid%kbeg = 1;          pybrid%kend = nlev
         331             :     pybrid%qbeg = qbeg_range; pybrid%qend = qend_range
         332             :   endif
         333             :
         334             :   if ( TRIM(region_name) == 'vertical_and_tracer' ) then
         335             :     call set_thread_ranges_2D ( work_pool_vert, work_pool_trac, kbeg_range, kend_range, &
         336             :                                                        qbeg_range, qend_range, idthread )
         337             :     !FIXME: need to set ibeg, iend as well
         338             :     pybrid%kbeg = kbeg_range; pybrid%kend = kend_range
         339             :     pybrid%qbeg = qbeg_range; pybrid%qend = qend_range
         340             :   endif
         341             :
         342             : #else
         343             :   call reset_loop_ranges(pybrid, region_name)
         344             : #endif
         345             :
         346             :   end subroutine set_loop_ranges
         347             :
         348     7047216 :   subroutine get_loop_ranges (pybrid, ibeg, iend, kbeg, kend, qbeg, qend)
         349             :
         350             :   type (hybrid_t), intent(in) :: pybrid
         351             :   integer, optional, intent(out) :: ibeg, iend, kbeg, kend, qbeg, qend
         352             :
         353     7047216 :   if ( present(ibeg) ) then
         354     1113600 :     ibeg = pybrid%ibeg
         355             :   endif
         356     7047216 :   if ( present(iend) ) then
         357     1113600 :     iend = pybrid%iend
         358             :   endif
         359     7047216 :   if ( present(kbeg) ) then
         360      738816 :     kbeg = pybrid%kbeg
         361             :   endif
         362     7047216 :   if ( present(kend) ) then
         363      738816 :     kend = pybrid%kend
         364             :   endif
         365     7047216 :   if ( present(qbeg) ) then
         366     5194800 :     qbeg = pybrid%qbeg
         367             :   endif
         368     7047216 :   if ( present(qend) ) then
         369     5194800 :     qend = pybrid%qend
         370             :   endif
         371             :
         372     7047216 :   end subroutine get_loop_ranges
         373             :
         374     1477632 :   function threadOwnsVertlevel(hybrid,value) result(found)
         375             :
         376             :    type (hybrid_t), intent(in) :: hybrid
         377             :    integer, intent(in) :: value
         378             :    logical :: found
         379             :
         380     1477632 :    found = .false.
         381     1477632 :    if ((value >= hybrid%kbeg) .and. (value <= hybrid%kend)) then
         382     1477632 :       found = .true.
         383             :    endif
         384             :
         385     1477632 :   end function threadOwnsVertlevel
         386             :
         387           0 :   function threadOwnsTracer(hybrid,value) result(found)
         388             :
         389             :    type (hybrid_t), intent(in) :: hybrid
         390             :    integer, intent(in) :: value
         391             :    logical :: found
         392             :
         393           0 :    found = .false.
         394           0 :    if ((value >= hybrid%qbeg) .and. (value <= hybrid%qend)) then
         395           0 :       found = .true.
         396             :    endif
         397             :
         398           0 :   end function threadOwnsTracer
         399             :
         400             :   subroutine reset_loop_ranges (pybrid, region_name)
         401             :
         402             :   type (hybrid_p)              :: pybrid
         403             :   character(len=*), intent(in) :: region_name
         404             :
         405             :   if ( TRIM(region_name) == 'vertical' ) then
         406             :     pybrid%kbeg = 1; pybrid%kend = nlev
         407             :   endif
         408             :
         409             :   if ( TRIM(region_name) == 'tracer' ) then
         410             :     pybrid%qbeg = 1; pybrid%qend = qsize
         411             :   endif
         412             :
         413             :   if ( TRIM(region_name) == 'vertical_and_tracer' ) then
         414             :     pybrid%kbeg = 1; pybrid%kend = nlev
         415             :     pybrid%qbeg = 1; pybrid%qend = qsize
         416             :   endif
         417             :
         418             :   end subroutine reset_loop_ranges
         419             :
         420             :   subroutine set_thread_ranges_3D ( work_pool_x, work_pool_y, work_pool_z, &
         421             :                        beg_range_1, end_range_1, beg_range_2, end_range_2, &
         422             :                                     beg_range_3, end_range_3, idthread )
         423             :
         424             :   integer, intent (in   ) :: work_pool_x(:,:)
         425             :   integer, intent (in   ) :: work_pool_y(:,:)
         426             :   integer, intent (in   ) :: work_pool_z(:,:)
         427             :   integer, intent (inout) :: beg_range_1
         428             :   integer, intent (inout) :: end_range_1
         429             :   integer, intent (inout) :: beg_range_2
         430             :   integer, intent (inout) :: end_range_2
         431             :   integer, intent (inout) :: beg_range_3
         432             :   integer, intent (inout) :: end_range_3
         433             :   integer, intent (inout) :: idthread
         434             :
         435             :   integer :: index(3)
         436             :   integer :: i, j, k, ind, irange, jrange, krange
         437             :
         438             :   ind = 0
         439             :
         440             :   krange = SIZE(work_pool_z,1)
         441             :   jrange = SIZE(work_pool_y,1)
         442             :   irange = SIZE(work_pool_x,1)
         443             :   do k = 1, krange
         444             :     do j = 1, jrange
         445             :       do i = 1, irange
         446             :         if( ind == idthread ) then
         447             :           index(1) = i
         448             :           index(2) = j
         449             :           index(3) = k
         450             :         endif
         451             :         ind = ind + 1
         452             :       enddo
         453             :     enddo
         454             :   enddo
         455             :   beg_range_1 = work_pool_x(index(1),1)
         456             :   end_range_1 = work_pool_x(index(1),2)
         457             :   beg_range_2 = work_pool_y(index(2),1)
         458             :   end_range_2 = work_pool_y(index(2),2)
         459             :   beg_range_3 = work_pool_z(index(3),1)
         460             :   end_range_3 = work_pool_z(index(3),2)
         461             :
         462             : !  write(6,1000) idthread, beg_range_1, end_range_1, &
         463             : !                          beg_range_2, end_range_2, &
         464             : !                          beg_range_3, end_range_3
         465             : !  call flush(6)
         466             : 1000 format( 'set_thread_ranges_3D', 7(i4) )
         467             :
         468             :   end subroutine set_thread_ranges_3D
         469             :
         470           0 :   subroutine set_thread_ranges_2D( work_pool_x, work_pool_y, beg_range_1, end_range_1, &
         471             :                                                     beg_range_2, end_range_2, idthread )
         472             :
         473             :   integer, intent (in   ) :: work_pool_x(:,:)
         474             :   integer, intent (in   ) :: work_pool_y(:,:)
         475             :   integer, intent (inout) :: beg_range_1
         476             :   integer, intent (inout) :: end_range_1
         477             :   integer, intent (inout) :: beg_range_2
         478             :   integer, intent (inout) :: end_range_2
         479             :   integer, intent (inout) :: idthread
         480             :
         481             :   integer :: index(2)
         482             :   integer :: i, j, ind, irange, jrange
         483             :
         484           0 :   ind = 0
         485             :
         486           0 :   jrange = SIZE(work_pool_y,1)
         487           0 :   irange = SIZE(work_pool_x,1)
         488           0 :   do j = 1, jrange
         489           0 :     do i = 1, irange
         490           0 :       if( ind == idthread ) then
         491           0 :         index(1) = i
         492           0 :         index(2) = j
         493             :       endif
         494           0 :       ind = ind + 1
         495             :     enddo
         496             :   enddo
         497           0 :   beg_range_1 = work_pool_x(index(1),1)
         498           0 :   end_range_1 = work_pool_x(index(1),2)
         499           0 :   beg_range_2 = work_pool_y(index(2),1)
         500           0 :   end_range_2 = work_pool_y(index(2),2)
         501             :
         502             : ! write(6,1000) idthread, beg_range_1, end_range_1, &
         503             : !                         beg_range_2, end_range_2
         504             : ! call flush(6)
         505             :
         506             : 1000 format( 'set_thread_ranges_2D', 7(i4) )
         507             :
         508           0 :   end subroutine set_thread_ranges_2D
         509             :
         510     7047216 :   subroutine set_thread_ranges_1D( work_pool, beg_range, end_range, idthread )
         511             :
         512             :   integer, intent (in   ) :: work_pool(:,:)
         513             :   integer, intent (inout) :: beg_range
         514             :   integer, intent (inout) :: end_range
         515             :   integer, intent (inout) :: idthread
         516             :
         517             :   integer :: index
         518             :   integer :: i, j, ind, irange
         519             :
         520     7047216 :   ind = 0
         521             :
         522    21141648 :   irange = SIZE(work_pool)
         523    21141648 :   do i = 1, irange
         524    14094432 :     if( ind == idthread ) then
         525     7047216 :       index = i
         526             :     endif
         527    21141648 :     ind = ind + 1
         528             :   enddo
         529     7047216 :   beg_range = work_pool(index,1)
         530     7047216 :   end_range = work_pool(index,2)
         531             :
         532             : ! write(6,1000) idthread, beg_range, end_range
         533             : ! call flush(6)
         534             : 1000 format( 'set_thread_ranges_1D', 7(i4) )
         535             :
         536     7047216 :   end subroutine set_thread_ranges_1D
         537             :
         538        6144 :   subroutine create_work_pool( start_domain, end_domain, ndomains, ipe, beg_index, end_index )
         539             :
         540             :   integer, intent(in) :: start_domain, end_domain
         541             :   integer, intent(in) :: ndomains, ipe
         542             :   integer, intent(out) ::beg_index, end_index
         543             :
         544       12288 :   integer :: beg(0:ndomains)
         545             :   integer :: length
         546             :   integer :: n
         547             :
         548        6144 :   length = end_domain - start_domain + 1
         549        6144 :   beg(0) = start_domain
         550             :
         551        6144 :   do n=1,ndomains-1
         552        6144 :      if (n.le.mod(length,ndomains)) then
         553           0 :         beg(n)=beg(n-1)+(length-1)/ndomains+1
         554             :      else
         555           0 :         beg(n)=beg(n-1)+length/ndomains
         556             :      end if
         557             :   end do
         558             :
         559        6144 :   beg(ndomains) = start_domain + length
         560             :
         561        6144 :   beg_index = beg(ipe)
         562        6144 :   end_index = beg(ipe+1) - 1
         563             :
         564        6144 :   end subroutine create_work_pool
         565             :
         566           0 : end module hybrid_mod

Generated by: LCOV version 1.14