Rosetta hydraulic conductivity & infiltration

This notebook shows how fast water moves through soil and how compaction slows it, which are two questions central to stormwater management and soil health. Three interactive charts let you explore by texture class and bulk density:

All charts use stormwater units (in/hr) with bulk-density sliders. Bulk density data for a given texture are outside of calibration range of ROSETTA model are greyed as extrapolation, as in Notebook 1.

Charts read rosetta_porosity_by_texture.csv (run Notebook 1 first), which carries Rosetta’s saturated Ksat and the Mualem-van Genuchten unsaturated-conductivity parameters (k0_cm_day, mualem_L, vg_alpha_1cm, vg_n).

Show code
import numpy as np
import pandas as pd
import hvplot.pandas  # noqa: F401  (registers the .hvplot accessor)
import holoviews as hv

# Shared helpers (display table, Mualem K(h), extrapolation-aware line plot); importing _helpers
# also sets the shared pandas float_format. See notebooks/_helpers.py.
from _helpers import show, mualem_k, line_with_extrapolation

# Rosetta baseline + Mualem-van Genuchten parameters from Notebook 1
result = pd.read_csv("rosetta_porosity_by_texture.csv")

# Reconstruct shared constants from the table (canonical sand -> clay order)
TEXTURE_CLASSES = list(result["texture_class"].drop_duplicates())
HYDROLOGIC_SOIL_GROUP = dict(
    result[["texture_class", "hydrologic_soil_group"]].drop_duplicates().itertuples(index=False, name=None)
)
bulk_densities = np.sort(result["bulk_density_g_cm3"].unique())
texture_x = {cls: i for i, cls in enumerate(TEXTURE_CLASSES)}
texture_ticks = [(i, f"{cls} ({HYDROLOGIC_SOIL_GROUP[cls]})") for cls, i in texture_x.items()]


# mualem_k and line_with_extrapolation are shared with Notebook 1 and imported from _helpers.
# bd_slider_line (the slider-driven K(h) / Green-Ampt line plots) is specific to this notebook.
def bd_slider_line(dfL, x, y, xlabel, ylabel, title, **kw):
    """Line plot (one per texture) with a bulk-density slider; rows flagged implausible_bd are
    drawn grey-dashed. Returns a HoloMap keyed by bulk_density_g_cm3 (caller overlays/redims)."""
    common = dict(
        x=x, y=y, by="texture_class", groupby="bulk_density_g_cm3", dynamic=False,
        width=820, height=520, **kw,
    )
    solid = dfL.assign(**{y: dfL[y].where(~dfL["implausible_bd"])}).hvplot.line(
        xlabel=xlabel, ylabel=ylabel, title=title, legend="right", grid=True, **common
    )
    dashed = (
        dfL.assign(**{y: dfL[y].where(dfL["implausible_bd"])}).hvplot.line(**common)
        .opts(hv.opts.Curve(color="lightgray", line_dash="dashed", alpha=0.9))
        .opts(show_legend=False)
    )
    return solid * dashed


print(f"loaded {len(result)} rows: {len(TEXTURE_CLASSES)} textures x {len(bulk_densities)} bulk densities")
show(result)
loaded 144 rows: 12 textures x 12 bulk densities
texture_class hydrologic_soil_group sand_pct silt_pct clay_pct bulk_density_g_cm3 total_porosity field_capacity_porosity wilting_point_porosity available_water_capacity ksat_cm_day ksat_in_hr k_fc_cm_day k_wp_cm_day theta_r vg_alpha_1cm vg_n k0_cm_day mualem_L implausible_bd
0 sand A 92 5 3 0.800 0.560 0.141 0.072 0.069 992.244 16.277 0.008 0.000 0.070 0.029 1.848 53.148 -0.574 False
1 sand A 92 5 3 0.900 0.531 0.129 0.068 0.062 874.440 14.344 0.006 0.000 0.066 0.026 1.930 36.508 -0.473 False
2 sand A 92 5 3 1.000 0.503 0.113 0.064 0.049 803.505 13.181 0.004 0.000 0.063 0.025 2.033 29.219 -0.477 False
3 sand A 92 5 3 1.100 0.475 0.096 0.061 0.036 763.127 12.518 0.003 0.000 0.060 0.025 2.154 24.929 -0.542 False
4 sand A 92 5 3 1.200 0.450 0.082 0.058 0.024 731.398 11.998 0.002 0.000 0.058 0.026 2.289 22.146 -0.638 False
5 sand A 92 5 3 1.300 0.425 0.072 0.056 0.016 690.465 11.327 0.002 0.000 0.056 0.027 2.430 20.779 -0.734 False
6 sand A 92 5 3 1.400 0.401 0.064 0.054 0.010 630.566 10.344 0.001 0.000 0.054 0.029 2.563 20.654 -0.809 False
7 sand A 92 5 3 1.500 0.376 0.059 0.052 0.007 544.378 8.930 0.001 0.000 0.052 0.031 2.653 21.556 -0.857 False
8 sand A 92 5 3 1.600 0.352 0.057 0.050 0.006 424.038 6.956 0.001 0.000 0.050 0.032 2.638 23.625 -0.874 False
9 sand A 92 5 3 1.700 0.327 0.056 0.049 0.007 301.562 4.947 0.001 0.000 0.049 0.033 2.532 27.468 -0.876 False
10 sand A 92 5 3 1.800 0.303 0.055 0.048 0.007 218.069 3.577 0.002 0.000 0.048 0.035 2.449 36.333 -0.883 False
11 sand A 92 5 3 1.900 0.281 0.054 0.047 0.007 173.663 2.849 0.003 0.000 0.047 0.038 2.415 83.843 -0.888 False
12 loamy sand A 82 12 6 0.800 0.554 0.253 0.097 0.156 487.050 7.990 0.011 0.000 0.074 0.018 1.545 16.326 -0.346 False
13 loamy sand A 82 12 6 0.900 0.525 0.228 0.088 0.140 421.489 6.914 0.009 0.000 0.071 0.018 1.589 14.527 -0.322 False
14 loamy sand A 82 12 6 1.000 0.498 0.203 0.081 0.123 369.826 6.067 0.008 0.000 0.068 0.018 1.636 13.651 -0.361 False
15 loamy sand A 82 12 6 1.100 0.472 0.180 0.074 0.106 321.878 5.280 0.008 0.000 0.066 0.019 1.684 13.228 -0.433 False
16 loamy sand A 82 12 6 1.200 0.447 0.159 0.070 0.090 274.748 4.507 0.007 0.000 0.064 0.020 1.729 13.048 -0.520 False
17 loamy sand A 82 12 6 1.300 0.423 0.141 0.066 0.076 229.151 3.759 0.006 0.000 0.061 0.021 1.769 13.056 -0.614 False
18 loamy sand A 82 12 6 1.400 0.400 0.127 0.062 0.065 186.012 3.051 0.006 0.000 0.059 0.022 1.799 13.213 -0.706 False
19 loamy sand A 82 12 6 1.500 0.377 0.116 0.060 0.057 145.188 2.382 0.006 0.000 0.057 0.024 1.810 13.454 -0.796 False
20 loamy sand A 82 12 6 1.600 0.353 0.111 0.058 0.053 105.214 1.726 0.006 0.000 0.055 0.025 1.782 13.723 -0.890 False
21 loamy sand A 82 12 6 1.700 0.328 0.112 0.058 0.054 69.610 1.142 0.007 0.000 0.054 0.027 1.716 14.156 -0.996 False
22 loamy sand A 82 12 6 1.800 0.305 0.112 0.058 0.054 45.577 0.748 0.008 0.000 0.053 0.028 1.649 16.243 -1.096 False
23 loamy sand A 82 12 6 1.900 0.282 0.109 0.058 0.051 32.713 0.537 0.015 0.000 0.052 0.030 1.609 31.984 -1.179 False
24 sandy loam A 65 25 10 0.800 0.544 0.339 0.129 0.210 345.058 5.660 0.013 0.000 0.081 0.010 1.455 4.963 0.012 False
25 sandy loam A 65 25 10 0.900 0.517 0.313 0.119 0.194 261.554 4.291 0.012 0.000 0.078 0.010 1.472 4.803 -0.047 False
26 sandy loam A 65 25 10 1.000 0.490 0.289 0.110 0.178 196.156 3.218 0.011 0.000 0.075 0.011 1.486 4.834 -0.143 False
27 sandy loam A 65 25 10 1.100 0.466 0.266 0.103 0.163 145.698 2.390 0.010 0.000 0.073 0.012 1.496 4.954 -0.257 False
28 sandy loam A 65 25 10 1.200 0.442 0.246 0.097 0.148 107.304 1.760 0.009 0.000 0.071 0.013 1.501 5.111 -0.381 False
29 sandy loam A 65 25 10 1.300 0.419 0.228 0.093 0.135 78.162 1.282 0.009 0.000 0.068 0.014 1.502 5.289 -0.509 False
30 sandy loam A 65 25 10 1.400 0.396 0.213 0.089 0.124 56.362 0.925 0.008 0.000 0.066 0.015 1.496 5.509 -0.641 False
31 sandy loam A 65 25 10 1.500 0.374 0.201 0.087 0.114 39.936 0.655 0.008 0.000 0.064 0.016 1.481 5.772 -0.776 False
32 sandy loam A 65 25 10 1.600 0.351 0.192 0.086 0.106 27.110 0.445 0.008 0.000 0.063 0.017 1.451 6.082 -0.926 False
33 sandy loam A 65 25 10 1.700 0.328 0.188 0.089 0.099 17.322 0.284 0.008 0.000 0.061 0.018 1.406 6.551 -1.113 False
34 sandy loam A 65 25 10 1.800 0.306 0.184 0.092 0.092 10.893 0.179 0.008 0.000 0.060 0.019 1.360 7.607 -1.347 False
35 sandy loam A 65 25 10 1.900 0.284 0.179 0.095 0.083 7.269 0.119 0.011 0.000 0.060 0.021 1.322 11.189 -1.619 True
36 loam B 40 40 20 0.800 0.559 0.421 0.163 0.258 256.843 4.213 0.022 0.000 0.098 0.005 1.453 1.999 0.334 False
37 loam B 40 40 20 0.900 0.530 0.395 0.154 0.241 165.697 2.718 0.018 0.000 0.095 0.005 1.456 1.745 0.281 False
38 loam B 40 40 20 1.000 0.502 0.371 0.147 0.224 104.354 1.712 0.016 0.000 0.093 0.006 1.456 1.624 0.180 False
39 loam B 40 40 20 1.100 0.476 0.348 0.141 0.207 65.280 1.071 0.014 0.000 0.091 0.006 1.452 1.585 0.054 False
40 loam B 40 40 20 1.200 0.451 0.326 0.137 0.190 41.158 0.675 0.012 0.000 0.089 0.006 1.444 1.588 -0.083 False
41 loam B 40 40 20 1.300 0.427 0.307 0.133 0.174 26.290 0.431 0.011 0.000 0.087 0.007 1.432 1.613 -0.227 False
42 loam B 40 40 20 1.400 0.404 0.290 0.131 0.159 17.009 0.279 0.010 0.000 0.086 0.007 1.416 1.657 -0.377 False
43 loam B 40 40 20 1.500 0.381 0.275 0.130 0.145 11.107 0.182 0.009 0.000 0.084 0.008 1.393 1.731 -0.538 False
44 loam B 40 40 20 1.600 0.358 0.262 0.130 0.131 7.236 0.119 0.008 0.000 0.083 0.009 1.362 1.852 -0.732 False
45 loam B 40 40 20 1.700 0.336 0.250 0.133 0.117 4.656 0.076 0.008 0.000 0.081 0.009 1.324 2.071 -0.994 False
46 loam B 40 40 20 1.800 0.314 0.239 0.136 0.103 3.015 0.049 0.008 0.000 0.080 0.010 1.285 2.502 -1.350 False
47 loam B 40 40 20 1.900 0.293 0.228 0.139 0.090 2.038 0.033 0.008 0.000 0.080 0.011 1.252 3.372 -1.803 True
48 silt loam B 20 65 15 0.800 0.557 0.458 0.146 0.313 330.144 5.416 0.069 0.000 0.092 0.003 1.572 1.515 0.746 False
49 silt loam B 20 65 15 0.900 0.527 0.431 0.138 0.293 203.429 3.337 0.056 0.000 0.088 0.003 1.574 1.286 0.741 False
50 silt loam B 20 65 15 1.000 0.499 0.404 0.131 0.273 127.725 2.095 0.046 0.000 0.085 0.003 1.572 1.166 0.668 False
51 silt loam B 20 65 15 1.100 0.473 0.378 0.125 0.253 81.420 1.336 0.038 0.000 0.083 0.003 1.565 1.109 0.553 False
52 silt loam B 20 65 15 1.200 0.449 0.354 0.121 0.233 52.349 0.859 0.032 0.000 0.080 0.004 1.554 1.095 0.422 False
53 silt loam B 20 65 15 1.300 0.427 0.331 0.117 0.214 33.895 0.556 0.027 0.000 0.078 0.004 1.538 1.110 0.284 False
54 silt loam B 20 65 15 1.400 0.405 0.310 0.115 0.195 22.196 0.364 0.023 0.000 0.077 0.004 1.516 1.144 0.141 False
55 silt loam B 20 65 15 1.500 0.384 0.291 0.113 0.178 14.735 0.242 0.019 0.000 0.075 0.005 1.489 1.195 -0.010 False
56 silt loam B 20 65 15 1.600 0.364 0.274 0.114 0.161 9.942 0.163 0.016 0.000 0.074 0.005 1.455 1.269 -0.178 False
57 silt loam B 20 65 15 1.700 0.343 0.259 0.115 0.144 6.902 0.113 0.013 0.000 0.073 0.006 1.416 1.390 -0.376 False
58 silt loam B 20 65 15 1.800 0.323 0.244 0.117 0.127 5.086 0.083 0.012 0.000 0.073 0.007 1.376 1.603 -0.617 True
59 silt loam B 20 65 15 1.900 0.303 0.230 0.118 0.111 4.470 0.073 0.011 0.000 0.073 0.008 1.340 2.003 -0.915 True
60 silt B/D 7 88 5 0.800 0.562 0.351 0.103 0.249 1381.028 22.655 0.039 0.000 0.083 0.006 1.711 3.927 0.390 False
61 silt B/D 7 88 5 0.900 0.533 0.380 0.102 0.278 690.764 11.331 0.064 0.000 0.078 0.004 1.707 2.692 0.642 False
62 silt B/D 7 88 5 1.000 0.506 0.377 0.100 0.277 369.838 6.067 0.067 0.000 0.074 0.004 1.701 2.103 0.713 False
63 silt B/D 7 88 5 1.100 0.482 0.361 0.096 0.265 215.558 3.536 0.059 0.000 0.070 0.004 1.693 1.801 0.686 False
64 silt B/D 7 88 5 1.200 0.459 0.341 0.093 0.248 136.101 2.233 0.050 0.000 0.068 0.004 1.680 1.669 0.601 False
65 silt B/D 7 88 5 1.300 0.438 0.319 0.090 0.229 92.347 1.515 0.041 0.000 0.066 0.004 1.664 1.632 0.482 False
66 silt B/D 7 88 5 1.400 0.418 0.297 0.088 0.209 68.169 1.118 0.033 0.000 0.064 0.004 1.644 1.661 0.342 False
67 silt B/D 7 88 5 1.500 0.398 0.274 0.086 0.189 58.825 0.965 0.026 0.000 0.063 0.005 1.620 1.760 0.182 False
68 silt B/D 7 88 5 1.600 0.379 0.252 0.084 0.167 70.476 1.156 0.020 0.000 0.062 0.006 1.591 1.956 -0.007 False
69 silt B/D 7 88 5 1.700 0.360 0.228 0.084 0.145 129.258 2.120 0.015 0.000 0.062 0.008 1.560 2.337 -0.241 True
70 silt B/D 7 88 5 1.800 0.341 0.201 0.082 0.120 571.274 9.371 0.011 0.000 0.063 0.010 1.540 3.146 -0.535 True
71 silt B/D 7 88 5 1.900 0.323 0.174 0.080 0.094 1463.279 24.004 0.009 0.000 0.064 0.015 1.527 4.956 -0.883 True
72 sandy clay loam C 60 13 27 0.800 0.586 0.386 0.186 0.200 231.903 3.804 0.010 0.000 0.112 0.013 1.350 6.082 -0.785 False
73 sandy clay loam C 60 13 27 0.900 0.560 0.367 0.176 0.191 174.015 2.855 0.009 0.000 0.108 0.013 1.359 4.962 -0.751 False
74 sandy clay loam C 60 13 27 1.000 0.534 0.348 0.168 0.181 128.898 2.114 0.008 0.000 0.106 0.013 1.366 4.333 -0.755 False
75 sandy clay loam C 60 13 27 1.100 0.509 0.330 0.160 0.170 93.746 1.538 0.007 0.000 0.103 0.013 1.370 3.974 -0.787 False
76 sandy clay loam C 60 13 27 1.200 0.484 0.313 0.154 0.159 66.541 1.092 0.006 0.000 0.101 0.014 1.371 3.742 -0.843 False
77 sandy clay loam C 60 13 27 1.300 0.459 0.298 0.149 0.149 45.805 0.751 0.006 0.000 0.099 0.014 1.368 3.551 -0.921 False
78 sandy clay loam C 60 13 27 1.400 0.434 0.285 0.146 0.138 30.569 0.501 0.006 0.000 0.097 0.014 1.359 3.371 -1.023 False
79 sandy clay loam C 60 13 27 1.500 0.408 0.273 0.145 0.128 19.687 0.323 0.005 0.000 0.096 0.014 1.342 3.212 -1.159 False
80 sandy clay loam C 60 13 27 1.600 0.381 0.264 0.147 0.117 12.022 0.197 0.005 0.000 0.094 0.015 1.313 3.111 -1.363 False
81 sandy clay loam C 60 13 27 1.700 0.354 0.257 0.152 0.105 6.918 0.113 0.005 0.000 0.094 0.015 1.275 3.166 -1.697 False
82 sandy clay loam C 60 13 27 1.800 0.327 0.249 0.157 0.091 3.975 0.065 0.005 0.000 0.093 0.015 1.239 3.572 -2.195 True
83 sandy clay loam C 60 13 27 1.900 0.301 0.237 0.159 0.078 2.444 0.040 0.006 0.000 0.093 0.016 1.211 4.640 -2.809 True
84 clay loam D 30 35 35 0.800 0.599 0.448 0.205 0.244 215.577 3.536 0.016 0.000 0.121 0.007 1.379 2.611 -0.202 False
85 clay loam D 30 35 35 0.900 0.570 0.427 0.196 0.231 137.810 2.261 0.013 0.000 0.118 0.007 1.380 2.049 -0.189 False
86 clay loam D 30 35 35 1.000 0.542 0.406 0.189 0.216 85.477 1.402 0.010 0.000 0.115 0.007 1.378 1.713 -0.237 False
87 clay loam D 30 35 35 1.100 0.514 0.385 0.184 0.202 51.959 0.852 0.009 0.000 0.113 0.007 1.374 1.511 -0.320 False
88 clay loam D 30 35 35 1.200 0.487 0.366 0.179 0.187 31.207 0.512 0.008 0.000 0.112 0.007 1.366 1.386 -0.418 False
89 clay loam D 30 35 35 1.300 0.461 0.349 0.176 0.172 18.636 0.306 0.007 0.000 0.111 0.007 1.355 1.299 -0.530 False
90 clay loam D 30 35 35 1.400 0.434 0.332 0.175 0.157 11.137 0.183 0.006 0.000 0.110 0.008 1.340 1.232 -0.663 False
91 clay loam D 30 35 35 1.500 0.408 0.317 0.174 0.142 6.693 0.110 0.006 0.000 0.109 0.008 1.320 1.186 -0.830 False
92 clay loam D 30 35 35 1.600 0.381 0.302 0.176 0.127 4.037 0.066 0.005 0.000 0.109 0.008 1.294 1.174 -1.058 False
93 clay loam D 30 35 35 1.700 0.355 0.289 0.178 0.110 2.447 0.040 0.005 0.000 0.109 0.008 1.263 1.228 -1.399 False
94 clay loam D 30 35 35 1.800 0.330 0.274 0.181 0.094 1.524 0.025 0.005 0.000 0.109 0.009 1.231 1.412 -1.890 True
95 clay loam D 30 35 35 1.900 0.305 0.260 0.181 0.078 1.009 0.017 0.006 0.000 0.110 0.009 1.204 1.848 -2.537 True
96 silty clay loam D 10 56 34 0.800 0.609 0.479 0.199 0.280 229.209 3.760 0.033 0.000 0.122 0.005 1.436 2.158 0.129 False
97 silty clay loam D 10 56 34 0.900 0.578 0.460 0.192 0.267 138.366 2.270 0.026 0.000 0.118 0.004 1.438 1.567 0.221 False
98 silty clay loam D 10 56 34 1.000 0.549 0.438 0.186 0.252 81.976 1.345 0.021 0.000 0.115 0.004 1.437 1.219 0.207 False
99 silty clay loam D 10 56 34 1.100 0.520 0.416 0.181 0.236 47.675 0.782 0.017 0.000 0.114 0.004 1.432 1.013 0.132 False
100 silty clay loam D 10 56 34 1.200 0.492 0.395 0.176 0.218 27.436 0.450 0.015 0.000 0.112 0.004 1.424 0.895 0.030 False
101 silty clay loam D 10 56 34 1.300 0.465 0.374 0.174 0.200 15.812 0.259 0.013 0.000 0.112 0.005 1.412 0.825 -0.087 False
102 silty clay loam D 10 56 34 1.400 0.439 0.354 0.172 0.182 9.222 0.151 0.011 0.000 0.111 0.005 1.394 0.779 -0.221 False
103 silty clay loam D 10 56 34 1.500 0.413 0.336 0.172 0.164 5.486 0.090 0.009 0.000 0.111 0.005 1.372 0.752 -0.379 False
104 silty clay loam D 10 56 34 1.600 0.388 0.318 0.172 0.146 3.339 0.055 0.008 0.000 0.111 0.005 1.343 0.748 -0.573 False
105 silty clay loam D 10 56 34 1.700 0.362 0.301 0.174 0.127 2.092 0.034 0.007 0.000 0.111 0.006 1.311 0.779 -0.829 True
106 silty clay loam D 10 56 34 1.800 0.338 0.285 0.175 0.109 1.377 0.023 0.006 0.000 0.111 0.006 1.279 0.868 -1.167 True
107 silty clay loam D 10 56 34 1.900 0.315 0.268 0.176 0.093 0.974 0.016 0.006 0.000 0.111 0.007 1.250 1.064 -1.599 True
108 sandy clay D 50 7 43 0.800 0.616 0.408 0.222 0.186 240.026 3.937 0.009 0.000 0.133 0.018 1.302 8.437 -1.512 False
109 sandy clay D 50 7 43 0.900 0.590 0.398 0.216 0.183 166.103 2.725 0.008 0.000 0.130 0.016 1.305 6.062 -1.395 False
110 sandy clay D 50 7 43 1.000 0.564 0.386 0.209 0.176 115.164 1.889 0.006 0.000 0.126 0.016 1.305 4.659 -1.351 False
111 sandy clay D 50 7 43 1.100 0.539 0.372 0.204 0.168 79.444 1.303 0.005 0.000 0.124 0.015 1.304 3.821 -1.345 False
112 sandy clay D 50 7 43 1.200 0.514 0.358 0.199 0.159 54.335 0.891 0.005 0.000 0.122 0.015 1.300 3.312 -1.370 False
113 sandy clay D 50 7 43 1.300 0.488 0.345 0.195 0.149 36.772 0.603 0.004 0.000 0.120 0.015 1.293 2.968 -1.434 False
114 sandy clay D 50 7 43 1.400 0.463 0.332 0.194 0.139 24.361 0.400 0.004 0.000 0.119 0.015 1.282 2.687 -1.543 False
115 sandy clay D 50 7 43 1.500 0.436 0.321 0.193 0.127 15.598 0.256 0.004 0.000 0.118 0.015 1.265 2.441 -1.723 True
116 sandy clay D 50 7 43 1.600 0.408 0.310 0.196 0.115 9.416 0.154 0.003 0.000 0.117 0.015 1.242 2.248 -2.029 True
117 sandy clay D 50 7 43 1.700 0.380 0.300 0.200 0.100 5.387 0.088 0.003 0.000 0.117 0.015 1.214 2.186 -2.542 True
118 sandy clay D 50 7 43 1.800 0.350 0.288 0.203 0.084 3.138 0.051 0.003 0.000 0.118 0.015 1.186 2.423 -3.307 True
119 sandy clay D 50 7 43 1.900 0.322 0.272 0.203 0.069 2.041 0.033 0.004 0.000 0.120 0.015 1.165 3.192 -4.266 True
120 silty clay D 7 47 46 0.800 0.635 0.473 0.224 0.249 217.292 3.565 0.019 0.000 0.137 0.007 1.372 3.245 -0.458 False
121 silty clay D 7 47 46 0.900 0.605 0.460 0.219 0.241 131.925 2.164 0.015 0.000 0.133 0.007 1.372 2.269 -0.334 False
122 silty clay D 7 47 46 1.000 0.575 0.443 0.213 0.230 78.732 1.292 0.012 0.000 0.130 0.006 1.369 1.657 -0.298 False
123 silty clay D 7 47 46 1.100 0.546 0.425 0.209 0.216 45.845 0.752 0.010 0.000 0.128 0.006 1.364 1.305 -0.330 False
124 silty clay D 7 47 46 1.200 0.518 0.406 0.205 0.201 26.160 0.429 0.008 0.000 0.127 0.006 1.356 1.093 -0.405 False
125 silty clay D 7 47 46 1.300 0.489 0.388 0.203 0.185 14.805 0.243 0.007 0.000 0.127 0.006 1.344 0.954 -0.503 False
126 silty clay D 7 47 46 1.400 0.461 0.370 0.202 0.168 8.421 0.138 0.006 0.000 0.126 0.006 1.328 0.858 -0.624 False
127 silty clay D 7 47 46 1.500 0.433 0.352 0.201 0.151 4.871 0.080 0.005 0.000 0.126 0.006 1.309 0.789 -0.786 False
128 silty clay D 7 47 46 1.600 0.405 0.335 0.202 0.133 2.887 0.047 0.005 0.000 0.127 0.007 1.285 0.749 -1.013 True
129 silty clay D 7 47 46 1.700 0.377 0.318 0.203 0.114 1.773 0.029 0.004 0.000 0.128 0.007 1.259 0.749 -1.338 True
130 silty clay D 7 47 46 1.800 0.350 0.300 0.204 0.096 1.152 0.019 0.004 0.000 0.129 0.007 1.233 0.817 -1.791 True
131 silty clay D 7 47 46 1.900 0.324 0.282 0.203 0.079 0.818 0.013 0.004 0.000 0.132 0.008 1.209 1.016 -2.381 True
132 clay D 20 20 60 0.800 0.647 0.449 0.252 0.197 207.818 3.409 0.008 0.000 0.151 0.016 1.291 6.239 -1.596 False
133 clay D 20 20 60 0.900 0.619 0.442 0.248 0.194 130.710 2.144 0.007 0.000 0.147 0.014 1.288 4.412 -1.453 False
134 clay D 20 20 60 1.000 0.591 0.432 0.244 0.188 82.545 1.354 0.006 0.000 0.143 0.013 1.285 3.219 -1.393 False
135 clay D 20 20 60 1.100 0.563 0.418 0.239 0.179 52.323 0.858 0.005 0.000 0.141 0.012 1.280 2.469 -1.391 False
136 clay D 20 20 60 1.200 0.536 0.404 0.236 0.168 33.173 0.544 0.004 0.000 0.139 0.012 1.273 2.010 -1.427 False
137 clay D 20 20 60 1.300 0.509 0.390 0.233 0.157 20.956 0.344 0.004 0.000 0.137 0.011 1.264 1.717 -1.501 False
138 clay D 20 20 60 1.400 0.481 0.375 0.231 0.144 13.182 0.216 0.003 0.000 0.137 0.011 1.252 1.507 -1.628 True
139 clay D 20 20 60 1.500 0.453 0.360 0.230 0.131 8.264 0.136 0.003 0.000 0.136 0.011 1.238 1.350 -1.831 True
140 clay D 20 20 60 1.600 0.425 0.345 0.230 0.115 5.162 0.085 0.003 0.000 0.136 0.011 1.219 1.248 -2.163 True
141 clay D 20 20 60 1.700 0.395 0.330 0.230 0.099 3.240 0.053 0.002 0.000 0.138 0.011 1.198 1.240 -2.681 True
142 clay D 20 20 60 1.800 0.366 0.313 0.230 0.083 2.247 0.037 0.003 0.000 0.140 0.012 1.178 1.417 -3.430 True
143 clay D 20 20 60 1.900 0.338 0.295 0.228 0.067 2.749 0.045 0.003 0.000 0.144 0.012 1.159 1.973 -4.424 True

1. Saturated hydraulic conductivity (Ksat)

Rosetta’s saturated hydraulic conductivity vs. bulk density, one line per texture class, on a log axis in stormwater units (in/hr); grey-dashed where bulk denisty-texture combinations are outside of calibration.

Note the spurious upturn at high BD for silt and other fine textures are an extrapolation artifact (those dense fine-soil states are absent from empirical observations used to build Rosetta), not a real rise in conductivity; it falls entirely inside the greyed region.

Show code
line_with_extrapolation(
    result,
    "ksat_in_hr",
    "Saturated hydraulic conductivity Ksat (in/hr, log scale)",
    "Rosetta saturated hydraulic conductivity vs. bulk density by USDA texture class",
    logy=True,
)

Takeaway: Sandy soils transmit water orders of magnitude faster than clays, and increasing bulk density (compaction) reduces Ksat sharply across all texture classes. A healthy, loose soil infiltrates far more water than a compacted one of the same texture.

2. Unsaturated hydraulic conductivity K(h)

As soil dries out, its ability to transmit water drops by many orders of magnitude. The log-log chart below shows how K(h) falls with increasing matric potential (suction) for each texture class. Use the bulk-density slider to see how compaction shifts every curve downward. Dotted verticals mark field capacity (FC, 330 cm suction) and wilting point (WP, 15000 cm suction).

Rosetta gives the full Mualem-van Genuchten parameter set, so conductivity is defined not just at saturation but at every suction: K(h) = K0·Se(h)^L·[1 − (1 − Se(1/m))m]² with Se(h) = [1 + (αh)^n]^(−m) (see mualem_k). Curves use Rosetta’s K0 (matching point) and L (columns 5-6), not Ksat. k_fc_cm_day / k_wp_cm_day in the table are K at those tensions. Log-log axes; bulk-density slider; implausible (implausible_bd) BD × texture combinations are grey-dashed.

Show code
hv.output(widget_location="bottom")

# K(h) over a log-spaced suction grid for every texture × bulk density
_suction = np.logspace(0.0, np.log10(15000.0), 36)  # 1 .. 15000 cm (log-spaced; 36 pts render identically on the log-log axis)
_kh_rows = []
for r in result.itertuples():
    K = mualem_k(_suction, r.vg_alpha_1cm, r.vg_n, r.k0_cm_day, r.mualem_L)  # cm/day
    for h, k in zip(_suction, K):
        _kh_rows.append((r.texture_class, r.bulk_density_g_cm3, h, k / (24.0 * 2.54), r.implausible_bd))
kh_df = pd.DataFrame(_kh_rows, columns=["texture_class", "bulk_density_g_cm3", "suction_cm", "k_in_hr", "implausible_bd"])
kh_df["texture_class"] = pd.Categorical(kh_df["texture_class"], categories=list(TEXTURE_CLASSES), ordered=True)

_kh_markers = (
    hv.VLine(330).opts(color="black", line_dash="dotted", line_width=1)
    * hv.VLine(15000).opts(color="gray", line_dash="dotted", line_width=1)
    * hv.Text(330, 30, " FC", halign="left", valign="top").opts(text_font_size="8pt")
    * hv.Text(15000, 30, "WP ", halign="right", valign="top").opts(text_font_size="8pt")
)
(
    bd_slider_line(
        kh_df, "suction_cm", "k_in_hr",
        "suction head h (cm, log)", "unsaturated K (in/hr, log)",
        "Rosetta unsaturated hydraulic conductivity K(h) — {dimensions}",
        logx=True, logy=True, ylim=(1e-7, 1e2),
    )
    * _kh_markers
).redim(bulk_density_g_cm3=hv.Dimension("Bulk density, g/cm³ (higher is more compacted)", default=1.4, value_format=lambda v: f"{v:.1f}"))

Takeaway: Between field capacity and wilting point — the range where plants can extract water — conductivity is already thousands of times lower than at saturation; compaction compresses this window further, making it harder for both water and roots to move through the soil profile.

3. Green-Ampt infiltration

Infiltration starts fast, especially in healthy soils, and slows toward a steady rate as the wetting front advances. The two charts below show the infiltration rate f(t) and cumulative depth F(t) over the first two hours of ponded conditions. Use the bulk-density slider to see how compaction cuts both curves dramatically, increasing runoff risk.

The Green-Ampt model gives the infiltration rate f and cumulative depth F for ponded / intense-rain conditions:

\[f = K_s\left(1 + \frac{\psi_f\,\Delta\theta}{F}\right), \qquad t = \frac{1}{K_s}\left[F - \psi_f\Delta\theta\,\ln\!\left(1 + \frac{F}{\psi_f\Delta\theta}\right)\right]\]

Parameterization: Rosetta supplies the BD-sensitive Ksat and the moisture deficit Δθ = θₛ − θ_initial (initial = wilting point here, i.e. dry antecedent). The wetting-front suction ψ_f is taken from the Rawls, Brakensiek & Miller (1983) texture table (cm) — deriving ψ_f from Rosetta’s Mualem K(h) integral proved unreliable (Rosetta’s fitted L mis-orders the capillary drive, putting sand above clay), so the published textural values are more robust.

Caveats: matrix-only (real infiltration is often higher via macropores/structure); Ksat is Rosetta’s least-certain output; high-BD × texture extrapolations are grey-dashed.

Show code
hv.output(widget_location="bottom")

# Rawls, Brakensiek & Miller (1983) Green-Ampt wetting-front suction head, cm (silt ≈ silt loam)
RAWLS_PSI_F_CM = {
    "sand": 4.95, "loamy sand": 6.13, "sandy loam": 11.01, "loam": 8.89,
    "silt loam": 16.68, "silt": 16.68, "sandy clay loam": 21.85, "clay loam": 20.88,
    "silty clay loam": 27.30, "sandy clay": 23.90, "silty clay": 29.22, "clay": 31.63,
}
GA_T_MAX_HR = 2.0  # plot the first 2 hours
# Geometric (log) spacing keeps the early-time / small-F detail dense, where slow soils
# spend the whole 2-hour window, while using far fewer points than a uniform grid.
_F_grid = np.geomspace(0.2, 80.0, 120)  # cumulative infiltration, cm

_ga_rows = []
for r in result.itertuples():
    Ks = r.ksat_cm_day  # cm/day
    dtheta = max(r.total_porosity - r.wilting_point_porosity, 1e-6)
    Sf = RAWLS_PSI_F_CM[r.texture_class] * dtheta  # cm
    t_hr = (_F_grid - Sf * np.log1p(_F_grid / Sf)) / Ks * 24.0
    f_in_hr = Ks * (1.0 + Sf / _F_grid) / (24.0 * 2.54)
    F_in = _F_grid / 2.54
    keep = t_hr <= GA_T_MAX_HR
    for th, fi, Fi in zip(t_hr[keep], f_in_hr[keep], F_in[keep]):
        _ga_rows.append((r.texture_class, r.bulk_density_g_cm3, th, fi, Fi, r.implausible_bd))
ga_df = pd.DataFrame(_ga_rows, columns=["texture_class", "bulk_density_g_cm3", "t_hr", "f_in_hr", "F_in", "implausible_bd"])
ga_df["texture_class"] = pd.Categorical(ga_df["texture_class"], categories=list(TEXTURE_CLASSES), ordered=True)

bd_slider_line(
    ga_df, "t_hr", "f_in_hr",
    "time (hours)", "infiltration rate f (in/hr, log)",
    "Green-Ampt infiltration rate vs. time — {dimensions}",
    logy=True, ylim=(0.05, 300),
).redim(bulk_density_g_cm3=hv.Dimension("Bulk density, g/cm³ (higher is more compacted)", default=1.4, value_format=lambda v: f"{v:.1f}"))
Show code
# Cumulative infiltration depth F(t).
hv.output(widget_location="bottom")
bd_slider_line(
    ga_df, "t_hr", "F_in",
    "time (hours)", "cumulative infiltration F (inches)",
    "Green-Ampt cumulative infiltration vs. time — {dimensions}",
    ylim=(0, 25),
).redim(bulk_density_g_cm3=hv.Dimension("Bulk density, g/cm³ (higher is more compacted)", default=1.4, value_format=lambda v: f"{v:.1f}"))

Takeaway: Infiltration starts fast and settles toward the saturated rate — but compaction lowers the ceiling, so a compacted soil ponds and runs off far sooner than a healthy one of the same texture, even under the same rainfall intensity.

Back to top