@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,178 @@
|
|
|
1
|
+
//#region src/thermo/expansion.ts
|
|
2
|
+
/**
|
|
3
|
+
* Thermal expansion: how much bigger things get when they are warmed, and what
|
|
4
|
+
* happens when they are not allowed to.
|
|
5
|
+
*
|
|
6
|
+
* THE MODEL. To first order every dimension grows in proportion to its own
|
|
7
|
+
* length and to the temperature rise:
|
|
8
|
+
*
|
|
9
|
+
* length ΔL = L₀·α·Δθ
|
|
10
|
+
* area ΔA = A₀·β·Δθ with β ≈ 2α
|
|
11
|
+
* volume ΔV = V₀·γ·Δθ with γ ≈ 3α
|
|
12
|
+
*
|
|
13
|
+
* WHY β = 2α AND γ = 3α ARE NOT SEPARATE MEASUREMENTS. A square of side L has
|
|
14
|
+
* area L², and (1+αΔθ)² = 1 + 2αΔθ + (αΔθ)², so the area coefficient is twice
|
|
15
|
+
* the linear one plus a term in α² that is about 10⁻⁸ for a metal over a 100 K
|
|
16
|
+
* rise. The functions below use the EXACT powers rather than the doubled and
|
|
17
|
+
* tripled approximations, and `areaCoefficient` / `volumeCoefficient` return
|
|
18
|
+
* the textbook 2α and 3α, so a lab can show the two agreeing and then show
|
|
19
|
+
* where they part company.
|
|
20
|
+
*
|
|
21
|
+
* THE THING STUDENTS GET WRONG. A hole in a plate gets BIGGER, not smaller.
|
|
22
|
+
* Every function here takes a dimension and scales it, with no notion of
|
|
23
|
+
* "solid" or "hole", precisely because the material does not have one: the
|
|
24
|
+
* plate expands as if the hole were filled with more plate.
|
|
25
|
+
*
|
|
26
|
+
* UNITS: SI. Lengths in m, areas in m², volumes in m³, coefficients per kelvin,
|
|
27
|
+
* temperature changes in K (identical to changes in °C).
|
|
28
|
+
*/
|
|
29
|
+
const finite = (value, what) => {
|
|
30
|
+
if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
const positive = (value, what) => {
|
|
34
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
35
|
+
return value;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Linear expansivity α, per kelvin, for materials that appear in the standard
|
|
39
|
+
* questions.
|
|
40
|
+
*
|
|
41
|
+
* Invar is in the table because it is the control: an alloy chosen to have
|
|
42
|
+
* almost no expansion, which is what makes the others' numbers mean something.
|
|
43
|
+
* The glass pair matters for the same reason, since the whole point of Pyrex is
|
|
44
|
+
* that a third of the expansion is a third of the thermal shock.
|
|
45
|
+
*/
|
|
46
|
+
const LINEAR_EXPANSIVITY = {
|
|
47
|
+
aluminium: 23e-6,
|
|
48
|
+
brass: 19e-6,
|
|
49
|
+
copper: 17e-6,
|
|
50
|
+
steel: 12e-6,
|
|
51
|
+
iron: 12e-6,
|
|
52
|
+
concrete: 12e-6,
|
|
53
|
+
glass: 85e-7,
|
|
54
|
+
pyrex: 32e-7,
|
|
55
|
+
invar: 12e-7,
|
|
56
|
+
quartz: 55e-8
|
|
57
|
+
};
|
|
58
|
+
/** Length after a temperature change: L = L₀(1 + αΔθ). */
|
|
59
|
+
function expandedLengthM(length0, alpha, deltaT) {
|
|
60
|
+
return positive(length0, "A length") * (1 + finite(alpha, "The expansivity") * finite(deltaT, "A temperature change"));
|
|
61
|
+
}
|
|
62
|
+
/** The change in length itself, m: ΔL = L₀·α·Δθ. */
|
|
63
|
+
function lengthChangeM(length0, alpha, deltaT) {
|
|
64
|
+
return positive(length0, "A length") * finite(alpha, "The expansivity") * finite(deltaT, "A temperature change");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Area after a temperature change, using the exact square rather than 2α.
|
|
68
|
+
*
|
|
69
|
+
* A = A₀(1 + αΔθ)², which is where β = 2α comes from and where it stops being
|
|
70
|
+
* quite right.
|
|
71
|
+
*/
|
|
72
|
+
function expandedAreaM2(area0, alpha, deltaT) {
|
|
73
|
+
return positive(area0, "An area") * (1 + finite(alpha, "The expansivity") * finite(deltaT, "A temperature change")) ** 2;
|
|
74
|
+
}
|
|
75
|
+
/** Volume after a temperature change, using the exact cube rather than 3α. */
|
|
76
|
+
function expandedVolumeM3(volume0, alpha, deltaT) {
|
|
77
|
+
return positive(volume0, "A volume") * (1 + finite(alpha, "The expansivity") * finite(deltaT, "A temperature change")) ** 3;
|
|
78
|
+
}
|
|
79
|
+
/** The area expansivity β = 2α, as the textbook approximation. */
|
|
80
|
+
const areaCoefficient = (alpha) => 2 * finite(alpha, "The expansivity");
|
|
81
|
+
/** The volume expansivity γ = 3α, as the textbook approximation. */
|
|
82
|
+
const volumeCoefficient = (alpha) => 3 * finite(alpha, "The expansivity");
|
|
83
|
+
/**
|
|
84
|
+
* Density after a temperature change, kg/m³: ρ = ρ₀/(1 + γΔθ).
|
|
85
|
+
*
|
|
86
|
+
* The mass does not change and the volume does, so the density falls. This is
|
|
87
|
+
* the engine behind convection: warmed fluid is less dense, so it rises, and
|
|
88
|
+
* the buoyancy that drives every convection current is this division.
|
|
89
|
+
*/
|
|
90
|
+
function densityAfterExpansionKgM3(density0, volumeExpansivity, deltaT) {
|
|
91
|
+
const factor = 1 + finite(volumeExpansivity, "The volume expansivity") * finite(deltaT, "A temperature change");
|
|
92
|
+
if (factor <= 0) throw new RangeError("That temperature change would shrink the material to nothing or less.");
|
|
93
|
+
return positive(density0, "A density") / factor;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The real expansivity of a liquid from the apparent one:
|
|
97
|
+
*
|
|
98
|
+
* γ_real = γ_apparent + γ_container
|
|
99
|
+
*
|
|
100
|
+
* Measuring a liquid's expansion means watching it rise in a vessel that is
|
|
101
|
+
* also expanding, so what you see is the DIFFERENCE. Forgetting the container's
|
|
102
|
+
* share is the standard error in this experiment, and it is systematic rather
|
|
103
|
+
* than random, so no amount of repetition finds it.
|
|
104
|
+
*/
|
|
105
|
+
function realExpansivity(apparent, containerVolumeExpansivity) {
|
|
106
|
+
return finite(apparent, "The apparent expansivity") + finite(containerVolumeExpansivity, "The container expansivity");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Thermal stress in a bar held rigidly while its temperature changes, Pa:
|
|
110
|
+
*
|
|
111
|
+
* σ = E·α·Δθ
|
|
112
|
+
*
|
|
113
|
+
* Note what is NOT in it: the length. A rail a kilometre long and a bolt a
|
|
114
|
+
* centimetre long, both clamped, reach the same stress for the same temperature
|
|
115
|
+
* rise, because the strain that would have been αΔθ is the same fraction
|
|
116
|
+
* either way. That is why expansion gaps are about the same size whatever the
|
|
117
|
+
* span, and why a long bridge needs more of them rather than bigger ones.
|
|
118
|
+
*/
|
|
119
|
+
function thermalStressPa(youngsModulus, alpha, deltaT) {
|
|
120
|
+
return positive(youngsModulus, "Young's modulus") * finite(alpha, "The expansivity") * finite(deltaT, "A temperature change");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* A bimetallic strip's bend, for two bonded strips of EQUAL thickness and
|
|
124
|
+
* equal Young's modulus:
|
|
125
|
+
*
|
|
126
|
+
* 1/ρ = 3·(α₂ − α₁)·Δθ / (2·t)
|
|
127
|
+
*
|
|
128
|
+
* with t the TOTAL thickness of the pair. The strip bends because the two
|
|
129
|
+
* metals want different lengths and are not allowed to have them, so it curves
|
|
130
|
+
* with the faster-expanding metal on the OUTSIDE of the curve.
|
|
131
|
+
*
|
|
132
|
+
* The sign follows through: a negative Δθ bends it the other way, which is what
|
|
133
|
+
* makes the strip a switch rather than merely a warning light.
|
|
134
|
+
*
|
|
135
|
+
* SCOPE: the equal-thickness, equal-modulus case of Timoshenko's result, which
|
|
136
|
+
* is how these strips are actually made and what every textbook quotes. A pair
|
|
137
|
+
* with different moduli bends less than this predicts.
|
|
138
|
+
*/
|
|
139
|
+
function bimetallicBend(totalThicknessM, alphaHigh, alphaLow, deltaT, lengthM) {
|
|
140
|
+
const t = positive(totalThicknessM, "The strip thickness");
|
|
141
|
+
const L = positive(lengthM, "The strip length");
|
|
142
|
+
const curvature = 3 * (finite(alphaHigh, "The higher expansivity") - finite(alphaLow, "The lower expansivity")) * finite(deltaT, "A temperature change") / (2 * t);
|
|
143
|
+
if (curvature === 0) return {
|
|
144
|
+
radiusM: Number.POSITIVE_INFINITY,
|
|
145
|
+
angleRad: 0,
|
|
146
|
+
deflectionM: 0
|
|
147
|
+
};
|
|
148
|
+
const radiusM = 1 / curvature;
|
|
149
|
+
const angleRad = L * curvature;
|
|
150
|
+
return {
|
|
151
|
+
radiusM,
|
|
152
|
+
angleRad,
|
|
153
|
+
deflectionM: radiusM * (1 - Math.cos(angleRad))
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The density of liquid water, kg/m³, between 0 °C and 100 °C.
|
|
158
|
+
*
|
|
159
|
+
* Water is the exception this whole file otherwise assumes away: its density
|
|
160
|
+
* PEAKS near 4 °C, so between 0 and 4 it contracts on warming and its expansion
|
|
161
|
+
* coefficient is negative. That anomaly is why ice floats, why a lake freezes
|
|
162
|
+
* from the top down, and why fish survive winter, so it is worth having as real
|
|
163
|
+
* data rather than as a note saying water is unusual.
|
|
164
|
+
*
|
|
165
|
+
* Uses the Thiesen-Scheel-Diesselhorst form, which fits measurement to about
|
|
166
|
+
* one part in 10⁵ across the range. A polynomial, not a physical model: it
|
|
167
|
+
* knows the shape of the curve and nothing about why.
|
|
168
|
+
*/
|
|
169
|
+
function waterDensityKgM3(celsius) {
|
|
170
|
+
const t = finite(celsius, "A temperature");
|
|
171
|
+
if (t < 0 || t > 100) throw new RangeError(`This fit covers liquid water from 0 to 100 °C, and ${t} °C is outside it.`);
|
|
172
|
+
return 999.97495 * (1 - (t + 288.9414) * (t - 3.9863) ** 2 / (508929.2 * (t + 68.12963)));
|
|
173
|
+
}
|
|
174
|
+
/** The temperature at which water is densest, °C: the anomaly's turning point. */
|
|
175
|
+
const WATER_DENSITY_PEAK_C = 3.9863;
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
export { LINEAR_EXPANSIVITY, WATER_DENSITY_PEAK_C, areaCoefficient, bimetallicBend, densityAfterExpansionKgM3, expandedAreaM2, expandedLengthM, expandedVolumeM3, lengthChangeM, realExpansivity, thermalStressPa, volumeCoefficient, waterDensityKgM3 };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
//#region src/thermo/gas.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The ideal gas and the kinetic theory behind it.
|
|
4
|
+
*
|
|
5
|
+
* THE MODEL, in one line each:
|
|
6
|
+
*
|
|
7
|
+
* equation of state pV = nRT = Nk_BT
|
|
8
|
+
* kinetic theory pV = ⅓·N·m·⟨c²⟩
|
|
9
|
+
*
|
|
10
|
+
* Setting those equal is the derivation the syllabus asks for, and it gives the
|
|
11
|
+
* whole of this file: ½m⟨c²⟩ = (3/2)k_BT says temperature IS mean translational
|
|
12
|
+
* kinetic energy, and everything about molecular speeds follows from it.
|
|
13
|
+
*
|
|
14
|
+
* WHY BOTH FORMS ARE HERE. `pV = nRT` is per MOLE and `pV = Nk_BT` is per
|
|
15
|
+
* MOLECULE, and mixing them up by a factor of N_A is the single most common
|
|
16
|
+
* arithmetic failure in this topic. Each function below states which it uses in
|
|
17
|
+
* its parameter names: `moles`/`molarMassKgPerMol` for the first,
|
|
18
|
+
* `molecules`/`particleMassKg` for the second.
|
|
19
|
+
*
|
|
20
|
+
* UNITS: strict SI. Pressure in pascals, volume in m³, temperature in KELVIN
|
|
21
|
+
* (never Celsius: these are ratios and proportionalities, so an offset scale
|
|
22
|
+
* gives nonsense rather than an error), molar mass in kg/mol (so oxygen is
|
|
23
|
+
* 0.032, not 32), speeds in m/s, energy in joules.
|
|
24
|
+
*
|
|
25
|
+
* SCOPE. The ideal gas, plus van der Waals as the first correction. No
|
|
26
|
+
* quantised internal modes, so the molar heat capacities here are the classical
|
|
27
|
+
* equipartition values and do not fall off at low temperature.
|
|
28
|
+
*/
|
|
29
|
+
/** Molar gas constant, J/(mol·K). The one value, re-exported under its physics name. */
|
|
30
|
+
declare const R: number;
|
|
31
|
+
/** Boltzmann constant, J/K: the gas constant per molecule rather than per mole. */
|
|
32
|
+
declare const k_B = 1.380649e-23;
|
|
33
|
+
/** Avogadro constant, per mole. */
|
|
34
|
+
declare const N_A = 6.02214076e+23;
|
|
35
|
+
interface GasStateSpec {
|
|
36
|
+
/** Pressure, Pa. */
|
|
37
|
+
pressurePa?: number;
|
|
38
|
+
/** Volume, m³. */
|
|
39
|
+
volumeM3?: number;
|
|
40
|
+
/** Amount, mol. */
|
|
41
|
+
moles?: number;
|
|
42
|
+
/** Temperature, K. */
|
|
43
|
+
temperatureK?: number;
|
|
44
|
+
}
|
|
45
|
+
interface SolvedGasState {
|
|
46
|
+
pressurePa: number;
|
|
47
|
+
volumeM3: number;
|
|
48
|
+
moles: number;
|
|
49
|
+
temperatureK: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Solve pV = nRT for whichever single variable is missing.
|
|
53
|
+
*
|
|
54
|
+
* One function rather than four, because the equation is one equation: a lab
|
|
55
|
+
* that lets a student pick which quantity to find should not need a switch
|
|
56
|
+
* statement, and a question that changes which variable is unknown should not
|
|
57
|
+
* need a different call.
|
|
58
|
+
*
|
|
59
|
+
* Throws unless exactly one of the four is absent, since zero missing is a
|
|
60
|
+
* consistency check rather than a solve, and two missing has no unique answer.
|
|
61
|
+
*/
|
|
62
|
+
declare function solveIdealGas(spec: GasStateSpec): SolvedGasState;
|
|
63
|
+
/**
|
|
64
|
+
* The combined gas law across a change of conditions: p₁V₁/T₁ = p₂V₂/T₂.
|
|
65
|
+
*
|
|
66
|
+
* Give the full initial state and the two known coordinates of the final one;
|
|
67
|
+
* the third comes back. This is the same physics as `solveIdealGas` with the
|
|
68
|
+
* amount held fixed, and it exists separately because the amount is what
|
|
69
|
+
* cancels: a question about a sealed container never mentions n, and forcing a
|
|
70
|
+
* caller to invent one would be asking them to supply a number the answer does
|
|
71
|
+
* not depend on.
|
|
72
|
+
*/
|
|
73
|
+
declare function combinedGasLaw(from: {
|
|
74
|
+
pressurePa: number;
|
|
75
|
+
volumeM3: number;
|
|
76
|
+
temperatureK: number;
|
|
77
|
+
}, to: {
|
|
78
|
+
pressurePa?: number;
|
|
79
|
+
volumeM3?: number;
|
|
80
|
+
temperatureK?: number;
|
|
81
|
+
}): {
|
|
82
|
+
pressurePa: number;
|
|
83
|
+
volumeM3: number;
|
|
84
|
+
temperatureK: number;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Pressure from the kinetic theory: p = N·m·⟨c²⟩ / 3V.
|
|
88
|
+
*
|
|
89
|
+
* The factor of three is the only interesting thing in it: molecules move in
|
|
90
|
+
* three dimensions and only the component along one axis pushes on that axis's
|
|
91
|
+
* wall, so ⟨c_x²⟩ = ⟨c²⟩/3.
|
|
92
|
+
*/
|
|
93
|
+
declare function kineticPressurePa(molecules: number, particleMassKg: number, meanSquareSpeed: number, volumeM3: number): number;
|
|
94
|
+
/** Mean square speed ⟨c²⟩ = 3RT/M, m²/s². */
|
|
95
|
+
declare function meanSquareSpeed(temperatureK: number, molarMassKgPerMol: number): number;
|
|
96
|
+
/**
|
|
97
|
+
* Root mean square speed, √(3RT/M), m/s.
|
|
98
|
+
*
|
|
99
|
+
* The speed that appears in the pressure, and the largest of the three
|
|
100
|
+
* averages below. It is larger than the plain mean because squaring weights the
|
|
101
|
+
* fast molecules more heavily, and that difference is not a rounding detail:
|
|
102
|
+
* evaporation and escape from the atmosphere both depend on the tail.
|
|
103
|
+
*/
|
|
104
|
+
declare function rmsSpeedMs(temperatureK: number, molarMassKgPerMol: number): number;
|
|
105
|
+
/** Mean (arithmetic average) speed, √(8RT/πM), m/s. */
|
|
106
|
+
declare function meanSpeedMs(temperatureK: number, molarMassKgPerMol: number): number;
|
|
107
|
+
/** Most probable speed, √(2RT/M), m/s: the peak of the distribution. */
|
|
108
|
+
declare function mostProbableSpeedMs(temperatureK: number, molarMassKgPerMol: number): number;
|
|
109
|
+
/**
|
|
110
|
+
* The root mean square of a list of individual speeds.
|
|
111
|
+
*
|
|
112
|
+
* For the question that hands you five molecules and asks for the rms rather
|
|
113
|
+
* than a temperature. Kept beside the theoretical version so the two can be
|
|
114
|
+
* compared, which is the point of asking.
|
|
115
|
+
*/
|
|
116
|
+
declare function rmsOf(speeds: readonly number[]): number;
|
|
117
|
+
/** Mean translational kinetic energy per molecule, (3/2)k_BT, J. */
|
|
118
|
+
declare function meanTranslationalEnergyJ(temperatureK: number): number;
|
|
119
|
+
/**
|
|
120
|
+
* The Maxwell-Boltzmann speed distribution, as a probability density in s/m:
|
|
121
|
+
*
|
|
122
|
+
* f(v) = 4π (M/2πRT)^{3/2} · v² · exp(−Mv²/2RT)
|
|
123
|
+
*
|
|
124
|
+
* Note it is a DENSITY, so f(v) alone is not a probability and only ∫f dv
|
|
125
|
+
* between two speeds is. The v² in front is why the curve starts at zero rather
|
|
126
|
+
* than at its maximum: there are very few ways to be slow in three dimensions,
|
|
127
|
+
* however favourable the exponential.
|
|
128
|
+
*/
|
|
129
|
+
declare function maxwellBoltzmannPdf(speedMs: number, temperatureK: number, molarMassKgPerMol: number): number;
|
|
130
|
+
/**
|
|
131
|
+
* Mean free path, m: λ = 1 / (√2 · π · d² · n).
|
|
132
|
+
*
|
|
133
|
+
* `numberDensity` is molecules per m³, `diameterM` the molecular diameter. The
|
|
134
|
+
* √2 is the correction for the other molecules moving too, which is the part
|
|
135
|
+
* that is usually dropped in a first derivation and then quietly restored.
|
|
136
|
+
*/
|
|
137
|
+
declare function meanFreePathM(diameterM: number, numberDensity: number): number;
|
|
138
|
+
interface MolarHeatCapacities {
|
|
139
|
+
/** At constant volume, J/(mol·K). */
|
|
140
|
+
cv: number;
|
|
141
|
+
/** At constant pressure, J/(mol·K). */
|
|
142
|
+
cp: number;
|
|
143
|
+
/** The ratio Cp/Cv. */
|
|
144
|
+
gamma: number;
|
|
145
|
+
/** Degrees of freedom implied by that ratio. */
|
|
146
|
+
degreesOfFreedom: number;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The molar heat capacities implied by a ratio γ, through Mayer's relation.
|
|
150
|
+
*
|
|
151
|
+
* Cp − Cv = R and γ = Cp/Cv ⟹ Cv = R/(γ−1), Cp = γR/(γ−1)
|
|
152
|
+
*
|
|
153
|
+
* Mayer's relation is not an extra assumption: heating at constant pressure has
|
|
154
|
+
* to pay for the expansion work as well as the internal energy, and for an
|
|
155
|
+
* ideal gas that work is exactly R per mole per kelvin. So the two capacities
|
|
156
|
+
* differ by R and by nothing else, and the ratio alone fixes both.
|
|
157
|
+
*/
|
|
158
|
+
declare function molarHeatCapacities(gamma: number): MolarHeatCapacities;
|
|
159
|
+
/**
|
|
160
|
+
* γ from the number of active degrees of freedom: γ = 1 + 2/f.
|
|
161
|
+
*
|
|
162
|
+
* Equipartition gives each degree of freedom ½k_BT, so f fixes Cv and therefore
|
|
163
|
+
* γ. Monatomic f = 3 (translation only) → 5/3; diatomic f = 5 (plus two
|
|
164
|
+
* rotations) → 7/5; a non-linear triatomic f = 6 → 4/3.
|
|
165
|
+
*/
|
|
166
|
+
declare function gammaFromDegreesOfFreedom(f: number): number;
|
|
167
|
+
/** γ = 5/3, a monatomic gas: three translational degrees of freedom and no more. */
|
|
168
|
+
declare const gammaMonatomic: number;
|
|
169
|
+
/** γ = 7/5, a diatomic gas: translation plus two rotations. */
|
|
170
|
+
declare const gammaDiatomic: number;
|
|
171
|
+
/** γ = 4/3, a non-linear polyatomic gas: translation plus three rotations. */
|
|
172
|
+
declare const gammaPolyatomic: number;
|
|
173
|
+
/**
|
|
174
|
+
* Internal energy of an ideal gas, J: U = n·Cv·T.
|
|
175
|
+
*
|
|
176
|
+
* Depends on temperature ALONE, with no volume term, and that is the defining
|
|
177
|
+
* property of an ideal gas rather than an approximation to one. There are no
|
|
178
|
+
* intermolecular forces, so pulling the molecules further apart costs nothing
|
|
179
|
+
* and the internal energy does not notice the volume changed.
|
|
180
|
+
*/
|
|
181
|
+
declare function internalEnergyJ(moles: number, temperatureK: number, gamma?: number): number;
|
|
182
|
+
/**
|
|
183
|
+
* Van der Waals pressure, Pa:
|
|
184
|
+
*
|
|
185
|
+
* p = nRT/(V − nb) − a·n²/V²
|
|
186
|
+
*
|
|
187
|
+
* The two corrections say the two things an ideal gas denies. `b` is the volume
|
|
188
|
+
* the molecules themselves occupy, so the space available to move in is less
|
|
189
|
+
* than V; `a` is the attraction between them, so a molecule about to strike the
|
|
190
|
+
* wall is pulled back by the ones behind it and the pressure is less than it
|
|
191
|
+
* would otherwise be.
|
|
192
|
+
*
|
|
193
|
+
* Units: `a` in Pa·m⁶/mol², `b` in m³/mol.
|
|
194
|
+
*/
|
|
195
|
+
declare function vanDerWaalsPressurePa(moles: number, volumeM3: number, temperatureK: number, a: number, b: number): number;
|
|
196
|
+
//#endregion
|
|
197
|
+
export { GasStateSpec, MolarHeatCapacities, N_A, R, SolvedGasState, combinedGasLaw, gammaDiatomic, gammaFromDegreesOfFreedom, gammaMonatomic, gammaPolyatomic, internalEnergyJ, k_B, kineticPressurePa, maxwellBoltzmannPdf, meanFreePathM, meanSpeedMs, meanSquareSpeed, meanTranslationalEnergyJ, molarHeatCapacities, mostProbableSpeedMs, rmsOf, rmsSpeedMs, solveIdealGas, vanDerWaalsPressurePa };
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { AVOGADRO, BOLTZMANN, GAS_CONSTANT } from "../core/constants.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/thermo/gas.ts
|
|
4
|
+
/**
|
|
5
|
+
* The ideal gas and the kinetic theory behind it.
|
|
6
|
+
*
|
|
7
|
+
* THE MODEL, in one line each:
|
|
8
|
+
*
|
|
9
|
+
* equation of state pV = nRT = Nk_BT
|
|
10
|
+
* kinetic theory pV = ⅓·N·m·⟨c²⟩
|
|
11
|
+
*
|
|
12
|
+
* Setting those equal is the derivation the syllabus asks for, and it gives the
|
|
13
|
+
* whole of this file: ½m⟨c²⟩ = (3/2)k_BT says temperature IS mean translational
|
|
14
|
+
* kinetic energy, and everything about molecular speeds follows from it.
|
|
15
|
+
*
|
|
16
|
+
* WHY BOTH FORMS ARE HERE. `pV = nRT` is per MOLE and `pV = Nk_BT` is per
|
|
17
|
+
* MOLECULE, and mixing them up by a factor of N_A is the single most common
|
|
18
|
+
* arithmetic failure in this topic. Each function below states which it uses in
|
|
19
|
+
* its parameter names: `moles`/`molarMassKgPerMol` for the first,
|
|
20
|
+
* `molecules`/`particleMassKg` for the second.
|
|
21
|
+
*
|
|
22
|
+
* UNITS: strict SI. Pressure in pascals, volume in m³, temperature in KELVIN
|
|
23
|
+
* (never Celsius: these are ratios and proportionalities, so an offset scale
|
|
24
|
+
* gives nonsense rather than an error), molar mass in kg/mol (so oxygen is
|
|
25
|
+
* 0.032, not 32), speeds in m/s, energy in joules.
|
|
26
|
+
*
|
|
27
|
+
* SCOPE. The ideal gas, plus van der Waals as the first correction. No
|
|
28
|
+
* quantised internal modes, so the molar heat capacities here are the classical
|
|
29
|
+
* equipartition values and do not fall off at low temperature.
|
|
30
|
+
*/
|
|
31
|
+
/** Molar gas constant, J/(mol·K). The one value, re-exported under its physics name. */
|
|
32
|
+
const R = GAS_CONSTANT;
|
|
33
|
+
/** Boltzmann constant, J/K: the gas constant per molecule rather than per mole. */
|
|
34
|
+
const k_B = BOLTZMANN;
|
|
35
|
+
/** Avogadro constant, per mole. */
|
|
36
|
+
const N_A = AVOGADRO;
|
|
37
|
+
const finite = (value, what) => {
|
|
38
|
+
if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
|
|
39
|
+
return value;
|
|
40
|
+
};
|
|
41
|
+
const positive = (value, what) => {
|
|
42
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
43
|
+
return value;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Guard for a thermodynamic temperature.
|
|
47
|
+
*
|
|
48
|
+
* Separate from `positive` so the message can say the useful thing. A caller
|
|
49
|
+
* who passes 25 meaning room temperature gets a plausible wrong answer, but a
|
|
50
|
+
* caller who passes −10 meaning a cold day gets told what the problem is.
|
|
51
|
+
*/
|
|
52
|
+
const kelvin = (value) => {
|
|
53
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`Temperature must be a positive number of kelvin (got ${value}). Celsius readings need converting first.`);
|
|
54
|
+
return value;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Solve pV = nRT for whichever single variable is missing.
|
|
58
|
+
*
|
|
59
|
+
* One function rather than four, because the equation is one equation: a lab
|
|
60
|
+
* that lets a student pick which quantity to find should not need a switch
|
|
61
|
+
* statement, and a question that changes which variable is unknown should not
|
|
62
|
+
* need a different call.
|
|
63
|
+
*
|
|
64
|
+
* Throws unless exactly one of the four is absent, since zero missing is a
|
|
65
|
+
* consistency check rather than a solve, and two missing has no unique answer.
|
|
66
|
+
*/
|
|
67
|
+
function solveIdealGas(spec) {
|
|
68
|
+
const { pressurePa: p, volumeM3: V, moles: n, temperatureK: T } = spec;
|
|
69
|
+
const given = [
|
|
70
|
+
p,
|
|
71
|
+
V,
|
|
72
|
+
n,
|
|
73
|
+
T
|
|
74
|
+
].filter((x) => x !== void 0);
|
|
75
|
+
if (given.length !== 3) throw new RangeError(`pV = nRT determines one unknown from three knowns, but ${given.length} of the four were given.`);
|
|
76
|
+
if (p === void 0) return {
|
|
77
|
+
pressurePa: positive(n, "Amount") * R * kelvin(T) / positive(V, "Volume"),
|
|
78
|
+
volumeM3: V,
|
|
79
|
+
moles: n,
|
|
80
|
+
temperatureK: T
|
|
81
|
+
};
|
|
82
|
+
if (V === void 0) return {
|
|
83
|
+
pressurePa: p,
|
|
84
|
+
volumeM3: positive(n, "Amount") * R * kelvin(T) / positive(p, "Pressure"),
|
|
85
|
+
moles: n,
|
|
86
|
+
temperatureK: T
|
|
87
|
+
};
|
|
88
|
+
if (n === void 0) return {
|
|
89
|
+
pressurePa: p,
|
|
90
|
+
volumeM3: V,
|
|
91
|
+
moles: positive(p, "Pressure") * positive(V, "Volume") / (R * kelvin(T)),
|
|
92
|
+
temperatureK: T
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
pressurePa: p,
|
|
96
|
+
volumeM3: V,
|
|
97
|
+
moles: n,
|
|
98
|
+
temperatureK: positive(p, "Pressure") * positive(V, "Volume") / (positive(n, "Amount") * R)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The combined gas law across a change of conditions: p₁V₁/T₁ = p₂V₂/T₂.
|
|
103
|
+
*
|
|
104
|
+
* Give the full initial state and the two known coordinates of the final one;
|
|
105
|
+
* the third comes back. This is the same physics as `solveIdealGas` with the
|
|
106
|
+
* amount held fixed, and it exists separately because the amount is what
|
|
107
|
+
* cancels: a question about a sealed container never mentions n, and forcing a
|
|
108
|
+
* caller to invent one would be asking them to supply a number the answer does
|
|
109
|
+
* not depend on.
|
|
110
|
+
*/
|
|
111
|
+
function combinedGasLaw(from, to) {
|
|
112
|
+
const ratio = positive(from.pressurePa, "Initial pressure") * positive(from.volumeM3, "Initial volume") / kelvin(from.temperatureK);
|
|
113
|
+
const given = [
|
|
114
|
+
to.pressurePa,
|
|
115
|
+
to.volumeM3,
|
|
116
|
+
to.temperatureK
|
|
117
|
+
].filter((x) => x !== void 0);
|
|
118
|
+
if (given.length !== 2) throw new RangeError(`The final state needs exactly two of its three coordinates, but ${given.length} were given.`);
|
|
119
|
+
if (to.pressurePa === void 0) return {
|
|
120
|
+
pressurePa: ratio * kelvin(to.temperatureK) / positive(to.volumeM3, "Final volume"),
|
|
121
|
+
volumeM3: to.volumeM3,
|
|
122
|
+
temperatureK: to.temperatureK
|
|
123
|
+
};
|
|
124
|
+
if (to.volumeM3 === void 0) return {
|
|
125
|
+
pressurePa: to.pressurePa,
|
|
126
|
+
volumeM3: ratio * kelvin(to.temperatureK) / positive(to.pressurePa, "Final pressure"),
|
|
127
|
+
temperatureK: to.temperatureK
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
pressurePa: to.pressurePa,
|
|
131
|
+
volumeM3: to.volumeM3,
|
|
132
|
+
temperatureK: positive(to.pressurePa, "Final pressure") * positive(to.volumeM3, "Final volume") / ratio
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Pressure from the kinetic theory: p = N·m·⟨c²⟩ / 3V.
|
|
137
|
+
*
|
|
138
|
+
* The factor of three is the only interesting thing in it: molecules move in
|
|
139
|
+
* three dimensions and only the component along one axis pushes on that axis's
|
|
140
|
+
* wall, so ⟨c_x²⟩ = ⟨c²⟩/3.
|
|
141
|
+
*/
|
|
142
|
+
function kineticPressurePa(molecules, particleMassKg, meanSquareSpeed, volumeM3) {
|
|
143
|
+
return positive(molecules, "The number of molecules") * positive(particleMassKg, "Particle mass") * positive(meanSquareSpeed, "Mean square speed") / (3 * positive(volumeM3, "Volume"));
|
|
144
|
+
}
|
|
145
|
+
/** Mean square speed ⟨c²⟩ = 3RT/M, m²/s². */
|
|
146
|
+
function meanSquareSpeed(temperatureK, molarMassKgPerMol) {
|
|
147
|
+
return 3 * R * kelvin(temperatureK) / positive(molarMassKgPerMol, "Molar mass");
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Root mean square speed, √(3RT/M), m/s.
|
|
151
|
+
*
|
|
152
|
+
* The speed that appears in the pressure, and the largest of the three
|
|
153
|
+
* averages below. It is larger than the plain mean because squaring weights the
|
|
154
|
+
* fast molecules more heavily, and that difference is not a rounding detail:
|
|
155
|
+
* evaporation and escape from the atmosphere both depend on the tail.
|
|
156
|
+
*/
|
|
157
|
+
function rmsSpeedMs(temperatureK, molarMassKgPerMol) {
|
|
158
|
+
return Math.sqrt(meanSquareSpeed(temperatureK, molarMassKgPerMol));
|
|
159
|
+
}
|
|
160
|
+
/** Mean (arithmetic average) speed, √(8RT/πM), m/s. */
|
|
161
|
+
function meanSpeedMs(temperatureK, molarMassKgPerMol) {
|
|
162
|
+
return Math.sqrt(8 * R * kelvin(temperatureK) / (Math.PI * positive(molarMassKgPerMol, "Molar mass")));
|
|
163
|
+
}
|
|
164
|
+
/** Most probable speed, √(2RT/M), m/s: the peak of the distribution. */
|
|
165
|
+
function mostProbableSpeedMs(temperatureK, molarMassKgPerMol) {
|
|
166
|
+
return Math.sqrt(2 * R * kelvin(temperatureK) / positive(molarMassKgPerMol, "Molar mass"));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The root mean square of a list of individual speeds.
|
|
170
|
+
*
|
|
171
|
+
* For the question that hands you five molecules and asks for the rms rather
|
|
172
|
+
* than a temperature. Kept beside the theoretical version so the two can be
|
|
173
|
+
* compared, which is the point of asking.
|
|
174
|
+
*/
|
|
175
|
+
function rmsOf(speeds) {
|
|
176
|
+
if (speeds.length === 0) throw new RangeError("No speeds to average.");
|
|
177
|
+
return Math.sqrt(speeds.reduce((sum, v) => sum + finite(v, "A speed") ** 2, 0) / speeds.length);
|
|
178
|
+
}
|
|
179
|
+
/** Mean translational kinetic energy per molecule, (3/2)k_BT, J. */
|
|
180
|
+
function meanTranslationalEnergyJ(temperatureK) {
|
|
181
|
+
return 1.5 * k_B * kelvin(temperatureK);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The Maxwell-Boltzmann speed distribution, as a probability density in s/m:
|
|
185
|
+
*
|
|
186
|
+
* f(v) = 4π (M/2πRT)^{3/2} · v² · exp(−Mv²/2RT)
|
|
187
|
+
*
|
|
188
|
+
* Note it is a DENSITY, so f(v) alone is not a probability and only ∫f dv
|
|
189
|
+
* between two speeds is. The v² in front is why the curve starts at zero rather
|
|
190
|
+
* than at its maximum: there are very few ways to be slow in three dimensions,
|
|
191
|
+
* however favourable the exponential.
|
|
192
|
+
*/
|
|
193
|
+
function maxwellBoltzmannPdf(speedMs, temperatureK, molarMassKgPerMol) {
|
|
194
|
+
const v = finite(speedMs, "Speed");
|
|
195
|
+
if (v < 0) throw new RangeError("A speed cannot be negative.");
|
|
196
|
+
const M = positive(molarMassKgPerMol, "Molar mass");
|
|
197
|
+
const T = kelvin(temperatureK);
|
|
198
|
+
const a = M / (2 * Math.PI * R * T);
|
|
199
|
+
return 4 * Math.PI * a ** 1.5 * v * v * Math.exp(-M * v * v / (2 * R * T));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Mean free path, m: λ = 1 / (√2 · π · d² · n).
|
|
203
|
+
*
|
|
204
|
+
* `numberDensity` is molecules per m³, `diameterM` the molecular diameter. The
|
|
205
|
+
* √2 is the correction for the other molecules moving too, which is the part
|
|
206
|
+
* that is usually dropped in a first derivation and then quietly restored.
|
|
207
|
+
*/
|
|
208
|
+
function meanFreePathM(diameterM, numberDensity) {
|
|
209
|
+
return 1 / (Math.SQRT2 * Math.PI * positive(diameterM, "Molecular diameter") ** 2 * positive(numberDensity, "Number density"));
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The molar heat capacities implied by a ratio γ, through Mayer's relation.
|
|
213
|
+
*
|
|
214
|
+
* Cp − Cv = R and γ = Cp/Cv ⟹ Cv = R/(γ−1), Cp = γR/(γ−1)
|
|
215
|
+
*
|
|
216
|
+
* Mayer's relation is not an extra assumption: heating at constant pressure has
|
|
217
|
+
* to pay for the expansion work as well as the internal energy, and for an
|
|
218
|
+
* ideal gas that work is exactly R per mole per kelvin. So the two capacities
|
|
219
|
+
* differ by R and by nothing else, and the ratio alone fixes both.
|
|
220
|
+
*/
|
|
221
|
+
function molarHeatCapacities(gamma) {
|
|
222
|
+
if (!(gamma > 1)) throw new RangeError(`γ must exceed 1 (got ${gamma}). Cp always exceeds Cv, because heating at constant pressure also pays for the expansion.`);
|
|
223
|
+
return {
|
|
224
|
+
cv: R / (gamma - 1),
|
|
225
|
+
cp: gamma * R / (gamma - 1),
|
|
226
|
+
gamma,
|
|
227
|
+
degreesOfFreedom: 2 / (gamma - 1)
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* γ from the number of active degrees of freedom: γ = 1 + 2/f.
|
|
232
|
+
*
|
|
233
|
+
* Equipartition gives each degree of freedom ½k_BT, so f fixes Cv and therefore
|
|
234
|
+
* γ. Monatomic f = 3 (translation only) → 5/3; diatomic f = 5 (plus two
|
|
235
|
+
* rotations) → 7/5; a non-linear triatomic f = 6 → 4/3.
|
|
236
|
+
*/
|
|
237
|
+
function gammaFromDegreesOfFreedom(f) {
|
|
238
|
+
return 1 + 2 / positive(f, "The number of degrees of freedom");
|
|
239
|
+
}
|
|
240
|
+
/** γ = 5/3, a monatomic gas: three translational degrees of freedom and no more. */
|
|
241
|
+
const gammaMonatomic = 5 / 3;
|
|
242
|
+
/** γ = 7/5, a diatomic gas: translation plus two rotations. */
|
|
243
|
+
const gammaDiatomic = 7 / 5;
|
|
244
|
+
/** γ = 4/3, a non-linear polyatomic gas: translation plus three rotations. */
|
|
245
|
+
const gammaPolyatomic = 4 / 3;
|
|
246
|
+
/**
|
|
247
|
+
* Internal energy of an ideal gas, J: U = n·Cv·T.
|
|
248
|
+
*
|
|
249
|
+
* Depends on temperature ALONE, with no volume term, and that is the defining
|
|
250
|
+
* property of an ideal gas rather than an approximation to one. There are no
|
|
251
|
+
* intermolecular forces, so pulling the molecules further apart costs nothing
|
|
252
|
+
* and the internal energy does not notice the volume changed.
|
|
253
|
+
*/
|
|
254
|
+
function internalEnergyJ(moles, temperatureK, gamma = gammaMonatomic) {
|
|
255
|
+
return positive(moles, "Amount") * molarHeatCapacities(gamma).cv * kelvin(temperatureK);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Van der Waals pressure, Pa:
|
|
259
|
+
*
|
|
260
|
+
* p = nRT/(V − nb) − a·n²/V²
|
|
261
|
+
*
|
|
262
|
+
* The two corrections say the two things an ideal gas denies. `b` is the volume
|
|
263
|
+
* the molecules themselves occupy, so the space available to move in is less
|
|
264
|
+
* than V; `a` is the attraction between them, so a molecule about to strike the
|
|
265
|
+
* wall is pulled back by the ones behind it and the pressure is less than it
|
|
266
|
+
* would otherwise be.
|
|
267
|
+
*
|
|
268
|
+
* Units: `a` in Pa·m⁶/mol², `b` in m³/mol.
|
|
269
|
+
*/
|
|
270
|
+
function vanDerWaalsPressurePa(moles, volumeM3, temperatureK, a, b) {
|
|
271
|
+
const n = positive(moles, "Amount");
|
|
272
|
+
const V = positive(volumeM3, "Volume");
|
|
273
|
+
const free = V - n * finite(b, "The excluded volume b");
|
|
274
|
+
if (free <= 0) throw new RangeError("The gas is compressed past the volume of its own molecules, where van der Waals no longer applies.");
|
|
275
|
+
return n * R * kelvin(temperatureK) / free - finite(a, "The attraction term a") * n * n / (V * V);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
//#endregion
|
|
279
|
+
export { N_A, R, combinedGasLaw, gammaDiatomic, gammaFromDegreesOfFreedom, gammaMonatomic, gammaPolyatomic, internalEnergyJ, k_B, kineticPressurePa, maxwellBoltzmannPdf, meanFreePathM, meanSpeedMs, meanSquareSpeed, meanTranslationalEnergyJ, molarHeatCapacities, mostProbableSpeedMs, rmsOf, rmsSpeedMs, solveIdealGas, vanDerWaalsPressurePa };
|