@essrt/physics 2.4.0 → 3.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/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@essrt/physics",
3
- "version": "2.4.0",
3
+ "version": "3.0.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
- "modelVersion": "v12.0",
6
+ "modelVersion": "v13.0",
7
7
  "_note": "The model identity this package version ships (IP-unified-architecture \u00a710: package semver tracks the API axis; the model version + CONSTANTS_HASH/COEFFICIENTS_HASH in src/constants/ carry the scientific identity). The version-pinning gate enforces this pairing against public/input/model-version.json."
8
8
  },
9
9
  "type": "module",
@@ -636,6 +636,9 @@ export declare const REFERENCE_DATA: {
636
636
  "neptuneObservedRateArcsecCy": number;
637
637
  "ascNodeJointRmsArcsec": number;
638
638
  "generalPrecessionArcsecCy": number;
639
+ "generalPrecessionNewcombArcsecCy": number;
640
+ "mercuryObservedLonOfDateClemenceArcsecCy": number;
641
+ "mercuryNewtonianClassicalArcsecCy": number;
639
642
  "bepiColomboPrecisionArcsec": number;
640
643
  "chandlerWobbleCycleMonths": number;
641
644
  "chandlerWobbleAmplitudeRange": string;
@@ -35,7 +35,7 @@
35
35
  export const CONSTANTS_HASH = "ffbce6e075ca2f25";
36
36
 
37
37
  /** Model version label — single source: public/input/model-version.json (§10 two-axis scheme). */
38
- export const MODEL_VERSION = "v12.0";
38
+ export const MODEL_VERSION = "v13.0";
39
39
 
40
40
  /** Canonical preprint DOI — single source: public/input/model-version.json. */
41
41
  export const PREPRINT_DOI = "10.21203/rs.3.rs-8758810/v4";
@@ -784,6 +784,9 @@ export const REFERENCE_DATA = Object.freeze({
784
784
  "neptuneObservedRateArcsecCy": 200,
785
785
  "ascNodeJointRmsArcsec": 5.8,
786
786
  "generalPrecessionArcsecCy": 5028.8,
787
+ "generalPrecessionNewcombArcsecCy": 5025.645,
788
+ "mercuryObservedLonOfDateClemenceArcsecCy": 5599.74,
789
+ "mercuryNewtonianClassicalArcsecCy": 531.54,
787
790
  "bepiColomboPrecisionArcsec": 0.0015,
788
791
  "chandlerWobbleCycleMonths": 14,
789
792
  "chandlerWobbleAmplitudeRange": "3–15",
package/src/index.js CHANGED
@@ -145,9 +145,11 @@ export { createSunLongitudeCorrection } from './sun/longitude-correction.cjs';
145
145
  * even though the body is empty.
146
146
  *
147
147
  * @param {Constants} [constants]
148
+ * @param {{ laws?: { eccentricityAt?: (year: number) => number, eccentricityRateAt?: (year: number) => number, perihelionLongitudeDegAt?: (year: number) => number } }} [opts]
149
+ * `laws` — research overrides for Earth's orbit laws (doc 109 §7); absent = the shipped laws, bit-identical. Not part of the hash.
148
150
  * @returns {Model}
149
151
  */
150
- export const createModel = (constants = GENERATED) => {
152
+ export const createModel = (constants = GENERATED, opts = {}) => {
151
153
  // Validation targets are not merely absent from DEFAULT_CONSTANTS — they are
152
154
  // REFUSED here. Absence alone only stops the spread form
153
155
  // `{...DEFAULT_CONSTANTS, x}`; nothing stopped a caller passing a bound
@@ -183,7 +185,9 @@ export const createModel = (constants = GENERATED) => {
183
185
 
184
186
  // The §7a assembly: every factory wired from THIS context, so counterfactual
185
187
  // constants flow through the entire motion model.
186
- const surfaces = assembleModel(ctx, FITTED);
188
+ // opts.laws research overrides for Earth's orbit laws (see assembleModel);
189
+ // absent = the shipped laws, bit-identical. Never part of the hash.
190
+ const surfaces = assembleModel(ctx, FITTED, opts.laws ?? {});
187
191
 
188
192
  return {
189
193
  constants: ctx,
package/src/model.js CHANGED
@@ -65,9 +65,16 @@ const MOON_ECC_SENSITIVITY_NODE = 1.018;
65
65
  *
66
66
  * @param {Readonly<Record<string, any>>} C the frozen constants context
67
67
  * @param {Readonly<Record<string, any>>} F the fitted coefficients
68
+ * @param {{ eccentricityAt?: (year: number) => number, eccentricityRateAt?: (year: number) => number, perihelionLongitudeDegAt?: (year: number) => number }} [laws]
69
+ * RESEARCH OVERRIDES for Earth's orbit laws (doc 109 §7): an alternative e(t),
70
+ * de/dt(t) and ϖ_of-date(t) flow through every consumer (the eclipse Sun, the
71
+ * Moon's E-factor, the cardinal points) exactly as the shipped laws do. Default
72
+ * {} = the shipped laws, bit-identical to before this parameter existed. Not a
73
+ * counterfactual in the §2d sense (no hash change) — callers must say when
74
+ * they used it; the generators refuse to --write under an override.
68
75
  * @returns the assembled surfaces (epoch, earth, lengths, cardinal, moon) — type inferred so ReturnType stays precise
69
76
  */
70
- export function assembleModel(C, F) {
77
+ export function assembleModel(C, F, laws = {}) {
71
78
  // ── Derived constants (constants.js §9 order) ─────────────────────────────
72
79
  const H = C.foundational.holisticyearLength;
73
80
  const meanSolarYearDays = Math.round(C.foundational.inputmeanlengthsolaryearindays * (H / 8)) / (H / 8);
@@ -290,14 +297,14 @@ export function assembleModel(C, F) {
290
297
 
291
298
  // ── Earth scalars (integrated-phase display semantics) ────────────────────
292
299
  /** @param {number} year @returns {number} */
293
- const earthPerihelionDeg = (year) => {
300
+ const earthPerihelionDeg = laws.perihelionLongitudeDegAt ?? ((year) => {
294
301
  let longitude = 270.0 + 360.0 * cyclesBetween(balancedYear, year, 16);
295
302
  for (const [div, sinC, cosC] of F.PERI_HARMONICS_RAW) {
296
303
  const ph = phaseRadians(balancedYear, year, div);
297
304
  longitude += sinC * Math.sin(ph) + cosC * Math.cos(ph);
298
305
  }
299
306
  return (((longitude + F.PERI_OFFSET) % 360) + 360) % 360;
300
- };
307
+ });
301
308
  /** @param {number} year @returns {number} */
302
309
  const obliquityDeg = (year) => {
303
310
  let obliq = solsticeObliquityMean;
@@ -343,10 +350,10 @@ export function assembleModel(C, F) {
343
350
  eccentricityJ2000: C.earthOrbital.earthEccentricityJ2000,
344
351
  });
345
352
  /** @param {number} year @returns {number} */
346
- const eccentricityAt = (year) => moonEcc.eccAt(year - 2000);
353
+ const eccentricityAt = laws.eccentricityAt ?? ((year) => moonEcc.eccAt(year - 2000));
347
354
  /** de/dyear of the one law — the cardinal braid's equation-of-centre
348
355
  * derivative rides it. @param {number} year @returns {number} */
349
- const eccentricityRateAt = (year) => moonEcc.eccRateAt(year - 2000);
356
+ const eccentricityRateAt = laws.eccentricityRateAt ?? ((year) => moonEcc.eccRateAt(year - 2000));
350
357
  /** @param {number} year @returns {number} */
351
358
  const inclinationDeg = (year) => earthInclMean
352
359
  - earthInclAmplitude * Math.cos(phaseRadians(balancedYear, year, 3));