Skip to content
Back to skills

Docs

ASecurity

> **Stage ID**: s2_soil_params > **Pipeline order**: 2 of 8 > **Depends on**: none

  • 200 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 11, 2026
testingpythonspringgitdatabase

Security analysis

A100/100

Pro scans all 14 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add lzwei196/KISS---Knowledge-Infrastructure-for-Scientific-Simulation --skill docs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Docs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Docs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lzwei196-docs-b1a04323/badge)](https://www.skillsdirectory.com/skills/lzwei196-docs-b1a04323)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Soil Parameter Setup — Skill Document

> **Stage ID**: s2_soil_params
> **Pipeline order**: 2 of 8
> **Depends on**: none

## Purpose

Configure soil hydraulic and physical parameters for the WOFOST classic water balance. Unlike DSSAT's multi-layer soil profile, WOFOST uses a single-layer "bucket" model characterized by three moisture limits (SMW, SMFCF, SM0) and hydraulic conductivity (K0). The soil parameters determine water stress patterns, which directly control yield in water-limited (WLP) simulations. Incorrect soil parameters produce plausible-looking but wrong yields with no error message.

## Prerequisites

- [ ] Target location coordinates known (lat, lon)
- [ ] HWSD global raster accessible at `data/soil/HWSD_RASTER/hwsd.bil` (or equivalent soil database)
- [ ] HWSD MDB database accessible at `data/forcing/huaihe_raw/soil/HWSD.mdb`
- [ ] Understanding of which simulation mode will be used (soil params not needed for Wofost72_PP)

## Inputs

| Input | Type | Source | Description |
|-------|------|--------|-------------|
| lat | number | basin delineation | Latitude of grid cell center |
| lon | number | basin delineation | Longitude of grid cell center |
| hwsd_raster | file | data/soil/HWSD_RASTER/hwsd.bil | HWSD global soil raster |
| hwsd_mdb | file | data/forcing/huaihe_raw/soil/HWSD.mdb | HWSD properties database |
| sand_pct | number | HWSD or lab data | Sand fraction (%) |
| clay_pct | number | HWSD or lab data | Clay fraction (%) |
| organic_carbon | number | HWSD or lab data | Organic carbon (%) |
| bulk_density | number | HWSD or lab data | Bulk density (g/cm3) |

## Procedure

### Step 1: Extract soil properties from HWSD

```python
# Use the shared HWSD soil adapter (same source as VIC and DSSAT)
# This extracts sand, silt, clay, OC, bulk density for the location
from hwsd_soil_adapter import get_soil_properties
props = get_soil_properties(lat=52.0, lon=5.5,
    hwsd_raster='data/soil/HWSD_RASTER/hwsd.bil',
    hwsd_mdb='data/forcing/huaihe_raw/soil/HWSD.mdb')
```

**Expected result**: Dictionary with T_SAND, T_SILT, T_CLAY, T_OC, T_REF_BULK_DENSITY.

**If this fails**: Check HWSD file paths; verify lat/lon is on land (ocean cells have no soil data).

### Step 2: Convert to WOFOST soil parameters via pedotransfer functions

```python
# Pedotransfer functions (Wosten et al. 1999)
import math

sand = props['T_SAND']   # %
clay = props['T_CLAY']   # %
om = props['T_OC'] * 1.724  # OC% → OM%
bd = props['T_REF_BULK_DENSITY']  # g/cm3

# Wilting point (pF 4.2, -1500 kPa)
SMW = 0.001 + 0.26 * clay/100 + 0.05 * om/100
# Field capacity (pF 2.0, -10 kPa)
SMFCF = 0.02 + 0.37 * clay/100 + 0.15 * om/100 + 0.10 * (1 - sand/100 - clay/100)
# Saturation (porosity)
SM0 = 1.0 - bd / 2.65  # assuming particle density 2.65 g/cm3

# Clamp to valid ranges
SMW = max(0.01, min(SMW, 0.50))
SMFCF = max(SMW + 0.01, min(SMFCF, SM0 - 0.02))

# Hydraulic conductivity (simplified Cosby et al.)
K0 = 10.0 ** (1.26 - 0.0064 * clay - 0.0126 * sand * 0)  # cm/day, simplified
K0 = max(1.0, min(K0, 100.0))

soil_params = {
    'SMW': round(SMW, 3),
    'SMFCF': round(SMFCF, 3),
    'SM0': round(SM0, 3),
    'CRAIRC': round(max(0.02, SM0 - SMFCF - 0.02), 3),
    'K0': round(K0, 1),
    'SOPE': 1.0,      # max percolation rate root zone (cm/day)
    'KSUB': 1.0,      # max percolation rate subsoil (cm/day)
    'RDMSOL': 120.0,   # max rootable depth (cm) — adjust per soil
    'IFUNRN': 0,       # 0=no runoff curve, 1=USDA curve number
    'SSMAX': 0.0,      # max surface storage (cm)
    'SSI': 0.0,        # initial surface storage (cm)
    'WAV': 20.0,       # initial available water in profile (cm)
    'NOTINF': 0.0,     # fraction not infiltrating
    'SMLIM': round(SMFCF, 3),  # soil moisture limit
}
```

**Expected result**: Dictionary with all 14 required soil parameters.

### Step 3: Validate water limits

```python
assert soil_params['SMW'] < soil_params['SMFCF'], \
    f"SMW ({soil_params['SMW']}) must be < SMFCF ({soil_params['SMFCF']})"
assert soil_params['SMFCF'] < soil_params['SM0'], \
    f"SMFCF ({soil_params['SMFCF']}) must be < SM0 ({soil_params['SM0']})"
assert soil_params['SM0'] <= 0.65, \
    f"SM0 ({soil_params['SM0']}) unreasonably high (max porosity ~0.65)"
assert soil_params['CRAIRC'] < soil_params['SM0'] - soil_params['SMFCF'], \
    "CRAIRC must be < SM0 - SMFCF (available air at field capacity)"
```

**Expected result**: All assertions pass.

**If this fails**: See diagnostic triplet dt_009 (soil FC < WP).

### Step 4: Set rootable depth

RDMSOL should reflect actual soil depth. For shallow soils (rocky, hardpan), reduce from default 120 cm.

```python
# Adjust RDMSOL based on soil type
if clay > 60:
    soil_params['RDMSOL'] = 80.0  # heavy clay, shallow roots
elif sand > 80:
    soil_params['RDMSOL'] = 150.0  # sandy, deep roots possible
# Leave at 120.0 for medium textures
```

### Step 5: Save soil parameters

```python
import json
output_path = f'outputs/{run_name}/wofost/soil_params.json'
with open(output_path, 'w') as f:
    json.dump(soil_params, f, indent=2)
```

## Expected Outputs

| Output | Path | Verification |
|--------|------|--------------|
| soil_params dict | `outputs/{run}/wofost/soil_params.json` | JSON with 14 keys; SMW < SMFCF < SM0 |

## Validation Checks

1. **Water limits ordered**: SMW < SMFCF < SM0 — violation means pedotransfer failed
   - Command: `assert soil['SMW'] < soil['SMFCF'] < soil['SM0']`
   - If unexpected: See diagnostic triplet dt_009

2. **SM0 physically possible**: SM0 <= 0.65 (porosity cannot exceed ~65%)
   - If SM0 > 0.65: bulk density is too low or miscalculated

3. **K0 positive**: K0 > 0 cm/day — zero K0 means no water movement
   - Typical range: 1-50 cm/day

4. **RDMSOL reasonable**: 10-300 cm — shallower than 10 cm is extreme; deeper than 300 cm is unrealistic

## Common Pitfalls

> **PITFALL**: Using DSSAT soil parameters directly
> DSSAT uses multi-layer SLLL/SDUL/SSAT per layer. WOFOST uses single-layer SMW/SMFCF/SM0 for the entire profile. You cannot simply copy DSSAT layer 1 values — you need a profile-average or pedotransfer from raw texture.
> **Do this instead**: Always use pedotransfer from HWSD sand/clay/OC to WOFOST parameters.
> See diagnostic triplet dt_009.

> **PITFALL**: Forgetting WAV (initial available water)
> WAV defaults to 0 if not set. Starting a simulation with completely dry soil can cause immediate crop death, especially for spring-sown crops.
> **Do this instead**: Set WAV to a reasonable value (10-50 cm) representing antecedent moisture. For VIC-coupled runs, use VIC soil moisture output to initialize WAV.

> **PITFALL**: Not needed for PP mode
> If running Wofost72_PP (potential production), soil parameters are ignored. Don't waste time optimizing soil params for PP runs.

---

*This skill document is part of the wofost-pcse-knowledge infrastructure.*
*Stage 2 of 8 | Tools: convert_hwsd_to_pcse_soil, validate_soil_params | Related triplets: dt_009*

Files in this skill

  • REFERENCES.md1.5 KB
  • format_spec.yaml41.2 KB
  • model_couplings.yaml14.4 KB
  • papers.json6.5 KB
  • s1_crop_params_skill.md6.9 KB
  • s2_soil_params_skill.md6.8 KB
  • s3_weather_prep_skill.md8.4 KB
  • s4_agromanagement_skill.md7.1 KB
  • s5_engine_config_skill.md5.8 KB
  • s6_execution_skill.md5.9 KB
  • s7_output_parsing_skill.md5 KB
  • s8_yield_analysis_skill.md6.5 KB
  • validation_convention.yaml22.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…