Constraints¶
1. Mutual exclusion constraints¶
Most constraints ensure that at most one measure from a group can be implemented on the same field. These are essential because many measures occupy the same land or are agronomically incompatible.
Core field exclusion (mutexc1)¶
Only one measure from the mem set can be selected per field. mem includes nearly all field measures except LRl.
Core field exclusion with LRl (mutexc3)¶
mem2 is the same as mem but replaces LRh with LRl. Also accounts for any permanent VP2 measures already on the field (x_VP2_p).
Land use accounting (mutexc4, mutexc5, mutexc6)¶
These define and enforce me(i), an indicator that counts whether a land-retirement type measure is in use:
mutexc4(i).. me(i) =e= Sum(lr1(j), x(i,j) + x_VP2_p(i,j)) + Sum(lr2(j), x(i,j) + x_VP2_p(i,j)) / 2
mutexc5(i).. Sum(lm(j), x(i,j)) + me(i) ≤ 1 [land management measures cannot co-exist with land retirement]
mutexc6(i).. Sum(bz(j), x(i,j)) + me(i) ≤ 1 [buffer zones cannot co-exist with land retirement]
lr1 = WL, FO (full land retirement); lr2 = LRl, LRh (land retirement counted at 50% in me).
WWT mutual exclusion (mutexc8)¶
Only one WWT upgrade level per plant.
IBZ-specific exclusions (mutexc10–mutexc17)¶
IBZ (in-stream buffer zone) has the most exclusions of any measure. It cannot co-exist with: - BZ10 or BZ20 (10, 11) - LRh or LRl (12, 13) - WL (16) - FO (17) - VP2 WL or FO (14, 15) - VP2 LRl (7)
Stream measure exclusion (mutexc18)¶
A watercourse cannot have both re-meandering and bed raising.
VP2 LRl double-counting prevention (LRl_VP2)¶
2. Tripartite Agreement area floors¶
These constraints encode the 2021 Danish Tripartite Agreement minimum implementation areas. They are always active in the current model. exceed_lav is a penalty variable allowing the lavbund floor to be soft when physical potential is insufficient. The MW, FO, WL, LRH, and SA floors are hard constraints (exceed_MW was removed from the model — confirmed 2026-04-06):
Lavbund_eq.. Sum(i, PotV(i,"LRL") × x(i,"LRL")) + exceed_lav ≥ 51,000 [ha]
Afforestation_eq.. Sum(k$(n_targets(k)>0), Sum(i$setki(k,i), PotV(i,"FO") × x(i,"FO"))) ≥ 28,000 [ha]
Wetland_eq.. Sum(k$(n_targets(k)>0), Sum(i$setki(k,i), PotV(i,"WL") × x(i,"WL"))) ≥ 7,500 [ha]
MW_eq.. [sum of MW areas in catchments with N targets] ≥ 40,000 [ha equivalent]
LRH_eq.. Sum(k$(n_targets(k)>0), Sum(i$setki(k,i), PotV(i,"LRH") × x(i,"LRH"))) ≥ 17,700 [ha]
SA_eq.. Sum(k$(n_targets(k)>0), Sum(i$setki(k,i), PotV(i,"SA") × x(i,"SA"))) ≥ 84,000 [ha]
Scope: Afforestation, Wetland, MW, LRH, and SA floors apply only to catchments with N targets (n_targets(k)>0). The lavbund (LRl) floor is nationwide.
See Tripartite Agreement for policy background.
3. P wetland vs. stream measure constraints¶
A P wetland (PWET) on field i and a stream restoration measure (re-meandering or raising) on adjacent watercourse w cannot both be implemented. This is encoded via the binary indicator s(w):
Pwet1_eq(w).. s(w) ≥ Sum(w_Pwet(w_m), v_w(w,w_m)) [s = 1 if stream measure chosen]
Pwet2_eq(w,i)$wi_pwet.. x(i,"Pwet") + s(w) ≤ 1 [PWET excluded if stream measure]
Pwet3_eq(w).. Sum(w_Pwet(w_m), v_w(w,w_m)) ≥ s(w) [s = 0 if no stream measure]
Additionally, total P reduction from P wetlands is capped at total P loss in the upstream lake catchment:
P_Wet_limit_eq(up_lakecatch)..
Sum(i$up_lake_i, P_Effects_Total(i,"Pwet") × x(i,"Pwet")) ≤ Total_P_loss(up_lakecatch)
4. VP2 legacy constraints¶
Results from Water Action Plan 2 (VP2) are loaded as fixed parameters:
- x_VP2_p(i,j) — binary, 1 if field i had measure j implemented in VP2
- MW1x_VP2_p, MW2x_VP2_p, MW3x_VP2_p — VP2 mini-wetland decisions
These are used in:
- mutexc3: VP2 permanent measures block re-use of the same field
- LRl_VP2: prevents double implementation of LRl
- mutexc7, 14, 15: IBZ exclusions with VP2 WL, FO, LRl
- MW potential cap: VP2_adapt(ret) = max(MW_precalc2(ret), VP2MW_per_ret(ret)) ensures VP3 MW does not overclaim relative to VP2 baseline
See VP2 & VP3.
5. Mini-wetland potential cap¶
Where:
- MW_precalc1(ret) = total MW area chosen in VP3 (including VP2 MW)
- VP2_adapt(ret) = max(MW_precalc2(ret), VP2MW_per_ret(ret))
- MW_precalc2(ret) = natural potential (from MiniPot files: dark green + 10% light green + 10% dark yellow)
- VP2MW_per_ret(ret) = VP2 implemented area
Only VP3 new MW is counted against the potential for additonality: MW_precalc1_noVP2 tracks new VP3 decisions only.
Commented-out scenario constraints¶
The model code contains several commented-out constraint blocks that represent alternative scenario configurations. These are important design history:
* x.UP(i,j) = 0; [turning off all measures, then selectively enabling by P-loss percentile]
* Scenario_pho_eq: limit P measures to 75% of potential in each lake catchment
* Scenario_ochre_eq, sand_eq, etc.: limit stream measures to 75% of count
* Effectiveness_limit(i,j): exclude field-measure combos with cost-effectiveness > 50,000 DKK/kg P
These represent scenarios that were tested but are not the default. Each could be re-activated for specific scenario runs.
Open questions¶
- ✅
exceed_MWconfirmed removed from model (2026-04-06). MW_eq is a hard constraint. Onlyexceed_lavremains as a penalty variable (lavbund floor can be soft if physical potential is insufficient). - The scope condition
n_targets(k)>0on tripartite constraints — does this mean the area floors only apply in catchments that have N targets? Is this correct policy-wise? - The 75% potential scenario constraints (Scenario_pho_eq, etc.) — under what policy assumption would these be activated?