Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
actual_et__fao56__two_stage.F90
Go to the documentation of this file.
1!> @file
2!> Contains a single module, \ref actual_et__fao56__two_stage, which
3!> provides support for calculating actual evapotranspiration by means of the
4
5!> Provide support for assessing the effect of irrigation on recharge
6!> values by estimating the irrigation required to maintain soil moisture levels
7!> for specific crop types.
9
10 use iso_c_binding, only : c_short, c_int, c_float, c_double, c_bool
11 use logfiles, only : logs, log_all
14 use fstring, only : ascharacter
16 use parameters, only : params
17
18 use exceptions
22 implicit none
23
24 real (c_float), allocatable :: rew_l(:,:)
25 real (c_float), allocatable :: tew_l(:,:)
26 real (c_float), allocatable :: depletion_fraction(:)
27 real (c_float), allocatable :: mean_plant_height(:)
28 real (c_float), allocatable :: min_fraction_covered_soil(:)
29
30contains
31
32 !> Adjust the depletion fraction based on current reference ET0.
33 !!
34 !! From FAO-56: "The fraction p is a function of the evaporation power of the atmosphere.
35 !! At low rates of ETc, the p values listed in Table 22 are higher than at high rates of ETc.
36 !! For hot dry weather conditions, where ETc is high, p is 10-25% less than the values
37 !! presented in Table 22, and the soil is still relatively wet when the stress starts to occur.
38 !! When the crop evapotranspiration is low, p will be up to 20% more than the listed values.
39 !!
40 !! @param[in] p_table_22 This is the unadjusted depletion fraction value; FAO-56
41 !! table 22 gives values of the depletion fraction relative to a reference ET0 value of 5mm.
42 !! @param[in] reference_et0 The reference ET0 to which the depletion fraction will be
43 !! adjusted.
44 !! @note Discussed as a footnote to Table 22, FAO-56, Allen and others.
45 !! See @ref http://www.fao.org/docrep/x0490e/x0490e0e.htm#TopOfPage for details.
46
47 elemental function adjust_depletion_fraction_p( landuse_index, reference_et0 ) result( p )
48
49 integer ( c_int), intent(in) :: landuse_index
50 real (c_double), intent(in) :: reference_et0
51 real (c_double) :: p
52
53 p = real(depletion_fraction( landuse_index ),c_double) + 0.04_c_double &
54 * ( 5.0_c_double - in_to_mm( reference_et0 ) )
55
56 p = min( p, 0.8_c_double )
57 p = max( p, 0.1_c_double )
58
60
61!------------------------------------------------------------------------------
62
64
65 use parameters, only : params
66
67 integer (c_int) :: number_of_landuses
68 integer (c_int) :: number_of_records
69 logical (c_bool) :: list_lengths_are_equal
70 type(fstring_list_t) :: slList
71 integer (c_int), allocatable :: landuse_table_codes(:)
72 real (c_float), allocatable :: tempvals(:)
73 integer (c_int) :: status
74
75 ! create list of possible table headings to look for...
76 call sllist%append( "LU_Code" )
77 call sllist%append( "Landuse_Lookup_Code" )
78
79 !> Determine how many landuse codes are present
80 call params%get_parameters( slkeys=sllist, ivalues=landuse_table_codes )
81 number_of_landuses = count( landuse_table_codes >= 0 )
82 call sllist%clear()
83
84 ! Retrieve and populate the Readily Evaporable Water (REW_l table values
85 CALL params%get_parameters( fvalues=rew_l, sprefix="REW_", inumrows=number_of_landuses, lfatal=true )
86
87 ! Retrieve and populate the Total Evaporable Water (TEW_l table values
88 CALL params%get_parameters( fvalues=tew_l, sprefix="TEW_", inumrows=number_of_landuses, lfatal=true )
89
90 call params%get_parameters( skey="Mean_Plant_Height", fvalues=mean_plant_height, lfatal=true )
91
92 sllist = create_list("Depletion_fraction, Plant_stress_depletion_fraction")
93 call params%get_parameters( slkeys=sllist, fvalues=depletion_fraction, lfatal=true )
94 call sllist%clear()
95
96 sllist = create_list("Minimum_fraction_vegetative_cover, Min_fraction_covered_soil, Min_vegetative_cover_fraction")
97 call params%get_parameters( slkeys=sllist, fvalues=min_fraction_covered_soil, lfatal=false )
98 call sllist%clear()
99
100 number_of_records = ubound(min_fraction_covered_soil,1)
101 list_lengths_are_equal = ( number_of_records == number_of_landuses )
102
103 if ( .not. list_lengths_are_equal ) then
104 call warn( smessage="The number of landuses does not match the number of values supplied for the " &
105 //"minimum fraction of soil covered by vegetation.", &
106 shints="A default value of 0.05 was assigned for the minimum fraction of covered soil.", &
107 smodule=__file__, iline=__line__, lfatal=false )
108 allocate(tempvals(number_of_landuses), stat=status)
109 tempvals = 0.05
110 call move_alloc(tempvals, min_fraction_covered_soil)
111 endif
112
114
115!------------------------------------------------------------------------------
116
117elemental subroutine update_evaporable_water_storage( evaporable_water_storage, evaporable_water_deficit, &
118 infiltration, landuse_index, soil_group)
119
120 real (c_float), intent(inout) :: evaporable_water_storage
121 real (c_float), intent(inout) :: evaporable_water_deficit
122 real (c_float), intent(in) :: infiltration
123 integer (c_int), intent(in) :: landuse_index
124 integer (c_int), intent(in) :: soil_group
125
126 associate( rew => rew_l( landuse_index, soil_group ), &
127 tew => tew_l( landuse_index, soil_group ) )
128
129 evaporable_water_storage = clip( evaporable_water_storage + infiltration, minval=0.0, maxval=tew)
130 evaporable_water_deficit = max( 0.0, tew - evaporable_water_storage)
131
132 end associate
133
135
136!------------------------------------------------------------------------------
137
138elemental function calculate_evaporation_reduction_coefficient_kr( landuse_index, &
139 soil_group, &
140 evaporable_water_deficit ) result( Kr )
141
142 ! [ ARGUMENTS ]
143 integer (c_int), intent(in) :: landuse_index
144 integer (c_int), intent(in) :: soil_group
145 real (c_float), intent(in) :: evaporable_water_deficit
146
147 ! [ RESULT ]
148 real (c_double) :: kr
149
150 associate( rew => rew_l( landuse_index, soil_group ), &
151 tew => tew_l( landuse_index, soil_group ) )
152
153 if ( evaporable_water_deficit <= rew ) then
154 kr = 1._c_double
155 elseif ( evaporable_water_deficit < tew ) then
156 kr = ( real(tew, c_double) - evaporable_water_deficit ) &
157 / ( real(tew, c_double) - real(rew, c_double) + 1.0e-8)
158 else
159 kr = 0._c_double
160 endif
161
162 end associate
163
165
166!------------------------------------------------------------------------------
167
168!> This function estimates the fraction of the ground covered by
169!> vegetation during the growing season
170!> @note Implemented as equation 76, FAO-56, Allen and others
171impure elemental function calculate_fraction_exposed_and_wetted_soil_fc( landuse_index, Kcb, current_plant_height) result ( few )
172
173 ! [ ARGUMENTS ]
174 integer (c_int), intent(in) :: landuse_index
175 real (c_float), intent(in) :: kcb
176 real (c_float), intent(in) :: current_plant_height
177
178 ! [ RESULT ]
179 real (c_float) :: few
180
181 ! [ LOCALS ]
182 real (c_float) :: fc
183 real (c_double) :: numerator
184 real (c_double) :: denominator
185 real (c_double) :: exponent
186
187 numerator = max(real(kcb, c_double) - kcb_l( kcb_min, landuse_index), 0.0_c_double)
188 denominator = kcb_l( kcb_mid, landuse_index) - kcb_l( kcb_min, landuse_index)
189 exponent = 1.0_c_double + 0.5_c_double * current_plant_height * m_per_foot
190
191 if( denominator > 0.0_c_double ) then
192 fc = real(( numerator / denominator ) ** exponent, c_float)
193 else
194 fc = 1.0_c_float
195 endif
196
197 fc = max(fc, min_fraction_covered_soil( landuse_index ))
198 few = clip(1.0_c_float - fc, minval=0.05, maxval=1.0)
199
201
202!------------------------------------------------------------------------------
203
204!> This function estimates Ke, the bare surface evaporation coefficient
205!> @note Implemented as equation 71, FAO-56, Allen and others
206elemental function calculate_surface_evap_coefficient_ke( landuse_index, Kcb, Kcb_max, Kr, &
207 fraction_exposed_and_wetted_soil) result( Ke )
208
209 ! [ ARGUMENTS ]
210 integer (c_int), intent(in) :: landuse_index
211 real (c_float), intent(in) :: kcb
212 real (c_float), intent(in) :: kcb_max
213 real (c_double), intent(in) :: kr
214 real (c_float), intent(in) :: fraction_exposed_and_wetted_soil
215 real (c_double) :: ke
216
217 real (c_double) :: maximum_value
218
219 ! OK, not quite spelled out in FAO-56, but I don't want to see evaporation coefficients
220 ! greater than one returned from this function
221 maximum_value = min( 1.0_c_double, real(fraction_exposed_and_wetted_soil, c_double) * kcb_max )
222
223 ke = min( kr * ( real(kcb_max, c_double) - real(kcb, c_double)), maximum_value )
224
226
227!------------------------------------------------------------------------------
228
229!> This subroutine updates the total available water (TAW)
230!> (water within the rootzone) for a gridcell
231elemental subroutine calculate_total_available_water( taw, raw, &
232 adjusted_depletion_fraction_p, &
233 current_rooting_depth, &
234 awc )
235
236 real (c_double), intent(inout) :: raw
237 real (c_double), intent(inout) :: taw
238 real (c_double), intent(in) :: adjusted_depletion_fraction_p
239 real (c_float), intent(in) :: current_rooting_depth
240 real (c_float), intent(in) :: awc
241
242 taw = real(current_rooting_depth, c_double) * real(awc, c_double)
243 raw = taw * adjusted_depletion_fraction_p
244
246
247!------------------------------------------------------------------------------
248
249!> This function updates the plant height by scaling values relative to the
250!> position of the current Kcb value on the Kcb curve
251impure elemental function update_plant_height( landuse_index, it_is_growing_season, Kcb) result(plant_height)
252
253 integer (c_int), intent(in) :: landuse_index
254 logical (c_bool), intent(in) :: it_is_growing_season
255 real (c_float), intent(in) :: kcb
256 real (c_float) :: plant_height
257
258 ! [ LOCALS ]
259 real (c_float) :: plant_height_minimum_m
260 real (c_double) :: numerator
261 real (c_double) :: denominator
262
263 plant_height_minimum_m = 0.1
264
265 numerator = kcb - kcb_l( kcb_min, landuse_index)
266 denominator = kcb_l( kcb_mid, landuse_index) - kcb_l( kcb_min, landuse_index)
267
268 if (denominator < near_zero) then
269
270 plant_height = real(mean_plant_height( landuse_index ) * m_per_foot, kind=c_float)
271
272 elseif ( it_is_growing_season ) then
273
274 ! FAO documentation suggests limiting the plant height range to a value between 1 and 10 meters
275 plant_height = clip(real( numerator/denominator * mean_plant_height( landuse_index ) * m_per_foot, kind=c_float), &
276 minval=plant_height_minimum_m, maxval=10.)
277 else
278
279 plant_height = plant_height_minimum_m
280
281 endif
282
283end function update_plant_height
284
285!------------------------------------------------------------------------------
286
287!> This function estimates Ks, water stress coefficient
288!> @note Implemented as equation 84, FAO-56, Allen and others
289elemental function calculate_water_stress_coefficient_ks( taw, raw, &
290 soil_moisture_deficit) result( Ks )
291
292 real (c_double), intent(in) :: raw
293 real (c_double), intent(in) :: taw
294 real (c_double), intent(in) :: soil_moisture_deficit
295 real (c_double) :: ks
296
297 if ( soil_moisture_deficit < raw ) then
298
299 ks = 1.0_c_float
300
301 elseif ( soil_moisture_deficit < taw ) then
302
303 ks = ( taw - soil_moisture_deficit ) / ( taw - raw + 1.0e-6)
304
305 else
306
307 ks = 0.0_c_float
308
309 endif
310
312
313!------------------------------------------------------------------------------
314
315impure elemental subroutine calculate_actual_et_fao56_two_stage( &
316 actual_et, &
317 crop_etc, &
318 bare_soil_evap, &
319 taw, &
320 raw, &
321 fraction_exposed_and_wetted_soil, &
322 Kr, &
323 Ke, &
324 Ks, &
325 adjusted_depletion_fraction_p, &
326 soil_moisture_deficit, &
327 evaporable_water_storage, &
328 evaporable_water_deficit, &
329 it_is_growing_season, &
330 Kcb, &
331 landuse_index, &
332 soil_group, &
333 awc, &
334 current_rooting_depth, &
335 current_plant_height, &
336 soil_storage, &
337 soil_storage_max, &
338 reference_et0, &
339 infiltration )
340
341 real (c_double), intent(inout) :: actual_et
342 real (c_float), intent(inout) :: crop_etc
343 real (c_float), intent(inout) :: bare_soil_evap
344 real (c_double), intent(inout) :: taw
345 real (c_double), intent(inout) :: raw
346 real (c_float), intent(inout) :: fraction_exposed_and_wetted_soil
347 real (c_double), intent(inout) :: kr
348 real (c_double), intent(inout) :: ke
349 real (c_double), intent(inout) :: ks
350 real (c_double), intent(inout) :: adjusted_depletion_fraction_p
351 real (c_double), intent(inout) :: soil_moisture_deficit
352 real (c_float), intent(inout) :: current_plant_height
353 real (c_float), intent(inout) :: evaporable_water_storage
354 real (c_float), intent(inout) :: evaporable_water_deficit
355 logical (c_bool), intent(in) :: it_is_growing_season
356 real (c_float), intent(in) :: kcb
357 integer (c_int), intent(in) :: landuse_index
358 integer (c_int), intent(in) :: soil_group
359 real (c_float), intent(in) :: awc
360 real (c_float), intent(in) :: current_rooting_depth
361 real (c_double), intent(in) :: soil_storage
362 real (c_float), intent(in) :: soil_storage_max
363 real (c_double), intent(in) :: reference_et0
364 real (c_float), intent(in) :: infiltration
365
366 real (c_float) :: interim_soil_storage
367 real (c_float) :: interim_soil_storage2
368 real (c_float) :: kcb_max
369
370 current_plant_height = update_plant_height( landuse_index, it_is_growing_season, kcb )
371
372 ! ! !
373 ! for now, hard-wiring reasonable values for SE U.S.
374 kcb_max = crop_coefficients_fao56_calculate_kcb_max(wind_speed_meters_per_sec=2., &
375 relative_humidity_min_pct=55., &
376 kcb=kcb, &
377 plant_height_meters=current_plant_height)
378
379 adjusted_depletion_fraction_p = adjust_depletion_fraction_p( landuse_index, reference_et0 )
380
381
382 call update_evaporable_water_storage( evaporable_water_storage, evaporable_water_deficit, infiltration, &
383 landuse_index, soil_group )
384
385 call calculate_total_available_water( taw, raw, &
386 adjusted_depletion_fraction_p, &
387 current_rooting_depth, &
388 awc )
389
391 soil_group, &
392 evaporable_water_deficit )
393
394 fraction_exposed_and_wetted_soil = calculate_fraction_exposed_and_wetted_soil_fc( landuse_index, kcb, current_plant_height )
395
396 ke = calculate_surface_evap_coefficient_ke( landuse_index, kcb, kcb_max, kr, fraction_exposed_and_wetted_soil )
397
398 bare_soil_evap = real(reference_et0 * ke, c_float)
399 evaporable_water_storage = max(0.0, evaporable_water_storage - bare_soil_evap / fraction_exposed_and_wetted_soil)
400
401 ! need to remove bare soil evap from interim soil to yield lower Ks values
402 interim_soil_storage = clip(real(soil_storage + infiltration, kind=c_float), minval=0.0, maxval=soil_storage_max)
403 interim_soil_storage2 = clip(real(soil_storage + infiltration - bare_soil_evap, kind=c_float), minval=0.0, maxval=soil_storage_max)
404 ! need to update bare soil evap term to reduce it in the event that more evap is calculated than water available
405 bare_soil_evap = clip(interim_soil_storage - interim_soil_storage2, minval=0.0, maxval=soil_storage_max)
406
407 soil_moisture_deficit = max( 0.0_c_double, real(soil_storage_max, c_double) - interim_soil_storage2)
408 ks = calculate_water_stress_coefficient_ks(taw, raw, soil_moisture_deficit)
409
410 crop_etc = real(min(reference_et0 * kcb * ks, real(interim_soil_storage2, c_double)), c_float)
411
412 ! actual_et needs to respect limitations on the amount of remaining soil moisture present
413 actual_et = crop_etc + bare_soil_evap
414
416
Provide support for assessing the effect of irrigation on recharge values by estimating the irrigatio...
real(c_float), dimension(:), allocatable mean_plant_height
impure elemental real(c_float) function update_plant_height(landuse_index, it_is_growing_season, kcb)
This function updates the plant height by scaling values relative to the position of the current Kcb ...
impure elemental real(c_float) function calculate_fraction_exposed_and_wetted_soil_fc(landuse_index, kcb, current_plant_height)
This function estimates the fraction of the ground covered by vegetation during the growing season.
real(c_float), dimension(:), allocatable min_fraction_covered_soil
real(c_float), dimension(:,:), allocatable tew_l
real(c_float), dimension(:,:), allocatable rew_l
elemental subroutine calculate_total_available_water(taw, raw, adjusted_depletion_fraction_p, current_rooting_depth, awc)
This subroutine updates the total available water (TAW) (water within the rootzone) for a gridcell.
elemental real(c_double) function adjust_depletion_fraction_p(landuse_index, reference_et0)
Adjust the depletion fraction based on current reference ET0.
elemental real(c_double) function calculate_water_stress_coefficient_ks(taw, raw, soil_moisture_deficit)
This function estimates Ks, water stress coefficient.
elemental subroutine update_evaporable_water_storage(evaporable_water_storage, evaporable_water_deficit, infiltration, landuse_index, soil_group)
elemental real(c_double) function calculate_evaporation_reduction_coefficient_kr(landuse_index, soil_group, evaporable_water_deficit)
elemental real(c_double) function calculate_surface_evap_coefficient_ke(landuse_index, kcb, kcb_max, kr, fraction_exposed_and_wetted_soil)
This function estimates Ke, the bare surface evaporation coefficient.
impure elemental subroutine calculate_actual_et_fao56_two_stage(actual_et, crop_etc, bare_soil_evap, taw, raw, fraction_exposed_and_wetted_soil, kr, ke, ks, adjusted_depletion_fraction_p, soil_moisture_deficit, evaporable_water_storage, evaporable_water_deficit, it_is_growing_season, kcb, landuse_index, soil_group, awc, current_rooting_depth, current_plant_height, soil_storage, soil_storage_max, reference_et0, infiltration)
real(c_float), dimension(:), allocatable depletion_fraction
This module contains physical constants and convenience functions aimed at performing unit conversion...
logical(c_bool), parameter, public true
real(c_float), parameter, public near_zero
logical(c_bool), parameter, public false
real(c_double), parameter, public m_per_foot
Update crop coefficients for crop types in simulation.
pure elemental real(c_float) function, public crop_coefficients_fao56_calculate_kcb_max(wind_speed_meters_per_sec, relative_humidity_min_pct, kcb, plant_height_meters)
real(c_float), dimension(:,:), allocatable, public kcb_l
integer(c_int), dimension(:), allocatable, public kcb_method
subroutine, public warn(smessage, smodule, iline, shints, lfatal, iloglevel, lecho)
type(logfile_t), public logs
Definition logfiles.F90:62
type(parameters_t), public params