MODULE module_tiles

  USE module_configure

  INTERFACE set_tiles
    MODULE PROCEDURE set_tiles1 , set_tiles2, set_tiles3, set_tiles_once
  END INTERFACE

CONTAINS









  SUBROUTINE set_tiles1 ( grid , ids , ide , jds , jde , bdyw )

     USE module_domain, ONLY : domain
     USE module_driver_constants
     USE module_machine
     USE module_wrf_error

     IMPLICIT NONE
  
     
  
     TYPE(domain)                   , INTENT(INOUT)  :: grid
     INTEGER                        , INTENT(IN)     :: ids , ide , jds , jde , bdyw

     

     INTEGER                                :: spx, epx, spy, epy, t, tt, ts, te
     INTEGER                                :: smx, emx, smy, emy
     INTEGER                                :: ntiles , num_tiles

     CHARACTER*80              :: mess

     data_ordering : SELECT CASE ( model_data_order )
       CASE  ( DATA_ORDER_XYZ )
         spx = grid%sp31 ; epx = grid%ep31 ; spy = grid%sp32 ; epy = grid%ep32
       CASE  ( DATA_ORDER_YXZ )
         spx = grid%sp32 ; epx = grid%ep32 ; spy = grid%sp31 ; epy = grid%ep31
       CASE  ( DATA_ORDER_ZXY )
         spx = grid%sp32 ; epx = grid%ep32 ; spy = grid%sp33 ; epy = grid%ep33
       CASE  ( DATA_ORDER_ZYX )
         spx = grid%sp33 ; epx = grid%ep33 ; spy = grid%sp32 ; epy = grid%ep32
       CASE  ( DATA_ORDER_XZY )
         spx = grid%sp31 ; epx = grid%ep31 ; spy = grid%sp33 ; epy = grid%ep33
       CASE  ( DATA_ORDER_YZX )
         spx = grid%sp33 ; epx = grid%ep33 ; spy = grid%sp31 ; epy = grid%ep31
     END SELECT data_ordering

     num_tiles = 4

     IF ( num_tiles > grid%max_tiles ) THEN
       IF ( ASSOCIATED(grid%i_start) ) THEN ; DEALLOCATE( grid%i_start ) ; NULLIFY( grid%i_start ) ; ENDIF
       IF ( ASSOCIATED(grid%i_end) )   THEN ; DEALLOCATE( grid%i_end   ) ; NULLIFY( grid%i_end   ) ; ENDIF
       IF ( ASSOCIATED(grid%j_start) ) THEN ; DEALLOCATE( grid%j_start ) ; NULLIFY( grid%j_start ) ; ENDIF
       IF ( ASSOCIATED(grid%j_end) )   THEN ; DEALLOCATE( grid%j_end   ) ; NULLIFY( grid%j_end   ) ; ENDIF
       ALLOCATE(grid%i_start(num_tiles))
       ALLOCATE(grid%i_end(num_tiles))
       ALLOCATE(grid%j_start(num_tiles))
       ALLOCATE(grid%j_end(num_tiles))
       grid%max_tiles = num_tiles
     ENDIF


     IF      ( ids .ge. spx .and. ids .le. epx ) THEN
        grid%i_start(1) = ids
        grid%i_end(1)   = min( ids+bdyw-1 , epx )
        grid%j_start(1) = max( spy , jds )
        grid%j_end(1)   = min( epy , jde )
     ELSEIF  ( (ids+bdyw-1) .ge. spx .and. (ids+bdyw-1) .le. epx ) THEN
        grid%i_start(1) = max( ids , spx )
        grid%i_end(1)   = ids+bdyw-1
        grid%j_start(1) = max( spy , jds )
        grid%j_end(1)   = min( epy , jde )
     ELSE
        grid%i_start(1) = 1
        grid%i_end(1)   = -1
        grid%j_start(1) = 1
        grid%j_end(1)   = -1
     ENDIF


     IF      ( ide .ge. spx .and. ide .le. epx ) THEN
        grid%i_start(2) = max( ide-bdyw+1 , spx )
        grid%i_end(2)   = ide
        grid%j_start(2) = max( spy , jds )
        grid%j_end(2)   = min( epy , jde )
     ELSEIF  ( (ide-bdyw+1) .ge. spx .and. (ide-bdyw+1) .le. epx ) THEN
        grid%i_start(2) = ide-bdyw+1
        grid%i_end(2)   = min( ide , epx )
        grid%j_start(2) = max( spy , jds )
        grid%j_end(2)   = min( epy , jde )
     ELSE
        grid%i_start(2) = 1
        grid%i_end(2)   = -1
        grid%j_start(2) = 1
        grid%j_end(2)   = -1
     ENDIF


     IF      ( jds .ge. spy .and. jds .le. epy ) THEN
        grid%j_start(3) = jds
        grid%j_end(3)   = min( jds+bdyw-1 , epy )
        grid%i_start(3) = max( spx , ids+bdyw )
        grid%i_end(3)   = min( epx , ide-bdyw )
     ELSEIF  ( (jds+bdyw-1) .ge. spy .and. (jds+bdyw-1) .le. epy ) THEN
        grid%j_start(3) = max( jds , spy )
        grid%j_end(3)   = jds+bdyw-1
        grid%i_start(3) = max( spx , ids+bdyw )
        grid%i_end(3)   = min( epx , ide-bdyw )
     ELSE
        grid%j_start(3) = 1
        grid%j_end(3)   = -1
        grid%i_start(3) = 1
        grid%i_end(3)   = -1
     ENDIF


     IF      ( jde .ge. spy .and. jde .le. epy ) THEN
        grid%j_start(4) = max( jde-bdyw+1 , spy )
        grid%j_end(4)   = jde
        grid%i_start(4) = max( spx , ids+bdyw )
        grid%i_end(4)   = min( epx , ide-bdyw )
     ELSEIF  ( (jde-bdyw+1) .ge. spy .and. (jde-bdyw+1) .le. epy ) THEN
        grid%j_start(4) = jde-bdyw+1
        grid%j_end(4)   = min( jde , epy )
        grid%i_start(4) = max( spx , ids+bdyw )
        grid%i_end(4)   = min( epx , ide-bdyw )
     ELSE
        grid%j_start(4) = 1
        grid%j_end(4)   = -1
        grid%i_start(4) = 1
        grid%i_end(4)   = -1
     ENDIF

     grid%num_tiles = num_tiles

     RETURN
  END SUBROUTINE set_tiles1





  SUBROUTINE set_tiles_once ( zone, grid , ids , ide , jds , jde , ips , ipe , jps , jpe )
     USE module_domain, ONLY : domain, MAX_TILING_ZONES
     IMPLICIT NONE
     TYPE(domain)                   , INTENT(INOUT)  :: grid
     INTEGER                        , INTENT(IN)     :: zone
     INTEGER                        , INTENT(IN)     :: ids , ide , jds , jde
     INTEGER                        , INTENT(IN)     :: ips , ipe , jps , jpe
       
     INTEGER num_tiles, num_tiles_x, num_tiles_y
     IF ( zone .LT. 1 .OR. zone .GT. MAX_TILING_ZONES ) THEN
       CALL wrf_error_fatal3("module_tiles.b",168,&
'set_tiles_once: zone out of range, increase MAX_TILE_ZONES in module_domain_type')
     ENDIF
     IF ( .NOT. grid%tiling_latch(zone) ) THEN
       grid%tiling_latch(zone) = .TRUE.
       CALL set_tiles2 ( grid, ids, ide, jds, jde, ips, ipe, jps, jpe )
       num_tiles   = grid%num_tiles
       num_tiles_x = grid%num_tiles_x
       num_tiles_y = grid%num_tiles_y
       ALLOCATE(grid%tile_zones(zone)%i_start(num_tiles))
       ALLOCATE(grid%tile_zones(zone)%i_end(num_tiles))
       ALLOCATE(grid%tile_zones(zone)%j_start(num_tiles))
       ALLOCATE(grid%tile_zones(zone)%j_end(num_tiles))
       grid%tile_zones(zone)%i_start = grid%i_start 
       grid%tile_zones(zone)%i_end   = grid%i_end 
       grid%tile_zones(zone)%j_start = grid%j_start 
       grid%tile_zones(zone)%j_end   = grid%j_end 
       grid%tile_zones(zone)%num_tiles = num_tiles
       grid%tile_zones(zone)%num_tiles_x = num_tiles_x
       grid%tile_zones(zone)%num_tiles_y = num_tiles_y
     ELSE
       grid%i_start = grid%tile_zones(zone)%i_start
       grid%i_end   = grid%tile_zones(zone)%i_end
       grid%j_start = grid%tile_zones(zone)%j_start
       grid%j_end   = grid%tile_zones(zone)%j_end
       grid%num_tiles = grid%tile_zones(zone)%num_tiles
       grid%num_tiles_x = grid%tile_zones(zone)%num_tiles_x
       grid%num_tiles_y = grid%tile_zones(zone)%num_tiles_y
     ENDIF
  END SUBROUTINE set_tiles_once
 


  SUBROUTINE set_tiles2 ( grid , ids , ide , jds , jde , ips , ipe , jps , jpe )
     USE module_domain, ONLY : domain
     USE module_driver_constants
     USE module_machine
     USE module_wrf_error

     IMPLICIT NONE
  
     
  
     TYPE(domain)                   , INTENT(INOUT)  :: grid
     INTEGER                        , INTENT(IN)     :: ids , ide , jds , jde
     INTEGER                        , INTENT(IN)     :: ips , ipe , jps , jpe

     

     
  
     INTEGER                                :: num_tiles_x, num_tiles_y, num_tiles_inc,num_tiles
     INTEGER                                :: tile_strategy,tile_strategy_spec
     INTEGER                                :: tile_sz_x, tile_sz_y
     INTEGER                                :: spx, epx, spy, epy, t, tt, ts, te
     INTEGER                                :: smx, emx, smy, emy
     INTEGER                                :: ntiles
     INTEGER                                :: one
     INTEGER                                :: nt
     CHARACTER*255              :: mess
     CHARACTER*255              :: envval
     INTEGER                   :: tnum_tiles, istat
     LOGICAL                   :: verbose 

     data_ordering : SELECT CASE ( model_data_order )
       CASE  ( DATA_ORDER_XYZ )
         spx = grid%sp31 ; epx = grid%ep31 ; spy = grid%sp32 ; epy = grid%ep32
         smx = grid%sm31 ; emx = grid%em31 ; smy = grid%sm32 ; emy = grid%em32
       CASE  ( DATA_ORDER_YXZ )
         spx = grid%sp32 ; epx = grid%ep32 ; spy = grid%sp31 ; epy = grid%ep31
         smx = grid%sm32 ; emx = grid%em32 ; smy = grid%sm31 ; emy = grid%em31
       CASE  ( DATA_ORDER_ZXY )
         spx = grid%sp32 ; epx = grid%ep32 ; spy = grid%sp33 ; epy = grid%ep33
         smx = grid%sm32 ; emx = grid%em32 ; smy = grid%sm33 ; emy = grid%em33
       CASE  ( DATA_ORDER_ZYX )
         spx = grid%sp33 ; epx = grid%ep33 ; spy = grid%sp32 ; epy = grid%ep32
         smx = grid%sm33 ; emx = grid%em33 ; smy = grid%sm32 ; emy = grid%em32
       CASE  ( DATA_ORDER_XZY )
         spx = grid%sp31 ; epx = grid%ep31 ; spy = grid%sp33 ; epy = grid%ep33
         smx = grid%sm31 ; emx = grid%em31 ; smy = grid%sm33 ; emy = grid%em33
       CASE  ( DATA_ORDER_YZX )
         spx = grid%sp33 ; epx = grid%ep33 ; spy = grid%sp31 ; epy = grid%ep31
         smx = grid%sm33 ; emx = grid%em33 ; smy = grid%sm31 ; emy = grid%em31
     END SELECT data_ordering

     IF( ips < smx )THEN;WRITE(mess,'(3A4)')'ips','<','smx';CALL WRF_ERROR_FATAL(mess);ENDIF
     IF( ipe > emx )THEN;WRITE(mess,'(3A4)')'ipe','>','emx';CALL WRF_ERROR_FATAL(mess);ENDIF
     IF( jps < smy )THEN;WRITE(mess,'(3A4)')'jps','<','smy';CALL WRF_ERROR_FATAL(mess);ENDIF
     IF( jpe > emy )THEN;WRITE(mess,'(3A4)')'jpe','>','emy';CALL WRF_ERROR_FATAL(mess);ENDIF

     
     
     
     
     
     
     

     verbose = .false.
     IF ( grid%num_tiles_spec .EQ. 0 ) THEN
       verbose = .true.
       CALL nl_get_numtiles( 1, num_tiles )
       IF ( num_tiles .EQ. 1 ) THEN
         num_tiles = 1
         CALL get_environment_variable("WRF_NUM_TILES",envval, status=istat)
         IF ( envval .NE. "" .and. istat .eq. 0) THEN
           READ (envval,*) tnum_tiles
           IF ( tnum_tiles .GT. 0 ) THEN
             num_tiles=tnum_tiles
             WRITE(mess,'("WRF NUMBER OF TILES FROM ENV WRF_NUM_TILES = ",I3)')num_tiles
             CALL WRF_MESSAGE ( mess )
           ENDIF
         ENDIF
       ENDIF

       CALL nl_get_tile_sz_x( 1, tile_sz_x )
       CALL nl_get_tile_sz_y( 1, tile_sz_y )
       CALL nl_get_tile_strategy( 1, tile_strategy_spec )
       CALL nl_get_numtiles_inc( 1, num_tiles_inc )
       CALL nl_get_numtiles_x( 1, num_tiles_x )
       CALL nl_get_numtiles_y( 1, num_tiles_y )
       IF ( num_tiles_x .EQ. 0 ) THEN
         CALL get_environment_variable ("WRF_NUM_TILES_X",envval, status=istat)
         IF ( envval .NE. "" .and. istat .eq. 0) THEN
           READ (envval,*) tnum_tiles
           IF ( tnum_tiles .GT. 0 ) THEN
             num_tiles_x=tnum_tiles
             WRITE(mess,'("WRF NUMBER OF TILES X FROM ENV WRF_NUM_TILES_X = ",I3)')num_tiles_x
             CALL WRF_MESSAGE ( mess )
           ENDIF
         ENDIF
       ENDIF

       IF ( num_tiles_y .EQ. 0 ) THEN
         CALL get_environment_variable ("WRF_NUM_TILES_Y",envval, status=istat)
         IF ( envval .NE. "" .and. istat .eq. 0) THEN
           READ (envval,*) tnum_tiles
           IF ( tnum_tiles .GT. 0 ) THEN
             num_tiles_y=tnum_tiles
             WRITE(mess,'("WRF NUMBER OF TILES Y FROM ENV WRF_NUM_TILES_Y = ",I3)')num_tiles_y
             CALL WRF_MESSAGE ( mess )
           ENDIF
         ENDIF
       ENDIF

       IF ( num_tiles_inc .EQ. 0 ) THEN
         CALL get_environment_variable ("WRF_NUM_TILES_INC",envval, status=istat)
         IF ( envval .NE. "" .and. istat .eq. 0) THEN
           READ (envval,*) tnum_tiles
           IF ( tnum_tiles .GT. 0 ) THEN
             num_tiles_inc=tnum_tiles
             WRITE(mess,'("WRF NUMBER OF TILES INCREMENT FROM ENV WRF_NUM_TILES_INC = ",I3)')num_tiles_inc
             CALL WRF_MESSAGE ( mess )
           ENDIF
         ENDIF
       ENDIF
       num_tiles_inc=max( num_tiles_inc , 1)
       IF ( tile_strategy_spec == TILE_NONE) then 
          tile_strategy=TILE_Y
          WRITE(mess,*)'Tile Strategy is not specified. Assuming 1D-Y'
          CALL WRF_MESSAGE ( mess )
          IF ( num_tiles > (epy-spy+1)/1 .and. num_tiles_x == 0 .and. num_tiles_y == 0) THEN 
            num_tiles_x=1
            num_tiles_y=(epy-spy+1)/1
            DO WHILE (num_tiles_x*num_tiles_inc*num_tiles_y < num_tiles)
               num_tiles_x=num_tiles_x+1
            END DO
          num_tiles_x=num_tiles_x*num_tiles_inc
          WRITE(mess,'("Total number of tiles is too big for 1D-Y tiling. Going 2D. New tiling is ",I3,"x",I3)') &
                        num_tiles_x,num_tiles_y
          CALL WRF_MESSAGE ( mess )
          tile_strategy=TILE_XY
         ENDIF
       ELSE
          tile_strategy = tile_strategy_spec
       ENDIF

       IF ( tile_sz_x >= 1 .and. tile_sz_y >= 1 ) THEN
        
          num_tiles_x = (epx-spx+1) / tile_sz_x
          if ( tile_sz_x*num_tiles_x < epx-spx+1 ) num_tiles_x = num_tiles_x + 1
          num_tiles_y = (epy-spy+1) / tile_sz_y
          if ( tile_sz_y*num_tiles_y < epy-spy+1 ) num_tiles_y = num_tiles_y + 1
          num_tiles = num_tiles_x * num_tiles_y
       ELSE
         IF ( num_tiles_x >= 1 .or. num_tiles_y >= 1 ) THEN
        
           IF ( num_tiles_x >= 1 .and. num_tiles_y >= 1 ) THEN
              
               num_tiles=num_tiles_x*num_tiles_y;
           ELSE IF ( num_tiles_x >= 1 ) THEN
               num_tiles_y=num_tiles/num_tiles_x;
           ELSE 
               num_tiles_x=num_tiles/num_tiles_y;
           ENDIF
         ELSE
           IF      ( tile_strategy == TILE_X ) THEN
             num_tiles_x = num_tiles
             num_tiles_y = 1
           ELSE IF ( tile_strategy == TILE_Y ) THEN
             num_tiles_x = 1
             num_tiles_y = num_tiles
           ELSE 
             one = 1
             call least_aspect( num_tiles, one, one, num_tiles_y, num_tiles_x )
           ENDIF
         ENDIF
       ENDIF

       num_tiles=max( num_tiles , 1)
       num_tiles_x=max( num_tiles_x , 1)
       num_tiles_y=max( num_tiles_y , 1)
       grid%num_tiles_spec = num_tiles
       grid%num_tiles_x = num_tiles_x
       grid%num_tiles_y = num_tiles_y
     ENDIF

     num_tiles   = grid%num_tiles_spec
     num_tiles_x = grid%num_tiles_x
     num_tiles_y = grid%num_tiles_y

     IF ( num_tiles > grid%max_tiles ) THEN
       IF ( ASSOCIATED(grid%i_start) ) THEN ; DEALLOCATE( grid%i_start ) ; NULLIFY( grid%i_start ) ; ENDIF
       IF ( ASSOCIATED(grid%i_end) )   THEN ; DEALLOCATE( grid%i_end   ) ; NULLIFY( grid%i_end   ) ; ENDIF
       IF ( ASSOCIATED(grid%j_start) ) THEN ; DEALLOCATE( grid%j_start ) ; NULLIFY( grid%j_start ) ; ENDIF
       IF ( ASSOCIATED(grid%j_end) )   THEN ; DEALLOCATE( grid%j_end   ) ; NULLIFY( grid%j_end   ) ; ENDIF
       ALLOCATE(grid%i_start(num_tiles))
       ALLOCATE(grid%i_end(num_tiles))
       ALLOCATE(grid%j_start(num_tiles))
       ALLOCATE(grid%j_end(num_tiles))
       grid%max_tiles = num_tiles
     ENDIF

     nt = 1
     DO t = 0, num_tiles-1

       
        ntiles = t / num_tiles_x
        CALL region_bounds( spy, epy,                                  &
                            num_tiles_y, ntiles,                       &
                            ts, te )
        
        IF ( ts .LE. te ) THEN  







          IF ( jps .lt. spy .and. ts .eq. spy ) ts = jps ;
          IF ( jpe .gt. epy .and. te .eq. epy ) te = jpe ;

          grid%j_start(nt) = max ( ts , jds )
          grid%j_end(nt)   = min ( te , jde )

          
          ntiles = mod(t,num_tiles_x)
          CALL region_bounds( spx, epx,                                  &
                              num_tiles_x, ntiles,                       &
                              ts, te )
          IF ( ts .LE. te ) THEN  
            IF ( ips .lt. spx .and. ts .eq. spx ) ts = ips ;
            IF ( ipe .gt. epx .and. te .eq. epx ) te = ipe ;

            grid%i_start(nt) = max ( ts , ids )
            grid%i_end(nt)   = min ( te , ide )
            IF ( verbose ) THEN
              WRITE(mess,'("WRF TILE ",I3," IS ",I6," IE ",I6," JS ",I6," JE ",I6)') &
                        nt,grid%i_start(nt),grid%i_end(nt),grid%j_start(nt),grid%j_end(nt)
              CALL WRF_MESSAGE ( mess )
            ENDIF
            nt = nt + 1
          ENDIF
        ENDIF
     END DO
     num_tiles = nt-1
     IF ( verbose ) THEN
       WRITE(mess,'("WRF NUMBER OF TILES = ",I3)')num_tiles
       CALL WRF_MESSAGE ( mess )
     ENDIF
     grid%num_tiles = num_tiles

     RETURN
  END SUBROUTINE set_tiles2






  SUBROUTINE set_tiles3 ( grid , imask, ims, ime, jms, jme, ips, ipe, jps, jpe )
     USE module_domain, ONLY : domain
     USE module_driver_constants
     USE module_machine
     USE module_wrf_error

     IMPLICIT NONE
  
     
  
     TYPE(domain)                   , INTENT(INOUT)  :: grid
     INTEGER                        , INTENT(IN)     :: ims , ime , jms , jme
     INTEGER                        , INTENT(IN)     :: ips , ipe , jps , jpe
     INTEGER, DIMENSION(ims:ime,jms:jme), INTENT(IN) :: imask
     INTEGER                :: num_tiles
     INTEGER, DIMENSION(50) :: i_start, i_end, j_start, j_end

     

     
     INTEGER nt
     CHARACTER*80              :: mess

     CALL set_tiles_masked ( imask, ims, ime, jms, jme, ips, ipe, jps, jpe, &
                             num_tiles, i_start, i_end, j_start, j_end )

     IF ( num_tiles > grid%max_tiles ) THEN
       IF ( ASSOCIATED(grid%i_start) ) THEN ; DEALLOCATE( grid%i_start ) ; NULLIFY( grid%i_start ) ; ENDIF
       IF ( ASSOCIATED(grid%i_end) )   THEN ; DEALLOCATE( grid%i_end   ) ; NULLIFY( grid%i_end   ) ; ENDIF
       IF ( ASSOCIATED(grid%j_start) ) THEN ; DEALLOCATE( grid%j_start ) ; NULLIFY( grid%j_start ) ; ENDIF
       IF ( ASSOCIATED(grid%j_end) )   THEN ; DEALLOCATE( grid%j_end   ) ; NULLIFY( grid%j_end   ) ; ENDIF
       ALLOCATE(grid%i_start(num_tiles))
       ALLOCATE(grid%i_end(num_tiles))
       ALLOCATE(grid%j_start(num_tiles))
       ALLOCATE(grid%j_end(num_tiles))
       grid%max_tiles = num_tiles
     ENDIF
     grid%num_tiles = num_tiles
     grid%i_start(1:num_tiles) = i_start(1:num_tiles)
     grid%i_end(1:num_tiles)   = i_end(1:num_tiles)
     grid%j_start(1:num_tiles) = j_start(1:num_tiles)
     grid%j_end(1:num_tiles)   = j_end(1:num_tiles)
     DO nt = 1, num_tiles
        WRITE(mess,'("WRF TILE ",I3," IS ",I6," IE ",I6," JS ",I6," JE ",I6)') &
                      nt,grid%i_start(nt),grid%i_end(nt),grid%j_start(nt),grid%j_end(nt)
        CALL wrf_debug ( 1, mess )
     ENDDO
     WRITE(mess,'("set_tiles3: NUMBER OF TILES = ",I3)')num_tiles
     CALL wrf_debug ( 1, mess )

     RETURN
  END SUBROUTINE set_tiles3

  SUBROUTINE set_tiles_masked ( imask, ims, ime, jms, jme, ips, ipe, jps, jpe, &
                                num_tiles, istarts, iends, jstarts, jends )

      IMPLICIT NONE

      

      INTEGER                        , INTENT(IN)     :: ims , ime , jms , jme
      INTEGER, DIMENSION(ims:ime,jms:jme), INTENT(IN) :: imask
      INTEGER                        , INTENT(IN)     :: ips , ipe , jps , jpe
      INTEGER                        , INTENT(OUT)    :: num_tiles
      INTEGER, DIMENSION(*)          , INTENT(OUT)    :: istarts, iends
      INTEGER, DIMENSION(*)          , INTENT(OUT)    :: jstarts, jends

      

      
      CHARACTER*80              :: mess
      INTEGER :: i, j, ir, jr
      INTEGER :: imaskcopy(ips:ipe,jps:jpe)    

      imaskcopy = imask(ips:ipe,jps:jpe)
      num_tiles = 0
      
      DO WHILE (ANY(imaskcopy == 1))
        DO j = jps,jpe
          DO i = ips,ipe
            
            IF ( imaskcopy(i,j) == 1 ) THEN
              num_tiles = num_tiles + 1
              istarts(num_tiles) = i
              iends(num_tiles)   = i
              jstarts(num_tiles) = j
              jends(num_tiles)   = j
              
              imaskcopy(i,j) = 0
              
              DO ir = istarts(num_tiles)+1,ipe
                IF ( imaskcopy(ir,j) == 1 ) THEN
                  iends(num_tiles) = ir
                  
                  imaskcopy(ir,j) = 0
                ELSE
                  EXIT
                ENDIF
              ENDDO
              
              DO jr = jstarts(num_tiles)+1,jpe
                IF (ALL(imaskcopy(istarts(num_tiles):iends(num_tiles),jr) == 1)) THEN
                  jends(num_tiles) = jr
                  
                  imaskcopy(istarts(num_tiles):iends(num_tiles),jr) = 0
                ELSE
                  EXIT
                ENDIF
              ENDDO
            ENDIF   
          ENDDO
        ENDDO
      ENDDO
      RETURN
  END SUBROUTINE set_tiles_masked

  
  SUBROUTINE init_module_tiles
  END SUBROUTINE init_module_tiles

END MODULE module_tiles