@classytic/stage 0.2.0 → 0.4.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/LICENSE +1 -1
- package/README.md +5 -1
- package/dist/_virtual/_rolldown/runtime.mjs +18 -0
- package/dist/assets/index.mjs +0 -1
- package/dist/atomic/aufbau.d.mts +144 -0
- package/dist/atomic/aufbau.mjs +384 -0
- package/dist/atomic/elements.d.mts +67 -0
- package/dist/atomic/elements.mjs +785 -0
- package/dist/atomic/emission.d.mts +112 -0
- package/dist/atomic/emission.mjs +179 -0
- package/dist/atomic/index.d.mts +8 -0
- package/dist/atomic/index.mjs +9 -0
- package/dist/atomic/periodic.d.mts +82 -0
- package/dist/atomic/periodic.mjs +231 -0
- package/dist/atomic/properties.d.mts +100 -0
- package/dist/atomic/properties.mjs +574 -0
- package/dist/atomic/shells.d.mts +137 -0
- package/dist/atomic/shells.mjs +170 -0
- package/dist/atomic/trends.d.mts +148 -0
- package/dist/atomic/trends.mjs +225 -0
- package/dist/builder/Palette.mjs +50 -89
- package/dist/builder/SceneBuilder.mjs +15 -73
- package/dist/chem/chromatography.d.mts +66 -0
- package/dist/chem/chromatography.mjs +63 -0
- package/dist/chem/complex.d.mts +114 -0
- package/dist/chem/complex.mjs +234 -0
- package/dist/chem/cycle.d.mts +75 -0
- package/dist/chem/cycle.mjs +145 -0
- package/dist/chem/equation.d.mts +86 -0
- package/dist/chem/equation.mjs +168 -0
- package/dist/chem/formula.d.mts +90 -0
- package/dist/chem/formula.mjs +201 -0
- package/dist/chem/functional-groups.d.mts +31 -0
- package/dist/chem/functional-groups.mjs +187 -0
- package/dist/chem/hazard.d.mts +94 -0
- package/dist/chem/hazard.mjs +329 -0
- package/dist/chem/index.d.mts +34 -33
- package/dist/chem/index.mjs +34 -28
- package/dist/chem/ionic.d.mts +98 -0
- package/dist/chem/ionic.mjs +156 -0
- package/dist/chem/layout.d.mts +46 -0
- package/dist/chem/layout.mjs +342 -0
- package/dist/chem/lewis.d.mts +79 -0
- package/dist/chem/lewis.mjs +163 -0
- package/dist/chem/molecular-orbital.d.mts +114 -0
- package/dist/chem/molecular-orbital.mjs +201 -0
- package/dist/chem/molecule.d.mts +154 -0
- package/dist/chem/molecule.mjs +282 -0
- package/dist/chem/nmr.d.mts +153 -0
- package/dist/chem/nmr.mjs +165 -0
- package/dist/chem/polymer.d.mts +65 -0
- package/dist/chem/polymer.mjs +179 -0
- package/dist/chem/redox.d.mts +138 -0
- package/dist/chem/redox.mjs +328 -0
- package/dist/chem/relations.d.mts +183 -0
- package/dist/chem/relations.mjs +299 -0
- package/dist/chem/skeleton.d.mts +51 -0
- package/dist/chem/skeleton.mjs +186 -0
- package/dist/chem/solution.d.mts +116 -0
- package/dist/chem/solution.mjs +186 -0
- package/dist/chem/species.d.mts +47 -0
- package/dist/chem/species.mjs +128 -0
- package/dist/chem/stereo.d.mts +108 -0
- package/dist/chem/stereo.mjs +286 -0
- package/dist/chem/stoichiometry.d.mts +95 -0
- package/dist/chem/stoichiometry.mjs +145 -0
- package/dist/chem/synthesis.d.mts +113 -0
- package/dist/chem/synthesis.mjs +281 -0
- package/dist/chem/vsepr.d.mts +80 -0
- package/dist/chem/vsepr.mjs +247 -0
- package/dist/circuit/ac.d.mts +163 -0
- package/dist/circuit/ac.mjs +452 -0
- package/dist/circuit/dc.d.mts +92 -0
- package/dist/circuit/dc.mjs +333 -0
- package/dist/circuit/index.d.mts +5 -92
- package/dist/circuit/index.mjs +5 -332
- package/dist/circuit/network.d.mts +99 -0
- package/dist/circuit/network.mjs +440 -0
- package/dist/circuit/topology.d.mts +102 -0
- package/dist/circuit/topology.mjs +143 -0
- package/dist/colour/absorption.d.mts +79 -0
- package/dist/colour/absorption.mjs +137 -0
- package/dist/colour/index.d.mts +6 -0
- package/dist/colour/index.mjs +7 -0
- package/dist/colour/name.d.mts +14 -0
- package/dist/colour/name.mjs +76 -0
- package/dist/colour/observer.d.mts +31 -0
- package/dist/colour/observer.mjs +46 -0
- package/dist/colour/spectrum.d.mts +61 -0
- package/dist/colour/spectrum.mjs +108 -0
- package/dist/colour/srgb.d.mts +49 -0
- package/dist/colour/srgb.mjs +108 -0
- package/dist/core/constants.d.mts +138 -0
- package/dist/core/constants.mjs +139 -0
- package/dist/core/index.d.mts +4 -1
- package/dist/core/index.mjs +4 -1
- package/dist/core/math.d.mts +26 -0
- package/dist/core/math.mjs +37 -0
- package/dist/core/vec3.d.mts +94 -0
- package/dist/core/vec3.mjs +123 -0
- package/dist/core/worked.d.mts +35 -0
- package/dist/core/worked.mjs +44 -0
- package/dist/electro/cell.d.mts +102 -0
- package/dist/electro/cell.mjs +170 -0
- package/dist/electro/conductivity.d.mts +157 -0
- package/dist/electro/conductivity.mjs +156 -0
- package/dist/electro/couples.d.mts +114 -0
- package/dist/electro/couples.mjs +334 -0
- package/dist/electro/electrolysis.d.mts +96 -0
- package/dist/electro/electrolysis.mjs +274 -0
- package/dist/electro/faraday.d.mts +150 -0
- package/dist/electro/faraday.mjs +118 -0
- package/dist/electro/index.d.mts +6 -0
- package/dist/electro/index.mjs +7 -0
- package/dist/finance/accounting/adjustments.d.mts +17 -0
- package/dist/finance/accounting/adjustments.mjs +202 -0
- package/dist/finance/accounting/analysis.d.mts +8 -0
- package/dist/finance/accounting/analysis.mjs +205 -0
- package/dist/finance/accounting/clubs.d.mts +21 -0
- package/dist/finance/accounting/clubs.mjs +217 -0
- package/dist/finance/accounting/company-statements.d.mts +7 -0
- package/dist/finance/accounting/company-statements.mjs +150 -0
- package/dist/finance/accounting/harness.d.mts +7 -0
- package/dist/finance/accounting/harness.mjs +45 -0
- package/dist/finance/accounting/index.d.mts +18 -0
- package/dist/finance/accounting/index.mjs +18 -0
- package/dist/finance/accounting/journalize.d.mts +16 -0
- package/dist/finance/accounting/journalize.mjs +128 -0
- package/dist/finance/accounting/manufacturing.d.mts +8 -0
- package/dist/finance/accounting/manufacturing.mjs +236 -0
- package/dist/finance/accounting/partnership.d.mts +7 -0
- package/dist/finance/accounting/partnership.mjs +152 -0
- package/dist/finance/accounting/period-case.d.mts +6 -0
- package/dist/finance/accounting/period-case.mjs +71 -0
- package/dist/finance/accounting/post.d.mts +9 -0
- package/dist/finance/accounting/post.mjs +84 -0
- package/dist/finance/accounting/precision.d.mts +9 -0
- package/dist/finance/accounting/precision.mjs +15 -0
- package/dist/finance/accounting/rules.d.mts +21 -0
- package/dist/finance/accounting/rules.mjs +37 -0
- package/dist/finance/accounting/solve.d.mts +28 -0
- package/dist/finance/accounting/solve.mjs +92 -0
- package/dist/finance/accounting/statements.d.mts +7 -0
- package/dist/finance/accounting/statements.mjs +142 -0
- package/dist/finance/accounting/types.d.mts +649 -0
- package/dist/finance/accounting/validate.d.mts +7 -0
- package/dist/finance/accounting/validate.mjs +67 -0
- package/dist/finance/accounting/verification.d.mts +24 -0
- package/dist/finance/accounting/verification.mjs +386 -0
- package/dist/finance/bizsim.d.mts +75 -0
- package/dist/finance/bizsim.mjs +296 -0
- package/dist/finance/index.d.mts +95 -0
- package/dist/finance/index.mjs +145 -0
- package/dist/finance/investment-math.d.mts +7 -0
- package/dist/finance/investment-math.mjs +18 -0
- package/dist/finance/management-accounting/budgeting.d.mts +7 -0
- package/dist/finance/management-accounting/budgeting.mjs +189 -0
- package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
- package/dist/finance/management-accounting/cash-budget.mjs +154 -0
- package/dist/finance/management-accounting/costing.d.mts +8 -0
- package/dist/finance/management-accounting/costing.mjs +175 -0
- package/dist/finance/management-accounting/decisions.d.mts +8 -0
- package/dist/finance/management-accounting/decisions.mjs +164 -0
- package/dist/finance/management-accounting/index.d.mts +13 -0
- package/dist/finance/management-accounting/index.mjs +13 -0
- package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
- package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
- package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
- package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
- package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
- package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
- package/dist/finance/management-accounting/management-case.d.mts +8 -0
- package/dist/finance/management-accounting/management-case.mjs +91 -0
- package/dist/finance/management-accounting/master-budget.d.mts +7 -0
- package/dist/finance/management-accounting/master-budget.mjs +137 -0
- package/dist/finance/management-accounting/production-costing.d.mts +8 -0
- package/dist/finance/management-accounting/production-costing.mjs +214 -0
- package/dist/finance/management-accounting/types.d.mts +644 -0
- package/dist/finance/management-accounting/variances.d.mts +7 -0
- package/dist/finance/management-accounting/variances.mjs +150 -0
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +5 -5
- package/dist/interaction/MovableDot.mjs +19 -0
- package/dist/interaction/useDraggable.mjs +24 -4
- package/dist/math/analysis.d.mts +61 -0
- package/dist/math/analysis.mjs +187 -0
- package/dist/math/answer-check.d.mts +50 -0
- package/dist/math/answer-check.mjs +106 -0
- package/dist/math/calculus.d.mts +17 -1
- package/dist/math/calculus.mjs +365 -2
- package/dist/math/complex.d.mts +93 -0
- package/dist/math/complex.mjs +239 -0
- package/dist/math/expr.d.mts +23 -0
- package/dist/math/expr.mjs +36 -0
- package/dist/math/index.d.mts +9 -23
- package/dist/math/index.mjs +9 -38
- package/dist/math/latex.mjs +10 -1
- package/dist/math/parse.mjs +1 -1
- package/dist/math/poly.d.mts +55 -0
- package/dist/math/poly.mjs +273 -0
- package/dist/math/rearrange.d.mts +14 -0
- package/dist/math/rearrange.mjs +125 -0
- package/dist/math/solve.d.mts +21 -0
- package/dist/math/solve.mjs +75 -0
- package/dist/networking/addressing.d.mts +26 -0
- package/dist/networking/addressing.mjs +33 -0
- package/dist/networking/cloud/access.d.mts +36 -0
- package/dist/networking/cloud/access.mjs +95 -0
- package/dist/networking/cloud/containers.d.mts +43 -0
- package/dist/networking/cloud/containers.mjs +54 -0
- package/dist/networking/cloud/edge.d.mts +17 -0
- package/dist/networking/cloud/edge.mjs +31 -0
- package/dist/networking/cloud/failure-domains.d.mts +19 -0
- package/dist/networking/cloud/failure-domains.mjs +22 -0
- package/dist/networking/cloud/geo-routing.d.mts +22 -0
- package/dist/networking/cloud/geo-routing.mjs +64 -0
- package/dist/networking/cloud/index.d.mts +18 -0
- package/dist/networking/cloud/index.mjs +19 -0
- package/dist/networking/cloud/inference-reliability.d.mts +30 -0
- package/dist/networking/cloud/inference-reliability.mjs +76 -0
- package/dist/networking/cloud/inference.d.mts +118 -0
- package/dist/networking/cloud/inference.mjs +179 -0
- package/dist/networking/cloud/infrastructure.d.mts +45 -0
- package/dist/networking/cloud/infrastructure.mjs +96 -0
- package/dist/networking/cloud/observability.d.mts +24 -0
- package/dist/networking/cloud/observability.mjs +34 -0
- package/dist/networking/cloud/orchestration.d.mts +32 -0
- package/dist/networking/cloud/orchestration.mjs +38 -0
- package/dist/networking/cloud/recovery.d.mts +21 -0
- package/dist/networking/cloud/recovery.mjs +27 -0
- package/dist/networking/cloud/releases.d.mts +42 -0
- package/dist/networking/cloud/releases.mjs +135 -0
- package/dist/networking/cloud/scaling.d.mts +25 -0
- package/dist/networking/cloud/scaling.mjs +65 -0
- package/dist/networking/cloud/secrets.d.mts +39 -0
- package/dist/networking/cloud/secrets.mjs +68 -0
- package/dist/networking/cloud/server-deployment.d.mts +29 -0
- package/dist/networking/cloud/server-deployment.mjs +72 -0
- package/dist/networking/cloud/storage.d.mts +16 -0
- package/dist/networking/cloud/storage.mjs +58 -0
- package/dist/networking/cloud/vpc.d.mts +18 -0
- package/dist/networking/cloud/vpc.mjs +100 -0
- package/dist/networking/delivery.d.mts +34 -0
- package/dist/networking/delivery.mjs +52 -0
- package/dist/networking/index.d.mts +47 -0
- package/dist/networking/index.mjs +47 -0
- package/dist/networking/ipv6.d.mts +28 -0
- package/dist/networking/ipv6.mjs +17 -0
- package/dist/networking/journeys.d.mts +83 -0
- package/dist/networking/journeys.mjs +161 -0
- package/dist/networking/models/airtime.d.mts +87 -0
- package/dist/networking/models/airtime.mjs +130 -0
- package/dist/networking/models/cellular.d.mts +157 -0
- package/dist/networking/models/cellular.mjs +252 -0
- package/dist/networking/models/encapsulation.d.mts +98 -0
- package/dist/networking/models/encapsulation.mjs +132 -0
- package/dist/networking/models/handover.d.mts +116 -0
- package/dist/networking/models/handover.mjs +209 -0
- package/dist/networking/models/handshake.d.mts +90 -0
- package/dist/networking/models/handshake.mjs +122 -0
- package/dist/networking/models/index.d.mts +14 -0
- package/dist/networking/models/index.mjs +15 -0
- package/dist/networking/models/media.d.mts +82 -0
- package/dist/networking/models/media.mjs +188 -0
- package/dist/networking/models/satellite.d.mts +86 -0
- package/dist/networking/models/satellite.mjs +121 -0
- package/dist/networking/models/spectrum.d.mts +83 -0
- package/dist/networking/models/spectrum.mjs +235 -0
- package/dist/networking/models/switch.d.mts +80 -0
- package/dist/networking/models/switch.mjs +155 -0
- package/dist/networking/models/vlan.d.mts +62 -0
- package/dist/networking/models/vlan.mjs +100 -0
- package/dist/networking/models/vpn.d.mts +66 -0
- package/dist/networking/models/vpn.mjs +125 -0
- package/dist/networking/models/wifi-privacy.d.mts +82 -0
- package/dist/networking/models/wifi-privacy.mjs +130 -0
- package/dist/networking/models/wifi.d.mts +240 -0
- package/dist/networking/models/wifi.mjs +562 -0
- package/dist/networking/nat-traversal.d.mts +24 -0
- package/dist/networking/nat-traversal.mjs +38 -0
- package/dist/networking/protocols.d.mts +17 -0
- package/dist/networking/protocols.mjs +57 -0
- package/dist/networking/queue.d.mts +12 -0
- package/dist/networking/queue.mjs +18 -0
- package/dist/networking/route-learning.d.mts +23 -0
- package/dist/networking/route-learning.mjs +43 -0
- package/dist/networking/routing.d.mts +11 -0
- package/dist/networking/routing.mjs +25 -0
- package/dist/networking/signals.d.mts +26 -0
- package/dist/networking/signals.mjs +35 -0
- package/dist/networking/subnet.d.mts +49 -0
- package/dist/networking/subnet.mjs +89 -0
- package/dist/networking/tcp-reliability.d.mts +24 -0
- package/dist/networking/tcp-reliability.mjs +38 -0
- package/dist/networking/topology/contract.d.mts +123 -0
- package/dist/networking/topology/index.d.mts +4 -0
- package/dist/networking/topology/index.mjs +4 -0
- package/dist/networking/topology/presets.d.mts +7 -0
- package/dist/networking/topology/presets.mjs +302 -0
- package/dist/networking/topology/simulation.d.mts +8 -0
- package/dist/networking/topology/simulation.mjs +179 -0
- package/dist/networking/wireless.d.mts +11 -0
- package/dist/networking/wireless.mjs +17 -0
- package/dist/optics/imaging.d.mts +218 -0
- package/dist/optics/imaging.mjs +276 -0
- package/dist/optics/index.d.mts +7 -0
- package/dist/optics/index.mjs +8 -0
- package/dist/optics/laws.d.mts +70 -0
- package/dist/optics/laws.mjs +195 -0
- package/dist/optics/prism.d.mts +148 -0
- package/dist/optics/prism.mjs +197 -0
- package/dist/optics/refraction.d.mts +201 -0
- package/dist/optics/refraction.mjs +270 -0
- package/dist/optics/wave-optics.d.mts +171 -0
- package/dist/optics/wave-optics.mjs +259 -0
- package/dist/physics/ac/index.d.mts +183 -0
- package/dist/physics/ac/index.mjs +203 -0
- package/dist/physics/dynamics/forces.d.mts +98 -0
- package/dist/physics/dynamics/forces.mjs +153 -0
- package/dist/physics/dynamics/friction.d.mts +76 -0
- package/dist/physics/dynamics/friction.mjs +119 -0
- package/dist/physics/dynamics/system.d.mts +68 -0
- package/dist/physics/dynamics/system.mjs +125 -0
- package/dist/physics/electrostatics/index.d.mts +169 -0
- package/dist/physics/electrostatics/index.mjs +249 -0
- package/dist/physics/energy/centre-of-mass.d.mts +115 -0
- package/dist/physics/energy/centre-of-mass.mjs +180 -0
- package/dist/physics/energy/conservation.d.mts +81 -0
- package/dist/physics/energy/conservation.mjs +129 -0
- package/dist/physics/energy/power.d.mts +90 -0
- package/dist/physics/energy/power.mjs +167 -0
- package/dist/physics/energy/spring.d.mts +73 -0
- package/dist/physics/energy/spring.mjs +129 -0
- package/dist/physics/energy/store.d.mts +63 -0
- package/dist/physics/energy/store.mjs +108 -0
- package/dist/physics/energy/theorem.d.mts +65 -0
- package/dist/physics/energy/theorem.mjs +113 -0
- package/dist/physics/energy/work.d.mts +114 -0
- package/dist/physics/energy/work.mjs +219 -0
- package/dist/physics/gravitation/body.d.mts +85 -0
- package/dist/physics/gravitation/body.mjs +168 -0
- package/dist/physics/gravitation/kepler.d.mts +127 -0
- package/dist/physics/gravitation/kepler.mjs +216 -0
- package/dist/physics/gravitation/law.d.mts +117 -0
- package/dist/physics/gravitation/law.mjs +175 -0
- package/dist/physics/gravitation/orbit.d.mts +119 -0
- package/dist/physics/gravitation/orbit.mjs +202 -0
- package/dist/physics/gravitation/potential.d.mts +114 -0
- package/dist/physics/gravitation/potential.mjs +202 -0
- package/dist/physics/gravitation/variation.d.mts +97 -0
- package/dist/physics/gravitation/variation.mjs +175 -0
- package/dist/physics/index.d.mts +35 -0
- package/dist/physics/index.mjs +36 -0
- package/dist/physics/integral-sweep.d.mts +63 -0
- package/dist/physics/integral-sweep.mjs +126 -0
- package/dist/physics/kinematics/equations.d.mts +47 -0
- package/dist/physics/kinematics/equations.mjs +126 -0
- package/dist/physics/kinematics/free-fall.d.mts +53 -0
- package/dist/physics/kinematics/free-fall.mjs +71 -0
- package/dist/physics/kinematics/given.d.mts +16 -0
- package/dist/physics/kinematics/given.mjs +55 -0
- package/dist/physics/kinematics/roots.d.mts +41 -0
- package/dist/physics/kinematics/roots.mjs +72 -0
- package/dist/physics/kinematics/solve.d.mts +52 -0
- package/dist/physics/kinematics/solve.mjs +172 -0
- package/dist/physics/magnetism/biot-savart.d.mts +161 -0
- package/dist/physics/magnetism/biot-savart.mjs +353 -0
- package/dist/physics/magnetism/flux.d.mts +94 -0
- package/dist/physics/magnetism/flux.mjs +313 -0
- package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
- package/dist/physics/magnetism/geomagnetism.mjs +184 -0
- package/dist/physics/magnetism/index.d.mts +12 -0
- package/dist/physics/magnetism/index.mjs +74 -0
- package/dist/physics/magnetism/lorentz.d.mts +28 -0
- package/dist/physics/magnetism/lorentz.mjs +88 -0
- package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
- package/dist/physics/magnetism/magnetic-force.mjs +169 -0
- package/dist/physics/momentum/collide.d.mts +77 -0
- package/dist/physics/momentum/collide.mjs +115 -0
- package/dist/physics/momentum/impulse.d.mts +89 -0
- package/dist/physics/momentum/impulse.mjs +159 -0
- package/dist/physics/momentum/planar.d.mts +60 -0
- package/dist/physics/momentum/planar.mjs +110 -0
- package/dist/physics/projectile.d.mts +107 -0
- package/dist/physics/projectile.mjs +185 -0
- package/dist/physics/rotation/angular.d.mts +85 -0
- package/dist/physics/rotation/angular.mjs +130 -0
- package/dist/physics/rotation/circular.d.mts +79 -0
- package/dist/physics/rotation/circular.mjs +131 -0
- package/dist/physics/rotation/inertia.d.mts +164 -0
- package/dist/physics/rotation/inertia.mjs +332 -0
- package/dist/physics/rotation/torque.d.mts +65 -0
- package/dist/physics/rotation/torque.mjs +134 -0
- package/dist/physics/vectors.d.mts +64 -0
- package/dist/physics/vectors.mjs +114 -0
- package/dist/primitives/Dot.d.mts +2 -15
- package/dist/primitives/Dot.mjs +6 -4
- package/dist/primitives/Grid.d.mts +33 -17
- package/dist/primitives/Grid.mjs +89 -17
- package/dist/primitives/Label.d.mts +1 -14
- package/dist/primitives/Label.mjs +3 -2
- package/dist/primitives/Lines.d.mts +4 -32
- package/dist/primitives/Lines.mjs +10 -8
- package/dist/primitives/Shapes.d.mts +5 -43
- package/dist/primitives/Shapes.mjs +12 -10
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/primitives/props.mjs +31 -0
- package/dist/quantity/index.d.mts +119 -0
- package/dist/quantity/index.mjs +417 -0
- package/dist/relation/derive.d.mts +74 -0
- package/dist/relation/derive.mjs +73 -0
- package/dist/relation/index.d.mts +56 -0
- package/dist/relation/index.mjs +234 -0
- package/dist/scene/Scene.d.mts +6 -1
- package/dist/scene/Scene.mjs +15 -40
- package/dist/scene/evaluators.mjs +1 -1
- package/dist/sim/thermal.mjs +45 -20
- package/dist/thermo/calorimetry.d.mts +207 -0
- package/dist/thermo/calorimetry.mjs +345 -0
- package/dist/thermo/cycles.d.mts +142 -0
- package/dist/thermo/cycles.mjs +256 -0
- package/dist/thermo/entropy.d.mts +87 -0
- package/dist/thermo/entropy.mjs +140 -0
- package/dist/thermo/expansion.d.mts +130 -0
- package/dist/thermo/expansion.mjs +178 -0
- package/dist/thermo/gas.d.mts +197 -0
- package/dist/thermo/gas.mjs +279 -0
- package/dist/thermo/heat-transfer.d.mts +164 -0
- package/dist/thermo/heat-transfer.mjs +217 -0
- package/dist/thermo/index.d.mts +9 -82
- package/dist/thermo/index.mjs +9 -132
- package/dist/thermo/processes.d.mts +95 -0
- package/dist/thermo/processes.mjs +154 -0
- package/dist/thermo/temperature.d.mts +174 -0
- package/dist/thermo/temperature.mjs +236 -0
- package/dist/view/Stage.mjs +4 -11
- package/dist/waves/damping.d.mts +224 -0
- package/dist/waves/damping.mjs +317 -0
- package/dist/waves/doppler.d.mts +72 -0
- package/dist/waves/doppler.mjs +125 -0
- package/dist/waves/index.d.mts +10 -0
- package/dist/waves/index.mjs +10 -0
- package/dist/waves/pendulum.d.mts +130 -0
- package/dist/waves/pendulum.mjs +211 -0
- package/dist/waves/pitch.d.mts +125 -0
- package/dist/waves/pitch.mjs +158 -0
- package/dist/waves/shm.d.mts +170 -0
- package/dist/waves/shm.mjs +279 -0
- package/dist/waves/springs.d.mts +103 -0
- package/dist/waves/springs.mjs +176 -0
- package/dist/waves/superposition.d.mts +124 -0
- package/dist/waves/superposition.mjs +196 -0
- package/dist/waves/wave.d.mts +154 -0
- package/dist/waves/wave.mjs +178 -0
- package/package.json +103 -23
- package/styles.css +125 -8
- package/dist/assets/kit/index.mjs +0 -4
package/dist/view/Stage.mjs
CHANGED
|
@@ -31,7 +31,7 @@ function Stage({ view = DEFAULT_VIEW, width, height, aspectRatio, pad = 12, pres
|
|
|
31
31
|
}), [
|
|
32
32
|
w,
|
|
33
33
|
h,
|
|
34
|
-
view
|
|
34
|
+
`${view.xMin} ${view.xMax} ${view.yMin} ${view.yMax}`,
|
|
35
35
|
pad,
|
|
36
36
|
preserveAspect
|
|
37
37
|
]);
|
|
@@ -43,8 +43,7 @@ function Stage({ view = DEFAULT_VIEW, width, height, aspectRatio, pad = 12, pres
|
|
|
43
43
|
} : void 0;
|
|
44
44
|
return /* @__PURE__ */ jsx("div", {
|
|
45
45
|
ref: wrapRef,
|
|
46
|
-
className,
|
|
47
|
-
style: { width: "100%" },
|
|
46
|
+
className: ["stage-root", className].filter(Boolean).join(" "),
|
|
48
47
|
children: /* @__PURE__ */ jsxs("svg", {
|
|
49
48
|
ref: svgRef,
|
|
50
49
|
width: w,
|
|
@@ -53,14 +52,8 @@ function Stage({ view = DEFAULT_VIEW, width, height, aspectRatio, pad = 12, pres
|
|
|
53
52
|
role: "group",
|
|
54
53
|
"aria-label": ariaLabel,
|
|
55
54
|
onPointerDown: handlePointer,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
background,
|
|
59
|
-
borderRadius: 12,
|
|
60
|
-
border: "1px solid var(--stage-grid)",
|
|
61
|
-
userSelect: "none",
|
|
62
|
-
touchAction: "none"
|
|
63
|
-
},
|
|
55
|
+
className: "stage-canvas",
|
|
56
|
+
style: { background },
|
|
64
57
|
children: [/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("marker", {
|
|
65
58
|
id: "stage-arrow",
|
|
66
59
|
viewBox: "0 0 10 10",
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
//#region src/waves/damping.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Damped and driven oscillation: why a car does not bounce, and why a bridge
|
|
4
|
+
* sometimes does.
|
|
5
|
+
*
|
|
6
|
+
* ## One number decides everything
|
|
7
|
+
*
|
|
8
|
+
* ζ = c / (2√(mk))
|
|
9
|
+
*
|
|
10
|
+
* The damping ratio. It is dimensionless, and it sorts every oscillator into
|
|
11
|
+
* one of three behaviours with no room for anything in between:
|
|
12
|
+
*
|
|
13
|
+
* ζ < 1 UNDERDAMPED overshoots and rings a worn shock absorber
|
|
14
|
+
* ζ = 1 CRITICAL returns fastest, without overshoot a good one
|
|
15
|
+
* ζ > 1 OVERDAMPED returns slowly, without overshoot a door closer
|
|
16
|
+
*
|
|
17
|
+
* The suspension of a car is deliberately set a little under 1, because
|
|
18
|
+
* perfectly critical feels dead and a slight overshoot reads as comfortable.
|
|
19
|
+
* The spring alone would leave ζ = 0 and the car would bounce down the road;
|
|
20
|
+
* the damper is the entire reason it does not.
|
|
21
|
+
*
|
|
22
|
+
* ## Critical damping is not "the most damping"
|
|
23
|
+
*
|
|
24
|
+
* It is the BOUNDARY, and the standard misreading is that more damping always
|
|
25
|
+
* settles faster. It does not. Past ζ = 1 the oscillator crawls back, and an
|
|
26
|
+
* overdamped car would still be sinking into the dip long after it had left it.
|
|
27
|
+
* `settlingTime` is the function that shows this turning round.
|
|
28
|
+
*
|
|
29
|
+
* ## Driving it, and where the peak actually is
|
|
30
|
+
*
|
|
31
|
+
* Push an oscillator at a frequency near its own and the amplitude climbs. The
|
|
32
|
+
* peak is NOT at ω₀ once there is damping: it sits at
|
|
33
|
+
*
|
|
34
|
+
* ω_peak = ω₀√(1 − 2ζ²)
|
|
35
|
+
*
|
|
36
|
+
* and for ζ above 1/√2 ≈ 0.707 there is no peak at all, only a curve that falls
|
|
37
|
+
* from the start. Both of those are routinely taught as "resonance is at the
|
|
38
|
+
* natural frequency", which is the undamped limit of a more interesting fact.
|
|
39
|
+
*
|
|
40
|
+
* ## Relation to the RLC circuit
|
|
41
|
+
*
|
|
42
|
+
* A series RLC is the same equations with m↔L, k↔1/C, c↔R, so `mechanicalQ`
|
|
43
|
+
* here and `qualityFactor` in `@classytic/stage/circuit` are the same quantity
|
|
44
|
+
* for the same reason. They are kept apart because the arguments are different
|
|
45
|
+
* physical things, not because the mathematics differs, and
|
|
46
|
+
* `tests/waves/damping.test.ts` checks that the two agree under the analogy so
|
|
47
|
+
* they cannot drift.
|
|
48
|
+
*
|
|
49
|
+
* Units: SI. The damping coefficient `c` is in N·s/m, so that cv is a force.
|
|
50
|
+
*/
|
|
51
|
+
/** How an oscillator returns to rest. The three cases are exhaustive. */
|
|
52
|
+
type DampingRegime = 'underdamped' | 'critically damped' | 'overdamped';
|
|
53
|
+
/**
|
|
54
|
+
* The damping coefficient that sits exactly on the boundary: c_c = 2√(mk).
|
|
55
|
+
*
|
|
56
|
+
* The target a shock absorber is designed against. Quoted in N·s/m, and for a
|
|
57
|
+
* quarter of a family car (around 300 kg on a 30 kN/m spring) it comes out near
|
|
58
|
+
* 6,000 N·s/m. A real damper is fitted at roughly a third of that, because the
|
|
59
|
+
* car is deliberately left underdamped: see the module note above.
|
|
60
|
+
*/
|
|
61
|
+
declare const criticalDamping: (mass: number, stiffness: number) => number;
|
|
62
|
+
/** The damping ratio ζ = c/c_c. Dimensionless, and the only number that matters. */
|
|
63
|
+
declare const dampingRatio: (mass: number, stiffness: number, coefficient: number) => number;
|
|
64
|
+
/**
|
|
65
|
+
* Which of the three behaviours a damping ratio produces.
|
|
66
|
+
*
|
|
67
|
+
* The boundary is tested with a tolerance because exact equality is not
|
|
68
|
+
* something a measured ζ ever achieves, and a ratio of 0.9999999 behaves like
|
|
69
|
+
* critical damping in every way that a learner or a graph can see.
|
|
70
|
+
*/
|
|
71
|
+
declare function dampingRegime(ratio: number, tolerance?: number): DampingRegime;
|
|
72
|
+
/**
|
|
73
|
+
* The frequency a damped oscillator actually rings at: ω_d = ω₀√(1 − ζ²).
|
|
74
|
+
*
|
|
75
|
+
* LOWER than the natural frequency, always. Damping slows the ringing as well
|
|
76
|
+
* as shrinking it, though only slightly until ζ gets large: at ζ = 0.1 the
|
|
77
|
+
* frequency is down by half a percent, which is why the effect is usually
|
|
78
|
+
* ignored and why ignoring it is usually fine.
|
|
79
|
+
*
|
|
80
|
+
* Throws at ζ ≥ 1, where there is no ringing left to have a frequency.
|
|
81
|
+
*/
|
|
82
|
+
declare function dampedAngularFrequency(naturalOmega: number, ratio: number): number;
|
|
83
|
+
/**
|
|
84
|
+
* Displacement of a damped oscillator released from rest at `amplitude`.
|
|
85
|
+
*
|
|
86
|
+
* x(0) = A, v(0) = 0: pulled aside and let go, which is the car meeting a bump
|
|
87
|
+
* and the door being pushed open. All three regimes are handled, and they are
|
|
88
|
+
* three different formulas rather than one with a parameter:
|
|
89
|
+
*
|
|
90
|
+
* under A·e^(−ζω₀t)·[cos ω_d t + (ζω₀/ω_d)·sin ω_d t]
|
|
91
|
+
* critical A·e^(−ω₀t)·(1 + ω₀t)
|
|
92
|
+
* over A·e^(−ζω₀t)·[cosh rt + (ζω₀/r)·sinh rt], r = ω₀√(ζ² − 1)
|
|
93
|
+
*
|
|
94
|
+
* The critical case is not a special case of the other two: at ζ = 1 both ω_d
|
|
95
|
+
* and r are zero and both expressions become 0/0. Evaluating the underdamped
|
|
96
|
+
* form at ζ = 0.99999 gives the right answer only because floating point has
|
|
97
|
+
* not quite reached the singularity yet, which is not a thing to rely on. The
|
|
98
|
+
* tests check that the three agree as ζ approaches 1 from either side, which is
|
|
99
|
+
* what makes the seam safe.
|
|
100
|
+
*/
|
|
101
|
+
declare function dampedDisplacement(amplitude: number, naturalOmega: number, ratio: number, t: number): number;
|
|
102
|
+
/**
|
|
103
|
+
* Velocity of that same released oscillator, m/s.
|
|
104
|
+
*
|
|
105
|
+
* Worth having separately rather than differencing the displacement, because
|
|
106
|
+
* the interesting question about a suspension is how hard it throws you, and
|
|
107
|
+
* that is a rate rather than a position. Every regime collapses to the same
|
|
108
|
+
* tidy form once differentiated:
|
|
109
|
+
*
|
|
110
|
+
* under −A·(ω₀²/ω_d)·e^(−ζω₀t)·sin ω_d t
|
|
111
|
+
* critical −A·ω₀²·t·e^(−ω₀t)
|
|
112
|
+
* over −A·(ω₀²/r)·e^(−ζω₀t)·sinh rt
|
|
113
|
+
*/
|
|
114
|
+
declare function dampedVelocity(amplitude: number, naturalOmega: number, ratio: number, t: number): number;
|
|
115
|
+
/**
|
|
116
|
+
* The mechanical quality factor: Q = √(mk)/c = 1/(2ζ).
|
|
117
|
+
*
|
|
118
|
+
* How many radians of oscillation it takes to lose most of the energy, near
|
|
119
|
+
* enough. A tuning fork has a Q in the thousands and rings for seconds; a car
|
|
120
|
+
* suspension has a Q near 1 and does not ring at all, which is the entire
|
|
121
|
+
* design intent.
|
|
122
|
+
*/
|
|
123
|
+
declare const mechanicalQ: (mass: number, stiffness: number, coefficient: number) => number;
|
|
124
|
+
/** Q directly from a damping ratio: Q = 1/(2ζ). */
|
|
125
|
+
declare const qFromDampingRatio: (ratio: number) => number;
|
|
126
|
+
/**
|
|
127
|
+
* The steady amplitude of an oscillator driven at ω by a force of amplitude F₀.
|
|
128
|
+
*
|
|
129
|
+
* A(ω) = (F₀/m) / √((ω₀² − ω²)² + (2ζω₀ω)²)
|
|
130
|
+
*
|
|
131
|
+
* The resonance curve. At ω far below ω₀ it settles to the static deflection
|
|
132
|
+
* F₀/k, which is the sanity check worth knowing: push slowly and the spring
|
|
133
|
+
* just stretches. At ω far above, the mass cannot keep up and the amplitude
|
|
134
|
+
* falls away as 1/ω².
|
|
135
|
+
*
|
|
136
|
+
* With ζ = 0 and ω = ω₀ the denominator is zero and the amplitude is infinite.
|
|
137
|
+
* That is not a bug to guard against: it is the statement that an undriven,
|
|
138
|
+
* undamped resonance has no limit, which is why every real structure has
|
|
139
|
+
* damping designed into it.
|
|
140
|
+
*/
|
|
141
|
+
declare function drivenAmplitude(forceAmplitude: number, mass: number, naturalOmega: number, ratio: number, omega: number): number;
|
|
142
|
+
/**
|
|
143
|
+
* Amplitude as a multiple of the static deflection F₀/k, dimensionless.
|
|
144
|
+
*
|
|
145
|
+
* The shape of the resonance curve with the units taken out, so two oscillators
|
|
146
|
+
* of different size can be compared on one graph. It is 1 at ω = 0 by
|
|
147
|
+
* construction, which anchors the curve at a value a learner can reason about
|
|
148
|
+
* instead of a bare number.
|
|
149
|
+
*/
|
|
150
|
+
declare function amplificationFactor(naturalOmega: number, ratio: number, omega: number): number;
|
|
151
|
+
/**
|
|
152
|
+
* The driving frequency that gives the LARGEST amplitude: ω₀√(1 − 2ζ²).
|
|
153
|
+
*
|
|
154
|
+
* Below ω₀, and noticeably so once ζ is appreciable. Above ζ = 1/√2 there is no
|
|
155
|
+
* peak: the amplitude only falls as the driving frequency rises, so a heavily
|
|
156
|
+
* damped system cannot be made to resonate at all. Throws there rather than
|
|
157
|
+
* returning the square root of a negative number, because "there is no
|
|
158
|
+
* resonant frequency" is the answer and NaN does not say it.
|
|
159
|
+
*/
|
|
160
|
+
declare function resonantAngularFrequency(naturalOmega: number, ratio: number): number;
|
|
161
|
+
/**
|
|
162
|
+
* The phase by which the oscillator lags the driving force, radians, 0 to π.
|
|
163
|
+
*
|
|
164
|
+
* tan φ = 2ζ(ω/ω₀) / (1 − (ω/ω₀)²)
|
|
165
|
+
*
|
|
166
|
+
* Exactly π/2 AT ω₀, whatever the damping, and that is the sharpest way to find
|
|
167
|
+
* a resonance in practice: the amplitude peak moves with ζ and is broad, but the
|
|
168
|
+
* quarter-cycle lag sits at ω₀ and crosses steeply. Well below resonance the
|
|
169
|
+
* mass follows the force in step; well above, it moves exactly opposite to it,
|
|
170
|
+
* which is why a spinning machine mounted softly enough transmits almost
|
|
171
|
+
* nothing to its floor.
|
|
172
|
+
*/
|
|
173
|
+
declare function drivenPhaseLag(naturalOmega: number, ratio: number, omega: number): number;
|
|
174
|
+
/**
|
|
175
|
+
* How long until a released oscillator stays within `band` of its amplitude.
|
|
176
|
+
*
|
|
177
|
+
* `band` is a fraction, so 0.05 is the usual "settled to within 5 %". Found by
|
|
178
|
+
* stepping rather than solved, because the crossing has no closed form once the
|
|
179
|
+
* oscillation is still ringing through the band.
|
|
180
|
+
*
|
|
181
|
+
* The reason this function exists is to make the turning point visible: sweep ζ
|
|
182
|
+
* and the settling time falls to a minimum near 1 and climbs again after it.
|
|
183
|
+
* That minimum is what a suspension engineer is buying.
|
|
184
|
+
*/
|
|
185
|
+
declare function settlingTime(naturalOmega: number, ratio: number, band?: number, maxPeriods?: number): number;
|
|
186
|
+
/**
|
|
187
|
+
* The fraction of its amplitude an underdamped oscillator keeps each cycle.
|
|
188
|
+
*
|
|
189
|
+
* ratio = e^(−2πζ/√(1 − ζ²))
|
|
190
|
+
*
|
|
191
|
+
* Successive peaks fall by the same FACTOR, never the same amount, so the decay
|
|
192
|
+
* is a geometric sequence. The natural logarithm of this is the logarithmic
|
|
193
|
+
* decrement, which is how ζ is measured off a real trace: count the peaks.
|
|
194
|
+
*/
|
|
195
|
+
declare function amplitudeRatioPerCycle(ratio: number): number;
|
|
196
|
+
/**
|
|
197
|
+
* The decay time constant, seconds: τ = 1/(ζω₀).
|
|
198
|
+
*
|
|
199
|
+
* The bridge between the two ways this topic is parameterised. Engineering
|
|
200
|
+
* states damping as ζ; the light-damping treatment in most physics courses
|
|
201
|
+
* states it as an envelope A₀·e^(−t/τ) and never mentions ζ at all. They are
|
|
202
|
+
* the same oscillator, and this is the conversion, so neither vocabulary needs
|
|
203
|
+
* its own copy of the decay.
|
|
204
|
+
*/
|
|
205
|
+
declare const decayTimeConstant: (naturalOmega: number, ratio: number) => number;
|
|
206
|
+
/**
|
|
207
|
+
* Amplitude of a lightly damped oscillator after a time: A = A₀·e^(−t/τ).
|
|
208
|
+
*
|
|
209
|
+
* The ENVELOPE, not the displacement: the oscillation rings inside this curve
|
|
210
|
+
* and touches it at the peaks. `dampedDisplacement` is the thing itself.
|
|
211
|
+
*
|
|
212
|
+
* The energy falls as the SQUARE of the amplitude, so it decays twice as fast:
|
|
213
|
+
* an oscillator that has lost half its amplitude has lost three quarters of its
|
|
214
|
+
* energy. That factor of two is the thing most often dropped.
|
|
215
|
+
*/
|
|
216
|
+
declare function dampedAmplitude(initialAmplitude: number, timeConstant: number, t: number): number;
|
|
217
|
+
/** Energy of a lightly damped oscillator after a time: E = E₀·e^(−2t/τ). */
|
|
218
|
+
declare function dampedEnergy(initialEnergy: number, timeConstant: number, t: number): number;
|
|
219
|
+
/** The logarithmic decrement δ = 2πζ/√(1 − ζ²), read off a decaying trace. */
|
|
220
|
+
declare const logarithmicDecrement: (ratio: number) => number;
|
|
221
|
+
/** The damping ratio implied by a measured logarithmic decrement: ζ = δ/√(4π² + δ²). */
|
|
222
|
+
declare function dampingRatioFromDecrement(decrement: number): number;
|
|
223
|
+
//#endregion
|
|
224
|
+
export { DampingRegime, amplificationFactor, amplitudeRatioPerCycle, criticalDamping, dampedAmplitude, dampedAngularFrequency, dampedDisplacement, dampedEnergy, dampedVelocity, dampingRatio, dampingRatioFromDecrement, dampingRegime, decayTimeConstant, drivenAmplitude, drivenPhaseLag, logarithmicDecrement, mechanicalQ, qFromDampingRatio, resonantAngularFrequency, settlingTime };
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
//#region src/waves/damping.ts
|
|
2
|
+
/**
|
|
3
|
+
* Damped and driven oscillation: why a car does not bounce, and why a bridge
|
|
4
|
+
* sometimes does.
|
|
5
|
+
*
|
|
6
|
+
* ## One number decides everything
|
|
7
|
+
*
|
|
8
|
+
* ζ = c / (2√(mk))
|
|
9
|
+
*
|
|
10
|
+
* The damping ratio. It is dimensionless, and it sorts every oscillator into
|
|
11
|
+
* one of three behaviours with no room for anything in between:
|
|
12
|
+
*
|
|
13
|
+
* ζ < 1 UNDERDAMPED overshoots and rings a worn shock absorber
|
|
14
|
+
* ζ = 1 CRITICAL returns fastest, without overshoot a good one
|
|
15
|
+
* ζ > 1 OVERDAMPED returns slowly, without overshoot a door closer
|
|
16
|
+
*
|
|
17
|
+
* The suspension of a car is deliberately set a little under 1, because
|
|
18
|
+
* perfectly critical feels dead and a slight overshoot reads as comfortable.
|
|
19
|
+
* The spring alone would leave ζ = 0 and the car would bounce down the road;
|
|
20
|
+
* the damper is the entire reason it does not.
|
|
21
|
+
*
|
|
22
|
+
* ## Critical damping is not "the most damping"
|
|
23
|
+
*
|
|
24
|
+
* It is the BOUNDARY, and the standard misreading is that more damping always
|
|
25
|
+
* settles faster. It does not. Past ζ = 1 the oscillator crawls back, and an
|
|
26
|
+
* overdamped car would still be sinking into the dip long after it had left it.
|
|
27
|
+
* `settlingTime` is the function that shows this turning round.
|
|
28
|
+
*
|
|
29
|
+
* ## Driving it, and where the peak actually is
|
|
30
|
+
*
|
|
31
|
+
* Push an oscillator at a frequency near its own and the amplitude climbs. The
|
|
32
|
+
* peak is NOT at ω₀ once there is damping: it sits at
|
|
33
|
+
*
|
|
34
|
+
* ω_peak = ω₀√(1 − 2ζ²)
|
|
35
|
+
*
|
|
36
|
+
* and for ζ above 1/√2 ≈ 0.707 there is no peak at all, only a curve that falls
|
|
37
|
+
* from the start. Both of those are routinely taught as "resonance is at the
|
|
38
|
+
* natural frequency", which is the undamped limit of a more interesting fact.
|
|
39
|
+
*
|
|
40
|
+
* ## Relation to the RLC circuit
|
|
41
|
+
*
|
|
42
|
+
* A series RLC is the same equations with m↔L, k↔1/C, c↔R, so `mechanicalQ`
|
|
43
|
+
* here and `qualityFactor` in `@classytic/stage/circuit` are the same quantity
|
|
44
|
+
* for the same reason. They are kept apart because the arguments are different
|
|
45
|
+
* physical things, not because the mathematics differs, and
|
|
46
|
+
* `tests/waves/damping.test.ts` checks that the two agree under the analogy so
|
|
47
|
+
* they cannot drift.
|
|
48
|
+
*
|
|
49
|
+
* Units: SI. The damping coefficient `c` is in N·s/m, so that cv is a force.
|
|
50
|
+
*/
|
|
51
|
+
const finite = (value, what) => {
|
|
52
|
+
if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
|
|
53
|
+
return value;
|
|
54
|
+
};
|
|
55
|
+
const positive = (value, what) => {
|
|
56
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
57
|
+
return value;
|
|
58
|
+
};
|
|
59
|
+
const nonNegative = (value, what) => {
|
|
60
|
+
if (!Number.isFinite(value) || value < 0) throw new RangeError(`${what} cannot be negative.`);
|
|
61
|
+
return value;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* The damping coefficient that sits exactly on the boundary: c_c = 2√(mk).
|
|
65
|
+
*
|
|
66
|
+
* The target a shock absorber is designed against. Quoted in N·s/m, and for a
|
|
67
|
+
* quarter of a family car (around 300 kg on a 30 kN/m spring) it comes out near
|
|
68
|
+
* 6,000 N·s/m. A real damper is fitted at roughly a third of that, because the
|
|
69
|
+
* car is deliberately left underdamped: see the module note above.
|
|
70
|
+
*/
|
|
71
|
+
const criticalDamping = (mass, stiffness) => 2 * Math.sqrt(positive(mass, "A mass") * positive(stiffness, "A spring stiffness"));
|
|
72
|
+
/** The damping ratio ζ = c/c_c. Dimensionless, and the only number that matters. */
|
|
73
|
+
const dampingRatio = (mass, stiffness, coefficient) => nonNegative(coefficient, "A damping coefficient") / criticalDamping(mass, stiffness);
|
|
74
|
+
/**
|
|
75
|
+
* Which of the three behaviours a damping ratio produces.
|
|
76
|
+
*
|
|
77
|
+
* The boundary is tested with a tolerance because exact equality is not
|
|
78
|
+
* something a measured ζ ever achieves, and a ratio of 0.9999999 behaves like
|
|
79
|
+
* critical damping in every way that a learner or a graph can see.
|
|
80
|
+
*/
|
|
81
|
+
function dampingRegime(ratio, tolerance = 1e-9) {
|
|
82
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
83
|
+
if (Math.abs(zeta - 1) <= tolerance) return "critically damped";
|
|
84
|
+
return zeta < 1 ? "underdamped" : "overdamped";
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The frequency a damped oscillator actually rings at: ω_d = ω₀√(1 − ζ²).
|
|
88
|
+
*
|
|
89
|
+
* LOWER than the natural frequency, always. Damping slows the ringing as well
|
|
90
|
+
* as shrinking it, though only slightly until ζ gets large: at ζ = 0.1 the
|
|
91
|
+
* frequency is down by half a percent, which is why the effect is usually
|
|
92
|
+
* ignored and why ignoring it is usually fine.
|
|
93
|
+
*
|
|
94
|
+
* Throws at ζ ≥ 1, where there is no ringing left to have a frequency.
|
|
95
|
+
*/
|
|
96
|
+
function dampedAngularFrequency(naturalOmega, ratio) {
|
|
97
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
98
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
99
|
+
if (zeta >= 1) throw new RangeError(`At a damping ratio of ${zeta} the motion does not oscillate, so it has no damped frequency.`);
|
|
100
|
+
return w0 * Math.sqrt(1 - zeta * zeta);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Displacement of a damped oscillator released from rest at `amplitude`.
|
|
104
|
+
*
|
|
105
|
+
* x(0) = A, v(0) = 0: pulled aside and let go, which is the car meeting a bump
|
|
106
|
+
* and the door being pushed open. All three regimes are handled, and they are
|
|
107
|
+
* three different formulas rather than one with a parameter:
|
|
108
|
+
*
|
|
109
|
+
* under A·e^(−ζω₀t)·[cos ω_d t + (ζω₀/ω_d)·sin ω_d t]
|
|
110
|
+
* critical A·e^(−ω₀t)·(1 + ω₀t)
|
|
111
|
+
* over A·e^(−ζω₀t)·[cosh rt + (ζω₀/r)·sinh rt], r = ω₀√(ζ² − 1)
|
|
112
|
+
*
|
|
113
|
+
* The critical case is not a special case of the other two: at ζ = 1 both ω_d
|
|
114
|
+
* and r are zero and both expressions become 0/0. Evaluating the underdamped
|
|
115
|
+
* form at ζ = 0.99999 gives the right answer only because floating point has
|
|
116
|
+
* not quite reached the singularity yet, which is not a thing to rely on. The
|
|
117
|
+
* tests check that the three agree as ζ approaches 1 from either side, which is
|
|
118
|
+
* what makes the seam safe.
|
|
119
|
+
*/
|
|
120
|
+
function dampedDisplacement(amplitude, naturalOmega, ratio, t) {
|
|
121
|
+
const A = finite(amplitude, "An amplitude");
|
|
122
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
123
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
124
|
+
const time = nonNegative(t, "A time");
|
|
125
|
+
const decay = Math.exp(-zeta * w0 * time);
|
|
126
|
+
if (dampingRegime(zeta) === "critically damped") return A * decay * (1 + w0 * time);
|
|
127
|
+
if (zeta < 1) {
|
|
128
|
+
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
129
|
+
return A * decay * (Math.cos(wd * time) + zeta * w0 / wd * Math.sin(wd * time));
|
|
130
|
+
}
|
|
131
|
+
const r = w0 * Math.sqrt(zeta * zeta - 1);
|
|
132
|
+
return A * decay * (Math.cosh(r * time) + zeta * w0 / r * Math.sinh(r * time));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Velocity of that same released oscillator, m/s.
|
|
136
|
+
*
|
|
137
|
+
* Worth having separately rather than differencing the displacement, because
|
|
138
|
+
* the interesting question about a suspension is how hard it throws you, and
|
|
139
|
+
* that is a rate rather than a position. Every regime collapses to the same
|
|
140
|
+
* tidy form once differentiated:
|
|
141
|
+
*
|
|
142
|
+
* under −A·(ω₀²/ω_d)·e^(−ζω₀t)·sin ω_d t
|
|
143
|
+
* critical −A·ω₀²·t·e^(−ω₀t)
|
|
144
|
+
* over −A·(ω₀²/r)·e^(−ζω₀t)·sinh rt
|
|
145
|
+
*/
|
|
146
|
+
function dampedVelocity(amplitude, naturalOmega, ratio, t) {
|
|
147
|
+
const A = finite(amplitude, "An amplitude");
|
|
148
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
149
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
150
|
+
const time = nonNegative(t, "A time");
|
|
151
|
+
const decay = Math.exp(-zeta * w0 * time);
|
|
152
|
+
if (dampingRegime(zeta) === "critically damped") return -A * w0 * w0 * time * decay;
|
|
153
|
+
if (zeta < 1) {
|
|
154
|
+
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
155
|
+
return -A * (w0 * w0) * decay * Math.sin(wd * time) / wd;
|
|
156
|
+
}
|
|
157
|
+
const r = w0 * Math.sqrt(zeta * zeta - 1);
|
|
158
|
+
return -A * (w0 * w0) * decay * Math.sinh(r * time) / r;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The mechanical quality factor: Q = √(mk)/c = 1/(2ζ).
|
|
162
|
+
*
|
|
163
|
+
* How many radians of oscillation it takes to lose most of the energy, near
|
|
164
|
+
* enough. A tuning fork has a Q in the thousands and rings for seconds; a car
|
|
165
|
+
* suspension has a Q near 1 and does not ring at all, which is the entire
|
|
166
|
+
* design intent.
|
|
167
|
+
*/
|
|
168
|
+
const mechanicalQ = (mass, stiffness, coefficient) => 1 / (2 * dampingRatio(mass, stiffness, coefficient));
|
|
169
|
+
/** Q directly from a damping ratio: Q = 1/(2ζ). */
|
|
170
|
+
const qFromDampingRatio = (ratio) => 1 / (2 * positive(ratio, "A damping ratio"));
|
|
171
|
+
/**
|
|
172
|
+
* The steady amplitude of an oscillator driven at ω by a force of amplitude F₀.
|
|
173
|
+
*
|
|
174
|
+
* A(ω) = (F₀/m) / √((ω₀² − ω²)² + (2ζω₀ω)²)
|
|
175
|
+
*
|
|
176
|
+
* The resonance curve. At ω far below ω₀ it settles to the static deflection
|
|
177
|
+
* F₀/k, which is the sanity check worth knowing: push slowly and the spring
|
|
178
|
+
* just stretches. At ω far above, the mass cannot keep up and the amplitude
|
|
179
|
+
* falls away as 1/ω².
|
|
180
|
+
*
|
|
181
|
+
* With ζ = 0 and ω = ω₀ the denominator is zero and the amplitude is infinite.
|
|
182
|
+
* That is not a bug to guard against: it is the statement that an undriven,
|
|
183
|
+
* undamped resonance has no limit, which is why every real structure has
|
|
184
|
+
* damping designed into it.
|
|
185
|
+
*/
|
|
186
|
+
function drivenAmplitude(forceAmplitude, mass, naturalOmega, ratio, omega) {
|
|
187
|
+
const F0 = nonNegative(forceAmplitude, "A driving force amplitude");
|
|
188
|
+
const m = positive(mass, "A mass");
|
|
189
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
190
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
191
|
+
const w = nonNegative(omega, "A driving angular frequency");
|
|
192
|
+
const denominator = Math.hypot(w0 * w0 - w * w, 2 * zeta * w0 * w);
|
|
193
|
+
return denominator === 0 ? Number.POSITIVE_INFINITY : F0 / m / denominator;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Amplitude as a multiple of the static deflection F₀/k, dimensionless.
|
|
197
|
+
*
|
|
198
|
+
* The shape of the resonance curve with the units taken out, so two oscillators
|
|
199
|
+
* of different size can be compared on one graph. It is 1 at ω = 0 by
|
|
200
|
+
* construction, which anchors the curve at a value a learner can reason about
|
|
201
|
+
* instead of a bare number.
|
|
202
|
+
*/
|
|
203
|
+
function amplificationFactor(naturalOmega, ratio, omega) {
|
|
204
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
205
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
206
|
+
const r = nonNegative(omega, "A driving angular frequency") / w0;
|
|
207
|
+
const denominator = Math.hypot(1 - r * r, 2 * zeta * r);
|
|
208
|
+
return denominator === 0 ? Number.POSITIVE_INFINITY : 1 / denominator;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* The driving frequency that gives the LARGEST amplitude: ω₀√(1 − 2ζ²).
|
|
212
|
+
*
|
|
213
|
+
* Below ω₀, and noticeably so once ζ is appreciable. Above ζ = 1/√2 there is no
|
|
214
|
+
* peak: the amplitude only falls as the driving frequency rises, so a heavily
|
|
215
|
+
* damped system cannot be made to resonate at all. Throws there rather than
|
|
216
|
+
* returning the square root of a negative number, because "there is no
|
|
217
|
+
* resonant frequency" is the answer and NaN does not say it.
|
|
218
|
+
*/
|
|
219
|
+
function resonantAngularFrequency(naturalOmega, ratio) {
|
|
220
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
221
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
222
|
+
if (zeta >= Math.SQRT1_2) throw new RangeError(`At a damping ratio of ${zeta} the amplitude peaks at zero frequency: above 1/√2 there is no resonance to find.`);
|
|
223
|
+
return w0 * Math.sqrt(1 - 2 * zeta * zeta);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* The phase by which the oscillator lags the driving force, radians, 0 to π.
|
|
227
|
+
*
|
|
228
|
+
* tan φ = 2ζ(ω/ω₀) / (1 − (ω/ω₀)²)
|
|
229
|
+
*
|
|
230
|
+
* Exactly π/2 AT ω₀, whatever the damping, and that is the sharpest way to find
|
|
231
|
+
* a resonance in practice: the amplitude peak moves with ζ and is broad, but the
|
|
232
|
+
* quarter-cycle lag sits at ω₀ and crosses steeply. Well below resonance the
|
|
233
|
+
* mass follows the force in step; well above, it moves exactly opposite to it,
|
|
234
|
+
* which is why a spinning machine mounted softly enough transmits almost
|
|
235
|
+
* nothing to its floor.
|
|
236
|
+
*/
|
|
237
|
+
function drivenPhaseLag(naturalOmega, ratio, omega) {
|
|
238
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
239
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
240
|
+
const r = nonNegative(omega, "A driving angular frequency") / w0;
|
|
241
|
+
const lag = Math.atan2(2 * zeta * r, 1 - r * r);
|
|
242
|
+
return lag < 0 ? lag + Math.PI : lag;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* How long until a released oscillator stays within `band` of its amplitude.
|
|
246
|
+
*
|
|
247
|
+
* `band` is a fraction, so 0.05 is the usual "settled to within 5 %". Found by
|
|
248
|
+
* stepping rather than solved, because the crossing has no closed form once the
|
|
249
|
+
* oscillation is still ringing through the band.
|
|
250
|
+
*
|
|
251
|
+
* The reason this function exists is to make the turning point visible: sweep ζ
|
|
252
|
+
* and the settling time falls to a minimum near 1 and climbs again after it.
|
|
253
|
+
* That minimum is what a suspension engineer is buying.
|
|
254
|
+
*/
|
|
255
|
+
function settlingTime(naturalOmega, ratio, band = .05, maxPeriods = 200) {
|
|
256
|
+
const w0 = positive(naturalOmega, "A natural angular frequency");
|
|
257
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
258
|
+
if (!(band > 0 && band < 1)) throw new RangeError("A settling band must be a fraction between 0 and 1.");
|
|
259
|
+
if (zeta === 0) return Number.POSITIVE_INFINITY;
|
|
260
|
+
const horizon = maxPeriods * 2 * Math.PI / w0;
|
|
261
|
+
const step = 2 * Math.PI / w0 / 400;
|
|
262
|
+
let settledAt = Number.POSITIVE_INFINITY;
|
|
263
|
+
for (let t = 0; t <= horizon; t += step) if (Math.abs(dampedDisplacement(1, w0, zeta, t)) > band) settledAt = Number.POSITIVE_INFINITY;
|
|
264
|
+
else if (settledAt === Number.POSITIVE_INFINITY) settledAt = t;
|
|
265
|
+
return settledAt;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The fraction of its amplitude an underdamped oscillator keeps each cycle.
|
|
269
|
+
*
|
|
270
|
+
* ratio = e^(−2πζ/√(1 − ζ²))
|
|
271
|
+
*
|
|
272
|
+
* Successive peaks fall by the same FACTOR, never the same amount, so the decay
|
|
273
|
+
* is a geometric sequence. The natural logarithm of this is the logarithmic
|
|
274
|
+
* decrement, which is how ζ is measured off a real trace: count the peaks.
|
|
275
|
+
*/
|
|
276
|
+
function amplitudeRatioPerCycle(ratio) {
|
|
277
|
+
const zeta = nonNegative(ratio, "A damping ratio");
|
|
278
|
+
if (zeta >= 1) throw new RangeError(`At a damping ratio of ${zeta} there are no successive peaks to compare.`);
|
|
279
|
+
return Math.exp(-2 * Math.PI * zeta / Math.sqrt(1 - zeta * zeta));
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* The decay time constant, seconds: τ = 1/(ζω₀).
|
|
283
|
+
*
|
|
284
|
+
* The bridge between the two ways this topic is parameterised. Engineering
|
|
285
|
+
* states damping as ζ; the light-damping treatment in most physics courses
|
|
286
|
+
* states it as an envelope A₀·e^(−t/τ) and never mentions ζ at all. They are
|
|
287
|
+
* the same oscillator, and this is the conversion, so neither vocabulary needs
|
|
288
|
+
* its own copy of the decay.
|
|
289
|
+
*/
|
|
290
|
+
const decayTimeConstant = (naturalOmega, ratio) => 1 / (positive(naturalOmega, "A natural angular frequency") * positive(ratio, "A damping ratio"));
|
|
291
|
+
/**
|
|
292
|
+
* Amplitude of a lightly damped oscillator after a time: A = A₀·e^(−t/τ).
|
|
293
|
+
*
|
|
294
|
+
* The ENVELOPE, not the displacement: the oscillation rings inside this curve
|
|
295
|
+
* and touches it at the peaks. `dampedDisplacement` is the thing itself.
|
|
296
|
+
*
|
|
297
|
+
* The energy falls as the SQUARE of the amplitude, so it decays twice as fast:
|
|
298
|
+
* an oscillator that has lost half its amplitude has lost three quarters of its
|
|
299
|
+
* energy. That factor of two is the thing most often dropped.
|
|
300
|
+
*/
|
|
301
|
+
function dampedAmplitude(initialAmplitude, timeConstant, t) {
|
|
302
|
+
return positive(initialAmplitude, "An amplitude") * Math.exp(-Math.max(0, finite(t, "A time")) / positive(timeConstant, "A time constant"));
|
|
303
|
+
}
|
|
304
|
+
/** Energy of a lightly damped oscillator after a time: E = E₀·e^(−2t/τ). */
|
|
305
|
+
function dampedEnergy(initialEnergy, timeConstant, t) {
|
|
306
|
+
return positive(initialEnergy, "An energy") * Math.exp(-2 * Math.max(0, finite(t, "A time")) / positive(timeConstant, "A time constant"));
|
|
307
|
+
}
|
|
308
|
+
/** The logarithmic decrement δ = 2πζ/√(1 − ζ²), read off a decaying trace. */
|
|
309
|
+
const logarithmicDecrement = (ratio) => -Math.log(amplitudeRatioPerCycle(ratio));
|
|
310
|
+
/** The damping ratio implied by a measured logarithmic decrement: ζ = δ/√(4π² + δ²). */
|
|
311
|
+
function dampingRatioFromDecrement(decrement) {
|
|
312
|
+
const d = positive(decrement, "A logarithmic decrement");
|
|
313
|
+
return d / Math.sqrt(4 * Math.PI ** 2 + d * d);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
//#endregion
|
|
317
|
+
export { amplificationFactor, amplitudeRatioPerCycle, criticalDamping, dampedAmplitude, dampedAngularFrequency, dampedDisplacement, dampedEnergy, dampedVelocity, dampingRatio, dampingRatioFromDecrement, dampingRegime, decayTimeConstant, drivenAmplitude, drivenPhaseLag, logarithmicDecrement, mechanicalQ, qFromDampingRatio, resonantAngularFrequency, settlingTime };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Vec2 } from "../core/vec.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/waves/doppler.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Component of a velocity along the line from source to observer, positive when closing.
|
|
6
|
+
*
|
|
7
|
+
* This is what turns the one-dimensional textbook formula into something a scene can use: only the
|
|
8
|
+
* radial part shifts the pitch, so a source passing to one side is at its unshifted frequency at
|
|
9
|
+
* the moment of closest approach, when all of its motion is transverse. That instant is the thing a
|
|
10
|
+
* learner should see and almost never does.
|
|
11
|
+
*/
|
|
12
|
+
declare function radialSpeed(source: Vec2, observer: Vec2, velocity: Vec2): number;
|
|
13
|
+
/**
|
|
14
|
+
* Observed frequency for a source moving through a still medium: `f_s v / (v - v_r)`.
|
|
15
|
+
*
|
|
16
|
+
* `radialSourceSpeed` is positive when the source is closing on the observer. Returns `Infinity` at
|
|
17
|
+
* exactly Mach 1 (see the header) and a NEGATIVE frequency above it, which is the honest reading of
|
|
18
|
+
* the formula in a regime where it no longer describes anything: past the sound barrier the wave
|
|
19
|
+
* arrives before the source does, and this expression stops being the right model. Callers should
|
|
20
|
+
* branch on `machNumber >= 1` rather than trusting the number.
|
|
21
|
+
*/
|
|
22
|
+
declare function observedFrequencyMovingSource(sourceFrequency: number, waveSpeed: number, radialSourceSpeed: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Observed frequency for an observer moving through a still medium: `f_s (v + v_r) / v`.
|
|
25
|
+
*
|
|
26
|
+
* Note the different shape: this one cannot diverge, because the observer cannot outrun the wave
|
|
27
|
+
* into a zero denominator. Racing away at exactly the wave speed gives zero, which is right, as the
|
|
28
|
+
* crests never catch up.
|
|
29
|
+
*/
|
|
30
|
+
declare function observedFrequencyMovingObserver(sourceFrequency: number, waveSpeed: number, radialObserverSpeed: number): number;
|
|
31
|
+
/**
|
|
32
|
+
* Both moving, the general case: `f_s (v + v_o) / (v - v_s)`.
|
|
33
|
+
*
|
|
34
|
+
* Provided because a scene with a moving listener needs it, not because the syllabus asks. Radial
|
|
35
|
+
* speeds are positive when closing, for both.
|
|
36
|
+
*/
|
|
37
|
+
declare function observedFrequency(sourceFrequency: number, waveSpeed: number, radialSourceSpeed: number, radialObserverSpeed?: number): number;
|
|
38
|
+
/** Wavelength in the medium ahead of a moving source: `(v - v_s) / f_s`. Goes to zero at Mach 1. */
|
|
39
|
+
declare function wavelengthAhead(sourceFrequency: number, waveSpeed: number, sourceSpeed: number): number;
|
|
40
|
+
/** Wavelength behind a moving source: `(v + v_s) / f_s`. */
|
|
41
|
+
declare function wavelengthBehind(sourceFrequency: number, waveSpeed: number, sourceSpeed: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* The rise coming and the fall going, as multiples of the source frequency.
|
|
44
|
+
*
|
|
45
|
+
* Returns `{ approaching, receding, riseOverFall }`. The third number is the one worth showing: it
|
|
46
|
+
* is never 1, and it grows with speed, so "the pitch drops as it passes" is only half the story.
|
|
47
|
+
*/
|
|
48
|
+
declare function frequencyShiftAsymmetry(waveSpeed: number, sourceSpeed: number): {
|
|
49
|
+
approaching: number;
|
|
50
|
+
receding: number;
|
|
51
|
+
riseOverFall: number;
|
|
52
|
+
};
|
|
53
|
+
/** Mach number: source speed as a multiple of the wave speed. */
|
|
54
|
+
declare function machNumber(sourceSpeed: number, waveSpeed: number): number;
|
|
55
|
+
/**
|
|
56
|
+
* Half-angle of the Mach cone, radians: `asin(1 / M)`.
|
|
57
|
+
*
|
|
58
|
+
* `null` below Mach 1, because there is no cone: the wavefronts still nest inside one another and
|
|
59
|
+
* nothing piles up. Returning null rather than NaN lets a scene ask "is there a cone" by asking.
|
|
60
|
+
*/
|
|
61
|
+
declare function machConeHalfAngle(mach: number): number | null;
|
|
62
|
+
/** Radius a wavefront has reached, given when it left and the time now. */
|
|
63
|
+
declare function wavefrontRadius(waveSpeed: number, emittedAt: number, now: number): number;
|
|
64
|
+
/**
|
|
65
|
+
* Speed of a source from a measured frequency shift, which is the direction the astronomy and radar
|
|
66
|
+
* uses run in: you have `f_o` and want `v`.
|
|
67
|
+
*
|
|
68
|
+
* `v_s = v (1 - f_s / f_o)`, positive when closing.
|
|
69
|
+
*/
|
|
70
|
+
declare function sourceSpeedFromShift(sourceFrequency: number, observedFrequency: number, waveSpeed: number): number;
|
|
71
|
+
//#endregion
|
|
72
|
+
export { frequencyShiftAsymmetry, machConeHalfAngle, machNumber, observedFrequency, observedFrequencyMovingObserver, observedFrequencyMovingSource, radialSpeed, sourceSpeedFromShift, wavefrontRadius, wavelengthAhead, wavelengthBehind };
|