{ "cells": [ { "cell_type": "markdown", "id": "b603ee6c-02ce-4786-80a2-8bb2072b24b7", "metadata": {}, "source": [ "# Introduction\n", "\n", "The forward model refers to the set of functions in which the electromagnetic spectrum of a planetary atmosphere is calculated based on the information from the reference classes and the selected model parameterisations. In archNEMESIS, all these functions are implemented in the ForwardModel class. In essence, the inputs of the ForwardModel class are the reference classes and the Variables class, and the information within this class is used to perform the radiative transfer calculations and calculate the spectra.\n", "\n", "For the users, running a forward model with archNEMESIS is relatively easy, given the information in the input reference classes is appropriately defined." ] }, { "cell_type": "markdown", "id": "1334399c-b100-49cc-b138-d78d26fe0a75", "metadata": {}, "source": [ "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating forward model\n", "SPECONV = ForwardModel.nemesisfm()\n", "```" ] }, { "cell_type": "markdown", "id": "6a453755-7cce-4fd7-9b93-0b71988239e4", "metadata": {}, "source": [ "We recommend users to check the [Examples](https://archnemesis.readthedocs.io/en/latest/examples/Jupiter_CIRS_nadir_thermal_emission/Jupiter_CIRS.html) to see how this forward model can be applied in practice.\n", "\n" ] }, { "cell_type": "markdown", "id": "f0485585-28f1-4464-a8b3-ba8c3a727986", "metadata": {}, "source": [ "# Structure" ] }, { "cell_type": "markdown", "id": "59c896fa-9b87-467e-8be3-30124681b6ee", "metadata": {}, "source": [ "The figure below shows a sketch of the most relevant functions within the standard forward model implementation in archNEMESIS (i.e., ForwardModel.nemesisfm). As mentioned before, the inputs of the ForwardModel class are the reference classes and the model parameterisations, which are fed into the subprofretg method of this class. In this function, the reference classes are modified based on the selected model parameterisations, and the updated information is returned. After this, the calc_path method of the ForwardModel class splits the atmosphere into a finite number of layers and the atmospheric paths are calculated based on the geometry of the observation. CIRSrad is the main method where the radiative transfer calculations are performed, first calculating the relevant optical properties of each layer (e.g., absorption and scattering optical depths), calculating the internal radiation field if required, and finally calculating the electromagnetic spectrum of the planet given by our observing geometry. After the spectrum has been calculated, the subspecret method is in charge of modifying this modelled spectrum based on any relevant model parameterisations that might be added to mimic some instrument characteristics. Finally, the updated spectrum is convolved with the instrument lineshape to account for the spectral resolution of the instrument. \n", "\n", "Typically, users of archNEMESIS will not generally need to modify most of these functions. The model parameterisations are implemented in *subprofretg* and *subspecret*, and users might want to familiarise with these two routines in case new parameterisations need to be added to the code for their specific use. \n", "\n", "\"Drawing\"" ] }, { "cell_type": "markdown", "id": "0bb35be6-e1e5-49e3-85b4-99bb2df4cf44", "metadata": {}, "source": [ "# Jacobian matrix" ] }, { "cell_type": "markdown", "id": "3c52454c-0433-4c8a-9944-29ed73bfe533", "metadata": {}, "source": [ "The Jacobian matrix is the matrix holding the information about the partial derivatives of the spectrum with respect to the model parameters. The information in this matrix is essential to perform retrievals using the optimal estimation framework, but also provide very useful diagnostic information about the sensitivity of the spectrum to certain atmospheric or surface properties.\n", "\n", "In archNEMESIS, the Jacobian matrix can be calculated either analytically (in cases of non-scattering calculations), or numerically. The choice of calculating the derivatives analytically or numerically is automatically setup by the code using the Variables.INUM flag for each model parameter. When calculating the Jacobian matrix numerically, the forward models are simulated in parallel to increase the speed of the calculations.\n", "\n", "The Jacobian matrix can be easily calculated with archNEMESIS by using the following code:\n", "\n", "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating Jacobian Matrix\n", "YN,KK = ForwardModel.jacobian_nemesis()\n", "```" ] }, { "cell_type": "markdown", "id": "7ab72ecd-9c5f-45dd-8024-41a695f1df7e", "metadata": {}, "source": [ "# Special cases\n", "\n", "In certain cases, the radiative transfer calculations can be optimised so that computations are not unnecessarily repeated. This is typically the case when observing the same atmospheric column in different geometries for example, were most of the calculations can be performed only once (e.g., optical depths in each atmospheric layer will be the same), and only the final calculation of the specific geometry needs to be separate. In archNEMESIS, there are currently two alternative forward models that take advantage of these optimisations, which are explained in the following. In the future, new optimisations of the forward model can be introduced based on users needs." ] }, { "cell_type": "markdown", "id": "ab9cd21f-6ddd-4498-9274-407033ce577f", "metadata": {}, "source": [ "## nemesisSO\n", "\n", "This option of the forward model is optimised for solar occulation observations. In these observations, the atmosphere is assumed to be spherically symmetric and it is observed at a set of different tangent heights through the limb. In this case, all geometries can be calculated simultaneously and the speed of the calculations is substantially increased. This option is only currently available for calculating atmospheric transmissions through the limb, but thermal emission calculations can be easily introduced if needed by the users.\n", "\n", "A forward model of this type, as well as the calculation of the Jacobian matrix, can be easily run by using the following code." ] }, { "cell_type": "markdown", "id": "c7585f6f-96b0-492d-a8b5-5f6e3663c8b5", "metadata": {}, "source": [ "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating forward model\n", "SPECONV = ForwardModel.nemesisSOfm()\n", "\n", "#Calculating the Jacobian Matrix\n", "YN,KK = ForwardModel.jacobian_nemesis(nemesisSO=True)\n", "```" ] }, { "cell_type": "markdown", "id": "db52143b-39e3-471c-97fc-7568346803a6", "metadata": {}, "source": [ "In addition, we recommend the users to check the [Examples](https://archnemesis.readthedocs.io/en/latest/examples/mars_solocc/mars_SO.html) for getting insight of the kind of simulations performed in this mode." ] }, { "cell_type": "markdown", "id": "7ff03f25-ff24-454f-a0ea-77c5529807c8", "metadata": {}, "source": [ "## nemesisL\n", "\n", "This option of the forward model is optimised for the analysis of limb-viewing observations at different tangent heights. By definition, this is equivalent to the solar occultation version, but this focuses in the calculation of the thermal emission from the atmosphere rather than the transmission through the limb. In the future, these two versions of the forward model will be combined.\n", "\n", "A forward model of this type, as well as the calculation of the Jacobian matrix, can be easily run by using the following code.\n", "\n", "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating forward model\n", "SPECONV = ForwardModel.nemesisLfm()\n", "\n", "#Calculating the Jacobian Matrix\n", "YN,KK = ForwardModel.jacobian_nemesis(nemesisL=True)\n", "```" ] }, { "cell_type": "markdown", "id": "7d68d511-2c20-4698-b43d-7344e681df05", "metadata": {}, "source": [ "## nemesisC\n", "\n", "In some cases, we may assume that the same atmospheric column is observed from a variety of geometries. This may be for example if observing the same atmospheric column from different spacecraft, or when we can assume that the atmosphere is symmetric in some region (e.g., latitudinally-symmetric). Similarly, when performing observations when surface-based instrumentation, the same atmosphere may be observed at different angles. In these situations, the speed of the calculations can be substantially increased by solving the radiative transfer equation generally and only separating the geometries at the end. This is particularly true when computing forward models in a multiple scattering scenario, when the internal radiation field of the atmosphere in all directions must be calculated regardless of whether we are modelling one or multiple geometries.\n", "\n", "We introduced the forward model variation nemesisC, that essentially allows the calculation of multiple geometries under multiple scattering conditions. The only limitation is that all geometries must be either nadir-viewing (i.e., 0 $\\geq$ EMISS_ANG < 90) or upward-looking (i.e., 90 < EMISS_ANG $\\leq$ 180).\n", "\n", "This forward model variation can be run by using the code below.\n", "\n", "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating forward model\n", "SPECONV = ForwardModel.nemesisCfm()\n", "```" ] }, { "cell_type": "markdown", "id": "7842b179-5f02-44a4-a222-cdf9745171e4", "metadata": {}, "source": [ "## nemesisdisc\n", "\n", "This version of the forward model is optimised for the analysis of disc-averaged observations with no scattering (i.e., when the gradients can be mostly computed in parallel). In these observations, we need to compute the spectra at a variety of points across the planet's disk, and even from the limb, which are then averaged according to their weights (the averaging points are defined in the Measurement class). In this version of the forward model, the spectra at these points is calculated in parallel.\n", "\n", "This forward model variation, as well as the computation of the jacobian matrix, can be run by using the code below.\n", "\n", "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating forward model\n", "SPECONV = ForwardModel.nemesisdiscfm()\n", "\n", "#Calculating the Jacobian Matrix\n", "YN,KK = ForwardModel.jacobian_nemesis(nemesisdisc=True)\n", "```" ] }, { "cell_type": "markdown", "id": "8bdf5c66-920c-4e72-a648-3eef6d9d924b", "metadata": {}, "source": [ "## nemesisPT\n", "\n", "This version of the forward model is optimised for the analysis of planetary transit observations of exoplanets. In these observations, we essentially model the transmission through the planets limb. However, since the limb is not spatially resolved, the transmission at different altitudes is combined according to the size of the annulus (i.e., 2$\\pi (R_\\mathrm{planet}+h)$). This version of the forward model is optimised because, similar to nemesisSO, it computes the transmission spectra at all the tangent heights simultaneously.\n", "\n", "This forward model variation, as well as the computation of the jacobian matrix, can be run by using the code below.\n", "\n", "```python\n", "import archnemesis as ans\n", "\n", "#Reading the input information from the HDF5 file\n", "Atmosphere,Measurement,Spectroscopy,Scatter,Stellar,Surface,CIA,Layer,Variables,Retrieval,Telluric = ans.Files.read_input_files_hdf5(runname)\n", "\n", "#Initialising ForwardModel class and feeding reference classes as input information\n", "ForwardModel = ans.ForwardModel_0(Atmosphere=Atmosphere,Surface=Surface,Measurement=Measurement,Spectroscopy=Spectroscopy,Stellar=Stellar,Scatter=Scatter,CIA=CIA,Layer=Layer,Variables=Variables,Telluric=Telluric)\n", "\n", "#Calculating forward model\n", "SPECONV = ForwardModel.nemesisPTfm()\n", "\n", "#Calculating the Jacobian Matrix\n", "YN,KK = ForwardModel.jacobian_nemesis(nemesisPT=True)\n", "```" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.13" } }, "nbformat": 4, "nbformat_minor": 5 }