Created
September 7, 2025 04:13
-
-
Save pukpr/ef590090364bd3de76b7a9d551fdda18 to your computer and use it in GitHub Desktop.
Animation of QBO, opens window in Browser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from vpython import * | |
| Running = True | |
| def exit_app(evt): | |
| global Running | |
| if evt.key == 'q': # Press 'q' to quit | |
| print("Exiting simulation...") | |
| Running = False | |
| scene.bind('keydown', exit_app) | |
| scene.width = 1920 | |
| scene.height = 1080 | |
| scene.range = 100 | |
| earth = sphere(pos=vector(0,0,0), radius=5, color=color.blue) | |
| ring = ring(pos=earth.pos, axis=vector(0,1,0), radius=7, thickness=0.5, color=color.red) | |
| # Arrow position: place it on the edge of the ring | |
| arrow_pos = vector(0, 0, 10) | |
| # Create the directional arrow | |
| arrow_obj = arrow(pos=arrow_pos, axis=vector(0, -1, 0), shaftwidth=0.5, color=color.white) | |
| sun = sphere(radius=2, color=color.yellow, make_trail=True, trail_radius=0.2, retain=30) | |
| moon = sphere(radius=1, color=color.white, make_trail=True, trail_radius=0.1, retain=10) | |
| timer_label = label(pos=vector(0,15,0), text='t = 0.0 yr', height=10, box=False, color=color.white) | |
| annual_label = label(pos=vector(0,20,0), text='declination', height=10, box=False, color=color.white) | |
| obliquity = radians(23.44) | |
| moon_incl = radians(5.145*3) | |
| year = 365.2422 | |
| draconic = 27.2122 | |
| t = 0 | |
| dt = 0.1 | |
| # Interval in days | |
| interval = 1.185 * year | |
| # toggle = True | |
| while Running: | |
| rate(600) | |
| sun.pos = vector(50*cos(2*pi*t/year), | |
| 50*sin(2*pi*t/year)*sin(obliquity), | |
| 50*sin(2*pi*t/year)*cos(obliquity)) | |
| moon.pos = vector(10*cos(2*pi*t/draconic), | |
| 10*sin(2*pi*t/draconic)*sin(moon_incl), | |
| 10*sin(2*pi*t/draconic)*cos(moon_incl)) | |
| # Color toggle every 1.185 years | |
| cycle = int(t // interval) | |
| if cycle % 2 == 0: | |
| ring.color = color.green | |
| arrow_obj.axis = vector(5, 0, 0) # CW: tangent points downward | |
| else: | |
| ring.color = color.red | |
| arrow_obj.axis = vector(-5, 0, 0) # CW: tangent points upward | |
| annual_label.color = ring.color | |
| if abs((t/year) % 1) < dt/year: | |
| # This block runs only when t is approximately an integer multiple of 'year' | |
| print(f"Year marker reached: {t/year:.0f}") | |
| annual_label.text = f'decl = {5*cos(2*pi*t/draconic):.2f}°' | |
| # annual_label.axis = vector(cos(5*cos(2*pi*t/draconic)*2*pi/180), sin(5*cos(2*pi*t/draconic)*2*pi/180), 0) | |
| t += dt | |
| timer_label.text = f'time = {t/year:.2f} yr' |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
[
Screen.Recording.2025-09-06.232242.mp4
](url)
When lunar declination is positive during an annual synching impulse, the QBO shifts to the GREEN direction, and when the lunar declination is negative, the QBO reverses to the opposite RED direction.