code wiki / _hdl_build / nx_research_orbit_gate.nx
nx_research_orbit_gate.nx source
↩ module page · 98 lines · 6081 B
1// nx_research_orbit_gate.nx -- the capstone of the dynamics thread: a 2-D gravitational orbit (inverse-square
2// central force, a = -GM r / |r|^3) integrated in sovereign fixed-point (using our isqrt for |r|). THE canonical
3// reason symplectic integrators exist: over many orbits the SYMPLECTIC leapfrog keeps the orbit BOUNDED and energy
4// conserved, while naive forward-EULER pumps energy in and the orbit SPIRALS OUTWARD.
5// Fixed-point precision trick: store velocity scaled by VS=2D, so the leapfrog half-kick v += a*dt/2 = a/(2D)
6// becomes v_scaled += a EXACTLY (no truncation -- the dominant error source). Position step then divides by 2D*D.
7// Verifier = energy conservation + orbit-radius bound; liar-kill = Euler's plausible orbit fails the bound the
8// symplectic orbit holds. No float, deterministic. GREEN iff 6/6. license_tier: ORIGINAL
9import "nx_syscalls.nx"
10
11func g_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
12func g_n(v: i64) -> i64 { var m: i64=v; if m<0{g_w("-");m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1}; sys_write(1,o,k); return 0 }
13func g_row(id: *u8, ok: i64, pass: *i64) -> i64 { g_w(" "); g_w(id); g_w(": "); if ok==1 { g_w("OK\n"); pass[0]=pass[0]+1 } else { g_w("FAIL\n") } return 0 }
14func iabs(x: i64) -> i64 { if x<0 { return 0-x } return x }
15func isqrt(N: i64) -> i64 { if N<2 { return N } var x: i64=N; var y: i64=(x+1)/2; while y<x { x=y; y=(x + N/x)/2 } return x }
16
17func accel(x: i64, y: i64, GM: i64, out: *i64) -> i64 {
18 let r2: i64 = x*x + y*y
19 let r: i64 = isqrt(r2)
20 let r3: i64 = r2*r
21 out[0] = 0 - GM*x/r3
22 out[1] = 0 - GM*y/r3
23 return 0
24}
25// 2x specific energy using scaled velocities (v_real = vs/VS): (vsx^2+vsy^2)/VS^2 - 2GM/r.
26func orbit_E2(x: i64, y: i64, vsx: i64, vsy: i64, GM: i64, VS: i64) -> i64 { let r: i64=isqrt(x*x+y*y); let vrx: i64=vsx/VS; let vry: i64=vsy/VS; return vrx*vrx+vry*vry - 2*GM/r }
27
28// leapfrog with velocity scaled by VS=2D (exact half-kick). out[0]=max|E-E0|, out[1]=min r, out[2]=max r.
29func sim_lf_orbit(x0: i64, y0: i64, vx0: i64, vy0: i64, GM: i64, D: i64, N: i64, out: *i64) -> i64 {
30 let VS: i64=2*D; let DD2: i64=2*D*D
31 var x: i64=x0; var y: i64=y0; var vsx: i64=vx0*VS; var vsy: i64=vy0*VS
32 let E0: i64=orbit_E2(x,y,vsx,vsy,GM,VS)
33 let a: *i64=sys_mmap(8*4) as *i64
34 var maxdev: i64=0; var minr: i64=isqrt(x*x+y*y); var maxr: i64=minr
35 var i: i64=0
36 while i<N {
37 accel(x,y,GM,a)
38 let vhx: i64=vsx + a[0]; let vhy: i64=vsy + a[1] // exact: a*VS/(2D)=a
39 x = x + vhx/DD2; y = y + vhy/DD2
40 accel(x,y,GM,a)
41 vsx = vhx + a[0]; vsy = vhy + a[1]
42 let E: i64=orbit_E2(x,y,vsx,vsy,GM,VS); let dd: i64=iabs(E-E0); if dd>maxdev { maxdev=dd }
43 let r: i64=isqrt(x*x+y*y); if r<minr { minr=r } if r>maxr { maxr=r }
44 i=i+1
45 }
46 out[0]=maxdev; out[1]=minr; out[2]=maxr
47 return 0
48}
49// forward-Euler (same VS scaling). out[0]=max|E-E0|, out[1]=max r.
50func sim_eu_orbit(x0: i64, y0: i64, vx0: i64, vy0: i64, GM: i64, D: i64, N: i64, out: *i64) -> i64 {
51 let VS: i64=2*D; let DD2: i64=2*D*D
52 var x: i64=x0; var y: i64=y0; var vsx: i64=vx0*VS; var vsy: i64=vy0*VS
53 let E0: i64=orbit_E2(x,y,vsx,vsy,GM,VS)
54 let a: *i64=sys_mmap(8*4) as *i64
55 var maxdev: i64=0; var maxr: i64=isqrt(x*x+y*y)
56 var i: i64=0
57 while i<N {
58 accel(x,y,GM,a)
59 let nx: i64=x + vsx/DD2; let ny: i64=y + vsy/DD2
60 let nvsx: i64=vsx + 2*a[0]; let nvsy: i64=vsy + 2*a[1] // euler: a*VS/D = 2a
61 x=nx; y=ny; vsx=nvsx; vsy=nvsy
62 let E: i64=orbit_E2(x,y,vsx,vsy,GM,VS); let dd: i64=iabs(E-E0); if dd>maxdev { maxdev=dd }
63 let r: i64=isqrt(x*x+y*y); if r>maxr { maxr=r }
64 i=i+1
65 }
66 out[0]=maxdev; out[1]=maxr
67 return 0
68}
69
70func main() -> i64 {
71 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0
72 g_w("=== NX-RESEARCH-ORBIT GATE (gravitational orbit: symplectic stays bounded, Euler spirals out) ===\n")
73 let SC: i64=100000; let D: i64=64; let N: i64=40000
74 let GM: i64=15625000000000 // (SC/8)^2 * SC -> circular speed SC/8 at r=SC
75 let x0: i64=SC; let y0: i64=0; let vx0: i64=0; let vy0: i64=12500
76 let VS: i64=2*D
77 let E0: i64=orbit_E2(x0,y0,vx0*VS,vy0*VS,GM,VS); let aE0: i64=iabs(E0)
78
79 let lp: *i64=sys_mmap(8*4) as *i64; sim_lf_orbit(x0,y0,vx0,vy0,GM,D,N,lp)
80 let eu: *i64=sys_mmap(8*4) as *i64; sim_eu_orbit(x0,y0,vx0,vy0,GM,D,N,eu)
81 let lp_pm: i64=lp[0]*1000/aE0; let eu_pm: i64=eu[0]*1000/aE0
82
83 g_w(" steps="); g_n(N); g_w(" (~12 orbits) r0="); g_n(SC); g_w(" E0(x2)="); g_n(E0); g_w("\n")
84 g_w(" leapfrog: Edev_permille="); g_n(lp_pm); g_w(" rmin/SC*1000="); g_n(lp[1]/(SC/1000)); g_w(" rmax/SC*1000="); g_n(lp[2]/(SC/1000)); g_w("\n")
85 g_w(" euler: Edev_permille="); g_n(eu_pm); g_w(" rmax/SC*1000="); g_n(eu[1]/(SC/1000)); g_w("\n")
86
87 g_row("SETUP: bound orbit initialized (E<0), isqrt gives r0=SC" as *u8, ((E0<0) as i64)*((isqrt(x0*x0+y0*y0)==SC) as i64), pass)
88 g_row("BOUND (leapfrog): orbit radius stays bounded over ~12 orbits (rmax < 1.3*SC, rmin > 0.7*SC)" as *u8, ((lp[2] < SC+SC*3/10) as i64)*((lp[1] > SC*7/10) as i64), pass)
89 g_row("CONSERVATION (leapfrog): orbital energy stays bounded (deviation < 5%)" as *u8, (lp_pm < 50) as i64, pass)
90 g_row("SPIRAL (euler): forward-Euler pumps energy and the radius grows outward (rmax > 1.2*SC vs leapfrog ~1.0*SC)" as *u8, (eu[1] > SC+SC/5) as i64, pass)
91 g_row("DISCRIMINATION: leapfrog energy deviation far below Euler's (>=3x better)" as *u8, (eu_pm > lp_pm*3) as i64, pass)
92 var liar: i64=0; if lp_pm < 50 { if eu_pm >= 50 { liar=1 } }
93 g_row("LIAR-KILL: Euler's spiraling orbit FAILS the energy bound the symplectic orbit holds" as *u8, liar, pass)
94
95 g_w("RESEARCH-ORBIT-GATE rows=6 pass="); g_n(pass[0])
96 if pass[0]==6 { g_w(" verdict=GREEN\n"); sys_exit(0); return 0 }
97 g_w(" verdict=RED\n"); sys_exit(1); return 1
98}