Skip to content

timestep

aquacrop.timestep

aquacrop.timestep.check_if_model_is_finished

check_model_is_finished(step_end_time, simulation_end_date, model_is_finished, season_counter, n_seasons, harvest_flag)

Function to check and declare model termination

Arguments:

step_end_time (str):  date of next step

simulation_end_date (str):  date of end of simulation

model_is_finished (bool):  is model finished

season_counter (int):  tracking the number of seasons simulated

n_seasons (int):  total number of seasons being simulated

harvest_flag (bool):  Has crop been harvested

Returns:

model_is_finished (bool): is simulation finished
Source code in aquacrop/timestep/check_if_model_is_finished.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def check_model_is_finished(
    step_end_time: str,
    simulation_end_date: str,
    model_is_finished: bool,
    season_counter: int,
    n_seasons: int,
    harvest_flag: bool,
) -> bool:
    """
    Function to check and declare model termination


    Arguments:

        step_end_time (str):  date of next step

        simulation_end_date (str):  date of end of simulation

        model_is_finished (bool):  is model finished

        season_counter (int):  tracking the number of seasons simulated

        n_seasons (int):  total number of seasons being simulated

        harvest_flag (bool):  Has crop been harvested

    Returns:

        model_is_finished (bool): is simulation finished


    """

    # Check if current time-step is the last
    current_time = step_end_time
    if current_time < simulation_end_date:
        model_is_finished = False
    elif current_time >= simulation_end_date:
        model_is_finished = True

    # Check if at the end of last growing season ##
    # Allow model to exit early if crop has reached maturity or died, and in
    # the last simulated growing season
    if (harvest_flag is True) and (season_counter == n_seasons - 1):
        model_is_finished = True

    return model_is_finished

aquacrop.timestep.outputs_when_model_is_finished

outputs_when_model_is_finished(model_is_finished, flux_output, water_output, growth_outputs, steps_are_finished)

Function that turns numpy array outputs into pandas dataframes

Arguments:

model_is_finished (bool):  is model finished

flux_output (numpy.array): water flux_output

water_output (numpy.array):  water storage in each compartment

growth_outputs (numpy.array):  crop growth variables

n_seasons (int):  total number of seasons being simulated

steps_are_finished (bool):  have the simulated num_steps finished

Returns:

flux_output (pandas.DataFrame): water flux_output

water_output (pandas.DataFrame):  water storage in each compartment

growth_outputs (pandas.DataFrame):  crop growth variables
Source code in aquacrop/timestep/outputs_when_model_is_finished.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def outputs_when_model_is_finished(
    model_is_finished: bool,
    flux_output: "ndarray",
    water_output: "ndarray",
    growth_outputs: "ndarray",
    steps_are_finished: bool,
):
    """
    Function that turns numpy array outputs into pandas dataframes

    Arguments:

        model_is_finished (bool):  is model finished

        flux_output (numpy.array): water flux_output

        water_output (numpy.array):  water storage in each compartment

        growth_outputs (numpy.array):  crop growth variables

        n_seasons (int):  total number of seasons being simulated

        steps_are_finished (bool):  have the simulated num_steps finished

    Returns:

        flux_output (pandas.DataFrame): water flux_output

        water_output (pandas.DataFrame):  water storage in each compartment

        growth_outputs (pandas.DataFrame):  crop growth variables


    """
    if model_is_finished is True or steps_are_finished is True:
        # ClockStruct.step_start_time = ClockStruct.step_end_time
        # ClockStruct.step_end_time = ClockStruct.step_end_time + np.timedelta64(1, "D")
        flux_output_df = pd.DataFrame(
            flux_output,
            columns=[
                "time_step_counter",
                "season_counter",
                "dap",
                "Wr",
                "z_gw",
                "surface_storage",
                "IrrDay",
                "Infl",
                "Runoff",
                "DeepPerc",
                "CR",
                "GwIn",
                "Es",
                "EsPot",
                "Tr",
                "TrPot",
            ],
        )

        water_output_df = pd.DataFrame(
            water_output,
            columns=["time_step_counter", "growing_season", "dap"]
            + ["th" + str(i) for i in range(1, water_output.shape[1] - 2)],
        )

        growth_outputs_df = pd.DataFrame(
            growth_outputs,
            columns=[
                "time_step_counter",
                "season_counter",
                "dap",
                "gdd",
                "gdd_cum",
                "z_root",
                "canopy_cover",
                "canopy_cover_ns",
                "biomass",
                "biomass_ns",
                "harvest_index",
                "harvest_index_adj",
                "DryYield",
                "FreshYield",
                "YieldPot",
            ],
        )

        return flux_output_df, water_output_df, growth_outputs_df

    return False

aquacrop.timestep.reset_initial_conditions

reset_initial_conditions(ClockStruct, InitCond, ParamStruct, weather, crop)

Function to reset initial model conditions for start of growing season (when running model over multiple seasons)

Arguments:

ClockStruct (ClockStruct):  model time paramaters

InitCond (InitialCondition):  containing current model paramaters

ParamStruct (ParamStruct):  containing current model paramaters

weather (numpy.ndarray):  weather data for simulation period

Returns:

InitCond (InitialCondition):  containing reset simulation variables and counters

ParamStruct (ParamStruct):  contains all model params
Source code in aquacrop/timestep/reset_initial_conditions.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
def reset_initial_conditions(
    ClockStruct: "ClockStruct",
    InitCond: "InitialCondition",
    ParamStruct: "ParamStruct",
    weather: "ndarray",
    crop: "Crop") -> Tuple["InitialCondition", "ParamStruct"]:

    """
    Function to reset initial model conditions for start of growing
    season (when running model over multiple seasons)

    Arguments:

        ClockStruct (ClockStruct):  model time paramaters

        InitCond (InitialCondition):  containing current model paramaters

        ParamStruct (ParamStruct):  containing current model paramaters

        weather (numpy.ndarray):  weather data for simulation period


    Returns:

        InitCond (InitialCondition):  containing reset simulation variables and counters

        ParamStruct (ParamStruct):  contains all model params



    """

    # Extract crop type
    # TODO: This is necessary?
    CropType = ParamStruct.CropChoices[ClockStruct.season_counter]

    # Extract structures for updating
    Soil = ParamStruct.Soil
    crop = ParamStruct.Seasonal_Crop_List[ClockStruct.season_counter]
    FieldMngt = ParamStruct.FieldMngt

    # Reset counters
    InitCond.age_days = 0
    InitCond.age_days_ns = 0
    InitCond.aer_days = 0
    InitCond.irr_cum = 0
    InitCond.delayed_gdds = 0
    InitCond.delayed_cds = 0
    InitCond.pct_lag_phase = 0
    InitCond.t_early_sen = 0
    InitCond.gdd_cum = 0
    InitCond.day_submerged = 0
    InitCond.irr_net_cum = 0
    InitCond.dap = 0

    InitCond.aer_days_comp = np.zeros(int(Soil.nComp))

    # Reset states
    # States
    InitCond.pre_adj = False
    InitCond.crop_mature = False
    InitCond.crop_dead = False
    InitCond.germination = False
    InitCond.premat_senes = False
    InitCond.harvest_flag = False

    # Harvest index
    # harvest_index
    InitCond.stage = 1
    InitCond.f_pre = 1
    InitCond.f_post = 1
    InitCond.fpost_dwn = 1
    InitCond.fpost_upp = 1

    InitCond.h1_cor_asum = 0
    InitCond.h1_cor_bsum = 0
    InitCond.f_pol = 0
    InitCond.s_cor1 = 0
    InitCond.s_cor2 = 0

    # Growth stage
    InitCond.growth_stage = 0

    # Transpiration
    InitCond.tr_ratio = 1

    # crop growth
    InitCond.r_cor = 1

    InitCond.canopy_cover = 0
    InitCond.canopy_cover_adj = 0
    InitCond.canopy_cover_ns = 0
    InitCond.canopy_cover_adj_ns = 0
    InitCond.biomass = 0
    InitCond.biomass_ns = 0
    InitCond.harvest_index = 0
    InitCond.harvest_index_adj = 0
    InitCond.ccx_act = 0
    InitCond.ccx_act_ns = 0
    InitCond.ccx_w = 0
    InitCond.ccx_w_ns = 0
    InitCond.ccx_early_sen = 0
    InitCond.cc_prev = 0
    InitCond.protected_seed = 0
    InitCond.sumET0EarlySen = 0
    InitCond.HIfinal = crop.HI0
    InitCond.DryYield = 0
    InitCond.FreshYield = 0

    # Update CO2 concentration ##
    # Get CO2 concentration

    # if user specified constant concentration
    if  ParamStruct.CO2.constant_conc is True:
        if ParamStruct.CO2.current_concentration > 0.:
            CO2conc = ParamStruct.CO2.current_concentration
        else:
            CO2conc = ParamStruct.CO2.co2_data_processed.iloc[0]
    else:
        Yri = pd.DatetimeIndex([ClockStruct.step_start_time]).year[0]
        CO2conc = ParamStruct.CO2.co2_data_processed.loc[Yri]

    ParamStruct.CO2.current_concentration = CO2conc

    # Get CO2 weighting factor for first year
    CO2conc = ParamStruct.CO2.current_concentration
    CO2ref = ParamStruct.CO2.ref_concentration

    if CO2conc <= CO2ref:
        fw = 0
    else:
        if CO2conc >= 550:
            fw = 1
        else:
            fw = 1 - ((550 - CO2conc) / (550 - CO2ref))

    # Determine initial adjustment
    if CO2conc <= 550:
        # Set weighting factor for CO2
        if CO2conc <= CO2ref:
            fw = 0
        elif CO2conc >= 550:
            fw = 1
        else:
            fw = 1 - ((550 - CO2conc) / (550 - CO2ref))
        # Set fCO2old within the 'if CO2conc <= 550' block:
        fCO2old = (CO2conc / CO2ref) / (
            1
            + (CO2conc - CO2ref)
            * (
                (1 - fw) * crop.bsted
                + fw * ((crop.bsted * crop.fsink) + (crop.bface * (1 - crop.fsink)))
            )
        )
    # New adjusted correction coefficient for CO2 (version 7 of AquaCrop)
    if (CO2conc > CO2ref):
        # Calculate shape factor
        fshape = -4.61824 - 3.43831*crop.fsink - 5.32587*crop.fsink*crop.fsink
        # Determine adjustment for CO2
        if (CO2conc >= 2000):
            fCO2new = 1.58  # Maximum CO2 adjustment 
        else:
            CO2rel = (CO2conc-CO2ref)/(2000-CO2ref)
            fCO2new = 1 + 0.58 * ((np.exp(CO2rel*fshape) - 1)/(np.exp(fshape) - 1))


    # Select adjusted coefficient for CO2
    if (CO2conc <= CO2ref):
        fCO2 = fCO2old
    else:
        fCO2 = fCO2new
        if ((CO2conc <= 550) and (fCO2old < fCO2new)): 
            fCO2 = fCO2old


    # Consider crop type
    if crop.WP >= 40:
        # No correction for C4 crops
        ftype = 0
    elif crop.WP <= 20:
        # Full correction for C3 crops
        ftype = 1
    else:
        ftype = (40 - crop.WP) / (40 - 20)

    # Total adjustment
    crop.fCO2 = 1 + ftype * (fCO2 - 1)

    # Reset soil water conditions (if not running off-season)
    if ClockStruct.sim_off_season is False:
        # Reset water content to starting conditions
        InitCond.th = InitCond.thini
        # Reset surface storage
        if (FieldMngt.bunds) and (FieldMngt.z_bund > 0.001):
            # Get initial storage between surface bunds
            InitCond.surface_storage = min(FieldMngt.bund_water, FieldMngt.z_bund)
        else:
            # No surface bunds
            InitCond.surface_storage = 0

    # Update crop parameters (if in gdd mode)
    if crop.CalendarType == 2:
        # Extract weather data for upcoming growing season
        weather_df = weather[
            weather[:, 4] >= ClockStruct.planting_dates[ClockStruct.season_counter]
        ]

        temp_min = weather_df[:, 0]
        temp_max = weather_df[:, 1]

        # Calculate gdd's
        if crop.GDDmethod == 1:
            Tmean = (temp_max + temp_min) / 2
            Tmean[Tmean > crop.Tupp] = crop.Tupp
            Tmean[Tmean < crop.Tbase] = crop.Tbase
            gdd = Tmean - crop.Tbase
        elif crop.GDDmethod == 2:
            temp_max[temp_max > crop.Tupp] = crop.Tupp
            temp_max[temp_max < crop.Tbase] = crop.Tbase
            temp_min[temp_min > crop.Tupp] = crop.Tupp
            temp_min[temp_min < crop.Tbase] = crop.Tbase
            Tmean = (temp_max + temp_min) / 2
            gdd = Tmean - crop.Tbase
        elif crop.GDDmethod == 3:
            temp_max[temp_max > crop.Tupp] = crop.Tupp
            temp_max[temp_max < crop.Tbase] = crop.Tbase
            temp_min[temp_min > crop.Tupp] = crop.Tupp
            Tmean = (temp_max + temp_min) / 2
            Tmean[Tmean < crop.Tbase] = crop.Tbase
            gdd = Tmean - crop.Tbase

        gdd_cum = np.cumsum(gdd)

        assert (
            gdd_cum[-1] > crop.Maturity
        ), f"not enough growing degree days in simulation ({gdd_cum[-1]}) to reach maturity ({crop.Maturity})"

        crop.MaturityCD = np.argmax((gdd_cum > crop.Maturity)) + 1

        assert crop.MaturityCD < 365, "crop will take longer than 1 year to mature"

        # 1. gdd's from sowing to maximum canopy cover
        crop.MaxCanopyCD = (gdd_cum > crop.MaxCanopy).argmax() + 1
        # 2. gdd's from sowing to end of vegetative growth
        crop.CanopyDevEndCD = (gdd_cum > crop.CanopyDevEnd).argmax() + 1
        # 3. Calendar days from sowing to start of yield_ formation
        crop.HIstartCD = (gdd_cum > crop.HIstart).argmax() + 1
        # 4. Calendar days from sowing to end of yield_ formation
        crop.HIendCD = (gdd_cum > crop.HIend).argmax() + 1
        # 5. Duration of yield_ formation in calendar days
        crop.YldFormCD = crop.HIendCD - crop.HIstartCD
        if crop.CropType == 3:
            # 1. Calendar days from sowing to end of flowering
            FloweringEnd = (gdd_cum > crop.FloweringEnd).argmax() + 1
            # 2. Duration of flowering in calendar days
            crop.FloweringCD = FloweringEnd - crop.HIstartCD
        else:
            crop.FloweringCD = ModelConstants.NO_VALUE

        # Update harvest index growth coefficient
        crop.HIGC = calculate_HIGC(
            crop.YldFormCD,
            crop.HI0,
            crop.HIini,
        )

        # Update day to switch to linear harvest_index build-up
        if crop.CropType == 3:
            # Determine linear switch point and HIGC rate for fruit/grain crops
            crop.tLinSwitch, crop.dHILinear = calculate_HI_linear(
                crop.YldFormCD, crop.HIini, crop.HI0, crop.HIGC
            )

        else:
            # No linear switch for leafy vegetable or root/tiber crops
            crop.tLinSwitch = 0
            crop.dHILinear = 0.0

    # Update global variables
    ParamStruct.Seasonal_Crop_List[ClockStruct.season_counter] = crop

    return InitCond, ParamStruct

aquacrop.timestep.run_single_timestep

solution_single_time_step(init_cond, param_struct, clock_struct, weather_step, outputs)

Function to perform AquaCrop solution for a single time step

Arguments:

init_cond (InitialCondition):  containing current variables+counters

param_struct (ParamStruct):  contains model paramaters

clock_struct (ClockStruct):  model time paramaters

weather_step (numpy.ndarray):  contains precipitation,ET,temp_max,temp_min for current day

outputs (Output):  object to store outputs

Returns:

NewCond (InitialCondition):  containing updated simulation variables+counters

param_struct (ParamStruct):  contains model paramaters

outputs (Output):  object to store outputs
Source code in aquacrop/timestep/run_single_timestep.py
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
def solution_single_time_step(
    init_cond: "InitialCondition",
    param_struct: "ParamStruct",
    clock_struct: "ClockStruct",
    weather_step: "ndarray",
    outputs:"Output",
) ->  Tuple["InitialCondition", "ParamStruct","Output"]:
    """
    Function to perform AquaCrop solution for a single time step

    Arguments:

        init_cond (InitialCondition):  containing current variables+counters

        param_struct (ParamStruct):  contains model paramaters

        clock_struct (ClockStruct):  model time paramaters

        weather_step (numpy.ndarray):  contains precipitation,ET,temp_max,temp_min for current day

        outputs (Output):  object to store outputs

    Returns:

        NewCond (InitialCondition):  containing updated simulation variables+counters

        param_struct (ParamStruct):  contains model paramaters

        outputs (Output):  object to store outputs

    """

    # Unpack structures
    Soil = param_struct.Soil
    CO2 = param_struct.CO2
    precipitation = weather_step[2]
    temp_max = weather_step[1]
    temp_min = weather_step[0]
    et0 = weather_step[3]

    # Store initial conditions in structure for updating %%
    NewCond = init_cond
    if param_struct.water_table == 1:
        GroundWater = param_struct.z_gw[clock_struct.time_step_counter]
    else:
        GroundWater = 0

    # Check if growing season is active on current time step %%
    if clock_struct.season_counter >= 0:
        # Check if in growing season
        CurrentDate = clock_struct.step_start_time
        planting_date = clock_struct.planting_dates[clock_struct.season_counter]
        harvest_date = clock_struct.harvest_dates[clock_struct.season_counter]

        if (
            (planting_date <= CurrentDate)
            and (harvest_date >= CurrentDate)
            and (NewCond.crop_mature is False)
            and (NewCond.crop_dead is False)
        ):
            growing_season = True
        else:
            growing_season = False

        # Assign crop, irrigation management, and field management structures
        Crop_ = param_struct.Seasonal_Crop_List[clock_struct.season_counter]
        Crop_Name = param_struct.CropChoices[clock_struct.season_counter]
        IrrMngt = param_struct.IrrMngt

        if growing_season is True:
            FieldMngt = param_struct.FieldMngt
        else:
            FieldMngt = param_struct.FallowFieldMngt

    else:
        # Not yet reached start of first growing season
        growing_season = False
        # Assign crop, irrigation management, and field management structures
        # Assign first crop as filler crop
        Crop_ = param_struct.Fallow_Crop
        Crop_Name = "fallow"

        Crop_.Aer = 5
        Crop_.Zmin = 0.3
        IrrMngt = param_struct.FallowIrrMngt
        FieldMngt = param_struct.FallowFieldMngt

    # Increment time counters %%
    if growing_season is True:
        # Calendar days after planting
        NewCond.dap = NewCond.dap + 1
        # Growing degree days after planting

        gdd = growing_degree_day(
            Crop_.GDDmethod, Crop_.Tupp, Crop_.Tbase, temp_max, temp_min
        )

        # Update cumulative gdd counter
        NewCond.gdd = gdd
        NewCond.gdd_cum = NewCond.gdd_cum + gdd

        NewCond.growing_season = True
    else:
        NewCond.growing_season = False

        # Calendar days after planting
        NewCond.dap = 0
        # Growing degree days after planting
        gdd = 0.3
        NewCond.gdd_cum = 0

    # save current timestep counter
    NewCond.time_step_counter = clock_struct.time_step_counter
    NewCond.precipitation = weather_step[2]
    NewCond.temp_max = weather_step[1]
    NewCond.temp_min = weather_step[0]
    NewCond.et0 = weather_step[3]


    class_args = {
        key: value
        for key, value in Crop_.__dict__.items()
        if not key.startswith("__") and not callable(key)
    }
    Crop = CropStructNT(**class_args)

    # Run simulations %%
    # 1. Check for groundwater table
    NewCond.th_fc_Adj, NewCond.wt_in_soil, NewCond.z_gw = check_groundwater_table(
        Soil.Profile,
        NewCond.z_gw,
        NewCond.th,
        NewCond.th_fc_Adj,
        param_struct.water_table,
        GroundWater
    )

    # 2. Root development
    NewCond.z_root, NewCond.r_cor = root_development(
        Crop,
        Soil.Profile,
        NewCond.dap,
        NewCond.z_root,
        NewCond.delayed_cds,
        NewCond.gdd_cum,
        NewCond.delayed_gdds,
        NewCond.tr_ratio,
        NewCond.th,
        NewCond.canopy_cover,
        NewCond.canopy_cover_ns,
        NewCond.germination,
        NewCond.r_cor,
        NewCond.t_pot,
        NewCond.z_gw,
        gdd,
        growing_season,
        param_struct.water_table,
    )

    # 3. Pre-irrigation
    NewCond, PreIrr = pre_irrigation(
        Soil.Profile, Crop, NewCond, growing_season, IrrMngt
    )

    # 4. Drainage

    NewCond.th, DeepPerc, FluxOut = drainage(
        Soil.Profile,
        NewCond.th,
        NewCond.th_fc_Adj,
    )

    # 5. Surface runoff
    Runoff, Infl, NewCond.day_submerged = rainfall_partition(
        precipitation,
        NewCond.th,
        NewCond.day_submerged,
        FieldMngt.sr_inhb,
        FieldMngt.bunds,
        FieldMngt.z_bund,
        FieldMngt.curve_number_adj_pct,
        Soil.cn,
        Soil.adj_cn,
        Soil.z_cn,
        Soil.nComp,
        Soil.Profile,
    )

    # 6. Irrigation
    NewCond.depletion, NewCond.taw, NewCond.irr_cum, Irr = irrigation(
        IrrMngt.irrigation_method,
        IrrMngt.SMT,
        IrrMngt.AppEff,
        IrrMngt.MaxIrr,
        IrrMngt.IrrInterval,
        IrrMngt.Schedule,
        IrrMngt.depth,
        IrrMngt.MaxIrrSeason,
        NewCond.growth_stage,
        NewCond.irr_cum,
        NewCond.e_pot,
        NewCond.t_pot,
        NewCond.z_root,
        NewCond.th,
        NewCond.dap,
        NewCond.time_step_counter,
        Crop,
        Soil.Profile,
        Soil.z_top,
        growing_season,
        precipitation,
        Runoff,
    )

    # 7. Infiltration
    (
        NewCond.th,
        NewCond.surface_storage,
        DeepPerc,
        Runoff,
        Infl,
        FluxOut,
    ) = infiltration(
        Soil.Profile,
        NewCond.surface_storage,
        NewCond.th_fc_Adj,
        NewCond.th,
        Infl,
        Irr,
        IrrMngt.AppEff,
        FieldMngt.bunds,
        FieldMngt.z_bund,
        FluxOut,
        DeepPerc,
        Runoff,
        growing_season,
    )
    # 8. Capillary Rise
    NewCond, CR = capillary_rise(
        Soil.Profile,
        Soil.nLayer,
        Soil.fshape_cr,
        NewCond,
        FluxOut,
        param_struct.water_table,
    )

    # 9. Check germination
    NewCond = germination(
        NewCond,
        Soil.z_germ,
        Soil.Profile,
        Crop.GermThr,
        Crop.PlantMethod,
        gdd,
        growing_season,
    )

    # 10. Update growth stage
    NewCond = growth_stage(Crop, NewCond, growing_season)

    # 11. Canopy cover development
    NewCond = canopy_cover(
        Crop, Soil.Profile, Soil.z_top, NewCond, gdd, et0, growing_season
    )

    # 12. Soil evaporation
    (
        NewCond.e_pot,
        NewCond.th,
        NewCond.stage2,
        NewCond.w_stage_2,
        NewCond.w_surf,
        NewCond.surface_storage,
        NewCond.evap_z,
        Es,
        EsPot,
    ) = soil_evaporation(
        clock_struct.evap_time_steps,
        clock_struct.sim_off_season,
        clock_struct.time_step_counter,
        Soil.Profile,
        Soil.evap_z_min,
        Soil.evap_z_max,
        Soil.rew,
        Soil.kex,
        Soil.fwcc,
        Soil.f_wrel_exp,
        Soil.f_evap,
        Crop.CalendarType,
        Crop.Senescence,
        IrrMngt.irrigation_method,
        IrrMngt.WetSurf,
        FieldMngt.mulches,
        FieldMngt.f_mulch,
        FieldMngt.mulch_pct,
        NewCond.dap,
        NewCond.w_surf,
        NewCond.evap_z,
        NewCond.stage2,
        NewCond.th,
        NewCond.delayed_cds,
        NewCond.gdd_cum,
        NewCond.delayed_gdds,
        NewCond.ccx_w,
        NewCond.canopy_cover_adj,
        NewCond.ccx_act,
        NewCond.canopy_cover,
        NewCond.premat_senes,
        NewCond.surface_storage,
        NewCond.w_stage_2,
        NewCond.e_pot,
        et0,
        Infl,
        precipitation,
        Irr,
        growing_season,
    )

    # 13. Crop transpiration
    Tr, TrPot_NS, TrPot, NewCond, IrrNet = transpiration(
        Soil.Profile,
        Soil.nComp,
        Soil.z_top,
        Crop,
        IrrMngt.irrigation_method,
        IrrMngt.NetIrrSMT,
        NewCond,
        et0,
        CO2,
        growing_season,
        gdd,
    )

    # 14. Groundwater inflow
    NewCond, GwIn = groundwater_inflow(Soil.Profile, NewCond)

    # 15. Reference harvest index
    (NewCond.hi_ref, NewCond.yield_form, NewCond.pct_lag_phase) = HIref_current_day( # ,NewCond.HIfinal
        NewCond.hi_ref,
        NewCond.HIfinal,
        NewCond.dap,
        NewCond.delayed_cds,
        NewCond.yield_form,
        NewCond.pct_lag_phase,
        NewCond.canopy_cover,
        NewCond.cc_prev,
        NewCond.ccx_w,
        Crop,
        growing_season,
    )

    # 16. Biomass accumulation
    (NewCond.biomass, NewCond.biomass_ns) = biomass_accumulation(
        Crop,
        NewCond.dap,
        NewCond.delayed_cds,
        NewCond.hi_ref,
        NewCond.pct_lag_phase,
        NewCond.biomass,
        NewCond.biomass_ns,
        Tr,
        TrPot_NS,
        et0,
        growing_season,
    )

    # 17. Harvest index
    NewCond = harvest_index(
        Soil.Profile, Soil.z_top, Crop, NewCond, et0, temp_max, temp_min, growing_season
    )

    # 18. Yield potential
    NewCond.YieldPot = (NewCond.biomass_ns / 100) * NewCond.harvest_index

    # 19. Crop yield_ (dry and fresh)
    if growing_season is True:
        # Calculate crop yield_ (tonne/ha)
        NewCond.DryYield = (NewCond.biomass / 100) * NewCond.harvest_index_adj
        NewCond.FreshYield = NewCond.DryYield / (Crop.YldWC / 100)
        # print( clock_struct.time_step_counter,(NewCond.biomass/100),NewCond.harvest_index_adj)
        # Check if crop has reached maturity
        if ((Crop.CalendarType == 1) and (NewCond.dap >= Crop.Maturity)) or (
            (Crop.CalendarType == 2) and (NewCond.gdd_cum >= Crop.Maturity)
        ):
            # Crop has reached maturity
            NewCond.crop_mature = True

    elif growing_season is False:
        # Crop yield_ is zero outside of growing season
        NewCond.DryYield = 0
        NewCond.FreshYield = 0

    # 20. Root zone water
    _TAW = TAW()
    _water_root_depletion = Dr()
    # thRZ = RootZoneWater()

    Wr, _water_root_depletion.Zt, _water_root_depletion.Rz, _TAW.Zt, _TAW.Rz, _, _, _, _, _, _ = root_zone_water(
        Soil.Profile,
        float(NewCond.z_root),
        NewCond.th,
        Soil.z_top,
        float(Crop.Zmin),
        Crop.Aer,
    )

    # 21. Update net irrigation to add any pre irrigation
    IrrNet = IrrNet + PreIrr
    NewCond.irr_net_cum = NewCond.irr_net_cum + PreIrr

    # Update model outputs %%
    row_day = clock_struct.time_step_counter
    row_gs = clock_struct.season_counter

    # Irrigation
    if growing_season is True:
        if IrrMngt.irrigation_method == 4:
            # Net irrigation
            IrrDay = IrrNet
            IrrTot = NewCond.irr_net_cum
        else:
            # Irrigation
            IrrDay = Irr
            IrrTot = NewCond.irr_cum

    else:
        IrrDay = 0
        IrrTot = 0

        NewCond.depletion = _water_root_depletion.Rz
        NewCond.taw = _TAW.Rz

    # Water contents
    outputs.water_storage[row_day, :3] = np.array(
        [clock_struct.time_step_counter, growing_season, NewCond.dap]
    )
    outputs.water_storage[row_day, 3:] = NewCond.th

    # Water fluxes
    # print(f'Saving NewCond.z_gw to outputs: {NewCond.z_gw}')
    outputs.water_flux[row_day, :] = [
        clock_struct.time_step_counter,
        clock_struct.season_counter,
        NewCond.dap,
        Wr,
        NewCond.z_gw,
        NewCond.surface_storage,
        IrrDay,
        Infl,
        Runoff,
        DeepPerc,
        CR,
        GwIn,
        Es,
        EsPot,
        Tr,
        TrPot,
    ]

    # Crop growth
    outputs.crop_growth[row_day, :] = [
        clock_struct.time_step_counter,
        clock_struct.season_counter,
        NewCond.dap,
        gdd,
        NewCond.gdd_cum,
        NewCond.z_root,
        NewCond.canopy_cover,
        NewCond.canopy_cover_ns,
        NewCond.biomass,
        NewCond.biomass_ns,
        NewCond.harvest_index,
        NewCond.harvest_index_adj,
        NewCond.DryYield,
        NewCond.FreshYield,
        NewCond.YieldPot,
    ]

    # Final output (if at end of growing season)
    if clock_struct.season_counter > -1:
        if (
            (NewCond.crop_mature is True)
            or (NewCond.crop_dead is True)
            or (
                clock_struct.harvest_dates[clock_struct.season_counter]
                == clock_struct.step_end_time
            )
        ) and (NewCond.harvest_flag is False):

            # Store final outputs
            outputs.final_stats.loc[row_gs] = [
                clock_struct.season_counter,
                Crop_Name,
                clock_struct.step_end_time,
                clock_struct.time_step_counter,
                NewCond.DryYield,
                NewCond.FreshYield,
                NewCond.YieldPot,
                IrrTot,
            ]

            # Set harvest flag
            NewCond.harvest_flag = True

    return NewCond, param_struct, outputs

aquacrop.timestep.update_time

Update time function

update_time(clock_struct, init_cond, param_struct, weather, crop)

Function to update current time in model.

Arguments:

clock_struct (ClockStruct):  model time paramaters

init_cond (InitialCondition):  containing sim variables+counters

param_struct (ParamStruct):  containing model paramaters

weather (numpy.array):  weather data for simulation period

Returns:

clock_struct (ClockStruct):  model time paramaters

init_cond (InitialCondition):  containing reset model paramaters

param_struct (ParamStruct):  containing model paramaters
Source code in aquacrop/timestep/update_time.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def update_time(
    clock_struct: "ClockStruct",
    init_cond: "InitialCondition",
    param_struct: "ParamStruct",
    weather: "ndarray",
    crop: "Crop",
    ) -> Tuple["ClockStruct","InitialCondition", "ParamStruct"]:
    """
    Function to update current time in model.

    Arguments:

        clock_struct (ClockStruct):  model time paramaters

        init_cond (InitialCondition):  containing sim variables+counters

        param_struct (ParamStruct):  containing model paramaters

        weather (numpy.array):  weather data for simulation period

    Returns:

        clock_struct (ClockStruct):  model time paramaters

        init_cond (InitialCondition):  containing reset model paramaters

        param_struct (ParamStruct):  containing model paramaters
    """
    # Update time
    if clock_struct.model_is_finished is False:
        if (init_cond.harvest_flag is True) and (
            (clock_struct.sim_off_season is False)
        ):
            # TODO: sim_off_season will always be False.

            # End of growing season has been reached and not simulating
            # off-season soil water balance. Advance time to the start of the
            # next growing season.
            # Check if in last growing season
            if clock_struct.season_counter < clock_struct.n_seasons - 1:
                # Update growing season counter
                clock_struct.season_counter = clock_struct.season_counter + 1
                # Update time-step counter

                clock_struct.time_step_counter = clock_struct.time_span.get_loc(
                    clock_struct.planting_dates[clock_struct.season_counter]
                )
                # Update start time of time-step
                clock_struct.step_start_time = clock_struct.time_span[
                    clock_struct.time_step_counter
                ]
                # Update end time of time-step
                clock_struct.step_end_time = clock_struct.time_span[
                    clock_struct.time_step_counter + 1
                ]
                # Reset initial conditions for start of growing season
                init_cond, param_struct = reset_initial_conditions(
                    clock_struct, init_cond, param_struct, weather, crop
                )

        else:
            # Simulation considers off-season, so progress by one time-step
            # (one day)
            # Time-step counter
            clock_struct.time_step_counter = clock_struct.time_step_counter + 1
            # Start of time step (beginning of current day)
            # clock_struct.time_span = pd.Series(clock_struct.time_span)
            clock_struct.step_start_time = clock_struct.time_span[
                clock_struct.time_step_counter
            ]
            # End of time step (beginning of next day)
            clock_struct.step_end_time = clock_struct.time_span[
                clock_struct.time_step_counter + 1
            ]
            # Check if it is not the last growing season
            if clock_struct.season_counter < clock_struct.n_seasons - 1:
                # Check if upcoming day is the start of a new growing season
                if (
                    clock_struct.step_start_time
                    == clock_struct.planting_dates[clock_struct.season_counter + 1]
                ):
                    # Update growing season counter
                    clock_struct.season_counter = clock_struct.season_counter + 1
                    # Reset initial conditions for start of growing season
                    init_cond, param_struct = reset_initial_conditions(
                        clock_struct, init_cond, param_struct, weather, crop
                    )

    return clock_struct, init_cond, param_struct