LCOV - code coverage report
Current view: top level - src - mo_smi_read.F90 (source / functions) Hit Total Coverage
Test: SMI coverage Lines: 174 215 80.9 %
Date: 2024-04-30 09:16:25 Functions: 4 4 100.0 %

          Line data    Source code
       1             : !> \file mo_smi_read.f90
       2             : !> \brief   \copybrief mo_smi_read
       3             : !> \details \copydetails mo_smi_read
       4             : 
       5             : !> \brief Reading routines for SMI
       6             : !> \author Luis Samaniego
       7             : !> \date 09.02.2011
       8             : !> \author Stephan Thober
       9             : !> \date 07.11.2017
      10             : !!       - switched to mo_netcdf
      11             : !        - added invert_SMI
      12             : !> \copyright Copyright 2005-\today, the CHS Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
      13             : !! SMI is released under the LGPLv3+ license \license_note
      14             : module mo_smi_read
      15             : 
      16             :   USE mo_kind,   only : i4, sp, dp
      17             : 
      18             :   IMPLICIT NONE
      19             : 
      20             :   PRIVATE
      21             : 
      22             :   PUBLIC :: ReadDataMain   ! read everything
      23             : 
      24             :   ! ------------------------------------------------------------------
      25             : 
      26             : CONTAINS
      27             : 
      28             :   ! ------------------------------------------------------------------
      29             : 
      30             : 
      31             :   !> \brief Reads main file
      32             :   !> \author Luis E. Samaniego-Eguiguren, UFZ
      33             :   !> \date 23.05.2007
      34             :   !> \note packed fields are stored in dim1->dim2 sequence
      35           6 :   subroutine ReadDataMain( SMI_in, do_cluster, ext_smi, invert_SMI, read_opt_h, silverman_h, opt_h, lats_1d, lons_1d,&
      36             :                            lats_2d, lons_2d,easting, northing, basin_flag, mask, SM_kde,  SM_eval,  &
      37             :                            Basin_Id, SMI_thld, outpath, cellsize, thCellClus, nCellInter, do_sad, deltaArea, &
      38             :                            nCalendarStepsYear, per_kde, per_eval, per_smi )
      39             : 
      40             :     use mo_kind,                 only: i4
      41             :     use mo_message,              only: message
      42             :     use mo_utils,                only: notequal, equal
      43             :     use mo_netcdf,               only: NcDataset, NcVariable
      44             :     use mo_constants,            only: nodata_dp
      45             :     use mo_smi_global_variables, only: period
      46             :     use mo_smi_info,             only: version, version_date, file_namelist
      47             :     use mo_os,                   only: check_path_isfile, path_isfile
      48             : 
      49             :     implicit none
      50             : 
      51             :     ! input / output Variables
      52             :     real(sp),    dimension(:,:), allocatable, intent(out) :: SMI_in      !< SMI only read if ext_smi is TRUE
      53             :     logical,                                  intent(out) :: do_sad      !< do SAD analysis
      54             :     logical,                                  intent(out) :: do_cluster  !< do cluster calculation
      55             :     logical,                                  intent(out) :: ext_smi     !< clsutering external data
      56             :     logical,                                  intent(out) :: invert_SMI  !< do inversion of SMI
      57             :     logical,                                  intent(out) :: read_opt_h  !< read kernel width
      58             :     logical,                                  intent(out) :: silverman_h !< optimize kernel width
      59             :     logical,                                  intent(out) :: basin_flag  !< basin flag
      60             :     logical,     dimension(:,:), allocatable, intent(out) :: mask        !< grid mask
      61             :     integer(i4),                              intent(out) :: thCellClus  !< treshold  for cluster formation in space ~ 640 km2
      62             :     integer(i4),                              intent(out) :: nCellInter  !< number cells for joining clusters in time ~ 6400 km2
      63             :     integer(i4),                              intent(out) :: deltaArea   !< number of cells per area interval
      64             :     !> number of calendar time steps per year (month=12, day=365)
      65             :     integer(i4),                              intent(out) :: nCalendarStepsYear
      66             :     integer(i4), dimension(:,:), allocatable, intent(out) :: Basin_Id    !< IDs for basinwise drought analysis
      67             :     real(sp),                                 intent(out) :: cellsize    !< cell edge lenght of input data
      68             :     real(sp),    dimension(:,:), allocatable, intent(out) :: SM_kde      !< daily / monthly fields packed for estimation
      69             :     real(sp),    dimension(:,:), allocatable, intent(out) :: SM_eval     !< monthly fields packed for evaluation
      70             :     real(dp),    dimension(:,:), allocatable, intent(out) :: opt_h       !< optimized kernel width
      71             :     real(dp), dimension(:), allocatable, intent(out) :: lats_1d, lons_1d !< latitude and longitude vectors of input
      72             :     real(dp), dimension(:,:), allocatable, intent(out) :: lats_2d        !< latitude vectors of input
      73             :     real(dp), dimension(:,:), allocatable, intent(out) :: lons_2d        !< longitude vectors of input
      74             :     real(dp), dimension(:), allocatable, intent(out) :: easting          !< easting coordinates of input
      75             :     real(dp), dimension(:), allocatable, intent(out) :: northing         !< easting coordinates of input
      76             :     real(sp),                                 intent(out) :: SMI_thld    !< SMI threshold for clustering
      77             :     character(len=256),                       intent(out) :: outpath     !< ouutput path for results
      78             :     type(period),                             intent(out) :: per_kde     !< period contain information during estimation
      79             :     type(period),                             intent(out) :: per_eval    !< period during evaluation
      80             :     type(period),                             intent(out) :: per_smi     !< period of smi file
      81             : 
      82             :     ! local Variables
      83             :     logical                                         :: read_sm
      84             :     integer(i4)                                     :: ii
      85             :     integer(i4)                                     :: nCells         ! number of effective cells
      86             :     integer(i4)                                     :: lag! number of lag days for daily files (0,7,31)
      87             :     integer(i4)                                     :: nTimeSteps     ! number of time steps excluding leap days
      88             : 
      89             :     ! directories, filenames, attributes
      90             :     character(256)                                  :: maskfName
      91             :     character(256)                                  :: opt_h_file
      92             :     character(256)                                  :: basinfName
      93             : 
      94             :     ! variable names in netcdf input files
      95             :     character(256)                                  :: soilmoist_file
      96             :     character(256)                                  :: mask_vname
      97             :     character(256)                                  :: SM_vname
      98             :     character(256)                                  :: ext_smi_file
      99             :     character(256)                                  :: basin_vname
     100             :     character(256)                                  :: opt_h_vname
     101             :     character(256)                                  :: opt_h_sm_vname
     102             :     real(sp)                                        :: nodata_value ! local data nodata value in nc for mask creation
     103             : 
     104           6 :     real(sp),       dimension(:,:),     allocatable :: dummy_D2_sp
     105           6 :     real(sp),       dimension(:,:,:),   allocatable :: dummy_D3_sp
     106           6 :     real(dp),       dimension(:,:,:),   allocatable :: dummy_D3_dp
     107             : 
     108             :     type(NcDataset)                                 :: nc_in
     109             :     type(NcVariable)                                :: nc_var
     110             : 
     111             :     ! read main config
     112             :     namelist/mainconfig/basin_flag, basinfName, basin_vname, maskfName, mask_vname, &
     113             :          soilmoist_file, SM_vname, outpath, nCalendarStepsYear, lag, &
     114             :          silverman_h, read_opt_h, opt_h_vname, opt_h_sm_vname, opt_h_file,     &
     115             :          SMI_thld, do_cluster, ext_smi, ext_smi_file, cellsize, thCellClus, nCellInter, &
     116             :          do_sad, deltaArea, invert_SMI
     117             : 
     118             : 
     119           6 :     call message("")
     120           6 :     call message("====================================================")
     121           6 :     call message("||")
     122           6 :     call message("||              SOIL MOISTURE INDEX")
     123           6 :     call message("||              VERSION ", version, " (", version_date, ")")
     124           6 :     call message("||")
     125           6 :     call message("====================================================")
     126           6 :     call message("")
     127             : 
     128             :     ! dummy init to avoid gnu compiler complaint
     129           6 :     outpath    = '-999'; cellsize=-999.0_sp; thCellClus=-999; nCellInter=-999; deltaArea=-999
     130             : 
     131           6 :     do_cluster = .FALSE.
     132           6 :     do_sad = .FALSE.
     133           6 :     SMI_thld   = 0.0_dp
     134           6 :     silverman_h = .FALSE.
     135             : 
     136             :     ! read namelist
     137           6 :     call check_path_isfile(path=file_namelist, raise=.true.)
     138           6 :     open (unit=10, file=file_namelist, status='old')
     139           6 :       read(10, nml=mainconfig)
     140           6 :     close (10)
     141           6 :     call message(file_namelist, ' read ...ok')
     142             : 
     143             :     ! consistency check
     144           6 :     if ( .not.(( nCalendarStepsYear == 12) .or. ( nCalendarStepsYear == 365) ) ) &
     145           0 :          stop '***ERROR: number of time steps per year different from 12 or 365'
     146             : 
     147           6 :     if ( ( lag .gt. 0 ) .and. ( nCalendarStepsYear == 12)  ) &
     148           0 :          stop '***ERROR: lag = 0 for montly SM values'
     149             : 
     150           6 :     if ( do_sad .and. (.not. do_cluster) ) &
     151           0 :          stop '***ERROR: flag do_cluster must be set to .TRUE. to perform SAD analisys'
     152             : 
     153           6 :     if (invert_SMI .and. (.not. ext_smi)) &
     154           0 :          stop '***ERROR: if invert_SMI is .TRUE., then ext_smi must be .TRUE. and ext_smi_file must be given.'
     155             : 
     156             :     ! read sm if not external smi or invert is given
     157           6 :     read_sm = (.not. ext_smi)
     158             : 
     159             :     ! read main mask
     160           9 :     if (path_isfile(maskfName)) then
     161           3 :       nc_in  = NcDataset(maskfName, "r")
     162           3 :       nc_var = nc_in%getVariable(trim(mask_vname))
     163           3 :       call nc_var%getData(dummy_D2_sp)
     164           3 :       call nc_var%getAttribute('missing_value', nodata_value)
     165           3 :       call read_latlon( nc_in, lats_1d, lons_1d, lats_2d, lons_2d,easting, northing)
     166           3 :       call nc_in%close()
     167             : 
     168             :       ! create mask
     169         126 :       mask = merge( .true., .false., notequal(dummy_D2_sp, nodata_value ) )
     170           3 :       deallocate( dummy_D2_sp )
     171           3 :       nCells = n_cells_consistency(mask)
     172           3 :       call message('mask read ...ok')
     173             :     else
     174           3 :       call message('Mask file ' // trim(maskfName) // ' does not exist!')
     175             :     end if
     176             : 
     177             :     ! read basin mask
     178           6 :     if ( basin_flag .AND. (.NOT. ext_smi)) then
     179           0 :        nc_in  = NcDataset(basinfName, "r")
     180           0 :        nc_var = nc_in%getVariable(trim(basin_vname))
     181           0 :        call nc_var%getData(Basin_id)
     182           0 :        call nc_var%getAttribute('missing_value', nodata_value)
     183           0 :        call nc_in%close()
     184             : 
     185             :        ! consistency check
     186           0 :        if ( ( size( Basin_Id, 1) .ne. size( mask, 1 ) ) .or. &
     187             :             ( size( Basin_Id, 2) .ne. size( mask, 2 ) ) ) then
     188           0 :           call message('***ERROR: size mismatch between basin field and given mask file')
     189           0 :           stop 1
     190             :        end if
     191             :        ! intersect mask and basin_id
     192           0 :        mask     = merge( .true., .false., mask .and. ( Basin_Id .ne. int( nodata_value, i4) ) )
     193           0 :        Basin_Id = merge( Basin_Id, int( nodata_value, i4), mask )
     194           0 :        call message('basin ID read ...ok')
     195             :     end if
     196             : 
     197             :     ! *************************************************************************
     198             :     ! >>> read SM field
     199             :     ! *************************************************************************
     200           6 :     if ( read_sm )  then
     201           4 :        nc_in  = NcDataset(soilmoist_file, "r")
     202           4 :        nc_var = nc_in%getVariable(trim(SM_vname))
     203           4 :        call nc_var%getData(dummy_D3_sp)
     204           4 :        if (.not. allocated(mask)) then
     205           1 :          call nc_var%getAttribute('missing_value', nodata_value)
     206          32 :          mask = (dummy_D3_sp(:, :, 1) .ne. nodata_value)
     207           1 :          nCells = n_cells_consistency(mask)
     208           1 :          call message('mask read ...ok')
     209             :        end if
     210             : 
     211             :        ! consistency check
     212           4 :        if ( ( size( dummy_D3_sp, 1) .ne. size( mask, 1 ) ) .or. &
     213             :             ( size( dummy_D3_sp, 2) .ne. size( mask, 2 ) ) ) then
     214           0 :           call message('***ERROR: size mismatch between SM field and given mask file')
     215           0 :           call nc_in%close()
     216           0 :           stop 1
     217             :        end if
     218             : 
     219             :        ! find number of leap years in  SM data set
     220             :        ! get timepoints in days and masks for climatologies at calendar day or month
     221           4 :        call get_time(nc_in,  size( dummy_D3_sp, 3 ), nCalendarStepsYear, per_eval)
     222             : 
     223             :        ! read lats and lon from file
     224           4 :        call read_latlon( nc_in, lats_1d, lons_1d, lats_2d, lons_2d,easting, northing)
     225           4 :        call nc_in%close()
     226             : 
     227             : 
     228             :        ! if ( nCalendarStepsYear .eq. YearMonths ) then
     229          16 :        allocate( SM_eval( nCells, size( dummy_D3_sp, 3 ) ) )
     230             :        ! no lag average, use monthly data as read
     231        1029 :        do ii = 1, size( dummy_D3_sp, 3 )
     232       39029 :          SM_eval(:,ii) = pack( real(dummy_D3_sp(:,:,ii),sp), mask )
     233             :        end do
     234             : 
     235           4 :        deallocate( dummy_D3_sp )
     236             : 
     237             :        ! calculate moving-lag average
     238           8 :        if (lag .gt. 0) then
     239           1 :          call message('calculate moving average')
     240           1 :          nTimeSteps = size(SM_eval, dim=2)
     241           4 :          allocate(dummy_d2_sp(size(SM_eval, dim=1), size(SM_eval, dim=2)))
     242        3902 :          dummy_d2_sp = SM_eval
     243         301 :          do ii = 1, nTimeSteps
     244         301 :            if ( ii .lt. lag ) then
     245        2327 :              SM_eval(:,ii) = dummy_d2_sp(:,ii)
     246             :            else
     247      262933 :              SM_eval(:,ii) = sum(dummy_D2_sp(:,ii-lag+1:ii), DIM=2) / real(lag,sp)
     248             :            end if
     249             :          end do
     250           1 :          deallocate(dummy_d2_sp)
     251             :        end if
     252             : 
     253             :     end if
     254             : 
     255             :     ! *************************************************************************
     256             :     ! >>> read_opt_h
     257             :     ! *************************************************************************
     258           6 :     if (allocated(mask)) then
     259          16 :       allocate( opt_h(ncells, nCalendarStepsYear))
     260        5577 :       opt_h = nodata_dp
     261             :     end if
     262             :     !
     263           6 :     if ( read_opt_h ) then
     264             : 
     265           4 :       nc_in  = NcDataset(trim( opt_h_file ), 'r')
     266             : 
     267           4 :       nc_var = nc_in%getVariable(trim(opt_h_sm_vname))
     268           4 :       call nc_var%getData(dummy_D3_sp)
     269             :       ! read mask if not done already
     270           4 :       if (.not. allocated(mask)) then
     271           1 :         call nc_var%getAttribute('missing_value', nodata_value)
     272          42 :         mask = (dummy_D3_sp(:, :, 1) .ne. nodata_value)
     273           1 :         nCells = n_cells_consistency(mask)
     274           4 :         allocate( opt_h(ncells, nCalendarStepsYear))
     275         277 :         opt_h = nodata_dp
     276           1 :         call message('mask read ...ok')
     277             :       end if
     278             :       ! unpack values
     279          16 :       allocate(SM_kde(nCells, size(dummy_D3_sp, 3)))
     280       35417 :       do ii = 1, size( dummy_D3_sp, 3 )
     281       35417 :         SM_kde(:, ii) = pack( dummy_D3_sp(:,:,ii), mask)
     282             :       end do
     283           4 :       deallocate( dummy_D3_sp )
     284           4 :       call message('read kde soil moisture values from file... ok')
     285             : 
     286             :       ! read optimized kernel width from file
     287           4 :       nc_var = nc_in%getVariable(trim(opt_h_vname))
     288           4 :       call nc_var%getData(dummy_D3_dp)
     289         405 :       do ii = 1, size( dummy_D3_dp, 3 )
     290       17967 :         opt_h( :, ii ) = pack( real( dummy_D3_dp(:,:,ii),sp ), mask )
     291             :       end do
     292           4 :       deallocate( dummy_D3_dp )
     293        5577 :       if ( any( equal( opt_h, nodata_dp ) ) ) &
     294             :       ! if ( any( opt_h .eq. nodata_dp ) ) &
     295           0 :           stop '***ERROR kernel width contains nodata values'
     296           4 :       call message('read kde kernel width from file... ok')
     297             : 
     298             : 
     299             :       ! get timepoints in days and mask of months
     300           4 :       call get_time(nc_in, size(SM_kde, 2), nCalendarStepsYear, per_kde)
     301             :       ! close file
     302           4 :       call nc_in%close()
     303             : 
     304             :     else
     305             :       ! SM_eval is SM_kde too
     306           2 :       if (allocated(SM_eval)) then
     307        8284 :         SM_kde = SM_eval
     308           1 :         per_kde = per_eval
     309             :       end if
     310             :     end if
     311             : 
     312           6 :     if (allocated(SM_kde)) then
     313           5 :       if (((nCalendarStepsYear .eq. 12) .and. (modulo(size( SM_kde, 2 ), nCalendarStepsYear) .ne. 0_i4)) .or. &
     314           5 :           ((nCalendarStepsYear .ne. 12) .and. (modulo(size( SM_kde, 2 ), nCalendarStepsYear) .ne. per_kde%n_leap_days))) then
     315             : #ifdef SMIDEBUG
     316             :         print *, modulo(size( SM_kde, 2 ), nCalendarStepsYear),  per_kde%n_leap_days
     317             : #endif
     318           0 :         print *, '***ERROR: timesteps in provided SM_kde field must be multiple of nCalendarStepsYear (', &
     319           0 :             nCalendarStepsYear, '; leap days are accounted for)'
     320           0 :         stop
     321             :       end if
     322             :     end if
     323             : 
     324             : 
     325             :     ! *************************************************************************
     326             :     ! >>> read external SMI field
     327             :     ! *************************************************************************
     328           6 :     if (ext_smi) then
     329           2 :       nc_in  = NcDataset(trim(ext_smi_file), 'r')
     330           2 :       nc_var = nc_in%getVariable('SMI')
     331           2 :       call nc_var%getData(dummy_D3_sp)
     332           2 :       if (.not. allocated(mask)) then
     333           1 :         call nc_var%getAttribute('missing_value', nodata_value)
     334          42 :         mask = (dummy_D3_sp(:, :, 1) .ne. nodata_value)
     335           1 :         nCells = n_cells_consistency(mask)
     336           1 :         call message('mask read ...ok')
     337             :       end if
     338             :       ! consistency check
     339           2 :       if ( ( size( dummy_D3_sp, 1) .ne. size( mask, 1 ) ) .or. &
     340             :            ( size( dummy_D3_sp, 2) .ne. size( mask, 2 ) ) ) then
     341           0 :          call message('***ERROR: size mismatch between SMI field and given mask file')
     342           0 :          stop
     343             :       end if
     344             : 
     345           8 :       allocate(SMI_in( nCells, size( dummy_D3_sp, 3 ) ) )
     346         367 :       do ii = 1, size( dummy_D3_sp, 3 )
     347         367 :          SMI_in(:,ii) = pack(dummy_D3_sp(:,:,ii), mask)
     348             :       end do
     349           2 :       deallocate( dummy_D3_sp )
     350             : 
     351             :       ! get timepoints in days and mask of months
     352           2 :       call get_time( nc_in, size(SMI_in, dim=2), nCalendarStepsYear, per_smi)
     353             : 
     354           2 :       call read_latlon( nc_in, lats_1d, lons_1d, lats_2d, lons_2d,easting, northing)
     355           2 :       call nc_in%close()
     356             :     else
     357           4 :       per_smi = per_kde
     358             :     end if
     359             : 
     360           6 :   end subroutine ReadDataMain
     361             : 
     362             : 
     363             :   !> \brief Convert input time into months & check timesteps & determine mask for months
     364             :   !> \author Matthias Zink, Oct 2012
     365             :   !> \author Stephan Thober
     366             :   !> \date Nov 2017
     367             :   !!       - convert to mo_netcdf
     368             :   !> \author Stephan Thober
     369             :   !> \date Aug 2019
     370             :   !!       - added type period
     371           0 :   subroutine get_time(nc_in, in_time_steps, nCalendarStepsYear, per_out) !, mask)
     372             :     !
     373           6 :     use mo_julian,               only: date2dec, dec2date
     374             :     use mo_message,              only: message
     375             :     use mo_string_utils,         only: DIVIDE_STRING
     376             :     use mo_netcdf,               only: NcDataset, NcVariable
     377             :     use mo_constants,            only: YearMonths, DayHours
     378             :     use mo_smi_global_variables, only: period, period_init
     379             : 
     380             :     implicit none
     381             : 
     382             :     type(NcDataset),              intent(in)  :: nc_in      ! NetCDF dataset
     383             :     integer(i4),                  intent(in)  :: in_time_steps
     384             :     integer(i4),                  intent(in)  :: nCalendarStepsYear
     385             :     type(period),                 intent(out) :: per_out
     386             :     integer(i4)                               :: yStart     ! start year  of the dataser
     387             :     integer(i4)                               :: mStart     ! start month of the dataser
     388             :     integer(i4)                               :: dStart     ! start day   of the dataser
     389             :     integer(i4)                               :: yEnd       ! end year of the dataset
     390             :     integer(i4)                               :: mEnd       ! end month of the dataset
     391             :     integer(i4)                               :: dEnd       ! end day of the dataset
     392             :     integer(i4)                               :: nTimeSteps ! size of the time dimension
     393          10 :     integer(i4), dimension(:),   allocatable  :: timepoints
     394             :     ! timestep in days or months
     395             : 
     396             :     type(ncVariable)                          :: nc_var
     397             :     integer(i4)                               :: i                      ! loop variable
     398             :     integer(i4)                               :: yRef, dRef, mRef       ! reference time of NetCDF (unit attribute of
     399             :     integer(i4)                               :: month, year, d         !
     400             :     !
     401          10 :     integer(i4),   dimension(:), allocatable  :: timesteps              ! time variable of NetCDF in input units
     402             :     !
     403             :     character(256)                            :: AttValues              ! netcdf attribute values
     404          10 :     character(256), dimension(:), allocatable :: strArr                 ! dummy for netcdf attribute handling
     405          10 :     character(256), dimension(:), allocatable :: date                   ! dummy for netcdf attribute handling
     406             :     real(dp)                                  :: ref_jday               ! refernce date of dateset as julian day
     407             :     !
     408             :     ! get unit attribute of variable 'time'
     409          10 :     nc_var = nc_in%getVariable('time')
     410          10 :     call nc_var%getAttribute('units', AttValues)
     411             :     ! AttValues looks like "<unit> since YYYY-MM-DD HH:MM:SS"
     412          10 :     call DIVIDE_STRING(trim(AttValues), ' ', strArr)
     413             :     !
     414          10 :     call DIVIDE_STRING(trim(strArr(3)), '-', date)
     415          10 :     read(date(1),*) yRef
     416          10 :     read(date(2),*) mRef
     417          10 :     read(date(3),*) dRef
     418             : 
     419             :     ! allocate and initialize
     420          10 :     call nc_var%getData(timesteps)
     421          10 :     nTimeSteps = size(timesteps, dim=1)
     422          30 :     allocate(timepoints ( nTimeSteps ))
     423       36813 :     timepoints = 0
     424             : 
     425             : 
     426             :     ! strArr(1) is <unit>
     427          10 :     ref_jday = date2dec(dd=dRef, mm=mRef, yy=yRef)
     428       36813 :     do i = 1, nTimeSteps
     429       38908 :        select case (strArr(1))
     430             :        case('hours')
     431        2105 :           call dec2date(real(timesteps(i), dp)/DayHours + ref_jday, dd=d, mm=month, yy=year)
     432        2105 :           timepoints(i) = timepoints(i) + nint( real(timesteps(i) - timesteps(1), dp) / DayHours , i4)
     433             :        case('days')
     434       34698 :           call dec2date(real(timesteps(i), dp) + ref_jday, dd=d, mm=month, yy=year)
     435       34698 :           timepoints(i) = timepoints(i) + timesteps(i) - timesteps(1)
     436             :        case('months')
     437           0 :           d       = dRef ! set to dref as default
     438           0 :           month   = mod( (timesteps(i) + mRef ), int(YearMonths, i4) )
     439           0 :           year    = yRef + floor(real( timesteps(i) + mRef, dp) / YearMonths )
     440             :           ! correct month and year for december
     441           0 :           if (month .eq. 0 ) then
     442           0 :              month = 12
     443           0 :              year  = year - 1
     444             :           end if
     445             :           !
     446           0 :           if (i .EQ. 1) then
     447           0 :              timepoints(i) = 0
     448             :           else
     449           0 :              timepoints(i) = timepoints(i) +  nint(date2dec(dd=15 ,mm=month, yy=year) - date2dec(dd=15 ,mm=mStart, yy=yStart), i4)
     450             :           end if
     451             :        case DEFAULT
     452           0 :           call message('***ERROR: Time slicing in ' , trim(strArr(1)), ' not implemented!')
     453       36803 :           stop
     454             :        end select
     455             : 
     456             :        ! save start year and month output timestamp
     457       36803 :        if (i .EQ. 1) then
     458          10 :           yStart = year
     459          10 :           mStart = month
     460          10 :           dStart = d
     461             :        end if
     462       36813 :        if (i .EQ. nTimeSteps) then
     463          10 :          yEnd = year
     464          10 :          mEnd = month
     465          10 :          dEnd = d
     466             :        end if
     467             :     end do
     468             : 
     469          10 :     per_out = period_init(yStart, mStart, dStart, yEnd, mEnd, dEnd, timepoints, strArr(1), nCalendarStepsYear)
     470             : 
     471             :     ! consistency check
     472          10 :     if (in_time_steps .ne. size(per_out%time_points, dim=1)) then
     473           0 :       call message('***ERROR: time steps of array and time axis are different by more than leap days')
     474           0 :       stop 1
     475             :     end if
     476             : 
     477          10 :   end subroutine get_time
     478             : 
     479           6 :   integer(i4) function n_cells_consistency(mask)
     480             : 
     481          10 :     use mo_message, only: message
     482             : 
     483             :     implicit none
     484             : 
     485             :     logical, intent(in) :: mask(:, :)
     486             : 
     487         236 :     n_cells_consistency = count( mask )
     488           6 :     if ( n_cells_consistency .eq. 0 ) then
     489           0 :       call message('***ERROR: no cell selected in mask')
     490           0 :       stop 1
     491             :     end if
     492           6 :   end function n_cells_consistency
     493             : 
     494           9 :   subroutine read_latlon(nc_in, lats_1d, lons_1d, lats_2d, lons_2d,easting, northing)
     495             : 
     496             :     use mo_kind,   only: dp,i4
     497             :     use mo_netcdf, only: NcDataset, NcVariable
     498             : 
     499             :     implicit none
     500             : 
     501             :     type(NcDataset), intent(in) :: nc_in ! NetCDF dataset
     502             :     real(dp), dimension(:), allocatable, intent(out) :: lats_1d, lons_1d ! latitude and longitude vectors of input
     503             :     real(dp), dimension(:,:), allocatable, intent(out) :: lats_2d, lons_2d ! latitude and longitude vectors of input
     504             :     real(dp), dimension(:), allocatable, intent(out) :: easting ! easting coordinates of input
     505             :     real(dp), dimension(:), allocatable, intent(out) :: northing ! easting coordinates of input
     506             :     integer(i4)              :: lat_lon_Ndim
     507             :     type(NcVariable) :: nc_var
     508             : 
     509             :     ! read lats and lon from file
     510           9 :     if (nc_in%hasVariable('lat')) then
     511           8 :        nc_var = nc_in%getVariable('lat')
     512           8 :        lat_lon_Ndim=nc_var%getNoDimensions()
     513           8 :        if (lat_lon_Ndim == 1) then
     514           0 :           call nc_var%getData(lats_1d)
     515           8 :        else if (lat_lon_Ndim == 2) then
     516           8 :           call nc_var%getData(lats_2d)
     517             :           ! nc_var = nc_in%getVariable('northing')
     518             :           ! call nc_var%getData(northing)
     519             :        end if
     520             :     end if
     521           9 :     if (nc_in%hasVariable('lon')) then
     522           8 :       nc_var = nc_in%getVariable('lon')
     523           8 :       lat_lon_Ndim=nc_var%getNoDimensions()
     524           8 :       if (lat_lon_Ndim == 1) then
     525           0 :          call nc_var%getData(lons_1d)
     526           8 :       else if (lat_lon_Ndim == 2) then
     527           8 :          call nc_var%getData(lons_2d)
     528             :          ! nc_var = nc_in%getVariable('easting')
     529             :          ! call nc_var%getData(easting)
     530             :       end if
     531             :     end if
     532             : 
     533           9 :   end subroutine read_latlon
     534             : 
     535             : end module mo_smi_read

Generated by: LCOV version 1.16