LCOV - code coverage report
Current view: top level - meteo - mo_meteo_helper.f90 (source / functions) Hit Total Coverage
Test: mHM coverage Lines: 97 124 78.2 %
Date: 2024-04-30 08:53:32 Functions: 5 5 100.0 %

          Line data    Source code
       1             : !> \file mo_meteo_helper.f90
       2             : !> \brief \copybrief mo_meteo_helper
       3             : !> \details \copydetails mo_meteo_helper
       4             : 
       5             : !> \brief Prepare meteorological forcings data for mHM.
       6             : !> \details Prepare meteorological forcings data for mHM.
       7             : !> \authors Rohini Kumar
       8             : !> \date Jan 2012
       9             : !> \copyright Copyright 2005-\today, the mHM Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
      10             : !! mHM is released under the LGPLv3+ license \license_note
      11             : !> \ingroup f_meteo
      12             : MODULE mo_meteo_helper
      13             : 
      14             :   ! This module provides routines to read meteorological data.
      15             : 
      16             :   ! Written  Rohini Kumar, Jan 2013
      17             :   ! Modified
      18             : 
      19             :   USE mo_kind, ONLY : i4, dp
      20             :   use mo_message, only: message, error_message
      21             : 
      22             :   IMPLICIT NONE
      23             : 
      24             :   PRIVATE
      25             : 
      26             :   public :: meteo_forcings_wrapper
      27             :   public :: meteo_weights_wrapper
      28             :   public :: chunk_config
      29             : 
      30             : CONTAINS
      31             : 
      32             :   !> \brief Prepare meteorological forcings data for mHM at Level-1
      33             :   !> \details Prepare meteorological forcings data for mHM, which include
      34             :   !! 1) Reading meteo. datasets at their native resolution for every Domain
      35             :   !! 2) Perform aggregation or disaggregation of meteo. datasets from their
      36             :   !! native resolution (level-2) to the required hydrologic resolution (level-1)
      37             :   !! 3) Pad the above datasets of every Domain to their respective global ones
      38             :   !> \changelog
      39             :   !! - Stephan Thober Jun 2014
      40             :   !!   - changed to readPer
      41             :   !! - Stephan Thober Feb 2016
      42             :   !!   - refactored deallocate statements
      43             :   !! - Robert Schweppe Jun 2018
      44             :   !!   - refactoring and reformatting
      45             :   !! - Sebastian Müller Mar 2023
      46             :   !!   - used by meteo-handler
      47             :   !!   - now independent of global variables
      48             :   !> \authors Rohini Kumar
      49             :   !> \date Jan 2013
      50         391 :   subroutine meteo_forcings_wrapper( &
      51         391 :     iDomain, dataPath, inputFormat, dataOut1, readPer, nTstepForcingDay, level1, level2, lower, upper, ncvarName, bound_error)
      52             : 
      53             :     use mo_append, only : append
      54             :     use mo_common_constants, only : nodata_dp
      55             :     use mo_common_types, only : period, grid
      56             :     use mo_read_nc, only : read_nc
      57             :     use mo_meteo_spatial_tools, only : spatial_aggregation, spatial_disaggregation
      58             : 
      59             :     implicit none
      60             : 
      61             :     !> Domain Id
      62             :     integer(i4), intent(in) :: iDomain
      63             :     !> Data path where a given meteo. variable is stored
      64             :     character(len = *), intent(in) :: dataPath
      65             :     !> only 'nc' possible at the moment
      66             :     character(len = *), intent(in) :: inputFormat
      67             :     !> Packed meterological variable for the whole simulation period
      68             :     real(dp), dimension(:, :), allocatable, intent(inout) :: dataOut1
      69             :     !> start and end dates of read period
      70             :     type(period), intent(in) :: readPer
      71             :     !> Number of forcing intervals per day
      72             :     integer(i4), intent(inout) :: nTstepForcingDay
      73             :     !> grid information at hydrologic level
      74             :     type(Grid), dimension(:), intent(in) :: level1
      75             :     !> Reference of the metereological variables
      76             :     type(Grid), dimension(:), intent(in) :: level2
      77             :     !> Lower bound for check of validity of data values
      78             :     real(dp), optional, intent(in) :: lower
      79             :     !> Upper bound for check of validity of data values
      80             :     real(dp), optional, intent(in) :: upper
      81             :     !> name of the variable (for .nc files)
      82             :     character(len = *), optional, intent(in) :: ncvarName
      83             :     !> .FALSE. to only warn about bound (lower, upper) violations, default = .TRUE. - raise an error
      84             :     logical, optional, intent(in) :: bound_error
      85             : 
      86         391 :     logical, dimension(:, :), allocatable :: mask1
      87             :     integer(i4) :: ncells1
      88             :     integer(i4) :: nrows2, ncols2
      89         391 :     logical, dimension(:, :), allocatable :: mask2
      90             :     ! meteo data at level-2
      91         391 :     real(dp), dimension(:, :, :), allocatable :: L2_data
      92             :     ! meteo data at level-1
      93         391 :     real(dp), dimension(:, :, :), allocatable :: L1_data
      94             :     ! packed meteo data at level-1 from 3D to 2D
      95         391 :     real(dp), dimension(:, :), allocatable :: L1_data_packed
      96             :     integer(i4) :: nTimeSteps
      97             :     ! level-1_resolution/level-2_resolution
      98         391 :     real(dp) :: cellFactorHbyM
      99             :     integer(i4) :: t
     100             : 
     101             :     ! get basic Domain information at level-1
     102         391 :     nCells1 = level1(iDomain)%nCells
     103       27147 :     mask1 = level1(iDomain)%mask
     104             : 
     105             :     ! make  basic Domain information at level-2
     106         391 :     nrows2 = level2(iDomain)%nrows
     107         391 :     ncols2 = level2(iDomain)%ncols
     108       25999 :     mask2 = level2(iDomain)%mask
     109             : 
     110             : 
     111         782 :     select case (trim(inputFormat))
     112             :       case('nc')
     113             :         ! Fortran 2008 allowes to pass optional dummy arguments to another routine (when they are optional there too)
     114             :         CALL read_nc(dataPath, nRows2, nCols2, ncvarName, mask2, L2_data, target_period=readPer, &
     115         391 :                      lower=lower, upper=upper, is_meteo=.True., bound_error=bound_error, nTstepForcingDay=nTstepForcingDay)
     116             :       case DEFAULT
     117         782 :         call error_message('***ERROR: meteo_forcings_wrapper: Not recognized input format')
     118             :     end select
     119             :     ! cellfactor to decide on the upscaling or downscaling of meteo. fields
     120         391 :     cellFactorHbyM = level1(iDomain)%cellsize / level2(iDomain)%cellsize
     121             : 
     122             :     ! upscaling & packing
     123         391 :     if(cellFactorHbyM .gt. 1.0_dp) then
     124           0 :       call spatial_aggregation(L2_data, level2(iDomain)%cellsize, level1(iDomain)%cellsize, mask1, mask2, L1_data)
     125             :       ! downscaling
     126         400 :     elseif(cellFactorHbyM .lt. 1.0_dp) then
     127           9 :       call spatial_disaggregation(L2_data, level2(iDomain)%cellsize, level1(iDomain)%cellsize, mask1, mask2, L1_data)
     128             :       ! nothing
     129             :     else
     130        1910 :       allocate(L1_data(size(L2_data, 1), size(L2_data, 2), size(L2_data, 3)))
     131     3585940 :       L1_data(:, :, :) = L2_data(:, :, :)
     132             :     end if
     133             :     ! free memory immediately
     134         391 :     deallocate(L2_data)
     135             : 
     136             :     ! pack variables
     137         391 :     nTimeSteps = size(L1_data, 3)
     138        1564 :     allocate(L1_data_packed(nCells1, nTimeSteps))
     139       63442 :     do t = 1, nTimeSteps
     140             : 
     141       63442 :       L1_data_packed(:, t) = pack(L1_data(:, :, t), MASK = mask1(:, :))
     142             : 
     143             :     end do
     144             : 
     145             :     ! free memory immediately
     146         391 :     deallocate(L1_data)
     147             : 
     148             :     ! append
     149         391 :     call append(dataOut1, L1_data_packed(:, :), nodata_dp)
     150             : 
     151             :     !free space
     152         391 :     deallocate(L1_data_packed)
     153             : 
     154         391 :   end subroutine meteo_forcings_wrapper
     155             : 
     156             : 
     157             :   !> \brief Prepare weights for meteorological forcings data for mHM at Level-1
     158             :   !> \details Prepare meteorological weights data for mHM, which include
     159             :   !! 1) Reading meteo. weights datasets at their native resolution for every Domain
     160             :   !! 2) Perform aggregation or disaggregation of meteo. weights datasets from their
     161             :   !! native resolution (level-2) to the required hydrologic resolution (level-1)
     162             :   !! 3) Pad the above datasets of every Domain to their respective global ones
     163             :   !> \changelog
     164             :   !! - Stephan Thober May 2017
     165             :   !!   - updated documentation
     166             :   !! - Robert Schweppe Jun 2018
     167             :   !!   - refactoring and reformatting
     168             :   !! - Oldrich Rakovec Aug 2018
     169             :   !!   - adding message about reading meteo_weights
     170             :   !! - Sebastian Müller Mar 2023
     171             :   !!   - used by meteo-handler
     172             :   !!   - now independent of global variables
     173             :   !> \authors Stephan Thober & Rohini Kumar
     174             :   !> \date Jan 2017
     175         156 :   subroutine meteo_weights_wrapper(iDomain, read_meteo_weights, dataPath, dataOut1, level1, level2, lower, upper, ncvarName)
     176             : 
     177         391 :     use mo_append, only : append
     178             :     use mo_common_constants, only : nodata_dp
     179             :     use mo_common_types, only : grid
     180             :     use mo_read_nc, only : read_weights_nc
     181             :     use mo_meteo_spatial_tools, only : spatial_aggregation, spatial_disaggregation
     182             : 
     183             :     implicit none
     184             : 
     185             :     !> Domain Id
     186             :     integer(i4), intent(in) :: iDomain
     187             :     !> Flag for reading meteo weights
     188             :     logical, intent(in) :: read_meteo_weights
     189             :     !> Data path where a given meteo. variable is stored
     190             :     character(len = *), intent(in) :: dataPath
     191             :     !> Packed meterological variable for the whole simulation period
     192             :     real(dp), dimension(:, :, :), allocatable, intent(inout) :: dataOut1
     193             :     !> grid information at hydrologic level
     194             :     type(Grid), dimension(:), intent(in) :: level1
     195             :     !> Reference of the metereological variables
     196             :     type(Grid), dimension(:), intent(in) :: level2
     197             :     !> Lower bound for check of validity of data values
     198             :     real(dp), optional, intent(in) :: lower
     199             :     !> Upper bound for check of validity of data values
     200             :     real(dp), optional, intent(in) :: upper
     201             :     !> name of the variable (for .nc files)
     202             :     character(len = *), optional, intent(in) :: ncvarName
     203             : 
     204          78 :     logical, dimension(:, :), allocatable :: mask1
     205             :     integer(i4) :: ncells1
     206             :     integer(i4) :: nrows2, ncols2
     207          78 :     logical, dimension(:, :), allocatable :: mask2
     208             :     ! meteo weights data at level-2
     209          78 :     real(dp), dimension(:, :, :, :), allocatable :: L2_data
     210             :     ! meteo weights data at level-1
     211          78 :     real(dp), dimension(:, :, :, :), allocatable :: L1_data
     212             :     ! packed meteo weights data at level-1 from 4D to 3D
     213          78 :     real(dp), dimension(:, :, :), allocatable :: L1_data_packed
     214             :     integer(i4) :: nMonths, nHours
     215             :     ! level-1_resolution/level-2_resolution
     216          78 :     real(dp) :: cellFactorHbyM
     217             :     integer(i4) :: t, j
     218             : 
     219             :     ! get basic Domain information at level-1
     220          78 :     nCells1 = level1(iDomain)%nCells
     221        6489 :     mask1 = level1(iDomain)%mask
     222             : 
     223             :     ! make  basic Domain information at level-2
     224          78 :     nrows2 = level2(iDomain)%nrows
     225          78 :     ncols2 = level2(iDomain)%ncols
     226        5028 :     mask2 = level2(iDomain)%mask
     227             : 
     228          78 :     if (read_meteo_weights) then
     229           0 :       call message('  read_meteo_weights = .TRUE. ... Reading meteo weights ... ')
     230           0 :       CALL read_weights_nc(dataPath, nRows2, nCols2, ncvarName, L2_data, mask2, lower=lower, upper=upper)
     231             : 
     232             :       ! cellfactor to decide on the upscaling or downscaling of meteo. fields
     233           0 :       cellFactorHbyM = level1(iDomain)%cellsize / level2(iDomain)%cellsize
     234             : 
     235             :       ! upscaling & packing
     236           0 :       if(cellFactorHbyM .gt. 1.0_dp) then
     237           0 :         call spatial_aggregation(L2_data, level2(iDomain)%cellsize, level1(iDomain)%cellsize, mask1, mask2, L1_data)
     238             :         ! downscaling
     239           0 :       elseif(cellFactorHbyM .lt. 1.0_dp) then
     240           0 :         call spatial_disaggregation(L2_data, level2(iDomain)%cellsize, level1(iDomain)%cellsize, mask1, mask2, L1_data)
     241             :         ! nothing
     242             :       else
     243           0 :         L1_data = L2_data
     244             :       end if
     245             :       ! free memory immediately
     246           0 :       deallocate(L2_data)
     247             : 
     248             :       ! pack variables
     249           0 :       nMonths = size(L1_data, dim = 3)
     250           0 :       nHours = size(L1_data, dim = 4)
     251           0 :       allocate(L1_data_packed(nCells1, nMonths, nHours))
     252           0 :       do t = 1, nMonths
     253           0 :         do j = 1, nHours
     254           0 :           L1_data_packed(:, t, j) = pack(L1_data(:, :, t, j), MASK = mask1(:, :))
     255             :         end do
     256             :       end do
     257             :       ! free memory immediately
     258           0 :       deallocate(L1_data)
     259             :     else
     260             :       ! dummy allocation
     261         312 :       allocate(L1_data_packed(nCells1, 12, 24))
     262      956748 :       L1_data_packed = nodata_dp
     263             :     end if
     264             : 
     265             :     ! append
     266          78 :     call append(dataOut1, L1_data_packed)
     267             : 
     268             :     !free space
     269          78 :     deallocate(L1_data_packed)
     270             : 
     271          78 :   end subroutine meteo_weights_wrapper
     272             : 
     273             : 
     274             :   !> \brief determines the start date, end date, and read_flag given Domain id and current timestep
     275             :   !> \changelog
     276             :   !! - Robert Schweppe Jun 2018
     277             :   !!   - refactoring and reformatting
     278             :   !! - Sebastian Müller Mar 2023
     279             :   !!   - used by meteo-handler
     280             :   !!   - now independent of global variables
     281             :   !> \authors Stephan Thober
     282             :   !> \date Jun 2014
     283      131082 :   subroutine chunk_config(iDomain, tt, nTstepDay, simPer, timestep, timeStep_model_inputs, read_flag, readPer)
     284             : 
     285          78 :     use mo_common_constants, only : nodata_dp
     286             :     use mo_common_types, only: period
     287             : 
     288             :     implicit none
     289             : 
     290             :     !> current Domain
     291             :     integer(i4), intent(in) :: iDomain
     292             :     !> current timestep
     293             :     integer(i4), intent(in) :: tt
     294             :     !> Number of time intervals per day
     295             :     integer(i4), intent(in) :: nTstepDay
     296             :     !> warmPer + evalPer
     297             :     type(period), dimension(:), intent(in) :: simPer
     298             :     !> [h] simulation time step (= TS) in [h]
     299             :     integer(i4), intent(in) :: timeStep
     300             :     !> frequency for reading meteo input
     301             :     integer(i4), dimension(:), intent(in) :: timeStep_model_inputs
     302             :     !> indicate whether reading data should be read
     303             :     logical, intent(out) :: read_flag
     304             :     ! start and end dates of reading Period
     305             :     type(period), intent(out) :: readPer
     306             : 
     307             :     ! initialize
     308       65541 :     read_flag = .false.
     309       65541 :     if (tt .eq. 1_i4) then
     310          26 :       readPer%julStart = int(nodata_dp, i4)
     311          26 :       readPer%julEnd = int(nodata_dp, i4)
     312          26 :       readPer%dstart = int(nodata_dp, i4)
     313          26 :       readPer%mstart = int(nodata_dp, i4)
     314          26 :       readPer%ystart = int(nodata_dp, i4)
     315          26 :       readPer%dend = int(nodata_dp, i4)
     316          26 :       readper%mend = int(nodata_dp, i4)
     317          26 :       readper%yend = int(nodata_dp, i4)
     318          26 :       readPer%Nobs = int(nodata_dp, i4)
     319             :     end if
     320             : 
     321             :     ! evaluate date and timeStep_model_inputs to get read_flag -------
     322       65541 :     read_flag = is_read(iDomain, tt, nTstepDay, simPer, timestep, timeStep_model_inputs)
     323             :     !
     324             :     ! determine start and end date of chunk to read
     325       65541 :     if (read_flag) call chunk_size(iDomain, tt, nTstepDay, simPer, timeStep_model_inputs, readPer)
     326             :     !
     327       65541 :   end subroutine chunk_config
     328             : 
     329             : 
     330             :   !> \brief evaluate whether new chunk should be read at this timestep
     331             :   !> \changelog
     332             :   !! - Robert Schweppe Jun 2018
     333             :   !!   - refactoring and reformatting
     334             :   !! - Sebastian Müller Mar 2023
     335             :   !!   - used by meteo-handler
     336             :   !!   - now independent of global variables
     337             :   !> \authors Stephan Thober
     338             :   !> \date Jun 2014
     339      131082 :   function is_read(iDomain, tt, nTstepDay, simPer, timestep, timeStep_model_inputs)
     340             : 
     341       65541 :     use mo_common_types, only : period
     342             :     use mo_julian, only : caldat
     343             : 
     344             :     implicit none
     345             : 
     346             :     !> current Domain
     347             :     integer(i4), intent(in) :: iDomain
     348             :     !> current time step
     349             :     integer(i4), intent(in) :: tt
     350             :     !> Number of time intervals per day
     351             :     integer(i4), intent(in) :: nTstepDay
     352             :     !> warmPer + evalPer
     353             :     type(period), dimension(:), intent(in) :: simPer
     354             :     !> [h] simulation time step (= TS) in [h]
     355             :     integer(i4), intent(in) :: timeStep
     356             :     !> frequency for reading meteo input
     357             :     integer(i4), dimension(:), intent(in) :: timeStep_model_inputs
     358             : 
     359             :     logical :: is_read
     360             : 
     361             :     ! number of simulated days
     362             :     integer(i4) :: Ndays
     363             :     ! day
     364             :     integer(i4) :: day
     365             :     ! months
     366             :     integer(i4) :: month
     367             :     ! years
     368             :     integer(i4) :: year
     369             :     ! number of simulated days one timestep before
     370             :     integer(i4) :: Ndays_before
     371             :     ! day one simulated timestep before
     372             :     integer(i4) :: day_before
     373             :     ! month one simulated timestep before
     374             :     integer(i4) :: month_before
     375             :     ! year one simulated timestep before
     376             :     integer(i4) :: year_before
     377             : 
     378             :     ! initialize
     379       65541 :     is_read = .false.
     380             : 
     381             :     ! special case for first timestep
     382       65541 :     if (tt .eq. 1_i4) then
     383             :       is_read = .true.
     384             :     else
     385             :       ! check if a new day started by comparing the day of the current time step (Ndays)
     386             :       ! with the one before (Ndays_before)
     387       65515 :       Ndays = ceiling((real(tt, dp)) / real(nTstepDay, dp))
     388       65515 :       Ndays_before = ceiling((real(tt, dp) - 1.0_dp) / real(nTstepDay, dp))
     389             : 
     390             :       ! evaluate cases of given timeStep_model_inputs
     391       65515 :       select case(timeStep_model_inputs(iDomain))
     392             :       case(0)  ! only at the beginning of the period
     393             :         if (tt .eq. 1_i4) is_read = .true.
     394             :       case(1 :) ! every timestep with frequency timeStep_model_inputs
     395           0 :         if (mod((tt - 1) * timestep, timeStep_model_inputs(iDomain) * 24) .eq. 0_i4) is_read = .true.
     396             :       case(-1) ! every day
     397           0 :         if (Ndays .ne. Ndays_before) is_read = .true.
     398             :       case(-2) ! every month
     399       65515 :         if (Ndays .ne. Ndays_before) then
     400             :           ! calculate months
     401        2725 :           call caldat(simPer(iDomain)%julStart + Ndays - 1, dd = day, mm = month, yy = year)
     402        2725 :           call caldat(simPer(iDomain)%julStart + Ndays_before - 1, dd = day_before, mm = month_before, yy = year_before)
     403        2725 :           if (month .ne. month_before) is_read = .true.
     404             :         end if
     405             :       case(-3) ! every year
     406           0 :         if (Ndays .ne. Ndays_before) then
     407             :           ! calculate months
     408           0 :           call caldat(simPer(iDomain)%julStart + Ndays - 1, dd = day, mm = month, yy = year)
     409           0 :           call caldat(simPer(iDomain)%julStart + Ndays_before - 1, dd = day_before, mm = month_before, yy = year_before)
     410           0 :           if (year .ne. year_before) is_read = .true.
     411             :         end if
     412             :       case default ! not specified correctly
     413       65515 :         call error_message('ERROR*** mo_meteo_helper: function is_read: timStep_model_inputs not specified correctly!')
     414             :       end select
     415             :     end if
     416             : 
     417       65541 :   end function is_read
     418             : 
     419             : 
     420             :   !> \brief calculate beginning and end of read Period, i.e. that is length of current chunk to read
     421             :   !> \changelog
     422             :   !! - Stephan Thober  Jan 2015
     423             :   !!   - added iDomain
     424             :   !! - Robert Schweppe Jun 2018
     425             :   !!   - refactoring and reformatting
     426             :   !! - Sebastian Müller Mar 2023
     427             :   !!   - used by meteo-handler
     428             :   !!   - now independent of global variables
     429             :   !> \authors Stephan Thober
     430             :   !> \date Jun 2014
     431         111 :   subroutine chunk_size(iDomain, tt, nTstepDay, simPer, timeStep_model_inputs, readPer)
     432             : 
     433       65541 :     use mo_common_types, only: period
     434             :     use mo_julian, only : caldat, julday
     435             : 
     436             :     implicit none
     437             : 
     438             :     !> current Domain to process
     439             :     integer(i4), intent(in) :: iDomain
     440             :     !> current time step
     441             :     integer(i4), intent(in) :: tt
     442             :     !> Number of time intervals per day
     443             :     integer(i4), intent(in) :: nTstepDay
     444             :     !> warmPer + evalPer
     445             :     type(period), dimension(:), intent(in) :: simPer
     446             :     !> frequency for reading meteo input
     447             :     integer(i4), dimension(:), intent(in) :: timeStep_model_inputs
     448             :     !> start and end dates of read Period
     449             :     type(period), intent(out) :: readPer
     450             : 
     451             :     ! number of simulated days
     452             :     integer(i4) :: Ndays
     453             :     ! day
     454             :     integer(i4) :: day
     455             :     ! months
     456             :     integer(i4) :: month
     457             :     ! years
     458             :     integer(i4) :: year
     459             : 
     460             :     ! calculate date of start date
     461         111 :     Ndays = ceiling(real(tt, dp) / real(nTstepDay, dp))
     462             : 
     463             :     ! get start date
     464         111 :     readPer%julStart = simPer(iDomain)%julStart + Ndays - 1
     465             : 
     466             :     ! calculate end date according to specified frequency
     467         111 :     select case (timeStep_model_inputs(iDomain))
     468             :     case(0)  ! length of chunk has to cover whole period
     469          21 :       readPer%julEnd = simPer(iDomain)%julEnd
     470             :     case(1 :) ! every timestep with frequency timeStep_model_inputs
     471           0 :       readPer%julEnd = readPer%julStart + timeStep_model_inputs(iDomain) - 1
     472             :     case(-1) ! every day
     473           0 :       readPer%julEnd = readPer%julStart
     474             :     case(-2) ! every month
     475             :       ! calculate date
     476          90 :       call caldat(simPer(iDomain)%julStart + Ndays, dd = day, mm = month, yy = year)
     477             :       ! increment month
     478          90 :       if (month .eq. 12) then
     479           5 :         month = 1
     480           5 :         year = year + 1
     481             :       else
     482          85 :         month = month + 1
     483             :       end if
     484          90 :       readPer%julEnd = julday(dd = 1, mm = month, yy = year) - 1
     485             :     case(-3) ! every year
     486             :       ! calculate date
     487           0 :       call caldat(simPer(iDomain)%julStart + Ndays, dd = day, mm = month, yy = year)
     488           0 :       readPer%julEnd = julday(dd = 31, mm = 12, yy = year)
     489             :     case default ! not specified correctly
     490         111 :       call error_message('ERROR*** mo_meteo_helper: chunk_size: timStep_model_inputs not specified correctly!')
     491             :     end select
     492             : 
     493             :     ! end date should not be greater than end of simulation period
     494         111 :     readPer%julEnd = min(readPer%julEnd, simPer(iDomain)%julEnd)
     495             : 
     496             :     ! calculate the dates of the start and end dates
     497         111 :     call caldat(readPer%julStart, dd = readPer%dstart, mm = readPer%mstart, yy = readPer%ystart)
     498         111 :     call caldat(readPer%julEnd, dd = readPer%dEnd, mm = readPer%mend, yy = readPer%yend)
     499         111 :     readPer%Nobs = readPer%julEnd - readPer%julstart + 1
     500             : 
     501         111 :   end subroutine chunk_size
     502             : 
     503             : END MODULE mo_meteo_helper

Generated by: LCOV version 1.16