@essrt/physics 22.1.0 → 23.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/README.md +2 -1
- package/package.json +4 -3
- package/src/constants/coefficients.d.ts +11 -11
- package/src/constants/coefficients.js +4 -4
- package/src/constants/generated.d.ts +2 -15
- package/src/constants/generated.js +6 -31
- package/src/deltat/deep-time.cjs +26 -12
- package/src/deltat/moon-distance-artifact.cjs +20 -0
- package/src/deltat/moon-distance-history.cjs +115 -0
- package/src/earth/deep-orbital-history.cjs +25 -4
- package/src/index.js +6 -1
- package/src/layer0/derive-params.js +1 -5
- package/src/layer0/index.js +13 -14
- package/src/model.js +36 -51
- package/src/moon/month-chain.cjs +12 -19
- package/src/planets/chain-artifact.js +2 -2
- package/types/constants/coefficients.d.ts +11 -11
- package/types/constants/generated.d.ts +2 -15
- package/types/deltat/deep-time.d.cts +28 -12
- package/types/deltat/moon-distance-artifact.d.cts +19 -0
- package/types/deltat/moon-distance-history.d.cts +36 -0
- package/types/index.d.ts +2 -1
- package/types/layer0/derive-params.d.ts +3 -2
- package/types/layer0/index.d.ts +7 -5
- package/types/moon/month-chain.d.cts +7 -13
- package/src/deltat/recession-history.cjs +0 -169
- package/types/deltat/recession-history.d.cts +0 -80
|
@@ -500,6 +500,8 @@ function createDeepOrbitalHistory({
|
|
|
500
500
|
};
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
+
/** The factory's walks, one per step size — see build(). @type {Map<number, { grid: Map<number, any>, frontier: Record<number, { s: number[], t: number }> }>} */
|
|
504
|
+
const walks = new Map();
|
|
503
505
|
/**
|
|
504
506
|
* Integrate once over [min(t0,t1,0), max(t0,t1,0)] and return a sampler
|
|
505
507
|
* on a stepYr grid (linear interpolation; angles interpolated on the
|
|
@@ -514,7 +516,18 @@ function createDeepOrbitalHistory({
|
|
|
514
516
|
if (Math.max(Math.abs(tMin), Math.abs(tMax)) > 50000 && stepYr % 250 !== 0) {
|
|
515
517
|
throw new Error(`deep-orbital-history: builds beyond ±50 kyr need stepYr % 250 === 0 (got ${stepYr})`);
|
|
516
518
|
}
|
|
517
|
-
|
|
519
|
+
// ONE WALK PER STEP SIZE, EXTENDED, NEVER RESTARTED (plan 13 A1, measured):
|
|
520
|
+
// every caller's tier routing asked for `build(span, -span, step)` and
|
|
521
|
+
// rebuilt from J2000 whenever a deeper epoch arrived, so the four deep
|
|
522
|
+
// fixture anchors (380…2460 Ma) walked ~49 million RK4 steps — 14 of the
|
|
523
|
+
// chain's 17 minutes — and the API's first read at −498 Myr would walk
|
|
524
|
+
// ~5 million. The walk is a pure function of t from the fixed J2000 state
|
|
525
|
+
// S0, so continuing a stored walk from its last (s, t) yields the SAME
|
|
526
|
+
// step sequence as a fresh walk to the farther end: bit-identical nodes
|
|
527
|
+
// (the sampler-order-purity gate pins this). The grid and the two
|
|
528
|
+
// direction frontiers live on the factory, keyed by stepYr; a returned
|
|
529
|
+
// sampler reads the shared grid, which only ever gains nodes.
|
|
530
|
+
let w = walks.get(stepYr);
|
|
518
531
|
const S0 = S0A;
|
|
519
532
|
// D1-revised adaptive stepping: 5-yr RK4 near the era (the certified-
|
|
520
533
|
// precision zone), 250-yr beyond ±50 kyr — still 103 steps per
|
|
@@ -526,8 +539,16 @@ function createDeepOrbitalHistory({
|
|
|
526
539
|
// 250-aligned; switching one fine-step later would leave the coarse walk
|
|
527
540
|
// permanently off-grid — measured: every key beyond ±50 kyr missing).
|
|
528
541
|
const hStepAt = (/** @type {number} */ t) => (Math.abs(t) < 50000 ? 5 : 250);
|
|
542
|
+
if (!w) {
|
|
543
|
+
w = { grid: new Map(), frontier: { [-1]: { s: S0, t: 0 }, [1]: { s: S0, t: 0 } } };
|
|
544
|
+
walks.set(stepYr, w);
|
|
545
|
+
}
|
|
546
|
+
const grid = w.grid;
|
|
529
547
|
for (const dir of [-1, +1]) {
|
|
530
|
-
|
|
548
|
+
const end = dir < 0 ? tMin : tMax;
|
|
549
|
+
const front = w.frontier[dir];
|
|
550
|
+
if (dir < 0 ? end >= front.t : end <= front.t) continue; // already walked this far
|
|
551
|
+
let s = front.s, t = front.t;
|
|
531
552
|
// Each stored node also carries the equinox-node RATE (deg/yr) from a
|
|
532
553
|
// ±2.5-yr central difference on the integrator's own state — the C1
|
|
533
554
|
// (Hermite) interpolation input. Linear interpolation of the node
|
|
@@ -552,8 +573,7 @@ function createDeepOrbitalHistory({
|
|
|
552
573
|
smp.periOfDateRateDegPerYr = (((lp.peri - lm.peri + 540) % 360) - 180) / (2 * hR);
|
|
553
574
|
grid.set(key, smp);
|
|
554
575
|
};
|
|
555
|
-
storeWithRate(0, s, 0);
|
|
556
|
-
const end = dir < 0 ? tMin : tMax;
|
|
576
|
+
if (t === 0 && !grid.has(0)) storeWithRate(0, s, 0);
|
|
557
577
|
while (dir < 0 ? t > end : t < end) {
|
|
558
578
|
const H_STEP = hStepAt(t);
|
|
559
579
|
s = rk4(s, t, dir * H_STEP);
|
|
@@ -568,6 +588,7 @@ function createDeepOrbitalHistory({
|
|
|
568
588
|
// zone boundary is itself 250-aligned, so the walk stays on-grid).
|
|
569
589
|
if (Math.abs(t - Math.round(t / stepYr) * stepYr) < 1e-6) storeWithRate(Math.round(t / stepYr) * stepYr, s, t);
|
|
570
590
|
}
|
|
591
|
+
w.frontier[dir] = { s, t };
|
|
571
592
|
}
|
|
572
593
|
return {
|
|
573
594
|
/** @param {number} tYr */
|
package/src/index.js
CHANGED
|
@@ -167,7 +167,12 @@ export { PLANET_DISPLAY_NAMES } from './planets/display-names.cjs';
|
|
|
167
167
|
// Phase 8.4 — the climate/ΔT machinery, extracted layer by layer.
|
|
168
168
|
export { createDeltaTCycles } from './deltat/cycles.cjs';
|
|
169
169
|
export { createDeepTimeLod } from './deltat/deep-time.cjs';
|
|
170
|
-
|
|
170
|
+
// plan 12 (option A): the Earth–Moon distance history is a CITED PHYSICAL
|
|
171
|
+
// INPUT (Farhat et al. 2022, the AstroGeo22 ephemeris) read as a shape on the
|
|
172
|
+
// model's J2000 anchor; the fitted quartic, the rock-fitted regime spline and
|
|
173
|
+
// the solar-channel budget are deleted.
|
|
174
|
+
export { createMoonDistanceHistory } from './deltat/moon-distance-history.cjs';
|
|
175
|
+
export { MOON_DISTANCE_ARTIFACT, MOON_DISTANCE_ARTIFACT_HASH } from './deltat/moon-distance-artifact.cjs';
|
|
171
176
|
export { deltaTEspenakMeeusCanonSeconds } from './deltat/historical.cjs';
|
|
172
177
|
export { evalClimateL1OrbitalPermil, laggedL1Terms, createAlphaGiaChannel } from './climate/l1-orbital.cjs';
|
|
173
178
|
// 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,
|
package/src/layer0/index.js
CHANGED
|
@@ -32,9 +32,7 @@
|
|
|
32
32
|
/**
|
|
33
33
|
* @typedef {Object} EpochParams
|
|
34
34
|
* @property {number} epochYear year at t_Ma = 0 (2000, NOT startmodelYear)
|
|
35
|
-
* @property {number} alpha1PerMa Moon recession, LLR-anchored
|
|
36
|
-
* @property {number} alpha3PerMa3
|
|
37
|
-
* @property {number} alpha4PerMa4
|
|
35
|
+
* @property {number} alpha1PerMa Moon recession, LLR-anchored (the J2000 slope of the cited history)
|
|
38
36
|
* @property {number} moonDistanceNowM a_Moon at J2000, metres
|
|
39
37
|
* @property {number} moonLockDistanceM tidal-lock asymptote, metres
|
|
40
38
|
* @property {number} totalAngularMomentumKgM2S L_tot of the Earth-Moon system
|
|
@@ -53,17 +51,21 @@
|
|
|
53
51
|
/**
|
|
54
52
|
* @typedef {Object} EpochPrimitives
|
|
55
53
|
* @property {(year: number) => number} tMa
|
|
56
|
-
* @property {(year: number) => number} moonDistanceMetres
|
|
54
|
+
* @property {(year: number) => number|null} moonDistanceMetres - null beyond the cited history's span
|
|
57
55
|
* @property {(year: number) => number|null} lodSeconds
|
|
58
56
|
* @property {(year: number) => number} siderealYearSeconds
|
|
59
57
|
* @property {(year: number) => number} tropicalYearSeconds sidereal less one equinox turn per T_p(t) (the composed precession period)
|
|
60
58
|
*/
|
|
61
59
|
|
|
62
60
|
/**
|
|
63
|
-
* @param {{params: EpochParams, alphaAtAgeMa: (tMa: number) => number
|
|
61
|
+
* @param {{params: EpochParams, alphaAtAgeMa: (tMa: number) => number,
|
|
62
|
+
* moonDistanceMetresAtAge: (tMa: number) => number|null}} deps —
|
|
63
|
+
* moonDistanceMetresAtAge is the engine's cited distance history
|
|
64
|
+
* (deltat/moon-distance-history: Farhat et al. 2022 as a shape on the
|
|
65
|
+
* J2000 anchor; plan 12 option A — the layer0 quartic twin is deleted).
|
|
64
66
|
* @returns {EpochPrimitives}
|
|
65
67
|
*/
|
|
66
|
-
export const createEpochPrimitives = ({ params: p, alphaAtAgeMa }) => {
|
|
68
|
+
export const createEpochPrimitives = ({ params: p, alphaAtAgeMa, moonDistanceMetresAtAge }) => {
|
|
67
69
|
/**
|
|
68
70
|
* Years before the epoch, in Ma. The ONE place this conversion lives.
|
|
69
71
|
* @param {number} year
|
|
@@ -72,24 +74,21 @@ export const createEpochPrimitives = ({ params: p, alphaAtAgeMa }) => {
|
|
|
72
74
|
const tMa = (year) => (p.epochYear - year) / 1e6;
|
|
73
75
|
|
|
74
76
|
/**
|
|
75
|
-
* Moon
|
|
76
|
-
* are the Farhat 2022 deep-time fit.
|
|
77
|
+
* Moon distance at age t — the cited history (null beyond its span).
|
|
77
78
|
* @param {number} t age in Ma
|
|
78
|
-
* @returns {number} metres
|
|
79
|
+
* @returns {number|null} metres
|
|
79
80
|
*/
|
|
80
|
-
const moonDistanceMetresCore = (t) =>
|
|
81
|
-
p.moonDistanceNowM
|
|
82
|
-
* (1 + p.alpha1PerMa * t + p.alpha3PerMa3 * t * t * t + p.alpha4PerMa4 * t * t * t * t);
|
|
81
|
+
const moonDistanceMetresCore = (t) => moonDistanceMetresAtAge(t);
|
|
83
82
|
|
|
84
83
|
/**
|
|
85
84
|
* Length of day from angular-momentum conservation: as the Moon recedes it
|
|
86
85
|
* takes orbital angular momentum and Earth's spin slows to compensate.
|
|
87
86
|
* @param {number} t age in Ma
|
|
88
|
-
* @returns {number|null} seconds; null past the tidal-lock asymptote
|
|
87
|
+
* @returns {number|null} seconds; null past the tidal-lock asymptote or the history's span
|
|
89
88
|
*/
|
|
90
89
|
const lodSecondsCore = (t) => {
|
|
91
90
|
const a = moonDistanceMetresCore(t);
|
|
92
|
-
if (a <= 0 || a >= p.moonLockDistanceM) return null;
|
|
91
|
+
if (a === null || a <= 0 || a >= p.moonLockDistanceM) return null;
|
|
93
92
|
const iEarth = alphaAtAgeMa(t) * p.earthMassKg * p.earthRadiusM * p.earthRadiusM;
|
|
94
93
|
return (2 * Math.PI * iEarth)
|
|
95
94
|
/ (p.totalAngularMomentumKgM2S
|
package/src/model.js
CHANGED
|
@@ -28,7 +28,8 @@ import { createPlanetSpinChannelFromArtifacts, computeObliquityJ2000Deg } from '
|
|
|
28
28
|
import { PLANET_DISPLAY_NAMES } from './planets/display-names.cjs';
|
|
29
29
|
import { createDeltaTCycles } from './deltat/cycles.cjs';
|
|
30
30
|
import { createDeepTimeLod } from './deltat/deep-time.cjs';
|
|
31
|
-
import {
|
|
31
|
+
import { createMoonDistanceHistory } from './deltat/moon-distance-history.cjs';
|
|
32
|
+
import { MOON_DISTANCE_ARTIFACT } from './deltat/moon-distance-artifact.cjs';
|
|
32
33
|
import { evalClimateL1OrbitalPermil, createAlphaGiaChannel } from './climate/l1-orbital.cjs';
|
|
33
34
|
import { createDeepEccChannel } from './moon/deep-ecc-channel.cjs';
|
|
34
35
|
import { DEEP_MODES_ARTIFACT } from './moon/deep-modes-artifact.cjs';
|
|
@@ -197,8 +198,6 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
197
198
|
solarWindKgPerS: C.physicalConstants.solarWindMassLossKgPerS,
|
|
198
199
|
speedOfLightKmPerS: C.physicalConstants.speedOfLight,
|
|
199
200
|
alpha1PerMa: C.deepTime.alpha1PerMa,
|
|
200
|
-
alpha3PerMa3: C.deepTime.alpha3PerMa3,
|
|
201
|
-
alpha4PerMa4: C.deepTime.alpha4PerMa4,
|
|
202
201
|
meanSiderealYearSeconds,
|
|
203
202
|
lodJ2000Seconds: meanLengthOfDay, // plan 09: ω₀ = the SI day (was the H/13 kinematic day)
|
|
204
203
|
sunMassKg: M_SUN,
|
|
@@ -219,38 +218,22 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
219
218
|
axialPrecessionJ2000Years: certifiedAxialPrecessionJ2000Years(),
|
|
220
219
|
});
|
|
221
220
|
|
|
222
|
-
// ──
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
// ── The Earth–Moon distance history — a CITED PHYSICAL INPUT (plan 12, option A)
|
|
222
|
+
// Farhat et al. 2022 (the AstroGeo22 ephemeris, embedded VERBATIM by the
|
|
223
|
+
// constants generator) read as the ratio a(t)/a(0) on the model's own J2000
|
|
224
|
+
// anchor, the J2000 slope the LLR observation α₁; null beyond its span. LOD
|
|
225
|
+
// follows by angular-momentum conservation with the J2000 L_EM constant —
|
|
226
|
+
// the former quartic, regime spline and solar-channel budget are deleted.
|
|
227
|
+
const recession = createMoonDistanceHistory({
|
|
228
|
+
table: MOON_DISTANCE_ARTIFACT,
|
|
228
229
|
aMoonNowMetres: EPOCH_PARAMS.moonDistanceNowM,
|
|
229
230
|
alpha1PerMa: EPOCH_PARAMS.alpha1PerMa,
|
|
230
|
-
alpha3PerMa3: EPOCH_PARAMS.alpha3PerMa3,
|
|
231
|
-
alpha4PerMa4: EPOCH_PARAMS.alpha4PerMa4,
|
|
232
|
-
regime: {
|
|
233
|
-
jointMa: REGIME.jointMa,
|
|
234
|
-
knotAgesMa: REGIME.knotAgesMa,
|
|
235
|
-
knotDistancesKm: REGIME.knotDistancesKm,
|
|
236
|
-
genesisMa: REGIME.genesisMa,
|
|
237
|
-
rocheLimitKm: REGIME.rocheLimitKm,
|
|
238
|
-
},
|
|
239
231
|
});
|
|
240
232
|
const moonDistanceMetresAtAge = recession.distanceMetresAtAge;
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
eFactorMoon: EPOCH_PARAMS.moonEccentricityFactor,
|
|
246
|
-
beta0: REGIME.solarOceanLeakBeta0,
|
|
247
|
-
pumpStartMa: REGIME.thermalPumpStartMa,
|
|
248
|
-
pumpEndMa: REGIME.thermalPumpEndMa,
|
|
249
|
-
pumpFactor: REGIME.thermalPumpFactor,
|
|
250
|
-
jointMa: REGIME.jointMa,
|
|
251
|
-
genesisMa: REGIME.genesisMa,
|
|
252
|
-
distanceMetresAtAge: moonDistanceMetresAtAge,
|
|
253
|
-
});
|
|
233
|
+
/** The published surfaces' km reading — NaN beyond the cited history's span (the API's
|
|
234
|
+
* validity span lies inside it; the deep charts stop where the input stops).
|
|
235
|
+
* @param {number} year @returns {number} */
|
|
236
|
+
const moonDistanceKmAtYearOrNaN = (year) => { const m = moonDistanceMetresAtAge(yearToTMa(year)); return m === null ? NaN : m / 1000; };
|
|
254
237
|
|
|
255
238
|
const DT = F.DT_STACK;
|
|
256
239
|
const RES = F.DT_RESONATOR;
|
|
@@ -343,8 +326,6 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
343
326
|
aLockMetres: EPOCH_PARAMS.moonLockDistanceM,
|
|
344
327
|
aMoonNowMetres: EPOCH_PARAMS.moonDistanceNowM,
|
|
345
328
|
alpha1PerMa: EPOCH_PARAMS.alpha1PerMa,
|
|
346
|
-
alpha3PerMa3: EPOCH_PARAMS.alpha3PerMa3,
|
|
347
|
-
alpha4PerMa4: EPOCH_PARAMS.alpha4PerMa4,
|
|
348
329
|
lodNowH13Seconds: EPOCH_PARAMS.lodNowH13Seconds,
|
|
349
330
|
meanSiderealYearJ2000Seconds: meanSiderealYearSeconds,
|
|
350
331
|
solarMassLossFracPerYear: EPOCH_PARAMS.solarMassLossFracPerYear,
|
|
@@ -361,7 +342,9 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
361
342
|
cycleLodSumAt: dtCycleLodCorrectionSum,
|
|
362
343
|
swingLodAt: (year) => dtCycles.swingLodSecondsAt(year),
|
|
363
344
|
swingLodRateAt: (year) => dtCycles.swingLodRateAt(year),
|
|
364
|
-
|
|
345
|
+
// plan 12 option A: L_EM is the J2000 constant (conservation; no channels);
|
|
346
|
+
// the LOD-rate decomposition's tidal term reads the history's analytic slope.
|
|
347
|
+
moonDistanceSlopeMetresPerMaAtAge: recession.slopeMetresPerMaAtAge,
|
|
365
348
|
});
|
|
366
349
|
|
|
367
350
|
// (Plan 09 step 7a: the integrated ∫dt/H_era phase table and its counter
|
|
@@ -588,19 +571,23 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
588
571
|
// and the year-length rates (±0.5-yr central differences through the
|
|
589
572
|
// grid) then returned grid-segment averages instead of local rates
|
|
590
573
|
// (anomalistic of date +2.63 s / +19 s, visit-order dependent).
|
|
591
|
-
const samplers = /** @type {Map<number
|
|
592
|
-
let deepRangeYr = 0;
|
|
574
|
+
const samplers = /** @type {Map<number, any>} */ (new Map());
|
|
593
575
|
const gridStep = (/** @type {number} */ n) => (n <= 50000 ? 100 : n <= 2000000 ? 1000 : 5000);
|
|
594
|
-
const tierSpan = (/** @type {number} */ n) => (n <= 50000 ? 50000 :
|
|
576
|
+
const tierSpan = (/** @type {number} */ n) => (n <= 50000 ? 50000 : 2000000);
|
|
595
577
|
const sampleAt = (/** @type {number} */ year) => {
|
|
596
578
|
const t = year - 2000, need = Math.max(20000, Math.abs(t) * 1.25);
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
579
|
+
if (need > 2000000) {
|
|
580
|
+
// The deep tier (5000-yr grid): walked in the queried DIRECTION only,
|
|
581
|
+
// to two nodes past the query, and EXTENDED by the factory's shared
|
|
582
|
+
// walk when a deeper epoch arrives (plan 13 A1). It was built to
|
|
583
|
+
// ±1.25·|t| in both directions and rebuilt from J2000 on every deeper
|
|
584
|
+
// probe — bit-identical values, 4× the RK4 steps of one walk.
|
|
585
|
+
const span = Math.ceil((Math.abs(t) + 2 * 5000) / 5000) * 5000;
|
|
586
|
+
return hist.build(t < 0 ? -span : span, 0, 5000).at(t);
|
|
602
587
|
}
|
|
603
|
-
|
|
588
|
+
const span = tierSpan(need);
|
|
589
|
+
if (!samplers.has(span)) samplers.set(span, hist.build(span, -span, gridStep(span)));
|
|
590
|
+
return samplers.get(span).at(t);
|
|
604
591
|
};
|
|
605
592
|
// The anomalistic year rides THIS movement's own apsidal line (the
|
|
606
593
|
// scene's perihelion) — the factory owns the construction; the planet
|
|
@@ -686,8 +673,9 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
686
673
|
const moonSiderealMonthDaysAt = (year) => {
|
|
687
674
|
const tMa = yearToTMa(year);
|
|
688
675
|
const lod = deepLod.lodSecondsAtAge(tMa);
|
|
689
|
-
|
|
690
|
-
|
|
676
|
+
const aAppM = moonDistanceMetresAtAge(tMa);
|
|
677
|
+
if (lod === null || aAppM === null) return NaN;
|
|
678
|
+
const aAppKm = aAppM / 1000;
|
|
691
679
|
const sidYrDays = deepLod.siderealYearSecondsAtAge(tMa) / lod;
|
|
692
680
|
const deltaA = aAppKm * (1 / (MASS_RATIO_EARTH_MOON + 1)) * (moonSiderealMonthInput / sidYrDays);
|
|
693
681
|
const aCorrM = (aAppKm + deltaA) * 1000;
|
|
@@ -973,9 +961,6 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
973
961
|
const moonChain = createMoonMonthChain({
|
|
974
962
|
constants: {
|
|
975
963
|
aMoonNowMetres: EPOCH_PARAMS.moonDistanceNowM,
|
|
976
|
-
alpha1PerMa: EPOCH_PARAMS.alpha1PerMa,
|
|
977
|
-
alpha3PerMa3: EPOCH_PARAMS.alpha3PerMa3,
|
|
978
|
-
alpha4PerMa4: EPOCH_PARAMS.alpha4PerMa4,
|
|
979
964
|
gmEarthMoonM3PerS2: EPOCH_PARAMS.gmEarthMoonM3S2,
|
|
980
965
|
massRatioEarthMoon: MASS_RATIO_EARTH_MOON,
|
|
981
966
|
moonSiderealMonthInputDays: moonSiderealMonthInput,
|
|
@@ -1568,7 +1553,7 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
1568
1553
|
// + the calibrated ΔT cycle stack. 86,400.001780 s at J2000.
|
|
1569
1554
|
lodRealSecondsAtYear: /** @param {number} year @returns {number} */ (year) => lodRealSeconds(year),
|
|
1570
1555
|
alphaAtYear: /** @param {number} year @returns {number} */ (year) => earthMoiFactorAtAge(yearToTMa(year)),
|
|
1571
|
-
moonDistanceKmAtYear: /** @param {number} year @returns {number} */ (year) =>
|
|
1556
|
+
moonDistanceKmAtYear: /** @param {number} year @returns {number} */ (year) => moonDistanceKmAtYearOrNaN(year),
|
|
1572
1557
|
// D6: OF-DATE — mass-loss law / the banked planetary λ̇ ratio
|
|
1573
1558
|
// (identical at J2000 where the ratio ≡ 1 by construction)
|
|
1574
1559
|
siderealYearSecondsAtYear: /** @param {number} year @returns {number} */ (year) => yearLengthsM.siderealYearSecondsAtYear(year),
|
|
@@ -1746,7 +1731,7 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
1746
1731
|
// the single surface the panel, charts, API and website consume.
|
|
1747
1732
|
yearLengths: yearLengthsM,
|
|
1748
1733
|
moon: Object.freeze({
|
|
1749
|
-
distanceKmAtYear: /** @param {number} year @returns {number} */ (year) =>
|
|
1734
|
+
distanceKmAtYear: /** @param {number} year @returns {number} */ (year) => moonDistanceKmAtYearOrNaN(year),
|
|
1750
1735
|
siderealMonthDaysAtYear: moonSiderealMonthDaysAt,
|
|
1751
1736
|
synodicMonthDays: moonSynodicMonthDays,
|
|
1752
1737
|
// The apparent-position chain (truncated Meeus Ch. 47 series on
|
|
@@ -1780,7 +1765,7 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
|
|
|
1780
1765
|
// construction sites (tools/verify/eclipse-audit.js, the browser
|
|
1781
1766
|
// _eclipse twins) spread the SAME assembly into their own
|
|
1782
1767
|
// createEclipseFinders call instead of triplicating it (the
|
|
1783
|
-
// three-runtimes rule — cf.
|
|
1768
|
+
// three-runtimes rule — cf. moon-distance-history):
|
|
1784
1769
|
frameworkSunDeps: Object.freeze({
|
|
1785
1770
|
sunMeanLongitudeJ2000Deg: sunL0Deg,
|
|
1786
1771
|
tropicalRateDegPerCy: sunTropicalRateDegPerCy,
|
package/src/moon/month-chain.cjs
CHANGED
|
@@ -49,9 +49,6 @@
|
|
|
49
49
|
* @param {{
|
|
50
50
|
* constants: {
|
|
51
51
|
* aMoonNowMetres: number,
|
|
52
|
-
* alpha1PerMa: number,
|
|
53
|
-
* alpha3PerMa3: number,
|
|
54
|
-
* alpha4PerMa4: number,
|
|
55
52
|
* gmEarthMoonM3PerS2: number,
|
|
56
53
|
* massRatioEarthMoon: number,
|
|
57
54
|
* moonSiderealMonthInputDays: number,
|
|
@@ -67,7 +64,7 @@
|
|
|
67
64
|
* meanSiderealYearSecondsAtAge: (tMa: number) => number,
|
|
68
65
|
* precessionPeriodYearsAtAge: (tMa: number) => (number | null),
|
|
69
66
|
* modulation: (tMa: number, s: number) => number,
|
|
70
|
-
* distanceMetresAtAge
|
|
67
|
+
* distanceMetresAtAge: (tMa: number) => number|null,
|
|
71
68
|
* },
|
|
72
69
|
* }} deps — fns are the ENGINE'S OWN layer-0/1 evaluators and the shared
|
|
73
70
|
* eccentricity channel's modulation; constants are the engine's derived
|
|
@@ -77,32 +74,27 @@
|
|
|
77
74
|
* 5c — the tropical month's equinox turn, formerly the counter's 13/H(t),
|
|
78
75
|
* 0.086 % slow: the chain's J2000 tropical month sat 5.85 ms above the IAU
|
|
79
76
|
* input, the 1/T_p form is within 0.1 ms of it).
|
|
80
|
-
* fns.distanceMetresAtAge
|
|
81
|
-
*
|
|
82
|
-
*
|
|
77
|
+
* fns.distanceMetresAtAge is the engine's CITED distance history
|
|
78
|
+
* (deltat/moon-distance-history; plan 12 option A — the internal quartic
|
|
79
|
+
* twin this chain carried until then is deleted; null beyond the span).
|
|
83
80
|
*/
|
|
84
81
|
function createMoonMonthChain({ constants, fns }) {
|
|
85
82
|
const {
|
|
86
|
-
aMoonNowMetres,
|
|
83
|
+
aMoonNowMetres,
|
|
87
84
|
gmEarthMoonM3PerS2, massRatioEarthMoon, moonSiderealMonthInputDays,
|
|
88
85
|
meanSiderealYearJ2000Seconds,
|
|
89
86
|
moonApsidalJ2000Seconds, moonNodalJ2000Seconds,
|
|
90
87
|
moonSiderealMonthJ2000Seconds,
|
|
91
88
|
sPerigee, sNode,
|
|
92
89
|
} = constants;
|
|
93
|
-
const { meanLodSecondsAtAge, meanSiderealYearSecondsAtAge, precessionPeriodYearsAtAge, modulation } = fns;
|
|
90
|
+
const { meanLodSecondsAtAge, meanSiderealYearSecondsAtAge, precessionPeriodYearsAtAge, modulation, distanceMetresAtAge } = fns;
|
|
91
|
+
if (typeof distanceMetresAtAge !== 'function') throw new Error('month-chain: fns.distanceMetresAtAge (the cited distance history) is required');
|
|
92
|
+
void aMoonNowMetres;
|
|
94
93
|
|
|
95
|
-
/**
|
|
96
|
-
* @param {number} tMa @returns {number} */
|
|
97
|
-
function quarticMetresAtAge(tMa) {
|
|
98
|
-
const t = tMa;
|
|
99
|
-
return aMoonNowMetres * (1 + alpha1PerMa * t + alpha3PerMa3 * t * t * t + alpha4PerMa4 * t * t * t * t);
|
|
100
|
-
}
|
|
101
|
-
const distanceMetresAtAge = fns.distanceMetresAtAge ?? quarticMetresAtAge;
|
|
102
|
-
|
|
103
|
-
/** @param {number} tMa @returns {number} */
|
|
94
|
+
/** @param {number} tMa @returns {number|null} */
|
|
104
95
|
function distanceKmAtAge(tMa) {
|
|
105
|
-
|
|
96
|
+
const m = distanceMetresAtAge(tMa);
|
|
97
|
+
return m === null ? null : m / 1000;
|
|
106
98
|
}
|
|
107
99
|
|
|
108
100
|
/** Solar Δa correction (km) for the Moon's apparent semi-major axis
|
|
@@ -120,6 +112,7 @@ function createMoonMonthChain({ constants, fns }) {
|
|
|
120
112
|
* @param {number} tMa @returns {number | null} */
|
|
121
113
|
function distanceCorrectedKmAtAge(tMa) {
|
|
122
114
|
const aApp = distanceKmAtAge(tMa);
|
|
115
|
+
if (aApp === null) return null;
|
|
123
116
|
const dA = solarDeltaAKmAtAge(tMa, aApp);
|
|
124
117
|
return (dA === null) ? null : aApp + dA;
|
|
125
118
|
}
|