@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,74 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { MIN_DISTANCE_M, MU_0, arcCentreT, circularArc, coilAxisT, coilCentreT, fieldAt, finiteWireT, flatCoil, helmholtzPair, longWire, longWireT, pathField, rectangularLoop, segmentField, solenoid, solenoidRings, solenoidT, straightWire, toroidT, traceFieldLine, traceFullFieldLine } from "./biot-savart.mjs";
|
|
3
|
+
import { MIN_LOOP_CLEARANCE_M, emfFromMutualInductance, emfFromSelfInductance, fluxBesideWire, fluxLinkage, fluxThroughLoop, fluxThroughUniform, inducedEmfV, loopArea, magneticEnergyJ, mutualInductanceH, selfInductanceH, solenoidInductanceH } from "./flux.mjs";
|
|
4
|
+
import { angleFromPlaneDeg, coilTorqueNm, forceOnPath, forcePerMetreOnWire, magneticMomentAm2, momentOfLoop, parallelWireForce, torqueFromMoment } from "./magnetic-force.mjs";
|
|
5
|
+
import { EARTH_DIPOLE_MOMENT_AM2, EARTH_RADIUS_M, GEOMAGNETIC_NORTH_POLE, apparentDipDeg, compassBearingDeg, dipFromMagneticLatitude, dipoleFieldAt, dipoleFieldLine, earthComponents, earthFromComponents, fieldAtPlace, footLatitudeDeg, magneticLatitudeFromDip, trueBearingDeg, trueDipFromTwo } from "./geomagnetism.mjs";
|
|
6
|
+
import { fieldsFor, lorentzForce3D, traceLorentz } from "./lorentz.mjs";
|
|
7
|
+
|
|
8
|
+
//#region src/physics/magnetism/index.ts
|
|
9
|
+
var magnetism_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
+
EARTH_DIPOLE_MOMENT_AM2: () => EARTH_DIPOLE_MOMENT_AM2,
|
|
11
|
+
EARTH_RADIUS_M: () => EARTH_RADIUS_M,
|
|
12
|
+
GEOMAGNETIC_NORTH_POLE: () => GEOMAGNETIC_NORTH_POLE,
|
|
13
|
+
MIN_DISTANCE_M: () => MIN_DISTANCE_M,
|
|
14
|
+
MIN_LOOP_CLEARANCE_M: () => MIN_LOOP_CLEARANCE_M,
|
|
15
|
+
MU_0: () => MU_0,
|
|
16
|
+
angleFromPlaneDeg: () => angleFromPlaneDeg,
|
|
17
|
+
apparentDipDeg: () => apparentDipDeg,
|
|
18
|
+
arcCentreT: () => arcCentreT,
|
|
19
|
+
circularArc: () => circularArc,
|
|
20
|
+
coilAxisT: () => coilAxisT,
|
|
21
|
+
coilCentreT: () => coilCentreT,
|
|
22
|
+
coilTorqueNm: () => coilTorqueNm,
|
|
23
|
+
compassBearingDeg: () => compassBearingDeg,
|
|
24
|
+
dipFromMagneticLatitude: () => dipFromMagneticLatitude,
|
|
25
|
+
dipoleFieldAt: () => dipoleFieldAt,
|
|
26
|
+
dipoleFieldLine: () => dipoleFieldLine,
|
|
27
|
+
earthComponents: () => earthComponents,
|
|
28
|
+
earthFromComponents: () => earthFromComponents,
|
|
29
|
+
emfFromMutualInductance: () => emfFromMutualInductance,
|
|
30
|
+
emfFromSelfInductance: () => emfFromSelfInductance,
|
|
31
|
+
fieldAt: () => fieldAt,
|
|
32
|
+
fieldAtPlace: () => fieldAtPlace,
|
|
33
|
+
fieldsFor: () => fieldsFor,
|
|
34
|
+
finiteWireT: () => finiteWireT,
|
|
35
|
+
flatCoil: () => flatCoil,
|
|
36
|
+
fluxBesideWire: () => fluxBesideWire,
|
|
37
|
+
fluxLinkage: () => fluxLinkage,
|
|
38
|
+
fluxThroughLoop: () => fluxThroughLoop,
|
|
39
|
+
fluxThroughUniform: () => fluxThroughUniform,
|
|
40
|
+
footLatitudeDeg: () => footLatitudeDeg,
|
|
41
|
+
forceOnPath: () => forceOnPath,
|
|
42
|
+
forcePerMetreOnWire: () => forcePerMetreOnWire,
|
|
43
|
+
helmholtzPair: () => helmholtzPair,
|
|
44
|
+
inducedEmfV: () => inducedEmfV,
|
|
45
|
+
longWire: () => longWire,
|
|
46
|
+
longWireT: () => longWireT,
|
|
47
|
+
loopArea: () => loopArea,
|
|
48
|
+
lorentzForce3D: () => lorentzForce3D,
|
|
49
|
+
magneticEnergyJ: () => magneticEnergyJ,
|
|
50
|
+
magneticLatitudeFromDip: () => magneticLatitudeFromDip,
|
|
51
|
+
magneticMomentAm2: () => magneticMomentAm2,
|
|
52
|
+
momentOfLoop: () => momentOfLoop,
|
|
53
|
+
mutualInductanceH: () => mutualInductanceH,
|
|
54
|
+
parallelWireForce: () => parallelWireForce,
|
|
55
|
+
pathField: () => pathField,
|
|
56
|
+
rectangularLoop: () => rectangularLoop,
|
|
57
|
+
segmentField: () => segmentField,
|
|
58
|
+
selfInductanceH: () => selfInductanceH,
|
|
59
|
+
solenoid: () => solenoid,
|
|
60
|
+
solenoidInductanceH: () => solenoidInductanceH,
|
|
61
|
+
solenoidRings: () => solenoidRings,
|
|
62
|
+
solenoidT: () => solenoidT,
|
|
63
|
+
straightWire: () => straightWire,
|
|
64
|
+
toroidT: () => toroidT,
|
|
65
|
+
torqueFromMoment: () => torqueFromMoment,
|
|
66
|
+
traceFieldLine: () => traceFieldLine,
|
|
67
|
+
traceFullFieldLine: () => traceFullFieldLine,
|
|
68
|
+
traceLorentz: () => traceLorentz,
|
|
69
|
+
trueBearingDeg: () => trueBearingDeg,
|
|
70
|
+
trueDipFromTwo: () => trueDipFromTwo
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
export { EARTH_DIPOLE_MOMENT_AM2, EARTH_RADIUS_M, GEOMAGNETIC_NORTH_POLE, MIN_DISTANCE_M, MIN_LOOP_CLEARANCE_M, MU_0, angleFromPlaneDeg, apparentDipDeg, arcCentreT, circularArc, coilAxisT, coilCentreT, coilTorqueNm, compassBearingDeg, dipFromMagneticLatitude, dipoleFieldAt, dipoleFieldLine, earthComponents, earthFromComponents, emfFromMutualInductance, emfFromSelfInductance, fieldAt, fieldAtPlace, fieldsFor, finiteWireT, flatCoil, fluxBesideWire, fluxLinkage, fluxThroughLoop, fluxThroughUniform, footLatitudeDeg, forceOnPath, forcePerMetreOnWire, helmholtzPair, inducedEmfV, longWire, longWireT, loopArea, lorentzForce3D, magneticEnergyJ, magneticLatitudeFromDip, magneticMomentAm2, magnetism_exports, momentOfLoop, mutualInductanceH, parallelWireForce, pathField, rectangularLoop, segmentField, selfInductanceH, solenoid, solenoidInductanceH, solenoidRings, solenoidT, straightWire, toroidT, torqueFromMoment, traceFieldLine, traceFullFieldLine, traceLorentz, trueBearingDeg, trueDipFromTwo };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Vec3 } from "../../core/vec3.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/magnetism/lorentz.d.ts
|
|
4
|
+
type SpatialFieldMode = 'electric' | 'magnetic' | 'crossed';
|
|
5
|
+
/**
|
|
6
|
+
* The Lorentz force on a point charge: F = q(E + v x B).
|
|
7
|
+
*
|
|
8
|
+
* Both halves in one expression on purpose. A velocity selector works because
|
|
9
|
+
* the two can cancel, and splitting them into separate functions makes that
|
|
10
|
+
* cancellation something a lab has to arrange rather than something the law
|
|
11
|
+
* already says.
|
|
12
|
+
*/
|
|
13
|
+
declare function lorentzForce3D(q: number, v: Vec3, e: Vec3, b: Vec3): Vec3;
|
|
14
|
+
/**
|
|
15
|
+
* RK4 trajectory for constant fields, in normalised teaching units.
|
|
16
|
+
*
|
|
17
|
+
* Not SI: the point of this one is the SHAPE of the path (a circle in a pure
|
|
18
|
+
* magnetic field, a helix when the velocity has a component along it, a
|
|
19
|
+
* straight line when E and v x B cancel), and real electron masses would put
|
|
20
|
+
* every interesting radius outside any sensible viewport.
|
|
21
|
+
*/
|
|
22
|
+
declare function traceLorentz(q: number, m: number, v0: Vec3, e: Vec3, b: Vec3, steps?: number, dt?: number): Vec3[];
|
|
23
|
+
declare function fieldsFor(mode: SpatialFieldMode, strength: number): {
|
|
24
|
+
e: Vec3;
|
|
25
|
+
b: Vec3;
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { SpatialFieldMode, fieldsFor, lorentzForce3D, traceLorentz };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { add3, cross3, scale3 } from "../../core/vec3.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/magnetism/lorentz.ts
|
|
4
|
+
/**
|
|
5
|
+
* @classytic/stage/physics/magnetism/lorentz — the force a field puts on a
|
|
6
|
+
* moving CHARGE, and the path that follows.
|
|
7
|
+
*
|
|
8
|
+
* The companion to `magnetic-force.ts`, which does the same for a current.
|
|
9
|
+
* They are the same physics at two scales: a current is drifting charge, so
|
|
10
|
+
* `F = qv x B` summed over the carriers in a wire IS `F = I l x B`.
|
|
11
|
+
*/
|
|
12
|
+
const add = (a, b, s = 1) => add3(a, scale3(b, s));
|
|
13
|
+
/**
|
|
14
|
+
* The Lorentz force on a point charge: F = q(E + v x B).
|
|
15
|
+
*
|
|
16
|
+
* Both halves in one expression on purpose. A velocity selector works because
|
|
17
|
+
* the two can cancel, and splitting them into separate functions makes that
|
|
18
|
+
* cancellation something a lab has to arrange rather than something the law
|
|
19
|
+
* already says.
|
|
20
|
+
*/
|
|
21
|
+
function lorentzForce3D(q, v, e, b) {
|
|
22
|
+
const c = cross3(v, b);
|
|
23
|
+
return {
|
|
24
|
+
x: q * (e.x + c.x),
|
|
25
|
+
y: q * (e.y + c.y),
|
|
26
|
+
z: q * (e.z + c.z)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* RK4 trajectory for constant fields, in normalised teaching units.
|
|
31
|
+
*
|
|
32
|
+
* Not SI: the point of this one is the SHAPE of the path (a circle in a pure
|
|
33
|
+
* magnetic field, a helix when the velocity has a component along it, a
|
|
34
|
+
* straight line when E and v x B cancel), and real electron masses would put
|
|
35
|
+
* every interesting radius outside any sensible viewport.
|
|
36
|
+
*/
|
|
37
|
+
function traceLorentz(q, m, v0, e, b, steps = 180, dt = .025) {
|
|
38
|
+
let p = {
|
|
39
|
+
x: 0,
|
|
40
|
+
y: 0,
|
|
41
|
+
z: 0
|
|
42
|
+
}, v = { ...v0 };
|
|
43
|
+
const out = [p];
|
|
44
|
+
for (let i = 0; i < steps; i++) {
|
|
45
|
+
const a = (x) => {
|
|
46
|
+
const f = lorentzForce3D(q, x, e, b);
|
|
47
|
+
return {
|
|
48
|
+
x: f.x / m,
|
|
49
|
+
y: f.y / m,
|
|
50
|
+
z: f.z / m
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const k1 = a(v), k2 = a(add(v, k1, dt / 2)), k3 = a(add(v, k2, dt / 2)), k4 = a(add(v, k3, dt));
|
|
54
|
+
v = add(v, {
|
|
55
|
+
x: (k1.x + 2 * k2.x + 2 * k3.x + k4.x) / 6,
|
|
56
|
+
y: (k1.y + 2 * k2.y + 2 * k3.y + k4.y) / 6,
|
|
57
|
+
z: (k1.z + 2 * k2.z + 2 * k3.z + k4.z) / 6
|
|
58
|
+
}, dt);
|
|
59
|
+
p = add(p, v, dt);
|
|
60
|
+
out.push(p);
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
function fieldsFor(mode, strength) {
|
|
65
|
+
return {
|
|
66
|
+
e: mode === "magnetic" ? {
|
|
67
|
+
x: 0,
|
|
68
|
+
y: 0,
|
|
69
|
+
z: 0
|
|
70
|
+
} : {
|
|
71
|
+
x: 0,
|
|
72
|
+
y: strength,
|
|
73
|
+
z: 0
|
|
74
|
+
},
|
|
75
|
+
b: mode === "electric" ? {
|
|
76
|
+
x: 0,
|
|
77
|
+
y: 0,
|
|
78
|
+
z: 0
|
|
79
|
+
} : {
|
|
80
|
+
x: 0,
|
|
81
|
+
y: 0,
|
|
82
|
+
z: strength
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//#endregion
|
|
88
|
+
export { fieldsFor, lorentzForce3D, traceLorentz };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Vec3 } from "../../core/vec3.mjs";
|
|
2
|
+
import { CurrentPath } from "./biot-savart.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/magnetism/magnetic-force.d.ts
|
|
5
|
+
interface ForceOnPathOptions {
|
|
6
|
+
/** A uniform background field, added to whatever the current sources make. */
|
|
7
|
+
uniformT?: Vec3;
|
|
8
|
+
/** Point the torque is taken about. Defaults to the origin. */
|
|
9
|
+
about?: Vec3;
|
|
10
|
+
/**
|
|
11
|
+
* Quadrature points per segment of the test path.
|
|
12
|
+
*
|
|
13
|
+
* A straight segment in a slowly varying field needs one; a segment that is
|
|
14
|
+
* part of a polygon approximating a circle, sitting close to another
|
|
15
|
+
* conductor, needs several.
|
|
16
|
+
*/
|
|
17
|
+
samplesPerSegment?: number;
|
|
18
|
+
}
|
|
19
|
+
interface PathForce {
|
|
20
|
+
/** Net force on the test path, in newtons. */
|
|
21
|
+
force: Vec3;
|
|
22
|
+
/** Its magnitude, in newtons. */
|
|
23
|
+
newtons: number;
|
|
24
|
+
/** Net torque about `about`, in newton metres. */
|
|
25
|
+
torque: Vec3;
|
|
26
|
+
/**
|
|
27
|
+
* Where the force acts, segment by segment.
|
|
28
|
+
*
|
|
29
|
+
* Kept because the interesting thing about a coil in a uniform field is that
|
|
30
|
+
* the net force is zero while the individual forces are not: a lesson has to
|
|
31
|
+
* be able to draw the parts to make the couple visible.
|
|
32
|
+
*/
|
|
33
|
+
contributions: Array<{
|
|
34
|
+
at: Vec3;
|
|
35
|
+
force: Vec3;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Force and torque on one current path, in the field of any others plus an
|
|
40
|
+
* optional uniform background.
|
|
41
|
+
*
|
|
42
|
+
* The test path is NOT a source of its own field. A filament's self-force is
|
|
43
|
+
* divergent and, for a rigid circuit, is not what anybody means by "the force
|
|
44
|
+
* on the coil" anyway.
|
|
45
|
+
*/
|
|
46
|
+
declare function forceOnPath(sources: readonly CurrentPath[], test: CurrentPath, options?: ForceOnPathOptions): PathForce;
|
|
47
|
+
/**
|
|
48
|
+
* Force per unit length on a long straight test wire, for comparing against the
|
|
49
|
+
* textbook result.
|
|
50
|
+
*
|
|
51
|
+
* Measured over a short span at the MIDDLE of the test wire, because the ends of
|
|
52
|
+
* any finite wire feel less than the middle does and averaging over the whole
|
|
53
|
+
* thing would quietly build that end effect into the answer.
|
|
54
|
+
*/
|
|
55
|
+
declare function forcePerMetreOnWire(sources: readonly CurrentPath[], through: Vec3, direction: Vec3, currentA: number, spanM?: number): Vec3;
|
|
56
|
+
/** Torque on a closed circuit from its magnetic moment: tau = m x B. */
|
|
57
|
+
declare function torqueFromMoment(momentAm2: Vec3, fieldT: Vec3): Vec3;
|
|
58
|
+
/**
|
|
59
|
+
* Magnetic moment of a planar closed loop, as a vector: m = I A n.
|
|
60
|
+
*
|
|
61
|
+
* Computed from the loop's own geometry by the surface-vector form of the
|
|
62
|
+
* shoelace formula, so it needs no separate area argument and gets the normal's
|
|
63
|
+
* direction from the order the loop is walked. That is the right-hand rule made
|
|
64
|
+
* arithmetic.
|
|
65
|
+
*/
|
|
66
|
+
declare function momentOfLoop(loop: CurrentPath): Vec3;
|
|
67
|
+
interface WireForce {
|
|
68
|
+
/** Force per unit length, in newtons per metre. Always positive. */
|
|
69
|
+
newtonsPerMetre: number;
|
|
70
|
+
/** Currents the same way attract; opposite ways repel. */
|
|
71
|
+
sense: 'attract' | 'repel';
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Force per metre between two long parallel wires: mu0 I1 I2 / 2 pi d.
|
|
75
|
+
*
|
|
76
|
+
* This is the definition of the ampere, and it is the cleanest demonstration
|
|
77
|
+
* that a current both makes a field and feels one: wire 1's field at wire 2,
|
|
78
|
+
* times wire 2's I L.
|
|
79
|
+
*/
|
|
80
|
+
declare function parallelWireForce(current1A: number, current2A: number, separationM: number): WireForce;
|
|
81
|
+
/** Magnetic dipole moment of a coil: M = N I A, in A m^2. */
|
|
82
|
+
declare function magneticMomentAm2(turns: number, currentA: number, areaM2: number): number;
|
|
83
|
+
/**
|
|
84
|
+
* Torque on a current-carrying coil in a uniform field: tau = N I A B sin(theta),
|
|
85
|
+
* where theta is the angle between the coil's NORMAL and the field.
|
|
86
|
+
*
|
|
87
|
+
* The angle is the standard trap. A question almost always states the angle the
|
|
88
|
+
* coil's PLANE makes with the field, which is the complement. Rather than pick
|
|
89
|
+
* a convention and hope, this takes the physically correct angle and
|
|
90
|
+
* `angleFromPlaneDeg` does the conversion in the open.
|
|
91
|
+
*/
|
|
92
|
+
declare function coilTorqueNm(fieldT: number, turns: number, currentA: number, areaM2: number, normalToFieldDeg: number): number;
|
|
93
|
+
/**
|
|
94
|
+
* Convert "the coil's plane makes this angle with B" into the normal-to-field
|
|
95
|
+
* angle that `coilTorqueNm` wants.
|
|
96
|
+
*
|
|
97
|
+
* A coil whose plane lies along the field (0 degrees) has its normal across the
|
|
98
|
+
* field (90 degrees), which is where the torque is greatest.
|
|
99
|
+
*/
|
|
100
|
+
declare const angleFromPlaneDeg: (planeToFieldDeg: number) => number;
|
|
101
|
+
//#endregion
|
|
102
|
+
export { ForceOnPathOptions, PathForce, WireForce, angleFromPlaneDeg, coilTorqueNm, forceOnPath, forcePerMetreOnWire, magneticMomentAm2, momentOfLoop, parallelWireForce, torqueFromMoment };
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { ZERO3, add3, cross3, mag3, scale3, sub3 } from "../../core/vec3.mjs";
|
|
2
|
+
import { MU_0, fieldAt } from "./biot-savart.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/magnetism/magnetic-force.ts
|
|
5
|
+
/**
|
|
6
|
+
* @classytic/stage/field/magnetic-force — the force a magnetic field puts on a
|
|
7
|
+
* current, over arbitrary geometry.
|
|
8
|
+
*
|
|
9
|
+
* `parallelWireForce` answers one case in closed form: two infinite straight
|
|
10
|
+
* wires. Everything else a real circuit does -- a loop beside a wire, a coil
|
|
11
|
+
* inside another coil, a rectangular armature in a magnet's gap -- needs the
|
|
12
|
+
* line integral that case was derived from:
|
|
13
|
+
*
|
|
14
|
+
* F = integral of I dl x B
|
|
15
|
+
*
|
|
16
|
+
* With that, the closed form stops being a separate fact and becomes a check.
|
|
17
|
+
*
|
|
18
|
+
* ── A uniform background field is a first-class source ────────────────────────
|
|
19
|
+
* Almost every exam question puts a conductor in "a uniform field of 0.35 T"
|
|
20
|
+
* without saying what makes it. Demanding a current geometry for that would be
|
|
21
|
+
* pedantry: the uniform field is the idealisation the question is posed in. So
|
|
22
|
+
* it is an explicit option, added to whatever the current sources contribute.
|
|
23
|
+
*
|
|
24
|
+
* ── Why the torque needs an origin, and when it does not ──────────────────────
|
|
25
|
+
* Torque is about a point, so `about` has to be given. The exception is the
|
|
26
|
+
* case that matters most: when the NET FORCE is zero, as it is for any closed
|
|
27
|
+
* circuit in a uniform field, the torque is the same about every point. That is
|
|
28
|
+
* what makes "the torque on a coil" a well-posed phrase at all, and it is
|
|
29
|
+
* asserted in the tests rather than assumed.
|
|
30
|
+
*/
|
|
31
|
+
const radians = (deg) => deg * Math.PI / 180;
|
|
32
|
+
const segmentsOf = (path) => {
|
|
33
|
+
const pairs = [];
|
|
34
|
+
const points = path.points;
|
|
35
|
+
for (let i = 0; i + 1 < points.length; i += 1) {
|
|
36
|
+
const from = points[i];
|
|
37
|
+
const to = points[i + 1];
|
|
38
|
+
if (from && to) pairs.push([from, to]);
|
|
39
|
+
}
|
|
40
|
+
if (path.closed && points.length > 2) {
|
|
41
|
+
const last = points[points.length - 1];
|
|
42
|
+
const first = points[0];
|
|
43
|
+
if (last && first) pairs.push([last, first]);
|
|
44
|
+
}
|
|
45
|
+
return pairs;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Force and torque on one current path, in the field of any others plus an
|
|
49
|
+
* optional uniform background.
|
|
50
|
+
*
|
|
51
|
+
* The test path is NOT a source of its own field. A filament's self-force is
|
|
52
|
+
* divergent and, for a rigid circuit, is not what anybody means by "the force
|
|
53
|
+
* on the coil" anyway.
|
|
54
|
+
*/
|
|
55
|
+
function forceOnPath(sources, test, options = {}) {
|
|
56
|
+
const { uniformT = ZERO3, about = ZERO3, samplesPerSegment = 4 } = options;
|
|
57
|
+
if (samplesPerSegment < 1) throw new RangeError("A segment needs at least one sample.");
|
|
58
|
+
if (sources.some((s) => s.id === test.id)) throw new RangeError("A path cannot be its own source: a filament self-force diverges.");
|
|
59
|
+
let force = ZERO3;
|
|
60
|
+
let torque = ZERO3;
|
|
61
|
+
const contributions = [];
|
|
62
|
+
for (const [from, to] of segmentsOf(test)) {
|
|
63
|
+
const along = sub3(to, from);
|
|
64
|
+
const piece = scale3(along, 1 / samplesPerSegment);
|
|
65
|
+
let segmentForce = ZERO3;
|
|
66
|
+
let segmentTorque = ZERO3;
|
|
67
|
+
let segmentMidpoint = ZERO3;
|
|
68
|
+
for (let k = 0; k < samplesPerSegment; k += 1) {
|
|
69
|
+
const at = add3(from, scale3(along, (k + .5) / samplesPerSegment));
|
|
70
|
+
const dF = scale3(cross3(piece, add3(uniformT, fieldAt(sources, at).field)), test.currentA);
|
|
71
|
+
segmentForce = add3(segmentForce, dF);
|
|
72
|
+
segmentTorque = add3(segmentTorque, cross3(sub3(at, about), dF));
|
|
73
|
+
segmentMidpoint = add3(segmentMidpoint, scale3(at, 1 / samplesPerSegment));
|
|
74
|
+
}
|
|
75
|
+
force = add3(force, segmentForce);
|
|
76
|
+
torque = add3(torque, segmentTorque);
|
|
77
|
+
contributions.push({
|
|
78
|
+
at: segmentMidpoint,
|
|
79
|
+
force: segmentForce
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
force,
|
|
84
|
+
newtons: mag3(force),
|
|
85
|
+
torque,
|
|
86
|
+
contributions
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Force per unit length on a long straight test wire, for comparing against the
|
|
91
|
+
* textbook result.
|
|
92
|
+
*
|
|
93
|
+
* Measured over a short span at the MIDDLE of the test wire, because the ends of
|
|
94
|
+
* any finite wire feel less than the middle does and averaging over the whole
|
|
95
|
+
* thing would quietly build that end effect into the answer.
|
|
96
|
+
*/
|
|
97
|
+
function forcePerMetreOnWire(sources, through, direction, currentA, spanM = .001) {
|
|
98
|
+
const len = mag3(direction);
|
|
99
|
+
if (len === 0) throw new RangeError("A wire needs a direction.");
|
|
100
|
+
const half = scale3(direction, spanM / (2 * len));
|
|
101
|
+
return scale3(forceOnPath(sources, {
|
|
102
|
+
id: "force-probe",
|
|
103
|
+
currentA,
|
|
104
|
+
points: [sub3(through, half), add3(through, half)]
|
|
105
|
+
}, { samplesPerSegment: 8 }).force, 1 / spanM);
|
|
106
|
+
}
|
|
107
|
+
/** Torque on a closed circuit from its magnetic moment: tau = m x B. */
|
|
108
|
+
function torqueFromMoment(momentAm2, fieldT) {
|
|
109
|
+
return cross3(momentAm2, fieldT);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Magnetic moment of a planar closed loop, as a vector: m = I A n.
|
|
113
|
+
*
|
|
114
|
+
* Computed from the loop's own geometry by the surface-vector form of the
|
|
115
|
+
* shoelace formula, so it needs no separate area argument and gets the normal's
|
|
116
|
+
* direction from the order the loop is walked. That is the right-hand rule made
|
|
117
|
+
* arithmetic.
|
|
118
|
+
*/
|
|
119
|
+
function momentOfLoop(loop) {
|
|
120
|
+
const points = loop.points;
|
|
121
|
+
if (points.length < 3) throw new RangeError("A loop needs at least three vertices.");
|
|
122
|
+
const origin = points[0];
|
|
123
|
+
let area = ZERO3;
|
|
124
|
+
const pairs = segmentsOf(loop);
|
|
125
|
+
for (const [from, to] of pairs) area = add3(area, scale3(cross3(sub3(from, origin), sub3(to, origin)), .5));
|
|
126
|
+
return scale3(area, loop.currentA);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Force per metre between two long parallel wires: mu0 I1 I2 / 2 pi d.
|
|
130
|
+
*
|
|
131
|
+
* This is the definition of the ampere, and it is the cleanest demonstration
|
|
132
|
+
* that a current both makes a field and feels one: wire 1's field at wire 2,
|
|
133
|
+
* times wire 2's I L.
|
|
134
|
+
*/
|
|
135
|
+
function parallelWireForce(current1A, current2A, separationM) {
|
|
136
|
+
if (separationM <= 0) throw new RangeError("Two wires need a positive separation.");
|
|
137
|
+
return {
|
|
138
|
+
newtonsPerMetre: MU_0 * Math.abs(current1A * current2A) / (2 * Math.PI * separationM),
|
|
139
|
+
sense: current1A * current2A >= 0 ? "attract" : "repel"
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** Magnetic dipole moment of a coil: M = N I A, in A m^2. */
|
|
143
|
+
function magneticMomentAm2(turns, currentA, areaM2) {
|
|
144
|
+
if (turns < 0 || areaM2 < 0) throw new RangeError("Turns and area cannot be negative.");
|
|
145
|
+
return turns * currentA * areaM2;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Torque on a current-carrying coil in a uniform field: tau = N I A B sin(theta),
|
|
149
|
+
* where theta is the angle between the coil's NORMAL and the field.
|
|
150
|
+
*
|
|
151
|
+
* The angle is the standard trap. A question almost always states the angle the
|
|
152
|
+
* coil's PLANE makes with the field, which is the complement. Rather than pick
|
|
153
|
+
* a convention and hope, this takes the physically correct angle and
|
|
154
|
+
* `angleFromPlaneDeg` does the conversion in the open.
|
|
155
|
+
*/
|
|
156
|
+
function coilTorqueNm(fieldT, turns, currentA, areaM2, normalToFieldDeg) {
|
|
157
|
+
return magneticMomentAm2(turns, currentA, areaM2) * fieldT * Math.sin(radians(normalToFieldDeg));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Convert "the coil's plane makes this angle with B" into the normal-to-field
|
|
161
|
+
* angle that `coilTorqueNm` wants.
|
|
162
|
+
*
|
|
163
|
+
* A coil whose plane lies along the field (0 degrees) has its normal across the
|
|
164
|
+
* field (90 degrees), which is where the torque is greatest.
|
|
165
|
+
*/
|
|
166
|
+
const angleFromPlaneDeg = (planeToFieldDeg) => 90 - planeToFieldDeg;
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
export { angleFromPlaneDeg, coilTorqueNm, forceOnPath, forcePerMetreOnWire, magneticMomentAm2, momentOfLoop, parallelWireForce, torqueFromMoment };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Worked } from "../../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/momentum/collide.d.ts
|
|
4
|
+
interface CollisionInput {
|
|
5
|
+
readonly m1: number;
|
|
6
|
+
readonly u1: number;
|
|
7
|
+
readonly m2: number;
|
|
8
|
+
readonly u2: number;
|
|
9
|
+
/**
|
|
10
|
+
* Coefficient of restitution, 0 to 1. Defaults to 1, perfectly elastic.
|
|
11
|
+
*
|
|
12
|
+
* Not clamped silently: a value outside the range means the bodies separate faster than they
|
|
13
|
+
* approached, which needs an energy source the collision does not have, and that is a mistake
|
|
14
|
+
* worth reporting rather than rounding away.
|
|
15
|
+
*/
|
|
16
|
+
readonly restitution?: number;
|
|
17
|
+
}
|
|
18
|
+
interface CollisionOutcome {
|
|
19
|
+
readonly v1: number;
|
|
20
|
+
readonly v2: number;
|
|
21
|
+
readonly restitution: number;
|
|
22
|
+
readonly momentumBefore: number;
|
|
23
|
+
readonly momentumAfter: number;
|
|
24
|
+
readonly kineticBefore: number;
|
|
25
|
+
readonly kineticAfter: number;
|
|
26
|
+
/** Energy turned into heat, sound and deformation. Zero only at `e = 1`. */
|
|
27
|
+
readonly kineticLost: number;
|
|
28
|
+
/** The closing speed, and the separating speed, whose ratio IS `e`. */
|
|
29
|
+
readonly approachSpeed: number;
|
|
30
|
+
readonly separationSpeed: number;
|
|
31
|
+
readonly worked: Worked;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Solve a head-on collision.
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* collide({ m1: 5, u1: 2, m2: 3, u2: 0 }); // elastic
|
|
38
|
+
* collide({ m1: 0.025, u1: 400, m2: 1.975, u2: 0, restitution: 0 }); // bullet into a block
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare function collide(input: CollisionInput, sf?: number): CollisionOutcome;
|
|
42
|
+
/**
|
|
43
|
+
* The restitution a collision actually had, measured from what happened.
|
|
44
|
+
*
|
|
45
|
+
* The inverse, and the one an experiment produces: drop a ball, measure the bounce, divide. Worth
|
|
46
|
+
* having because it turns `e` from a number in a formula into something a learner has measured.
|
|
47
|
+
*/
|
|
48
|
+
declare function restitutionOf(u1: number, u2: number, v1: number, v2: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* A ball bouncing on the ground: `e = √(h_bounce / h_drop)`.
|
|
51
|
+
*
|
|
52
|
+
* The standard measurement, and the square root is the part that surprises people. Restitution is a
|
|
53
|
+
* ratio of SPEEDS and height goes as speed squared, so a ball returning to half its height has
|
|
54
|
+
* `e = 0.71`, not 0.5.
|
|
55
|
+
*/
|
|
56
|
+
declare function restitutionFromBounce(dropHeight: number, bounceHeight: number, sf?: number): {
|
|
57
|
+
value: number;
|
|
58
|
+
worked: Worked;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Bodies that start together and fly apart: an explosion, a recoiling gun, a person stepping off a
|
|
62
|
+
* boat.
|
|
63
|
+
*
|
|
64
|
+
* Not a different law. Total momentum before is whatever it was, usually zero, and it is still that
|
|
65
|
+
* afterwards, so the fragments' momenta must cancel. Give every fragment's velocity except one and
|
|
66
|
+
* this returns the missing one.
|
|
67
|
+
*/
|
|
68
|
+
declare function separateFrom(initialMomentum: number, known: readonly {
|
|
69
|
+
label: string;
|
|
70
|
+
mass: number;
|
|
71
|
+
velocity: number;
|
|
72
|
+
}[], unknownMass: number, sf?: number): {
|
|
73
|
+
velocity: number;
|
|
74
|
+
worked: Worked;
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
77
|
+
export { CollisionInput, CollisionOutcome, collide, restitutionFromBounce, restitutionOf, separateFrom };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/momentum/collide.ts
|
|
4
|
+
/**
|
|
5
|
+
* Collisions in one dimension, with elastic and perfectly inelastic as the ENDS OF ONE SCALE.
|
|
6
|
+
*
|
|
7
|
+
* Textbooks present two types with two sets of formulas, and students memorise which to use. They
|
|
8
|
+
* are the same collision with one number changed. That number is the coefficient of restitution,
|
|
9
|
+
*
|
|
10
|
+
* e = (speed of separation) / (speed of approach) = (v₂ − v₁) / (u₁ − u₂)
|
|
11
|
+
*
|
|
12
|
+
* and it runs from 1 (perfectly elastic, nothing lost, they separate as fast as they closed) to 0
|
|
13
|
+
* (perfectly inelastic, they move off together). Every real collision is somewhere in between, and
|
|
14
|
+
* no real collision is either. A slider from 0 to 1 is a better teaching object than two formulas,
|
|
15
|
+
* because it shows the kinetic energy draining away continuously as `e` falls and being exactly
|
|
16
|
+
* conserved only at the single point `e = 1`.
|
|
17
|
+
*
|
|
18
|
+
* TWO EQUATIONS, TWO UNKNOWNS, always. Momentum is conserved in every collision without exception,
|
|
19
|
+
* which gives one equation; restitution gives the second; and the pair solves for both final
|
|
20
|
+
* velocities. Energy is NOT an input, it is a RESULT, and the amount lost is what `e` is really
|
|
21
|
+
* telling you.
|
|
22
|
+
*
|
|
23
|
+
* Signs matter and are not negotiable: velocities are along one axis, positive one way. Two bodies
|
|
24
|
+
* approaching each other have opposite signs.
|
|
25
|
+
*
|
|
26
|
+
* Pure: no React, no pixels.
|
|
27
|
+
*/
|
|
28
|
+
const kinetic = (m, v) => .5 * m * v * v;
|
|
29
|
+
/**
|
|
30
|
+
* Solve a head-on collision.
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* collide({ m1: 5, u1: 2, m2: 3, u2: 0 }); // elastic
|
|
34
|
+
* collide({ m1: 0.025, u1: 400, m2: 1.975, u2: 0, restitution: 0 }); // bullet into a block
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function collide(input, sf = 3) {
|
|
38
|
+
const { m1, u1, m2, u2 } = input;
|
|
39
|
+
const e = input.restitution ?? 1;
|
|
40
|
+
if (m1 <= 0 || m2 <= 0) throw new Error("Both masses must be positive.");
|
|
41
|
+
if (e < 0 || e > 1) throw new Error(`A coefficient of restitution of ${e} is not physical: it must lie between 0 (they stay together) and 1 (nothing is lost). Above 1 the bodies would leave faster than they arrived.`);
|
|
42
|
+
const total = m1 + m2;
|
|
43
|
+
const v1 = (m1 * u1 + m2 * u2 + m2 * e * (u2 - u1)) / total;
|
|
44
|
+
const v2 = (m1 * u1 + m2 * u2 + m1 * e * (u1 - u2)) / total;
|
|
45
|
+
const momentumBefore = m1 * u1 + m2 * u2;
|
|
46
|
+
const momentumAfter = m1 * v1 + m2 * v2;
|
|
47
|
+
const kineticBefore = kinetic(m1, u1) + kinetic(m2, u2);
|
|
48
|
+
const kineticAfter = kinetic(m1, v1) + kinetic(m2, v2);
|
|
49
|
+
const approachSpeed = u1 - u2;
|
|
50
|
+
const separationSpeed = v2 - v1;
|
|
51
|
+
const w = calc().step("m_1u_1 + m_2u_2 = m_1v_1 + m_2v_2", "momentum is conserved in EVERY collision, elastic or not. This is the equation that never changes").step("e = \\frac{v_2 - v_1}{u_1 - u_2}", `restitution supplies the second equation. Here e = ${texSigFigs(e, sf)}${e === 1 ? ", perfectly elastic" : e === 0 ? ", perfectly inelastic: they move off together" : ""}`).step(`u_1 = ${texSigFigs(u1, sf)},\\quad u_2 = ${texSigFigs(u2, sf)}\\ \\mathrm{m\\,s^{-1}}`, "signed along one axis: bodies approaching each other have opposite signs").step(`v_1 = ${texSigFigs(v1, sf)},\\quad v_2 = ${texSigFigs(v2, sf)}\\ \\mathrm{m\\,s^{-1}}`, "two equations, two unknowns").step(`E_k: ${texSigFigs(kineticBefore, sf)} \\to ${texSigFigs(kineticAfter, sf)}\\ \\mathrm{J}`, kineticBefore - kineticAfter < 1e-9 ? "nothing lost, which happens at e = 1 and nowhere else" : `${texSigFigs(kineticBefore - kineticAfter, sf)} J became heat, sound and deformation. Energy is a RESULT here, not an input`);
|
|
52
|
+
return {
|
|
53
|
+
v1,
|
|
54
|
+
v2,
|
|
55
|
+
restitution: e,
|
|
56
|
+
momentumBefore,
|
|
57
|
+
momentumAfter,
|
|
58
|
+
kineticBefore,
|
|
59
|
+
kineticAfter,
|
|
60
|
+
kineticLost: kineticBefore - kineticAfter,
|
|
61
|
+
approachSpeed,
|
|
62
|
+
separationSpeed,
|
|
63
|
+
worked: w.done(v1)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The restitution a collision actually had, measured from what happened.
|
|
68
|
+
*
|
|
69
|
+
* The inverse, and the one an experiment produces: drop a ball, measure the bounce, divide. Worth
|
|
70
|
+
* having because it turns `e` from a number in a formula into something a learner has measured.
|
|
71
|
+
*/
|
|
72
|
+
function restitutionOf(u1, u2, v1, v2) {
|
|
73
|
+
const approach = u1 - u2;
|
|
74
|
+
if (Math.abs(approach) < 1e-12) throw new Error("They were not approaching each other, so there is no collision to measure.");
|
|
75
|
+
return (v2 - v1) / approach;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A ball bouncing on the ground: `e = √(h_bounce / h_drop)`.
|
|
79
|
+
*
|
|
80
|
+
* The standard measurement, and the square root is the part that surprises people. Restitution is a
|
|
81
|
+
* ratio of SPEEDS and height goes as speed squared, so a ball returning to half its height has
|
|
82
|
+
* `e = 0.71`, not 0.5.
|
|
83
|
+
*/
|
|
84
|
+
function restitutionFromBounce(dropHeight, bounceHeight, sf = 3) {
|
|
85
|
+
if (dropHeight <= 0) throw new Error("The drop height must be positive.");
|
|
86
|
+
if (bounceHeight < 0 || bounceHeight > dropHeight) throw new Error("The bounce cannot be higher than the drop, or negative.");
|
|
87
|
+
const value = Math.sqrt(bounceHeight / dropHeight);
|
|
88
|
+
return {
|
|
89
|
+
value,
|
|
90
|
+
worked: calc().step("v = \\sqrt{2gh}", "the speed at the ground, from the drop and from the rebound").step("e = \\frac{v_{up}}{v_{down}} = \\sqrt{\\frac{h_{bounce}}{h_{drop}}}", "the g and the 2 cancel").step(`e = \\sqrt{\\frac{${texSigFigs(bounceHeight, sf)}}{${texSigFigs(dropHeight, sf)}}} = ${texSigFigs(value, sf)}`, "a ratio of SPEEDS, so the height ratio is squared: half the height is e = 0.707, not 0.5").done(value)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Bodies that start together and fly apart: an explosion, a recoiling gun, a person stepping off a
|
|
95
|
+
* boat.
|
|
96
|
+
*
|
|
97
|
+
* Not a different law. Total momentum before is whatever it was, usually zero, and it is still that
|
|
98
|
+
* afterwards, so the fragments' momenta must cancel. Give every fragment's velocity except one and
|
|
99
|
+
* this returns the missing one.
|
|
100
|
+
*/
|
|
101
|
+
function separateFrom(initialMomentum, known, unknownMass, sf = 3) {
|
|
102
|
+
if (unknownMass <= 0) throw new Error("The remaining mass must be positive.");
|
|
103
|
+
const accounted = known.reduce((p, k) => p + k.mass * k.velocity, 0);
|
|
104
|
+
const velocity = (initialMomentum - accounted) / unknownMass;
|
|
105
|
+
const w = calc().step("\\sum p_{\\text{before}} = \\sum p_{\\text{after}}", initialMomentum === 0 ? "it started at rest, so the pieces’ momenta must cancel exactly" : "total momentum is unchanged, however many pieces there now are");
|
|
106
|
+
for (const k of known) w.step(`${k.label}: ${texSigFigs(k.mass, sf)} \\times ${texSigFigs(k.velocity, sf)} = ${texSigFigs(k.mass * k.velocity, sf)}\\ \\mathrm{kg\\,m\\,s^{-1}}`);
|
|
107
|
+
w.step(`v = \\frac{${texSigFigs(initialMomentum, sf)} - ${texSigFigs(accounted, sf)}}{${texSigFigs(unknownMass, sf)}} = ${texSigFigs(velocity, sf)}\\ \\mathrm{m\\,s^{-1}}`, "the sign says which way it goes, and it is opposite to whatever the others did");
|
|
108
|
+
return {
|
|
109
|
+
velocity,
|
|
110
|
+
worked: w.done(velocity)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
export { collide, restitutionFromBounce, restitutionOf, separateFrom };
|