@essrt/physics 1.11.0 → 1.12.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 +1 -1
- package/src/model.js +53 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@essrt/physics",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.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": "v11.0",
|
package/src/model.js
CHANGED
|
@@ -867,40 +867,64 @@ export function assembleModel(C, F) {
|
|
|
867
867
|
return eccentricityAt(year) + (eccentricityBase / 2) * (cos3 - cos3J2000);
|
|
868
868
|
};
|
|
869
869
|
const sunMeanLongitudeDegAt = (() => {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
870
|
+
// SW PHASE B — the CLOSED FORM on the integrated lattice phase
|
|
871
|
+
// (supersedes the E5 ±3,000-yr trapezoid table; valid at EVERY epoch,
|
|
872
|
+
// no table, no domain window). drift = D_smooth + Σₖ D_k + D_torque:
|
|
873
|
+
// · D_smooth — the deep chain's smooth SI tropical-year physics
|
|
874
|
+
// (tropicalYearDaysBase × LOD), two-point trapezoid: the same
|
|
875
|
+
// structure the scene twin uses, so the scene δ stays bounded.
|
|
876
|
+
// · Each oscillatory term integrates ANALYTICALLY: the antiderivative
|
|
877
|
+
// of cos/sin on the integrated phase is (H/2πk)·[sin/−cos] — the H
|
|
878
|
+
// drift lives in the phase itself; the amplitude factor uses H_J2000
|
|
879
|
+
// (ppm-class difference, negligible).
|
|
880
|
+
// · THE REBASE (E5's corpus-preferred J2000 rate anchor) is applied
|
|
881
|
+
// PER HARMONIC as a SIN-SATURATED ramp, (H/2πk)·sin(Δφₖ): equal to
|
|
882
|
+
// the linear rebase for |Δφₖ| ≪ 1 (the corpus era) and bounded by
|
|
883
|
+
// the harmonic's own period beyond — extending a linearized local
|
|
884
|
+
// slope to deep time would be the fitted-linear-slope trap. Every
|
|
885
|
+
// quantity is derived; zero new constants; each component and its
|
|
886
|
+
// slope vanish at year 2000 by construction (the drift-only
|
|
887
|
+
// property is exact, not tabulated).
|
|
888
|
+
const RATE_LIN = sunTropicalRateDegPerCy / 100; // deg / SI yr
|
|
873
889
|
const precessionP0DegPerYr = 13 * 360 / H;
|
|
874
890
|
const tanEps = Math.tan(earthtiltMean * Math.PI / 180);
|
|
875
|
-
|
|
876
|
-
* @param {number} year @returns {number} */
|
|
877
|
-
const obliquityExcursionRad = (year) => (
|
|
878
|
-
-earthInclAmplitude * Math.cos(phaseRadians(balancedYear, year, 3))
|
|
879
|
-
+ earthInclAmplitude * Math.cos(phaseRadians(balancedYear, year, 8))
|
|
880
|
-
) * Math.PI / 180;
|
|
891
|
+
const A_RAD = earthInclAmplitude * Math.PI / 180;
|
|
881
892
|
/** @param {number} year @returns {number} */
|
|
882
|
-
const
|
|
883
|
-
/ (
|
|
884
|
-
* (deepLod.lodSecondsAtAge(yearToTMa(year)) ?? meanLengthOfDay))
|
|
885
|
-
|
|
893
|
+
const rateSmooth = (year) => 360 * (365.25 * 86400)
|
|
894
|
+
/ (tropicalYearDaysBase(year)
|
|
895
|
+
* (deepLod.lodSecondsAtAge(yearToTMa(year)) ?? meanLengthOfDay));
|
|
896
|
+
/** @type {{rateSm0: number, ph0: Map<number, number>}|null} */
|
|
897
|
+
let anchor = null;
|
|
886
898
|
return /** @param {number} year @returns {number} */ (year) => {
|
|
887
|
-
if (
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
for (let i = 1; i < n; i++) {
|
|
893
|
-
const next = rateSIYr(Y_LO + i * STEP) - ref;
|
|
894
|
-
cum[i] = cum[i - 1] + 0.5 * (prev + next) * STEP;
|
|
895
|
-
prev = next;
|
|
896
|
-
}
|
|
897
|
-
const at2000 = cum[(2000 - Y_LO) / STEP];
|
|
898
|
-
for (let i = 0; i < n; i++) cum[i] -= at2000;
|
|
899
|
+
if (anchor === null) {
|
|
900
|
+
const ph0 = new Map();
|
|
901
|
+
for (const [k] of F.TROPICAL_YEAR_HARMONICS) ph0.set(k, phaseRadians(balancedYear, 2000, k));
|
|
902
|
+
for (const k of [3, 8]) if (!ph0.has(k)) ph0.set(k, phaseRadians(balancedYear, 2000, k));
|
|
903
|
+
anchor = { rateSm0: rateSmooth(2000), ph0 };
|
|
899
904
|
}
|
|
900
|
-
const
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
905
|
+
const dy = year - 2000;
|
|
906
|
+
// smooth deep physics (two-point trapezoid; exact 0 at 2000)
|
|
907
|
+
let drift = 0.5 * (rateSmooth(year) - anchor.rateSm0) * dy;
|
|
908
|
+
// year-harmonic ripple: rate ≈ −(RATE_LIN/T̄)·h(y); antiderivative +
|
|
909
|
+
// sin-saturated per-harmonic rebase
|
|
910
|
+
const HK = H / (2 * Math.PI);
|
|
911
|
+
for (const [k, sK, cK] of F.TROPICAL_YEAR_HARMONICS) {
|
|
912
|
+
const ph = phaseRadians(balancedYear, year, k);
|
|
913
|
+
const ph0 = /** @type {number} */ (anchor.ph0.get(k));
|
|
914
|
+
const scale = -(RATE_LIN / meanSolarYearDays) * (HK / k);
|
|
915
|
+
const anti = (-sK) * (Math.cos(ph) - Math.cos(ph0)) + cK * (Math.sin(ph) - Math.sin(ph0));
|
|
916
|
+
const h0 = sK * Math.sin(ph0) + cK * Math.cos(ph0);
|
|
917
|
+
drift += scale * (anti - h0 * Math.sin(ph - ph0));
|
|
918
|
+
}
|
|
919
|
+
// torque (E5): rate = −p₀·tanε·δε, δε = A(−cos φ₃ + cos φ₈); same
|
|
920
|
+
// antiderivative + per-component sin-saturated rebase
|
|
921
|
+
for (const [k, sgn] of [[3, -1], [8, 1]]) {
|
|
922
|
+
const ph = phaseRadians(balancedYear, year, k);
|
|
923
|
+
const ph0 = /** @type {number} */ (anchor.ph0.get(k));
|
|
924
|
+
const scale = -precessionP0DegPerYr * tanEps * A_RAD * sgn * (HK / k);
|
|
925
|
+
drift += scale * ((Math.sin(ph) - Math.sin(ph0)) - Math.cos(ph0) * Math.sin(ph - ph0));
|
|
926
|
+
}
|
|
927
|
+
return sunL0Deg + sunTropicalRateDegPerCy * dy / 100 + drift;
|
|
904
928
|
};
|
|
905
929
|
})();
|
|
906
930
|
|