5.13.3-dev0
mHM
The mesoscale Hydrological Model
Loading...
Searching...
No Matches
mo_mpr_smhorizons.f90
Go to the documentation of this file.
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
13
14 use mo_kind, only : i4, dp
16
17 implicit none
18
19 public :: mpr_smhorizons
20
21 private
22
23contains
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 subroutine mpr_smhorizons(param, processMatrix, iFlag_soil, nHorizons_mHM, HorizonDepth, LCOVER0, soilID0, nHorizons, &
121 nTillHorizons, thetaS_till, thetaFC_till, thetaPW_till, thetaS, thetaFC, thetaPW, Wd, Db, &
122 DbM, RZdepth, mask0, cell_id0, upp_row_L1, low_row_L1, lef_col_L1, rig_col_L1, nL0_in_L1, &
123 L1_beta, L1_SMs, L1_FC, L1_PW, L1_fRoots, &
124 ! neutron count
125 latWat_till , & ! lattice water upto tillage depth
126 COSMIC_L3_till, & ! COSMIC parameter L3 upto tillage depth
127 latWat , & ! lattice water
128 COSMIC_L3 , & ! COSMIC paramter L3
129 L1_bulkDens , & ! L bulk density
130 L1_latticeWater,& ! L1 lattice water content
131 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
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 real(dp) :: dpth_f
270
271 real(dp) :: dpth_t
272
273 real(dp) :: ftotroots
274
275 ! beta 0
276 real(dp), dimension(size(LCOVER0, 1)) :: beta0
277
278 ! [10^3 kg/m3] Bulk density
279 real(dp), dimension(size(LCOVER0, 1)) :: bd0
280
281 ! [10^-3 m] depth of saturated SM cont
282 real(dp), dimension(size(LCOVER0, 1)) :: sms0
283
284 ! [10^-3 m] field capacity
285 real(dp), dimension(size(LCOVER0, 1)) :: fc0
286
287 ! [10^-3 m] permanent wilting point
288 real(dp), dimension(size(LCOVER0, 1)) :: pw0
289
290 ! neutron count
291 real(dp), dimension(size(LCOVER0,1)) :: lw0 ! lattice water
292 real(dp), dimension(size(LCOVER0,1)) :: l30 ! COSMIC parameter L3
293
294
295 ! fraction of roots in soil horizons
296 real(dp), dimension(size(LCOVER0, 1)) :: froots0
297
298 real(dp) :: tmp_rootfractioncoefficient_forest
299
300 real(dp) :: tmp_rootfractioncoefficient_impervious
301
302 real(dp) :: tmp_rootfractioncoefficient_pervious
303
304 ! Field capacity dependent
305 ! root frac coeffiecient
306 real(dp) :: tmp_rootfractioncoefficient_perviousfc
307
308 ! Model parameter describing the threshold for
309 ! actual ET reduction for sand
310 real(dp) :: tmp_rootfractioncoefficient_sand
311
312 ! Model parameter describing the threshold for actual
313 ! ET reduction for clay
314 real(dp) :: tmp_rootfractioncoefficient_clay
315
316 real(dp) :: fcmin_glob
317
318 ! real(dp) :: FCdelta_glob
319
320 real(dp) :: fcmax_glob
321
322 real(dp) :: fcnorm
323 ! the minimum number of till horizons
324 integer(i4) :: min_nth
325
326
327 min_nth = minval(ntillhorizons(:))
328 tmp_rootfractioncoefficient_forest = param(1) ! min(1.0_dp, param(2) + param(3) + param(1))
329 tmp_rootfractioncoefficient_impervious = param(2)
330
331 ! decide which parameterization should be used for route fraction:
332 select case (processmatrix(3, 1))
333 case(1,2)
334 ! 1 and 2 - dependent on land cover
335 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 tmp_rootfractioncoefficient_pervious = param(3) ! min(1.0_dp, param(2) + param(3))
342 !delta approach is used as in tmp_rootFractionCoefficient_pervious
343 tmp_rootfractioncoefficient_sand = param(6) - param(5)
344 !the value in parameter namelist is before substraction i.e. param(5)
345 tmp_rootfractioncoefficient_clay = param(6)
346 fcmin_glob=param(7)
347 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 SELECT CASE(iflag_soil)
360 ! classical mHM soil database format
361 CASE(0)
362 do h = 1, nhorizons_mhm
363
364 bd0 = nodata_dp
365 sms0 = nodata_dp
366 fc0 = nodata_dp
367 pw0 = nodata_dp
368 froots0 = nodata_dp
369 tmp_rootfractioncoefficient_perviousfc = nodata_dp
370
371 ! neutron count
372 lw0 = nodata_dp
373 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 dpth_f = 0.0_dp
379 dpth_t = horizondepth(h)
380 ! check for the layer (2, ... n-1 layers) update depth
381 if( (h .gt. 1) .and. (h .lt. nhorizons_mhm) ) then
382 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 cellloop0 : do k = 1, size(lcover0, 1)
389 l = lcover0(k)
390 s = soilid0(k, 1) ! >> in this case the second dimension of soilId0 = 1
391 ! depth weightage bulk density
392 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 + sum(dbm(s, ntillhorizons(s) + 1 : nhorizons(s)) &
395 * wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)), &
396 wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)) >= 0.0_dp)
397 ! depth weightage thetaS
398 sms0(k) = sum(thetas_till(s, : ntillhorizons(s), l) &
399 * wd(s, h, 1 : ntillhorizons(s)), &
400 wd(s, h, 1 : ntillhorizons(s)) > 0.0_dp) &
401 + sum(thetas(s, ntillhorizons(s) + 1 - min_nth : nhorizons(s) - min_nth) &
402 * wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)), &
403 wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)) > 0.0_dp)
404 ! depth weightage FC
405 fc0(k) = sum(thetafc_till(s, : ntillhorizons(s), l) &
406 * wd(s, h, 1 : ntillhorizons(s)), &
407 wd(s, h, 1 : ntillhorizons(s)) > 0.0_dp) &
408 + sum(thetafc(s, ntillhorizons(s) + 1 - min_nth : nhorizons(s) - min_nth) &
409 * wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)), &
410 wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)) > 0.0_dp)
411 ! depth weightage PWP
412 pw0(k) = sum(thetapw_till(s, : ntillhorizons(s), l) &
413 * wd(s, h, 1 : ntillhorizons(s)), &
414 wd(s, h, 1 : ntillhorizons(s)) > 0.0_dp) &
415 + sum(thetapw(s, ntillhorizons(s) + 1 - min_nth : nhorizons(s) - min_nth) &
416 * wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)), &
417 wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)) > 0.0_dp)
418
419 ! neutron count --> depth weightage LW and L30
420 lw0(k) = sum( latwat_till(s, : ntillhorizons(s), l) &
421 * wd(s, h, 1 : ntillhorizons(s) ), &
422 wd(s, h, 1 : ntillhorizons(s)) > 0.0_dp ) &
423 + sum( latwat(s,ntillhorizons(s) + 1 - min_nth : nhorizons(s) - min_nth) &
424 * wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)), &
425 wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)) > 0.0_dp )
426
427 l30(k) = sum( cosmic_l3_till(s, : ntillhorizons(s), l) &
428 * wd(s, h, 1 : ntillhorizons(s) ), &
429 wd(s, h, 1 : ntillhorizons(s)) > 0.0_dp ) &
430 + sum( cosmic_l3(s,ntillhorizons(s) + 1 - min_nth : nhorizons(s) - min_nth) &
431 * wd(s, h, ntillhorizons(s) + 1 : nhorizons(s)), &
432 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 if(h .eq. nhorizons_mhm) then
438 dpth_f = horizondepth(nhorizons_mhm - 1)
439 dpth_t = rzdepth(s)
440 end if
441 ! other soil properties [SMs, FC, PWP in mm]
442 sms0(k) = sms0(k) * (dpth_t - dpth_f)
443 fc0(k) = fc0(k) * (dpth_t - dpth_f)
444 pw0(k) = pw0(k) * (dpth_t - dpth_f)
445 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 celllloop0 : do k = 1, size(lcover0, 1)
454 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 select case(l)
491 case(1)
492 ! forest
493 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_forest**(dpth_t * 0.1_dp)) &
494 - (1.0_dp - tmp_rootfractioncoefficient_forest**(dpth_f * 0.1_dp))
495 case(2)
496 ! impervious
497 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_impervious**(dpth_t * 0.1_dp)) &
498 - (1.0_dp - tmp_rootfractioncoefficient_impervious**(dpth_f * 0.1_dp))
499 case(3)
500 ! permeable
501 select case (processmatrix(3, 1))
502 case(1,2)
503 ! permeable
504 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_pervious**(dpth_t * 0.1_dp)) &
505 - (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 fcnorm = (((fc0(k) / (dpth_t - dpth_f)) - fcmin_glob) / (fcmax_glob - fcmin_glob))
514
515 if(fcnorm .lt. 0.0_dp) then
516 ! print*, "FCnorm is below 0, will become 0", FCnorm
517 fcnorm=0.0_dp
518 else if(fcnorm .gt. 1.0_dp) then
519 ! print*, "FCnorm is above 1, will become 1", FCnorm
520 fcnorm=1.0_dp
521 end if
522
523 tmp_rootfractioncoefficient_perviousfc = (fcnorm * tmp_rootfractioncoefficient_clay) &
524 + ((1 - fcnorm) * tmp_rootfractioncoefficient_sand)
525
526 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_perviousfc**(dpth_t * 0.1_dp)) &
527 - (1.0_dp - tmp_rootfractioncoefficient_perviousfc**(dpth_f * 0.1_dp))
528
529 end select
530
531 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 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 beta0 = bd0 * param(4)
544
545 !---------------------------------------------
546 ! Upscale the soil related parameters
547 !---------------------------------------------
548 l1_sms(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
549 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, sms0)
550 l1_beta(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
551 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, beta0)
552 l1_pw(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
553 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, pw0)
554 l1_fc(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
555 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, fc0)
556 l1_froots(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
557 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, froots0)
558
559 ! !> neutron count
560 l1_bulkdens(:,h) = upscale_harmonic_mean( nl0_in_l1, upp_row_l1, low_row_l1, &
561 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, bd0 )
562 l1_latticewater(:,h) = upscale_harmonic_mean( nl0_in_l1, upp_row_l1, low_row_l1, &
563 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, lw0 )
564 l1_cosmicl3(:,h) = upscale_harmonic_mean( nl0_in_l1, upp_row_l1, low_row_l1, &
565 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 do h = 1, nhorizons_mhm
573 bd0 = nodata_dp
574 sms0 = nodata_dp
575 fc0 = nodata_dp
576 pw0 = nodata_dp
577 froots0 = nodata_dp
578 tmp_rootfractioncoefficient_perviousfc = nodata_dp
579
580 ! neutron count
581 lw0 = nodata_dp
582 l30 = nodata_dp
583
584 ! initalise mHM horizon depth
585 if (h .eq. 1) then
586 dpth_f = 0.0_dp
587 dpth_t = horizondepth(h)
588 ! check for the layer (2, ... n-1 layers) update depth
589 else
590 dpth_f = horizondepth(h - 1)
591 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 cellloop1 : do k = 1, size(lcover0, 1)
597 l = lcover0(k)
598 s = soilid0(k, h)
599 if (h .le. ntillhorizons(1)) then
600 bd0(k) = db(s, 1, l)
601 sms0(k)= thetas_till(s, 1, l) * (dpth_t - dpth_f) ! in mm
602 fc0(k) = thetafc_till(s, 1, l) * (dpth_t - dpth_f) ! in mm
603 pw0(k) = thetapw_till(s, 1, l) * (dpth_t - dpth_f) ! in mm
604 lw0(k) = latwat_till(s, 1, l) * (dpth_t - dpth_f) ! in mm ! >> neutron count
605 else
606 bd0(k) = dbm(s, 1)
607 sms0(k)= thetas(s, 1) * (dpth_t - dpth_f) ! in mm
608 fc0(k) = thetafc(s, 1) * (dpth_t - dpth_f) ! in mm
609 pw0(k) = thetapw(s, 1) * (dpth_t - dpth_f) ! in mm
610 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 celllloop1 : do k = 1, size(lcover0, 1)
621 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 select case(l)
629 case(1)
630 ! forest
631 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_forest**(dpth_t * 0.1_dp)) &
632 - (1.0_dp - tmp_rootfractioncoefficient_forest**(dpth_f * 0.1_dp))
633 case(2)
634 ! impervious
635 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_impervious**(dpth_t * 0.1_dp)) &
636 - (1.0_dp - tmp_rootfractioncoefficient_impervious**(dpth_f * 0.1_dp))
637 case(3)
638
639 select case (processmatrix(3, 1))
640 case(1,2)
641 ! permeable
642 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_pervious**(dpth_t * 0.1_dp)) &
643 - (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 fcnorm = (((fc0(k) / (dpth_t - dpth_f)) - fcmin_glob) / (fcmax_glob - fcmin_glob))
651
652 if(fcnorm .lt. 0.0_dp) then
653 ! print*, "FCnorm is below 0, will become 0", FCnorm
654 fcnorm=0.0_dp
655 else if(fcnorm .gt. 1.0_dp) then
656 ! print*, "FCnorm is above 1, will become 1", FCnorm
657 fcnorm=1.0_dp
658 end if
659
660 tmp_rootfractioncoefficient_perviousfc = (fcnorm * tmp_rootfractioncoefficient_clay) &
661 + ((1 - fcnorm) * tmp_rootfractioncoefficient_sand)
662
663
664 froots0(k) = (1.0_dp - tmp_rootfractioncoefficient_perviousfc**(dpth_t * 0.1_dp)) &
665 - (1.0_dp - tmp_rootfractioncoefficient_perviousfc**(dpth_f * 0.1_dp))
666
667 end select
668
669 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 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 beta0 = bd0 * param(4)
683
684 ! Upscale the soil related parameters
685 l1_sms(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
686 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, sms0)
687 l1_beta(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
688 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, beta0)
689 l1_pw(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
690 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, pw0)
691 l1_fc(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
692 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, fc0)
693 l1_froots(:, h) = upscale_harmonic_mean(nl0_in_l1, upp_row_l1, low_row_l1, &
694 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, froots0)
695
696 ! neutron count
697 l1_bulkdens(:,h) = upscale_harmonic_mean( nl0_in_l1, upp_row_l1, low_row_l1, &
698 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, bd0 )
699 l1_latticewater(:,h) = upscale_harmonic_mean( nl0_in_l1, upp_row_l1, low_row_l1, &
700 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, lw0 )
701 l1_cosmicl3(:,h) = upscale_harmonic_mean( nl0_in_l1, upp_row_l1, low_row_l1, &
702 lef_col_l1, rig_col_l1, cell_id0, mask0, nodata_dp, l30 )
703
704 end do
705 ! anything else
706 CASE DEFAULT
707 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 l1_fc = merge(l1_sms - 0.01_dp * l1_sms, l1_fc, l1_fc .gt. l1_sms)
721 l1_pw = merge(l1_fc - 0.01_dp * l1_fc, l1_pw, l1_pw .gt. l1_fc )
722 ! check the physical limit
723 l1_sms = merge(0.0001_dp, l1_sms, l1_sms .lt. 0.0_dp)
724 l1_fc = merge(0.0001_dp, l1_fc, l1_fc .lt. 0.0_dp)
725 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 do k = 1, size(l1_froots, 1)
729 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 if (ftotroots .gt. 0.0_dp) then
732 l1_froots(k, :) = l1_froots(k, :) / ftotroots
733 else
734 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 end subroutine mpr_smhorizons
742
743end module mo_mpr_smhorizons
Provides constants commonly used by mHM, mRM and MPR.
real(dp), parameter, public nodata_dp
setting up the soil moisture horizons
subroutine, public mpr_smhorizons(param, processmatrix, iflag_soil, nhorizons_mhm, horizondepth, lcover0, soilid0, nhorizons, ntillhorizons, thetas_till, thetafc_till, thetapw_till, thetas, thetafc, thetapw, wd, db, dbm, rzdepth, mask0, cell_id0, upp_row_l1, low_row_l1, lef_col_l1, rig_col_l1, nl0_in_l1, l1_beta, l1_sms, l1_fc, l1_pw, l1_froots, latwat_till, cosmic_l3_till, latwat, cosmic_l3, l1_bulkdens, l1_latticewater, l1_cosmicl3)
upscale soil moisture horizons
Module containing upscaling operators.
real(dp) function, dimension(size(nl0_cells_in_l1_cell, 1)), public upscale_harmonic_mean(nl0_cells_in_l1_cell, l1_upper_rowid_cell, l1_lower_rowid_cell, l1_left_colonid_cell, l1_right_colonid_cell, l0_cellid, mask0, nodata_value, l0_finescale_data)
harmonic mean