LCOV - code coverage report
Current view: top level - app - EDK_driver.f90 (source / functions) Hit Total Coverage
Test: edk coverage Lines: 96 121 79.3 %
Date: 2024-04-30 08:52:45 Functions: 2 2 100.0 %

          Line data    Source code
       1             : !> \file    EDK_driver.f90
       2             : !> \brief   \copybrief ed_kriging
       3             : !> \details \copydetails ed_kriging
       4             : 
       5             : !> \brief   External drift kriging - EDK
       6             : !> \details Perform EDK (daily)
       7             : !!          Store results suitable for mHM
       8             : !!          special version to interpolate values in blocks
       9             : !!          *** can be parallelized ***
      10             : !> \author  Luis Samaniego
      11             : !> \date    21.03.2006
      12             : !> \date    11.06.2010
      13             : !!          - blocks, whole Germany
      14             : !> \date    04.02.2012
      15             : !!          - changed to general edk version (excluded block seperation)
      16             : !> \copyright Copyright 2005-\today, the CHS Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
      17             : !! EDK is released under the LGPLv3+ license \license_note
      18           2 : program ED_Kriging
      19             : 
      20           2 :   use mo_kind                , only: i4, dp, sp
      21             :   use mo_edk_print_message       , only: print_start_message, print_end_message
      22             :   use mo_julian              , only: NDAYS, NDYIN, dec2date, julday
      23             :   use runControl             , only: flagEDK, interMth,        & ! flag for activate kriging, flag for 'OK' or 'EDK'
      24             :     correctNeg,                 & ! pre or temp
      25             :     distZero,                    &
      26             :     flagVario                     ! flag for activate variogram estimation
      27             :   use mainVar                , only: yStart, yEnd, jStart, jEnd, tBuffer, nSta, DEMNcFlag, & ! interpolation time periods
      28             :     grid, gridMeteo,            & ! grid properties of input and output grid
      29             :     nCell, MetSta, &
      30             :     noDataValue
      31             :   use kriging                , only: edk_dist, cell
      32             :   use mo_edk_setvario            , only: setVario, dMatrix
      33             :   use mo_netcdf              , only: NcDataset, NcVariable
      34             :   use mo_edk_write               , only: open_netcdf
      35             :   use mo_message             , only: message
      36             :   use mo_edk                 , only: EDK, clean, WriteDataMeteo
      37             :   use mo_edk_read_data            , only: readData
      38             :   use NetCDFVar              , only: invert_y, variable_name
      39             :   USE mo_timer, ONLY : &
      40             :     timers_init, timer_start, timer_stop, timer_get              ! Timing of processes
      41             :   use mo_string_utils, ONLY : num2str
      42             :   use mo_edk_cli, only: parse_command_line
      43             :   !$ use omp_lib, ONLY : OMP_GET_NUM_THREADS           ! OpenMP routines
      44             :   implicit none
      45             : 
      46             :   character(256)        :: fname
      47             :   character(256)        :: author_name
      48             :   character(256)        :: vname_data
      49             :   integer(i4)           :: i, j, k, t
      50             :   integer(i4)           :: icell              ! loop varaible for cells
      51             :   integer(i4)           :: jDay               ! loop variable - current julian day
      52             :   integer(i4)           :: itimer
      53             :   integer(i4)           :: doy                ! day of year
      54             :   integer(i4)           :: year, month, day   ! current date
      55             :   integer(i4)           :: itime, itemp,sttemp,cnttemp       ! loop variable for chunking write
      56             :   integer(i4)           :: jstarttmp, jendtmp ! more loop variables
      57             :   integer(i4)           :: n_threads          ! OpenMP number of parallel threads
      58             :   integer(i4)           :: ncell_thread
      59             :   integer(i4)           :: iThread
      60             :   integer(i4)           :: loop_factor
      61           2 :   real(sp), allocatable :: tmp_array(:, :, :) ! temporal array for output
      62           2 :   real(sp), allocatable :: tmp_time(:)        ! temporal array for time output
      63           8 :   real(dp)              :: param(3)           ! variogram parameters
      64             :   type(NcDataset)       :: nc_out
      65             :   type(NcVariable)      :: nc_data, nc_time
      66             : 
      67           2 :   call parse_command_line()
      68           2 :   call print_start_message()
      69             : 
      70           2 :   loop_factor = 10 ! factor for setting openMP loop size
      71             : 
      72           2 :   n_threads = 1
      73             :   !$OMP PARALLEL
      74             :   !$ n_threads = OMP_GET_NUM_THREADS()
      75             :   !$OMP END PARALLEL
      76             :   !$ print *, 'Run with OpenMP with ', trim(num2str(n_threads)), ' threads.'
      77             : 
      78             :   ! initialize timers
      79           2 :   call timers_init
      80             : 
      81             :   ! start timer for reading
      82           2 :   itimer = 1
      83           2 :   call timer_start(itimer)
      84             : 
      85           2 :   call message('')
      86           2 :   call message(' >>> Reading data')
      87           2 :   call message('')
      88           2 :   call ReadData
      89           2 :   call timer_stop(itimer)
      90           2 :   call message('')
      91           2 :   call message('    in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
      92           2 :   call message('')
      93             :   ! number of cells per thread
      94           2 :   ncell_thread = ceiling(real(nCell, sp) / real(loop_factor * n_threads, sp))
      95             : 
      96             :   ! sanity check
      97           2 :   if (variable_name == "pre") then
      98           2 :     if ( .not. correctNeg ) call message( &
      99             :       '***WARNING: you are probably interpolating precipitation data, but correctNeg is set .False.', &
     100           0 :       'It should be set to .True. Check namelist!')
     101           2 :     if ( .not. distZero ) call message( &
     102             :       '***WARNING: you are probably interpolating precipitation data, but distZero is set .False. ', &
     103           0 :       'It should be set to .True.  Check namelist!')
     104             :   end if
     105             : 
     106           2 :   itimer = 2
     107           2 :   call timer_start(itimer)
     108           2 :   call message(' >>> Calculating distances and neighborhoods')
     109           2 :   call message('')
     110             :   ! call distance matrix
     111           2 :   call dMatrix
     112           2 :   call timer_stop(itimer)
     113           2 :   call message('')
     114           2 :   call message('    in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
     115           2 :   call message('')
     116             : 
     117           2 :   itimer = 3
     118           2 :   call timer_start(itimer)
     119           2 :   call message(' >>> Estimate variogram')
     120           2 :   call message('')
     121             :   ! estimate variogram
     122           2 :   call setVario(param)
     123             :   ! write variogram
     124           2 :   if (flagVario) call WriteDataMeteo
     125           2 :   call timer_stop(itimer)
     126           2 :   call message('')
     127           2 :   call message('    in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
     128           2 :   call message('')
     129             : 
     130             :   !write(*,*), "jStart = ",jStart
     131             : 
     132           2 :   if (interMth .gt. 0) then
     133           2 :     itimer = 4
     134           2 :     call timer_start(itimer)
     135           2 :     call message(' >>> Perform interpolation')
     136           2 :     call message('')
     137             :     ! open netcdf if necessary
     138           2 :     call open_netcdf(nc_out, nc_data, nc_time)
     139             : 
     140             :     ! do iCell = 1, nCell
     141             :     !   ! initialize cell
     142             :     !   allocate(cell(iCell)%Nk_old(nSta))
     143             :     !   cell(iCell)%Nk_old = nint(noDataValue)
     144             :     ! end do
     145             : 
     146           2 :     if (mod((jEnd - jStart + 1),tBuffer) .eq. 0) then  ! just use mod
     147           0 :       iTime = ((jEnd - jStart + 1)/tBuffer)
     148             :     else
     149           2 :       iTime = ((jEnd - jStart + 1)/tBuffer) + 1
     150             :     end if
     151           2 :     write(*,*) "Total Number of Threads = ",n_threads
     152           2 :     write(*,*) "Total Number of Time Buffers = ",iTime
     153           2 :     t = 0
     154          76 :     bufferloop: do iTemp = 1, iTime
     155          74 :       write(*,*) "  >>> Started buffer #", iTemp
     156          74 :       jStartTmp = jStart + (iTemp - 1) * tBuffer
     157          74 :       if (iTemp .lt. iTime) then
     158          72 :         jEndTmp = jStartTmp + tBuffer - 1
     159             :       else
     160           2 :         jEndTmp = jStartTmp + (jEnd-jStartTmp+1)
     161             :       end if   ! use minimum to never exceed jEnd
     162          74 :       jEndTmp = min(jEndTmp, jEnd)
     163             : 
     164        4514 :       do iCell = 1, nCell
     165             :         ! initialize cell        ! deallocate similarly
     166       13320 :         allocate(cell(iCell)%z(jStartTmp:jEndTmp))
     167       48314 :         cell(iCell)%z = real(noDataValue, sp)
     168             :       end do
     169             : 
     170             :       !print *, iTemp, iTime
     171             : 
     172             :       !$OMP parallel default(shared) &
     173             :       !$OMP private(iThread, iCell)
     174             :       !$OMP do SCHEDULE(dynamic)
     175         814 :       do iThread = 1, loop_factor * n_threads
     176             :         !  print *, 'thread: ', iThread, " start"
     177             : 
     178        5254 :         ncellsloop: do iCell = (iThread - 1) * ncell_thread + 1, min(iThread * ncell_thread, ncell)
     179             : 
     180             :           ! check DEM
     181        4440 :           if (nint(cell(iCell)%h) == grid%nodata_value ) then
     182       19296 :             cell(iCell)%z = gridMeteo%nodata_value
     183             :             cycle
     184             :           end if
     185             :           ! interploation
     186        3404 :           call EDK(iCell, jStartTmp, jEndTmp, edk_dist, MetSta, cell(iCell), doOK=(interMth==1))
     187             :         end do ncellsloop
     188             : 
     189             :         ! print *, 'thread: ', iThread, " end"
     190             :       end do
     191             :       !$OMP end do
     192             :       !$OMP end parallel
     193             : 
     194          74 :       if (DEMNcFlag == 1) then
     195             :         ! write output
     196           0 :         allocate(tmp_array(gridMeteo%nrows, gridMeteo%ncols, jEndTmp - jStartTmp + 1))
     197           0 :         allocate(tmp_time(jEndTmp - jStartTmp + 1))
     198             : 
     199           0 :         k = 0
     200           0 :         if (invert_y) then
     201           0 :           do i = 1, gridMeteo%ncols
     202           0 :             do j = 1, gridMeteo%nrows
     203           0 :               k = k + 1
     204           0 :               tmp_array(j,gridMeteo%ncols - i + 1,:) = cell(k)%z
     205             :             end do
     206             :           end do
     207             :         else
     208           0 :           do i = 1, gridMeteo%ncols
     209           0 :             do j = 1, gridMeteo%nrows
     210           0 :               k = k + 1
     211           0 :               tmp_array(j,i,:) = cell(k)%z
     212             :             end do
     213             :           end do
     214             :         end if
     215             : 
     216           0 :         do i = 1, jEndTmp - jStartTmp + 1
     217           0 :           tmp_time(i) = t
     218           0 :           t = t + 1
     219             :         end do
     220             : 
     221           0 :         sttemp = nint(tmp_time(1)+1)
     222           0 :         cnttemp = nint((tmp_time(size(tmp_time)) - sttemp))+2
     223             : 
     224             :         !write(*,*),"Final Output ",shape(tmp_array)
     225             : 
     226           0 :         call nc_time%setData(values=tmp_time,start=(/sttemp/),cnt=(/cnttemp/))
     227             :         !call nc_data%setData(values=tmp_array,start=(/1,1,sttemp/),cnt=(/size(tmp_array,1),size(tmp_array,2),cnttemp/))
     228           0 :         call nc_data%setData(values=tmp_array,start=(/1,1,sttemp/),cnt=(/size(tmp_array,1),size(tmp_array,2),cnttemp/))
     229             : 
     230             :       else
     231             :         ! write output
     232         370 :         allocate(tmp_array(gridMeteo%ncols, gridMeteo%nrows, jEndTmp - jStartTmp + 1))
     233         222 :         allocate(tmp_time(jEndTmp - jStartTmp + 1))
     234             : 
     235          74 :         k = 0
     236         518 :         do i = 1, gridMeteo%ncols
     237             :           !    do j = 1, gridMeteo%nrows
     238             :           !       k = k + 1
     239             :           !       tmp_array(i, gridMeteo%nrows - j + 1, :) = cell(k)%z
     240             :           !    end do
     241             :           ! end do
     242         518 :           if (invert_y) then
     243        4884 :             do j = gridMeteo%nrows, 1, -1
     244        4440 :               k = k + 1
     245       48684 :               tmp_array(i, gridMeteo%nrows - j + 1, :) = cell(k)%z
     246             :             end do
     247             :           else
     248           0 :             do j = 1, gridMeteo%nrows
     249           0 :               k = k + 1
     250           0 :               tmp_array(i, gridMeteo%nrows - j + 1, :) = cell(k)%z
     251             :             end do
     252             :           end if
     253             :         end do
     254             :         !t = 0
     255             :         !do i = 1,  jEnd - jStart + 1
     256             :         !  tmp_time(i) = t
     257             :         !  t = t + 1
     258             :         !end do
     259             : 
     260         804 :         do i = 1,  jEndTmp - jStartTmp + 1
     261         730 :           tmp_time(i) = t
     262         804 :           t = t + 1
     263             :         end do
     264             : 
     265             :         !write(*,*),tmp_time
     266          74 :         sttemp = nint(tmp_time(1)+1)
     267          74 :         cnttemp = nint((tmp_time(size(tmp_time)) - sttemp))+2
     268             : 
     269             :         !write(*,*),"Final Output ",shape(tmp_array)
     270             : 
     271         222 :         call nc_time%setData(values=tmp_time,start=(/sttemp/),cnt=(/cnttemp/))
     272             :         !call nc_data%setData(values=tmp_array,start=(/1,1,sttemp/),cnt=(/size(tmp_array,1),size(tmp_array,2),cnttemp/))
     273         518 :         call nc_data%setData(values=tmp_array,start=(/1,1,sttemp/),cnt=(/size(tmp_array,1),size(tmp_array,2),cnttemp/))
     274             :       end if
     275             : 
     276          74 :       deallocate(tmp_array, tmp_time)
     277             :       !deallocate(cell)
     278             : 
     279        4516 :       do iCell = 1, nCell
     280             :         ! initialize cell
     281        4514 :         deallocate(cell(iCell)%z)
     282             :         !cell(iCell)%z = noDataValue
     283             :       end do
     284             : 
     285             :       ! close netcdf if necessary
     286             :       !call nc_out%close()   ! outside
     287             : 
     288             :     end do bufferloop
     289             : 
     290             :     ! close netcdf if necessary
     291           2 :     call nc_out%close()
     292             : 
     293           2 :     call timer_stop(itimer)
     294           2 :     call message('')
     295           2 :     call message('    in ', trim(num2str(timer_get(itimer), '(F9.3)')), ' seconds.')
     296           2 :     call message('')
     297             :   end if
     298             :   ! deallocate memory
     299           2 :   call clean
     300             :   !
     301           2 :   call print_end_message()
     302             :   !
     303           2 : end program ED_Kriging

Generated by: LCOV version 1.16