"""
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))