Example #1
0
    def calc_et(self, tleaf, tair, vpd, pressure, wind, par, gh, gw, rnet):
        """
        Calculate transpiration following Penman-Monteith at the leaf level
        accounting for effects of leaf temperature and feedback on evaporation.
        For example, if leaf temperature is above the leaf temp, it can increase
        vpd, but it also reduves the lw and thus the net rad availble for
        evaporaiton.

        Parameters:
        ----------
        tair : float
            air temperature (deg C)
        tleaf : float
            leaf temperature (deg C)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)
        wind : float
            wind speed (m s-1)
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        gh : float
            boundary layer conductance to heat - free & forced & radiative
            components (mol m-2 s-1)
        gw :float
            conductance to water vapour - stomatal & bdry layer components
            (mol m-2 s-1)
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        Returns:
        --------
        et : float
            transpiration (mol H2O m-2 s-1)
        lambda_et : float
            latent heat flux (W m-2)
        """
        # latent heat of water vapour at air temperature (J mol-1)
        lambda_et = (c.H2OLV0 - 2.365E3 * tair) * c.H2OMW

        # slope of sat. water vapour pressure (e_sat) to temperature curve
        # (Pa K-1), note kelvin conversion in func
        slope = (calc_esat(tair + 0.1) - calc_esat(tair)) / 0.1

        # psychrometric constant (Pa K-1)
        gamma = c.CP * c.AIR_MASS * pressure / lambda_et

        # Y cancels in eqn 10
        arg1 = slope * rnet + (vpd * c.KPA_2_PA) * gh * c.CP * c.AIR_MASS
        arg2 = slope + gamma * gh / gw

        # W m-2
        LE = max(0.0, arg1 / arg2)

        # transpiration, mol H20 m-2 s-1
        et = max(0.0, LE / lambda_et)

        return (et, LE)
def get_values(rh, Ca, tair, par, pressure, C):

    esat = calc_esat(tair)
    ea = rh / 100. * esat
    vpd = (esat - ea) * c.PA_2_KPA
    vpd = np.where(vpd < 0.05, 0.05, vpd)

    #print rh, vpd
    gs_store = []
    et_store = []
    An_store = []
    tair_store = []
    Cs_store = []
    Ci_store = []
    et_conv = c.MOL_WATER_2_G_WATER * c.G_TO_KG * c.SEC_TO_DAY
    an_conv = c.UMOL_TO_MOL * c.MOL_C_TO_GRAMS_C * c.SEC_TO_DAY
    for i,ta in enumerate(tair):

        # We can't vary VPD independent of Tair ...
        Td = get_dewpoint(ta, rh)
        if Td > 0.0:
            (An, gsw, et, LE,
             Cs, Ci) = C.main(ta, par, vpd[i], wind, pressure, Ca)
            gs_store.append(gsw) # mol H20 m-2 s-1
            et_store.append(et * et_conv) # mm d-1
            An_store.append(An * an_conv) # g C m-2 d-1
            Cs_store.append(Cs)
            Ci_store.append(Ci)
            tair_store.append(ta)

    return gs_store, et_store, An_store, tair_store, Cs_store, Ci_store
Example #3
0
def get_values(rh, Ca, tair, par, pressure, C):
    kpa_2_pa = 1000.
    pa_2_kpa = 1.0 / kpa_2_pa

    esat = calc_esat(tair, pressure)
    ea = rh / 100. * esat
    vpd = (esat - ea) * pa_2_kpa
    #print rh, vpd
    gs_store = []
    et_store = []
    An_store = []
    tair_store = []
    for i, ta in enumerate(tair):

        #Td = get_dewpoint(ta, rh)
        #if Td > 0.0:
        (An, gsw, et, LE) = C.main(ta, par, vpd[i], wind, pressure, Ca)
        gs_store.append(gsw)  # mol H20 m-2 s-1
        et_store.append(et * 18 * 0.001 * 86400.)  # mm d-1
        #et_store.append(LE)
        An_store.append(An)  #umol m-2 s-1
        #An_store.append(An*12.*0.000001*86400.) # g C m-2 d-1
        tair_store.append(ta)

    return gs_store, et_store, An_store, tair_store
    def calc_rnet(self, par, tair, tair_k, vpd, pressure):
        """
        Net isothermal radaiation (Rnet, W m-2), i.e. the net radiation that
        would be recieved if leaf and air temperature were the same.

        References:
        ----------
        Jarvis and McNaughton (1986)

        Parameters:
        ----------
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        tair : float
            air temperature (deg C)
        tair_k : float
            air temperature (K)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)

        Returns:
        --------
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        """
        print("**", par)
        # Short wave radiation (W m-2)
        #sw_rad = par * c.PAR_2_SW

        # this matches CABLE's logic ...  which means they are halving the
        # SW_down that is used to compute the direct/diffuse terms and presumbly
        # all other calcs
        sw_rad = par / 4.6  # W m-2

        # absorbed short-wave radiation
        #SW_abs = self.SW_abs * math.cos(math.radians(self.angle)) * SW_rad

        # atmospheric water vapour pressure (Pa)
        ea = max(0.0, calc_esat(tair) - (vpd * c.KPA_2_PA))

        # apparent emissivity for a hemisphere radiating at air temperature
        # eqn D4
        emissivity_atm = 0.642 * (ea / tair_k)**(1.0 / 7.0)

        # isothermal net LW radiaiton at top of canopy, assuming emissivity of
        # the canopy is 1
        net_lw_rad = (1.0 - emissivity_atm) * c.SIGMA * tair_k**4

        # black leaves, table 1, Leuning 1995
        #kd = 0.8

        # isothermal net radiation (W m-2)
        rnet = p.SW_abs * sw_rad - net_lw_rad  #* kd * exp(-kd * lai)

        return rnet
    def calc_rnet(self, par, tair, tair_k, tleaf_k, vpd, pressure):
        """
        Net isothermal radaiation (Rnet, W m-2), i.e. the net radiation that
        would be recieved if leaf and air temperature were the same.

        References:
        ----------
        Jarvis and McNaughton (1986)

        Parameters:
        ----------
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        tair : float
            air temperature (deg C)
        tair_k : float
            air temperature (K)
        tleaf_k : float
            leaf temperature (K)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)

        Returns:
        --------
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        """

        # Short wave radiation (W m-2)
        SW_rad = par * self.PAR_2_SW

        # absorbed short-wave radiation
        SW_abs = self.SW_abs * math.cos(math.radians(self.angle)) * SW_rad

        # atmospheric water vapour pressure (Pa)
        ea = max(0.0, calc_esat(tair, pressure) - (vpd * self.kpa_2_pa))

        # apparent emissivity for a hemisphere radiating at air temperature
        # eqn D4
        emissivity_atm = 0.642 * (ea / tair_k)**(1.0 / 7.0)

        # downward long-wave radiation from the sky (W m-2)
        lw_dw = emissivity_atm * self.sigma * tair_k**4

        # outgoing long-wave radiation at the top of the canopy (leaf) (W m-2)
        lw_up = self.emissivity_leaf * self.sigma * tleaf_k**4

        # isothermal net radiation (W m-2), note W m-2 = J m-2 s-1
        rnet = SW_abs + (lw_up - lw_dw)

        return rnet
Example #6
0
    def calc_rnet(self, par, tair, tair_k, tleaf_k, vpd, pressure):
        """
        Net isothermal radaiation (Rnet, W m-2), i.e. the net radiation that
        would be recieved if leaf and air temperature were the same.

        References:
        ----------
        Jarvis and McNaughton (1986)

        Parameters:
        ----------
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        tair : float
            air temperature (deg C)
        tair_k : float
            air temperature (K)
        tleaf_k : float
            leaf temperature (K)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)

        Returns:
        --------
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        """

        # Short wave radiation (W m-2)
        SW_rad = par * self.PAR_2_SW

        # absorbed short-wave radiation
        #SW_abs = self.SW_abs * math.cos(math.radians(self.angle)) * SW_rad

        # atmospheric water vapour pressure (Pa)
        ea = max(0.0, calc_esat(tair, pressure) - (vpd * self.kpa_2_pa))

        # apparent emissivity for a hemisphere radiating at air temperature
        # eqn D4
        emissivity_atm = 0.642 * (ea / tair_k)**(1.0 / 7.0)

        # isothermal net LW radiaiton at top of canopy, assuming emissivity of
        # the canopy is 1
        net_lw_rad = (1.0 - emissivity_atm) * self.sigma * tair_k**4

        # isothermal net radiation (W m-2)
        rnet = self.SW_abs * SW_rad - net_lw_rad #* kd * exp(-kd * s->lai)

        return rnet
    def calc_rnet(self, par, tair, tair_k, tleaf_k, vpd, pressure):
        """
        Net isothermal radaiation (Rnet, W m-2), i.e. the net radiation that
        would be recieved if leaf and air temperature were the same.

        References:
        ----------
        Jarvis and McNaughton (1986)

        Parameters:
        ----------
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        tair : float
            air temperature (deg C)
        tair_k : float
            air temperature (K)
        tleaf_k : float
            leaf temperature (K)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)

        Returns:
        --------
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        """
        leaf_abs = 0.5
        # Short wave radiation (W m-2)
        SW_rad = par * self.PAR_2_SW

        # absorbed short-wave radiation
        #SW_abs = self.SW_abs * math.cos(math.radians(self.angle)) * SW_rad

        # atmospheric water vapour pressure (Pa)
        ea = max(0.0, calc_esat(tair, pressure) - (vpd * self.kpa_2_pa))

        # apparent emissivity for a hemisphere radiating at air temperature
        # eqn D4
        emissivity_atm = 0.642 * (ea / tair_k)**(1.0 / 7.0)

        # isothermal net LW radiaiton at top of canopy, assuming emissivity of
        # the canopy is 1
        net_lw_rad = (1.0 - emissivity_atm) * self.sigma * tair_k**4

        # isothermal net radiation (W m-2)
        rnet = self.SW_abs * SW_rad - net_lw_rad #* kd * exp(-kd * s->lai)

        return rnet
def get_values(rh, Ca, tair, par, pressure, C):
    kpa_2_pa = 1000.
    pa_2_kpa = 1.0 / kpa_2_pa

    esat = calc_esat(tair, pressure)
    ea = rh / 100. * esat
    vpd = (esat - ea) * pa_2_kpa
    #print rh, vpd
    gs_store = []
    et_store = []
    An_store = []
    tair_store = []
    for i,ta in enumerate(tair):

        #Td = get_dewpoint(ta, rh)
        #if Td > 0.0:
        (An, gsw, et) = C.main(ta, par, vpd[i], wind, pressure, Ca)
        gs_store.append(gsw)
        et_store.append(et*18*0.001*86400.)
        An_store.append(An*12.*0.000001*86400.)
        tair_store.append(ta)
    return gs_store, et_store, An_store, tair_store
Example #9
0
    def calc_et(self, tleaf, tair, vpd, pressure, wind, par, gh, gw,
                rnet):
        """
        Calculate transpiration following Penman-Monteith at the leaf level
        accounting for effects of leaf temperature and feedback on evaporation.
        For example, if leaf temperature is above the leaf temp, it can increase
        vpd, but it also reduves the lw and thus the net rad availble for
        evaporaiton.

        Parameters:
        ----------
        tair : float
            air temperature (deg C)
        tleaf : float
            leaf temperature (deg C)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)
        wind : float
            wind speed (m s-1)
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        gh : float
            boundary layer conductance to heat (mol m-2 s-1)
        gw :float
            conductance to water vapour (mol m-2 s-1)
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        Returns:
        --------
        et : float
            transpiration (mol H2O m-2 s-1)
        lambda_et : float
            latent heat flux (W m-2)
        """
        # latent heat of water vapour at air temperature (j mol-1)
        lambda_et = (self.h2olv0 - 2.365E3 * tair) * self.h2omw

        # slope of sat. water vapour pressure (e_sat) to temperature curve
        # (pa K-1), note kelvin conversion in func
        slope = ((calc_esat(tair + 0.1, pressure) -
                  calc_esat(tair, pressure)) / 0.1)
        #slope = self.calc_slope_of_saturation_vapour_pressure_curve(tair)

        # psychrometric constant
        gamma = self.cp * self.air_mass * pressure / lambda_et

        # Y cancels in eqn 10
        arg1 = (slope * rnet + (vpd * self.kpa_2_pa) * gh * self.cp *
                self.air_mass)
        arg2 = slope + gamma * gh / gw

        # W m-2
        LE = arg1 / arg2

        # transpiration, mol H20 m-2 s-1
        # multiply by 18 (grams)* 0.001 (grams to kg) * 86400.
        # to get to kg m2 d-1 or mm d-1
        et = LE / lambda_et

        # et units = mol H20 m-2 s-1,
        return (et, LE)
def main(fname):

    wtc = read_file(fname)

    # create hourly values for subsequent averaging of fluxes
    wtc["DateTime_hr"] = wtc["DateTime_hr"].apply(\
                            lambda x: pd.to_datetime(x).round('30min'))
    wtc_m = wtc.groupby(
        ['DateTime_hr', 'chamber', 'T_treatment', 'HWtrt', 'combotrt'],
        as_index=False).mean()
    wtc_m = wtc_m.set_index('DateTime_hr')

    st = pd.datetime.strptime('2016-10-20 00:00:00', '%Y-%m-%d %H:%M:%S')
    en = pd.datetime.strptime('2016-11-11 20:00:00', '%Y-%m-%d %H:%M:%S')
    wtc_m = wtc_m[(wtc_m.index >= st) & (wtc_m.index <= en)]

    df_ct = wtc_m[(wtc_m["HWtrt"] == "C") & (wtc_m["PAR"] > 10.0)]
    df_hw = wtc_m[(wtc_m["HWtrt"] == "HW") & (wtc_m["PAR"] > 10.0)]

    PARlimit = 600
    df_ct = df_ct[df_ct["PAR"] > PARlimit]
    df_hw = df_hw[df_hw["PAR"] > PARlimit]

    # Parameters

    # A stuff
    Vcmax25 = 34.0
    Jmax25 = 60.0
    Rd25 = 0.92
    Eaj = 21640.
    Eav = 51780.
    deltaSj = 633.0
    deltaSv = 640.0
    Hdv = 200000.0
    Hdj = 200000.0
    Q10 = 1.92

    # Misc stuff
    leaf_width = 0.01
    SW_abs = 0.86  # absorptance to short_wave rad [0,1], typically 0.4-0.6

    lat = -33.611111
    lon = 150.740694

    # variables though obviously fixed here.
    wind = 8.0
    pressure = 100.0 * c.KPA_2_PA
    g0 = 0.003
    g1 = 2.9
    Ca = 400.
    D0 = 1.5  # Not used
    gamma = 0.0  # Not used
    C = CoupledModel(g0,
                     g1,
                     D0,
                     gamma,
                     Vcmax25,
                     Jmax25,
                     Rd25,
                     Eaj,
                     Eav,
                     deltaSj,
                     deltaSv,
                     Hdv,
                     Hdj,
                     Q10,
                     leaf_width,
                     SW_abs,
                     gs_model="medlyn")
    Et_hw = []
    An_hw = []
    for i in range(len(df_hw)):

        (An, gsw, et, LE) = C.main(df_hw.Tair_al[i],
                                   df_hw.PAR[i],
                                   df_hw.VPD[i],
                                   wind,
                                   pressure,
                                   Ca,
                                   rnet=None)
        Et_hw.append(et * c.MOL_2_MMOL)  # mmol m-2 s-1
        An_hw.append(An)  # umol m-2 s-1

    Et_hw2 = []
    An_hw2 = []
    for i in range(len(df_hw)):
        ea = max(
            0.0,
            calc_esat(df_hw.Tair_al[i], pressure) -
            (df_hw.VPD[i] * c.KPA_2_PA))
        rnet = calc_net_radiation(df_hw.index[i].dayofyear,
                                  df_hw.index[i].hour, lat, lon,
                                  df_hw.PAR[i] * c.PAR_2_SW, df_hw.Tair_al[i],
                                  ea)
        (An, gsw, et, LE) = C.main(df_hw.Tair_al[i],
                                   df_hw.PAR[i],
                                   df_hw.VPD[i],
                                   wind,
                                   pressure,
                                   Ca,
                                   rnet=rnet)
        Et_hw2.append(et * c.MOL_2_MMOL)  # mmol m-2 s-1
        An_hw2.append(An)  # umol m-2 s-1

    width = 9
    height = width / 1.618
    fig = plt.figure(figsize=(width, height))
    fig.subplots_adjust(hspace=0.1)
    fig.subplots_adjust(wspace=0.05)
    plt.rcParams['text.usetex'] = False
    plt.rcParams['font.family'] = "sans-serif"
    plt.rcParams['font.sans-serif'] = "Helvetica"
    plt.rcParams['axes.labelsize'] = 20
    plt.rcParams['font.size'] = 18
    plt.rcParams['legend.fontsize'] = 18
    plt.rcParams['xtick.labelsize'] = 18
    plt.rcParams['ytick.labelsize'] = 18

    ax1 = fig.add_subplot(111)

    x = df_hw.TargTempC_Avg
    y = df_hw.Trans
    x = np.nan_to_num(x)
    y = np.nan_to_num(y)
    xy = np.vstack([x, y])
    z = gaussian_kde(xy)(xy)
    ax1.scatter(x,
                y,
                c=z,
                s=25,
                edgecolor='',
                cmap='Reds',
                alpha=0.7,
                label="HW")
    ax1.scatter(x, Et_hw, color='black', s=5, alpha=0.7, label="Model")
    ax1.scatter(x,
                Et_hw2,
                color='green',
                s=5,
                alpha=0.7,
                label="Varying R$_{net}$")

    ax1.legend(scatterpoints=1,
               loc="upper right",
               frameon=False,
               handletextpad=0.1)
    legend = ax1.get_legend()
    legend.legendHandles[0].set_color("red")
    legend.legendHandles[0]._sizes = [60]
    legend.legendHandles[1]._sizes = [60]
    legend.legendHandles[2]._sizes = [60]

    ax1.locator_params(nbins=4, axis='x')
    ax1.locator_params(nbins=4, axis='y')

    ax1.set_ylim(0, 4)
    ax1.set_xlim(15, 50)

    ax1.set_ylabel('E$_{canopy}$ (mmol m$^{-2}$ s$^{-1}$)')
    ax1.set_xlabel('Canopy temperature ($^\circ$C)')

    #fig.savefig("plots/increasing_g0.pdf", bbox_inches='tight',
    #            pad_inches=0.1)
    fig.savefig("plots/varying_rnet.png",
                dpi=300,
                bbox_inches='tight',
                pad_inches=0.1)
        return (new_Tleaf, et, le_et, gbH, gw)


if __name__ == "__main__":

    from get_days_met_forcing import get_met_data

    doy = 180.
    #
    ## Met data ...
    #
    (par, tair, vpd) = get_met_data(p.lat, p.lon, doy)

    # more realistic VPD
    rh = 40.
    esat = calc_esat(tair)
    ea = rh / 100. * esat
    vpd = (esat - ea) * c.PA_2_KPA
    vpd = np.where(vpd < 0.05, 0.05, vpd)

    #
    ##  Fixed met stuff
    #
    wind = 2.5
    pressure = 101325.0
    Ca = 400.0
    lai = p.LAI

    ##
    ### Run Two-leaf
    ##
Example #12
0
def main():

    doy = 180.
    #
    ## Met data ...
    #
    (par, tair, vpd) = get_met_data(p.lat, p.lon, doy)

    # more realistic VPD
    rh = 40.
    esat = calc_esat(tair)
    ea = rh / 100. * esat
    vpd = (esat - ea) * c.PA_2_KPA
    vpd = np.where(vpd < 0.05, 0.05, vpd)

    #
    ##  Fixed met stuff
    #
    wind = 2.5
    pressure = 101325.0
    Ca = 400.0
    LAI = p.LAI

    ##
    ### Run Big-leaf
    ##
    B = BigLeaf(p, gs_model="medlyn")

    An_bl = np.zeros(48)
    gsw_bl = np.zeros(48)
    et_bl = np.zeros(48)
    tcan_bl = np.zeros(48)

    for i in range(len(par)):

        hod = float(i) / 2. + 1800. / 3600. / 2.

        (An, gsw, et, Tcan) = B.main(p, tair[i], par[i], vpd[i], wind,
                                     pressure, Ca, doy, hod, LAI)

        An_bl[i] = An
        et_bl[i] = et
        tcan_bl[i] = Tcan

    ##
    ### Run 2-leaf
    ##
    T = TwoLeaf(p, gs_model="medlyn")

    An_tl = np.zeros(48)
    et_tl = np.zeros(48)
    tcan_tl = np.zeros(48)

    hod = 0
    for i in range(len(par)):

        (An, et, Tcan, apar, lai_leaf) = T.main(p, tair[i], par[i], vpd[i],
                                                wind, pressure, Ca, doy,
                                                hod / 2., LAI)

        sun_frac = lai_leaf[c.SUNLIT] / np.sum(lai_leaf)
        sha_frac = lai_leaf[c.SHADED] / np.sum(lai_leaf)
        An_tl[i] = np.sum(An)
        et_tl[i] = np.sum(et)
        tcan_tl[i] = (Tcan[c.SUNLIT] * sun_frac) + (Tcan[c.SHADED] * sha_frac)

        hod += 1

    fig = plt.figure(figsize=(16, 4))
    fig.subplots_adjust(hspace=0.1)
    fig.subplots_adjust(wspace=0.2)
    plt.rcParams['text.usetex'] = False
    plt.rcParams['font.family'] = "sans-serif"
    plt.rcParams['font.sans-serif'] = "Helvetica"
    plt.rcParams['axes.labelsize'] = 14
    plt.rcParams['font.size'] = 14
    plt.rcParams['legend.fontsize'] = 10
    plt.rcParams['xtick.labelsize'] = 14
    plt.rcParams['ytick.labelsize'] = 14

    almost_black = '#262626'
    # change the tick colors also to the almost black
    plt.rcParams['ytick.color'] = almost_black
    plt.rcParams['xtick.color'] = almost_black

    # change the text colors also to the almost black
    plt.rcParams['text.color'] = almost_black

    # Change the default axis colors from black to a slightly lighter black,
    # and a little thinner (0.5 instead of 1)
    plt.rcParams['axes.edgecolor'] = almost_black
    plt.rcParams['axes.labelcolor'] = almost_black

    ax1 = fig.add_subplot(131)
    ax2 = fig.add_subplot(132)
    ax3 = fig.add_subplot(133)

    ax1.plot(np.arange(48) / 2., An_bl, label="Big leaf")
    ax1.plot(np.arange(48) / 2., An_tl, label="Two leaf")
    ax1.legend(numpoints=1, loc="best")
    ax1.set_ylabel("$A_{\mathrm{n}}$ ($\mathrm{\mu}$mol m$^{-2}$ s$^{-1}$)")

    ax2.plot(np.arange(48) / 2., et_bl * c.MOL_TO_MMOL, label="Big leaf")
    ax2.plot(np.arange(48) / 2., et_tl * c.MOL_TO_MMOL, label="Two leaf")
    ax2.set_ylabel("E (mmol m$^{-2}$ s$^{-1}$)")
    ax2.set_xlabel("Hour of day")

    ax3.plot(np.arange(48) / 2., tcan_bl, label="Tcanopy$_{1leaf}$")
    ax3.plot(np.arange(48) / 2., tcan_tl, label="Tcanopy$_{2leaf}$")
    ax3.plot(np.arange(48) / 2., tair, label="Tair")
    ax3.set_ylabel("Temperature (deg C)")
    ax3.legend(numpoints=1, loc="best")

    ax1.locator_params(nbins=6, axis="y")
    ax2.locator_params(nbins=6, axis="y")

    plt.show()
    fig.savefig("/Users/%s/Desktop/A_E_Tcan.pdf" % (os.getlogin()),
                bbox_inches='tight',
                pad_inches=0.1)
    def calc_et(self, tleaf, tair, vpd, pressure, wind, par, gh, gw,
                rnet):
        """
        Calculate transpiration following Penman-Monteith at the leaf level
        accounting for effects of leaf temperature and feedback on evaporation.
        For example, if leaf temperature is above the leaf temp, it can increase
        vpd, but it also reduves the lw and thus the net rad availble for
        evaporaiton.

        Parameters:
        ----------
        tair : float
            air temperature (deg C)
        tleaf : float
            leaf temperature (deg C)
        vpd : float
            Vapour pressure deficit (kPa, needs to be in Pa, see conversion
            below)
        pressure : float
            air pressure (using constant) (Pa)
        wind : float
            wind speed (m s-1)
        par : float
            Photosynthetically active radiation (umol m-2 s-1)
        gh : float
            boundary layer conductance to heat (mol m-2 s-1)
        gw :float
            conductance to water vapour (mol m-2 s-1)
        rnet : float
            Net radiation (J m-2 s-1 = W m-2)

        Returns:
        --------
        et : float
            transpiration (mol H2O m-2 s-1)
        lambda_et : float
            latent heat flux (W m-2)
        """
        # latent heat of water vapour at air temperature (j mol-1)
        lambda_et = (self.h2olv0 - 2.365E3 * tair) * self.h2omw

        # slope of sat. water vapour pressure (e_sat) to temperature curve
        # (pa K-1), note kelvin conversion in func
        slope = ((calc_esat(tair + 0.1, pressure) -
                  calc_esat(tair, pressure)) / 0.1)
        #slope = self.calc_slope_of_saturation_vapour_pressure_curve(tair)

        # psychrometric constant
        gamma = self.cp * self.air_mass * pressure / lambda_et

        # Y cancels in eqn 10
        arg1 = (slope * rnet + (vpd * self.kpa_2_pa) * gh * self.cp *
                self.air_mass)
        arg2 = slope + gamma * gh / gw

        # W m-2
        LE = arg1 / arg2

        # transpiration, mol H20 m-2 s-1
        # multiply by 18 (grams)* 0.001 (grams to kg) * 86400.
        # to get to kg m2 d-1 or mm d-1
        et = LE / lambda_et

        # et units = mol H20 m-2 s-1,
        return (et, LE)
Example #14
0
def main():

    lat = -23.575001
    lon = 152.524994
    doy = 180.0
    #
    ## Met data ...
    #
    (par, tair, vpd) = get_met_data(lat, lon, doy)
    wind = 2.5
    pressure = 101325.0
    Ca = 400.0

    # more realistic VPD
    rh = 40.
    esat = calc_esat(tair)
    ea = rh / 100. * esat
    vpd = (esat - ea) * c.PA_2_KPA
    vpd = np.where(vpd < 0.05, 0.05, vpd)

    #plt.plot(vpd)
    #plt.show()
    #sys.exit()

    ## Parameters
    #
    g0 = 0.001
    g1 = 1.5635  # Puechabon
    D0 = 1.5  # kpa
    Vcmax25 = 60.0
    Jmax25 = Vcmax25 * 1.67
    Rd25 = 2.0
    Eaj = 30000.0
    Eav = 60000.0
    deltaSj = 650.0
    deltaSv = 650.0
    Hdv = 200000.0
    Hdj = 200000.0
    Q10 = 2.0
    gamma = 0.0
    leaf_width = 0.02
    LAI = 3.

    # Cambell & Norman, 11.5, pg 178
    # The solar absorptivities of leaves (-0.5) from Table 11.4 (Gates, 1980)
    # with canopies (~0.8) from Table 11.2 reveals a surprising difference.
    # The higher absorptivityof canopies arises because of multiple reflections
    # among leaves in a canopy and depends on the architecture of the canopy.
    SW_abs = 0.8  # use canopy absorptance of solar radiation

    ##
    ### Run Big-leaf
    ##

    B = BigLeaf(g0,
                g1,
                D0,
                gamma,
                Vcmax25,
                Jmax25,
                Rd25,
                Eaj,
                Eav,
                deltaSj,
                deltaSv,
                Hdv,
                Hdj,
                Q10,
                leaf_width,
                SW_abs,
                gs_model="medlyn")

    An_bl = np.zeros(48)
    gsw_bl = np.zeros(48)
    et_bl = np.zeros(48)
    tcan_bl = np.zeros(48)

    hod = 0
    for i in range(len(par)):

        (An_bl[i], gsw_bl[i], et_bl[i],
         tcan_bl[i]) = B.main(tair[i], par[i], vpd[i], wind, pressure, Ca, doy,
                              hod, lat, lon, LAI)

        hod += 1

    ##
    ### Run 2-leaf
    ##

    T = TwoLeaf(g0,
                g1,
                D0,
                gamma,
                Vcmax25,
                Jmax25,
                Rd25,
                Eaj,
                Eav,
                deltaSj,
                deltaSv,
                Hdv,
                Hdj,
                Q10,
                leaf_width,
                SW_abs,
                gs_model="medlyn")

    An_tl = np.zeros(48)
    gsw_tl = np.zeros(48)
    et_tl = np.zeros(48)
    tcan_tl = np.zeros(48)

    hod = 0
    for i in range(len(par)):

        (An_tl[i], gsw_tl[i], et_tl[i],
         tcan_tl[i]) = T.main(tair[i], par[i], vpd[i], wind, pressure, Ca, doy,
                              hod, lat, lon, LAI)

        hod += 1

    ##
    ### Run 2-leaf opt
    ##

    T = TwoLeafOpt(g0,
                   g1,
                   D0,
                   gamma,
                   Vcmax25,
                   Jmax25,
                   Rd25,
                   Eaj,
                   Eav,
                   deltaSj,
                   deltaSv,
                   Hdv,
                   Hdj,
                   Q10,
                   leaf_width,
                   SW_abs,
                   gs_model="medlyn")

    An_tlo = np.zeros(48)
    gsw_tlo = np.zeros(48)
    et_tlo = np.zeros(48)
    tcan_tlo = np.zeros(48)

    hod = 0
    for i in range(len(par)):

        (An_tlo[i], gsw_tlo[i], et_tlo[i],
         tcan_tlo[i]) = T.main(tair[i], par[i], vpd[i], wind, pressure, Ca,
                               doy, hod, lat, lon, LAI)

        hod += 1

    ##
    ### Run 2-leaf Manon
    ##

    Ao = np.zeros(48)
    gso = np.zeros(48)
    Eo = np.zeros(48)

    Aob = np.zeros(48)
    gsob = np.zeros(48)
    Eob = np.zeros(48)

    hod = 0
    for i in range(len(par)):

        cos_zenith = calculate_solar_geometry(doy, hod, lat, lon)
        zenith_angle = np.rad2deg(np.arccos(cos_zenith))
        elevation = 90.0 - zenith_angle
        if elevation > 0.0 and par[i] > 50.0:

            p = declared_params()

            p.PPFD = par[i]
            p.sw_rad_day = par[i] * c.PAR_2_SW
            p.LAI = LAI
            p.coszen = cos_zenith
            p.VPD = vpd[i]
            p.precip = 0
            p.Tair = tair[i]
            p.Vmax25 = Vcmax25
            p.g1 = g1
            p.CO2 = Ca / 1000 * 101.325
            p.JV = 1.67
            p.Rlref = Rd25
            p.Ej = Eaj
            p.Ev = Eav
            p.deltaSv = deltaSv
            p.deltaSj = deltaSj
            p.max_leaf_width = leaf_width
            p.gamstar25 = 4.33  # 42.75 / 101.25 umol m-2 s-1
            p.Kc25 = 41.0264925  # 404.9 umol m-2 s-1
            p.Ko25 = 28208.88  # 278.4 mmol mol-1
            p.O2 = 21.27825  # 210 *1000. / 101.25 210 mmol mol-1
            p.alpha = 0.3
            p.albedo = 0.2
            p.Egamstar = 37830.0
            p.Ec = 79430.0
            p.Eo = 36380.0
            p.P50 = 2.02  # Puechabon
            p.P88 = 4.17
            p.kmax = 0.862457122856143

            _, _, fscale2can = absorbed_radiation_2_leaves(p)
            p = p.append(pd.Series([np.nansum(fscale2can)], index=['fscale']))

            Eo[i], gso[i], Ao[i], __, __ = solve_std(p, p.fc, photo='Farquhar')

            #"""
            try:
                fstom_opt_psi, Eo[i], gso[i], Ao[i], _, _ = profit_psi(
                    p, photo='Farquhar', res='med', case=2)
                p = p.append(
                    pd.Series([fstom_opt_psi], index=['fstom_opt_psi']))

            except (ValueError, AttributeError):
                (Eo[i], gso[i], Ao[i]) = (0., 0., 0.)

            #"""

        hod += 1

    fig = plt.figure(figsize=(16, 4))
    fig.subplots_adjust(hspace=0.1)
    fig.subplots_adjust(wspace=0.2)
    plt.rcParams['text.usetex'] = False
    plt.rcParams['font.family'] = "sans-serif"
    plt.rcParams['font.sans-serif'] = "Helvetica"
    plt.rcParams['axes.labelsize'] = 14
    plt.rcParams['font.size'] = 14
    plt.rcParams['legend.fontsize'] = 10
    plt.rcParams['xtick.labelsize'] = 14
    plt.rcParams['ytick.labelsize'] = 14

    almost_black = '#262626'
    # change the tick colors also to the almost black
    plt.rcParams['ytick.color'] = almost_black
    plt.rcParams['xtick.color'] = almost_black

    # change the text colors also to the almost black
    plt.rcParams['text.color'] = almost_black

    # Change the default axis colors from black to a slightly lighter black,
    # and a little thinner (0.5 instead of 1)
    plt.rcParams['axes.edgecolor'] = almost_black
    plt.rcParams['axes.labelcolor'] = almost_black

    ax1 = fig.add_subplot(131)
    ax2 = fig.add_subplot(132)
    ax3 = fig.add_subplot(133)

    #ax1.plot(np.arange(48)/2., An_bl, label="Big leaf")
    ax1.plot(np.arange(48) / 2., An_tl, label="Two leaf")
    ax1.plot(np.arange(48) / 2., An_tlo, label="Two leaf Opt")
    ax1.plot(np.arange(48) / 2., Ao, label="Two leaf Manon")
    ax1.legend(numpoints=1, loc="best")
    ax1.set_ylabel("$A_{\mathrm{n}}$ ($\mathrm{\mu}$mol m$^{-2}$ s$^{-1}$)")

    #ax2.plot(np.arange(48)/2., et_bl * c.MOL_TO_MMOL, label="Big leaf")
    ax2.plot(np.arange(48) / 2., et_tl * c.MOL_TO_MMOL, label="Two leaf")
    ax2.plot(np.arange(48) / 2., et_tlo * c.MOL_TO_MMOL, label="Two leaf opt")
    ax2.plot(np.arange(48) / 2., Eo, label="Two leaf Manon")
    ax2.set_ylabel("E (mmol m$^{-2}$ s$^{-1}$)")
    ax2.set_xlabel("Hour of day")

    #ax3.plot(np.arange(48)/2., tcan_bl, label="Tcanopy$_{1leaf}$")
    ax3.plot(np.arange(48) / 2., tcan_tl, label="Tcanopy$_{2leaf}$")
    ax3.plot(np.arange(48) / 2., tair, label="Tair")
    ax3.set_ylabel("Temperature (deg C)")
    ax3.legend(numpoints=1, loc="best")

    ax1.locator_params(nbins=6, axis="y")
    ax2.locator_params(nbins=6, axis="y")

    plt.show()
    fig.savefig("/Users/%s/Desktop/A_E_Tcan.pdf" % (os.getlogin()),
                bbox_inches='tight',
                pad_inches=0.1)