Ejemplo n.º 1
0
def test_hydraulic_prop_attributes_the_right_properties_to_the_different_organs(
):
    simple_shoot = potted_syrah()
    simple_shoot.node(simple_shoot.root).vid_base = architecture.mtg_base(
        simple_shoot, vtx_label='inT')

    vid_base = simple_shoot.node(simple_shoot.root).vid_base
    for vtx_id in traversal.post_order2(simple_shoot, vid_base):
        n = simple_shoot.node(vtx_id)
        if n.label.startswith('LI'):
            n.E = 0.
            n.An = 0.

    hydraulic.hydraulic_prop(simple_shoot,
                             mass_conv=18.01528,
                             length_conv=1.e-2,
                             a=2.6,
                             b=2.0,
                             min_kmax=0.)

    for vtx_id in traversal.post_order2(simple_shoot, vid_base):
        n = simple_shoot.node(vtx_id)
        assert hasattr(n, 'Flux')
        assert hasattr(n, 'FluxC')
        if n.label.startswith(('in', 'cx', 'Pet')):
            assert hasattr(n, 'Kmax')
Ejemplo n.º 2
0
def hydraulic_prop(g, mass_conv=18.01528, length_conv=1.e-2, a=2.6, b=2.0, min_kmax=0.):
    """Computes water flux `Flux` and maximum hydraulic conductivity `Kmax` of each hydraulic segment. Both properties
        are then attached to the corresponding mtg nodes.

    Args:
        g (openalea.mtg.MTG): a multiscale tree graph object
        mass_conv (float): [gr mol-1] molar mass of H2O
        length_conv (float): conversion coefficient from the length unit of the mtg to that of [1 m]
        a (float): [kg s-1 MPa-1] slope of the Kh(D) relationship, see :func:`conductivity_max` for details
        b (float): [-] exponent of the Kh(D) relationship, see :func:`conductivity_max` for details
        min_kmax (float): [kg s-1 m MPa-1] minimum value for the maximum conductivity, see :func:`conductivity_max`
            for details

    Returns:
        (openalea.mtg.MTG): the multiscale tree graph object

    Notes:
        The units of **Flux** and **Kmax** properties are related:
            - if `Flux` is given as water flux [kg s-1], then `Kmax` is in [kg m s-1 Pa-1] (or [kg m s-1 MPa-1])
            - else if `Flux` is given as water flux density [kg m-2 s-1], then `Kmax` is in [kg m-1 s-1 Pa-1]
            (or [kg m-1 s-1 MPa-1])
        Transpiration flux density per leaf surface area `E` (propery of the :arg:`mtg`) must be in [mol m-2 s-1],
            otherwise, the :arg:`mass_conv` value must be re-adapted

        The resulting water potential, calculated in :func:`transient_xylem_water_potential` is then given in [MPa]

    """

    vid_base = g.node(g.root).vid_base

    for vtx_id in traversal.post_order2(g, vid_base):
        n = g.node(vtx_id)
        if n.label.startswith('LI'):
            try:
                leaf_area = n.leaf_area * 1.
            except (AttributeError, TypeError):
                leaf_area = surf(n.geometry) * length_conv ** 2  # [m2]
                # Note: The surface of the leaf mesh is overestimated compared to allometry results
                # leaf_area = (0.0175*(n.Length*10.)**1.9057)*LengthConv**2 #[m2]
                n.leaf_area = leaf_area

            n.Flux = (n.E * mass_conv * 1.e-3) * leaf_area
            # n.FluxC = ((n.An)*44.0095*1.e-9)*leaf_area # [kgCO2 s-1]
            n.FluxC = n.An * leaf_area  # [umol s-1]

        elif n.label.startswith(('in', 'cx', 'Pet')):
            n.Flux = sum([vtx.Flux for vtx in n.children()])
            diam = 0.5 * (n.TopDiameter + n.BotDiameter) * length_conv
            n.Kmax = conductivity_max(diam, a, b, min_kmax)

            n.FluxC = sum([vtx.FluxC for vtx in n.children()])

        elif n.label.startswith('rhyzo'):
            n.Flux = sum([vtx.Flux for vtx in n.children()])
            n.FluxC = sum([vtx.FluxC for vtx in n.children()])

            n.Kmax = None

    return g
Ejemplo n.º 3
0
def hydraulic_prop(mtg, vtx_label='inT', MassConv=18.01528, LengthConv=1.e-2,
                   a=2.6, b=2.0, min_kmax=0.):
    """
    Returns water flux, `F` [kg s-1] and maximum stem conductivity [kg m s-1 Pa-1] of each internode.
    
    :Attention:
    1. The units of **F** and **K** are related:
     - if `F` is given as water flux [kg s-1], then `K` must be given as [kg m s-1 Pa-1] (or [kg m s-1 MPa-1])
     - else if `F` is given as water flux density [kg m-2 s-1], then `K` must be given as [kg m-1 s-1 Pa-1] (or [kg m-1 s-1 MPa-1]).
    2. Transpiration flux density per leaf surface area `E` must be in [mol m-2 s-1], otherwise, the `MassConv` value must be readapted.
    
     The resulting water portential, calculated in :func:`transient_xylem_water_potential` is then given in [MPa].
     
    :Parameters:
    - **mtg**: an MTG object
    - **vtx_label**: string, the label prefix of the basal vertex at highest scale
    - **MassConv**: molar mass of H2O [gr mol-1]
    - **LengthConv**: conversion coefficient from the length unit of the mtg to that of 1 m
    - **a** and **b**: respectively the slope and power parameters for the Kh(D) relationship
    - **min_kmax**: float, minimum value for the maximum conductivity [kg s-1 m MPa-1]
    """

    # Getting the basal vertex of the highest scale vertices
    vid_base = mtg.node(mtg.root).vid_base

    for vtx_id in traversal.post_order2(mtg,vid_base):
        n = mtg.node(vtx_id)
        if n.label.startswith('LI'):
            try:
                leaf_area = n.leaf_area*1.
            except:
                leaf_area = surf(n.geometry)*LengthConv**2    #[m2]
#                leaf_area = (0.0175*(n.Length*10.)**1.9057)*LengthConv**2 #[m2]
                n.leaf_area = leaf_area
# Note: The surface of the leaf mesh is overestimated compared to allometry results
            n.Flux = ((n.E)*MassConv*1.e-3)*leaf_area
#            n.FluxC = ((n.An)*44.0095*1.e-9)*leaf_area # [kgCO2 s-1]
            n.FluxC = (n.An)*leaf_area # [umol s-1]

        elif n.label.startswith(('in','cx','Pet')):
            n.Flux = sum([vtx.Flux for vtx in n.children()])
            Diam = 0.5*(n.TopDiameter + n.BotDiameter)*LengthConv
            n.Kmax = k_max(Diam,a,b,min_kmax)

            n.FluxC = sum([vtx.FluxC for vtx in n.children()])

        elif n.label.startswith('rhyzo'):
            n.Flux = sum([vtx.Flux for vtx in n.children()])
            n.FluxC = sum([vtx.FluxC for vtx in n.children()])
            
            n.Kmax = None
            

    return mtg
Ejemplo n.º 4
0
def pipemodel(mtg, rootradius, leafradius, root=None):
    from math import log
    from openalea.mtg.traversal import post_order2
    if root is None:
        roots = mtg.roots(scale=mtg.max_scale())
        assert len(roots) == 1
        root = roots[0]

    vertices = list(post_order2(mtg, root))

    leaves = [vid for vid in vertices if len(mtg.children(vid)) == 0]
    # pipeexponent = log(len(leaves)) / (log(rootradius) - log(leafradius))
    # print pipeexponent
    # invpipeexponent = 1./ pipeexponent

    radiusprop = dict()
    for vid in leaves:
        radiusprop[vid] = leafradius

    nbelems = dict()
    for vid in leaves:
        nbelems[vid] = 1
    for vid in vertices:
        if not vid in nbelems:
            nbelems[vid] = sum([nbelems[child]
                                for child in mtg.children(vid)]) + 1

    print(root, nbelems[root])

    # pipeexponent = log(nbelems[root]) / (log(rootradius) - log(leafradius))
    pipeexponent = (log(rootradius) - log(leafradius)) / log(nbelems[root])
    print(pipeexponent)
    invpipeexponent = 1. / pipeexponent

    for vid in vertices:
        if not vid in radiusprop:
            radiusprop[vid] = leafradius * (nbelems[vid]**pipeexponent)

    # for vid in post_order2(mtg, root):
    #    if not vid in radiusprop:
    #        rad = pow(sum([pow(radiusprop[child], pipeexponent) for child in mtg.children(vid)]), invpipeexponent)
    #        radiusprop[vid] = rad

    return radiusprop
Ejemplo n.º 5
0
def pipemodel(mtg, rootradius, leafradius, root = None):
    from math import log
    from openalea.mtg.traversal import post_order2
    if root is None:
        roots = mtg.roots(scale=mtg.max_scale())
        assert len(roots) == 1
        root = roots[0]

    vertices = list(post_order2(mtg, root))

    leaves = [vid for vid in vertices if len(mtg.children(vid)) == 0]
    #pipeexponent = log(len(leaves)) / (log(rootradius) - log(leafradius))
    #print pipeexponent
    #invpipeexponent = 1./ pipeexponent


    radiusprop = dict()
    for vid in leaves:  radiusprop[vid] = leafradius

    nbelems = dict()
    for vid in leaves:  nbelems[vid] = 1
    for vid in vertices:
        if not vid in nbelems:
            nbelems[vid] = sum([nbelems[child] for child in mtg.children(vid)]) + 1

    print root, nbelems[root]

    #pipeexponent = log(nbelems[root]) / (log(rootradius) - log(leafradius))
    pipeexponent = (log(rootradius) - log(leafradius))/log(nbelems[root]) 
    print pipeexponent
    invpipeexponent = 1./ pipeexponent

    for vid in vertices:
        if not vid in radiusprop:
            radiusprop[vid] = leafradius*(nbelems[vid]**pipeexponent)

    #for vid in post_order2(mtg, root):
    #    if not vid in radiusprop:
    #        rad = pow(sum([pow(radiusprop[child], pipeexponent) for child in mtg.children(vid)]), invpipeexponent)
    #        radiusprop[vid] = rad

    return radiusprop