Matemáticas para calcular la longitud terrestre directamente bajo el sol con el tiempo

Estoy tratando de calcular la longitud en la tierra donde es mediodía en algún momento. (Es decir, la longitud que es coplanar con el plano definido por el sol y el eje de la tierra).

Aquí está mi código Python:

from math import sin, cos, tan, atan, pi
def sun_longitude(when):
    """Given time in ms since 1/1/1970, return the longitude the sun is over at that moment"""
    # https://en.wikipedia.org/wiki/Position_of_the_Sun
    jdn = 2440587.5 + when / (1000.0 * 3600 * 24)
    n = jdn - 2451545.0 # 1/1/2000
    L = (280.460 + 0.9856474 * n) % 360.0
    g = (357.528 + 0.9856004 * n) % 360.0
    degtorad = 2.0 * pi / 360.0
    lambda_ = L + 1.915 * sin(g * degtorad) + 0.020 * sin(2 * g * degtorad)

    # https://en.wikipedia.org/wiki/Axial_tilt#Short_term
    T = n / (365 * 100.0) # julian centuries from 2000
    # ε = 23° 26′ 21.406″ − 46.836769″ T − 0.0001831″ T2
    epsilon = 23.4392794 - 0.780612817 * T - 5.0861e-8 * T * T;
    alpha = atan(cos(epsilon * degtorad) * tan(lambda_ * degtorad)) / degtorad

    # https://en.wikipedia.org/wiki/Sidereal_time
    # https://en.wikipedia.org/wiki/Hour_angle
    GMST = (18.697374558 + 24.06570982441908 * n) % 24.0
    print "jdn = {jdn}, n = {n}, L = {L}, g = {g}, lambda_ = {lambda_}, T = {T}, epsilon = {epsilon}, alpha = {alpha}, GMST = {GMST}".format(**locals())
    LHA = GMST * 360/24 + alpha;

    return LHA

from datetime import datetime
def sun_long_from_str(whenstr):
    when = datetime.strptime(whenstr, "%Y-%m-%d %H:%M")
    secs = (when - datetime(1970, 1, 1)).total_seconds()
    return sun_longitude(secs * 1000.0)

Soy consciente de que no estoy corrigiendo el cuadrante correcto al calcular alfa, pero tengo errores en otros lugares; por ejemplo, para el mediodía GMT del 1 de enero de 2000, obtengo 279° en lugar de cerca de 0, que es lo que esperaría.

Esto no me está dando respuestas correctas, y no sé cómo depurarlo. ¿Alguien puede encontrar mis errores o indicarme algún código de muestra razonable o un ejemplo elaborado para esto?

Porque, una vez que obtenga el algoritmo correcto, lo volveré a implementar para un dispositivo integrado, no puedo simplemente usar un paquete de implementación y no he encontrado una biblioteca que sea lo suficientemente sencilla para entender cómo puedo implementar esto. pregunta especifica

Gracias por un par de correcciones de errores. Ahora, cuando lo ejecuto, obtengo lo siguiente para estos ejemplos:

2000-01-01 12:00:
  jdn = 2451545.0, n = 0.0, L = 280.46, g = 357.528, lambda_ = 280.375680197, T = 0.0, epsilon = 23.4392794, alpha = -78.7141369122, GMST = 18.697374558
  result: 201.74648145775257

2000-03-20 07:35:
  jdn = 2451623.81597, n = 78.815972222, L = 358.144758099, g = 75.2090537484, lambda_ = 360.006175505, T = 0.00215934170471, epsilon = 23.4375937902, alpha = 0.00566598789588, GMST = 19.4596915825
  291.9010397253072

Como puede ver, la primera consulta (mediodía del 1 de enero de 2000) ahora tiene un número de día juliano correcto. Al mediodía GMT, esperaría que el sol estuviera por encima de una longitud cercana a 0, por lo que 201 es incorrecto.

La segunda consulta es la hora del equinoccio de primavera en 2000, que esperaba que pusiera a cero la parte sideral del cálculo, pero no es así.

Intenté consultar la interfaz web de NASA HORIZONS para las efemérides del sol el 1/1/2000 al mediodía GMT, tanto para las ubicaciones "Geocéntricas" como para las de Greenwich, pero no sé cómo evaluar el resultado y compararlo con mi trabajo. encima.

Geocéntrico:

 Date__(UT)__HR:MN     R.A._(ICRF/J2000.0)_DEC  APmag  S-brt            delta      deldot    S-O-T /r    S-T-O
**************************************************************************************************************
 2000-Jan-01 12:00     18 45 09.36 -23 01 59.7 -26.78 -10.59 0.98332762653520  -0.0127281   0.0000 /?   0.0000

Greenwich:

 Date__(UT)__HR:MN     R.A._(ICRF/J2000.0)_DEC  APmag  S-brt            delta      deldot    S-O-T /r    S-T-O
**************************************************************************************************************
 2000-Jan-01 12:00 *m  18 45 09.36 -23 02 08.3 -26.78 -10.59 0.98331613178086  -0.0166655   0.0000 /?   0.0000

Gracias de nuevo por cualquier ayuda que pueda proporcionar.

[Editado para corregir el cálculo del día juliano y el uso de grados frente a radianes para alfa y para agregar ejemplos]

Sugerencia general de depuración: imprima las variables después de calcularlas para ver dónde se equivoca. Además, creo que puedes hacer esto simplemente usando la Ecuación del Tiempo y el hecho de que la Tierra gira cada 24 horas (con respecto al Sol)
¿Podría mostrarnos la salida también?
Lo primero que noté es que el tiempo de Unix se mide en segundos desde la medianoche, mientras que las fechas julianas se miden desde el mediodía. Intentarjdn = 2440587.5 + when / (1000.0 * 3600 * 24)
@barrycarter depende de qué tan preciso quieras ser. Debido a que la Tierra está en una órbita elíptica (velocidad cambiante), el día solar literal varía ligeramente de 24 horas según el lugar en el que te encuentres en la órbita. El día solar tiene un promedio exacto de 24 horas.
Lo siguiente que parece extraño es que "alfa" se calcula en radianes, en lugar de las Horas Min Seg habituales. y lambda está en grados.
@Aabaakawad Sí, es por eso que mencioné la Ecuación del tiempo (como una corrección del ciclo de rotación de 24 horas con el sol)
Gracias por todos los comentarios. @barrycarter: imprime los valores casi al final.
@james-kilfiger: gracias; Estaba haciendo esa corrección para el cálculo del tiempo sideral (ver n - 0.5), pero por alguna razón tenía la impresión de que los días julianos usados ​​para los otros cálculos comenzaban a medianoche. ¡Y, por supuesto, tienes razón sobre alfa!

Respuestas (1)

Hay dos cosas que puedo ver en este código:

Primero, la fecha juliana se mide desde el mediodía, mientras que la época unix se mide desde la medianoche. jdn = 2440587.5 + when / (1000.0 * 3600 * 24)debe ser la expresión correcta.

En segundo lugar, alpha = atan(cos(epsilon * degtorad) * tan(lambda_ * degtorad))calcula una ascensión recta en radianes, debe convertir esto a grados para la última parte de los cálculos.

edit Necesitas arreglar el cuadrante, por ejemplo cuando n==0, deberías obtener una ascensión recta de 281.285. Sin embargo, el último error está en el cálculo de la longitud.

La ecuación relevante es L H A = GRAMO METRO S T λ α . Cuando el sol está en el meridiano, LHA = 0 y (reordenando) λ = GRAMO METRO S T α . Así LHA = GMST * 360/24 + alphadebería ser la línea longitude = GMST*360/24 - alpha. (y regresa longitude) Si haces esto con n=0, obtienes una longitud de -1.5 grados. El sol está en el meridiano del mediodía del 1 de enero de 2000, si se encuentra a 1,5 grados al oeste de Greenwich.

Parece que estás intentando unas efemérides muy precisas para el sol. Puede verificar su precisión contra PyEphem , o las efemérides de Nasa Horizon .

Gracias, hice estas correcciones, muy útiles. Sin embargo, los resultados todavía parecen incorrectos.
Creo que el error está en el cálculo de LHA, que debería ser LHA = GMST - alfa. Además, el valor de alfa debe estar en el rango 0--360, mientras que atan regresa en el rango -90--90, deberá pensar en corregir el cuadrante.
Gracias, los miraré. ¿No debería esperar que GMST sea cero en el equinoccio de primavera?