@essrt/physics 9.1.0 → 9.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # @essrt/physics
2
2
 
3
3
  The physics core of **ESSRT** — the Expanding Solar System Resonance Theory —
4
- as implemented by the [Holistic Universe Model](https://3d.holisticuniverse.com)
4
+ as implemented by the [ESSRT simulator](https://3d.holisticuniverse.com)
5
5
  ([source, AGPL-3.0](https://github.com/dvansonsbeek/3d)). Pure computation:
6
6
  no I/O, no globals, no DOM, constants injected. The package ships the
7
7
  **complete model**, including the fitted coefficients, so an installed copy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@essrt/physics",
3
- "version": "9.1.0",
3
+ "version": "9.1.1",
4
4
  "description": "ESSRT (Expanding Solar System Resonance Theory) physics core — 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": "v14.0",
@@ -125,7 +125,15 @@ function createDeepTimeLod(deps) {
125
125
  * the unit H(t) below.
126
126
  * @param {number} t_Ma @returns {number|null} */
127
127
  function eraClockHAtAge(t_Ma) {
128
- const LOD_s = lodSecondsAtAge(t_Ma);
128
+ return eraClockHFromLod(lodSecondsAtAge(t_Ma));
129
+ }
130
+ // The `…FromLod` twins take an ALREADY-COMPUTED LOD(t): the Simpson ΔT
131
+ // integrand below evaluated the LOD four times and the tropical year twice
132
+ // per node through these helpers (measured 8.8 → 4.8 ms per cardinal panel
133
+ // year with the model's ΔT memo). Same operations, same inputs — every
134
+ // value bit-identical (11,958-value sweep, 0 differences).
135
+ /** @param {number|null} LOD_s @returns {number|null} */
136
+ function eraClockHFromLod(LOD_s) {
129
137
  if (LOD_s === null) return null;
130
138
  return K.holisticYearJ2000 * LOD_s / K.lodNowH13Seconds;
131
139
  }
@@ -156,7 +164,11 @@ function createDeepTimeLod(deps) {
156
164
  * ≡ H_era wherever (a₀/a_M)³ ≈ 1. Identifier kept (plan 06 P4).
157
165
  * @param {number} t_Ma @returns {number|null} */
158
166
  function hAtAge(t_Ma) {
159
- const hEra = eraClockHAtAge(t_Ma);
167
+ return hFromLod(t_Ma, lodSecondsAtAge(t_Ma));
168
+ }
169
+ /** @param {number} t_Ma @param {number|null} LOD_s @returns {number|null} */
170
+ function hFromLod(t_Ma, LOD_s) {
171
+ const hEra = eraClockHFromLod(LOD_s);
160
172
  const term = composed.torqueTermAtAge(t_Ma);
161
173
  return hEra === null || term === null ? null : hEra / term;
162
174
  }
@@ -202,8 +214,12 @@ function createDeepTimeLod(deps) {
202
214
  * ±2 Myr, measured), and re-basing would move every comb coefficient
203
215
  * for a rounding-level gain. This tier stays a named device. */
204
216
  function tropicalYearSecondsAtAge(t_Ma) {
217
+ return tropicalYearSecondsFromLod(t_Ma, lodSecondsAtAge(t_Ma));
218
+ }
219
+ /** @param {number} t_Ma @param {number|null} LOD_s @returns {number} */
220
+ function tropicalYearSecondsFromLod(t_Ma, LOD_s) {
205
221
  const sidSec = siderealYearSecondsAtAge(t_Ma);
206
- const Ht = hAtAge(t_Ma);
222
+ const Ht = hFromLod(t_Ma, LOD_s);
207
223
  if (Ht === null) return sidSec * (1 - 13 / K.holisticYearJ2000);
208
224
  return sidSec * (1 - 13 / Ht);
209
225
  }
@@ -281,15 +297,16 @@ function createDeepTimeLod(deps) {
281
297
  const tau = i * h;
282
298
  const lodMean = lodSecondsAtAge(tau);
283
299
  if (lodMean === null) return NaN;
284
- const yearS = tropicalYearSecondsAtAge(tau);
300
+ const yearS = tropicalYearSecondsFromLod(tau, lodMean);
285
301
  // Ecliptic "missing motion" — the solar day is measured against the
286
302
  // Sun on the ECLIPTIC, whose plane turns on the invariable plane at the
287
303
  // nodal rate s₃ (period ≈ 68,751 yr, an orbital quantity), not in the
288
304
  // inclination frame. Adds ~3.4 ms at J2000; the fitted cycle stack
289
305
  // closes Layer-4 LOD_real onto the USNO anchor. Non-null: the helper
290
306
  // can only be null when lodSecondsAtAge(tau) is null, which already
291
- // returned NaN above — the checker can't see the chain.
292
- const lodH5Raw = lodMean + /** @type {number} */ (eclipticLodCorrectionSecondsAtAge(tau));
307
+ // returned NaN above. Spelled inline from the node's own lodMean and
308
+ // yearS — the same operations as eclipticLodCorrectionSecondsAtAge(tau).
309
+ const lodH5Raw = lodMean + lodMean / (deps.nodalPeriodYearsFn() * (yearS / 86400));
293
310
  const integrand = (86400 - lodH5Raw) * yearS * 1e6 / 86400;
294
311
  const w = (i === 0 || i === n) ? 1 : (i % 2 === 1 ? 4 : 2);
295
312
  sum += w * integrand;
package/src/model.js CHANGED
@@ -411,9 +411,9 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
411
411
  // own ±10-Myr mode table, anchored form — feeds the ENTIRE lunar chain
412
412
  // (modulation, cycle counts, arguments eccAt/channelIntegral, E-factor).
413
413
  // The Sun/clock machinery (eclipse Sun EoC, besselian Sun distance,
414
- // cardinal braid) stays on the H/3 channel above — a certification
415
- // split, not a physics one (the two agree within 4.2e-5 in-era). The
416
- // laws hook deliberately does NOT reach this channel.
414
+ // cardinal braid) reads the one-source series below (plan 06 layer B —
415
+ // the two agree within 4.2e-5 in-era). The laws hook deliberately does
416
+ // NOT reach this channel.
417
417
  const deepEcc = createDeepEccChannel(DEEP_MODES_ARTIFACT);
418
418
  /** @param {number} year @returns {number} */
419
419
  // Plan 06 layer B: the PUBLISHED Earth eccentricity is the one-source series
@@ -673,8 +673,17 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
673
673
 
674
674
  // ── ΔT (TT − UT1): raw Simpson + sequential stack adds ────────────────────
675
675
  /** @param {number} tMa @returns {number} */
676
+ // Exact-argument memo (the alphaMemo pattern above): the cardinal Newton
677
+ // solve asks for ΔT at the SAME jd twice per step (jdTTFromUT in the
678
+ // apparent Sun and again under the planetary completion) — measured 8.8 →
679
+ // 5.6 ms per panel year (8 solves) at modern epochs, values bit-identical.
680
+ /** @type {Map<number, number>} */
681
+ const dtMemo = new Map();
682
+ /** @param {number} tMa @returns {number} */
676
683
  const meanDeltaTSecondsAtAge = (tMa) => {
677
684
  if (tMa === 0) return 0;
685
+ const hit = dtMemo.get(tMa);
686
+ if (hit !== undefined) return hit;
678
687
  let result = deepLod.deltaTRawSecondsAtAge(tMa);
679
688
  const yearY = 2000 - tMa * 1e6;
680
689
  result += dtCycles.cycleDeltaTSecondsAt('bond', yearY);
@@ -682,6 +691,8 @@ export function assembleModel(C, F, laws = {}, secularSeriesArtifact = /** @type
682
691
  result += dtCycles.cycleDeltaTSecondsAt('jose5', yearY);
683
692
  result += dtCycles.cycleDeltaTSecondsAt('jose4', yearY);
684
693
  result += dtCycles.swingDeltaTSecondsAt(yearY);
694
+ if (dtMemo.size >= 8192) dtMemo.clear();
695
+ dtMemo.set(tMa, result);
685
696
  return result;
686
697
  };
687
698
  /** @param {number} year @returns {number} */
@@ -14,7 +14,7 @@
14
14
  *
15
15
  * Two ascending-node conventions exist and BOTH are quantities (the S-P4
16
16
  * lesson): the year-2000-anchored linear node here
17
- * (ascendingNodeInvPlaneLinearAt — the node-integrator/dashboard mirror)
17
+ * (ascendingNodeInvPlaneLinearAt — the node-integrator mirror)
18
18
  * and the balanced-year −8H/N node inside the scene tilt
19
19
  * (eclipticInclinationFromBalanced). Do not merge them.
20
20
  */
@@ -54,7 +54,7 @@ function invPlaneInclinationAt(body, yearsSinceBalanced, env) {
54
54
 
55
55
  /**
56
56
  * Ascending node on the invariable plane — the LINEAR year-2000-anchored
57
- * convention (node-integrator/dashboard; see the header).
57
+ * convention (node-integrator; see the header).
58
58
  * @param {{ ascendingNodeInvPlane?: number, ascendingNodePeriod?: number,
59
59
  * perihelionEclipticYears: number }} body
60
60
  * @param {number} year @returns {number} degrees 0–360 */
@@ -25,7 +25,7 @@ export function invPlaneInclinationAt(body: {
25
25
  }): number;
26
26
  /**
27
27
  * Ascending node on the invariable plane — the LINEAR year-2000-anchored
28
- * convention (node-integrator/dashboard; see the header).
28
+ * convention (node-integrator; see the header).
29
29
  * @param {{ ascendingNodeInvPlane?: number, ascendingNodePeriod?: number,
30
30
  * perihelionEclipticYears: number }} body
31
31
  * @param {number} year @returns {number} degrees 0–360 */