Forest carbon growth-curve update, other-planted forest pool, and satellite forest ages - #917
Draft
flohump wants to merge 10 commits into
Draft
Forest carbon growth-curve update, other-planted forest pool, and satellite forest ages#917flohump wants to merge 10 commits into
flohump wants to merge 10 commits into
Conversation
MAgPIE derived a forest's carbon stock and its harvestable wood from a single growth curve, so the FRA growing-stock (wood) calibration bent the carbon curve. This keeps one realistic carbon curve for all forest and meets the FRA wood target with a per-region, wood-only multiplier (lambda); carbon is never bent. - 52_carbon: replace the k-bisection calibration with an analytic wood-only lambda (natural forest weighted by the GFAD age distribution, plantations sampled at the cellular rotation age). Carbon densities keep the realistic three-curve growth parameters for naturally regenerating / other planted / plantation forest (f52_growth_par_3curve.csv). Add a wood-only niche floor for arid divide-by-near-zero cells (s52_gs_niche_floor). - 14_yields: scale the growing stock by lambda before the harvest floors; carbon is untouched. - 35_natveg: remove the natural-origin carbon blend and the natural-origin harvest floor (collapse to the single realistic curve); keep the WDPA conservation floor. Keep the ac35 young-secondary proxy. - 32_forestry: other-planted forest becomes its own harvestable pool; the plantation rotation comes from an external per-Koeppen table (f32_plant_rotation.cs4) and the curve-derived rotation machinery (CAI/MAI/Faustmann) is retired. - 28_ageclass: add GAMI v2.1 (Besnard et al. 2024) as an age-class source option (c28_ageclass_source, default gami); the GFAD path is unchanged. - 56_ghg_policy: remove the minimum C-price floor (s56_minimum_cprice = 0), which had suppressed historical deforestation. Input data ship via additional_data (f52_growth_par_3curve.csv, f32_plant_rotation.cs4) and the preprocessing pipeline (forestageclasses_gami.cs3).
…s realization Merging develop brought in the new dynRegPastrTau_apr26 realization of module 14, which was branched from the pre-decouple managementcalib_aug19 and so still built the harvestable growing stock the old (coupled) way: it computed im_growing_stock_ysf from the uncalibrated secondary-forest curve and applied no wood-only lambda. Mirror the decoupled wood block from managementcalib_aug19 into it so both realizations of module 14 provide the same wood interface: scale the harvestable growing stock by the module-52 multipliers (pm_lambda_pla / pm_lambda_nrf) and the niche floor (pm_gs_niche_fac), and compute im_growing_stock_oplant for the other-planted pool. Carbon densities are untouched. Without this, running yields = dynRegPastrTau_apr26 would leave wood coupled to carbon and reference im_growing_stock_oplant (consumed in module 32) without computing it.
The decouple's forestry inputs ship through the input-data pipeline: rev4.133 (regional/cellular/validation) carries the FRA2025 forest data and the GAMI age-class dataset; additional_data rev4.68 carries the three-curve growth parameters (f52_growth_par_3curve.csv) and the plantation rotation lengths (f32_plant_rotation.cs4). Note: rev4.133FH is an interim personal preprocessing build; re-point to the official published revision before merge.
setScenario reads config/scenario_config.csv to set the per-rcp cellular input tarball, overriding cfg$input in default.cfg. Bump its cellular row from rev4.131 to rev4.133FH so it is consistent with the input-data revision already committed to default.cfg (the config-hash is invariant across revisions, only the prefix changes). Note: rev4.133FH is an interim personal preprocessing build; re-point to the official published revision before merge (same as default.cfg).
… selectable The observation-based 3-curve refit is the default (refit). Setting c52_growth_par_source = braakhekke selects the legacy Braakhekke et al. 2019 curves; since those predate the other-planted forest type, other_planted falls back to the naturally regenerating (natveg) curve. This uses the old curve shape within the new (decoupled) framework, not a full revert.
The rev4.133 input data (mrland R36M414 coupled REMIND-MAgPIE runs) adds new GHG-price and 2nd-gen bioenergy-demand scenarios. Regenerate the ghgscen56 (56) and bioenergy-demand (60) scenario sets from the distributed input so they list the new R36M414-* scenarios; existing R34M410-* scenarios are unchanged.
The forestry land-split mapping only covered {aff, ndc, plant}. With the new
other_planted forestry pool, landForestry() returns a fourth pool that was not in
the mapping, so toolAggregate aborted the forestry disaggregation and cell.land_split
was never written (breaking the gridded reportPBland/reportPBbiosphere/reportBII).
Fold other_planted into the NPiNDC grid category, consistent with the develop-branch
land split (where it was part of the ndc pool).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🐦 Description of this PR 🐦
This PR replaces MAgPIE's modelled forest growth curves with observation-based ones, adds an "other planted" forest pool matching the FRA 2025 taxonomy, and adds a satellite forest-age dataset — together with the mechanism change that lets a realistic carbon curve coexist with the FRA wood calibration.
1. Observation-based forest growth curves
MAgPIE's forest carbon growth curves are currently a process-model output (Braakhekke et al. 2019). This PR replaces them with observation-based curves, one per forest type — naturally regrowing forest (Robinson et al. 2025, global regrowth data), timber plantations (Bukoski et al. 2022, global plantation-plot database), and other planted forest (new curve, derived from the naturally-regrowing one). They grow faster and more realistically in the early decades, especially plantations and boreal forest; the mature-carbon level (asymptote) is unchanged — only the growth shape. (central figure below) The legacy Braakhekke curves remain selectable via
c52_growth_par_source = braakhekke(other-planted forest, which those curves predate, then falls back to naturally regenerating forest). Note this applies the old curve shape inside the new framework — a sensitivity option, not a full revert to develop's behaviour.2. Other-planted forest as its own pool
The FRA 2025 taxonomy distinguishes naturally regenerating → other planted → plantation forest. This other-planted forest — the planted forest present at model initialisation that is not an intensive plantation — already existed in MAgPIE, but it was not harvestable and was wrongly assigned to the NPI/NDC afforestation category (a policy-afforestation label, not an observed forest type). This PR promotes it to its own harvestable pool with its own growth curve, correctly separated from policy-driven afforestation. Planted forest is now split into
Timber(plantations) andOther Plantedacross the land pools, reporting, and validation.3. Satellite forest ages (GAMI)
The forest age-class distribution sets how much young vs. mature forest the model starts with — and therefore how much regrowth carbon it can credit. It currently comes from GFAD (Poulter et al. 2019). This PR adds the GAMI global forest-age dataset (Besnard et al. 2024, satellite-derived) as the new default age-class source (
c28_ageclass_source); GFAD remains selectable (c28_ageclass_source = gfad). Globally the two carry the same total forest area but a different age shape: GFAD is strongly bimodal (most forest in the youngest 0–10 yr class or the >140 yr old-growth pool), while GAMI shifts area toward the middle age classes. (comparison figure below) Shipped via pik-piam/mrmagpie#66.4. Separating the wood calibration from the carbon curve
One growth curve currently sets both a forest's carbon and its harvestable wood, and its rate was tuned (k-bisection) so the wood matched the FRA growing-stock (timber) target — bending the carbon curve to fit a wood target. This PR keeps one realistic carbon curve for all forest and meets the FRA wood target separately, with a per-region wood-only multiplier on the harvestable growing stock; carbon is never touched. Across the 12 regions this multiplier stays order-one — 0.5–3.3 for naturally regrowing forest and 0.3–1.6 for plantations — with a single arid outlier (MEA, which has almost no forest: 8.3 and 3.6). It reconciles the realistic-curve growing stock with the regional FRA timber target, not a large or arbitrary rescaling. That makes the old work-arounds obsolete — the k-bisection calibration, the "natural-origin" secondary-forest blend and harvest floor, and the young-secondary-forest harvest loophole.
5. Plantation rotation from an external table
Plantation harvest rotation used to be derived from the growth curve itself, via the current-annual-increment (CAI) criterion — cut at the age where the curve's annual increment peaks. That only worked while a single curve stood in for both a stand's carbon and its merchantable wood. Two reasons it no longer does: (i) the optimal age to cut a plantation is set by the growth of its merchantable wood volume, and total biomass carbon accumulates on a different shape and timescale than merchantable stem volume, so the carbon-increment peak is not the wood-increment peak; and (ii) once wood is calibrated separately from carbon (point 4), the carbon curve carries no wood signal left to optimise a rotation against. Rotation is therefore now an explicit input — a per-Köppen table of plantation rotation lengths (
f32_plant_rotation.cs4; ~15 yr tropical, ~30 temperate, ~60 boreal) that sets both the cellular and regional rotation directly, consistent with the FAO-validated ranges reported by Mishra et al. 2021.6. Removed the minimum carbon-price floor
MAgPIE applied a small floor to the carbon price in every timestep (
s56_minimum_cprice, 3.67 USD/tC) to dampen sudden year-to-year jumps in carbon-stock change. As a side effect, that floor suppressed historical deforestation. This PR sets it to 0, giving more realistic historical land-use change. The jump-damping the floor provided is now handled in reporting instead, by the legacy land-clearing reframe in magpie4 (which spreads land-clearing emissions over a decay tail — see the companion PR below). ⚠ This changes calibrated historical land-use change — flagged for review.Input data: ships as preprocessing rev4.133 (FRA2025 forest data + the new growth curves via additional_data; GAMI ages via mrmagpie).
Validation: compiles clean (
codeCheck); 4 test runs (develop vs. this PR × NPi + PkBudg650) solve to 2100. The realistic curves roughly triple the mid-century land-carbon sink under mitigation (PkBudg650, 2050: −5.4 vs −1.7 GtCO2/yr).Companion PRs:
Suggested label: High risk (changes a model default and a core mechanic).
Figures
Comparison, develop vs. this PR:
🔧 Checklist for PR creator 🔧
If a point is not applicable, check the checkbox anyway and write "non-applicable" next to the checkbox.
Label pull request from the label list.
Self-review own code
magpie4R library has been updated accordingly and backwards compatible where necessary.scenario_config.csvhas been updated accordingly (important ifdefault.cfghas been updated)Document changes
CHANGELOG.mdgoxygen::goxygen()and verify the modified code is properly documentedPerform test runs
Rscript start.R --> "compilation check"Rscript start.R --> "default"Rscript start.R --> "test runs"Reporting produces no errors and no new warnings
3 warnings regarding the piaminterfaces mapping will be fixed after approval and before merging the PR
Get two approving reviews (at least one from RSE)
📉 Performance 📈
🚨 Checklist for reviewer 🚨
CHANGELOGis updated correctly