Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
awc__depth_integrated.F90
Go to the documentation of this file.
1!> @file
2!> Contains the module awc__depth_integrated, which populates
3!! the available water content by reading in and depth-averaging
4!! soil available water contents over multiple soil horizons.
5
6
7!> Populate the available water content by reading in and depth-averaging
8!! soil available water contents over multiple soil horizons.
9
11
12 use iso_c_binding, only : c_short, c_int, c_float, c_double
14 use data_catalog
16 use exceptions
17 use parameters
18 use fstring
19 use fstring_list
20
21 implicit none
22
23 private
24
26
28 real (c_float), allocatable :: available_water_content(:,:)
29
30contains
31
32 subroutine awc_depth_integrated_read( fRooting_Depth )
33
34 real (c_float), intent(inout) :: frooting_depth(:,:)
35
36 ! [ LOCALS ]
37
38 integer (c_int), allocatable :: ilanduse_code(:)
39 integer (c_int), allocatable :: isoils_table_code(:)
40 integer (c_int), allocatable :: isoils_components(:)
41 integer (c_int), allocatable :: isoils_horizons(:)
42 real (c_float), allocatable :: fsoils_awc(:)
43 real (c_float), allocatable :: fsoils_top_depth(:)
44 real (c_float), allocatable :: fsoils_bottom_depth(:)
45 real (c_float), allocatable :: fsoils_component_fraction(:)
46 real (c_float), allocatable :: fsoils_horizon_thickness(:)
47
48 integer (c_int) :: inumberoflanduses
49 integer (c_int) :: inumberofsoils
50 integer (c_int) :: inumberofsoilscomponents
51 integer (c_int) :: inumberofsoilshorizons
52 integer (c_int) :: inumberofsoilsawc
53 integer (c_int) :: inumberofsoilstopdepths
54 integer (c_int) :: inumberofsoilsbottomdepths
55 integer (c_int) :: inumberofsoilscomponentfractions
56
57 real (c_float) :: ftemp_awc
58 real (c_float) :: fdepthofdeepesthorizon
59 real (c_float) :: ffinal_awc
60 integer (c_int) :: ideepestsoilhorizon
61 logical (c_bool) :: lfirst
62
63 type (fstring_list_t) :: sllist
64 integer (c_int) :: istat
65 integer (c_int) :: iindex, iindex2
66 integer (c_int) :: iindex_x, iindex_y
67 real (c_float) :: frooting_depth_inches
68 real (c_float) :: fsoil_thickness_total
69
70 call sllist%append("LU_Code")
71 call sllist%append("Landuse_Code")
72 call sllist%append("Landuse_Lookup_Code")
73
74 call params%get_parameters( slkeys=sllist, ivalues=ilanduse_code )
75 inumberoflanduses = count( ilanduse_code >= 0 )
76 call sllist%clear()
77
78
79 call sllist%append("Soils_Code")
80 call sllist%append("Soils_Lookup_Code")
81 call sllist%append("Soil_Code")
82 call sllist%append("Soil_Lookup_Code")
83
84 call params%get_parameters( slkeys=sllist, ivalues=isoils_table_code )
85 inumberofsoils = count( isoils_table_code >= 0 )
86 call sllist%clear()
87
88 call sllist%append("Soils_Component")
89 call sllist%append("Soils_Component_Number")
90 call sllist%append("Soil_Component")
91 call sllist%append("Soil_Component_Number")
92
93 call params%get_parameters( slkeys=sllist, ivalues=isoils_components )
94 inumberofsoilscomponents = count( isoils_components >= 0 )
95 call sllist%clear()
96
97 call sllist%append("Soils_Top_Depth")
98 call sllist%append("Soil_Top_Depth")
99 call sllist%append("Soils_Z_Top")
100 call sllist%append("Soils_Top_of_Horizon")
101
102 call params%get_parameters( slkeys=sllist, fvalues=fsoils_top_depth )
103 inumberofsoilstopdepths = count( fsoils_top_depth >= 0 )
104 call sllist%clear()
105
106 call sllist%append("Soils_Bottom_Depth")
107 call sllist%append("Soil_Bottom_Depth")
108 call sllist%append("Soils_Z_Bottom")
109 call sllist%append("Soils_Bottom_of_Horizon")
110
111 call params%get_parameters( slkeys=sllist, fvalues=fsoils_bottom_depth )
112 inumberofsoilsbottomdepths = count( fsoils_bottom_depth >= 0 )
113 call sllist%clear()
114
115 call sllist%append("Soils_Horizon")
116 call sllist%append("Soils_Horizon_Number")
117 call sllist%append("Soil_Horizon")
118 call sllist%append("Soil_Horizon_Number")
119
120 call params%get_parameters( slkeys=sllist, ivalues=isoils_horizons )
121 inumberofsoilshorizons = count( isoils_horizons >= 0 )
122 call sllist%clear()
123
124 call sllist%append("Soils_Component_Fraction")
125 call sllist%append("Soil_Component_Fraction")
126
127 call params%get_parameters( slkeys=sllist, fvalues=fsoils_component_fraction )
128 inumberofsoilscomponentfractions = count( fsoils_component_fraction >= 0 )
129 call sllist%clear()
130
131
132 call sllist%append("Soils_Available_Water_Content")
133 call sllist%append("Soils_AWC")
134 call sllist%append("Soil_Available_Water_Content")
135 call sllist%append("Soil_AWC")
136 call sllist%append("Available_Water_Content")
137 call sllist%append("AWC")
138
139 call params%get_parameters( slkeys=sllist, fvalues=fsoils_awc )
140 inumberofsoilsawc = count( fsoils_awc >= 0 )
141 call sllist%clear()
142
143 !> @todo Need a *LOT* more data validation and guard code here to prevent execution in the case
144 !! where only some data fields are found, or are only partially populated.
145
146 ! locate the data structure associated with the gridded rainfall zone entries
147 psoils_code_grid => dat%find("SOILS_CODE")
148 call assert( associated(psoils_code_grid), &
149 "A SOILS_CODE grid must be supplied in order to make use of this option.", __file__, __line__)
150
151 call psoils_code_grid%getvalues( )
152
153 allocate (fsoils_horizon_thickness( ubound( fsoils_bottom_depth, 1) ), stat=istat )
154
155 allocate(available_water_content( ubound(frooting_depth, 1), ubound(frooting_depth, 2) ), stat=istat )
156
157 ! this should be in units of inches
158 fsoils_horizon_thickness = fsoils_bottom_depth - fsoils_top_depth
159
160 do iindex_x=lbound( frooting_depth, 1 ), ubound( frooting_depth, 1 )
161
162 do iindex_y=lbound( frooting_depth, 2 ), ubound( frooting_depth, 2 )
163
164 ! rooting depth in feet * 12 in/ft = rooting depth in inches
165 frooting_depth_inches = frooting_depth( iindex_x, iindex_y ) * 12.0_c_float
166
167 ftemp_awc = 0.0_c_float
168 lfirst = true
169 ideepestsoilhorizon = 0_c_int
170 fdepthofdeepesthorizon = 0.0_c_float
171 ffinal_awc = 0.0_c_float
172
173 do iindex=1, inumberofsoils
174 if ( psoils_code_grid%pGrdBase%iData( iindex_x, iindex_y ) == isoils_table_code( iindex ) ) then
175
176 ! look for current soil code; calculate the component-weighted mean AWC for the deepest horizon
177 if ( lfirst ) then
178
179 lfirst = false
180
181 ! find deepest soil horizon for the current soils code
182 do iindex2=iindex, inumberofsoils
183 if ( psoils_code_grid%pGrdBase%iData( iindex_x, iindex_y ) == isoils_table_code( iindex2 ) ) &
184 ideepestsoilhorizon = max( ideepestsoilhorizon, isoils_horizons( iindex2 ) )
185 enddo
186
187 ! if we are in the deepest horizon of the current soils code, calculate the composite averaged AWC
188 do iindex2=iindex, inumberofsoils
189 if ( ( psoils_code_grid%pGrdBase%iData( iindex_x, iindex_y ) == isoils_table_code( iindex2 ) ) &
190 .and. ( ideepestsoilhorizon == isoils_horizons( iindex2) ) ) &
191 ffinal_awc = ffinal_awc + fsoils_awc( iindex2 ) * fsoils_component_fraction( iindex2 )
192 fdepthofdeepesthorizon = fsoils_bottom_depth( iindex2 )
193 enddo
194
195 endif
196
197 ! rooting depth never reaches to this horizon; ignore
198 if ( frooting_depth_inches < fsoils_top_depth( iindex ) ) cycle
199
200 ! rooting depth exceeds lower bound of current horizon; entire horizon
201 ! depth used as weight factor
202 if ( frooting_depth_inches > fsoils_bottom_depth( iindex ) ) then
203
204 ftemp_awc = ftemp_awc + fsoils_awc( iindex ) * fsoils_component_fraction( iindex ) &
205 * fsoils_horizon_thickness( iindex )
206
207 ! rooting depth falls in between the upper and lower bounds of the current soil horizon
208 elseif ( frooting_depth_inches >= fsoils_top_depth( iindex ) &
209 .and. frooting_depth_inches <= fsoils_bottom_depth( iindex ) ) then
210
211 ftemp_awc = ftemp_awc + fsoils_awc( iindex ) * fsoils_component_fraction( iindex ) &
212 * ( frooting_depth_inches - fsoils_top_depth( iindex ) )
213
214 endif
215
216 endif
217
218 enddo
219
220 ! if the soil data from the table does not extend to the rooting depth, extrapolate
221 if (frooting_depth_inches > fdepthofdeepesthorizon ) &
222
223 ftemp_awc = ftemp_awc + ffinal_awc * ( frooting_depth_inches - fdepthofdeepesthorizon )
224
225
226 if ( frooting_depth_inches > 0.0_c_float ) then
227 ftemp_awc = ftemp_awc / frooting_depth_inches ! divide by total rooting depth to obtain weighted average
228 else
229 ftemp_awc = 0.0_c_float
230 endif
231
232 ! table values are in/in; multiply by 12 in/ft to return AWC in inches/foot
233 available_water_content(iindex_x, iindex_y) = ftemp_awc * 12.0_c_float
234
235 enddo
236
237 enddo
238
239
240! Original HWB code...
241
242! c........compute area-weighted soil-moisture storage capacity and account for
243! c depth-varying AWC
244! smca(i,k)=0.
245! do 420 j=1,nseq(i)
246! do 400 l=1,nlay(i,j)
247! if(z.ge.zt(i,j,l).and.z.le.zb(i,j,l))then
248! c...........bottom of root zone is within current layer
249! smca(i,k)=smca(i,k)+pct(i,j,l)*awc(i,j,l)*(z-zt(i,j,l))
250! elseif(z.gt.zb(i,j,l).and.l.eq.nlay(i,j))then
251! c...........bottom of root zone is below current layer, which is the
252! c bottom layer; extrapolate bottom layer down to root depth
253! smca(i,k)=smca(i,k)+pct(i,j,l)*awc(i,j,l)*(z-zt(i,j,l))
254! elseif(z.gt.zb(i,j,l).and.l.lt.nlay(i,j))then
255! c...........bottom of root zone is below current layer, which is not the
256! c bottom layer; include entire current layer
257! smca(i,k)=smca(i,k)+pct(i,j,l)*awc(i,j,l)*
258! 1 (zb(i,j,l)-zt(i,j,l))
259! c...........exit if bottom of root zone is above current layer
260! elseif(z.lt.zt(i,j,l))then
261! goto 440
262! endif
263! 400 continue
264! 420 continue
265! 440 continue
266
267
268
269
270 end subroutine awc_depth_integrated_read
271
272!--------------------------------------------------------------------------------------------------
273
274 subroutine awc_depth_integrated_initialize( lActive, fAWC, iSoils_Code )
275
276 logical (c_bool), intent(in) :: lactive(:,:)
277 real (c_float), intent(inout) :: fawc(:)
278 integer (c_int), intent(inout) :: isoils_code(:)
279
280 isoils_code = pack( psoils_code_grid%pGrdBase%iData, lactive )
281
282 fawc = pack( available_water_content, lactive )
283
285
286end module awc__depth_integrated
Populate the available water content by reading in and depth-averaging soil available water contents ...
subroutine, public awc_depth_integrated_initialize(lactive, fawc, isoils_code)
type(data_catalog_entry_t), pointer psoils_code_grid
subroutine, public awc_depth_integrated_read(frooting_depth)
real(c_float), dimension(:,:), allocatable, public available_water_content
This module contains physical constants and convenience functions aimed at performing unit conversion...
logical(c_bool), parameter, public true
logical(c_bool), parameter, public false
Defines the DATA_CATALOG_T data type, which contains type-bound procedures to add,...
type(data_catalog_t), public dat
DAT is a global to hold data catalog entries.
type(parameters_t), public params