Table of Contents
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)
- Start GroIMP and open the project
Transport.gsz(File → Open). - The model code is in the file
Example1.rgg. Open it in the text editor (Panels → Explorers → Files, then double-click the file). - 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 ongrow= one time step = one hour of simulated time. - 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. - Click
growa 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):
- Q1. Name three sources and three sinks in a tomato plant bearing fruit.
- 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.
- 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
calculatePSconverts 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,demandandfare. What is the value offwhen 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:
- Write your prediction before running (effect on fruit number, fruit size, internode length, sugar distribution).
- Change one value only, save (the model resets), run to step 600.
- 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:
- Give
Internodea new variable for its developmental age: change the module declaration tomodule Internode(super.length, int age, int rank, float as) extends Cylinder(length, 0.1) { float dev; }. - In the internode block, use
itn[dev]instead ofitn[age]to compute the potential. - At the end of the block, let development advance only as fast as growth is satisfied:
itn[dev] += f; - The function
logisticexpects anintfor time. Change its declaration tofloat 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.
