
Build source-exact gridded critical-nitrogen exceedance.
Source:R/n_boundary_exceedance.R
build_n_boundary_exceedance.RdCompares WHEP crop nitrogen pressure with the deposited Schulte-Uebbing et al. (2022) 2010 yield-gap critical surface. The calculation first aggregates every crop and polity contribution in a source cell, compares that one cell pressure with one critical allowance, and only then attributes the cell allowance, signed margin and positive overshoot back to crops. Total-input attribution uses crop input shares; surplus attribution uses signed crop surplus shares. Signed surplus shares can be negative or greater than one.
The critical layer must carry its deposited source_area_ha and
image_region. resolution = "cell" returns one row per source cell and
year. Other resolutions return the approved crop attribution. Exactly zero
or numerically near-zero pressure denominators keep the complete cell result
but allocate no crop share; an explicit cell_residual record carries the
unallocated critical allowance, signed margin and positive overshoot. APIs
requiring complete crop attribution hard-error rather than fabricate a
fallback.
Actual-pressure rows naming no crop cannot meet a critical allowance and are
excluded before the cell comparison. The exclusion is reported, never
silent: a message names the rows and the pressure they carried when that
pressure is zero (the only case a gridded build_nitrogen_balance()
produces), and a warning when it is not.
Usage
build_n_boundary_exceedance(
surplus = NULL,
critical = NULL,
land_use = c("ara", "all", "igl"),
resolution = c("grid", "cell", "polity", "country", "image_region"),
metric = c("surplus", "input", "new_fixation"),
cell_polity = NULL,
allocation_scenario = c("yield_gap", "no_increase", "new_fixation"),
actual_year = NULL,
critical_reference_year = NULL,
actual = NULL,
boundary = NULL,
indicator = NULL,
land_class = NULL,
impact_scope = NULL,
grassland_split = c("image_density", "none"),
grassland = list(classes = NULL, extensive_budget = NULL, critical_ara = NULL,
critical_igl = NULL),
negative_critical = c("keep", "clamp"),
regime_comparison = c("netted", "separate"),
binding = NULL,
example = FALSE
)Arguments
- surplus
A
calculate_n_surplus()output with the grid/crop/year key. Surplus mode uses signedsurplus_n_twhen present, otherwise derives it fromsurplus_kgn_ha * area_ha / 1000. Input mode usesn_input_std_t.- critical
A
read_critical_n()critical layer. In addition to layer identity, it must carry depositedsource_area_haandimage_region.- land_use
Source land class:
"ara","igl", or"all".- resolution
Output grain: source
"cell", crop-cell"grid", crop"polity"/"country", or crop"image_region".- metric
Selected actual pressure: signed
"surplus"or total agricultural"input".- cell_polity
Retained for API compatibility. IMAGE membership now comes from the deposited cell-key crosswalk in
critical; country attribution comes from the crop rows themselves.- allocation_scenario
Only source-exact
"yield_gap"is supported."no_increase"and"new_fixation"hard-error.- actual_year
The actual-pressure year to compare. Must select exactly one year from
surplusand is always retained in results.- critical_reference_year
Must be
2010, matching the deposited fixed reference surface, and is always retained in results.- actual
Alias of
surplusfor the selector-oriented interface.- boundary
Alias of
criticalfor the selector-oriented interface.- indicator
Selector-oriented pressure name:
"surplus","total_input", or the unsupported"new_fixation"mode (which hard-errors). When supplied, it overridesmetric.- land_class
Alias of
land_use.- impact_scope
Deposited impact surface:
"mi","sw","gw", or"de". When supplied, it is validated against the critical layer.- grassland_split
Grassland treatment under
land_use = "all":"image_density"(default) splits each cell into a managed and an extensive component (see the section below);"none"compares one cell pressure with the deposited allowance, as before the split existed. Ignored for"ara"and"igl". Under"image_density",metric = "new_fixation"aborts: the archive has no extensive budget for it.- grassland
Named list of the inputs the split needs, all required under
grassland_split = "image_density"(their absence aborts; there is no fallback):classes, thebuild_grassland_intensity_classes()table (one row per cell and year:cell_id,lon,lat,year,country_2010,image_region,a_crop_ha,grass_ha_image,whep_grass_ha,image_class_2010,grassland_class,method_grassland_split), andextensive_budget, IMAGE's 2010 extensive-grassland budget per cell (cell_id,ext_input_kgn_ha,ext_surplus_kgn_ha); andcritical_araandcritical_igl, theread_critical_n()layers withland_use = "ara"and"igl"for the same threshold and metric ascritical(validated).criticalitself still defines the cell domain and is checked against the class table's areas. A cell absent fromclassesmust carry no grassland pressure; it is compared as cropland only.- negative_critical
Treatment of a cell whose critical value is below zero.
"keep"(default) compares the actual pressure with the deposited value as it is, as the source does."clamp"sets it to zero (a zero allowance) before the cell comparison. The choice is stamped in every output row asnegative_critical; see the Negative critical surplus section.- regime_comparison
Treatment of a balance split into rainfed and irrigated rows (
build_nitrogen_balance()'smethods$regime)."netted"(default) sums the two regimes of a cell before the comparison, so irrigated excess is offset by rainfed headroom in the same cell."separate"compares each regime as its own part of the cell (or of the grassland-split component), so it is not offset. It needs awater_regimecolumn insurplusand aborts without one. The choice is stamped in every output row asregime_comparison; see the Rainfed and irrigated parts section.- binding
Optional
build_critical_n_binding()output for the same land-use scope. When supplied, its per-cellbinding_thresholdandbinding_matches_miare carried into the cell and grid results; whenNULL(default) both columns areNA.- example
If
TRUE, return the package fixture.
Value
A tibble at the requested grain. Cell results retain actual and
critical masses, signed margin, positive overshoot, coverage state,
integer source-grid key, IMAGE context, explicit years, selectors, and
provenance. critical_kgn_ha is the value compared (after the
negative_critical treatment) and source_critical_kgn_ha the deposited
one; the two differ only in clamped cells. Crop results additionally
retain the signed pressure share and crop-attributed quantities, which
reconcile algebraically to the cell. exceedance_n_t is the crop's share
of the cell overshoot pmax(actual - critical, 0) and
within_boundary_n_t is actual_n_t - exceedance_n_t, so the two always
sum to the actual pressure. Summed over a cell, within_boundary_n_t is
min(actual, critical): under negative_critical = "keep" it is negative
wherever the critical value is negative, and under "clamp" it is
negative only where the actual pressure itself is. Under the grassland
split these hold per component (managed, extensive) rather than per cell.
Cell and grid results also carry the split components:
managed_actual_n_t, managed_critical_n_t,
managed_positive_overshoot_n_t, extensive_actual_n_t,
extensive_critical_n_t, extensive_positive_overshoot_n_t, their areas
(managed_area_ha, extensive_area_ha), compared rates
(managed_critical_kgn_ha, extensive_critical_kgn_ha, after the
negative_critical treatment) and the rates before it
(source_managed_critical_kgn_ha, source_extensive_critical_kgn_ha),
coverage states, excluded_actual_n_t (of which
excluded_igl_actual_n_t is intensive grassland without an "igl"
rate), grassland_class, method_allowance_managed,
method_allowance_extensive and method_grassland_split (the per-cell
class method, "no_grassland" for a cell outside the class table,
"none" without the split). These are NA when the split is not
applied, so the schema does not depend on it. Under the split,
critical_kgn_ha and source_critical_kgn_ha remain the "all"-scope
surface (it defines the domain and checks the "ara"/"igl" layers);
the cell allowance is the sum of the component allowances. Grid rows add
boundary_component ("managed"/"extensive", NA without the
split); within the split, pressure_share is the row's share of its
component, and binding_threshold/binding_matches_mi are NA on
extensive rows (see the Negative critical surplus section). Every row
carries the call-level grassland_split; aggregated rows list the
per-cell methods they span in method_grassland_split, separated by ;.
Grassland intensity split (land_use = "all")
The deposited all-scope critical rate is per hectare of cropland plus
IMAGE-intensive grassland, while WHEP's pressure covers all grassland. With
grassland_split = "image_density" (the default) each cell is compared as
two independent components:
managed – crop rows plus grassland rows (CBS 3000, 3002, 3003) of a cell classed intensive, against the cell's own
"ara"critical rate times its IMAGE 2010 cropland plus, when the cell is classed intensive, an"igl"critical rate times its IMAGE 2010 grassland. The deposited per-hectare"ara"and"igl"layers combine exactly into the"all"layer (area-weighted, measured on the archive for every threshold and both metrics), so with the IMAGE 2010 classes this reproduces the"all"-scope allowance;extensive – grassland rows of a cell classed extensive, against IMAGE's 2010 extensive-grassland input or surplus per hectare (Schulte-Uebbing et al. 2022, SI Supplementary Table 4) times the cell's IMAGE 2010 grassland.
Cell overshoot is the sum of the two component overshoots: headroom on
one never nets against excess on the other. Cell actual, critical and
margin are the sums over the compared components. A component with no
allowance area but non-zero pressure (in practice crop pressure where IMAGE
has no cropland and the cell is extensive) is excluded from its comparison
(managed_coverage_state/extensive_coverage_state "zero_land"); a
component with area but no rate even after transfer is
"missing_critical". Excluded pressure is reported per cell in
excluded_actual_n_t and in a message (classes
whep_nbx_zero_land_component, whep_nbx_missing_critical_component),
and never counts as overshoot. Crop attribution shares each component's
allowance, margin and overshoot among that component's rows only, and
reconciles to the component and to the cell. A compared component with
allowance area but no pressure row keeps its allowance in a
cell_residual record naming the component.
Declared assumptions (constructed methods without published precedent):
the classes are IMAGE's 2010 production-system map moved through time by a
national grazing-density proxy (see grassland$classes); the extensive
allowance is IMAGE's 2010 budget held constant – "no more than in 2010",
not an environmental limit, so 2010 extensive exceedance is zero wherever
WHEP's 2010 extensive pressure equals IMAGE's; a rate a cell lacks for its
class is borrowed from the nearest cell (great-circle distance) with one in
the same 2010 country, else the same IMAGE region – an "igl" rate for
grassland promoted from extensive to intensive, an extensive budget rate
for grassland classed extensive; cropland keeps its own "ara" rate and
is never lent one – stamped in
method_allowance_managed/method_allowance_extensive
("archive", "nearest_country", "nearest_region", "none", or
"no_area" for a component without area; NA outside the critical
domain). IMAGE 2010 intensive grassland with no published "igl" value
is not lent one (maintainer decision 2026-09-24): its pressure is left out
of the comparison and reported in excluded_igl_actual_n_t, the cell's
cropland is still compared at its own "ara" rate, and the managed method
is "none". Allowance areas are IMAGE 2010
areas, fixed, except WHEP grassland in a cell with no IMAGE grassland,
whose extensive allowance uses WHEP's own grassland area of the year
(method suffix "_whep_area", maintainer decision 2026-09-24).
grassland_split = "none" reproduces the unsplit comparison exactly.
Negative critical surplus
Schulte-Uebbing et al. (2022, Methods) set critical fertilizer and manure
inputs to zero where non-agricultural losses alone exceed a threshold, but
keep biological fixation and deposition in the critical input, so their
deposited critical surplus stays negative in those cells (on the "mi"
surface: 1,796 of 28,881 cells for "all", minimum -396 kg N/ha; 2,075 of
28,573 cells for "ara", minimum -317 kg N/ha). negative_critical = "keep" follows the source, and it is the setting under which the published
2010 decomposition (43 Mt N allowable plus 76 Mt N exceedance, 119 Mt N
current surplus) is reproduced. "clamp" is a declared departure from the
source: it gives such cells a zero allowance instead of a negative one,
which lowers their overshoot to the actual pressure and keeps the cell
within-boundary mass at or above zero wherever the actual pressure is.
Under grassland_split = "image_density" the treatment applies to each
component's allowance, the unit a component is compared against: a
negative managed allowance (the cell's "ara" rate on its cropland plus
its "igl" rate on its intensive grassland, which can net against each
other as they do inside the "all" rate) becomes zero, and so would a
negative extensive one (IMAGE's 2010 extensive budget, which is never
negative on the deposited archive). The component rates are not clamped
one by one, so with the 2010 classes the managed comparison under
"clamp" matches the unsplit "all"-scope comparison under "clamp"
(to the 1 % within which the "ara" and "igl" layers combine into
"all").
A binding threshold names the impact that sets a critical surplus, so it
describes the managed allowance only; the extensive allowance is a 2010
level, not a threshold, and its grid rows carry no binding label.
Rainfed and irrigated parts
Under regime_comparison = "separate" each comparison unit (the cell, or
under the grassland split its managed and its extensive component) is
divided into a rainfed and an irrigated part. Each part gets a share of
the unit allowance equal to its share of the unit's area_ha, summed over
its rows. The deposited critical surface has one rate per hectare and no
regime axis, so this keeps the rate the same on both regimes. It also
keeps every unit allowance, actual pressure and signed margin exactly as
under "netted". The unit overshoot becomes the sum of the part
overshoots, sum(pmax(part actual - part allowance, 0)), which is never
below the netted pmax(actual - allowance, 0). The areas are WHEP's
harvested hectares. Irrigated land is more often multi-cropped, so
harvested area can overstate the irrigated share of physical land. This is
a declared assumption with no published precedent. A unit with no
harvested area gives its whole allowance to the one part that carries
pressure, which is the netted comparison. It aborts
(whep_nbx_regime_no_area) when both parts do. Crop rows share the
allowance, margin and overshoot of their own part. They keep their
water_regime, plus that part's regime_actual_n_t,
regime_critical_n_t and regime_positive_overshoot_n_t. Cell and grid
rows add the per-cell totals rainfed_actual_n_t,
rainfed_critical_n_t, rainfed_positive_overshoot_n_t and their
irrigated_* counterparts, summed over the parts that carry pressure
rows. Under "netted" all of these are NA, so the schema does not
depend on the choice.
Examples
build_n_boundary_exceedance(example = TRUE)
#> # A tibble: 5 × 90
#> year area_code polity_area_code reporting_polity_code reporting_polity_name
#> <int> <int> <int> <chr> <chr>
#> 1 2010 1 1 ARM-1991-2025 Armenia
#> 2 2010 1 1 ARM-1991-2025 Armenia
#> 3 2010 1 1 ARM-1991-2025 Armenia
#> 4 2010 1 1 ARM-1991-2025 Armenia
#> 5 2010 1 1 ARM-1991-2025 Armenia
#> # ℹ 85 more variables: reporting_polity_has_geometry <lgl>, cell_id <int>,
#> # source_row <int>, source_col <int>, lon <dbl>, lat <dbl>,
#> # item_cbs_code <int>, water_regime <chr>, actual_year <int>,
#> # critical_reference_year <int>, area_ha <dbl>, source_area_ha <dbl>,
#> # image_region <int>, critical_threshold <chr>, binding_threshold <chr>,
#> # binding_matches_mi <lgl>, actual_n_t <dbl>, pressure_share <dbl>,
#> # pressure_condition_ratio <dbl>, critical_n_t <dbl>, …