@essrt/physics 22.1.0 → 23.2.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/README.md +2 -1
- package/package.json +9 -3
- package/src/constants/coefficients.d.ts +11 -11
- package/src/constants/coefficients.js +4 -4
- package/src/constants/generated.d.ts +4 -16
- package/src/constants/generated.js +8 -32
- package/src/constants/units.cjs +20 -0
- package/src/deltat/deep-time-chain.js +457 -0
- package/src/deltat/deep-time.cjs +68 -25
- package/src/deltat/moon-distance-artifact.cjs +23 -0
- package/src/deltat/moon-distance-history.cjs +115 -0
- package/src/earth/deep-orbital-history.cjs +69 -19
- package/src/earth/mass-chain.cjs +95 -0
- package/src/earth/mean-obliquity-history.cjs +94 -0
- package/src/earth/precession-composed.cjs +49 -3
- package/src/index.js +23 -1
- package/src/layer0/derive-params.js +1 -5
- package/src/layer0/index.js +30 -17
- package/src/math/angles.cjs +38 -0
- package/src/model.js +100 -266
- package/src/moon/arguments.cjs +5 -31
- package/src/moon/month-chain.cjs +12 -19
- package/src/planets/chain-artifact.js +2 -2
- package/src/time/calendar.cjs +165 -0
- package/types/constants/coefficients.d.ts +11 -11
- package/types/constants/generated.d.ts +4 -16
- package/types/constants/units.d.cts +8 -0
- package/types/deltat/deep-time-chain.d.ts +266 -0
- package/types/deltat/deep-time.d.cts +42 -12
- package/types/deltat/moon-distance-artifact.d.cts +22 -0
- package/types/deltat/moon-distance-history.d.cts +36 -0
- package/types/earth/deep-orbital-history.d.cts +5 -3
- package/types/earth/mass-chain.d.cts +78 -0
- package/types/earth/mean-obliquity-history.d.cts +32 -0
- package/types/earth/precession-composed.d.cts +11 -1
- package/types/index.d.ts +8 -1
- package/types/layer0/derive-params.d.ts +3 -2
- package/types/layer0/index.d.ts +9 -6
- package/types/math/angles.d.cts +18 -0
- package/types/model.d.ts +21 -3
- package/types/moon/arguments.d.cts +2 -6
- package/types/moon/month-chain.d.cts +7 -13
- package/types/time/calendar.d.cts +78 -0
- package/src/deltat/recession-history.cjs +0 -169
- package/types/deltat/recession-history.d.cts +0 -80
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Earth–Moon distance history — a CITED PHYSICAL INPUT, read as a shape
|
|
3
|
+
* on the model's own J2000 anchor (plan 12, option A).
|
|
4
|
+
*
|
|
5
|
+
* WHY AN INPUT. Everything downstream of a(t) is derived here by our own
|
|
6
|
+
* equations: the day length by angular-momentum conservation (deep-time.cjs),
|
|
7
|
+
* the composed lunisolar precession and the clock T_p(t)
|
|
8
|
+
* (earth/precession-composed.cjs), the month chain (moon/month-chain.cjs).
|
|
9
|
+
* a(t) itself cannot be derived without an ocean-tide dissipation history —
|
|
10
|
+
* the continental configuration and the resonance crossings that decide how
|
|
11
|
+
* fast the Moon recedes in each era — and the model has no physics for it.
|
|
12
|
+
* With constant dissipation at today's rate the Moon sits at the Roche limit
|
|
13
|
+
* 1.5 Gyr ago, three billion years too late for its age. The published
|
|
14
|
+
* solution that computes that history from a modelled ocean is Farhat,
|
|
15
|
+
* Auclair-Desrotour, Boué & Laskar 2022 (A&A 665, L1), distributed as the
|
|
16
|
+
* AstroGeo22 ephemeris; it is the input, as the planetary masses are DE440's
|
|
17
|
+
* and p₀ is IAU 2006's. Before plan 12 the history was a quartic whose two
|
|
18
|
+
* higher coefficients were least-squares fitted to that same curve (0.5 h of
|
|
19
|
+
* day off at 1 Ga) and, beyond 1 Ga, a spline through knots fitted to the
|
|
20
|
+
* rock record — a fit to the data the falsification leg then tested.
|
|
21
|
+
*
|
|
22
|
+
* WHAT IS READ. The table's distance column as the RATIO r(t) = a(t)/a(0):
|
|
23
|
+
* Farhat's a is the Keplerian semi-major axis (383,598 km at J2000); the
|
|
24
|
+
* model's anchor is the observed mean distance (384,399 km). The history
|
|
25
|
+
* enters as a(t) = a₀ · r(t), so J2000 stays the observation and the shape is
|
|
26
|
+
* Farhat's.
|
|
27
|
+
*
|
|
28
|
+
* INTERPOLATION. Monotone cubic Hermite (Fritsch–Carlson) between the 1-Myr
|
|
29
|
+
* samples — C1, so the LOD-rate decomposition's tidal term (the slope) is
|
|
30
|
+
* smooth. The J2000 END-SLOPE is the OBSERVED LLR recession rate, the α₁
|
|
31
|
+
* input (3.820 cm/yr; Farhat's own first sample reads 3.833, his fit to the
|
|
32
|
+
* same observation): the boundary condition is the measurement, so the ΔT
|
|
33
|
+
* era's tidal term does not move with the input.
|
|
34
|
+
*
|
|
35
|
+
* DOMAIN. Forward of J2000 (t < 0) the LLR rate is held constant — the
|
|
36
|
+
* charts' labelled extrapolation (the input has no future). Beyond the
|
|
37
|
+
* table's last sample (4,429 Ma — the lunar age is the input's end) the
|
|
38
|
+
* history REFUSES: null, never an extrapolation. The former "Roche crossing
|
|
39
|
+
* at 4.498 Ga, a self-validation" was the spline's pinned endpoint, not a
|
|
40
|
+
* derivation, and is withdrawn.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
'use strict';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} MoonDistanceTable
|
|
47
|
+
* @property {ReadonlyArray<number>} ageMa - ascending, 0 first, uniform 1-Myr step
|
|
48
|
+
* @property {ReadonlyArray<number>} aEarthRadii - the distance column (any consistent unit; only ratios are read)
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param {{ table: MoonDistanceTable, aMoonNowMetres: number, alpha1PerMa: number }} deps
|
|
53
|
+
* aMoonNowMetres — the model's J2000 anchor (the observed mean distance);
|
|
54
|
+
* alpha1PerMa — the LLR rate as a fraction of a₀ per Ma (negative into the past: a shrinks).
|
|
55
|
+
* @returns {{
|
|
56
|
+
* distanceMetresAtAge: (tMa: number) => number|null,
|
|
57
|
+
* slopeMetresPerMaAtAge: (tMa: number) => number|null,
|
|
58
|
+
* ratioAtAge: (tMa: number) => number|null,
|
|
59
|
+
* spanMa: number,
|
|
60
|
+
* }}
|
|
61
|
+
*/
|
|
62
|
+
function createMoonDistanceHistory(deps) {
|
|
63
|
+
const { table, aMoonNowMetres: aNow, alpha1PerMa: a1 } = deps;
|
|
64
|
+
const ages = table.ageMa, aRE = table.aEarthRadii;
|
|
65
|
+
const n = ages.length;
|
|
66
|
+
if (!(n >= 2) || aRE.length !== n || ages[0] !== 0) throw new Error('moon-distance-history: the table must start at age 0 with ≥ 2 samples');
|
|
67
|
+
const step = ages[1] - ages[0];
|
|
68
|
+
for (let i = 1; i < n; i++) {
|
|
69
|
+
if (ages[i] - ages[i - 1] !== step) throw new Error(`moon-distance-history: non-uniform age step at index ${i}`);
|
|
70
|
+
if (aRE[i] > aRE[i - 1]) throw new Error(`moon-distance-history: the distance must be monotone into the past (index ${i})`);
|
|
71
|
+
}
|
|
72
|
+
const spanMa = ages[n - 1];
|
|
73
|
+
// The ratio table and its Fritsch–Carlson tangents (ratio per Ma).
|
|
74
|
+
const r = new Float64Array(n);
|
|
75
|
+
for (let i = 0; i < n; i++) r[i] = aRE[i] / aRE[0];
|
|
76
|
+
const d = new Float64Array(n - 1);
|
|
77
|
+
for (let i = 0; i < n - 1; i++) d[i] = (r[i + 1] - r[i]) / step;
|
|
78
|
+
const m = new Float64Array(n);
|
|
79
|
+
m[0] = a1; // the LLR observation, in ratio/Ma
|
|
80
|
+
for (let i = 1; i < n - 1; i++) m[i] = (d[i - 1] * d[i] <= 0) ? 0 : (d[i - 1] + d[i]) / 2;
|
|
81
|
+
m[n - 1] = d[n - 2];
|
|
82
|
+
for (let i = 0; i < n - 1; i++) { // monotonicity limiter (Fritsch–Carlson)
|
|
83
|
+
if (d[i] === 0) { m[i] = 0; m[i + 1] = 0; continue; }
|
|
84
|
+
const al = m[i] / d[i], be = m[i + 1] / d[i];
|
|
85
|
+
const s = al * al + be * be;
|
|
86
|
+
if (s > 9) { const tau = 3 / Math.sqrt(s); m[i] = tau * al * d[i]; m[i + 1] = tau * be * d[i]; }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** @param {number} tMa @returns {number|null} the ratio a(t)/a₀ */
|
|
90
|
+
function ratioAtAge(tMa) {
|
|
91
|
+
if (tMa <= 0) return 1 + a1 * tMa; // forward: the LLR rate held constant (labelled extrapolation)
|
|
92
|
+
if (tMa > spanMa) return null; // beyond the input: refused
|
|
93
|
+
const i = Math.min(Math.floor(tMa / step), n - 2);
|
|
94
|
+
const h = step, s = (tMa - ages[i]) / h, s2 = s * s, s3 = s2 * s;
|
|
95
|
+
return (2 * s3 - 3 * s2 + 1) * r[i] + (s3 - 2 * s2 + s) * h * m[i]
|
|
96
|
+
+ (-2 * s3 + 3 * s2) * r[i + 1] + (s3 - s2) * h * m[i + 1];
|
|
97
|
+
}
|
|
98
|
+
/** @param {number} tMa @returns {number|null} d(ratio)/dt, per Ma */
|
|
99
|
+
function ratioSlopePerMaAtAge(tMa) {
|
|
100
|
+
if (tMa <= 0) return a1;
|
|
101
|
+
if (tMa > spanMa) return null;
|
|
102
|
+
const i = Math.min(Math.floor(tMa / step), n - 2);
|
|
103
|
+
const h = step, s = (tMa - ages[i]) / h, s2 = s * s;
|
|
104
|
+
return ((6 * s2 - 6 * s) * r[i] + (3 * s2 - 4 * s + 1) * h * m[i]
|
|
105
|
+
+ (-6 * s2 + 6 * s) * r[i + 1] + (3 * s2 - 2 * s) * h * m[i + 1]) / h;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
distanceMetresAtAge: (tMa) => { const q = ratioAtAge(tMa); return q === null ? null : aNow * q; },
|
|
109
|
+
slopeMetresPerMaAtAge: (tMa) => { const q = ratioSlopePerMaAtAge(tMa); return q === null ? null : aNow * q; },
|
|
110
|
+
ratioAtAge,
|
|
111
|
+
spanMa,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = { createMoonDistanceHistory };
|
|
@@ -57,9 +57,11 @@
|
|
|
57
57
|
* measured at the 500-yr artifact cadence: 0.16″/0.18″ rms vs IAU-2006
|
|
58
58
|
* over 1900–2100/1600–2400 vs the era tier's 0.31″/0.63″, and 0.0396°
|
|
59
59
|
* vs La2004 over −200 kyr vs the deep tier's 0.069° — the C-1 verdict,
|
|
60
|
-
* plan 02) and zetaModes serves only as the TAIL beyond the span
|
|
61
|
-
*
|
|
62
|
-
*
|
|
60
|
+
* plan 02) and zetaModes serves only as the TAIL beyond the span, joined
|
|
61
|
+
* to the series at each edge so n̂ is continuous there (plan 12 §8.3 — the
|
|
62
|
+
* J2000-point anchor left a 1.6° step at −10 Myr that kicked the hybrid's
|
|
63
|
+
* mean obliquity +0.9° for the whole tail; far outside every certified window).
|
|
64
|
+
* solarTorqueShareJ2000 and
|
|
63
65
|
* dynamicalEllipticityRatioAtYearFn: THE PRECESSION OF DATE — the two
|
|
64
66
|
* factors on the precession constant (see alphaAtGeneral below); absent,
|
|
65
67
|
* the constant is the secular law alone, bit-identical.
|
|
@@ -73,19 +75,22 @@ function createDeepOrbitalHistory({
|
|
|
73
75
|
}) {
|
|
74
76
|
const D2R = Math.PI / 180, R2D = 180 / Math.PI;
|
|
75
77
|
|
|
78
|
+
const mkRawSum = (
|
|
79
|
+
/** @type {ReadonlyArray<{omegaRadPerYr: number, re: number, im: number}>} */ modes,
|
|
80
|
+
) => (/** @type {number} */ t) => {
|
|
81
|
+
let re = 0, im = 0;
|
|
82
|
+
for (const m of modes) {
|
|
83
|
+
const c = Math.cos(m.omegaRadPerYr * t), s = Math.sin(m.omegaRadPerYr * t);
|
|
84
|
+
re += m.re * c - m.im * s;
|
|
85
|
+
im += m.re * s + m.im * c;
|
|
86
|
+
}
|
|
87
|
+
return [re, im];
|
|
88
|
+
};
|
|
76
89
|
const mkAnchored = (
|
|
77
90
|
/** @type {ReadonlyArray<{omegaRadPerYr: number, re: number, im: number}>} */ modes,
|
|
78
91
|
/** @type {[number, number]} */ anchor,
|
|
79
92
|
) => {
|
|
80
|
-
const sum = (
|
|
81
|
-
let re = 0, im = 0;
|
|
82
|
-
for (const m of modes) {
|
|
83
|
-
const c = Math.cos(m.omegaRadPerYr * t), s = Math.sin(m.omegaRadPerYr * t);
|
|
84
|
-
re += m.re * c - m.im * s;
|
|
85
|
-
im += m.re * s + m.im * c;
|
|
86
|
-
}
|
|
87
|
-
return [re, im];
|
|
88
|
-
};
|
|
93
|
+
const sum = mkRawSum(modes);
|
|
89
94
|
const s0 = sum(0), R = [anchor[0] - s0[0], anchor[1] - s0[1]];
|
|
90
95
|
return (/** @type {number} */ t) => { const [x, y] = sum(t); return [x + R[0], y + R[1]]; };
|
|
91
96
|
};
|
|
@@ -161,9 +166,33 @@ function createDeepOrbitalHistory({
|
|
|
161
166
|
const nS = sq.length, tEndYr = t0Yr + (nS - 1) * stepYr;
|
|
162
167
|
const li = mkSeriesCubic(t0Yr, stepYr, nS);
|
|
163
168
|
const R = [zetaAnchor[0] - li(sq, 0), zetaAnchor[1] - li(sp, 0)];
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
169
|
+
// THE TAIL JOINS THE SERIES AT EACH SEAM (plan 12 §8.3, measured 2026-10).
|
|
170
|
+
// The mode-sum tail anchored to the J2000 POINT reached the span edges
|
|
171
|
+
// 1.61° (past) / 0.74° (future) away from the series — its ~70-kyr phases
|
|
172
|
+
// drift over 10 Myr (the extraction residual) and its J2000 anchor misses
|
|
173
|
+
// the series' mean plane by 0.506° — and the hybrid's mean obliquity
|
|
174
|
+
// STEPPED +0.90° / +0.30° there and stayed stepped (24.17° over ±1 Myr at
|
|
175
|
+
// −20 Myr against 23.3° inside the span; the API served it to ±500 Myr).
|
|
176
|
+
// Three anchors measured: J2000 point (above), the series' MEAN plane
|
|
177
|
+
// (n̂ step 1.12°/0.54°, ε step +0.74°/+0.57°), and the SEAM POINT per side
|
|
178
|
+
// — the tail's constant chosen so n̂ is continuous at the edge it continues
|
|
179
|
+
// (ε step +0.09°/+0.13°, the tail's mean 23.31–23.36° over ±100 Myr). The
|
|
180
|
+
// pole follows n̂ adiabatically (ds/dt = α(ŝ·n̂)(ŝ×n̂) conserves ŝ·n̂ for a
|
|
181
|
+
// slowly moving n̂), so a DISCONTINUITY in n̂ is what kicks ε, not the
|
|
182
|
+
// tail's mean plane: continuity wins. Inside the span nothing changes
|
|
183
|
+
// (bit-identical); beyond it the hybrid carries the Quaternary mean on the
|
|
184
|
+
// tail — NO tidal evolution of the mean (the cited mean obliquity of date
|
|
185
|
+
// is model.earth.meanObliquityCitedDeg).
|
|
186
|
+
const rawSum = mkRawSum(zetaModes);
|
|
187
|
+
const e0 = rawSum(t0Yr), e1 = rawSum(tEndYr);
|
|
188
|
+
const RPast = [li(sq, t0Yr) + R[0] - e0[0], li(sp, t0Yr) + R[1] - e0[1]];
|
|
189
|
+
const RFuture = [li(sq, tEndYr) + R[0] - e1[0], li(sp, tEndYr) + R[1] - e1[1]];
|
|
190
|
+
zetaAt = (/** @type {number} */ t) => {
|
|
191
|
+
if (t >= t0Yr && t <= tEndYr) return [li(sq, t) + R[0], li(sp, t) + R[1]];
|
|
192
|
+
const [x, y] = rawSum(t);
|
|
193
|
+
const Rt = t < t0Yr ? RPast : RFuture;
|
|
194
|
+
return [x + Rt[0], y + Rt[1]];
|
|
195
|
+
};
|
|
167
196
|
}
|
|
168
197
|
const zAnchor = /** @type {[number, number]} */ (
|
|
169
198
|
[anchorE * Math.cos(anchorPeriEclipticDeg * D2R), anchorE * Math.sin(anchorPeriEclipticDeg * D2R)]);
|
|
@@ -500,6 +529,8 @@ function createDeepOrbitalHistory({
|
|
|
500
529
|
};
|
|
501
530
|
}
|
|
502
531
|
|
|
532
|
+
/** The factory's walks, one per step size — see build(). @type {Map<number, { grid: Map<number, any>, frontier: Record<number, { s: number[], t: number }> }>} */
|
|
533
|
+
const walks = new Map();
|
|
503
534
|
/**
|
|
504
535
|
* Integrate once over [min(t0,t1,0), max(t0,t1,0)] and return a sampler
|
|
505
536
|
* on a stepYr grid (linear interpolation; angles interpolated on the
|
|
@@ -514,7 +545,18 @@ function createDeepOrbitalHistory({
|
|
|
514
545
|
if (Math.max(Math.abs(tMin), Math.abs(tMax)) > 50000 && stepYr % 250 !== 0) {
|
|
515
546
|
throw new Error(`deep-orbital-history: builds beyond ±50 kyr need stepYr % 250 === 0 (got ${stepYr})`);
|
|
516
547
|
}
|
|
517
|
-
|
|
548
|
+
// ONE WALK PER STEP SIZE, EXTENDED, NEVER RESTARTED (plan 13 A1, measured):
|
|
549
|
+
// every caller's tier routing asked for `build(span, -span, step)` and
|
|
550
|
+
// rebuilt from J2000 whenever a deeper epoch arrived, so the four deep
|
|
551
|
+
// fixture anchors (380…2460 Ma) walked ~49 million RK4 steps — 14 of the
|
|
552
|
+
// chain's 17 minutes — and the API's first read at −498 Myr would walk
|
|
553
|
+
// ~5 million. The walk is a pure function of t from the fixed J2000 state
|
|
554
|
+
// S0, so continuing a stored walk from its last (s, t) yields the SAME
|
|
555
|
+
// step sequence as a fresh walk to the farther end: bit-identical nodes
|
|
556
|
+
// (the sampler-order-purity gate pins this). The grid and the two
|
|
557
|
+
// direction frontiers live on the factory, keyed by stepYr; a returned
|
|
558
|
+
// sampler reads the shared grid, which only ever gains nodes.
|
|
559
|
+
let w = walks.get(stepYr);
|
|
518
560
|
const S0 = S0A;
|
|
519
561
|
// D1-revised adaptive stepping: 5-yr RK4 near the era (the certified-
|
|
520
562
|
// precision zone), 250-yr beyond ±50 kyr — still 103 steps per
|
|
@@ -526,8 +568,16 @@ function createDeepOrbitalHistory({
|
|
|
526
568
|
// 250-aligned; switching one fine-step later would leave the coarse walk
|
|
527
569
|
// permanently off-grid — measured: every key beyond ±50 kyr missing).
|
|
528
570
|
const hStepAt = (/** @type {number} */ t) => (Math.abs(t) < 50000 ? 5 : 250);
|
|
571
|
+
if (!w) {
|
|
572
|
+
w = { grid: new Map(), frontier: { [-1]: { s: S0, t: 0 }, [1]: { s: S0, t: 0 } } };
|
|
573
|
+
walks.set(stepYr, w);
|
|
574
|
+
}
|
|
575
|
+
const grid = w.grid;
|
|
529
576
|
for (const dir of [-1, +1]) {
|
|
530
|
-
|
|
577
|
+
const end = dir < 0 ? tMin : tMax;
|
|
578
|
+
const front = w.frontier[dir];
|
|
579
|
+
if (dir < 0 ? end >= front.t : end <= front.t) continue; // already walked this far
|
|
580
|
+
let s = front.s, t = front.t;
|
|
531
581
|
// Each stored node also carries the equinox-node RATE (deg/yr) from a
|
|
532
582
|
// ±2.5-yr central difference on the integrator's own state — the C1
|
|
533
583
|
// (Hermite) interpolation input. Linear interpolation of the node
|
|
@@ -552,8 +602,7 @@ function createDeepOrbitalHistory({
|
|
|
552
602
|
smp.periOfDateRateDegPerYr = (((lp.peri - lm.peri + 540) % 360) - 180) / (2 * hR);
|
|
553
603
|
grid.set(key, smp);
|
|
554
604
|
};
|
|
555
|
-
storeWithRate(0, s, 0);
|
|
556
|
-
const end = dir < 0 ? tMin : tMax;
|
|
605
|
+
if (t === 0 && !grid.has(0)) storeWithRate(0, s, 0);
|
|
557
606
|
while (dir < 0 ? t > end : t < end) {
|
|
558
607
|
const H_STEP = hStepAt(t);
|
|
559
608
|
s = rk4(s, t, dir * H_STEP);
|
|
@@ -568,6 +617,7 @@ function createDeepOrbitalHistory({
|
|
|
568
617
|
// zone boundary is itself 250-aligned, so the walk stays on-grid).
|
|
569
618
|
if (Math.abs(t - Math.round(t / stepYr) * stepYr) < 1e-6) storeWithRate(Math.round(t / stepYr) * stepYr, s, t);
|
|
570
619
|
}
|
|
620
|
+
w.frontier[dir] = { s, t };
|
|
571
621
|
}
|
|
572
622
|
return {
|
|
573
623
|
/** @param {number} tYr */
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The J2000 mass chain and the Moon's J2000 periods — ONE home (holisticuniverse
|
|
3
|
+
* plan 13 B3). Before B3 the mass chain (Moon Kepler → GM_EM → the Earth/Moon
|
|
4
|
+
* split → the Sun) was computed in three places (model.js, tools/lib/
|
|
5
|
+
* constants.js, src/script.js), and the Moon's derived periods in three more.
|
|
6
|
+
*
|
|
7
|
+
* Every expression here is the twins' expression in the twins' operation
|
|
8
|
+
* order (floating point is not associative; the goldens pin the values).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The mass chain in §9 order: Δa (the Sun's tidal coupling to the Earth–Moon
|
|
15
|
+
* barycentric wobble, leading order), the corrected Moon distance, Kepler on
|
|
16
|
+
* the Moon's orbit → G(M_E + M_M), the DE440 split → GM_E and GM_M, Kepler on
|
|
17
|
+
* Earth's orbit → G(M_☉ + M_E), the subtraction → GM_☉ and M_☉.
|
|
18
|
+
* @param {{
|
|
19
|
+
* moonDistanceKm: number, moonSiderealMonthDays: number, meanSiderealYearDays: number,
|
|
20
|
+
* meanLengthOfDaySeconds: number, massRatioEarthMoon: number, currentAUDistanceKm: number,
|
|
21
|
+
* gravitationalConstantKm3KgS2: number,
|
|
22
|
+
* }} c
|
|
23
|
+
* @returns {{
|
|
24
|
+
* meanSiderealYearSeconds: number, moonOrbitalShiftKm: number, moonDistanceCorrectedKm: number,
|
|
25
|
+
* gmEarthMoonSystemKm3S2: number, gmEarthAloneKm3S2: number, gmMoonAloneKm3S2: number,
|
|
26
|
+
* gmSunPlusEarthKm3S2: number, gmSunKm3S2: number, sunMassKg: number,
|
|
27
|
+
* }}
|
|
28
|
+
*/
|
|
29
|
+
function computeMassChainJ2000(c) {
|
|
30
|
+
const meanSiderealYearSeconds = c.meanSiderealYearDays * 86400;
|
|
31
|
+
const moonOrbitalShiftKm = c.moonDistanceKm * (1 / (c.massRatioEarthMoon + 1)) * (c.moonSiderealMonthDays / c.meanSiderealYearDays);
|
|
32
|
+
const moonDistanceCorrectedKm = c.moonDistanceKm + moonOrbitalShiftKm;
|
|
33
|
+
const gmEarthMoonSystemKm3S2 = (4 * Math.PI * Math.PI * Math.pow(moonDistanceCorrectedKm, 3))
|
|
34
|
+
/ Math.pow(c.moonSiderealMonthDays * c.meanLengthOfDaySeconds, 2);
|
|
35
|
+
const gmEarthAloneKm3S2 = gmEarthMoonSystemKm3S2 * (c.massRatioEarthMoon / (c.massRatioEarthMoon + 1));
|
|
36
|
+
const gmMoonAloneKm3S2 = gmEarthMoonSystemKm3S2 / (c.massRatioEarthMoon + 1);
|
|
37
|
+
const gmSunPlusEarthKm3S2 = (4 * Math.PI * Math.PI * Math.pow(c.currentAUDistanceKm, 3))
|
|
38
|
+
/ Math.pow(meanSiderealYearSeconds, 2);
|
|
39
|
+
const gmSunKm3S2 = gmSunPlusEarthKm3S2 - gmEarthAloneKm3S2;
|
|
40
|
+
const sunMassKg = gmSunKm3S2 / c.gravitationalConstantKm3KgS2;
|
|
41
|
+
return { meanSiderealYearSeconds, moonOrbitalShiftKm, moonDistanceCorrectedKm, gmEarthMoonSystemKm3S2, gmEarthAloneKm3S2, gmMoonAloneKm3S2, gmSunPlusEarthKm3S2, gmSunKm3S2, sunMassKg };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The Moon's J2000 periods on the IAU inputs. The two precession inputs are
|
|
46
|
+
* equinox-OF-DATE observables (3231.50 d / 6798.38 d; the legacy "ICRF" name
|
|
47
|
+
* is kept); the star-referenced periods remove the equinox's own precession,
|
|
48
|
+
* 1/T_E = 1/T_I ∓ 1/T_p (the perigee advances, the node regresses), T_p the
|
|
49
|
+
* J2000 precession anchor in days. The months follow kinematically.
|
|
50
|
+
* @param {{
|
|
51
|
+
* moonSiderealMonthDays: number, moonApsidalPrecessionDaysInput: number, moonNodalPrecessionDaysInput: number,
|
|
52
|
+
* axialPrecessionJ2000Days: number, meanSiderealYearDays: number, meanSolarYearDays: number,
|
|
53
|
+
* }} c
|
|
54
|
+
* @returns {{
|
|
55
|
+
* moonApsidalPrecessionDaysEarth: number, moonNodalPrecessionDaysEarth: number,
|
|
56
|
+
* moonApsidalJ2000Seconds: number, moonNodalJ2000Seconds: number, moonSiderealMonthJ2000Seconds: number,
|
|
57
|
+
* moonAnomalisticMonthDays: number, moonNodalMonthDays: number, moonSynodicMonthDays: number, moonTropicalMonthDays: number,
|
|
58
|
+
* moonFullMoonCycleEarthDays: number, moonFullMoonCycleICRFDays: number,
|
|
59
|
+
* moonApsidalMeetsNodalDays: number, moonLunarLevelingCycleDays: number,
|
|
60
|
+
* moonDraconicYearICRFDays: number, moonDraconicYearEarthDays: number,
|
|
61
|
+
* }}
|
|
62
|
+
*/
|
|
63
|
+
function computeMoonPeriodsJ2000(c) {
|
|
64
|
+
const T = c.axialPrecessionJ2000Days;
|
|
65
|
+
const M = c.moonSiderealMonthDays;
|
|
66
|
+
// the days forms (tools/lib/constants.js §7, src/script.js)
|
|
67
|
+
const moonApsidalPrecessionDaysEarth = 1 / (1 / c.moonApsidalPrecessionDaysInput - 1 / T);
|
|
68
|
+
const moonNodalPrecessionDaysEarth = 1 / (1 / c.moonNodalPrecessionDaysInput + 1 / T);
|
|
69
|
+
const moonAnomalisticMonthDays = 1 / (1 / M - 1 / moonApsidalPrecessionDaysEarth);
|
|
70
|
+
const moonNodalMonthDays = 1 / (1 / M + 1 / moonNodalPrecessionDaysEarth);
|
|
71
|
+
const moonSynodicMonthDays = M * c.meanSiderealYearDays / (c.meanSiderealYearDays - M);
|
|
72
|
+
const moonTropicalMonthDays = 1 / (1 / M + 1 / T);
|
|
73
|
+
const moonFullMoonCycleEarthDays = (moonSynodicMonthDays / (moonSynodicMonthDays - moonAnomalisticMonthDays)) * moonAnomalisticMonthDays;
|
|
74
|
+
const moonFullMoonCycleICRFDays = 1 / (1 / moonFullMoonCycleEarthDays + 1 / T);
|
|
75
|
+
const moonApsidalMeetsNodalDays = (moonNodalMonthDays / (moonAnomalisticMonthDays - moonNodalMonthDays)) * moonAnomalisticMonthDays;
|
|
76
|
+
const moonLunarLevelingCycleDays = (moonNodalPrecessionDaysEarth / (moonNodalPrecessionDaysEarth - moonApsidalPrecessionDaysEarth) * (moonApsidalPrecessionDaysEarth / c.meanSolarYearDays)) * c.meanSolarYearDays;
|
|
77
|
+
const moonDraconicYearICRFDays = 1 / ((1 / c.meanSolarYearDays) + (1 / moonNodalPrecessionDaysEarth));
|
|
78
|
+
const moonDraconicYearEarthDays = 1 / (1 / moonDraconicYearICRFDays - 1 / T);
|
|
79
|
+
// the seconds forms the deep-time chain anchors on (model.js / tools/lib/deep-time.js — the same
|
|
80
|
+
// relation written on the seconds, so the J2000 anchors of the month chain are bit-identical)
|
|
81
|
+
const moonApsidalOfDateJ2000Seconds = c.moonApsidalPrecessionDaysInput * 86400;
|
|
82
|
+
const moonNodalOfDateJ2000Seconds = c.moonNodalPrecessionDaysInput * 86400;
|
|
83
|
+
const moonApsidalJ2000Seconds = 1 / (1 / moonApsidalOfDateJ2000Seconds - 1 / (T * 86400));
|
|
84
|
+
const moonNodalJ2000Seconds = 1 / (1 / moonNodalOfDateJ2000Seconds + 1 / (T * 86400));
|
|
85
|
+
const moonSiderealMonthJ2000Seconds = M * 86400;
|
|
86
|
+
return {
|
|
87
|
+
moonApsidalPrecessionDaysEarth, moonNodalPrecessionDaysEarth,
|
|
88
|
+
moonApsidalJ2000Seconds, moonNodalJ2000Seconds, moonSiderealMonthJ2000Seconds,
|
|
89
|
+
moonAnomalisticMonthDays, moonNodalMonthDays, moonSynodicMonthDays, moonTropicalMonthDays,
|
|
90
|
+
moonFullMoonCycleEarthDays, moonFullMoonCycleICRFDays, moonApsidalMeetsNodalDays, moonLunarLevelingCycleDays,
|
|
91
|
+
moonDraconicYearICRFDays, moonDraconicYearEarthDays,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { computeMassChainJ2000, computeMoonPeriodsJ2000 };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The mean obliquity of date ε̄(t) — the SECOND column the model reads from the
|
|
3
|
+
* cited Earth–Moon history (plan 12 §8, option (a)): Farhat, Auclair-Desrotour,
|
|
4
|
+
* Boué & Laskar 2022's own mean obliquity, carried in
|
|
5
|
+
* data/astrogeo22-earth-moon.json beside the distance.
|
|
6
|
+
*
|
|
7
|
+
* WHY AN INPUT. The composed lunisolar law (earth/precession-composed.cjs)
|
|
8
|
+
* scales the precession CONSTANT of date — α(t)/α₀ on the spin history and the
|
|
9
|
+
* lunar torque's (a₀/a_M)³. The precession RATE is α(t)·cos ε̄(t), and the chain
|
|
10
|
+
* had held cos ε̄ at its J2000 value at every epoch — a purity freeze without
|
|
11
|
+
* its twin. Standard theory since Goldreich 1966 (Touma & Wisdom 1994; Farhat
|
|
12
|
+
* et al. 2022) has the mean obliquity lower in the deep past, evolved by the
|
|
13
|
+
* lunar tidal torque through the Laplace-plane transition — the same
|
|
14
|
+
* ocean-dissipation physics option A declined to model for the distance. The
|
|
15
|
+
* published solution that computes ε̄(t) alongside a(t) is the input, as the
|
|
16
|
+
* distance is. Measured (plan 12 §8.1): the factor cos ε̄(t)/cos ε̄(0) closes
|
|
17
|
+
* the composed rate to Farhat's own precession column from −2.0 % to +0.4 % at
|
|
18
|
+
* 2.46 Ga and moves every paleo precession referee toward its source.
|
|
19
|
+
*
|
|
20
|
+
* WHAT IS READ. The column's cosine RATIO cos ε̄(t)/cos ε̄(0) — the SHAPE, as
|
|
21
|
+
* the distance is read as a(t)/a(0). The column's own value is published as the
|
|
22
|
+
* cited mean: 23.2545° at age 0, a Myr-scale MEAN of a secular solution, not
|
|
23
|
+
* the J2000 instant 23.4393° the hybrid obliquity integration starts from.
|
|
24
|
+
*
|
|
25
|
+
* INTERPOLATION. Cubic Hermite with central-difference tangents between the
|
|
26
|
+
* 1-Myr samples (one-sided at the ends) — C1. The column is monotone (measured:
|
|
27
|
+
* no sign change of its first difference across the 4,429 samples), so no
|
|
28
|
+
* limiter is needed. Forward of J2000 (t < 0) the column's J2000 one-sided
|
|
29
|
+
* slope is held — a labelled extrapolation, as the distance holds the LLR rate
|
|
30
|
+
* (the input has no future). Beyond the table's last sample the history
|
|
31
|
+
* REFUSES: null, never an extrapolation.
|
|
32
|
+
*
|
|
33
|
+
* HISTORICAL ERA. The slope at J2000 is −0.00264°/Myr: the factor is
|
|
34
|
+
* 1 − 2.0e-7 at 10 kyr and 1 − 2.0e-6 at 100 kyr — the ΔT era is untouched at
|
|
35
|
+
* the 1e-7 class; the deep-time clock T_p(t) shortens 0.75 % at the Devonian
|
|
36
|
+
* and 2.5 % at 2.46 Ga.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
'use strict';
|
|
40
|
+
|
|
41
|
+
const D2R = Math.PI / 180;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {Object} MeanObliquityTable
|
|
45
|
+
* @property {ReadonlyArray<number>} ageMa - ascending, 0 first, uniform 1-Myr step
|
|
46
|
+
* @property {ReadonlyArray<number>} obliquityDeg - the cited mean obliquity column, degrees
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {{ table: MeanObliquityTable }} deps
|
|
51
|
+
* @returns {{
|
|
52
|
+
* meanObliquityDegAtAge: (tMa: number) => number|null,
|
|
53
|
+
* cosRatioAtAge: (tMa: number) => number|null,
|
|
54
|
+
* meanObliquityJ2000Deg: number,
|
|
55
|
+
* spanMa: number,
|
|
56
|
+
* }}
|
|
57
|
+
*/
|
|
58
|
+
function createMeanObliquityHistory(deps) {
|
|
59
|
+
const ages = deps.table.ageMa, eps = deps.table.obliquityDeg;
|
|
60
|
+
const n = ages ? ages.length : 0;
|
|
61
|
+
if (!(n >= 2) || !eps || eps.length !== n || ages[0] !== 0) {
|
|
62
|
+
throw new Error('mean-obliquity-history: the table must start at age 0 with ≥ 2 obliquity samples (a stale moon-distance embed lacks the obliquity column — regenerate the constants)');
|
|
63
|
+
}
|
|
64
|
+
const step = ages[1] - ages[0];
|
|
65
|
+
for (let i = 1; i < n; i++) {
|
|
66
|
+
if (ages[i] - ages[i - 1] !== step) throw new Error(`mean-obliquity-history: non-uniform age step at index ${i}`);
|
|
67
|
+
}
|
|
68
|
+
const spanMa = ages[n - 1];
|
|
69
|
+
// Central-difference tangents, deg per Ma (one-sided at the ends).
|
|
70
|
+
const m = new Float64Array(n);
|
|
71
|
+
m[0] = (eps[1] - eps[0]) / step;
|
|
72
|
+
for (let i = 1; i < n - 1; i++) m[i] = (eps[i + 1] - eps[i - 1]) / (2 * step);
|
|
73
|
+
m[n - 1] = (eps[n - 1] - eps[n - 2]) / step;
|
|
74
|
+
const cos0 = Math.cos(eps[0] * D2R);
|
|
75
|
+
|
|
76
|
+
/** @param {number} tMa @returns {number|null} the cited mean obliquity, degrees */
|
|
77
|
+
function meanObliquityDegAtAge(tMa) {
|
|
78
|
+
if (tMa <= 0) return eps[0] + m[0] * tMa; // forward: the J2000 slope held (labelled extrapolation)
|
|
79
|
+
if (tMa > spanMa) return null; // beyond the input: refused
|
|
80
|
+
const i = Math.min(Math.floor(tMa / step), n - 2);
|
|
81
|
+
const h = step, s = (tMa - ages[i]) / h, s2 = s * s, s3 = s2 * s;
|
|
82
|
+
return (2 * s3 - 3 * s2 + 1) * eps[i] + (s3 - 2 * s2 + s) * h * m[i]
|
|
83
|
+
+ (-2 * s3 + 3 * s2) * eps[i + 1] + (s3 - s2) * h * m[i + 1];
|
|
84
|
+
}
|
|
85
|
+
/** cos ε̄(t)/cos ε̄(0) — the factor the precession RATE of date carries on the precession constant. ≡ 1 at J2000.
|
|
86
|
+
* @param {number} tMa @returns {number|null} */
|
|
87
|
+
function cosRatioAtAge(tMa) {
|
|
88
|
+
const e = meanObliquityDegAtAge(tMa);
|
|
89
|
+
return e === null ? null : Math.cos(e * D2R) / cos0;
|
|
90
|
+
}
|
|
91
|
+
return { meanObliquityDegAtAge, cosRatioAtAge, meanObliquityJ2000Deg: eps[0], spanMa };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { createMeanObliquityHistory };
|
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
* (1 − e²)^(−3/2) eccentricity factors and the lunar-inclination factor
|
|
14
14
|
* 1 − 3/2·sin² i_M; ≈ 0.316, the textbook value). At J2000 every factor is 1.
|
|
15
15
|
*
|
|
16
|
+
* THE RATE OF DATE vs THE CONSTANT (plan 12 §8, option (a)): the law above
|
|
17
|
+
* scales the precession CONSTANT α(t) ∝ ω(t)·[torque term] — the rate at the
|
|
18
|
+
* J2000 obliquity. The precession RATE is α(t)·cos ε̄(t), so the published
|
|
19
|
+
* rate carries one more factor, the cited mean obliquity's cos ε̄(t)/cos ε̄(0)
|
|
20
|
+
* (earth/mean-obliquity-history.cjs — Farhat 2022's own column, the second
|
|
21
|
+
* column read from the distance history; the chain had held cos ε̄ at J2000
|
|
22
|
+
* at every epoch). torqueRate… is the constant's scaling — what the hybrid
|
|
23
|
+
* obliquity integration takes, since its own ŝ·n̂ carries the cosine;
|
|
24
|
+
* composedRate… is the rate of date — T_p(t), the obliquity beat, the tropical
|
|
25
|
+
* year of date, the paleo referees' precession constant k. Both ≡ p₀ at J2000;
|
|
26
|
+
* the factor is 1 − 2e-7 at 10 kyr and 1.0245 at 2.46 Ga (the composed rate
|
|
27
|
+
* 106.6 → 109.2 ″/yr against Lantink 2022's 108.6 ± 8.5; Farhat's own
|
|
28
|
+
* precession column on the same table: 108.8).
|
|
29
|
+
*
|
|
16
30
|
* THE ANCHOR p₀ (plan 06 S5 — one J2000 precession reading): p₀ is the
|
|
17
31
|
* model's DERIVED J2000 rate, 1,296,000/axial0 with axial0 the certified
|
|
18
32
|
* year-length laws' beat at 2000 (sid/(sid − trop) = 25,771.4 yr = 50.2883
|
|
@@ -64,14 +78,20 @@ function computeSolarTorqueShare(c) {
|
|
|
64
78
|
* moonDistanceMetresAtAge: (tMa: number) => (number | null),
|
|
65
79
|
* moonDistanceJ2000Metres: number,
|
|
66
80
|
* yearToTMa: (year: number) => number,
|
|
81
|
+
* meanObliquityCosRatioAtAge?: (tMa: number) => (number | null),
|
|
67
82
|
* }} deps - p0 = the model's derived J2000 rate, 1,296,000/axial0 (S5; a
|
|
68
83
|
* number or a LAZY getter — the callers' certified year laws read the
|
|
69
84
|
* deep-time factory this is built inside, so the anchor is resolved on
|
|
70
85
|
* the first RATE use, never at construction; the torque term needs no
|
|
71
|
-
* anchor); lodJ2000Seconds the SAME day basis lodSecondsAtAge(0) returns
|
|
86
|
+
* anchor); lodJ2000Seconds the SAME day basis lodSecondsAtAge(0) returns;
|
|
87
|
+
* meanObliquityCosRatioAtAge the cited mean obliquity's cos ε̄(t)/cos ε̄(0)
|
|
88
|
+
* (OPTIONAL — absent, the rate of date is the constant alone, bit-identical).
|
|
72
89
|
* @returns {{
|
|
73
90
|
* composedRateArcsecPerYrAtAge: (tMa: number) => (number | null),
|
|
74
91
|
* composedPeriodYearsAtAge: (tMa: number) => (number | null),
|
|
92
|
+
* torqueRateArcsecPerYrAtAge: (tMa: number) => (number | null),
|
|
93
|
+
* torquePeriodYearsAtAge: (tMa: number) => (number | null),
|
|
94
|
+
* obliquityFactorAtAge: (tMa: number) => (number | null),
|
|
75
95
|
* composedRateArcsecPerYrAtYear: (year: number) => (number | null),
|
|
76
96
|
* composedPeriodYearsAtYear: (year: number) => (number | null),
|
|
77
97
|
* composedRateRatioAtAge: (tMa: number) => (number | null),
|
|
@@ -107,14 +127,37 @@ function createComposedPrecession(deps) {
|
|
|
107
127
|
const lf = lunarTorqueFactorAtAge(tMa);
|
|
108
128
|
return lf === null ? null : fS + (1 - fS) * lf;
|
|
109
129
|
};
|
|
110
|
-
/**
|
|
111
|
-
|
|
130
|
+
/** cos ε̄(t)/cos ε̄(0) from the cited mean obliquity — 1 when no history is
|
|
131
|
+
* injected (the constant alone, bit-identical). @param {number} tMa @returns {number|null} */
|
|
132
|
+
const cosRatio = deps.meanObliquityCosRatioAtAge;
|
|
133
|
+
/** @type {(tMa: number) => number|null} */
|
|
134
|
+
const obliquityFactorAtAge = cosRatio ? (tMa) => cosRatio(tMa) : () => 1;
|
|
135
|
+
/** THE PRECESSION CONSTANT OF DATE as a rate on the J2000 obliquity, ″/yr —
|
|
136
|
+
* [ω(t)/ω₀]·p₀·[f_S + (1 − f_S)(a₀/a_M)³] = α(t)·cos ε̄₀. The hybrid
|
|
137
|
+
* obliquity integration takes THIS: ds/dt = α(ŝ·n̂)(ŝ×n̂) carries its own cosine.
|
|
138
|
+
* @param {number} tMa */
|
|
139
|
+
const torqueRateArcsecPerYrAtAge = (tMa) => {
|
|
112
140
|
const lod = deps.lodSecondsAtAge(tMa);
|
|
113
141
|
const term = torqueTermAtAge(tMa);
|
|
114
142
|
if (lod === null || !(lod > 0) || term === null) return null;
|
|
115
143
|
return (deps.lodJ2000Seconds / lod) * p0() * term;
|
|
116
144
|
};
|
|
117
145
|
/** @param {number} tMa */
|
|
146
|
+
const torquePeriodYearsAtAge = (tMa) => {
|
|
147
|
+
const r = torqueRateArcsecPerYrAtAge(tMa);
|
|
148
|
+
return r === null ? null : 1296000 / r;
|
|
149
|
+
};
|
|
150
|
+
/** THE PRECESSION RATE OF DATE ψ̇(t), ″/yr — the constant × cos ε̄(t)/cos ε̄(0):
|
|
151
|
+
* the published rate (T_p(t) = 1,296,000/ψ̇, the obliquity beat, the tropical
|
|
152
|
+
* year of date, the paleo referees' precession constant k).
|
|
153
|
+
* @param {number} tMa */
|
|
154
|
+
const composedRateArcsecPerYrAtAge = (tMa) => {
|
|
155
|
+
const r = torqueRateArcsecPerYrAtAge(tMa);
|
|
156
|
+
if (r === null) return null;
|
|
157
|
+
const f = obliquityFactorAtAge(tMa);
|
|
158
|
+
return f === null ? null : r * f;
|
|
159
|
+
};
|
|
160
|
+
/** @param {number} tMa */
|
|
118
161
|
const composedPeriodYearsAtAge = (tMa) => {
|
|
119
162
|
const r = composedRateArcsecPerYrAtAge(tMa);
|
|
120
163
|
return r === null ? null : 1296000 / r;
|
|
@@ -134,6 +177,9 @@ function createComposedPrecession(deps) {
|
|
|
134
177
|
composedRateArcsecPerYrAtYear: (year) => composedRateArcsecPerYrAtAge(deps.yearToTMa(year)),
|
|
135
178
|
composedPeriodYearsAtYear: (year) => composedPeriodYearsAtAge(deps.yearToTMa(year)),
|
|
136
179
|
composedRateRatioAtAge,
|
|
180
|
+
torqueRateArcsecPerYrAtAge,
|
|
181
|
+
torquePeriodYearsAtAge,
|
|
182
|
+
obliquityFactorAtAge,
|
|
137
183
|
torqueTermAtAge,
|
|
138
184
|
lunarTorqueFactorAtAge,
|
|
139
185
|
solarShare: fS,
|
package/src/index.js
CHANGED
|
@@ -106,6 +106,20 @@ export { createDerivedViews } from './layer1/index.js';
|
|
|
106
106
|
// file via the exports-map subpath; re-exported here so bundled ESM
|
|
107
107
|
// consumers need only the package root.
|
|
108
108
|
export { createDeepCalendar } from './phase/deep-calendar.cjs';
|
|
109
|
+
// Plan 13 B1: the civil calendar ↔ JD (Meeus ch. 7 with the 1582-10-15
|
|
110
|
+
// reform) and the angle constants/wraps — ONE home; the browser's eighteen
|
|
111
|
+
// calendar copies and 27 local D2R constants import these.
|
|
112
|
+
export { GREGORIAN_START, GREGORIAN_START_JD, calendarToJD, jdToCalendar, jdToDecimalYear, dayFractionToHMS, julianCalendarToJD, jdToJulianCalendar } from './time/calendar.cjs';
|
|
113
|
+
export { DEG2RAD, RAD2DEG, ARCSEC_PER_TURN, ARCSEC_PER_RAD, wrap360, wrap180, wrap180Closed, wrap2pi, wrapPi } from './math/angles.cjs';
|
|
114
|
+
// Plan 13 B2: THE deep-time chain assembly — the GIA α channel, the Layer-0
|
|
115
|
+
// bundle, the cited Moon-distance history, the ΔT cycle stack, |s₃|, the
|
|
116
|
+
// LOD/ΔT core, the lunar month chain and the mean*AtAge family, assembled
|
|
117
|
+
// ONCE from the generated constants; the Node twin and the browser destructure it.
|
|
118
|
+
export { createDeepTimeChain, MOON_ECC_SENSITIVITY_PERIGEE, MOON_ECC_SENSITIVITY_NODE } from './deltat/deep-time-chain.js';
|
|
119
|
+
// Plan 13 B3: the J2000 mass chain and the Moon's J2000 periods (one home for
|
|
120
|
+
// three copies each) and the unit constants.
|
|
121
|
+
export { computeMassChainJ2000, computeMoonPeriodsJ2000 } from './earth/mass-chain.cjs';
|
|
122
|
+
export { SECONDS_PER_DAY, DAYS_PER_JULIAN_YEAR, JULIAN_CENTURY_DAYS, SECONDS_PER_JULIAN_YEAR } from './constants/units.cjs';
|
|
109
123
|
// D4b: the one-source cardinal structure — the EoC layer (year lengths,
|
|
110
124
|
// crossing offsets, the e(t)-proportional spread) on the movement's own
|
|
111
125
|
// e(t)/ϖ(t). Absolute dates deliberately excluded (per-renderer mean chain).
|
|
@@ -156,6 +170,9 @@ export { createYearLengths, computeMeanTropicalYearJ2000Days, ONE_FAMILY_WINDOW_
|
|
|
156
170
|
// (spin ω(t) × [solar torque + lunar torque on the recession history]) —
|
|
157
171
|
// leg-1's physical rate; the structural H(t)/13 clock is its named diagnostic.
|
|
158
172
|
export { computeSolarTorqueShare, createComposedPrecession } from './earth/precession-composed.cjs';
|
|
173
|
+
// Plan 12 §8 option (a): the cited mean obliquity of date — the second column read from the
|
|
174
|
+
// Earth–Moon history; the precession RATE of date carries its cos ε̄(t)/cos ε̄(0) on the constant.
|
|
175
|
+
export { createMeanObliquityHistory } from './earth/mean-obliquity-history.cjs';
|
|
159
176
|
// (planets/predict.cjs — the planet predictive-precession feature basis — was
|
|
160
177
|
// retired at plan 06 R8 with PREDICT_COEFFS_PHYSICAL.)
|
|
161
178
|
// L10 — the composition front door: one law set, N body records. Thin by
|
|
@@ -167,7 +184,12 @@ export { PLANET_DISPLAY_NAMES } from './planets/display-names.cjs';
|
|
|
167
184
|
// Phase 8.4 — the climate/ΔT machinery, extracted layer by layer.
|
|
168
185
|
export { createDeltaTCycles } from './deltat/cycles.cjs';
|
|
169
186
|
export { createDeepTimeLod } from './deltat/deep-time.cjs';
|
|
170
|
-
|
|
187
|
+
// plan 12 (option A): the Earth–Moon distance history is a CITED PHYSICAL
|
|
188
|
+
// INPUT (Farhat et al. 2022, the AstroGeo22 ephemeris) read as a shape on the
|
|
189
|
+
// model's J2000 anchor; the fitted quartic, the rock-fitted regime spline and
|
|
190
|
+
// the solar-channel budget are deleted.
|
|
191
|
+
export { createMoonDistanceHistory } from './deltat/moon-distance-history.cjs';
|
|
192
|
+
export { MOON_DISTANCE_ARTIFACT, MOON_DISTANCE_ARTIFACT_HASH } from './deltat/moon-distance-artifact.cjs';
|
|
171
193
|
export { deltaTEspenakMeeusCanonSeconds } from './deltat/historical.cjs';
|
|
172
194
|
export { evalClimateL1OrbitalPermil, laggedL1Terms, createAlphaGiaChannel } from './climate/l1-orbital.cjs';
|
|
173
195
|
// Phase 8.5 — eclipse geometry (single-copy: the browser had no Node twin).
|
|
@@ -24,9 +24,7 @@ import { computeSolarTorqueShare } from '../earth/precession-composed.cjs';
|
|
|
24
24
|
* @property {number} solarLuminosityW IAU 2015 nominal (W)
|
|
25
25
|
* @property {number} solarWindKgPerS Ulysses/ACE/Wind
|
|
26
26
|
* @property {number} speedOfLightKmPerS km/s (fallback 299792458 m/s if falsy)
|
|
27
|
-
* @property {number} alpha1PerMa
|
|
28
|
-
* @property {number} alpha3PerMa3
|
|
29
|
-
* @property {number} alpha4PerMa4
|
|
27
|
+
* @property {number} alpha1PerMa the LLR recession rate — the cited distance history's J2000 slope
|
|
30
28
|
* @property {number} meanSiderealYearSeconds
|
|
31
29
|
* @property {number} lodJ2000Seconds ω₀: the J2000 day length, SI seconds (the SI day since plan 09)
|
|
32
30
|
* @property {number} sunMassKg M_SUN
|
|
@@ -85,8 +83,6 @@ export const deriveEpochParams = (raw) => {
|
|
|
85
83
|
return Object.freeze({
|
|
86
84
|
epochYear: 2000,
|
|
87
85
|
alpha1PerMa: raw.alpha1PerMa,
|
|
88
|
-
alpha3PerMa3: raw.alpha3PerMa3,
|
|
89
|
-
alpha4PerMa4: raw.alpha4PerMa4,
|
|
90
86
|
moonDistanceNowM,
|
|
91
87
|
moonLockDistanceM,
|
|
92
88
|
totalAngularMomentumKgM2S,
|