LCOV - code coverage report
Current view: | top level - physics/rrtmgp/ext/rte-frontend - mo_rte_util_array_validation.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 35 | 75 | 46.7 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 9 | 19 | 47.4 %

              Line data    Source code
           1             : ! This code is part of Radiative Transfer for Energetics (RTE)
           2             : !
           3             : ! Contacts: Robert Pincus and Eli Mlawer
           4             : ! email:  rrtmgp@aer.com
           5             : !
           6             : ! Copyright 2015-  Atmospheric and Environmental Research,
           7             : !    Regents of the University of Colorado,
           8             : !    Trustees of Columbia University in the City of New York
           9             : ! All right reserved.
          10             : !
          11             : ! Use and duplication is permitted under the terms of the
          12             : !    BSD 3-clause license, see http://opensource.org/licenses/BSD-3-Clause
          13             : ! -------------------------------------------------------------------------------------------------
          14             : module mo_rte_util_array_validation
          15             : !
          16             : !> Provide utilites for sanitizing input arrays:
          17             : !    checking values and sizes
          18             : ! These are in a module so code can be written for both CPUs and GPUs
          19             : ! Used only by Fortran classes so routines don't need C bindings and can use assumed-shape
          20             : !
          21             :   use mo_rte_kind,      only: wp, wl
          22             :   implicit none
          23             :   !>
          24             :   !> Values less than a floor (including masked versions)
          25             :   !>
          26             :   interface any_vals_less_than
          27             :     module procedure any_vals_less_than_1D,        any_vals_less_than_2D,        any_vals_less_than_3D
          28             :     module procedure any_vals_less_than_1D_masked, any_vals_less_than_2D_masked, any_vals_less_than_3D_masked
          29             :   end interface
          30             :   !>
          31             :   !> Values outside a range (including masked versions)
          32             :   !>
          33             :   interface any_vals_outside
          34             :     module procedure any_vals_outside_1D,        any_vals_outside_2D,        any_vals_outside_3D
          35             :     module procedure any_vals_outside_1D_masked, any_vals_outside_2D_masked, any_vals_outside_3D_masked
          36             :   end interface
          37             :   !>
          38             :   !> Find the extents of an array
          39             :   !>
          40             :   interface extents_are
          41             :     module procedure extents_are_1D, extents_are_2D, extents_are_3D
          42             :     module procedure extents_are_4D, extents_are_5D, extents_are_6D
          43             :     module procedure extents_are_2d_int
          44             :   end interface extents_are
          45             :
          46             :   private
          47             :   public :: any_vals_less_than, any_vals_outside, extents_are
          48             : contains
          49             :   !-------------------------------------------------------------------------------------------------
          50             :   ! Values less than a floor
          51             :   !-------------------------------------------------------------------------------------------------
          52           0 :   logical function any_vals_less_than_1D(array, check_value)
          53             :     real(wp), dimension(:), intent(in) :: array
          54             :     real(wp),               intent(in) :: check_value
          55             :
          56             :     real(wp) :: minValue
          57             :
          58             :     !$acc kernels copyin(array)
          59             :     !$omp target map(to:array) map(from:minValue)
          60           0 :     minValue = minval(array)
          61             :     !$acc end kernels
          62             :     !$omp end target
          63             :
          64           0 :     any_vals_less_than_1D = (minValue < check_value)
          65             :
          66           0 :   end function any_vals_less_than_1D
          67             : !-------------------------------------------------------------------------------------------------
          68     6069330 :   logical function any_vals_less_than_2D(array, check_value)
          69             :     real(wp), dimension(:,:), intent(in) :: array
          70             :     real(wp),                 intent(in) :: check_value
          71             :
          72             :     real(wp) :: minValue
          73             :
          74             :     !$acc kernels copyin(array)
          75             :     !$omp target map(to:array) map(from:minValue)
          76  3374427337 :     minValue = minval(array)
          77             :     !$acc end kernels
          78             :     !$omp end target
          79             :
          80     6069330 :     any_vals_less_than_2D = (minValue < check_value)
          81             :
          82     6069330 :   end function any_vals_less_than_2D
          83             : !-------------------------------------------------------------------------------------------------
          84     4152333 :   logical function any_vals_less_than_3D(array, check_value)
          85             :     real(wp), dimension(:,:,:), intent(in) :: array
          86             :     real(wp),                   intent(in) :: check_value
          87             :
          88             :     real(wp) :: minValue
          89             :
          90             : #ifdef _OPENMP
          91             :     integer :: dim1, dim2, dim3, i, j, k
          92             :     dim1 = size(array,1)
          93             :     dim2 = size(array,2)
          94             :     dim3 = size(array,3)
          95             :     minValue = check_value + epsilon(check_value) ! initialize to some value
          96             :     !$omp target teams map(to:array) &
          97             :     !$omp defaultmap(tofrom:scalar) reduction(min:minValue)
          98             :     !$omp distribute parallel do simd reduction(min:minValue)
          99             :     do i = 1, dim1
         100             :        do j = 1, dim2
         101             :           do k = 1, dim3
         102             :              minValue = min(minValue,array(i,j,k))
         103             :           enddo
         104             :        enddo
         105             :     enddo
         106             :     !$omp end target teams
         107             : #else
         108             :     !$acc kernels copyin(array)
         109 >66614*10^7 :     minValue = minval(array)
         110             :     !$acc end kernels
         111             : #endif
         112             :
         113     4152333 :     any_vals_less_than_3D = (minValue < check_value)
         114             :
         115     4152333 :   end function any_vals_less_than_3D
         116             :   !-------------------------------------------------------------------------------------------------
         117             :   ! Masked versions
         118             :   !-------------------------------------------------------------------------------------------------
         119           0 :   logical function any_vals_less_than_1D_masked(array, mask, check_value)
         120             :     real   (wp), dimension(:), intent(in) :: array
         121             :     logical(wl), dimension(:), intent(in) :: mask
         122             :     real   (wp),               intent(in) :: check_value
         123             :
         124             :     real(wp) :: minValue
         125             :
         126             :     !$acc kernels copyin(array, mask)
         127             :     !$omp target map(to: array, mask) map(from:minValue)
         128           0 :     minValue = minval(array, mask=mask)
         129             :     !$acc end kernels
         130             :     !$omp end target
         131             :
         132           0 :     any_vals_less_than_1D_masked = (minValue < check_value)
         133             :
         134           0 :   end function any_vals_less_than_1D_masked
         135             :   !-------------------------------------------------------------------------------------------------
         136           0 :   logical function any_vals_less_than_2D_masked(array, mask, check_value)
         137             :     real   (wp), dimension(:,:), intent(in) :: array
         138             :     logical(wl), dimension(:,:), intent(in) :: mask
         139             :     real   (wp),                 intent(in) :: check_value
         140             :
         141             :     real(wp) :: minValue
         142             :
         143             :     !$acc kernels copyin(array, mask)
         144             :     !$omp target map(to: array, mask) map(from:minValue)
         145           0 :     minValue = minval(array, mask=mask)
         146             :     !$acc end kernels
         147             :     !$omp end target
         148             :
         149           0 :     any_vals_less_than_2D_masked = (minValue < check_value)
         150             :
         151           0 :   end function any_vals_less_than_2D_masked
         152             :   !-------------------------------------------------------------------------------------------------
         153           0 :   logical function any_vals_less_than_3D_masked(array, mask, check_value)
         154             :     real   (wp), dimension(:,:,:), intent(in) :: array
         155             :     logical(wl), dimension(:,:,:), intent(in) :: mask
         156             :     real   (wp),                   intent(in) :: check_value
         157             :
         158             :     real(wp) :: minValue
         159             :
         160             :     !$acc kernels copyin(array, mask)
         161             :     !$omp target map(to: array, mask) map(from:minValue)
         162           0 :     minValue = minval(array, mask=mask)
         163             :     !$acc end kernels
         164             :     !$omp end target
         165             :
         166           0 :     any_vals_less_than_3D_masked = (minValue < check_value)
         167             :
         168           0 :   end function any_vals_less_than_3D_masked
         169             :   !-------------------------------------------------------------------------------------------------
         170             :   ! Values outside a range
         171             :   !-------------------------------------------------------------------------------------------------
         172      746136 :   logical function any_vals_outside_1D(array, checkMin, checkMax)
         173             :     real(wp), dimension(:), intent(in) :: array
         174             :     real(wp),               intent(in) :: checkMin, checkMax
         175             :
         176             :     real(wp) :: minValue, maxValue
         177             :
         178             :     !$acc kernels copyin(array)
         179             :     !$omp target map(to:array) map(from:minValue, maxValue)
         180    13204872 :     minValue = minval(array)
         181    13204872 :     maxValue = maxval(array)
         182             :     !$acc end kernels
         183             :     !$omp end target
         184      746136 :     any_vals_outside_1D = minValue < checkMin .or. maxValue > checkMax
         185             :
         186      746136 :   end function any_vals_outside_1D
         187             : ! ----------------------------------------------------------
         188    15181840 :   logical function any_vals_outside_2D(array, checkMin, checkMax)
         189             :     real(wp), dimension(:,:), intent(in) :: array
         190             :     real(wp),                 intent(in) :: checkMin, checkMax
         191             :
         192             :     real(wp) :: minValue, maxValue
         193             :
         194             :     !$acc kernels copyin(array)
         195             :     !$omp target map(to:array) map(from:minValue, maxValue)
         196 19520995144 :     minValue = minval(array)
         197 19520995144 :     maxValue = maxval(array)
         198             :     !$acc end kernels
         199             :     !$omp end target
         200    15181840 :     any_vals_outside_2D = minValue < checkMin .or. maxValue > checkMax
         201             :
         202    15181840 :   end function any_vals_outside_2D
         203             : ! ----------------------------------------------------------
         204     2335578 :   logical function any_vals_outside_3D(array, checkMin, checkMax)
         205             :     real(wp), dimension(:,:,:), intent(in) :: array
         206             :     real(wp),                   intent(in) :: checkMin, checkMax
         207             :
         208             :       ! Compact version using intrinsics below
         209             :       ! but an explicit loop is the only current solution on GPUs
         210             :     real(wp) :: minValue, maxValue
         211             :
         212             :
         213             : #ifdef _OPENMP
         214             :     integer :: dim1, dim2, dim3, i, j, k
         215             :     dim1 = size(array,1)
         216             :     dim2 = size(array,2)
         217             :     dim3 = size(array,3)
         218             :     minValue = checkMin + epsilon(checkMin) ! initialize to some value
         219             :     maxValue = checkMax - epsilon(checkMax) ! initialize to some value
         220             :     !$omp target teams map(to:array) &
         221             :     !$omp defaultmap(tofrom:scalar) reduction(min:minValue) reduction(max:maxValue)
         222             :     !$omp distribute parallel do simd reduction(min:minValue) reduction(max:maxValue)
         223             :     do i= 1, dim1
         224             :        do j = 1, dim2
         225             :           do k = 1, dim3
         226             :              minValue = min(minValue,array(i,j,k))
         227             :              maxValue = max(maxValue,array(i,j,k))
         228             :           enddo
         229             :        enddo
         230             :     enddo
         231             :     !$omp end target teams
         232             : #else
         233             :     !$acc kernels copyin(array)
         234 >39478*10^7 :     minValue = minval(array)
         235 >39478*10^7 :     maxValue = maxval(array)
         236             :     !$acc end kernels
         237             : #endif
         238             :
         239     2335578 :     any_vals_outside_3D = minValue < checkMin .or. maxValue > checkMax
         240             :
         241     2335578 :   end function any_vals_outside_3D
         242             :   ! ----------------------------------------------------------
         243             :   ! Masked versions
         244             :   ! ----------------------------------------------------------
         245           0 :   logical function any_vals_outside_1D_masked(array, mask, checkMin, checkMax)
         246             :     real   (wp), dimension(:), intent(in) :: array
         247             :     logical(wl), dimension(:), intent(in) :: mask
         248             :     real(wp),                  intent(in) :: checkMin, checkMax
         249             :
         250             :     real(wp) :: minValue, maxValue
         251             :
         252             :     !$acc kernels copyin(array, mask)
         253             :     !$omp target map(to: array, mask) map(from:minValue, maxValue)
         254           0 :     minValue = minval(array, mask=mask)
         255           0 :     maxValue = maxval(array, mask=mask)
         256             :     !$acc end kernels
         257             :     !$omp end target
         258           0 :     any_vals_outside_1D_masked = minValue < checkMin .or. maxValue > checkMax
         259             :
         260           0 :   end function any_vals_outside_1D_masked
         261             : ! ----------------------------------------------------------
         262           0 :   logical function any_vals_outside_2D_masked(array, mask, checkMin, checkMax)
         263             :     real   (wp), dimension(:,:), intent(in) :: array
         264             :     logical(wl), dimension(:,:), intent(in) :: mask
         265             :     real(wp),                    intent(in) :: checkMin, checkMax
         266             :
         267             :     real(wp) :: minValue, maxValue
         268             :
         269             :     !$acc kernels copyin(array, mask)
         270             :     !$omp target map(to: array, mask) map(from:minValue, maxValue)
         271           0 :     minValue = minval(array, mask=mask)
         272           0 :     maxValue = maxval(array, mask=mask)
         273             :     !$acc end kernels
         274             :     !$omp end target
         275           0 :     any_vals_outside_2D_masked = minValue < checkMin .or. maxValue > checkMax
         276             :
         277           0 :   end function any_vals_outside_2D_masked
         278             : ! ----------------------------------------------------------
         279           0 :   logical function any_vals_outside_3D_masked(array, mask, checkMin, checkMax)
         280             :     real   (wp), dimension(:,:,:), intent(in) :: array
         281             :     logical(wl), dimension(:,:,:), intent(in) :: mask
         282             :     real(wp),                      intent(in) :: checkMin, checkMax
         283             :
         284             :     real(wp) :: minValue, maxValue
         285             :
         286             :     !$acc kernels copyin(array, mask)
         287             :     !$omp target map(to: array, mask) map(from:minValue, maxValue)
         288           0 :     minValue = minval(array, mask=mask)
         289           0 :     maxValue = maxval(array, mask=mask)
         290             :     !$acc end kernels
         291             :     !$omp end target
         292           0 :     any_vals_outside_3D_masked = minValue < checkMin .or. maxValue > checkMax
         293             :
         294           0 :   end function any_vals_outside_3D_masked
         295             :   !--------------------------------------------------------------------------------------------------------------------
         296             :   !
         297             :   ! Extents
         298             :   !
         299             :   ! --------------------------------------------------------------------------------------
         300      746136 :   function extents_are_1d(array, n1)
         301             :     real(wp), dimension(:          ), intent(in) :: array
         302             :     integer,                          intent(in) :: n1
         303             :     logical(wl)                                  :: extents_are_1d
         304             :
         305      746136 :     extents_are_1d = (size(array,1) == n1)
         306      746136 :   end function extents_are_1d
         307             :   ! --------------------------------------------------------------------------------------
         308    12197296 :   function extents_are_2d(array, n1, n2)
         309             :     real(wp), dimension(:,:        ), intent(in) :: array
         310             :     integer,                          intent(in) :: n1, n2
         311             :     logical(wl)                                  :: extents_are_2d
         312             :
         313             :     extents_are_2d = (size(array,1) == n1 .and. &
         314    12197296 :                       size(array,2) == n2 )
         315    12197296 :   end function extents_are_2d
         316             :   ! --------------------------------------------------------------------------------------
         317     5417292 :   function extents_are_3d(array, n1, n2, n3)
         318             :     real(wp), dimension(:,:,:      ), intent(in) :: array
         319             :     integer,                          intent(in) :: n1, n2, n3
         320             :     logical(wl)                                  :: extents_are_3d
         321             :
         322             :     extents_are_3d = (size(array,1) == n1 .and. &
         323             :                       size(array,2) == n2 .and. &
         324     5417292 :                       size(array,3) == n3)
         325     5417292 :   end function extents_are_3d
         326             :   ! --------------------------------------------------------------------------------------
         327           0 :   function extents_are_4d(array, n1, n2, n3, n4)
         328             :     real(wp), dimension(:,:,:,:    ), intent(in) :: array
         329             :     integer,                          intent(in) :: n1, n2, n3, n4
         330             :     logical(wl)                                  :: extents_are_4d
         331             :
         332             :     extents_are_4d = (size(array,1) == n1 .and. &
         333             :                       size(array,2) == n2 .and. &
         334             :                       size(array,3) == n3 .and. &
         335           0 :                       size(array,4) == n4)
         336           0 :   end function extents_are_4d
         337             :   ! --------------------------------------------------------------------------------------
         338           0 :   function extents_are_5d(array, n1, n2, n3, n4, n5)
         339             :     real(wp), dimension(:,:,:,:,:  ), intent(in) :: array
         340             :     integer,                          intent(in) :: n1, n2, n3, n4, n5
         341             :     logical(wl)                                  :: extents_are_5d
         342             :
         343             :     extents_are_5d = (size(array,1) == n1 .and. &
         344             :                       size(array,2) == n2 .and. &
         345             :                       size(array,3) == n3 .and. &
         346             :                       size(array,4) == n4 .and. &
         347           0 :                       size(array,5) == n5 )
         348           0 :   end function extents_are_5d
         349             :   ! --------------------------------------------------------------------------------------
         350           0 :   function extents_are_6d(array, n1, n2, n3, n4, n5, n6)
         351             :     real(wp), dimension(:,:,:,:,:,:), intent(in) :: array
         352             :     integer,                          intent(in) :: n1, n2, n3, n4, n5, n6
         353             :     logical(wl)                                  :: extents_are_6d
         354             :
         355             :     extents_are_6d = (size(array,1) == n1 .and. &
         356             :                       size(array,2) == n2 .and. &
         357             :                       size(array,3) == n3 .and. &
         358             :                       size(array,4) == n4 .and. &
         359             :                       size(array,5) == n5 .and. &
         360           0 :                       size(array,6) == n6 )
         361           0 :   end function extents_are_6d
         362             :   ! --------------------------------------------------------------------------------------
         363     3020006 :   function extents_are_2d_int(array, n1, n2)
         364             :     integer,  dimension(:,:        ), intent(in) :: array
         365             :     integer,                          intent(in) :: n1, n2
         366             :     logical(wl)                                  :: extents_are_2d_int
         367             :
         368             :     extents_are_2d_int = (size(array,1) == n1 .and. &
         369     3020006 :                           size(array,2) == n2 )
         370     3020006 :   end function extents_are_2d_int
         371             :
         372             : end module mo_rte_util_array_validation

Generated by: LCOV version 1.14