Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
growing_season.F90
Go to the documentation of this file.
2
3 use iso_c_binding
5 use datetime, only : mmdd2doy
6 use exceptions
7 use parameters, only : params
9 use fstring
11 implicit none
12
13 private
14
16 public :: growing_season_update
17
18 integer (c_int), allocatable :: ilandusecodes(:)
19 real (c_float), allocatable :: first_day_of_growing_season(:)
20 real (c_float), allocatable :: last_day_of_growing_season(:)
21 real (c_float), allocatable :: gdd_first_day_of_growing_season(:)
22 real (c_float), allocatable :: killing_frost_temp_last_day_of_growing_season(:)
23
24 character( len=2 ), parameter :: date_delims = "/-"
25 real (c_float), parameter :: nodata_value = -9999._c_float
26
27contains
28
30
31 ! [ LOCALS ]
32 integer (c_int) :: inumberoflanduses
33 logical (c_bool) :: larelengthsequal
34 character (len=:), allocatable :: stemp
35 type (fstring_list_t) :: sl_temp_list
36 type (fstring_list_t) :: sl_growing_season_begin
37 type (fstring_list_t) :: sl_growing_season_end
38 character (len=32) :: str_buffer
39 real (c_float), allocatable :: temp_values(:)
40 integer (c_int) :: indx
41 integer (c_int) :: status
42 integer (c_int) :: count_gdd_start
43 integer (c_int) :: count_killing_frost_end
44 integer (c_int) :: count_grow_start
45 integer (c_int) :: count_grow_end
46
47 !> Determine how many landuse codes are present
48 stemp = "LU_Code"
49 call params%get_parameters( skey=stemp, &
50 ivalues=ilandusecodes )
51
52 inumberoflanduses = count( ilandusecodes >= 0 )
53
54 !> retrieve first day of growing season
55 call sl_temp_list%clear()
56 call sl_temp_list%append("First_day_of_growing_season")
57 call sl_temp_list%append("First_DOY_growing_season")
58 call sl_temp_list%append("Growing_season_start")
59 call sl_temp_list%append("Growing_season_begin")
60
61 call params%get_parameters( slkeys=sl_temp_list, &
62 slvalues=sl_growing_season_begin, &
63 lfatal=false )
64
65 !> process first day of growing season. retrieved as a list of strings;
66 !! must convert the strings from mm/dd to DOY
67 allocate( first_day_of_growing_season( inumberoflanduses ), stat=status )
68 call assert( status==0, "Problem allocating memory.", __file__, __line__ )
69
70 if ( sl_growing_season_begin%count == inumberoflanduses &
71 .and. sl_growing_season_begin%count_matching("<NA>") == 0 ) then
72
73 do indx = 1, sl_growing_season_begin%count
74 str_buffer = sl_growing_season_begin%get( indx )
75
76 if ( scan( str_buffer, date_delims ) > 0 ) then
77 first_day_of_growing_season( indx ) = mmdd2doy( str_buffer, "FIRST_DAY_OF_GROWING_SEASON" )
78 else
79 first_day_of_growing_season( indx ) = asint( str_buffer )
80 endif
81 enddo
82
83 else
84
86
87 endif
88
89 !> retrieve last day of growing season
90 call sl_temp_list%clear()
91 call sl_temp_list%append("Last_day_of_growing_season")
92 call sl_temp_list%append("Last_DOY_growing_season")
93 call sl_temp_list%append("Growing_season_end")
94 call sl_temp_list%append("Growing_season_stop")
95
96 call params%get_parameters( slkeys=sl_temp_list, &
97 slvalues=sl_growing_season_end, &
98 lfatal=false)
99
100 !> process last day of growing season. retrieved as a list of strings;
101 !! must convert the strings from mm/dd to DOY
102 allocate( last_day_of_growing_season( inumberoflanduses ), stat=status )
103 call assert( status==0, "Problem allocating memory.", __file__, __line__ )
104
105 if ( sl_growing_season_end%count == inumberoflanduses &
106 .and. sl_growing_season_end%count_matching("<NA>") == 0 ) then
107
108 do indx = 1, sl_growing_season_end%count
109 str_buffer = sl_growing_season_end%get( indx )
110 if ( scan( str_buffer, date_delims ) > 0 ) then
111 last_day_of_growing_season( indx ) = mmdd2doy( str_buffer, "LAST_DAY_OF_GROWING_SEASON" )
112 else
113 last_day_of_growing_season( indx ) = asint( str_buffer )
114 endif
115 enddo
116
117 else
118
120
121 endif
122
123 !> GDD for first day of growing season
124 call sl_temp_list%clear()
125 call sl_temp_list%append("GDD_first_day_of_growing_season")
126 call sl_temp_list%append("GDD_start_of_growing_season")
127 call sl_temp_list%append("GDD_growing_season_start")
128
129 call params%get_parameters( slkeys=sl_temp_list, &
130 fvalues=temp_values, &
131 lfatal=false )
132
133 larelengthsequal = ( ubound(temp_values,1) == ubound(ilandusecodes,1) )
134
135 if ( larelengthsequal ) then
136
137 call move_alloc( temp_values, gdd_first_day_of_growing_season )
138
139 else
140
141 call warn( smessage="The number of landuses does not match the number of GDD values " &
142 //"specified for defining the beginning of the growing season.", &
143 smodule=__file__, iline=__line__, lfatal=false )
144
145 allocate( gdd_first_day_of_growing_season( ubound( ilandusecodes, 1) ), stat=status )
146 call assert( status==0, "Problem allocating memory.", __file__, __line__)
147
149
150 endif
151
152 !> Air temperature defining last day of growing season
153 call sl_temp_list%clear()
154 call sl_temp_list%append("Killing_frost_temperature")
155 call sl_temp_list%append("Air_temperature_end_of_growing_season")
156 call sl_temp_list%append("Air_temperature_growing_season_end")
157
158 call params%get_parameters( slkeys=sl_temp_list, &
159 fvalues=temp_values, &
160 lfatal=false )
161
162 larelengthsequal = ( ubound(temp_values,1) == ubound(ilandusecodes,1) )
163
164 if ( larelengthsequal ) then
165
166 call move_alloc( temp_values, killing_frost_temp_last_day_of_growing_season )
167
168 else
169
170 call warn( smessage="The number of landuses does not match the number of killing frost values " &
171 //"specified to define the end of the growing season.", &
172 smodule=__file__, iline=__line__, lfatal=false )
173
174 allocate( killing_frost_temp_last_day_of_growing_season( ubound( ilandusecodes, 1) ), stat=status )
175 call assert( status==0, "Problem allocating memory.", __file__, __line__)
176
178
179 endif
180
181 count_gdd_start = count( gdd_first_day_of_growing_season > nodata_value )
182 count_killing_frost_end = count( killing_frost_temp_last_day_of_growing_season > nodata_value )
183 count_grow_start = count( first_day_of_growing_season > nodata_value )
184 count_grow_end = count( last_day_of_growing_season > nodata_value )
185
186 if ( (count_gdd_start == 0) .and. (count_killing_frost_end == 0) &
187 .and. (count_grow_start == 0) .and. (count_grow_end == 0) ) &
188 call warn( smessage="A pair of values (GDD or DOY) must be given to " &
189 //"define the start and end of the growing season for each landuse" &
190 //" present in the lookup table.", lfatal=true)
191
192 if ( count_gdd_start /= count_killing_frost_end ) &
193 call warn( smessage="Unequal numbers of values given for defining the " &
194 //"start (GDD_first_day_of_growing_season) and end (Killing_frost_temperature) " &
195 //"of the growing season.", smodule=__file__, iline=__line__, lfatal=true )
196
197 if ( count_grow_start /= count_grow_end ) &
198 call warn( smessage="Unequal numbers of values given for defining the " &
199 //"start (Growing_season_start) and end (Growing_season_end) of the " &
200 //"growing season.", smodule=__file__, iline=__line__, lfatal=true )
201
202 if ( ( (count_gdd_start + count_grow_start) /= ubound( ilandusecodes, 1) ) &
203 .and. ( (count_gdd_start + count_grow_start) > 0 ) ) &
204 call warn( smessage="Two growing season start definitions " &
205 //"(GDD_first_day_of_growing_season and Growing_season_start) are " &
206 //"provided for one or more land uses. Only one of these values " &
207 //"should be non-zero for each entry the lookup table.", &
208 smodule=__file__, iline=__line__, lfatal=true )
209
210 if ( ( (count_killing_frost_end + count_grow_end) /= ubound( ilandusecodes, 1) ) &
211 .and. ( (count_killing_frost_end + count_grow_end) > 0) ) &
212 call warn( smessage="Two growing season ending definitions " &
213 //"(Killing_frost_temperature and Growing_season_end) are " &
214 //"provided for one or more land uses. Only one of these values " &
215 //"should be non-zero for each entry the lookup table.", &
216 smodule=__file__, iline=__line__, lfatal=true )
217
218 end subroutine growing_season_initialize
219
220!--------------------------------------------------------------------------------------------------
221
222 elemental subroutine growing_season_update( landuse_index, &
223 GDD, &
224 mean_air_temp, &
225 it_is_growing_season )
226
227 integer (c_int), intent(in) :: landuse_index
228 real (c_float), intent(in) :: gdd
229 real (c_float), intent(in) :: mean_air_temp
230 logical (c_bool), intent(inout) :: it_is_growing_season
231
232 ! first growing season day > last if we are growing a winter crop, winter wheat for example
233 if ( first_day_of_growing_season(landuse_index) > last_day_of_growing_season(landuse_index) ) then
234
235 if ( it_is_growing_season ) then
236
238
239 if ( mean_air_temp <= killing_frost_temp_last_day_of_growing_season( landuse_index ) ) &
240 it_is_growing_season = false
241
242 elseif ( sim_dt%iDOY > last_day_of_growing_season( landuse_index ) ) then
243 it_is_growing_season = false
244 endif
245
246 else ! not growing season; should it be?
247
248 if ( gdd_first_day_of_growing_season( landuse_index ) > nodata_value ) then
249
250 if ( gdd >= gdd_first_day_of_growing_season( landuse_index ) ) &
251 it_is_growing_season = true
252 elseif ( ( sim_dt%iDOY <= last_day_of_growing_season( landuse_index ) ) &
253 .or. ( sim_dt%iDOY >= first_day_of_growing_season( landuse_index ) ) ) then
254 it_is_growing_season = true
255 endif
256
257 endif
258
259 else ! normal situation where FIRST day of growing season < LAST day of growing season
260
261 if ( it_is_growing_season ) then
262
264
265 if ( mean_air_temp <= killing_frost_temp_last_day_of_growing_season( landuse_index ) ) &
266 it_is_growing_season = false
267
268 elseif ( sim_dt%iDOY > last_day_of_growing_season( landuse_index ) ) then
269 it_is_growing_season = false
270 endif
271
272 else ! not growing season; should it be?
273
274 if ( gdd_first_day_of_growing_season( landuse_index ) > nodata_value ) then
275
276 if ( gdd >= gdd_first_day_of_growing_season( landuse_index ) ) &
277 it_is_growing_season = true
278 else
279
280 if ( sim_dt%iDOY <= last_day_of_growing_season( landuse_index ) &
281 .and. sim_dt%iDOY >= first_day_of_growing_season( landuse_index ) ) &
282 it_is_growing_season = true
283
284 endif
285
286 endif
287
288 endif
289
290 end subroutine growing_season_update
291
292end module growing_season
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
This module contains the DATETIME_T class and associated time and date-related routines,...
Definition datetime.F90:9
integer(c_int) function, public mmdd2doy(smmdd, sinputitemname)
subroutine, public warn(smessage, smodule, iline, shints, lfatal, iloglevel, lecho)
elemental subroutine, public growing_season_update(landuse_index, gdd, mean_air_temp, it_is_growing_season)
real(c_float), dimension(:), allocatable last_day_of_growing_season
real(c_float), dimension(:), allocatable first_day_of_growing_season
character(len=2), parameter date_delims
integer(c_int), dimension(:), allocatable ilandusecodes
real(c_float), dimension(:), allocatable killing_frost_temp_last_day_of_growing_season
subroutine, public growing_season_initialize()
real(c_float), dimension(:), allocatable gdd_first_day_of_growing_season
real(c_float), parameter nodata_value
type(parameters_t), public params
type(date_range_t), public sim_dt