@essrt/physics 4.0.0 → 4.1.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/package.json +4 -1
- package/src/constants/generated.d.ts +9 -0
- package/src/constants/generated.js +10 -0
- package/src/earth/deep-orbital-history.cjs +190 -0
- package/src/index.js +7 -0
- package/src/model.js +31 -10
- package/src/moon/deep-ecc-channel.cjs +132 -0
- package/src/moon/deep-modes-artifact.cjs +19 -0
- package/src/moon/ecc-channel.cjs +11 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@essrt/physics",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "ESSRT (Expanding Solar System Resonance Theory) physics core \u2014 pure, injectable-constants, no I/O, no globals, no DOM. The complete model incl. fitted coefficients; every published version immutably ships one recorded model identity.",
|
|
5
5
|
"essrt": {
|
|
6
6
|
"modelVersion": "v13.0",
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"./phase": "./src/phase/index.cjs",
|
|
33
33
|
"./cardinal": "./src/cardinal/index.cjs",
|
|
34
34
|
"./moon/ecc-channel": "./src/moon/ecc-channel.cjs",
|
|
35
|
+
"./moon/deep-ecc-channel": "./src/moon/deep-ecc-channel.cjs",
|
|
36
|
+
"./moon/deep-modes-artifact": "./src/moon/deep-modes-artifact.cjs",
|
|
37
|
+
"./earth/deep-orbital-history": "./src/earth/deep-orbital-history.cjs",
|
|
35
38
|
"./moon/month-chain": "./src/moon/month-chain.cjs",
|
|
36
39
|
"./chain-cycles": "./src/chain-cycles/index.cjs",
|
|
37
40
|
"./moon/arguments": "./src/moon/arguments.cjs",
|
|
@@ -741,4 +741,13 @@ export declare const REFERENCE_DATA: {
|
|
|
741
741
|
"max": number;
|
|
742
742
|
};
|
|
743
743
|
};
|
|
744
|
+
readonly planetSpinObserved: {
|
|
745
|
+
"marsSpinPrecessionArcsecPerYr": number;
|
|
746
|
+
"jupiterSpinPrecessionApproxArcsecPerYr": number;
|
|
747
|
+
"saturnSpinPrecessionPresentArcsecPerYr": number;
|
|
748
|
+
"saturnPresentToLongTermFraction": number;
|
|
749
|
+
"marsObliquityJ2000Deg": number;
|
|
750
|
+
"jupiterObliquityJ2000Deg": number;
|
|
751
|
+
"saturnObliquityJ2000Deg": number;
|
|
752
|
+
};
|
|
744
753
|
};
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* moonGrailWilliams2014 target
|
|
15
15
|
* giaCoxChaoPeltier target
|
|
16
16
|
* obliquityChapront2002 target
|
|
17
|
+
* planetSpinObserved target
|
|
17
18
|
* ascendingNodesSouamiSouchay target
|
|
18
19
|
* laplaceLagrangeBounds target
|
|
19
20
|
* jplEclipticInclinationTrends target
|
|
@@ -913,4 +914,13 @@ export const REFERENCE_DATA = Object.freeze({
|
|
|
913
914
|
"max": 200
|
|
914
915
|
}
|
|
915
916
|
},
|
|
917
|
+
planetSpinObserved: {
|
|
918
|
+
"marsSpinPrecessionArcsecPerYr": -7.606,
|
|
919
|
+
"jupiterSpinPrecessionApproxArcsecPerYr": -2.8,
|
|
920
|
+
"saturnSpinPrecessionPresentArcsecPerYr": -0.45,
|
|
921
|
+
"saturnPresentToLongTermFraction": 0.68,
|
|
922
|
+
"marsObliquityJ2000Deg": 25.19,
|
|
923
|
+
"jupiterObliquityJ2000Deg": 3.13,
|
|
924
|
+
"saturnObliquityJ2000Deg": 26.73
|
|
925
|
+
},
|
|
916
926
|
});
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE DEEP ORBITAL HISTORY FACTORY — the ONE home for the Stage-C hybrid
|
|
3
|
+
* mathematics (plan 02 §8, C-3): Earth's deep-time orbital quantities from
|
|
4
|
+
* the engine's own governed mode tables, and the obliquity hybrid
|
|
5
|
+
*
|
|
6
|
+
* ds/dt = α (ŝ·n̂)(ŝ×n̂), α = ψ̇_J2000 / cos ε₀
|
|
7
|
+
*
|
|
8
|
+
* with the orbit normal n̂(t) from an anchored ζ mode-sum and ψ̇_J2000 the
|
|
9
|
+
* injected engine-K anchor (the equinox-precession rate measured from the
|
|
10
|
+
* engine's own year lengths). ZERO fitted constants; the J2000 celestial
|
|
11
|
+
* pole sits at ecliptic longitude +90° (s₀ = (0, +sin ε₀, cos ε₀) — the
|
|
12
|
+
* −90° choice anti-correlates perfectly, the recorded convention catch).
|
|
13
|
+
*
|
|
14
|
+
* Consumers (each injecting its own certified surfaces, cross-engine
|
|
15
|
+
* matched): the Stage-C lab / verdict generator (both ζ tiers), the Node
|
|
16
|
+
* shim tools/lib/deep-orbital-history.js (the deep insolation extractor),
|
|
17
|
+
* and the browser's published ε surfaces (VFP chart, Earth-panel row) via
|
|
18
|
+
* the generated deep-modes embed. The ERA machinery (frame conversions,
|
|
19
|
+
* lunar D5, besselian, the scene's A-solve and Step 6b) stays on the
|
|
20
|
+
* certified fitted law — measured: the hybrid differs from it by 5″ rms in
|
|
21
|
+
* 1900–2100 / 19.5″ in 1600–2400, mostly hybrid-side there — the same
|
|
22
|
+
* certification split as e and ϖ.
|
|
23
|
+
*
|
|
24
|
+
* The climatic precession is the PHYSICAL of-date angle from the moving
|
|
25
|
+
* equinox γ = unit(ŝ×n̂) to the perihelion direction, measured in the orbit
|
|
26
|
+
* plane about n̂ — no linear-precession approximation at any epoch
|
|
27
|
+
* (validated: reproduces the J2000 ecliptic longitude and La2004's
|
|
28
|
+
* e·sin ϖ̃ exactly at t = 0).
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
'use strict';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {{
|
|
35
|
+
* zModes: ReadonlyArray<{omegaRadPerYr: number, re: number, im: number}>,
|
|
36
|
+
* zetaModes: ReadonlyArray<{omegaRadPerYr: number, re: number, im: number}>,
|
|
37
|
+
* anchorE: number,
|
|
38
|
+
* anchorPeriEclipticDeg: number,
|
|
39
|
+
* anchorInclEclipticDeg: number,
|
|
40
|
+
* anchorAscNodeEclipticDeg: number,
|
|
41
|
+
* axialPrecessionYearsJ2000: number,
|
|
42
|
+
* obliquityJ2000Deg: number,
|
|
43
|
+
* }} deps — mode tables from the governed deep artifact (choose the ζ tier
|
|
44
|
+
* per consumer: era = its own 8-term extraction, deep = the 16-term
|
|
45
|
+
* table; NEVER a slice); anchors from the chain artifact's one home; the
|
|
46
|
+
* axial-precession years and ε₀ from the injecting engine's certified
|
|
47
|
+
* surfaces.
|
|
48
|
+
*/
|
|
49
|
+
function createDeepOrbitalHistory({
|
|
50
|
+
zModes, zetaModes,
|
|
51
|
+
anchorE, anchorPeriEclipticDeg, anchorInclEclipticDeg, anchorAscNodeEclipticDeg,
|
|
52
|
+
axialPrecessionYearsJ2000, obliquityJ2000Deg,
|
|
53
|
+
}) {
|
|
54
|
+
const D2R = Math.PI / 180, R2D = 180 / Math.PI;
|
|
55
|
+
|
|
56
|
+
const mkAnchored = (
|
|
57
|
+
/** @type {ReadonlyArray<{omegaRadPerYr: number, re: number, im: number}>} */ modes,
|
|
58
|
+
/** @type {[number, number]} */ anchor,
|
|
59
|
+
) => {
|
|
60
|
+
const sum = (/** @type {number} */ t) => {
|
|
61
|
+
let re = 0, im = 0;
|
|
62
|
+
for (const m of modes) {
|
|
63
|
+
const c = Math.cos(m.omegaRadPerYr * t), s = Math.sin(m.omegaRadPerYr * t);
|
|
64
|
+
re += m.re * c - m.im * s;
|
|
65
|
+
im += m.re * s + m.im * c;
|
|
66
|
+
}
|
|
67
|
+
return [re, im];
|
|
68
|
+
};
|
|
69
|
+
const s0 = sum(0), R = [anchor[0] - s0[0], anchor[1] - s0[1]];
|
|
70
|
+
return (/** @type {number} */ t) => { const [x, y] = sum(t); return [x + R[0], y + R[1]]; };
|
|
71
|
+
};
|
|
72
|
+
const s2h = Math.sin(anchorInclEclipticDeg / 2 * D2R);
|
|
73
|
+
const zetaAt = mkAnchored(zetaModes,
|
|
74
|
+
[s2h * Math.cos(anchorAscNodeEclipticDeg * D2R), s2h * Math.sin(anchorAscNodeEclipticDeg * D2R)]);
|
|
75
|
+
const zAt = mkAnchored(zModes,
|
|
76
|
+
[anchorE * Math.cos(anchorPeriEclipticDeg * D2R), anchorE * Math.sin(anchorPeriEclipticDeg * D2R)]);
|
|
77
|
+
|
|
78
|
+
/** @param {number} t */
|
|
79
|
+
const inclNode = (t) => {
|
|
80
|
+
const [q, p] = zetaAt(t);
|
|
81
|
+
return { i: 2 * Math.asin(Math.min(1, Math.hypot(q, p))), Om: Math.atan2(p, q) };
|
|
82
|
+
};
|
|
83
|
+
/** @param {number} t */
|
|
84
|
+
const orbitNormal = (t) => {
|
|
85
|
+
const { i, Om } = inclNode(t);
|
|
86
|
+
return [Math.sin(i) * Math.sin(Om), -Math.sin(i) * Math.cos(Om), Math.cos(i)];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const psiDot = (2 * Math.PI) / axialPrecessionYearsJ2000;
|
|
90
|
+
const EPS0 = obliquityJ2000Deg * D2R;
|
|
91
|
+
const ALPHA = psiDot / Math.cos(EPS0);
|
|
92
|
+
|
|
93
|
+
const cross = (/** @type {number[]} */ a, /** @type {number[]} */ b) =>
|
|
94
|
+
[a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
|
|
95
|
+
const dot = (/** @type {number[]} */ a, /** @type {number[]} */ b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
96
|
+
const deriv = (/** @type {number[]} */ s, /** @type {number} */ t) => {
|
|
97
|
+
const n = orbitNormal(t);
|
|
98
|
+
const k = ALPHA * dot(s, n);
|
|
99
|
+
const c = cross(s, n);
|
|
100
|
+
return [k * c[0], k * c[1], k * c[2]];
|
|
101
|
+
};
|
|
102
|
+
const rk4 = (/** @type {number[]} */ s, /** @type {number} */ t, /** @type {number} */ h) => {
|
|
103
|
+
const k1 = deriv(s, t);
|
|
104
|
+
const k2 = deriv([s[0] + h / 2 * k1[0], s[1] + h / 2 * k1[1], s[2] + h / 2 * k1[2]], t + h / 2);
|
|
105
|
+
const k3 = deriv([s[0] + h / 2 * k2[0], s[1] + h / 2 * k2[1], s[2] + h / 2 * k2[2]], t + h / 2);
|
|
106
|
+
const k4 = deriv([s[0] + h * k3[0], s[1] + h * k3[1], s[2] + h * k3[2]], t + h);
|
|
107
|
+
const o = [0, 1, 2].map((i) => s[i] + h / 6 * (k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]));
|
|
108
|
+
const r = Math.hypot(o[0], o[1], o[2]);
|
|
109
|
+
return [o[0] / r, o[1] / r, o[2] / r];
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/** One quantity bundle at time t (years from J2000) from spin axis s. */
|
|
113
|
+
function sampleAt(/** @type {number[]} */ s, /** @type {number} */ t) {
|
|
114
|
+
const n = orbitNormal(t);
|
|
115
|
+
const { i, Om } = inclNode(t);
|
|
116
|
+
const [zx, zy] = zAt(t);
|
|
117
|
+
const e = Math.hypot(zx, zy);
|
|
118
|
+
const w = Math.atan2(zy, zx) - Om;
|
|
119
|
+
const ph = [
|
|
120
|
+
Math.cos(Om) * Math.cos(w) - Math.sin(Om) * Math.sin(w) * Math.cos(i),
|
|
121
|
+
Math.sin(Om) * Math.cos(w) + Math.cos(Om) * Math.sin(w) * Math.cos(i),
|
|
122
|
+
Math.sin(w) * Math.sin(i),
|
|
123
|
+
];
|
|
124
|
+
const g = cross(s, n);
|
|
125
|
+
const gn = Math.hypot(g[0], g[1], g[2]);
|
|
126
|
+
const gu = [g[0] / gn, g[1] / gn, g[2] / gn];
|
|
127
|
+
const cosA = dot(gu, ph);
|
|
128
|
+
const sinA = dot(n, cross(gu, ph));
|
|
129
|
+
const periOfDateDeg = ((Math.atan2(sinA, cosA) * R2D) % 360 + 360) % 360;
|
|
130
|
+
return {
|
|
131
|
+
epsDeg: Math.acos(Math.max(-1, Math.min(1, dot(s, n)))) * R2D,
|
|
132
|
+
e,
|
|
133
|
+
periOfDateDeg,
|
|
134
|
+
eSinPeri: e * Math.sin(periOfDateDeg * D2R),
|
|
135
|
+
eCosPeri: e * Math.cos(periOfDateDeg * D2R),
|
|
136
|
+
inclEclDeg: i * R2D,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Integrate once over [min(t0,t1,0), max(t0,t1,0)] and return a sampler
|
|
142
|
+
* on a stepYr grid (linear interpolation; angles interpolated on the
|
|
143
|
+
* wrapped difference). t in years from J2000, negative = past.
|
|
144
|
+
* @param {number} t0Yr @param {number} t1Yr @param {number} stepYr
|
|
145
|
+
*/
|
|
146
|
+
function build(t0Yr, t1Yr, stepYr) {
|
|
147
|
+
const tMin = Math.min(t0Yr, t1Yr, 0), tMax = Math.max(t0Yr, t1Yr, 0);
|
|
148
|
+
const grid = new Map();
|
|
149
|
+
const S0 = [0, Math.sin(EPS0), Math.cos(EPS0)];
|
|
150
|
+
const H_STEP = 5;
|
|
151
|
+
for (const dir of [-1, +1]) {
|
|
152
|
+
let s = S0, t = 0;
|
|
153
|
+
grid.set(0, sampleAt(s, 0));
|
|
154
|
+
const end = dir < 0 ? tMin : tMax;
|
|
155
|
+
while (dir < 0 ? t > end : t < end) {
|
|
156
|
+
s = rk4(s, t, dir * H_STEP);
|
|
157
|
+
t += dir * H_STEP;
|
|
158
|
+
// Store ONLY at true step multiples: an end-of-range sample under a
|
|
159
|
+
// ROUNDED key collides with a real grid node (measured during C-3:
|
|
160
|
+
// build(+200, …, 1000) stored ε(+200) under key 0, clobbering the
|
|
161
|
+
// t = 0 sample by 94″ — the verdict generator's rms caught it).
|
|
162
|
+
// Partial edge segments are covered by at()'s a-side fallback.
|
|
163
|
+
if (Math.abs(t % stepYr) < H_STEP / 2) grid.set(Math.round(t / stepYr) * stepYr, sampleAt(s, t));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
/** @param {number} tYr */
|
|
168
|
+
at(tYr) {
|
|
169
|
+
const k0 = Math.floor(tYr / stepYr) * stepYr, k1 = k0 + stepYr;
|
|
170
|
+
const a = grid.get(k0), b = grid.get(k1) ?? a;
|
|
171
|
+
if (!a) throw new Error(`deep-orbital-history: ${tYr} outside the built range`);
|
|
172
|
+
const f = (tYr - k0) / stepYr;
|
|
173
|
+
const lerp = (/** @type {number} */ x, /** @type {number} */ y) => x + (y - x) * f;
|
|
174
|
+
const dAng = (/** @type {number} */ x, /** @type {number} */ y) => x + (((y - x + 540) % 360) - 180) * f;
|
|
175
|
+
return {
|
|
176
|
+
epsDeg: lerp(a.epsDeg, b.epsDeg),
|
|
177
|
+
e: lerp(a.e, b.e),
|
|
178
|
+
periOfDateDeg: ((dAng(a.periOfDateDeg, b.periOfDateDeg) % 360) + 360) % 360,
|
|
179
|
+
eSinPeri: lerp(a.eSinPeri, b.eSinPeri),
|
|
180
|
+
eCosPeri: lerp(a.eCosPeri, b.eCosPeri),
|
|
181
|
+
inclEclDeg: lerp(a.inclEclDeg, b.inclEclDeg),
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { build, alphaArcsecPerYr: ALPHA * R2D * 3600 };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = { createDeepOrbitalHistory };
|
package/src/index.js
CHANGED
|
@@ -121,6 +121,13 @@ export * as planetOrbitChain from './planets/orbit-chain.cjs';
|
|
|
121
121
|
// governed artifact; the browser flag path consumes exactly these).
|
|
122
122
|
export { buildPlanetChainsFromArtifactData, computePlanetElementsAtYear, computeHeliocentricEclipticFromElements, computePoissonArgRad, computeOsculatingElements, solveKeplerRad, ANCHOR_EPOCH_YEAR, ANCHOR_EPOCH_JD } from './planets/keplerian-chain.cjs';
|
|
123
123
|
export { CHAIN_ARTIFACT, CHAIN_ARTIFACT_HASH } from './planets/chain-artifact.js';
|
|
124
|
+
// Engine-switch Stage B, T5d-(d): the deep-time Earth-z channel (the deep
|
|
125
|
+
// lunar-chain modulation rides it; era consumers stay on the H/3 channel).
|
|
126
|
+
export { createDeepEccChannel } from './moon/deep-ecc-channel.cjs';
|
|
127
|
+
export { DEEP_MODES_ARTIFACT, DEEP_MODES_ARTIFACT_HASH } from './moon/deep-modes-artifact.cjs';
|
|
128
|
+
// Stage C-3: the ONE home of the obliquity-hybrid / deep-orbital-history
|
|
129
|
+
// mathematics (published-ε surfaces + the deep insolation features).
|
|
130
|
+
export { createDeepOrbitalHistory } from './earth/deep-orbital-history.cjs';
|
|
124
131
|
export { createPredictivePrecession, calcPlanetPerihelionLongDeg } from './planets/predict.cjs';
|
|
125
132
|
// L10 — the composition front door: one law set, N body records. Thin by
|
|
126
133
|
// design; engines keep their direct call sites (see planets/model.cjs).
|
package/src/model.js
CHANGED
|
@@ -27,6 +27,8 @@ import { createDeepTimeLod } from './deltat/deep-time.cjs';
|
|
|
27
27
|
import { createMoonRecessionHistory, createSolarChannelBudget } from './deltat/recession-history.cjs';
|
|
28
28
|
import { evalClimateL1OrbitalPermil } from './climate/l1-orbital.cjs';
|
|
29
29
|
import { createMoonEccChannel } from './moon/ecc-channel.cjs';
|
|
30
|
+
import { createDeepEccChannel } from './moon/deep-ecc-channel.cjs';
|
|
31
|
+
import { DEEP_MODES_ARTIFACT } from './moon/deep-modes-artifact.cjs';
|
|
30
32
|
import { createMoonMonthChain } from './moon/month-chain.cjs';
|
|
31
33
|
import { createChainCycleIntegrator } from './chain-cycles/index.cjs';
|
|
32
34
|
import { createMoonArguments, jdToDecimalYear } from './moon/arguments.cjs';
|
|
@@ -333,9 +335,13 @@ export function assembleModel(C, F, laws = {}) {
|
|
|
333
335
|
// measured, the H/16 law's present ė (−0.84e-5/cy) is 5× below the
|
|
334
336
|
// observed −4.20e-5 while this law reads −4.31e-5 (Phase-0 record:
|
|
335
337
|
// tools/explore/fq7s-h3-law-candidate.mjs; JPL Sun 1.49″, registry 0.80″,
|
|
336
|
-
// syzygy 3.72″). Consumers
|
|
337
|
-
//
|
|
338
|
-
// and the cardinal-point braid —
|
|
338
|
+
// syzygy 3.72″). Consumers (engine-switch decision (ii) restatement,
|
|
339
|
+
// plan 02 §8): the eclipse Sun (equation of centre), the besselian Sun
|
|
340
|
+
// distance and the cardinal-point braid — the CLOCK-side machinery. The
|
|
341
|
+
// LUNAR chain (E-factor, perigee/node modulation/T², argument Δe² and
|
|
342
|
+
// of-date rates) rides the ONE deep e (deep-ecc-channel.cjs — the
|
|
343
|
+
// engine's own ±10-Myr z-vector); this H/3 line is its epoch-local
|
|
344
|
+
// tangent (E18), agreeing within 4.2e-5 across the historical era.
|
|
339
345
|
// ONE implementation for all three runtimes: moon/ecc-channel.cjs (the
|
|
340
346
|
// Node engine's deep-time.js and the browser's script.js instantiate the
|
|
341
347
|
// same channel with the same inputs). Its phase counter runs from J2000
|
|
@@ -349,6 +355,14 @@ export function assembleModel(C, F, laws = {}) {
|
|
|
349
355
|
inclinationCycleAnchorDeg: C.earthOrbital.earthInclinationCycleAnchor,
|
|
350
356
|
eccentricityJ2000: C.earthOrbital.earthEccentricityJ2000,
|
|
351
357
|
});
|
|
358
|
+
// Engine-switch decision (ii) (plan 02 §8): the ONE deep e — the engine's
|
|
359
|
+
// own ±10-Myr mode table, anchored form — feeds the ENTIRE lunar chain
|
|
360
|
+
// (modulation, cycle counts, arguments eccAt/channelIntegral, E-factor).
|
|
361
|
+
// The Sun/clock machinery (eclipse Sun EoC, besselian Sun distance,
|
|
362
|
+
// cardinal braid) stays on the H/3 channel above — a certification
|
|
363
|
+
// split, not a physics one (the two agree within 4.2e-5 in-era). The
|
|
364
|
+
// laws hook deliberately does NOT reach this channel.
|
|
365
|
+
const deepEcc = createDeepEccChannel(DEEP_MODES_ARTIFACT);
|
|
352
366
|
/** @param {number} year @returns {number} */
|
|
353
367
|
const eccentricityAt = laws.eccentricityAt ?? ((year) => moonEcc.eccAt(year - 2000));
|
|
354
368
|
/** de/dyear of the one law — the cardinal braid's equation-of-centre
|
|
@@ -682,7 +696,13 @@ export function assembleModel(C, F, laws = {}) {
|
|
|
682
696
|
meanLodSecondsAtAge: /** @param {number} tMa */ (tMa) => deepLod.lodSecondsAtAge(tMa),
|
|
683
697
|
meanSiderealYearSecondsAtAge: /** @param {number} tMa */ (tMa) => deepLod.siderealYearSecondsAtAge(tMa),
|
|
684
698
|
meanHAtAge: /** @param {number} tMa */ (tMa) => deepLod.hAtAge(tMa),
|
|
685
|
-
|
|
699
|
+
// Decision (ii) (owner-approved MODEL CHANGE, plan 02 §8): the whole
|
|
700
|
+
// lunar chain — this modulation, the integrated cycle counts it
|
|
701
|
+
// drives, the arguments' eccAt/channelIntegral and the E-factor —
|
|
702
|
+
// reads the ONE deep e. The era shift in the ancient eclipse stack is
|
|
703
|
+
// accepted and rebaselined with its explanation (deep e is
|
|
704
|
+
// La2004-corroborated in-era).
|
|
705
|
+
modulation: /** @param {number} tMa @param {number} s */ (tMa, s) => deepEcc.modulation(tMa, s),
|
|
686
706
|
distanceMetresAtAge: moonDistanceMetresAtAge,
|
|
687
707
|
},
|
|
688
708
|
});
|
|
@@ -757,11 +777,12 @@ export function assembleModel(C, F, laws = {}) {
|
|
|
757
777
|
eccentricityDotDotJ2000: C.earthOrbital.earthEccentricityDotDotJ2000,
|
|
758
778
|
elpEarthFigureJ2ArcsecPerCy2: C.moonMeeus.elpW1T2Decomposition_arcsecPerCy2.earthFigureJ2,
|
|
759
779
|
elpGeneralPrecessionPA_T2ArcsecPerCy2: C.moonMeeus.elpW1T2Decomposition_arcsecPerCy2.generalPrecessionPA_T2_Lieske1976,
|
|
760
|
-
|
|
780
|
+
// Decision (ii): the lunar chain reads ONE deep e end to end
|
|
781
|
+
eccE0: deepEcc.e0,
|
|
761
782
|
},
|
|
762
783
|
fns: {
|
|
763
|
-
eccAt: /** @param {number} tYr */ (tYr) =>
|
|
764
|
-
channelIntegral: /** @param {number} T @param {number} s */ (T, s) =>
|
|
784
|
+
eccAt: /** @param {number} tYr */ (tYr) => deepEcc.eccAt(tYr),
|
|
785
|
+
channelIntegral: /** @param {number} T @param {number} s */ (T, s) => deepEcc.channelIntegral(T, s),
|
|
765
786
|
computeObliquityEarth: obliquitySnapshotDeg,
|
|
766
787
|
jdToSIyear: yearFromJD,
|
|
767
788
|
tropicalOrbitsBetween: mcTropical,
|
|
@@ -809,10 +830,10 @@ export function assembleModel(C, F, laws = {}) {
|
|
|
809
830
|
return Number.isFinite(dT) ? dT : 0;
|
|
810
831
|
};
|
|
811
832
|
|
|
812
|
-
// Bounded Meeus E-factor from the
|
|
813
|
-
//
|
|
833
|
+
// Bounded Meeus E-factor from the ONE deep e (decision (ii); the
|
|
834
|
+
// pure-Meeus polynomial A/B branch stays engine-local)
|
|
814
835
|
/** @param {number} dDays @returns {number} */
|
|
815
|
-
const fwEFactor = (dDays) =>
|
|
836
|
+
const fwEFactor = (dDays) => deepEcc.eFactorAt(dDays / C.foundational.inputmeanlengthsolaryearindays);
|
|
816
837
|
|
|
817
838
|
// D2 derived additional-argument rates (deg/cy, J2000 8H-lattice months;
|
|
818
839
|
// record: tools/explore/derive-a1a2a3.js)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The DEEP Earth-eccentricity channel — engine-switch Stage B, the T5d-(d)
|
|
3
|
+
* decision (ii) (plan 02 §8, owner-approved MODEL CHANGE, pre-registered
|
|
4
|
+
* acceptance in the same record).
|
|
5
|
+
*
|
|
6
|
+
* Evaluates Earth's e(t) from the engine's own ±10-Myr NAFF mode table
|
|
7
|
+
* (data/nbody-deep-secular-modes.json, embedded verbatim by generate.mjs as
|
|
8
|
+
* deep-modes-artifact.cjs) in the ANCHORED form the era chain also uses:
|
|
9
|
+
*
|
|
10
|
+
* z(t) = Σ (re + i·im)·e^{iωt} + (z_J2000 − Σ(0)), e = |z|
|
|
11
|
+
*
|
|
12
|
+
* — the constant remainder pins the unresolved short/ultra-long content at
|
|
13
|
+
* the JPL J2000 seed anchor, so e(J2000) is exact by construction.
|
|
14
|
+
*
|
|
15
|
+
* DOMAIN (decision (ii), proper physics — no mixed device): the ENTIRE
|
|
16
|
+
* lunar chain reads THIS channel — eccAt (the Δe² argument terms),
|
|
17
|
+
* channelIntegral (perigee/node of-date rates), modulation (the
|
|
18
|
+
* month/precession chain and its integrated cycle counts), eFactorAt (the
|
|
19
|
+
* Meeus E-factor). The Sun/clock machinery (eclipse Sun equation of
|
|
20
|
+
* centre, besselian Sun distance, cardinal braid) stays on the H/3 law
|
|
21
|
+
* (moon/ecc-channel.cjs) — a CERTIFICATION split, not a physics one: the
|
|
22
|
+
* two e's agree within 4.2e-5 wherever the domains overlap, and the H/3
|
|
23
|
+
* line keeps its E18 role as the epoch-local tangent inside the fitted
|
|
24
|
+
* clock stack.
|
|
25
|
+
*
|
|
26
|
+
* MEASURED at adoption (banked in the plan record): vs the H/3 law the
|
|
27
|
+
* attractor-mean modulation shifts are +2,526 ppm (perigee channel,
|
|
28
|
+
* s = 2.407) and +1,067 ppm (node, s = 1.018) — month/LOD shifts of
|
|
29
|
+
* ~10–25 ppm class, all 41 paleo anchors in bands; the ancient eclipse
|
|
30
|
+
* stack's cycle counts shift (χ² IMPROVES — recorded with its
|
|
31
|
+
* explanation: this e is La2004-corroborated in-era, 3× closer than the
|
|
32
|
+
* H/3 line; theory-corroborated, never tuned). Beyond ~5 Myr the table is
|
|
33
|
+
* spectrum-class (phases decohere) — the quasi-periodic ATTRACTOR (mean e
|
|
34
|
+
* and the 405-kyr-class beat structure) is the claim, never a pointwise
|
|
35
|
+
* ephemeris.
|
|
36
|
+
*
|
|
37
|
+
* LOAD-BEARING conventions (carried VERBATIM from the era channel —
|
|
38
|
+
* moon/ecc-channel.cjs — so the certified numerics match):
|
|
39
|
+
* - channelIntegral uses composite Simpson with step ≤ ~4,000 yr
|
|
40
|
+
* (N ≥ 2, even);
|
|
41
|
+
* - modulation(tMa, s) takes age in Myr, positive = past, ≡ 1 at J2000;
|
|
42
|
+
* - eFactorAt(tYr) = eccAt(tYr) / e0, ≡ 1 at J2000.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
'use strict';
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {{
|
|
49
|
+
* earthZ: ReadonlyArray<{omegaRadPerYr: number, re: number, im: number}>,
|
|
50
|
+
* anchorE: number,
|
|
51
|
+
* anchorPeriEclipticDeg: number,
|
|
52
|
+
* }} artifact — the embedded deep-modes artifact (earth z-modes + the J2000
|
|
53
|
+
* anchor pair joined from the chain artifact's one home).
|
|
54
|
+
*/
|
|
55
|
+
function createDeepEccChannel({ earthZ, anchorE, anchorPeriEclipticDeg }) {
|
|
56
|
+
const D2R = Math.PI / 180;
|
|
57
|
+
const zA = [anchorE * Math.cos(anchorPeriEclipticDeg * D2R), anchorE * Math.sin(anchorPeriEclipticDeg * D2R)];
|
|
58
|
+
/** @param {number} tYr @returns {[number, number]} */
|
|
59
|
+
const modeSum = (tYr) => {
|
|
60
|
+
let re = 0, im = 0;
|
|
61
|
+
for (const m of earthZ) {
|
|
62
|
+
const c = Math.cos(m.omegaRadPerYr * tYr), s = Math.sin(m.omegaRadPerYr * tYr);
|
|
63
|
+
re += m.re * c - m.im * s;
|
|
64
|
+
im += m.re * s + m.im * c;
|
|
65
|
+
}
|
|
66
|
+
return [re, im];
|
|
67
|
+
};
|
|
68
|
+
const s0 = modeSum(0);
|
|
69
|
+
const R = [zA[0] - s0[0], zA[1] - s0[1]]; // the constant remainder
|
|
70
|
+
|
|
71
|
+
/** Earth's e at tYr years from J2000 (negative = past).
|
|
72
|
+
* @param {number} tYr @returns {number} */
|
|
73
|
+
function eccAt(tYr) {
|
|
74
|
+
const [x, y] = modeSum(tYr);
|
|
75
|
+
return Math.hypot(x + R[0], y + R[1]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** de/dyear — analytic from the mode sum: d|z|/dt = (z·ż)/|z|.
|
|
79
|
+
* @param {number} tYr @returns {number} */
|
|
80
|
+
function eccRateAt(tYr) {
|
|
81
|
+
const [x0, y0] = modeSum(tYr);
|
|
82
|
+
const x = x0 + R[0], y = y0 + R[1];
|
|
83
|
+
let dx = 0, dy = 0;
|
|
84
|
+
for (const m of earthZ) {
|
|
85
|
+
const c = Math.cos(m.omegaRadPerYr * tYr), s = Math.sin(m.omegaRadPerYr * tYr);
|
|
86
|
+
dx += m.omegaRadPerYr * (-m.re * s - m.im * c);
|
|
87
|
+
dy += m.omegaRadPerYr * (m.re * c - m.im * s);
|
|
88
|
+
}
|
|
89
|
+
const r = Math.hypot(x, y);
|
|
90
|
+
return r === 0 ? 0 : (x * dx + y * dy) / r;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const e0 = eccAt(0); // ≡ anchorE by construction
|
|
94
|
+
const g0 = Math.pow(1 - e0 * e0, -1.5);
|
|
95
|
+
|
|
96
|
+
/** [g(e(t))/g₀]^s — the perigee/node rate modulation, ≡ 1 at J2000.
|
|
97
|
+
* tMa is age in Myr (positive = past, the deep-time chain convention).
|
|
98
|
+
* @param {number} tMa @param {number} s @returns {number} */
|
|
99
|
+
function modulation(tMa, s) {
|
|
100
|
+
if (tMa === 0) return 1;
|
|
101
|
+
const e = eccAt(-tMa * 1e6);
|
|
102
|
+
return Math.pow(Math.pow(1 - e * e, -1.5) / g0, s);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** ∫₀ᵀ [(g(e(t′))/g₀)^s − 1] dt′ in Julian centuries — the phase-aware
|
|
106
|
+
* channel-rate integral. Composite Simpson, step ≤ ~4 kyr (the era
|
|
107
|
+
* channel's certified discretization, verbatim).
|
|
108
|
+
* @param {number} T @param {number} s @returns {number} */
|
|
109
|
+
function channelIntegral(T, s) {
|
|
110
|
+
if (T === 0) return 0;
|
|
111
|
+
/** @param {number} t */
|
|
112
|
+
const f = (t) => {
|
|
113
|
+
const e = eccAt(t * 100); // t in cy → years
|
|
114
|
+
return Math.pow(Math.pow(1 - e * e, -1.5) / g0, s) - 1;
|
|
115
|
+
};
|
|
116
|
+
const N = Math.max(2, 2 * Math.ceil(Math.abs(T) * 100 / 8000));
|
|
117
|
+
const h = T / N;
|
|
118
|
+
let sum = f(0) + f(T);
|
|
119
|
+
for (let i = 1; i < N; i++) sum += f(i * h) * (i % 2 ? 4 : 2);
|
|
120
|
+
return sum * h / 3;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Bounded Meeus E-factor: E ≡ e(t)/e(J2000), ≡ 1 at J2000.
|
|
124
|
+
* @param {number} tYr @returns {number} */
|
|
125
|
+
function eFactorAt(tYr) {
|
|
126
|
+
return eccAt(tYr) / e0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return { eccAt, eccRateAt, modulation, channelIntegral, eFactorAt, e0, g0 };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = { createDeepEccChannel };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED — do not edit. Regenerate:
|
|
3
|
+
* node tools/constants/generate.mjs --write
|
|
4
|
+
*
|
|
5
|
+
* Source: data/nbody-deep-secular-modes.json (the governed deep-time
|
|
6
|
+
* Earth-z mode table, engine-switch Stage B), earth z-modes + verdict
|
|
7
|
+
* emitted VERBATIM, plus the J2000 anchor pair (e, ϖ) joined from
|
|
8
|
+
* data/nbody-secular-frequencies.json j2000AnchorElements.earth — the
|
|
9
|
+
* anchor's ONE home. Two gates guard the chain: check:artifacts pins
|
|
10
|
+
* artifact ↔ engine; generate.mjs check mode pins this embed ↔ artifact.
|
|
11
|
+
* CJS because the lunar-chain consumers are CommonJS modules.
|
|
12
|
+
*/
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const DEEP_MODES_ARTIFACT_HASH = "b74be2d9b00a3460";
|
|
16
|
+
|
|
17
|
+
const DEEP_MODES_ARTIFACT = Object.freeze({"meta":{"integrator":"wh","order":2,"dtDays":2,"spanYears":20000000,"sampleDays":20000,"gr":true,"seed":"JPL Horizons J2000 heliocentric state vectors (tools/explore/j2000-state.mjs, the one home)","masses":"DE440 mass ratios (astro-reference physicalConstants)","runCommand":"node tools/explore/lattice-long-window-test.mjs years=20000000 integrator=wh dt=2 order=2 gr=1 frame=both sample=20000","dumpFile":"tools/explore/lattice-long-window-ecliptic-20000000-gr.local.json (untracked, 337 MB)","dumpSha256":"c6f37b93f8f53c5b72d9e2935085145820d384ed61ecdf69f3831895d5f0a516","conservationMaxDE":1.3523274883097007e-8,"decimation":4,"naffTerms":18,"naffZetaTerms":16,"naffZetaTermsEra":8,"frame":"ecliptic-J2000 (z-modes for the lunar-chain e; ζ-modes for the Stage-C obliquity hybrid — the invariable-frame ζ table remains unbanked, no consumer)","laskarRef":"Laskar, J. et al. (2004), A&A 428, 261–285, Table 3 (theory reference labels)"},"verdict":{"strongestBeatPeriodKyr":409.398962153882,"strongestBeatArcsecPerYr":3.165616232101899,"la2004BeatPeriodKyr":405.6972922210049,"rockMetronomeKyr":405.6,"companion124Kyr":123.63439229002236,"companion95Kyr":94.95801992141148,"earthLeadingModesArcsecPerYr":[4.257339363798321,7.422955595900221,17.905475677851488,17.35600814229943],"topBeatLines":[{"periodKyr":409.398962153882,"productAmp":0.0003189871275662614},{"periodKyr":94.95801992141148,"productAmp":0.00023593726318903166},{"periodKyr":123.63439229002236,"productAmp":0.0002021269449318684},{"periodKyr":98.94135212634195,"productAmp":0.0001820123713850866},{"periodKyr":130.4734867701679,"productAmp":0.00015592960633097004},{"periodKyr":2358.6470831218417,"productAmp":0.00011533256795834209},{"periodKyr":974.251698194696,"productAmp":0.00007391281237249426},{"periodKyr":706.1267630803258,"productAmp":0.00006332094707822819}],"note":"g5 matches La2004 to 0.0002 ″/yr; the beat gap vs 405.6 is g2 (chaotic-diffusion window sensitivity + omitted separate-Moon/asteroid terms) — the anatomy is the plan’s Stage-B record."},"earthZ":[{"omegaRadPerYr":0.000020640163686955943,"re":0.01663782532735386,"im":0.009773828910268845},{"omegaRadPerYr":0.00003598750427161015,"re":-0.0155511555977695,"im":-0.005606883657279738},{"omegaRadPerYr":0.00008680819575396443,"re":-0.011017310146969267,"im":0.005302931248387234},{"omegaRadPerYr":0.00008414430196835267,"re":0.005902460235142885,"im":-0.0073575521441138925},{"omegaRadPerYr":0.000027089406032463197,"re":0.0003820712762735637,"im":0.00381132243985138},{"omegaRadPerYr":0.00008287265957255809,"re":0.0018740756883102302,"im":0.0007570047078217853},{"omegaRadPerYr":0.00008556055947193001,"re":0.00065046714460136,"im":0.001636722269192129},{"omegaRadPerYr":0.00003343872861356042,"re":-0.0015906877043739744,"im":0.0008131867314299489},{"omegaRadPerYr":0.00008733249835491452,"re":0.0019695845162428804,"im":0.0007638996859228755},{"omegaRadPerYr":0.00008624160326238742,"re":-0.0007912287558015328,"im":0.0008454083667608703},{"omegaRadPerYr":0.00013693637603446235,"re":-0.00091728504412424,"im":0.0011947455784994275},{"omegaRadPerYr":0.00008149221104720623,"re":-0.0002919323858022318,"im":0.0013378769276789224},{"omegaRadPerYr":0.000035340366616489944,"re":-0.0014017009332458236,"im":-0.0005418283702703829},{"omegaRadPerYr":0.00003411910644328693,"re":0.0009644062512081837,"im":-0.0009278208477004621},{"omegaRadPerYr":0.000026443547751027787,"re":-0.0003484265086069058,"im":-0.0019049634588757702},{"omegaRadPerYr":0.00008946536777652535,"re":-0.0010363626781434278,"im":-0.00021237189770655706},{"omegaRadPerYr":0.000027681653760243513,"re":0.00026309559235420505,"im":0.0013827244513428105},{"omegaRadPerYr":0.00003665339440166644,"re":0.001341581161662452,"im":0.00035305205249495507}],"earthZeta":[{"omegaRadPerYr":-2.96732779276946e-14,"re":-0.004153530797421736,"im":0.013136287139943213},{"omegaRadPerYr":-0.00009139185627510659,"re":-0.0039341668744113665,"im":-0.007077440344808186},{"omegaRadPerYr":-0.000027083329194200705,"re":0.0041703974742109,"im":0.0016342020564862083},{"omegaRadPerYr":-0.00008606223132085272,"re":0.0015441443378585364,"im":-0.0036871518361985415},{"omegaRadPerYr":-0.00003413935334637193,"re":-0.002956817542124509,"im":0.0024359440436811054},{"omegaRadPerYr":-0.00008872604497912732,"re":-0.00013216158559522037,"im":-0.002797304033559708},{"omegaRadPerYr":-0.00003326020694677573,"re":0.0008627085184454156,"im":-0.0008468691172706413},{"omegaRadPerYr":-0.00003470927143831441,"re":0.0013226438289662852,"im":-0.0011121945465339342},{"omegaRadPerYr":-0.00009406049953471362,"re":0.001297329508193755,"im":0.0008926331980509192},{"omegaRadPerYr":-0.00002648259433928881,"re":0.001695647505347929,"im":0.0006707872920285527},{"omegaRadPerYr":-0.00012773804995598164,"re":-0.0008156188441322624,"im":0.0010583300732716742},{"omegaRadPerYr":-0.00003267570575865712,"re":0.00028878599128559593,"im":-0.0004498471691632459},{"omegaRadPerYr":-0.000033725843136033775,"re":0.0012152922715564112,"im":-0.0007872735440399818},{"omegaRadPerYr":-0.000014507526525427572,"re":-0.00064166716018201,"im":0.0005786259131500737},{"omegaRadPerYr":-0.00009265988888533535,"re":-0.0005654435501795496,"im":0.00014913577755089046},{"omegaRadPerYr":-0.000003353112962211696,"re":0.0006060116994915085,"im":0.00025189133351366343}],"earthZetaEra":[{"omegaRadPerYr":-2.96732779276946e-14,"re":-0.0041400895842324354,"im":0.01314865914923023},{"omegaRadPerYr":-0.00009139185627510659,"re":-0.0038874970989988566,"im":-0.0070425256250290546},{"omegaRadPerYr":-0.000027083329194200705,"re":0.004075700185805294,"im":0.0016137774467260707},{"omegaRadPerYr":-0.00008606223132085272,"re":0.0015261120191598105,"im":-0.0036992031256430353},{"omegaRadPerYr":-0.00003413935334637193,"re":-0.0031492966403078486,"im":0.002570649693650614},{"omegaRadPerYr":-0.00008872604497912732,"re":-0.00014686941549255626,"im":-0.0027917154781614112},{"omegaRadPerYr":-0.00003326020694677573,"re":0.0005693304183459907,"im":-0.0006693278314130071},{"omegaRadPerYr":-0.00003470927143831441,"re":0.0012956912361530007,"im":-0.0010932966486614268}],"anchorE":0.016702435651957018,"anchorPeriEclipticDeg":462.9179213996577,"anchorInclEclipticDeg":0.00010345820355474172,"anchorAscNodeEclipticDeg":140.29217988414328});
|
|
18
|
+
|
|
19
|
+
module.exports = { DEEP_MODES_ARTIFACT, DEEP_MODES_ARTIFACT_HASH };
|
package/src/moon/ecc-channel.cjs
CHANGED
|
@@ -8,14 +8,17 @@
|
|
|
8
8
|
* max. The observed J2000 e (−0.86%), ė (+1.7%) and the sign of ë are
|
|
9
9
|
* PREDICTIONS of this line, not inputs.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
* eclipse Sun's equation of centre
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* (
|
|
17
|
-
*
|
|
18
|
-
*
|
|
11
|
+
* DOMAIN (engine-switch decision (ii) restatement, plan 02 §8): this H/3
|
|
12
|
+
* line is the CLOCK-side e — the eclipse Sun's equation of centre (FQ-7-Sun
|
|
13
|
+
* option C-small, doc 66 §5), the besselian Sun distance, the cardinal
|
|
14
|
+
* braid and the scene machinery ride it. The LUNAR chain (E-factor,
|
|
15
|
+
* modulation, channelIntegral, argument Δe²) rides the ONE deep e
|
|
16
|
+
* (deep-ecc-channel.cjs — the engine's own ±10-Myr z-vector); the two
|
|
17
|
+
* agree within 4.2e-5 across the historical era, and this line keeps its
|
|
18
|
+
* E18 role as the epoch-local tangent. Eccentricity remains
|
|
19
|
+
* frame-invariant (fixed-frame periods only); the H/16 perihelion cycle
|
|
20
|
+
* (the H/3 rotation seen from the H/13 equinox, 13 + 3 = 16) belongs to
|
|
21
|
+
* ϖ, not e (doc 108).
|
|
19
22
|
*
|
|
20
23
|
* Extracted VERBATIM from src/script.js (_FW_ECC, _fwEarthEcc,
|
|
21
24
|
* _eCompModulation, _fwChannelIntegral, the framework branch of _fwEFactor),
|