User Tools

Site Tools


02_user_tutorials:exercises:exercise:start

Sources, sinks and assimilate transport in a virtual plant

Master 2 BV, specialties “SEPPRO&SPP” and “Santé des Plantes - PHP”. Duration: about 2 hours. You may work alone or in pairs.

Learning objectives

At the end of this session you should be able to:

  • explain how a functional–structural plant model (FSPM) links light interception → photosynthesis → transport → growth of sinks;
  • identify, in real model code, where each of these processes is computed and which organs act as sources or sinks;
  • explain the difference between the potential growth of an organ and its actual growth when sugar is limiting;
  • run a model experiment rigorously: predict, run, observe, explain;
  • modify the model to represent a situation from your own field (a pest or disease, or fruit and seed set);
  • critically judge what a model does and does not represent.

You do not need to be a programmer. Every code change you are asked to make is given or guided step by step.

Schedule

Part Content Time
0 Setup: open and start the model 10 min
1 The biology in brief 10 min
2 The model at a glance 15 min
3 Observe the reference run 15 min
4 Reading the code: production, transport, use 25 min
5 Virtual experiments 25 min
6 Your specialty: plant health or seed science 15 min
7 Synthesis 5 min
(Bonus) Let organs catch up: developmental plasticity for fast groups

Part 0 – Setup (10 min)

  1. Start GroIMP and open the project Transport.gsz (File → Open).
  2. The model code is in the file Example1.rgg. Open it in the text editor (Panels → Explorers → Files, then double-click the file).
  3. In the toolbar of the 3D view you will find buttons for the public methods of the model. Here there is one: grow. Each click on grow = one time step = one hour of simulated time.
  4. To reset the plant to its initial state, use the reset button (this executes the init() method). Every time you save the code (Ctrl+S), the model is also recompiled and reset.
  5. Click grow a few times, then start a long run (run/loop button). Let it run to about step 600 (≈ 25 days) while you work on Parts 1 and 2. You will need the result in Part 3.

Four charts open automatically:

Chart What it shows
Light intercepted by canopy total light absorbed by all leaves during the last hour
Canopy photosynthesis total amount of sugar stored in all leaves, in mg (a stock, not the hourly production!)
Fruit growth size of every fruit over time (one series per fruit)
Distribution of sugar in the internodes sugar content (mg) of every internode at the current step, plotted against its rank

Colour code in the 3D view (false colours, for display only):

  • Leaves: colour depends on the light they absorbed.
  • Internodes: colour depends on their sugar content.
  • The brown floor is made of light-absorbing tiles; bright tiles receive more light.

The XL Console. Messages from the model appear here. You can also type queries into it, for example:

((* Example1.Fruit *)[size])      // size of every fruit
((* Example1.Fruit *)[as])        // sugar stock of every fruit
count((* Example1.Fruit *))       // number of fruits

Part 1 – The biology in brief (10 min)

Plants produce sugars (assimilates) in source organs – mainly mature leaves – and use them in sink organs – young leaves, stems, roots, flowers, fruits and seeds. Sugars travel through the phloem. In the widely accepted Münch model, sugar loading at the source raises the osmotic pressure there, unloading at the sink lowers it, and the resulting pressure difference drives a mass flow from source to sink. A young leaf is first a sink and becomes a source when it reaches roughly a third to half of its final size (sink–source transition).

Questions (answer in 2–3 lines each):

  1. Q1. Name three sources and three sinks in a tomato plant bearing fruit.
  2. Q2. Give one example of a pest or pathogen that changes the source–sink balance of a crop, and say whether it mainly reduces the source, adds a sink, or blocks transport.
  3. Q3. In a seed crop, why can the number of fruits/seeds set early in the season limit the final seed size?

Part 2 – The model at a glance (15 min)

2.1 The organs (modules)

Module Role Important attributes
Bud apical meristem; produces new metamers rank (position on the axis), phyllo (countdown until next metamer), order (1 = main stem, 2 = branch, 3 = dormant bud)
Internode stem segment; transport pathway and sink length, age, rank, as (assimilate content, mg)
Node attachment point of a leaf and a lateral bud –
Leaf source (and sink while young) length, width, al (absorbed light), age, as (assimilate content, mg)
Flower becomes a fruit if enough sugar is available, otherwise it is shed age, max_age
Fruit main sink size, age, as, no (fruit number)
Tile light-absorbing ground al
MyLight a 200 W spotlight 50 units above the plant –

2.2 What happens during one call of grow()

public void grow () {
    run();            // 1. architecture: new metamers, flowers, fruit set, leaf death
    lm.compute();     // 2. light model: ray tracing of the whole scene
    absorbAndGrow();  // 3. light absorption, photosynthesis, organ growth
    //if(time % 24 == 0) {
        //for(int hour = 0; hour < 24; hour++) {
            transport();   // 4. one round of transport per hour
       // }
    //}
    updateChart();    // 5. charts
    time++;
}

Q4. In an earlier version of the model, the lines now commented out were active: transport happened 24 times in a row, but only once every 24 steps. A young leaf is a sink only during its first ~13 hours. What problem did this cause? Why is it important that the time step of transport matches the time scale of the processes it feeds?

2.3 How the plant is built

The rule that makes a bud produce a new metamer is:

Bud(r, p, o), (r < 10 && p == 0 && o < 3) ==>
    RV(-0.1) Internode(0.1, 1, r, (r==1 && o==1) ? 0.2 : 0.0) Node
    [ RL(BRANCH_ANGLE) Bud(r, PHYLLOCHRON, o+1) ]   // lateral bud -> branch
    [ LFA(1) Leaf(0.1, 0.07, 0, 1, 0, r) ]          // leaf
    RH(GOLDEN_ANGLE) RV(-0.1) Internode(0.1, 1, r, (r==1 && o==1) ? 0.1 : 0.0)
    Bud(r+1, PHYLLOCHRON, o);                       // the apex continues

Q5. Draw (on paper) one metamer as produced by this rule: which organs, in which order, and what is inside the square brackets [ ]?

Q6. When rank reaches 10, the bud turns into a Flower. How many flowers do you expect on the plant? (Hint: look at the condition o < 3 and at the order given to the main stem in init().)

Q7. Only the first two internodes of the main stem (r==1 && o==1) start with some sugar; all other new organs start empty. What does this initial sugar represent biologically? Why is it a good idea not to give every new organ a “start capital”?

Part 3 – Observe the reference run (15 min)

Look at your run (about 600 steps). Use the 3D view, the charts and the console queries.

Fill in:

Observation Your answer
Step at which the first flower appears
Step at which the first fruit appears
Number of flowers / number of fruits
Final size of each fruit (console query)
Shape of the fruit growth curves (linear? S-shaped? all the same?)
Sugar distribution in the internodes: at which ranks is it highest?
Which leaves absorb the most light?

Q8. The internode sugar chart shows the highest sugar content in the middle ranks, not at the base or at the top. Propose an explanation. (Think about which leaves are mature and well lit, and which organs at the top are consuming sugar.)

Part 4 – Reading the code: production, transport, use (25 min)

We now follow a sugar molecule from where it is made to where it is used.

4.1 Production: the light response curve

float calculateCER(float ppfd) {
    return ((FMAX + DARK_RESPIRATION_RATE) * PHOTO_EFFICIENCY * ppfd)
         / (PHOTO_EFFICIENCY * ppfd + FMAX + DARK_RESPIRATION_RATE)
         - DARK_RESPIRATION_RATE;
}

ppfd is the photon flux density received by the leaf (µmol photons m⁻² s⁻¹), CER is the CO₂ exchange rate (µmol CO₂ m⁻² s⁻¹). FMAX = 20, DARK_RESPIRATION_RATE = 0.5, PHOTO_EFFICIENCY = 0.85.

  • Q9. What is the value of CER in darkness (ppfd = 0)? What does a negative value mean for the leaf?
  • Q10. What value does CER approach when ppfd becomes very large? Sketch the curve.
  • Q11. The function calculatePS converts CER into milligrams of glucose produced by one leaf in one hour. Which quantities is CER multiplied by? (Look at the code.)

In absorbAndGrow(), every leaf adds its production to its own stock: lf[as] += calculatePS(…).

4.2 Transport

The method transport() contains three rules. The rate constants are defined at the top of the file:

const float LEAF_EXPORT  = 0.05;  // fraction of leaf stock exported per hour
const float D_PHLOEM     = 0.2;   // exchange between adjacent internodes
const float FRUIT_UNLOAD = 0.1;   // unloading into the fruit per hour

Rule 1 – between a leaf and the internode that carries it

lf:Leaf -ancestor-> itn:Internode ::> {
    boolean sink = lf[length] < 1.0;   // about 1/3 of final length
    if (!sink && lf[as] > 0.001) {            // mature leaf: EXPORT
        float r = LEAF_EXPORT * lf[as];
        lf[as] -= r;  itn[as] += r;
    }
    else if (sink && itn[as] > 0.001) {       // young leaf: IMPORT
        float r = LEAF_EXPORT * itn[as];
        lf[as] += r;  itn[as] -= r;
    }
}

Rule 2 – between two successive internodes

i_top:Internode -ancestor-> i_bottom:Internode ::> {
    float r = D_PHLOEM * (i_top[as] - i_bottom[as]);
    i_bottom[as] :+= r;
    i_top[as]    :-= r;
}

Rule 3 – from an internode into the fruit it carries

itn:Internode -successor-> fr:Fruit ::> {
    float r = FRUIT_UNLOAD * Math.max(0, itn[as] - fr[as]);
    itn[as] :-= r;
    fr[as]  :+= r;
}

Reading tips: a -ancestor→ b:Internode means “starting from a, go down towards the base and take the first Internode you meet”. a -successor→ b means “b follows a directly”. The operators :+= and :-= collect all changes and apply them together at the end of the step, so the result does not depend on the order in which the rules are applied.

  • Q12. When does a leaf switch from sink to source in this model? Why is a criterion based on leaf size closer to the biology than one based on leaf age?
  • Q13. In Rule 2, can sugar move upwards as well as downwards? What decides the direction? Which physical process does this rule resemble (hint: Fick's law)?
  • Q14. Does the export of a mature leaf (Rule 1) depend on how much sugar is already in the internode? Is that consistent with the Münch model?
  • Q15. In Rule 3, the flux into the fruit depends on the difference between the internode and the fruit. What happens to the flux when a fruit uses its sugar quickly? What does this tell you about what makes a sink “strong”?

4.3 Use: potential and actual growth

Internodes and fruits grow with the same logic. Here is the internode version:

itn:Internode ::> {
    itn[age]++;
    itn[as] *= (1 - MR);                                     // maintenance respiration
    float potential = logistic(INT_MAX_LENGTH, itn[age], 20, 0.2); // growth if sugar were unlimited
    float demand = potential * GROWTH_COST;                  // sugar needed for that growth
    float f = (demand > 0) ? Math.min(1.0, itn[as] / demand) : 0;  // fraction of demand satisfied
    itn[length] += potential * f;                            // actual growth
    itn[as]     -= demand * f;                               // sugar consumed
}

The fruit block is identical, with FRUIT_MAX_SIZE and FRUIT_COST.

  • Q16. Explain in your own words what potential, demand and f are. What is the value of f when the organ has more sugar than it needs? When it has none?
  • Q17. The potential growth depends only on the organ's age. If an internode receives no sugar during its first 40 hours, can it catch up later? Is this realistic?
  • Q18. Growth consumes sugar (last line). Using your answer to Q15, explain why this consumption is what makes sugar flow towards growing organs.
  • Q19. An internode needs INT_MAX_LENGTH × GROWTH_COST = 1.5 mg of sugar for its whole growth. Compare with the values in the internode sugar chart. Is this plant limited by its sources or by its sinks?
  • Q20. Does leaf growth depend on the amount of sugar in the leaf? (Read the comment in the code, then the code itself.)

4.4 Fruit set

fl:Flower(t, m)(* -ancestor-> itn:Internode *), (t >= m && t < m+2) ==>
    { float sugar = itn[as]; println("flower sugar: " + sugar); }
    if (sugar > FRUIT_SET_THRESHOLD) ( {noFrts++;} Fruit(0.01, 1, 0.1, noFrts) );

Q21. In words: under which condition does a flower become a fruit? Where is the sugar measured? What happens to a flower when the condition is not met? (Hint: what is on the right-hand side of the rule in that case?)

Part 5 – Virtual experiments (25 min)

Method, for each experiment:

  1. Write your prediction before running (effect on fruit number, fruit size, internode length, sugar distribution).
  2. Change one value only, save (the model resets), run to step 600.
  3. Record the result, then restore the original value.

A run takes several minutes, so the experiments are shared out between the pairs. Your teacher will tell you which ones to do; the results are pooled at the end.

Exp. What to change Question behind it
E1 D_PHLOEM: 0.2 → 0.02 How far can sugar travel in the stem?
E2 MR: 0.002 → 0.02 What does respiration cost the plant?
E3 LEAF_EXPORT: 0.05 → 0.01 What if leaves keep their sugar?
E4 Lamp power: setPower(200.0) → 100.0 (module MyLamp) Source limitation
E5 FRUIT_COST: 250 → 500 A more demanding sink
E6 Sink–source transition: lf[length] < 1.0 → < 2.0 (Rule 1) Longer sink phase of young leaves
E7 FRUIT_SET_THRESHOLD: 3.5 → 1.0, then → 10 Fruit set vs. abortion

Results table (one line per run):

Exp. Value Prediction Nb fruits Mean fruit size Internode sugar profile Plant height / internode length Explanation
Ref – –

Q22. Which experiments changed fruit size, and which changed fruit number? Why are these two responses controlled by different parts of the model?

Q23. Was any result the opposite of your prediction? Explain it using the code.

Part 6 – Your specialty (15 min)

Choose one track and do at least one task.

Track A – Plant Health

A1. Aphids: a new phloem sink. Aphids feed directly on phloem sap. Add a colony on the internodes of rank 3, starting at step 100.

At the top of the file, next to the other constants, add:

const float APHID_RATE = 0.02;   // fraction of internode sugar taken per hour
float aphidSugar = 0;            // total sugar taken by the aphids

Inside transport(), add a fourth rule (before the closing ]):

itn:Internode, (itn[rank] == 3 && time > 100) ::> {
    float r = APHID_RATE * itn[as];
    itn[as] :-= r;
    aphidSugar += r;
}

Print the total at each step: add println(“aphids: ” + aphidSugar); in grow(). Compare with the reference run. Then move the colony to rank 9, just below the flowers.

A2. Defoliation by a leaf disease. Remove all leaves of rank ≤ 4 at step 200. Add this rule in run():

lf:Leaf, (time == 200 && lf[rank] <= 4) ==> ;

A3. A pathogen that lowers photosynthetic capacity (e.g. a leaf spot or a virus): reduce FMAX from 20 to 10.

Questions:

  • QA1. Which intervention reduced fruit number or fruit size the most? Was the position of the aphid colony important? Why?
  • QA2. Which of A1, A2, A3 reduces the source, which adds a sink? Why is it useful for a plant pathologist to make this distinction?
  • QA3. What would you need to add to the model to represent an aphid population that grows over time?

Track B – Seed Science and Plant Propagation

B1. Fruit thinning. Remove every second fruit at step 360. Add this rule in run():

fr:Fruit, (time == 360 && fr[no] % 2 == 0) ==> ;

Compare the final size of the remaining fruits with the reference run.

B2. Fruit set threshold. Run experiment E7 if nobody else has. How do the number of fruits and the mean fruit size change together?

B3. Variable developmental speed. In the reference plant, all branches develop in step, so all fruits have almost the same age. Make development less regular: in the metamer rule (Part 2.3), replace both occurrences of PHYLLOCHRON by irandom(PHYLLOCHRON-8, PHYLLOCHRON+8). Run the model twice and compare the spread of fruit sizes (largest minus smallest) with the reference run.

Questions:

  • QB1. Is there a trade-off between the number and the size of fruits? Show it with your results.
  • QB2. In B3, do early-set or late-set fruits end up larger? Why? What are the consequences for seed-lot uniformity?
  • QB3. A seed producer wants large, uniform seeds. Based on the model, what would you advise, and what is missing from the model to give a reliable answer?

Part 7 – Synthesis (5 min)

  • Q24. Draw a diagram (boxes and arrows) of the sugar flows in the model: production → stocks → transport → use. Mark every place where sugar enters or leaves the system.
  • Q25. List two strengths and two limitations of this model for studying source–sink relations.

Bonus – Let organs catch up: developmental plasticity

For fast groups. At present an internode's potential growth depends on its calendar age (Q17): if it is starved during its growth window, the loss is permanent. Real organs can often delay their development instead.

Hints:

  1. Give Internode a new variable for its developmental age: change the module declaration to module Internode(super.length, int age, int rank, float as) extends Cylinder(length, 0.1) { float dev; }.
  2. In the internode block, use itn[dev] instead of itn[age] to compute the potential.
  3. At the end of the block, let development advance only as fast as growth is satisfied: itn[dev] += f;
  4. The function logistic expects an int for time. Change its declaration to float time.

Compare the internode lengths along the main stem with the reference run. Where does the change have the largest effect?

Before the exam

This exercise is not handed in, but the questions above cover the kind of reasoning expected in the exam: explaining source–sink relations, reading a simple model rule, and predicting and interpreting the outcome of a virtual experiment. Keep your answers and tables as revision notes.

02_user_tutorials/exercises/exercise/start.txt · Last modified: by barley1965