Почему продолжается численное интегрирование солнечной системы? (Схема MIT SCMUTILS) - PullRequest
1 голос
/ 06 мая 2020

Я пытаюсь провести численное интегрирование солнечной системы. Раньше я делал это на простой схеме, а теперь хочу сделать это с помощью очень интересной SCMUTILS-библиотеки от MIT . Что я сделал:

  1. Я взял данные о солнечной системе из Лаборатории реактивного движения; то есть: масса, положение и скорость Солнца, Меркурия, Венеры и Земли в барицентрических c координатах.
  2. Я написал код для дифференциального уравнения, так что каждый объект в системе (солнце , mercurius, venus, earth) притягивается к 3 другим правильным образом.
  3. Я провел моделирование путем численного интегрирования с помощью SCMUTILS.

Если я запустил моделирование с солнце + 1 др. пл anet, работает. Если я попробую взять солнце + 2 другие планеты, вроде зависнет. Это странно, поскольку я запускал моделирование с теми же данными несколько лет go с моим собственным самодельным интегратором Рунге-Кутта, и он работал нормально.

Обратите внимание, что я хорошо знаком с MIT-схема и численное интегрирование, и я хочу изучить только SCMUTILS. Я явно делаю что-то не так, и меня бы удивило, если бы эту проблему нельзя было решить с помощью SCMUTILS.

Кроме того, я не фиксирую свой код: если кто-то может предоставить мне работающую реализацию в SCMUTILS, это тоже нормально, если я понимаю, что я делаю неправильно в своей программе. Я просто хочу использовать SCMUTILS идиоматическим c способом ...

Мой код ниже (около 60 хорошо задокументированных строк). Спасибо за любые комментарии или улучшения рабочего моделирования.

;JPL-DE - Ephemerides from Jet Propulsion Laboratory http://ssd.jpl.nasa.gov
(define solar-system
  (up (+ 0.0 (decoded-time->universal-time (make-decoded-time 0 0 0 1 1 2000 0))) ; January 1st 2000 at 0h0m0s UT
      (up (up 1.3271244004193937e20                                               ; Sun mass * gravitational constant                    
          (up -1068000648.30182 -417680212.56849295 30844670.2068709)             ; Sun position (x,y,z) in meters in barycentric coordinates
          (up 9.305300847631916 -12.83176670344807 -.1631528028381386))           ; Sun velocity (vx,vy,vz) in meters per second
      (up 22031780000000.                                                         ; Mercurius
          (up -22120621758.62221 -66824318296.10253 -3461601353.17608) 
          (up 36662.29236478603 -12302.66986781422 -4368.33605178479)) 
      (up 324858592000000.                                                        ; Venus
          (up -108573550917.8141 -3784200933.160055 6190064472.97799)
          (up 898.4651054838754 -35172.03950794635 -532.0225582712421))
;     (up 398600435436000.                                                        ; Earth
;         (up -26278929286.8248 144510239358.6391 30228181.35935813)
;         (up -29830.52803283506 -5220.465685407924 -.1014621798034465))
      )))

(define (ss-time state)       ; Select time from solar system state
  (ref state 0))
(define (ss-planets state)    ; Select up-tuple with all planets
  (ref state 1))
(define (ss-planet state i)   ; Select i-th planet in system (0: sun, 1: mercurius, 2: venus, 3: earth) (Note: the sun is also a "planet")
  (ref (ss-planets state) i))
(define (GM planet)           ; Select GM from planet (GM is gravitational constant times mass of planet)
  (ref planet 0))
(define (position planet)     ; Select position up-tuple (x,y,z) from planet
  (ref planet 1))
(define (velocity planet)     ; Select velocity up-tuple (vx,vy,vz) from planet
  (ref planet 2))

(define ((dy/dt) state)
  (define (gravitational-force on-planet by-planet)              ; Calculate gravitational force on planet "on-planet" by "by-planet"
    (if (equal? on-planet by-planet)                             ; Compare planets
        (up 0.0 0.0 0.0)                                         ; There is no force of a planet on itself
        (let* ((r (- (position on-planet) (position by-planet))) ; Position of "on-planet" seen from "by-planet"
               (d (abs r)))                                      ; Distance between the two
          (* -1.0 (GM by-planet) (/ r (* d d d))))))             ; Gravitational force is negatively directed, we divide by d^3 to cancel out r in nominator
  (define (dy/dt-planet planet)                                                                                         ; Calculate dy/dt for a planet
    (up 0.0                                                                                                             ; No change in GM
        (velocity planet)                                                                                               ; Change in position is velocity
        (* (s:generate (s:length (ss-planets state)) 'up (lambda (i) (gravitational-force planet (ss-planet state i)))) ; Calculate gravitation forces from
           (s:generate (s:length (ss-planets state)) 'down (lambda (i) 1.0)))))           ; all other planets, and sum them via inner product with down-tuple
  (up 1.0                                                                                              ; Timestep: dt/dt=1.0
      (s:generate (s:length (ss-planets state)) 'up (lambda (i) (dy/dt-planet (ss-planet state i)))))) ; Calculate dy/dt for all planets

(define win (frame -150e9 150e9 -150e9 150e9 512 512)) ; Viewport: a square of 300e9 meters by 300e9 meters plotted in a 512 by 512 window

(define ((monitor-xy) state)
  ((s:elementwise (lambda (planet) (plot-point win (ref (position planet) 0) (ref (position planet) 1)))) (ss-planets state))) ; Plot X,Y (no Z) for planets 

(define end                                                             ; Define end state
  ((evolve dy/dt)                                                       ; Run simulation
   solar-system                                                         ; Starting state, Jan. 1st 2000 0h0m0s
   (monitor-xy)                                                         ; Plot positions throughout simulation
   (* 1.0 60 60)                                                        ; Timestep: 1 hour
   (decoded-time->universal-time (make-decoded-time 0 0 0 1 1 2005 0))) ; Run for 5 years
)

1 Ответ

3 голосов
/ 13 мая 2020

Интересен способ, которым scmutils выполняет интеграцию. Функция производной состояния работает с локальным кортежем, как описано в SICM, но интегратор хочет работать с функцией, которая принимает массив чисел с плавающей запятой в качестве входных данных и создает массив равного размера в качестве выходных. Для этого scmutils берет данные начального состояния, заменяет значения в них символами и передает их вашей производной. Это производит вывод symboli c, который можно использовать для подготовки функции с правильной сигнатурой для интегратора. (Я могу описать этот процесс более подробно, если хотите).

Однако ваша проблема в декартовых координатах, и результирующее выражение symboli c выглядит волосатым. Вы можете увидеть этот процесс в действии, создав свой собственный символ c состояние и передав его производной функции, а также упростив вывод (передав результат через pe (выражение печати)):

(define symbolic-system
  (up 't
      (up (up 'g_0
          (up 'x_0 'y_0 'z_0)             ; Sun position (x,y,z) in meters in barycentric coordinates
          (up 'vx_0 'vy_0 'vz_0))           ; Sun velocity (vx,vy,vz) in meters per second
      (up 'g_1
          (up 'x_1 'y_1 'z_1)
          (up 'vx_1 'vy_1 'vz_1))
;     (up 'g_2
;          (up 'x_2 'y_2 'z_2)
;          (up 'vx_2 'vy_2 'vz_2))
;     (up 'g_3
;          (up 'x_3 'y_3 'z_3)
;          (up 'vx_3 'vy_3 'vz_3))
      )))

(pe ((dy/dt) symbolic-system))

Результат потрясающий, поэтому я не вставлял его сюда. Если вы теперь добавите еще один pl anet, раскомментировав строки с нижним индексом 2, вы обнаружите, что печать зависает, что означает, что упрощатель выражений застрял. Числовой интегратор еще даже не запустился.

Что делать? Возможно, вам удастся вернуть некоторую емкость, исключив координату z. Вы можете переместить параметры GM, которые являются постоянными, в список аргументов функции конструктора производных состояний, оставив только те вещи, которые будут изменяться в самом кортеже состояний. Вы можете немного сгладить кортеж состояний; его структура полностью зависит от вас.

Однако в конечном итоге интегрируемая функция будет намного сложнее, чем функция, которую вы написали бы сами, и многое из этого связано с условиями sqrt(x^2 + y^2 + ...), которые вы получаете из декартовых координат. . Scmutils был разработан для задач, в которых использование обобщенных координат создает компактные лагранжианы, из которых могут быть получены более простые производные функции состояния (автоматически, что является magi c scmutils). Я думаю, что эта конкретная проблема будет подъёмом в гору. , который экономит на координатах, фокусируясь на третьем теле, которое, как предполагается, намного меньше, чем два других, и имеет систему координат, вращающуюся так, что первые два тела l ie по оси x. Другой пример - это спин-орбитальная связь , в которой есть два тела, но отклонение формы спутника от окружности не является незначительным. Оба этих подхода дают формулировки, в которых координат намного меньше, чем 3 * (количество тел)

...