Source code for sunpy.sun.models

"""
Solar Physical Models
---------------------
This module contains models of the Sun from various sources:

* ``interior``: `~astropy.table.QTable` of the structure of the solar interior
  as defined in Table 7 of Turck-Chieze et al. (1988)
* ``evolution``: `~astropy.table.QTable` of the evolution of the Sun over time
  as defined in Table 6 of Turck-Chieze et al. (1988)
* :func:`~sunpy.sun.models.differential_rotation`: Function for calculating
  solar differential rotation for different models

References
----------
* `Turck-Chieze et al. (1988), *ApJ*, **335**, 415-424 <https://doi.org/10.1086/166936>`__
"""
import numpy as np

import astropy.units as u
from astropy.coordinates import Longitude
from astropy.table import QTable

from sunpy.sun.constants import sidereal_rotation_rate

__all__ = ["interior", "evolution", "differential_rotation"]


# Radius -  R_sun
_radius = [0, 0.01, 0.022, 0.061, 0.090, 0.120,
           0.166, 0.202, 0.246, 0.281, 0.317,
           0.370, 0.453, 0.611, 0.7304, 0.862,
           0.965, 1.0000] * u.Rsun

# mass -  M_sun
_mass = [0, 0.0001, 0.002, 0.020, 0.057, 0.115,
         0.235, 0.341, 0.470, 0.562, 0.647, 0.748,
         0.854, 0.951, 0.9809, 0.9964, 0.9999, 1.000] * u.Msun

# luminosity -  L_sun
_luminosity = [0, 0.0009, 0.009, 0.154, 0.365,
               0.594, 0.845, 0.940, 0.985, 0.997,
               0.992, 0.9996, 1.000, 1.0, 1.0, 1.0, 1.0, 1.0] * u.Lsun

# temperature -  10^6 K
_temperature = [15.513, 15.48, 15.36, 14.404,
                13.37, 12.25, 10.53, 9.30, 8.035,
                7.214, 6.461, 5.531, 4.426, 2.981,
                2.035, 0.884, 0.1818, 0.005770] * u.MK

# density -  g cm^-3
_density = [147.74, 146.66, 142.73, 116.10, 93.35,
            72.73, 48.19, 34.28, 21.958, 15.157,
            10.157, 5.566, 2.259, 0.4483, 0.1528,
            0.042, 0.00361, 1.99e-7] * u.g*u.cm**-3

_d = {'radius': _radius, 'mass': _mass, 'luminosity': _luminosity,
      'temperature': _temperature, 'density': _density}
interior = QTable(_d)
interior.source = 'Turck-Chieze et al. (1988)'
interior.add_index('radius')

# time -  10^9 years
_time = [0, 0.143, 0.856, 1.863, 2.193, 3.020,
         3.977, 4.587, 5.506, 6.074, 6.577, 7.027,
         7.728, 8.258, 8.7566, 9.805] * u.Gyr

# luminosity -  L_sun
_tluminosity = [0.7688, 0.7248, 0.7621, 0.8156,
                0.8352, 0.8855, 0.9522, 1.0, 1.079,
                1.133, 1.186, 1.238, 1.318, 1.399,
                1.494, 1.760] * u.Lsun

# radius -  R_sun
_tradius = [0.872, 0.885, 0.902, 0.924, 0.932,
            0.953, 0.981, 1.0, 1.035, 1.059, 1.082,
            1.105, 1.143, 1.180, 1.224, 1.361] * u.Rsun

# central temperature -  10^6 K
_tcentral_temperature = [13.35, 13.46, 13.68, 14.08, 14.22, 14.60,
                         15.12, 15.51, 16.18, 16.65, 17.13, 17.62,
                         18.42, 18.74, 18.81, 19.25] * u.MK

_t = {'time': _time, 'luminosity': _tluminosity, 'radius': _tradius,
      'central temperature': _tcentral_temperature}
evolution = QTable(_t)
evolution.source = 'Turck-Chieze et al. (1988)'
evolution.add_index('time')


[docs] @u.quantity_input def differential_rotation(duration: u.s, latitude: u.deg, *, model='howard', frame_time='sidereal'): r""" Computes the change in longitude over a duration for a given latitude. Since the Sun is not a rigid body, different heliographic latitudes rotate with different periods. This is known as solar differential rotation. Parameters ---------- duration : `~astropy.units.Quantity` Amount of time to rotate over. latitude : `~astropy.units.Quantity` Heliographic latitude. model : `str` The differential-rotation model to use. One of: | ``howard`` : Use values from Howard et al. (1990) | ``snodgrass`` : Use values from Snodgrass et. al. (1983) | ``allen`` : Use values from Allen's Astrophysical Quantities, and simpler equation. | ``rigid`` : Use values from `~sunpy.sun.constants.sidereal_rotation_rate`. frame_time : `str` If ``'sidereal'``, returns the change in longitude as referenced to distant stars. If ``'synodic'``, returns the apparent change in longitude as observed by the average orbital motion of Earth, which results in a slower rotation rate. Defaults to ``'sidereal'``. Returns ------- `~astropy.units.Quantity` The change in longitude Notes ----- The rotation rate at a heliographic latitude :math:`\theta` is given by .. math:: A + B \sin^{2} \left (\theta \right ) + C \sin^{4} \left ( \theta \right ) where :math:`A, B, C` are constants that depend on the model: ========= ======= ====== ====== ========== Model A B C Unit ========= ======= ====== ====== ========== howard 2.894 -0.428 -0.370 microrad/s snodgrass 2.851 -0.343 -0.474 microrad/s allen 14.44 -3.0 0 deg/day rigid 14.1844 0 0 deg/day ========= ======= ====== ====== ========== 1 microrad/s is approximately 4.95 deg/day. References ---------- * `Solar surface velocity fields determined from small magnetic features (Howard et al. 1990) <https://doi.org/10.1007/BF00156795>`__ * `A comparison of differential rotation measurements (Beck 2000, includes Snodgrass values) <https://doi.org/10.1023/A:1005226402796>`__ Examples -------- .. minigallery:: sunpy.sun.models.differential_rotation Default rotation calculation over two days at 30 degrees latitude: >>> import numpy as np >>> import astropy.units as u >>> from sunpy.sun.models import differential_rotation >>> differential_rotation(2 * u.day, 30 * u.deg) <Longitude 27.36432679 deg> Default rotation over two days for a number of latitudes: >>> differential_rotation(2 * u.day, np.linspace(-70, 70, 20) * u.deg) <Longitude [22.05449682, 23.03214991, 24.12033958, 25.210281 , 26.21032832, 27.05716463, 27.71932645, 28.19299667, 28.49196765, 28.63509765, 28.63509765, 28.49196765, 28.19299667, 27.71932645, 27.05716463, 26.21032832, 25.210281 , 24.12033958, 23.03214991, 22.05449682] deg> With rotation model 'allen': >>> differential_rotation(2 * u.day, np.linspace(-70, 70, 20) * u.deg, model='allen') <Longitude [23.58186667, 24.14800185, 24.82808733, 25.57737945, 26.34658134, 27.08508627, 27.74430709, 28.28087284, 28.6594822 , 28.85522599, 28.85522599, 28.6594822 , 28.28087284, 27.74430709, 27.08508627, 26.34658134, 25.57737945, 24.82808733, 24.14800185, 23.58186667] deg> """ latitude = latitude.to(u.deg) sin2l = (np.sin(latitude))**2 sin4l = sin2l**2 rot_params = {'howard': [2.894, -0.428, -0.370] * u.urad / u.second, 'snodgrass': [2.851, -0.343, -0.474] * u.urad / u.second, 'allen': [14.44, -3.0, 0] * u.deg / u.day, 'rigid': sidereal_rotation_rate * [1, 0, 0] } if model not in rot_params: raise ValueError("model must equal one of " "{{ {} }}".format(" , ".join(rot_params.keys()))) A, B, C = rot_params[model] # This calculation of the rotation assumes a sidereal frame time. rotation = (A + B * sin2l + C * sin4l) * duration # Applying this correction assumes that the observer is on the Earth, # and that the Earth is at the same distance from the Sun at all times # during the year. if frame_time == 'synodic': rotation -= 0.9856 * u.deg / u.day * duration return Longitude(rotation.to(u.deg))