
Assemble soil carbon inputs per cell, crop and year.
Source:R/soil_carbon_inputs.R
build_soil_carbon_inputs.RdBuilds the carbon returned to soil from crop residues, crop roots, weeds and
applied manure, as the carbon-input layer the soil-organic-carbon turnover
models (calculate_soc_dynamics()) consume. Soil-returned residue carbon
(residue net of the fraction removed for feed, fuel and burning), root carbon
and weed (spontaneous-grass) carbon come from
calculate_npp_carbon_nitrogen() (per polity, crop and year); manure carbon
comes from build_livestock_nutrient_flows()'s applied stream. The four
component carbon masses are converted to megagrams of carbon (1 tonne =
1 Mg), gridded to cells in proportion to each crop's harvested area, and
divided by the cell-crop area to give Mg C per hectare per year. A
carbon-weighted humification fraction is computed per cell-year from
residue_humification, with the weed carbon humified at the weed
(spontaneous-grass) coefficient.
The weed stream is structurally present but ZERO on the default path: the
turnkey chain runs calculate_crop_npp() and
calculate_npp_carbon_nitrogen() without calculate_crop_npp_components(),
which is the only producer of weed_ag_dm_t, so weed carbon is zero for
every crop, polity and year unless data$npp is supplied from a chain that
includes it. Whether to wire it into the default path is open (whep#806);
until then the zero is reported rather than passed off as computed.
At "polity" resolution the component carbon masses are summed back to
(area_code, item_prod_code, year) and the per-hectare values and humified
fraction re-derived from the polity totals.
Arguments
- resolution
"grid"(default, per cell) or"polity"(aggregated toarea_code).- data
Optional named list of pre-loaded inputs, each falling back to its reader when absent:
npp(soil-returned residue, root and weed carbon perarea_code,item_prod_code,year, columnsresidue_soil_c_t,root_c_tandweed_npp_c_t, tonnes C);manure(theappliedtibble ofbuild_livestock_nutrient_flows(), withcropeither an existingitem_prod_codeor anitem_prodname from items_prod_full (matched case-insensitively), andterritorya stringifiedarea_code– aniso3cliteral is still resolved but deprecated, seeestimate_n_excretion());country_grid, the polycell support resolved to one row per cell andarea_code(lon,lat,area_code,cell_area_frac, the polycell's share of the cell's land), refused when a cell-area_codegroup is duplicated orNA(DA-23);crop_patterns(the static per-cellcrop_area_halayer, read only undermethod_crop_weights = "static");gridded_crops(the crop-levelbuild_gridded_landuse()output on the samecountry_gridsupport,lon,lat,area_code,item_prod_code,year,rainfed_ha,irrigated_ha, read only under"spatialized"and built from the pinned spatialization inputs when absent);harvested_area(the FAOSTAT national harvested area perarea_code,item_prod_code,yearin afaostat_area_hacolumn, used to renormalize each polity-crop-year's spatialized cell area to the national total so per-hectare densities are the national density and carbon mass is conserved; defaults to the sameget_primary_production()table the NPP reader uses, and is skipped when a hand-suppliednppkeeps the pipeline offline unless supplied here);residue_humification(defaults to residue_humification);fodder_patterns(only read undermethod_unspatialized = "fodder_pattern": per-cell fodder crop area in thecrop_patternsschema, defaulting to the pooled Monfreda et al. (2008) forage layer from thespatialize-fodder-patternspin, or rebuilt from the rasters underWHEP_MONFREDA_DIRwhen that is set).- years
Optional integer vector of calendar years to keep.
NULL(default) keeps every year the inputs cover. Threaded into the default NPP and manure readers so they slice to the requested years; ignored for inputs supplied viadata.- method_unspatialized
What happens to a polity-crop whose crop has no hectares in the (time-invariant)
crop_patternslayer."fodder_pattern"(default) first places the fodder crops (FAOSTAT items 636-649, 651 and 655) on the pooled 16 forage layers of Monfreda, Ramankutty and Foley (2008, doi:10.1029/2007GB002947 ), which the crop-pattern pin omits, gridded exactly as a crop-pattern crop is. The layers are pooled because the per-item ones follow the circa-2000 reporting vocabulary, not where each item is grown later. Whatever the layer still cannot place is reallocated as under"reallocate". The layer is read from thespatialize-fodder-patternspin (built byinst/scripts/prepare_fodder_patterns.R); settingWHEP_MONFREDA_DIRto theHarvestedAreaYield175Crops_Geotifffolder of the Monfreda archive (inst/scripts/download/download_monfreda.R) rebuilds it from the rasters instead, anddata$fodder_patternsreplaces it. It aborts rather than falling back to uniform reallocation when the layer is empty or a setWHEP_MONFREDA_DIRis wrong. The layer codes are matched on the layer names, as the archive's metadata gives no FAO name for them (assumed, unverified against a Monfreda table). At 2010 it moves 83.6 Mt C between cells relative to"reallocate", with polity totals unchanged."reallocate"spreads that carbon over the polity's crop-pattern cropland cells in proportion to each cell's total cropland area, and puts it on the crop's FAOSTAT national harvested area, so the polity's gridded carbon mass equals its national mass; this is the rule the sibling nitrogen spatialization already applies to the same gap (spatialize_country_n_to_crops()), and was the default before whep#1118."drop"discards it, which is what the package did before and what a caller who prefers a hole to a smear should ask for. Either way the mass and the affected crops are reported, and the choice is recorded inmethod_unspatialized. Reallocation needs a national area to put the carbon on, so a polity-crop with noharvested_arearow – and a polity with no cell at all in the support, which no rule here can reach (see whep#1002) – is dropped under all three methods, reported separately. Under eithermethod_crop_weights, the fodder layer only fills the polity-crops that year's crop weights do not place, and the 83.6 Mt C figure above was measured on the static weights.- method_crop_weights
Where each crop's within-polity cell weights come from.
"spatialized"(default) takes them from the spatialization engine's crop-level output,build_gridded_landuse()run on the pinned spatialization inputs and the same cell support, year by year: the crop's placement follows that year's cropland, its irrigated share and the engine's per-cell capacity ceiling, so the carbon lands where the gridded land use puts the crop.data$gridded_cropssupplies that output pre-built."static"uses the time-invariantcrop_patternslayer (harvest_fractiontimes each cell's cropland averaged over every year of the gridded-cropland pin), one map for every year, which is what the package did before (whep#1002). Measured on the pins, the L1 distance between the two cell-share vectors of a polity-crop (0 = same placement, 2 = disjoint) has an area-weighted mean of 0.30 in 1961, 0.44 in 2010 and 0.47 in 2020. Polity totals are the same under both; only where the carbon sits moves. Recorded inmethod_crop_weights.- method_manure_placement
Where the cropland manure carbon is put.
"livestock"(default) places it where the animals are, the grain the gridded nitrogen balance uses for the same manure (whep#1300): the feed intake is spread to cells by gridded livestock heads oncountry_grid(the local grain ofbuild_feed_intake_local()), andbuild_livestock_nutrient_flows()runs at"subnational", so each cell's collected manure goes to that cell's crops up to the 170 kg N/ha ceiling and the excess is trucked to neighbouring cells with room. Its crop layer is that year's cell-crop area, the hectares the carbon is divided by. Manure with no crop – trucked in, or over-applied above the cap – is spread over its cell's crops by area, as the nitrogen balance spreads it, and manure on a cell with no crop over its polity's cropland; only a polity with no cropland cell loses it, with a warning. Measured at 2010, it places 322.1 Tg C of cropland manure where"crop_area"places 346.9 Tg C, because the cell-grain intake caps grazing at each cell's grass; 41.5% of the manure carbon sits on a different cell."crop_area"allocates the polity's manure to its crops by harvested area and fans each polity-crop out to cells by crop area, as residue and roots are, which is what the package did before (whep#1307); it drops the over-cap manure the national allocation leaves with no crop (whep#805). A supplieddata$manuremust be keyed on cells (sub_territorya"lon_lat"cell id) under"livestock"; a national stream aborts. Recorded inmethod_manure_placement.- example
If
TRUE, return a small fixture instead of reading remote data. Defaults toFALSE.
Value
A tibble keyed by (lon, lat, area_code, item_prod_code, year) at
"grid" resolution (or (area_code, item_prod_code, year) at
"polity"), with residue_c_mgc_ha_yr, root_c_mgc_ha_yr,
weed_c_mgc_ha_yr, manure_c_mgc_ha_yr, total_c_input_mgc_ha_yr,
input_cn (the C:N of the components whose nitrogen is known),
input_n_mgn_ha_yr (their nitrogen, Mg N per hectare per year, so
input_cn times it is their carbon), residue_n_mgn_ha_yr and
root_n_mgn_ha_yr (the soil-returned residue and root nitrogen within
it, NA where unknown), humified_fraction, method_c_input,
method_unspatialized, method_crop_weights, method_manure_placement
and
crop_area_ha – the crop's area at that grain on the basis the
densities are computed on: the FAOSTAT-renormalised cell area where a
national harvested area was supplied, the spatialized area otherwise, so
a consumer can recover the carbon mass without re-deriving it – plus the
polity columns below.
Polity columns
Every area-keyed output carries the polity its area_code resolves to in
that row's year:
polity_area_code: The numeric key rows are AGGREGATED on, for the matrix workflows. It is a bucket, not an identity: usereporting_polity_codeto say which territory a row belongs to.reporting_polity_code: The polity itself, e.g.ESP-1846-1914. It is year-aware, so the samearea_coderesolves to different polities in different years, which is the point of the crosswalk.reporting_polity_name: Its name. It can differ from the area's own name where the area folds into an aggregate.reporting_polity_has_geometry: Whether the polity has a polygon in the WHEP polity database, for callers that need to map or intersect it.FALSEis a documented gap upstream, not an error.
Rows whose area_code resolves to no polity keep the columns with NA
rather than being dropped, so a gap is visible instead of silent.
Rows before the back-cast anchor year resolve to the polity live in that
anchor year rather than to the polity live in the row's own year, because
WHEP's pre-anchor series are back-cast onto the anchor-year territory. See
add_polity_code() for the reasoning. Where that polity is not live in the
row's own year – 41.5% of the pre-1961 (area, year) cells –
add_polity_code() says so as mapping_status == "backcast_anchor", and
polity_coverage_gaps() reports it as gap_kind == "backcast_anchor".
These columns do not say so either way.
A row whose year no mapped period covers is resolved to the NEAREST period of
the same area instead, so reporting_polity_code can name a polity that did
not exist in that row's year – FAOSTAT bucket 206 "Sudan (former)" keeps
reporting after SUD-1956-2011 ends, and its post-2011 rows carry that code.
These columns do not say so: add_polity_code() reports such a row as
mapping_status == "out_of_span", and that column is dropped here so that
adding it does not change the schema of every area-keyed output at once.
polity_coverage_gaps() reports the stand-in rows of a built table, and
options(whep.polity_mapping_status = "flag") (or "status") carries the
signal on the outputs themselves. Both are opt-in; the default is no extra
column.
Examples
build_soil_carbon_inputs(example = TRUE)
#> # A tibble: 4 × 20
#> year area_code polity_area_code reporting_polity_code reporting_polity_name
#> <int> <int> <int> <chr> <chr>
#> 1 2020 1 1 ARM-1991-2025 Armenia
#> 2 2020 1 1 ARM-1991-2025 Armenia
#> 3 2020 1 1 ARM-1991-2025 Armenia
#> 4 2020 1 1 ARM-1991-2025 Armenia
#> # ℹ 15 more variables: reporting_polity_has_geometry <lgl>, lon <dbl>,
#> # lat <dbl>, item_prod_code <chr>, crop_area_ha <dbl>,
#> # residue_c_mgc_ha_yr <dbl>, root_c_mgc_ha_yr <dbl>, weed_c_mgc_ha_yr <dbl>,
#> # manure_c_mgc_ha_yr <dbl>, total_c_input_mgc_ha_yr <dbl>,
#> # humified_fraction <dbl>, method_c_input <chr>, method_unspatialized <chr>,
#> # method_crop_weights <chr>, method_manure_placement <chr>