@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,161 @@
|
|
|
1
|
+
import { Vec3 } from "../../core/vec3.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/magnetism/biot-savart.d.ts
|
|
4
|
+
/** Permeability of free space, in T m A^-1. */
|
|
5
|
+
declare const MU_0: number;
|
|
6
|
+
/**
|
|
7
|
+
* Closest a field point may sit to a current filament, in metres.
|
|
8
|
+
*
|
|
9
|
+
* A filament is a modelling fiction with zero thickness, so B genuinely
|
|
10
|
+
* diverges on it. We refuse rather than return a huge number, because a huge
|
|
11
|
+
* number looks like an answer and a student will write it down.
|
|
12
|
+
*/
|
|
13
|
+
declare const MIN_DISTANCE_M = 0.000001;
|
|
14
|
+
/** A polyline carrying a steady current, walked from points[0] to the last. */
|
|
15
|
+
interface CurrentPath {
|
|
16
|
+
id: string;
|
|
17
|
+
/** Current in amperes. Negative reverses the sense of travel. */
|
|
18
|
+
currentA: number;
|
|
19
|
+
/** Vertices in metres. A segment is drawn between consecutive vertices. */
|
|
20
|
+
points: Vec3[];
|
|
21
|
+
/** When true, a closing segment joins the last vertex back to the first. */
|
|
22
|
+
closed?: boolean;
|
|
23
|
+
}
|
|
24
|
+
interface FieldContribution {
|
|
25
|
+
pathId: string;
|
|
26
|
+
field: Vec3;
|
|
27
|
+
magnitudeT: number;
|
|
28
|
+
}
|
|
29
|
+
interface FieldResult {
|
|
30
|
+
field: Vec3;
|
|
31
|
+
magnitudeT: number;
|
|
32
|
+
/** Per-path breakdown, so a lesson can show superposition rather than assert it. */
|
|
33
|
+
contributions: FieldContribution[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Field at `point` from one straight segment carrying `currentA` from `from` to `to`.
|
|
37
|
+
*
|
|
38
|
+
* Exact, not sampled. Integrating dl x r / |r|^3 along a straight line gives
|
|
39
|
+
*
|
|
40
|
+
* B = (mu0 I / 4pi) * (lhat x r1) / |lhat x r1|^2 * (lhat . r1hat - lhat . r2hat)
|
|
41
|
+
*
|
|
42
|
+
* where r1, r2 are the vectors from each end to the field point. The right-hand
|
|
43
|
+
* factor is the (sin theta1 + sin theta2) of the textbook, written so that it
|
|
44
|
+
* never needs an angle convention.
|
|
45
|
+
*/
|
|
46
|
+
declare function segmentField(from: Vec3, to: Vec3, point: Vec3, currentA: number): Vec3;
|
|
47
|
+
/** Field at a point from one current path. */
|
|
48
|
+
declare function pathField(path: CurrentPath, point: Vec3): Vec3;
|
|
49
|
+
/**
|
|
50
|
+
* Field at a point from any number of current paths.
|
|
51
|
+
*
|
|
52
|
+
* Superposition is the whole reason this is one function and not many: two
|
|
53
|
+
* wires, a wire and a coil, a Helmholtz pair, all add the same way.
|
|
54
|
+
*/
|
|
55
|
+
declare function fieldAt(paths: readonly CurrentPath[], point: Vec3): FieldResult;
|
|
56
|
+
interface StreamlineOptions {
|
|
57
|
+
/** Arc length per step, in metres. Smaller is smoother and slower. */
|
|
58
|
+
stepM?: number;
|
|
59
|
+
maxSteps?: number;
|
|
60
|
+
/** +1 follows the field, -1 runs against it. Trace both to get a whole line. */
|
|
61
|
+
direction?: 1 | -1;
|
|
62
|
+
/** Abandon the line once it strays this far from the seed. */
|
|
63
|
+
boundsM?: number;
|
|
64
|
+
/** Treat the line as closed once it returns this close to its own start. */
|
|
65
|
+
closeToleranceM?: number;
|
|
66
|
+
}
|
|
67
|
+
interface Streamline {
|
|
68
|
+
points: Vec3[];
|
|
69
|
+
/** Why the trace stopped, which is information a lesson can use. */
|
|
70
|
+
ended: 'closed' | 'left-bounds' | 'hit-current' | 'max-steps';
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Trace one magnetic field line from a seed point.
|
|
74
|
+
*
|
|
75
|
+
* A field line is the curve whose tangent is B everywhere, so tracing it means
|
|
76
|
+
* stepping along the UNIT field: that keeps the step a fixed arc length instead
|
|
77
|
+
* of a fixed time, so the spacing stays even where the field is strong.
|
|
78
|
+
* Integrated with RK4, because a field line through a coil turns sharply enough
|
|
79
|
+
* that Euler visibly spirals outward and a student would be looking at the
|
|
80
|
+
* integrator's error rather than at the physics.
|
|
81
|
+
*/
|
|
82
|
+
declare function traceFieldLine(paths: readonly CurrentPath[], seed: Vec3, options?: StreamlineOptions): Streamline;
|
|
83
|
+
/**
|
|
84
|
+
* Trace a full field line through a seed, running both ways from it.
|
|
85
|
+
*
|
|
86
|
+
* A magnetic field line has no start and no end, so seeding one and following
|
|
87
|
+
* it forwards only would draw half a line and imply the seed was special.
|
|
88
|
+
*/
|
|
89
|
+
declare function traceFullFieldLine(paths: readonly CurrentPath[], seed: Vec3, options?: StreamlineOptions): Streamline;
|
|
90
|
+
/** A straight run of wire between two points. */
|
|
91
|
+
declare function straightWire(from: Vec3, to: Vec3, currentA: number, id?: string): CurrentPath;
|
|
92
|
+
/**
|
|
93
|
+
* A wire long enough to stand in for an infinite one, centred on `through` and
|
|
94
|
+
* running along `direction`.
|
|
95
|
+
*
|
|
96
|
+
* "Infinite" is not a geometry, so a lesson that wants the textbook
|
|
97
|
+
* mu0 I / 2 pi a has to pick a length. Making that choice visible is the point:
|
|
98
|
+
* the student can shorten it and watch the answer fall away from the formula.
|
|
99
|
+
*/
|
|
100
|
+
declare function longWire(through: Vec3, direction: Vec3, currentA: number, halfLengthM?: number, id?: string): CurrentPath;
|
|
101
|
+
/**
|
|
102
|
+
* A circular arc of `arcDeg` in the xy plane, centred on `centre`, radius `radiusM`.
|
|
103
|
+
*
|
|
104
|
+
* A full loop is `arcDeg = 360`. Positive current circulates anticlockwise seen
|
|
105
|
+
* from +z, so by the right-hand rule B points along +z at the centre.
|
|
106
|
+
*/
|
|
107
|
+
declare function circularArc(centre: Vec3, radiusM: number, currentA: number, arcDeg?: number, segments?: number, id?: string): CurrentPath;
|
|
108
|
+
/** A flat coil of `turns` identical loops, treated as `turns` times one loop's current. */
|
|
109
|
+
declare function flatCoil(centre: Vec3, radiusM: number, currentA: number, turns?: number, segments?: number, id?: string): CurrentPath;
|
|
110
|
+
/**
|
|
111
|
+
* A helical solenoid along z, centred on the origin.
|
|
112
|
+
*
|
|
113
|
+
* Wound as a real solenoid is: one continuous helix, not a stack of separate
|
|
114
|
+
* rings. That matters at the ends, which is exactly where the mu0 n I formula
|
|
115
|
+
* stops being true and where a student should be able to see it stop.
|
|
116
|
+
*/
|
|
117
|
+
declare function solenoid(radiusM: number, lengthM: number, turns: number, currentA: number, perTurn?: number, id?: string): CurrentPath;
|
|
118
|
+
/**
|
|
119
|
+
* An IDEAL solenoid: `turns` separate coaxial rings, with no axial current at all.
|
|
120
|
+
*
|
|
121
|
+
* This is the model teaching uses, and the difference from `solenoid()` is real
|
|
122
|
+
* rather than cosmetic. A helix carries a net current ALONG its axis as well as
|
|
123
|
+
* around it, so it makes a weak circulating field of its own on top of the
|
|
124
|
+
* axial one. The numbers barely move, but a traced field line drifts out of the
|
|
125
|
+
* plane and comes back somewhere else, so a diagram of a helix's lines is a
|
|
126
|
+
* tangle rather than the clean picture the physics deserves.
|
|
127
|
+
*
|
|
128
|
+
* Use this to draw and to reason; use `solenoid()` when the question is what a
|
|
129
|
+
* real winding does, which is what the end-of-coil behaviour is about.
|
|
130
|
+
*/
|
|
131
|
+
declare function solenoidRings(radiusM: number, lengthM: number, turns: number, currentA: number, segments?: number, id?: string): CurrentPath[];
|
|
132
|
+
/** Two coaxial coils one radius apart: the standard uniform-field arrangement. */
|
|
133
|
+
declare function helmholtzPair(radiusM: number, currentA: number, turns?: number, segments?: number): CurrentPath[];
|
|
134
|
+
/** A rectangular loop in the xy plane, centred on the origin. */
|
|
135
|
+
declare function rectangularLoop(widthM: number, heightM: number, currentA: number, id?: string): CurrentPath;
|
|
136
|
+
/** B a perpendicular distance from a very long straight wire: mu0 I / 2 pi a. */
|
|
137
|
+
declare function longWireT(currentA: number, distanceM: number): number;
|
|
138
|
+
/**
|
|
139
|
+
* B from a finite straight wire: mu0 I / 4 pi a * (sin t1 + sin t2).
|
|
140
|
+
*
|
|
141
|
+
* The angles are measured at the field point, from the perpendicular to each
|
|
142
|
+
* end of the wire.
|
|
143
|
+
*/
|
|
144
|
+
declare function finiteWireT(currentA: number, perpDistanceM: number, angle1Deg: number, angle2Deg: number): number;
|
|
145
|
+
/** B at the centre of a flat circular coil: mu0 N I / 2 r. */
|
|
146
|
+
declare function coilCentreT(currentA: number, radiusM: number, turns?: number): number;
|
|
147
|
+
/** B on the axis of a flat coil, `axialM` from its centre. */
|
|
148
|
+
declare function coilAxisT(currentA: number, radiusM: number, axialM: number, turns?: number): number;
|
|
149
|
+
/**
|
|
150
|
+
* B at the centre of an arc subtending `arcDeg`: mu0 I theta / 4 pi r.
|
|
151
|
+
*
|
|
152
|
+
* A full 360 reduces to the coil-centre formula, which is the cleanest way to
|
|
153
|
+
* show a student that the two are not separate results.
|
|
154
|
+
*/
|
|
155
|
+
declare function arcCentreT(currentA: number, radiusM: number, arcDeg: number): number;
|
|
156
|
+
/** B inside a long solenoid: mu0 n I, with n in turns per metre. */
|
|
157
|
+
declare function solenoidT(currentA: number, turnsPerMetre: number): number;
|
|
158
|
+
/** B inside a toroid at mean radius r: mu0 N I / 2 pi r. */
|
|
159
|
+
declare function toroidT(currentA: number, turns: number, meanRadiusM: number): number;
|
|
160
|
+
//#endregion
|
|
161
|
+
export { CurrentPath, FieldContribution, FieldResult, MIN_DISTANCE_M, MU_0, Streamline, StreamlineOptions, arcCentreT, circularArc, coilAxisT, coilCentreT, fieldAt, finiteWireT, flatCoil, helmholtzPair, longWire, longWireT, pathField, rectangularLoop, segmentField, solenoid, solenoidRings, solenoidT, straightWire, toroidT, traceFieldLine, traceFullFieldLine };
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { ZERO3, add3, cross3, dot3, mag3, scale3, sub3, v3 } from "../../core/vec3.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/magnetism/biot-savart.ts
|
|
4
|
+
/**
|
|
5
|
+
* @classytic/stage/field/magnetostatics — Biot-Savart: the field a current MAKES.
|
|
6
|
+
*
|
|
7
|
+
* The rest of the magnetism engines answer "what does a field DO" (force on a
|
|
8
|
+
* conductor, force on a moving charge, Hall voltage, induced e.m.f.). Nothing
|
|
9
|
+
* answered the other half: given a geometry of current, what is B at a point?
|
|
10
|
+
*
|
|
11
|
+
* Textbooks answer that with a page of special cases -- straight wire, finite
|
|
12
|
+
* wire, circular coil centre, coil axis, arc, solenoid, toroid -- each with its
|
|
13
|
+
* own formula to memorise. They are all the same integral over a different
|
|
14
|
+
* shape. This module integrates that one law over an arbitrary current path, so
|
|
15
|
+
* every one of those cases is the same call with different geometry, and the
|
|
16
|
+
* closed forms below exist to CHECK the integrator rather than to replace it.
|
|
17
|
+
*
|
|
18
|
+
* Accuracy: a straight segment is integrated in closed form, so any polyline
|
|
19
|
+
* (wire, rectangle, square loop, solenoid leg) is exact to floating point. A
|
|
20
|
+
* curve is approximated by a polygon, whose error falls as 1/N^2.
|
|
21
|
+
*/
|
|
22
|
+
/** Permeability of free space, in T m A^-1. */
|
|
23
|
+
const MU_0 = 4 * Math.PI * 1e-7;
|
|
24
|
+
/**
|
|
25
|
+
* Closest a field point may sit to a current filament, in metres.
|
|
26
|
+
*
|
|
27
|
+
* A filament is a modelling fiction with zero thickness, so B genuinely
|
|
28
|
+
* diverges on it. We refuse rather than return a huge number, because a huge
|
|
29
|
+
* number looks like an answer and a student will write it down.
|
|
30
|
+
*/
|
|
31
|
+
const MIN_DISTANCE_M = 1e-6;
|
|
32
|
+
const sub = sub3;
|
|
33
|
+
const radians = (deg) => deg * Math.PI / 180;
|
|
34
|
+
/**
|
|
35
|
+
* Field at `point` from one straight segment carrying `currentA` from `from` to `to`.
|
|
36
|
+
*
|
|
37
|
+
* Exact, not sampled. Integrating dl x r / |r|^3 along a straight line gives
|
|
38
|
+
*
|
|
39
|
+
* B = (mu0 I / 4pi) * (lhat x r1) / |lhat x r1|^2 * (lhat . r1hat - lhat . r2hat)
|
|
40
|
+
*
|
|
41
|
+
* where r1, r2 are the vectors from each end to the field point. The right-hand
|
|
42
|
+
* factor is the (sin theta1 + sin theta2) of the textbook, written so that it
|
|
43
|
+
* never needs an angle convention.
|
|
44
|
+
*/
|
|
45
|
+
function segmentField(from, to, point, currentA) {
|
|
46
|
+
const along = sub(to, from);
|
|
47
|
+
const length = mag3(along);
|
|
48
|
+
if (length === 0) return ZERO3;
|
|
49
|
+
const lhat = scale3(along, 1 / length);
|
|
50
|
+
const r1 = sub(point, from);
|
|
51
|
+
const r2 = sub(point, to);
|
|
52
|
+
const d1 = mag3(r1);
|
|
53
|
+
const d2 = mag3(r2);
|
|
54
|
+
if (d1 < 1e-6 || d2 < 1e-6) throw new RangeError("The field point sits on the end of a current segment, where B diverges.");
|
|
55
|
+
const perp = cross3(lhat, r1);
|
|
56
|
+
const perpSq = dot3(perp, perp);
|
|
57
|
+
if (perpSq < 1e-6 * 1e-6) return ZERO3;
|
|
58
|
+
const endSpan = dot3(lhat, r1) / d1 - dot3(lhat, r2) / d2;
|
|
59
|
+
return scale3(perp, MU_0 * currentA / (4 * Math.PI) * (endSpan / perpSq));
|
|
60
|
+
}
|
|
61
|
+
const segmentsOf = (path) => {
|
|
62
|
+
const pairs = [];
|
|
63
|
+
const points = path.points;
|
|
64
|
+
for (let i = 0; i + 1 < points.length; i += 1) {
|
|
65
|
+
const from = points[i];
|
|
66
|
+
const to = points[i + 1];
|
|
67
|
+
if (from && to) pairs.push([from, to]);
|
|
68
|
+
}
|
|
69
|
+
if (path.closed && points.length > 2) {
|
|
70
|
+
const last = points[points.length - 1];
|
|
71
|
+
const first = points[0];
|
|
72
|
+
if (last && first) pairs.push([last, first]);
|
|
73
|
+
}
|
|
74
|
+
return pairs;
|
|
75
|
+
};
|
|
76
|
+
/** Field at a point from one current path. */
|
|
77
|
+
function pathField(path, point) {
|
|
78
|
+
return segmentsOf(path).reduce((total, [from, to]) => add3(total, segmentField(from, to, point, path.currentA)), ZERO3);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Field at a point from any number of current paths.
|
|
82
|
+
*
|
|
83
|
+
* Superposition is the whole reason this is one function and not many: two
|
|
84
|
+
* wires, a wire and a coil, a Helmholtz pair, all add the same way.
|
|
85
|
+
*/
|
|
86
|
+
function fieldAt(paths, point) {
|
|
87
|
+
const contributions = paths.map((path) => {
|
|
88
|
+
const field = pathField(path, point);
|
|
89
|
+
return {
|
|
90
|
+
pathId: path.id,
|
|
91
|
+
field,
|
|
92
|
+
magnitudeT: mag3(field)
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
const field = contributions.reduce((total, c) => add3(total, c.field), ZERO3);
|
|
96
|
+
return {
|
|
97
|
+
field,
|
|
98
|
+
magnitudeT: mag3(field),
|
|
99
|
+
contributions
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Trace one magnetic field line from a seed point.
|
|
104
|
+
*
|
|
105
|
+
* A field line is the curve whose tangent is B everywhere, so tracing it means
|
|
106
|
+
* stepping along the UNIT field: that keeps the step a fixed arc length instead
|
|
107
|
+
* of a fixed time, so the spacing stays even where the field is strong.
|
|
108
|
+
* Integrated with RK4, because a field line through a coil turns sharply enough
|
|
109
|
+
* that Euler visibly spirals outward and a student would be looking at the
|
|
110
|
+
* integrator's error rather than at the physics.
|
|
111
|
+
*/
|
|
112
|
+
function traceFieldLine(paths, seed, options = {}) {
|
|
113
|
+
const { stepM = .002, maxSteps = 4e3, direction = 1, boundsM = 1, closeToleranceM = stepM } = options;
|
|
114
|
+
if (stepM <= 0) throw new RangeError("A field line needs a positive step length.");
|
|
115
|
+
const unitField = (at) => {
|
|
116
|
+
let b;
|
|
117
|
+
try {
|
|
118
|
+
b = fieldAt(paths, at).field;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const size = mag3(b);
|
|
123
|
+
if (!Number.isFinite(size) || size === 0) return null;
|
|
124
|
+
return scale3(b, direction / size);
|
|
125
|
+
};
|
|
126
|
+
const points = [seed];
|
|
127
|
+
let current = seed;
|
|
128
|
+
for (let step = 0; step < maxSteps; step += 1) {
|
|
129
|
+
const k1 = unitField(current);
|
|
130
|
+
if (!k1) return {
|
|
131
|
+
points,
|
|
132
|
+
ended: "hit-current"
|
|
133
|
+
};
|
|
134
|
+
const k2 = unitField(add3(current, scale3(k1, stepM / 2)));
|
|
135
|
+
if (!k2) return {
|
|
136
|
+
points,
|
|
137
|
+
ended: "hit-current"
|
|
138
|
+
};
|
|
139
|
+
const k3 = unitField(add3(current, scale3(k2, stepM / 2)));
|
|
140
|
+
if (!k3) return {
|
|
141
|
+
points,
|
|
142
|
+
ended: "hit-current"
|
|
143
|
+
};
|
|
144
|
+
const k4 = unitField(add3(current, scale3(k3, stepM)));
|
|
145
|
+
if (!k4) return {
|
|
146
|
+
points,
|
|
147
|
+
ended: "hit-current"
|
|
148
|
+
};
|
|
149
|
+
const advance = scale3(add3(add3(k1, scale3(k2, 2)), add3(scale3(k3, 2), k4)), stepM / 6);
|
|
150
|
+
current = add3(current, advance);
|
|
151
|
+
points.push(current);
|
|
152
|
+
if (mag3(sub(current, seed)) > boundsM) return {
|
|
153
|
+
points,
|
|
154
|
+
ended: "left-bounds"
|
|
155
|
+
};
|
|
156
|
+
if (step > 8 && mag3(sub(current, seed)) < closeToleranceM) return {
|
|
157
|
+
points,
|
|
158
|
+
ended: "closed"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
points,
|
|
163
|
+
ended: "max-steps"
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Trace a full field line through a seed, running both ways from it.
|
|
168
|
+
*
|
|
169
|
+
* A magnetic field line has no start and no end, so seeding one and following
|
|
170
|
+
* it forwards only would draw half a line and imply the seed was special.
|
|
171
|
+
*/
|
|
172
|
+
function traceFullFieldLine(paths, seed, options = {}) {
|
|
173
|
+
const forward = traceFieldLine(paths, seed, {
|
|
174
|
+
...options,
|
|
175
|
+
direction: 1
|
|
176
|
+
});
|
|
177
|
+
if (forward.ended === "closed") return forward;
|
|
178
|
+
return {
|
|
179
|
+
points: [...traceFieldLine(paths, seed, {
|
|
180
|
+
...options,
|
|
181
|
+
direction: -1
|
|
182
|
+
}).points.slice(1).reverse(), ...forward.points],
|
|
183
|
+
ended: forward.ended
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/** A straight run of wire between two points. */
|
|
187
|
+
function straightWire(from, to, currentA, id = "wire") {
|
|
188
|
+
return {
|
|
189
|
+
id,
|
|
190
|
+
currentA,
|
|
191
|
+
points: [from, to]
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* A wire long enough to stand in for an infinite one, centred on `through` and
|
|
196
|
+
* running along `direction`.
|
|
197
|
+
*
|
|
198
|
+
* "Infinite" is not a geometry, so a lesson that wants the textbook
|
|
199
|
+
* mu0 I / 2 pi a has to pick a length. Making that choice visible is the point:
|
|
200
|
+
* the student can shorten it and watch the answer fall away from the formula.
|
|
201
|
+
*/
|
|
202
|
+
function longWire(through, direction, currentA, halfLengthM = 1e4, id = "long-wire") {
|
|
203
|
+
const unit = mag3(direction);
|
|
204
|
+
if (unit === 0) throw new RangeError("A wire needs a direction.");
|
|
205
|
+
const step = scale3(direction, halfLengthM / unit);
|
|
206
|
+
return {
|
|
207
|
+
id,
|
|
208
|
+
currentA,
|
|
209
|
+
points: [sub(through, step), add3(through, step)]
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* A circular arc of `arcDeg` in the xy plane, centred on `centre`, radius `radiusM`.
|
|
214
|
+
*
|
|
215
|
+
* A full loop is `arcDeg = 360`. Positive current circulates anticlockwise seen
|
|
216
|
+
* from +z, so by the right-hand rule B points along +z at the centre.
|
|
217
|
+
*/
|
|
218
|
+
function circularArc(centre, radiusM, currentA, arcDeg = 360, segments = 720, id = "arc") {
|
|
219
|
+
if (radiusM <= 0) throw new RangeError("A coil needs a positive radius.");
|
|
220
|
+
if (segments < 3) throw new RangeError("An arc needs at least 3 segments to be worth integrating.");
|
|
221
|
+
const span = radians(arcDeg);
|
|
222
|
+
const count = Math.max(3, Math.round(segments * Math.abs(arcDeg) / 360));
|
|
223
|
+
const points = [];
|
|
224
|
+
for (let i = 0; i <= count; i += 1) {
|
|
225
|
+
const t = span * (i / count);
|
|
226
|
+
points.push(v3(centre.x + radiusM * Math.cos(t), centre.y + radiusM * Math.sin(t), centre.z));
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
id,
|
|
230
|
+
currentA,
|
|
231
|
+
points
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/** A flat coil of `turns` identical loops, treated as `turns` times one loop's current. */
|
|
235
|
+
function flatCoil(centre, radiusM, currentA, turns = 1, segments = 720, id = "coil") {
|
|
236
|
+
if (!Number.isInteger(turns) || turns < 1) throw new RangeError("A coil needs a whole number of turns.");
|
|
237
|
+
return circularArc(centre, radiusM, currentA * turns, 360, segments, id);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* A helical solenoid along z, centred on the origin.
|
|
241
|
+
*
|
|
242
|
+
* Wound as a real solenoid is: one continuous helix, not a stack of separate
|
|
243
|
+
* rings. That matters at the ends, which is exactly where the mu0 n I formula
|
|
244
|
+
* stops being true and where a student should be able to see it stop.
|
|
245
|
+
*/
|
|
246
|
+
function solenoid(radiusM, lengthM, turns, currentA, perTurn = 32, id = "solenoid") {
|
|
247
|
+
if (radiusM <= 0 || lengthM <= 0) throw new RangeError("A solenoid needs a positive radius and length.");
|
|
248
|
+
if (!Number.isInteger(turns) || turns < 1) throw new RangeError("A solenoid needs a whole number of turns.");
|
|
249
|
+
const steps = turns * perTurn;
|
|
250
|
+
const points = [];
|
|
251
|
+
for (let i = 0; i <= steps; i += 1) {
|
|
252
|
+
const t = i / steps;
|
|
253
|
+
const angle = 2 * Math.PI * turns * t;
|
|
254
|
+
points.push(v3(radiusM * Math.cos(angle), radiusM * Math.sin(angle), -lengthM / 2 + lengthM * t));
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
id,
|
|
258
|
+
currentA,
|
|
259
|
+
points
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* An IDEAL solenoid: `turns` separate coaxial rings, with no axial current at all.
|
|
264
|
+
*
|
|
265
|
+
* This is the model teaching uses, and the difference from `solenoid()` is real
|
|
266
|
+
* rather than cosmetic. A helix carries a net current ALONG its axis as well as
|
|
267
|
+
* around it, so it makes a weak circulating field of its own on top of the
|
|
268
|
+
* axial one. The numbers barely move, but a traced field line drifts out of the
|
|
269
|
+
* plane and comes back somewhere else, so a diagram of a helix's lines is a
|
|
270
|
+
* tangle rather than the clean picture the physics deserves.
|
|
271
|
+
*
|
|
272
|
+
* Use this to draw and to reason; use `solenoid()` when the question is what a
|
|
273
|
+
* real winding does, which is what the end-of-coil behaviour is about.
|
|
274
|
+
*/
|
|
275
|
+
function solenoidRings(radiusM, lengthM, turns, currentA, segments = 180, id = "solenoid") {
|
|
276
|
+
if (radiusM <= 0 || lengthM <= 0) throw new RangeError("A solenoid needs a positive radius and length.");
|
|
277
|
+
if (!Number.isInteger(turns) || turns < 1) throw new RangeError("A solenoid needs a whole number of turns.");
|
|
278
|
+
return Array.from({ length: turns }, (_, i) => {
|
|
279
|
+
return circularArc(v3(0, 0, -lengthM / 2 + lengthM * (i + .5) / turns), radiusM, currentA, 360, segments, `${id}-${i}`);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/** Two coaxial coils one radius apart: the standard uniform-field arrangement. */
|
|
283
|
+
function helmholtzPair(radiusM, currentA, turns = 1, segments = 720) {
|
|
284
|
+
return [flatCoil(v3(0, 0, -radiusM / 2), radiusM, currentA, turns, segments, "coil-near"), flatCoil(v3(0, 0, radiusM / 2), radiusM, currentA, turns, segments, "coil-far")];
|
|
285
|
+
}
|
|
286
|
+
/** A rectangular loop in the xy plane, centred on the origin. */
|
|
287
|
+
function rectangularLoop(widthM, heightM, currentA, id = "loop") {
|
|
288
|
+
if (widthM <= 0 || heightM <= 0) throw new RangeError("A loop needs positive sides.");
|
|
289
|
+
const w = widthM / 2;
|
|
290
|
+
const h = heightM / 2;
|
|
291
|
+
return {
|
|
292
|
+
id,
|
|
293
|
+
currentA,
|
|
294
|
+
closed: true,
|
|
295
|
+
points: [
|
|
296
|
+
v3(-w, -h, 0),
|
|
297
|
+
v3(w, -h, 0),
|
|
298
|
+
v3(w, h, 0),
|
|
299
|
+
v3(-w, h, 0)
|
|
300
|
+
]
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/** B a perpendicular distance from a very long straight wire: mu0 I / 2 pi a. */
|
|
304
|
+
function longWireT(currentA, distanceM) {
|
|
305
|
+
if (distanceM <= 0) throw new RangeError("Distance from the wire must be positive.");
|
|
306
|
+
return MU_0 * Math.abs(currentA) / (2 * Math.PI * distanceM);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* B from a finite straight wire: mu0 I / 4 pi a * (sin t1 + sin t2).
|
|
310
|
+
*
|
|
311
|
+
* The angles are measured at the field point, from the perpendicular to each
|
|
312
|
+
* end of the wire.
|
|
313
|
+
*/
|
|
314
|
+
function finiteWireT(currentA, perpDistanceM, angle1Deg, angle2Deg) {
|
|
315
|
+
if (perpDistanceM <= 0) throw new RangeError("Perpendicular distance must be positive.");
|
|
316
|
+
const span = Math.sin(radians(angle1Deg)) + Math.sin(radians(angle2Deg));
|
|
317
|
+
return MU_0 * Math.abs(currentA) / (4 * Math.PI * perpDistanceM) * span;
|
|
318
|
+
}
|
|
319
|
+
/** B at the centre of a flat circular coil: mu0 N I / 2 r. */
|
|
320
|
+
function coilCentreT(currentA, radiusM, turns = 1) {
|
|
321
|
+
if (radiusM <= 0) throw new RangeError("A coil needs a positive radius.");
|
|
322
|
+
return MU_0 * turns * Math.abs(currentA) / (2 * radiusM);
|
|
323
|
+
}
|
|
324
|
+
/** B on the axis of a flat coil, `axialM` from its centre. */
|
|
325
|
+
function coilAxisT(currentA, radiusM, axialM, turns = 1) {
|
|
326
|
+
if (radiusM <= 0) throw new RangeError("A coil needs a positive radius.");
|
|
327
|
+
const denominator = Math.pow(radiusM * radiusM + axialM * axialM, 1.5);
|
|
328
|
+
return MU_0 * turns * Math.abs(currentA) * radiusM * radiusM / (2 * denominator);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* B at the centre of an arc subtending `arcDeg`: mu0 I theta / 4 pi r.
|
|
332
|
+
*
|
|
333
|
+
* A full 360 reduces to the coil-centre formula, which is the cleanest way to
|
|
334
|
+
* show a student that the two are not separate results.
|
|
335
|
+
*/
|
|
336
|
+
function arcCentreT(currentA, radiusM, arcDeg) {
|
|
337
|
+
if (radiusM <= 0) throw new RangeError("An arc needs a positive radius.");
|
|
338
|
+
return MU_0 * Math.abs(currentA) * radians(Math.abs(arcDeg)) / (4 * Math.PI * radiusM);
|
|
339
|
+
}
|
|
340
|
+
/** B inside a long solenoid: mu0 n I, with n in turns per metre. */
|
|
341
|
+
function solenoidT(currentA, turnsPerMetre) {
|
|
342
|
+
if (turnsPerMetre < 0) throw new RangeError("Turns per metre cannot be negative.");
|
|
343
|
+
return MU_0 * turnsPerMetre * Math.abs(currentA);
|
|
344
|
+
}
|
|
345
|
+
/** B inside a toroid at mean radius r: mu0 N I / 2 pi r. */
|
|
346
|
+
function toroidT(currentA, turns, meanRadiusM) {
|
|
347
|
+
if (meanRadiusM <= 0) throw new RangeError("A toroid needs a positive mean radius.");
|
|
348
|
+
if (turns < 0) throw new RangeError("Turns cannot be negative.");
|
|
349
|
+
return MU_0 * turns * Math.abs(currentA) / (2 * Math.PI * meanRadiusM);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
//#endregion
|
|
353
|
+
export { 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 };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Vec3 } from "../../core/vec3.mjs";
|
|
2
|
+
import { CurrentPath } from "./biot-savart.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/magnetism/flux.d.ts
|
|
5
|
+
type FluxLoop = {
|
|
6
|
+
kind: 'rectangle';
|
|
7
|
+
centre: Vec3;
|
|
8
|
+
normal: Vec3;
|
|
9
|
+
widthM: number;
|
|
10
|
+
heightM: number; /** Which in-plane direction the width runs along. Defaults to a stable choice. */
|
|
11
|
+
widthAxis?: Vec3;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'circle';
|
|
14
|
+
centre: Vec3;
|
|
15
|
+
normal: Vec3;
|
|
16
|
+
radiusM: number;
|
|
17
|
+
};
|
|
18
|
+
/** Area of the loop, in square metres. */
|
|
19
|
+
declare const loopArea: (loop: FluxLoop) => number;
|
|
20
|
+
/**
|
|
21
|
+
* Flux through a flat loop in a UNIFORM field: Phi = B A cos(theta).
|
|
22
|
+
*
|
|
23
|
+
* `normalToFieldDeg` is the angle between the loop's normal and the field, the
|
|
24
|
+
* same convention `coilTorqueNm` uses, so the two never disagree about what the
|
|
25
|
+
* angle means. The trap is the same one too: a question usually states the
|
|
26
|
+
* angle from the PLANE, and flux is greatest when the plane is ACROSS the field,
|
|
27
|
+
* which is exactly where the torque is zero.
|
|
28
|
+
*/
|
|
29
|
+
declare function fluxThroughUniform(fieldT: number, areaM2: number, normalToFieldDeg: number): number;
|
|
30
|
+
/** Flux linkage: the flux each turn sees, times the number of turns. */
|
|
31
|
+
declare function fluxLinkage(turns: number, fluxWb: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Magnitude of the average induced e.m.f. from Faraday's law.
|
|
34
|
+
*
|
|
35
|
+
* Unsigned on purpose. The direction is Lenz's law, which is a separate
|
|
36
|
+
* statement about what the induced current opposes, and folding a sign in here
|
|
37
|
+
* would let a student produce a direction without ever thinking about the
|
|
38
|
+
* opposition that gives it.
|
|
39
|
+
*/
|
|
40
|
+
declare function inducedEmfV(turns: number, fluxChangeWb: number, timeS: number): number;
|
|
41
|
+
/** How close a sample may come to a current filament before the flux is called divergent. */
|
|
42
|
+
declare const MIN_LOOP_CLEARANCE_M = 0.0001;
|
|
43
|
+
declare function fluxThroughLoop(sources: readonly CurrentPath[], loop: FluxLoop, order?: 8 | 16): number;
|
|
44
|
+
/**
|
|
45
|
+
* Self-inductance of a coil, in henries: L = N Phi / I.
|
|
46
|
+
*
|
|
47
|
+
* Measured by driving the coil with a test current and integrating the flux its
|
|
48
|
+
* own field puts through one turn. That the answer does not depend on the test
|
|
49
|
+
* current is the definition of inductance, and it is asserted in the tests
|
|
50
|
+
* rather than assumed.
|
|
51
|
+
*/
|
|
52
|
+
declare function selfInductanceH(coil: readonly CurrentPath[], oneTurn: FluxLoop, turns: number, testCurrentA?: number, order?: 8 | 16): number;
|
|
53
|
+
/**
|
|
54
|
+
* Mutual inductance between two circuits, in henries: M = N2 Phi2 / I1.
|
|
55
|
+
*
|
|
56
|
+
* The primary's field is integrated through one turn of the secondary. The
|
|
57
|
+
* reciprocity of this quantity, that driving either side gives the same M, is a
|
|
58
|
+
* real theorem and a good thing for a lesson to check rather than assert.
|
|
59
|
+
*/
|
|
60
|
+
declare function mutualInductanceH(primary: readonly CurrentPath[], secondaryTurn: FluxLoop, secondaryTurns: number, primaryCurrentA?: number, order?: 8 | 16): number;
|
|
61
|
+
/**
|
|
62
|
+
* Magnitude of the e.m.f. a changing current induces in its OWN circuit:
|
|
63
|
+
* E = L di/dt.
|
|
64
|
+
*
|
|
65
|
+
* The same physics as Faraday's law with the flux written as L I, and worth
|
|
66
|
+
* having separately because a question almost never gives you the flux. It
|
|
67
|
+
* gives you a current that changed and a time it took.
|
|
68
|
+
*/
|
|
69
|
+
declare function emfFromSelfInductance(inductanceH: number, currentChangeA: number, timeS: number): number;
|
|
70
|
+
/**
|
|
71
|
+
* Magnitude of the e.m.f. a changing current induces in a NEIGHBOURING circuit:
|
|
72
|
+
* E = M di/dt.
|
|
73
|
+
*
|
|
74
|
+
* Identical in form to the self-inductance case, with M in place of L. That the
|
|
75
|
+
* two are the same equation is the point: a transformer is not a new law, it is
|
|
76
|
+
* this one with the two coils wound on the same core.
|
|
77
|
+
*/
|
|
78
|
+
declare function emfFromMutualInductance(mutualH: number, currentChangeA: number, timeS: number): number;
|
|
79
|
+
/** Energy stored in an inductor's field, in joules: W = 1/2 L I squared. */
|
|
80
|
+
declare function magneticEnergyJ(inductanceH: number, currentA: number): number;
|
|
81
|
+
/** Ideal-solenoid self-inductance, for checking the integrated answer: mu0 N^2 A / l. */
|
|
82
|
+
declare function solenoidInductanceH(turns: number, areaM2: number, lengthM: number): number;
|
|
83
|
+
/**
|
|
84
|
+
* Flux through a rectangle lying beside a long straight wire, in closed form.
|
|
85
|
+
*
|
|
86
|
+
* Phi = (mu0 I l / 2 pi) ln(far / near)
|
|
87
|
+
*
|
|
88
|
+
* A standard exam result, and the best available check on the surface integral:
|
|
89
|
+
* the field varies as 1/r right across the loop, so nothing about this case is
|
|
90
|
+
* forgiving of a sloppy quadrature rule.
|
|
91
|
+
*/
|
|
92
|
+
declare function fluxBesideWire(currentA: number, lengthM: number, nearM: number, farM: number): number;
|
|
93
|
+
//#endregion
|
|
94
|
+
export { FluxLoop, MIN_LOOP_CLEARANCE_M, emfFromMutualInductance, emfFromSelfInductance, fluxBesideWire, fluxLinkage, fluxThroughLoop, fluxThroughUniform, inducedEmfV, loopArea, magneticEnergyJ, mutualInductanceH, selfInductanceH, solenoidInductanceH };
|