@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
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
//#region src/waves/pitch.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pitch: turning a frequency into a note, and a note into a place on a string.
|
|
4
|
+
*
|
|
5
|
+
* ## Why pitch is logarithmic, and why that is not a convention
|
|
6
|
+
*
|
|
7
|
+
* Doubling a frequency sounds like the same step wherever you start. 220 to
|
|
8
|
+
* 440 Hz and 440 to 880 Hz are both "an octave", although the second gap is
|
|
9
|
+
* twice as many hertz. So the ear measures RATIOS, and anything that behaves
|
|
10
|
+
* like a distance in pitch has to be a logarithm of one.
|
|
11
|
+
*
|
|
12
|
+
* one octave = ratio 2 = 1200 cents
|
|
13
|
+
* one semitone = ratio 2^(1/12) = 100 cents
|
|
14
|
+
*
|
|
15
|
+
* A cent is a hundredth of a semitone and is the unit tuners actually use,
|
|
16
|
+
* because "three hertz flat" means something different on a bass string and a
|
|
17
|
+
* piccolo while "eight cents flat" means the same thing everywhere.
|
|
18
|
+
*
|
|
19
|
+
* ## The twelfth root of two, and what it costs
|
|
20
|
+
*
|
|
21
|
+
* Equal temperament divides the octave into twelve identical ratio steps. The
|
|
22
|
+
* price is that no interval except the octave is exactly a whole-number ratio:
|
|
23
|
+
*
|
|
24
|
+
* pure fifth (3:2) 701.955 cents
|
|
25
|
+
* equal-tempered fifth 700 cents
|
|
26
|
+
*
|
|
27
|
+
* Two cents flat, everywhere, forever. That deliberate two-cent error is what
|
|
28
|
+
* buys you the ability to change key, and it is the reason a guitar is fretted
|
|
29
|
+
* the way it is. `centsBetween` makes the compromise something you can measure
|
|
30
|
+
* rather than a claim.
|
|
31
|
+
*
|
|
32
|
+
* ## Frets are geometric, not evenly spaced
|
|
33
|
+
*
|
|
34
|
+
* A fret shortens the vibrating length by a RATIO, so the gaps shrink as you go
|
|
35
|
+
* up the neck. The twelfth fret is exactly halfway along the string, because
|
|
36
|
+
* halving the length doubles the frequency: 2^(−12/12) = 1/2. That is a fact
|
|
37
|
+
* you can check with a ruler on a real guitar, which is the best kind.
|
|
38
|
+
*
|
|
39
|
+
* Units: frequencies in hertz, lengths in metres (or any one consistent unit,
|
|
40
|
+
* since `fretPosition` is a proportion of what it is given).
|
|
41
|
+
*/
|
|
42
|
+
const finite = (value, what) => {
|
|
43
|
+
if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
|
|
44
|
+
return value;
|
|
45
|
+
};
|
|
46
|
+
const positive = (value, what) => {
|
|
47
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
/** Concert A, hertz. The peg the whole system hangs from, fixed by agreement rather than physics. */
|
|
51
|
+
const A4_HZ = 440;
|
|
52
|
+
/** The frequency ratio of one equal-tempered semitone: the twelfth root of two. */
|
|
53
|
+
const SEMITONE_RATIO = Math.pow(2, 1 / 12);
|
|
54
|
+
/** Cents in one octave. A cent is a hundredth of a semitone. */
|
|
55
|
+
const CENTS_PER_OCTAVE = 1200;
|
|
56
|
+
/**
|
|
57
|
+
* The frequency a given number of semitones away: f·2^(n/12).
|
|
58
|
+
*
|
|
59
|
+
* `n` may be negative for downward, and need not be a whole number: a
|
|
60
|
+
* half-semitone is a perfectly good quarter tone, and bending a guitar string
|
|
61
|
+
* lands you between the frets.
|
|
62
|
+
*/
|
|
63
|
+
const frequencyAfterSemitones = (frequency, semitones) => positive(frequency, "A frequency") * Math.pow(2, finite(semitones, "A number of semitones") / 12);
|
|
64
|
+
/** How many semitones apart two frequencies are: 12·log₂(f₂/f₁). Signed. */
|
|
65
|
+
const semitonesBetween = (from, to) => 12 * Math.log2(positive(to, "A frequency") / positive(from, "A frequency"));
|
|
66
|
+
/**
|
|
67
|
+
* The interval between two frequencies in CENTS: 1200·log₂(f₂/f₁).
|
|
68
|
+
*
|
|
69
|
+
* Signed, so a negative result means `to` is flat of `from`. The numbers worth
|
|
70
|
+
* carrying: about 5 cents is the smallest error most people hear on a sustained
|
|
71
|
+
* note, 10 to 15 cents sounds wrong, and a semitone is 100.
|
|
72
|
+
*
|
|
73
|
+
* This is the function that makes "how out of tune is it" answerable. A gap of
|
|
74
|
+
* 3 Hz is badly out on a low E at 82 Hz and inaudible on a harmonic at 1300 Hz;
|
|
75
|
+
* in cents both questions have the same answer scale.
|
|
76
|
+
*/
|
|
77
|
+
const centsBetween = (from, to) => CENTS_PER_OCTAVE * Math.log2(positive(to, "A frequency") / positive(from, "A frequency"));
|
|
78
|
+
/** The frequency a number of cents away from a reference. The inverse of `centsBetween`. */
|
|
79
|
+
const frequencyAfterCents = (frequency, cents) => positive(frequency, "A frequency") * Math.pow(2, finite(cents, "An interval in cents") / CENTS_PER_OCTAVE);
|
|
80
|
+
/**
|
|
81
|
+
* Whether a frequency counts as in tune against a target.
|
|
82
|
+
*
|
|
83
|
+
* `toleranceCents` defaults to 5, which is roughly the threshold at which a
|
|
84
|
+
* sustained note starts to sound wrong to an ordinary listener. Expressed in
|
|
85
|
+
* cents rather than hertz on purpose: a fixed hertz tolerance would be far too
|
|
86
|
+
* strict at the top of the range and useless at the bottom.
|
|
87
|
+
*/
|
|
88
|
+
const isInTune = (frequency, target, toleranceCents = 5) => Math.abs(centsBetween(target, frequency)) <= positive(toleranceCents, "A tolerance");
|
|
89
|
+
/**
|
|
90
|
+
* The length of string still free to vibrate when a fret is held down.
|
|
91
|
+
*
|
|
92
|
+
* `L·2^(−n/12)`: each fret divides the length by the same ratio, which is why
|
|
93
|
+
* they crowd together going up the neck.
|
|
94
|
+
*/
|
|
95
|
+
const frettedLength = (scaleLength, fret) => positive(scaleLength, "A scale length") * Math.pow(2, -nonNegativeFret(fret) / 12);
|
|
96
|
+
/**
|
|
97
|
+
* How far along the string a fret sits, measured from the nut.
|
|
98
|
+
*
|
|
99
|
+
* `L(1 − 2^(−n/12))`. Fret 12 comes out at exactly L/2, which is the check that
|
|
100
|
+
* the formula is the right way round and the thing to verify against a real
|
|
101
|
+
* instrument.
|
|
102
|
+
*/
|
|
103
|
+
const fretPosition = (scaleLength, fret) => positive(scaleLength, "A scale length") - frettedLength(scaleLength, fret);
|
|
104
|
+
/** The gap between two consecutive frets. Always smaller than the one below it. */
|
|
105
|
+
const fretSpacing = (scaleLength, fret) => fretPosition(scaleLength, nonNegativeFret(fret) + 1) - fretPosition(scaleLength, fret);
|
|
106
|
+
function nonNegativeFret(fret) {
|
|
107
|
+
if (!Number.isInteger(fret) || fret < 0) throw new RangeError(`A fret number must be a whole number of at least 0, not ${fret}.`);
|
|
108
|
+
return fret;
|
|
109
|
+
}
|
|
110
|
+
/** The names of the twelve semitones, starting at C. Sharps only; no enharmonic choice is made. */
|
|
111
|
+
const SEMITONE_NAMES = [
|
|
112
|
+
"C",
|
|
113
|
+
"C♯",
|
|
114
|
+
"D",
|
|
115
|
+
"D♯",
|
|
116
|
+
"E",
|
|
117
|
+
"F",
|
|
118
|
+
"F♯",
|
|
119
|
+
"G",
|
|
120
|
+
"G♯",
|
|
121
|
+
"A",
|
|
122
|
+
"A♯",
|
|
123
|
+
"B"
|
|
124
|
+
];
|
|
125
|
+
/**
|
|
126
|
+
* The nearest named note to a frequency, and how far off it is.
|
|
127
|
+
*
|
|
128
|
+
* Returns the note with its octave number in scientific pitch notation (A4 is
|
|
129
|
+
* concert A), plus the signed error in cents. The error is the useful half: a
|
|
130
|
+
* tuner is a device for driving that number to zero.
|
|
131
|
+
*/
|
|
132
|
+
function nearestNote(frequency) {
|
|
133
|
+
const exact = semitonesBetween(440, positive(frequency, "A frequency"));
|
|
134
|
+
const steps = Math.round(exact);
|
|
135
|
+
const cents = (exact - steps) * 100;
|
|
136
|
+
const fromC0 = steps + 9 + 48;
|
|
137
|
+
const octave = Math.floor(fromC0 / 12);
|
|
138
|
+
return {
|
|
139
|
+
name: SEMITONE_NAMES[(fromC0 % 12 + 12) % 12],
|
|
140
|
+
octave,
|
|
141
|
+
cents
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The size of a just interval in cents, for comparison with the tempered one.
|
|
146
|
+
*
|
|
147
|
+
* `justIntervalCents(3, 2)` is the pure fifth at 701.955, against the
|
|
148
|
+
* equal-tempered 700. Feeding the small whole-number ratios through this is how
|
|
149
|
+
* the compromise in equal temperament stops being a story: the major third is
|
|
150
|
+
* the bad one, 386.3 just against 400 tempered, nearly 14 cents sharp, and it
|
|
151
|
+
* is audible.
|
|
152
|
+
*/
|
|
153
|
+
const justIntervalCents = (numerator, denominator) => CENTS_PER_OCTAVE * Math.log2(positive(numerator, "A ratio numerator") / positive(denominator, "A ratio denominator"));
|
|
154
|
+
/** The equal-tempered size of an interval of `semitones`, in cents. Always a multiple of 100. */
|
|
155
|
+
const temperedIntervalCents = (semitones) => 100 * finite(semitones, "A number of semitones");
|
|
156
|
+
|
|
157
|
+
//#endregion
|
|
158
|
+
export { A4_HZ, CENTS_PER_OCTAVE, SEMITONE_NAMES, SEMITONE_RATIO, centsBetween, frequencyAfterCents, frequencyAfterSemitones, fretPosition, fretSpacing, frettedLength, isInTune, justIntervalCents, nearestNote, semitonesBetween, temperedIntervalCents };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Worked } from "../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/waves/shm.d.ts
|
|
4
|
+
/** Angular frequency from a period: ω = 2π/T, rad/s. */
|
|
5
|
+
declare const angularFrequencyFromPeriod: (periodSeconds: number) => number;
|
|
6
|
+
/** Period from an angular frequency: T = 2π/ω, seconds. */
|
|
7
|
+
declare const periodFromAngularFrequency: (omega: number) => number;
|
|
8
|
+
/**
|
|
9
|
+
* Displacement at time t, starting from the CENTRE moving positive:
|
|
10
|
+
* x = A·sin(ωt + φ).
|
|
11
|
+
*
|
|
12
|
+
* Pass `phase = π/2` to start at maximum displacement instead, which is what a
|
|
13
|
+
* released-from-rest problem describes. Two starting conventions exist and both
|
|
14
|
+
* are called "the" SHM equation in different books, so the phase is explicit
|
|
15
|
+
* rather than baked in.
|
|
16
|
+
*/
|
|
17
|
+
declare function shmDisplacement(amplitude: number, omega: number, t: number, phase?: number): number;
|
|
18
|
+
/** Velocity at time t: v = ωA·cos(ωt + φ), m/s. */
|
|
19
|
+
declare function shmVelocity(amplitude: number, omega: number, t: number, phase?: number): number;
|
|
20
|
+
/** Acceleration at time t: a = −ω²x, m/s². */
|
|
21
|
+
declare function shmAcceleration(amplitude: number, omega: number, t: number, phase?: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* SPEED at a displacement, m/s: v = ω√(A² − x²).
|
|
24
|
+
*
|
|
25
|
+
* The workhorse. Independent of time and of where the motion started, so it
|
|
26
|
+
* answers "how fast at half amplitude" without anyone having to find t first.
|
|
27
|
+
* Returns the magnitude; the oscillator passes each point twice a cycle, once
|
|
28
|
+
* each way, and which one is a question about direction rather than speed.
|
|
29
|
+
*/
|
|
30
|
+
declare function speedAtDisplacement(amplitude: number, omega: number, displacement: number): number;
|
|
31
|
+
/** The displacement at which the oscillator reaches a given speed, m. */
|
|
32
|
+
declare function displacementAtSpeed(amplitude: number, omega: number, speed: number): number;
|
|
33
|
+
/** Greatest speed, at the centre: v_max = ωA, m/s. */
|
|
34
|
+
declare const maxSpeed: (amplitude: number, omega: number) => number;
|
|
35
|
+
/** Greatest acceleration, at the extremes: a_max = ω²A, m/s². */
|
|
36
|
+
declare const maxAcceleration: (amplitude: number, omega: number) => number;
|
|
37
|
+
interface OscillatorState {
|
|
38
|
+
/** Displacement, m. */
|
|
39
|
+
displacement: number;
|
|
40
|
+
/** Velocity, m/s. Signed: the direction of travel is the point of it. */
|
|
41
|
+
velocity: number;
|
|
42
|
+
/** Acceleration, m/s². Always −ω² times the displacement. */
|
|
43
|
+
acceleration: number;
|
|
44
|
+
/** The phase ωt + φ at this instant, radians, unwrapped. */
|
|
45
|
+
phase: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Displacement, velocity and acceleration at one instant, in one call.
|
|
49
|
+
*
|
|
50
|
+
* ## Why this exists rather than three calls
|
|
51
|
+
*
|
|
52
|
+
* Because the three are ONE object, and anything that draws them has to draw
|
|
53
|
+
* them from the same instant or the picture lies. A render loop asking for
|
|
54
|
+
* displacement, then velocity, then acceleration is three chances to pass a
|
|
55
|
+
* different `t`, and the symptom is a v–t curve that is no longer a quarter
|
|
56
|
+
* cycle ahead of the x–t one: a phase error that looks like a physics error.
|
|
57
|
+
*
|
|
58
|
+
* ## The chain the three form
|
|
59
|
+
*
|
|
60
|
+
* x = A·sin(ωt + φ)
|
|
61
|
+
* v = ωA·cos(ωt + φ) a quarter cycle AHEAD of x
|
|
62
|
+
* a = −ω²A·sin(ωt + φ) a quarter cycle ahead of v, so ANTIPHASE with x
|
|
63
|
+
*
|
|
64
|
+
* Each differentiation multiplies by ω and advances the phase by π/2. Two of
|
|
65
|
+
* them bring you back to a sine with a minus sign in front, which is the whole
|
|
66
|
+
* of a = −ω²x: the defining property of the motion falls out of differentiating
|
|
67
|
+
* twice and is not an extra assumption.
|
|
68
|
+
*
|
|
69
|
+
* `tests/waves/shm.test.ts` asserts each quarter-cycle lead against the others
|
|
70
|
+
* rather than against a formula, so the chain cannot be broken in one place
|
|
71
|
+
* only.
|
|
72
|
+
*/
|
|
73
|
+
declare function oscillatorStateAt(amplitude: number, omega: number, t: number, phase?: number): OscillatorState;
|
|
74
|
+
interface OscillatorEnergy {
|
|
75
|
+
/** Kinetic energy at this displacement, J. */
|
|
76
|
+
kinetic: number;
|
|
77
|
+
/** Potential energy at this displacement, J. */
|
|
78
|
+
potential: number;
|
|
79
|
+
/** The total, J. The same number at every displacement. */
|
|
80
|
+
total: number;
|
|
81
|
+
/**
|
|
82
|
+
* kinetic + potential − total, J.
|
|
83
|
+
*
|
|
84
|
+
* Reported rather than asserted, following the same choice the energy ledger
|
|
85
|
+
* makes elsewhere in this package: it must be zero to within rounding, and a
|
|
86
|
+
* caller who wants to PROVE conservation gets to see the number rather than
|
|
87
|
+
* take it on trust.
|
|
88
|
+
*/
|
|
89
|
+
residual: number;
|
|
90
|
+
/** Fraction of the total that is kinetic, 0 to 1. */
|
|
91
|
+
kineticFraction: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The energy split at a displacement.
|
|
95
|
+
*
|
|
96
|
+
* At x = 0 it is all kinetic, at x = ±A all potential, and at x = A/√2 exactly
|
|
97
|
+
* half each — which is the answer to "where is the energy shared equally" and
|
|
98
|
+
* is NOT at half amplitude, the usual guess.
|
|
99
|
+
*/
|
|
100
|
+
declare function energyAt(mass: number, amplitude: number, omega: number, displacement: number): OscillatorEnergy;
|
|
101
|
+
/** Total energy of the oscillation, J: E = ½mω²A². Independent of position. */
|
|
102
|
+
declare const totalEnergy: (mass: number, amplitude: number, omega: number) => number;
|
|
103
|
+
/**
|
|
104
|
+
* The displacement at which kinetic and potential are equal: x = A/√2.
|
|
105
|
+
*
|
|
106
|
+
* About 0.707 of the amplitude, not 0.5. The energies go as x², so the halfway
|
|
107
|
+
* point in ENERGY is not the halfway point in distance, and that gap is the
|
|
108
|
+
* whole lesson.
|
|
109
|
+
*/
|
|
110
|
+
declare const equalEnergyDisplacement: (amplitude: number) => number;
|
|
111
|
+
/**
|
|
112
|
+
* The energy split at a displacement, worked, in the form the question wants.
|
|
113
|
+
*
|
|
114
|
+
* Deliberately arrives at the same three numbers by TWO routes and shows both:
|
|
115
|
+
* ½mω²(A² − x²) directly, and ½mv² from the speed at that point. They must
|
|
116
|
+
* agree, and seeing them agree is the argument that the energy picture and the
|
|
117
|
+
* kinematic picture are one thing rather than two topics.
|
|
118
|
+
*
|
|
119
|
+
* The final step reports KE + PE against the total rather than asserting that
|
|
120
|
+
* they match, which is the same choice the energy ledger makes elsewhere in the
|
|
121
|
+
* package: conservation is evidence here, not a claim.
|
|
122
|
+
*/
|
|
123
|
+
declare function energyAtSteps(mass: number, amplitude: number, omega: number, displacement: number, sf?: number): Worked;
|
|
124
|
+
/**
|
|
125
|
+
* Period of a mass on a spring: T = 2π√(m/k), seconds.
|
|
126
|
+
*
|
|
127
|
+
* Independent of amplitude, which is the surprising part and the practical one:
|
|
128
|
+
* a spring clock keeps time even as the swing dies away.
|
|
129
|
+
*/
|
|
130
|
+
declare const springPeriod: (mass: number, stiffness: number) => number;
|
|
131
|
+
/** Angular frequency of a mass on a spring: ω = √(k/m), rad/s. */
|
|
132
|
+
declare const springAngularFrequency: (mass: number, stiffness: number) => number;
|
|
133
|
+
/**
|
|
134
|
+
* The period of the ENERGY, seconds: half the period of the motion.
|
|
135
|
+
*
|
|
136
|
+
* The single most reliable trap in the topic. Kinetic energy goes as cos²(ωt),
|
|
137
|
+
* and a squared sinusoid repeats twice as often as the sinusoid does: the
|
|
138
|
+
* oscillator is at full speed at the centre going one way AND going the other,
|
|
139
|
+
* and the energy cannot tell those apart because it does not carry a sign.
|
|
140
|
+
*
|
|
141
|
+
* So a question that gives you an energy-against-time graph and asks for the
|
|
142
|
+
* period of the MOTION wants twice what the graph shows. Reading the graph's
|
|
143
|
+
* own period straight off is the wrong answer, and it is wrong by exactly the
|
|
144
|
+
* factor this function applies.
|
|
145
|
+
*/
|
|
146
|
+
declare const energyPeriod: (period: number) => number;
|
|
147
|
+
/**
|
|
148
|
+
* The amplitude implied by a displacement and a velocity at the same moment:
|
|
149
|
+
* A = √(x² + (v/ω)²).
|
|
150
|
+
*
|
|
151
|
+
* v = ω√(A² − x²) rearranged. Any snapshot of the motion fixes the amplitude,
|
|
152
|
+
* which is how a question that never mentions an amplitude can still be asking
|
|
153
|
+
* for the total energy.
|
|
154
|
+
*/
|
|
155
|
+
declare function amplitudeFromState(omega: number, displacement: number, velocity: number): number;
|
|
156
|
+
/**
|
|
157
|
+
* The phase angle δ in x = A·sin(ωt + δ), from the state at t = 0.
|
|
158
|
+
*
|
|
159
|
+
* Returned in radians on (−π, π]. Uses `atan2` on (xω, v) rather than
|
|
160
|
+
* `asin(x₀/A)`, and that choice is the whole function: `asin` cannot tell a
|
|
161
|
+
* mass at +A/2 moving outward from one at +A/2 moving back, because they share
|
|
162
|
+
* a sine and differ only in the sign of the cosine. Half the answers from the
|
|
163
|
+
* `asin` route are the wrong one of the two, silently.
|
|
164
|
+
*
|
|
165
|
+
* The familiar special cases fall out: released from rest at full displacement
|
|
166
|
+
* gives π/2, so x = A·cos(ωt); started from the centre moving positive gives 0.
|
|
167
|
+
*/
|
|
168
|
+
declare function phaseFromState(omega: number, displacement: number, velocity: number): number;
|
|
169
|
+
//#endregion
|
|
170
|
+
export { OscillatorEnergy, OscillatorState, amplitudeFromState, angularFrequencyFromPeriod, displacementAtSpeed, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, maxAcceleration, maxSpeed, oscillatorStateAt, periodFromAngularFrequency, phaseFromState, shmAcceleration, shmDisplacement, shmVelocity, speedAtDisplacement, springAngularFrequency, springPeriod, totalEnergy };
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { calc, texNum, texSigFigs } from "../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/waves/shm.ts
|
|
4
|
+
/**
|
|
5
|
+
* Simple harmonic motion, and the energy bookkeeping that goes with it.
|
|
6
|
+
*
|
|
7
|
+
* ## The definition, which is the acceleration and not the sine
|
|
8
|
+
*
|
|
9
|
+
* a = −ω²x
|
|
10
|
+
*
|
|
11
|
+
* Acceleration proportional to displacement and directed back towards the
|
|
12
|
+
* centre. The sinusoid is a CONSEQUENCE of that, not the definition, and the
|
|
13
|
+
* distinction matters: a pendulum at large amplitude still swings back and
|
|
14
|
+
* forth sinusoidally to the eye, but its acceleration stops being proportional
|
|
15
|
+
* to displacement and its period starts depending on amplitude. The defining
|
|
16
|
+
* property is the one that fails first.
|
|
17
|
+
*
|
|
18
|
+
* ## The relation this module exists for
|
|
19
|
+
*
|
|
20
|
+
* v = ±ω·√(A² − x²)
|
|
21
|
+
*
|
|
22
|
+
* Speed as a function of POSITION rather than of time. Nearly every question
|
|
23
|
+
* that asks "how fast is it moving when it is halfway out" is this, and it is
|
|
24
|
+
* the bridge to energy: square it, multiply by ½m, and the kinetic energy falls
|
|
25
|
+
* out as ½mω²(A² − x²). The potential is whatever is left of the total, and the
|
|
26
|
+
* total is constant. That is conservation, visible as arithmetic rather than
|
|
27
|
+
* asserted.
|
|
28
|
+
*
|
|
29
|
+
* KE = ½mω²(A² − x²) max at the centre, zero at the extremes
|
|
30
|
+
* PE = ½mω²x² zero at the centre, max at the extremes
|
|
31
|
+
* E = ½mω²A² constant, independent of x
|
|
32
|
+
*
|
|
33
|
+
* Note KE + PE = ½mω²A² identically, for every x. `energyAt` returns all three
|
|
34
|
+
* and the residual, so a lab can SHOW the sum staying put while the two halves
|
|
35
|
+
* trade, rather than claiming it does.
|
|
36
|
+
*
|
|
37
|
+
* ## Scope
|
|
38
|
+
*
|
|
39
|
+
* The IDEAL oscillator: no damping, no driving, and given its ω rather than
|
|
40
|
+
* working one out. The three modules either side of it cover the rest:
|
|
41
|
+
*
|
|
42
|
+
* springs where k comes from, and what happens when springs are combined
|
|
43
|
+
* pendulum the pendulum family, which is a clock, a gravimeter and a lift
|
|
44
|
+
* damping what real oscillators do, which is stop
|
|
45
|
+
*
|
|
46
|
+
* They are separate because the failures are separate. Nothing in this file can
|
|
47
|
+
* be wrong about a spring that was cut in half, and nothing in `springs` can be
|
|
48
|
+
* wrong about where the energy went.
|
|
49
|
+
*
|
|
50
|
+
* Units: SI. Displacement and amplitude in metres, mass in kilograms, time in
|
|
51
|
+
* seconds, ω in radians per second, energy in joules.
|
|
52
|
+
*/
|
|
53
|
+
const finite = (value, what) => {
|
|
54
|
+
if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
|
|
55
|
+
return value;
|
|
56
|
+
};
|
|
57
|
+
const positive = (value, what) => {
|
|
58
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
59
|
+
return value;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Check a displacement lies within the amplitude.
|
|
63
|
+
*
|
|
64
|
+
* An oscillator cannot be found beyond its own amplitude, and asking for the
|
|
65
|
+
* speed there gives the square root of a negative number. Returning NaN would
|
|
66
|
+
* let an impossible position travel silently into a graph; the throw says which
|
|
67
|
+
* number was wrong.
|
|
68
|
+
*/
|
|
69
|
+
const within = (displacement, amplitude) => {
|
|
70
|
+
const x = finite(displacement, "A displacement");
|
|
71
|
+
const A = positive(amplitude, "An amplitude");
|
|
72
|
+
if (Math.abs(x) > A * 1.000000000001) throw new RangeError(`A displacement of ${x} lies outside the amplitude ${A}: the oscillator never reaches there.`);
|
|
73
|
+
return Math.max(-A, Math.min(A, x));
|
|
74
|
+
};
|
|
75
|
+
/** Angular frequency from a period: ω = 2π/T, rad/s. */
|
|
76
|
+
const angularFrequencyFromPeriod = (periodSeconds) => 2 * Math.PI / positive(periodSeconds, "A period");
|
|
77
|
+
/** Period from an angular frequency: T = 2π/ω, seconds. */
|
|
78
|
+
const periodFromAngularFrequency = (omega) => 2 * Math.PI / positive(omega, "An angular frequency");
|
|
79
|
+
/**
|
|
80
|
+
* Displacement at time t, starting from the CENTRE moving positive:
|
|
81
|
+
* x = A·sin(ωt + φ).
|
|
82
|
+
*
|
|
83
|
+
* Pass `phase = π/2` to start at maximum displacement instead, which is what a
|
|
84
|
+
* released-from-rest problem describes. Two starting conventions exist and both
|
|
85
|
+
* are called "the" SHM equation in different books, so the phase is explicit
|
|
86
|
+
* rather than baked in.
|
|
87
|
+
*/
|
|
88
|
+
function shmDisplacement(amplitude, omega, t, phase = 0) {
|
|
89
|
+
return positive(amplitude, "An amplitude") * Math.sin(positive(omega, "An angular frequency") * finite(t, "A time") + finite(phase, "A phase"));
|
|
90
|
+
}
|
|
91
|
+
/** Velocity at time t: v = ωA·cos(ωt + φ), m/s. */
|
|
92
|
+
function shmVelocity(amplitude, omega, t, phase = 0) {
|
|
93
|
+
const w = positive(omega, "An angular frequency");
|
|
94
|
+
return w * positive(amplitude, "An amplitude") * Math.cos(w * finite(t, "A time") + finite(phase, "A phase"));
|
|
95
|
+
}
|
|
96
|
+
/** Acceleration at time t: a = −ω²x, m/s². */
|
|
97
|
+
function shmAcceleration(amplitude, omega, t, phase = 0) {
|
|
98
|
+
const w = positive(omega, "An angular frequency");
|
|
99
|
+
return -(w * w) * shmDisplacement(amplitude, w, t, phase);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* SPEED at a displacement, m/s: v = ω√(A² − x²).
|
|
103
|
+
*
|
|
104
|
+
* The workhorse. Independent of time and of where the motion started, so it
|
|
105
|
+
* answers "how fast at half amplitude" without anyone having to find t first.
|
|
106
|
+
* Returns the magnitude; the oscillator passes each point twice a cycle, once
|
|
107
|
+
* each way, and which one is a question about direction rather than speed.
|
|
108
|
+
*/
|
|
109
|
+
function speedAtDisplacement(amplitude, omega, displacement) {
|
|
110
|
+
const A = positive(amplitude, "An amplitude");
|
|
111
|
+
const x = within(displacement, A);
|
|
112
|
+
return positive(omega, "An angular frequency") * Math.sqrt(A * A - x * x);
|
|
113
|
+
}
|
|
114
|
+
/** The displacement at which the oscillator reaches a given speed, m. */
|
|
115
|
+
function displacementAtSpeed(amplitude, omega, speed) {
|
|
116
|
+
const A = positive(amplitude, "An amplitude");
|
|
117
|
+
const w = positive(omega, "An angular frequency");
|
|
118
|
+
const s = finite(speed, "A speed");
|
|
119
|
+
const maximum = w * A;
|
|
120
|
+
if (Math.abs(s) > maximum * 1.000000000001) throw new RangeError(`This oscillator never exceeds ${maximum} m/s, so it is never moving at ${s} m/s.`);
|
|
121
|
+
return Math.sqrt(Math.max(0, A * A - (s / w) ** 2));
|
|
122
|
+
}
|
|
123
|
+
/** Greatest speed, at the centre: v_max = ωA, m/s. */
|
|
124
|
+
const maxSpeed = (amplitude, omega) => positive(omega, "An angular frequency") * positive(amplitude, "An amplitude");
|
|
125
|
+
/** Greatest acceleration, at the extremes: a_max = ω²A, m/s². */
|
|
126
|
+
const maxAcceleration = (amplitude, omega) => positive(omega, "An angular frequency") ** 2 * positive(amplitude, "An amplitude");
|
|
127
|
+
/**
|
|
128
|
+
* Displacement, velocity and acceleration at one instant, in one call.
|
|
129
|
+
*
|
|
130
|
+
* ## Why this exists rather than three calls
|
|
131
|
+
*
|
|
132
|
+
* Because the three are ONE object, and anything that draws them has to draw
|
|
133
|
+
* them from the same instant or the picture lies. A render loop asking for
|
|
134
|
+
* displacement, then velocity, then acceleration is three chances to pass a
|
|
135
|
+
* different `t`, and the symptom is a v–t curve that is no longer a quarter
|
|
136
|
+
* cycle ahead of the x–t one: a phase error that looks like a physics error.
|
|
137
|
+
*
|
|
138
|
+
* ## The chain the three form
|
|
139
|
+
*
|
|
140
|
+
* x = A·sin(ωt + φ)
|
|
141
|
+
* v = ωA·cos(ωt + φ) a quarter cycle AHEAD of x
|
|
142
|
+
* a = −ω²A·sin(ωt + φ) a quarter cycle ahead of v, so ANTIPHASE with x
|
|
143
|
+
*
|
|
144
|
+
* Each differentiation multiplies by ω and advances the phase by π/2. Two of
|
|
145
|
+
* them bring you back to a sine with a minus sign in front, which is the whole
|
|
146
|
+
* of a = −ω²x: the defining property of the motion falls out of differentiating
|
|
147
|
+
* twice and is not an extra assumption.
|
|
148
|
+
*
|
|
149
|
+
* `tests/waves/shm.test.ts` asserts each quarter-cycle lead against the others
|
|
150
|
+
* rather than against a formula, so the chain cannot be broken in one place
|
|
151
|
+
* only.
|
|
152
|
+
*/
|
|
153
|
+
function oscillatorStateAt(amplitude, omega, t, phase = 0) {
|
|
154
|
+
const A = positive(amplitude, "An amplitude");
|
|
155
|
+
const w = positive(omega, "An angular frequency");
|
|
156
|
+
const angle = w * finite(t, "A time") + finite(phase, "A phase");
|
|
157
|
+
const displacement = A * Math.sin(angle);
|
|
158
|
+
return {
|
|
159
|
+
displacement,
|
|
160
|
+
velocity: w * A * Math.cos(angle),
|
|
161
|
+
acceleration: -(w * w) * displacement,
|
|
162
|
+
phase: angle
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* The energy split at a displacement.
|
|
167
|
+
*
|
|
168
|
+
* At x = 0 it is all kinetic, at x = ±A all potential, and at x = A/√2 exactly
|
|
169
|
+
* half each — which is the answer to "where is the energy shared equally" and
|
|
170
|
+
* is NOT at half amplitude, the usual guess.
|
|
171
|
+
*/
|
|
172
|
+
function energyAt(mass, amplitude, omega, displacement) {
|
|
173
|
+
const m = positive(mass, "A mass");
|
|
174
|
+
const A = positive(amplitude, "An amplitude");
|
|
175
|
+
const w = positive(omega, "An angular frequency");
|
|
176
|
+
const x = within(displacement, A);
|
|
177
|
+
const half = .5 * m * w * w;
|
|
178
|
+
const kinetic = half * (A * A - x * x);
|
|
179
|
+
const potential = half * x * x;
|
|
180
|
+
const total = half * A * A;
|
|
181
|
+
return {
|
|
182
|
+
kinetic,
|
|
183
|
+
potential,
|
|
184
|
+
total,
|
|
185
|
+
residual: kinetic + potential - total,
|
|
186
|
+
kineticFraction: total === 0 ? 0 : kinetic / total
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/** Total energy of the oscillation, J: E = ½mω²A². Independent of position. */
|
|
190
|
+
const totalEnergy = (mass, amplitude, omega) => .5 * positive(mass, "A mass") * positive(omega, "An angular frequency") ** 2 * positive(amplitude, "An amplitude") ** 2;
|
|
191
|
+
/**
|
|
192
|
+
* The displacement at which kinetic and potential are equal: x = A/√2.
|
|
193
|
+
*
|
|
194
|
+
* About 0.707 of the amplitude, not 0.5. The energies go as x², so the halfway
|
|
195
|
+
* point in ENERGY is not the halfway point in distance, and that gap is the
|
|
196
|
+
* whole lesson.
|
|
197
|
+
*/
|
|
198
|
+
const equalEnergyDisplacement = (amplitude) => positive(amplitude, "An amplitude") / Math.SQRT2;
|
|
199
|
+
/**
|
|
200
|
+
* The energy split at a displacement, worked, in the form the question wants.
|
|
201
|
+
*
|
|
202
|
+
* Deliberately arrives at the same three numbers by TWO routes and shows both:
|
|
203
|
+
* ½mω²(A² − x²) directly, and ½mv² from the speed at that point. They must
|
|
204
|
+
* agree, and seeing them agree is the argument that the energy picture and the
|
|
205
|
+
* kinematic picture are one thing rather than two topics.
|
|
206
|
+
*
|
|
207
|
+
* The final step reports KE + PE against the total rather than asserting that
|
|
208
|
+
* they match, which is the same choice the energy ledger makes elsewhere in the
|
|
209
|
+
* package: conservation is evidence here, not a claim.
|
|
210
|
+
*/
|
|
211
|
+
function energyAtSteps(mass, amplitude, omega, displacement, sf = 3) {
|
|
212
|
+
const m = positive(mass, "A mass");
|
|
213
|
+
const A = positive(amplitude, "An amplitude");
|
|
214
|
+
const w = positive(omega, "An angular frequency");
|
|
215
|
+
const x = within(displacement, A);
|
|
216
|
+
const split = energyAt(m, A, w, x);
|
|
217
|
+
const v = speedAtDisplacement(A, w, x);
|
|
218
|
+
const stiffness = m * w * w;
|
|
219
|
+
return calc().step(`v = \\omega\\sqrt{A^2 - x^2} = ${texSigFigs(w, sf)}\\sqrt{${texSigFigs(A, sf)}^2 - ${texSigFigs(x, sf)}^2} = ${texSigFigs(v, sf)}\\ \\mathrm{m\\,s^{-1}}`, "speed from POSITION, so the time never has to be found").step(`E_k = \\tfrac{1}{2}mv^2 = ${texSigFigs(split.kinetic, sf)}\\ \\mathrm{J}`, "the kinematic route").step(`E_k = \\tfrac{1}{2}m\\omega^2(A^2 - x^2) = ${texSigFigs(split.kinetic, sf)}\\ \\mathrm{J}`, "and the energy route, which is the same statement with v substituted").step(`E_p = \\tfrac{1}{2}m\\omega^2 x^2 = \\tfrac{1}{2}kx^2 = ${texSigFigs(split.potential, sf)}\\ \\mathrm{J}`, `with k = m\\omega^2 = ${texSigFigs(stiffness, sf)}\\ \\mathrm{N\\,m^{-1}}, the spring form of the same energy`).step(`E = \\tfrac{1}{2}m\\omega^2 A^2 = ${texSigFigs(split.total, sf)}\\ \\mathrm{J}`, "independent of x: this number is the same everywhere in the swing").step(`E_k + E_p - E = ${texNum(split.residual)}\\ \\mathrm{J}`, "the books balance, and the residual is shown rather than the balance claimed").done(split.total);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Period of a mass on a spring: T = 2π√(m/k), seconds.
|
|
223
|
+
*
|
|
224
|
+
* Independent of amplitude, which is the surprising part and the practical one:
|
|
225
|
+
* a spring clock keeps time even as the swing dies away.
|
|
226
|
+
*/
|
|
227
|
+
const springPeriod = (mass, stiffness) => 2 * Math.PI * Math.sqrt(positive(mass, "A mass") / positive(stiffness, "A spring stiffness"));
|
|
228
|
+
/** Angular frequency of a mass on a spring: ω = √(k/m), rad/s. */
|
|
229
|
+
const springAngularFrequency = (mass, stiffness) => Math.sqrt(positive(stiffness, "A spring stiffness") / positive(mass, "A mass"));
|
|
230
|
+
/**
|
|
231
|
+
* The period of the ENERGY, seconds: half the period of the motion.
|
|
232
|
+
*
|
|
233
|
+
* The single most reliable trap in the topic. Kinetic energy goes as cos²(ωt),
|
|
234
|
+
* and a squared sinusoid repeats twice as often as the sinusoid does: the
|
|
235
|
+
* oscillator is at full speed at the centre going one way AND going the other,
|
|
236
|
+
* and the energy cannot tell those apart because it does not carry a sign.
|
|
237
|
+
*
|
|
238
|
+
* So a question that gives you an energy-against-time graph and asks for the
|
|
239
|
+
* period of the MOTION wants twice what the graph shows. Reading the graph's
|
|
240
|
+
* own period straight off is the wrong answer, and it is wrong by exactly the
|
|
241
|
+
* factor this function applies.
|
|
242
|
+
*/
|
|
243
|
+
const energyPeriod = (period) => positive(period, "A period") / 2;
|
|
244
|
+
/**
|
|
245
|
+
* The amplitude implied by a displacement and a velocity at the same moment:
|
|
246
|
+
* A = √(x² + (v/ω)²).
|
|
247
|
+
*
|
|
248
|
+
* v = ω√(A² − x²) rearranged. Any snapshot of the motion fixes the amplitude,
|
|
249
|
+
* which is how a question that never mentions an amplitude can still be asking
|
|
250
|
+
* for the total energy.
|
|
251
|
+
*/
|
|
252
|
+
function amplitudeFromState(omega, displacement, velocity) {
|
|
253
|
+
const w = positive(omega, "An angular frequency");
|
|
254
|
+
const x = finite(displacement, "A displacement");
|
|
255
|
+
const v = finite(velocity, "A velocity");
|
|
256
|
+
return Math.hypot(x, v / w);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The phase angle δ in x = A·sin(ωt + δ), from the state at t = 0.
|
|
260
|
+
*
|
|
261
|
+
* Returned in radians on (−π, π]. Uses `atan2` on (xω, v) rather than
|
|
262
|
+
* `asin(x₀/A)`, and that choice is the whole function: `asin` cannot tell a
|
|
263
|
+
* mass at +A/2 moving outward from one at +A/2 moving back, because they share
|
|
264
|
+
* a sine and differ only in the sign of the cosine. Half the answers from the
|
|
265
|
+
* `asin` route are the wrong one of the two, silently.
|
|
266
|
+
*
|
|
267
|
+
* The familiar special cases fall out: released from rest at full displacement
|
|
268
|
+
* gives π/2, so x = A·cos(ωt); started from the centre moving positive gives 0.
|
|
269
|
+
*/
|
|
270
|
+
function phaseFromState(omega, displacement, velocity) {
|
|
271
|
+
const w = positive(omega, "An angular frequency");
|
|
272
|
+
const x = finite(displacement, "A displacement");
|
|
273
|
+
const v = finite(velocity, "A velocity");
|
|
274
|
+
if (x === 0 && v === 0) throw new RangeError("An oscillator at rest at the centre has no phase: it is not oscillating.");
|
|
275
|
+
return Math.atan2(x * w, v);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
//#endregion
|
|
279
|
+
export { amplitudeFromState, angularFrequencyFromPeriod, displacementAtSpeed, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, maxAcceleration, maxSpeed, oscillatorStateAt, periodFromAngularFrequency, phaseFromState, shmAcceleration, shmDisplacement, shmVelocity, speedAtDisplacement, springAngularFrequency, springPeriod, totalEnergy };
|