Source code for openairclim.core.calc_dt

"""Calculates temperature changes for each species and scenario."""

import logging

import numpy as np

logger = logging.getLogger(__name__)

# CONSTANTS
#
# from Boucher & Reddy (2008)
# https://doi.org/10.1016/j.enpol.2007.08.039
C_ARR = [0.631, 0.429]  # in K / (W m-2)
D_ARR = [8.4, 409.5]  # in years


[docs] def calc_dtemp(config: dict, spec: str, rf_dict: dict) -> dict: """Calculates the temperature changes for a single species. Args: config (dict): Configuration dictionary from config spec (str): species rf_dict (dict): Dictionary of :class:`numpy.ndarray` of radiative forcing values for time range as defined in config Returns: dict: Dictionary of :class:`numpy.ndarray` of temperature values for time range as defined in config Raises: KeyError: If temperature method is unknown. """ rf_arr = rf_dict[spec] if config["temperature"]["method"] == "Boucher&Reddy": dtemp_arr = calc_dtemp_br2008(config, spec, rf_arr) return {spec: dtemp_arr} else: msg = "Method for temperature change calculation is not valid." logger.warning(msg) raise KeyError(msg)
[docs] def calc_dtemp_br2008(config: dict, spec: str, rf_arr: np.ndarray) -> np.ndarray: """Calculates temperature changes after Boucher and Reddy (2008). https://doi.org/10.1016/j.enpol.2007.08.039 Args: config (dict): configuration dictionary from config spec (str): species rf_arr (numpy.ndarray): array of radiative forcing values Returns: numpy.ndarray: array of temperature values """ time_config = config["time"]["range"] time_range = np.arange(time_config[0], time_config[1], time_config[2], dtype=int) delta_t = time_config[2] # calculate lambda for the species lambda_co2_input = config["temperature"]["CO2"]["lambda"] lambda_co2_br2008 = 1.06 # default value (sum of c_i) if spec == "CO2": efficacy = 1.0 else: efficacy = config["temperature"][spec]["efficacy"] lambda_spec = efficacy * lambda_co2_input # for loop over time dtemp_arr = np.zeros(len(time_range)) i = 0 for year in time_range: j = 0 dtemp = 0 for year_dash in time_range[: (i + 1)]: dtemp = ( dtemp + (lambda_spec / lambda_co2_br2008) * rf_arr[j] * calc_delta_temp_br2008((year - year_dash), C_ARR, D_ARR) * delta_t ) j = j + 1 dtemp_arr[i] = dtemp i = i + 1 return dtemp_arr
[docs] def calc_delta_temp_br2008(t: float, c_arr: list[float], d_arr: list[float]) -> float: """Impulse response function according to Boucher and Reddy (2008), Appendix A. Args: t (float): time c_arr (list[float]): parameter array of impulse response function, Table A1: ci in (K / (W m-2)) d_arr (list[float]): parameter array of impulse response function, Table A1: di in (years) Returns: float: temperature change according to the Boucher and Reddy (2008) model """ delta_temp = 0.0 for c, d in zip(c_arr, d_arr): delta_temp = delta_temp + (c / d) * np.exp(-t / d) return delta_temp