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: 2025-01-13 21:54:50 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      742656 :   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      742656 :       ithr            = omp_get_thread_num()
     148             : 
     149      742656 :       if ( TRIM(region_name) == 'serial') then
     150      371712 :          region_num_threads = 1
     151      371712 :          if ( .NOT. allocated(work_pool_horz) ) allocate(work_pool_horz(horz_num_threads,2))
     152      371712 :          call set_thread_ranges_1D ( work_pool_horz, ibeg_range, iend_range, ithr )
     153      371712 :          hybrid%ibeg = 1;          hybrid%iend = nelemd_save
     154      371712 :          hybrid%kbeg = 1;          hybrid%kend = nlev
     155      371712 :          hybrid%qbeg = 1;          hybrid%qend = qsize
     156             :       endif
     157             : 
     158      742656 :       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      742656 :       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      742656 :       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      742656 :       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      742656 :       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      742656 :       call omp_set_num_threads(region_num_threads)
     199             : 
     200             : !      hybrid%par          = par      ! relies on parallel_mod copy constructor
     201      742656 :       call copy_par(hybrid%par,par)
     202      742656 :       hybrid%nthreads     = region_num_threads
     203      742656 :       hybrid%ithr         = ithr
     204      742656 :       hybrid%masterthread = (par%masterproc .and. ithr==0)
     205             : 
     206      742656 :   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     6676272 :   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     6676272 :   if ( present(ibeg) ) then
     354      742656 :     ibeg = pybrid%ibeg
     355             :   endif
     356     6676272 :   if ( present(iend) ) then
     357      742656 :     iend = pybrid%iend
     358             :   endif
     359     6676272 :   if ( present(kbeg) ) then
     360      738816 :     kbeg = pybrid%kbeg
     361             :   endif
     362     6676272 :   if ( present(kend) ) then
     363      738816 :     kend = pybrid%kend
     364             :   endif
     365     6676272 :   if ( present(qbeg) ) then
     366     5194800 :     qbeg = pybrid%qbeg
     367             :   endif
     368     6676272 :   if ( present(qend) ) then
     369     5194800 :     qend = pybrid%qend
     370             :   endif
     371             : 
     372     6676272 :   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     6676272 :   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     6676272 :   ind = 0
     521             :   
     522    20028816 :   irange = SIZE(work_pool) 
     523    20028816 :   do i = 1, irange
     524    13352544 :     if( ind == idthread ) then
     525     6676272 :       index = i 
     526             :     endif
     527    20028816 :     ind = ind + 1
     528             :   enddo
     529     6676272 :   beg_range = work_pool(index,1)
     530     6676272 :   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     6676272 :   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