smoke-index/van-genuchten.html
2026-07-18 08:10:38 +00:00

122 lines
7.6 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Van Genuchten Soil Water Retention | Arthur Ibay</title>
<style>
:root{--bg:#0f0f12;--fg:#e6e6e8;--accent:#ff6b35;--panel:#1a1a20;--grid:#2a2a35}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:"Inter",system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--fg);line-height:1.6;font-size:16px;padding:2rem;letter-spacing:-0.01em}
h1{font-weight:700;font-size:clamp(1.8rem,4vw,2.8rem);margin-bottom:0.5rem;letter-spacing:-0.02em;color:#fff}
.subtitle{opacity:.75;font-size:1rem;margin-bottom:2rem;font-feature-settings:"tnum,onum"}
nav{display:flex;gap:1.5rem;margin-bottom:2.5rem;font-size:.9rem;flex-wrap:wrap}
nav a{color:inherit;text-decoration:none;border-bottom:1px solid transparent;padding-bottom:2px;transition:border-color .2s}
nav a:hover{border-color:var(--accent)}
main{max-width:1100px;margin:0 auto;display:grid;grid-template-columns:1fr 1fr;gap:2.5rem}
.panel{background:var(--panel);border-radius:12px;padding:2rem;border:1px solid var(--grid);box-shadow:0 10px 40px rgba(0,0,0,.4)}
.panel h2{font-size:1.1rem;margin-bottom:1.2rem;color:var(--accent);text-transform:uppercase;letter-spacing:.08em;font-weight:600}
label{display:block;font-size:.85rem;opacity:.85;margin-bottom:.4rem;font-weight:500}
select,input{width:100%;padding:.75rem 1rem;background:#0f0f12;border:1px solid var(--grid);color:var(--fg);border-radius:6px;font-size:.95rem;margin-bottom:1.2rem;font-family:inherit}
select:focus,input:focus{outline:none;border-color:var(--accent)}
button{background:var(--accent);color:#000;border:none;padding:.9rem 1.5rem;border-radius:6px;font-weight:700;cursor:pointer;width:100%;font-size:1rem;transition:transform .1s,filter .2s}
button:hover{filter:brightness(1.15)}
button:active{transform:scale(.99)}
.result{margin-top:1.5rem;padding:1.2rem;background:rgba(255,107,53,.08);border-left:3px solid var(--accent);border-radius:0 6px 6px 0}
.result-row{display:grid;grid-template-columns:1fr auto;gap:1rem;font-size:.9rem;margin-bottom:.5rem;padding:.35rem 0;border-bottom:1px dashed rgba(255,255,255,.08)}
.result-row:last-child{border:none;margin-bottom:0}
.result-label{opacity:.75}
.result-val{font-weight:600;font-feature-settings:"tnum,onum";text-align:right}
.caption{margin-top:.75rem;font-size:.8rem;opacity:.65;text-align:center}
.citation{margin-top:2rem;font-size:.8rem;opacity:.5;line-height:1.8}
@media(max-width:900px){main{grid-template-columns:1fr}}
img{width:100%;height:auto;border-radius:8px;margin-top:1.5rem;display:block}
</style>
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
</head>
<body>
<header>
<h1>Van Genuchten Soil Water Retention</h1>
<div class="subtitle">Computing θ_s, θ_r, α, n, m from USDA Texture Class and Bulk Density</div>
<nav>
<a href="/">Home</a><a href="/et-matrix.html">ET Matrix</a><a href="/irrigation-controller.html">Duty Cycle Controller</a><a href="/wasatch-assay.html">Wasatch Assay</a><a href="/garden-ledger.html">Garden Ledger</a>
</nav>
</header>
<main>
<section class="panel">
<h2>Input Parameters</h2>
<label for="texture">USDA Soil Texture Class</label>
<select id="texture">
<option value="sand">Sand</option>
<option value="loamy_sand">Loamy Sand</option>
<option value="sandy_loam">Sandy Loam</option>
<option value="loam" selected>Loam</option>
<option value="silt_loam">Silt Loam</option>
<option value="clay_loam">Clay Loam</option>
<option value="clay">Clay</option>
</select>
<label for="bd">Bulk Density (g/cm³)</label>
<input type="number" id="bd" step="0.01" value="1.35" min="1.0" max="2.0">
<label for="om">Organic Matter (%)</label>
<input type="number" id="om" step="0.1" value="2.5" min="0" max="20">
<button onclick="computeVG()">Compute Retention Curve</button>
</section>
<section class="panel">
<h2>Retained Water Fractions</h2>
<div id="out"></div>
<img src="https://images.pexels.com/photos/12697901/pexels-photo-12697901.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Cracked dry earth—the physical consequence of misjudged water retention">
<div class="caption">When θ_r exceeds plant-available thresholds, the land speaks in fractures.</div>
</section>
</main>
<footer class="citation">
Source: FAO Irrigation and Drainage Paper 56 (1998), Appendix IV. Parameters adapted from Rawls et al. (1982) pedotransfer functions for USDA texture classes.<br>
Implementation: Arthur Ibay, Salt Lake City. Machine-readable coefficients at /van-genuchten.json.
</footer>
<script>
const VG = {
sand:{theta_s:0.425, theta_r:0.065, alpha:0.037, n:2.12, bd_base:1.55, om_coef:0.008},
loamy_sand:{theta_s:0.410, theta_r:0.075, alpha:0.045, n:1.95, bd_base:1.50, om_coef:0.009},
sandy_loam:{theta_s:0.405, theta_r:0.085, alpha:0.052, n:1.88, bd_base:1.45, om_coef:0.010},
loam:{theta_s:0.400, theta_r:0.095, alpha:0.060, n:1.80, bd_base:1.35, om_coef:0.011},
silt_loam:{theta_s:0.395, theta_r:0.105, alpha:0.070, n:1.72, bd_base:1.30, om_coef:0.012},
clay_loam:{theta_s:0.385, theta_r:0.120, alpha:0.082, n:1.62, bd_base:1.25, om_coef:0.013},
clay:{theta_s:0.375, theta_r:0.135, alpha:0.095, n:1.52, bd_base:1.20, om_coef:0.014}
};
function computeVG(){
const txt=document.getElementById('texture').value;
const bd=parseFloat(document.getElementById('bd').value)||1.35;
const om=parseFloat(document.getElementById('om').value)||2.5;
const p=VG[txt];
// Adjust porosity by bulk density deviation from base
const phi_adj=(p.bd_base-bd)*0.02;
const theta_s=p.theta_s+phi_adj+(om*p.om_coef);
const theta_r=p.theta_r*(1-om*0.005);
const alpha=p.alpha*Math.pow(bd/p.bd_base,0.5);
const n=p.n*(1-om*0.002);
const m=1-1/n;
// Van Genuchten: theta(h)=theta_r+(theta_s-theta_r)/(1+(alpha*|h|)^n)^m
const fc=theta_r+(theta_s-theta_r)/Math.pow(1+Math.pow(alpha*0.33,n),m);
const pwp=theta_r+(theta_s-theta_r)/Math.pow(1+Math.pow(alpha*1.5,n),m);
const awc=fc-pwp;
const out=`
<div class="result"><strong>Computed Parameters</strong></div>
<div class="result-row"><span class="result-label">θ_s (Saturated Vol. Fraction)</span><span class="result-val">${theta_s.toFixed(4)}</span></div>
<div class="result-row"><span class="result-label">θ_r (Residual Vol. Fraction)</span><span class="result-val">${theta_r.toFixed(4)}</span></div>
<div class="result-row"><span class="result-label">α (Inverse Air Entry, cm⁻¹)</span><span class="result-val">${alpha.toFixed(5)}</span></div>
<div class="result-row"><span class="result-label">n (Pore Size Distribution)</span><span class="result-val">${n.toFixed(3)}</span></div>
<div class="result-row"><span class="result-label">m (Shape Parameter)</span><span class="result-val">${m.toFixed(3)}</span></div>
<hr style="border:0;border-top:1px dashed rgba(255,255,255,.1);margin:1rem 0">
<div class="result"><strong>Operational Points</strong></div>
<div class="result-row"><span class="result-label">Field Capacity (0.33MPa)</span><span class="result-val">${fc.toFixed(4)}cm³/cm³</span></div>
<div class="result-row"><span class="result-label">Permanent Wilting Pt (1.5MPa)</span><span class="result-val">${pwp.toFixed(4)}cm³/cm³</span></div>
<div class="result-row"><span class="result-label">Available Water Capacity</span><span class="result-val">${awc.toFixed(4)}cm³/cm³</span></div>
<div class="result-row"><span class="result-label">AWC (mm per meter depth)</span><span class="result-val">${(awc*1000).toFixed(1)}mm</span></div>
`;
document.getElementById('out').innerHTML=out;
}
// Pre-compute default
window.onload=()=>setTimeout(computeVG,150);
</script>
</body>
</html>