flowchart LR G["growth g<br/>pushes plants up<br/>the height axis"] --> N["the size<br/>distribution<br/>N(H | x, a)"] D["death d<br/>removes plants<br/>at each height"] --> N
The maths, gently
theory · start here
This page introduces the equations behind plant one idea at a time. It is for readers who want to understand the maths before tackling the denser size-structured PDE page. The equations are the same, but here we build them up gradually and explain every symbol in words. Next, the maths, worked through puts the equations to work in one small numerical example. The size-structured PDE page then gives the full derivations, boundary conditions, and appendices.
If you have not yet read the big picture, do that first; this page puts equations on the concepts introduced there. We build up in seven steps:
- where a single plant’s rates come from (the carbon economy);
- an individual as three running totals;
- from one plant to a whole size distribution (the central PDE);
- how that PDE is actually solved — by following cohorts;
- competition through shade;
- patches, disturbance, and the seed-rain balance;
- invasion fitness, and reading off averages.
The examples use the FF16 convention: plant size is height and plants compete through a canopy-light profile. The same demographic logic can use another size coordinate or competition model. K93, for example, uses stem diameter and basal-area competition.
The symbols you will meet
Most of the page uses the same small set of symbols. Keep this table nearby as you read:
| Symbol | Means | In words |
|---|---|---|
| \(x\) | traits | what kind of plant (LMA, wood density, seed mass, max height) |
| \(H\) | height | how big a plant is — the model’s measure of size |
| \(a\) | patch age | time since the patch was last cleared by disturbance |
| \(a_0\) | birth age | the patch age at which a given plant germinated |
| \(E_a\) | light environment | how much light reaches each height in a patch of age \(a\) |
| \(g,\ d,\ f\) | rates | growth, death, and fecundity (seed) rates |
| \(N\) | size-density | how many plants of each height are present |
| \(S_{\rm G}\) | germination survival | chance a seed survives to become a seedling |
| \(S_{\rm I}\) | individual survival | chance a plant is still alive at a given age |
| \(S_{\rm P}\) | patch survival | chance a patch has escaped disturbance so far |
| \(P\) | patch-age density | how common patches of each age are |
| \(\bar a\) | mean disturbance interval | average time a patch lasts before being reset |
| \(Y_x\) | seed rain | rate at which seeds of strategy \(x\) arrive in a patch |
| \(k_{\rm I}\) | extinction coefficient | how strongly leaves block light |
One useful way to read an integral \(\int\) is “add up continuously over time (or over height).” In the first few sections, you can think of each integral as a running total.
Step 1 — where a plant’s rates come from
The demographic core takes the growth, death, and fecundity rates \(g\), \(d\), and \(f\) as inputs, then uses them to work out how the population changes. Before we do that, it helps to see where those rates come from. In the default FF16 model, growth and fecundity are tied directly to the net biomass a plant produces per unit time. Net biomass also affects one component of mortality.
\[ \underbrace{\frac{{\rm d}B}{{\rm d}t}}_{\text{net biomass}} = \underbrace{\text{photosynthesis}}_{\text{income}} \; - \; \underbrace{\text{respiration}}_{\text{upkeep}} \; - \; \underbrace{\text{tissue turnover}}_{\text{replacement}}. \]
Photosynthesis depends on how much leaf area the plant has and how much light reaches those leaves. Respiration and turnover are the continuing costs of maintaining leaves, wood, and roots. The plant can invest whatever remains. That investment, together with the model’s mortality assumptions, determines the three demographic rates:
- Growth \(g\) is the share of net biomass spent building tissue, converted into height gain. Young plants spend most of their surplus here.
- Fecundity \(f\) is the share spent on seeds, divided by the cost of one seed. The fraction going to seeds rises as a plant nears its maximum height.
- Mortality \(d\) has a baseline part plus a part that rises as production falls — a starving, shaded plant is more likely to die.
The carbon budget therefore drives growth and fecundity directly and links low production to an increased risk of death. Background mortality remains a separate part of the model. A plant’s traits — its LMA, wood density, and so on — determine the terms of that budget. The full equations are on the FF16 and assimilation & hydraulics pages. For now, we will treat \(g\), \(d\), and \(f\) as rates supplied by the chosen strategy.
Step 2 — one plant, three running totals
Now consider a single plant with traits \(x\) that germinated when the patch was age \(a_0\). Its growth, survival, and seed production can each be written as a running total of the three rates above.
Its height is its starting height plus all the growth it has accumulated:
\[ H(a) = H_0 + \int_{a_0}^{a} g \, {\rm d}a'. \]
Its chance of still being alive falls off as death accumulates. Survival is the germination probability \(S_{\rm G}\) times the exponential of minus the total death risk so far:
\[ S_{\rm I}(a) = S_{\rm G} \, \exp\!\left(- \int_{a_0}^{a} d \, {\rm d}a'\right). \]
The exponential converts accumulated death risk into a survival probability. If no risk has accumulated, the exponential factor is 1, so survival equals \(S_{\rm G}\). As the risk grows, survival approaches 0.
Its total seeds so far add up fecundity over time — but only counting plants that are still alive to produce them, hence the survival factor:
\[ \tilde{R}(a) = \int_{a_0}^{a} f \, S_{\rm I}(a') \, {\rm d}a'. \]
These three integrals describe the plant growing, surviving, and producing seed. In practice, plant rewrites them as small differential equations and advances them through time with an ODE solver, rather than evaluating the integrals directly.
Step 3 — from one plant to a distribution
A patch contains many plants. Rather than list each plant separately, we describe them with a size-density distribution \(N(H \mid x, a)\). At patch age \(a\), this distribution tells us how many plants with traits \(x\) occur around each height \(H\). You can picture it as a curve over height that changes shape as the patch ages.
Two processes change that curve: growth moves plants between heights, while death removes them. These are the two rates that do not describe reproduction:
Written as an equation, this is the model’s central partial differential equation (PDE):
\[ \frac{\partial N}{\partial a} = \underbrace{-\, d \, N}_{\text{deaths remove plants}} \;\underbrace{-\, \frac{\partial}{\partial H}\big(g \, N\big)}_{\text{growth carries plants upward}}. \]
A conveyor belt is a useful analogy. Growth \(g\) carries plants along the height axis; the second term describes that flow. Death \(d\) removes plants wherever they are; the first term describes those losses. The left-hand side records the combined change in the distribution as the patch gets older.
New plants enter at the smallest height. The PDE needs a rule for this entry point, called a boundary condition: the flow of plants into the distribution must equal the rate at which viable seedlings appear,
\[ g(H_0) \, N(H_0 \mid x, a) = Y_x \, S_{\rm G}, \]
where \(Y_x\) is the seed rain (how many seeds arrive) and \(S_{\rm G}\) is the chance one survives germination. This is where the landscape-scale seed rain of Step 6 feeds back into a single patch.
Step 4 — how the PDE is actually solved
Solving the PDE on a fixed grid would mean repeatedly moving plants from one height cell to the next. plant instead uses the method of characteristics: rather than watching fixed heights, it follows plants as they grow.
Follow one cohort — a group of plants that all germinated together. Its height simply obeys the growth rate,
\[ \frac{{\rm d}H}{{\rm d}a} = g, \]
so the cohort traces a curve along the height axis. That curve is a characteristic of the PDE. As the cohort moves, its density changes for two reasons: plants die, and neighbouring cohorts spread apart or bunch together as growth speeds up or slows down. Both effects appear in one equation,
\[ \frac{{\rm d}}{{\rm d}a}\ln N = -\left(\, d + \frac{\partial g}{\partial H}\,\right). \]
The \(d\) term represents deaths, as before. The \(\partial g / \partial H\) term describes how growth changes with height. If growth slows with height (\(\partial g/\partial H < 0\)), successive cohorts bunch together and density rises. If growth speeds up, they spread apart and density falls. This is the same population change described by the PDE, viewed while moving with a cohort.
The calculation therefore represents a whole patch with a finite set of cohorts. Each cohort carries two values — its height and its log density — which advance together under simple differential equations. plant adaptively chooses how many cohorts to use and when to introduce them (see node spacing).
Step 5 — competition through shade
In a light-competition strategy, the rates \(g\) and \(d\) are not fixed. They depend on light, while the light available at each height depends on all the plants in the patch. plant represents shading with Beer’s law, borrowed from optics: light falls exponentially as the leaf area above a point increases.
\[ E_a(z) = \exp\!\left(-k_{\rm I} \times (\text{leaf area above height } z)\right). \]
Here \(z\) is a height in the canopy, \(E_a(z)\) is the fraction of open-sky light reaching it, and \(k_{\rm I}\) is the extinction coefficient (how strongly leaves block light). The “leaf area above \(z\)” is itself found by adding up the leaf area of every cohort taller than \(z\) — that is, by integrating over the size distribution \(N\).
We can now close the feedback loop from the big picture. The distribution \(N\) determines leaf area; leaf area determines the light \(E_a\); and light changes the growth and death rates that reshape \(N\). Taller plants usually shade a larger fraction of a shorter plant’s crown than the reverse, so this competition is strongly size-asymmetric.
Step 6 — patches, disturbance, and the seed-rain balance
The patch mosaic. Now zoom out from one patch to the landscape. Disturbances reset patches at different times, so the landscape contains patches of many ages. \(P(a)\) describes how common patches of age \(a\) are. It declines with age because older patches have had more time to be disturbed and reset:
\[ \frac{{\rm d}P}{{\rm d}a} = -\, d_{\rm P}(a) \, P(a), \]
where \(d_{\rm P}(a)\) is the disturbance rate for a patch of age \(a\). Solving this equation gives the chance that a patch has escaped disturbance up to age \(a\),
\[ S_{\rm P}(a) = \exp\!\left(-\int_0^a d_{\rm P}(a')\,{\rm d}a'\right), \]
and \(P(a)\) is proportional to \(S_{\rm P}(a)\). Two cases matter:
- If the disturbance risk \(d_{\rm P}\) is constant, old patches simply grow rarer and rarer — an exponential distribution of ages.
plant’s default instead lets the risk rise with age (\(d_{\rm P}\propto a\)): young patches almost always survive, old ones almost never do. This gives a Weibull distribution, \(S_{\rm P}(a) = \exp(-\lambda a^{2})\).
Once the shape of the disturbance-risk curve has been chosen, its scale can be set using \(\bar a\), the mean interval between disturbances. A different risk curve with the same mean can still produce a different distribution of patch ages.
The seed-rain balance. This is where the patch and landscape scales meet. To find a strategy’s seed output across the landscape, we add the seeds produced in patches of every age and weight each age by how common it is:
\[ Y_x = \int_0^\infty \int_0^\infty P(a) \, S_{\rm D} \, f \, N \, {\rm d}H \, {\rm d}a. \]
The inner integral adds seed production over all plant heights in a patch; the outer integral averages over patches of all ages; \(S_{\rm D}\) is the fraction of seeds surviving dispersal.
The same seed rain \(Y_x\) appears on both sides of the calculation. It feeds the patches through the boundary condition in Step 3, and it is also produced by those patches through the equation above. We can write the output seed rain as a function of the assumed input, \(Y_x^{\text{out}} = \Phi(Y_x)\). At equilibrium, input and output must agree,
\[ Y_x = \Phi(Y_x), \]
This is a fixed-point (root-finding) problem: we seek an input that reproduces itself as output. It is the same loop drawn in the big picture. For one strategy this is a one-dimensional numerical problem; with several competing strategies it becomes a more difficult multi-dimensional solve. The current package does not expose a general equilibrium seed-rain solver, so this section describes the mathematical condition rather than a ready-made user workflow.
Step 7 — invasion fitness and reading off answers
Can a mutant invade? Once the resident community has reached its balanced seed rain, we can test a rare mutant with traits \(x'\). The mutant is assumed to be too rare to change the light environment, so it grows in the shade created by the residents. Its invasion fitness is the expected number of dispersing offspring produced by one mutant seed over a full patch lifetime, averaged over the ages of the patches where that seed might land:
\[ R(x', x) = \int_0^\infty P(a_0) \, \tilde{R}(x', a_0) \, {\rm d}a_0, \]
where \(\tilde{R}(x', a_0)\) is that one seed’s lifetime seed output (Step 2, now also discounted by patch survival \(S_{\rm P}\)). The reading is simple:
- \(R(x', x) > 1\) → one seed makes more than one seed; the mutant can invade.
- \(R(x', x) < 1\) → the mutant fades out; the resident holds.
Trait values that no mutant can beat (\(R \le 1\) for every \(x'\)) are evolutionarily stable. They are the trait combinations predicted to resist invasion under the model’s assumptions. The adaptive dynamics page develops this idea in full.
Reading off averages. Finally, suppose we want a landscape-scale summary of a quantity \(w\), such as biomass or mortality. We first average over the size distribution within each patch, then weight patches by how common each age is:
\[ \hat{w}(x) = \frac{1}{\hat N(x)}\int_0^\infty \int_0^\infty P(a) \, N \, w \; {\rm d}H \, {\rm d}a, \qquad \hat N(x) = \int_0^\infty \int_0^\infty P(a) \, N \; {\rm d}H \, {\rm d}a, \]
Here \(\hat N(x)\) is the average total density: the same integral with \(w = 1\). Dividing by it normalises the weighted total. The same pattern can be used to calculate stem density, leaf area, biomass, and the size–density relationship behind self-thinning. The emergent properties guide shows these calculations in practice.
Where to go next
You now have the main mathematical structure of the model. Choose the next page according to what you want to understand:
- The maths, worked through — the gentlest next step: the same equations pushed through one small numerical example, one plant at a time, before the abstract treatment.
- The full size-structured PDE page — every equation above with its derivation, boundary conditions, and the Weibull appendix.
- Assimilation & hydraulics and the FF16 model — where the growth, death, and fecundity rates (\(g\), \(d\), \(f\)) actually come from.
- Adaptive dynamics — the full treatment of invasion fitness and evolutionary endpoints.
- The implementation pages — how these integrals and the PDE are actually solved: the characteristic method, ODE stepping, and node spacing.