@essrt/physics 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js CHANGED
@@ -110,14 +110,13 @@ export { createMoonArguments } from './moon/arguments.cjs';
110
110
  export { createMoonSeries } from './moon/series.cjs';
111
111
  export { createMoonApparent } from './moon/apparent.cjs';
112
112
  // Phase 8.3 — the planet machinery, extracted by LAW over body records
113
- // (survey order: geometry → Fibonacci laws → channels → chains → corrections).
113
+ // (survey order: geometry → Fibonacci laws → channels → chains).
114
114
  export { derivePlanetGeometry } from './planets/geometry.cjs';
115
115
  export * as planetFibonacciLaws from './planets/fibonacci-laws.cjs';
116
116
  export { eccentricityFromCycles, computeEccentricityIntegrated } from './planets/ecc-channel.cjs';
117
117
  export * as planetOrientation from './planets/orientation.cjs';
118
118
  export { integrateAscendingNode } from './planets/asc-node-integrator.cjs';
119
119
  export * as planetOrbitChain from './planets/orbit-chain.cjs';
120
- export { evaluateParallaxBasis, gravitationTermDeltasDeg, evaluateElongationBasis } from './planets/corrections.cjs';
121
120
  // P5/K4.6c — the engine-D Keplerian chain (pure evaluator + the embedded
122
121
  // governed artifact; the browser flag path consumes exactly these).
123
122
  export { buildPlanetChainsFromArtifactData, computePlanetElementsAtYear, computeHeliocentricEclipticFromElements, computePoissonArgRad, computeOsculatingElements, solveKeplerRad, ANCHOR_EPOCH_YEAR, ANCHOR_EPOCH_JD } from './planets/keplerian-chain.cjs';
@@ -136,7 +135,9 @@ export { evalClimateL1OrbitalPermil } from './climate/l1-orbital.cjs';
136
135
  export { createEclipseFinders } from './eclipse/finders.cjs';
137
136
  // Phase 8.6 — the published reference curves (external comparison formulas
138
137
  // and datasets, exactly as published; comparison references, never inputs).
139
- export * as publishedCurves from './reference/published-curves.cjs';
138
+ // (reference/published-curves MIGRATED to @essrt/reference at the 4.0.0
139
+ // major — the published model package carries no comparison references;
140
+ // the K2 one-way wall is package-structural.)
140
141
  // Phase 9 — S-P8: the fitted sun-longitude harmonic stack (three copies → one).
141
142
  export { createSunLongitudeCorrection } from './sun/longitude-correction.cjs';
142
143
 
@@ -1,167 +0,0 @@
1
- /**
2
- * Fitted post-hoc corrections — THE shared evaluators (Phase 8.3, L8).
3
- *
4
- * The parallax RA/Dec basis: ~80 fitted coefficient slots (A..CA) over a
5
- * geometric state (orbital phase u from the ascending node, inverse
6
- * geocentric distance, inverse heliocentric distance, Julian centuries,
7
- * the triple-synodic conjunction phase, the Sun mean longitude, and the
8
- * inner-planet mean anomaly). ONE basis served four hand-copies: browser
9
- * dec, browser RA, Node dec, Node RA (~80 duplicated terms each).
10
- *
11
- * MATCHED PAIR: these coefficients were fitted against exactly this basis
12
- * and this state derivation — the expression text is transcribed verbatim
13
- * (including the (x || 0) missing-slot guards and the AU_ key, which
14
- * avoids a collision with the AU unit name). Do not simplify.
15
- *
16
- * The engines OWN the state derivation (scene vectors, JD conventions) and
17
- * the application sign convention (RA subtracts, Dec adds) — this module
18
- * only evaluates.
19
- *
20
- * GRAVITATION (planet-planet perturbation harmonics): evaluated here PER
21
- * TERM — the engines apply each term inside their own loops, because
22
- * (x−a)−b ≠ x−(a+b) at the last bit and the fixtures pin the per-term
23
- * application order.
24
- *
25
- * ELONGATION (elongation × Earth-perihelion geometry, 21 fitted slots per
26
- * axis): BROWSER ASSOCIATION FORM — the six d² slots per table use the
27
- * precomputed invD² ((a·b)·invD²); the Node mirror carried inline
28
- * invD·invD (((a·b)·invD)·invD) at those sites — same 1-ULP class as the
29
- * five parallax slots, measured by the fixture recorders at extraction.
30
- */
31
-
32
- 'use strict';
33
-
34
- /**
35
- * @typedef {{ u: number, invD: number, invS: number, T: number,
36
- * cp: number, Lsun: number,
37
- * sinM: number, cosM: number, sin2M: number, cos2M: number }} ParallaxState
38
- */
39
-
40
- /**
41
- * Evaluate the fitted parallax basis for one coefficient table (RA or Dec —
42
- * same basis, different tables). Returns DEGREES (the engines apply their
43
- * own sign and rad conversion).
44
- * @param {Record<string, number>} c @param {ParallaxState} s
45
- * @returns {number} */
46
- function evaluateParallaxBasis(c, s) {
47
- const { u: _u, invD: _invD, invS: _invS, T: _T, Lsun: _Lsun } = s;
48
- const _invD2 = _invD * _invD;
49
- const _invD3 = _invD2 * _invD;
50
- const _invS2 = _invS * _invS;
51
- const _invDS = _invD * _invS;
52
- const _sinU = Math.sin(_u), _cosU = Math.cos(_u);
53
- const _sin2U = Math.sin(2 * _u), _cos2U = Math.cos(2 * _u);
54
- const _sin3U = Math.sin(3 * _u), _cos3U = Math.cos(3 * _u);
55
- const _sinCP = Math.sin(s.cp), _cosCP = Math.cos(s.cp);
56
- const _sin2CP = Math.sin(2 * s.cp), _cos2CP = Math.cos(2 * s.cp);
57
- const _sinL = Math.sin(_Lsun), _cosL = Math.cos(_Lsun);
58
- const _sinM = s.sinM, _cosM = s.cosM, _sin2M = s.sin2M, _cos2M = s.cos2M;
59
- return c.A + c.B * _invD + (c.C || 0) * _T
60
- + (c.D * _sinU + c.E * _cosU + c.F * _sin2U + c.G * _cos2U
61
- + (c.H || 0) * _sin3U + (c.I || 0) * _cos3U) * _invD
62
- + _T * ((c.J || 0) * _sinU + (c.K || 0) * _cosU) * _invD
63
- + (c.L || 0) * _invS + (c.M || 0) * _sinU * _invD2
64
- + (c.N || 0) * _sin2U * _invS + (c.O || 0) * _cosU * _invS
65
- + (c.P || 0) * _T * _sin2U * _invD + (c.Q || 0) * _T * _cos2U * _invD
66
- + (c.R || 0) * _T * _sinU * _invS
67
- + (c.S || 0) * _T * _invD + (c.U || 0) * _cosU * _invD2
68
- + (c.V || 0) * _invS2 + (c.W || 0) * _sinU * _invS2
69
- + (c.X || 0) * _cos3U * _invS + (c.Y || 0) * _sin3U * _invS
70
- + (c.Z || 0) * _invDS + (c.AA || 0) * _sinU * _invDS
71
- + (c.AB || 0) * _cos2U * _invDS + (c.AC || 0) * _T * _sin2U * _invS
72
- + (c.AD || 0) * _cos3U * _invD2 + (c.AE || 0) * _sin2U * _invS2
73
- + (c.AF || 0) * _sin3U * _invS2 + (c.AG || 0) * _cos3U * _invS2
74
- + (c.AH || 0) * _cosU * _invS2 + (c.AI || 0) * _sinU * _invD2 * _invS
75
- + (c.AJ || 0) * Math.cos(4 * _u) * _invS + (c.AK || 0) * _sin2U * _invD2 * _invS
76
- + (c.AL || 0) * Math.sin(4 * _u) * _invD + (c.AM || 0) * Math.cos(4 * _u) * _invD
77
- + (c.AN || 0) * _T * _sinU * _invD2 + (c.AO || 0) * _T * _cosU * _invD2
78
- + (c.AP || 0) * _sinU * _invD2 * _invD + (c.AQ || 0) * _cosU * _invD2 * _invD
79
- + (c.AR || 0) * _sinCP + (c.AS || 0) * _cosCP
80
- + (c.AT || 0) * _sin2CP + (c.AU_ || 0) * _cos2CP
81
- + (c.AV || 0) * _sinCP * _invD + (c.AW || 0) * _cosCP * _invD
82
- + (c.AX || 0) * _sinL * _invD + (c.AY || 0) * _cosL * _invD
83
- + (c.AZ || 0) * _sinL + (c.BA || 0) * _cosL
84
- + (c.BB || 0) * _T * _sinL * _invD + (c.BC || 0) * _T * _cosL * _invD
85
- + (c.BD || 0) * _T * _sinL + (c.BE || 0) * _T * _cosL
86
- + (c.BF || 0) * _cosU * _sinL * _invD2 + (c.BG || 0) * _cosU * _cosL * _invD2
87
- + (c.BH || 0) * _sinL * _invD3 + (c.BI || 0) * _cosL * _invD3
88
- + (c.BJ || 0) * Math.sin(_u - _Lsun) * _invD2 + (c.BK || 0) * Math.cos(_u - _Lsun) * _invD2
89
- + (c.BL || 0) * _T * _T * _invD + (c.BM || 0) * _T * _T * _sinU * _invD + (c.BN || 0) * _T * _T * _cosU * _invD
90
- + (c.BO || 0) * _sin2U * _invD3 + (c.BP || 0) * _cos2U * _invD3
91
- + (c.BQ || 0) * _sinU * _invD3 * _invD
92
- + (c.BR || 0) * _sinM * _invD + (c.BS || 0) * _cosM * _invD
93
- + (c.BT || 0) * _sin2M * _invD + (c.BU || 0) * _cos2M * _invD
94
- + (c.BV || 0) * _sinM + (c.BW || 0) * _cosM
95
- + (c.BX || 0) * _sin2M + (c.BY || 0) * _cos2M
96
- + (c.BZ || 0) * _sinM * _invD2 + (c.CA || 0) * _cosM * _invD2;
97
- }
98
-
99
- /**
100
- * Gravitation-correction term deltas, in DEGREES, one entry per fitted
101
- * term. The engines apply these PER TERM (sign convention and the
102
- * degrees→radians conversion stay engine-side).
103
- * @param {Array<{ period: number, raSin: number, raCos: number,
104
- * decSin: number, decCos: number }>} terms
105
- * @param {number} yearsFrom2000
106
- * @returns {Array<{ raDeg: number, decDeg: number }>} */
107
- function gravitationTermDeltasDeg(terms, yearsFrom2000) {
108
- const out = [];
109
- for (const term of terms) {
110
- const phase = 2 * Math.PI * yearsFrom2000 / term.period;
111
- const sp = Math.sin(phase), cp = Math.cos(phase);
112
- out.push({
113
- raDeg: term.raSin * sp + term.raCos * cp,
114
- decDeg: term.decSin * sp + term.decCos * cp,
115
- });
116
- }
117
- return out;
118
- }
119
-
120
- /**
121
- * @typedef {{ elongRad: number, vFromWERad: number, synPhaseRad: number,
122
- * invD: number }} ElongationState
123
- */
124
-
125
- /**
126
- * Evaluate the fitted 21-slot elongation basis for one axis. Returns
127
- * DEGREES; `suffix` selects the coefficient table ('ra' or 'dec' — same
128
- * basis, different fitted slots). The engines derive the state (frame Sun
129
- * RA, Earth-perihelion angle, exact synodic phase from the integer orbit
130
- * count) and apply their own sign and rad conversion.
131
- * @param {Record<string, number>} vc @param {ElongationState} s
132
- * @param {'ra'|'dec'} suffix
133
- * @returns {number} */
134
- function evaluateElongationBasis(vc, s, suffix) {
135
- const sinEl = Math.sin(s.elongRad), cosEl = Math.cos(s.elongRad);
136
- const cosVwE = Math.cos(s.vFromWERad), sinVwE = Math.sin(s.vFromWERad);
137
- const sin2VwE = Math.sin(2 * s.vFromWERad), cos2VwE = Math.cos(2 * s.vFromWERad);
138
- const sin3VwE = Math.sin(3 * s.vFromWERad), cos3VwE = Math.cos(3 * s.vFromWERad);
139
- const sin4VwE = Math.sin(4 * s.vFromWERad), cos4VwE = Math.cos(4 * s.vFromWERad);
140
- const invD = s.invD;
141
- const invD2 = invD * invD;
142
- /** @param {string} k @returns {number} */
143
- const c = (k) => vc[k + suffix] || 0;
144
- return c('cosVwE_sinEl_') * cosVwE * sinEl
145
- + c('sinEl_d_') * sinEl * invD
146
- + c('sinVwE_sinEl_') * sinVwE * sinEl
147
- + c('sin2VwE_sinEl_') * sin2VwE * sinEl
148
- + c('cos2VwE_sinEl_') * cos2VwE * sinEl
149
- + c('cos4VwE_sinEl_') * cos4VwE * sinEl
150
- + c('sin4VwE_sinEl_') * sin4VwE * sinEl
151
- + c('sinVwE_sinEl_d2_') * sinVwE * sinEl * invD2
152
- + c('cos3VwE_sinEl_') * cos3VwE * sinEl
153
- + c('sin3VwE_sinEl_') * sin3VwE * sinEl
154
- + c('sin2syn_') * Math.sin(2 * s.synPhaseRad)
155
- + c('cos1syn_') * Math.cos(s.synPhaseRad)
156
- + c('sin3VwE_sinEl_d2_') * sin3VwE * sinEl * invD2
157
- + c('sin2VwE_sinEl_d2_') * sin2VwE * sinEl * invD2
158
- + c('cos2VwE_sinEl_d2_') * cos2VwE * sinEl * invD2
159
- + c('cosEl_d_') * cosEl * invD
160
- + c('cosVwE_cosEl_d_') * cosVwE * cosEl * invD
161
- + c('sinVwE_cosEl_d_') * sinVwE * cosEl * invD
162
- + c('cosEl_d2_') * cosEl * invD2
163
- + c('cosVwE_cosEl_d2_') * cosVwE * cosEl * invD2
164
- + c('sinVwE_cosEl_d2_') * sinVwE * cosEl * invD2;
165
- }
166
-
167
- module.exports = { evaluateParallaxBasis, gravitationTermDeltasDeg, evaluateElongationBasis };
@@ -1,248 +0,0 @@
1
- /**
2
- * Published reference curves — the external comparison formulas and
3
- * datasets the model is plotted against (Phase 8.6). Single-copy
4
- * extraction from the browser; every curve is EXACTLY its published
5
- * form, with the source on each. These are comparison references, never
6
- * model inputs (the §2d goalpost rule: they are hard-coded here, not
7
- * injectable constants).
8
- *
9
- * Sources:
10
- * - Laskar (2004) analytic tropical-year polynomial.
11
- * - Peters: linear solar-day lengthening (1.7 ms/cy, +1.8 cy offset).
12
- * - Chapront: sidereal-year polynomial.
13
- * - Capitaine et al. (2009): general-precession rate polynomial.
14
- * - Berger, A.L. (1978), J. Atmos. Sci. 35(12), 2362–2367 — epoch
15
- * 1950.0; coefficients from the palinsol R package (Crucifix).
16
- * Table 4 eccentricity (19 terms), Table 1 obliquity (47 terms).
17
- * - Vondrák, Capitaine & Wallace (2011), A&A 534, A22 — Table 3
18
- * long-term precession p_A (polynomial + 10 periodic terms).
19
- * - Laskar et al. (2004), A&A 428, 261–285 — the La2004 N-body
20
- * solution (IMCCE): [year, eccentricity, obliquity°, perihelion°]
21
- * at 1000-yr intervals, −250,000..+100,000 from J2000, linearly
22
- * interpolated.
23
- * - Stephenson et al. (2016) ΔT cubic-spline segments (the poly is
24
- * app-loaded JSON data; only the pure evaluator lives here).
25
- * - Meeus (1998) eq. 22.2 first-order mean obliquity — DELIBERATELY
26
- * the IAU 1976/1980 convention (23.4392911°, −46.8150″/cy) because
27
- * the Meeus-comparison reports are checked against Meeus's own
28
- * worked values; NOT the same quantity as the IAU 2006 obliquity.
29
- *
30
- * The four T-based analytic polynomials need the engine's approximate
31
- * calendar→JD conversion — injected via createPublishedCurves.
32
- */
33
-
34
- 'use strict';
35
-
36
- const _BER78_ARCSEC2RAD = Math.PI / (180 * 3600);
37
- const _BER78_DEG2RAD = Math.PI / 180;
38
-
39
- // Berger 1978 Table 4: Eccentricity (19 terms) — e·sin(ω̃), e·cos(ω̃) projections
40
- const _BER78_ECC = [
41
- [0.01860798, 4.207205, 28.620089], [0.01627522, 7.346091, 193.788772],
42
- [-0.01300660, 17.857263, 308.307024], [0.00988829, 17.220546, 320.199637],
43
- [-0.00336700, 16.846733, 279.376984], [0.00333077, 5.199079, 87.195000],
44
- [-0.00235400, 18.231076, 349.129677], [0.00140015, 26.216758, 128.443387],
45
- [0.00100700, 6.359169, 154.143880], [0.00085700, 16.210016, 291.269597],
46
- [0.00064990, 3.065181, 114.860583], [0.00059900, 16.583829, 332.092251],
47
- [0.00037800, 18.493980, 296.414411], [-0.00033700, 6.190953, 145.769910],
48
- [0.00027600, 18.867793, 337.237063], [0.00018200, 17.425567, 152.092288],
49
- [-0.00017400, 6.186001, 126.839891], [-0.00012400, 18.417441, 210.667199],
50
- [0.00001250, 0.667863, 72.108838],
51
- ];
52
-
53
- /** Berger (1978) eccentricity. @param {number} year @returns {number} */
54
- function eccBerger1978(year) {
55
- const t = year - 1950; // years from 1950.0
56
- let esinP = 0, ecosP = 0;
57
- for (const [M, rate, phase] of _BER78_ECC) {
58
- const arg = rate * _BER78_ARCSEC2RAD * t + phase * _BER78_DEG2RAD;
59
- esinP += M * Math.sin(arg);
60
- ecosP += M * Math.cos(arg);
61
- }
62
- return Math.sqrt(esinP * esinP + ecosP * ecosP);
63
- }
64
-
65
- // Berger 1978 Table 1: Obliquity (47 terms) — amplitudes in arcseconds
66
- const _BER78_OBL_MEAN = 23.320556; // degrees
67
- const _BER78_OBL = [
68
- [-2462.2214466, 31.609974, 251.9025], [-857.3232075, 32.620504, 280.8325],
69
- [-629.3231835, 24.172203, 128.3057], [-414.2804924, 31.983787, 292.7252],
70
- [-311.7632587, 44.828336, 15.3747], [308.9408604, 30.973257, 263.7951],
71
- [-162.5533601, 43.668246, 308.4258], [-116.1077911, 32.246691, 240.0099],
72
- [101.1189923, 30.599444, 222.9725], [-67.6856209, 42.681324, 268.7809],
73
- [24.9079067, 43.836462, 316.7998], [22.5811241, 47.439436, 319.6024],
74
- [-21.1648355, 63.219948, 143.8050], [-15.6549876, 64.230478, 172.7351],
75
- [15.3936813, 1.010530, 28.9300], [14.6660938, 7.437771, 123.5968],
76
- [-11.7273029, 55.782177, 20.2082], [10.2742696, 0.373813, 40.8226],
77
- [6.4914588, 13.218362, 123.4722], [5.8539148, 62.583231, 155.6977],
78
- [-5.4872205, 63.593761, 184.6277], [-5.4290191, 76.438310, 267.2772],
79
- [5.1609570, 45.815258, 55.0196], [5.0786314, 8.448301, 152.5268],
80
- [-4.0735782, 56.792707, 49.1382], [3.7227167, 49.747842, 204.6609],
81
- [3.3971932, 12.058272, 56.5233], [-2.8347004, 75.278220, 200.3284],
82
- [-2.6550721, 65.241008, 201.6651], [-2.5717867, 64.604291, 213.5577],
83
- [-2.4712188, 1.647247, 17.0374], [2.4625410, 7.811584, 164.4194],
84
- [2.2464112, 12.207832, 94.5422], [-2.0755511, 63.856665, 131.9124],
85
- [-1.9713669, 56.155990, 61.0309], [-1.8813061, 77.448840, 296.2073],
86
- [-1.8468785, 6.801054, 135.4894], [1.8186742, 62.209418, 114.8750],
87
- [1.7601888, 20.656133, 247.0691], [-1.5428851, 48.344406, 256.6114],
88
- [1.4738838, 55.145460, 32.1008], [-1.4593669, 69.000539, 143.6804],
89
- [1.4192259, 11.071350, 16.8784], [-1.1818980, 74.291298, 160.6835],
90
- [1.1756474, 11.047742, 27.5932], [-1.1316126, 0.636717, 348.1074],
91
- [1.0896928, 12.844549, 82.6496],
92
- ];
93
-
94
- /** Berger (1978) obliquity, degrees. @param {number} year @returns {number} */
95
- function obliquityBerger1978(year) {
96
- const t = year - 1950;
97
- let eps = _BER78_OBL_MEAN;
98
- for (const [A, rate, phase] of _BER78_OBL) {
99
- eps += (A / 3600) * Math.cos(rate * _BER78_ARCSEC2RAD * t + phase * _BER78_DEG2RAD);
100
- }
101
- return eps;
102
- }
103
-
104
- // Vondrák et al. (2011) Table 3: general precession p_A periodic terms
105
- const _VONDRAK_PA = [
106
- // [period_cy, Cp, Sp]
107
- [409.90, -6908.287473, -2845.175469],
108
- [396.15, -3198.706291, 449.844989],
109
- [537.22, 1453.674527, -1255.915323],
110
- [402.90, -857.748557, 886.736783],
111
- [417.15, 1173.231614, 418.887514],
112
- [288.92, -156.981465, 997.912441],
113
- [4043.00, 371.836550, -240.979710],
114
- [306.00, -216.619040, 76.541307],
115
- [277.00, 193.691479, -36.788069],
116
- [203.00, 11.891524, -170.964086],
117
- ];
118
-
119
- /** Vondrák et al. (2011) axial-precession period in years (from dp_A/dT via
120
- * central difference at h = 0.01 cy). @param {number} year @returns {number} */
121
- function axialPrecessionVondrak2011(year) {
122
- const T = (year - 2000) / 100; // Julian centuries from J2000
123
- // Only the RATE dp_A/dT is used (central difference below); the browser
124
- // original also accumulated p_A itself at T, dead code lint rejects here.
125
- const h = 0.01;
126
- const T1 = T + h, T2 = T - h;
127
- let pA1 = 8134.017132 + 5043.0520035 * T1 - 0.00710733 * T1 * T1 + 271e-9 * Math.pow(T1, 3);
128
- let pA2 = 8134.017132 + 5043.0520035 * T2 - 0.00710733 * T2 * T2 + 271e-9 * Math.pow(T2, 3);
129
- for (const [P, Cp, Sp] of _VONDRAK_PA) {
130
- pA1 += Cp * Math.cos(2 * Math.PI * T1 / P) + Sp * Math.sin(2 * Math.PI * T1 / P);
131
- pA2 += Cp * Math.cos(2 * Math.PI * T2 / P) + Sp * Math.sin(2 * Math.PI * T2 / P);
132
- }
133
- const rateArcsecPerCy = (pA1 - pA2) / (2 * h);
134
- if (Math.abs(rateArcsecPerCy) < 1) return NaN;
135
- return 129600000 / rateArcsecPerCy; // period in years
136
- }
137
-
138
- // Laskar et al. (2004) La2004 N-body solution (IMCCE):
139
- // [year, eccentricity, obliquity_deg, perihelionLong_deg] at 1000-yr
140
- // intervals, −250,000..+100,000 from J2000.
141
- const _LA2004 = [[-250000,0.0315165,24.3794,145.31],[-249000,0.0324735,24.3282,160.39],[-248000,0.0334116,24.2517,175.63],[-247000,0.0343575,24.1508,190.85],[-246000,0.0352765,24.0275,206.35],[-245000,0.0362297,23.884,221.93],[-244000,0.0370854,23.7231,237.64],[-243000,0.0379822,23.5486,253.47],[-242000,0.0388937,23.3647,269.5],[-241000,0.0396536,23.1757,285.63],[-240000,0.0405339,22.9871,301.88],[-239000,0.0413137,22.8039,318.29],[-238000,0.0420487,22.6311,334.86],[-237000,0.042808,22.4744,351.49],[-236000,0.043484,22.3385,8.2],[-235000,0.0441832,22.2273,25.14],[-234000,0.0447901,22.1451,41.98],[-233000,0.0453852,22.0942,58.96],[-232000,0.0459956,22.0762,75.98],[-231000,0.0464806,22.0923,92.96],[-230000,0.046954,22.1415,109.96],[-229000,0.0474756,22.2224,126.88],[-228000,0.0477953,22.3327,143.83],[-227000,0.0482131,22.4684,160.66],[-226000,0.0485252,22.6253,177.37],[-225000,0.0488191,22.799,194.11],[-224000,0.0490673,22.9837,210.67],[-223000,0.0492749,23.1744,227.11],[-222000,0.0494882,23.3659,243.57],[-221000,0.0496216,23.553,259.8],[-220000,0.0497211,23.7311,276.04],[-219000,0.0498639,23.8964,292.12],[-218000,0.0498886,24.0447,308.17],[-217000,0.0499196,24.1733,324.16],[-216000,0.049952,24.2798,340.02],[-215000,0.0499272,24.362,355.9],[-214000,0.0498877,24.4188,11.76],[-213000,0.0498077,24.4498,27.45],[-212000,0.0497544,24.4546,43.3],[-211000,0.0496173,24.4339,59.04],[-210000,0.0494747,24.389,74.79],[-209000,0.0493332,24.321,90.58],[-208000,0.0491811,24.2325,106.39],[-207000,0.04892,24.1258,122.23],[-206000,0.048776,24.0035,138.08],[-205000,0.0485283,23.8691,154.03],[-204000,0.0482621,23.7258,169.99],[-203000,0.0480422,23.5768,186.01],[-202000,0.0477501,23.426,202.06],[-201000,0.0474933,23.2765,218.23],[-200000,0.0471698,23.1317,234.36],[-199000,0.0468767,22.9949,250.58],[-198000,0.046592,22.8688,266.9],[-197000,0.0462137,22.7558,283.14],[-196000,0.0458929,22.6582,299.5],[-195000,0.0455855,22.5776,315.82],[-194000,0.0451592,22.5151,332.21],[-193000,0.0448202,22.4717,348.54],[-192000,0.0444461,22.4476,4.88],[-191000,0.0440074,22.4425,21.25],[-190000,0.0436324,22.4562,37.53],[-189000,0.0431482,22.4877,53.76],[-188000,0.0427588,22.5357,70.08],[-187000,0.0422439,22.5989,86.21],[-186000,0.041765,22.6756,102.37],[-185000,0.0413159,22.764,118.5],[-184000,0.0407789,22.8622,134.51],[-183000,0.0402464,22.9682,150.54],[-182000,0.0397952,23.0799,166.37],[-181000,0.0392173,23.1954,182.29],[-180000,0.0387022,23.3123,198.03],[-179000,0.0381743,23.4287,213.63],[-178000,0.0376354,23.5424,229.33],[-177000,0.0370789,23.6513,244.79],[-176000,0.0365263,23.7531,260.15],[-175000,0.0359868,23.846,275.59],[-174000,0.0354318,23.9279,290.72],[-173000,0.0348408,23.9972,305.92],[-172000,0.0343287,24.0524,320.92],[-171000,0.0337606,24.0923,335.92],[-170000,0.0331736,24.1157,350.77],[-169000,0.0326849,24.1222,5.52],[-168000,0.032105,24.1113,20.23],[-167000,0.0316027,24.0828,34.9],[-166000,0.0310757,24.0371,49.35],[-165000,0.0306075,23.9745,63.88],[-164000,0.0301362,23.8959,78.36],[-163000,0.0296773,23.8025,92.62],[-162000,0.0292961,23.696,107.04],[-161000,0.0289342,23.5782,121.36],[-160000,0.0285697,23.4517,135.63],[-159000,0.0283255,23.3192,149.96],[-158000,0.0281089,23.184,164.28],[-157000,0.0278894,23.0495,178.66],[-156000,0.0278304,22.9196,193.04],[-155000,0.0277609,22.7981,207.45],[-154000,0.0277789,22.689,222.05],[-153000,0.0278466,22.5955,236.56],[-152000,0.0280041,22.5214,251.16],[-151000,0.0281962,22.4693,266.04],[-150000,0.0284393,22.441,280.66],[-149000,0.0287575,22.4381,295.63],[-148000,0.0291433,22.4611,310.56],[-147000,0.0295163,22.5092,325.55],[-146000,0.0299744,22.5815,340.61],[-145000,0.0305242,22.676,355.72],[-144000,0.030976,22.7897,10.87],[-143000,0.0315819,22.9198,26.05],[-142000,0.0321592,23.0623,41.19],[-141000,0.0327355,23.2131,56.51],[-140000,0.0333691,23.3681,71.7],[-139000,0.0339709,23.5227,86.95],[-138000,0.0346175,23.6725,102.3],[-137000,0.0352474,23.8134,117.58],[-136000,0.0358264,23.9412,132.88],[-135000,0.036557,24.0522,148.29],[-134000,0.0370818,24.1435,163.64],[-133000,0.0377168,24.2122,179.06],[-132000,0.0383481,24.2565,194.51],[-131000,0.0388824,24.2753,210.02],[-130000,0.0394456,24.2675,225.61],[-129000,0.0399994,24.2336,241.14],[-128000,0.0404894,24.1743,256.94],[-127000,0.0409858,24.091,272.65],[-126000,0.0414099,23.9858,288.48],[-125000,0.0418623,23.8616,304.47],[-124000,0.0422427,23.7213,320.48],[-123000,0.0425465,23.5689,336.59],[-122000,0.042919,23.4086,352.84],[-121000,0.043149,23.2448,9.16],[-120000,0.0433711,23.0822,25.62],[-119000,0.0435785,22.9257,42.11],[-118000,0.0437217,22.7796,58.75],[-117000,0.043813,22.6485,75.51],[-116000,0.0438771,22.5361,92.2],[-115000,0.0439208,22.4458,109.12],[-114000,0.0438843,22.3803,126],[-113000,0.0438391,22.3412,142.88],[-112000,0.0437289,22.3295,159.85],[-111000,0.043647,22.3455,176.76],[-110000,0.0434158,22.388,193.69],[-109000,0.0432494,22.4555,210.53],[-108000,0.0430309,22.5459,227.36],[-107000,0.0427226,22.6559,244.14],[-106000,0.042452,22.7821,260.81],[-105000,0.0421227,22.9209,277.36],[-104000,0.0417688,23.0682,293.99],[-103000,0.0413776,23.2201,310.31],[-102000,0.0409648,23.3727,326.66],[-101000,0.0405626,23.522,342.95],[-100000,0.04006,23.6647,359.07],[-99000,0.0395846,23.7976,15.17],[-98000,0.0391425,23.9176,31.2],[-97000,0.0385531,24.0227,47.13],[-96000,0.0380871,24.1109,63.05],[-95000,0.0375395,24.1805,78.79],[-94000,0.0369975,24.2308,94.65],[-93000,0.0364478,24.2612,110.35],[-92000,0.0358754,24.2714,125.97],[-91000,0.0353196,24.2617,141.71],[-90000,0.0347434,24.2329,157.27],[-89000,0.0341063,24.1855,172.89],[-88000,0.0335975,24.1209,188.49],[-87000,0.0329379,24.0405,204.11],[-86000,0.0323467,23.9458,219.69],[-85000,0.0317999,23.839,235.28],[-84000,0.0311582,23.7219,250.92],[-83000,0.0305811,23.5968,266.59],[-82000,0.0299867,23.4662,282.11],[-81000,0.0294041,23.3325,297.89],[-80000,0.0288047,23.198,313.58],[-79000,0.0282095,23.0655,329.22],[-78000,0.027646,22.9373,345.08],[-77000,0.0270783,22.8158,0.82],[-76000,0.02647,22.7035,16.67],[-75000,0.0259517,22.6028,32.47],[-74000,0.0254081,22.5157,48.38],[-73000,0.0248079,22.4445,64.28],[-72000,0.0243451,22.3907,80.09],[-71000,0.0237902,22.356,96.01],[-70000,0.0232796,22.3415,111.94],[-69000,0.0227768,22.348,127.66],[-68000,0.0222938,22.3755,143.5],[-67000,0.0217932,22.4241,159.32],[-66000,0.0213111,22.4929,174.82],[-65000,0.0208223,22.5806,190.53],[-64000,0.0203886,22.6857,205.93],[-63000,0.0198634,22.8062,221.33],[-62000,0.0194167,22.9394,236.54],[-61000,0.0189825,23.0826,251.63],[-60000,0.0184692,23.2329,266.65],[-59000,0.0180438,23.3869,281.46],[-58000,0.0176055,23.5413,296.01],[-57000,0.017156,23.693,310.79],[-56000,0.0167394,23.8382,324.93],[-55000,0.0163304,23.9741,339.16],[-54000,0.0159614,24.0975,353.36],[-53000,0.0155713,24.2052,7.12],[-52000,0.0152168,24.295,20.85],[-51000,0.0149581,24.3644,34.65],[-50000,0.0146002,24.4113,47.95],[-49000,0.0143854,24.4346,61.51],[-48000,0.0141818,24.4332,74.72],[-47000,0.0139868,24.4064,88.08],[-46000,0.0138427,24.3549,101.34],[-45000,0.0137927,24.279,114.34],[-44000,0.0137057,24.1803,127.89],[-43000,0.0137194,24.0608,141.04],[-42000,0.0137352,23.9228,154.35],[-41000,0.0138241,23.7693,168.05],[-40000,0.0139293,23.6042,181.64],[-39000,0.0140394,23.4307,195.37],[-38000,0.0142706,23.2534,209.58],[-37000,0.0144241,23.0769,223.72],[-36000,0.0146517,22.9055,238.2],[-35000,0.0149423,22.7439,252.89],[-34000,0.015175,22.5969,267.79],[-33000,0.0154495,22.4684,283.02],[-32000,0.0157785,22.3624,298.13],[-31000,0.0160455,22.2822,313.83],[-30000,0.0163655,22.2299,329.52],[-29000,0.0166518,22.2072,345.26],[-28000,0.0169668,22.2148,1.3],[-27000,0.017279,22.2518,17.51],[-26000,0.0175068,22.3173,33.5],[-25000,0.0178681,22.4089,49.92],[-24000,0.0180946,22.523,66.2],[-23000,0.0183406,22.6566,82.54],[-22000,0.0186174,22.8053,98.89],[-21000,0.0188354,22.9641,115.23],[-20000,0.0190027,23.129,131.69],[-19000,0.0192231,23.2951,147.9],[-18000,0.0193471,23.4577,164.3],[-17000,0.019487,23.6129,180.71],[-16000,0.0195602,23.7568,196.91],[-15000,0.0196349,23.8859,213.3],[-14000,0.0196791,23.9975,229.67],[-13000,0.0196506,24.0892,245.93],[-12000,0.0196128,24.1592,262.38],[-11000,0.0195974,24.2067,278.66],[-10000,0.0194246,24.2307,295.27],[-9000,0.0193255,24.2314,311.59],[-8000,0.0191801,24.2096,328.15],[-7000,0.0189374,24.166,344.84],[-6000,0.0187484,24.1024,1.41],[-5000,0.0184535,24.0211,18.08],[-4000,0.0182109,23.9241,35.03],[-3000,0.0178458,23.8144,51.77],[-2000,0.0174968,23.6949,68.76],[-1000,0.0171614,23.5688,85.82],[0,0.0167024,23.4393,102.92],[1000,0.0162752,23.3099,120.24],[2000,0.0158501,23.1837,137.38],[3000,0.0153397,23.0639,155],[4000,0.0148355,22.9537,172.44],[5000,0.0143165,22.8553,189.84],[6000,0.0137745,22.7714,207.76],[7000,0.0132086,22.7037,225.38],[8000,0.0125777,22.6534,243.17],[9000,0.0120396,22.6214,261.14],[10000,0.0113842,22.6081,279.19],[11000,0.0107392,22.613,297.22],[12000,0.0101622,22.6358,315.51],[13000,0.0094766,22.6752,333.75],[14000,0.0088687,22.7299,352.45],[15000,0.0082117,22.7981,10.7],[16000,0.0076037,22.8779,29.64],[17000,0.0069711,22.9669,48.77],[18000,0.0063187,23.063,67.63],[19000,0.0057218,23.1637,87.47],[20000,0.0051508,23.2665,107.44],[21000,0.0044876,23.3691,128.61],[22000,0.0039799,23.4692,150.09],[23000,0.0034542,23.5645,173.52],[24000,0.0029897,23.6532,199.81],[25000,0.0026293,23.7335,227.07],[26000,0.0024025,23.8038,257.55],[27000,0.0024027,23.8628,290.12],[28000,0.0024327,23.9093,321.06],[29000,0.0027336,23.9423,350.12],[30000,0.0030507,23.9611,15.72],[31000,0.0034656,23.9654,40.22],[32000,0.0038979,23.9547,62.27],[33000,0.0043068,23.9292,82.51],[34000,0.0048111,23.8891,102.79],[35000,0.0052274,23.835,121.54],[36000,0.0056449,23.7678,140.49],[37000,0.0061018,23.6887,158.19],[38000,0.0065058,23.599,176.39],[39000,0.0068818,23.5005,194.27],[40000,0.0072957,23.3951,211.25],[41000,0.0076519,23.2851,229.03],[42000,0.0080371,23.1731,246.2],[43000,0.0083584,23.0615,263.2],[44000,0.0087128,22.953,280.34],[45000,0.0090746,22.8507,297.3],[46000,0.0093273,22.7572,314.23],[47000,0.0096936,22.6751,330.98],[48000,0.0099767,22.6072,347.7],[49000,0.0102492,22.5555,4.59],[50000,0.010534,22.522,21.08],[51000,0.0108041,22.5083,37.52],[52000,0.0110625,22.5153,54.49],[53000,0.0112886,22.5434,70.53],[54000,0.0115398,22.5926,87.08],[55000,0.0117922,22.6617,103.53],[56000,0.0119791,22.7496,119.72],[57000,0.0122013,22.8541,135.91],[58000,0.0124675,22.9727,152.1],[59000,0.0126032,23.1024,168.15],[60000,0.0128592,23.2402,184.18],[61000,0.0130467,23.3822,199.93],[62000,0.013238,23.5251,215.96],[63000,0.0134382,23.6653,231.64],[64000,0.0136253,23.7993,247.19],[65000,0.0138244,23.9236,263.02],[66000,0.014012,24.0353,278.45],[67000,0.0141457,24.1312,293.92],[68000,0.0144056,24.2091,309.41],[69000,0.0145104,24.2668,324.82],[70000,0.0146758,24.3024,340.18],[71000,0.0148766,24.3151,355.49],[72000,0.0149859,24.3043,10.86],[73000,0.015121,24.2695,26.31],[74000,0.015268,24.2118,41.4],[75000,0.0153626,24.1321,57.05],[76000,0.0154713,24.0317,72.35],[77000,0.0155409,23.9132,87.77],[78000,0.015628,23.7789,103.37],[79000,0.0157098,23.632,118.94],[80000,0.0156889,23.4759,134.57],[81000,0.0158005,23.3143,150.25],[82000,0.0157903,23.1512,166.06],[83000,0.0157705,22.991,181.91],[84000,0.0158109,22.8375,197.72],[85000,0.0157672,22.695,213.64],[86000,0.0157318,22.5675,229.75],[87000,0.0156819,22.4583,245.49],[88000,0.0156346,22.3704,261.59],[89000,0.0155539,22.3066,277.6],[90000,0.0154636,22.2682,293.34],[91000,0.0153624,22.2563,309.34],[92000,0.0153008,22.2713,325.02],[93000,0.0151278,22.3122,340.72],[94000,0.0150463,22.3777,356.19],[95000,0.0149407,22.4658,11.55],[96000,0.014781,22.5736,26.81],[97000,0.014683,22.6979,41.81],[98000,0.0145718,22.8354,56.46],[99000,0.0144578,22.982,71.43],[100000,0.0143543,23.1341,85.57]];
142
-
143
- /** Interpolate La2004. col: 1=eccentricity, 2=obliquity, 3=perihelionLong.
144
- * @param {number} year - years from J2000 @param {number} col @returns {number} */
145
- function _la2004Interp(year, col) {
146
- if (year < _LA2004[0][0] || year > _LA2004[_LA2004.length - 1][0]) return NaN;
147
- const idx = (year - _LA2004[0][0]) / 1000;
148
- const i = Math.floor(idx);
149
- if (i >= _LA2004.length - 1) return _LA2004[_LA2004.length - 1][col];
150
- const frac = idx - i;
151
- return _LA2004[i][col] * (1 - frac) + _LA2004[i + 1][col] * frac;
152
- }
153
-
154
- /** La2004 eccentricity at calendar year. @param {number} year @returns {number} */
155
- function eccLa2004(year) { return _la2004Interp(year - 2000, 1); }
156
- /** La2004 obliquity (degrees) at calendar year. @param {number} year @returns {number} */
157
- function obliquityLa2004(year) { return _la2004Interp(year - 2000, 2); }
158
- /** La2004 perihelion longitude (degrees) at calendar year — WRAP-AWARE:
159
- * the longitude wraps at 360°/0°, so adjacent samples are unwrapped before
160
- * interpolating. @param {number} year @returns {number} */
161
- function perihelionLa2004(year) {
162
- const yearFromJ2000 = year - 2000;
163
- if (yearFromJ2000 < _LA2004[0][0] || yearFromJ2000 > _LA2004[_LA2004.length - 1][0]) return NaN;
164
- const idx = (yearFromJ2000 - _LA2004[0][0]) / 1000;
165
- const i = Math.floor(idx);
166
- if (i >= _LA2004.length - 1) return _LA2004[_LA2004.length - 1][3];
167
- const frac = idx - i;
168
- const v0 = _LA2004[i][3];
169
- let v1 = _LA2004[i + 1][3];
170
- // Unwrap: if values jump by more than 180°, adjust
171
- if (v1 - v0 > 180) v1 -= 360;
172
- else if (v0 - v1 > 180) v1 += 360;
173
- return ((v0 * (1 - frac) + v1 * frac) % 360 + 360) % 360;
174
- }
175
-
176
- /**
177
- * Stephenson et al. (2016) ΔT cubic-spline evaluator. The poly (segments
178
- * with [y0, y1, a0..a3]) is app-loaded JSON data — only the pure evaluator
179
- * lives here. Returns null outside the poly's window.
180
- * @param {number} year
181
- * @param {{ segments: Array<{y0: number, y1: number, a: number[]}> }} poly
182
- * @returns {number|null}
183
- */
184
- function stephensonDeltaT(year, poly) {
185
- for (const seg of poly.segments) {
186
- if (seg.y0 <= year && year <= seg.y1) {
187
- const t = (year - seg.y0) / (seg.y1 - seg.y0);
188
- const [a0, a1, a2, a3] = seg.a;
189
- return a0 + a1*t + a2*t*t + a3*t*t*t;
190
- }
191
- }
192
- return null;
193
- }
194
-
195
- /** Meeus (1998) eq. 22.2 first-order mean obliquity, RADIANS — the IAU
196
- * 1976/1980 convention, deliberately (see the module header).
197
- * @param {number} T - Julian centuries TT from J2000 @returns {number} */
198
- function meeusMeanObliquityRad(T) {
199
- return (23.4392911 - 0.0130042 * T) * (Math.PI / 180);
200
- }
201
-
202
- /**
203
- * The four T-based analytic polynomials, bound to the engine's approximate
204
- * calendar→JD conversion.
205
- * @param {{ yearToJDApprox: (year: number) => number, j2000JD: number,
206
- * julianCenturyDays: number }} deps
207
- */
208
- function createPublishedCurves(deps) {
209
- /** Laskar (2004) tropical year, days. @param {number} year @returns {number} */
210
- function tropicalYearLaskar(year) {
211
- const T = (deps.yearToJDApprox(year) - deps.j2000JD) / deps.julianCenturyDays;
212
- return 365.2421896698 - 0.00000615359 * T
213
- - 0.000000000729 * T * T + 0.000000000264 * Math.pow(T, 3);
214
- }
215
-
216
- /** Peters linear solar-day lengthening, SI seconds. @param {number} year @returns {number} */
217
- function solarDayPeters(year) {
218
- const T = (deps.yearToJDApprox(year) - deps.j2000JD) / deps.julianCenturyDays;
219
- return 86400 + (T + 1.8) * 0.0017;
220
- }
221
-
222
- /** Chapront sidereal year, days. @param {number} year @returns {number} */
223
- function siderealYearChapront(year) {
224
- const T = (deps.yearToJDApprox(year) - deps.j2000JD) / deps.julianCenturyDays;
225
- return 365.256362953 + 0.0000001139 * T
226
- - 0.000000000076 * T * T - 0.00000000000169 * Math.pow(T, 3);
227
- }
228
-
229
- /** Capitaine et al. (2009) axial-precession period, years. @param {number} year @returns {number} */
230
- function axialPrecessionCapitaine2009(year) {
231
- const T = (deps.yearToJDApprox(year) - deps.j2000JD) / deps.julianCenturyDays;
232
- const rateArcsecPerCy = 5028.796195 + 2.2108696 * T
233
- + 0.00023892 * T * T - 0.000095428 * Math.pow(T, 3)
234
- - 0.0000001915 * Math.pow(T, 4);
235
- if (Math.abs(rateArcsecPerCy) < 1) return NaN;
236
- // rate is arcsec/century; full circle = 1,296,000 arcsec
237
- return 129600000 / rateArcsecPerCy;
238
- }
239
-
240
- return { tropicalYearLaskar, solarDayPeters, siderealYearChapront, axialPrecessionCapitaine2009 };
241
- }
242
-
243
- module.exports = {
244
- createPublishedCurves,
245
- eccBerger1978, obliquityBerger1978, axialPrecessionVondrak2011,
246
- eccLa2004, obliquityLa2004, perihelionLa2004,
247
- stephensonDeltaT, meeusMeanObliquityRad,
248
- };