universal-physics-tensor 10.0.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/bin/upt.mjs +13 -1
- package/data/atlas/atlas.json +25 -25
- package/data/atlas/atlas.jsonld +1 -1
- package/data/atlas/diffusion.json +6 -6
- package/data/atlas/oscillators.json +7 -7
- package/data/atlas/waves.json +14 -14
- package/data/atlas/witness-results.json +11 -11
- package/data/bridge-catalog.json +371 -228
- package/data/bridge-catalog.schema.json +45 -7
- package/dist/atlas/applicability.d.ts.map +1 -1
- package/dist/atlas/applicability.js +21 -15
- package/dist/atlas/applicability.js.map +1 -1
- package/dist/atlas/benchmark/hybrid-retrieval.d.ts +9 -1
- package/dist/atlas/benchmark/hybrid-retrieval.d.ts.map +1 -1
- package/dist/atlas/benchmark/hybrid-retrieval.js +15 -13
- package/dist/atlas/benchmark/hybrid-retrieval.js.map +1 -1
- package/dist/atlas/benchmark/loader.js +2 -2
- package/dist/atlas/benchmark/loader.js.map +1 -1
- package/dist/atlas/benchmark/stats.d.ts +2 -2
- package/dist/atlas/benchmark/stats.d.ts.map +1 -1
- package/dist/atlas/benchmark/stats.js +15 -7
- package/dist/atlas/benchmark/stats.js.map +1 -1
- package/dist/atlas/catalog-formal-ref.d.ts +26 -3
- package/dist/atlas/catalog-formal-ref.d.ts.map +1 -1
- package/dist/atlas/catalog-formal-ref.js +52 -5
- package/dist/atlas/catalog-formal-ref.js.map +1 -1
- package/dist/atlas/chain-pipeline.d.ts.map +1 -1
- package/dist/atlas/chain-pipeline.js +7 -8
- package/dist/atlas/chain-pipeline.js.map +1 -1
- package/dist/atlas/diffusion/bridges-closure.d.ts +0 -4
- package/dist/atlas/diffusion/bridges-closure.d.ts.map +1 -1
- package/dist/atlas/diffusion/bridges-closure.js +8 -12
- package/dist/atlas/diffusion/bridges-closure.js.map +1 -1
- package/dist/atlas/diffusion/bridges.d.ts.map +1 -1
- package/dist/atlas/diffusion/bridges.js +27 -39
- package/dist/atlas/diffusion/bridges.js.map +1 -1
- package/dist/atlas/diffusion/dimensions.d.ts +6 -14
- package/dist/atlas/diffusion/dimensions.d.ts.map +1 -1
- package/dist/atlas/diffusion/dimensions.js +8 -16
- package/dist/atlas/diffusion/dimensions.js.map +1 -1
- package/dist/atlas/diffusion/models.d.ts +3 -3
- package/dist/atlas/diffusion/models.d.ts.map +1 -1
- package/dist/atlas/diffusion/models.js +5 -10
- package/dist/atlas/diffusion/models.js.map +1 -1
- package/dist/atlas/diffusion/numerics.d.ts +16 -4
- package/dist/atlas/diffusion/numerics.d.ts.map +1 -1
- package/dist/atlas/diffusion/numerics.js +38 -24
- package/dist/atlas/diffusion/numerics.js.map +1 -1
- package/dist/atlas/link-prediction.d.ts +106 -3
- package/dist/atlas/link-prediction.d.ts.map +1 -1
- package/dist/atlas/link-prediction.js +212 -66
- package/dist/atlas/link-prediction.js.map +1 -1
- package/dist/atlas/oscillators/bridges-coarse.d.ts.map +1 -1
- package/dist/atlas/oscillators/bridges-coarse.js +7 -11
- package/dist/atlas/oscillators/bridges-coarse.js.map +1 -1
- package/dist/atlas/oscillators/bridges-exact.d.ts.map +1 -1
- package/dist/atlas/oscillators/bridges-exact.js +6 -7
- package/dist/atlas/oscillators/bridges-exact.js.map +1 -1
- package/dist/atlas/oscillators/bridges-limits.d.ts +3 -16
- package/dist/atlas/oscillators/bridges-limits.d.ts.map +1 -1
- package/dist/atlas/oscillators/bridges-limits.js +23 -34
- package/dist/atlas/oscillators/bridges-limits.js.map +1 -1
- package/dist/atlas/oscillators/dimensions.d.ts +9 -21
- package/dist/atlas/oscillators/dimensions.d.ts.map +1 -1
- package/dist/atlas/oscillators/dimensions.js +9 -21
- package/dist/atlas/oscillators/dimensions.js.map +1 -1
- package/dist/atlas/oscillators/limit-witnesses.d.ts +2 -2
- package/dist/atlas/oscillators/limit-witnesses.d.ts.map +1 -1
- package/dist/atlas/oscillators/limit-witnesses.js +17 -15
- package/dist/atlas/oscillators/limit-witnesses.js.map +1 -1
- package/dist/atlas/oscillators/models.d.ts.map +1 -1
- package/dist/atlas/oscillators/models.js +2 -6
- package/dist/atlas/oscillators/models.js.map +1 -1
- package/dist/atlas/oscillators/pendulum-motion.d.ts +29 -6
- package/dist/atlas/oscillators/pendulum-motion.d.ts.map +1 -1
- package/dist/atlas/oscillators/pendulum-motion.js +60 -40
- package/dist/atlas/oscillators/pendulum-motion.js.map +1 -1
- package/dist/atlas/oscillators/phase-translation.d.ts +0 -11
- package/dist/atlas/oscillators/phase-translation.d.ts.map +1 -1
- package/dist/atlas/oscillators/phase-translation.js +3 -4
- package/dist/atlas/oscillators/phase-translation.js.map +1 -1
- package/dist/atlas/oscillators/position-translation.d.ts +68 -7
- package/dist/atlas/oscillators/position-translation.d.ts.map +1 -1
- package/dist/atlas/oscillators/position-translation.js +123 -12
- package/dist/atlas/oscillators/position-translation.js.map +1 -1
- package/dist/atlas/oscillators/rejections.d.ts +0 -2
- package/dist/atlas/oscillators/rejections.d.ts.map +1 -1
- package/dist/atlas/oscillators/rejections.js +0 -7
- package/dist/atlas/oscillators/rejections.js.map +1 -1
- package/dist/atlas/physjs-entries.generated.d.ts +25 -24
- package/dist/atlas/physjs-entries.generated.d.ts.map +1 -1
- package/dist/atlas/physjs-entries.generated.js +25 -24
- package/dist/atlas/physjs-entries.generated.js.map +1 -1
- package/dist/atlas/physjs-ref.d.ts +34 -31
- package/dist/atlas/physjs-ref.d.ts.map +1 -1
- package/dist/atlas/physjs-ref.js +55 -53
- package/dist/atlas/physjs-ref.js.map +1 -1
- package/dist/atlas/physjs-reviewed.d.ts +1 -1
- package/dist/atlas/physjs-reviewed.js +15 -15
- package/dist/atlas/physjs-reviewed.js.map +1 -1
- package/dist/atlas/poster/statements.d.ts +0 -19
- package/dist/atlas/poster/statements.d.ts.map +1 -1
- package/dist/atlas/poster/statements.js +1 -1
- package/dist/atlas/poster/statements.js.map +1 -1
- package/dist/atlas/proof-target.d.ts +1 -1
- package/dist/atlas/proof-target.js +1 -1
- package/dist/atlas/proof-target.js.map +1 -1
- package/dist/atlas/regime.d.ts +1 -1
- package/dist/atlas/regime.d.ts.map +1 -1
- package/dist/atlas/regime.js +1 -1
- package/dist/atlas/regime.js.map +1 -1
- package/dist/atlas/text-overlap.d.ts +23 -0
- package/dist/atlas/text-overlap.d.ts.map +1 -0
- package/dist/atlas/text-overlap.js +41 -0
- package/dist/atlas/text-overlap.js.map +1 -0
- package/dist/atlas/waves/bridges-closure.d.ts.map +1 -1
- package/dist/atlas/waves/bridges-closure.js +2 -6
- package/dist/atlas/waves/bridges-closure.js.map +1 -1
- package/dist/atlas/waves/bridges.d.ts.map +1 -1
- package/dist/atlas/waves/bridges.js +32 -48
- package/dist/atlas/waves/bridges.js.map +1 -1
- package/dist/atlas/waves/models.d.ts +5 -6
- package/dist/atlas/waves/models.d.ts.map +1 -1
- package/dist/atlas/waves/models.js +7 -13
- package/dist/atlas/waves/models.js.map +1 -1
- package/dist/atlas/waves/numerics.d.ts.map +1 -1
- package/dist/atlas/waves/numerics.js +10 -3
- package/dist/atlas/waves/numerics.js.map +1 -1
- package/dist/atlas/witness-numeric.d.ts +30 -0
- package/dist/atlas/witness-numeric.d.ts.map +1 -1
- package/dist/atlas/witness-numeric.js +53 -0
- package/dist/atlas/witness-numeric.js.map +1 -1
- package/dist/atlas/witness-specs.d.ts.map +1 -1
- package/dist/atlas/witness-specs.js +19 -0
- package/dist/atlas/witness-specs.js.map +1 -1
- package/dist/atlas/witness-symbolic.d.ts +75 -3
- package/dist/atlas/witness-symbolic.d.ts.map +1 -1
- package/dist/atlas/witness-symbolic.js +116 -10
- package/dist/atlas/witness-symbolic.js.map +1 -1
- package/dist/bridges/catalog-load.d.ts.map +1 -1
- package/dist/bridges/catalog-load.js +13 -8
- package/dist/bridges/catalog-load.js.map +1 -1
- package/dist/bridges/catalog-types.d.ts +26 -2
- package/dist/bridges/catalog-types.d.ts.map +1 -1
- package/dist/bridges/catalog-types.js +11 -1
- package/dist/bridges/catalog-types.js.map +1 -1
- package/dist/bridges/evaluation-errors.d.ts +31 -1
- package/dist/bridges/evaluation-errors.d.ts.map +1 -1
- package/dist/bridges/evaluation-errors.js +20 -2
- package/dist/bridges/evaluation-errors.js.map +1 -1
- package/dist/bridges/evaluator-inputs.d.ts.map +1 -1
- package/dist/bridges/evaluator-inputs.js +7 -5
- package/dist/bridges/evaluator-inputs.js.map +1 -1
- package/dist/bridges/evaluators.d.ts.map +1 -1
- package/dist/bridges/evaluators.js +27 -12
- package/dist/bridges/evaluators.js.map +1 -1
- package/dist/bridges/expr-parse.d.ts +11 -0
- package/dist/bridges/expr-parse.d.ts.map +1 -1
- package/dist/bridges/expr-parse.js +14 -5
- package/dist/bridges/expr-parse.js.map +1 -1
- package/dist/bridges/holds.d.ts +35 -3
- package/dist/bridges/holds.d.ts.map +1 -1
- package/dist/bridges/holds.js +117 -23
- package/dist/bridges/holds.js.map +1 -1
- package/dist/bridges/notices.d.ts.map +1 -1
- package/dist/bridges/notices.js +5 -5
- package/dist/bridges/notices.js.map +1 -1
- package/dist/bridges/relation-eval.d.ts +4 -4
- package/dist/bridges/relation-eval.d.ts.map +1 -1
- package/dist/bridges/relation-eval.js +15 -16
- package/dist/bridges/relation-eval.js.map +1 -1
- package/dist/bridges/sensitivity.d.ts.map +1 -1
- package/dist/bridges/sensitivity.js +3 -3
- package/dist/bridges/sensitivity.js.map +1 -1
- package/dist/bridges/validity.d.ts +33 -0
- package/dist/bridges/validity.d.ts.map +1 -0
- package/dist/bridges/validity.js +67 -0
- package/dist/bridges/validity.js.map +1 -0
- package/dist/canonical/entries/atomic.js +1 -3
- package/dist/canonical/entries/atomic.js.map +1 -1
- package/dist/canonical/entries/condensed-matter.d.ts.map +1 -1
- package/dist/canonical/entries/condensed-matter.js +4 -5
- package/dist/canonical/entries/condensed-matter.js.map +1 -1
- package/dist/canonical/entries/dimensional-classics.d.ts.map +1 -1
- package/dist/canonical/entries/dimensional-classics.js +3 -4
- package/dist/canonical/entries/dimensional-classics.js.map +1 -1
- package/dist/canonical/entries/electromagnetism.d.ts.map +1 -1
- package/dist/canonical/entries/electromagnetism.js +4 -10
- package/dist/canonical/entries/electromagnetism.js.map +1 -1
- package/dist/canonical/entries/fluids-waves.d.ts.map +1 -1
- package/dist/canonical/entries/fluids-waves.js +3 -7
- package/dist/canonical/entries/fluids-waves.js.map +1 -1
- package/dist/canonical/entries/mechanics.d.ts.map +1 -1
- package/dist/canonical/entries/mechanics.js +4 -6
- package/dist/canonical/entries/mechanics.js.map +1 -1
- package/dist/canonical/entries/nonmonomial.d.ts.map +1 -1
- package/dist/canonical/entries/nonmonomial.js +9 -17
- package/dist/canonical/entries/nonmonomial.js.map +1 -1
- package/dist/canonical/entries/relativity.d.ts.map +1 -1
- package/dist/canonical/entries/relativity.js +6 -6
- package/dist/canonical/entries/relativity.js.map +1 -1
- package/dist/canonical/entries/thermo-nuclear-cosmo.d.ts.map +1 -1
- package/dist/canonical/entries/thermo-nuclear-cosmo.js +6 -10
- package/dist/canonical/entries/thermo-nuclear-cosmo.js.map +1 -1
- package/dist/canonical/fixed-points.d.ts +94 -0
- package/dist/canonical/fixed-points.d.ts.map +1 -0
- package/dist/canonical/fixed-points.js +81 -0
- package/dist/canonical/fixed-points.js.map +1 -0
- package/dist/canonical/linkage.d.ts.map +1 -1
- package/dist/canonical/linkage.js +25 -44
- package/dist/canonical/linkage.js.map +1 -1
- package/dist/canonical/normal-form.d.ts.map +1 -1
- package/dist/canonical/normal-form.js +5 -11
- package/dist/canonical/normal-form.js.map +1 -1
- package/dist/canonical/structural.d.ts +21 -21
- package/dist/canonical/structural.d.ts.map +1 -1
- package/dist/canonical/structural.js +40 -19
- package/dist/canonical/structural.js.map +1 -1
- package/dist/cases/brownian-sphere.d.ts +3 -3
- package/dist/cases/brownian-sphere.d.ts.map +1 -1
- package/dist/cases/brownian-sphere.js +6 -5
- package/dist/cases/brownian-sphere.js.map +1 -1
- package/dist/cases/damped-resonator.d.ts.map +1 -1
- package/dist/cases/damped-resonator.js +6 -9
- package/dist/cases/damped-resonator.js.map +1 -1
- package/dist/cases/kepler-rv.d.ts +1 -1
- package/dist/cases/kepler-rv.d.ts.map +1 -1
- package/dist/cases/kepler-rv.js +3 -2
- package/dist/cases/kepler-rv.js.map +1 -1
- package/dist/cases/lumped-cooling.d.ts +8 -3
- package/dist/cases/lumped-cooling.d.ts.map +1 -1
- package/dist/cases/lumped-cooling.js +21 -23
- package/dist/cases/lumped-cooling.js.map +1 -1
- package/dist/cases/quadrature.d.ts +7 -9
- package/dist/cases/quadrature.d.ts.map +1 -1
- package/dist/cases/quadrature.js +28 -32
- package/dist/cases/quadrature.js.map +1 -1
- package/dist/cases/resistor-noise.js +4 -4
- package/dist/cases/resistor-noise.js.map +1 -1
- package/dist/cases/skin-depth.d.ts +0 -4
- package/dist/cases/skin-depth.d.ts.map +1 -1
- package/dist/cases/skin-depth.js +3 -7
- package/dist/cases/skin-depth.js.map +1 -1
- package/dist/cli/args.d.ts +23 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +30 -8
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/bindings.d.ts.map +1 -1
- package/dist/cli/bindings.js +5 -4
- package/dist/cli/bindings.js.map +1 -1
- package/dist/cli/command.d.ts +8 -1
- package/dist/cli/command.d.ts.map +1 -1
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/commands/_atlas-map.d.ts +0 -9
- package/dist/cli/commands/_atlas-map.d.ts.map +1 -1
- package/dist/cli/commands/_atlas-map.js +8 -18
- package/dist/cli/commands/_atlas-map.js.map +1 -1
- package/dist/cli/commands/_atlas-route.d.ts.map +1 -1
- package/dist/cli/commands/_atlas-route.js +6 -2
- package/dist/cli/commands/_atlas-route.js.map +1 -1
- package/dist/cli/commands/_discovery-opts.d.ts.map +1 -1
- package/dist/cli/commands/_discovery-opts.js +8 -9
- package/dist/cli/commands/_discovery-opts.js.map +1 -1
- package/dist/cli/commands/atlas.d.ts.map +1 -1
- package/dist/cli/commands/atlas.js +8 -5
- package/dist/cli/commands/atlas.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +8 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/axes.d.ts.map +1 -1
- package/dist/cli/commands/axes.js +20 -1
- package/dist/cli/commands/axes.js.map +1 -1
- package/dist/cli/commands/confront.d.ts.map +1 -1
- package/dist/cli/commands/confront.js +8 -14
- package/dist/cli/commands/confront.js.map +1 -1
- package/dist/cli/commands/derive.d.ts.map +1 -1
- package/dist/cli/commands/derive.js +22 -22
- package/dist/cli/commands/derive.js.map +1 -1
- package/dist/cli/commands/discover.d.ts.map +1 -1
- package/dist/cli/commands/discover.js +6 -2
- package/dist/cli/commands/discover.js.map +1 -1
- package/dist/cli/commands/eval.d.ts.map +1 -1
- package/dist/cli/commands/eval.js +1 -0
- package/dist/cli/commands/eval.js.map +1 -1
- package/dist/cli/commands/evaluate.d.ts.map +1 -1
- package/dist/cli/commands/evaluate.js +65 -37
- package/dist/cli/commands/evaluate.js.map +1 -1
- package/dist/cli/commands/explain.d.ts.map +1 -1
- package/dist/cli/commands/explain.js +2 -1
- package/dist/cli/commands/explain.js.map +1 -1
- package/dist/cli/commands/ground.d.ts.map +1 -1
- package/dist/cli/commands/ground.js +1 -0
- package/dist/cli/commands/ground.js.map +1 -1
- package/dist/cli/commands/map.d.ts.map +1 -1
- package/dist/cli/commands/map.js +75 -5
- package/dist/cli/commands/map.js.map +1 -1
- package/dist/cli/commands/metric.d.ts.map +1 -1
- package/dist/cli/commands/metric.js +12 -9
- package/dist/cli/commands/metric.js.map +1 -1
- package/dist/cli/commands/path.d.ts +10 -0
- package/dist/cli/commands/path.d.ts.map +1 -1
- package/dist/cli/commands/path.js +25 -3
- package/dist/cli/commands/path.js.map +1 -1
- package/dist/cli/commands/probe.d.ts.map +1 -1
- package/dist/cli/commands/probe.js +59 -16
- package/dist/cli/commands/probe.js.map +1 -1
- package/dist/cli/commands/regime.d.ts.map +1 -1
- package/dist/cli/commands/regime.js +1 -0
- package/dist/cli/commands/regime.js.map +1 -1
- package/dist/cli/commands/retrieve.d.ts.map +1 -1
- package/dist/cli/commands/retrieve.js +1 -0
- package/dist/cli/commands/retrieve.js.map +1 -1
- package/dist/cli/commands/search.d.ts.map +1 -1
- package/dist/cli/commands/search.js +1 -0
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/symbolic.d.ts.map +1 -1
- package/dist/cli/commands/symbolic.js +19 -28
- package/dist/cli/commands/symbolic.js.map +1 -1
- package/dist/cli/commands/testplan.d.ts.map +1 -1
- package/dist/cli/commands/testplan.js +4 -2
- package/dist/cli/commands/testplan.js.map +1 -1
- package/dist/cli/expr-print.d.ts +0 -2
- package/dist/cli/expr-print.d.ts.map +1 -1
- package/dist/cli/expr-print.js +7 -31
- package/dist/cli/expr-print.js.map +1 -1
- package/dist/cli/main.d.ts +7 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +18 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/numeric-flag.d.ts +12 -0
- package/dist/cli/numeric-flag.d.ts.map +1 -0
- package/dist/cli/numeric-flag.js +44 -0
- package/dist/cli/numeric-flag.js.map +1 -0
- package/dist/cli/output.d.ts +20 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +15 -0
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/record-reach.js +2 -2
- package/dist/cli/record-reach.js.map +1 -1
- package/dist/cli/record-tables.d.ts.map +1 -1
- package/dist/cli/record-tables.js +6 -5
- package/dist/cli/record-tables.js.map +1 -1
- package/dist/cli/record.d.ts +1 -5
- package/dist/cli/record.d.ts.map +1 -1
- package/dist/cli/record.js +9 -8
- package/dist/cli/record.js.map +1 -1
- package/dist/cli/search-index.d.ts.map +1 -1
- package/dist/cli/search-index.js +7 -6
- package/dist/cli/search-index.js.map +1 -1
- package/dist/cli/statuses.d.ts +0 -2
- package/dist/cli/statuses.d.ts.map +1 -1
- package/dist/cli/statuses.js +0 -7
- package/dist/cli/statuses.js.map +1 -1
- package/dist/cli/stored-results.d.ts +7 -0
- package/dist/cli/stored-results.d.ts.map +1 -0
- package/dist/cli/stored-results.js +23 -0
- package/dist/cli/stored-results.js.map +1 -0
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +7 -5
- package/dist/cli/version.js.map +1 -1
- package/dist/cli-api.d.ts +34 -5
- package/dist/cli-api.d.ts.map +1 -1
- package/dist/cli-api.js +28 -4
- package/dist/cli-api.js.map +1 -1
- package/dist/composition/algebraic-equivalence.d.ts +43 -0
- package/dist/composition/algebraic-equivalence.d.ts.map +1 -0
- package/dist/composition/algebraic-equivalence.js +115 -0
- package/dist/composition/algebraic-equivalence.js.map +1 -0
- package/dist/composition/axes.d.ts +0 -6
- package/dist/composition/axes.d.ts.map +1 -1
- package/dist/composition/axes.js +6 -6
- package/dist/composition/axes.js.map +1 -1
- package/dist/composition/axis-audit.d.ts +47 -20
- package/dist/composition/axis-audit.d.ts.map +1 -1
- package/dist/composition/axis-audit.js +82 -9
- package/dist/composition/axis-audit.js.map +1 -1
- package/dist/composition/bridge-analysis.d.ts +17 -0
- package/dist/composition/bridge-analysis.d.ts.map +1 -1
- package/dist/composition/bridge-analysis.js +102 -55
- package/dist/composition/bridge-analysis.js.map +1 -1
- package/dist/composition/canonical-compare.d.ts +40 -0
- package/dist/composition/canonical-compare.d.ts.map +1 -1
- package/dist/composition/canonical-compare.js +122 -24
- package/dist/composition/canonical-compare.js.map +1 -1
- package/dist/composition/canonical-graph.d.ts +1 -1
- package/dist/composition/canonical-graph.d.ts.map +1 -1
- package/dist/composition/canonical-graph.js +9 -36
- package/dist/composition/canonical-graph.js.map +1 -1
- package/dist/composition/canonical-json.js +2 -2
- package/dist/composition/canonical-json.js.map +1 -1
- package/dist/composition/catalog-graph.d.ts.map +1 -1
- package/dist/composition/catalog-graph.js +2 -5
- package/dist/composition/catalog-graph.js.map +1 -1
- package/dist/composition/chain-candidate.d.ts +8 -0
- package/dist/composition/chain-candidate.d.ts.map +1 -1
- package/dist/composition/chain-candidate.js +9 -2
- package/dist/composition/chain-candidate.js.map +1 -1
- package/dist/composition/chain-match.d.ts +6 -3
- package/dist/composition/chain-match.d.ts.map +1 -1
- package/dist/composition/chain-match.js +4 -1
- package/dist/composition/chain-match.js.map +1 -1
- package/dist/composition/chain-result.d.ts.map +1 -1
- package/dist/composition/chain-result.js +2 -14
- package/dist/composition/chain-result.js.map +1 -1
- package/dist/composition/compose-symbolic.d.ts.map +1 -1
- package/dist/composition/compose-symbolic.js +3 -2
- package/dist/composition/compose-symbolic.js.map +1 -1
- package/dist/composition/compose.d.ts.map +1 -1
- package/dist/composition/compose.js +13 -5
- package/dist/composition/compose.js.map +1 -1
- package/dist/composition/composition-recovery.d.ts.map +1 -1
- package/dist/composition/composition-recovery.js +4 -7
- package/dist/composition/composition-recovery.js.map +1 -1
- package/dist/composition/discovery.d.ts +56 -0
- package/dist/composition/discovery.d.ts.map +1 -1
- package/dist/composition/discovery.js +114 -60
- package/dist/composition/discovery.js.map +1 -1
- package/dist/composition/edge.d.ts +21 -2
- package/dist/composition/edge.d.ts.map +1 -1
- package/dist/composition/edge.js +23 -1
- package/dist/composition/edge.js.map +1 -1
- package/dist/composition/enumerate.d.ts.map +1 -1
- package/dist/composition/enumerate.js +18 -3
- package/dist/composition/enumerate.js.map +1 -1
- package/dist/composition/evaluate-relation.d.ts +35 -11
- package/dist/composition/evaluate-relation.d.ts.map +1 -1
- package/dist/composition/evaluate-relation.js +60 -39
- package/dist/composition/evaluate-relation.js.map +1 -1
- package/dist/composition/explain.d.ts +3 -12
- package/dist/composition/explain.d.ts.map +1 -1
- package/dist/composition/explain.js +7 -20
- package/dist/composition/explain.js.map +1 -1
- package/dist/composition/expr-eval.d.ts.map +1 -1
- package/dist/composition/expr-eval.js +2 -11
- package/dist/composition/expr-eval.js.map +1 -1
- package/dist/composition/expr-simplify.d.ts +16 -0
- package/dist/composition/expr-simplify.d.ts.map +1 -1
- package/dist/composition/expr-simplify.js +15 -20
- package/dist/composition/expr-simplify.js.map +1 -1
- package/dist/composition/formula-shape.d.ts +23 -4
- package/dist/composition/formula-shape.d.ts.map +1 -1
- package/dist/composition/formula-shape.js +57 -17
- package/dist/composition/formula-shape.js.map +1 -1
- package/dist/composition/graph-structure.d.ts +98 -0
- package/dist/composition/graph-structure.d.ts.map +1 -0
- package/dist/composition/graph-structure.js +167 -0
- package/dist/composition/graph-structure.js.map +1 -0
- package/dist/composition/graph-viz-svg.d.ts.map +1 -1
- package/dist/composition/graph-viz-svg.js +1 -1
- package/dist/composition/graph-viz-svg.js.map +1 -1
- package/dist/composition/graph-viz.d.ts.map +1 -1
- package/dist/composition/graph-viz.js +8 -37
- package/dist/composition/graph-viz.js.map +1 -1
- package/dist/composition/identifiability.d.ts +91 -4
- package/dist/composition/identifiability.d.ts.map +1 -1
- package/dist/composition/identifiability.js +363 -6
- package/dist/composition/identifiability.js.map +1 -1
- package/dist/composition/index.d.ts +8 -4
- package/dist/composition/index.d.ts.map +1 -1
- package/dist/composition/index.js +3 -2
- package/dist/composition/index.js.map +1 -1
- package/dist/composition/mathts-quiet.d.ts +4 -3
- package/dist/composition/mathts-quiet.d.ts.map +1 -1
- package/dist/composition/mathts-quiet.js +4 -3
- package/dist/composition/mathts-quiet.js.map +1 -1
- package/dist/composition/mathts-scalar-symbols.d.ts.map +1 -1
- package/dist/composition/mathts-scalar-symbols.js +2 -1
- package/dist/composition/mathts-scalar-symbols.js.map +1 -1
- package/dist/composition/probe/corpus.d.ts +4 -2
- package/dist/composition/probe/corpus.d.ts.map +1 -1
- package/dist/composition/probe/corpus.js +20 -9
- package/dist/composition/probe/corpus.js.map +1 -1
- package/dist/composition/probe/dataset.d.ts +17 -0
- package/dist/composition/probe/dataset.d.ts.map +1 -1
- package/dist/composition/probe/dataset.js +95 -50
- package/dist/composition/probe/dataset.js.map +1 -1
- package/dist/composition/probe/experiment-design.d.ts +5 -1
- package/dist/composition/probe/experiment-design.d.ts.map +1 -1
- package/dist/composition/probe/experiment-design.js +44 -24
- package/dist/composition/probe/experiment-design.js.map +1 -1
- package/dist/composition/probe/falsify.d.ts.map +1 -1
- package/dist/composition/probe/falsify.js +2 -0
- package/dist/composition/probe/falsify.js.map +1 -1
- package/dist/composition/probe/fit.d.ts +6 -0
- package/dist/composition/probe/fit.d.ts.map +1 -1
- package/dist/composition/probe/fit.js +46 -22
- package/dist/composition/probe/fit.js.map +1 -1
- package/dist/composition/probe/frontier.d.ts.map +1 -1
- package/dist/composition/probe/frontier.js +33 -15
- package/dist/composition/probe/frontier.js.map +1 -1
- package/dist/composition/probe/generator.d.ts +27 -1
- package/dist/composition/probe/generator.d.ts.map +1 -1
- package/dist/composition/probe/generator.js +53 -30
- package/dist/composition/probe/generator.js.map +1 -1
- package/dist/composition/probe/index.d.ts +14 -0
- package/dist/composition/probe/index.d.ts.map +1 -1
- package/dist/composition/probe/index.js +6 -0
- package/dist/composition/probe/index.js.map +1 -1
- package/dist/composition/probe/limits.d.ts +24 -1
- package/dist/composition/probe/limits.d.ts.map +1 -1
- package/dist/composition/probe/limits.js +53 -11
- package/dist/composition/probe/limits.js.map +1 -1
- package/dist/composition/probe/pipeline.d.ts.map +1 -1
- package/dist/composition/probe/pipeline.js +10 -4
- package/dist/composition/probe/pipeline.js.map +1 -1
- package/dist/composition/probe/power-law.d.ts +121 -0
- package/dist/composition/probe/power-law.d.ts.map +1 -0
- package/dist/composition/probe/power-law.js +255 -0
- package/dist/composition/probe/power-law.js.map +1 -0
- package/dist/composition/probe/problem.d.ts +7 -4
- package/dist/composition/probe/problem.d.ts.map +1 -1
- package/dist/composition/probe/problem.js +177 -49
- package/dist/composition/probe/problem.js.map +1 -1
- package/dist/composition/probe/report.js +1 -1
- package/dist/composition/probe/report.js.map +1 -1
- package/dist/composition/probe/residual.d.ts +6 -1
- package/dist/composition/probe/residual.d.ts.map +1 -1
- package/dist/composition/probe/residual.js +9 -7
- package/dist/composition/probe/residual.js.map +1 -1
- package/dist/composition/probe/structure.d.ts +82 -17
- package/dist/composition/probe/structure.d.ts.map +1 -1
- package/dist/composition/probe/structure.js +129 -55
- package/dist/composition/probe/structure.js.map +1 -1
- package/dist/composition/probe/study.d.ts +31 -9
- package/dist/composition/probe/study.d.ts.map +1 -1
- package/dist/composition/probe/study.js +236 -181
- package/dist/composition/probe/study.js.map +1 -1
- package/dist/composition/probe/t-tail.d.ts +17 -0
- package/dist/composition/probe/t-tail.d.ts.map +1 -0
- package/dist/composition/probe/t-tail.js +32 -0
- package/dist/composition/probe/t-tail.js.map +1 -0
- package/dist/composition/probe/types.d.ts +3 -0
- package/dist/composition/probe/types.d.ts.map +1 -1
- package/dist/composition/probe/types.js.map +1 -1
- package/dist/composition/proposed-bridges.d.ts +41 -10
- package/dist/composition/proposed-bridges.d.ts.map +1 -1
- package/dist/composition/proposed-bridges.js +100 -55
- package/dist/composition/proposed-bridges.js.map +1 -1
- package/dist/composition/quantity-clusters.d.ts +48 -0
- package/dist/composition/quantity-clusters.d.ts.map +1 -0
- package/dist/composition/quantity-clusters.js +98 -0
- package/dist/composition/quantity-clusters.js.map +1 -0
- package/dist/composition/rational-exponent.d.ts +40 -0
- package/dist/composition/rational-exponent.d.ts.map +1 -0
- package/dist/composition/rational-exponent.js +65 -0
- package/dist/composition/rational-exponent.js.map +1 -0
- package/dist/composition/representative-values.d.ts +22 -0
- package/dist/composition/representative-values.d.ts.map +1 -1
- package/dist/composition/representative-values.js +23 -0
- package/dist/composition/representative-values.js.map +1 -1
- package/dist/composition/retrodiction.d.ts.map +1 -1
- package/dist/composition/retrodiction.js +2 -1
- package/dist/composition/retrodiction.js.map +1 -1
- package/dist/composition/user-equation.d.ts.map +1 -1
- package/dist/composition/user-equation.js +2 -2
- package/dist/composition/user-equation.js.map +1 -1
- package/dist/core/assignment.d.ts +19 -0
- package/dist/core/assignment.d.ts.map +1 -0
- package/dist/core/assignment.js +19 -0
- package/dist/core/assignment.js.map +1 -0
- package/dist/core/compare.d.ts +32 -0
- package/dist/core/compare.d.ts.map +1 -0
- package/dist/core/compare.js +46 -0
- package/dist/core/compare.js.map +1 -0
- package/dist/core/constants.d.ts +30 -30
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +47 -30
- package/dist/core/constants.js.map +1 -1
- package/dist/core/data-file.d.ts +7 -0
- package/dist/core/data-file.d.ts.map +1 -1
- package/dist/core/data-file.js +17 -0
- package/dist/core/data-file.js.map +1 -1
- package/dist/core/format.d.ts +36 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +39 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/hash.d.ts +14 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/hash.js +17 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/json-schema.d.ts +2 -0
- package/dist/core/json-schema.d.ts.map +1 -1
- package/dist/core/json-schema.js +14 -13
- package/dist/core/json-schema.js.map +1 -1
- package/dist/core/labeled-tensor.d.ts.map +1 -1
- package/dist/core/labeled-tensor.js +0 -8
- package/dist/core/labeled-tensor.js.map +1 -1
- package/dist/core/mathts-read.d.ts +25 -0
- package/dist/core/mathts-read.d.ts.map +1 -0
- package/dist/core/mathts-read.js +51 -0
- package/dist/core/mathts-read.js.map +1 -0
- package/dist/core/tensor.d.ts.map +1 -1
- package/dist/core/tensor.js +24 -0
- package/dist/core/tensor.js.map +1 -1
- package/dist/core/types.d.ts +5 -5
- package/dist/diff/bridge-gradient.d.ts +19 -6
- package/dist/diff/bridge-gradient.d.ts.map +1 -1
- package/dist/diff/bridge-gradient.js +19 -11
- package/dist/diff/bridge-gradient.js.map +1 -1
- package/dist/diff/bridge-specs.d.ts.map +1 -1
- package/dist/diff/bridge-specs.js +3 -0
- package/dist/diff/bridge-specs.js.map +1 -1
- package/dist/dimensional/algebra.d.ts +18 -0
- package/dist/dimensional/algebra.d.ts.map +1 -1
- package/dist/dimensional/algebra.js +41 -1
- package/dist/dimensional/algebra.js.map +1 -1
- package/dist/dimensional/ast-builders.d.ts +7 -0
- package/dist/dimensional/ast-builders.d.ts.map +1 -1
- package/dist/dimensional/ast-builders.js +11 -0
- package/dist/dimensional/ast-builders.js.map +1 -1
- package/dist/dimensional/ast-leaves.d.ts +81 -0
- package/dist/dimensional/ast-leaves.d.ts.map +1 -0
- package/dist/dimensional/ast-leaves.js +146 -0
- package/dist/dimensional/ast-leaves.js.map +1 -0
- package/dist/dimensional/buckingham.d.ts.map +1 -1
- package/dist/dimensional/buckingham.js +15 -27
- package/dist/dimensional/buckingham.js.map +1 -1
- package/dist/dimensional/constant-rows.js +9 -9
- package/dist/dimensional/constant-rows.js.map +1 -1
- package/dist/dimensional/dimension-inference.d.ts.map +1 -1
- package/dist/dimensional/dimension-inference.js +1 -2
- package/dist/dimensional/dimension-inference.js.map +1 -1
- package/dist/dimensional/errors.d.ts +1 -1
- package/dist/dimensional/errors.d.ts.map +1 -1
- package/dist/dimensional/errors.js +1 -15
- package/dist/dimensional/errors.js.map +1 -1
- package/dist/dimensional/exact-scale.d.ts +0 -17
- package/dist/dimensional/exact-scale.d.ts.map +1 -1
- package/dist/dimensional/exact-scale.js +8 -8
- package/dist/dimensional/exact-scale.js.map +1 -1
- package/dist/dimensional/gauge-field.d.ts.map +1 -1
- package/dist/dimensional/gauge-field.js +2 -2
- package/dist/dimensional/gauge-field.js.map +1 -1
- package/dist/dimensional/hyphen-names.d.ts +12 -2
- package/dist/dimensional/hyphen-names.d.ts.map +1 -1
- package/dist/dimensional/hyphen-names.js +44 -19
- package/dist/dimensional/hyphen-names.js.map +1 -1
- package/dist/dimensional/metric.d.ts.map +1 -1
- package/dist/dimensional/metric.js +0 -1
- package/dist/dimensional/metric.js.map +1 -1
- package/dist/dimensional/symbolic-constants.d.ts +9 -0
- package/dist/dimensional/symbolic-constants.d.ts.map +1 -1
- package/dist/dimensional/symbolic-constants.js +13 -1
- package/dist/dimensional/symbolic-constants.js.map +1 -1
- package/dist/dimensional/types.d.ts +36 -0
- package/dist/dimensional/types.d.ts.map +1 -1
- package/dist/dimensional/types.js +45 -7
- package/dist/dimensional/types.js.map +1 -1
- package/dist/dimensional/unit-data.js +2 -2
- package/dist/dimensional/unit-data.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/numerical/christoffel-flat.d.ts.map +1 -1
- package/dist/numerical/christoffel-flat.js +3 -2
- package/dist/numerical/christoffel-flat.js.map +1 -1
- package/dist/numerical/covariant-eikonal.d.ts.map +1 -1
- package/dist/numerical/covariant-eikonal.js +34 -11
- package/dist/numerical/covariant-eikonal.js.map +1 -1
- package/dist/numerical/curvature-lowering-helpers.js +3 -2
- package/dist/numerical/curvature-lowering-helpers.js.map +1 -1
- package/dist/numerical/errors.d.ts.map +1 -1
- package/dist/numerical/errors.js +0 -3
- package/dist/numerical/errors.js.map +1 -1
- package/dist/numerical/finite-difference.d.ts +22 -0
- package/dist/numerical/finite-difference.d.ts.map +1 -0
- package/dist/numerical/finite-difference.js +27 -0
- package/dist/numerical/finite-difference.js.map +1 -0
- package/dist/numerical/geodesic-integrator.d.ts.map +1 -1
- package/dist/numerical/geodesic-integrator.js +22 -14
- package/dist/numerical/geodesic-integrator.js.map +1 -1
- package/dist/numerical/geometrized.d.ts.map +1 -1
- package/dist/numerical/geometrized.js +0 -1
- package/dist/numerical/geometrized.js.map +1 -1
- package/dist/numerical/mathts-engine.d.ts.map +1 -1
- package/dist/numerical/mathts-engine.js +10 -24
- package/dist/numerical/mathts-engine.js.map +1 -1
- package/dist/numerical/metric-inverse.d.ts.map +1 -1
- package/dist/numerical/metric-inverse.js +83 -46
- package/dist/numerical/metric-inverse.js.map +1 -1
- package/dist/numerical/null-ray-integrator.d.ts +2 -1
- package/dist/numerical/null-ray-integrator.d.ts.map +1 -1
- package/dist/numerical/null-ray-integrator.js +12 -12
- package/dist/numerical/null-ray-integrator.js.map +1 -1
- package/dist/numerical/painleve-gullstrand-metric.js +2 -2
- package/dist/numerical/painleve-gullstrand-metric.js.map +1 -1
- package/dist/numerical/perihelion-finder.d.ts +0 -36
- package/dist/numerical/perihelion-finder.d.ts.map +1 -1
- package/dist/numerical/perihelion-finder.js +41 -87
- package/dist/numerical/perihelion-finder.js.map +1 -1
- package/dist/numerical/quadrature.d.ts.map +1 -1
- package/dist/numerical/quadrature.js +8 -10
- package/dist/numerical/quadrature.js.map +1 -1
- package/dist/numerical/rk4-trajectory.d.ts +10 -0
- package/dist/numerical/rk4-trajectory.d.ts.map +1 -0
- package/dist/numerical/rk4-trajectory.js +37 -0
- package/dist/numerical/rk4-trajectory.js.map +1 -0
- package/dist/numerical/schwarzschild.d.ts +14 -0
- package/dist/numerical/schwarzschild.d.ts.map +1 -0
- package/dist/numerical/schwarzschild.js +17 -0
- package/dist/numerical/schwarzschild.js.map +1 -0
- package/dist/numerical/spacetime-metrics.d.ts +12 -0
- package/dist/numerical/spacetime-metrics.d.ts.map +1 -1
- package/dist/numerical/spacetime-metrics.js +72 -56
- package/dist/numerical/spacetime-metrics.js.map +1 -1
- package/dist/numerical/statistics.d.ts +24 -0
- package/dist/numerical/statistics.d.ts.map +1 -0
- package/dist/numerical/statistics.js +52 -0
- package/dist/numerical/statistics.js.map +1 -0
- package/dist/numerical/tensor-engine.d.ts +21 -0
- package/dist/numerical/tensor-engine.d.ts.map +1 -1
- package/dist/numerical/tensor-engine.js +12 -0
- package/dist/numerical/tensor-engine.js.map +1 -1
- package/dist/relations/regime.d.ts +10 -0
- package/dist/relations/regime.d.ts.map +1 -1
- package/dist/relations/regime.js +18 -1
- package/dist/relations/regime.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"null-ray-integrator.js","sourceRoot":"","sources":["../../src/numerical/null-ray-integrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"null-ray-integrator.js","sourceRoot":"","sources":["../../src/numerical/null-ray-integrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOpD,SAAS,WAAW,CAAC,CAAwB,EAAE,QAAgB;IAC7D,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,qBAAqB,CAC7B,8DAA8D,CAAC,CAAC,MAAM,cAAc,QAAQ,EAAE,CAC/F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAiB,EACjB,EAAyB,EACzB,OAAe,EACf,OAAe,EACf,KAAa;IAEb,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,qBAAqB,CAAC,4DAA4D,KAAK,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACvB,MAAM,MAAM,GAAG,aAAa,CAC1B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACZ,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC5B,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,CAAC,CAAC;IACX,CAAC,EACD,MAAM,EACN,OAAO,EACP,OAAO,EACP,KAAK,CACN,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * Fixed-step classical RK4 integrator for affine-parameterized null\n * geodesics, and the one-step RK4 the atlas and case modules call. The\n * covariant-eikonal path (`src/numerical/covariant-eikonal.ts`) uses the\n * symplectic `integrateGeodesicGL4` instead. The fixed steps are\n * `rk4Trajectory` (`rk4-trajectory.ts`, MathTS `solveODESystem` with `dt`),\n * the one owner of the step count; this module returns its last state.\n * Operates on plain `number[]` state vectors, no TensorEngine dependency.\n *\n * @module numerical/null-ray-integrator\n */\nimport { NumericalBackendError } from './errors.js';\nimport { rk4Trajectory } from './rk4-trajectory.js';\n\n/** A first-order ODE system: dy/dλ = f(λ, y). `y` and the return are\n * state vectors of equal length.\n * v0.6.1: dropped export — was @internal-tagged with no external consumer. */\ntype ODESystem = (lambda: number, y: ReadonlyArray<number>) => number[];\n\nfunction checkLength(k: ReadonlyArray<number>, expected: number): void {\n if (k.length !== expected) {\n throw new NumericalBackendError(\n `integrateRK4: ODE system returned a state vector of length ${k.length}, expected ${expected}`,\n );\n }\n}\n\n/**\n * Integrate `system` from affine parameter `lambda0` to `lambda1` in\n * `steps` fixed RK4 steps, starting from state `y0`. Returns the final\n * state vector. Classical 4th-order Runge-Kutta — global error O(h⁴). It takes\n * exactly `steps` steps of (lambda1 − lambda0)/steps (`rk4Trajectory`).\n *\n * @internal — cross-module/test use only; not part of the consumer surface.\n */\nexport function integrateRK4(\n system: ODESystem,\n y0: ReadonlyArray<number>,\n lambda0: number,\n lambda1: number,\n steps: number,\n): number[] {\n if (!Number.isInteger(steps) || steps <= 0) {\n throw new NumericalBackendError(`integrateRK4: step count must be a positive integer, got ${steps}`);\n }\n const yStart = [...y0];\n const states = rk4Trajectory(\n (lambda, y) => {\n const k = system(lambda, y);\n checkLength(k, yStart.length);\n return k;\n },\n yStart,\n lambda0,\n lambda1,\n steps,\n );\n return states[states.length - 1] ?? yStart;\n}\n"]}
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
*
|
|
51
51
|
* @module numerical/painleve-gullstrand-metric
|
|
52
52
|
*/
|
|
53
|
-
import {
|
|
53
|
+
import { schwarzschildRadius } from './schwarzschild.js';
|
|
54
54
|
/**
|
|
55
55
|
* Schwarzschild radius `r_s = 2 G M / c²` for a body of mass `M`.
|
|
56
56
|
* Inlined here to avoid an out-of-rootDir import on the test
|
|
@@ -59,7 +59,7 @@ import { C_SI, G_SI } from '../core/constants.js';
|
|
|
59
59
|
* @internal
|
|
60
60
|
*/
|
|
61
61
|
function schwarzschildRs(M_kg) {
|
|
62
|
-
return (
|
|
62
|
+
return schwarzschildRadius(M_kg);
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* Builds a Painlevé-Gullstrand metric function `g_μν(T, r, θ, φ)`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"painleve-gullstrand-metric.js","sourceRoot":"","sources":["../../src/numerical/painleve-gullstrand-metric.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"painleve-gullstrand-metric.js","sourceRoot":"","sources":["../../src/numerical/painleve-gullstrand-metric.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Painlevé-Gullstrand (PG) metric for Schwarzschild spacetime —\n * regular at the event horizon.\n *\n * Per `docs/architecture/archive/v0.7-near-horizon-kretschmann-design-note.md`\n * (v0.7 follow-up to v0.6.0's deferred \"Near-horizon Kretschmann\"\n * item). Schwarzschild coordinates have a coordinate singularity at\n * `r = r_s` (the event horizon); `g_rr = 1/(1−r_s/r) → ∞`. The\n * Painlevé-Gullstrand coordinate system is regular at the horizon\n * (and everywhere outside the curvature singularity at `r=0`).\n *\n * Coordinate transform (closed-form, no implicit-function solve):\n *\n * T = t + 2√(r·r_s) + r_s·ln|(√r − √r_s)/(√r + √r_s)|\n *\n * In PG coordinates (T, r, θ, φ):\n *\n * ds² = -(1 − r_s/r) dT² + 2√(r_s/r) dT dr + dr² + r² dΩ²\n *\n * Matrix form:\n *\n * g_μν = [[-(1−r_s/r), √(r_s/r), 0, 0 ],\n * [ √(r_s/r), 1, 0, 0 ],\n * [ 0, 0, r², 0 ],\n * [ 0, 0, 0, r² sin²θ ]]\n *\n * Inverse (closed-form via 2x2 block inverse on the (T,r) block,\n * det = -1):\n *\n * g^μν = [[-1, √(r_s/r), 0, 0 ],\n * [ √(r_s/r), (1−r_s/r), 0, 0 ],\n * [ 0, 0, 1/r², 0 ],\n * [ 0, 0, 0, 1/(r² sin²θ)]]\n *\n * Verification at the horizon:\n *\n * r → r_s: g_TT → 0, g_Tr → 1, g_rr → 1 (all finite)\n * g^rr → 0, g^Tr → 1, g^TT → -1 (all finite)\n *\n * Compare to Schwarzschild where g_rr → ∞. The Kretschmann\n * scalar K = R_μνρσ R^μνρσ is computed via the existing\n * `numerical/kretschmann.ts` (coordinate-agnostic — takes raw\n * arrays) fed by Riemann assembled from these closed-form metric\n * functions via the existing FD pipeline. At r=r_s the analytic\n * value `K = 48 G²M²/(c⁴ r_s⁶) = 12/r_s⁴` (in c=G=1 units) is\n * recovered numerically without coordinate-singularity blowup.\n *\n * Reference: MTW §31.4 (\"Lemaître coordinates\" + the\n * Painlevé-Gullstrand variant); Carroll §5.7.\n *\n * @module numerical/painleve-gullstrand-metric\n */\n\nimport { schwarzschildRadius } from './schwarzschild.js';\nimport type { MetricFnFlat } from './curvature-lowering-helpers.js';\n\n/**\n * Schwarzschild radius `r_s = 2 G M / c²` for a body of mass `M`.\n * Inlined here to avoid an out-of-rootDir import on the test\n * fixture's `schwarzschildRs` helper. Same formula.\n *\n * @internal\n */\nfunction schwarzschildRs(M_kg: number): number {\n return schwarzschildRadius(M_kg);\n}\n\n/**\n * Builds a Painlevé-Gullstrand metric function `g_μν(T, r, θ, φ)`\n * for a Schwarzschild black hole of mass `M_kg`.\n *\n * The returned function maps a 4-tuple coordinate point to the\n * 4×4 lower-lower metric as a row-major `Float64Array(16)` —\n * `flat[mu*4 + nu] = g_{μν}` (v0.9.0 O-6 migration, mirroring the\n * v0.6.0 BR-2 christoffelFn convention). Closed-form; no FD;\n * regular at r=r_s.\n *\n * BREAKING (v0.9.0) for subpath-import consumers: previously\n * returned `number[][]`.\n *\n * @public\n */\nexport function painleveGullstrandGFn(M_kg: number): MetricFnFlat {\n const r_s = schwarzschildRs(M_kg);\n return function pgG(x: ReadonlyArray<number>): Float64Array {\n const r = x[1];\n const theta = x[2];\n if (!(r > 0)) {\n throw new RangeError(`painleveGullstrandGFn: r must be > 0, got ${r}`);\n }\n const rho = r_s / r;\n const sqrtRho = Math.sqrt(rho);\n const sinTheta = Math.sin(theta);\n const out = new Float64Array(16);\n out[0 * 4 + 0] = -(1 - rho);\n out[0 * 4 + 1] = sqrtRho;\n out[1 * 4 + 0] = sqrtRho;\n out[1 * 4 + 1] = 1;\n out[2 * 4 + 2] = r * r;\n out[3 * 4 + 3] = r * r * sinTheta * sinTheta;\n return out;\n };\n}\n\n/**\n * Builds a Painlevé-Gullstrand inverse-metric function `g^μν(T, r,\n * θ, φ)`. Closed-form (2×2 block inverse on the (T, r) block,\n * det = -1; angular block is trivially diagonal).\n *\n * Returns a row-major `Float64Array(16)` — `flat[mu*4 + nu] = g^{μν}`\n * (v0.9.0 O-6 migration). At r=r_s, g^rr=0 (the horizon's\n * coordinate-regularity signature in PG: NO divergence). At r→∞,\n * g^rr → 1 (asymptotic flatness).\n *\n * BREAKING (v0.9.0) for subpath-import consumers: previously\n * returned `number[][]`.\n *\n * @public\n */\nexport function painleveGullstrandGInverseFn(M_kg: number): MetricFnFlat {\n const r_s = schwarzschildRs(M_kg);\n return function pgGInv(x: ReadonlyArray<number>): Float64Array {\n const r = x[1];\n const theta = x[2];\n if (!(r > 0)) {\n throw new RangeError(`painleveGullstrandGInverseFn: r must be > 0, got ${r}`);\n }\n const rho = r_s / r;\n const sqrtRho = Math.sqrt(rho);\n const sinTheta = Math.sin(theta);\n const out = new Float64Array(16);\n out[0 * 4 + 0] = -1;\n out[0 * 4 + 1] = sqrtRho;\n out[1 * 4 + 0] = sqrtRho;\n out[1 * 4 + 1] = 1 - rho;\n out[2 * 4 + 2] = 1 / (r * r);\n out[3 * 4 + 3] = 1 / (r * r * sinTheta * sinTheta);\n return out;\n };\n}\n"]}
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bisection perihelion finder via cubic-Hermite interpolation on cached
|
|
3
|
-
* GL4 snapshots (v0.5.0 Task 4, Phase 1b).
|
|
4
|
-
*
|
|
5
|
-
* Algorithm (Design §3 Task 1b):
|
|
6
|
-
* 1. Walk snapshots, extract `dr/dτ_i = g^{rν}(x_i) · p_{i,ν}` at each
|
|
7
|
-
* snapshot. Index `r` is the radial coordinate slot (index 1 by
|
|
8
|
-
* convention in (t, r, θ, φ)).
|
|
9
|
-
* 2. Locate consecutive indices `(i, i+1)` where `dr/dτ` sign-changes
|
|
10
|
-
* from `−` to `+` — that is the perihelion (inner radial turning
|
|
11
|
-
* point). Sign-change `+ → −` is apoapsis and is intentionally
|
|
12
|
-
* skipped.
|
|
13
|
-
* 3. **M3 bracket-width check:** if `|τ_{i+1} − τ_i| < 2 · h_snap`
|
|
14
|
-
* where `h_snap` is the median Δτ across all snapshots, emit a
|
|
15
|
-
* non-throwing `PerihelionBracketWidthWarning` via
|
|
16
|
-
* `process.emitWarning`. This indicates the GL4 step is too coarse
|
|
17
|
-
* to resolve the turning point — the caller should re-integrate
|
|
18
|
-
* with finer steps.
|
|
19
|
-
* 4. Fit a **cubic Hermite polynomial** through `(τ_i, dr/dτ_i)` and
|
|
20
|
-
* `(τ_{i+1}, dr/dτ_{i+1})`, with endpoint derivatives estimated
|
|
21
|
-
* from neighboring snapshots (4 values total: f and f' at both
|
|
22
|
-
* endpoints). Find an analytic root of the cubic on [τ_i, τ_{i+1}].
|
|
23
|
-
* 5. If `|P(τ_root)| > tauTolerance`, refine with **bisection on the
|
|
24
|
-
* polynomial** (not re-integration — Adam+Eve I6/F11 — that would
|
|
25
|
-
* cost a full GL4 sweep per bisection step, which defeats the
|
|
26
|
-
* cached-snapshot approach). Precision floor: 1e-9 × T_orbit
|
|
27
|
-
* (Adam+Eve I1 — 1e-12 needs ~40 cubic bisections and is wasted
|
|
28
|
-
* effort given the integrator's per-step error is already > 1e-12).
|
|
29
|
-
* 6. Return `{ tau, x, phi }` where `x` is the cubic-Hermite-interpolated
|
|
30
|
-
* 4-coordinate at the root and `phi = x[3]`.
|
|
31
|
-
*
|
|
32
|
-
* **Throws** `Error("no perihelion bracket")` if no `−→+` sign-change is
|
|
33
|
-
* found in the snapshot range.
|
|
34
|
-
*
|
|
35
|
-
* @module numerical/perihelion-finder
|
|
36
|
-
*/
|
|
37
1
|
/**
|
|
38
2
|
* Result of `findPerihelion`: the τ at the radial turning point, the
|
|
39
3
|
* interpolated 4-coordinate, and the orbital phase `phi = x[3]`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perihelion-finder.d.ts","sourceRoot":"","sources":["../../src/numerical/perihelion-finder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"perihelion-finder.d.ts","sourceRoot":"","sources":["../../src/numerical/perihelion-finder.ts"],"names":[],"mappings":"AA0CA;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC;wEACoE;IACpE,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;QAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC9B,QAAQ,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KAC/B,CAAC,CAAC;IACH;;4DAEwD;IACxD,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,YAAY,CAAC;IAC5D;;iEAE6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;qCACiC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAkGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,gBAAgB,CAwG/E"}
|
|
@@ -20,11 +20,14 @@
|
|
|
20
20
|
* `(τ_{i+1}, dr/dτ_{i+1})`, with endpoint derivatives estimated
|
|
21
21
|
* from neighboring snapshots (4 values total: f and f' at both
|
|
22
22
|
* endpoints). Find an analytic root of the cubic on [τ_i, τ_{i+1}].
|
|
23
|
-
* 5. If `|P(τ_root)| > tauTolerance`, refine with **
|
|
24
|
-
* polynomial** (not re-integration — Adam+Eve
|
|
25
|
-
* cost a full GL4 sweep per
|
|
26
|
-
* cached-snapshot approach).
|
|
27
|
-
*
|
|
23
|
+
* 5. If `|P(τ_root)| > tauTolerance`, refine with **Brent's method on the
|
|
24
|
+
* polynomial** (MathTS `findRoot`, not re-integration — Adam+Eve
|
|
25
|
+
* I6/F11 — that would cost a full GL4 sweep per step, which defeats
|
|
26
|
+
* the cached-snapshot approach). `tauTolerance` is a RESIDUAL tolerance
|
|
27
|
+
* in the units of dr/dτ, so the search is run with `xtol: 0`
|
|
28
|
+
* (`@danielsimonjr/mathts-functions` ≥ 0.68.3): the solver stops on
|
|
29
|
+
* `|P| ≤ tauTolerance` alone, never on the bracket width in `s`.
|
|
30
|
+
* Precision floor: 1e-9 × T_orbit (Adam+Eve I1 — 1e-12 is wasted
|
|
28
31
|
* effort given the integrator's per-step error is already > 1e-12).
|
|
29
32
|
* 6. Return `{ tau, x, phi }` where `x` is the cubic-Hermite-interpolated
|
|
30
33
|
* 4-coordinate at the root and `phi = x[3]`.
|
|
@@ -34,6 +37,8 @@
|
|
|
34
37
|
*
|
|
35
38
|
* @module numerical/perihelion-finder
|
|
36
39
|
*/
|
|
40
|
+
import { findRoot, hermiteInterp, median } from '@danielsimonjr/mathts-functions';
|
|
41
|
+
import { numberFrom } from '../core/mathts-read.js';
|
|
37
42
|
/** Compute `dr/dτ = g^{rν}(x) p_ν` at a single snapshot. */
|
|
38
43
|
function radialVelocity(x, p, gInverseFn, r) {
|
|
39
44
|
const gInv = gInverseFn(x);
|
|
@@ -44,41 +49,25 @@ function radialVelocity(x, p, gInverseFn, r) {
|
|
|
44
49
|
}
|
|
45
50
|
return v;
|
|
46
51
|
}
|
|
47
|
-
/** Median of
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
const n = sorted.length;
|
|
51
|
-
if (n === 0)
|
|
52
|
+
/** Median of the snapshot steps, MathTS `median` (0 for no steps, as before). */
|
|
53
|
+
function medianStep(values) {
|
|
54
|
+
if (values.length === 0)
|
|
52
55
|
return 0;
|
|
53
|
-
|
|
54
|
-
return sorted[(n - 1) / 2];
|
|
55
|
-
return 0.5 * (sorted[n / 2 - 1] + sorted[n / 2]);
|
|
56
|
+
return numberFrom('median', median([...values]));
|
|
56
57
|
}
|
|
57
58
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* Cubic Hermite interpolant of a scalar `f(τ)` over `[τ0, τ1]` with
|
|
59
|
+
* The cubic Hermite interpolant of a scalar `f(τ)` over `[τ0, τ1]` with
|
|
61
60
|
* endpoint values `f0, f1` and endpoint derivatives `m0, m1` (in `f` per
|
|
62
|
-
* `τ`)
|
|
63
|
-
*
|
|
64
|
-
*
|
|
61
|
+
* `τ`), at `s = (τ − τ0)/(τ1 − τ0)`: MathTS `hermiteInterp` on the two
|
|
62
|
+
* nodes `0` and `1` of the unit interval, where the derivatives are
|
|
63
|
+
* `(τ1 − τ0) m`. With two nodes that interpolant IS the cubic
|
|
65
64
|
*
|
|
66
|
-
*
|
|
67
|
-
* h00 = 2s³ − 3s² + 1
|
|
68
|
-
* h10 = s³ − 2s² + s
|
|
69
|
-
* h01 = −2s³ + 3s²
|
|
70
|
-
* h11 = s³ − s²
|
|
65
|
+
* P = h00(s) f0 + h10(s) (τ1−τ0) m0 + h01(s) f1 + h11(s) (τ1−τ0) m1
|
|
71
66
|
*
|
|
72
67
|
* (Numerical Recipes §3.4; Hairer/Lubich/Wanner §III.5.)
|
|
73
68
|
*/
|
|
74
69
|
function hermiteEval(f0, f1, m0, m1, dt, s) {
|
|
75
|
-
|
|
76
|
-
const s3 = s2 * s;
|
|
77
|
-
const h00 = 2 * s3 - 3 * s2 + 1;
|
|
78
|
-
const h10 = s3 - 2 * s2 + s;
|
|
79
|
-
const h01 = -2 * s3 + 3 * s2;
|
|
80
|
-
const h11 = s3 - s2;
|
|
81
|
-
return h00 * f0 + h10 * dt * m0 + h01 * f1 + h11 * dt * m1;
|
|
70
|
+
return hermiteInterp([0, 1], [f0, f1], [dt * m0, dt * m1], s);
|
|
82
71
|
}
|
|
83
72
|
/**
|
|
84
73
|
* Vector cubic-Hermite interpolation of a 4-coordinate `x^μ` at `τ`
|
|
@@ -95,61 +84,26 @@ function hermiteInterpVector(x0, x1, m0, m1, dt, s) {
|
|
|
95
84
|
return out;
|
|
96
85
|
}
|
|
97
86
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* the converged `s` and the
|
|
87
|
+
* The root of the cubic-Hermite polynomial for the scalar `dr/dτ`, on the
|
|
88
|
+
* normalised bracket coordinate `s ∈ [0,1]`, by MathTS `findRoot` (Brent).
|
|
89
|
+
* Returns the converged `s` and the polynomial value there.
|
|
101
90
|
*
|
|
102
|
-
* Precision:
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
91
|
+
* Precision: `tol` is a residual tolerance in the units of `dr/dτ` (the
|
|
92
|
+
* caller passes `tauTolerance`, matched to the integrator scale), so the
|
|
93
|
+
* solver runs with `xtol: 0` and stops on `|P(s)| ≤ tol` alone, never on
|
|
94
|
+
* the bracket width in `s`. `sInitial` (the linear estimate) is tried first
|
|
95
|
+
* and returned when it already meets `tol`. A hard iteration cap of 100
|
|
96
|
+
* bounds a tolerance the polynomial cannot meet in floating point; the
|
|
97
|
+
* solver then returns its best point.
|
|
107
98
|
*/
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
let fs = hermiteEval(f0, f1, m0, m1, dt, s);
|
|
117
|
-
// If sInitial already satisfies tol, return it.
|
|
118
|
-
let absFs = fs < 0 ? -fs : fs;
|
|
119
|
-
if (absFs <= tol)
|
|
120
|
-
return { s, residual: fs };
|
|
121
|
-
// Warm start: the sInitial evaluation above is otherwise discarded. Use its
|
|
122
|
-
// sign to tighten the GUARANTEED bracket before bisecting. This preserves the
|
|
123
|
-
// sign-bracket invariant (fLo < 0 < fHi) — so convergence is unaffected — and
|
|
124
|
-
// a good linear estimate yields a smaller starting interval (fewer iters).
|
|
125
|
-
if (sInitial > sLo && sInitial < sHi) {
|
|
126
|
-
if ((fs < 0) === (fLo < 0)) {
|
|
127
|
-
sLo = s;
|
|
128
|
-
fLo = fs;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
sHi = s;
|
|
132
|
-
fHi = fs;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
for (let iter = 0; iter < 60; iter++) {
|
|
136
|
-
// Bisect the (warm-started) bracket — robust regardless of the estimate.
|
|
137
|
-
s = 0.5 * (sLo + sHi);
|
|
138
|
-
fs = hermiteEval(f0, f1, m0, m1, dt, s);
|
|
139
|
-
absFs = fs < 0 ? -fs : fs;
|
|
140
|
-
if (absFs <= tol)
|
|
141
|
-
return { s, residual: fs };
|
|
142
|
-
// Maintain sign-bracket: fLo < 0 < fHi.
|
|
143
|
-
if ((fs < 0) === (fLo < 0)) {
|
|
144
|
-
sLo = s;
|
|
145
|
-
fLo = fs;
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
sHi = s;
|
|
149
|
-
fHi = fs;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return { s, residual: fs };
|
|
99
|
+
function rootOnCubic(f0, f1, m0, m1, dt, sInitial, tol) {
|
|
100
|
+
const P = (s) => hermiteEval(f0, f1, m0, m1, dt, s);
|
|
101
|
+
const atStart = P(sInitial);
|
|
102
|
+
if (Math.abs(atStart) <= tol)
|
|
103
|
+
return { s: sInitial, residual: atStart };
|
|
104
|
+
// By construction f(0) = f0 ≤ 0 < f1 = f(1) (or f0 < 0 ≤ f1), the sign change `findRoot` requires.
|
|
105
|
+
const s = findRoot(P, 0, 1, { tol, xtol: 0, maxIter: 100 });
|
|
106
|
+
return { s, residual: P(s) };
|
|
153
107
|
}
|
|
154
108
|
/**
|
|
155
109
|
* Find the perihelion (inner radial turning point) on a snapshot stream.
|
|
@@ -267,7 +221,7 @@ export function findPerihelion(options) {
|
|
|
267
221
|
for (let i = 0; i < snapshots.length - 1; i++) {
|
|
268
222
|
deltas.push(snapshots[i + 1].tau - snapshots[i].tau);
|
|
269
223
|
}
|
|
270
|
-
const hSnap =
|
|
224
|
+
const hSnap = medianStep(deltas);
|
|
271
225
|
if (dt < hSnap) {
|
|
272
226
|
process.emitWarning(`findPerihelion: bracket width Δτ=${dt} < h_snap=${hSnap} `
|
|
273
227
|
+ `(median snapshot step) — GL4 snapshot density is too coarse to `
|
|
@@ -284,8 +238,8 @@ export function findPerihelion(options) {
|
|
|
284
238
|
// Initial guess: linear interpolation root, s = f0 / (f0 − f1).
|
|
285
239
|
// For a linear sign-change this is exact; for cubic it's a warm start.
|
|
286
240
|
const sLinear = f0 / (f0 - f1);
|
|
287
|
-
// Step 5:
|
|
288
|
-
const { s: sRoot } =
|
|
241
|
+
// Step 5: solve the cubic-Hermite polynomial until residual ≤ tolerance.
|
|
242
|
+
const { s: sRoot } = rootOnCubic(f0, f1, m0, m1, dt, sLinear, tauTolerance);
|
|
289
243
|
const tauRoot = tau0 + sRoot * dt;
|
|
290
244
|
// Step 6: interpolate x^μ at τ_root via cubic Hermite using the same
|
|
291
245
|
// endpoint-derivative scheme. dx^μ/dτ at endpoints comes from
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perihelion-finder.js","sourceRoot":"","sources":["../../src/numerical/perihelion-finder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bisection perihelion finder via cubic-Hermite interpolation on cached\n * GL4 snapshots (v0.5.0 Task 4, Phase 1b).\n *\n * Algorithm (Design §3 Task 1b):\n * 1. Walk snapshots, extract `dr/dτ_i = g^{rν}(x_i) · p_{i,ν}` at each\n * snapshot. Index `r` is the radial coordinate slot (index 1 by\n * convention in (t, r, θ, φ)).\n * 2. Locate consecutive indices `(i, i+1)` where `dr/dτ` sign-changes\n * from `−` to `+` — that is the perihelion (inner radial turning\n * point). Sign-change `+ → −` is apoapsis and is intentionally\n * skipped.\n * 3. **M3 bracket-width check:** if `|τ_{i+1} − τ_i| < 2 · h_snap`\n * where `h_snap` is the median Δτ across all snapshots, emit a\n * non-throwing `PerihelionBracketWidthWarning` via\n * `process.emitWarning`. This indicates the GL4 step is too coarse\n * to resolve the turning point — the caller should re-integrate\n * with finer steps.\n * 4. Fit a **cubic Hermite polynomial** through `(τ_i, dr/dτ_i)` and\n * `(τ_{i+1}, dr/dτ_{i+1})`, with endpoint derivatives estimated\n * from neighboring snapshots (4 values total: f and f' at both\n * endpoints). Find an analytic root of the cubic on [τ_i, τ_{i+1}].\n * 5. If `|P(τ_root)| > tauTolerance`, refine with **bisection on the\n * polynomial** (not re-integration — Adam+Eve I6/F11 — that would\n * cost a full GL4 sweep per bisection step, which defeats the\n * cached-snapshot approach). Precision floor: 1e-9 × T_orbit\n * (Adam+Eve I1 — 1e-12 needs ~40 cubic bisections and is wasted\n * effort given the integrator's per-step error is already > 1e-12).\n * 6. Return `{ tau, x, phi }` where `x` is the cubic-Hermite-interpolated\n * 4-coordinate at the root and `phi = x[3]`.\n *\n * **Throws** `Error(\"no perihelion bracket\")` if no `−→+` sign-change is\n * found in the snapshot range.\n *\n * @module numerical/perihelion-finder\n */\n\n/**\n * Result of `findPerihelion`: the τ at the radial turning point, the\n * interpolated 4-coordinate, and the orbital phase `phi = x[3]`.\n *\n * @public\n */\nexport interface PerihelionResult {\n /** Proper time at the perihelion. */\n readonly tau: number;\n /** Interpolated 4-coordinate x^μ at τ_perihelion. */\n readonly x: readonly number[];\n /** Orbital phase φ = x[3] at τ_perihelion. */\n readonly phi: number;\n}\n\n/**\n * Options for {@link findPerihelion}.\n *\n * @public\n */\nexport interface FindPerihelionOptions {\n /** Snapshots produced by `integrateGeodesicGL4` (or any compatible\n * `(τ, x, p)` snapshot stream — only `tau`, `x`, `p` are read). */\n readonly snapshots: ReadonlyArray<{\n readonly tau: number;\n readonly x: readonly number[];\n readonly p: readonly number[];\n }>;\n /** Inverse-metric closure (v0.9.0 O-1 flat layout):\n * `gInverseFn(x)[μ*dim + ν] = g^{μν}(x)`, Float64Array(dim²). Used to\n * compute `dr/dτ = g^{rν}(x) p_ν` at each snapshot. */\n readonly gInverseFn: (x: readonly number[]) => Float64Array;\n /** Polynomial-bisection target tolerance on the cubic-Hermite root —\n * measured as `|P(τ_root)|`, not `|τ − τ_true|`. Precision floor 1e-9\n * per Adam+Eve I1; tighter values just waste bisections. */\n readonly tauTolerance: number;\n /** Coordinate index used as the \"radial\" slot. Defaults to 1\n * ((t, r, θ, φ) convention). */\n readonly radialIndex?: number;\n}\n\n/** Compute `dr/dτ = g^{rν}(x) p_ν` at a single snapshot. */\nfunction radialVelocity(\n x: readonly number[],\n p: readonly number[],\n gInverseFn: (x: readonly number[]) => Float64Array,\n r: number,\n): number {\n const gInv = gInverseFn(x);\n const dim = p.length;\n let v = 0;\n for (let nu = 0; nu < dim; nu++) {\n v += gInv[r * dim + nu] * p[nu];\n }\n return v;\n}\n\n/** Median of a numeric array (does not mutate input). */\nfunction median(values: readonly number[]): number {\n const sorted = [...values].sort((a, b) => a - b);\n const n = sorted.length;\n if (n === 0) return 0;\n if (n % 2 === 1) return sorted[(n - 1) / 2];\n return 0.5 * (sorted[n / 2 - 1] + sorted[n / 2]);\n}\n\n/**\n * Hermite basis on the unit interval, evaluated at `s ∈ [0,1]`.\n *\n * Cubic Hermite interpolant of a scalar `f(τ)` over `[τ0, τ1]` with\n * endpoint values `f0, f1` and endpoint derivatives `m0, m1` (in `f` per\n * `τ`):\n *\n * P(τ) = h00(s) f0 + h10(s) (τ1−τ0) m0 + h01(s) f1 + h11(s) (τ1−τ0) m1\n *\n * where `s = (τ − τ0)/(τ1 − τ0)` and\n * h00 = 2s³ − 3s² + 1\n * h10 = s³ − 2s² + s\n * h01 = −2s³ + 3s²\n * h11 = s³ − s²\n *\n * (Numerical Recipes §3.4; Hairer/Lubich/Wanner §III.5.)\n */\nfunction hermiteEval(\n f0: number,\n f1: number,\n m0: number,\n m1: number,\n dt: number,\n s: number,\n): number {\n const s2 = s * s;\n const s3 = s2 * s;\n const h00 = 2 * s3 - 3 * s2 + 1;\n const h10 = s3 - 2 * s2 + s;\n const h01 = -2 * s3 + 3 * s2;\n const h11 = s3 - s2;\n return h00 * f0 + h10 * dt * m0 + h01 * f1 + h11 * dt * m1;\n}\n\n/**\n * Vector cubic-Hermite interpolation of a 4-coordinate `x^μ` at `τ`\n * given the two bracket endpoints and their snapshot derivatives in `τ`\n * (here: the `x` arrays, with derivative `dx/dτ` approximated by central\n * differences on neighbor snapshots — passed in by the caller).\n */\nfunction hermiteInterpVector(\n x0: readonly number[],\n x1: readonly number[],\n m0: readonly number[],\n m1: readonly number[],\n dt: number,\n s: number,\n): number[] {\n const dim = x0.length;\n const out = new Array<number>(dim);\n for (let mu = 0; mu < dim; mu++) {\n out[mu] = hermiteEval(x0[mu], x1[mu], m0[mu], m1[mu], dt, s);\n }\n return out;\n}\n\n/**\n * Bisection on the cubic-Hermite polynomial for the scalar `dr/dτ` root.\n * Operates on `s ∈ [0,1]` — the normalised bracket coordinate. Returns\n * the converged `s` and the corresponding polynomial value.\n *\n * Precision: the loop terminates when `|P(s_mid)| ≤ tauTolerance` (scaled\n * to whatever units `dr/dτ` is in — the caller passes `tauTolerance`\n * matched to the integrator scale). A hard iteration cap of 60 prevents\n * runaway on pathological inputs (60 bisections halve `s` to ≈1e-18 — well\n * below floating-point resolution).\n */\nfunction bisectCubic(\n f0: number,\n f1: number,\n m0: number,\n m1: number,\n dt: number,\n sInitial: number,\n tol: number,\n): { s: number; residual: number } {\n // Establish a bracket around sInitial. The sign-change is at the\n // f(τ0)=f0 → f(τ1)=f1 endpoints (by construction f0 < 0, f1 > 0).\n let sLo = 0;\n let sHi = 1;\n let fLo = f0;\n let fHi = f1;\n let s = sInitial;\n let fs = hermiteEval(f0, f1, m0, m1, dt, s);\n\n // If sInitial already satisfies tol, return it.\n let absFs = fs < 0 ? -fs : fs;\n if (absFs <= tol) return { s, residual: fs };\n\n // Warm start: the sInitial evaluation above is otherwise discarded. Use its\n // sign to tighten the GUARANTEED bracket before bisecting. This preserves the\n // sign-bracket invariant (fLo < 0 < fHi) — so convergence is unaffected — and\n // a good linear estimate yields a smaller starting interval (fewer iters).\n if (sInitial > sLo && sInitial < sHi) {\n if ((fs < 0) === (fLo < 0)) {\n sLo = s;\n fLo = fs;\n } else {\n sHi = s;\n fHi = fs;\n }\n }\n\n for (let iter = 0; iter < 60; iter++) {\n // Bisect the (warm-started) bracket — robust regardless of the estimate.\n s = 0.5 * (sLo + sHi);\n fs = hermiteEval(f0, f1, m0, m1, dt, s);\n absFs = fs < 0 ? -fs : fs;\n if (absFs <= tol) return { s, residual: fs };\n // Maintain sign-bracket: fLo < 0 < fHi.\n if ((fs < 0) === (fLo < 0)) {\n sLo = s;\n fLo = fs;\n } else {\n sHi = s;\n fHi = fs;\n }\n }\n return { s, residual: fs };\n}\n\n/**\n * Find the perihelion (inner radial turning point) on a snapshot stream.\n *\n * See module-level docstring for the algorithm. Throws if no `−→+` sign\n * change in `dr/dτ` is found.\n *\n * **Units.** Inherited from the supplied snapshots and `gInverseFn` — the\n * finder is metric-agnostic. For the perihelion method used by catalog\n * relation be-52 on Schwarzschild:\n * - `snapshots[i].tau` — affine parameter in **seconds** (SI, the\n * covariant-eikonal method's null normalization, used by catalog\n * relation be-37) or **proper-time seconds** (timelike geodesics).\n * - `snapshots[i].x` — 4-coordinate `(t, r, θ, φ)` in\n * **(s, m, rad, rad)** (SI).\n * - `snapshots[i].p` — covariant momentum (units depend on the\n * normalization; see `integrateGeodesicGL4` JSDoc).\n * - `tauTolerance` — polynomial-residual tolerance on `dr/dτ`,\n * therefore in **m/s** for SI Schwarzschild. Floor `1e-9` ⇒ tighter\n * values are quietly clamped (see implementation).\n *\n * @param options — see {@link FindPerihelionOptions}:\n * - `snapshots` — `(τ, x, p)` stream from `integrateGeodesicGL4` (units\n * as above).\n * - `gInverseFn(x)[μ*dim+ν]` — inverse metric `g^{μν}(x)` (flat). Same units as\n * the matching integrator call.\n * - `tauTolerance` — bisection target on `|P(s_root)|` measured in the\n * units of `dr/dτ` (m/s for SI Schwarzschild).\n * - `radialIndex` — index of `r` within `x` (default `1` — standard\n * `(t, r, θ, φ)` ordering).\n * @returns `{ tau, x, phi }` — affine parameter, interpolated 4-coordinate,\n * and orbital phase `φ = x[3]` at the perihelion. Units of `tau` and `x`\n * match the inputs; `phi` is in **radians**.\n * @throws Error if `snapshots.length < 2` or no `−→+` sign change in `dr/dτ`.\n *\n * @example\n * ```typescript\n * import { findPerihelion, integrateGeodesicGL4 } from 'universal-physics-tensor';\n * import {\n * schwarzschildDgInverseFn,\n * schwarzschildGInverseFn,\n * schwarzschildRs,\n * } from '../tests/fixtures/schwarzschild.js';\n *\n * const M = 1.989e30;\n * const r0 = 20 * schwarzschildRs(M); // starting radius\n * // Canonical (x, p) state: covariant momentum p = [-E, 0, 0, L] from the\n * // orbit's conserved energy E and angular momentum L (see\n * // tests/bridges/perihelion-precession.test.ts for a full setup).\n * const snapshots = integrateGeodesicGL4(\n * { x: [0, r0, Math.PI / 2, 0], p: [-E, 0, 0, L] },\n * {\n * steps: 2000,\n * tauMax: 1e6,\n * gInverseFn: schwarzschildGInverseFn(M),\n * dgInverseFn: schwarzschildDgInverseFn(M),\n * },\n * );\n *\n * const perihelion = findPerihelion({\n * snapshots,\n * gInverseFn: schwarzschildGInverseFn(M),\n * tauTolerance: 1e-9,\n * });\n * // perihelion.phi — azimuthal angle at closest approach (radians)\n * ```\n *\n * @public\n */\nexport function findPerihelion(options: FindPerihelionOptions): PerihelionResult {\n const { snapshots, gInverseFn, tauTolerance, radialIndex = 1 } = options;\n if (snapshots.length < 2) {\n throw new Error('no perihelion bracket: need at least 2 snapshots');\n }\n\n // Step 1: extract dr/dτ at every snapshot.\n const drDtau = new Array<number>(snapshots.length);\n for (let i = 0; i < snapshots.length; i++) {\n drDtau[i] = radialVelocity(\n snapshots[i].x,\n snapshots[i].p,\n gInverseFn,\n radialIndex,\n );\n }\n\n // Step 2: locate the first `− → +` sign change.\n // Tolerant against snapshot landing exactly at the turning point\n // (drDtau ≈ 0): treat `≤ 0 → > 0` as a valid bracket. A snapshot with\n // f == 0 exactly is itself the perihelion — but we still return through\n // the Hermite path so the {x, phi} interpolation is uniform.\n let iBracket = -1;\n for (let i = 0; i < snapshots.length - 1; i++) {\n if (drDtau[i] <= 0 && drDtau[i + 1] > 0) {\n iBracket = i;\n break;\n }\n if (drDtau[i] < 0 && drDtau[i + 1] >= 0) {\n iBracket = i;\n break;\n }\n }\n if (iBracket < 0) {\n throw new Error('no perihelion bracket: dr/dτ does not change sign − → +');\n }\n\n const i0 = iBracket;\n const i1 = iBracket + 1;\n const tau0 = snapshots[i0].tau;\n const tau1 = snapshots[i1].tau;\n const dt = tau1 - tau0;\n\n // Step 3: M3 bracket-width check vs median Δτ.\n //\n // Plan spec literally says `< 2·h_snap`, but on a uniform-step grid\n // every bracket equals h_snap exactly (ratio 1.0), so `< 2·h_snap` would\n // fire on every successful call — useless as a diagnostic. The intent\n // of M3 is to flag brackets compressed below the nominal integrator\n // step (i.e., adaptive step-halving has run near perihelion, leaving a\n // suspicious cluster). We compare against `h_snap` directly: the\n // warning fires when the bracket is **narrower than the typical step**.\n // Documented deviation; honest framing maintained — see CHANGELOG.\n const deltas: number[] = [];\n for (let i = 0; i < snapshots.length - 1; i++) {\n deltas.push(snapshots[i + 1].tau - snapshots[i].tau);\n }\n const hSnap = median(deltas);\n if (dt < hSnap) {\n process.emitWarning(\n `findPerihelion: bracket width Δτ=${dt} < h_snap=${hSnap} `\n + `(median snapshot step) — GL4 snapshot density is too coarse to `\n + `resolve this turning point reliably; consider re-integrating `\n + `with finer steps.`,\n 'PerihelionBracketWidthWarning',\n );\n }\n\n // Step 4: build cubic-Hermite interpolant for dr/dτ on [τ_i0, τ_i1].\n // Endpoint derivatives (d/dτ of dr/dτ) approximated via central\n // differences on neighboring snapshots (one-sided at boundaries).\n const f0 = drDtau[i0];\n const f1 = drDtau[i1];\n const m0 = derivAt(drDtau, snapshots, i0);\n const m1 = derivAt(drDtau, snapshots, i1);\n\n // Initial guess: linear interpolation root, s = f0 / (f0 − f1).\n // For a linear sign-change this is exact; for cubic it's a warm start.\n const sLinear = f0 / (f0 - f1);\n\n // Step 5: bisect the cubic-Hermite polynomial until residual ≤ tolerance.\n const { s: sRoot } = bisectCubic(f0, f1, m0, m1, dt, sLinear, tauTolerance);\n\n const tauRoot = tau0 + sRoot * dt;\n\n // Step 6: interpolate x^μ at τ_root via cubic Hermite using the same\n // endpoint-derivative scheme. dx^μ/dτ at endpoints comes from\n // central-differencing neighboring snapshots' x arrays.\n const xMomentum0 = velocityAt(snapshots, i0, gInverseFn);\n const xMomentum1 = velocityAt(snapshots, i1, gInverseFn);\n const xInterp = hermiteInterpVector(\n snapshots[i0].x,\n snapshots[i1].x,\n xMomentum0,\n xMomentum1,\n dt,\n sRoot,\n );\n\n return {\n tau: tauRoot,\n x: xInterp,\n phi: xInterp[3] ?? 0,\n };\n}\n\n/**\n * Central-difference estimate of `d(dr/dτ)/dτ` at snapshot index `i`.\n * One-sided at i=0 and i=N−1. Used as the Hermite endpoint slope.\n */\nfunction derivAt(\n drDtau: readonly number[],\n snapshots: ReadonlyArray<{ readonly tau: number }>,\n i: number,\n): number {\n const N = snapshots.length;\n if (i === 0) {\n return (drDtau[1] - drDtau[0]) / (snapshots[1].tau - snapshots[0].tau);\n }\n if (i === N - 1) {\n return (drDtau[N - 1] - drDtau[N - 2])\n / (snapshots[N - 1].tau - snapshots[N - 2].tau);\n }\n return (drDtau[i + 1] - drDtau[i - 1])\n / (snapshots[i + 1].tau - snapshots[i - 1].tau);\n}\n\n/**\n * 4-velocity `v^μ = g^{μν}(x_i) p_{i,ν}` at snapshot `i`. Used as the\n * Hermite endpoint slope for the `x^μ` interpolation (since by definition\n * `dx^μ/dτ = g^{μν} p_ν` along a geodesic).\n */\nfunction velocityAt(\n snapshots: ReadonlyArray<{ readonly x: readonly number[]; readonly p: readonly number[] }>,\n i: number,\n gInverseFn: (x: readonly number[]) => Float64Array,\n): number[] {\n const x = snapshots[i].x;\n const p = snapshots[i].p;\n const gInv = gInverseFn(x);\n const dim = x.length;\n const v = new Array<number>(dim);\n for (let mu = 0; mu < dim; mu++) {\n let acc = 0;\n for (let nu = 0; nu < dim; nu++) {\n acc += gInv[mu * dim + nu] * p[nu];\n }\n v[mu] = acc;\n }\n return v;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"perihelion-finder.js","sourceRoot":"","sources":["../../src/numerical/perihelion-finder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bisection perihelion finder via cubic-Hermite interpolation on cached\n * GL4 snapshots (v0.5.0 Task 4, Phase 1b).\n *\n * Algorithm (Design §3 Task 1b):\n * 1. Walk snapshots, extract `dr/dτ_i = g^{rν}(x_i) · p_{i,ν}` at each\n * snapshot. Index `r` is the radial coordinate slot (index 1 by\n * convention in (t, r, θ, φ)).\n * 2. Locate consecutive indices `(i, i+1)` where `dr/dτ` sign-changes\n * from `−` to `+` — that is the perihelion (inner radial turning\n * point). Sign-change `+ → −` is apoapsis and is intentionally\n * skipped.\n * 3. **M3 bracket-width check:** if `|τ_{i+1} − τ_i| < 2 · h_snap`\n * where `h_snap` is the median Δτ across all snapshots, emit a\n * non-throwing `PerihelionBracketWidthWarning` via\n * `process.emitWarning`. This indicates the GL4 step is too coarse\n * to resolve the turning point — the caller should re-integrate\n * with finer steps.\n * 4. Fit a **cubic Hermite polynomial** through `(τ_i, dr/dτ_i)` and\n * `(τ_{i+1}, dr/dτ_{i+1})`, with endpoint derivatives estimated\n * from neighboring snapshots (4 values total: f and f' at both\n * endpoints). Find an analytic root of the cubic on [τ_i, τ_{i+1}].\n * 5. If `|P(τ_root)| > tauTolerance`, refine with **Brent's method on the\n * polynomial** (MathTS `findRoot`, not re-integration — Adam+Eve\n * I6/F11 — that would cost a full GL4 sweep per step, which defeats\n * the cached-snapshot approach). `tauTolerance` is a RESIDUAL tolerance\n * in the units of dr/dτ, so the search is run with `xtol: 0`\n * (`@danielsimonjr/mathts-functions` ≥ 0.68.3): the solver stops on\n * `|P| ≤ tauTolerance` alone, never on the bracket width in `s`.\n * Precision floor: 1e-9 × T_orbit (Adam+Eve I1 — 1e-12 is wasted\n * effort given the integrator's per-step error is already > 1e-12).\n * 6. Return `{ tau, x, phi }` where `x` is the cubic-Hermite-interpolated\n * 4-coordinate at the root and `phi = x[3]`.\n *\n * **Throws** `Error(\"no perihelion bracket\")` if no `−→+` sign-change is\n * found in the snapshot range.\n *\n * @module numerical/perihelion-finder\n */\nimport { findRoot, hermiteInterp, median } from '@danielsimonjr/mathts-functions';\nimport { numberFrom } from '../core/mathts-read.js';\n\n/**\n * Result of `findPerihelion`: the τ at the radial turning point, the\n * interpolated 4-coordinate, and the orbital phase `phi = x[3]`.\n *\n * @public\n */\nexport interface PerihelionResult {\n /** Proper time at the perihelion. */\n readonly tau: number;\n /** Interpolated 4-coordinate x^μ at τ_perihelion. */\n readonly x: readonly number[];\n /** Orbital phase φ = x[3] at τ_perihelion. */\n readonly phi: number;\n}\n\n/**\n * Options for {@link findPerihelion}.\n *\n * @public\n */\nexport interface FindPerihelionOptions {\n /** Snapshots produced by `integrateGeodesicGL4` (or any compatible\n * `(τ, x, p)` snapshot stream — only `tau`, `x`, `p` are read). */\n readonly snapshots: ReadonlyArray<{\n readonly tau: number;\n readonly x: readonly number[];\n readonly p: readonly number[];\n }>;\n /** Inverse-metric closure (v0.9.0 O-1 flat layout):\n * `gInverseFn(x)[μ*dim + ν] = g^{μν}(x)`, Float64Array(dim²). Used to\n * compute `dr/dτ = g^{rν}(x) p_ν` at each snapshot. */\n readonly gInverseFn: (x: readonly number[]) => Float64Array;\n /** Polynomial-bisection target tolerance on the cubic-Hermite root —\n * measured as `|P(τ_root)|`, not `|τ − τ_true|`. Precision floor 1e-9\n * per Adam+Eve I1; tighter values just waste bisections. */\n readonly tauTolerance: number;\n /** Coordinate index used as the \"radial\" slot. Defaults to 1\n * ((t, r, θ, φ) convention). */\n readonly radialIndex?: number;\n}\n\n/** Compute `dr/dτ = g^{rν}(x) p_ν` at a single snapshot. */\nfunction radialVelocity(\n x: readonly number[],\n p: readonly number[],\n gInverseFn: (x: readonly number[]) => Float64Array,\n r: number,\n): number {\n const gInv = gInverseFn(x);\n const dim = p.length;\n let v = 0;\n for (let nu = 0; nu < dim; nu++) {\n v += gInv[r * dim + nu] * p[nu];\n }\n return v;\n}\n\n/** Median of the snapshot steps, MathTS `median` (0 for no steps, as before). */\nfunction medianStep(values: readonly number[]): number {\n if (values.length === 0) return 0;\n return numberFrom('median', median([...values]));\n}\n\n/**\n * The cubic Hermite interpolant of a scalar `f(τ)` over `[τ0, τ1]` with\n * endpoint values `f0, f1` and endpoint derivatives `m0, m1` (in `f` per\n * `τ`), at `s = (τ − τ0)/(τ1 − τ0)`: MathTS `hermiteInterp` on the two\n * nodes `0` and `1` of the unit interval, where the derivatives are\n * `(τ1 − τ0) m`. With two nodes that interpolant IS the cubic\n *\n * P = h00(s) f0 + h10(s) (τ1−τ0) m0 + h01(s) f1 + h11(s) (τ1−τ0) m1\n *\n * (Numerical Recipes §3.4; Hairer/Lubich/Wanner §III.5.)\n */\nfunction hermiteEval(\n f0: number,\n f1: number,\n m0: number,\n m1: number,\n dt: number,\n s: number,\n): number {\n return hermiteInterp([0, 1], [f0, f1], [dt * m0, dt * m1], s);\n}\n\n/**\n * Vector cubic-Hermite interpolation of a 4-coordinate `x^μ` at `τ`\n * given the two bracket endpoints and their snapshot derivatives in `τ`\n * (here: the `x` arrays, with derivative `dx/dτ` approximated by central\n * differences on neighbor snapshots — passed in by the caller).\n */\nfunction hermiteInterpVector(\n x0: readonly number[],\n x1: readonly number[],\n m0: readonly number[],\n m1: readonly number[],\n dt: number,\n s: number,\n): number[] {\n const dim = x0.length;\n const out = new Array<number>(dim);\n for (let mu = 0; mu < dim; mu++) {\n out[mu] = hermiteEval(x0[mu], x1[mu], m0[mu], m1[mu], dt, s);\n }\n return out;\n}\n\n/**\n * The root of the cubic-Hermite polynomial for the scalar `dr/dτ`, on the\n * normalised bracket coordinate `s ∈ [0,1]`, by MathTS `findRoot` (Brent).\n * Returns the converged `s` and the polynomial value there.\n *\n * Precision: `tol` is a residual tolerance in the units of `dr/dτ` (the\n * caller passes `tauTolerance`, matched to the integrator scale), so the\n * solver runs with `xtol: 0` and stops on `|P(s)| ≤ tol` alone, never on\n * the bracket width in `s`. `sInitial` (the linear estimate) is tried first\n * and returned when it already meets `tol`. A hard iteration cap of 100\n * bounds a tolerance the polynomial cannot meet in floating point; the\n * solver then returns its best point.\n */\nfunction rootOnCubic(\n f0: number,\n f1: number,\n m0: number,\n m1: number,\n dt: number,\n sInitial: number,\n tol: number,\n): { s: number; residual: number } {\n const P = (s: number): number => hermiteEval(f0, f1, m0, m1, dt, s);\n const atStart = P(sInitial);\n if (Math.abs(atStart) <= tol) return { s: sInitial, residual: atStart };\n // By construction f(0) = f0 ≤ 0 < f1 = f(1) (or f0 < 0 ≤ f1), the sign change `findRoot` requires.\n const s = findRoot(P, 0, 1, { tol, xtol: 0, maxIter: 100 });\n return { s, residual: P(s) };\n}\n\n/**\n * Find the perihelion (inner radial turning point) on a snapshot stream.\n *\n * See module-level docstring for the algorithm. Throws if no `−→+` sign\n * change in `dr/dτ` is found.\n *\n * **Units.** Inherited from the supplied snapshots and `gInverseFn` — the\n * finder is metric-agnostic. For the perihelion method used by catalog\n * relation be-52 on Schwarzschild:\n * - `snapshots[i].tau` — affine parameter in **seconds** (SI, the\n * covariant-eikonal method's null normalization, used by catalog\n * relation be-37) or **proper-time seconds** (timelike geodesics).\n * - `snapshots[i].x` — 4-coordinate `(t, r, θ, φ)` in\n * **(s, m, rad, rad)** (SI).\n * - `snapshots[i].p` — covariant momentum (units depend on the\n * normalization; see `integrateGeodesicGL4` JSDoc).\n * - `tauTolerance` — polynomial-residual tolerance on `dr/dτ`,\n * therefore in **m/s** for SI Schwarzschild. Floor `1e-9` ⇒ tighter\n * values are quietly clamped (see implementation).\n *\n * @param options — see {@link FindPerihelionOptions}:\n * - `snapshots` — `(τ, x, p)` stream from `integrateGeodesicGL4` (units\n * as above).\n * - `gInverseFn(x)[μ*dim+ν]` — inverse metric `g^{μν}(x)` (flat). Same units as\n * the matching integrator call.\n * - `tauTolerance` — bisection target on `|P(s_root)|` measured in the\n * units of `dr/dτ` (m/s for SI Schwarzschild).\n * - `radialIndex` — index of `r` within `x` (default `1` — standard\n * `(t, r, θ, φ)` ordering).\n * @returns `{ tau, x, phi }` — affine parameter, interpolated 4-coordinate,\n * and orbital phase `φ = x[3]` at the perihelion. Units of `tau` and `x`\n * match the inputs; `phi` is in **radians**.\n * @throws Error if `snapshots.length < 2` or no `−→+` sign change in `dr/dτ`.\n *\n * @example\n * ```typescript\n * import { findPerihelion, integrateGeodesicGL4 } from 'universal-physics-tensor';\n * import {\n * schwarzschildDgInverseFn,\n * schwarzschildGInverseFn,\n * schwarzschildRs,\n * } from '../tests/fixtures/schwarzschild.js';\n *\n * const M = 1.989e30;\n * const r0 = 20 * schwarzschildRs(M); // starting radius\n * // Canonical (x, p) state: covariant momentum p = [-E, 0, 0, L] from the\n * // orbit's conserved energy E and angular momentum L (see\n * // tests/bridges/perihelion-precession.test.ts for a full setup).\n * const snapshots = integrateGeodesicGL4(\n * { x: [0, r0, Math.PI / 2, 0], p: [-E, 0, 0, L] },\n * {\n * steps: 2000,\n * tauMax: 1e6,\n * gInverseFn: schwarzschildGInverseFn(M),\n * dgInverseFn: schwarzschildDgInverseFn(M),\n * },\n * );\n *\n * const perihelion = findPerihelion({\n * snapshots,\n * gInverseFn: schwarzschildGInverseFn(M),\n * tauTolerance: 1e-9,\n * });\n * // perihelion.phi — azimuthal angle at closest approach (radians)\n * ```\n *\n * @public\n */\nexport function findPerihelion(options: FindPerihelionOptions): PerihelionResult {\n const { snapshots, gInverseFn, tauTolerance, radialIndex = 1 } = options;\n if (snapshots.length < 2) {\n throw new Error('no perihelion bracket: need at least 2 snapshots');\n }\n\n // Step 1: extract dr/dτ at every snapshot.\n const drDtau = new Array<number>(snapshots.length);\n for (let i = 0; i < snapshots.length; i++) {\n drDtau[i] = radialVelocity(\n snapshots[i].x,\n snapshots[i].p,\n gInverseFn,\n radialIndex,\n );\n }\n\n // Step 2: locate the first `− → +` sign change.\n // Tolerant against snapshot landing exactly at the turning point\n // (drDtau ≈ 0): treat `≤ 0 → > 0` as a valid bracket. A snapshot with\n // f == 0 exactly is itself the perihelion — but we still return through\n // the Hermite path so the {x, phi} interpolation is uniform.\n let iBracket = -1;\n for (let i = 0; i < snapshots.length - 1; i++) {\n if (drDtau[i] <= 0 && drDtau[i + 1] > 0) {\n iBracket = i;\n break;\n }\n if (drDtau[i] < 0 && drDtau[i + 1] >= 0) {\n iBracket = i;\n break;\n }\n }\n if (iBracket < 0) {\n throw new Error('no perihelion bracket: dr/dτ does not change sign − → +');\n }\n\n const i0 = iBracket;\n const i1 = iBracket + 1;\n const tau0 = snapshots[i0].tau;\n const tau1 = snapshots[i1].tau;\n const dt = tau1 - tau0;\n\n // Step 3: M3 bracket-width check vs median Δτ.\n //\n // Plan spec literally says `< 2·h_snap`, but on a uniform-step grid\n // every bracket equals h_snap exactly (ratio 1.0), so `< 2·h_snap` would\n // fire on every successful call — useless as a diagnostic. The intent\n // of M3 is to flag brackets compressed below the nominal integrator\n // step (i.e., adaptive step-halving has run near perihelion, leaving a\n // suspicious cluster). We compare against `h_snap` directly: the\n // warning fires when the bracket is **narrower than the typical step**.\n // Documented deviation; honest framing maintained — see CHANGELOG.\n const deltas: number[] = [];\n for (let i = 0; i < snapshots.length - 1; i++) {\n deltas.push(snapshots[i + 1].tau - snapshots[i].tau);\n }\n const hSnap = medianStep(deltas);\n if (dt < hSnap) {\n process.emitWarning(\n `findPerihelion: bracket width Δτ=${dt} < h_snap=${hSnap} `\n + `(median snapshot step) — GL4 snapshot density is too coarse to `\n + `resolve this turning point reliably; consider re-integrating `\n + `with finer steps.`,\n 'PerihelionBracketWidthWarning',\n );\n }\n\n // Step 4: build cubic-Hermite interpolant for dr/dτ on [τ_i0, τ_i1].\n // Endpoint derivatives (d/dτ of dr/dτ) approximated via central\n // differences on neighboring snapshots (one-sided at boundaries).\n const f0 = drDtau[i0];\n const f1 = drDtau[i1];\n const m0 = derivAt(drDtau, snapshots, i0);\n const m1 = derivAt(drDtau, snapshots, i1);\n\n // Initial guess: linear interpolation root, s = f0 / (f0 − f1).\n // For a linear sign-change this is exact; for cubic it's a warm start.\n const sLinear = f0 / (f0 - f1);\n\n // Step 5: solve the cubic-Hermite polynomial until residual ≤ tolerance.\n const { s: sRoot } = rootOnCubic(f0, f1, m0, m1, dt, sLinear, tauTolerance);\n\n const tauRoot = tau0 + sRoot * dt;\n\n // Step 6: interpolate x^μ at τ_root via cubic Hermite using the same\n // endpoint-derivative scheme. dx^μ/dτ at endpoints comes from\n // central-differencing neighboring snapshots' x arrays.\n const xMomentum0 = velocityAt(snapshots, i0, gInverseFn);\n const xMomentum1 = velocityAt(snapshots, i1, gInverseFn);\n const xInterp = hermiteInterpVector(\n snapshots[i0].x,\n snapshots[i1].x,\n xMomentum0,\n xMomentum1,\n dt,\n sRoot,\n );\n\n return {\n tau: tauRoot,\n x: xInterp,\n phi: xInterp[3] ?? 0,\n };\n}\n\n/**\n * Central-difference estimate of `d(dr/dτ)/dτ` at snapshot index `i`.\n * One-sided at i=0 and i=N−1. Used as the Hermite endpoint slope.\n */\nfunction derivAt(\n drDtau: readonly number[],\n snapshots: ReadonlyArray<{ readonly tau: number }>,\n i: number,\n): number {\n const N = snapshots.length;\n if (i === 0) {\n return (drDtau[1] - drDtau[0]) / (snapshots[1].tau - snapshots[0].tau);\n }\n if (i === N - 1) {\n return (drDtau[N - 1] - drDtau[N - 2])\n / (snapshots[N - 1].tau - snapshots[N - 2].tau);\n }\n return (drDtau[i + 1] - drDtau[i - 1])\n / (snapshots[i + 1].tau - snapshots[i - 1].tau);\n}\n\n/**\n * 4-velocity `v^μ = g^{μν}(x_i) p_{i,ν}` at snapshot `i`. Used as the\n * Hermite endpoint slope for the `x^μ` interpolation (since by definition\n * `dx^μ/dτ = g^{μν} p_ν` along a geodesic).\n */\nfunction velocityAt(\n snapshots: ReadonlyArray<{ readonly x: readonly number[]; readonly p: readonly number[] }>,\n i: number,\n gInverseFn: (x: readonly number[]) => Float64Array,\n): number[] {\n const x = snapshots[i].x;\n const p = snapshots[i].p;\n const gInv = gInverseFn(x);\n const dim = x.length;\n const v = new Array<number>(dim);\n for (let mu = 0; mu < dim; mu++) {\n let acc = 0;\n for (let nu = 0; nu < dim; nu++) {\n acc += gInv[mu * dim + nu] * p[nu];\n }\n v[mu] = acc;\n }\n return v;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quadrature.d.ts","sourceRoot":"","sources":["../../src/numerical/quadrature.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"quadrature.d.ts","sourceRoot":"","sources":["../../src/numerical/quadrature.ts"],"names":[],"mappings":"AAsBA,yFAAyF;AACzF,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAcD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,iBAAiB,CAG7D,CAAC;AAEH;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EACxB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,MAAM,CAmBR"}
|
|
@@ -17,18 +17,16 @@
|
|
|
17
17
|
*
|
|
18
18
|
* @module numerical/quadrature
|
|
19
19
|
*/
|
|
20
|
-
import { rootsLegendre } from '@danielsimonjr/mathts-functions';
|
|
20
|
+
import { legendreP, rootsLegendre } from '@danielsimonjr/mathts-functions';
|
|
21
|
+
import { numberFrom } from '../core/mathts-read.js';
|
|
21
22
|
const legendre16 = rootsLegendre(16);
|
|
22
|
-
/** P
|
|
23
|
+
/** `Pₙ(x)`, MathTS `legendreP`, read back as the number it is for a number. */
|
|
24
|
+
function legendre(n, x) {
|
|
25
|
+
return numberFrom('legendreP', legendreP(n, x));
|
|
26
|
+
}
|
|
27
|
+
/** P₁₆'(x) = 16 (x P₁₆(x) − P₁₅(x)) / (x² − 1), the derivative identity on MathTS `legendreP`. */
|
|
23
28
|
function legendre16Derivative(x) {
|
|
24
|
-
|
|
25
|
-
let p1 = x;
|
|
26
|
-
for (let k = 2; k <= 16; k++) {
|
|
27
|
-
const p2 = ((2 * k - 1) * x * p1 - (k - 1) * p0) / k;
|
|
28
|
-
p0 = p1;
|
|
29
|
-
p1 = p2;
|
|
30
|
-
}
|
|
31
|
-
return (16 * (x * p1 - p0)) / (x * x - 1);
|
|
29
|
+
return (16 * (x * legendre(16, x) - legendre(15, x))) / (x * x - 1);
|
|
32
30
|
}
|
|
33
31
|
/**
|
|
34
32
|
* 16-point Gauss–Legendre nodes and weights on [−1, 1] (Σ weights = 2). The
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quadrature.js","sourceRoot":"","sources":["../../src/numerical/quadrature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;
|
|
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"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrate `dy/dt = system(t, y)` from `t0` to `t1` in `steps` fixed RK4
|
|
3
|
+
* steps and return the `steps + 1` states, the first being `y0`.
|
|
4
|
+
*
|
|
5
|
+
* @throws NumericalBackendError if `steps` is not a positive integer, or the
|
|
6
|
+
* run did not produce exactly `steps + 1` states.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function rk4Trajectory(system: (t: number, y: ReadonlyArray<number>) => number[], y0: ReadonlyArray<number>, t0: number, t1: number, steps: number): number[][];
|
|
10
|
+
//# sourceMappingURL=rk4-trajectory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rk4-trajectory.d.ts","sourceRoot":"","sources":["../../src/numerical/rk4-trajectory.ts"],"names":[],"mappings":"AAcA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,EACzD,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,EACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,EAAE,CAcZ"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed-step classical RK4 that keeps EVERY state of the run: the one owner of
|
|
3
|
+
* the fixed-step count. `integrateRK4` (`null-ray-integrator.ts`) returns its
|
|
4
|
+
* last state and `integrateGeodesic` (`geodesic-integrator.ts`) samples its
|
|
5
|
+
* states; callers that read a quantity off the whole motion (a supremum over a
|
|
6
|
+
* window, a zero crossing) call it directly. A caller that re-entered a
|
|
7
|
+
* one-step integrator once per sample would not reproduce one continuous
|
|
8
|
+
* fixed-step run (`tests/numerical/rk4-trajectory.test.ts`).
|
|
9
|
+
*
|
|
10
|
+
* @module numerical/rk4-trajectory
|
|
11
|
+
*/
|
|
12
|
+
import { solveODESystem } from '@danielsimonjr/mathts-functions';
|
|
13
|
+
import { NumericalBackendError } from './errors.js';
|
|
14
|
+
/**
|
|
15
|
+
* Integrate `dy/dt = system(t, y)` from `t0` to `t1` in `steps` fixed RK4
|
|
16
|
+
* steps and return the `steps + 1` states, the first being `y0`.
|
|
17
|
+
*
|
|
18
|
+
* @throws NumericalBackendError if `steps` is not a positive integer, or the
|
|
19
|
+
* run did not produce exactly `steps + 1` states.
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export function rk4Trajectory(system, y0, t0, t1, steps) {
|
|
23
|
+
if (!Number.isInteger(steps) || steps <= 0) {
|
|
24
|
+
throw new NumericalBackendError(`rk4Trajectory: step count must be a positive integer, got ${steps}`);
|
|
25
|
+
}
|
|
26
|
+
// From @danielsimonjr/mathts-functions 0.68.5 (MathTS #371) a `span/dt` that is a whole number
|
|
27
|
+
// up to rounding takes exactly that many steps of span/n and ends on t1; before it, `ceil`
|
|
28
|
+
// could add one smaller step, and this module nudged `dt` by 4ε to avoid it. The count is
|
|
29
|
+
// still checked, so a regression in MathTS is refused here, not integrated.
|
|
30
|
+
const h = (t1 - t0) / steps;
|
|
31
|
+
const sol = solveODESystem(system, [...y0], [t0, t1], { dt: h });
|
|
32
|
+
if (sol.y.length !== steps + 1) {
|
|
33
|
+
throw new NumericalBackendError(`rk4Trajectory: expected ${steps + 1} states, got ${sol.y.length}`);
|
|
34
|
+
}
|
|
35
|
+
return sol.y.map((state) => [...state]);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=rk4-trajectory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rk4-trajectory.js","sourceRoot":"","sources":["../../src/numerical/rk4-trajectory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAyD,EACzD,EAAyB,EACzB,EAAU,EACV,EAAU,EACV,KAAa;IAEb,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,qBAAqB,CAAC,6DAA6D,KAAK,EAAE,CAAC,CAAC;IACxG,CAAC;IACD,+FAA+F;IAC/F,2FAA2F;IAC3F,0FAA0F;IAC1F,4EAA4E;IAC5E,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;IAC5B,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IACjE,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,qBAAqB,CAAC,2BAA2B,KAAK,GAAG,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * Fixed-step classical RK4 that keeps EVERY state of the run: the one owner of\n * the fixed-step count. `integrateRK4` (`null-ray-integrator.ts`) returns its\n * last state and `integrateGeodesic` (`geodesic-integrator.ts`) samples its\n * states; callers that read a quantity off the whole motion (a supremum over a\n * window, a zero crossing) call it directly. A caller that re-entered a\n * one-step integrator once per sample would not reproduce one continuous\n * fixed-step run (`tests/numerical/rk4-trajectory.test.ts`).\n *\n * @module numerical/rk4-trajectory\n */\nimport { solveODESystem } from '@danielsimonjr/mathts-functions';\nimport { NumericalBackendError } from './errors.js';\n\n/**\n * Integrate `dy/dt = system(t, y)` from `t0` to `t1` in `steps` fixed RK4\n * steps and return the `steps + 1` states, the first being `y0`.\n *\n * @throws NumericalBackendError if `steps` is not a positive integer, or the\n * run did not produce exactly `steps + 1` states.\n * @internal\n */\nexport function rk4Trajectory(\n system: (t: number, y: ReadonlyArray<number>) => number[],\n y0: ReadonlyArray<number>,\n t0: number,\n t1: number,\n steps: number,\n): number[][] {\n if (!Number.isInteger(steps) || steps <= 0) {\n throw new NumericalBackendError(`rk4Trajectory: step count must be a positive integer, got ${steps}`);\n }\n // From @danielsimonjr/mathts-functions 0.68.5 (MathTS #371) a `span/dt` that is a whole number\n // up to rounding takes exactly that many steps of span/n and ends on t1; before it, `ceil`\n // could add one smaller step, and this module nudged `dt` by 4ε to avoid it. The count is\n // still checked, so a regression in MathTS is refused here, not integrated.\n const h = (t1 - t0) / steps;\n const sol = solveODESystem(system, [...y0], [t0, t1], { dt: h });\n if (sol.y.length !== steps + 1) {\n throw new NumericalBackendError(`rk4Trajectory: expected ${steps + 1} states, got ${sol.y.length}`);\n }\n return sol.y.map((state) => [...state]);\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Schwarzschild radius, once.
|
|
3
|
+
*
|
|
4
|
+
* `r_s = 2GM/c²` was written at five sites (the covariant eikonal, the
|
|
5
|
+
* Painlevé–Gullstrand metric, the flat Christoffel closure and the metric
|
|
6
|
+
* library twice), each with its own constants. One function holds the
|
|
7
|
+
* formula; the constants default to the SI values and a caller that works
|
|
8
|
+
* in other units passes its own.
|
|
9
|
+
*
|
|
10
|
+
* @module numerical/schwarzschild
|
|
11
|
+
*/
|
|
12
|
+
/** `r_s = 2GM/c²` for a mass `M` (kg), with `G` and `c` in SI unless a caller passes its own. @internal */
|
|
13
|
+
export declare function schwarzschildRadius(M: number, G?: number, c?: number): number;
|
|
14
|
+
//# sourceMappingURL=schwarzschild.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schwarzschild.d.ts","sourceRoot":"","sources":["../../src/numerical/schwarzschild.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,2GAA2G;AAC3G,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAE,MAAa,EAAE,CAAC,GAAE,MAAa,GAAG,MAAM,CAEzF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Schwarzschild radius, once.
|
|
3
|
+
*
|
|
4
|
+
* `r_s = 2GM/c²` was written at five sites (the covariant eikonal, the
|
|
5
|
+
* Painlevé–Gullstrand metric, the flat Christoffel closure and the metric
|
|
6
|
+
* library twice), each with its own constants. One function holds the
|
|
7
|
+
* formula; the constants default to the SI values and a caller that works
|
|
8
|
+
* in other units passes its own.
|
|
9
|
+
*
|
|
10
|
+
* @module numerical/schwarzschild
|
|
11
|
+
*/
|
|
12
|
+
import { C_SI, G_SI } from '../core/constants.js';
|
|
13
|
+
/** `r_s = 2GM/c²` for a mass `M` (kg), with `G` and `c` in SI unless a caller passes its own. @internal */
|
|
14
|
+
export function schwarzschildRadius(M, G = G_SI, c = C_SI) {
|
|
15
|
+
return (2 * G * M) / (c * c);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=schwarzschild.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schwarzschild.js","sourceRoot":"","sources":["../../src/numerical/schwarzschild.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAElD,2GAA2G;AAC3G,MAAM,UAAU,mBAAmB,CAAC,CAAS,EAAE,CAAC,GAAW,IAAI,EAAE,CAAC,GAAW,IAAI;IAC/E,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * The Schwarzschild radius, once.\n *\n * `r_s = 2GM/c²` was written at five sites (the covariant eikonal, the\n * Painlevé–Gullstrand metric, the flat Christoffel closure and the metric\n * library twice), each with its own constants. One function holds the\n * formula; the constants default to the SI values and a caller that works\n * in other units passes its own.\n *\n * @module numerical/schwarzschild\n */\n\nimport { C_SI, G_SI } from '../core/constants.js';\n\n/** `r_s = 2GM/c²` for a mass `M` (kg), with `G` and `c` in SI unless a caller passes its own. @internal */\nexport function schwarzschildRadius(M: number, G: number = G_SI, c: number = C_SI): number {\n return (2 * G * M) / (c * c);\n}\n"]}
|