LCOV - code coverage report
Current view: top level - app - main.f90 (source / functions) Hit Total Coverage
Test: SMI coverage Lines: 54 60 90.0 %
Date: 2024-04-30 09:16:25 Functions: 2 2 100.0 %

          Line data    Source code
       1             : !> \file    main.f90
       2             : !> \brief   \copybrief sm_drought_index
       3             : !> \details \copydetails sm_drought_index
       4             : 
       5             : !>  \brief SOIL MOISTURE DROUGHT INDEX
       6             : !>  \details Estimate the soil moisture index using daily values generated by mHM
       7             : !!           ALGORITHM:
       8             : !!           1. Read netcdf files daily/montly
       9             : !!           2. Estimate monthly values of mHM-SM(sum over all layers) for each grid cell
      10             : !!              - write them into netCDF
      11             : !!           3. Estimate the empirical density function for each grid cell
      12             : !!              using a non-parametric approach,  e.g. kernel smoother whose
      13             : !!              bandwith is estimated with an unbiased cross-validation criterium
      14             : !!           4. Estimate the mHM-drought index
      15             : !!                   q(s) = \int_a^s f(s)ds
      16             : !!                   where:
      17             : !!                        s = total soil moisture in mm over all soil layers in mHM
      18             : !!                        a = lower limit of soil moisture a a given grid
      19             : !!                      q(s)= quantile corresponding to s
      20             : !!           5. Estimate the following indices
      21             : !!              - start
      22             : !!              - duration
      23             : !!              - magnitud
      24             : !!              - severity
      25             : !!              - affected area
      26             : !!           6. Save results in netCDF format
      27             : !!
      28             : !> \authors  Luis E. Samaniego-Eguiguren, Matthias Zink, Stephan Thober
      29             : !> \date     15.02.2011
      30             : !!           - (LS) main structure
      31             : !> \date     20.02.2011
      32             : !!           - (LS) debuging
      33             : !> \date     25.05.2011
      34             : !!           - (LS) v3. scenarios
      35             : !> \date     02.04.2012
      36             : !!           - (LS) v4. read COSMO SM
      37             : !> \date     22.06.2012
      38             : !!           - (LS) v4. read WRF-NOAH SM
      39             : !> \date     07.11.2016
      40             : !!           - (MZ) modularized version
      41             : !> \date     20.03.2017
      42             : !!           - (LS) daily SMI, SAD flag, restructuring SAD
      43             : !> \date     24.07.2018
      44             : !!           - (ST) bug fix in optimize width
      45             : !> \copyright Copyright 2005-\today, the CHS Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
      46             : !! SMI is released under the LGPLv3+ license \license_note
      47          12 : program SM_Drought_Index
      48             : 
      49           6 :   use mo_kind,                   only : i4, sp, dp
      50             :   use mo_message,                only : message
      51             :   use mo_smi_write,              only : WriteNetCDF, &
      52             :                                         nDurations, durList, nClusters, &
      53             :                                         writeResultsCluster, WriteResultsBasins, &
      54             :                                         WriteSMI, WriteCDF
      55             :   use mo_smi_read,               only : ReadDataMain
      56             :   use mo_smi,                    only : optimize_width, calSMI, invSMI
      57             :   use mo_smi_drought_evaluation, only : droughtIndicator, ClusterEvolution, ClusterStats, calSAD
      58             :   use mo_constants,              only : nodata_sp
      59             :   use mo_smi_global_variables,   only : period
      60             :   use mo_smi_cli,                only : parse_command_line
      61             :   !$ use omp_lib, ONLY : OMP_GET_NUM_THREADS           ! OpenMP routines
      62             : 
      63             :   implicit none
      64             : 
      65             :   ! variables
      66             :   logical                                    :: do_cluster  ! flag indicating whether cluster should be calculated
      67             :   logical                                    :: do_sad      ! flag indicating whether SAD analysis should be done
      68             :   logical                                    :: ext_smi  ! flag indicating to read external data for clustering
      69             :   logical                                    :: invert_SMI  ! flag for inverting SMI
      70             :   !                                                         ! calculated or read from file
      71             :   logical                                    :: read_opt_h  ! read kernel width from file
      72             :   logical                                    :: silverman_h ! flag indicating whether kernel width
      73             :   !                                                         ! should be optimized
      74             :   logical                                    :: do_basin    ! do_basin flag
      75           6 :   logical,     dimension(:,:), allocatable   :: mask
      76             : 
      77             :   integer(i4)                                :: ii
      78           6 :   type(period)                               :: per_kde, per_eval, per_smi
      79             :   integer(i4)                                :: nCells     ! number of effective cells
      80             :   integer(i4)                                :: d
      81             : 
      82             :   integer(i4)                                :: nCalendarStepsYear  !  Number of calendar time steps per year (month=12, day=365)
      83             : 
      84             :   integer(i4)                                :: thCellClus ! treshold  for cluster formation in space ~ 640 km2
      85             :   integer(i4)                                :: nCellInter ! number cells for joining clusters in time ~ 6400 km2
      86             :   integer(i4)                                :: deltaArea  ! number of cells per area interval
      87           6 :   integer(i4), dimension(:,:), allocatable   :: Basin_Id   ! IDs for basinwise drought analysis
      88           6 :   integer(i4), dimension(:,:), allocatable   :: cellCoor   !
      89             : 
      90             :   real(sp)                                   :: SMI_thld   ! SMI threshold for clustering
      91             :   real(sp)                                   :: cellsize   ! cell edge lenght of input data
      92           6 :   real(sp),    dimension(:,:), allocatable   :: SM_kde     ! monthly fields packed for estimation
      93           6 :   real(sp),    dimension(:,:), allocatable   :: SM_eval    ! monthly fields packed for evaluation
      94           6 :   real(sp),    dimension(:,:), allocatable   :: SM_invert  ! inverted monthly fields packed
      95           6 :   real(sp),    dimension(:,:), allocatable   :: SMI        ! soil moisture index at evaluation array
      96           6 :   real(sp),    dimension(:,:,:), allocatable :: dummy_d3_sp
      97           6 :   integer(i4), dimension(:,:,:), allocatable :: SMIc       ! Drought indicator 1 - is under drought
      98             :   !                                                        !                   0 - no drought
      99           6 :   real(dp),    dimension(:,:), allocatable   :: opt_h      ! optimized kernel width field
     100           6 :   real(dp), dimension(:), allocatable        :: lats_1d, lons_1d ! latitude and longitude vectors of input
     101           6 :   real(dp), dimension(:,:), allocatable      :: lats_2d, lons_2d ! latitude and longitude vectors of input
     102           6 :   real(dp), dimension(:), allocatable        :: easting ! easting coordinates of input
     103           6 :   real(dp), dimension(:), allocatable        :: northing ! easting coordinates of input
     104             : 
     105             : 
     106             :   ! file handling
     107             :   character(256)                             :: outpath    ! output path for results
     108             : 
     109             :   !parse CLI
     110           6 :   call parse_command_line()
     111             : 
     112             :   !$OMP PARALLEL
     113             :   !$ ii = OMP_GET_NUM_THREADS()
     114             :   !$OMP END PARALLEL
     115             :   !$ print *, 'Run with OpenMP with ', ii, ' threads.'
     116             : 
     117             :   call ReadDataMain( SMI, do_cluster, ext_smi, invert_smi, &
     118             :        read_opt_h, silverman_h, opt_h, lats_1d, lons_1d, lats_2d, lons_2d, easting, northing,&
     119             :         do_basin, mask, SM_kde, SM_eval, Basin_Id, &
     120             :        SMI_thld, outpath, cellsize, thCellClus, nCellInter, &
     121           6 :        do_sad, deltaArea, nCalendarStepsYear, per_kde, per_eval, per_smi )
     122             : 
     123             :   ! initialize some variables
     124         236 :   nCells = count( mask ) ! number of effective cells
     125             : 
     126           6 :   call message('FINISHED READING')
     127             : 
     128             :   ! optimize kernel width
     129           6 :   if ( (.NOT. read_opt_h) .AND. (.NOT. ext_smi)) then
     130           1 :      call optimize_width( opt_h, silverman_h, SM_kde, nCalendarStepsYear, per_kde)
     131           1 :      call message('optimizing kernel width...ok')
     132             :   end if
     133             : 
     134             :   ! calculate SMI values for SM_eval
     135           6 :   if (.NOT. ext_smi) then
     136          16 :     allocate( SMI( size( SM_eval, 1 ), size( SM_eval, 2 ) ) )
     137       20579 :     SMI(:,:) = nodata_sp
     138           4 :     call calSMI( opt_h, SM_kde, SM_eval, nCalendarStepsYear, SMI, per_kde, per_eval )
     139           4 :     call message('calculating SMI... ok')
     140             :   end if
     141             : 
     142             :   ! invert SMI according to given cdf
     143           6 :   if (invert_smi) then
     144             :      ! testing with calculated SMI -> SM_invert == SM_kde
     145             :      call invSMI(SM_kde, opt_h, SMI, nCalendarStepsYear, per_kde, per_smi, SM_invert)
     146             :      ! write results to file
     147           5 :      allocate(dummy_D3_sp(size(mask, 1), size(mask, 2), size(SM_invert, 2)))
     148           6 :      do ii = 1, size(SM_invert, 2)
     149           6 :        dummy_D3_sp(:, :, ii) = unpack(SM_invert(:, ii), mask, nodata_sp)
     150             :      end do
     151           1 :      call WriteNetcdf(outpath, 2, per_smi, lats_1d, lons_1d, lats_2d, lons_2d, easting, northing, SM_invert=dummy_D3_sp)
     152           2 :      deallocate(dummy_D3_sp)
     153             :   end if
     154             : 
     155             :   ! write output
     156           6 :   if (.NOT. ext_smi) then
     157           4 :      call WriteSMI( outpath, SMI, mask, per_eval, lats_1d, lons_1d, lats_2d, lons_2d, easting, northing)
     158           4 :     call message('write SMI...ok')
     159             :   end if
     160             : 
     161           6 :   if ((.not. read_opt_h) .and. (.not. ext_smi)) then
     162             :      call WriteCDF( outpath, SM_kde, opt_h, mask, per_kde, nCalendarStepsYear, &
     163           1 :           lats_1d, lons_1d, lats_2d, lons_2d, easting, northing)
     164           1 :     call message('write cdf_info file...ok')
     165             :   end if
     166             : 
     167             :   ! calculate drought cluster
     168           7 :   if ( do_cluster ) then
     169             :      ! drought indicator
     170           1 :      call droughtIndicator( SMI, mask, SMI_thld, cellCoor, SMIc )
     171           1 :      call WriteNetCDF(outpath, 3, per_smi, lats_1d, lons_1d, lats_2d, lons_2d, easting, northing, SMIc=SMIc)
     172             : 
     173             :      ! cluster indentification
     174             :      call ClusterEvolution( SMIc,  size( mask, 1), size( mask, 2 ), size(SMI, 2), &
     175           1 :          nCells, cellCoor, nCellInter, thCellClus)
     176           1 :      call WriteNetCDF(outpath, 4, per_smi, lats_1d, lons_1d, lats_2d, lons_2d, easting, northing)
     177             : 
     178             :      ! statistics
     179           1 :      call ClusterStats(SMI, mask, size( mask, 1), size( mask, 2 ), size(SMI, 2), nCells, SMI_thld )
     180             : 
     181             :      ! write results
     182           1 :      if (nClusters > 0) call writeResultsCluster(SMIc, outpath, 1, &
     183           1 :          per_smi%y_start, per_smi%y_end, size(SMI, 2), nCells, deltaArea, cellsize)
     184           1 :      call message('Cluster evolution ...ok')
     185             :   end if
     186             : 
     187             :   ! SAD analysis
     188           6 :   if ( do_sad ) then
     189           0 :      do d = 1, nDurations
     190           0 :         call calSAD(SMI, mask, d, size( mask, 1), size( mask, 2 ), size(SMI, 2), nCells, deltaArea, cellsize)
     191             :         ! write SAD for a given duration + percentiles
     192             :         call writeResultsCluster(SMIc, outpath, 2, per_smi%y_start, per_smi%y_end, size(SMI, 2), &
     193           0 :             nCells, deltaArea, cellsize, durList(d))
     194             :         call WriteNetCDF(outpath, 5, per_kde, lats_1d, lons_1d, lats_2d, lons_2d,&
     195           0 :              easting, northing, duration=durList(d))
     196             :      end do
     197             :   end if
     198             : 
     199             :   ! make basin averages
     200           6 :   if ( do_basin ) then
     201             :      ! write SMI average over major basins
     202           0 :      call message('calculate Basin Results ...')
     203           0 :      call WriteResultsBasins( outpath, SMI, mask, per_kde%y_start, per_kde%y_end, size( SM_kde, 2 ), Basin_Id )
     204             :   end if
     205             : 
     206             :   ! print statement for check_cases
     207           6 :   call message('SMI: finished!')
     208             :   !
     209           6 : end program SM_Drought_Index

Generated by: LCOV version 1.16