def main(lst, lst_vza, lai, csp, fgv, ar, mi, nsr, li, mask, soil_roughness, alpha_pt, atmospheric_measurement_height, green_vegetation_emissivity, soil_emissivity, save_component_fluxes, save_component_temperature, save_aerodynamic_parameters, output_file): # Read the required data lst = su.read_snappy_product(lst, 'sharpened_LST')[0].astype(np.float32) vza = su.read_snappy_product(lst_vza, 'sat_zenith_tn')[0].astype(np.float32) lai, geo_coding = su.read_snappy_product(lai, 'lai') lai = lai.astype(np.float32) lad = su.read_snappy_product( csp, 'veg_inclination_distribution')[0].astype(np.float32) frac_cover = su.read_snappy_product(csp, 'veg_fractional_cover')[0].astype( np.float32) h_w_ratio = su.read_snappy_product( csp, 'veg_height_width_ratio')[0].astype(np.float32) leaf_width = su.read_snappy_product(csp, 'veg_leaf_width')[0].astype(np.float32) veg_height = su.read_snappy_product(csp, 'veg_height')[0].astype(np.float32) landcover_band = su.read_snappy_product( csp, 'igbp_classification')[0].astype(np.float32) frac_green = su.read_snappy_product(fgv, 'frac_green')[0].astype(np.float32) z_0M = su.read_snappy_product(ar, 'roughness_length')[0].astype(np.float32) d_0 = su.read_snappy_product(ar, 'zero_plane_displacement')[0].astype( np.float32) ta = su.read_snappy_product(mi, 'air_temperature')[0].astype(np.float32) u = su.read_snappy_product(mi, 'wind_speed')[0].astype(np.float32) ea = su.read_snappy_product(mi, 'vapour_pressure')[0].astype(np.float32) p = su.read_snappy_product(mi, 'air_pressure')[0].astype(np.float32) shortwave_rad_c = su.read_snappy_product( nsr, 'net_shortwave_radiation_canopy')[0].astype(np.float32) shortwave_rad_s = su.read_snappy_product( nsr, 'net_shortwave_radiation_soil')[0].astype(np.float32) longwave_irrad = su.read_snappy_product( li, 'longwave_irradiance')[0].astype(np.float32) mask = su.read_snappy_product(mask, 'mask')[0].astype(np.float32) # Model outputs t_s = np.full(lai.shape, np.nan, np.float32) t_c = np.full(lai.shape, np.nan, np.float32) t_ac = np.full(lai.shape, np.nan, np.float32) h_s = np.full(lai.shape, np.nan, np.float32) h_c = np.full(lai.shape, np.nan, np.float32) le_s = np.full(lai.shape, np.nan, np.float32) le_c = np.full(lai.shape, np.nan, np.float32) g = np.full(lai.shape, np.nan, np.float32) ln_s = np.full(lai.shape, np.nan, np.float32) ln_c = np.full(lai.shape, np.nan, np.float32) r_s = np.full(lai.shape, np.nan, np.float32) r_x = np.full(lai.shape, np.nan, np.float32) r_a = np.full(lai.shape, np.nan, np.float32) u_friction = np.full(lai.shape, np.nan, np.float32) mol = np.full(lai.shape, np.nan, np.float32) n_iterations = np.full(lai.shape, np.nan, np.float32) flag = np.full(lai.shape, 255) # ====================================== # First process bare soil cases i = np.logical_and(lai <= 0, mask == 1) t_s[i] = lst[i] # Calculate soil fluxes [ flag[i], ln_s[i], le_s[i], h_s[i], g[i], r_a[i], u_friction[i], mol[i], n_iterations[i] ] = TSEB.OSEB(lst[i], ta[i], u[i], ea[i], p[i], shortwave_rad_s[i], longwave_irrad[i], soil_emissivity, z_0M[i], d_0[i], atmospheric_measurement_height, atmospheric_measurement_height, calcG_params=[[1], 0.35]) # Set canopy fluxes to 0 ln_c[i] = 0.0 le_c[i] = 0.0 h_c[i] = 0.0 # ====================================== # Then process vegetated cases i = np.logical_and(lai > 0, mask == 1) # Emissivity of canopy containing green and non-green elements. emissivity_veg = green_vegetation_emissivity * frac_green[i] + 0.91 * ( 1 - frac_green[i]) # Caculate component fluxes [ flag[i], t_s[i], t_c[i], t_ac[i], ln_s[i], ln_c[i], le_c[i], h_c[i], le_s[i], h_s[i], g[i], r_s[i], r_x[i], r_a[i], u_friction[i], mol[i], n_iterations[i] ] = TSEB.TSEB_PT(lst[i], vza[i], ta[i], u[i], ea[i], p[i], shortwave_rad_c[i], shortwave_rad_s[i], longwave_irrad[i], lai[i], veg_height[i], emissivity_veg, soil_emissivity, z_0M[i], d_0[i], atmospheric_measurement_height, atmospheric_measurement_height, f_c=frac_cover[i], f_g=frac_green[i], w_C=h_w_ratio[i], leaf_width=leaf_width[i], z0_soil=soil_roughness, alpha_PT=alpha_pt, x_LAD=lad[i], calcG_params=[[1], 0.35], resistance_form=[0, {}]) # Calculate the bulk fluxes le = le_c + le_s h = h_c + h_s r_ns = shortwave_rad_c + shortwave_rad_s r_nl = ln_c + ln_s r_n = r_ns + r_nl band_data = [{ 'band_name': 'sensible_heat_flux', 'band_data': h }, { 'band_name': 'latent_heat_flux', 'band_data': le }, { 'band_name': 'ground_heat_flux', 'band_data': g }, { 'band_name': 'net_radiation', 'band_data': r_n }, { 'band_name': 'quality_flag', 'band_data': flag }] if save_component_fluxes: band_data.extend([{ 'band_name': 'sensible_heat_flux_canopy', 'band_data': h_c }, { 'band_name': 'sensible_heat_flux_soil', 'band_data': h_s }, { 'band_name': 'latent_heat_flux_canopy', 'band_data': le_c }, { 'band_name': 'latent_heat_flux_soil', 'band_data': le_s }, { 'band_name': 'net_longwave_radiation_canopy', 'band_data': ln_c }, { 'band_name': 'net_longwave_radiation_soil', 'band_data': ln_s }]) if save_component_temperature: band_data.extend([{ 'band_name': 'temperature_canopy', 'band_data': t_c }, { 'band_name': 'temperature_soil', 'band_data': t_s }, { 'band_name': 'temperature_canopy_air', 'band_data': t_ac }]) if save_aerodynamic_parameters: band_data.extend([{ 'band_name': 'resistance_surface', 'band_data': r_a }, { 'band_name': 'resistance_canopy', 'band_data': r_x }, { 'band_name': 'resistance_soil', 'band_data': r_s }, { 'band_name': 'friction_velocity', 'band_data': u_friction }, { 'band_name': 'monin_obukhov_length', 'band_data': mol }]) su.write_snappy_product(output_file, band_data, 'turbulentFluxes', geo_coding)
def dis_TSEB(flux_LR, scale, Tr_K, vza, T_A_K, u, ea, p, Sn_C, Sn_S, L_dn, LAI, h_C, emis_C, emis_S, z_0M, d_0, z_u, z_T, UseL=np.inf, leaf_width=0.1, z0_soil=0.01, alpha_PT=1.26, x_LAD=1, f_c=1.0, f_g=1.0, w_C=1.0, resistance_form=[0, {}], calcG_params=[[1], 0.35], massman_profile=[0, []], flux_LR_method='EF', correct_LST=True): '''Priestley-Taylor TSEB Calculates the Priestley Taylor TSEB fluxes using a single observation of composite radiometric temperature and using resistances in series. Parameters ---------- Tr_K : float Radiometric composite temperature (Kelvin). vza : float View Zenith Angle (degrees). T_A_K : float Air temperature (Kelvin). u : float Wind speed above the canopy (m s-1). ea : float Water vapour pressure above the canopy (mb). p : float Atmospheric pressure (mb), use 1013 mb by default. Sn_C : float Canopy net shortwave radiation (W m-2). Sn_S : float Soil net shortwave radiation (W m-2). L_dn : float Downwelling longwave radiation (W m-2). LAI : float Effective Leaf Area Index (m2 m-2). h_C : float Canopy height (m). emis_C : float Leaf emissivity. emis_S : flaot Soil emissivity. z_0M : float Aerodynamic surface roughness length for momentum transfer (m). d_0 : float Zero-plane displacement height (m). z_u : float Height of measurement of windspeed (m). z_T : float Height of measurement of air temperature (m). UseL : float or None, optional Its value will be used to force the Moning-Obukhov stability length. leaf_width : float, optional average/effective leaf width (m). z0_soil : float, optional bare soil aerodynamic roughness length (m). alpha_PT : float, optional Priestley Taylor coeffient for canopy potential transpiration, use 1.26 by default. x_LAD : float, optional Campbell 1990 leaf inclination distribution function chi parameter. f_c : float, optional Fractional cover. f_g : float, optional Fraction of vegetation that is green. w_C : float, optional Canopy width to height ratio. resistance_form : int, optional Flag to determine which Resistances R_x, R_S model to use. * 0 [Default] Norman et al 1995 and Kustas et al 1999. * 1 : Choudhury and Monteith 1988. * 2 : McNaughton and Van der Hurk 1995. calcG_params : list[list,float or array], optional Method to calculate soil heat flux,parameters. * [1],G_ratio]: default, estimate G as a ratio of Rn_S, default Gratio=0.35. * [0],G_constant] : Use a constant G, usually use 0 to ignore the computation of G. * [[2,Amplitude,phase_shift,shape],time] : estimate G from Santanello and Friedl with G_param list of parameters (see :func:`~TSEB.calc_G_time_diff`). Returns ------- flag : int Quality flag, see Appendix for description. T_S : float Soil temperature (Kelvin). T_C : float Canopy temperature (Kelvin). T_AC : float Air temperature at the canopy interface (Kelvin). L_nS : float Soil net longwave radiation (W m-2) L_nC : float Canopy net longwave radiation (W m-2) LE_C : float Canopy latent heat flux (W m-2). H_C : float Canopy sensible heat flux (W m-2). LE_S : float Soil latent heat flux (W m-2). H_S : float Soil sensible heat flux (W m-2). G : float Soil heat flux (W m-2). R_S : float Soil aerodynamic resistance to heat transport (s m-1). R_x : float Bulk canopy aerodynamic resistance to heat transport (s m-1). R_A : float Aerodynamic resistance to heat transport (s m-1). u_friction : float Friction velocity (m s-1). L : float Monin-Obuhkov length (m). n_iterations : int number of iterations until convergence of L. References ---------- .. [Norman1995] J.M. Norman, W.P. Kustas, K.S. Humes, Source approach for estimating soil and vegetation energy fluxes in observations of directional radiometric surface temperature, Agricultural and Forest Meteorology, Volume 77, Issues 3-4, Pages 263-293, http://dx.doi.org/10.1016/0168-1923(95)02265-Y. .. [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. ''' # Initialize HR output variables [ flag, T_S, T_C, T_AC, Ln_S, Ln_C, LE_C, H_C, LE_S, H_S, G, R_S, R_x, R_A, u_friction, L, n_iterations ] = map(np.empty, 17 * [Tr_K.shape]) [ T_S[:], T_C[:], T_AC[:], Ln_S[:], Ln_C[:], LE_C[:], H_C[:], LE_S[:], H_S[:], G[:], R_S[:], R_x[:], R_A[:], u_friction[:], L[:] ] = 15 * [np.nan] n_iterations[:] = 0 flag[:] = NO_VALID_FLAG gt_LR = scale[0] prj_LR = scale[1] gt_HR = scale[2] prj_HR = scale[3] # Create mask that masks high-res pixels where low-res constant ratio # does not exist or is invalid dims_LR = flux_LR.shape dims_HR = Tr_K.shape const_ratio = scale_with_gdalwarp(flux_LR, prj_LR, prj_HR, dims_HR, gt_LR, gt_HR, gdal.GRA_NearestNeighbour) mask = np.ones(const_ratio.shape, dtype=bool) mask[np.logical_or(np.isnan(const_ratio), Tr_K <= 0)] = False # Set the starting conditions for disaggregation. counter = np.ones(const_ratio.shape) counter[~mask] = np.nan T_offset = np.zeros(const_ratio.shape) T_offset[~mask] = np.nan Tr_K_modified = Tr_K.copy() T_A_K_modified = T_A_K.copy() const_ratio_diff = np.zeros(const_ratio.shape) + 1000 const_ratio_HR = np.ones(const_ratio.shape) * np.nan print( 'Forcing low resolution MO stability length as starting point in the iteration' ) if isinstance(UseL, float): L = np.ones(Tr_K.shape) * UseL else: L = scale_with_gdalwarp(UseL, prj_LR, prj_HR, dims_HR, gt_LR, gt_HR, gdal.GRA_NearestNeighbour) del UseL rho = TSEB.met.calc_rho(p, ea, T_A_K) # Air density c_p = TSEB.met.calc_c_p(p, ea) # Heat capacity of air ####################################################################### # For all the pixels in the high res. TSEB # WHILE high-res contant ration != low-res constant ratio # adjust Tair or LST for unmasked pixels # run high-res TSBE for unmaksed pixels # claculate high-res consant ratio # mask pixels where ratios aggree while np.any(mask) and np.nanmax(counter) < DIS_TSEB_ITERATIONS: # Adjust LST or air temperature as required if correct_LST: Tr_K_modified[mask] = _adjust_temperature(Tr_K[mask], T_offset[mask], correct_LST, flux_LR_method) else: T_A_K_modified[mask] = _adjust_temperature(T_A_K[mask], T_offset[mask], correct_LST, flux_LR_method) # Run high-res TSEB on all unmasked pixels flag[mask] = VALID_FLAG # First process bare soil cases print('First process bare soil cases') i = np.array(np.logical_and(LAI == 0, mask)) [ flag[i], Ln_S[i], LE_S[i], H_S[i], G[i], R_A[i], u_friction[i], L[i], n_iterations[i] ] = TSEB.OSEB(Tr_K_modified[i], T_A_K_modified[i], u[i], ea[i], p[i], Sn_S[i], L_dn[i], emis_S[i], z_0M[i], d_0[i], z_u[i], z_T[i], calcG_params=[calcG_params[0], calcG_params[1][i]], UseL=L[i]) T_S[i] = Tr_K_modified[i] T_AC[i] = T_A_K_modified[i] # Set canopy fluxes to 0 Sn_C[i] = 0.0 Ln_C[i] = 0.0 LE_C[i] = 0.0 H_C[i] = 0.0 # Then process vegetated pixels print('Then process vegetated pixels') i = np.array(np.logical_and(LAI > 0, mask)) if resistance_form[0] == 0: resistance_flag = [ resistance_form[0], {k: resistance_form[1][k][i] for k in resistance_form[1]} ] else: resistance_flag = [resistance_form[0], {}] [ flag[i], T_S[i], T_C[i], T_AC[i], Ln_S[i], Ln_C[i], LE_C[i], H_C[i], LE_S[i], H_S[i], G[i], R_S[i], R_x[i], R_A[i], u_friction[i], L[i], n_iterations[i] ] = TSEB.TSEB_PT(Tr_K_modified[i], vza[i], T_A_K_modified[i], u[i], ea[i], p[i], Sn_C[i], Sn_S[i], L_dn[i], LAI[i], h_C[i], emis_C[i], emis_S[i], z_0M[i], d_0[i], z_u[i], z_T[i], leaf_width=leaf_width[i], z0_soil=z0_soil[i], alpha_PT=alpha_PT[i], x_LAD=x_LAD[i], f_c=f_c[i], f_g=f_g[i], w_C=w_C[i], resistance_form=resistance_flag, calcG_params=[calcG_params[0], calcG_params[1][i]], UseL=L[i]) LE_HR = LE_C + LE_S H_HR = H_C + H_S print('Recalculating MO stability length') L = TSEB.MO.calc_L(u_friction, T_A_K_modified, rho, c_p, H_HR, LE_HR) # Calcualte HR constant ratio valid = np.logical_and(mask, flag != NO_VALID_FLAG) if flux_LR_method == 'EF': # Calculate high-res Evaporative Fraction const_ratio_HR[valid] = LE_HR[valid] / (LE_HR[valid] + H_HR[valid]) elif flux_LR_method == 'LE': # Calculate high-res Evaporative Fraction const_ratio_HR[valid] = LE_HR[valid] elif flux_LR_method == 'H': # Calculate high-res Evaporative Fraction const_ratio_HR[valid] = H_HR[valid] # Calculate average constant ratio for each LR pixel from all HR # pixels it contains print( 'Calculating average constant ratio for each LR pixel using valid HR pixels' ) const_ratio_LR = scale_with_gdalwarp(const_ratio_HR, prj_HR, prj_LR, dims_LR, gt_HR, gt_LR, gdal.GRA_Average) const_ratio_HR = scale_with_gdalwarp(const_ratio_LR, prj_LR, prj_HR, dims_HR, gt_LR, gt_HR, gdal.GRA_NearestNeighbour) const_ratio_HR[~mask] = np.nan # Mask the low-res pixels for which constant ratio of hig-res and # low-res runs agree. const_ratio_diff = const_ratio_HR - const_ratio const_ratio_diff[np.logical_or(np.isnan(const_ratio_HR), np.isnan(const_ratio))] = 0 # Calculate temperature offset and ready-pixels mask if flux_LR_method == 'EF': mask = np.abs(const_ratio_diff) > 0.01 step = np.clip(const_ratio_diff * 5, -1, 1) elif flux_LR_method == 'LE' or flux_LR_method == 'H': mask = np.abs(const_ratio_diff) > 5 step = np.clip(const_ratio_diff * 0.01, -1, 1) counter[mask] += 1 T_offset[mask] += step[mask] print('disTSEB iteration %s' % np.nanmax(counter)) print('Recalculating over %s high resolution pixels' % np.size(Tr_K[mask])) #################################################################### # When constant ratios for all pixels match, smooth the resulting Ta adjustment # with a moving window size of 2x2 km and perform a final run of high-res model mask = np.ones(const_ratio.shape, dtype=bool) mask[np.isnan(const_ratio)] = False T_offset_orig = T_offset.copy() T_offset = moving_gaussian_filter(T_offset, int(2000 / float(gt_HR[1]))) # Smooth MO length L = moving_gaussian_filter(L, int(2000 / float(gt_HR[1]))) if correct_LST: Tr_K_modified = Tr_K.copy() Tr_K_modified[mask] = _adjust_temperature(Tr_K[mask], T_offset[mask], correct_LST, flux_LR_method) else: T_A_K_modified = T_A_K.copy() T_A_K_modified[mask] = _adjust_temperature(T_A_K[mask], T_offset[mask], correct_LST, flux_LR_method) flag[mask] = VALID_FLAG # Run high-res TSEB on all unmasked pixels TSEB.ITERATIONS = ITERATIONS_OUT print('Final run of TSEB at high resolution with adjusted temperature') # First process bare soil cases print('First process bare soil cases') i = np.array(np.logical_and(LAI == 0, mask)) [ flag[i], Ln_S[i], LE_S[i], H_S[i], G[i], R_A[i], u_friction[i], L[i], n_iterations[i] ] = TSEB.OSEB(Tr_K_modified[i], T_A_K_modified[i], u[i], ea[i], p[i], Sn_S[i], L_dn[i], emis_S[i], z_0M[i], d_0[i], z_u[i], z_T[i], calcG_params=[calcG_params[0], calcG_params[1][i]], UseL=L[i]) T_S[i] = Tr_K_modified[i] T_AC[i] = T_A_K_modified[i] # Set canopy fluxes to 0 Sn_C[i] = 0.0 Ln_C[i] = 0.0 LE_C[i] = 0.0 H_C[i] = 0.0 # Then process vegetated pixels print('Then process vegetated pixels') i = np.array(np.logical_and(LAI > 0, mask)) if resistance_form[0] == 0: resistance_flag = [ resistance_form[0], {k: resistance_form[1][k][i] for k in resistance_form[1]} ] else: resistance_flag = [resistance_form[0], {}] [ flag[i], T_S[i], T_C[i], T_AC[i], Ln_S[i], Ln_C[i], LE_C[i], H_C[i], LE_S[i], H_S[i], G[i], R_S[i], R_x[i], R_A[i], u_friction[i], L[i], n_iterations[i] ] = TSEB.TSEB_PT(Tr_K_modified[i], vza[i], T_A_K_modified[i], u[i], ea[i], p[i], Sn_C[i], Sn_S[i], L_dn[i], LAI[i], h_C[i], emis_C[i], emis_S[i], z_0M[i], d_0[i], z_u[i], z_T[i], leaf_width=leaf_width[i], z0_soil=z0_soil[i], alpha_PT=alpha_PT[i], x_LAD=x_LAD[i], f_c=f_c[i], f_g=f_g[i], w_C=w_C[i], resistance_form=resistance_flag, calcG_params=[calcG_params[0], calcG_params[1][i]], UseL=L[i]) return [ flag, T_S, T_C, T_AC, Ln_S, Ln_C, LE_C, H_C, LE_S, H_S, G, R_S, R_x, R_A, u_friction, L, n_iterations, T_offset, counter, T_offset_orig ]
def run_TSEB(self, in_data, mask=None): print("Processing...") if mask is None: mask = np.ones(in_data['LAI'].shape) # Create the output dictionary out_data = dict() for field in self._get_output_structure(): out_data[field] = np.zeros(in_data['LAI'].shape) + np.NaN # Esimate diffuse and direct irradiance difvis, difnir, fvis, fnir = rad.calc_difuse_ratio(in_data['S_dn'], in_data['SZA'], press=in_data['p']) out_data['fvis'] = fvis out_data['fnir'] = fnir out_data['Skyl'] = difvis * fvis + difnir * fnir out_data['S_dn_dir'] = in_data['S_dn'] * (1.0 - out_data['Skyl']) out_data['S_dn_dif'] = in_data['S_dn'] * out_data['Skyl'] #====================================== # First process bare soil cases noVegPixels = in_data['LAI'] <= 0 noVegPixels = np.logical_or.reduce( (in_data['f_c'] <= 0.01, in_data['LAI'] <= 0, np.isnan(in_data['LAI']))) #in_data['LAI'][noVegPixels] = 0 #in_data['f_c'][noVegPixels] = 0 i = np.array(np.logical_and(noVegPixels, mask == 1)) # Calculate roughness out_data['z_0M'][i] = in_data['z0_soil'][i] out_data['d_0'][i] = 5 * out_data['z_0M'][i] # Net shortwave radition for bare soil spectraGrdOSEB = out_data['fvis'] * \ in_data['rho_vis_S'] + out_data['fnir'] * in_data['rho_nir_S'] out_data['Sn_S1'][i] = (1. - spectraGrdOSEB[i]) * \ (out_data['S_dn_dir'][i] + out_data['S_dn_dif'][i]) # Other fluxes for bare soil if self.model_type == 'DTD': T_S_K = in_data['T_R1'][i] T0_K = (in_data['T_R0'][i], in_data['T_A0'][i]) elif self.model_type == 'TSEB_PT': T_S_K = in_data['T_R1'][i] T0_K = [] else: T_S_K = in_data['T_S'][i] T0_K = [] [ out_data['flag'][i], out_data['Ln_S1'][i], out_data['LE_S1'][i], out_data['H_S1'][i], out_data['G1'][i], out_data['R_A1'][i], out_data['u_friction'][i], out_data['L'][i], out_data['n_iterations'][i] ] = TSEB.OSEB(T_S_K, in_data['T_A1'][i], in_data['u'][i], in_data['ea'][i], in_data['p'][i], out_data['Sn_S1'][i], in_data['L_dn'][i], in_data['emis_S'][i], out_data['z_0M'][i], out_data['d_0'][i], in_data['z_u'][i], in_data['z_T'][i], calcG_params=[self.G_form[0], self.G_form[1][i]], T0_K=T0_K) # Set canopy fluxes to 0 out_data['Sn_C1'][i] = 0.0 out_data['Ln_C1'][i] = 0.0 out_data['LE_C1'][i] = 0.0 out_data['H_C1'][i] = 0.0 #====================================== # Then process vegetated cases i = np.array(np.logical_and(~noVegPixels, mask == 1)) # Calculate roughness out_data['z_0M'][i], out_data['d_0'][i] = \ res.calc_roughness(in_data['LAI'][i], in_data['h_C'][i], w_C = in_data['w_C'][i], landcover = in_data['landcover'][i], f_c = in_data['f_c'][i]) # Net shortwave radiation for vegetation F = np.zeros(in_data['LAI'].shape) F[i] = in_data['LAI'][i] / in_data['f_c'][i] # Clumping index omega0, Omega = np.zeros(in_data['LAI'].shape), np.zeros( in_data['LAI'].shape) omega0[i] = CI.calc_omega0_Kustas(in_data['LAI'][i], in_data['f_c'][i], x_LAD=in_data['x_LAD'][i], isLAIeff=True) if self.p['calc_row'][0] == 0: # randomly placed canopies Omega[i] = CI.calc_omega_Kustas(omega0[i], in_data['SZA'][i], w_C=in_data['w_C'][i]) else: Omega[i] = CI.calc_omega_Kustas(omega0[i], in_data['SZA'][i], w_C=in_data['w_C'][i]) LAI_eff = F * Omega [out_data['Sn_C1'][i], out_data['Sn_S1'][i] ] = rad.calc_Sn_Campbell(in_data['LAI'][i], in_data['SZA'][i], out_data['S_dn_dir'][i], out_data['S_dn_dif'][i], out_data['fvis'][i], out_data['fnir'][i], in_data['rho_vis_C'][i], in_data['tau_vis_C'][i], in_data['rho_nir_C'][i], in_data['tau_nir_C'][i], in_data['rho_vis_S'][i], in_data['rho_nir_S'][i], x_LAD=in_data['x_LAD'][i], LAI_eff=LAI_eff[i]) # Model settings calcG_params = [self.G_form[0], self.G_form[1][i]] resistance_form = [ self.resistance_form, {k: self.res_params[k][i] for k in self.res_params} ] # Other fluxes for vegetation if self.model_type == 'DTD': [out_data['flag'][i], out_data['T_S1'][i], out_data['T_C1'][i], out_data['T_AC1'][i], out_data['Ln_S1'][i], out_data['Ln_C1'][i], out_data['LE_C1'][i], out_data['H_C1'][i], out_data['LE_S1'][i], out_data['H_S1'][i], out_data['G1'][i], out_data['R_S1'][i], out_data['R_x1'][i], out_data['R_A1'][i], out_data['u_friction'][i], out_data['L'][i], out_data['Ri'], out_data['n_iterations'][i]] = \ TSEB.DTD(in_data['T_R0'][i], in_data['T_R1'][i], in_data['VZA'][i], in_data['T_A0'][i], in_data['T_A1'][i], in_data['u'][i], in_data['ea'][i], in_data['p'][i], out_data['Sn_C1'][i], out_data['Sn_S1'][i], in_data['L_dn'][i], in_data['LAI'][i], in_data['h_C'][i], in_data['emis_C'][i], in_data['emis_S'][i], out_data['z_0M'][i], out_data['d_0'][i], in_data['z_u'][i], in_data['z_T'][i], f_c=in_data['f_c'][i], w_C=in_data['w_C'][i], f_g=in_data['f_g'][i], leaf_width=in_data['leaf_width'][i], z0_soil=in_data['z0_soil'][i], alpha_PT=in_data['alpha_PT'][i], x_LAD=in_data['x_LAD'][i], calcG_params=calcG_params, resistance_form=resistance_form) elif self.model_type == 'TSEB_PT': [out_data['flag'][i], out_data['T_S1'][i], out_data['T_C1'][i], out_data['T_AC1'][i], out_data['Ln_S1'][i], out_data['Ln_C1'][i], out_data['LE_C1'][i], out_data['H_C1'][i], out_data['LE_S1'][i], out_data['H_S1'][i], out_data['G1'][i], out_data['R_S1'][i], out_data['R_x1'][i], out_data['R_A1'][i], out_data['u_friction'][i], out_data['L'][i], out_data['n_iterations'][i]] = \ TSEB.TSEB_PT(in_data['T_R1'][i], in_data['VZA'][i], in_data['T_A1'][i], in_data['u'][i], in_data['ea'][i], in_data['p'][i], out_data['Sn_C1'][i], out_data['Sn_S1'][i], in_data['L_dn'][i], in_data['LAI'][i], in_data['h_C'][i], in_data['emis_C'][i], in_data['emis_S'][i], out_data['z_0M'][i], out_data['d_0'][i], in_data['z_u'][i], in_data['z_T'][i], f_c=in_data['f_c'][i], f_g=in_data['f_g'][i], w_C=in_data['w_C'][i], leaf_width=in_data['leaf_width'][i], z0_soil=in_data['z0_soil'][i], alpha_PT=in_data['alpha_PT'][i], x_LAD=in_data['x_LAD'][i], calcG_params=calcG_params, resistance_form=resistance_form) elif self.model_type == 'TSEB_2T': # Run TSEB with the component temperatures T_S and T_C [out_data['flag'][i], out_data['T_AC1'][i], out_data['Ln_S1'][i], out_data['Ln_C1'][i], out_data['LE_C1'][i], out_data['H_C1'][i], out_data['LE_S1'][i], out_data['H_S1'][i], out_data['G1'][i], out_data['R_S1'][i], out_data['R_x1'][i], out_data['R_A1'][i], out_data['u_friction'][i], out_data['L'][i], out_data['n_iterations'][i]] = \ TSEB.TSEB_2T(in_data['T_C'][i], in_data['T_S'][i], in_data['T_A1'][i], in_data['u'][i], in_data['ea'][i], in_data['p'][i], out_data['Sn_C1'][i], out_data['Sn_S1'][i], in_data['L_dn'][i], in_data['LAI'][i], in_data['h_C'][i], in_data['emis_C'][i], in_data['emis_S'][i], out_data['z_0M'][i], out_data['d_0'][i], in_data['z_u'][i], in_data['z_T'][i], f_c=in_data['f_c'][i], f_g=in_data['f_g'][i], w_C=in_data['w_C'][i], leaf_width=in_data['leaf_width'][i], z0_soil=in_data['z0_soil'][i], alpha_PT=in_data['alpha_PT'][i], x_LAD=in_data['x_LAD'][i], calcG_params=calcG_params, resistance_form=resistance_form) # Calculate the bulk fluxes out_data['LE1'] = out_data['LE_C1'] + out_data['LE_S1'] out_data['LE_partition'] = out_data['LE_C1'] / out_data['LE1'] out_data['H1'] = out_data['H_C1'] + out_data['H_S1'] out_data['R_ns1'] = out_data['Sn_C1'] + out_data['Sn_S1'] out_data['R_nl1'] = out_data['Ln_C1'] + out_data['Ln_S1'] out_data['R_n1'] = out_data['R_ns1'] + out_data['R_nl1'] out_data['delta_R_n1'] = out_data['Sn_C1'] + out_data['Ln_C1'] print("Finished processing!") return out_data