universal-physics-tensor 11.0.0 → 12.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.
Files changed (287) hide show
  1. package/README.md +36 -34
  2. package/data/applied-cases.json +1892 -0
  3. package/data/applied-cases.schema.json +194 -0
  4. package/data/atlas/atlas.json +21 -21
  5. package/data/atlas/atlas.jsonld +1 -1
  6. package/data/atlas/diffusion.json +5 -5
  7. package/data/atlas/oscillators.json +7 -7
  8. package/data/atlas/waves.json +11 -11
  9. package/data/bridge-catalog.json +20 -4
  10. package/data/units.json +6 -25
  11. package/dist/atlas/benchmark/stats.d.ts.map +1 -1
  12. package/dist/atlas/benchmark/stats.js +6 -20
  13. package/dist/atlas/benchmark/stats.js.map +1 -1
  14. package/dist/atlas/physjs-entries.generated.d.ts +13 -4
  15. package/dist/atlas/physjs-entries.generated.d.ts.map +1 -1
  16. package/dist/atlas/physjs-entries.generated.js +15 -4
  17. package/dist/atlas/physjs-entries.generated.js.map +1 -1
  18. package/dist/atlas/physjs-reviewed.js +2 -2
  19. package/dist/atlas/physjs-reviewed.js.map +1 -1
  20. package/dist/cases/catalog-checks.d.ts +10 -0
  21. package/dist/cases/catalog-checks.d.ts.map +1 -0
  22. package/dist/cases/catalog-checks.js +241 -0
  23. package/dist/cases/catalog-checks.js.map +1 -0
  24. package/dist/cases/catalog.d.ts +83 -0
  25. package/dist/cases/catalog.d.ts.map +1 -0
  26. package/dist/cases/catalog.js +118 -0
  27. package/dist/cases/catalog.js.map +1 -0
  28. package/dist/cases/engine.d.ts +13 -0
  29. package/dist/cases/engine.d.ts.map +1 -0
  30. package/dist/cases/engine.js +179 -0
  31. package/dist/cases/engine.js.map +1 -0
  32. package/dist/cases/index.d.ts.map +1 -1
  33. package/dist/cases/index.js +5 -7
  34. package/dist/cases/index.js.map +1 -1
  35. package/dist/cases/methods.d.ts +215 -0
  36. package/dist/cases/methods.d.ts.map +1 -0
  37. package/dist/cases/methods.js +743 -0
  38. package/dist/cases/methods.js.map +1 -0
  39. package/dist/cases/types.d.ts +12 -0
  40. package/dist/cases/types.d.ts.map +1 -1
  41. package/dist/cases/types.js.map +1 -1
  42. package/dist/cli/args.d.ts +2 -0
  43. package/dist/cli/args.d.ts.map +1 -1
  44. package/dist/cli/args.js.map +1 -1
  45. package/dist/cli/command.d.ts +3 -0
  46. package/dist/cli/command.d.ts.map +1 -1
  47. package/dist/cli/command.js.map +1 -1
  48. package/dist/cli/commands/_discovery-opts.d.ts +1 -0
  49. package/dist/cli/commands/_discovery-opts.d.ts.map +1 -1
  50. package/dist/cli/commands/_discovery-opts.js +1 -0
  51. package/dist/cli/commands/_discovery-opts.js.map +1 -1
  52. package/dist/cli/commands/discover.d.ts.map +1 -1
  53. package/dist/cli/commands/discover.js +116 -71
  54. package/dist/cli/commands/discover.js.map +1 -1
  55. package/dist/cli/commands/evaluate.js +2 -2
  56. package/dist/cli/commands/evaluate.js.map +1 -1
  57. package/dist/cli/commands/explain.d.ts.map +1 -1
  58. package/dist/cli/commands/explain.js +22 -2
  59. package/dist/cli/commands/explain.js.map +1 -1
  60. package/dist/cli/commands/ground.d.ts.map +1 -1
  61. package/dist/cli/commands/ground.js +6 -1
  62. package/dist/cli/commands/ground.js.map +1 -1
  63. package/dist/cli/commands/map.d.ts.map +1 -1
  64. package/dist/cli/commands/map.js +9 -6
  65. package/dist/cli/commands/map.js.map +1 -1
  66. package/dist/cli/determination.d.ts +1 -0
  67. package/dist/cli/determination.d.ts.map +1 -1
  68. package/dist/cli/determination.js.map +1 -1
  69. package/dist/cli/flag-help.d.ts +1 -0
  70. package/dist/cli/flag-help.d.ts.map +1 -1
  71. package/dist/cli/flag-help.js +1 -0
  72. package/dist/cli/flag-help.js.map +1 -1
  73. package/dist/cli/graphs.d.ts +2 -0
  74. package/dist/cli/graphs.d.ts.map +1 -1
  75. package/dist/cli/graphs.js +1 -0
  76. package/dist/cli/graphs.js.map +1 -1
  77. package/dist/cli/main.d.ts +1 -0
  78. package/dist/cli/main.d.ts.map +1 -1
  79. package/dist/cli/main.js +1 -0
  80. package/dist/cli/main.js.map +1 -1
  81. package/dist/cli/output.d.ts +8 -0
  82. package/dist/cli/output.d.ts.map +1 -1
  83. package/dist/cli/output.js +8 -0
  84. package/dist/cli/output.js.map +1 -1
  85. package/dist/cli/statuses.d.ts.map +1 -1
  86. package/dist/cli/statuses.js +12 -2
  87. package/dist/cli/statuses.js.map +1 -1
  88. package/dist/cli/version.d.ts +1 -0
  89. package/dist/cli/version.d.ts.map +1 -1
  90. package/dist/cli/version.js +1 -0
  91. package/dist/cli/version.js.map +1 -1
  92. package/dist/cli-api.d.ts +2 -0
  93. package/dist/cli-api.d.ts.map +1 -1
  94. package/dist/cli-api.js +2 -0
  95. package/dist/cli-api.js.map +1 -1
  96. package/dist/composition/canonical-graph.d.ts +2 -2
  97. package/dist/composition/canonical-graph.js +2 -2
  98. package/dist/composition/canonical-graph.js.map +1 -1
  99. package/dist/composition/consequence.d.ts +15 -5
  100. package/dist/composition/consequence.d.ts.map +1 -1
  101. package/dist/composition/consequence.js +6 -4
  102. package/dist/composition/consequence.js.map +1 -1
  103. package/dist/composition/discovery.d.ts +78 -14
  104. package/dist/composition/discovery.d.ts.map +1 -1
  105. package/dist/composition/discovery.js +73 -23
  106. package/dist/composition/discovery.js.map +1 -1
  107. package/dist/composition/expr-eval.d.ts +1 -1
  108. package/dist/composition/expr-eval.d.ts.map +1 -1
  109. package/dist/composition/expr-eval.js +4 -4
  110. package/dist/composition/expr-eval.js.map +1 -1
  111. package/dist/composition/expr-simplify.d.ts +10 -14
  112. package/dist/composition/expr-simplify.d.ts.map +1 -1
  113. package/dist/composition/expr-simplify.js +49 -52
  114. package/dist/composition/expr-simplify.js.map +1 -1
  115. package/dist/composition/grounding.d.ts.map +1 -1
  116. package/dist/composition/grounding.js +19 -7
  117. package/dist/composition/grounding.js.map +1 -1
  118. package/dist/composition/mathts-quiet.d.ts +4 -6
  119. package/dist/composition/mathts-quiet.d.ts.map +1 -1
  120. package/dist/composition/mathts-quiet.js +4 -14
  121. package/dist/composition/mathts-quiet.js.map +1 -1
  122. package/dist/composition/own-equation-magnitude.d.ts +95 -0
  123. package/dist/composition/own-equation-magnitude.d.ts.map +1 -0
  124. package/dist/composition/own-equation-magnitude.js +270 -0
  125. package/dist/composition/own-equation-magnitude.js.map +1 -0
  126. package/dist/composition/probe/backend-protocol.d.ts +3 -0
  127. package/dist/composition/probe/backend-protocol.d.ts.map +1 -1
  128. package/dist/composition/probe/backend-protocol.js.map +1 -1
  129. package/dist/composition/probe/candidate-store.d.ts +1 -0
  130. package/dist/composition/probe/candidate-store.d.ts.map +1 -1
  131. package/dist/composition/probe/candidate-store.js +1 -0
  132. package/dist/composition/probe/candidate-store.js.map +1 -1
  133. package/dist/composition/probe/corpus.d.ts +4 -2
  134. package/dist/composition/probe/corpus.d.ts.map +1 -1
  135. package/dist/composition/probe/corpus.js +3 -3
  136. package/dist/composition/probe/corpus.js.map +1 -1
  137. package/dist/composition/probe/dataset.d.ts +1 -0
  138. package/dist/composition/probe/dataset.d.ts.map +1 -1
  139. package/dist/composition/probe/dataset.js.map +1 -1
  140. package/dist/composition/probe/experiment-design.d.ts +2 -0
  141. package/dist/composition/probe/experiment-design.d.ts.map +1 -1
  142. package/dist/composition/probe/experiment-design.js.map +1 -1
  143. package/dist/composition/probe/falsify.d.ts +2 -0
  144. package/dist/composition/probe/falsify.d.ts.map +1 -1
  145. package/dist/composition/probe/falsify.js.map +1 -1
  146. package/dist/composition/probe/fit.d.ts +1 -0
  147. package/dist/composition/probe/fit.d.ts.map +1 -1
  148. package/dist/composition/probe/fit.js.map +1 -1
  149. package/dist/composition/probe/generator.d.ts +3 -0
  150. package/dist/composition/probe/generator.d.ts.map +1 -1
  151. package/dist/composition/probe/generator.js +5 -6
  152. package/dist/composition/probe/generator.js.map +1 -1
  153. package/dist/composition/probe/limits.d.ts +1 -0
  154. package/dist/composition/probe/limits.d.ts.map +1 -1
  155. package/dist/composition/probe/limits.js.map +1 -1
  156. package/dist/composition/probe/pipeline.d.ts +5 -0
  157. package/dist/composition/probe/pipeline.d.ts.map +1 -1
  158. package/dist/composition/probe/pipeline.js +64 -21
  159. package/dist/composition/probe/pipeline.js.map +1 -1
  160. package/dist/composition/probe/power-law.d.ts.map +1 -1
  161. package/dist/composition/probe/power-law.js +3 -7
  162. package/dist/composition/probe/power-law.js.map +1 -1
  163. package/dist/composition/probe/problem.d.ts +1 -0
  164. package/dist/composition/probe/problem.d.ts.map +1 -1
  165. package/dist/composition/probe/problem.js.map +1 -1
  166. package/dist/composition/probe/residual.d.ts +1 -0
  167. package/dist/composition/probe/residual.d.ts.map +1 -1
  168. package/dist/composition/probe/residual.js +1 -0
  169. package/dist/composition/probe/residual.js.map +1 -1
  170. package/dist/composition/probe/run-manifest.d.ts +1 -0
  171. package/dist/composition/probe/run-manifest.d.ts.map +1 -1
  172. package/dist/composition/probe/run-manifest.js.map +1 -1
  173. package/dist/composition/probe/scalar-search.d.ts +50 -0
  174. package/dist/composition/probe/scalar-search.d.ts.map +1 -0
  175. package/dist/composition/probe/scalar-search.js +169 -0
  176. package/dist/composition/probe/scalar-search.js.map +1 -0
  177. package/dist/composition/probe/scoring.d.ts +1 -0
  178. package/dist/composition/probe/scoring.d.ts.map +1 -1
  179. package/dist/composition/probe/scoring.js.map +1 -1
  180. package/dist/composition/probe/study.d.ts +2 -2
  181. package/dist/composition/probe/study.d.ts.map +1 -1
  182. package/dist/composition/probe/study.js +6 -10
  183. package/dist/composition/probe/study.js.map +1 -1
  184. package/dist/composition/probe/t-tail.d.ts +3 -4
  185. package/dist/composition/probe/t-tail.d.ts.map +1 -1
  186. package/dist/composition/probe/t-tail.js +7 -10
  187. package/dist/composition/probe/t-tail.js.map +1 -1
  188. package/dist/composition/proposed-bridges.d.ts +11 -2
  189. package/dist/composition/proposed-bridges.d.ts.map +1 -1
  190. package/dist/composition/proposed-bridges.js +7 -5
  191. package/dist/composition/proposed-bridges.js.map +1 -1
  192. package/dist/composition/rational-exponent.d.ts +2 -2
  193. package/dist/composition/rational-exponent.d.ts.map +1 -1
  194. package/dist/composition/rational-exponent.js +4 -4
  195. package/dist/composition/rational-exponent.js.map +1 -1
  196. package/dist/composition/representative-values.d.ts.map +1 -1
  197. package/dist/composition/representative-values.js +6 -0
  198. package/dist/composition/representative-values.js.map +1 -1
  199. package/dist/composition/retrodiction.d.ts +15 -0
  200. package/dist/composition/retrodiction.d.ts.map +1 -1
  201. package/dist/composition/retrodiction.js +10 -3
  202. package/dist/composition/retrodiction.js.map +1 -1
  203. package/dist/composition/user-equation.d.ts +1 -0
  204. package/dist/composition/user-equation.d.ts.map +1 -1
  205. package/dist/composition/user-equation.js +1 -0
  206. package/dist/composition/user-equation.js.map +1 -1
  207. package/dist/core/constants.d.ts +12 -11
  208. package/dist/core/constants.d.ts.map +1 -1
  209. package/dist/core/constants.js +24 -21
  210. package/dist/core/constants.js.map +1 -1
  211. package/dist/diff/bridge-ast-gradient.d.ts +27 -23
  212. package/dist/diff/bridge-ast-gradient.d.ts.map +1 -1
  213. package/dist/diff/bridge-ast-gradient.js +75 -173
  214. package/dist/diff/bridge-ast-gradient.js.map +1 -1
  215. package/dist/dimensional/ast-types.d.ts +15 -0
  216. package/dist/dimensional/ast-types.d.ts.map +1 -1
  217. package/dist/dimensional/ast-types.js.map +1 -1
  218. package/dist/dimensional/curvature-composite.d.ts +1 -1
  219. package/dist/dimensional/curvature-composite.js.map +1 -1
  220. package/dist/dimensional/exact-scale.d.ts +41 -11
  221. package/dist/dimensional/exact-scale.d.ts.map +1 -1
  222. package/dist/dimensional/exact-scale.js +115 -123
  223. package/dist/dimensional/exact-scale.js.map +1 -1
  224. package/dist/dimensional/mathts-unit-delegation.d.ts +29 -0
  225. package/dist/dimensional/mathts-unit-delegation.d.ts.map +1 -0
  226. package/dist/dimensional/mathts-unit-delegation.js +187 -0
  227. package/dist/dimensional/mathts-unit-delegation.js.map +1 -0
  228. package/dist/dimensional/mathts-unit-wrapper.d.ts +33 -0
  229. package/dist/dimensional/mathts-unit-wrapper.d.ts.map +1 -0
  230. package/dist/dimensional/mathts-unit-wrapper.js +190 -0
  231. package/dist/dimensional/mathts-unit-wrapper.js.map +1 -0
  232. package/dist/dimensional/scalar-lowering.d.ts +21 -0
  233. package/dist/dimensional/scalar-lowering.d.ts.map +1 -0
  234. package/dist/dimensional/scalar-lowering.js +45 -0
  235. package/dist/dimensional/scalar-lowering.js.map +1 -0
  236. package/dist/dimensional/unit-data.d.ts +5 -1
  237. package/dist/dimensional/unit-data.d.ts.map +1 -1
  238. package/dist/dimensional/unit-data.js +28 -4
  239. package/dist/dimensional/unit-data.js.map +1 -1
  240. package/dist/dimensional/units.d.ts +2 -0
  241. package/dist/dimensional/units.d.ts.map +1 -1
  242. package/dist/dimensional/units.js +59 -3
  243. package/dist/dimensional/units.js.map +1 -1
  244. package/dist/dimensional/validator.d.ts +2 -0
  245. package/dist/dimensional/validator.d.ts.map +1 -1
  246. package/dist/dimensional/validator.js.map +1 -1
  247. package/dist/index.js.map +1 -1
  248. package/dist/numerical/connection-lowering-helpers.d.ts +3 -1
  249. package/dist/numerical/connection-lowering-helpers.d.ts.map +1 -1
  250. package/dist/numerical/connection-lowering-helpers.js +11 -15
  251. package/dist/numerical/connection-lowering-helpers.js.map +1 -1
  252. package/dist/numerical/pderiv.d.ts.map +1 -1
  253. package/dist/numerical/pderiv.js +2 -6
  254. package/dist/numerical/pderiv.js.map +1 -1
  255. package/dist/numerical/quadrature.js +3 -3
  256. package/dist/numerical/quadrature.js.map +1 -1
  257. package/dist/numerical/statistics.js +1 -1
  258. package/dist/numerical/statistics.js.map +1 -1
  259. package/dist/numerical/strides.d.ts +3 -2
  260. package/dist/numerical/strides.d.ts.map +1 -1
  261. package/dist/numerical/strides.js +3 -10
  262. package/dist/numerical/strides.js.map +1 -1
  263. package/package.json +9 -12
  264. package/dist/cases/brownian-sphere.d.ts +0 -68
  265. package/dist/cases/brownian-sphere.d.ts.map +0 -1
  266. package/dist/cases/brownian-sphere.js +0 -355
  267. package/dist/cases/brownian-sphere.js.map +0 -1
  268. package/dist/cases/damped-resonator.d.ts +0 -23
  269. package/dist/cases/damped-resonator.d.ts.map +0 -1
  270. package/dist/cases/damped-resonator.js +0 -221
  271. package/dist/cases/damped-resonator.js.map +0 -1
  272. package/dist/cases/kepler-rv.d.ts +0 -13
  273. package/dist/cases/kepler-rv.d.ts.map +0 -1
  274. package/dist/cases/kepler-rv.js +0 -173
  275. package/dist/cases/kepler-rv.js.map +0 -1
  276. package/dist/cases/lumped-cooling.d.ts +0 -51
  277. package/dist/cases/lumped-cooling.d.ts.map +0 -1
  278. package/dist/cases/lumped-cooling.js +0 -259
  279. package/dist/cases/lumped-cooling.js.map +0 -1
  280. package/dist/cases/resistor-noise.d.ts +0 -14
  281. package/dist/cases/resistor-noise.d.ts.map +0 -1
  282. package/dist/cases/resistor-noise.js +0 -215
  283. package/dist/cases/resistor-noise.js.map +0 -1
  284. package/dist/cases/skin-depth.d.ts +0 -17
  285. package/dist/cases/skin-depth.d.ts.map +0 -1
  286. package/dist/cases/skin-depth.js +0 -170
  287. package/dist/cases/skin-depth.js.map +0 -1
@@ -11,6 +11,7 @@
11
11
  *
12
12
  * @module numerical/connection-lowering-helpers
13
13
  */
14
+ import { Tensor } from '@danielsimonjr/mathts-tensor';
14
15
  import { NumericalBackendError } from './errors.js';
15
16
  import { rowMajorStrides as buildStrides, flatIndex, sameShape } from './strides.js';
16
17
  // ---------------------------------------------------------------------------
@@ -108,23 +109,18 @@ export function zeroTensor(shape, engine) {
108
109
  return engine.fromNested(buildNestedZeros([...shape]), [...shape]);
109
110
  }
110
111
  /**
111
- * Convert a flat number[] to a properly-nested NestedArray matching `shape`.
112
+ * Convert a flat number[] to a properly-nested NestedArray matching `shape`,
113
+ * in row-major order, through MathTS `new Tensor(shape, data).toNested()`.
112
114
  * Exported for use in lowering.ts where the engine requires nested structure.
115
+ * @throws NumericalBackendError when the data length is not the product of the shape.
113
116
  */
114
117
  export function flatToNested(flat, shape) {
115
- return flatToNestedImpl(flat, shape);
116
- }
117
- function flatToNestedImpl(flat, shape) {
118
- if (shape.length === 0)
119
- return flat[0] ?? 0;
120
- if (shape.length === 1)
121
- return flat.slice();
122
- const stride = flat.length / shape[0];
123
- const result = [];
124
- for (let i = 0; i < shape[0]; i++) {
125
- result.push(flatToNestedImpl(flat.slice(i * stride, (i + 1) * stride), shape.slice(1)));
118
+ try {
119
+ return new Tensor([...shape], Float64Array.from(flat)).toNested();
120
+ }
121
+ catch (e) {
122
+ throw new NumericalBackendError(`flatToNested: ${e.message}`);
126
123
  }
127
- return result;
128
124
  }
129
125
  /**
130
126
  * Elementwise a + b; throws on shape mismatch.
@@ -204,7 +200,7 @@ export function computeChristoffelTensor(gInverseFlat, getMetricDeriv, N, engine
204
200
  }
205
201
  }
206
202
  }
207
- return engine.fromNested(flatToNestedImpl(Gamma, [N, N, N]), [N, N, N]);
203
+ return engine.fromNested(flatToNested(Gamma, [N, N, N]), [N, N, N]);
208
204
  }
209
205
  // ---------------------------------------------------------------------------
210
206
  // Contraction of Γ with the operand tensor
@@ -312,7 +308,7 @@ export function contractChristoffelWithOperand(GammaFlat, ofFlat, ofShape, freeI
312
308
  outIdx[k] = 0;
313
309
  }
314
310
  }
315
- return engine.fromNested(flatToNestedImpl(out, outShape), outShape);
311
+ return engine.fromNested(flatToNested(out, outShape), outShape);
316
312
  }
317
313
  // ---------------------------------------------------------------------------
318
314
  // Metric-partial-derivative lookup (for 'supplied' strategy)
@@ -1 +1 @@
1
- {"version":3,"file":"connection-lowering-helpers.js","sourceRoot":"","sources":["../../src/numerical/connection-lowering-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Numerical helpers for covariant-derivative lowering (Task 12 [U]).\n *\n * These functions compute Christoffel symbols and tensor corrections from raw\n * metric data WITHOUT going through the christoffel() composite AST. The\n * composite AST is designed for symbolic/dimensional use; numerical lowering\n * builds Γ directly from metric components and metric-derivative arrays.\n *\n * All helpers are engine-agnostic: they operate on flat number[] arrays and\n * produce EngineTensor results via the engine.fromNested() interface.\n *\n * @module numerical/connection-lowering-helpers\n */\n\nimport type { EngineTensor, TensorEngine } from './tensor-engine.js';\nimport type { NestedArray } from './types.js';\nimport { NumericalBackendError } from './errors.js';\nimport { rowMajorStrides as buildStrides, flatIndex, sameShape } from './strides.js';\n\n// ---------------------------------------------------------------------------\n// Flat-array utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Flatten a NestedArray to a plain number[] in row-major order.\n * Canonical implementation for this module. `flattenNestedArray` in\n * lowering.ts wraps this and adds an expectedSize invariant check.\n * `pderiv.ts` previously had its own identical `flattenToNumbers` —\n * consolidated to this function in v0.4.6 (see Task 9 of the v0.4.6 plan).\n */\nexport function flattenNA(data: NestedArray): number[] {\n if (typeof data === 'number') return [data];\n\n // Fast path for 1D arrays (vectors)\n if (data.length > 0 && typeof data[0] === 'number') {\n const len = data.length;\n const out = new Array(len);\n for (let i = 0; i < len; i++) {\n out[i] = data[i] as number;\n }\n return out;\n }\n\n // Fast path for 2D arrays (matrices)\n if (data.length > 0 && Array.isArray(data[0]) && data[0].length > 0 && typeof data[0][0] === 'number') {\n const rows = data.length;\n const cols = (data[0] as NestedArray[]).length;\n const out = new Array(rows * cols);\n let idx = 0;\n for (let i = 0; i < rows; i++) {\n const row = data[i] as NestedArray[];\n for (let j = 0; j < cols; j++) {\n out[idx++] = row[j] as number;\n }\n }\n return out;\n }\n\n // Explicit stack based non-recursive approach\n // We avoid the `for...of` overhead and function call overhead of recursion.\n const out: number[] = [];\n const stack: NestedArray[] = [data];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (typeof current === 'number') {\n out.push(current);\n } else {\n const len = current.length;\n // Push in reverse order to maintain left-to-right output order when popping\n for (let i = len - 1; i >= 0; i--) {\n stack.push(current[i]);\n }\n }\n }\n\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// S2(c) helpers — specified by the Task 12 plan\n// ---------------------------------------------------------------------------\n\n/**\n * Build a properly-nested zero array matching the given shape.\n * engine.fromNested() expects nested arrays, not flat arrays, for rank > 1.\n */\nfunction buildNestedZeros(shape: ReadonlyArray<number>): NestedArray {\n if (shape.length === 0) return 0;\n if (shape.length === 1) return new Array<number>(shape[0]).fill(0);\n const inner = buildNestedZeros(shape.slice(1));\n // Deep-clone each inner node so they are independent arrays.\n const cloneNested = (n: NestedArray): NestedArray => {\n if (typeof n === 'number') return n;\n return (n as NestedArray[]).map(cloneNested);\n };\n const len = shape[0];\n const out = new Array(len);\n for (let i = 0; i < len; i++) out[i] = cloneNested(inner);\n return out;\n}\n\n/**\n * Return a same-shape EngineTensor whose data is all zeros.\n * S2(c) helper spec: returns a fresh zero tensor of the same shape as t.\n */\nexport function zeroTensorLike(t: EngineTensor, engine: TensorEngine): EngineTensor {\n const shape = [...t.shape];\n return engine.fromNested(buildNestedZeros(shape), shape);\n}\n\n/**\n * Return an all-zero EngineTensor of the given shape.\n */\nexport function zeroTensor(shape: ReadonlyArray<number>, engine: TensorEngine): EngineTensor {\n return engine.fromNested(buildNestedZeros([...shape]), [...shape]);\n}\n\n/**\n * Convert a flat number[] to a properly-nested NestedArray matching `shape`.\n * Exported for use in lowering.ts where the engine requires nested structure.\n */\nexport function flatToNested(flat: number[], shape: ReadonlyArray<number>): NestedArray {\n return flatToNestedImpl(flat, shape);\n}\n\nfunction flatToNestedImpl(flat: number[], shape: ReadonlyArray<number>): NestedArray {\n if (shape.length === 0) return flat[0] ?? 0;\n if (shape.length === 1) return flat.slice();\n const stride = flat.length / shape[0];\n const result: NestedArray[] = [];\n for (let i = 0; i < shape[0]; i++) {\n result.push(flatToNestedImpl(flat.slice(i * stride, (i + 1) * stride), shape.slice(1)));\n }\n return result;\n}\n\n/**\n * Elementwise a + b; throws on shape mismatch.\n * S2(c) helper spec.\n */\nexport function tensorAdd(a: EngineTensor, b: EngineTensor, engine: TensorEngine): EngineTensor {\n if (!sameShape(a.shape, b.shape)) {\n throw new NumericalBackendError(\n `tensorAdd: shape mismatch [${a.shape}] vs [${b.shape}]`,\n );\n }\n return engine.add(a, b);\n}\n\n/**\n * Elementwise a[i] + sign * b[i]; throws on shape mismatch.\n * S2(c) helper spec.\n */\nexport function tensorAddScaled(\n a: EngineTensor,\n b: EngineTensor,\n sign: 1 | -1,\n engine: TensorEngine,\n): EngineTensor {\n if (!sameShape(a.shape, b.shape)) {\n throw new NumericalBackendError(\n `tensorAddScaled: shape mismatch [${a.shape}] vs [${b.shape}]`,\n );\n }\n if (sign === 1) return engine.add(a, b);\n return engine.sub(a, b);\n}\n\n// ---------------------------------------------------------------------------\n// Christoffel numerical computation\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the full Christoffel symbol Γ^α_{μν} from raw metric arrays.\n *\n * Γ^α_{μν} = (1/2) g^{αρ} (∂_μ g_{ρν} + ∂_ν g_{ρμ} − ∂_ρ g_{μν})\n *\n * Returns an EngineTensor of shape [N, N, N] indexed [α][μ][ν] (row-major).\n *\n * @param gInverseFlat Flat [N*N] array for g^{αρ} (row-major, α outer)\n * @param getMetricDeriv Function (mu: number) => flat [N*N] ∂_{mu} g (row-major)\n * @param N Dimension\n * @param engine Active TensorEngine\n */\nexport function computeChristoffelTensor(\n gInverseFlat: number[],\n getMetricDeriv: (mu: number) => number[],\n N: number,\n engine: TensorEngine,\n): EngineTensor {\n // Output: Gamma[alpha][mu][nu] stored in row-major order\n const size = N * N * N;\n const Gamma = new Array<number>(size).fill(0);\n\n // Precompute all N metric derivative arrays before the triple loop.\n // For strategy='supplied', getMetricDeriv calls flattenNA on the stored NestedArray\n // each invocation. Precomputing reduces calls from O(N^2 + N^2 + N^3) to N.\n // Per Step 1 verification: getMetricDeriv (backed by getMetricDerivFlat) returns\n // FRESH arrays on every call — 'zero' branch uses new Array().fill(0) and 'supplied'\n // branch calls flattenNA() which allocates a new number[] each time. No cached\n // references exist, so shallow-cloning is NOT required.\n const dMetric: number[][] = new Array(N);\n for (let mu = 0; mu < N; mu++) dMetric[mu] = getMetricDeriv(mu);\n\n for (let alpha = 0; alpha < N; alpha++) {\n const alpha_N = alpha * N;\n const alpha_N_N = alpha_N * N;\n for (let mu = 0; mu < N; mu++) {\n const mu_N = mu * N;\n const dmu = dMetric[mu]; // ∂_μ g_{ρν} — shape [N,N], ρ outer\n for (let nu = 0; nu < N; nu++) {\n let sum = 0;\n const dnu = dMetric[nu]; // ∂_ν g_{ρμ}\n for (let rho = 0; rho < N; rho++) {\n const gInvAlphaRho = gInverseFlat[alpha_N + rho]; // g^{α ρ}\n if (gInvAlphaRho !== 0) {\n const drho = dMetric[rho]; // ∂_ρ g_{μν}\n const rho_N = rho * N;\n // ∂_μ g_{ρν} → index [ρ,ν] in flat ∂_μ g\n const term1 = dmu[rho_N + nu];\n // ∂_ν g_{ρμ} → index [ρ,μ] in flat ∂_ν g\n const term2 = dnu[rho_N + mu];\n // ∂_ρ g_{μν} → index [μ,ν] in flat ∂_ρ g\n const term3 = drho[mu_N + nu];\n sum += gInvAlphaRho * (term1 + term2 - term3);\n }\n }\n Gamma[alpha_N_N + mu_N + nu] = 0.5 * sum;\n }\n }\n }\n\n return engine.fromNested(flatToNestedImpl(Gamma, [N, N, N]), [N, N, N]);\n}\n\n// ---------------------------------------------------------------------------\n// Contraction of Γ with the operand tensor\n// ---------------------------------------------------------------------------\n\n/**\n * Contract Γ^α_{μλ} or Γ^λ_{μα} with the operand tensor along the axis\n * corresponding to `freeIdxPos` (the position of the contracted free index\n * in the operand's flat axis list).\n *\n * S2(c) spec — explicit loop body:\n *\n * Upper case (∇_μ T^α_β):\n * out[α, μ, β, ...] += Γ[α, μ, λ] * T[λ_at_pos, β, ...]\n * i.e., contract over λ (axis `freeIdxPos` of T, axis 2 of Γ)\n *\n * Lower case (∇_μ T_α_β):\n * out[α, μ, β, ...] += Γ[λ, μ, α] * T[λ_at_pos, β, ...]\n * i.e., contract over λ (axis `freeIdxPos` of T, axis 0 of Γ)\n * and α indexes the fixed axis of Γ at position 2.\n *\n * Shape conventions (all row-major):\n * Gamma: shape [N, N, N] — [α or λ, μ, ν or α]\n * ofFlat: flat [totalSize] with strides computed from `ofShape`\n * outputShape: same as the partial-derivative output: [N, ...ofShape]\n * (wrt axis prepended, the freeIdxPos axis contracted out,\n * all other axes kept — but since ∇_μ output equals ∂_μ output shape,\n * we match that shape exactly)\n *\n * @param GammaFlat Flat [N^3] Γ^α_{μν} — [α][μ][ν] row-major\n * @param ofFlat Flat operand data, shape `ofShape`\n * @param ofShape Shape of the operand tensor\n * @param freeIdxPos Position (0-based) of the free index being contracted in `ofShape`\n * @param variance 'upper' → Γ^α_{μλ} contracts λ; 'lower' → Γ^λ_{μα} contracts λ\n * @param N Dimension\n * @param engine Active TensorEngine\n *\n * Returns an EngineTensor of shape [N, ...ofShape_without_freeIdxPos]\n * i.e., the same shape as the partial-derivative output (wrt axis first, others follow).\n */\nexport function contractChristoffelWithOperand(\n GammaFlat: number[],\n ofFlat: number[],\n ofShape: ReadonlyArray<number>,\n freeIdxPos: number,\n variance: 'upper' | 'lower',\n N: number,\n engine: TensorEngine,\n): EngineTensor {\n // Output shape: [N (wrt/mu axis), ...ofShape with freeIdxPos axis removed and\n // replaced by the alpha axis of the Christoffel]\n // Concretely: output has the same shape as ∂_μ T which is [...ofShape, N]\n // with wrtIndex appended. But freeIdx is now contracted (replaced by α):\n // upper: T had axis freeIdxPos as α (upper) → output keeps α at same position, prepends μ\n // lower: T had axis freeIdxPos as α (lower) → output keeps α at same position, prepends μ\n //\n // The output axis order matches ∂_μ T: [...ofShape, N] (wrt axis last? or first?)\n // Actually ∂_μ appends wrt as the LAST axis per v0.3.5 design.\n // So output shape of ∇_μ T = [...ofShape, N] where N is the wrt axis.\n // But the correction term must have the same shape.\n //\n // For the correction: we keep all of T's axes, with freeIdxPos contracting,\n // and add a new μ axis (last, like ∂_μ). The α index replaces the contracted\n // position (same position in the output as freeIdxPos was in T).\n //\n // Output shape = [...ofShape, N] where ofShape[freeIdxPos] stays (α replaces λ)\n // and the last axis N is the μ axis.\n\n const rank = ofShape.length;\n const outShape = [...ofShape, N]; // [...T_shape, mu]\n const outSize = outShape.reduce((a, b) => a * b, 1);\n const out = new Array<number>(outSize).fill(0);\n\n // Build strides for ofFlat and out\n const ofStrides = buildStrides(ofShape);\n const outStrides = buildStrides(outShape);\n\n // Iterate over all output indices\n const outIdx = new Array<number>(outShape.length).fill(0);\n const tIdxBase = new Array<number>(rank).fill(0);\n\n for (let n = 0; n < outSize; n++) {\n const mu = outIdx[rank]; // last axis of output is μ\n // The other axes map to T's indices, with freeIdxPos being the α/result axis\n const alpha = outIdx[freeIdxPos]; // the \"free\" index value (α for upper, α for lower)\n\n let sum = 0;\n\n // Map back to tIdxBase\n for (let k = 0; k < rank; k++) {\n tIdxBase[k] = outIdx[k];\n }\n tIdxBase[freeIdxPos] = 0;\n let tFlat = flatIndex(tIdxBase, ofStrides);\n const tStride = ofStrides[freeIdxPos];\n\n const alpha_N_N = alpha * N * N;\n const mu_N = mu * N;\n const mu_N_alpha = mu_N + alpha;\n\n for (let lam = 0; lam < N; lam++) {\n let gammaFlat: number;\n if (variance === 'upper') {\n // Γ^α_{μλ} — shape [α][μ][λ]\n gammaFlat = alpha_N_N + mu_N + lam;\n } else {\n // Γ^λ_{μα} — shape [λ][μ][α]\n gammaFlat = lam * N * N + mu_N_alpha;\n }\n\n const gVal = GammaFlat[gammaFlat];\n if (gVal !== 0) {\n sum += gVal * ofFlat[tFlat];\n }\n tFlat += tStride;\n }\n\n out[n] = sum;\n\n // Increment multi-index odometer\n for (let k = outShape.length - 1; k >= 0; k--) {\n if (++outIdx[k] < outShape[k]) break;\n outIdx[k] = 0;\n }\n }\n\n return engine.fromNested(flatToNestedImpl(out, outShape), outShape);\n}\n\n// ---------------------------------------------------------------------------\n// Metric-partial-derivative lookup (for 'supplied' strategy)\n// ---------------------------------------------------------------------------\n\n/**\n * Look up ∂_{mu} g from inputs.metricDerivatives.\n * Key format: `${metricName}/${coordLabel}_${mu}` (e.g. 'g/x_0' where\n * 'x' is the coordLabel string and '0' is the mu index). The coordLabel\n * is whatever string the caller passes — typically a coordinate label\n * like 'x', 't', 'r'; the literal Greek letter μ is NOT used as a key.\n * Returns a flat [N*N] array.\n *\n * Strategy 'zero': returns [N*N] zeros.\n * Strategy 'supplied': looks up the key; throws if absent.\n */\nexport function getMetricDerivFlat(\n metricName: string,\n coordLabel: string,\n mu: number,\n strategy: 'zero' | 'supplied',\n N: number,\n metricDerivatives: ReadonlyMap<string, NestedArray> | undefined,\n): number[] {\n if (strategy === 'zero') {\n return new Array<number>(N * N).fill(0);\n }\n // strategy === 'supplied'\n const key = `${metricName}/${coordLabel}_${mu}`;\n const d = metricDerivatives?.get(key);\n if (d === undefined) {\n throw new NumericalBackendError(\n `connection-lowering: no metric derivative supplied for \"${key}\" — ` +\n `a covariant-derivative with derivativeStrategy='supplied' requires ` +\n `inputs.metricDerivatives to contain \"${key}\" (flat [N×N] of ∂_{${mu}} g)`,\n );\n }\n const flat = flattenNA(d);\n if (flat.length !== N * N) {\n throw new NumericalBackendError(\n `connection-lowering: metricDerivatives[\"${key}\"] has ${flat.length} elements, ` +\n `expected ${N * N} (N=${N})`,\n );\n }\n return flat;\n}\n"]}
1
+ {"version":3,"file":"connection-lowering-helpers.js","sourceRoot":"","sources":["../../src/numerical/connection-lowering-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Numerical helpers for covariant-derivative lowering (Task 12 [U]).\n *\n * These functions compute Christoffel symbols and tensor corrections from raw\n * metric data WITHOUT going through the christoffel() composite AST. The\n * composite AST is designed for symbolic/dimensional use; numerical lowering\n * builds Γ directly from metric components and metric-derivative arrays.\n *\n * All helpers are engine-agnostic: they operate on flat number[] arrays and\n * produce EngineTensor results via the engine.fromNested() interface.\n *\n * @module numerical/connection-lowering-helpers\n */\n\nimport { Tensor } from '@danielsimonjr/mathts-tensor';\nimport type { EngineTensor, TensorEngine } from './tensor-engine.js';\nimport type { NestedArray } from './types.js';\nimport { NumericalBackendError } from './errors.js';\nimport { rowMajorStrides as buildStrides, flatIndex, sameShape } from './strides.js';\n\n// ---------------------------------------------------------------------------\n// Flat-array utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Flatten a NestedArray to a plain number[] in row-major order.\n * Canonical implementation for this module. `flattenNestedArray` in\n * lowering.ts wraps this and adds an expectedSize invariant check.\n * `pderiv.ts` previously had its own identical `flattenToNumbers` —\n * consolidated to this function in v0.4.6 (see Task 9 of the v0.4.6 plan).\n */\nexport function flattenNA(data: NestedArray): number[] {\n if (typeof data === 'number') return [data];\n\n // Fast path for 1D arrays (vectors)\n if (data.length > 0 && typeof data[0] === 'number') {\n const len = data.length;\n const out = new Array(len);\n for (let i = 0; i < len; i++) {\n out[i] = data[i] as number;\n }\n return out;\n }\n\n // Fast path for 2D arrays (matrices)\n if (data.length > 0 && Array.isArray(data[0]) && data[0].length > 0 && typeof data[0][0] === 'number') {\n const rows = data.length;\n const cols = (data[0] as NestedArray[]).length;\n const out = new Array(rows * cols);\n let idx = 0;\n for (let i = 0; i < rows; i++) {\n const row = data[i] as NestedArray[];\n for (let j = 0; j < cols; j++) {\n out[idx++] = row[j] as number;\n }\n }\n return out;\n }\n\n // Explicit stack based non-recursive approach\n // We avoid the `for...of` overhead and function call overhead of recursion.\n const out: number[] = [];\n const stack: NestedArray[] = [data];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (typeof current === 'number') {\n out.push(current);\n } else {\n const len = current.length;\n // Push in reverse order to maintain left-to-right output order when popping\n for (let i = len - 1; i >= 0; i--) {\n stack.push(current[i]);\n }\n }\n }\n\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// S2(c) helpers — specified by the Task 12 plan\n// ---------------------------------------------------------------------------\n\n/**\n * Build a properly-nested zero array matching the given shape.\n * engine.fromNested() expects nested arrays, not flat arrays, for rank > 1.\n */\nfunction buildNestedZeros(shape: ReadonlyArray<number>): NestedArray {\n if (shape.length === 0) return 0;\n if (shape.length === 1) return new Array<number>(shape[0]).fill(0);\n const inner = buildNestedZeros(shape.slice(1));\n // Deep-clone each inner node so they are independent arrays.\n const cloneNested = (n: NestedArray): NestedArray => {\n if (typeof n === 'number') return n;\n return (n as NestedArray[]).map(cloneNested);\n };\n const len = shape[0];\n const out = new Array(len);\n for (let i = 0; i < len; i++) out[i] = cloneNested(inner);\n return out;\n}\n\n/**\n * Return a same-shape EngineTensor whose data is all zeros.\n * S2(c) helper spec: returns a fresh zero tensor of the same shape as t.\n */\nexport function zeroTensorLike(t: EngineTensor, engine: TensorEngine): EngineTensor {\n const shape = [...t.shape];\n return engine.fromNested(buildNestedZeros(shape), shape);\n}\n\n/**\n * Return an all-zero EngineTensor of the given shape.\n */\nexport function zeroTensor(shape: ReadonlyArray<number>, engine: TensorEngine): EngineTensor {\n return engine.fromNested(buildNestedZeros([...shape]), [...shape]);\n}\n\n/**\n * Convert a flat number[] to a properly-nested NestedArray matching `shape`,\n * in row-major order, through MathTS `new Tensor(shape, data).toNested()`.\n * Exported for use in lowering.ts where the engine requires nested structure.\n * @throws NumericalBackendError when the data length is not the product of the shape.\n */\nexport function flatToNested(flat: number[], shape: ReadonlyArray<number>): NestedArray {\n try {\n return new Tensor([...shape], Float64Array.from(flat)).toNested() as NestedArray;\n } catch (e) {\n throw new NumericalBackendError(`flatToNested: ${(e as Error).message}`);\n }\n}\n\n/**\n * Elementwise a + b; throws on shape mismatch.\n * S2(c) helper spec.\n */\nexport function tensorAdd(a: EngineTensor, b: EngineTensor, engine: TensorEngine): EngineTensor {\n if (!sameShape(a.shape, b.shape)) {\n throw new NumericalBackendError(\n `tensorAdd: shape mismatch [${a.shape}] vs [${b.shape}]`,\n );\n }\n return engine.add(a, b);\n}\n\n/**\n * Elementwise a[i] + sign * b[i]; throws on shape mismatch.\n * S2(c) helper spec.\n */\nexport function tensorAddScaled(\n a: EngineTensor,\n b: EngineTensor,\n sign: 1 | -1,\n engine: TensorEngine,\n): EngineTensor {\n if (!sameShape(a.shape, b.shape)) {\n throw new NumericalBackendError(\n `tensorAddScaled: shape mismatch [${a.shape}] vs [${b.shape}]`,\n );\n }\n if (sign === 1) return engine.add(a, b);\n return engine.sub(a, b);\n}\n\n// ---------------------------------------------------------------------------\n// Christoffel numerical computation\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the full Christoffel symbol Γ^α_{μν} from raw metric arrays.\n *\n * Γ^α_{μν} = (1/2) g^{αρ} (∂_μ g_{ρν} + ∂_ν g_{ρμ} − ∂_ρ g_{μν})\n *\n * Returns an EngineTensor of shape [N, N, N] indexed [α][μ][ν] (row-major).\n *\n * @param gInverseFlat Flat [N*N] array for g^{αρ} (row-major, α outer)\n * @param getMetricDeriv Function (mu: number) => flat [N*N] ∂_{mu} g (row-major)\n * @param N Dimension\n * @param engine Active TensorEngine\n */\nexport function computeChristoffelTensor(\n gInverseFlat: number[],\n getMetricDeriv: (mu: number) => number[],\n N: number,\n engine: TensorEngine,\n): EngineTensor {\n // Output: Gamma[alpha][mu][nu] stored in row-major order\n const size = N * N * N;\n const Gamma = new Array<number>(size).fill(0);\n\n // Precompute all N metric derivative arrays before the triple loop.\n // For strategy='supplied', getMetricDeriv calls flattenNA on the stored NestedArray\n // each invocation. Precomputing reduces calls from O(N^2 + N^2 + N^3) to N.\n // Per Step 1 verification: getMetricDeriv (backed by getMetricDerivFlat) returns\n // FRESH arrays on every call — 'zero' branch uses new Array().fill(0) and 'supplied'\n // branch calls flattenNA() which allocates a new number[] each time. No cached\n // references exist, so shallow-cloning is NOT required.\n const dMetric: number[][] = new Array(N);\n for (let mu = 0; mu < N; mu++) dMetric[mu] = getMetricDeriv(mu);\n\n for (let alpha = 0; alpha < N; alpha++) {\n const alpha_N = alpha * N;\n const alpha_N_N = alpha_N * N;\n for (let mu = 0; mu < N; mu++) {\n const mu_N = mu * N;\n const dmu = dMetric[mu]; // ∂_μ g_{ρν} — shape [N,N], ρ outer\n for (let nu = 0; nu < N; nu++) {\n let sum = 0;\n const dnu = dMetric[nu]; // ∂_ν g_{ρμ}\n for (let rho = 0; rho < N; rho++) {\n const gInvAlphaRho = gInverseFlat[alpha_N + rho]; // g^{α ρ}\n if (gInvAlphaRho !== 0) {\n const drho = dMetric[rho]; // ∂_ρ g_{μν}\n const rho_N = rho * N;\n // ∂_μ g_{ρν} → index [ρ,ν] in flat ∂_μ g\n const term1 = dmu[rho_N + nu];\n // ∂_ν g_{ρμ} → index [ρ,μ] in flat ∂_ν g\n const term2 = dnu[rho_N + mu];\n // ∂_ρ g_{μν} → index [μ,ν] in flat ∂_ρ g\n const term3 = drho[mu_N + nu];\n sum += gInvAlphaRho * (term1 + term2 - term3);\n }\n }\n Gamma[alpha_N_N + mu_N + nu] = 0.5 * sum;\n }\n }\n }\n\n return engine.fromNested(flatToNested(Gamma, [N, N, N]), [N, N, N]);\n}\n\n// ---------------------------------------------------------------------------\n// Contraction of Γ with the operand tensor\n// ---------------------------------------------------------------------------\n\n/**\n * Contract Γ^α_{μλ} or Γ^λ_{μα} with the operand tensor along the axis\n * corresponding to `freeIdxPos` (the position of the contracted free index\n * in the operand's flat axis list).\n *\n * S2(c) spec — explicit loop body:\n *\n * Upper case (∇_μ T^α_β):\n * out[α, μ, β, ...] += Γ[α, μ, λ] * T[λ_at_pos, β, ...]\n * i.e., contract over λ (axis `freeIdxPos` of T, axis 2 of Γ)\n *\n * Lower case (∇_μ T_α_β):\n * out[α, μ, β, ...] += Γ[λ, μ, α] * T[λ_at_pos, β, ...]\n * i.e., contract over λ (axis `freeIdxPos` of T, axis 0 of Γ)\n * and α indexes the fixed axis of Γ at position 2.\n *\n * Shape conventions (all row-major):\n * Gamma: shape [N, N, N] — [α or λ, μ, ν or α]\n * ofFlat: flat [totalSize] with strides computed from `ofShape`\n * outputShape: same as the partial-derivative output: [N, ...ofShape]\n * (wrt axis prepended, the freeIdxPos axis contracted out,\n * all other axes kept — but since ∇_μ output equals ∂_μ output shape,\n * we match that shape exactly)\n *\n * @param GammaFlat Flat [N^3] Γ^α_{μν} — [α][μ][ν] row-major\n * @param ofFlat Flat operand data, shape `ofShape`\n * @param ofShape Shape of the operand tensor\n * @param freeIdxPos Position (0-based) of the free index being contracted in `ofShape`\n * @param variance 'upper' → Γ^α_{μλ} contracts λ; 'lower' → Γ^λ_{μα} contracts λ\n * @param N Dimension\n * @param engine Active TensorEngine\n *\n * Returns an EngineTensor of shape [N, ...ofShape_without_freeIdxPos]\n * i.e., the same shape as the partial-derivative output (wrt axis first, others follow).\n */\nexport function contractChristoffelWithOperand(\n GammaFlat: number[],\n ofFlat: number[],\n ofShape: ReadonlyArray<number>,\n freeIdxPos: number,\n variance: 'upper' | 'lower',\n N: number,\n engine: TensorEngine,\n): EngineTensor {\n // Output shape: [N (wrt/mu axis), ...ofShape with freeIdxPos axis removed and\n // replaced by the alpha axis of the Christoffel]\n // Concretely: output has the same shape as ∂_μ T which is [...ofShape, N]\n // with wrtIndex appended. But freeIdx is now contracted (replaced by α):\n // upper: T had axis freeIdxPos as α (upper) → output keeps α at same position, prepends μ\n // lower: T had axis freeIdxPos as α (lower) → output keeps α at same position, prepends μ\n //\n // The output axis order matches ∂_μ T: [...ofShape, N] (wrt axis last? or first?)\n // Actually ∂_μ appends wrt as the LAST axis per v0.3.5 design.\n // So output shape of ∇_μ T = [...ofShape, N] where N is the wrt axis.\n // But the correction term must have the same shape.\n //\n // For the correction: we keep all of T's axes, with freeIdxPos contracting,\n // and add a new μ axis (last, like ∂_μ). The α index replaces the contracted\n // position (same position in the output as freeIdxPos was in T).\n //\n // Output shape = [...ofShape, N] where ofShape[freeIdxPos] stays (α replaces λ)\n // and the last axis N is the μ axis.\n\n const rank = ofShape.length;\n const outShape = [...ofShape, N]; // [...T_shape, mu]\n const outSize = outShape.reduce((a, b) => a * b, 1);\n const out = new Array<number>(outSize).fill(0);\n\n // Build strides for ofFlat and out\n const ofStrides = buildStrides(ofShape);\n const outStrides = buildStrides(outShape);\n\n // Iterate over all output indices\n const outIdx = new Array<number>(outShape.length).fill(0);\n const tIdxBase = new Array<number>(rank).fill(0);\n\n for (let n = 0; n < outSize; n++) {\n const mu = outIdx[rank]; // last axis of output is μ\n // The other axes map to T's indices, with freeIdxPos being the α/result axis\n const alpha = outIdx[freeIdxPos]; // the \"free\" index value (α for upper, α for lower)\n\n let sum = 0;\n\n // Map back to tIdxBase\n for (let k = 0; k < rank; k++) {\n tIdxBase[k] = outIdx[k];\n }\n tIdxBase[freeIdxPos] = 0;\n let tFlat = flatIndex(tIdxBase, ofStrides);\n const tStride = ofStrides[freeIdxPos];\n\n const alpha_N_N = alpha * N * N;\n const mu_N = mu * N;\n const mu_N_alpha = mu_N + alpha;\n\n for (let lam = 0; lam < N; lam++) {\n let gammaFlat: number;\n if (variance === 'upper') {\n // Γ^α_{μλ} — shape [α][μ][λ]\n gammaFlat = alpha_N_N + mu_N + lam;\n } else {\n // Γ^λ_{μα} — shape [λ][μ][α]\n gammaFlat = lam * N * N + mu_N_alpha;\n }\n\n const gVal = GammaFlat[gammaFlat];\n if (gVal !== 0) {\n sum += gVal * ofFlat[tFlat];\n }\n tFlat += tStride;\n }\n\n out[n] = sum;\n\n // Increment multi-index odometer\n for (let k = outShape.length - 1; k >= 0; k--) {\n if (++outIdx[k] < outShape[k]) break;\n outIdx[k] = 0;\n }\n }\n\n return engine.fromNested(flatToNested(out, outShape), outShape);\n}\n\n// ---------------------------------------------------------------------------\n// Metric-partial-derivative lookup (for 'supplied' strategy)\n// ---------------------------------------------------------------------------\n\n/**\n * Look up ∂_{mu} g from inputs.metricDerivatives.\n * Key format: `${metricName}/${coordLabel}_${mu}` (e.g. 'g/x_0' where\n * 'x' is the coordLabel string and '0' is the mu index). The coordLabel\n * is whatever string the caller passes — typically a coordinate label\n * like 'x', 't', 'r'; the literal Greek letter μ is NOT used as a key.\n * Returns a flat [N*N] array.\n *\n * Strategy 'zero': returns [N*N] zeros.\n * Strategy 'supplied': looks up the key; throws if absent.\n */\nexport function getMetricDerivFlat(\n metricName: string,\n coordLabel: string,\n mu: number,\n strategy: 'zero' | 'supplied',\n N: number,\n metricDerivatives: ReadonlyMap<string, NestedArray> | undefined,\n): number[] {\n if (strategy === 'zero') {\n return new Array<number>(N * N).fill(0);\n }\n // strategy === 'supplied'\n const key = `${metricName}/${coordLabel}_${mu}`;\n const d = metricDerivatives?.get(key);\n if (d === undefined) {\n throw new NumericalBackendError(\n `connection-lowering: no metric derivative supplied for \"${key}\" — ` +\n `a covariant-derivative with derivativeStrategy='supplied' requires ` +\n `inputs.metricDerivatives to contain \"${key}\" (flat [N×N] of ∂_{${mu}} g)`,\n );\n }\n const flat = flattenNA(d);\n if (flat.length !== N * N) {\n throw new NumericalBackendError(\n `connection-lowering: metricDerivatives[\"${key}\"] has ${flat.length} elements, ` +\n `expected ${N * N} (N=${N})`,\n );\n }\n return flat;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"pderiv.d.ts","sourceRoot":"","sources":["../../src/numerical/pderiv.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiClE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,UAAU,aAAa;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACvB,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,WAAW,EAClD,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,aAAa,GACtB,WAAW,CAgEb;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAC5C,WAAW,CAWb;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAClD,WAAW,CAYb"}
1
+ {"version":3,"file":"pderiv.d.ts","sourceRoot":"","sources":["../../src/numerical/pderiv.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAK9C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BlE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,UAAU,aAAa;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACvB,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,WAAW,EAClD,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,aAAa,GACtB,WAAW,CAgEb;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAC5C,WAAW,CAWb;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAClD,WAAW,CAYb"}
@@ -1,5 +1,6 @@
1
1
  import { NumericalBackendError } from './errors.js';
2
2
  import { flattenNA } from './connection-lowering-helpers.js';
3
+ import { rowMajorStrides } from './strides.js';
3
4
  /**
4
5
  * Centered finite-difference of a GridField along `axis`. Returns a flat
5
6
  * number[] of the same total size as the grid. O(h²) interior stencil;
@@ -19,12 +20,7 @@ export function pderivGrid(grid, axis) {
19
20
  }
20
21
  const flat = flattenNA(grid.data);
21
22
  const shape = grid.shape;
22
- const strides = new Array(shape.length);
23
- let acc = 1;
24
- for (let k = shape.length - 1; k >= 0; k--) {
25
- strides[k] = acc;
26
- acc *= shape[k];
27
- }
23
+ const strides = rowMajorStrides(shape);
28
24
  const out = new Array(flat.length).fill(0);
29
25
  const n = shape[axis];
30
26
  const step = strides[axis];
@@ -1 +1 @@
1
- {"version":3,"file":"pderiv.js","sourceRoot":"","sources":["../../src/numerical/pderiv.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Numerical partial derivative — two-way dispatch (v0.3.5-Design.md §6).\n * 'grid' — centered finite-difference over a GridField.\n * 'numerical-fn' — centered finite-difference over a caller-supplied fn.\n * 'symbolic' — no CAS in v0.3.5; consumes an explicit pre-supplied\n * derivative from NumericalInputs.derivatives.\n *\n * @module numerical/pderiv\n */\nimport type { GridField } from './grid-field.js';\nimport type { NestedArray } from './types.js';\nimport { NumericalBackendError } from './errors.js';\nimport { flattenNA } from './connection-lowering-helpers.js';\n\n/**\n * Centered finite-difference of a GridField along `axis`. Returns a flat\n * number[] of the same total size as the grid. O(h²) interior stencil;\n * edges follow `grid.boundary`:\n * - 'clamp' — one-sided (forward/backward) difference at the edge.\n * - 'periodic' — wraps to the opposite edge.\n *\n * @internal — consumed by the lowering pass; not part of the consumer surface.\n */\nexport function pderivGrid(grid: GridField, axis: number): number[] {\n if (axis < 0 || axis >= grid.shape.length) {\n throw new NumericalBackendError(`pderivGrid: axis ${axis} out of range for shape [${grid.shape}]`);\n }\n const h = grid.spacing[axis];\n if (!(h > 0)) {\n throw new NumericalBackendError(`pderivGrid: non-positive spacing ${h} on axis ${axis}`);\n }\n const flat = flattenNA(grid.data);\n const shape = grid.shape;\n const strides: number[] = new Array(shape.length);\n let acc = 1;\n for (let k = shape.length - 1; k >= 0; k--) { strides[k] = acc; acc *= shape[k]; }\n const out = new Array<number>(flat.length).fill(0);\n const n = shape[axis];\n const step = strides[axis];\n\n // Walk every multi-index; compute the axis position from the flat index.\n for (let f = 0; f < flat.length; f++) {\n const pos = Math.floor(f / step) % n;\n if (pos > 0 && pos < n - 1) {\n out[f] = (flat[f + step] - flat[f - step]) / (2 * h);\n } else if (grid.boundary === 'periodic') {\n const next = pos === n - 1 ? f - (n - 1) * step : f + step;\n const prev = pos === 0 ? f + (n - 1) * step : f - step;\n out[f] = (flat[next] - flat[prev]) / (2 * h);\n } else { // 'clamp' — one-sided difference at the edge\n out[f] = pos === 0\n ? (flat[f + step] - flat[f]) / h\n : (flat[f] - flat[f - step]) / h;\n }\n }\n return out;\n}\n\n/**\n * Options for {@link pderivNumericalFn}.\n *\n * - `order` — stencil order. Default **4** as of v0.6.0 (was 2 in v0.5.x,\n * Decision #7). `4` uses the 4-point centered\n * `(−f(x+2h) + 8 f(x+h) − 8 f(x−h) + f(x−2h)) / (12 h)`\n * form with adaptive `h = 1e-4·max(|x|,1)`. 4th-order has ~2× FD\n * evaluations vs 2nd-order but ~10⁴× lower truncation error; preferred\n * default for curvature/Schwarzschild-scale computations where\n * c²·g_tt ~ 6e16 causes 2nd-order cancellation noise.\n * `2` uses the classic centered `(f(x+h) − f(x−h)) / (2h)` form with\n * adaptive `h = 1e-6·max(|x|,1)`. Use `{ order: 2 }` explicitly to\n * preserve v0.5.x 2nd-order semantics.\n * v0.5.1 PD-7 introduced the parameter; v0.6.0 Task 2.12 flipped the default.\n *\n * - `h` — optional explicit step override. Used by\n * `curvature-lowering-helpers.ts` for its inner ∂g sampler where the\n * c²-scaled g_tt cancellation noise needs a larger-than-default step\n * (`1e-3·max(|x|,1)`) to balance truncation vs round-off. If supplied,\n * the adaptive default is bypassed entirely.\n */\n// v0.6.1: dropped export — internal-only options shape for pderivNumericalFn.\ninterface PderivOptions {\n readonly order?: 2 | 4;\n readonly h?: number;\n}\n\n/**\n * Centered finite-difference of a caller-supplied scalar (or tensor-valued)\n * field with respect to coordinate `axis`.\n *\n * - 4th-order (default as of v0.6.0): step h = 1e-4 · max(|x|, 1).\n * ~2× FD evaluations vs 2nd-order; ~10⁴× lower truncation error.\n * Preferred for curvature/Schwarzschild-scale computations.\n * - 2nd-order (`options.order === 2`): step h = 1e-6 · max(|x|, 1)\n * (v0.3.5-Design.md §13 Q3). Use `{ order: 2 }` to preserve v0.5.x semantics.\n *\n * @internal — consumed by the lowering pass; not part of the consumer surface.\n */\nexport function pderivNumericalFn(\n fn: (coords: ReadonlyArray<number>) => NestedArray,\n coords: ReadonlyArray<number>,\n axis: number,\n options?: PderivOptions,\n): NestedArray {\n if (axis < 0 || axis >= coords.length) {\n throw new NumericalBackendError(`pderivNumericalFn: axis ${axis} out of range`);\n }\n const order = options?.order ?? 4;\n if (order !== 2 && order !== 4) {\n throw new NumericalBackendError(\n `pderivNumericalFn: unsupported order ${order} — only 2 or 4 are supported`,\n );\n }\n const x = coords[axis];\n const defaultH = (order === 4 ? 1e-4 : 1e-6) * Math.max(Math.abs(x), 1);\n const h = options?.h ?? defaultH;\n if (!(h > 0) || !Number.isFinite(h)) {\n throw new NumericalBackendError(\n `pderivNumericalFn: non-positive or non-finite step h=${h}`,\n );\n }\n\n if (order === 2) {\n const plus = [...coords]; plus[axis] = x + h;\n const minus = [...coords]; minus[axis] = x - h;\n const fp = flattenNA(fn(plus));\n const fm = flattenNA(fn(minus));\n if (fp.length !== fm.length) {\n throw new NumericalBackendError('pderivNumericalFn: field returned inconsistent shapes');\n }\n const len = fp.length;\n const d = new Array(len);\n const inv2h = 1 / (2 * h);\n for (let i = 0; i < len; i++) {\n // A component that is the same number at every stencil point does not\n // move: its derivative is exactly 0, not the stencil's roundoff over h.\n d[i] = fp[i] === fm[i] ? 0 : (fp[i] - fm[i]) * inv2h;\n }\n return d.length === 1 ? d[0] : d;\n }\n\n // order === 4: f'(x) ≈ (−f(x+2h) + 8 f(x+h) − 8 f(x−h) + f(x−2h)) / (12 h)\n const p1 = [...coords]; p1[axis] = x + h;\n const m1 = [...coords]; m1[axis] = x - h;\n const p2 = [...coords]; p2[axis] = x + 2 * h;\n const m2 = [...coords]; m2[axis] = x - 2 * h;\n const fp1 = flattenNA(fn(p1));\n const fm1 = flattenNA(fn(m1));\n const fp2 = flattenNA(fn(p2));\n const fm2 = flattenNA(fn(m2));\n if (\n fp1.length !== fm1.length || fp1.length !== fp2.length || fp1.length !== fm2.length\n ) {\n throw new NumericalBackendError('pderivNumericalFn: field returned inconsistent shapes');\n }\n const inv12h = 1 / (12 * h);\n const len = fp1.length;\n const d = new Array(len);\n for (let i = 0; i < len; i++) {\n // A component that is the same number at every stencil point does not\n // move: its derivative is exactly 0. The stencil cancels a large constant\n // (g_tt = −c²) only up to the roundoff of 8·f, and that roundoff over h\n // is a fake derivative of order 10⁴.\n const still = fp1[i] === fm1[i] && fp1[i] === fp2[i] && fp1[i] === fm2[i];\n d[i] = still ? 0 : (-fp2[i] + 8 * fp1[i] - 8 * fm1[i] + fm2[i]) * inv12h;\n }\n return d.length === 1 ? d[0] : d;\n}\n\n/**\n * 'symbolic' numericalForm path: v0.3.5 has no CAS, so the caller supplies\n * the derivative explicitly, keyed `${symbolName}/${coordLabel}`.\n *\n * @internal — consumed by the lowering pass; not part of the consumer surface.\n */\nexport function pderivSymbolic(\n symbolName: string,\n coordLabel: string,\n derivatives: ReadonlyMap<string, NestedArray>,\n): NestedArray {\n const key = `${symbolName}/${coordLabel}`;\n const d = derivatives.get(key);\n if (d === undefined) {\n throw new NumericalBackendError(\n `pderivSymbolic: no explicit derivative supplied for \"${key}\" — `\n + `a 'symbolic' tensor-symbol under a partial-derivative requires `\n + `inputs.derivatives to contain its pre-computed components (v0.3.5 has no CAS)`,\n );\n }\n return d;\n}\n\n/**\n * 'supplied' derivativeStrategy path: v0.4.0 metric derivative looked up\n * from explicit caller-supplied components. Keyed `${metricName}/${coordLabel}`.\n * Mirror of `pderivSymbolic` for the metric-tensor lowering path.\n * Throws NumericalBackendError with a clear message when absent.\n */\nexport function metricDerivSupplied(\n metricName: string,\n coordLabel: string,\n metricDerivatives: ReadonlyMap<string, NestedArray>,\n): NestedArray {\n const key = `${metricName}/${coordLabel}`;\n const d = metricDerivatives.get(key);\n if (d === undefined) {\n throw new NumericalBackendError(\n `metricDerivSupplied: no metric derivative supplied for \"${key}\" — `\n + `a metric-tensor with derivativeStrategy='supplied' under a `\n + `christoffel/covariant-derivative requires inputs.metricDerivatives `\n + `to contain its pre-computed ∂g components`,\n );\n }\n return d;\n}\n"]}
1
+ {"version":3,"file":"pderiv.js","sourceRoot":"","sources":["../../src/numerical/pderiv.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Numerical partial derivative — two-way dispatch (v0.3.5-Design.md §6).\n * 'grid' — centered finite-difference over a GridField.\n * 'numerical-fn' — centered finite-difference over a caller-supplied fn.\n * 'symbolic' — no CAS in v0.3.5; consumes an explicit pre-supplied\n * derivative from NumericalInputs.derivatives.\n *\n * @module numerical/pderiv\n */\nimport type { GridField } from './grid-field.js';\nimport type { NestedArray } from './types.js';\nimport { NumericalBackendError } from './errors.js';\nimport { flattenNA } from './connection-lowering-helpers.js';\nimport { rowMajorStrides } from './strides.js';\n\n/**\n * Centered finite-difference of a GridField along `axis`. Returns a flat\n * number[] of the same total size as the grid. O(h²) interior stencil;\n * edges follow `grid.boundary`:\n * - 'clamp' — one-sided (forward/backward) difference at the edge.\n * - 'periodic' — wraps to the opposite edge.\n *\n * @internal — consumed by the lowering pass; not part of the consumer surface.\n */\nexport function pderivGrid(grid: GridField, axis: number): number[] {\n if (axis < 0 || axis >= grid.shape.length) {\n throw new NumericalBackendError(`pderivGrid: axis ${axis} out of range for shape [${grid.shape}]`);\n }\n const h = grid.spacing[axis];\n if (!(h > 0)) {\n throw new NumericalBackendError(`pderivGrid: non-positive spacing ${h} on axis ${axis}`);\n }\n const flat = flattenNA(grid.data);\n const shape = grid.shape;\n const strides = rowMajorStrides(shape);\n const out = new Array<number>(flat.length).fill(0);\n const n = shape[axis];\n const step = strides[axis];\n\n // Walk every multi-index; compute the axis position from the flat index.\n for (let f = 0; f < flat.length; f++) {\n const pos = Math.floor(f / step) % n;\n if (pos > 0 && pos < n - 1) {\n out[f] = (flat[f + step] - flat[f - step]) / (2 * h);\n } else if (grid.boundary === 'periodic') {\n const next = pos === n - 1 ? f - (n - 1) * step : f + step;\n const prev = pos === 0 ? f + (n - 1) * step : f - step;\n out[f] = (flat[next] - flat[prev]) / (2 * h);\n } else { // 'clamp' — one-sided difference at the edge\n out[f] = pos === 0\n ? (flat[f + step] - flat[f]) / h\n : (flat[f] - flat[f - step]) / h;\n }\n }\n return out;\n}\n\n/**\n * Options for {@link pderivNumericalFn}.\n *\n * - `order` — stencil order. Default **4** as of v0.6.0 (was 2 in v0.5.x,\n * Decision #7). `4` uses the 4-point centered\n * `(−f(x+2h) + 8 f(x+h) − 8 f(x−h) + f(x−2h)) / (12 h)`\n * form with adaptive `h = 1e-4·max(|x|,1)`. 4th-order has ~2× FD\n * evaluations vs 2nd-order but ~10⁴× lower truncation error; preferred\n * default for curvature/Schwarzschild-scale computations where\n * c²·g_tt ~ 6e16 causes 2nd-order cancellation noise.\n * `2` uses the classic centered `(f(x+h) − f(x−h)) / (2h)` form with\n * adaptive `h = 1e-6·max(|x|,1)`. Use `{ order: 2 }` explicitly to\n * preserve v0.5.x 2nd-order semantics.\n * v0.5.1 PD-7 introduced the parameter; v0.6.0 Task 2.12 flipped the default.\n *\n * - `h` — optional explicit step override. Used by\n * `curvature-lowering-helpers.ts` for its inner ∂g sampler where the\n * c²-scaled g_tt cancellation noise needs a larger-than-default step\n * (`1e-3·max(|x|,1)`) to balance truncation vs round-off. If supplied,\n * the adaptive default is bypassed entirely.\n */\n// v0.6.1: dropped export — internal-only options shape for pderivNumericalFn.\ninterface PderivOptions {\n readonly order?: 2 | 4;\n readonly h?: number;\n}\n\n/**\n * Centered finite-difference of a caller-supplied scalar (or tensor-valued)\n * field with respect to coordinate `axis`.\n *\n * - 4th-order (default as of v0.6.0): step h = 1e-4 · max(|x|, 1).\n * ~2× FD evaluations vs 2nd-order; ~10⁴× lower truncation error.\n * Preferred for curvature/Schwarzschild-scale computations.\n * - 2nd-order (`options.order === 2`): step h = 1e-6 · max(|x|, 1)\n * (v0.3.5-Design.md §13 Q3). Use `{ order: 2 }` to preserve v0.5.x semantics.\n *\n * @internal — consumed by the lowering pass; not part of the consumer surface.\n */\nexport function pderivNumericalFn(\n fn: (coords: ReadonlyArray<number>) => NestedArray,\n coords: ReadonlyArray<number>,\n axis: number,\n options?: PderivOptions,\n): NestedArray {\n if (axis < 0 || axis >= coords.length) {\n throw new NumericalBackendError(`pderivNumericalFn: axis ${axis} out of range`);\n }\n const order = options?.order ?? 4;\n if (order !== 2 && order !== 4) {\n throw new NumericalBackendError(\n `pderivNumericalFn: unsupported order ${order} — only 2 or 4 are supported`,\n );\n }\n const x = coords[axis];\n const defaultH = (order === 4 ? 1e-4 : 1e-6) * Math.max(Math.abs(x), 1);\n const h = options?.h ?? defaultH;\n if (!(h > 0) || !Number.isFinite(h)) {\n throw new NumericalBackendError(\n `pderivNumericalFn: non-positive or non-finite step h=${h}`,\n );\n }\n\n if (order === 2) {\n const plus = [...coords]; plus[axis] = x + h;\n const minus = [...coords]; minus[axis] = x - h;\n const fp = flattenNA(fn(plus));\n const fm = flattenNA(fn(minus));\n if (fp.length !== fm.length) {\n throw new NumericalBackendError('pderivNumericalFn: field returned inconsistent shapes');\n }\n const len = fp.length;\n const d = new Array(len);\n const inv2h = 1 / (2 * h);\n for (let i = 0; i < len; i++) {\n // A component that is the same number at every stencil point does not\n // move: its derivative is exactly 0, not the stencil's roundoff over h.\n d[i] = fp[i] === fm[i] ? 0 : (fp[i] - fm[i]) * inv2h;\n }\n return d.length === 1 ? d[0] : d;\n }\n\n // order === 4: f'(x) ≈ (−f(x+2h) + 8 f(x+h) − 8 f(x−h) + f(x−2h)) / (12 h)\n const p1 = [...coords]; p1[axis] = x + h;\n const m1 = [...coords]; m1[axis] = x - h;\n const p2 = [...coords]; p2[axis] = x + 2 * h;\n const m2 = [...coords]; m2[axis] = x - 2 * h;\n const fp1 = flattenNA(fn(p1));\n const fm1 = flattenNA(fn(m1));\n const fp2 = flattenNA(fn(p2));\n const fm2 = flattenNA(fn(m2));\n if (\n fp1.length !== fm1.length || fp1.length !== fp2.length || fp1.length !== fm2.length\n ) {\n throw new NumericalBackendError('pderivNumericalFn: field returned inconsistent shapes');\n }\n const inv12h = 1 / (12 * h);\n const len = fp1.length;\n const d = new Array(len);\n for (let i = 0; i < len; i++) {\n // A component that is the same number at every stencil point does not\n // move: its derivative is exactly 0. The stencil cancels a large constant\n // (g_tt = −c²) only up to the roundoff of 8·f, and that roundoff over h\n // is a fake derivative of order 10⁴.\n const still = fp1[i] === fm1[i] && fp1[i] === fp2[i] && fp1[i] === fm2[i];\n d[i] = still ? 0 : (-fp2[i] + 8 * fp1[i] - 8 * fm1[i] + fm2[i]) * inv12h;\n }\n return d.length === 1 ? d[0] : d;\n}\n\n/**\n * 'symbolic' numericalForm path: v0.3.5 has no CAS, so the caller supplies\n * the derivative explicitly, keyed `${symbolName}/${coordLabel}`.\n *\n * @internal — consumed by the lowering pass; not part of the consumer surface.\n */\nexport function pderivSymbolic(\n symbolName: string,\n coordLabel: string,\n derivatives: ReadonlyMap<string, NestedArray>,\n): NestedArray {\n const key = `${symbolName}/${coordLabel}`;\n const d = derivatives.get(key);\n if (d === undefined) {\n throw new NumericalBackendError(\n `pderivSymbolic: no explicit derivative supplied for \"${key}\" — `\n + `a 'symbolic' tensor-symbol under a partial-derivative requires `\n + `inputs.derivatives to contain its pre-computed components (v0.3.5 has no CAS)`,\n );\n }\n return d;\n}\n\n/**\n * 'supplied' derivativeStrategy path: v0.4.0 metric derivative looked up\n * from explicit caller-supplied components. Keyed `${metricName}/${coordLabel}`.\n * Mirror of `pderivSymbolic` for the metric-tensor lowering path.\n * Throws NumericalBackendError with a clear message when absent.\n */\nexport function metricDerivSupplied(\n metricName: string,\n coordLabel: string,\n metricDerivatives: ReadonlyMap<string, NestedArray>,\n): NestedArray {\n const key = `${metricName}/${coordLabel}`;\n const d = metricDerivatives.get(key);\n if (d === undefined) {\n throw new NumericalBackendError(\n `metricDerivSupplied: no metric derivative supplied for \"${key}\" — `\n + `a metric-tensor with derivativeStrategy='supplied' under a `\n + `christoffel/covariant-derivative requires inputs.metricDerivatives `\n + `to contain its pre-computed ∂g components`,\n );\n }\n return d;\n}\n"]}
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Gauss–Legendre quadrature — shared between the numerical AST lowering and the
3
- * traced reverse-mode-AD lowering of definite `integral` nodes.
2
+ * Gauss–Legendre quadrature for the numerical AST lowering of definite
3
+ * `integral` nodes.
4
4
  *
5
5
  * 16-point Gauss–Legendre on [−1, 1]: exact for polynomials of degree ≤ 31, and
6
6
  * highly accurate for smooth integrands (√, exp, trig away from singularities).
7
7
  * It is NOT reliable for highly oscillatory integrands or singularities at/near
8
- * the bounds — those are out of scope for the differentiable-integral feature.
8
+ * the bounds.
9
9
  *
10
10
  * The affine map from [−1, 1] to [a, b] is x = (b−a)/2·ξ + (a+b)/2 with Jacobian
11
11
  * (b−a)/2, so ∫ₐᵇ f dx ≈ (b−a)/2 · Σᵢ wᵢ·f(xᵢ). For b < a the (b−a)/2 factor is
@@ -1 +1 @@
1
- {"version":3,"file":"quadrature.js","sourceRoot":"","sources":["../../src/numerical/quadrature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAQpD,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;AAErC,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS;IACpC,OAAO,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,kGAAkG;AAClG,SAAS,oBAAoB,CAAC,CAAS;IACrC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IAC/F,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,CAAwB,EACxB,CAAS,EACT,CAAS;IAET,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,UAAU,CAClB,mEAAmE,CAAC,KAAK,CAAC,IAAI,CAC/E,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;QACjD,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,UAAU,CAClB,mEAAmE,MAAM,SAAS,CAAC,KAAK,CAAC,IAAI,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Gauss–Legendre quadrature — shared between the numerical AST lowering and the\n * traced reverse-mode-AD lowering of definite `integral` nodes.\n *\n * 16-point Gauss–Legendre on [−1, 1]: exact for polynomials of degree ≤ 31, and\n * highly accurate for smooth integrands (√, exp, trig away from singularities).\n * It is NOT reliable for highly oscillatory integrands or singularities at/near\n * the bounds — those are out of scope for the differentiable-integral feature.\n *\n * The affine map from [−1, 1] to [a, b] is x = (b−a)/2·ξ + (a+b)/2 with Jacobian\n * (b−a)/2, so ∫ₐᵇ f dx ≈ (b−a)/2 · Σᵢ wᵢ·f(xᵢ). For b < a the (b−a)/2 factor is\n * negative, giving the correct signed integral (∫ₐᵇ = −∫ᵦᵃ).\n *\n * The nodes are MathTS `rootsLegendre(16)`. `gaussQuad` is not this rule: its\n * single-interval order is only 2–5, and a larger `n` is that many panels of\n * order 5. `quad` is adaptive Gauss–Kronrod, not a fixed degree.\n *\n * @module numerical/quadrature\n */\nimport { legendreP, rootsLegendre } from '@danielsimonjr/mathts-functions';\nimport { numberFrom } from '../core/mathts-read.js';\n\n/** A Gauss–Legendre abscissa/weight pair on the reference interval [−1, 1]. @internal */\ninterface GaussLegendreNode {\n readonly node: number;\n readonly weight: number;\n}\n\nconst legendre16 = rootsLegendre(16);\n\n/** `Pₙ(x)`, MathTS `legendreP`, read back as the number it is for a number. */\nfunction legendre(n: number, x: number): number {\n return numberFrom('legendreP', legendreP(n, x));\n}\n\n/** P₁₆'(x) = 16 (x P₁₆(x) − P₁₅(x)) / (x² − 1), the derivative identity on MathTS `legendreP`. */\nfunction legendre16Derivative(x: number): number {\n return (16 * (x * legendre(16, x) - legendre(15, x))) / (x * x - 1);\n}\n\n/**\n * 16-point Gauss–Legendre nodes and weights on [−1, 1] (Σ weights = 2). The\n * nodes are MathTS `rootsLegendre(16)`'s. The weights are the closed form\n * `2 / ((1 − x²) P₁₆'(x)²)` on those nodes: MathTS's tabulated weights carried a\n * relative error of 8e-14 (Σ = 1.9999999999999956), 400 times the double\n * precision the degree-31 exactness claim rests on (Tom's second round).\n */\nexport const GAUSS_LEGENDRE_16: ReadonlyArray<GaussLegendreNode> = legendre16.nodes.map((node) => {\n const dp = legendre16Derivative(node);\n return { node, weight: 2 / ((1 - node * node) * dp * dp) };\n});\n\n/**\n * Evaluate the definite integral ∫ₐᵇ f(x) dx by 16-point Gauss–Legendre\n * quadrature. `f` is sampled at the 16 mapped abscissae.\n */\nexport function integrateGaussLegendre(\n f: (x: number) => number,\n a: number,\n b: number,\n): number {\n if (!Number.isFinite(a) || !Number.isFinite(b)) {\n throw new RangeError(\n `integrateGaussLegendre: integration bounds must be finite, got [${a}, ${b}].`,\n );\n }\n const half = (b - a) / 2;\n const mid = (a + b) / 2;\n let sum = 0;\n for (const { node, weight } of GAUSS_LEGENDRE_16) {\n sum += weight * f(half * node + mid);\n }\n const result = half * sum;\n if (!Number.isFinite(result)) {\n throw new RangeError(\n `integrateGaussLegendre: integrand produced a non-finite result (${result}) on [${a}, ${b}].`,\n );\n }\n return result;\n}\n"]}
1
+ {"version":3,"file":"quadrature.js","sourceRoot":"","sources":["../../src/numerical/quadrature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAQpD,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;AAErC,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS;IACpC,OAAO,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,kGAAkG;AAClG,SAAS,oBAAoB,CAAC,CAAS;IACrC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IAC/F,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,CAAwB,EACxB,CAAS,EACT,CAAS;IAET,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,UAAU,CAClB,mEAAmE,CAAC,KAAK,CAAC,IAAI,CAC/E,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;QACjD,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,UAAU,CAClB,mEAAmE,MAAM,SAAS,CAAC,KAAK,CAAC,IAAI,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Gauss–Legendre quadrature for the numerical AST lowering of definite\n * `integral` nodes.\n *\n * 16-point Gauss–Legendre on [−1, 1]: exact for polynomials of degree ≤ 31, and\n * highly accurate for smooth integrands (√, exp, trig away from singularities).\n * It is NOT reliable for highly oscillatory integrands or singularities at/near\n * the bounds.\n *\n * The affine map from [−1, 1] to [a, b] is x = (b−a)/2·ξ + (a+b)/2 with Jacobian\n * (b−a)/2, so ∫ₐᵇ f dx ≈ (b−a)/2 · Σᵢ wᵢ·f(xᵢ). For b < a the (b−a)/2 factor is\n * negative, giving the correct signed integral (∫ₐᵇ = −∫ᵦᵃ).\n *\n * The nodes are MathTS `rootsLegendre(16)`. `gaussQuad` is not this rule: its\n * single-interval order is only 2–5, and a larger `n` is that many panels of\n * order 5. `quad` is adaptive Gauss–Kronrod, not a fixed degree.\n *\n * @module numerical/quadrature\n */\nimport { legendreP, rootsLegendre } from '@danielsimonjr/mathts-functions';\nimport { numberFrom } from '../core/mathts-read.js';\n\n/** A Gauss–Legendre abscissa/weight pair on the reference interval [−1, 1]. @internal */\ninterface GaussLegendreNode {\n readonly node: number;\n readonly weight: number;\n}\n\nconst legendre16 = rootsLegendre(16);\n\n/** `Pₙ(x)`, MathTS `legendreP`, read back as the number it is for a number. */\nfunction legendre(n: number, x: number): number {\n return numberFrom('legendreP', legendreP(n, x));\n}\n\n/** P₁₆'(x) = 16 (x P₁₆(x) − P₁₅(x)) / (x² − 1), the derivative identity on MathTS `legendreP`. */\nfunction legendre16Derivative(x: number): number {\n return (16 * (x * legendre(16, x) - legendre(15, x))) / (x * x - 1);\n}\n\n/**\n * 16-point Gauss–Legendre nodes and weights on [−1, 1] (Σ weights = 2). The\n * nodes are MathTS `rootsLegendre(16)`'s. The weights are the closed form\n * `2 / ((1 − x²) P₁₆'(x)²)` on those nodes: MathTS's tabulated weights carried a\n * relative error of 8e-14 (Σ = 1.9999999999999956), 400 times the double\n * precision the degree-31 exactness claim rests on (Tom's second round).\n */\nexport const GAUSS_LEGENDRE_16: ReadonlyArray<GaussLegendreNode> = legendre16.nodes.map((node) => {\n const dp = legendre16Derivative(node);\n return { node, weight: 2 / ((1 - node * node) * dp * dp) };\n});\n\n/**\n * Evaluate the definite integral ∫ₐᵇ f(x) dx by 16-point Gauss–Legendre\n * quadrature. `f` is sampled at the 16 mapped abscissae.\n */\nexport function integrateGaussLegendre(\n f: (x: number) => number,\n a: number,\n b: number,\n): number {\n if (!Number.isFinite(a) || !Number.isFinite(b)) {\n throw new RangeError(\n `integrateGaussLegendre: integration bounds must be finite, got [${a}, ${b}].`,\n );\n }\n const half = (b - a) / 2;\n const mid = (a + b) / 2;\n let sum = 0;\n for (const { node, weight } of GAUSS_LEGENDRE_16) {\n sum += weight * f(half * node + mid);\n }\n const result = half * sum;\n if (!Number.isFinite(result)) {\n throw new RangeError(\n `integrateGaussLegendre: integrand produced a non-finite result (${result}) on [${a}, ${b}].`,\n );\n }\n return result;\n}\n"]}
@@ -14,7 +14,7 @@ import { numberFrom } from '../core/mathts-read.js';
14
14
  export function meanOf(values) {
15
15
  if (values.length === 0)
16
16
  throw new RangeError('meanOf: no values');
17
- return numberFrom('mean', mean([...values]));
17
+ return numberFrom('mean', mean(values));
18
18
  }
19
19
  /**
20
20
  * MathTS `std` with the `uncorrected` (population, divide by n) normalization.
@@ -1 +1 @@
1
- {"version":3,"file":"statistics.js","sourceRoot":"","sources":["../../src/numerical/statistics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,iGAAiG;AACjG,MAAM,UAAU,MAAM,CAAC,MAAyB;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAC;IACnE,OAAO,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,MAAyB;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,0BAA0B,CAAC,CAAC;IAC1E,OAAO,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS;IAC5C,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACjE,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,MAAyB;IACnD,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9D,CAAC","sourcesContent":["/**\n * Scalar statistics read from MathTS, typed back as the numbers they are.\n *\n * The typed MathTS functions (`mean`, `std`, `lgamma`) are dispatch objects\n * whose declared return is `unknown`; each reader here takes its number\n * through `core/mathts-read`, so a caller never carries an `unknown` into\n * arithmetic.\n *\n * @module numerical/statistics\n */\nimport { lgamma, mean, std } from '@danielsimonjr/mathts-functions';\nimport { numberFrom } from '../core/mathts-read.js';\n\n/** MathTS `mean` of a non-empty number array. @throws RangeError on an empty array. @internal */\nexport function meanOf(values: readonly number[]): number {\n if (values.length === 0) throw new RangeError('meanOf: no values');\n return numberFrom('mean', mean([...values]));\n}\n\n/**\n * MathTS `std` with the `uncorrected` (population, divide by n) normalization.\n * @throws RangeError on an empty array.\n */\nfunction populationStd(values: readonly number[]): number {\n if (values.length === 0) throw new RangeError('populationStd: no values');\n return numberFrom('std', std([...values], 'uncorrected'));\n}\n\n/** `log Γ(z)`, MathTS `lgamma`, read back as the number it is for a number. */\nfunction logGamma(z: number): number {\n return numberFrom('lgamma', lgamma(z));\n}\n\n/**\n * `ln C(n, k) = ln Γ(n+1) − ln Γ(k+1) − ln Γ(n−k+1)`, through MathTS `lgamma`.\n * The one owner of the log binomial coefficient: the lattice random walk and\n * the McNemar tail both read it (`TOOLS.md`, how `lgamma` compares to a sum\n * of logs at large n).\n * @internal\n */\nexport function logChoose(n: number, k: number): number {\n return logGamma(n + 1) - logGamma(k + 1) - logGamma(n - k + 1);\n}\n\n/** The mean of a set of ratios and their coefficient of variation (population σ over |mean|). @internal */\nexport interface RatioSpread {\n readonly mean: number;\n /** `σ/|mean|`; `Infinity` when the mean is 0 and the ratios are not all 0, `NaN` when they are all 0 or any ratio is not finite. */\n readonly cv: number;\n}\n\n/**\n * How far a set of ratios is from one constant: the mean and `σ/|mean|`. A\n * monomial fit is accepted when the ratios of a formula to the candidate\n * monomial agree to a relative spread below the caller's threshold.\n * @internal\n */\nexport function ratioSpread(ratios: readonly number[]): RatioSpread {\n const m = meanOf(ratios);\n return { mean: m, cv: populationStd(ratios) / Math.abs(m) };\n}\n"]}
1
+ {"version":3,"file":"statistics.js","sourceRoot":"","sources":["../../src/numerical/statistics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,iGAAiG;AACjG,MAAM,UAAU,MAAM,CAAC,MAAyB;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAC;IACnE,OAAO,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,MAAyB;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,0BAA0B,CAAC,CAAC;IAC1E,OAAO,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS;IAC5C,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACjE,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,MAAyB;IACnD,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9D,CAAC","sourcesContent":["/**\n * Scalar statistics read from MathTS, typed back as the numbers they are.\n *\n * The typed MathTS functions (`mean`, `std`, `lgamma`) are dispatch objects\n * whose declared return is `unknown`; each reader here takes its number\n * through `core/mathts-read`, so a caller never carries an `unknown` into\n * arithmetic.\n *\n * @module numerical/statistics\n */\nimport { lgamma, mean, std } from '@danielsimonjr/mathts-functions';\nimport { numberFrom } from '../core/mathts-read.js';\n\n/** MathTS `mean` of a non-empty number array. @throws RangeError on an empty array. @internal */\nexport function meanOf(values: readonly number[]): number {\n if (values.length === 0) throw new RangeError('meanOf: no values');\n return numberFrom('mean', mean(values));\n}\n\n/**\n * MathTS `std` with the `uncorrected` (population, divide by n) normalization.\n * @throws RangeError on an empty array.\n */\nfunction populationStd(values: readonly number[]): number {\n if (values.length === 0) throw new RangeError('populationStd: no values');\n return numberFrom('std', std([...values], 'uncorrected'));\n}\n\n/** `log Γ(z)`, MathTS `lgamma`, read back as the number it is for a number. */\nfunction logGamma(z: number): number {\n return numberFrom('lgamma', lgamma(z));\n}\n\n/**\n * `ln C(n, k) = ln Γ(n+1) − ln Γ(k+1) − ln Γ(n−k+1)`, through MathTS `lgamma`.\n * The one owner of the log binomial coefficient: the lattice random walk and\n * the McNemar tail both read it (`TOOLS.md`, how `lgamma` compares to a sum\n * of logs at large n).\n * @internal\n */\nexport function logChoose(n: number, k: number): number {\n return logGamma(n + 1) - logGamma(k + 1) - logGamma(n - k + 1);\n}\n\n/** The mean of a set of ratios and their coefficient of variation (population σ over |mean|). @internal */\nexport interface RatioSpread {\n readonly mean: number;\n /** `σ/|mean|`; `Infinity` when the mean is 0 and the ratios are not all 0, `NaN` when they are all 0 or any ratio is not finite. */\n readonly cv: number;\n}\n\n/**\n * How far a set of ratios is from one constant: the mean and `σ/|mean|`. A\n * monomial fit is accepted when the ratios of a formula to the candidate\n * monomial agree to a relative spread below the caller's threshold.\n * @internal\n */\nexport function ratioSpread(ratios: readonly number[]): RatioSpread {\n const m = meanOf(ratios);\n return { mean: m, cv: populationStd(ratios) / Math.abs(m) };\n}\n"]}
@@ -7,12 +7,13 @@
7
7
  * @module numerical/strides
8
8
  * @internal
9
9
  */
10
+ import { rowMajorStrides } from '@danielsimonjr/mathts-core';
10
11
  /**
11
- * Compute row-major strides for a given shape.
12
+ * Row-major strides for a shape, MathTS core `rowMajorStrides`:
12
13
  * strides[k] = product of shape[k+1..end], so that
13
14
  * flatIndex = sum(idx[k] * strides[k]).
14
15
  */
15
- export declare function rowMajorStrides(shape: ReadonlyArray<number>): number[];
16
+ export { rowMajorStrides };
16
17
  /**
17
18
  * Compute the flat (linear) index from a multi-index and precomputed strides.
18
19
  * flatIndex = sum_k(idx[k] * strides[k]).
@@ -1 +1 @@
1
- {"version":3,"file":"strides.d.ts","sourceRoot":"","sources":["../../src/numerical/strides.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAQtE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,EAC1B,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAC7B,MAAM,CAIR;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,EACxB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GACvB,OAAO,CAET"}
1
+ {"version":3,"file":"strides.d.ts","sourceRoot":"","sources":["../../src/numerical/strides.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,EAC1B,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAC7B,MAAM,CAIR;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,EACxB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GACvB,OAAO,CAET"}
@@ -7,20 +7,13 @@
7
7
  * @module numerical/strides
8
8
  * @internal
9
9
  */
10
+ import { rowMajorStrides } from '@danielsimonjr/mathts-core';
10
11
  /**
11
- * Compute row-major strides for a given shape.
12
+ * Row-major strides for a shape, MathTS core `rowMajorStrides`:
12
13
  * strides[k] = product of shape[k+1..end], so that
13
14
  * flatIndex = sum(idx[k] * strides[k]).
14
15
  */
15
- export function rowMajorStrides(shape) {
16
- const strides = new Array(shape.length);
17
- let s = 1;
18
- for (let k = shape.length - 1; k >= 0; k--) {
19
- strides[k] = s;
20
- s *= shape[k];
21
- }
22
- return strides;
23
- }
16
+ export { rowMajorStrides };
24
17
  /**
25
18
  * Compute the flat (linear) index from a multi-index and precomputed strides.
26
19
  * flatIndex = sum_k(idx[k] * strides[k]).
@@ -1 +1 @@
1
- {"version":3,"file":"strides.js","sourceRoot":"","sources":["../../src/numerical/strides.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAA4B;IAC1D,MAAM,OAAO,GAAG,IAAI,KAAK,CAAS,KAAK,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACf,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CACvB,GAA0B,EAC1B,OAA8B;IAE9B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,CAAwB,EACxB,CAAwB;IAExB,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC","sourcesContent":["/**\n * Shared stride and flat-index utilities for row-major tensor storage.\n *\n * Used by connection-lowering-helpers.ts (Christoffel / contraction loops).\n * Extracted in v0.4.6 to eliminate duplicate implementations.\n *\n * @module numerical/strides\n * @internal\n */\n\n/**\n * Compute row-major strides for a given shape.\n * strides[k] = product of shape[k+1..end], so that\n * flatIndex = sum(idx[k] * strides[k]).\n */\nexport function rowMajorStrides(shape: ReadonlyArray<number>): number[] {\n const strides = new Array<number>(shape.length);\n let s = 1;\n for (let k = shape.length - 1; k >= 0; k--) {\n strides[k] = s;\n s *= shape[k];\n }\n return strides;\n}\n\n/**\n * Compute the flat (linear) index from a multi-index and precomputed strides.\n * flatIndex = sum_k(idx[k] * strides[k]).\n */\nexport function flatIndex(\n idx: ReadonlyArray<number>,\n strides: ReadonlyArray<number>,\n): number {\n let f = 0;\n for (let k = 0; k < idx.length; k++) f += idx[k] * strides[k];\n return f;\n}\n\n/**\n * Check if two shape arrays are element-wise equal.\n */\nexport function sameShape(\n a: ReadonlyArray<number>,\n b: ReadonlyArray<number>,\n): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n"]}
1
+ {"version":3,"file":"strides.js","sourceRoot":"","sources":["../../src/numerical/strides.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B;;;GAGG;AACH,MAAM,UAAU,SAAS,CACvB,GAA0B,EAC1B,OAA8B;IAE9B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,CAAwB,EACxB,CAAwB;IAExB,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC","sourcesContent":["/**\n * Shared stride and flat-index utilities for row-major tensor storage.\n *\n * Used by connection-lowering-helpers.ts (Christoffel / contraction loops).\n * Extracted in v0.4.6 to eliminate duplicate implementations.\n *\n * @module numerical/strides\n * @internal\n */\n\nimport { rowMajorStrides } from '@danielsimonjr/mathts-core';\n\n/**\n * Row-major strides for a shape, MathTS core `rowMajorStrides`:\n * strides[k] = product of shape[k+1..end], so that\n * flatIndex = sum(idx[k] * strides[k]).\n */\nexport { rowMajorStrides };\n\n/**\n * Compute the flat (linear) index from a multi-index and precomputed strides.\n * flatIndex = sum_k(idx[k] * strides[k]).\n */\nexport function flatIndex(\n idx: ReadonlyArray<number>,\n strides: ReadonlyArray<number>,\n): number {\n let f = 0;\n for (let k = 0; k < idx.length; k++) f += idx[k] * strides[k];\n return f;\n}\n\n/**\n * Check if two shape arrays are element-wise equal.\n */\nexport function sameShape(\n a: ReadonlyArray<number>,\n b: ReadonlyArray<number>,\n): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-physics-tensor",
3
- "version": "11.0.0",
3
+ "version": "12.0.0",
4
4
  "description": "Computational framework for exploring unified physics through tensor formalism",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -98,26 +98,23 @@
98
98
  },
99
99
  "homepage": "https://github.com/danielsimonjr/Universal-Physics-Tensor#readme",
100
100
  "dependencies": {
101
- "@danielsimonjr/mathts-autograd": "^0.3.18",
102
- "@danielsimonjr/mathts-core": "^0.18.1",
103
- "@danielsimonjr/mathts-expression": "^0.10.2",
104
- "@danielsimonjr/mathts-functions": "^0.68.5",
105
- "@danielsimonjr/mathts-matrix": "^0.7.8",
106
- "@danielsimonjr/mathts-parallel": "^0.6.8",
107
- "@danielsimonjr/mathts-tensor": "^0.2.24",
108
- "@danielsimonjr/mathts-wasm": "^0.3.0",
109
- "@danielsimonjr/mathts-workerpool": "^0.2.6"
101
+ "@danielsimonjr/mathts-autograd": "^0.4.1",
102
+ "@danielsimonjr/mathts-core": "^0.22.0",
103
+ "@danielsimonjr/mathts-expression": "^0.12.2",
104
+ "@danielsimonjr/mathts-functions": "^0.73.0",
105
+ "@danielsimonjr/mathts-matrix": "^0.9.1",
106
+ "@danielsimonjr/mathts-tensor": "^0.3.1"
110
107
  },
111
108
  "devDependencies": {
112
109
  "@types/node": "^22.0.0",
113
- "@vitest/coverage-v8": "^4.1.7",
110
+ "@vitest/coverage-v8": "^4.1.12",
114
111
  "@viz-js/viz": "^3.28.0",
115
112
  "fast-check": "^4.8.0",
116
113
  "js-yaml": "^5.0.0",
117
114
  "tree-sitter": "0.22.4",
118
115
  "tree-sitter-typescript": "0.23.2",
119
116
  "typescript": "^7.0.2",
120
- "vitest": "^4.1.7"
117
+ "vitest": "^4.1.12"
121
118
  },
122
119
  "peerDependencies": {
123
120
  "@viz-js/viz": "^3.28.0"
@@ -1,68 +0,0 @@
1
- import { type AppliedCase } from './types.js';
2
- /** Standard gravity (CGPM 1901), for the sedimentation speed: the unit table's `standard_gravity` row, read as newtons per kilogram-force. @internal */
3
- export declare const G_STANDARD: number;
4
- /** The thresholds `ab-stokes-einstein` states: Re ≤ 0.1 and τ_p/t ≤ 0.01. @internal */
5
- export declare const MAX_RE = 0.1;
6
- export declare const MAX_TAU_P_RATIO = 0.01;
7
- /** Ceiling on the memory term's own share of the MSD, |MSD_H/MSD_OU − 1|. @internal */
8
- export declare const MAX_MEMORY_CORRECTION = 0.01;
9
- /** (v_s t)²/(2Dt) ceiling along gravity when the vertical axis is tracked. @internal */
10
- export declare const MAX_DRIFT_RATIO = 0.01;
11
- /** Ceiling on |MSD/MSD_wall − 1|: the wall's correction to the tracked MSD is negligible. @internal */
12
- export declare const MAX_WALL_CORRECTION = 0.01;
13
- /** Ceiling on the last retained Faxén term (a/h)⁵/16 over the series' value. @internal */
14
- export declare const MAX_FAXEN_LAST_TERM = 0.01;
15
- /** Ceiling on √(2 D_⊥ t)/(h − a): the height, and so D_∥ and D_⊥, barely change over t. @internal */
16
- export declare const MAX_WALL_EXCURSION = 0.1;
17
- /** t − τ(1 − e^{−t/τ}) in units of τ, i.e. x − (1 − e^{−x}), without its cancellation at small x. @internal */
18
- export declare function ballisticDeficit(x: number): number;
19
- /**
20
- * MSD/(2Dt) per axis for a sphere with fluid inertia: added mass and the Basset
21
- * memory force, in an unbounded incompressible fluid, velocities in equilibrium.
22
- *
23
- * The velocity autocorrelation has the Laplace transform
24
- * Ĉ(s) = k_BT/(M s + γ(1 + √(s τ_f))), M = m + m_f/2, from the frequency-dependent
25
- * Stokes drag γ(1 + √(sτ_f)) + s m_f/2 (Stokes 1851; the Basset 1888 term is its
26
- * √s part; Hinch 1975, J. Fluid Mech. 72, 499; Clercx & Schram 1992, Phys. Rev.
27
- * A 46, 1942). Its poles in √s both have negative real part, so Ĉ has none on the
28
- * principal sheet and C(t) is the branch-cut integral
29
- * C(t) = (k_BT/πγ) ∫₀^∞ e^{−ut} √(τ_f u)/((1 − τ_p u)² + τ_f u) du, τ_p = M/γ.
30
- * Then ⟨Δx²⟩ = 2∫₀ᵗ (t − s) C(s) ds, and with v = ut,
31
- * MSD/(2Dt) = (1/π) ∫₀^∞ √(βv) (v − 1 + e^{−v}) / (v² ((1 − αv)² + βv)) dv, α = τ_p/t, β = τ_f/t,
32
- * integrated here over ln v by MathTS `quad` (adaptive Gauss–Kronrod), split at v = 1, 1/β and around
33
- * the near-resonance at v = 1/α (width √(β/α) in ln v; β/α ≤ 9 for any densities).
34
- *
35
- * Limits: → 1 − 2√(τ_f/(πt)) + (τ_f − τ_p)/t for t ≫ τ_p, τ_f (expanding Ĉ in √s),
36
- * whose second derivative is the VACF tail k_BT/(12 ρ_f (πνt)^{3/2}); → t/(2τ_p)
37
- * for t ≪ τ_p, i.e. ⟨Δx²⟩ → (k_BT/M) t². Requires β > 0: without memory the
38
- * poles reach the principal sheet and this integral no longer holds them.
39
- * @internal
40
- */
41
- export declare function hydrodynamicMsdRatio(alpha: number, beta: number): number;
42
- /**
43
- * D_∥/D₀ for a sphere translating parallel to a plane wall, centre at h:
44
- * 1 − (9/16)ξ + (1/8)ξ³ − (45/256)ξ⁴ − (1/16)ξ⁵, ξ = a/h (Faxén 1923, method of
45
- * reflections, as quoted in Happel & Brenner 1965, Low Reynolds Number
46
- * Hydrodynamics, ch. 7). A series in a/h, truncated:
47
- * its error is not bounded here, and near contact it misses the logarithmic
48
- * lubrication divergence of the drag.
49
- * @internal
50
- */
51
- export declare function faxenParallel(aOverH: number): number;
52
- /**
53
- * λ = F/(6πηaU) for a sphere approaching a plane wall head-on, centre at h > a,
54
- * exact in Stokes flow (Brenner 1961, Chem. Eng. Sci. 16, 242, bispherical coordinates):
55
- * λ = (4/3) sinh α Σₙ n(n+1)/((2n−1)(2n+3)) · [(2 sinh(2n+1)α + (2n+1) sinh 2α) /
56
- * (4 sinh²(n+½)α − (2n+1)² sinh²α) − 1], cosh α = h/a. D_⊥ = D₀/λ.
57
- *
58
- * The bracket is rewritten over 4 sinh²(n+½)α so that no sinh overflows; its
59
- * terms fall as e^{−(2n+1)α}, so near contact (α → 0) the sum needs ~40/α terms,
60
- * and the low-n denominators lose ~α⁻² of relative precision to cancellation.
61
- * Limits: λ → 1 + (9/8)(a/h) far away (Lorentz 1907); λ → a/δ + (1/5) ln(a/δ) +
62
- * 0.971 as the gap δ = h − a → 0 (Cox & Brenner 1967, Chem. Eng. Sci. 22, 1753).
63
- * @throws Error if h/a ≤ 1.
64
- * @internal
65
- */
66
- export declare function brennerPerpendicular(hOverA: number): number;
67
- export declare const BROWNIAN_SPHERE_CASE: AppliedCase;
68
- //# sourceMappingURL=brownian-sphere.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"brownian-sphere.d.ts","sourceRoot":"","sources":["../../src/cases/brownian-sphere.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAoD,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAIhG,wJAAwJ;AACxJ,eAAO,MAAM,UAAU,QAA0C,CAAC;AAElE,uFAAuF;AACvF,eAAO,MAAM,MAAM,MAAM,CAAC;AAC1B,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,uFAAuF;AACvF,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,wFAAwF;AACxF,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,uGAAuG;AACvG,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,0FAA0F;AAC1F,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,+GAA+G;AAC/G,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAcxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkB3D;AAED,eAAO,MAAM,oBAAoB,EAAE,WA2OlC,CAAC"}