# -*- coding: latin-1 -*-
from __future__ import division # use "//" to do integer division
import copy
import warnings
from openalea.cnwgrass.growth import model
from openalea.cnwgrass.respiration.model import RespirationModel
"""
growth.simulation
~~~~~~~~~~~~~~~~~~
The module :mod:`growth.simulation`.
"""
[docs]
class SimulationError(Exception):
pass
[docs]
class SimulationRunError(SimulationError):
pass
[docs]
class Simulation(object):
"""The Simulation class permits to initialize and run a simulation.
"""
def __init__(self, delta_t=1, hydraulics=False, update_parameters=None):
"""
:param int delta_t: the delta t of the simulation (in seconds)
:param bool hydraulics: if True the model will assume the coupling to the turgor-driven growth model
:param None or dict update_parameters: if a dict is provided, the specified parameters in keys will be updated
"""
#: `inputs` is a dictionary of dictionaries:
#: {'hiddenzone': {(plant_index, axis_label, metamer_index): {hiddenzone_input_name: hiddenzone_input_value, ...}, ...},
#: 'elements': {(plant_index, axis_label, metamer_index, organ_label, element_label): {organ_input_name: organ_input_value, ...}, ...},
#: 'roots': {(plant_index, axis_label): {root_input_name: root_input_value, ...}, ...}}
self.inputs = {}
#: `outputs` is a dictionary of dictionaries:
#: {'hiddenzone': {(plant_index, axis_label, metamer_index): {hiddenzone_input_name: hiddenzone_input_value, ...}, ...},
#: 'elements': {(plant_index, axis_label, metamer_index, organ_label, element_label): {organ_input_name: organ_input_value, ...}, ...}
#: 'roots': {(plant_index, axis_label): {root_input_name: root_input_value, ...}, ...}}
self.outputs = {}
#: the delta t of the simulation (in seconds)
self.delta_t = delta_t
#: Checks whether the Hydraulic version should be used
self.hydraulics = hydraulics
if not self.hydraulics:
self.model = model.GrowthModel()
else:
self.model = model.GrowthModelHydraulics()
self.organ_init = self.model.organ_init
#: The inputs and outputs of Growth at each scale.
self.axis_inputs = self.model.axis_inputs
self.axis_outputs = self.model.axis_outputs
self.axis_inputs_outputs = sorted(set(self.axis_inputs + self.axis_outputs))
self.hiddenzone_inputs = self.model.hiddenzone_inputs
self.hiddenzone_outputs = self.model.hiddenzone_outputs
self.hiddenzone_inputs_outputs = sorted(set(self.hiddenzone_inputs + self.hiddenzone_outputs))
self.element_inputs = self.model.element_inputs
self.element_outputs = self.model.element_outputs
self.element_inputs_outputs = sorted(set(self.element_inputs + self.element_outputs))
self.root_inputs = self.model.root_inputs
self.root_outputs = self.model.root_outputs
self.root_inputs_outputs = sorted(set(self.root_inputs + self.root_outputs))
#: Update parameters if specified
if update_parameters:
for key, value in update_parameters.items():
if hasattr(self.model.parameters, key):
setattr(self.model.parameters, key, value)
else:
warnings.warn(f"Parameter '{key}' is not defined in class self.self.model.parameters.")
[docs]
def initialize(self, inputs):
"""
Initialize :attr:`inputs` from `inputs`.
:param dict inputs: must be a dictionary with the same structure as :attr:`inputs`.
"""
self.inputs.clear()
self.inputs.update(inputs)
[docs]
def run(self, postflowering_stages=False):
"""
Run the simulation.
:param bool postflowering_stages: if True the model will calculate root growth with the parameters calibrated for post flowering stages
"""
# Copy the inputs into the output dict
self.outputs.update({inputs_type: copy.deepcopy(all_inputs) for inputs_type, all_inputs in self.inputs.items() if inputs_type in {'hiddenzone', 'elements', 'roots', 'axes'}})
# Hidden growing zones
all_hiddenzone_inputs = self.inputs['hiddenzone']
all_hiddenzone_outputs = self.outputs['hiddenzone']
# elements
all_elements_inputs = self.inputs['elements']
all_elements_outputs = self.outputs['elements']
# roots
all_roots_inputs = self.inputs['roots']
all_roots_outputs = self.outputs['roots']
# axes
all_axes_inputs = self.inputs['axes']
all_axes_outputs = self.outputs['axes']
# ----------------------------------------------
# ----------- Hiddenzones and elements ---------
# ----------------------------------------------
for hiddenzone_id, hiddenzone_inputs in sorted(all_hiddenzone_inputs.items()):
curr_hiddenzone_outputs = all_hiddenzone_outputs[hiddenzone_id]
axe_label = hiddenzone_id[1]
phytomer_id = hiddenzone_id[2]
#: Tillers (we copy corresponding elements of MS)
if axe_label != 'MS': # TODO: temporary or should be an option at least
pass
#: Main stem
else:
# Initialisation of the exports towards the growing lamina or sheath
delta_leaf_enclosed_mstruct = delta_leaf_enclosed_Nstruct = delta_lamina_mstruct = delta_sheath_mstruct = delta_lamina_Nstruct = delta_sheath_Nstruct = leaf_export_sucrose = \
delta_internode_Nstruct = leaf_export_amino_acids = leaf_remob_fructan = leaf_export_proteins = internode_export_sucrose = \
internode_export_amino_acids = internode_remob_fructan = internode_export_proteins = 0.
# -- Delta Growth internode
if hiddenzone_inputs['internode_pseudo_age'] < self.model.parameters.internode_rapid_growth_t: #: Internode is not yet in rapide growth stage TODO : tester sur une variable "is_ligulated"
# delta mstruct of the internode
ratio_mstruct_DM = self.model.calculate_ratio_mstruct_DM(hiddenzone_inputs['mstruct'], hiddenzone_inputs['sucrose'], hiddenzone_inputs['fructan'],
hiddenzone_inputs['amino_acids'], hiddenzone_inputs['proteins'])
delta_internode_enclosed_mstruct = self.model.calculate_delta_internode_enclosed_mstruct(hiddenzone_inputs['internode_L'], hiddenzone_inputs['delta_internode_L'], ratio_mstruct_DM)
# delta Nstruct of the internode
delta_internode_enclosed_Nstruct = self.model.calculate_delta_Nstruct(delta_internode_enclosed_mstruct)
else:
# delta mstruct of the enclosed internode
delta_internode_enclosed_mstruct = self.model.calculate_delta_internode_enclosed_mstruct_postL(hiddenzone_inputs['delta_internode_pseudo_age'],
hiddenzone_inputs['internode_pseudo_age'],
hiddenzone_inputs['internode_L'],
hiddenzone_inputs['internode_distance_to_emerge'],
hiddenzone_inputs['internode_Lmax'],
hiddenzone_inputs['LSIW'],
hiddenzone_inputs['internode_enclosed_mstruct'])
# delta Nstruct of the enclosed internode
delta_internode_enclosed_Nstruct = self.model.calculate_delta_Nstruct(delta_internode_enclosed_mstruct)
if hiddenzone_inputs['internode_is_visible']: #: Internode is visible
visible_internode_id = hiddenzone_id + tuple(['internode', 'StemElement'])
curr_visible_internode_inputs = all_elements_inputs[visible_internode_id]
curr_visible_internode_outputs = all_elements_outputs[visible_internode_id]
# Delta mstruct of the emerged internode
delta_internode_mstruct = self.model.calculate_delta_emerged_tissue_mstruct(hiddenzone_inputs['LSIW'], curr_visible_internode_inputs['mstruct'], curr_visible_internode_inputs['length'])
# Delta Nstruct of the emerged internode
delta_internode_Nstruct = self.model.calculate_delta_Nstruct(delta_internode_mstruct)
# Export of sucrose from hiddenzone towards emerged internode
internode_export_sucrose = self.model.calculate_export(delta_internode_mstruct, hiddenzone_inputs['sucrose'], hiddenzone_inputs['mstruct'])
# Export of amino acids from hiddenzone towards emerged internode
internode_export_amino_acids = self.model.calculate_export(delta_internode_mstruct, hiddenzone_inputs['amino_acids'], hiddenzone_inputs['mstruct'])
internode_remob_fructan = self.model.calculate_export(delta_internode_mstruct, hiddenzone_inputs['fructan'], hiddenzone_inputs['mstruct'])
internode_export_proteins = self.model.calculate_export(delta_internode_mstruct, hiddenzone_inputs['proteins'], hiddenzone_inputs['mstruct'])
# Update of internode outputs
curr_visible_internode_outputs['mstruct'] += delta_internode_mstruct
curr_visible_internode_outputs['max_mstruct'] = curr_visible_internode_outputs['mstruct']
curr_visible_internode_outputs['Nstruct'] += delta_internode_Nstruct
curr_visible_internode_outputs['sucrose'] += internode_export_sucrose + internode_remob_fructan
curr_visible_internode_outputs['amino_acids'] += internode_export_amino_acids
curr_visible_internode_outputs['proteins'] += internode_export_proteins
self.outputs['elements'][visible_internode_id] = curr_visible_internode_outputs
# -- Delta Growth leaf
if not hiddenzone_inputs['leaf_is_emerged']: #: Leaf is not emerged
# delta mstruct of the hidden leaf
ratio_mstruct_DM = self.model.calculate_ratio_mstruct_DM(hiddenzone_inputs['mstruct'], hiddenzone_inputs['sucrose'], hiddenzone_inputs['fructan'],
hiddenzone_inputs['amino_acids'], hiddenzone_inputs['proteins'])
init_leaf_L = hiddenzone_inputs.get('init_leaf_L') # Set at None if hydraulics is False
delta_leaf_enclosed_mstruct = self.model.calculate_delta_leaf_enclosed_mstruct(hiddenzone_inputs['leaf_L'], hiddenzone_inputs['delta_leaf_L'], ratio_mstruct_DM,
init_leaf_L, hiddenzone_inputs['leaf_pseudo_age'])
# delta Nstruct of the hidden leaf
delta_leaf_enclosed_Nstruct = self.model.calculate_delta_Nstruct(delta_leaf_enclosed_mstruct)
elif hiddenzone_inputs['leaf_is_growing']: #: Leaf has emerged and growing
delta_leaf_enclosed_mstruct = self.model.calculate_delta_leaf_enclosed_mstruct_postE(hiddenzone_inputs['delta_leaf_pseudo_age'],
hiddenzone_inputs['leaf_pseudo_age'],
hiddenzone_inputs['leaf_pseudostem_length'],
hiddenzone_inputs['leaf_enclosed_mstruct'],
hiddenzone_inputs['LSSW'],
hiddenzone_inputs['sucrose'],
hiddenzone_inputs['mstruct'])
# delta Nstruct of the enclosed en leaf
delta_leaf_enclosed_Nstruct = self.model.calculate_delta_Nstruct(delta_leaf_enclosed_mstruct)
# leaf has emerged and still growing
visible_lamina_id = hiddenzone_id + tuple(['blade', 'LeafElement1'])
#: Lamina is growing
if visible_lamina_id in all_elements_inputs and all_elements_inputs[visible_lamina_id]['is_growing']:
curr_visible_lamina_inputs = all_elements_inputs[visible_lamina_id]
curr_visible_lamina_outputs = all_elements_outputs[visible_lamina_id]
# Delta mstruct of the emerged lamina
delta_lamina_mstruct = self.model.calculate_delta_emerged_tissue_mstruct(hiddenzone_inputs['SSLW'], curr_visible_lamina_inputs['mstruct'], curr_visible_lamina_inputs['green_area'])
# Delta Nstruct of the emerged lamina
delta_lamina_Nstruct = self.model.calculate_delta_Nstruct(delta_lamina_mstruct)
# Export of metabolite from hiddenzone towards emerged lamina
leaf_export_sucrose = self.model.calculate_export(delta_lamina_mstruct, hiddenzone_inputs['sucrose'], hiddenzone_inputs['mstruct'])
leaf_export_amino_acids = self.model.calculate_export(delta_lamina_mstruct, hiddenzone_inputs['amino_acids'], hiddenzone_inputs['mstruct'])
leaf_remob_fructan = self.model.calculate_export(delta_lamina_mstruct, hiddenzone_inputs['fructan'], hiddenzone_inputs['mstruct'])
leaf_export_proteins = self.model.calculate_export(delta_lamina_mstruct, hiddenzone_inputs['proteins'], hiddenzone_inputs['mstruct'])
# Cytokinins in the newly visible mstruct
addition_cytokinins = self.model.calculate_init_cytokinins_emerged_tissue(delta_lamina_mstruct)
# Update of lamina outputs
curr_visible_lamina_outputs['mstruct'] += delta_lamina_mstruct
curr_visible_lamina_outputs['max_mstruct'] = curr_visible_lamina_outputs['mstruct']
curr_visible_lamina_outputs['Nstruct'] += delta_lamina_Nstruct
curr_visible_lamina_outputs['sucrose'] += leaf_export_sucrose + leaf_remob_fructan
curr_visible_lamina_outputs['amino_acids'] += leaf_export_amino_acids
curr_visible_lamina_outputs['proteins'] += leaf_export_proteins
curr_visible_lamina_outputs['cytokinins'] += addition_cytokinins
self.outputs['elements'][visible_lamina_id] = curr_visible_lamina_outputs
else: #: Mature lamina, growing sheath
if not self.hydraulics:
# The hidden part of the sheath is only updated once, at the end of leaf elongation, by remobilisation from the hiddenzone
visible_sheath_id = hiddenzone_id + tuple(['sheath', 'StemElement'])
curr_visible_sheath_inputs = all_elements_inputs[visible_sheath_id]
curr_visible_sheath_outputs = all_elements_outputs[visible_sheath_id]
# Delta mstruct of the emerged sheath
delta_sheath_mstruct = self.model.calculate_delta_emerged_tissue_mstruct(hiddenzone_inputs['LSSW'], curr_visible_sheath_inputs['mstruct'], curr_visible_sheath_inputs['length'])
# Delta Nstruct of the emerged sheath
delta_sheath_Nstruct = self.model.calculate_delta_Nstruct(delta_sheath_mstruct)
# Export of metabolite from hiddenzone towards emerged sheath
leaf_export_sucrose = self.model.calculate_export(delta_sheath_mstruct, hiddenzone_inputs['sucrose'], hiddenzone_inputs['mstruct'])
leaf_export_amino_acids = self.model.calculate_export(delta_sheath_mstruct, hiddenzone_inputs['amino_acids'], hiddenzone_inputs['mstruct'])
leaf_remob_fructan = self.model.calculate_export(delta_sheath_mstruct, hiddenzone_inputs['fructan'], hiddenzone_inputs['mstruct'])
leaf_export_proteins = self.model.calculate_export(delta_sheath_mstruct, hiddenzone_inputs['proteins'], hiddenzone_inputs['mstruct'])
addition_cytokinins = self.model.calculate_init_cytokinins_emerged_tissue(delta_sheath_mstruct)
# Update of sheath outputs
curr_visible_sheath_outputs['mstruct'] += delta_sheath_mstruct
curr_visible_sheath_outputs['max_mstruct'] = curr_visible_sheath_outputs['mstruct']
curr_visible_sheath_outputs['Nstruct'] += delta_sheath_Nstruct
curr_visible_sheath_outputs['sucrose'] += leaf_export_sucrose + leaf_remob_fructan
curr_visible_sheath_outputs['amino_acids'] += leaf_export_amino_acids
curr_visible_sheath_outputs['proteins'] += leaf_export_proteins
curr_visible_sheath_outputs['cytokinins'] += addition_cytokinins
self.outputs['elements'][visible_sheath_id] = curr_visible_sheath_outputs
# -- CN consumption due to mstruct/Nstruct growth of the enclosed leaf and of the internode
curr_hiddenzone_outputs['AA_consumption_mstruct'] = self.model.calculate_s_Nstruct_amino_acids((delta_leaf_enclosed_Nstruct + delta_internode_enclosed_Nstruct),
delta_lamina_Nstruct,
delta_sheath_Nstruct,
delta_internode_Nstruct) #: Consumption of amino acids due to mstruct growth (µmol N)
curr_hiddenzone_outputs['sucrose_consumption_mstruct'] = self.model.calculate_s_mstruct_sucrose((delta_leaf_enclosed_mstruct + delta_internode_enclosed_mstruct),
delta_lamina_mstruct,
delta_sheath_mstruct,
curr_hiddenzone_outputs[
'AA_consumption_mstruct']) #: Consumption of sucrose due to mstruct growth (µmol C)
curr_hiddenzone_outputs['Respi_growth'] = RespirationModel.R_growth(curr_hiddenzone_outputs['sucrose_consumption_mstruct']) #: Respiration growth (µmol C)
# -- Update of hiddenzone outputs
curr_hiddenzone_outputs['leaf_enclosed_mstruct'] += delta_leaf_enclosed_mstruct
curr_hiddenzone_outputs['leaf_enclosed_Nstruct'] += delta_leaf_enclosed_Nstruct
curr_hiddenzone_outputs['internode_enclosed_mstruct'] += delta_internode_enclosed_mstruct
curr_hiddenzone_outputs['internode_enclosed_Nstruct'] += delta_internode_enclosed_Nstruct
curr_hiddenzone_outputs['mstruct'] = curr_hiddenzone_outputs['leaf_enclosed_mstruct'] + curr_hiddenzone_outputs['internode_enclosed_mstruct']
curr_hiddenzone_outputs['Nstruct'] = curr_hiddenzone_outputs['leaf_enclosed_Nstruct'] + curr_hiddenzone_outputs['internode_enclosed_Nstruct']
curr_hiddenzone_outputs['sucrose'] -= (
curr_hiddenzone_outputs['sucrose_consumption_mstruct'] + curr_hiddenzone_outputs['Respi_growth'] + leaf_export_sucrose + internode_export_sucrose)
curr_hiddenzone_outputs['fructan'] -= (leaf_remob_fructan + internode_remob_fructan)
curr_hiddenzone_outputs['amino_acids'] -= (curr_hiddenzone_outputs['AA_consumption_mstruct'] + leaf_export_amino_acids + internode_export_amino_acids)
curr_hiddenzone_outputs['proteins'] -= (leaf_export_proteins + internode_export_proteins)
self.outputs['hiddenzone'][hiddenzone_id] = curr_hiddenzone_outputs
# -- Remobilisation at the end of leaf elongation
if hiddenzone_inputs['leaf_is_remobilizing']:
if phytomer_id == 0:
share_leaf = share_hidden_sheath = 1
else:
share_leaf = curr_hiddenzone_outputs['leaf_enclosed_mstruct'] / curr_hiddenzone_outputs['mstruct']
if not self.hydraulics:
# Case when the hiddenzone contains a hidden part of lamina
if hiddenzone_inputs['leaf_pseudostem_length'] > hiddenzone_inputs['sheath_Lmax']:
hidden_sheath_mstruct = self.model.calculate_sheath_mstruct(hiddenzone_inputs['sheath_Lmax'], hiddenzone_inputs['LSSW'])
share_hidden_sheath = hidden_sheath_mstruct / curr_hiddenzone_outputs['leaf_enclosed_mstruct']
else:
share_hidden_sheath = 1
else:
share_hidden_sheath = 1
# Add to hidden part of the sheath delta_leaf_enclosed_mstruct
hidden_sheath_id = hiddenzone_id + tuple(['sheath', 'HiddenElement'])
if hidden_sheath_id not in self.outputs['elements'].keys():
new_sheath_outputs = self.organ_init.__dict__.copy()
self.outputs['elements'][hidden_sheath_id] = new_sheath_outputs
curr_hidden_sheath_outputs = self.outputs['elements'][hidden_sheath_id]
curr_hidden_sheath_outputs['mstruct'] = curr_hiddenzone_outputs['leaf_enclosed_mstruct'] * share_hidden_sheath
curr_hidden_sheath_outputs['max_mstruct'] = curr_hiddenzone_outputs['leaf_enclosed_mstruct'] * share_hidden_sheath
curr_hidden_sheath_outputs['Nstruct'] = curr_hiddenzone_outputs['leaf_enclosed_Nstruct'] * share_hidden_sheath
curr_hidden_sheath_outputs['sucrose'] = curr_hiddenzone_outputs['sucrose'] * share_leaf * share_hidden_sheath
curr_hidden_sheath_outputs['amino_acids'] = curr_hiddenzone_outputs['amino_acids'] * share_leaf * share_hidden_sheath
curr_hidden_sheath_outputs['fructan'] = curr_hiddenzone_outputs['fructan'] * share_leaf * share_hidden_sheath
curr_hidden_sheath_outputs['proteins'] = curr_hiddenzone_outputs['proteins'] * share_leaf * share_hidden_sheath
curr_hidden_sheath_outputs['cytokinins'] = self.model.calculate_init_cytokinins_emerged_tissue(curr_hidden_sheath_outputs['mstruct'])
self.outputs['elements'][hidden_sheath_id] = curr_hidden_sheath_outputs
if self.hydraulics:
# Add to visible part of the sheath
visible_lamina_id = hiddenzone_id + tuple(['blade', 'LeafElement1'])
curr_visible_leaf_inputs = all_elements_inputs[visible_lamina_id]
visible_sheath_id = hiddenzone_id + tuple(['sheath', 'StemElement'])
curr_visible_sheath_inputs = self.inputs['elements'][visible_sheath_id]
curr_visible_sheath_outputs = self.outputs['elements'][visible_sheath_id]
if visible_sheath_id not in self.outputs['elements'].keys():
new_sheath_outputs = self.organ_init.__dict__.copy()
self.outputs['elements'][visible_sheath_id] = new_sheath_outputs
share_visible_leaf = curr_visible_sheath_inputs['length'] / curr_visible_leaf_inputs['length']
curr_visible_sheath_outputs['mstruct'] = curr_visible_leaf_inputs['mstruct'] * share_visible_leaf
curr_visible_sheath_outputs['max_mstruct'] = curr_visible_leaf_inputs['mstruct'] * share_visible_leaf
curr_visible_sheath_outputs['Nstruct'] = curr_visible_leaf_inputs['Nstruct'] * share_visible_leaf
curr_visible_sheath_outputs['sucrose'] = curr_visible_leaf_inputs['sucrose'] * share_visible_leaf
curr_visible_sheath_outputs['amino_acids'] = curr_visible_leaf_inputs['amino_acids'] * share_visible_leaf
curr_visible_sheath_outputs['fructan'] = curr_visible_leaf_inputs['fructan'] * share_visible_leaf
curr_visible_sheath_outputs['proteins'] = curr_visible_leaf_inputs['proteins'] * share_visible_leaf
curr_visible_sheath_outputs['cytokinins'] = self.model.calculate_init_cytokinins_emerged_tissue(curr_visible_sheath_outputs['mstruct']) * share_visible_leaf
self.outputs['elements'][visible_sheath_id] = curr_visible_sheath_outputs
# Remove to visible leaf
curr_visible_leaf_outputs = all_elements_outputs[visible_lamina_id]
curr_visible_leaf_outputs['mstruct'] -= curr_visible_sheath_outputs['mstruct']
curr_visible_leaf_outputs['Nstruct'] -= curr_visible_sheath_outputs['Nstruct']
curr_visible_leaf_outputs['sucrose'] -= curr_visible_sheath_outputs['sucrose']
curr_visible_leaf_outputs['amino_acids'] -= curr_visible_sheath_outputs['amino_acids']
curr_visible_leaf_outputs['fructan'] -= curr_visible_sheath_outputs['fructan']
curr_visible_leaf_outputs['proteins'] -= curr_visible_sheath_outputs['proteins']
self.outputs['elements'][visible_lamina_id] = curr_visible_leaf_outputs
else:
# Add to hidden part of the lamina, if any
if share_hidden_sheath < 1:
hidden_lamina_id = hiddenzone_id + tuple(['blade', 'HiddenElement'])
curr_hidden_lamina_outputs = self.outputs['elements'][hidden_lamina_id]
curr_hidden_lamina_outputs['mstruct'] = curr_hiddenzone_outputs['leaf_enclosed_mstruct'] * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['max_mstruct'] = curr_hiddenzone_outputs['leaf_enclosed_mstruct'] * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['Nstruct'] = curr_hiddenzone_outputs['leaf_enclosed_Nstruct'] * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['sucrose'] = curr_hiddenzone_outputs['sucrose'] * share_leaf * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['amino_acids'] = curr_hiddenzone_outputs['amino_acids'] * share_leaf * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['fructan'] = curr_hiddenzone_outputs['fructan'] * share_leaf * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['proteins'] = curr_hiddenzone_outputs['proteins'] * share_leaf * (1 - share_hidden_sheath)
curr_hidden_lamina_outputs['cytokinins'] = self.model.calculate_init_cytokinins_emerged_tissue(curr_hidden_lamina_outputs['mstruct'])
self.outputs['elements'][hidden_lamina_id] = curr_hidden_lamina_outputs
# Remove in hiddenzone
curr_hiddenzone_outputs = self.outputs['hiddenzone'][hiddenzone_id]
curr_hiddenzone_outputs['leaf_enclosed_mstruct'] = 0
curr_hiddenzone_outputs['leaf_enclosed_Nstruct'] = 0
curr_hiddenzone_outputs['mstruct'] = curr_hiddenzone_outputs['internode_enclosed_mstruct']
curr_hiddenzone_outputs['Nstruct'] = curr_hiddenzone_outputs['internode_enclosed_Nstruct']
curr_hiddenzone_outputs['sucrose'] -= curr_hiddenzone_outputs['sucrose'] * share_leaf
curr_hiddenzone_outputs['amino_acids'] -= curr_hiddenzone_outputs['amino_acids'] * share_leaf
curr_hiddenzone_outputs['fructan'] -= curr_hiddenzone_outputs['fructan'] * share_leaf
curr_hiddenzone_outputs['proteins'] -= curr_hiddenzone_outputs['proteins'] * share_leaf
self.outputs['hiddenzone'][hiddenzone_id] = curr_hiddenzone_outputs
# Turn remobilizing flag to False
self.outputs['hiddenzone'][hiddenzone_id]['leaf_is_remobilizing'] = False
# -- Remobilisation at the end of internode elongation
# Internodes stop to elongate after leaves. We cannot test delta_internode_L > 0 for the cases of short internodes which are mature before GA production.
if hiddenzone_inputs['internode_is_remobilizing']:
# Add to hidden part of the internode
hidden_internode_id = hiddenzone_id + tuple(['internode', 'HiddenElement'])
if hidden_internode_id not in self.outputs['elements'].keys():
new_internode_outputs = self.organ_init.__dict__.copy()
self.outputs['elements'][hidden_internode_id] = new_internode_outputs
curr_hidden_internode_outputs = self.outputs['elements'][hidden_internode_id]
curr_hidden_internode_outputs['mstruct'] += curr_hiddenzone_outputs['internode_enclosed_mstruct']
curr_hidden_internode_outputs['max_mstruct'] = curr_hidden_internode_outputs['mstruct']
curr_hidden_internode_outputs['Nstruct'] += curr_hiddenzone_outputs['internode_enclosed_Nstruct']
curr_hidden_internode_outputs['sucrose'] += curr_hiddenzone_outputs['sucrose']
curr_hidden_internode_outputs['amino_acids'] += curr_hiddenzone_outputs['amino_acids']
curr_hidden_internode_outputs['fructan'] += curr_hiddenzone_outputs['fructan']
curr_hidden_internode_outputs['proteins'] += curr_hiddenzone_outputs['proteins']
curr_hidden_internode_outputs['is_growing'] = False
self.outputs['elements'][hidden_internode_id] = curr_hidden_internode_outputs
# Turn remobilizing flag to False
self.outputs['hiddenzone'][hiddenzone_id]['internode_is_remobilizing'] = False
#: Turn the flag to true after remobilisation in order to Delete Hiddenzone in both MTG and shared_outputs
self.outputs['hiddenzone'][hiddenzone_id]['is_over'] = True
# --------------------------------
# -------------- Roots -----------
# --------------------------------
for root_id, root_inputs in all_roots_inputs.items():
curr_root_outputs = all_roots_outputs[root_id]
axis_id = root_id[:2]
curr_axis_outputs = all_axes_outputs[axis_id]
# Temperature-compensated time (delta_teq)
delta_teq = all_axes_inputs[axis_id]['delta_teq_roots']
# Growth
xylem_water_potential = all_axes_inputs[axis_id].get('xylem_water_potential') # Set at None if hydraulics is False
mstruct_C_growth, mstruct_growth, Nstruct_growth, Nstruct_N_growth = self.model.calculate_roots_mstruct_growth(root_inputs['sucrose'], root_inputs['amino_acids'],
root_inputs['mstruct'], delta_teq, postflowering_stages,
all_axes_inputs[axis_id]['nb_leaves'], xylem_water_potential)
# Respiration growth
curr_root_outputs['Respi_growth'] = RespirationModel.R_growth(mstruct_C_growth)
# Update of root outputs
curr_root_outputs['mstruct'] += mstruct_growth
curr_root_outputs['AA_consumption_mstruct'] = Nstruct_N_growth
curr_root_outputs['sucrose_consumption_mstruct'] = self.model.calculate_roots_s_mstruct_sucrose(mstruct_growth, Nstruct_N_growth)
curr_root_outputs['sucrose'] -= (curr_root_outputs['sucrose_consumption_mstruct'] + curr_root_outputs['Respi_growth'])
curr_root_outputs['Nstruct'] += Nstruct_growth
curr_root_outputs['amino_acids'] -= curr_root_outputs['AA_consumption_mstruct']
curr_root_outputs['delta_mstruct_growth'] = mstruct_growth
self.outputs['roots'][root_id] = curr_root_outputs
# Update of axis outputs
self.outputs['axes'][axis_id] = curr_axis_outputs