Source code for act.retrievals.radiation

"""
Functions for solar radiation related calculations and retrievals.

"""

import numpy as np
import xarray as xr
from scipy.constants import Stefan_Boltzmann

from act.utils.geo_utils import get_solar_azimuth_elevation


[docs]def calculate_dsh_from_dsdh_sdn( ds, dsdh='down_short_diffuse_hemisp', sdn='short_direct_normal', lat='lat', lon='lon', ): """ Function to derive the downwelling shortwave hemispheric irradiance from the downwelling shortwave diffuse hemispheric irradiance (dsdh) and the shortwave direct normal irradiance (sdn) at a given location (lat,lon) Parameters ---------- ds : xarray.Dataset Xarray dataset where variables for these calculations are stored dsdh : str Name of the downwelling shortwave diffuse hemispheric irradiance field to use. Defaults to downwelling_sw_diffuse_hemisp_irradiance. sdn : str Name of shortwave direct normal irradiance field to use. Defaults to shortwave_direct_normal_irradiance. lat : str Name of latitude field in dataset to use. Defaults to 'lat'. lon : str Name of longitued field in dataset to use. Defaults to 'lon'. Returns ------- ds: xarray.Dataset ACT Xarray Dataset with calculations included as new variables. """ # Calculating Derived Down Short Hemisp elevation, _, _ = get_solar_azimuth_elevation(ds[lat].values, ds[lon].values, ds['time'].values) solar_zenith = np.cos(np.radians(90.0 - elevation)) dsh = ds[dsdh].values + (solar_zenith * ds[sdn].values) # Add data back to DataArray ds['derived_down_short_hemisp'] = xr.DataArray( dsh, dims=['time'], attrs={ 'long_name': 'Derived Downwelling Shortwave Hemispheric Irradiance', 'units': 'W/m^2', }, ) return ds
[docs]def calculate_irradiance_stats( ds, variable=None, variable2=None, diff_output_variable=None, ratio_output_variable=None, threshold=None, ): """ Function to calculate the difference and ratio between two irradiance. Parameters ---------- ds : xarray.Dataset Xarray dataset where variables for these calculations are stored variable : str Name of the first irradiance variable variable2 : str Name of the second irradiance variable diff_output_variable : str Variable name to store the difference results Defaults to 'diff[underscore]'+variable ratio_output_variable : str Variable name to store the ratio results Defaults to 'ratio[underscore]'+variable Returns ------- ds : xarray.Dataset Xarray dataset with calculations included as new variables. """ if variable is None or variable2 is None: return ds if diff_output_variable is None: diff_output_variable = 'diff_' + variable if ratio_output_variable is None: ratio_output_variable = 'ratio_' + variable # --------------------------------- # Calculating Difference # --------------------------------- diff = ds[variable] - ds[variable2] atts = { 'long_name': ' '.join(['Difference between', variable, 'and', variable2]), 'units': 'W/m^2', } da = xr.DataArray(diff, coords={'time': ds['time'].values}, dims=['time'], attrs=atts) ds[diff_output_variable] = da # --------------------------------- # Calculating Irradiance Ratio # --------------------------------- ratio = ds[variable].values / ds[variable2].values if threshold is not None: index = np.where((ds[variable].values < threshold) & (ds[variable2].values < threshold)) ratio[index] = np.nan atts = { 'long_name': ' '.join(['Ratio between', variable, 'and', variable2]), 'units': '', } da = xr.DataArray(ratio, coords={'time': ds['time'].values}, dims=['time'], attrs=atts) ds[ratio_output_variable] = da return ds
[docs]def calculate_net_radiation( ds, ush='up_short_hemisp', ulh='up_long_hemisp', dsh='down_short_hemisp', dlhs='down_long_hemisp_shaded', smooth=None, ): """ Function to calculate the net radiation from upwelling short and long-wave irradiance and downwelling short and long-wave hemisperic irradiances Parameters ---------- ds : xarray.Dataset Xarray dataset where variables for these calculations are stored ush : str Name of the upwelling shortwave hemispheric variable ulh : str Name of the upwelling longwave hemispheric variable dsh : str Name of the downwelling shortwave hemispheric variable dlhs : str Name of the downwelling longwave hemispheric variable smooth : int Smoothing to apply to the net radiation. This will create an additional variable Returns ------- ds : xarray.Dataset Xarray dataset with calculations included as new variables. """ # Calculate Net Radiation ush_da = ds[ush] ulh_da = ds[ulh] dsh_da = ds[dsh] dlhs_da = ds[dlhs] net = -ush_da + dsh_da - ulh_da + dlhs_da atts = {'long_name': 'Calculated Net Radiation', 'units': 'W/m^2'} da = xr.DataArray(net, coords={'time': ds['time'].values}, dims=['time'], attrs=atts) ds['net_radiation'] = da if smooth is not None: net_smoothed = net.rolling(time=smooth).mean() atts = { 'long_name': 'Net Radiation Smoothed by ' + str(smooth), 'units': 'W/m^2', } da = xr.DataArray( net_smoothed, coords={'time': ds['time'].values}, dims=['time'], attrs=atts ) ds['net_radiation_smoothed'] = da return ds
[docs]def calculate_longwave_radiation( ds, temperature_var=None, vapor_pressure_var=None, met_ds=None, emiss_a=0.61, emiss_b=0.06, ): """ Function to calculate longwave radiation during clear and cloudy sky conditions using equations from Monteith and Unsworth 2013, Prata 1996, as reported in Splitt and Bahrmann 1999. Parameters ---------- ds : xarray.Dataset Xarray dataset where variables for these calculations are stored temperature_var : str Name of the temperature variable to use vapor_pressure_var : str Name of the vapor pressure variable to use met_ds : xarray.Dataset Xarray dataset where surface meteorological variables for these calculations are stored if not given, will assume they are in the main dataset passed in emiss_a : float a coefficient for the emissivity calculation of e = a + bT emiss_b : float a coefficient for the emissivity calculation of e = a + bT Returns ------- ds : xarray.Dataset Xarray dataset with 3 new variables; monteith_clear, monteith_cloudy, prata_clear References --------- Monteith, John L., and Mike H. Unsworth. 2013. Principles of Environmental Physics. Edited by John L. Monteith and Mike H. Unsworth. Boston: Academic Press. Prata, A. J. 1996. “A New Long-Wave Formula for Estimating Downward Clear-Sky Radiation at the Surface.” Quarterly Journal of the Royal Meteorological Society 122 (533): 1127–51. Splitt, M. E., and C. P. Bahrmann. 1999. Improvement in the Assessment of SIRS Broadband Longwave Radiation Data Quality. Ninth ARM Science Team Meeting Proceedings, San Antonio, Texas, March 22-26 """ if met_ds is not None: T = met_ds[temperature_var] + 273.15 # C to K e = met_ds[vapor_pressure_var] * 10.0 # kpa to hpa else: T = ds[temperature_var] + 273.15 # C to K e = ds[vapor_pressure_var] * 10.0 # kpa to hpa if len(T) == 0 or len(e) == 0: raise ValueError('Temperature and Vapor Pressure are Needed') # Get Stefan Boltzmann Constant stefan = Stefan_Boltzmann # Calculate sky emissivity from Splitt and Bahrmann 1999 esky = emiss_a + emiss_b * np.sqrt(e) # Base clear sky longwave calculation from Monteith 2013 lw_calc_clear = esky * stefan * T**4 # Prata 1996 Calculation xi = 46.5 * (e / T) lw_calc_clear_prata = (1.0 - (1.0 + xi) * np.exp(-((1.2 + 3.0 * xi) ** 0.5))) * stefan * T**4 # Monteith Cloudy Calcuation as indicated by Splitt and Bahrmann 1999 lw_calc_cldy = esky * (1.0 + (0.178 - 0.00957 * (T - 290.0))) * stefan * T**4 atts = {'long_name': 'Clear Sky Estimate-(Monteith, 1973)', 'units': 'W/m^2'} da = xr.DataArray(lw_calc_clear, coords={'time': ds['time'].values}, dims=['time'], attrs=atts) ds['monteith_clear'] = da atts = {'long_name': 'Overcast Sky Estimate-(Monteith, 1973)', 'units': 'W/m^2'} da = xr.DataArray(lw_calc_cldy, coords={'time': ds['time'].values}, dims=['time'], attrs=atts) ds['monteith_cloudy'] = da atts = {'long_name': 'Clear Sky Estimate-(Prata, 1996)', 'units': 'W/m^2'} da = xr.DataArray( lw_calc_clear_prata, coords={'time': ds['time'].values}, dims=['time'], attrs=atts, ) ds['prata_clear'] = da return ds