@essrt/physics 13.0.0 → 15.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.
@@ -2,31 +2,29 @@
2
2
  * createPlanetModel — the planet composition front door (Phase 8.3, L10).
3
3
  *
4
4
  * ONE law set, N body records: this factory binds an environment once and
5
- * runs the certified derivation chain over every body record, in the order
6
- * the chain requires (each step feeds the next):
5
+ * runs the certified derivation chain over every body record:
7
6
  *
8
- * ψ constant → inclination law (amplitude, mean)
9
- * → wobble period (beat of |axial| and |ICRF|)
10
- * K constant → obliquity mean (snapshot form) → eccentricity law
11
- * (amplitude, base, J2000 phase)
12
- * geometry (the type-branched ellipse family — the law-derived
13
- * eccentricity base feeds geometry for the seven carriers;
14
- * minor bodies use their record's base)
7
+ * inputs the chain's g-mode beat (wobble) and the spin channel's
8
+ * derived J2000 obliquity, carried on the record since plan 06
9
+ * Phase 7 commit 2
10
+ * geometry (the type-branched ellipse family on the OBSERVED J2000
11
+ * eccentricity; minor bodies use their record's base)
12
+ *
13
+ * The ψ and K amplitude laws that opened this chain (ψ constant →
14
+ * inclination amplitude/mean; K constant → eccentricity amplitude/base/
15
+ * phase) are DELETED — K at plan 07 R6, ψ at plan 07 R5. A planet's
16
+ * inclination and eccentricity of date have one home, the N-body chain
17
+ * (model.js planetChainElementsAt); docs/retired-record.md is the record.
15
18
  *
16
19
  * THIN BY DESIGN. This is the composition surface, not a rewiring: both
17
- * engines keep their existing direct call sites into the law modules, and
18
- * the runtime channels (eccentricity-at-year, orientation, the ascending-
19
- * node integrator, predictive precession) stay direct module calls because
20
- * they consume engine-owned state (scene JD, epoch machinery, fitted
21
- * tables). What this factory adds is the seam future bodies plug into:
22
- * a new body is a record + (at most) one new geometry branch — see the
23
- * minor-body placeholder note in geometry.cjs (Phase 18 perturbation
24
- * types land the same way).
20
+ * engines keep their existing direct call sites, and the runtime channels
21
+ * stay direct module calls because they consume engine-owned state (scene
22
+ * JD, epoch machinery, fitted tables). What this factory adds is the seam
23
+ * future bodies plug into: a new body is a record + (at most) one new
24
+ * geometry branch — see the minor-body placeholder note in geometry.cjs
25
+ * (Phase 18 perturbation types land the same way).
25
26
  *
26
- * Guard semantics mirror tools/lib/constants.js verbatim: the law steps
27
- * run only where the record carries the required fields (fibonacciD +
28
- * mass fraction for the ψ/K families, perihelion + axial periods for
29
- * wobble); geometry runs for every body. The identity gate
27
+ * Geometry runs for every body. The identity gate
30
28
  * (test/planet-model-identity.test.mjs) holds this factory bit-exact
31
29
  * against the shipped Node derivation.
32
30
  */
@@ -34,18 +32,13 @@
34
32
  'use strict';
35
33
 
36
34
  const { derivePlanetGeometry } = require('./geometry.cjs');
37
- const FL = require('./fibonacci-laws.cjs');
38
35
 
39
36
  /**
40
37
  * @typedef {Object} PlanetModelBody
41
38
  * @property {string} [type] - geometry type branch ('I' | 'II' | 'III')
42
39
  * @property {number} solarYearInput
43
- * @property {number} [fibonacciD]
44
40
  * @property {number} [invPlaneInclinationJ2000]
45
41
  * @property {number} [longitudePerihelion]
46
- * @property {number} [inclinationCycleAnchor]
47
- * @property {boolean} [antiPhase]
48
- * @property {number} [perihelionEclipticYears]
49
42
  * @property {number} [wobblePeriodYears] - carriers: the chain's g-mode beat (input since Phase 7 commit 2)
50
43
  * @property {number} [obliquityMeanDeg] - carriers: the derived J2000 obliquity (input since Phase 7 commit 2)
51
44
  * @property {number} [axialTiltJ2000]
@@ -66,15 +59,10 @@ const FL = require('./fibonacci-laws.cjs');
66
59
  * @property {number} currentAUDistanceKm
67
60
  * @property {number} earthEccentricityJ2000
68
61
  * @property {number} earthPerihelionLongitudeJ2000Deg
69
- * @property {{ earthInvPlaneInclinationAmplitude: number,
70
- * massEarthAlone: number, massSun: number }} calibration
71
- * @property {Record<string, number>} massFractions
72
62
  */
73
63
 
74
64
  /**
75
65
  * @typedef {Object} PlanetModelRecord
76
- * @property {number} [invPlaneInclinationAmplitude]
77
- * @property {number} [invPlaneInclinationMean]
78
66
  * @property {number} [wobblePeriodYears]
79
67
  * @property {number} [obliquityMeanDeg]
80
68
  * @property {ReturnType<typeof derivePlanetGeometry>} geometry
@@ -87,18 +75,13 @@ const FL = require('./fibonacci-laws.cjs');
87
75
  * @param {Record<string, PlanetModelBody>} bodies - keyed by body name
88
76
  * (the key selects the body-unique geometry branches: mercury, pluto,
89
77
  * halleys, ceres)
90
- * @returns {{ psiConstant: number,
91
- * bodies: Record<string, PlanetModelRecord> }}
78
+ * @returns {{ bodies: Record<string, PlanetModelRecord> }}
92
79
  */
93
80
  function createPlanetModel(env, bodies) {
94
- const psiConstant = FL.computePsiConstant({
95
- earthInvPlaneInclinationAmplitude: env.calibration.earthInvPlaneInclinationAmplitude,
96
- massEarthAlone: env.calibration.massEarthAlone,
97
- massSun: env.calibration.massSun,
98
- });
99
81
  // Plan 07 R6: kConstant, the System-Reset eccentricityAnchor
100
82
  // (balancedYear − systemResetN·H) and the t2000 phase it fed went with the
101
- // eccentricity law.
83
+ // eccentricity law; plan 07 R5: psiConstant (ψ = 3·A_earth·√(m_E/m_☉),
84
+ // from env.calibration) went with the inclination law.
102
85
 
103
86
  const geomEnv = {
104
87
  holisticYears: env.holisticYears,
@@ -111,22 +94,9 @@ function createPlanetModel(env, bodies) {
111
94
  /** @type {Record<string, PlanetModelRecord>} */
112
95
  const out = {};
113
96
  for (const [key, b] of Object.entries(bodies)) {
114
- const massFrac = env.massFractions[key];
115
97
  /** @type {PlanetModelRecord} */
116
98
  const rec = /** @type {PlanetModelRecord} */ ({});
117
99
 
118
- if (b.fibonacciD && massFrac && b.invPlaneInclinationJ2000 !== undefined) {
119
- const il = FL.computeInclinationLaw({
120
- fibonacciD: b.fibonacciD, massFrac,
121
- invPlaneInclinationJ2000: b.invPlaneInclinationJ2000,
122
- longitudePerihelion: /** @type {number} */ (b.longitudePerihelion),
123
- inclinationCycleAnchor: /** @type {number} */ (b.inclinationCycleAnchor),
124
- antiPhase: /** @type {boolean} */ (b.antiPhase),
125
- }, psiConstant);
126
- rec.invPlaneInclinationAmplitude = il.amplitude;
127
- rec.invPlaneInclinationMean = il.mean;
128
- }
129
-
130
100
  // Plan 06 Phase 7 commit 2: the K law's cycle period and obliquity input
131
101
  // are INPUTS of the record now — the chain's own g-mode beat
132
102
  // (keplerian-chain computeSecularShape) and the derived J2000 obliquity
@@ -156,7 +126,7 @@ function createPlanetModel(env, bodies) {
156
126
  out[key] = rec;
157
127
  }
158
128
 
159
- return { psiConstant, bodies: out };
129
+ return { bodies: out };
160
130
  }
161
131
 
162
132
  module.exports = { createPlanetModel };
@@ -2,14 +2,14 @@
2
2
  // Gives the TypeScript website full type safety at the boundary (§2g) while
3
3
  // packages/physics stays JavaScript.
4
4
 
5
- export declare const CONSTANTS_HASH: "726b10e23d8ace09";
5
+ export declare const CONSTANTS_HASH: "5ce921f2efa2e845";
6
6
 
7
7
  export declare const MODEL_VERSION: string;
8
8
 
9
9
  export declare const PREPRINT_DOI: string;
10
10
 
11
11
  export declare const DEFAULT_CONSTANTS: {
12
- readonly hash: "726b10e23d8ace09";
12
+ readonly hash: "5ce921f2efa2e845";
13
13
  readonly additionalBodies: {
14
14
  "pluto": {
15
15
  "name": string;
@@ -17,9 +17,7 @@ export declare const DEFAULT_CONSTANTS: {
17
17
  "type": string;
18
18
  "angleCorrection": number;
19
19
  "startpos": number;
20
- "perihelionEclipticFraction": [number, number];
21
20
  "ascendingNodeInvPlane": number;
22
- "inclinationCycleAnchor": number;
23
21
  "invPlaneInclinationMean": number;
24
22
  "invPlaneInclinationAmplitude": number;
25
23
  };
@@ -29,9 +27,7 @@ export declare const DEFAULT_CONSTANTS: {
29
27
  "type": string;
30
28
  "angleCorrection": number;
31
29
  "startpos": number;
32
- "perihelionEclipticFraction": [number, number];
33
30
  "ascendingNodeInvPlane": number;
34
- "inclinationCycleAnchor": number;
35
31
  "invPlaneInclinationMean": number;
36
32
  "invPlaneInclinationAmplitude": number;
37
33
  };
@@ -41,9 +37,7 @@ export declare const DEFAULT_CONSTANTS: {
41
37
  "type": string;
42
38
  "angleCorrection": number;
43
39
  "startpos": number;
44
- "perihelionEclipticFraction": [number, number];
45
40
  "ascendingNodeInvPlane": number;
46
- "inclinationCycleAnchor": number;
47
41
  "invPlaneInclinationMean": number;
48
42
  "invPlaneInclinationAmplitude": number;
49
43
  };
@@ -53,9 +47,7 @@ export declare const DEFAULT_CONSTANTS: {
53
47
  "orbitDistanceOverride": number;
54
48
  "angleCorrection": number;
55
49
  "startpos": number;
56
- "perihelionEclipticFraction": [number, number];
57
50
  "ascendingNodeInvPlane": number;
58
- "inclinationCycleAnchor": number;
59
51
  "invPlaneInclinationMean": number;
60
52
  "invPlaneInclinationAmplitude": number;
61
53
  };
@@ -486,13 +478,9 @@ export declare const DEFAULT_CONSTANTS: {
486
478
  "eocFraction": number;
487
479
  "startpos": number;
488
480
  "angleCorrection": number;
489
- "perihelionEclipticFraction": [number, number];
490
481
  "type": string;
491
482
  "mirrorPair": string;
492
- "fibonacciD": number;
493
483
  "ascendingNodeInvPlane": number;
494
- "inclinationCycleAnchor": number;
495
- "antiPhase": boolean;
496
484
  "ascendingNodeCyclesIn8H": number;
497
485
  };
498
486
  "venus": {
@@ -500,13 +488,9 @@ export declare const DEFAULT_CONSTANTS: {
500
488
  "eocFraction": number;
501
489
  "startpos": number;
502
490
  "angleCorrection": number;
503
- "perihelionEclipticFraction": [number, number];
504
491
  "type": string;
505
492
  "mirrorPair": string;
506
- "fibonacciD": number;
507
493
  "ascendingNodeInvPlane": number;
508
- "inclinationCycleAnchor": number;
509
- "antiPhase": boolean;
510
494
  "ascendingNodeCyclesIn8H": number;
511
495
  };
512
496
  "mars": {
@@ -514,13 +498,9 @@ export declare const DEFAULT_CONSTANTS: {
514
498
  "eocFraction": number;
515
499
  "startpos": number;
516
500
  "angleCorrection": number;
517
- "perihelionEclipticFraction": [number, number];
518
501
  "type": string;
519
502
  "mirrorPair": string;
520
- "fibonacciD": number;
521
503
  "ascendingNodeInvPlane": number;
522
- "inclinationCycleAnchor": number;
523
- "antiPhase": boolean;
524
504
  "ascendingNodeCyclesIn8H": number;
525
505
  };
526
506
  "jupiter": {
@@ -528,13 +508,9 @@ export declare const DEFAULT_CONSTANTS: {
528
508
  "eocFraction": number;
529
509
  "startpos": number;
530
510
  "angleCorrection": number;
531
- "perihelionEclipticFraction": [number, number];
532
511
  "type": string;
533
512
  "mirrorPair": string;
534
- "fibonacciD": number;
535
513
  "ascendingNodeInvPlane": number;
536
- "inclinationCycleAnchor": number;
537
- "antiPhase": boolean;
538
514
  "ascendingNodeCyclesIn8H": number;
539
515
  };
540
516
  "saturn": {
@@ -542,13 +518,9 @@ export declare const DEFAULT_CONSTANTS: {
542
518
  "eocFraction": number;
543
519
  "startpos": number;
544
520
  "angleCorrection": number;
545
- "perihelionEclipticFraction": [number, number];
546
521
  "type": string;
547
522
  "mirrorPair": string;
548
- "fibonacciD": number;
549
523
  "ascendingNodeInvPlane": number;
550
- "inclinationCycleAnchor": number;
551
- "antiPhase": boolean;
552
524
  "ascendingNodeCyclesIn8H": number;
553
525
  };
554
526
  "uranus": {
@@ -556,13 +528,9 @@ export declare const DEFAULT_CONSTANTS: {
556
528
  "eocFraction": number;
557
529
  "startpos": number;
558
530
  "angleCorrection": number;
559
- "perihelionEclipticFraction": [number, number];
560
531
  "type": string;
561
532
  "mirrorPair": string;
562
- "fibonacciD": number;
563
533
  "ascendingNodeInvPlane": number;
564
- "inclinationCycleAnchor": number;
565
- "antiPhase": boolean;
566
534
  "ascendingNodeCyclesIn8H": number;
567
535
  };
568
536
  "neptune": {
@@ -570,13 +538,9 @@ export declare const DEFAULT_CONSTANTS: {
570
538
  "eocFraction": number;
571
539
  "startpos": number;
572
540
  "angleCorrection": number;
573
- "perihelionEclipticFraction": [number, number];
574
541
  "type": string;
575
542
  "mirrorPair": string;
576
- "fibonacciD": number;
577
543
  "ascendingNodeInvPlane": number;
578
- "inclinationCycleAnchor": number;
579
- "antiPhase": boolean;
580
544
  "ascendingNodeCyclesIn8H": number;
581
545
  };
582
546
  };
package/types/index.d.ts CHANGED
@@ -12,9 +12,6 @@ export { createMoonArguments } from "./moon/arguments.cjs";
12
12
  export { createMoonSeries } from "./moon/series.cjs";
13
13
  export { createMoonApparent } from "./moon/apparent.cjs";
14
14
  export { derivePlanetGeometry } from "./planets/geometry.cjs";
15
- export * as planetFibonacciLaws from "./planets/fibonacci-laws.cjs";
16
- export * as planetOrientation from "./planets/orientation.cjs";
17
- export { integrateAscendingNode } from "./planets/asc-node-integrator.cjs";
18
15
  export * as planetOrbitChain from "./planets/orbit-chain.cjs";
19
16
  export { computeSecularShape } from "./planets/secular-shape.cjs";
20
17
  export { createSecularSeriesOverride } from "./planets/secular-series.cjs";
@@ -4,12 +4,8 @@ export type PlanetModelBody = {
4
4
  */
5
5
  type?: string | undefined;
6
6
  solarYearInput: number;
7
- fibonacciD?: number | undefined;
8
7
  invPlaneInclinationJ2000?: number | undefined;
9
8
  longitudePerihelion?: number | undefined;
10
- inclinationCycleAnchor?: number | undefined;
11
- antiPhase?: boolean | undefined;
12
- perihelionEclipticYears?: number | undefined;
13
9
  /**
14
10
  * - carriers: the chain's g-mode beat (input since Phase 7 commit 2)
15
11
  */
@@ -37,16 +33,8 @@ export type PlanetModelEnv = {
37
33
  currentAUDistanceKm: number;
38
34
  earthEccentricityJ2000: number;
39
35
  earthPerihelionLongitudeJ2000Deg: number;
40
- calibration: {
41
- earthInvPlaneInclinationAmplitude: number;
42
- massEarthAlone: number;
43
- massSun: number;
44
- };
45
- massFractions: Record<string, number>;
46
36
  };
47
37
  export type PlanetModelRecord = {
48
- invPlaneInclinationAmplitude?: number | undefined;
49
- invPlaneInclinationMean?: number | undefined;
50
38
  wobblePeriodYears?: number | undefined;
51
39
  obliquityMeanDeg?: number | undefined;
52
40
  geometry: ReturnType<typeof derivePlanetGeometry>;
@@ -55,12 +43,8 @@ export type PlanetModelRecord = {
55
43
  * @typedef {Object} PlanetModelBody
56
44
  * @property {string} [type] - geometry type branch ('I' | 'II' | 'III')
57
45
  * @property {number} solarYearInput
58
- * @property {number} [fibonacciD]
59
46
  * @property {number} [invPlaneInclinationJ2000]
60
47
  * @property {number} [longitudePerihelion]
61
- * @property {number} [inclinationCycleAnchor]
62
- * @property {boolean} [antiPhase]
63
- * @property {number} [perihelionEclipticYears]
64
48
  * @property {number} [wobblePeriodYears] - carriers: the chain's g-mode beat (input since Phase 7 commit 2)
65
49
  * @property {number} [obliquityMeanDeg] - carriers: the derived J2000 obliquity (input since Phase 7 commit 2)
66
50
  * @property {number} [axialTiltJ2000]
@@ -80,14 +64,9 @@ export type PlanetModelRecord = {
80
64
  * @property {number} currentAUDistanceKm
81
65
  * @property {number} earthEccentricityJ2000
82
66
  * @property {number} earthPerihelionLongitudeJ2000Deg
83
- * @property {{ earthInvPlaneInclinationAmplitude: number,
84
- * massEarthAlone: number, massSun: number }} calibration
85
- * @property {Record<string, number>} massFractions
86
67
  */
87
68
  /**
88
69
  * @typedef {Object} PlanetModelRecord
89
- * @property {number} [invPlaneInclinationAmplitude]
90
- * @property {number} [invPlaneInclinationMean]
91
70
  * @property {number} [wobblePeriodYears]
92
71
  * @property {number} [obliquityMeanDeg]
93
72
  * @property {ReturnType<typeof derivePlanetGeometry>} geometry
@@ -99,11 +78,9 @@ export type PlanetModelRecord = {
99
78
  * @param {Record<string, PlanetModelBody>} bodies - keyed by body name
100
79
  * (the key selects the body-unique geometry branches: mercury, pluto,
101
80
  * halleys, ceres)
102
- * @returns {{ psiConstant: number,
103
- * bodies: Record<string, PlanetModelRecord> }}
81
+ * @returns {{ bodies: Record<string, PlanetModelRecord> }}
104
82
  */
105
83
  export function createPlanetModel(env: PlanetModelEnv, bodies: Record<string, PlanetModelBody>): {
106
- psiConstant: number;
107
84
  bodies: Record<string, PlanetModelRecord>;
108
85
  };
109
86
  import { derivePlanetGeometry } from "./geometry.cjs";
@@ -1,120 +0,0 @@
1
- /**
2
- * Dynamic ascending node — rate-based segment integration (Phase 8.3, L5).
3
- *
4
- * dΩ/dε = −sin(Ω)/tan(i), integrated over obliquity change with segment
5
- * handling at obliquity extrema and Earth-inclination crossovers (the
6
- * inclination DIRECTION flips the sign of the effect per segment).
7
- *
8
- * Extracted from tools/lib/orbital-engine.js
9
- * calculateDynamicAscendingNodeFromTilts (itself the mirror of the
10
- * browser's 6-arg variant — S-P5). The BROWSER variant remains engine-side
11
- * this slice: neither copy is fixture-pinned, so the signature unification
12
- * is deferred to the factory pass, WITH probes first (recorded follow-up).
13
- *
14
- * §2h BOUNDARY: this module takes {ascendingNodeDeg, inclinationDeg} — the
15
- * Tychosium `orbitTilta/orbitTiltb` scheme names never enter the package;
16
- * the engines own the atan2/hypot decomposition at their edge.
17
- *
18
- * All time-dependent inputs are INJECTED per call: the engine's obliquity
19
- * and Earth-inclination evaluators, the precomputed obliquity-extrema
20
- * lookup, the inclination-crossing finder, and (optionally) the per-planet
21
- * dynamic ecliptic inclination.
22
- */
23
-
24
- 'use strict';
25
-
26
- /**
27
- * @param {{ ascendingNodeDeg: number, inclinationDeg: number }} tilt —
28
- * static node and inclination (engine-decomposed from its scene scheme)
29
- * @param {number} currentYear
30
- * @param {{
31
- * obliquityAt: (year: number) => number,
32
- * earthInclinationAt: (year: number) => number,
33
- * obliquityExtremaInRange: (yearMin: number, yearMax: number) => number[],
34
- * inclinationCrossingsInRange: (inclinationDeg: number, yearMin: number, yearMax: number) => number[],
35
- * eclipticInclinationAt: ((year: number) => number) | null,
36
- * earthInclinationMeanDeg: number,
37
- * earthInclinationAmplitudeDeg: number,
38
- * epochYear?: number,
39
- * }} deps — eclipticInclinationAt non-null enables the dynamic-inclination
40
- * crossover search and per-segment rates (the planetName path).
41
- * @returns {number} dynamic ascending node longitude, degrees 0–360
42
- */
43
- function integrateAscendingNode(tilt, currentYear, deps) {
44
- const DEG2RAD = Math.PI / 180;
45
- const RAD2DEG = 180 / Math.PI;
46
-
47
- const staticOmega = ((tilt.ascendingNodeDeg % 360) + 360) % 360;
48
- const planetInclination = tilt.inclinationDeg;
49
-
50
- if (planetInclination < 1e-6) return staticOmega;
51
-
52
- const i = planetInclination * DEG2RAD;
53
- const OmegaRad = staticOmega * DEG2RAD;
54
- const tanI = Math.tan(i);
55
- if (Math.abs(tanI) < 1e-10) return staticOmega;
56
-
57
- const sinOmega = Math.sin(OmegaRad);
58
- const EPOCH_YEAR = deps.epochYear !== undefined ? deps.epochYear : 2000;
59
-
60
- /** @param {number} fromYear @param {number} toYear @returns {number} */
61
- const integrateEffect = (fromYear, toYear) => {
62
- if (Math.abs(toYear - fromYear) < 0.1) return 0;
63
-
64
- const yearMin = Math.min(fromYear, toYear);
65
- const yearMax = Math.max(fromYear, toYear);
66
- const dir = toYear >= fromYear ? 1 : -1; // integration direction — signs the total
67
-
68
- /** @type {number[]} */
69
- let criticalYears = [yearMin, yearMax];
70
-
71
- criticalYears.push(...deps.obliquityExtremaInRange(yearMin, yearMax));
72
-
73
- // Find ALL inclination crossings
74
- const minEarthIncl = deps.earthInclinationMeanDeg - deps.earthInclinationAmplitudeDeg;
75
- const maxEarthIncl = deps.earthInclinationMeanDeg + deps.earthInclinationAmplitudeDeg;
76
-
77
- // With a dynamic ecliptic inclination the planet can enter Earth's range
78
- // even if the static value is outside — always search for crossovers.
79
- if (deps.eclipticInclinationAt || (planetInclination >= minEarthIncl && planetInclination <= maxEarthIncl)) {
80
- const crossIncl = deps.eclipticInclinationAt
81
- ? deps.eclipticInclinationAt((yearMin + yearMax) / 2)
82
- : planetInclination;
83
- criticalYears.push(...deps.inclinationCrossingsInRange(crossIncl, yearMin, yearMax));
84
- }
85
-
86
- criticalYears = [...new Set(criticalYears)].sort((a, b) => a - b);
87
-
88
- // Integrate over segments
89
- let effect = 0;
90
- for (let idx = 0; idx < criticalYears.length - 1; idx++) {
91
- const segStart = criticalYears[idx];
92
- const segEnd = criticalYears[idx + 1];
93
-
94
- const oblStart = deps.obliquityAt(segStart);
95
- const oblEnd = deps.obliquityAt(segEnd);
96
- const deltaObl = (oblEnd - oblStart) * DEG2RAD;
97
-
98
- const midYear = (segStart + segEnd) / 2;
99
- const earthInclAtMid = deps.earthInclinationAt(midYear);
100
-
101
- const dynIncl = deps.eclipticInclinationAt
102
- ? deps.eclipticInclinationAt(midYear)
103
- : planetInclination;
104
- const inclDirection = earthInclAtMid > dynIncl ? 1 : -1;
105
- const dynTanI = Math.tan(dynIncl * DEG2RAD);
106
- if (Math.abs(dynTanI) < 1e-10) continue; // skip near-zero inclination
107
- const segRate = -sinOmega / dynTanI;
108
-
109
- effect += segRate * inclDirection * deltaObl * RAD2DEG;
110
- }
111
- return effect * dir;
112
- };
113
-
114
- const effectFromEpoch = integrateEffect(EPOCH_YEAR, currentYear);
115
-
116
- const newOmega = staticOmega + effectFromEpoch;
117
- return ((newOmega % 360) + 360) % 360;
118
- }
119
-
120
- module.exports = { integrateAscendingNode };
@@ -1,95 +0,0 @@
1
- /**
2
- * The ψ/K amplitude relations + the retired law-loop constructions —
3
- * THE shared implementation (Phase 8.3, layer L2). Status per relation
4
- * (doc 10 "The Six Fibonacci Relations"; the restatement: the N-body
5
- * chain is the planet path):
6
- * - ψ (computePsiConstant/computeInclinationLaw) and K (computeKConstant/
7
- * computeEccentricityLaw's amplitude) are OPEN PREDICTIONS — untested
8
- * empirical amplitude laws, derived from Earth alone, kept as stated.
9
- * - The wobble beat (computeWobblePeriodYears) is kinematic frame
10
- * arithmetic — the permanent class.
11
- * - The obliquity-mean snapshot and the eccentricity base/phase
12
- * (System-Reset construction) belong to the RETIRED law framework —
13
- * today serving the legacy scene scaffolding, the no-chain bodies
14
- * (Pluto/Halley/Eros) and the o.fib* diagnostics (doc 72 — the closed
15
- * loop; docs/37 is archived, see docs/retired-record.md).
16
- *
17
- * Extracted VERBATIM in the BROWSER's expression forms from src/script.js
18
- * (the ψ loop, calcWobblePeriod, the obliquity-cycle aliases,
19
- * calcObliquityMean's load-time snapshot branch, the K loop), which
20
- * tools/lib/constants.js + constants/utils.js hand-mirrored with last-ulp
21
- * operation-order variants (measured: 32/42 law outputs bit-exact, 10 at
22
- * the 1e-11..1e-15 relative class) — those variants dissolve here.
23
- *
24
- * LOAD-BEARING conventions:
25
- * - ψ = 3·A_earth·√(M_EARTH_ALONE/M_SUN): the ALONE/SYSTEM mass asymmetry
26
- * is calibration convention (doc 24) — switching Earth to SYSTEM shifts
27
- * ψ by 0.612% and would require re-calibrating A_earth.
28
- * - Wobble = beat of |axial| and |ICRF| RATES (sign-free — Venus's
29
- * prograde-axial/retrograde-ICRF case); |axial| > 8H ⇒ frozen ⇒
30
- * wobble = |ICRF| exactly.
31
- * - The obliquity-mean law here is the SNAPSHOT form (the browser's
32
- * module-load TDZ fallback — the value both engines actually ship at
33
- * load); the browser's runtime integrated path stays engine-side with
34
- * its Phase-8 anchors. Note it uses 1/(H/13), where the runtime
35
- * integrated form uses 13/H — historical operation orders, preserved.
36
- * - K-law phase offset: 90° in-phase, 270° anti-phase (Saturn) — the n=7
37
- * System Reset state (all planets at mean e, Saturn falling).
38
- * - The Node mirror carried an `else` branch for bodies without a wobble
39
- * period — DEAD code (the loop is fibonacciD-guarded and all seven
40
- * carriers have wobble periods); dropped here, recorded in the commit.
41
- */
42
-
43
- 'use strict';
44
-
45
- /**
46
- * ψ constant from Earth's calibration. @param {{
47
- * earthInvPlaneInclinationAmplitude: number,
48
- * massEarthAlone: number, massSun: number }} c @returns {number} */
49
- function computePsiConstant(c) {
50
- return 3 * c.earthInvPlaneInclinationAmplitude * Math.sqrt(c.massEarthAlone / c.massSun);
51
- }
52
-
53
- /**
54
- * ψ law: invariable-plane inclination amplitude and mean.
55
- * @param {{ fibonacciD: number, massFrac: number,
56
- * invPlaneInclinationJ2000: number, longitudePerihelion: number,
57
- * inclinationCycleAnchor: number, antiPhase: boolean }} b
58
- * @param {number} psiConstant
59
- * @returns {{ amplitude: number, mean: number }} */
60
- function computeInclinationLaw(b, psiConstant) {
61
- const amplitude = psiConstant / (b.fibonacciD * Math.sqrt(b.massFrac));
62
- const antiPhase = b.antiPhase ? -1 : 1;
63
- const mean = b.invPlaneInclinationJ2000
64
- - antiPhase * amplitude * Math.cos((b.longitudePerihelion - b.inclinationCycleAnchor) * Math.PI / 180);
65
- return { amplitude, mean };
66
- }
67
-
68
- // (The device's wobble beat of integer axial and obliquity fractions, the
69
- // Venus/Neptune |ICRF| obliquity-cycle fallback and the snapshot "mean
70
- // obliquity" left with plan 06 Phase 7 commit 2: the K law's cycle period is
71
- // the chain's own g-mode beat (keplerian-chain computeSecularShape) and its
72
- // obliquity input the derived J2000 obliquity (spin-channel
73
- // computeObliquityJ2000Deg). docs/retired-record.md carries the record.)
74
-
75
- // Plan 07 R6: computeKConstant and computeEccentricityLaw stood here — the
76
- // K relation (K = e_amp·√m·a^1.5 / (sin(tilt)·√d), inverted per planet) and
77
- // the System-Reset eccentricity construction it fed
78
- // (base = A·cosθ + √(e_J2000² − A²sin²θ) at the J2000 phase, θ measured on
79
- // the wobble beat with a 90°/270° anti-phase offset).
80
- //
81
- // They are DELETED, not reclassified. Measured first (plan 07 §9e): scaling
82
- // their outputs by 1.10 moved no scene position and no published record
83
- // field — both twins place planets from the N-body chain, which overwrites
84
- // the construction entirely — and the registry keys built on them had no
85
- // consumer in the docs, on the website or in the paper. The nine balance and
86
- // Fibonacci-law instruments that computed from them are retired with them;
87
- // docs/retired-record.md is the record.
88
- //
89
- // A planet's eccentricity of date now has one home: the chain
90
- // (`model.planets.eccentricity(k, year)`), and its long-term shape is the
91
- // chain's own g-mode structure.
92
-
93
- module.exports = {
94
- computePsiConstant, computeInclinationLaw,
95
- };