:mod:`exo_k.atm2` ================= .. py:module:: exo_k.atm2 .. autoapi-nested-parse:: @author: jeremy leconte Contains classes for atmospheric profiles and their radiative properties. That's where forward models are computed. Module Contents --------------- .. py:class:: Atm_profile2(composition={}, psurf=None, ptop=None, logplev=None, tlev=None, Tsurf=None, Tstrat=None, grav=None, Rp=None, Mgas=None, rcp=0.28, Nlev=20, **kwargs) Bases: :class:`object` A class defining an atmospheric PT profile with some global data (gravity, etc.) The derived class :class:`~exo_k.atm.Atm` handles radiative transfer calculations. Initializes atmospheric profiles :param composition: Keys are molecule names and values the vmr. Vmr can be arrays of size Nlev-1 (i.e. the number of layers). :type composition: dict :param grav: Planet surface gravity (gravity constant with altitude for now). :type grav: float :param Rp: Planet radius. If float, Jupiter radii are assumed. :type Rp: float or Astropy.unit quantity :param rcp: Adiabatic lapse rate for the gas (R/cp) :type rcp: float :param Mgas: Molar mass of the gas (kg/mol). If given, overrides the molar mass computed from composition. :type Mgas: float, optional There are two ways to define the profile. Either define: * Nlev: int Number of level interfaces (Number of layers is Nlev-1) * psurf, Tsurf: float Surface pressure (Pa) and temperature * ptop: float Pressure at the top of the model (Pa) * Tstrat: float Stratospheric temperature or: * logplev: array * tlev: array (same size) These will become the pressures (Pa) and temperatures at the level interfaces. This will be used to define the surface and top pressures. Nlev becomes the size of the arrays. .. warning:: Layers are counted from the top down (increasing pressure order). All methods follow the same convention. .. method:: set_logPT_profile(self, log_plev, tlev) Set the logP-T profile of the atmosphere with a new one :param log_plev: Log pressure (in Pa) at the level surfaces :type log_plev: numpy array :param tlev: temperature at the level surfaces. :type tlev: numpy array (same size) .. method:: set_T_profile(self, tlev) Reset the temperature profile without changing the pressure levels .. method:: compute_pressure_levels(self) Computes various pressure related quantities .. method:: set_adiab_profile(self, Tsurf=None, Tstrat=None) Initializes the logP-T atmospheric profile with an adiabat with index R/cp=rcp :param Tsurf: Surface temperature. :type Tsurf: float :param Tstrat: Temperature of the stratosphere. If None is given, an isothermal atmosphere with T=Tsurf is returned. :type Tstrat: float, optional .. method:: set_grav(self, grav=None) Sets the surface gravity of the planet :param grav: surface gravity (m/s^2) :type grav: float .. method:: set_gas(self, composition_dict) Sets the composition of the atmosphere :param composition_dict: Keys are molecule names, and values are volume mixing ratios. A 'background' value means that the gas will be used to fill up to vmr=1 If they do not add up to 1 and there is no background gas_mix, the rest of the gas_mix is considered transparent. :type composition_dict: dictionary :param compute_col_dens: If True, the column density per layer of the atmosphere is recomputed. This si mostly to save time when we know this will be done later on. :type compute_col_dens: boolean, optional .. method:: set_Mgas(self, Mgas=None) Sets the mean molar mass of the atmosphere. :param Mgas: Mean molar mass (kg/mol). If None is give, the mmm is computed from the composition. :type Mgas: float or array of size Nlay .. method:: set_rcp(self, rcp) Sets the adiabatic index of the atmosphere :param rcp: R/c_p :type rcp: float .. method:: set_Rp(self, Rp) Sets the radius of the planet :param Rp: radius of the planet (m) :type Rp: float .. method:: set_Rstar(self, Rstar) Sets the radius of the star :param Rstar: radius of the star (m) :type Rstar: float .. method:: compute_density(self) Computes the number density (m^-3) profile of the atmosphere .. method:: compute_layer_col_density(self) Computes the column number density (molecules/m^-2) per layer of the atmosphere .. method:: compute_altitudes(self) Compute altitudes of the level surfaces (zlev) and mid layers (zlay). .. method:: compute_area(self) Computes the area of the annulus covered by each layer in a transit setup. .. method:: compute_tangent_path(self) Computes a triangular array of the tangent path length (in m) spent in each layer. self.tangent_path[ilay][jlay] is the length that the ray that is tangent to the ilay layer spends in the jlay>=ilay layer (accounting for a factor of 2 due to symmetry) .. py:class:: Atm2(k_database=None, cia_database=None, wn_range=None, wl_range=None, **kwargs) Bases: :class:`exo_k.atm2.Atm_profile2` Class based on Atm_profile that handles radiative trasnfer calculations. Radiative data are accessed through the :any:`gas_mix.Gas_mix` class. Initialization method that calls Atm_Profile().__init__() and links to Kdatabase and other radiative data. .. method:: set_k_database(self, k_database=None) Change the radiative database used by the :class:`Gas_mix` object handling opacities inside :class:`Atm`. See :any:`gas_mix.Gas_mix.set_k_database` for details. :param k_database: New Kdatabase to use. :type k_database: :class:`Kdatabase` object .. method:: set_cia_database(self, cia_database=None) Change the CIA database used by the :class:`Gas_mix` object handling opacities inside :class:`Atm`. See :any:`gas_mix.Gas_mix.set_cia_database` for details. :param cia_database: New CIAdatabase to use. :type cia_database: :class:`CIAdatabase` object .. method:: set_spectral_range(self, wn_range=None, wl_range=None) Sets the spectral range in which computations will be done by specifying either the wavenumber (in cm^-1) or the wavelength (in micron) range. See :any:`gas_mix.Gas_mix.set_spectral_range` for details. .. method:: spectral_integration(self, spectral_var) Spectrally integrate an array, taking care of whether we are dealing with corr-k or xsec data. :param spectral_var: array to integrate :type spectral_var: array :returns: **var** -- array integrated over wavenumber (and g-space if relevant) :rtype: array .. method:: opacity(self, rayleigh=False, **kwargs) Computes the opacity of each of the layers. See :any:`gas_mix.Gas_mix.cross_section` for details. .. method:: source_function(self, integral=True, source=True) Compute the blackbody source function (Pi*Bnu) for each layer of the atmosphere. :param integral: * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :param source: If False, the source function is put to 0 (for solar absorption calculations) :type source: boolean, optional .. method:: setup_emission_caculation(self, mu_eff=0.5, rayleigh=False, integral=True, source=True, **kwargs) Computes all necessary quantities for emission calculations (opacity, source, etc.) .. method:: emission_spectrum(self, integral=True, mu0=0.5, mu_quad_order=None, **kwargs) Returns the emission flux at the top of the atmosphere (in W/m^2/cm^-1) :param integral: * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :Other Parameters: * **mu0** (*float*) -- Cosine of the quadrature angle use to compute output flux * **mu_quad_order** (*int*) -- If an integer is given, the emission intensity is computed for a number of angles and integrated following a gauss legendre quadrature rule of order `mu_quad_order`. :returns: A spectrum with the Spectral flux at the top of the atmosphere (in W/m^2/cm^-1) :rtype: Spectrum object .. method:: emission_spectrum_quad(self, integral=True, mu_quad_order=3, **kwargs) Returns the emission flux at the top of the atmosphere (in W/m^2/cm^-1) using gauss legendre qudrature of order `mu_quad_order` :param integral: * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :returns: A spectrum with the Spectral flux at the top of the atmosphere (in W/m^2/cm^-1) :rtype: Spectrum object .. method:: emission_spectrum_2stream(self, integral=True, mu0=0.5, method='toon', dtau_min=1e-10, mid_layer=False, rayleigh=False, flux_top_dw=None, source=True, compute_kernel=False, **kwargs) Returns the emission flux at the top of the atmosphere (in W/m^2/cm^-1) :param integral: * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :Other Parameters: * **mu0** (*float*) -- Cosine of the quadrature angle use to compute output flux * **dtau_min** (*float*) -- If the optical depth in a layer is smaller than dtau_min, dtau_min is used in that layer instead. Important as too transparent layers can cause important numerical rounding errors. :returns: A spectrum with the Spectral flux at the top of the atmosphere (in W/m^2/cm^-1) :rtype: Spectrum object .. method:: compute_kernel(self, solve_2stream_nu, epsilon=0.01, mid_layer=False, mu0=0.5, per_unit_mass=True, integral=True, **kwargs) Compute the Jacobian matrix d Heating[lev=i] / d T[lev=j] .. method:: flux_divergence(self, internal_flux=0.0, per_unit_mass=True) Computes the divergence of the net flux in the layers (used to compute heating rates). :func:`emission_spectrum_2stream` needs to be ran first. :param internal_flux: flux coming from below in W/m^2 :type internal_flux: float :param per_unit_mass: If True, the heating rates are normalized by the mass of each layer (result in W/kg). :type per_unit_mass: bool :returns: * **net** (*array*) -- Net fluxes at level surfaces * **H** (*array*) -- Heating rate in each layer (Difference of the net fluxes). Positive means heating. The last value is the net flux impinging on the surface + the internal flux. .. method:: bolometric_fluxes(self, internal_flux=0.0, per_unit_mass=True) Computes the bolometric fluxes at levels and the divergence of the net flux in the layers (used to compute heating rates). :func:`emission_spectrum_2stream` needs to be ran first. :param internal_flux: flux coming from below in W/m^2 :type internal_flux: float :param per_unit_mass: If True, the heating rates are normalized by the mass of each layer (result in W/kg). :type per_unit_mass: bool :returns: * **up** (*array*) -- Upward fluxes at level surfaces * **dw** (*array*) -- Downward fluxes at level surfaces * **net** (*array*) -- Net fluxes at level surfaces * **H** (*array*) -- Heating rate in each layer (Difference of the net fluxes). Positive means heating. The last value is the net flux impinging on the surface + the internal flux. .. method:: exp_minus_tau(self) Sums Exp(-tau) over gauss points .. method:: exp_minus_tau_g(self, g_index) Sums Exp(-tau) over gauss points .. method:: surf_bb(self, integral=True) Computes the surface black body flux (in W/m^2/cm^-1) :param integral: * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :returns: Spectral flux at the surface (in W/m^2/cm^-1) :rtype: Spectrum object .. method:: top_bb(self, integral=True) Computes the top of atmosphere black body flux (in W/m^2/cm^-1) :param integral: If true, the black body is integrated within each wavenumber bin. If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :returns: Spectral flux of a bb at the temperature at the top of atmosphere (in W/m^2/cm^-1) :rtype: Spectrum object .. method:: transmittance_profile(self, **kwargs) Computes the transmittance profile of an atmosphere, i.e. Exp(-tau) for each layer of the model. Real work done in the numbafied function path_integral_corrk/xsec depending on the type of data. .. method:: transmission_spectrum(self, normalized=False, Rstar=None, **kwargs) Computes the transmission spectrum of the atmosphere. In general (see options below), the code returns the transit depth: .. math:: \delta_\nu=(\pi R_p^2+\alpha_\nu)/(\pi R_{star}^2), where .. math:: \alpha_\nu=2 \pi \int_0^{z_{max}} (R_p+z)*(1-e^{-\tau_\nu(z)) d z. :param Rstar: Radius of the host star. Does not need to be given here if as already been specified as an attribute of the self.Atm object. If specified, the result is the transit depth: .. math:: \delta_\nu=(\pi R_p^2+\alpha_\nu)/(\pi R_{star}^2). :type Rstar: float, optional :param normalized: Used only if self.Rstar and Rstar are None: * If True, the result is normalized to the planetary radius: .. math:: \delta_\nu=1+\frac{\alpha_\nu}{\pi R_p^2}. * If False, .. math:: \delta_\nu=\pi R_p^2+\alpha_\nu. :type normalized: boolean, optional :returns: The transit spectrum (see above for normalization options). :rtype: array .. method:: heating_rate(self, Fin=1.0, Tstar=5570.0, szangle=60.0, **kwargs) Computes the heating rate in the atmosphere :param Fin: Bolometric stellar flux at the top of atmopshere (W/m^2). :type Fin: float :param Tstar: Stellar temperature :type Tstar: float :param szangle: Solar zenith angle :type szangle: float :returns: Heating rate in each atmospheric layer (K/s). :rtype: array .. method:: emission_spectrum_exp_integral(self, integral=True, **kwargs) Computes the emission flux at the top of the atmosphere (in W/m^2/cm^-1) .. warning:: This method uses a formulation with exponential integrals that is not yet perceived as accurate enough by the author. It is left for testing only. :param integral: * If true, the black body is integrated within each wavenumber bin. * If not, only the central value is used. False is faster and should be ok for small bins, but True is the correct version. :type integral: boolean, optional :returns: A spectrum with the Spectral flux at the top of the atmosphere (in W/m^2/cm^-1) :rtype: Spectrum object .. function:: convadj(timestep, Nlev, tlev, exner, dp_lay, verbose=False) Computes the heating rates needed to adjust unstable regions of a given atmosphere to a convectively neutral T profile on a given timestep. .. important:: The *layers* here are not the same as the *layers* in the radiative transfer! In the radiative transfer, a layer is the volume between two pressure level boundaries (`plev`). Here, a layer is centered on a pressure level (`plev`) with its temperature `tlev`. Therefore, `dp_lay[0]=play[0]-plev[0]`, `dp_lay[i]=play[i]-play[i-1]`, and `dp_lay[-1]=psurf-play[-1]`. :param timestep: Duration of the adjustment in seconds. :type timestep: float :param Nlev: Number of atmospheric layers :type Nlev: int :param tlev: Temperatures of the atmospheric layers :type tlev: array :param exner: Exner function computed at the layer centers ((p/psurf)**rcp) .. math:: \Pi=(p / p_{s})^{R/c_p} :type exner: array :param dp_lay: Pressure difference between the bottom and top of each layer :type dp_lay: array :returns: Heating rate in each atmospheric layer (K/s). :rtype: array