Source code for pyTSEB.clumping_index

# This file is part of pyTSEB for calculating the canopy clumping index
# Copyright 2016 Hector Nieto and contributors listed in the README.md file.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
Created on Apr 6 2015
@author: Hector Nieto (hnieto@ias.csic.es)

Modified on Mar 28 2016
@author: Hector Nieto (hnieto@ias.csic.es)

DESCRIPTION
===========
Routines for calculating the clumping index for both randomly placed canopies and
structured row crops such as vineyards.

PACKAGE CONTENTS
================
* :func:`calc_omega0_Kustas` Nadir viewing clmping factor.
* :func:`calc_omega_Kustas` Clumping index at an incidence angle.
* :func:`calc_omega_rows` Clumping index for row crops at an incidence angle.
"""

import numpy as np
from . import net_radiation as rad

[docs]def calc_omega0_Kustas(LAI, f_C, x_LAD=1, isLAIeff=True): ''' Nadir viewing clmping factor Estimates the clumping factor forcing equal gap fraction between the real canopy and the homogeneous case, after [Kustas1999]_. Parameters ---------- LAI : float Leaf Area Index, it can be either the effective LAI or the real LAI , default input LAI is effective. f_C : float Apparent fractional cover, estimated from large gaps, means that are still gaps within the canopy to be quantified. x_LAD : float, optional Chi parameter for the ellipsoildal Leaf Angle Distribution function of [Campbell1988]_ [default=1, spherical LIDF]. isLAIeff : bool, optional Defines whether the input LAI is effective or local. Returns ------- omega0 : float clumping index at nadir. References ---------- .. [Kustas1999] William P Kustas, John M Norman, Evaluation of soil and vegetation heat flux predictions using a simple two-source model with radiometric temperatures for partial canopy cover, Agricultural and Forest Meteorology, Volume 94, Issue 1, Pages 13-29, http://dx.doi.org/10.1016/S0168-1923(99)00005-2. .. [Campbell1998] Campbell, G. S. & Norman, J. M. (1998), An introduction to environmental biophysics. Springer, New York https://archive.org/details/AnIntroductionToEnvironmentalBiophysics. ''' # Convert input scalars to numpy array LAI, f_C, x_LAD = map(np.asarray, (LAI, f_C, x_LAD)) theta = np.zeros(LAI.shape) # Estimate the beam extinction coefficient based on a ellipsoidal LAD function # Eq. 15.4 of Campbell and Norman (1998) K_be = np.sqrt(x_LAD**2 + np.tan(theta)**2) / \ (x_LAD + 1.774 * (x_LAD + 1.182)**-0.733) if isLAIeff: F = LAI / f_C else: # The input LAI is actually the real LAI F = np.array(LAI) # Calculate the gap fraction of our canopy trans = np.asarray(f_C * np.exp(-K_be * F) + (1.0 - f_C)) trans[trans <= 0] = 1e-36 # and then the nadir clumping factor omega0 = -np.log(trans) / (F * K_be) return omega0
[docs]def calc_omega_Kustas(omega0, theta, w_C=1): ''' Clumping index at an incidence angle. Estimates the clumping index for a given incidence angle assuming randomnly placed canopies. Parameters ---------- omega0 : float clumping index at nadir, estimated for instance by :func:`calc_omega0_Kustas`. theta : float incidence angle (degrees). w_C : float, optional canopy witdth to height ratio, [default = 1]. Returns ------- Omega : float Clumping index at an incidenc angle. References ---------- .. [Kustas1999] William P Kustas, John M Norman, Evaluation of soil and vegetation heat flux predictions using a simple two-source model with radiometric temperatures for partial canopy cover, Agricultural and Forest Meteorology, Volume 94, Issue 1, Pages 13-29, http://dx.doi.org/10.1016/S0168-1923(99)00005-2. ''' w_C = 1.0 / w_C omega = omega0 / (omega0 + (1.0 - omega0) * np.exp(-2.2 * (np.radians(theta))**(3.8 - 0.46 * w_C))) return omega
[docs]def calc_omega_rows(lai, f_c0, theta=0, psi=0, w_c=1, x_lad=1, is_lai_eff=True): ''' Clumping index in row crops. Calculates the clumping index for a given incidence angle assuming structured row crops. Parameters ---------- lai : float Leaf Area Index, it can be either the effective LAI or the real LAI depending on isLAIeff, default input LAI is effective. f_c0 : float Apparent nadir fractional cover, can be expresses as canopy width/row spacing. theta : float, optional Incidence angle (degrees), default nadir. psi : float, optional relative row-sun azimiuth angle w_c : float, optional canopy witdht to height ratio, [default = 1]. x_lad : float, optional Chi parameter for the ellipsoildal Leaf Angle Distribution function of [Campbell1988]_ [default=1, spherical LIDF]. is_lai_eff : bool, optional Defines whether the input LAI is effective or real. [default True] Returns ------- omega : float clumping index at an incidence angle. References ---------- .. [Parry2018] Parry, C. K., H. Nieto, P. Guillevic, N. Agam, W. P. Kustas, J. Alfieri, L. McKee, and A. J. McElrone. An intercomparison of radiation partitioning models in vineyard canopies. Irrigation Science. Pages 1-14. https://doi.org/10.1007/s00271-019-00621-x. ''' # Convert input scalars in numpy arrays lai, f_c0, theta, psi, w_c, x_lad = map( np.asarray, (lai, f_c0, theta, psi, w_c, x_lad)) omega = np.zeros(lai.shape) # Calculate the zenith angle of incidence towards the normal of the row # direction tan_alpha_x = np.tan(np.radians(theta)) * abs(np.sin(np.radians(psi))) # Calculate the fraction that is transmitted trough vegetation f_c = np.asarray(f_c0 * (1.0 + (tan_alpha_x / w_c))) f_c = np.minimum(f_c, 1.0) # Estimate the beam extinction coefficient based on a elipsoidal LAD function # Eq. 15.4 of Campbell and Norman (1998) k_be = rad.calc_K_be_Campbell(theta, x_lad=x_lad) if is_lai_eff is True: f = lai / f_c0 else: f = np.asarray(lai) # Calculate the real gap fraction of our canopy trans = f_c * np.exp(-k_be * f) + (1.0 - f_c) # and then the clumping factor omega[trans > 0] = -np.log(trans[trans > 0]) / (f[trans > 0] * k_be[trans > 0]) return omega