LCOV - code coverage report
Current view: top level - src - mo_smi_drought_evaluation.f90 (source / functions) Hit Total Coverage
Test: SMI coverage Lines: 178 227 78.4 %
Date: 2024-04-30 09:16:25 Functions: 4 5 80.0 %

          Line data    Source code
       1             : !> \file mo_smi_drought_evaluation.f90
       2             : !> \brief   \copybrief mo_smi_drought_evaluation
       3             : !> \details \copydetails mo_smi_drought_evaluation
       4             : 
       5             : !> \brief drought evaluation for SMI
       6             : !> \copyright Copyright 2005-\today, the CHS Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
       7             : !! SMI is released under the LGPLv3+ license \license_note
       8             : module mo_smi_drought_evaluation
       9             : 
      10             :   USE mo_kind,   only : i4, sp, dp
      11             : 
      12             :   IMPLICIT NONE
      13             : 
      14             :   PRIVATE
      15             : 
      16             :   PUBLIC :: droughtIndicator
      17             :   PUBLIC :: ClusterEvolution
      18             :   PUBLIC :: ClusterStats
      19             :   PUBLIC :: calSAD
      20             : 
      21             :   ! ------------------------------------------------------------------
      22             : 
      23             : CONTAINS
      24             : 
      25             :   ! ------------------------------------------------------------------
      26             : 
      27             : !> \brief Find drought clusters and statistics
      28             : !!        1) truncate SMIp < SMI_th
      29             : !> \author Luis Samaniego
      30             : !> \date 28.02.2011
      31             : !> \date 05.10.2011
      32           1 : subroutine droughtIndicator( SMI, mask, SMI_thld, cellCoor , SMIc)
      33             : 
      34             :   use mo_constants,     only : nodata_sp, nodata_i4
      35             :   use mo_utils,         only : lesserequal, notequal
      36             : 
      37             :   implicit none
      38             : 
      39             :   ! input variable
      40             :   real(sp),    dimension(:,:),                intent(in)  :: SMI
      41             :   logical,     dimension(:,:),                intent(in)  :: mask
      42             :   real(sp),                                   intent(in)  :: SMI_thld
      43             :   integer(i4), dimension(:,:), allocatable,   intent(out) :: cellCoor
      44             :   integer(i4), dimension(:,:,:), allocatable, intent(out) :: SMIc       ! Drought indicator
      45             : 
      46             :   ! local variables
      47             :   real(sp), dimension(size(mask, dim=1),&
      48           2 :                       size(mask, dim=2))        :: dummy_2d_sp
      49             :   integer(i4)                                   :: i, j, m, k
      50             :   integer(i4)                                   :: nrows
      51             :   integer(i4)                                   :: ncols
      52             :   integer(i4)                                   :: nMonths
      53             : 
      54             :   ! initialize
      55           1 :   nrows   = size( mask, 1 )
      56           1 :   ncols   = size( mask, 2 )
      57           1 :   nMonths = size( SMI,  2 )
      58             :   !
      59           1 :   print *, 'Threshold for drought identification: ', SMI_thld
      60           5 :   allocate ( SMIc( nrows, ncols, nMonths) )
      61             : 
      62         361 :   do m = 1, nMonths
      63         360 :      dummy_2d_sp = unpack(SMI(:,m), mask, nodata_sp)
      64             :      ! filter for possible error within domain
      65             :      ! where (SMI(:,:,m) .le. SMI_thld .and. SMI(:,:,m) .ne. nodata_sp )
      66       72361 :      where ( (lesserequal(dummy_2d_sp, SMI_thld)) .and. (notequal(dummy_2d_sp, nodata_sp)) )
      67             :         SMIc(:,:,m) = 1
      68             :      elsewhere ( notequal(dummy_2d_sp, nodata_sp) )
      69             :         SMIc(:,:,m) = 0
      70             :      elsewhere
      71             :         SMIc(:,:,m) = nodata_i4
      72             :      end where
      73             :   end do
      74             : 
      75             :   !
      76          43 :   allocate (cellCoor( count(mask),2 ))
      77           1 :   k = 0
      78           6 :   do j=1,ncols
      79          41 :      do i=1,nrows
      80          40 :         if ( mask(i,j)) then
      81          22 :            k = k + 1
      82          22 :            cellCoor(k,1) = i
      83          22 :            cellCoor(k,2) = j
      84             :            ! if (k==7645.or.k==2479) print*, i,j,k
      85             :         end if
      86             :      end do
      87             :   end do
      88             :   !
      89           1 : end subroutine droughtIndicator
      90             : 
      91             : !> \brief cluster drought clusters in space and time
      92             : !> \date developed in Budapest, 10-11.03.2011
      93           1 : subroutine ClusterEvolution( SMIc, nrows, ncols, nMonths, nCells, cellCoor, nCellInter, thCellClus)
      94             : 
      95             :   use mo_orderpack,     only : sort
      96             :   use mo_constants,     only : nodata_i4
      97             :   use mo_smi_write,     only : idCluster, &
      98             :                                shortCnoList, &
      99             :                                nClusters
     100             : 
     101             : 
     102             :  implicit none
     103             : 
     104             :   ! input variables
     105             :   integer(i4), dimension(:,:,:),            intent(inout) :: SMIc     ! Drought indicator
     106             :   integer(i4),                              intent(in)    :: nrows
     107             :   integer(i4),                              intent(in)    :: ncols
     108             :   integer(i4),                              intent(in)    :: nMonths
     109             :   integer(i4),                              intent(in)    :: nCells   ! number of effective cells
     110             :   integer(i4), dimension(:,:), allocatable, intent(in)    :: cellCoor
     111             :   integer(i4),                              intent(in)    :: thCellClus ! treshold  for cluster formation in space
     112             :   integer(i4),                              intent(in)    :: nCellInter ! number cells for joining clusters in time
     113             : 
     114             : 
     115             :   ! local variables
     116             :   integer(i4)                              :: i, j, t
     117           1 :   integer(i4), dimension(:),   allocatable :: nC
     118             :   integer(i4), parameter                   :: factor = 1000
     119             :   integer(i4)                              :: ncInter
     120           1 :   integer(i4), dimension(:,:), allocatable :: cno
     121           1 :   integer(i4), dimension(:),   allocatable :: cnoList
     122           1 :   integer(i4), dimension(:),   allocatable :: vec
     123             :   integer(i4)                              :: maxNc, nTotal, idRep
     124           1 :   integer(i4), dimension(:,:), allocatable :: idCnew
     125             : 
     126             : 
     127           5 :   if (.not. allocated(idCluster) )  allocate   (idCluster(nrows, ncols, nMonths))
     128           3 :   if (.not. allocated(nC) )         allocate   (nC(nMonths))
     129             :   if ( allocated(cno) )             deallocate (cno, vec, cnoList)
     130           4 :   if (.not. allocated(idCnew))      allocate   (idCnew(nrows, ncols))
     131             : 
     132             :   ! ---------------------------------------------
     133             :   ! CLUSTERING IN SPACE and remove small clusters
     134             :   ! ---------------------------------------------
     135         361 :   do t=1,nMonths
     136       14760 :      if ( count(SMIc(:,:,t) == 1) < thCellClus) then
     137         289 :         nC(t) = 0
     138       11849 :         idCluster(:,:,t) = nodata_i4
     139             :         cycle
     140             :      end if
     141          72 :      call findClusters (cellCoor, thCellClus, t, idCluster(:,:,t), nC(t), nrows, ncols, nCells, SMIc)
     142             :      !print*, 'Finding clusters time :', t, nC(t)
     143             :   end do
     144           1 :   print*, 'Clusters in space done ...'
     145             :   !
     146             :   ! maximum number of clusters at all time steps
     147         361 :   maxNc = maxval(nC(:))
     148           1 :   nTotal = nMonths*maxNc
     149           7 :   allocate ( cno(nMonths,maxNc), vec(nTotal), cnoList(nTotal) )
     150         362 :   cno = -9
     151             :   !
     152             :   ! set unique cluster numbers and store them
     153             :   ! NOTE
     154             :   !      e.g. month*factor + running nr.,
     155             :   !           5*1000+1 = 5001              => fisrt cluster in 5th month
     156             :   !
     157         361 :   do t=1,nMonths
     158         360 :      if (nC(t) == 0) cycle
     159         139 :      do i=1, nC(t)
     160          69 :         cno(t,i) = t*factor + i
     161        3189 :         where ( idCluster(:,:,t) == i ) idCluster(:,:,t) = cno(t,i)
     162             :      end do
     163             :   end do
     164             :   ! ---------------------------------
     165             :   ! FIND CLUSTERS IN TIME
     166             :   ! determine intersection sets, join
     167             :   ! ---------------------------------
     168         360 :   do t=2,nMonths
     169         428 :      do i=1,nC(t)
     170          68 :         if (cno(t,i) == -9) cycle
     171         477 :         do j=1,nC(t-1)
     172          50 :            if (cno(t-1,j) == -9) cycle
     173        2050 :            ncInter = count ( idCluster(:,:,t) == cno(t,i) .and. idCluster(:,:,t-1) == cno(t-1,j) )
     174         118 :            if ( ncInter >= nCellInter ) then
     175             :               ! renumber all from 1 to t
     176           0 :               where ( idCluster(:,:,1:t) == cno(t-1,j) ) idCluster(:,:,1:t) =  cno(t,i)
     177             :               ! rename cluster id from cno
     178           0 :               where ( cno(1:t,:) == cno(t-1,j) ) cno(1:t,:) = cno(t,i)
     179             :            end if
     180             :         end do
     181             :      end do
     182             :   end do
     183           1 :   print*, 'Clustering in time done ...'
     184             :   ! --------------------------
     185             :   ! COMPILE CLUSTER IDS + list
     186             :   ! --------------------------
     187         361 :   vec = -9
     188         362 :   cnoList = pack (cno, mask = cno > 0, vector=vec)
     189             :   !
     190             :   ! 1. sort
     191           1 :   idRep = -9
     192         361 :   forall(i=1:nTotal) vec(i) = i
     193             :   ! call SVIGN(nTotal,cnoList,cnoList)
     194           1 :   call sort(cnoList)
     195             :   ! 2.  remove repeated values
     196         360 :   do i=nTotal, 2,-1
     197         359 :      if (cnoList(i) < 0 ) cycle
     198          69 :      if (.not. cnoList(i-1) == cnoList(i) ) then
     199          69 :         if (idRep > 0) idRep = -9
     200             :         cycle
     201             :      end if
     202           0 :      if (idRep == -9) idRep = cnoList(i)
     203         291 :      cnoList(i) = -9
     204             :   end do
     205             :   ! call SVIGN(nTotal,cnoList,cnoList)
     206           1 :   call sort(cnoList)
     207             :   !
     208             :   ! 3. final consolidated list
     209         361 :   nClusters = count(cnoList > 0)
     210           3 :   allocate ( shortCnoList(nClusters) )
     211         361 :   shortCnoList = pack(cnoList, mask = cnoList > 0)
     212             :   !
     213           1 :   print*, '# Consolidated Clusters :', nClusters
     214             :   !
     215           1 :   deallocate(vec, nC, cnoList, cno )
     216           1 : end subroutine ClusterEvolution
     217             : 
     218             : !> \brief SVAT statistics
     219           1 : subroutine ClusterStats( SMI, mask, nrows, ncols, nMonths, nCells, SMI_thld )
     220             : 
     221             :   use mo_orderpack,     only : sort_index
     222             :   use mo_constants,     only: nodata_sp
     223             :   use mo_smi_write,     only: aDA, aDD, TDM, DTMagEvol, DAreaEvol,     &
     224             :                               nClusters, idCluster, shortCnoList, &
     225             :                               dASevol, nBasins, nEvents, eIdPerm, eventId
     226             : 
     227             :   implicit none
     228             : 
     229             :   ! input variables
     230             : 
     231             :   real(sp), dimension(:,:),    intent(in) :: SMI
     232             :   logical,  dimension(:,:),    intent(in) :: mask
     233             :   integer(i4),                 intent(in) :: nrows
     234             :   integer(i4),                 intent(in) :: ncols
     235             :   integer(i4),                 intent(in) :: nMonths
     236             :   integer(i4),                 intent(in) :: nCells      ! number of effective cell
     237             : !  integer(i4), dimension(:,:), intent(in) :: Basin_Id    ! IDs for basinwise drought analysiss
     238             :   real(sp),                    intent(in) :: SMI_thld    ! SMI threshold for clustering
     239             : 
     240             :   ! local variables
     241           2 :   real(sp), dimension(nrows, ncols)                         :: dummy_2d_sp
     242             :   integer(i4)                                               :: ic, i
     243             :   integer(i4)                                               :: t
     244           1 :   integer(i4) , dimension(:), allocatable                   :: counterA
     245           1 :   integer(i4) , dimension(:,:), allocatable                 :: aDDG
     246           1 :   real(dp) , dimension(:,:), allocatable                    :: mSev
     247             : 
     248             :   integer(i4)                                               :: eCounter
     249             : 
     250           1 :   integer(i4), dimension(:), allocatable                    :: vec
     251             : 
     252           4 :   allocate ( aDDG     (nrows, ncols) )
     253           4 :   allocate ( DAreaEvol(nMonths,nClusters) )
     254           3 :   allocate ( DTMagEvol(nMonths,nClusters) )
     255           3 :   allocate ( aDD      (nClusters)   )
     256           2 :   allocate ( aDA      (nClusters)   )
     257           3 :   allocate ( counterA (nClusters)   )
     258           2 :   allocate ( TDM      (nClusters)   )
     259           4 :   allocate ( dASevol  (nMonths,2,nBasins+1)   )       ! (area, severity) whole Germany => nBasins+1
     260           4 :   allocate ( mSev     (nrows, ncols) )      ! mean  severity
     261             :   !
     262       24910 :   DAreaEvol = 0.0_dp
     263       24910 :   DTMagEvol = 0.0_dp
     264          70 :   counterA  = 0
     265          70 :   do ic = 1, nClusters
     266             :      !print*, 'Statistics of cluster : 'shortCnoList(ic)
     267        2829 :      aDDG = 0
     268       24909 :      do t = 1, nMonths
     269     1018440 :         where (idCluster(:,:,t) == shortCnoList(ic) )
     270             :            ! duration
     271             :            aDDG = aDDG + 1
     272             :         end where
     273             :         !
     274             :         !  drought area evolution
     275     1018440 :         DAreaEvol(t,ic) =  real( count(idCluster(:,:,t) == shortCnoList(ic) ), dp) / real(nCells, dp)
     276       24840 :         if (DAreaEvol(t,ic) > 0.0_dp) counterA(ic) = counterA(ic) + 1
     277             : 
     278             :         ! total magnitude (NEW  SM_tr -SMI) !!!
     279       24840 :         dummy_2d_sp = unpack(SMI(:,t), mask, nodata_sp)
     280     1018509 :         DTMagEvol(t,ic) = sum( (SMI_thld - dummy_2d_sp), mask = idCluster(:,:,t) == shortCnoList(ic) )
     281             :      end do
     282             : 
     283             :      ! AVERAGE (MEAN) DURATION
     284        5658 :      aDD(ic) = real( sum(aDDG, mask = aDDG > 0),dp ) / real( count(aDDG > 0), dp)
     285             : 
     286             :      ! TOTAL MAGNITUD (sum over space and time of SMI over all
     287             :      !                 cells afected by the event ic )
     288       24910 :      TDM(ic) = sum( DTMagEvol(:,ic) )
     289             :   end do
     290             :   !  AVERAGE (MEAN) DROUGHT AREA per cluster event
     291       24911 :   aDA = sum(DAreaEvol, DIM=1) / real(counterA, dp)
     292             :   !
     293             :   ! (NEW) Time evolution of the area and monthly severity
     294             :   ! whole domain
     295         361 :   do t = 1, nMonths
     296       14760 :      dASevol(t,1,nBasins+1) = real( count( idCluster(:,:,t) > 0 ), dp ) / real( nCells, dp) * 1e2_dp
     297         360 :      dummy_2d_sp = unpack(SMI(:,t), mask, nodata_sp)
     298       14760 :      where (idCluster(:,:,t) > 0 )
     299             :         mSev(:,:) = 1.0_dp - real(dummy_2d_sp, dp)
     300             :      end where
     301       14761 :      dASevol(t,2,nBasins+1) = sum( mSev(:,:), mask = idCluster(:,:,t) > 0 ) / real( nCells, dp)
     302             :   end do
     303             :   ! ! evolution at basin wise
     304             :   ! do t = 1, nMonths
     305             :   !   do i = 1, nBasins
     306             :   !     dASevol(t,1,i) = real ( count( idCluster(:,:,t) > 0 .and.  Basin_Id(:,:) == i  ), dp) &
     307             :   !                      / real(count(Basin_Id(:,:) == i), dp)  * 1e2_dp
     308             :   !     where (idCluster(:,:,t) > 0 .and.  Basin_Id(:,:) == i )
     309             :   !        mSev(:,:) = 1.0_dp - SMI(:,:,t)
     310             :   !     end where
     311             :   !     dASevol(t,2,i) = sum( mSev(:,:), mask = idCluster(:,:,t) > 0 .and. Basin_Id(:,:) == i ) &
     312             :   !                     / real(count(Basin_Id(:,:) == i), dp)
     313             :   !   end do
     314             :   ! end do
     315             : 
     316             : 
     317             :      !!! ORIGINALLY in SAD anaylysis
     318       24910 :      nEvents = count (DAreaEvol .gt. 0.0_dp )
     319           3 :      allocate (  eIdPerm   (nEvents)    )
     320           3 :      allocate (  eventId   (nEvents, 3) )                !  dim1: running Nr.
     321             :                                                          !  dim2: 1 == cluster Id,
     322             :                                                          !        2 == month of ocurrence,
     323             :                                                          !        3 == number of cells
     324             : 
     325             :      ! keep event identification
     326           1 :      eCounter = 0
     327          70 :      do ic = 1,  nClusters
     328       24910 :         do t = 1, nMonths
     329       24909 :            if (DAreaEvol(t,ic) > 0.0_dp ) then
     330          69 :               eCounter = eCounter + 1
     331          69 :               eventId(eCounter,1) = shortCnoList(ic)
     332          69 :               eventId(eCounter,2) = t
     333        2829 :               eventId(eCounter,3) = count( idCluster(:,:,t) == shortCnoList(ic) )
     334             :            end if
     335             :         end do
     336             :      end do
     337             :      ! sort event in order of area magnitude
     338          70 :      forall(i=1:nEvents) eIdPerm(i) = i
     339           3 :      allocate (vec(nEvents))
     340             :      ! call SVIGP (nEvents, eventId(:,3), vec, eIdPerm)
     341          71 :      eIdPerm = sort_index( eventID(:,3) )
     342           1 :      deallocate (vec)
     343             : 
     344           1 :      print*, 'Cluster statistics were estimated ... '
     345           1 :      deallocate ( counterA, aDDG, mSev )
     346           1 : end subroutine ClusterStats
     347             : 
     348             : !> \brief SAD analysis
     349           0 : subroutine calSAD(SMI, mask, iDur, nrows, ncols, nMonths, nCells, deltaArea, cellsize)
     350             : 
     351             :   use mo_orderpack,     only : sort      !, sort_index
     352             :   use mo_percentile,    only : percentile
     353             :   use mo_constants,     only : nodata_dp
     354             :   use mo_smi_write,     only : shortCnoList, &
     355             :                                nInterArea, nEvents, nClusters,  idCluster, &
     356             :                                SAD, SADperc, DAreaEvol, severity, nDsteps, &
     357             :                                durList, eventId, eIdPerm, &
     358             :                                nLargerEvents, nQProp, QProp
     359             : 
     360             :   implicit none
     361             : 
     362             :   ! input variable
     363             :   real(sp),    dimension(:,:), intent(in) :: SMI
     364             :   logical,     dimension(:,:), intent(in) :: mask
     365             :   integer(i4),                 intent(in) :: iDur
     366             :   integer(i4),                 intent(in) :: nrows
     367             :   integer(i4),                 intent(in) :: ncols
     368             :   integer(i4),                 intent(in) :: nMonths
     369             :   integer(i4),                 intent(in) :: nCells  ! number of effective cells
     370             :   integer(i4),                 intent(in) :: deltaArea  ! number of cells per area interval
     371             :   real(sp),                    intent(in) :: cellsize
     372             : 
     373             :   ! local variable
     374           0 :   real(dp),    dimension(nrows,ncols, nMonths)        :: SMI_unpack
     375             :   integer(i4)                                         :: t, i, k
     376             : !  integer(i4)                                         :: ic
     377             :   integer(i4)                                         :: iDc
     378             :   integer(i4)                                         :: d
     379             :   integer(i4)                                         :: ms, me
     380             :   integer(i4)                                         :: ke
     381             :   integer(i4)                                         :: eC
     382             :   integer(i4)                                         :: eCounter
     383             : 
     384             :   integer(i4)                                         :: ncic
     385             :   integer(i4)                                         :: nIntA
     386           0 :   real(dp), dimension(:), allocatable                 :: sevP
     387             :   !
     388             :   integer(i4)                                         :: nObs
     389             : !  integer(i4), dimension(:), allocatable              :: vec
     390             :   !
     391           0 :   do i = 1, size(SMI,2)
     392           0 :      SMI_unpack(:,:,i) = unpack(real(SMI(:,i), dp), mask, nodata_dp)
     393             :   end do
     394             : 
     395           0 :   if (iDur == 1) then
     396             :      ! set up SAD curves
     397           0 :      nInterArea = int( ceiling( real(nCells,dp) / real(deltaArea, dp) ), i4 )
     398             :      !
     399             :      ! total number of events to be evaluated
     400             :  !    nEvents = count (DAreaEvol > 0.0_dp )
     401           0 :      nLargerEvents = nEvents
     402             :  !     allocate (  eventId   (nEvents, 3) )                !  dim1: running Nr.
     403             :  !                                                         !  dim2: 1 == cluster Id,
     404             :  !                                                         !        2 == month of ocurrence,
     405             :  !                                                         !        3 == number of cells
     406             :  !
     407             :  !    allocate (  eIdPerm   (nEvents)    )
     408           0 :      allocate (  SAD       (nInterArea, 2, nLargerEvents ) )    !  dim2: 1 == area, 2 == Severity
     409           0 :      allocate (  SADperc   (nInterArea, nQProp ) )
     410             :      !
     411             :      ! ! keep event identification
     412             :      ! eCounter = 0
     413             :      ! do ic = 1,  nClusters
     414             :      !    do t = 1, nMonths
     415             :      !       if (DAreaEvol(t,ic) > 0.0_dp ) then
     416             :      !          eCounter = eCounter + 1
     417             :      !          eventId(eCounter,1) = shortCnoList(ic)
     418             :      !          eventId(eCounter,2) = t
     419             :      !          eventId(eCounter,3) = count( idCluster(:,:,t) == shortCnoList(ic) )
     420             :      !       end if
     421             :      !    end do
     422             :      ! end do
     423             :      ! ! sort event in order of magnitude
     424             :      ! forall(i=1:nEvents) eIdPerm(i) = i
     425             :      ! allocate (vec(nEvents))
     426             :      ! ! call SVIGP (nEvents, eventId(:,3), vec, eIdPerm)
     427             :      ! eIdPerm = sort_index( eventID(:,3) )
     428             :      ! deallocate (vec)
     429             :   end if
     430             :   !
     431             :   ! SAD
     432           0 :   print*, 'SAD for duration started: ', durList (iDur)
     433           0 :   SAD     = -9.0_dp
     434           0 :   SADperc = -9.0_dp
     435           0 :   nDsteps = ceiling (real(nMonths,dp) / real(durList (iDur),dp) )
     436           0 :   if ( allocated (severity) )  deallocate(severity)
     437           0 :   allocate ( severity (nrows, ncols, nDsteps ) )
     438           0 :   severity = nodata_dp
     439             :   !
     440             :   ! estimate severities for a given duration over all time steps
     441           0 :   do d = 1, nDsteps
     442           0 :      ms = (d-1)*durList(iDur) + 1
     443           0 :      me = ms + durList(iDur) - 1
     444           0 :      if (me > nMonths) me = nMonths
     445             :      !where ( ne(SMI_unpack(:,:,1), nodata_dp) )
     446           0 :      where ( mask )
     447             :         severity(:,:,d) = 1.0_dp - sum( SMI_unpack(:,:,ms:me), DIM=3 ) / real( me-ms+1, dp )
     448             :      end where
     449             :   end do
     450             :   !
     451             :   ! estimate curves for larger events ONLY
     452           0 :   do eC = 1, nLargerEvents
     453           0 :      eCounter = eIdPerm( nEvents + 1 - eC )
     454           0 :      iDc = eventId(eCounter,1)
     455           0 :      t   = eventId(eCounter,2)
     456           0 :      d   = (t-1)/durList (iDur) + 1
     457             :      ! number of cells of the event in eCounter
     458           0 :      ncic = eventId(eCounter,3)
     459           0 :      if (allocated (sevP)) deallocate(sevP)
     460           0 :      allocate (sevP(ncic))
     461           0 :      sevP = pack (severity(:,:,d), mask = idCluster(:,:,t) == iDc )
     462             :      !
     463             :      ! ----------------------------------------------
     464             :      ! fast approach
     465             :      ! rank severities and estimate cummulative areas
     466             :      ! ----------------------------------------------
     467             :      ! call DSVRGN (ncic,sevP,sevP)
     468           0 :      call sort( sevP )
     469           0 :      nIntA = int( ceiling( real(ncic,dp) / real(deltaArea, dp) ), i4 )
     470           0 :      do k = 1, nIntA
     471           0 :         ke = k*deltaArea
     472             :         if (ke > ncic ) ke = ncic
     473           0 :         SAD(k, 1, eC ) = real(ke, dp) *  real(cellsize,dp)**2.0_dp  ! cumulative area
     474           0 :         SAD(k, 2, eC ) = sum( sevP(ncic+1-ke:ncic) ) / real(ke, dp) ! sorted by incresing value
     475             :      end do
     476             :   end do
     477             :   !
     478             :   ! estimate percentilles for all intervals
     479           0 :   do k = 1, nInterArea
     480           0 :      nObs = count(SAD(k,2,:) > 0.0_dp)
     481           0 :      if (.not. nObs > 1) cycle
     482           0 :      if (allocated (sevP)) deallocate(sevP)
     483           0 :      allocate (sevP(nObs))
     484           0 :      sevP = pack (SAD(k,2,:), mask = SAD(k,2,:) > 0.0_dp )
     485             :      ! call DEQTIL (nObs, sevP, nQprop, Qprop, SADperc(k,:), Xlo, Xhi, nMiss)
     486           0 :      SADperc(k,:) =  percentile( sevP, Qprop )
     487             :   end do
     488             :   !
     489           0 :   if ( allocated(sevP) ) deallocate ( sevP )
     490           0 : end subroutine calSAD
     491             : 
     492             : !> \brief clustering in space
     493             : !> \details assign a unique running number at time t
     494          71 : subroutine findClusters (cellCoor, thCellClus, t,iC,nCluster, nrows, ncols, nCells, SMIc)
     495             : 
     496             :   use mo_constants,     only : nodata_i4
     497             : 
     498             :   implicit none
     499             : 
     500             :   integer(i4), dimension(:,:),                intent(in)    :: cellCoor
     501             :   integer(i4),                                intent(in)    :: thCellClus ! treshold  for cluster formation
     502             :   integer(i4),                                intent(in)    :: nrows
     503             :   integer(i4),                                intent(in)    :: ncols
     504             :   integer(i4),                                intent(in)    :: nCells     ! number of effective cells
     505             :   integer(i4),                                intent(in)    :: t          !  time step
     506             :   integer(i4), dimension(:,:,:),              intent(inout) :: SMIc       ! SMI indicator
     507             :   integer(i4),                                intent(out)   :: nCluster   !  number of clusters larger than a threshold
     508             :   integer(i4), dimension(nrows,ncols),        intent(out)   :: iC
     509             : 
     510             :   ! local variables
     511             :   integer(i4)                                           :: i, j, k, klu, klu1
     512             :   integer(i4)                                           :: iul, idr, jul, jdr
     513             :   integer(i4)                                           :: krow, kcol
     514          71 :   integer(i4), dimension(:), allocatable                :: cno, vec
     515          71 :   integer(i4), dimension(:), allocatable                :: nCxCluster
     516             :   integer(i4)                                           :: nClusterR, ncc
     517             :   !
     518        2911 :   iC = nodata_i4
     519          71 :   nCluster = 0
     520        1633 :   do k = 1, nCells
     521        1562 :      krow = cellCoor(k,1)
     522        1562 :      kcol = cellCoor(k,2)
     523        1562 :      iul  = max(krow-1,1)
     524        1562 :      idr  = min(krow+1,nrows)
     525        1562 :      jul  = kcol
     526        1562 :      jdr  = min(kcol+1,ncols)
     527             :      ! SMIc of k
     528        1562 :      klu  = SMIc(krow, kcol, t)
     529        1562 :      if (klu /= 1) cycle
     530        1244 :      if ( (klu == 1) .and. (iC(krow, kcol) == nodata_i4) ) then
     531          87 :         nCluster=nCluster+1
     532          87 :         iC(krow, kcol) = nCluster
     533             :      end if
     534        3581 :      do j=jul, jdr
     535       10244 :         do i= iul, idr
     536        6416 :            if (iC(i,j) == nodata_i4 .and. &
     537        2266 :                 SMIc(i,j,t) == klu                     ) then
     538        1157 :               iC(i,j) = iC(krow, kcol)
     539             :            end if
     540             :         end do
     541             :      end do
     542             :   end do
     543             : 
     544             :   ! consolidate clusters
     545          71 :   if ( nCluster > 0 ) then
     546         284 :      allocate ( cno(nCluster), vec(nCluster) )
     547         474 :      cno = (/(i, i=1,nCluster)/)
     548         158 :      vec = -9
     549             :      nClusterR = nCluster
     550             : 
     551        1633 :      do k = nCells, 1, -1
     552        1562 :         krow = cellCoor(k,1)
     553        1562 :         kcol = cellCoor(k,2)
     554        1562 :         klu  = iC(krow, kcol)
     555        1562 :         iul  = max(krow-1,1)
     556        1562 :         idr  = min(krow+1,nrows)
     557        1562 :         jul  = kcol
     558        1562 :         jdr  = min(kcol+1,ncols)
     559        4473 :         do j=jul, jdr
     560       12425 :            do i= iul, idr
     561        8023 :               klu1 = iC(i, j)
     562             :               if ( klu  /= nodata_i4 .and. &
     563        8023 :                    klu1 /= nodata_i4 .and. &
     564        2840 :                    klu  /= klu1                       ) then
     565           7 :                  cno(klu1) = -9
     566           7 :                  nClusterR = nClusterR - 1
     567         287 :                  where ( iC == klu1 ) iC = klu
     568             :               end if
     569             :            end do
     570             :         end do
     571             :      end do
     572             :      !
     573             :      ! delete small clusters < thesh. area
     574         158 :      do i=1, nCluster
     575          87 :         if (cno(i) == -9 ) cycle
     576        3280 :         ncc = count(iC == cno(i))
     577         151 :         if ( ncc <= thCellClus ) then
     578         451 :            where (iC == cno(i)) iC = nodata_i4
     579          11 :            cno(i) = -9
     580          11 :            nClusterR = nClusterR -1
     581             :         end if
     582             :      end do
     583             :      !
     584             :      ! reordering
     585         403 :      cno = pack (cno, mask = cno > 0, vector=vec)
     586         158 :      where (cno <= 0) cno = 0
     587             :      !
     588             :      !
     589         211 :      allocate (nCxCluster(nClusterR))
     590         140 :      do i=1, nClusterR
     591        2829 :         where (iC == cno(i)) iC = i
     592        2900 :         nCxCluster(i) = count(iC == i)
     593             :      end do
     594             :      !
     595          71 :      deallocate (cno, nCxCluster)
     596             :   end if
     597          71 :   nCluster = nClusterR
     598          71 : end subroutine findClusters
     599             : 
     600             : END MODULE mo_smi_drought_evaluation

Generated by: LCOV version 1.16