Soil Water#
The soil-water model computes the water content of the soil, the ponds and the overland flow on a grid of 4 m cells. The tyre-soil model reads the result at each wheel contact, and the wheels change the soil in return.
Scope and Assumptions#
The model is the class AcresFarm::WaterGrid in AcresFarmModel.cpp. It is an engine-free model.
The class FAcresFarmRuntime in AcresFarmRuntime.cpp loads the data, runs the grid on the water thread and answers the queries of the vehicles.
- Each cell is a soil column with two layers: a surface layer and a subsoil.
- The rain rate and the potential evaporation are the same for all cells. They come from the weather model.
- The model has no channels, no erosion, no groundwater table, no lateral flow in the soil and no frozen soil.
- The soil units and their properties are survey data (SSURGO). No value is a measurement at ACRE.
- Plants do not take water from the soil. The evaporation is the only loss to the air.
- ACRES Core does not step the water grid. It holds a constant water content for each field during an episode.
Symbols#
| Symbol | Quantity | Unit |
|---|---|---|
| \(\Delta x\) | Cell size | m |
| \(\Delta t\) | Step of the grid | s |
| \(z\) | Bed elevation of a cell | m |
| \(h\) | Pond depth | m |
| \(\eta\) | Elevation of the water surface, \(z + h\) | m |
| \(\theta, \theta_2\) | Water content of the surface layer and of the subsoil | m³/m³ |
| \(\theta_0, \theta_{2,0}\) | Water contents at the start | m³/m³ |
| \(\theta_s, \theta_{fc}, \theta_{wp}, \theta_r\) | Water content at saturation, at field capacity, at the wilting point, and the residual value | m³/m³ |
| \(d_1, d_2\) | Thickness of the surface layer and of the subsoil | m |
| \(K_s\) | Saturated conductivity of the open surface | m/s |
| \(K_{seal}\) | Conductivity of a sealed surface | m/s |
| \(\psi\) | Suction at the wetting front | m |
| \(F\) | Water that the column took in from the start | m |
| \(c\) | Wheel compaction | 0 to 1 |
| \(q_p, q_t\) | Limit of the deep percolation and of the tile drain | m/s |
| \(n_M\) | Manning roughness | s/m^(1/3) |
| \(d_c\) | Detention depth | m |
| \(v\) | Flow velocity | m/s |
| \(Q\) | Volume that moves between two cells in a substep | m³ |
| \(r\) | Rut depth | m |
The configuration files use mm/h and mm/day. The code converts them to m/s.
Grid and Data#
| Grid | Cell | Size | Content |
|---|---|---|---|
| Water grid | 4 m | 382 × 382 cells | Water state, field number, land cover. |
| Survey grid | 1.524 m | 1001 × 1001 nodes | Terrain heights, soil unit of each cell. |
| Rut map | 0.25 m | Sparse | Rut depth. See Compaction and Ruts. |
The water grid and the survey grid start at the same corner, at −762.0015 m on both axes. The coordinates are metres in the Unreal frame: X is east and Y is south. The index of a cell is \(i = v\,W + u\) with the row \(v\) along Y.
| File | Content |
|---|---|
farm.json |
The block hydrology with the parameters of this model. |
ACRE/field-grid.json |
Width, cell size and origin of the water grid. |
ACRE/field_ids.u8 |
The field number of each 4 m cell: 1 to 59, or 0. |
ACRE/cover.u8 |
The cover code of each 4 m cell. See Crops and Ground Classes. |
ACRE/soils.json |
The 16 SSURGO soil units and their properties. |
ACRE/soil_units.u8 |
The index of the soil unit of each survey cell. |
ACRE/heights.f32 |
The terrain heights at the survey nodes. |
All files are in the folder Acres/Content/Simulation.
FAcresFarmRuntime::Initialize builds each cell from the point at its centre.
- The bed elevation is the survey height plus the terrain edit of the field setup.
- The soil unit is the unit of the survey cell that contains the centre.
- A cell with the cover asphalt or concrete gets the pavement unit. A cell with the cover gravel gets the gravel unit.
- A field cell on a soil with a drained class gets the copy of its unit with a tile drain.
- A cell of a field with a soil override gets the unit of that field. Pavement and gravel cells keep their unit.
Soil Units#
Each soil unit is one AcresFarm::WaterUnit. soils.json gives these values for the SSURGO units of the tile.
All units have a surface layer of 0.3 m and a subsoil of 1.2 m.
The columns Open and Sealed are the conductivities \(K_s\) and \(K_{seal}\) in mm/h. The suction \(\psi\) is in m. The water contents \(\theta_s\), \(\theta_{fc}\) and \(\theta_{wp}\) are in m³/m³.
| Index | Symbol | Soil | Drainage | Open | Sealed | Suction | Saturation | Field Capacity | Wilting Point |
|---|---|---|---|---|---|---|---|---|---|
| 1 | RcA | Raub-Brenton complex | SP | 33.0 | 3.4 | 0.167 | 0.419 | 0.312 | 0.172 |
| 2 | CwB2 | Crosby-Miami silt loams | SP | 33.0 | 3.4 | 0.167 | 0.437 | 0.281 | 0.130 |
| 3 | SwA | Starks-Fincastle complex | SP | 33.0 | 3.4 | 0.167 | 0.415 | 0.279 | 0.127 |
| 4 | RdB2 | Richardville silt loam | W | 33.0 | 3.4 | 0.167 | 0.412 | 0.288 | 0.144 |
| 5 | RoB | Rockfield silt loam | MW | 33.0 | 3.4 | 0.167 | 0.418 | 0.308 | 0.165 |
| 6 | TmA | Toronto-Millbrook complex | SP | 33.0 | 3.4 | 0.167 | 0.418 | 0.297 | 0.151 |
| 7 | Pg | Pella silty clay loam | P | 33.0 | 1.0 | 0.273 | 0.430 | 0.349 | 0.235 |
| 8 | RdC2 | Richardville silt loam | W | 33.0 | 3.4 | 0.167 | 0.412 | 0.288 | 0.144 |
| 9 | Cm | Chalmers silty clay loam | P | 33.0 | 1.0 | 0.273 | 0.430 | 0.345 | 0.229 |
| 10 | Mu | Milford silty clay loam | VP | 21.4 | 1.0 | 0.273 | 0.430 | 0.356 | 0.250 |
| 11 | Ua | Udorthents, loamy | MW | 3.4 | 3.4 | 0.167 | 0.470 | 0.300 | 0.120 |
| 12 | Md | Mahalasville-Treaty complex | P | 33.0 | 1.0 | 0.273 | 0.428 | 0.342 | 0.223 |
| 13 | Pk | Peotone silty clay loam | VP | 9.4 | 1.0 | 0.273 | 0.420 | 0.362 | 0.262 |
| 14 | TfB | Throckmorton silt loam | MW | 33.0 | 3.4 | 0.167 | 0.418 | 0.301 | 0.155 |
| 15 | MsD2 | Miami silt loam | W | 33.0 | 3.4 | 0.167 | 0.413 | 0.287 | 0.142 |
| 16 | MsC2 | Miami silt loam | MW | 33.0 | 3.4 | 0.167 | 0.426 | 0.296 | 0.149 |
The drainage codes are the NRCS classes Well drained (W), Moderately well drained (MW), Somewhat poorly drained (SP), Poorly drained (P) and Very poorly drained (VP).
The water contents in the table are those of the surface layer. The file also gives the three values of the subsoil.
\(\psi\) and \(K_{seal}\) are means of the texture class from Rawls, Brakensiek and Miller (1983) and Rawls, Brakensiek and Saxton (1982).
The runtime makes a table of water units from these 16 units. With \(K = 17\):
| Index | Unit |
|---|---|
| 0 | A copy of the unit with the most cells (Chalmers, index 9). It applies where the survey has no soil unit. |
| 1 to \(K - 1\) | The SSURGO units. |
| \(K\) to \(2K - 1\) | The same units with a tile drain: \(q_t\) = tile_drainage_mm_day. |
| \(2K\) | Pavement: no infiltration, no soil store, \(\theta = 0\). |
| \(2K + 1\) | Gravel. |
| \(2K + 2\) and more | One unit for each field with a soil override. |
For each SSURGO unit, \(\theta_r\) is the smaller of residual_theta and \(0.5\,\theta_{wp}\). The unit also gets the exponent vg_n and the percolation limit of its drainage class.
The gravel unit has \(K_s\) = 5 mm/h and \(d_1\) = 0.3 m from farm.json. Its other values are constants in the code.
| Value of the Gravel Unit | Surface Layer | Subsoil |
|---|---|---|
| Thickness | 0.3 m | 0.5 m |
| Water content at saturation | 0.35 | 0.37 |
| Water content at field capacity | 0.12 | 0.30 |
| Water content at the wilting point | 0.04 | 0.17 |
| Residual water content | 0.02 | |
| Suction at the wetting front | 0.05 m | |
| Limit of the deep percolation | 1.5 mm/h |
A field with a soil override gets a copy of the unit below the centre of the field. The copy keeps the depths and the percolation limit. The preset or the custom values replace \(K_s\), \(K_{seal}\), \(\psi\), \(\theta_s\), \(\theta_{fc}\) and \(\theta_{wp}\) of both layers. The copy always has a tile drain. Crops and Ground Classes gives the presets and the limits of the custom values.
Initial Water Content#
Each layer starts at a fraction \(f\) of the range between the wilting point and the field capacity.
\(f\) is initial_fraction_between_wilting_and_field_capacity or the option -FarmInitialTheta=.
A field can have its own wetness \(w\) for the surface layer. Values above 1 go from the field capacity to saturation.
The subsoil always uses \(f\). A pavement cell starts at 0. A gravel cell starts at its field capacity. \(\theta_0\) is also the reference of the wetness that the tyres read.
The table shows all the ways to set the water content of the soil.
| Method | Scale | Effect |
|---|---|---|
| Menu, tab Fields, column Start Wetness | 0 wilting point, 1 field capacity, 1.3 maximum | The wetness \(w\) of one field. |
-FieldSetup=<folder> |
0 wilting point, 1 field capacity, 2 saturation | The wetness \(w\) of each field in field-setup.json. |
-FarmInitialTheta= |
0 wilting point, 1 field capacity | The fraction \(f\) of all cells and both layers. |
rain.prior_mm, rain.prior_hours |
mm, h | The grid runs this rain at a constant rate before the session starts. |
-FarmPreDays= |
days, 0 to 366 | The grid runs this time with the start weather before the session starts. |
-FarmLoad=<file> |
Loads the water state of a saved session. | |
acres/set_conditions, part soil_water |
0 wilting point, 1 saturation | Sets \(\theta\) of the fields during the session. |
The service acres/set_conditions uses a different scale. FAcresFarmRuntime::SetSoilWetness applies it to the surface layer of the soil cells of the fields.
An empty field list selects all 59 fields. The function does not change \(\theta_0\) and the subsoil. Set Soil and Weather shows each method.
Step of the Grid#
WaterGrid::Step advances the full grid by \(\Delta t\). The runtime always uses \(\Delta t = 10\) s in a session.
- Update the wheel sub-grid of the cells that got new wheel stamps.
- Compute the vertical balance of each cell one time for the full \(\Delta t\).
- Make the list of the active cells: \(h > d_c + 10^{-6}\) m.
- Route the pond water of the active cells in substeps until \(\Delta t\) is complete.
A cell that gets its first water during the routing becomes active in the subsequent step.
Vertical Balance#
WaterGrid::Infiltrate does these calculations for each cell, in this sequence.
Rain#
\(R\) is the rain rate in mm/h. The rain first goes into the pond.
Effective Conductivity#
\(s_K\) is ksat_scale and \(a_c\) is compaction_ksat_loss. The limit \(K_{seal}\) applies to the cover codes 0, 1, 2 and 9 when surface_sealing is true.
It is the crust that rain makes on bare soil. Grass and woodland keep the open value.
\(c\) is the mean compaction of the cell from the wheel sub-grid.
Green-Ampt Infiltration#
The surface layer takes water from the pond at the Green-Ampt rate. The code uses the rate form with an explicit step.
Two details are different from the classic form. \(F\) is the gain of storage in both layers from the start, with a minimum of 0.1 mm. \(\Delta\theta\) is the current deficit, not the deficit at the start of the storm. The rate thus decreases while the layer fills. The layer has one water content. The model does not track the depth of the wetting front.
Redistribution to the Subsoil#
When \(\theta > \theta_{fc}\), water moves into the subsoil at the unsaturated conductivity of van Genuchten and Mualem.
This flux uses the open \(K_s\). The crust and the compaction change only the surface.
Deep Percolation and Tile Drains#
When \(\theta_2 > \theta_{fc,2}\), the excess \(X_2 = (\theta_2 - \theta_{fc,2})\,d_2\) leaves the subsoil. The deep percolation takes water first.
The limit \(q_p\) comes from the NRCS drainage class of the unit. A soil with a poor class has slow subsoil or a high water table.
The tile drain \(q_t\) is 9.525 mm/day (3/8 inch) on the field cells of the three classes in tile_drainage_classes.
Evaporation#
The demand is \(E_d = \max(0, E)\,\Delta t / (8.64 \times 10^{7})\) with \(E\) in mm/day. The pond gives water first, then the surface layer.
The evaporation stops at the wilting point. The subsoil does not lose water to the air.
The physics step sets \(E\) to 24 times the EvaporationMmH of the weather model. The option -FarmEvap= keeps a constant value.
Overland Flow#
WaterGrid::Route moves the pond water between the four neighbours of each cell. The scheme is an explicit diffusive wave with Manning friction, in the style of LISFLOOD-FP (Bates and De Roo 2000).
Only the water above the detention depth can flow: \(h_{free} = h - d_c\).
For the cell \(i\) and its neighbour \(j\):
\(h_f\) is the depth that can go across the edge between the two cells. No water flows when \(\Delta\eta \le 10^{-6}\) m or \(h_f \le 10^{-5}\) m.
The limit \(\tfrac{1}{4}\Delta\eta\,\Delta x^2\) is half of the volume that makes the two water surfaces level. It prevents oscillation. The factor \(h_f/h_{free}\) replaces its power 2/3. This decreases the flow across a step of the bed.
When the four volumes of a cell are more than its free water, the model scales them.
All cells compute their volumes from the old depths. Then each cell applies the sum.
Edge of the Grid#
A negative edge_outflow_slope closes the edge. In the shipped configuration the edge is open.
The model assumes that the terrain continues with the slope \(s_e\) between the edge cell and the cell behind it.
\(s_{min}\) is edge_outflow_slope. The water that leaves the grid goes into the run-off ledger.
Substeps#
The length of a routing substep follows the Courant condition with the largest velocity \(v_p\) of the previous substep.
When \(v_p\) is zero, the substep is \(\Delta t\). At the velocity limit of 1.5 m/s the substep is 2.1 s. The routing runs in two passes in 32 parallel parts of the grid.
Detention and Roughness#
The detention depth of a cell is the value of its cover plus the mean rut depth of its wheel sub-grid.
Mass Balance#
Each cell keeps cumulative ledgers in metres of water.
The ledgers are rain \(P\), infiltration, evaporation \(E\), deep percolation \(D_p\), tile drain \(D_t\), net lateral inflow \(L\) and edge run-off \(R_e\).
WaterGrid::Residual gives the error of the balance.
A check with one column of the unit RcA under 20 mm/h of rain for 1 h gave \(|\varepsilon| < 10^{-14}\) m after 6 h.
| Time | Rain | Water Content | Pond | Infiltration |
|---|---|---|---|---|
| 0 min | 0 mm | 0.242 | 0 mm | 0 mm |
| 20 min | 6.67 mm | 0.264 | 0.10 mm | 6.57 mm |
| 40 min | 13.33 mm | 0.278 | 2.39 mm | 10.94 mm |
| 60 min | 20.00 mm | 0.289 | 5.83 mm | 14.17 mm |
| 90 min | 20.00 mm | 0.302 | 1.84 mm | 18.10 mm |
| 110 min | 20.00 mm | 0.308 | 0 mm | 19.91 mm |
The column has a corn cover, thus the sealed conductivity of 3.4 mm/h applies. With a grass cover all the rain infiltrates during the storm.
The check used a small test program with AcresFarmModel.cpp, a flat grid of 3 × 3 cells and a closed edge.
Compaction and Ruts#
A wheel that sinks into the soil leaves a rut and compacts the soil. FAcresFarmRuntime::Wheel records both on the rut map.
It examines the footprint of the tyre at intervals of 0.125 m. For the sinkage \(z_w\), each rut cell gets:
A rut keeps 65 % of the sinkage and has a maximum depth of 0.35 m. A sinkage of 0.1 m gives full compaction. Ruts only become deeper. Tillage makes the surface level again, but the compaction stays.
Wheel Sub-Grid#
A tyre contact is 0.5 m to 0.7 m wide. A 4 m cell cannot show a rut.
Each cell that a wheel changed thus gets a sub-grid of 16 × 16 sub-cells of 0.25 m (WaterGrid::FineTile).
A sub-cell holds the rut depth, the compaction and a moisture anomaly. The sub-grid changes the cell in three ways.
| Effect | Rule | Function |
|---|---|---|
| Infiltration | \(c\) of the cell is the mean compaction of its sub-cells. | EffectiveCompaction |
| Pond storage | The mean rut depth \(\bar r\) adds to the detention depth. | Detention |
| Local water | The pond fills the deepest ruts first. | FineLevel |
FineLevel gives the water level \(L\) relative to the bed without ruts. With the rut depths in the sequence \(r_1 \ge r_2 \ge \dots \ge r_K\):
The function increases \(M\) from 1. It stops when \(M = K\) or when \(L_M \le -r_{M+1}\). The local pond depth of a sub-cell is \(\max(0, L + r_k)\). The mean of these depths is equal to \(h\).
Moisture Anomaly#
WaterGrid::DistributeFine divides the infiltration \(I\) of a step between the sub-cells. The mean of the anomaly is zero, thus the water balance of the cell does not change.
The capacity of the sub-cell \(s\) is the Green-Ampt capacity of the cell, \(C = f_i\,\Delta t\), with its own compaction.
The rain of the step, \(P' = \min(P, h)\), falls on each sub-cell. Each sub-cell takes \(a_s = \min(P', C_s)\). The remaining water \(h_r\) goes into the ruts at the level \(L(h_r)\).
The wet sub-cells (\(L + r_s > 0\)) take more water, up to their capacity.
The anomaly \(A_s\) first decays with the time constant \(\tau_a\) (wheel_subgrid_relax_h). Then it gets the share of the step.
\(\Delta t_a\) is the time from the last update of the tile. The function then limits \(\theta + A_s\) to the range from \(\theta_{wp}\) to \(\theta_s\) and removes the mean again. It repeats this a maximum of four times.
The grid holds a maximum of 16384 tiles. After that, a stamp sets the compaction of the full 4 m cell and the rut does not store water.
Moisture State for the Tyre-Soil Model#
The water thread publishes a snapshot of the grid (FAcresWaterSnapshot). The snapshot holds these values for each cell:
The wetness is 0 at the start state and 1 at saturation. The snapshot also holds \(\theta\), \(h\), the mean values of each field and the tiles of the wheel sub-grid.
FAcresFarmRuntime::Sample fills the surface input of one wheel, the structure AcresSim::FVehicleInput. It runs in each physics step for each wheel.
- Interpolate the cell values between the centres of the four nearest cells. On soil, \(\theta\) and the wetness use only the soil cells.
- Compute the local pond depth: \(\max(0,\ L + r)\) with the rut depth \(r\) below the wheel. Without a tile, \(L = h\) and \(r = 0\).
- On soil, add the moisture anomaly, interpolated between the centres of the four nearest sub-cells.
- Limit \(\theta\) to the range 0 to 0.6.
| Field | Value on Soil | Value on a Hard Surface |
|---|---|---|
Theta |
\(\theta\) plus the anomaly. | Not used. |
Wetness |
The largest of the wetness, the rain film and \(\min(1, \text{pond}/0.002)\). | \(\min(1, \text{pond}/0.002)\). |
WaterDepthM |
The local pond depth. | The local pond depth. |
RutDepthM |
The rut depth of the rut cell. | 0. |
The rain film is the SurfaceWetness of the weather model. It makes the soil surface wet in the first minutes of a storm.
The water content of the 0.3 m layer increases more slowly.
The tyre-soil model uses the four fields as follows. Tyre and Soil gives the equations.
| Field | Use in the Tyre-Soil Model |
|---|---|
Theta |
SoilStateAt computes the saturation, the suction, the strength, the Bekker moduli and the cone index from it. |
Wetness |
It decreases the friction between rubber and soil, and the friction of a hard surface. |
WaterDepthM |
The drag of the water on the tyre. |
RutDepthM |
The minimum sinkage, and a higher density of the soil below the rut (CompactedDensity). |
In the soil-and-weather study, silt loam had a cone index of 2.14 MPa at \(\theta = 0.236\). At \(\theta = 0.374\) the value was 0.63 MPa.
A wheel reads the farm only on the mapped surface. A surface that the driver selects with the keys 1 to 6 uses the constant values of its template.
Water Thread and Clock#
The grid has 145 924 cells. One step is too slow for a physics step of 1/120 s. A worker thread with the name AcresWater runs the grid.
| Thread | Functions |
|---|---|
| Physics thread | Advance, Sample, Wheel. It holds the farm lock during the step of a vehicle. |
| Game thread | Initialize, UpdateVisuals, save and load. |
| Water thread | WaterGrid::Step and the snapshots. |
FAcresFarmRuntime::Advance converts the physics step to environment time with the time scale \(k\) of the weather model.
It adds \(\Delta t_{env}\) to the request of the water thread. The water thread takes the request in parts of exactly 10 s. The result thus does not change with the frame rate or with the time scale. A remainder of less than 10 s stays in the request.
At a high time scale the grid can be late. The snapshot contains the delay (BacklogS).
The HUD shows the text "water lags" when the delay is more than 60 s.
The water thread writes each snapshot into one of three buffers and then changes an index. A reader takes the current buffer without a lock. The thread publishes a snapshot each 0.2 s of real time while it steps, and each 0.5 s when it has no work. Wheel stamps go to the water thread through a queue. The thread applies them before each step and each snapshot.
Before the session starts, Initialize runs the grid on the game thread for -FarmPreDays= and for the prior rain. These runs use steps of 300 s.
Lockstep#
In lockstep the water must be a function of the simulation only. FAcresFarmRuntime::SetDeterministicWater moves the grid to the physics thread.
Advancesteps the grid by 10 s each time 10 s of environment time are complete.Advancepublishes a snapshot each 0.5 s of simulation time, with the wheel stamps of that time.- The water thread waits.
The same commands thus give the same soil below the tyres. Time Stepping and Determinism gives the rules for all models. Without lockstep, a snapshot can arrive one or more physics steps earlier or later between two runs.
Ground Conditions from the Station#
The folder Calibration/Weather connects the model to the real soil at ACRE. The source is the Purdue Mesonet station ACRE.
The station has rain, air and wind sensors, and soil water probes at 5 cm, 10 cm, 20 cm and 40 cm.
| File | Function |
|---|---|
acre_mesonet.py |
Downloads the 30-minute record of the station and applies quality checks. |
ground_conditions.py |
Computes the weather and the soil wetness for each real run of the Polaris. |
ground_conditions.md, ground_conditions.json |
The results for 269 runs. |
Replay/env_<date>.json |
A weather replay file for each day with runs. |
Replay/fields_w<index>/field-setup.json |
A field setup that gives all fields the wetness index of a day. |
soil_state_cli.cpp |
Evaluates the soil library at a water content, to report the soil strength. |
The probes do not give absolute water contents for these soils. The script thus refers each probe to its own record.
| Probe | Dry End | Drained Upper Limit | Wettest |
|---|---|---|---|
| 5 cm | 0.147 | 0.376 | 0.461 |
| 10 cm | 0.198 | 0.412 | 0.456 |
| 20 cm | 0.155 | 0.334 | 0.438 |
| 40 cm | 0.338 | 0.437 | 0.478 |
The three columns are the index values \(w = 0\), \(w = 1\) and \(w = 2\) of a probe, in m³/m³. The dry end is the 0.5th percentile of the record. The wettest value is the 99.5th percentile. The drained upper limit is the median reading from 24 h to 48 h after each rain of 12 mm or more. The wetness index of the 0.3 m surface layer is a weighted mean of three probes.
This index is the wetness \(w\) of Initial Water Content. The script writes it into the field setups.
Parameters#
farm.json, Block hydrology#
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
initial_fraction_between_wilting_and_field_capacity |
number | 0.5 | The start fraction \(f\). Range 0 to 1. | |
ksat_scale |
number | 1.0 | The factor \(s_K\) on all conductivities. Range above 0 to 10. | |
compaction_ksat_loss |
number | 0.7 | The fraction \(a_c\) of the conductivity that full compaction removes. | |
residual_theta |
number | m³/m³ | 0.06 | The residual water content \(\theta_r\). |
vg_n |
number | 1.6 | The exponent \(n\) of van Genuchten. | |
tile_drainage_mm_day |
number | mm/day | 9.525 | The tile drain \(q_t\). |
tile_drainage_classes |
list | 3 classes | The drainage classes that get tile drains on field cells. | |
gravel.ksat_mm_h |
number | mm/h | 5.0 | The conductivity of gravel. |
gravel.depth_m |
number | m | 0.3 | The depth of the gravel layer. |
covers.<name>.manning_n |
number | s/m^(1/3) | see below | The Manning roughness of a cover. |
covers.<name>.detention_m |
number | m | see below | The detention depth of a cover. |
edge_outflow_slope |
number | m/m | 0.002 | The minimum slope at the open edge. A negative value closes the edge. |
max_sheet_flow_velocity_mps |
number | m/s | 1.5 | The velocity limit \(v_{max}\). |
deep_percolation_mm_h_by_drainage_class |
object | mm/h | see below | The limit \(q_p\) for each drainage class. |
surface_sealing |
boolean | true | Applies \(K_{seal}\) on bare soil and row crops. | |
wheel_subgrid_relax_h |
number | h | 24 | The time constant \(\tau_a\) of the moisture anomaly. Optional. |
wheel_subgrid_max_tiles |
integer | 16384 | The maximum number of tiles of the wheel sub-grid. Optional. |
| Cover | Code | Manning Roughness | Detention Depth |
|---|---|---|---|
bare |
0 | 0.05 | 0.002 m |
corn |
1 | 0.10 | 0.003 m |
soybean |
2 | 0.10 | 0.003 m |
grass |
3 | 0.24 | 0.003 m |
woodland |
4 | 0.40 | 0.005 m |
shrubs |
5 | 0.40 | 0.005 m |
asphalt |
6 | 0.011 | 0.0005 m |
concrete |
7 | 0.011 | 0.0005 m |
gravel |
8 | 0.02 | 0.001 m |
potato |
9 | 0.08 | 0.004 m |
| Drainage Class | Percolation Limit |
|---|---|
Excessively drained |
100 mm/h |
Somewhat excessively drained |
60 mm/h |
Well drained |
33 mm/h |
Moderately well drained |
8 mm/h |
Somewhat poorly drained |
1.5 mm/h |
Poorly drained |
0.4 mm/h |
Very poorly drained |
0.1 mm/h |
The percolation limits are estimates, not measurements. The roughness values come from Table 3-1 of SCS TR-55.
farm.json, Block weather#
The block applies only when the map has no weather model. On the ACRE map the physics step replaces these values.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
rain_mm_h |
number | mm/h | 0 | The rain rate. Range 0 to 200. |
minimum_c |
number | °C | 16 | The minimum temperature of the day. |
maximum_c |
number | °C | 28 | The maximum temperature of the day. |
evaporation_mm_day |
number | mm/day | 2 | The potential evaporation. Range 0 to 20. |
time_scale |
number | 1 | Environment seconds for each physics second. Range 0 to 86400. |
Command-Line Options#
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
-FarmInitialTheta= |
number | 0.5 | The start fraction \(f\). Range 0 to 1. | |
-FarmKsatScale= |
number | 1.0 | The factor \(s_K\). | |
-FarmEvap= |
number | mm/day | from the weather | A constant potential evaporation. |
-FarmPreDays= |
number | days | 0 | Time that the grid runs before the session starts. |
-FarmLoad= |
path | The farm-state.json of a saved session. |
||
-FieldSetup= |
path | The folder with field-setup.json. |
||
-FarmDisabled |
flag | off | Starts the session without the farm. The wheels then use the surface templates. |
Constants in the Code#
| Constant | Value | Description |
|---|---|---|
CflFactor |
0.8 | The Courant number of the routing. |
MinSubstepS |
1 s | The shortest routing substep. |
FineDiv |
16 | Sub-cells on each side of a tile. |
RutCellM |
0.25 m | The cell of the rut map. |
RutShare |
0.65 | The share of the sinkage that stays as a rut. |
RutMaxM |
0.35 m | The largest rut depth. |
CompactionSinkageM |
0.1 m | The sinkage that gives full compaction. |
Outputs#
FAcresFarmRuntime::Export writes these files into the session folder at the end of a session and on the F5 key.
| File | Content |
|---|---|
farm-fields.csv |
One row for each field: mean \(\theta\), pond, rain, evaporation, drainage, lateral flow and the balance error. |
farm-water.json |
A summary of the grid: largest pond, mean ledgers, number of substeps, size of the wheel sub-grid. |
water-depth.f32, theta.f32 |
The pond depth and \(\theta\) of each cell, 382 × 382 values of 32 bits. |
farm-weather.csv |
One row each hour: rain, temperatures, the balance error and the ponds. |
farm-state.json, farm-water.bin |
The saved state. The binary file holds 11 arrays of 64-bit values for the grid. |
The rows F60, F61 and F62 of farm-fields.csv are the asphalt, concrete and gravel cells. The row F00 is all other cells outside the fields.
Session Log gives the columns.
Code Map#
| Item | File | Function |
|---|---|---|
| Soil unit, cover, grid state | AcresFarmModel.h |
AcresFarm::WaterUnit, WaterCover, WaterGrid |
| Step of the grid | AcresFarmModel.cpp |
WaterGrid::Step |
| Vertical balance | AcresFarmModel.cpp |
WaterGrid::Infiltrate |
| Overland flow | AcresFarmModel.cpp |
WaterGrid::Route |
| Balance error | AcresFarmModel.cpp |
WaterGrid::Residual, TotalResidual |
| Wheel sub-grid | AcresFarmModel.cpp |
StampFine, PrepareFine, FineLevel, DistributeFine, FineAnomalies |
| Units, cells, start state | AcresFarmRuntime.cpp |
FAcresFarmRuntime::Initialize |
| Water thread, snapshot | AcresFarmRuntime.cpp |
FAcresWaterThread::Run, Publish |
| Clock | AcresFarmRuntime.cpp |
FAcresFarmRuntime::Advance |
| Wheel query | AcresFarmRuntime.cpp |
FAcresFarmRuntime::Sample |
| Ruts and compaction | AcresFarmRuntime.cpp |
FAcresFarmRuntime::Wheel, StampFine |
| Wetness in a session | AcresFarmRuntime.cpp |
FAcresFarmRuntime::SetSoilWetness |
| Lockstep | AcresFarmRuntime.cpp |
FAcresFarmRuntime::SetDeterministicWater |
| Save and export | AcresFarmRuntime.cpp |
Save, Load, Export |
| Constant conditions of Core | Core/Source/AcresCoreWorld.cpp |
FAcresWorld::CellTheta, SurfaceAt |
| Station data | Calibration/Weather/ground_conditions.py |
Limitations#
- The hydraulic values are survey values and texture means. They have no calibration against ACRE measurements.
- One surface layer of 0.3 m holds the water of a storm. The model does not show a thin wet layer at the top, apart from the rain film.
- A 4 m cell takes its soil unit and its height from one point. The grid does not show a ditch that is narrower than 4 m.
- Each field with a soil override gets a tile drain, also on a well-drained soil.
- The water can be late at a high time scale, because a grid step is always 10 s.
- The grid reads the rain rate one time for each 10 s step. At a time scale of 60, a field got 16.81 mm in one session and 16.90 mm in a second session. The storm had 16.80 mm.
- Compaction does not recover. The rut map and the wheel sub-grid only grow during a session.
SetSoilWetnessdoes not change \(\theta_0\). After the call, the balance error \(\varepsilon\) includes the change of storage. A test gave an error of 5.8 mm for field F21.- The game does not limit the wetness of a field setup file. A value above 2 gives a water content above saturation.
- The command
-FarmLoad=does not prevent the pre-run days and the prior rain. They run after the load. - The fingerprint of a saved state does not include the terrain heights or the field setup.
- Hard surfaces become wet only from pond water, not from the rain film.
References#
- Bates, P. D., and De Roo, A. P. J. (2000). A simple raster-based model for flood inundation simulation. Journal of Hydrology, 236(1-2), 54-77.
- Purdue University Cooperative Extension Service. Drainage and wet soil management: drainage recommendations for Indiana soils (AY-300). West Lafayette, Indiana.
- Green, W. H., and Ampt, G. A. (1911). Studies on soil physics. Part I. The flow of air and water through soils. Journal of Agricultural Science, 4(1), 1-24.
- Mualem, Y. (1976). A new model for predicting the hydraulic conductivity of unsaturated porous media. Water Resources Research, 12(3), 513-522.
- Rawls, W. J., Brakensiek, D. L., and Miller, N. (1983). Green-Ampt infiltration parameters from soils data. Journal of Hydraulic Engineering, 109(1), 62-70.
- Rawls, W. J., Brakensiek, D. L., and Saxton, K. E. (1982). Estimation of soil water properties. Transactions of the ASAE, 25(5), 1316-1320.
- Soil Conservation Service (1986). Urban hydrology for small watersheds (Technical Release 55). Washington, DC: United States Department of Agriculture.
- Soil Survey Staff. Soil Survey Geographic (SSURGO) database. United States Department of Agriculture, Natural Resources Conservation Service.
- van Genuchten, M. T. (1980). A closed-form equation for predicting the hydraulic conductivity of unsaturated soils. Soil Science Society of America Journal, 44(5), 892-898.