236 lines
9.6 KiB
HTML
236 lines
9.6 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title>Spokane Soil Moisture Deficit | Benjamin Salais</title>
|
||
|
|
<style>
|
||
|
|
:root {
|
||
|
|
--bg: #1a1a1a;
|
||
|
|
--fg: #e0e0e0;
|
||
|
|
--accent: #d4af37; /* Gold of the harvest */
|
||
|
|
--panel: #2a2a2a;
|
||
|
|
--border: #444;
|
||
|
|
}
|
||
|
|
body {
|
||
|
|
font-family: 'Georgia', serif;
|
||
|
|
background-color: var(--bg);
|
||
|
|
color: var(--fg);
|
||
|
|
margin: 0;
|
||
|
|
padding: 0;
|
||
|
|
line-height: 1.6;
|
||
|
|
}
|
||
|
|
header {
|
||
|
|
background: linear-gradient(180deg, #111 0%, #1a1a1a 100%);
|
||
|
|
border-bottom: 1px solid var(--accent);
|
||
|
|
padding: 2rem 1rem;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
h1 {
|
||
|
|
font-size: 2rem;
|
||
|
|
margin: 0;
|
||
|
|
letter-spacing: 0.05em;
|
||
|
|
color: var(--accent);
|
||
|
|
}
|
||
|
|
.subtitle {
|
||
|
|
font-size: 0.9rem;
|
||
|
|
opacity: 0.8;
|
||
|
|
margin-top: 0.5rem;
|
||
|
|
font-style: italic;
|
||
|
|
}
|
||
|
|
main {
|
||
|
|
max-width: 800px;
|
||
|
|
margin: 2rem auto;
|
||
|
|
padding: 0 1rem;
|
||
|
|
}
|
||
|
|
.grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
gap: 2rem;
|
||
|
|
margin: 2rem 0;
|
||
|
|
}
|
||
|
|
@media (max-width: 700px) {
|
||
|
|
.grid { grid-template-columns: 1fr; }
|
||
|
|
}
|
||
|
|
.panel {
|
||
|
|
background: var(--panel);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: 4px;
|
||
|
|
padding: 1.5rem;
|
||
|
|
}
|
||
|
|
img.soil-sample {
|
||
|
|
width: 100%;
|
||
|
|
height: auto;
|
||
|
|
border-radius: 4px;
|
||
|
|
margin-bottom: 1rem;
|
||
|
|
filter: sepia(0.2);
|
||
|
|
}
|
||
|
|
label {
|
||
|
|
display: block;
|
||
|
|
margin-bottom: 0.5rem;
|
||
|
|
font-weight: bold;
|
||
|
|
color: var(--accent);
|
||
|
|
}
|
||
|
|
input[type="range"] {
|
||
|
|
width: 100%;
|
||
|
|
margin: 0.5rem 0;
|
||
|
|
accent-color: var(--accent);
|
||
|
|
}
|
||
|
|
select, input[type="number"] {
|
||
|
|
background: #111;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
color: var(--fg);
|
||
|
|
padding: 0.5rem;
|
||
|
|
width: 100%;
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
.result-box {
|
||
|
|
background: #111;
|
||
|
|
border-left: 4px solid var(--accent);
|
||
|
|
padding: 1rem;
|
||
|
|
margin-top: 1rem;
|
||
|
|
}
|
||
|
|
.metric {
|
||
|
|
font-size: 1.2rem;
|
||
|
|
font-weight: bold;
|
||
|
|
color: var(--accent);
|
||
|
|
}
|
||
|
|
.citation {
|
||
|
|
font-size: 0.75rem;
|
||
|
|
opacity: 0.6;
|
||
|
|
margin-top: 1rem;
|
||
|
|
text-decoration: underline;
|
||
|
|
}
|
||
|
|
nav {
|
||
|
|
text-align: center;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
font-size: 0.9rem;
|
||
|
|
}
|
||
|
|
nav a {
|
||
|
|
color: var(--accent);
|
||
|
|
text-decoration: none;
|
||
|
|
margin: 0 0.5rem;
|
||
|
|
}
|
||
|
|
nav a:hover {
|
||
|
|
text-decoration: underline;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<header>
|
||
|
|
<h1>Soil Moisture Deficit</h1>
|
||
|
|
<div class="subtitle">Calculated for the Spokane Valley, WA</div>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<main>
|
||
|
|
<nav>
|
||
|
|
<a href="/">Home</a> • <a href="/spokane-soil-deficit.html">Calculator</a> • <a href="/garden-log.html">Field Log</a>
|
||
|
|
</nav>
|
||
|
|
|
||
|
|
<section class="panel">
|
||
|
|
<h2>The Principle</h2>
|
||
|
|
<p>In Spokane, the summer air is dry. The soil breathes out its moisture through evapotranspiration. To survive the drought, we must know how much water our soil can hold.</p>
|
||
|
|
<p>This tool calculates the <strong>Available Water Capacity (AWC)</strong> based on soil texture, then compares it to the estimated seasonal loss. The result tells you how many days your plants can endure without irrigation.</p>
|
||
|
|
|
||
|
|
<img src="https://pixabay.com/get/g689f71f8334980f07af955048c3c436230fce9325ee28c85dd1f740845eb588041aa2fe13a9f09fc35d3612d1a08d947e66a908593f6f11a3bb518f170279ade_1280.png" alt="Cross-section of soil layers" class="soil-sample">
|
||
|
|
<p style="font-size: 0.8rem; text-align: center; opacity: 0.7;">Fig 1: Soil profile. The top layer holds the moisture; the bottom anchors the roots.</p>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<div class="grid">
|
||
|
|
<section class="panel">
|
||
|
|
<h3>Input Parameters</h3>
|
||
|
|
|
||
|
|
<label for="texture">Soil Texture Class</label>
|
||
|
|
<select id="texture">
|
||
|
|
<option value="sand">Sand (Low retention)</option>
|
||
|
|
<option value="loamy-sand">Loamy Sand</option>
|
||
|
|
<option value="sandy-loam" selected>Sandy Loam (Typical Spokane)</option>
|
||
|
|
<option value="loam">Loam (Ideal)</option>
|
||
|
|
<option value="silty-loam">Silty Loam</option>
|
||
|
|
<option value="clay-loam">Clay Loam (High retention, high effort)</option>
|
||
|
|
</select>
|
||
|
|
|
||
|
|
<label for="depth">Root Zone Depth (cm)</label>
|
||
|
|
<input type="number" id="depth" value="30" min="10" max="100">
|
||
|
|
<small>Standard vegetable bed: 30cm. Deep-rooted shrubs: 60cm+</small>
|
||
|
|
|
||
|
|
<label for="wetness">Current Saturation (% of Field Capacity)</label>
|
||
|
|
<input type="range" id="wetness" min="0" max="100" value="100">
|
||
|
|
<span id="wetness-val">100%</span>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="panel">
|
||
|
|
<h3>Output: Resilience Estimate</h3>
|
||
|
|
<div class="result-box">
|
||
|
|
<div>AWC (mm/cm): <span id="awc-display" class="metric">-</span></div>
|
||
|
|
<div>Total Storage (mm): <span id="storage-display" class="metric">-</span></div>
|
||
|
|
<hr style="border-color: #333; border-style: dashed;">
|
||
|
|
<div>Evapotranspiration Rate (July Avg): <span class="metric">5.2 mm/day</span></div>
|
||
|
|
<div style="margin-top: 1rem; font-size: 1.5rem; color: var(--accent);">
|
||
|
|
Days Until Deficit: <span id="days-display" class="metric">-</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<p class="citation">Data Source: USDA-NRCS Soil Survey Geographic Database (SSURGO) & Van Genuchten Model Constants (Q3457648).</p>
|
||
|
|
</section>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<section class="panel">
|
||
|
|
<h3>Notes on Method</h3>
|
||
|
|
<p>The calculation uses the Van Genuchten soil-water characteristic curve parameters adapted for USDA texture classes. The <strong>Available Water Capacity</strong> is defined as the difference between Field Capacity (θ_fc) and Permanent Wilting Point (θ_pwp).</p>
|
||
|
|
<ul>
|
||
|
|
<li><strong>Field Capacity:</strong> Water retained after gravity drainage (≈ -33 kPa).</li>
|
||
|
|
<li><strong>Wilting Point:</strong> Water remaining when plants can no longer extract moisture (≈ -1500 kPa).</li>
|
||
|
|
</ul>
|
||
|
|
<p><em>For Spokane (Lat 47.6° N):</em> Peak summer ET₀ is approximately 5.2 mm/day (FAO Penman-Monteith approximation for mid-July conditions).</p>
|
||
|
|
</section>
|
||
|
|
</main>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// USDA Texture Classes -> Van Genuchten Derived AWC (mm/cm)
|
||
|
|
// Based on USDA-NRCS National Engineering Handbook Section 4
|
||
|
|
const SOIL_DATA = {
|
||
|
|
"sand": { awc_per_cm: 0.08, desc: "Very low water holding capacity" },
|
||
|
|
"loamy-sand": { awc_per_cm: 0.12, desc: "Low capacity, drains rapidly" },
|
||
|
|
"sandy-loam": { awc_per_cm: 0.16, desc: "Moderate capacity, typical of Spokane river terraces" },
|
||
|
|
"loam": { awc_per_cm: 0.20, desc: "Optimal balance of drainage and retention" },
|
||
|
|
"silty-loam": { awc_per_cm: 0.24, desc: "High retention, prone to compaction" },
|
||
|
|
"clay-loam": { awc_per_cm: 0.28, desc: "Maximum retention, difficult to till when wet" }
|
||
|
|
};
|
||
|
|
|
||
|
|
const ET_RATE_MM_PER_DAY = 5.2; // Spokane July Average
|
||
|
|
|
||
|
|
function calculate() {
|
||
|
|
const textureKey = document.getElementById('texture').value;
|
||
|
|
const depth = parseFloat(document.getElementById('depth').value) || 30;
|
||
|
|
const saturation = parseInt(document.getElementById('wetness').value) / 100;
|
||
|
|
|
||
|
|
const soil = SOIL_DATA[textureKey];
|
||
|
|
const totalStorage = soil.awc_per_cm * depth; // Total mm available if fully saturated
|
||
|
|
const currentWater = totalStorage * saturation; // Current usable water
|
||
|
|
|
||
|
|
const daysUntilDeficit = Math.floor(currentWater / ET_RATE_MM_PER_DAY);
|
||
|
|
|
||
|
|
document.getElementById('awc-display').textContent = soil.awc_per_cm.toFixed(2);
|
||
|
|
document.getElementById('storage-display').textContent = totalStorage.toFixed(1);
|
||
|
|
document.getElementById('days-display').textContent = daysUntilDeficit;
|
||
|
|
|
||
|
|
// Update slider label
|
||
|
|
document.getElementById('wetness-val').textContent = (saturation * 100).toFixed(0) + "%";
|
||
|
|
}
|
||
|
|
|
||
|
|
// Event Listeners
|
||
|
|
document.getElementById('texture').addEventListener('change', calculate);
|
||
|
|
document.getElementById('depth').addEventListener('input', calculate);
|
||
|
|
document.getElementById('wetness').addEventListener('input', () => {
|
||
|
|
const val = document.getElementById('wetness').value;
|
||
|
|
document.getElementById('wetness-val').textContent = val + "%";
|
||
|
|
calculate();
|
||
|
|
});
|
||
|
|
|
||
|
|
// Initial Calc
|
||
|
|
calculate();
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|