@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,259 @@
|
|
|
1
|
+
import { pathFromPhase, phaseFromPath } from "../waves/wave.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/optics/wave-optics.ts
|
|
4
|
+
/**
|
|
5
|
+
* Wave optics: interference, diffraction and polarisation.
|
|
6
|
+
*
|
|
7
|
+
* THE MODEL. Everything here follows from two statements. Waves superpose by
|
|
8
|
+
* adding their displacements, and a path difference of one wavelength is a
|
|
9
|
+
* phase difference of 2π:
|
|
10
|
+
*
|
|
11
|
+
* φ = (2π/λ) · path difference
|
|
12
|
+
*
|
|
13
|
+
* Constructive where the path difference is a whole number of wavelengths,
|
|
14
|
+
* destructive where it is a half-odd number. Young's slits, a single slit's
|
|
15
|
+
* envelope and a grating are the same statement applied to two sources, to a
|
|
16
|
+
* continuum of sources across one opening, and to many evenly spaced ones.
|
|
17
|
+
*
|
|
18
|
+
* THE SIGN THAT CATCHES EVERYONE. For a DOUBLE slit, `a sin θ = nλ` is a
|
|
19
|
+
* BRIGHT fringe. For a SINGLE slit, `a sin θ = nλ` is a DARK one. Same-looking
|
|
20
|
+
* equation, opposite meaning, because in the first `a` separates two sources
|
|
21
|
+
* and in the second it spans one. The functions below are named for what they
|
|
22
|
+
* return (`...Bright...`, `...Minimum...`) rather than for the equation, so the
|
|
23
|
+
* two can never be confused at a call site.
|
|
24
|
+
*
|
|
25
|
+
* UNITS: SI. Wavelengths, slit separations and screen distances in METRES, so a
|
|
26
|
+
* 589 nm line is `589e-9`. Angles come back in degrees to match the geometric
|
|
27
|
+
* side of this package; positions come back in metres.
|
|
28
|
+
*
|
|
29
|
+
* SCOPE. Far-field (Fraunhofer) only. The small-angle fringe spacing assumes
|
|
30
|
+
* the screen is far compared with the slit separation, which every laboratory
|
|
31
|
+
* arrangement satisfies by a factor of thousands; `fringeAngleDeg` is exact and
|
|
32
|
+
* does not assume it.
|
|
33
|
+
*/
|
|
34
|
+
const DEG = Math.PI / 180;
|
|
35
|
+
const toDeg = (r) => r / DEG;
|
|
36
|
+
const positive = (value, what) => {
|
|
37
|
+
if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
|
|
38
|
+
return value;
|
|
39
|
+
};
|
|
40
|
+
const order = (value, what = "An order") => {
|
|
41
|
+
if (!Number.isInteger(value)) throw new RangeError(`${what} must be a whole number (got ${value}).`);
|
|
42
|
+
return value;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Fringe spacing in Young's experiment: w = λD/a.
|
|
46
|
+
*
|
|
47
|
+
* The workhorse, and the reason the experiment is the classic measurement of a
|
|
48
|
+
* wavelength: every quantity on the right is measurable with a ruler, and the
|
|
49
|
+
* left is a few tenths of a millimetre magnified into something you can count.
|
|
50
|
+
*
|
|
51
|
+
* The slit separation `a` is in the DENOMINATOR, which is the counter-intuitive
|
|
52
|
+
* part: pushing the slits closer together spreads the fringes apart.
|
|
53
|
+
*/
|
|
54
|
+
function fringeSpacing(wavelength, screenDistance, slitSeparation) {
|
|
55
|
+
return positive(wavelength, "A wavelength") * positive(screenDistance, "The screen distance") / positive(slitSeparation, "The slit separation");
|
|
56
|
+
}
|
|
57
|
+
/** Wavelength from a measured fringe spacing, the inverse of `fringeSpacing`. */
|
|
58
|
+
function wavelengthFromFringes(fringeWidth, screenDistance, slitSeparation) {
|
|
59
|
+
return positive(fringeWidth, "A fringe width") * positive(slitSeparation, "The slit separation") / positive(screenDistance, "The screen distance");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Distance from the centre of the pattern to the nth BRIGHT fringe, metres.
|
|
63
|
+
*
|
|
64
|
+
* `n = 0` is the central maximum, which sits at zero path difference and is
|
|
65
|
+
* therefore in the same place for every wavelength. That is why the centre of a
|
|
66
|
+
* white-light interference pattern is white and everything either side is
|
|
67
|
+
* coloured.
|
|
68
|
+
*/
|
|
69
|
+
function brightFringePosition(n, wavelength, screenDistance, slitSeparation) {
|
|
70
|
+
return order(n, "A fringe order") * fringeSpacing(wavelength, screenDistance, slitSeparation);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Distance to the nth DARK fringe, metres, with `n = 0` the first one out from
|
|
74
|
+
* the centre.
|
|
75
|
+
*
|
|
76
|
+
* Half a fringe width further out than the bright one of the same index, which
|
|
77
|
+
* is the (n + ½) in the textbook formula written where it cannot be misread as
|
|
78
|
+
* (2n+1)/2 applied to the wrong thing.
|
|
79
|
+
*/
|
|
80
|
+
function darkFringePosition(n, wavelength, screenDistance, slitSeparation) {
|
|
81
|
+
return (order(n, "A fringe order") + .5) * fringeSpacing(wavelength, screenDistance, slitSeparation);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The exact angle to the nth bright fringe, degrees, from a sin θ = nλ.
|
|
85
|
+
*
|
|
86
|
+
* No small-angle assumption, so it stays right where `fringeSpacing` starts to
|
|
87
|
+
* drift. Returns `null` when the order does not exist, which happens once
|
|
88
|
+
* nλ exceeds the slit separation.
|
|
89
|
+
*/
|
|
90
|
+
function fringeAngleDeg(n, wavelength, slitSeparation) {
|
|
91
|
+
const s = order(n, "A fringe order") * positive(wavelength, "A wavelength") / positive(slitSeparation, "The slit separation");
|
|
92
|
+
return Math.abs(s) > 1 ? null : toDeg(Math.asin(s));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Relative intensity of a two-slit pattern at a phase difference φ:
|
|
96
|
+
* I = I₀·cos²(φ/2).
|
|
97
|
+
*
|
|
98
|
+
* Note the pattern's peaks are FOUR times one slit's intensity, not twice, and
|
|
99
|
+
* the average is twice. Energy is conserved by redistribution, not by creation:
|
|
100
|
+
* the light missing from the dark fringes is exactly the excess in the bright
|
|
101
|
+
* ones.
|
|
102
|
+
*/
|
|
103
|
+
const twoSlitIntensity = (peakIntensity, phase) => peakIntensity * Math.cos(phase / 2) ** 2;
|
|
104
|
+
/**
|
|
105
|
+
* The single-slit ENVELOPE at an angle, normalised to 1 straight ahead:
|
|
106
|
+
*
|
|
107
|
+
* I/I₀ = (sin α / α)² with α = πa·sinθ/λ
|
|
108
|
+
*
|
|
109
|
+
* The shape every diffraction pattern sits inside. `α = 0` is 0/0 and the limit
|
|
110
|
+
* is 1, handled explicitly rather than left to produce NaN on the axis, which
|
|
111
|
+
* is the one point every plot draws.
|
|
112
|
+
*
|
|
113
|
+
* Note the contrast with the two-slit fringe term: the same algebra
|
|
114
|
+
* `a sinθ = nλ` gives a MINIMUM here and a MAXIMUM there. Confusing the two is
|
|
115
|
+
* the commonest error in the topic.
|
|
116
|
+
*/
|
|
117
|
+
function singleSlitEnvelope(thetaDeg, wavelength, slitWidth) {
|
|
118
|
+
const alpha = Math.PI * positive(slitWidth, "A slit width") * Math.sin(thetaDeg * DEG) / positive(wavelength, "A wavelength");
|
|
119
|
+
return alpha === 0 ? 1 : (Math.sin(alpha) / alpha) ** 2;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The full two-slit pattern at an angle, normalised to 1 straight ahead:
|
|
123
|
+
* the envelope times the fringes.
|
|
124
|
+
*
|
|
125
|
+
* Two independent effects multiplied, and that product is the insight the
|
|
126
|
+
* pattern exists to deliver. The slit WIDTH sets the broad envelope, which
|
|
127
|
+
* decides how bright each fringe is; the slit SEPARATION sets the fine fringes
|
|
128
|
+
* inside it. Students routinely attribute both to one number, and a lab that
|
|
129
|
+
* draws only the fringe term cannot show them otherwise.
|
|
130
|
+
*
|
|
131
|
+
* `interfere: false` drops the fringe term and leaves the envelope, which is
|
|
132
|
+
* what covering one slit looks like, and what a which-path measurement does to
|
|
133
|
+
* the quantum version.
|
|
134
|
+
*/
|
|
135
|
+
function doubleSlitPattern(thetaDeg, wavelength, slitSeparation, slitWidth, options = {}) {
|
|
136
|
+
const envelope = singleSlitEnvelope(thetaDeg, wavelength, slitWidth);
|
|
137
|
+
if (options.interfere === false) return envelope;
|
|
138
|
+
const beta = Math.PI * positive(slitSeparation, "A slit separation") * Math.sin(thetaDeg * DEG) / positive(wavelength, "A wavelength");
|
|
139
|
+
return envelope * Math.cos(beta) ** 2;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Angle to the nth diffraction MINIMUM of a single slit, degrees: a sin θ = nλ.
|
|
143
|
+
*
|
|
144
|
+
* `n` starts at 1; there is no n = 0 minimum, because straight ahead every
|
|
145
|
+
* contribution across the slit arrives in phase and that is the central
|
|
146
|
+
* maximum. Returns `null` when the order does not exist.
|
|
147
|
+
*/
|
|
148
|
+
function singleSlitMinimumDeg(n, wavelength, slitWidth) {
|
|
149
|
+
const k = order(n, "A minimum order");
|
|
150
|
+
if (k === 0) throw new RangeError("There is no zeroth minimum: straight ahead is the central MAXIMUM.");
|
|
151
|
+
const s = k * positive(wavelength, "A wavelength") / positive(slitWidth, "The slit width");
|
|
152
|
+
return Math.abs(s) > 1 ? null : toDeg(Math.asin(s));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Angular half-width of the central diffraction maximum, degrees.
|
|
156
|
+
*
|
|
157
|
+
* The central bright band is TWICE this wide, and twice as wide as every other
|
|
158
|
+
* band, which is the single most recognisable feature of a diffraction pattern.
|
|
159
|
+
*/
|
|
160
|
+
function centralMaximumHalfWidthDeg(wavelength, slitWidth) {
|
|
161
|
+
return singleSlitMinimumDeg(1, wavelength, slitWidth);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Width of the central maximum on a screen, metres, in the small-angle limit:
|
|
165
|
+
* 2λD/a.
|
|
166
|
+
*
|
|
167
|
+
* Narrowing the slit WIDENS the patch. Push it to a slit comparable with the
|
|
168
|
+
* wavelength and the light spreads through most of a hemisphere, which is the
|
|
169
|
+
* observation that rules out light being a stream of particles travelling in
|
|
170
|
+
* straight lines.
|
|
171
|
+
*/
|
|
172
|
+
function centralMaximumWidth(wavelength, screenDistance, slitWidth) {
|
|
173
|
+
return 2 * positive(wavelength, "A wavelength") * positive(screenDistance, "The screen distance") / positive(slitWidth, "The slit width");
|
|
174
|
+
}
|
|
175
|
+
/** Slit spacing from a ruling density: d = 1/N, with N lines per metre. */
|
|
176
|
+
const gratingSpacing = (linesPerMetre) => 1 / positive(linesPerMetre, "The ruling density");
|
|
177
|
+
/**
|
|
178
|
+
* Angle of the nth order from a grating, degrees: d sin θ = nλ.
|
|
179
|
+
*
|
|
180
|
+
* Returns `null` when that order does not exist, rather than NaN, because
|
|
181
|
+
* "which orders can I see" is the question and a missing order is an answer to
|
|
182
|
+
* it.
|
|
183
|
+
*/
|
|
184
|
+
function gratingAngleDeg(n, wavelength, spacing) {
|
|
185
|
+
const s = order(n, "A grating order") * positive(wavelength, "A wavelength") / positive(spacing, "The grating spacing");
|
|
186
|
+
return Math.abs(s) > 1 ? null : toDeg(Math.asin(s));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The highest order a grating can show: floor(d/λ).
|
|
190
|
+
*
|
|
191
|
+
* Because sin θ cannot exceed 1. A subtlety worth the comment: the order at
|
|
192
|
+
* exactly d/λ would sit at 90 degrees, grazing along the grating and carrying
|
|
193
|
+
* no light, so when d/λ is a whole number the highest OBSERVABLE order is one
|
|
194
|
+
* less. That edge is handled rather than rounded past.
|
|
195
|
+
*/
|
|
196
|
+
function maximumGratingOrder(wavelength, spacing) {
|
|
197
|
+
const ratio = positive(spacing, "The grating spacing") / positive(wavelength, "A wavelength");
|
|
198
|
+
const floor = Math.floor(ratio);
|
|
199
|
+
return floor === ratio ? floor - 1 : floor;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Wavelength from a grating measurement: λ = d sin θ / n.
|
|
203
|
+
*
|
|
204
|
+
* The grating's advantage over two slits is that many slits make each maximum
|
|
205
|
+
* very sharp, so the angle can be read precisely, which is why spectrometers
|
|
206
|
+
* use gratings rather than double slits.
|
|
207
|
+
*/
|
|
208
|
+
function wavelengthFromGrating(n, angleDeg, spacing) {
|
|
209
|
+
const k = order(n, "A grating order");
|
|
210
|
+
if (k === 0) throw new RangeError("The zeroth order is undeviated for every wavelength, so it measures none of them.");
|
|
211
|
+
return positive(spacing, "The grating spacing") * Math.sin(angleDeg * DEG) / k;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Malus's law: I = I₀·cos²θ, with θ between the analyser and the polarisation.
|
|
215
|
+
*
|
|
216
|
+
* Crossed polarisers pass nothing, and a third one inserted between them at 45
|
|
217
|
+
* degrees lets light through again, which is impossible to explain if
|
|
218
|
+
* polarisers are filters that merely remove things. They do not filter, they
|
|
219
|
+
* PROJECT, and cos² is the projection.
|
|
220
|
+
*/
|
|
221
|
+
function malusIntensity(incidentIntensity, analyserAngleDeg) {
|
|
222
|
+
if (!Number.isFinite(incidentIntensity) || incidentIntensity < 0) throw new RangeError("An intensity cannot be negative.");
|
|
223
|
+
return incidentIntensity * Math.cos(analyserAngleDeg * DEG) ** 2;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Intensity after unpolarised light passes one ideal polariser: exactly half.
|
|
227
|
+
*
|
|
228
|
+
* Half rather than cos² of anything, because unpolarised light carries every
|
|
229
|
+
* orientation equally and the average of cos² over all angles is a half. The
|
|
230
|
+
* first polariser is the one that loses half; the second loses by Malus.
|
|
231
|
+
*/
|
|
232
|
+
const unpolarisedThroughPolariser = (intensity) => {
|
|
233
|
+
if (!Number.isFinite(intensity) || intensity < 0) throw new RangeError("An intensity cannot be negative.");
|
|
234
|
+
return intensity / 2;
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Intensity at a distance from a point source: I = P/(4πr²).
|
|
238
|
+
*
|
|
239
|
+
* The inverse square is geometry, not a property of light: the same power
|
|
240
|
+
* spread over a sphere whose area grows as r².
|
|
241
|
+
*/
|
|
242
|
+
function pointSourceIntensity(power, distance) {
|
|
243
|
+
return positive(power, "A power") / (4 * Math.PI * positive(distance, "A distance") ** 2);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The Rayleigh criterion, radians: θ = 1.22·λ/D.
|
|
247
|
+
*
|
|
248
|
+
* Two point sources are just resolved when the first's diffraction maximum
|
|
249
|
+
* falls on the other's first minimum. The 1.22 is the first zero of a Bessel
|
|
250
|
+
* function, and it is there because the aperture is a CIRCLE; a slit gives
|
|
251
|
+
* exactly 1. This is the hard limit on every telescope and microscope, and the
|
|
252
|
+
* reason bigger mirrors see finer detail quite apart from gathering more light.
|
|
253
|
+
*/
|
|
254
|
+
function rayleighResolutionRad(wavelength, aperture) {
|
|
255
|
+
return 1.22 * positive(wavelength, "A wavelength") / positive(aperture, "An aperture diameter");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
//#endregion
|
|
259
|
+
export { brightFringePosition, centralMaximumHalfWidthDeg, centralMaximumWidth, darkFringePosition, doubleSlitPattern, fringeAngleDeg, fringeSpacing, gratingAngleDeg, gratingSpacing, malusIntensity, maximumGratingOrder, pointSourceIntensity, rayleighResolutionRad, singleSlitEnvelope, singleSlitMinimumDeg, twoSlitIntensity, unpolarisedThroughPolariser, wavelengthFromFringes, wavelengthFromGrating };
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
declare namespace ac_d_exports {
|
|
2
|
+
export { AcState, AcSupply, RectifiedInput, RectifiedPoint, RectifiedTrace, RectifierMode, WavePoint, acCurrentAt, acPeriodS, acRectifiedTrace, acState, acVoltageAt, acWaveTrace, formFactor, integrateSquareOverPeriod, meanAcPowerW, meanOverHalfCycle, meanRectifiedVoltage, meanSquareByIntegration, meanSquareFromPeak, peakFactor, rectify, rippleFrequencyHz, rmsFromPeak };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* @classytic/stage/circuit/ac-waveform — Alternating currents (Cambridge International A Level Physics 9702, chapter 21).
|
|
6
|
+
*
|
|
7
|
+
* A sinusoidal supply v(t) = V0 sin(2 pi f t) drives a resistor R, so i(t) = v(t) / R. Three
|
|
8
|
+
* ideas live here, and only the middle one is hard:
|
|
9
|
+
*
|
|
10
|
+
* period and peak T = 1/f, and v and i share the same shape because R is constant
|
|
11
|
+
* r.m.s. V_rms = V0 / sqrt(2), DEFINED by equal heating, not by averaging v
|
|
12
|
+
* rectification one diode keeps half the wave, a bridge folds the whole wave up, and a
|
|
13
|
+
* capacitor across the load turns the ripple into a nearly steady line
|
|
14
|
+
*
|
|
15
|
+
* The r.m.s. part is the reason this file exists. The mean of v over a whole cycle is zero, so
|
|
16
|
+
* averaging the wave tells a learner nothing. What is NOT zero is the mean of v squared, because
|
|
17
|
+
* squaring makes every value positive. Power is v squared over R, so the mean of v squared is
|
|
18
|
+
* what sets the heating. Take the root of that mean and you have the steady d.c. voltage that
|
|
19
|
+
* would heat the same resistor at the same rate: root, of the mean, of the square.
|
|
20
|
+
*
|
|
21
|
+
* `meanSquareFromPeak` returns the exact answer V0^2 / 2. `meanSquareByIntegration` returns the
|
|
22
|
+
* SAME number by adding up v^2 across one period with Simpson's rule, reading nothing from the
|
|
23
|
+
* algebra. The lab draws the integrated value, so the horizontal line on the graph is a measured
|
|
24
|
+
* mean and not a formula redrawn as a line.
|
|
25
|
+
*
|
|
26
|
+
* Everything here is pure, deterministic and React-free, so it can be tested directly.
|
|
27
|
+
*/
|
|
28
|
+
interface AcSupply {
|
|
29
|
+
/** Peak (maximum) voltage V0, in volts. */
|
|
30
|
+
peakVoltageV: number;
|
|
31
|
+
/** Frequency f, in hertz. */
|
|
32
|
+
frequencyHz: number;
|
|
33
|
+
/** Load resistance R, in ohms. */
|
|
34
|
+
resistanceOhm: number;
|
|
35
|
+
}
|
|
36
|
+
/** One diode keeps the positive halves; a bridge of four folds the negative halves up. */
|
|
37
|
+
type RectifierMode = 'half' | 'full';
|
|
38
|
+
/** Period of the supply, T = 1 / f, in seconds. */
|
|
39
|
+
declare function acPeriodS(frequencyHz: number): number;
|
|
40
|
+
/** v(t) = V0 sin(2 pi f t), in volts. */
|
|
41
|
+
declare function acVoltageAt(supply: AcSupply, t: number): number;
|
|
42
|
+
/** i(t) = v(t) / R, in amperes. In phase with v, because a resistor has no phase shift. */
|
|
43
|
+
declare function acCurrentAt(supply: AcSupply, t: number): number;
|
|
44
|
+
/** The r.m.s. value of a SINUSOID from its peak: peak / sqrt(2). Works for volts and amps. */
|
|
45
|
+
declare function rmsFromPeak(peak: number): number;
|
|
46
|
+
/**
|
|
47
|
+
* Mean of a sine over HALF a cycle: 2 V0 / pi, about 0.637 of the peak.
|
|
48
|
+
*
|
|
49
|
+
* Not "the average value of an alternating current", which is zero over a whole
|
|
50
|
+
* cycle and is why the question always means the half-cycle average. Stating it
|
|
51
|
+
* as a half-cycle quantity keeps that from being something a student has to
|
|
52
|
+
* remember as an exception.
|
|
53
|
+
*/
|
|
54
|
+
declare function meanOverHalfCycle(peak: number): number;
|
|
55
|
+
/**
|
|
56
|
+
* Form factor: r.m.s. divided by the half-cycle mean, about 1.11 for a sine.
|
|
57
|
+
*
|
|
58
|
+
* Its job is to say how PEAKY a waveform is. It depends only on the shape, not
|
|
59
|
+
* on the amplitude, which is the property worth showing: double the supply and
|
|
60
|
+
* it does not move.
|
|
61
|
+
*/
|
|
62
|
+
declare function formFactor(peak: number): number;
|
|
63
|
+
/** Peak factor: peak divided by r.m.s., exactly root two for a sine. */
|
|
64
|
+
declare function peakFactor(peak: number): number;
|
|
65
|
+
/** The mean of v^2 over a whole cycle, from the algebra: V0^2 / 2. */
|
|
66
|
+
declare function meanSquareFromPeak(peak: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* The integral of v^2 over ONE whole period, in V^2 s, by Simpson's rule.
|
|
69
|
+
*
|
|
70
|
+
* This is the honest route to the mean square: no identity for sin^2 is used anywhere. The exact
|
|
71
|
+
* answer is V0^2 T / 2, and Simpson's rule on a smooth periodic function reaches it to far more
|
|
72
|
+
* figures than the lab ever prints. `intervals` is rounded up to an even number, as Simpson's
|
|
73
|
+
* rule requires.
|
|
74
|
+
*/
|
|
75
|
+
declare function integrateSquareOverPeriod(peakVoltageV: number, frequencyHz: number, intervals?: number): number;
|
|
76
|
+
/** The mean of v^2 over one period, measured by integration: (integral over T) / T. */
|
|
77
|
+
declare function meanSquareByIntegration(peakVoltageV: number, frequencyHz: number, intervals?: number): number;
|
|
78
|
+
/**
|
|
79
|
+
* Mean power delivered to R, in watts.
|
|
80
|
+
*
|
|
81
|
+
* P_mean = V_rms^2 / R = V0^2 / (2 R), which is exactly HALF the peak power. This single number
|
|
82
|
+
* is what r.m.s. is for: a steady d.c. supply of V_rms volts across the same R delivers it too.
|
|
83
|
+
*/
|
|
84
|
+
declare function meanAcPowerW(supply: AcSupply): number;
|
|
85
|
+
interface AcState {
|
|
86
|
+
/** Period T = 1/f, s. */
|
|
87
|
+
periodS: number;
|
|
88
|
+
peakVoltageV: number;
|
|
89
|
+
/** I0 = V0 / R, A. */
|
|
90
|
+
peakCurrentA: number;
|
|
91
|
+
/** V_rms = V0 / sqrt(2), V. */
|
|
92
|
+
rmsVoltageV: number;
|
|
93
|
+
/** I_rms = I0 / sqrt(2) = V_rms / R, A. */
|
|
94
|
+
rmsCurrentA: number;
|
|
95
|
+
/** Mean of v^2 over a cycle, measured by integration, V^2. */
|
|
96
|
+
meanSquareVoltageV2: number;
|
|
97
|
+
/** Mean of v^2 from the algebra, V0^2 / 2, V^2. The two agree; the lab shows both. */
|
|
98
|
+
meanSquareExactV2: number;
|
|
99
|
+
/** Mean power into R, W. */
|
|
100
|
+
meanPowerW: number;
|
|
101
|
+
/** Peak power into R, V0^2 / R, W. Twice the mean. */
|
|
102
|
+
peakPowerW: number;
|
|
103
|
+
}
|
|
104
|
+
/** Everything the lab reads off one supply driving one resistor. */
|
|
105
|
+
declare function acState(supply: AcSupply): AcState;
|
|
106
|
+
interface WavePoint {
|
|
107
|
+
/** Time, s. */
|
|
108
|
+
t: number;
|
|
109
|
+
/** Supply voltage, V. */
|
|
110
|
+
v: number;
|
|
111
|
+
/** Current in R, A. */
|
|
112
|
+
i: number;
|
|
113
|
+
}
|
|
114
|
+
/** The supply sampled over whole cycles. Deterministic: the same input gives the same points. */
|
|
115
|
+
declare function acWaveTrace(supply: AcSupply, cycles?: number, samplesPerCycle?: number): WavePoint[];
|
|
116
|
+
/** What the diodes let through: half-wave keeps v when positive, full-wave folds it up. */
|
|
117
|
+
declare function rectify(v: number, mode: RectifierMode): number;
|
|
118
|
+
/**
|
|
119
|
+
* Mean of the rectified output over a whole cycle, with no smoothing capacitor.
|
|
120
|
+
*
|
|
121
|
+
* Half-wave gives V0 / pi (0.318 V0), because half the cycle is flat zero. Full-wave gives
|
|
122
|
+
* 2 V0 / pi (0.637 V0). Neither is V_rms: this is a mean HEIGHT, not a heating value.
|
|
123
|
+
*/
|
|
124
|
+
declare function meanRectifiedVoltage(peakVoltageV: number, mode: RectifierMode): number;
|
|
125
|
+
/** The ripple repeats once per cycle after one diode, twice per cycle after a bridge. */
|
|
126
|
+
declare function rippleFrequencyHz(frequencyHz: number, mode: RectifierMode): number;
|
|
127
|
+
interface RectifiedPoint {
|
|
128
|
+
/** Time, s. */
|
|
129
|
+
t: number;
|
|
130
|
+
/** Supply voltage before the diodes, V. */
|
|
131
|
+
input: number;
|
|
132
|
+
/** Diode output with no capacitor, V. */
|
|
133
|
+
rectified: number;
|
|
134
|
+
/** Voltage across the load with the smoothing capacitor fitted, V. */
|
|
135
|
+
output: number;
|
|
136
|
+
}
|
|
137
|
+
interface RectifiedTrace {
|
|
138
|
+
points: RectifiedPoint[];
|
|
139
|
+
/** Largest output voltage in the last whole cycle, V. */
|
|
140
|
+
maxV: number;
|
|
141
|
+
/** Smallest output voltage in the last whole cycle, V. */
|
|
142
|
+
minV: number;
|
|
143
|
+
/** Peak-to-peak ripple in the last whole cycle, V. */
|
|
144
|
+
rippleV: number;
|
|
145
|
+
/** Mean output over the last whole cycle, V. */
|
|
146
|
+
meanV: number;
|
|
147
|
+
/** How often the output dips, Hz. */
|
|
148
|
+
rippleFrequencyHz: number;
|
|
149
|
+
/** Time constant R C, s. Compare it with the period: large R C means small ripple. */
|
|
150
|
+
timeConstantS: number;
|
|
151
|
+
}
|
|
152
|
+
interface RectifiedInput {
|
|
153
|
+
supply: AcSupply;
|
|
154
|
+
/** Smoothing capacitance across the load, farads. Zero means no capacitor. */
|
|
155
|
+
capacitanceF: number;
|
|
156
|
+
rectifier: RectifierMode;
|
|
157
|
+
cycles?: number;
|
|
158
|
+
samplesPerCycle?: number;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The load voltage after rectification, with an ideal peak-detector capacitor.
|
|
162
|
+
*
|
|
163
|
+
* The model is the one a textbook draws: while the rectified wave is above the capacitor
|
|
164
|
+
* voltage the diodes conduct and the capacitor follows the wave up; once the wave falls away
|
|
165
|
+
* the diodes stop conducting and the capacitor discharges through R, decaying by
|
|
166
|
+
* exp(-dt / RC) each step. So the output is
|
|
167
|
+
*
|
|
168
|
+
* v_out(t) = max( rectified(t), v_out(t - dt) * exp(-dt / RC) )
|
|
169
|
+
*
|
|
170
|
+
* With no capacitor RC is zero, the decay factor is zero, and the output is the bare rectified
|
|
171
|
+
* wave. Charging is instantaneous here (ideal diodes, no series resistance), so the trace is in
|
|
172
|
+
* its steady state from the first peak onward, which is why the ripple and the mean are measured
|
|
173
|
+
* over the LAST whole cycle. Nothing random and nothing clock-based: same input, same trace.
|
|
174
|
+
*/
|
|
175
|
+
declare function acRectifiedTrace({
|
|
176
|
+
supply,
|
|
177
|
+
capacitanceF,
|
|
178
|
+
rectifier,
|
|
179
|
+
cycles,
|
|
180
|
+
samplesPerCycle
|
|
181
|
+
}: RectifiedInput): RectifiedTrace;
|
|
182
|
+
//#endregion
|
|
183
|
+
export { AcState, AcSupply, RectifiedInput, RectifiedPoint, RectifiedTrace, RectifierMode, WavePoint, acCurrentAt, acPeriodS, acRectifiedTrace, acState, acVoltageAt, acWaveTrace, ac_d_exports, formFactor, integrateSquareOverPeriod, meanAcPowerW, meanOverHalfCycle, meanRectifiedVoltage, meanSquareByIntegration, meanSquareFromPeak, peakFactor, rectify, rippleFrequencyHz, rmsFromPeak };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/ac.ts
|
|
4
|
+
var ac_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
acCurrentAt: () => acCurrentAt,
|
|
6
|
+
acPeriodS: () => acPeriodS,
|
|
7
|
+
acRectifiedTrace: () => acRectifiedTrace,
|
|
8
|
+
acState: () => acState,
|
|
9
|
+
acVoltageAt: () => acVoltageAt,
|
|
10
|
+
acWaveTrace: () => acWaveTrace,
|
|
11
|
+
formFactor: () => formFactor,
|
|
12
|
+
integrateSquareOverPeriod: () => integrateSquareOverPeriod,
|
|
13
|
+
meanAcPowerW: () => meanAcPowerW,
|
|
14
|
+
meanOverHalfCycle: () => meanOverHalfCycle,
|
|
15
|
+
meanRectifiedVoltage: () => meanRectifiedVoltage,
|
|
16
|
+
meanSquareByIntegration: () => meanSquareByIntegration,
|
|
17
|
+
meanSquareFromPeak: () => meanSquareFromPeak,
|
|
18
|
+
peakFactor: () => peakFactor,
|
|
19
|
+
rectify: () => rectify,
|
|
20
|
+
rippleFrequencyHz: () => rippleFrequencyHz,
|
|
21
|
+
rmsFromPeak: () => rmsFromPeak
|
|
22
|
+
});
|
|
23
|
+
/** Period of the supply, T = 1 / f, in seconds. */
|
|
24
|
+
function acPeriodS(frequencyHz) {
|
|
25
|
+
return 1 / frequencyHz;
|
|
26
|
+
}
|
|
27
|
+
/** v(t) = V0 sin(2 pi f t), in volts. */
|
|
28
|
+
function acVoltageAt(supply, t) {
|
|
29
|
+
return supply.peakVoltageV * Math.sin(2 * Math.PI * supply.frequencyHz * t);
|
|
30
|
+
}
|
|
31
|
+
/** i(t) = v(t) / R, in amperes. In phase with v, because a resistor has no phase shift. */
|
|
32
|
+
function acCurrentAt(supply, t) {
|
|
33
|
+
return acVoltageAt(supply, t) / supply.resistanceOhm;
|
|
34
|
+
}
|
|
35
|
+
/** The r.m.s. value of a SINUSOID from its peak: peak / sqrt(2). Works for volts and amps. */
|
|
36
|
+
function rmsFromPeak(peak) {
|
|
37
|
+
return peak / Math.SQRT2;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Mean of a sine over HALF a cycle: 2 V0 / pi, about 0.637 of the peak.
|
|
41
|
+
*
|
|
42
|
+
* Not "the average value of an alternating current", which is zero over a whole
|
|
43
|
+
* cycle and is why the question always means the half-cycle average. Stating it
|
|
44
|
+
* as a half-cycle quantity keeps that from being something a student has to
|
|
45
|
+
* remember as an exception.
|
|
46
|
+
*/
|
|
47
|
+
function meanOverHalfCycle(peak) {
|
|
48
|
+
return 2 * peak / Math.PI;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Form factor: r.m.s. divided by the half-cycle mean, about 1.11 for a sine.
|
|
52
|
+
*
|
|
53
|
+
* Its job is to say how PEAKY a waveform is. It depends only on the shape, not
|
|
54
|
+
* on the amplitude, which is the property worth showing: double the supply and
|
|
55
|
+
* it does not move.
|
|
56
|
+
*/
|
|
57
|
+
function formFactor(peak) {
|
|
58
|
+
if (peak === 0) throw new RangeError("A waveform with no amplitude has no form factor.");
|
|
59
|
+
return rmsFromPeak(peak) / meanOverHalfCycle(peak);
|
|
60
|
+
}
|
|
61
|
+
/** Peak factor: peak divided by r.m.s., exactly root two for a sine. */
|
|
62
|
+
function peakFactor(peak) {
|
|
63
|
+
if (peak === 0) throw new RangeError("A waveform with no amplitude has no peak factor.");
|
|
64
|
+
return peak / rmsFromPeak(peak);
|
|
65
|
+
}
|
|
66
|
+
/** The mean of v^2 over a whole cycle, from the algebra: V0^2 / 2. */
|
|
67
|
+
function meanSquareFromPeak(peak) {
|
|
68
|
+
return peak * peak / 2;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The integral of v^2 over ONE whole period, in V^2 s, by Simpson's rule.
|
|
72
|
+
*
|
|
73
|
+
* This is the honest route to the mean square: no identity for sin^2 is used anywhere. The exact
|
|
74
|
+
* answer is V0^2 T / 2, and Simpson's rule on a smooth periodic function reaches it to far more
|
|
75
|
+
* figures than the lab ever prints. `intervals` is rounded up to an even number, as Simpson's
|
|
76
|
+
* rule requires.
|
|
77
|
+
*/
|
|
78
|
+
function integrateSquareOverPeriod(peakVoltageV, frequencyHz, intervals = 720) {
|
|
79
|
+
const n = Math.max(2, Math.ceil(intervals / 2) * 2);
|
|
80
|
+
const T = acPeriodS(frequencyHz);
|
|
81
|
+
const h = T / n;
|
|
82
|
+
const square = (t) => {
|
|
83
|
+
const v = peakVoltageV * Math.sin(2 * Math.PI * frequencyHz * t);
|
|
84
|
+
return v * v;
|
|
85
|
+
};
|
|
86
|
+
let sum = square(0) + square(T);
|
|
87
|
+
for (let k = 1; k < n; k++) sum += square(k * h) * (k % 2 === 1 ? 4 : 2);
|
|
88
|
+
return h / 3 * sum;
|
|
89
|
+
}
|
|
90
|
+
/** The mean of v^2 over one period, measured by integration: (integral over T) / T. */
|
|
91
|
+
function meanSquareByIntegration(peakVoltageV, frequencyHz, intervals = 720) {
|
|
92
|
+
return integrateSquareOverPeriod(peakVoltageV, frequencyHz, intervals) / acPeriodS(frequencyHz);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Mean power delivered to R, in watts.
|
|
96
|
+
*
|
|
97
|
+
* P_mean = V_rms^2 / R = V0^2 / (2 R), which is exactly HALF the peak power. This single number
|
|
98
|
+
* is what r.m.s. is for: a steady d.c. supply of V_rms volts across the same R delivers it too.
|
|
99
|
+
*/
|
|
100
|
+
function meanAcPowerW(supply) {
|
|
101
|
+
return supply.peakVoltageV * supply.peakVoltageV / (2 * supply.resistanceOhm);
|
|
102
|
+
}
|
|
103
|
+
/** Everything the lab reads off one supply driving one resistor. */
|
|
104
|
+
function acState(supply) {
|
|
105
|
+
const { peakVoltageV, frequencyHz, resistanceOhm } = supply;
|
|
106
|
+
const rmsVoltageV = rmsFromPeak(peakVoltageV);
|
|
107
|
+
return {
|
|
108
|
+
periodS: acPeriodS(frequencyHz),
|
|
109
|
+
peakVoltageV,
|
|
110
|
+
peakCurrentA: peakVoltageV / resistanceOhm,
|
|
111
|
+
rmsVoltageV,
|
|
112
|
+
rmsCurrentA: rmsVoltageV / resistanceOhm,
|
|
113
|
+
meanSquareVoltageV2: meanSquareByIntegration(peakVoltageV, frequencyHz),
|
|
114
|
+
meanSquareExactV2: meanSquareFromPeak(peakVoltageV),
|
|
115
|
+
meanPowerW: meanAcPowerW(supply),
|
|
116
|
+
peakPowerW: peakVoltageV * peakVoltageV / resistanceOhm
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** The supply sampled over whole cycles. Deterministic: the same input gives the same points. */
|
|
120
|
+
function acWaveTrace(supply, cycles = 2, samplesPerCycle = 120) {
|
|
121
|
+
const n = Math.max(4, Math.round(samplesPerCycle));
|
|
122
|
+
const steps = Math.max(1, Math.round(cycles)) * n;
|
|
123
|
+
const dt = acPeriodS(supply.frequencyHz) / n;
|
|
124
|
+
const points = [];
|
|
125
|
+
for (let k = 0; k <= steps; k++) {
|
|
126
|
+
const t = k * dt;
|
|
127
|
+
const v = acVoltageAt(supply, t);
|
|
128
|
+
points.push({
|
|
129
|
+
t,
|
|
130
|
+
v,
|
|
131
|
+
i: v / supply.resistanceOhm
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return points;
|
|
135
|
+
}
|
|
136
|
+
/** What the diodes let through: half-wave keeps v when positive, full-wave folds it up. */
|
|
137
|
+
function rectify(v, mode) {
|
|
138
|
+
return mode === "half" ? Math.max(0, v) : Math.abs(v);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Mean of the rectified output over a whole cycle, with no smoothing capacitor.
|
|
142
|
+
*
|
|
143
|
+
* Half-wave gives V0 / pi (0.318 V0), because half the cycle is flat zero. Full-wave gives
|
|
144
|
+
* 2 V0 / pi (0.637 V0). Neither is V_rms: this is a mean HEIGHT, not a heating value.
|
|
145
|
+
*/
|
|
146
|
+
function meanRectifiedVoltage(peakVoltageV, mode) {
|
|
147
|
+
return mode === "half" ? peakVoltageV / Math.PI : 2 * peakVoltageV / Math.PI;
|
|
148
|
+
}
|
|
149
|
+
/** The ripple repeats once per cycle after one diode, twice per cycle after a bridge. */
|
|
150
|
+
function rippleFrequencyHz(frequencyHz, mode) {
|
|
151
|
+
return mode === "half" ? frequencyHz : 2 * frequencyHz;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The load voltage after rectification, with an ideal peak-detector capacitor.
|
|
155
|
+
*
|
|
156
|
+
* The model is the one a textbook draws: while the rectified wave is above the capacitor
|
|
157
|
+
* voltage the diodes conduct and the capacitor follows the wave up; once the wave falls away
|
|
158
|
+
* the diodes stop conducting and the capacitor discharges through R, decaying by
|
|
159
|
+
* exp(-dt / RC) each step. So the output is
|
|
160
|
+
*
|
|
161
|
+
* v_out(t) = max( rectified(t), v_out(t - dt) * exp(-dt / RC) )
|
|
162
|
+
*
|
|
163
|
+
* With no capacitor RC is zero, the decay factor is zero, and the output is the bare rectified
|
|
164
|
+
* wave. Charging is instantaneous here (ideal diodes, no series resistance), so the trace is in
|
|
165
|
+
* its steady state from the first peak onward, which is why the ripple and the mean are measured
|
|
166
|
+
* over the LAST whole cycle. Nothing random and nothing clock-based: same input, same trace.
|
|
167
|
+
*/
|
|
168
|
+
function acRectifiedTrace({ supply, capacitanceF, rectifier, cycles = 2, samplesPerCycle = 180 }) {
|
|
169
|
+
const n = Math.max(8, Math.round(samplesPerCycle));
|
|
170
|
+
const steps = Math.max(1, Math.round(cycles)) * n;
|
|
171
|
+
const dt = acPeriodS(supply.frequencyHz) / n;
|
|
172
|
+
const timeConstantS = supply.resistanceOhm * capacitanceF;
|
|
173
|
+
const decay = timeConstantS > 0 ? Math.exp(-dt / timeConstantS) : 0;
|
|
174
|
+
const points = [];
|
|
175
|
+
let held = 0;
|
|
176
|
+
for (let k = 0; k <= steps; k++) {
|
|
177
|
+
const t = k * dt;
|
|
178
|
+
const input = acVoltageAt(supply, t);
|
|
179
|
+
const rectified = rectify(input, rectifier);
|
|
180
|
+
held = Math.max(rectified, held * decay);
|
|
181
|
+
points.push({
|
|
182
|
+
t,
|
|
183
|
+
input,
|
|
184
|
+
rectified,
|
|
185
|
+
output: held
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const window = points.slice(steps - n, steps).map((p) => p.output);
|
|
189
|
+
const maxV = Math.max(...window);
|
|
190
|
+
const minV = Math.min(...window);
|
|
191
|
+
return {
|
|
192
|
+
points,
|
|
193
|
+
maxV,
|
|
194
|
+
minV,
|
|
195
|
+
rippleV: maxV - minV,
|
|
196
|
+
meanV: window.reduce((sum, v) => sum + v, 0) / window.length,
|
|
197
|
+
rippleFrequencyHz: rippleFrequencyHz(supply.frequencyHz, rectifier),
|
|
198
|
+
timeConstantS
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//#endregion
|
|
203
|
+
export { acCurrentAt, acPeriodS, acRectifiedTrace, acState, acVoltageAt, acWaveTrace, ac_exports, formFactor, integrateSquareOverPeriod, meanAcPowerW, meanOverHalfCycle, meanRectifiedVoltage, meanSquareByIntegration, meanSquareFromPeak, peakFactor, rectify, rippleFrequencyHz, rmsFromPeak };
|