#    Copyright Brandon Stafford
#
#    This file is part of Pysolar.
#
#    Pysolar is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 3 of the License, or
#    (at your option) any later version.
#
#    Pysolar is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with Pysolar. If not, see <http://www.gnu.org/licenses/>.

"""This file is consists of numerical constants for calculating corrections,
such as the wiggling ("nutation") of the axis of the earth. It also includes
functions for building dictionaries of polynomial functions for rapid
calculation of corrections.

Most of the constants come from a 2005 paper by Reda and Andreas:

I. Reda and A. Andreas, "Solar Position Algorithm for Solar Radiation
Applications," National Renewable Energy Laboratory, NREL/TP-560-34302,
revised November 2005.

http://www.osti.gov/bridge/servlets/purl/15003974-iP3z6k/native/15003974.PDF

However, it seems that Reda and Andreas took the bulk of the constants
(L0, etc.) from Pierre Bretagnon and Gerard Francou's Variations Seculaires
des Orbites Planetaires, or VSOP87:

http://en.wikipedia.org/wiki/Secular_variations_of_the_planetary_orbits#VSOP87

See also ftp://ftp.imcce.fr/pub/ephem/planets/vsop87/VSOP87D.ear

"""

aberration_coeffs = None

def get_aberration_coeffs():
    """This function builds a dictionary of polynomial functions from a list of
    coefficients, so that the functions can be called by name. This is used in
    calculating nutation.
    """
    global aberration_coeffs
    if aberration_coeffs == None :
        aberration_coeffs = dict \
          (
            (name, (lambda a, b, c, d: lambda x: a + b * x + c * x ** 2 + (x ** 3) / d)(*coeffs))
            for name, coeffs in
                (
                    ('ArgumentOfLatitudeOfMoon', (93.27191, 483202.017538, -0.0036825, 327270.0)),
                    ('LongitudeOfAscendingNode', (125.04452, -1934.136261, 0.0020708, 450000.0)),
                    ('MeanElongationOfMoon', (297.85036, 445267.111480, -0.0019142, 189474.0)),
                    ('MeanAnomalyOfMoon', (134.96298, 477198.867398, 0.0086972, 56250.0)),
                    ('MeanAnomalyOfSun', (357.52772, 35999.050340, -0.0001603, -300000.0)),
                )
          )
    #end if
    return \
        aberration_coeffs
#end get_aberration_coeffs

earth_radius = 6378140.0  # meters
earth_axis_inclination = 23.45  # degrees
seconds_per_day = 86400

standard_pressure = 101325.00  # pascals
standard_temperature = 288.15  # kelvin
celsius_offset = 273.15  # subtract from kelvin to get deg C, add to deg C to get kelvin
earth_temperature_lapse_rate = -0.0065  # change in temperature with height, kelvin/metre
air_gas_constant = 8.31432  # N*m/s^2
earth_gravity = 9.80665  # m/s^2 or N/kg
earth_atmosphere_molar_mass = 0.0289644  # kg/mol

aberration_sin_terms = \
    [
        (0,0,0,0,1),
        (-2,0,0,2,2),
        (0,0,0,2,2),
        (0,0,0,0,2),
        (0,1,0,0,0),
        (0,0,1,0,0),
        (-2,1,0,2,2),
        (0,0,0,2,1),
        (0,0,1,2,2),
        (-2,-1,0,2,2),
        (-2,0,1,0,0),
        (-2,0,0,2,1),
        (0,0,-1,2,2),
        (2,0,0,0,0),
        (0,0,1,0,1),
        (2,0,-1,2,2),
        (0,0,-1,0,1),
        (0,0,1,2,1),
        (-2,0,2,0,0),
        (0,0,-2,2,1),
        (2,0,0,2,2),
        (0,0,2,2,2),
        (0,0,2,0,0),
        (-2,0,1,2,2),
        (0,0,0,2,0),
        (-2,0,0,2,0),
        (0,0,-1,2,1),
        (0,2,0,0,0),
        (2,0,-1,0,1),
        (-2,2,0,2,2),
        (0,1,0,0,1),
        (-2,0,1,0,1),
        (0,-1,0,0,1),
        (0,0,2,-2,0),
        (2,0,-1,2,1),
        (2,0,1,2,2),
        (0,1,0,2,2),
        (-2,1,1,0,0),
        (0,-1,0,2,2),
        (2,0,0,2,1),
        (2,0,1,0,0),
        (-2,0,2,2,2),
        (-2,0,1,2,1),
        (2,0,-2,0,1),
        (2,0,0,0,1),
        (0,-1,1,0,0),
        (-2,-1,0,2,1),
        (-2,0,0,0,1),
        (0,0,2,2,1),
        (-2,0,2,0,1),
        (-2,1,0,2,1),
        (0,0,1,-2,0),
        (-1,0,1,0,0),
        (-2,1,0,0,0),
        (1,0,0,0,0),
        (0,0,1,2,0),
        (0,0,-2,2,2),
        (-1,-1,1,0,0),
        (0,1,1,0,0),
        (0,-1,1,2,2),
        (2,-1,-1,2,2),
        (0,0,3,2,2),
        (2,-1,0,2,2),
    ]

nutation_coefficients = \
    [
        (-171996,-174.2,92025,8.9),
        (-13187,-1.6,5736,-3.1),
        (-2274,-0.2,977,-0.5),
        (2062,0.2,-895,0.5),
        (1426,-3.4,54,-0.1),
        (712,0.1,-7,0),
        (-517,1.2,224,-0.6),
        (-386,-0.4,200,0),
        (-301,0,129,-0.1),
        (217,-0.5,-95,0.3),
        (-158,0,0,0),
        (129,0.1,-70,0),
        (123,0,-53,0),
        (63,0,0,0),
        (63,0.1,-33,0),
        (-59,0,26,0),
        (-58,-0.1,32,0),
        (-51,0,27,0),
        (48,0,0,0),
        (46,0,-24,0),
        (-38,0,16,0),
        (-31,0,13,0),
        (29,0,0,0),
        (29,0,-12,0),
        (26,0,0,0),
        (-22,0,0,0),
        (21,0,-10,0),
        (17,-0.1,0,0),
        (16,0,-8,0),
        (-16,0.1,7,0),
        (-15,0,9,0),
        (-13,0,7,0),
        (-12,0,6,0),
        (11,0,0,0),
        (-10,0,5,0),
        (-8,0,3,0),
        (7,0,-3,0),
        (-7,0,0,0),
        (-7,0,3,0),
        (-7,0,3,0),
        (6,0,0,0),
        (6,0,-3,0),
        (6,0,-3,0),
        (-6,0,3,0),
        (-6,0,3,0),
        (5,0,0,0),
        (-5,0,3,0),
        (-5,0,3,0),
        (-5,0,3,0),
        (4,0,0,0),
        (4,0,0,0),
        (4,0,0,0),
        (-4,0,0,0),
        (-4,0,0,0),
        (-4,0,0,0),
        (3,0,0,0),
        (-3,0,0,0),
        (-3,0,0,0),
        (-3,0,0,0),
        (-3,0,0,0),
        (-3,0,0,0),
        (-3,0,0,0),
        (-3,0,0,0),
    ]

heliocentric_longitude_coeffs = \
    [
        [  # L0
            (175347046.0,0,0),
            (3341656.0,4.6692568,6283.07585),
            (34894.0,4.6261,12566.1517),
            (3497.0,2.7441,5753.3849),
            (3418.0,2.8289,3.5231),
            (3136.0,3.6277,77713.7715),
            (2676.0,4.4181,7860.4194),
            (2343.0,6.1352,3930.2097),
            (1324.0,0.7425,11506.7698),
            (1273.0,2.0371,529.691),
            (1199.0,1.1096,1577.3435),
            (990,5.233,5884.927),
            (902,2.045,26.298),
            (857,3.508,398.149),
            (780,1.179,5223.694),
            (753,2.533,5507.553),
            (505,4.583,18849.228),
            (492,4.205,775.523),
            (357,2.92,0.067),
            (317,5.849,11790.629),
            (284,1.899,796.298),
            (271,0.315,10977.079),
            (243,0.345,5486.778),
            (206,4.806,2544.314),
            (205,1.869,5573.143),
            (202,2.458,6069.777),
            (156,0.833,213.299),
            (132,3.411,2942.463),
            (126,1.083,20.775),
            (115,0.645,0.98),
            (103,0.636,4694.003),
            (102,0.976,15720.839),
            (102,4.267,7.114),
            (99,6.21,2146.17),
            (98,0.68,155.42),
            (86,5.98,161000.69),
            (85,1.3,6275.96),
            (85,3.67,71430.7),
            (80,1.81,17260.15),
            (79,3.04,12036.46),
            (75,1.76,5088.63),
            (74,3.5,3154.69),
            (74,4.68,801.82),
            (70,0.83,9437.76),
            (62,3.98,8827.39),
            (61,1.82,7084.9),
            (57,2.78,6286.6),
            (56,4.39,14143.5),
            (56,3.47,6279.55),
            (52,0.19,12139.55),
            (52,1.33,1748.02),
            (51,0.28,5856.48),
            (49,0.49,1194.45),
            (41,5.37,8429.24),
            (41,2.4,19651.05),
            (39,6.17,10447.39),
            (37,6.04,10213.29),
            (37,2.57,1059.38),
            (36,1.71,2352.87),
            (36,1.78,6812.77),
            (33,0.59,17789.85),
            (30,0.44,83996.85),
            (30,2.74,1349.87),
            (25,3.16,4690.48)
        ],
        [  # L1
            (628331966747.0,0,0),
            (206059.0,2.678235,6283.07585),
            (4303.0,2.6351,12566.1517),
            (425.0,1.59,3.523),
            (119.0,5.796,26.298),
            (109.0,2.966,1577.344),
            (93,2.59,18849.23),
            (72,1.14,529.69),
            (68,1.87,398.15),
            (67,4.41,5507.55),
            (59,2.89,5223.69),
            (56,2.17,155.42),
            (45,0.4,796.3),
            (36,0.47,775.52),
            (29,2.65,7.11),
            (21,5.34,0.98),
            (19,1.85,5486.78),
            (19,4.97,213.3),
            (17,2.99,6275.96),
            (16,0.03,2544.31),
            (16,1.43,2146.17),
            (15,1.21,10977.08),
            (12,2.83,1748.02),
            (12,3.26,5088.63),
            (12,5.27,1194.45),
            (12,2.08,4694),
            (11,0.77,553.57),
            (10,1.3,6286.6),
            (10,4.24,1349.87),
            (9,2.7,242.73),
            (9,5.64,951.72),
            (8,5.3,2352.87),
            (6,2.65,9437.76),
            (6,4.67,4690.48)
        ],
        [  # L2
            (52919.0,0,0),
            (8720.0,1.0721,6283.0758),
            (309.0,0.867,12566.152),
            (27,0.05,3.52),
            (16,5.19,26.3),
            (16,3.68,155.42),
            (10,0.76,18849.23),
            (9,2.06,77713.77),
            (7,0.83,775.52),
            (5,4.66,1577.34),
            (4,1.03,7.11),
            (4,3.44,5573.14),
            (3,5.14,796.3),
            (3,6.05,5507.55),
            (3,1.19,242.73),
            (3,6.12,529.69),
            (3,0.31,398.15),
            (3,2.28,553.57),
            (2,4.38,5223.69),
            (2,3.75,0.98)
        ],
        [  # L3
            (289.0,5.844,6283.076),
            (35,0,0),
            (17,5.49,12566.15),
            (3,5.2,155.42),
            (1,4.72,3.52),
            (1,5.3,18849.23),
            (1,5.97,242.73)
        ],
        [  # L4
            (114.0,3.142,0),
            (8,4.13,6283.08),
            (1,3.84,12566.15)
        ],
        [  # L5
            (1,3.14,0)
        ],
    ]

heliocentric_latitude_coeffs = \
    [
        [  # B0
            (280.0,3.199,84334.662),
            (102.0,5.422,5507.553),
            (80,3.88,5223.69),
            (44,3.7,2352.87),
            (32,4,1577.34)
        ],
        [  # B1
            (9,3.9,5507.55),
            (6,1.73,5223.69)
        ],
    ]

sun_earth_distance_coeffs = \
    [
        [  # R0
            (100013989.0,0,0),
            (1670700.0,3.0984635,6283.07585),
            (13956.0,3.05525,12566.1517),
            (3084.0,5.1985,77713.7715),
            (1628.0,1.1739,5753.3849),
            (1576.0,2.8469,7860.4194),
            (925.0,5.453,11506.77),
            (542.0,4.564,3930.21),
            (472.0,3.661,5884.927),
            (346.0,0.964,5507.553),
            (329.0,5.9,5223.694),
            (307.0,0.299,5573.143),
            (243.0,4.273,11790.629),
            (212.0,5.847,1577.344),
            (186.0,5.022,10977.079),
            (175.0,3.012,18849.228),
            (110.0,5.055,5486.778),
            (98,0.89,6069.78),
            (86,5.69,15720.84),
            (86,1.27,161000.69),
            (65,0.27,17260.15),
            (63,0.92,529.69),
            (57,2.01,83996.85),
            (56,5.24,71430.7),
            (49,3.25,2544.31),
            (47,2.58,775.52),
            (45,5.54,9437.76),
            (43,6.01,6275.96),
            (39,5.36,4694),
            (38,2.39,8827.39),
            (37,0.83,19651.05),
            (37,4.9,12139.55),
            (36,1.67,12036.46),
            (35,1.84,2942.46),
            (33,0.24,7084.9),
            (32,0.18,5088.63),
            (32,1.78,398.15),
            (28,1.21,6286.6),
            (28,1.9,6279.55),
            (26,4.59,10447.39)
        ],
        [  # R1
            (103019.0,1.10749,6283.07585),
            (1721.0,1.0644,12566.1517),
            (702.0,3.142,0),
            (32,1.02,18849.23),
            (31,2.84,5507.55),
            (25,1.32,5223.69),
            (18,1.42,1577.34),
            (10,5.91,10977.08),
            (9,1.42,6275.96),
            (9,0.27,5486.78)
        ],
        [  # R2
            (4359.0,5.7846,6283.0758),
            (124.0,5.579,12566.152),
            (12,3.14,0),
            (9,3.63,77713.77),
            (6,1.87,5573.14),
            (3,5.47,18849.23)
        ],
        [  # R3
            (145.0,4.273,6283.076),
            (7,3.92,12566.15),
        ],
        [  # R4
            (4,2.56,6283.08)
        ],
    ]
