LCOV - code coverage report
Current view: top level - MPR - mo_mpr_smhorizons.f90 (source / functions) Hit Total Coverage
Test: mHM coverage Lines: 127 204 62.3 %
Date: 2024-04-30 08:53:32 Functions: 1 1 100.0 %

          Line data    Source code
       1             : !> \file mo_mpr_smhorizons.f90
       2             : !> \brief \copybrief mo_mpr_smhorizons
       3             : !> \details \copydetails mo_mpr_smhorizons
       4             : 
       5             : !> \brief setting up the soil moisture horizons
       6             : !> \details This module sets up the soil moisture horizons
       7             : !> \authors Stephan Thober, Rohini Kumar
       8             : !> \date Dec 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_mpr
      12             : module mo_mpr_SMhorizons
      13             : 
      14             :   use mo_kind, only : i4, dp
      15             :   use mo_common_constants, only : nodata_dp
      16             : 
      17             :   implicit none
      18             : 
      19             :   public :: mpr_SMhorizons
      20             : 
      21             :   private
      22             : 
      23             : contains
      24             : 
      25             :   ! ----------------------------------------------------------------------------
      26             : 
      27             :   !    NAME
      28             :   !        mpr_SMhorizons
      29             : 
      30             :   !    PURPOSE
      31             :   !>       \brief upscale soil moisture horizons
      32             : 
      33             :   !>       \details calculate soil properties at the level 1.
      34             :   !>       Global parameters needed (see mhm_parameter.nml):
      35             :   !>       - param(1) = rootFractionCoefficient_forest
      36             :   !>       - param(2) = rootFractionCoefficient_impervious
      37             :   !>       - param(3) = rootFractionCoefficient_pervious
      38             :   !>       - param(4) = infiltrationShapeFactor
      39             : 
      40             :   !    INTENT(IN)
      41             :   !>       \param[in] "real(dp), dimension(:) :: param"               parameters
      42             :   !>       \param[in] "integer(i4), dimension(:, :) :: processMatrix" - matrix specifying user defined processes
      43             :   !>       \param[in] "integer(i4) :: iFlag_soil"                     - flags for handling multiple soil databases
      44             :   !>       \param[in] "integer(i4) :: nHorizons_mHM"                  - number of horizons to model
      45             :   !>       \param[in] "real(dp), dimension(:) :: HorizonDepth"        [10^-3 m] horizon depth from
      46             :   !>       surface, postive downwards
      47             :   !>       \param[in] "integer(i4), dimension(:) :: LCOVER0"          Land cover at level 0
      48             :   !>       \param[in] "integer(i4), dimension(:, :) :: soilID0"       soil ID at level 0
      49             :   !>       \param[in] "integer(i4), dimension(:) :: nHorizons"        horizons per soil type
      50             :   !>       \param[in] "integer(i4), dimension(:) :: nTillHorizons"    Number of Tillage horizons
      51             :   !>       \param[in] "real(dp), dimension(:, :, :) :: thetaS_till"   saturated water content of soil
      52             :   !>       horizons upto tillage depth,
      53             :   !>       f(OM, management)
      54             :   !>       \param[in] "real(dp), dimension(:, :, :) :: thetaFC_till"  Field capacity of tillage
      55             :   !>       layers; LUC dependent,
      56             :   !>       f(OM, management)
      57             :   !>       \param[in] "real(dp), dimension(:, :, :) :: thetaPW_till"  Permament wilting point of
      58             :   !>       tillage layers; LUC dependent,
      59             :   !>       f(OM, management)
      60             :   !>       \param[in] "real(dp), dimension(:, :) :: thetaS"           saturated water content of soil
      61             :   !>       horizons after tillage depth
      62             :   !>       \param[in] "real(dp), dimension(:, :) :: thetaFC"          Field capacity of deeper layers
      63             :   !>       \param[in] "real(dp), dimension(:, :) :: thetaPW"          Permanent wilting point of
      64             :   !>       deeper layers
      65             :   !>       \param[in] "real(dp), dimension(:, :, :) :: Wd"            weights of mHM Horizons
      66             :   !>       according to horizons provided
      67             :   !>       in soil database
      68             :   !>       \param[in] "real(dp), dimension(:, :, :) :: Db"            Bulk density
      69             :   !>       \param[in] "real(dp), dimension(:, :) :: DbM"              mineral Bulk density
      70             :   !>       \param[in] "real(dp), dimension(:) :: RZdepth"             [mm]       Total soil depth
      71             :   !>       \param[in] "logical, dimension(:, :) :: mask0"             mask at L0
      72             :   !>       \param[in] "integer(i4), dimension(:) :: cell_id0"         Cell ids of hi res field
      73             :   !>       \param[in] "integer(i4), dimension(:) :: upp_row_L1"       Upper row of hi res block
      74             :   !>       \param[in] "integer(i4), dimension(:) :: low_row_L1"       Lower row of hi res block
      75             :   !>       \param[in] "integer(i4), dimension(:) :: lef_col_L1"       Left column of hi res block
      76             :   !>       \param[in] "integer(i4), dimension(:) :: rig_col_L1"       Right column of hi res block
      77             :   !>       \param[in] "integer(i4), dimension(:) :: nL0_in_L1"        Number of L0 cells within a L1 cel
      78             : 
      79             :   !    INTENT(INOUT)
      80             :   !>       \param[inout] "real(dp), dimension(:, :) :: L1_beta"   Parameter that determines the
      81             :   !>       relative contribution to SM, upscaled
      82             :   !>       Bulk density
      83             :   !>       \param[inout] "real(dp), dimension(:, :) :: L1_SMs"    [10^-3 m] depth of saturated SM cont
      84             :   !>       \param[inout] "real(dp), dimension(:, :) :: L1_FC"     [10^-3 m] field capacity
      85             :   !>       \param[inout] "real(dp), dimension(:, :) :: L1_PW"     [10^-3 m] permanent wilting point
      86             :   !>       \param[inout] "real(dp), dimension(:, :) :: L1_fRoots" fraction of roots in soil horizons
      87             : 
      88             :   !    HISTORY
      89             :   !>       \authors Luis Samaniego, Rohini Kumar, Stephan Thober
      90             : 
      91             :   !>       \date Dec 2012
      92             : 
      93             :   ! Modifications:
      94             :   ! Stephan Thober                  Jan 2013 - updated calling sequence for upscaling operators
      95             :   ! Juliane Mai                     Oct 2013 - OLD parametrization
      96             :   !                                                --> param(1) = rootFractionCoefficient_forest
      97             :   !                                                --> param(2) = rootFractionCoefficient_impervious
      98             :   !                                                --> param(3) = rootFractionCoefficient_pervious
      99             :   !                                                --> param(4) = infiltrationShapeFactor
     100             :   !                                             -------------------------------
     101             :   !                                             rootFractionCoeff_perv   = rootFractionCoeff_forest - delta_1
     102             :   !                                             -------------------------------
     103             :   !                                             NEW parametrization
     104             :   !                                                --> param(1) = rootFractionCoefficient_forest
     105             :   !                                                --> param(2) = rootFractionCoefficient_impervious
     106             :   !                                                --> param(3) = delta_1
     107             :   !                                                --> param(4) = infiltrationShapeFactor
     108             :   !                                                ! if processMatrix(3,1) = 3 and 4 additionally
     109             :   !                                                --> param(5) = rootFractionCoefficient_sand
     110             :   !                                                --> param(6) = rootFractionCoefficient_clay
     111             :   !                                                --> param(7) = FCmin_glob
     112             :   !                                                --> param(8) = FCdelta_glob
     113             :   ! Stephan Thober                  Mar 2014 - added omp parallelization
     114             :   ! Rohini Kumar                    Mar 2016 - changes for handling multiple soil database options
     115             :   ! M. Cuneyd Demirel, Simon Stisen Apr 2017 - added FC dependency on root fraction coefficient
     116             :   ! Robert Schweppe Jun 2018 - refactoring and reformatting
     117             :   ! M. Cuneyd Demirel, Simon Stisen Jun 2020 - added Feddes and FC dependency on root fraction coefficient processCase(3) = 4
     118             :   ! M. Cuneyd Demirel, Simon Stisen Feb 2021 - Bug fix normalization of FCnorm
     119             : 
     120         828 :   subroutine mpr_SMhorizons(param, processMatrix, iFlag_soil, nHorizons_mHM, HorizonDepth, LCOVER0, soilID0, nHorizons, &
     121        1242 :                            nTillHorizons, thetaS_till, thetaFC_till, thetaPW_till, thetaS, thetaFC, thetaPW, Wd, Db, &
     122         828 :                            DbM, RZdepth, mask0, cell_id0, upp_row_L1, low_row_L1, lef_col_L1, rig_col_L1, nL0_in_L1, &
     123         828 :                            L1_beta, L1_SMs, L1_FC, L1_PW, L1_fRoots, &
     124             :                            ! neutron count
     125         414 :                            latWat_till   , & ! lattice water upto tillage depth
     126         828 :                            COSMIC_L3_till, & ! COSMIC parameter L3 upto tillage depth
     127         414 :                            latWat        , & ! lattice water
     128         414 :                            COSMIC_L3     , & ! COSMIC paramter L3
     129         414 :                            L1_bulkDens   , & ! L bulk density
     130         414 :                            L1_latticeWater,& ! L1 lattice water content
     131         414 :                            L1_COSMICL3   )   ! L1 COSMIC L3 parameter from neutron module
     132             : 
     133             :     use mo_message, only : message, error_message
     134             :     use mo_string_utils, only : num2str
     135             :     use mo_upscaling_operators, only : upscale_harmonic_mean
     136             :     !$ use omp_lib
     137             : 
     138             :     implicit none
     139             : 
     140             :     ! parameters
     141             :     real(dp), dimension(:), intent(in) :: param
     142             : 
     143             :     ! - matrix specifying user defined processes
     144             :     integer(i4), dimension(:, :), intent(in) :: processMatrix
     145             : 
     146             :     ! - flags for handling multiple soil databases
     147             :     integer(i4), intent(in) :: iFlag_soil
     148             : 
     149             :     ! - number of horizons to model
     150             :     integer(i4), intent(in) :: nHorizons_mHM
     151             : 
     152             :     ! [10^-3 m] horizon depth from
     153             :     ! surface, postive downwards
     154             :     real(dp), dimension(:), intent(in) :: HorizonDepth
     155             : 
     156             :     ! Land cover at level 0
     157             :     integer(i4), dimension(:), intent(in) :: LCOVER0
     158             : 
     159             :     ! soil ID at level 0
     160             :     integer(i4), dimension(:, :), intent(in) :: soilID0
     161             : 
     162             :     ! horizons per soil type
     163             :     integer(i4), dimension(:), intent(in) :: nHorizons
     164             : 
     165             :     ! Number of Tillage horizons
     166             :     integer(i4), dimension(:), intent(in) :: nTillHorizons
     167             : 
     168             :     ! saturated water content of soil
     169             :     ! horizons upto tillage depth,
     170             :     ! f(OM, management)
     171             :     real(dp), dimension(:, :, :), intent(in) :: thetaS_till
     172             : 
     173             :     ! Field capacity of tillage
     174             :     ! layers; LUC dependent,
     175             :     ! f(OM, management)
     176             :     real(dp), dimension(:, :, :), intent(in) :: thetaFC_till
     177             : 
     178             :     ! Permament wilting point of
     179             :     ! tillage layers; LUC dependent,
     180             :     ! f(OM, management)
     181             :     real(dp), dimension(:, :, :), intent(in) :: thetaPW_till
     182             : 
     183             :     ! saturated water content of soil
     184             :     ! horizons after tillage depth
     185             :     real(dp), dimension(:, :), intent(in) :: thetaS
     186             : 
     187             :     ! Field capacity of deeper layers
     188             :     real(dp), dimension(:, :), intent(in) :: thetaFC
     189             : 
     190             :     ! Permanent wilting point of
     191             :     ! deeper layers
     192             :     real(dp), dimension(:, :), intent(in) :: thetaPW
     193             : 
     194             :     ! weights of mHM Horizons
     195             :     ! according to horizons provided
     196             :     ! in soil database
     197             :     real(dp), dimension(:, :, :), intent(in) :: Wd
     198             : 
     199             :     ! Bulk density
     200             :     real(dp), dimension(:, :, :), intent(in) :: Db
     201             : 
     202             :     ! mineral Bulk density
     203             :     real(dp), dimension(:, :), intent(in) :: DbM
     204             : 
     205             :     ! [mm]       Total soil depth
     206             :     real(dp), dimension(:), intent(in) :: RZdepth
     207             : 
     208             :     ! mask at L0
     209             :     logical, dimension(:, :), intent(in) :: mask0
     210             : 
     211             :     ! Cell ids of hi res field
     212             :     integer(i4), dimension(:), intent(in) :: cell_id0
     213             : 
     214             :     ! Upper row of hi res block
     215             :     integer(i4), dimension(:), intent(in) :: upp_row_L1
     216             : 
     217             :     ! Lower row of hi res block
     218             :     integer(i4), dimension(:), intent(in) :: low_row_L1
     219             : 
     220             :     ! Left column of hi res block
     221             :     integer(i4), dimension(:), intent(in) :: lef_col_L1
     222             : 
     223             :     ! Right column of hi res block
     224             :     integer(i4), dimension(:), intent(in) :: rig_col_L1
     225             : 
     226             :     ! Number of L0 cells within a L1 cel
     227             :     integer(i4), dimension(:), intent(in) :: nL0_in_L1
     228             : 
     229             :     ! Parameter that determines the
     230             :     ! relative contribution to SM, upscaled
     231             :     ! Bulk density
     232             :     real(dp), dimension(:, :), intent(inout) :: L1_beta
     233             : 
     234             :     ! [10^-3 m] depth of saturated SM cont
     235             :     real(dp), dimension(:, :), intent(inout) :: L1_SMs
     236             : 
     237             :     ! [10^-3 m] field capacity
     238             :     real(dp), dimension(:, :), intent(inout) :: L1_FC
     239             : 
     240             :     ! [10^-3 m] permanent wilting point
     241             :     real(dp), dimension(:, :), intent(inout) :: L1_PW
     242             : 
     243             :     ! fraction of roots in soil horizons
     244             :     real(dp), dimension(:, :), intent(inout) :: L1_fRoots
     245             : 
     246             :     ! neutron count
     247             :     real(dp), dimension(:,:,:), intent(in) :: latWat_till   ! lattice water
     248             :     real(dp), dimension(:,:,:), intent(in) :: COSMIC_L3_till! COSMIC parameter L3
     249             :     real(dp), dimension(:,:),   intent(in) :: latWat        ! lattice water
     250             :     real(dp), dimension(:,:),   intent(in) :: COSMIC_L3     ! COSMIC paramter L3
     251             :     ! out
     252             :     real(dp), dimension(:,:), intent(inout) :: L1_bulkDens
     253             :     real(dp), dimension(:,:), intent(inout) :: L1_latticeWater
     254             :     real(dp), dimension(:,:), intent(inout) :: L1_COSMICL3
     255             : 
     256             : 
     257             :     ! loop index
     258             :     integer(i4) :: h
     259             : 
     260             :     ! loop index
     261             :     integer(i4) :: k
     262             : 
     263             :     ! loop index
     264             :     integer(i4) :: l
     265             : 
     266             :     ! loop index
     267             :     integer(i4) :: s
     268             : 
     269    19167964 :     real(dp) :: dpth_f
     270             : 
     271    19167964 :     real(dp) :: dpth_t
     272             : 
     273    19167964 :     real(dp) :: fTotRoots
     274             : 
     275             :     ! beta 0
     276    19167964 :     real(dp), dimension(size(LCOVER0, 1)) :: beta0
     277             : 
     278             :     ! [10^3 kg/m3] Bulk density
     279    19168378 :     real(dp), dimension(size(LCOVER0, 1)) :: Bd0
     280             : 
     281             :     ! [10^-3 m] depth of saturated SM cont
     282    19167550 :     real(dp), dimension(size(LCOVER0, 1)) :: SMs0
     283             : 
     284             :     ! [10^-3 m] field capacity
     285    19167964 :     real(dp), dimension(size(LCOVER0, 1)) :: FC0
     286             : 
     287             :     ! [10^-3 m] permanent wilting point
     288    19168378 :     real(dp), dimension(size(LCOVER0, 1)) :: PW0
     289             : 
     290             :     ! neutron count
     291    19168378 :     real(dp), dimension(size(LCOVER0,1))    :: LW0     ! lattice water
     292    19168378 :     real(dp), dimension(size(LCOVER0,1))    :: L30     ! COSMIC parameter L3
     293             : 
     294             : 
     295             :     ! fraction of roots in soil horizons
     296    19168378 :     real(dp), dimension(size(LCOVER0, 1)) :: fRoots0
     297             : 
     298    19167964 :     real(dp) :: tmp_rootFractionCoefficient_forest
     299             : 
     300    19167964 :     real(dp) :: tmp_rootFractionCoefficient_impervious
     301             : 
     302    19167964 :     real(dp) :: tmp_rootFractionCoefficient_pervious
     303             : 
     304             :     ! Field capacity dependent
     305             :     ! root frac coeffiecient
     306    19167964 :     real(dp) :: tmp_rootFractionCoefficient_perviousFC
     307             : 
     308             :     ! Model parameter describing the threshold for
     309             :     ! actual ET reduction for sand
     310    19167964 :     real(dp) :: tmp_rootFractionCoefficient_sand
     311             : 
     312             :     ! Model parameter describing the threshold for actual
     313             :     ! ET reduction for clay
     314    19167964 :     real(dp) :: tmp_rootFractionCoefficient_clay
     315             : 
     316    19167964 :     real(dp) :: FCmin_glob
     317             : 
     318             :     ! real(dp) :: FCdelta_glob
     319             : 
     320    19167964 :     real(dp) :: FCmax_glob
     321             : 
     322    19167964 :     real(dp) :: FCnorm
     323             :     ! the minimum number of till horizons
     324             :     integer(i4) :: min_nTH
     325             : 
     326             : 
     327      611064 :     min_nTH = minval(nTillHorizons(:))
     328         414 :     tmp_rootFractionCoefficient_forest     = param(1)     ! min(1.0_dp, param(2) + param(3) + param(1))
     329         414 :     tmp_rootFractionCoefficient_impervious = param(2)
     330             : 
     331             :     ! decide which parameterization should be used for route fraction:
     332         414 :     select case (processMatrix(3, 1))
     333             :     case(1,2)
     334             :        ! 1 and 2 - dependent on land cover
     335         410 :        tmp_rootFractionCoefficient_pervious = param(1) - param(3) ! min(1.0_dp, param(2) + param(3))
     336             :        !write(*,*) 'tmp_rootFractionCoefficient_forest     = ', tmp_rootFractionCoefficient_forest
     337             :        !write(*,*) 'tmp_rootFractionCoefficient_impervious = ', tmp_rootFractionCoefficient_impervious
     338             :        !write(*,*) 'tmp_rootFractionCoefficient_pervious   = ', tmp_rootFractionCoefficient_pervious
     339             :     case(3,4)
     340             :        ! 3 and 4 - dependent on land cover and additionally soil texture
     341           4 :        tmp_rootFractionCoefficient_pervious = param(3) ! min(1.0_dp, param(2) + param(3))
     342             :        !delta approach is used as in tmp_rootFractionCoefficient_pervious
     343           4 :        tmp_rootFractionCoefficient_sand = param(6) - param(5)
     344             :        !the value in parameter namelist is before substraction i.e. param(5)
     345           4 :        tmp_rootFractionCoefficient_clay = param(6)
     346           4 :        FCmin_glob=param(7)
     347         418 :        FCmax_glob=param(7)+param(8)
     348             :        !write(*,*) 'tmp_rootFractionCoefficient_forest     = ', tmp_rootFractionCoefficient_forest
     349             :        !write(*,*) 'tmp_rootFractionCoefficient_impervious = ', tmp_rootFractionCoefficient_impervious
     350             :        !write(*,*) 'tmp_rootFractionCoefficient_pervious   = ', tmp_rootFractionCoefficient_pervious
     351             :        !write(*,*) 'tmp_rootFractionCoefficient_sand       = ', tmp_rootFractionCoefficient_sand
     352             :        !write(*,*) 'tmp_rootFractionCoefficient_clay       = ', tmp_rootFractionCoefficient_clay
     353             :        !write(*,*) 'FCmin_glob = ', FCmin_glob
     354             :        !write(*,*) 'FCmax_glob = ', FCmax_glob
     355             :     end select
     356             : 
     357             : 
     358             :     ! select case according to a given soil database flag
     359         828 :     SELECT CASE(iFlag_soil)
     360             :       ! classical mHM soil database format
     361             :     CASE(0)
     362        1242 :        do h = 1, nHorizons_mHM
     363             : 
     364    38335928 :           Bd0  = nodata_dp
     365    38335928 :           SMs0 = nodata_dp
     366    38335928 :           FC0  = nodata_dp
     367    38335928 :           PW0  = nodata_dp
     368    38335928 :           fRoots0 = nodata_dp
     369    38335928 :           tmp_rootFractionCoefficient_perviousFC = nodata_dp
     370             : 
     371             :           ! neutron count
     372    38335928 :           LW0 = nodata_dp
     373    38335928 :           L30 = nodata_dp
     374             : 
     375             :           ! Initalise mHM horizon depth
     376             :           ! Last layer depth is soil type dependent, and hence it assigned within the inner loop
     377             :           ! by default for the first soil layer
     378         828 :           dpth_f = 0.0_dp
     379         828 :           dpth_t = HorizonDepth(H)
     380             :           ! check for the layer (2, ... n-1 layers) update depth
     381         828 :           if( (H .gt. 1) .and. (H .lt. nHorizons_mHM) ) then
     382           0 :              dpth_f = HorizonDepth(H-1)
     383             :              dpth_t = HorizonDepth(H)
     384             :           end if
     385             : 
     386             :           !$OMP PARALLEL
     387             :           !$OMP DO PRIVATE( l, s ) SCHEDULE( STATIC )
     388    38335928 :           cellloop0 : do k = 1, size(LCOVER0, 1)
     389    38335100 :              l = LCOVER0(k)
     390    38335100 :              s = soilID0(k, 1)  ! >> in this case the second dimension of soilId0 = 1
     391             :              ! depth weightage bulk density
     392   191675500 :              Bd0(k) = sum(Db(s, : nTillHorizons(s), L) * Wd(S, H, 1 : nTillHorizons(S)), &
     393             :                   Wd(S, H, 1 : nTillHorizons(S)) > 0.0_dp) &
     394    38335100 :                   + sum(dbM(S, nTillHorizons(S) + 1 : nHorizons(S)) &
     395           0 :                   * Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)), &
     396   345015900 :                   Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)) >= 0.0_dp)
     397             :              ! depth weightage thetaS
     398    76670200 :              SMs0(k) = sum(thetaS_till(S, : nTillHorizons(s), L) &
     399    38335100 :                   * Wd(S, H, 1 : nTillHorizons(S)), &
     400             :                   Wd(S, H, 1 : nTillHorizons(S)) > 0.0_dp) &
     401           0 :                   + sum(thetaS(S, nTillHorizons(S) + 1 - min_nTH : nHorizons(s) - min_nTH) &
     402           0 :                   * Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)), &
     403   230010600 :                   Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)) > 0.0_dp)
     404             :              ! depth weightage FC
     405    76670200 :              FC0(k) = sum(thetaFC_till(S, : nTillHorizons(s), L) &
     406    38335100 :                   * Wd(S, H, 1 : nTillHorizons(S)), &
     407             :                   Wd(S, H, 1 : nTillHorizons(S)) > 0.0_dp) &
     408           0 :                   + sum(thetaFC(S, nTillHorizons(S) + 1 - min_nTH : nHorizons(s) - min_nTH) &
     409           0 :                   * Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)), &
     410   230010600 :                   Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)) > 0.0_dp)
     411             :              ! depth weightage PWP
     412    76670200 :              PW0(k) = sum(thetaPW_till(S, : nTillHorizons(s), L) &
     413    38335100 :                   * Wd(S, H, 1 : nTillHorizons(S)), &
     414             :                   Wd(S, H, 1 : nTillHorizons(S)) > 0.0_dp) &
     415           0 :                   + sum(thetaPW(S, nTillHorizons(S) + 1 - min_nTH : nHorizons(s) - min_nTH) &
     416           0 :                   * Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)), &
     417   230010600 :                   Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)) > 0.0_dp)
     418             : 
     419             :              ! neutron count --> depth weightage LW and L30
     420    76670200 :              LW0(k) = sum( latWat_till(S, : nTillHorizons(s), L) &
     421    38335100 :                   * Wd(S, H, 1 : nTillHorizons(S) ), &
     422             :                   Wd(S, H, 1 : nTillHorizons(S)) > 0.0_dp ) &
     423           0 :                   + sum( latWat(S,nTillHorizons(S) + 1 - min_nTH : nHorizons(s) - min_nTH) &
     424           0 :                   * Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)), &
     425   230010600 :                   Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)) > 0.0_dp )
     426             : 
     427    76670200 :              L30(k) = sum( COSMIC_L3_till(S, : nTillHorizons(s), L) &
     428    38335100 :                   * Wd(S, H, 1 : nTillHorizons(S) ), &
     429             :                   Wd(S, H, 1 : nTillHorizons(S)) > 0.0_dp ) &
     430           0 :                   + sum( COSMIC_L3(S,nTillHorizons(S) + 1 - min_nTH : nHorizons(s) - min_nTH) &
     431           0 :                   * Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)), &
     432   230010600 :                   Wd(S, H, nTillHorizons(S) + 1 : nHorizons(S)) > 0.0_dp )
     433             : 
     434             : 
     435             :              ! Horizon depths: last soil horizon is varying, and thus the depth
     436             :              ! of the horizon too...
     437    38335100 :              if(H .eq. nHorizons_mHM) then
     438    19167550 :                 dpth_f = HorizonDepth(nHorizons_mHM - 1)
     439    19167550 :                 dpth_t = RZdepth(S)
     440             :              end if
     441             :              ! other soil properties [SMs, FC, PWP in mm]
     442    38335100 :              SMs0(k) = SMs0(k) * (dpth_t - dpth_f)
     443    38335100 :              FC0(k)  = FC0(k)  * (dpth_t - dpth_f)
     444    38335100 :              PW0(k)  = PW0(k)  * (dpth_t - dpth_f)
     445    38335928 :              LW0(k)  = LW0(k)  * (dpth_t - dpth_f)
     446             :           end do cellloop0
     447             :           !$OMP END DO
     448             :           !$OMP END PARALLEL
     449             : 
     450             : 
     451             :           !$OMP PARALLEL
     452             :           !$OMP DO PRIVATE( l, tmp_rootFractionCoefficient_perviousFC, FCnorm ) SCHEDULE( STATIC )
     453    38335928 :           celllloop0 : do k = 1, size(LCOVER0, 1)
     454    38335100 :              l = LCOVER0(k)
     455             :              !---------------------------------------------------------------------
     456             :              ! Effective root fractions in soil horizon...
     457             :              !  as weightage sum (according to LC fraction)
     458             :              !---------------------------------------------------------------------
     459             :              ! vertical root distribution = f(LC), following asymptotic equation
     460             :              ! [for refrence see, Jackson et. al., Oecologia, 1996. 108(389-411)]
     461             : 
     462             :              ! Roots(H) = 1 - beta^d
     463             :              !  where,
     464             :              !   Roots(H) = cumulative root fraction [-], range: 0-1
     465             :              !   beta     = fitted extinction cofficient parameter [-], as a f(LC)
     466             :              !   d        = soil surface to depth [cm]
     467             : 
     468             :              ! NOTES **
     469             :              !  sum(fRoots) for soil horions = 1.0
     470             : 
     471             :              !  if [sum(fRoots) for soil horions < 1.0], then
     472             :              !  normalise fRoot distribution such that all roots end up
     473             :              !  in soil horizon and thus satisfying the constrain that
     474             :              !  sum(fRoots) = 1
     475             : 
     476             :              !  The above constrains means that there are not roots below the soil horizon.
     477             :              !  This may or may not be realistic but it has been coded here to satisfy the
     478             :              !  conditions of the EVT vales, otherwise which the EVT values would be lesser
     479             :              !  than the acutal EVT from whole soil layers.
     480             : 
     481             :              !  Code could be modified in a way that a portion of EVT comes from the soil layer
     482             :              !  which is in between unsaturated and saturated zone or if necessary the saturated
     483             :              !  layer (i.e. Groundwater layer) can also contribute to EVT. Note that the above
     484             :              !  modification should be done only if and only if [sum(fRoots) for soil horions < 1.0].
     485             :              !  In such cases, you have to judiciously decide which layers (either soil layer between
     486             :              !  unsaturated and saturated zone or saturated zone) will contribute to EVT and in which
     487             :              !  proportions. Also note that there are no obervations on the depth avialable ata a
     488             :              !  moment on these layers.
     489             :              !------------------------------------------------------------------------
     490         828 :              select case(L)
     491             :              case(1)
     492             :                 ! forest
     493    13734852 :                 fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_forest**(dpth_t * 0.1_dp)) &
     494    13734852 :                      - (1.0_dp - tmp_rootFractionCoefficient_forest**(dpth_f * 0.1_dp))
     495             :              case(2)
     496             :                 ! impervious
     497     2412708 :                 fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_impervious**(dpth_t * 0.1_dp)) &
     498     2412708 :                      - (1.0_dp - tmp_rootFractionCoefficient_impervious**(dpth_f * 0.1_dp))
     499             :              case(3)
     500             :                 ! permeable
     501    22187540 :                 select case (processMatrix(3, 1))
     502             :                 case(1,2)
     503             :                    ! permeable
     504    21971588 :                    fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_pervious**(dpth_t * 0.1_dp)) &
     505    21971588 :                         - (1.0_dp - tmp_rootFractionCoefficient_pervious**(dpth_f * 0.1_dp))
     506             :                 case(3,4)
     507             :                    ! permeable
     508             :                    ! introducing global FC dependency on root frac. coef. by Simon Stisen and M. Cuneyd Demirel from GEUS.dk
     509             :                    ! The normalization is based on Demirel et al 2018 (doi: 10.5194/hess-22-1299-2018)
     510             :                    ! Case 3 is based on Jarvis (doi: 10.1016/0022-1694(89)90050-4)
     511             :                    ! Case 4 is based on Feddes (doi: 10.1016/0022-1694(76)90017-2)
     512             : 
     513      215952 :                    FCnorm = (((FC0(k) / (dpth_t - dpth_f)) - FCmin_glob) / (FCmax_glob - FCmin_glob))
     514             : 
     515      215952 :                    if(FCnorm .lt. 0.0_dp) then
     516             :                       ! print*, "FCnorm is below 0, will become 0", FCnorm
     517             :                       FCnorm=0.0_dp
     518      215216 :                    else if(FCnorm .gt. 1.0_dp) then
     519             :                       ! print*, "FCnorm is above 1, will become 1", FCnorm
     520        8804 :                       FCnorm=1.0_dp
     521             :                    end if
     522             : 
     523             :                    tmp_rootFractionCoefficient_perviousFC = (FCnorm * tmp_rootFractionCoefficient_clay) &
     524      215952 :                         + ((1 - FCnorm) * tmp_rootFractionCoefficient_sand)
     525             : 
     526             :                    fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_perviousFC**(dpth_t * 0.1_dp)) &
     527      215952 :                         - (1.0_dp - tmp_rootFractionCoefficient_perviousFC**(dpth_f * 0.1_dp))
     528             : 
     529             :                 end select
     530             : 
     531    22187540 :                 if((fRoots0(k) .lt. 0.0_dp) .OR. (fRoots0(k) .gt. 1.0_dp)) then
     532             :                   ! why is this not stopping here?
     533             :                   call message('***ERROR: Fraction of roots out of range [0,1]. Cell', &
     534           0 :                         num2str(k), ' has value ', num2str(fRoots0(k)))
     535             :                   ! stop
     536             :                 end if
     537             :              end select
     538             : 
     539             :           end do celllloop0
     540             :           !$OMP END DO
     541             :           !$OMP END PARALLEL
     542             : 
     543    38335928 :           beta0 = Bd0 * param(4)
     544             : 
     545             :           !---------------------------------------------
     546             :           ! Upscale the soil related parameters
     547             :           !---------------------------------------------
     548         828 :           L1_SMs(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     549       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, SMs0)
     550         828 :           L1_beta(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     551       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, beta0)
     552         828 :           L1_PW(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     553       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, PW0)
     554         828 :           L1_FC(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     555       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, FC0)
     556         828 :           L1_fRoots(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     557       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, fRoots0)
     558             : 
     559             :           ! !> neutron count
     560         828 :           L1_bulkDens(:,h) = upscale_harmonic_mean( nL0_in_L1, Upp_row_L1, Low_row_L1, &
     561       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, Bd0 )
     562         828 :           L1_latticeWater(:,h) = upscale_harmonic_mean( nL0_in_L1, Upp_row_L1, Low_row_L1, &
     563       32088 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, LW0 )
     564         828 :           L1_COSMICL3(:,h) = upscale_harmonic_mean( nL0_in_L1, Upp_row_L1, Low_row_L1, &
     565       32502 :                Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, L30 )
     566             : 
     567             :        end do
     568             : 
     569             :       ! to handle multiple soil horizons with unique soil class
     570             :     CASE(1)
     571             :       ! horizon wise calculation
     572           0 :       do h = 1, nHorizons_mHM
     573           0 :         Bd0 = nodata_dp
     574           0 :         SMs0 = nodata_dp
     575           0 :         FC0 = nodata_dp
     576           0 :         PW0 = nodata_dp
     577           0 :         fRoots0 = nodata_dp
     578           0 :         tmp_rootFractionCoefficient_perviousFC = nodata_dp
     579             : 
     580             :         ! neutron count
     581           0 :         LW0     = nodata_dp
     582           0 :         L30     = nodata_dp
     583             : 
     584             :         ! initalise mHM horizon depth
     585           0 :         if (h .eq. 1) then
     586           0 :           dpth_f = 0.0_dp
     587           0 :           dpth_t = HorizonDepth(h)
     588             :           ! check for the layer (2, ... n-1 layers) update depth
     589             :         else
     590           0 :           dpth_f = HorizonDepth(h - 1)
     591           0 :           dpth_t = HorizonDepth(h)
     592             :         end if
     593             :         ! need to be done for every layer to get fRoots
     594             :         !$OMP PARALLEL
     595             :         !$OMP DO PRIVATE( l, s ) SCHEDULE( STATIC )
     596           0 :         cellloop1 : do k = 1, size(LCOVER0, 1)
     597           0 :           L = LCOVER0(k)
     598           0 :           s = soilID0(k, h)
     599           0 :           if (h .le. nTillHorizons(1)) then
     600           0 :             Bd0(k) = Db(s, 1, L)
     601           0 :             SMs0(k)= thetaS_till (s, 1, L) * (dpth_t - dpth_f)  ! in mm
     602           0 :             FC0(k) = thetaFC_till(s, 1, L) * (dpth_t - dpth_f)  ! in mm
     603           0 :             PW0(k) = thetaPW_till(s, 1, L) * (dpth_t - dpth_f)  ! in mm
     604           0 :             LW0(k) = latWat_till(s, 1, L)  * (dpth_t - dpth_f)  ! in mm  ! >> neutron count
     605             :           else
     606           0 :             Bd0(k) = DbM(s, 1)
     607           0 :             SMs0(k)= thetaS (s, 1) * (dpth_t - dpth_f)  ! in mm
     608           0 :             FC0(k) = thetaFC(s, 1) * (dpth_t - dpth_f)  ! in mm
     609           0 :             PW0(k) = thetaPW(s, 1) * (dpth_t - dpth_f)  ! in mm
     610           0 :             LW0(k) = latWat(s, 1)  * (dpth_t - dpth_f)  ! in mm  ! >> neutron count
     611             :           end if
     612             :         end do cellloop1
     613             :         !$OMP END DO
     614             :         !$OMP END PARALLEL
     615             : 
     616             : 
     617             :         !$OMP PARALLEL
     618             :         !$OMP DO PRIVATE( l, tmp_rootFractionCoefficient_perviousFC, FCnorm ) SCHEDULE( STATIC )
     619             : 
     620           0 :         celllloop1 : do k = 1, size(LCOVER0, 1)
     621           0 :           l = LCOVER0(k)
     622             :           !================================================================================
     623             :           ! fRoots = f[LC] --> (fRoots(H) = 1 - beta^d)
     624             :           ! see below for comments and references for the use of this simple equation
     625             :           ! NOTE that in this equation the unit of soil depth is in cm
     626             :           !================================================================================
     627             : 
     628           0 :           select case(L)
     629             :           case(1)
     630             :             ! forest
     631           0 :             fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_forest**(dpth_t * 0.1_dp)) &
     632           0 :                     - (1.0_dp - tmp_rootFractionCoefficient_forest**(dpth_f * 0.1_dp))
     633             :           case(2)
     634             :             ! impervious
     635           0 :             fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_impervious**(dpth_t * 0.1_dp)) &
     636           0 :                     - (1.0_dp - tmp_rootFractionCoefficient_impervious**(dpth_f * 0.1_dp))
     637             :           case(3)
     638             : 
     639           0 :             select case (processMatrix(3, 1))
     640             :             case(1,2)
     641             :               ! permeable
     642           0 :               fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_pervious**(dpth_t * 0.1_dp)) &
     643           0 :                       - (1.0_dp - tmp_rootFractionCoefficient_pervious**(dpth_f * 0.1_dp))
     644             :             case(3,4)
     645             :               ! permeable
     646             :               ! introducing global FC dependency on root frac. coef. by Simon Stisen and M. Cuneyd Demirel from GEUS.dk
     647             :               ! The normalization is based on Demirel et al 2018 (doi: 10.5194/hess-22-1299-2018)
     648             :               ! Case 3 is based on Jarvis (doi: 10.1016/0022-1694(89)90050-4)
     649             :               ! Case 4 is based on Feddes (doi: 10.1016/0022-1694(76)90017-2)
     650           0 :               FCnorm = (((FC0(k) / (dpth_t - dpth_f)) - FCmin_glob) / (FCmax_glob - FCmin_glob))
     651             : 
     652           0 :               if(FCnorm .lt. 0.0_dp) then
     653             :                 ! print*, "FCnorm is below 0, will become 0", FCnorm
     654             :                 FCnorm=0.0_dp
     655           0 :               else if(FCnorm .gt. 1.0_dp) then
     656             :                 ! print*, "FCnorm is above 1, will become 1", FCnorm
     657           0 :                 FCnorm=1.0_dp
     658             :               end if
     659             : 
     660             :               tmp_rootFractionCoefficient_perviousFC = (FCnorm * tmp_rootFractionCoefficient_clay) &
     661           0 :                       + ((1 - FCnorm) * tmp_rootFractionCoefficient_sand)
     662             : 
     663             : 
     664             :               fRoots0(k) = (1.0_dp - tmp_rootFractionCoefficient_perviousFC**(dpth_t * 0.1_dp)) &
     665           0 :                       - (1.0_dp - tmp_rootFractionCoefficient_perviousFC**(dpth_f * 0.1_dp))
     666             : 
     667             :             end select
     668             : 
     669           0 :             if((fRoots0(k) .lt. 0.0_dp) .OR. (fRoots0(k) .gt. 1.0_dp)) then
     670             :               ! why is this not stopping here?
     671             :               call message('***ERROR: Fraction of roots out of range [0,1]. Cell', &
     672           0 :                     num2str(k), ' has value ', num2str(fRoots0(k)))
     673             :               ! stop
     674             :             end if
     675             :           end select
     676             : 
     677             :         end do celllloop1
     678             :         !$OMP END DO
     679             :         !$OMP END PARALLEL
     680             : 
     681             :         ! beta parameter
     682           0 :         beta0 = Bd0 * param(4)
     683             : 
     684             :         ! Upscale the soil related parameters
     685           0 :         L1_SMs(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     686           0 :                 Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, SMs0)
     687           0 :         L1_beta(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     688           0 :                 Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, beta0)
     689           0 :         L1_PW(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     690           0 :                 Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, PW0)
     691           0 :         L1_FC(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     692           0 :                 Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, FC0)
     693           0 :         L1_fRoots(:, h) = upscale_harmonic_mean(nL0_in_L1, Upp_row_L1, Low_row_L1, &
     694           0 :              Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, fRoots0)
     695             : 
     696             :         ! neutron count
     697           0 :         L1_bulkDens(:,h) = upscale_harmonic_mean( nL0_in_L1, Upp_row_L1, Low_row_L1, &
     698           0 :              Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, Bd0 )
     699           0 :        L1_latticeWater(:,h)   = upscale_harmonic_mean( nL0_in_L1, Upp_row_L1, Low_row_L1, &
     700           0 :              Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, LW0  )
     701           0 :         L1_COSMICL3(:,h)   = upscale_harmonic_mean( nL0_in_L1, Upp_row_L1, Low_row_L1, &
     702           0 :              Lef_col_L1, Rig_col_L1, cell_id0, mask0, nodata_dp, L30  )
     703             : 
     704             :       end do
     705             :       ! anything else
     706             :     CASE DEFAULT
     707         414 :       call error_message('***ERROR: iFlag_soilDB option given does not exist. Only 0 and 1 is taken at the moment.')
     708             :     END SELECT
     709             : 
     710             : 
     711             :     ! below operations are common to all soil databases flags
     712             :     !$OMP PARALLEL
     713             :     !------------------------------------------------------------------------
     714             :     ! CHECK LIMITS OF PARAMETERS
     715             :     !   [PW <= FC <= ThetaS]
     716             :     !  units of all variables are now in [mm]
     717             :     ! If by any means voilation of this rule appears (e.g. numerical errors)
     718             :     ! than correct it --> threshold limit = 1% of the upper ones
     719             :     !------------------------------------------------------------------------
     720       31674 :     L1_FC = merge(L1_SMs - 0.01_dp * L1_SMs, L1_FC, L1_FC .gt. L1_SMs)
     721       31674 :     L1_PW = merge(L1_FC - 0.01_dp  * L1_FC,  L1_PW, L1_PW .gt. L1_FC )
     722             :     ! check the physical limit
     723       31674 :     L1_SMs = merge(0.0001_dp, L1_SMs, L1_SMs .lt. 0.0_dp)
     724       31674 :     L1_FC  = merge(0.0001_dp, L1_FC,  L1_FC  .lt. 0.0_dp)
     725       31674 :     L1_PW  = merge(0.0001_dp, L1_PW,  L1_PW  .lt. 0.0_dp)
     726             :     ! Normalise the vertical root distribution profile such that [sum(fRoots) = 1.0]
     727             :     !$OMP DO PRIVATE( fTotRoots ) SCHEDULE( STATIC )
     728       15630 :     do k = 1, size(L1_fRoots, 1)
     729       45648 :       fTotRoots = sum(L1_fRoots(k, :), L1_fRoots(k, :) .gt. 0.0_dp)
     730             :       ! This if clause is necessary for test program but may be redundant in actual program
     731       15630 :       if (fTotRoots .gt. 0.0_dp) then
     732       45648 :         L1_fRoots(k, :) = L1_fRoots(k, :) / fTotRoots
     733             :       else
     734           0 :         L1_fRoots(k, :) = 0.0_dp
     735             :       end If
     736             :     end do
     737             : 
     738             :     !$OMP END DO
     739             :     !$OMP END PARALLEL
     740             : !close(1)
     741         414 :   end subroutine mpr_SMhorizons
     742             : 
     743             : end module mo_mpr_SMhorizons

Generated by: LCOV version 1.16