@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.
Files changed (458) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -1
  3. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  4. package/dist/assets/index.mjs +0 -1
  5. package/dist/atomic/aufbau.d.mts +144 -0
  6. package/dist/atomic/aufbau.mjs +384 -0
  7. package/dist/atomic/elements.d.mts +67 -0
  8. package/dist/atomic/elements.mjs +785 -0
  9. package/dist/atomic/emission.d.mts +112 -0
  10. package/dist/atomic/emission.mjs +179 -0
  11. package/dist/atomic/index.d.mts +8 -0
  12. package/dist/atomic/index.mjs +9 -0
  13. package/dist/atomic/periodic.d.mts +82 -0
  14. package/dist/atomic/periodic.mjs +231 -0
  15. package/dist/atomic/properties.d.mts +100 -0
  16. package/dist/atomic/properties.mjs +574 -0
  17. package/dist/atomic/shells.d.mts +137 -0
  18. package/dist/atomic/shells.mjs +170 -0
  19. package/dist/atomic/trends.d.mts +148 -0
  20. package/dist/atomic/trends.mjs +225 -0
  21. package/dist/builder/Palette.mjs +50 -89
  22. package/dist/builder/SceneBuilder.mjs +15 -73
  23. package/dist/chem/chromatography.d.mts +66 -0
  24. package/dist/chem/chromatography.mjs +63 -0
  25. package/dist/chem/complex.d.mts +114 -0
  26. package/dist/chem/complex.mjs +234 -0
  27. package/dist/chem/cycle.d.mts +75 -0
  28. package/dist/chem/cycle.mjs +145 -0
  29. package/dist/chem/equation.d.mts +86 -0
  30. package/dist/chem/equation.mjs +168 -0
  31. package/dist/chem/formula.d.mts +90 -0
  32. package/dist/chem/formula.mjs +201 -0
  33. package/dist/chem/functional-groups.d.mts +31 -0
  34. package/dist/chem/functional-groups.mjs +187 -0
  35. package/dist/chem/hazard.d.mts +94 -0
  36. package/dist/chem/hazard.mjs +329 -0
  37. package/dist/chem/index.d.mts +34 -33
  38. package/dist/chem/index.mjs +34 -28
  39. package/dist/chem/ionic.d.mts +98 -0
  40. package/dist/chem/ionic.mjs +156 -0
  41. package/dist/chem/layout.d.mts +46 -0
  42. package/dist/chem/layout.mjs +342 -0
  43. package/dist/chem/lewis.d.mts +79 -0
  44. package/dist/chem/lewis.mjs +163 -0
  45. package/dist/chem/molecular-orbital.d.mts +114 -0
  46. package/dist/chem/molecular-orbital.mjs +201 -0
  47. package/dist/chem/molecule.d.mts +154 -0
  48. package/dist/chem/molecule.mjs +282 -0
  49. package/dist/chem/nmr.d.mts +153 -0
  50. package/dist/chem/nmr.mjs +165 -0
  51. package/dist/chem/polymer.d.mts +65 -0
  52. package/dist/chem/polymer.mjs +179 -0
  53. package/dist/chem/redox.d.mts +138 -0
  54. package/dist/chem/redox.mjs +328 -0
  55. package/dist/chem/relations.d.mts +183 -0
  56. package/dist/chem/relations.mjs +299 -0
  57. package/dist/chem/skeleton.d.mts +51 -0
  58. package/dist/chem/skeleton.mjs +186 -0
  59. package/dist/chem/solution.d.mts +116 -0
  60. package/dist/chem/solution.mjs +186 -0
  61. package/dist/chem/species.d.mts +47 -0
  62. package/dist/chem/species.mjs +128 -0
  63. package/dist/chem/stereo.d.mts +108 -0
  64. package/dist/chem/stereo.mjs +286 -0
  65. package/dist/chem/stoichiometry.d.mts +95 -0
  66. package/dist/chem/stoichiometry.mjs +145 -0
  67. package/dist/chem/synthesis.d.mts +113 -0
  68. package/dist/chem/synthesis.mjs +281 -0
  69. package/dist/chem/vsepr.d.mts +80 -0
  70. package/dist/chem/vsepr.mjs +247 -0
  71. package/dist/circuit/ac.d.mts +163 -0
  72. package/dist/circuit/ac.mjs +452 -0
  73. package/dist/circuit/dc.d.mts +92 -0
  74. package/dist/circuit/dc.mjs +333 -0
  75. package/dist/circuit/index.d.mts +5 -92
  76. package/dist/circuit/index.mjs +5 -332
  77. package/dist/circuit/network.d.mts +99 -0
  78. package/dist/circuit/network.mjs +440 -0
  79. package/dist/circuit/topology.d.mts +102 -0
  80. package/dist/circuit/topology.mjs +143 -0
  81. package/dist/colour/absorption.d.mts +79 -0
  82. package/dist/colour/absorption.mjs +137 -0
  83. package/dist/colour/index.d.mts +6 -0
  84. package/dist/colour/index.mjs +7 -0
  85. package/dist/colour/name.d.mts +14 -0
  86. package/dist/colour/name.mjs +76 -0
  87. package/dist/colour/observer.d.mts +31 -0
  88. package/dist/colour/observer.mjs +46 -0
  89. package/dist/colour/spectrum.d.mts +61 -0
  90. package/dist/colour/spectrum.mjs +108 -0
  91. package/dist/colour/srgb.d.mts +49 -0
  92. package/dist/colour/srgb.mjs +108 -0
  93. package/dist/core/constants.d.mts +138 -0
  94. package/dist/core/constants.mjs +139 -0
  95. package/dist/core/index.d.mts +4 -1
  96. package/dist/core/index.mjs +4 -1
  97. package/dist/core/math.d.mts +26 -0
  98. package/dist/core/math.mjs +37 -0
  99. package/dist/core/vec3.d.mts +94 -0
  100. package/dist/core/vec3.mjs +123 -0
  101. package/dist/core/worked.d.mts +35 -0
  102. package/dist/core/worked.mjs +44 -0
  103. package/dist/electro/cell.d.mts +102 -0
  104. package/dist/electro/cell.mjs +170 -0
  105. package/dist/electro/conductivity.d.mts +157 -0
  106. package/dist/electro/conductivity.mjs +156 -0
  107. package/dist/electro/couples.d.mts +114 -0
  108. package/dist/electro/couples.mjs +334 -0
  109. package/dist/electro/electrolysis.d.mts +96 -0
  110. package/dist/electro/electrolysis.mjs +274 -0
  111. package/dist/electro/faraday.d.mts +150 -0
  112. package/dist/electro/faraday.mjs +118 -0
  113. package/dist/electro/index.d.mts +6 -0
  114. package/dist/electro/index.mjs +7 -0
  115. package/dist/finance/accounting/adjustments.d.mts +17 -0
  116. package/dist/finance/accounting/adjustments.mjs +202 -0
  117. package/dist/finance/accounting/analysis.d.mts +8 -0
  118. package/dist/finance/accounting/analysis.mjs +205 -0
  119. package/dist/finance/accounting/clubs.d.mts +21 -0
  120. package/dist/finance/accounting/clubs.mjs +217 -0
  121. package/dist/finance/accounting/company-statements.d.mts +7 -0
  122. package/dist/finance/accounting/company-statements.mjs +150 -0
  123. package/dist/finance/accounting/harness.d.mts +7 -0
  124. package/dist/finance/accounting/harness.mjs +45 -0
  125. package/dist/finance/accounting/index.d.mts +18 -0
  126. package/dist/finance/accounting/index.mjs +18 -0
  127. package/dist/finance/accounting/journalize.d.mts +16 -0
  128. package/dist/finance/accounting/journalize.mjs +128 -0
  129. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  130. package/dist/finance/accounting/manufacturing.mjs +236 -0
  131. package/dist/finance/accounting/partnership.d.mts +7 -0
  132. package/dist/finance/accounting/partnership.mjs +152 -0
  133. package/dist/finance/accounting/period-case.d.mts +6 -0
  134. package/dist/finance/accounting/period-case.mjs +71 -0
  135. package/dist/finance/accounting/post.d.mts +9 -0
  136. package/dist/finance/accounting/post.mjs +84 -0
  137. package/dist/finance/accounting/precision.d.mts +9 -0
  138. package/dist/finance/accounting/precision.mjs +15 -0
  139. package/dist/finance/accounting/rules.d.mts +21 -0
  140. package/dist/finance/accounting/rules.mjs +37 -0
  141. package/dist/finance/accounting/solve.d.mts +28 -0
  142. package/dist/finance/accounting/solve.mjs +92 -0
  143. package/dist/finance/accounting/statements.d.mts +7 -0
  144. package/dist/finance/accounting/statements.mjs +142 -0
  145. package/dist/finance/accounting/types.d.mts +649 -0
  146. package/dist/finance/accounting/validate.d.mts +7 -0
  147. package/dist/finance/accounting/validate.mjs +67 -0
  148. package/dist/finance/accounting/verification.d.mts +24 -0
  149. package/dist/finance/accounting/verification.mjs +386 -0
  150. package/dist/finance/bizsim.d.mts +75 -0
  151. package/dist/finance/bizsim.mjs +296 -0
  152. package/dist/finance/index.d.mts +95 -0
  153. package/dist/finance/index.mjs +145 -0
  154. package/dist/finance/investment-math.d.mts +7 -0
  155. package/dist/finance/investment-math.mjs +18 -0
  156. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  157. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  158. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  159. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  160. package/dist/finance/management-accounting/costing.d.mts +8 -0
  161. package/dist/finance/management-accounting/costing.mjs +175 -0
  162. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  163. package/dist/finance/management-accounting/decisions.mjs +164 -0
  164. package/dist/finance/management-accounting/index.d.mts +13 -0
  165. package/dist/finance/management-accounting/index.mjs +13 -0
  166. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  167. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  168. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  169. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  170. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  171. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  172. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  173. package/dist/finance/management-accounting/management-case.mjs +91 -0
  174. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  175. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  176. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  177. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  178. package/dist/finance/management-accounting/types.d.mts +644 -0
  179. package/dist/finance/management-accounting/variances.d.mts +7 -0
  180. package/dist/finance/management-accounting/variances.mjs +150 -0
  181. package/dist/index.d.mts +9 -8
  182. package/dist/index.mjs +5 -5
  183. package/dist/interaction/MovableDot.mjs +19 -0
  184. package/dist/interaction/useDraggable.mjs +24 -4
  185. package/dist/math/analysis.d.mts +61 -0
  186. package/dist/math/analysis.mjs +187 -0
  187. package/dist/math/answer-check.d.mts +50 -0
  188. package/dist/math/answer-check.mjs +106 -0
  189. package/dist/math/calculus.d.mts +17 -1
  190. package/dist/math/calculus.mjs +365 -2
  191. package/dist/math/complex.d.mts +93 -0
  192. package/dist/math/complex.mjs +239 -0
  193. package/dist/math/expr.d.mts +23 -0
  194. package/dist/math/expr.mjs +36 -0
  195. package/dist/math/index.d.mts +9 -23
  196. package/dist/math/index.mjs +9 -38
  197. package/dist/math/latex.mjs +10 -1
  198. package/dist/math/parse.mjs +1 -1
  199. package/dist/math/poly.d.mts +55 -0
  200. package/dist/math/poly.mjs +273 -0
  201. package/dist/math/rearrange.d.mts +14 -0
  202. package/dist/math/rearrange.mjs +125 -0
  203. package/dist/math/solve.d.mts +21 -0
  204. package/dist/math/solve.mjs +75 -0
  205. package/dist/networking/addressing.d.mts +26 -0
  206. package/dist/networking/addressing.mjs +33 -0
  207. package/dist/networking/cloud/access.d.mts +36 -0
  208. package/dist/networking/cloud/access.mjs +95 -0
  209. package/dist/networking/cloud/containers.d.mts +43 -0
  210. package/dist/networking/cloud/containers.mjs +54 -0
  211. package/dist/networking/cloud/edge.d.mts +17 -0
  212. package/dist/networking/cloud/edge.mjs +31 -0
  213. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  214. package/dist/networking/cloud/failure-domains.mjs +22 -0
  215. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  216. package/dist/networking/cloud/geo-routing.mjs +64 -0
  217. package/dist/networking/cloud/index.d.mts +18 -0
  218. package/dist/networking/cloud/index.mjs +19 -0
  219. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  220. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  221. package/dist/networking/cloud/inference.d.mts +118 -0
  222. package/dist/networking/cloud/inference.mjs +179 -0
  223. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  224. package/dist/networking/cloud/infrastructure.mjs +96 -0
  225. package/dist/networking/cloud/observability.d.mts +24 -0
  226. package/dist/networking/cloud/observability.mjs +34 -0
  227. package/dist/networking/cloud/orchestration.d.mts +32 -0
  228. package/dist/networking/cloud/orchestration.mjs +38 -0
  229. package/dist/networking/cloud/recovery.d.mts +21 -0
  230. package/dist/networking/cloud/recovery.mjs +27 -0
  231. package/dist/networking/cloud/releases.d.mts +42 -0
  232. package/dist/networking/cloud/releases.mjs +135 -0
  233. package/dist/networking/cloud/scaling.d.mts +25 -0
  234. package/dist/networking/cloud/scaling.mjs +65 -0
  235. package/dist/networking/cloud/secrets.d.mts +39 -0
  236. package/dist/networking/cloud/secrets.mjs +68 -0
  237. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  238. package/dist/networking/cloud/server-deployment.mjs +72 -0
  239. package/dist/networking/cloud/storage.d.mts +16 -0
  240. package/dist/networking/cloud/storage.mjs +58 -0
  241. package/dist/networking/cloud/vpc.d.mts +18 -0
  242. package/dist/networking/cloud/vpc.mjs +100 -0
  243. package/dist/networking/delivery.d.mts +34 -0
  244. package/dist/networking/delivery.mjs +52 -0
  245. package/dist/networking/index.d.mts +47 -0
  246. package/dist/networking/index.mjs +47 -0
  247. package/dist/networking/ipv6.d.mts +28 -0
  248. package/dist/networking/ipv6.mjs +17 -0
  249. package/dist/networking/journeys.d.mts +83 -0
  250. package/dist/networking/journeys.mjs +161 -0
  251. package/dist/networking/models/airtime.d.mts +87 -0
  252. package/dist/networking/models/airtime.mjs +130 -0
  253. package/dist/networking/models/cellular.d.mts +157 -0
  254. package/dist/networking/models/cellular.mjs +252 -0
  255. package/dist/networking/models/encapsulation.d.mts +98 -0
  256. package/dist/networking/models/encapsulation.mjs +132 -0
  257. package/dist/networking/models/handover.d.mts +116 -0
  258. package/dist/networking/models/handover.mjs +209 -0
  259. package/dist/networking/models/handshake.d.mts +90 -0
  260. package/dist/networking/models/handshake.mjs +122 -0
  261. package/dist/networking/models/index.d.mts +14 -0
  262. package/dist/networking/models/index.mjs +15 -0
  263. package/dist/networking/models/media.d.mts +82 -0
  264. package/dist/networking/models/media.mjs +188 -0
  265. package/dist/networking/models/satellite.d.mts +86 -0
  266. package/dist/networking/models/satellite.mjs +121 -0
  267. package/dist/networking/models/spectrum.d.mts +83 -0
  268. package/dist/networking/models/spectrum.mjs +235 -0
  269. package/dist/networking/models/switch.d.mts +80 -0
  270. package/dist/networking/models/switch.mjs +155 -0
  271. package/dist/networking/models/vlan.d.mts +62 -0
  272. package/dist/networking/models/vlan.mjs +100 -0
  273. package/dist/networking/models/vpn.d.mts +66 -0
  274. package/dist/networking/models/vpn.mjs +125 -0
  275. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  276. package/dist/networking/models/wifi-privacy.mjs +130 -0
  277. package/dist/networking/models/wifi.d.mts +240 -0
  278. package/dist/networking/models/wifi.mjs +562 -0
  279. package/dist/networking/nat-traversal.d.mts +24 -0
  280. package/dist/networking/nat-traversal.mjs +38 -0
  281. package/dist/networking/protocols.d.mts +17 -0
  282. package/dist/networking/protocols.mjs +57 -0
  283. package/dist/networking/queue.d.mts +12 -0
  284. package/dist/networking/queue.mjs +18 -0
  285. package/dist/networking/route-learning.d.mts +23 -0
  286. package/dist/networking/route-learning.mjs +43 -0
  287. package/dist/networking/routing.d.mts +11 -0
  288. package/dist/networking/routing.mjs +25 -0
  289. package/dist/networking/signals.d.mts +26 -0
  290. package/dist/networking/signals.mjs +35 -0
  291. package/dist/networking/subnet.d.mts +49 -0
  292. package/dist/networking/subnet.mjs +89 -0
  293. package/dist/networking/tcp-reliability.d.mts +24 -0
  294. package/dist/networking/tcp-reliability.mjs +38 -0
  295. package/dist/networking/topology/contract.d.mts +123 -0
  296. package/dist/networking/topology/index.d.mts +4 -0
  297. package/dist/networking/topology/index.mjs +4 -0
  298. package/dist/networking/topology/presets.d.mts +7 -0
  299. package/dist/networking/topology/presets.mjs +302 -0
  300. package/dist/networking/topology/simulation.d.mts +8 -0
  301. package/dist/networking/topology/simulation.mjs +179 -0
  302. package/dist/networking/wireless.d.mts +11 -0
  303. package/dist/networking/wireless.mjs +17 -0
  304. package/dist/optics/imaging.d.mts +218 -0
  305. package/dist/optics/imaging.mjs +276 -0
  306. package/dist/optics/index.d.mts +7 -0
  307. package/dist/optics/index.mjs +8 -0
  308. package/dist/optics/laws.d.mts +70 -0
  309. package/dist/optics/laws.mjs +195 -0
  310. package/dist/optics/prism.d.mts +148 -0
  311. package/dist/optics/prism.mjs +197 -0
  312. package/dist/optics/refraction.d.mts +201 -0
  313. package/dist/optics/refraction.mjs +270 -0
  314. package/dist/optics/wave-optics.d.mts +171 -0
  315. package/dist/optics/wave-optics.mjs +259 -0
  316. package/dist/physics/ac/index.d.mts +183 -0
  317. package/dist/physics/ac/index.mjs +203 -0
  318. package/dist/physics/dynamics/forces.d.mts +98 -0
  319. package/dist/physics/dynamics/forces.mjs +153 -0
  320. package/dist/physics/dynamics/friction.d.mts +76 -0
  321. package/dist/physics/dynamics/friction.mjs +119 -0
  322. package/dist/physics/dynamics/system.d.mts +68 -0
  323. package/dist/physics/dynamics/system.mjs +125 -0
  324. package/dist/physics/electrostatics/index.d.mts +169 -0
  325. package/dist/physics/electrostatics/index.mjs +249 -0
  326. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  327. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  328. package/dist/physics/energy/conservation.d.mts +81 -0
  329. package/dist/physics/energy/conservation.mjs +129 -0
  330. package/dist/physics/energy/power.d.mts +90 -0
  331. package/dist/physics/energy/power.mjs +167 -0
  332. package/dist/physics/energy/spring.d.mts +73 -0
  333. package/dist/physics/energy/spring.mjs +129 -0
  334. package/dist/physics/energy/store.d.mts +63 -0
  335. package/dist/physics/energy/store.mjs +108 -0
  336. package/dist/physics/energy/theorem.d.mts +65 -0
  337. package/dist/physics/energy/theorem.mjs +113 -0
  338. package/dist/physics/energy/work.d.mts +114 -0
  339. package/dist/physics/energy/work.mjs +219 -0
  340. package/dist/physics/gravitation/body.d.mts +85 -0
  341. package/dist/physics/gravitation/body.mjs +168 -0
  342. package/dist/physics/gravitation/kepler.d.mts +127 -0
  343. package/dist/physics/gravitation/kepler.mjs +216 -0
  344. package/dist/physics/gravitation/law.d.mts +117 -0
  345. package/dist/physics/gravitation/law.mjs +175 -0
  346. package/dist/physics/gravitation/orbit.d.mts +119 -0
  347. package/dist/physics/gravitation/orbit.mjs +202 -0
  348. package/dist/physics/gravitation/potential.d.mts +114 -0
  349. package/dist/physics/gravitation/potential.mjs +202 -0
  350. package/dist/physics/gravitation/variation.d.mts +97 -0
  351. package/dist/physics/gravitation/variation.mjs +175 -0
  352. package/dist/physics/index.d.mts +35 -0
  353. package/dist/physics/index.mjs +36 -0
  354. package/dist/physics/integral-sweep.d.mts +63 -0
  355. package/dist/physics/integral-sweep.mjs +126 -0
  356. package/dist/physics/kinematics/equations.d.mts +47 -0
  357. package/dist/physics/kinematics/equations.mjs +126 -0
  358. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  359. package/dist/physics/kinematics/free-fall.mjs +71 -0
  360. package/dist/physics/kinematics/given.d.mts +16 -0
  361. package/dist/physics/kinematics/given.mjs +55 -0
  362. package/dist/physics/kinematics/roots.d.mts +41 -0
  363. package/dist/physics/kinematics/roots.mjs +72 -0
  364. package/dist/physics/kinematics/solve.d.mts +52 -0
  365. package/dist/physics/kinematics/solve.mjs +172 -0
  366. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  367. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  368. package/dist/physics/magnetism/flux.d.mts +94 -0
  369. package/dist/physics/magnetism/flux.mjs +313 -0
  370. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  371. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  372. package/dist/physics/magnetism/index.d.mts +12 -0
  373. package/dist/physics/magnetism/index.mjs +74 -0
  374. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  375. package/dist/physics/magnetism/lorentz.mjs +88 -0
  376. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  377. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  378. package/dist/physics/momentum/collide.d.mts +77 -0
  379. package/dist/physics/momentum/collide.mjs +115 -0
  380. package/dist/physics/momentum/impulse.d.mts +89 -0
  381. package/dist/physics/momentum/impulse.mjs +159 -0
  382. package/dist/physics/momentum/planar.d.mts +60 -0
  383. package/dist/physics/momentum/planar.mjs +110 -0
  384. package/dist/physics/projectile.d.mts +107 -0
  385. package/dist/physics/projectile.mjs +185 -0
  386. package/dist/physics/rotation/angular.d.mts +85 -0
  387. package/dist/physics/rotation/angular.mjs +130 -0
  388. package/dist/physics/rotation/circular.d.mts +79 -0
  389. package/dist/physics/rotation/circular.mjs +131 -0
  390. package/dist/physics/rotation/inertia.d.mts +164 -0
  391. package/dist/physics/rotation/inertia.mjs +332 -0
  392. package/dist/physics/rotation/torque.d.mts +65 -0
  393. package/dist/physics/rotation/torque.mjs +134 -0
  394. package/dist/physics/vectors.d.mts +64 -0
  395. package/dist/physics/vectors.mjs +114 -0
  396. package/dist/primitives/Dot.d.mts +2 -15
  397. package/dist/primitives/Dot.mjs +6 -4
  398. package/dist/primitives/Grid.d.mts +33 -17
  399. package/dist/primitives/Grid.mjs +89 -17
  400. package/dist/primitives/Label.d.mts +1 -14
  401. package/dist/primitives/Label.mjs +3 -2
  402. package/dist/primitives/Lines.d.mts +4 -32
  403. package/dist/primitives/Lines.mjs +10 -8
  404. package/dist/primitives/Shapes.d.mts +5 -43
  405. package/dist/primitives/Shapes.mjs +12 -10
  406. package/dist/primitives/index.d.mts +2 -2
  407. package/dist/primitives/index.mjs +2 -2
  408. package/dist/primitives/props.mjs +31 -0
  409. package/dist/quantity/index.d.mts +119 -0
  410. package/dist/quantity/index.mjs +417 -0
  411. package/dist/relation/derive.d.mts +74 -0
  412. package/dist/relation/derive.mjs +73 -0
  413. package/dist/relation/index.d.mts +56 -0
  414. package/dist/relation/index.mjs +234 -0
  415. package/dist/scene/Scene.d.mts +6 -1
  416. package/dist/scene/Scene.mjs +15 -40
  417. package/dist/scene/evaluators.mjs +1 -1
  418. package/dist/sim/thermal.mjs +45 -20
  419. package/dist/thermo/calorimetry.d.mts +207 -0
  420. package/dist/thermo/calorimetry.mjs +345 -0
  421. package/dist/thermo/cycles.d.mts +142 -0
  422. package/dist/thermo/cycles.mjs +256 -0
  423. package/dist/thermo/entropy.d.mts +87 -0
  424. package/dist/thermo/entropy.mjs +140 -0
  425. package/dist/thermo/expansion.d.mts +130 -0
  426. package/dist/thermo/expansion.mjs +178 -0
  427. package/dist/thermo/gas.d.mts +197 -0
  428. package/dist/thermo/gas.mjs +279 -0
  429. package/dist/thermo/heat-transfer.d.mts +164 -0
  430. package/dist/thermo/heat-transfer.mjs +217 -0
  431. package/dist/thermo/index.d.mts +9 -82
  432. package/dist/thermo/index.mjs +9 -132
  433. package/dist/thermo/processes.d.mts +95 -0
  434. package/dist/thermo/processes.mjs +154 -0
  435. package/dist/thermo/temperature.d.mts +174 -0
  436. package/dist/thermo/temperature.mjs +236 -0
  437. package/dist/view/Stage.mjs +4 -11
  438. package/dist/waves/damping.d.mts +224 -0
  439. package/dist/waves/damping.mjs +317 -0
  440. package/dist/waves/doppler.d.mts +72 -0
  441. package/dist/waves/doppler.mjs +125 -0
  442. package/dist/waves/index.d.mts +10 -0
  443. package/dist/waves/index.mjs +10 -0
  444. package/dist/waves/pendulum.d.mts +130 -0
  445. package/dist/waves/pendulum.mjs +211 -0
  446. package/dist/waves/pitch.d.mts +125 -0
  447. package/dist/waves/pitch.mjs +158 -0
  448. package/dist/waves/shm.d.mts +170 -0
  449. package/dist/waves/shm.mjs +279 -0
  450. package/dist/waves/springs.d.mts +103 -0
  451. package/dist/waves/springs.mjs +176 -0
  452. package/dist/waves/superposition.d.mts +124 -0
  453. package/dist/waves/superposition.mjs +196 -0
  454. package/dist/waves/wave.d.mts +154 -0
  455. package/dist/waves/wave.mjs +178 -0
  456. package/package.json +103 -23
  457. package/styles.css +125 -8
  458. package/dist/assets/kit/index.mjs +0 -4
@@ -0,0 +1,158 @@
1
+ //#region src/waves/pitch.ts
2
+ /**
3
+ * Pitch: turning a frequency into a note, and a note into a place on a string.
4
+ *
5
+ * ## Why pitch is logarithmic, and why that is not a convention
6
+ *
7
+ * Doubling a frequency sounds like the same step wherever you start. 220 to
8
+ * 440 Hz and 440 to 880 Hz are both "an octave", although the second gap is
9
+ * twice as many hertz. So the ear measures RATIOS, and anything that behaves
10
+ * like a distance in pitch has to be a logarithm of one.
11
+ *
12
+ * one octave = ratio 2 = 1200 cents
13
+ * one semitone = ratio 2^(1/12) = 100 cents
14
+ *
15
+ * A cent is a hundredth of a semitone and is the unit tuners actually use,
16
+ * because "three hertz flat" means something different on a bass string and a
17
+ * piccolo while "eight cents flat" means the same thing everywhere.
18
+ *
19
+ * ## The twelfth root of two, and what it costs
20
+ *
21
+ * Equal temperament divides the octave into twelve identical ratio steps. The
22
+ * price is that no interval except the octave is exactly a whole-number ratio:
23
+ *
24
+ * pure fifth (3:2) 701.955 cents
25
+ * equal-tempered fifth 700 cents
26
+ *
27
+ * Two cents flat, everywhere, forever. That deliberate two-cent error is what
28
+ * buys you the ability to change key, and it is the reason a guitar is fretted
29
+ * the way it is. `centsBetween` makes the compromise something you can measure
30
+ * rather than a claim.
31
+ *
32
+ * ## Frets are geometric, not evenly spaced
33
+ *
34
+ * A fret shortens the vibrating length by a RATIO, so the gaps shrink as you go
35
+ * up the neck. The twelfth fret is exactly halfway along the string, because
36
+ * halving the length doubles the frequency: 2^(−12/12) = 1/2. That is a fact
37
+ * you can check with a ruler on a real guitar, which is the best kind.
38
+ *
39
+ * Units: frequencies in hertz, lengths in metres (or any one consistent unit,
40
+ * since `fretPosition` is a proportion of what it is given).
41
+ */
42
+ const finite = (value, what) => {
43
+ if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
44
+ return value;
45
+ };
46
+ const positive = (value, what) => {
47
+ if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
48
+ return value;
49
+ };
50
+ /** Concert A, hertz. The peg the whole system hangs from, fixed by agreement rather than physics. */
51
+ const A4_HZ = 440;
52
+ /** The frequency ratio of one equal-tempered semitone: the twelfth root of two. */
53
+ const SEMITONE_RATIO = Math.pow(2, 1 / 12);
54
+ /** Cents in one octave. A cent is a hundredth of a semitone. */
55
+ const CENTS_PER_OCTAVE = 1200;
56
+ /**
57
+ * The frequency a given number of semitones away: f·2^(n/12).
58
+ *
59
+ * `n` may be negative for downward, and need not be a whole number: a
60
+ * half-semitone is a perfectly good quarter tone, and bending a guitar string
61
+ * lands you between the frets.
62
+ */
63
+ const frequencyAfterSemitones = (frequency, semitones) => positive(frequency, "A frequency") * Math.pow(2, finite(semitones, "A number of semitones") / 12);
64
+ /** How many semitones apart two frequencies are: 12·log₂(f₂/f₁). Signed. */
65
+ const semitonesBetween = (from, to) => 12 * Math.log2(positive(to, "A frequency") / positive(from, "A frequency"));
66
+ /**
67
+ * The interval between two frequencies in CENTS: 1200·log₂(f₂/f₁).
68
+ *
69
+ * Signed, so a negative result means `to` is flat of `from`. The numbers worth
70
+ * carrying: about 5 cents is the smallest error most people hear on a sustained
71
+ * note, 10 to 15 cents sounds wrong, and a semitone is 100.
72
+ *
73
+ * This is the function that makes "how out of tune is it" answerable. A gap of
74
+ * 3 Hz is badly out on a low E at 82 Hz and inaudible on a harmonic at 1300 Hz;
75
+ * in cents both questions have the same answer scale.
76
+ */
77
+ const centsBetween = (from, to) => CENTS_PER_OCTAVE * Math.log2(positive(to, "A frequency") / positive(from, "A frequency"));
78
+ /** The frequency a number of cents away from a reference. The inverse of `centsBetween`. */
79
+ const frequencyAfterCents = (frequency, cents) => positive(frequency, "A frequency") * Math.pow(2, finite(cents, "An interval in cents") / CENTS_PER_OCTAVE);
80
+ /**
81
+ * Whether a frequency counts as in tune against a target.
82
+ *
83
+ * `toleranceCents` defaults to 5, which is roughly the threshold at which a
84
+ * sustained note starts to sound wrong to an ordinary listener. Expressed in
85
+ * cents rather than hertz on purpose: a fixed hertz tolerance would be far too
86
+ * strict at the top of the range and useless at the bottom.
87
+ */
88
+ const isInTune = (frequency, target, toleranceCents = 5) => Math.abs(centsBetween(target, frequency)) <= positive(toleranceCents, "A tolerance");
89
+ /**
90
+ * The length of string still free to vibrate when a fret is held down.
91
+ *
92
+ * `L·2^(−n/12)`: each fret divides the length by the same ratio, which is why
93
+ * they crowd together going up the neck.
94
+ */
95
+ const frettedLength = (scaleLength, fret) => positive(scaleLength, "A scale length") * Math.pow(2, -nonNegativeFret(fret) / 12);
96
+ /**
97
+ * How far along the string a fret sits, measured from the nut.
98
+ *
99
+ * `L(1 − 2^(−n/12))`. Fret 12 comes out at exactly L/2, which is the check that
100
+ * the formula is the right way round and the thing to verify against a real
101
+ * instrument.
102
+ */
103
+ const fretPosition = (scaleLength, fret) => positive(scaleLength, "A scale length") - frettedLength(scaleLength, fret);
104
+ /** The gap between two consecutive frets. Always smaller than the one below it. */
105
+ const fretSpacing = (scaleLength, fret) => fretPosition(scaleLength, nonNegativeFret(fret) + 1) - fretPosition(scaleLength, fret);
106
+ function nonNegativeFret(fret) {
107
+ if (!Number.isInteger(fret) || fret < 0) throw new RangeError(`A fret number must be a whole number of at least 0, not ${fret}.`);
108
+ return fret;
109
+ }
110
+ /** The names of the twelve semitones, starting at C. Sharps only; no enharmonic choice is made. */
111
+ const SEMITONE_NAMES = [
112
+ "C",
113
+ "C♯",
114
+ "D",
115
+ "D♯",
116
+ "E",
117
+ "F",
118
+ "F♯",
119
+ "G",
120
+ "G♯",
121
+ "A",
122
+ "A♯",
123
+ "B"
124
+ ];
125
+ /**
126
+ * The nearest named note to a frequency, and how far off it is.
127
+ *
128
+ * Returns the note with its octave number in scientific pitch notation (A4 is
129
+ * concert A), plus the signed error in cents. The error is the useful half: a
130
+ * tuner is a device for driving that number to zero.
131
+ */
132
+ function nearestNote(frequency) {
133
+ const exact = semitonesBetween(440, positive(frequency, "A frequency"));
134
+ const steps = Math.round(exact);
135
+ const cents = (exact - steps) * 100;
136
+ const fromC0 = steps + 9 + 48;
137
+ const octave = Math.floor(fromC0 / 12);
138
+ return {
139
+ name: SEMITONE_NAMES[(fromC0 % 12 + 12) % 12],
140
+ octave,
141
+ cents
142
+ };
143
+ }
144
+ /**
145
+ * The size of a just interval in cents, for comparison with the tempered one.
146
+ *
147
+ * `justIntervalCents(3, 2)` is the pure fifth at 701.955, against the
148
+ * equal-tempered 700. Feeding the small whole-number ratios through this is how
149
+ * the compromise in equal temperament stops being a story: the major third is
150
+ * the bad one, 386.3 just against 400 tempered, nearly 14 cents sharp, and it
151
+ * is audible.
152
+ */
153
+ const justIntervalCents = (numerator, denominator) => CENTS_PER_OCTAVE * Math.log2(positive(numerator, "A ratio numerator") / positive(denominator, "A ratio denominator"));
154
+ /** The equal-tempered size of an interval of `semitones`, in cents. Always a multiple of 100. */
155
+ const temperedIntervalCents = (semitones) => 100 * finite(semitones, "A number of semitones");
156
+
157
+ //#endregion
158
+ export { A4_HZ, CENTS_PER_OCTAVE, SEMITONE_NAMES, SEMITONE_RATIO, centsBetween, frequencyAfterCents, frequencyAfterSemitones, fretPosition, fretSpacing, frettedLength, isInTune, justIntervalCents, nearestNote, semitonesBetween, temperedIntervalCents };
@@ -0,0 +1,170 @@
1
+ import { Worked } from "../core/worked.mjs";
2
+
3
+ //#region src/waves/shm.d.ts
4
+ /** Angular frequency from a period: ω = 2π/T, rad/s. */
5
+ declare const angularFrequencyFromPeriod: (periodSeconds: number) => number;
6
+ /** Period from an angular frequency: T = 2π/ω, seconds. */
7
+ declare const periodFromAngularFrequency: (omega: number) => number;
8
+ /**
9
+ * Displacement at time t, starting from the CENTRE moving positive:
10
+ * x = A·sin(ωt + φ).
11
+ *
12
+ * Pass `phase = π/2` to start at maximum displacement instead, which is what a
13
+ * released-from-rest problem describes. Two starting conventions exist and both
14
+ * are called "the" SHM equation in different books, so the phase is explicit
15
+ * rather than baked in.
16
+ */
17
+ declare function shmDisplacement(amplitude: number, omega: number, t: number, phase?: number): number;
18
+ /** Velocity at time t: v = ωA·cos(ωt + φ), m/s. */
19
+ declare function shmVelocity(amplitude: number, omega: number, t: number, phase?: number): number;
20
+ /** Acceleration at time t: a = −ω²x, m/s². */
21
+ declare function shmAcceleration(amplitude: number, omega: number, t: number, phase?: number): number;
22
+ /**
23
+ * SPEED at a displacement, m/s: v = ω√(A² − x²).
24
+ *
25
+ * The workhorse. Independent of time and of where the motion started, so it
26
+ * answers "how fast at half amplitude" without anyone having to find t first.
27
+ * Returns the magnitude; the oscillator passes each point twice a cycle, once
28
+ * each way, and which one is a question about direction rather than speed.
29
+ */
30
+ declare function speedAtDisplacement(amplitude: number, omega: number, displacement: number): number;
31
+ /** The displacement at which the oscillator reaches a given speed, m. */
32
+ declare function displacementAtSpeed(amplitude: number, omega: number, speed: number): number;
33
+ /** Greatest speed, at the centre: v_max = ωA, m/s. */
34
+ declare const maxSpeed: (amplitude: number, omega: number) => number;
35
+ /** Greatest acceleration, at the extremes: a_max = ω²A, m/s². */
36
+ declare const maxAcceleration: (amplitude: number, omega: number) => number;
37
+ interface OscillatorState {
38
+ /** Displacement, m. */
39
+ displacement: number;
40
+ /** Velocity, m/s. Signed: the direction of travel is the point of it. */
41
+ velocity: number;
42
+ /** Acceleration, m/s². Always −ω² times the displacement. */
43
+ acceleration: number;
44
+ /** The phase ωt + φ at this instant, radians, unwrapped. */
45
+ phase: number;
46
+ }
47
+ /**
48
+ * Displacement, velocity and acceleration at one instant, in one call.
49
+ *
50
+ * ## Why this exists rather than three calls
51
+ *
52
+ * Because the three are ONE object, and anything that draws them has to draw
53
+ * them from the same instant or the picture lies. A render loop asking for
54
+ * displacement, then velocity, then acceleration is three chances to pass a
55
+ * different `t`, and the symptom is a v–t curve that is no longer a quarter
56
+ * cycle ahead of the x–t one: a phase error that looks like a physics error.
57
+ *
58
+ * ## The chain the three form
59
+ *
60
+ * x = A·sin(ωt + φ)
61
+ * v = ωA·cos(ωt + φ) a quarter cycle AHEAD of x
62
+ * a = −ω²A·sin(ωt + φ) a quarter cycle ahead of v, so ANTIPHASE with x
63
+ *
64
+ * Each differentiation multiplies by ω and advances the phase by π/2. Two of
65
+ * them bring you back to a sine with a minus sign in front, which is the whole
66
+ * of a = −ω²x: the defining property of the motion falls out of differentiating
67
+ * twice and is not an extra assumption.
68
+ *
69
+ * `tests/waves/shm.test.ts` asserts each quarter-cycle lead against the others
70
+ * rather than against a formula, so the chain cannot be broken in one place
71
+ * only.
72
+ */
73
+ declare function oscillatorStateAt(amplitude: number, omega: number, t: number, phase?: number): OscillatorState;
74
+ interface OscillatorEnergy {
75
+ /** Kinetic energy at this displacement, J. */
76
+ kinetic: number;
77
+ /** Potential energy at this displacement, J. */
78
+ potential: number;
79
+ /** The total, J. The same number at every displacement. */
80
+ total: number;
81
+ /**
82
+ * kinetic + potential − total, J.
83
+ *
84
+ * Reported rather than asserted, following the same choice the energy ledger
85
+ * makes elsewhere in this package: it must be zero to within rounding, and a
86
+ * caller who wants to PROVE conservation gets to see the number rather than
87
+ * take it on trust.
88
+ */
89
+ residual: number;
90
+ /** Fraction of the total that is kinetic, 0 to 1. */
91
+ kineticFraction: number;
92
+ }
93
+ /**
94
+ * The energy split at a displacement.
95
+ *
96
+ * At x = 0 it is all kinetic, at x = ±A all potential, and at x = A/√2 exactly
97
+ * half each — which is the answer to "where is the energy shared equally" and
98
+ * is NOT at half amplitude, the usual guess.
99
+ */
100
+ declare function energyAt(mass: number, amplitude: number, omega: number, displacement: number): OscillatorEnergy;
101
+ /** Total energy of the oscillation, J: E = ½mω²A². Independent of position. */
102
+ declare const totalEnergy: (mass: number, amplitude: number, omega: number) => number;
103
+ /**
104
+ * The displacement at which kinetic and potential are equal: x = A/√2.
105
+ *
106
+ * About 0.707 of the amplitude, not 0.5. The energies go as x², so the halfway
107
+ * point in ENERGY is not the halfway point in distance, and that gap is the
108
+ * whole lesson.
109
+ */
110
+ declare const equalEnergyDisplacement: (amplitude: number) => number;
111
+ /**
112
+ * The energy split at a displacement, worked, in the form the question wants.
113
+ *
114
+ * Deliberately arrives at the same three numbers by TWO routes and shows both:
115
+ * ½mω²(A² − x²) directly, and ½mv² from the speed at that point. They must
116
+ * agree, and seeing them agree is the argument that the energy picture and the
117
+ * kinematic picture are one thing rather than two topics.
118
+ *
119
+ * The final step reports KE + PE against the total rather than asserting that
120
+ * they match, which is the same choice the energy ledger makes elsewhere in the
121
+ * package: conservation is evidence here, not a claim.
122
+ */
123
+ declare function energyAtSteps(mass: number, amplitude: number, omega: number, displacement: number, sf?: number): Worked;
124
+ /**
125
+ * Period of a mass on a spring: T = 2π√(m/k), seconds.
126
+ *
127
+ * Independent of amplitude, which is the surprising part and the practical one:
128
+ * a spring clock keeps time even as the swing dies away.
129
+ */
130
+ declare const springPeriod: (mass: number, stiffness: number) => number;
131
+ /** Angular frequency of a mass on a spring: ω = √(k/m), rad/s. */
132
+ declare const springAngularFrequency: (mass: number, stiffness: number) => number;
133
+ /**
134
+ * The period of the ENERGY, seconds: half the period of the motion.
135
+ *
136
+ * The single most reliable trap in the topic. Kinetic energy goes as cos²(ωt),
137
+ * and a squared sinusoid repeats twice as often as the sinusoid does: the
138
+ * oscillator is at full speed at the centre going one way AND going the other,
139
+ * and the energy cannot tell those apart because it does not carry a sign.
140
+ *
141
+ * So a question that gives you an energy-against-time graph and asks for the
142
+ * period of the MOTION wants twice what the graph shows. Reading the graph's
143
+ * own period straight off is the wrong answer, and it is wrong by exactly the
144
+ * factor this function applies.
145
+ */
146
+ declare const energyPeriod: (period: number) => number;
147
+ /**
148
+ * The amplitude implied by a displacement and a velocity at the same moment:
149
+ * A = √(x² + (v/ω)²).
150
+ *
151
+ * v = ω√(A² − x²) rearranged. Any snapshot of the motion fixes the amplitude,
152
+ * which is how a question that never mentions an amplitude can still be asking
153
+ * for the total energy.
154
+ */
155
+ declare function amplitudeFromState(omega: number, displacement: number, velocity: number): number;
156
+ /**
157
+ * The phase angle δ in x = A·sin(ωt + δ), from the state at t = 0.
158
+ *
159
+ * Returned in radians on (−π, π]. Uses `atan2` on (xω, v) rather than
160
+ * `asin(x₀/A)`, and that choice is the whole function: `asin` cannot tell a
161
+ * mass at +A/2 moving outward from one at +A/2 moving back, because they share
162
+ * a sine and differ only in the sign of the cosine. Half the answers from the
163
+ * `asin` route are the wrong one of the two, silently.
164
+ *
165
+ * The familiar special cases fall out: released from rest at full displacement
166
+ * gives π/2, so x = A·cos(ωt); started from the centre moving positive gives 0.
167
+ */
168
+ declare function phaseFromState(omega: number, displacement: number, velocity: number): number;
169
+ //#endregion
170
+ export { OscillatorEnergy, OscillatorState, amplitudeFromState, angularFrequencyFromPeriod, displacementAtSpeed, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, maxAcceleration, maxSpeed, oscillatorStateAt, periodFromAngularFrequency, phaseFromState, shmAcceleration, shmDisplacement, shmVelocity, speedAtDisplacement, springAngularFrequency, springPeriod, totalEnergy };
@@ -0,0 +1,279 @@
1
+ import { calc, texNum, texSigFigs } from "../core/worked.mjs";
2
+
3
+ //#region src/waves/shm.ts
4
+ /**
5
+ * Simple harmonic motion, and the energy bookkeeping that goes with it.
6
+ *
7
+ * ## The definition, which is the acceleration and not the sine
8
+ *
9
+ * a = −ω²x
10
+ *
11
+ * Acceleration proportional to displacement and directed back towards the
12
+ * centre. The sinusoid is a CONSEQUENCE of that, not the definition, and the
13
+ * distinction matters: a pendulum at large amplitude still swings back and
14
+ * forth sinusoidally to the eye, but its acceleration stops being proportional
15
+ * to displacement and its period starts depending on amplitude. The defining
16
+ * property is the one that fails first.
17
+ *
18
+ * ## The relation this module exists for
19
+ *
20
+ * v = ±ω·√(A² − x²)
21
+ *
22
+ * Speed as a function of POSITION rather than of time. Nearly every question
23
+ * that asks "how fast is it moving when it is halfway out" is this, and it is
24
+ * the bridge to energy: square it, multiply by ½m, and the kinetic energy falls
25
+ * out as ½mω²(A² − x²). The potential is whatever is left of the total, and the
26
+ * total is constant. That is conservation, visible as arithmetic rather than
27
+ * asserted.
28
+ *
29
+ * KE = ½mω²(A² − x²) max at the centre, zero at the extremes
30
+ * PE = ½mω²x² zero at the centre, max at the extremes
31
+ * E = ½mω²A² constant, independent of x
32
+ *
33
+ * Note KE + PE = ½mω²A² identically, for every x. `energyAt` returns all three
34
+ * and the residual, so a lab can SHOW the sum staying put while the two halves
35
+ * trade, rather than claiming it does.
36
+ *
37
+ * ## Scope
38
+ *
39
+ * The IDEAL oscillator: no damping, no driving, and given its ω rather than
40
+ * working one out. The three modules either side of it cover the rest:
41
+ *
42
+ * springs where k comes from, and what happens when springs are combined
43
+ * pendulum the pendulum family, which is a clock, a gravimeter and a lift
44
+ * damping what real oscillators do, which is stop
45
+ *
46
+ * They are separate because the failures are separate. Nothing in this file can
47
+ * be wrong about a spring that was cut in half, and nothing in `springs` can be
48
+ * wrong about where the energy went.
49
+ *
50
+ * Units: SI. Displacement and amplitude in metres, mass in kilograms, time in
51
+ * seconds, ω in radians per second, energy in joules.
52
+ */
53
+ const finite = (value, what) => {
54
+ if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
55
+ return value;
56
+ };
57
+ const positive = (value, what) => {
58
+ if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${what} must be positive.`);
59
+ return value;
60
+ };
61
+ /**
62
+ * Check a displacement lies within the amplitude.
63
+ *
64
+ * An oscillator cannot be found beyond its own amplitude, and asking for the
65
+ * speed there gives the square root of a negative number. Returning NaN would
66
+ * let an impossible position travel silently into a graph; the throw says which
67
+ * number was wrong.
68
+ */
69
+ const within = (displacement, amplitude) => {
70
+ const x = finite(displacement, "A displacement");
71
+ const A = positive(amplitude, "An amplitude");
72
+ if (Math.abs(x) > A * 1.000000000001) throw new RangeError(`A displacement of ${x} lies outside the amplitude ${A}: the oscillator never reaches there.`);
73
+ return Math.max(-A, Math.min(A, x));
74
+ };
75
+ /** Angular frequency from a period: ω = 2π/T, rad/s. */
76
+ const angularFrequencyFromPeriod = (periodSeconds) => 2 * Math.PI / positive(periodSeconds, "A period");
77
+ /** Period from an angular frequency: T = 2π/ω, seconds. */
78
+ const periodFromAngularFrequency = (omega) => 2 * Math.PI / positive(omega, "An angular frequency");
79
+ /**
80
+ * Displacement at time t, starting from the CENTRE moving positive:
81
+ * x = A·sin(ωt + φ).
82
+ *
83
+ * Pass `phase = π/2` to start at maximum displacement instead, which is what a
84
+ * released-from-rest problem describes. Two starting conventions exist and both
85
+ * are called "the" SHM equation in different books, so the phase is explicit
86
+ * rather than baked in.
87
+ */
88
+ function shmDisplacement(amplitude, omega, t, phase = 0) {
89
+ return positive(amplitude, "An amplitude") * Math.sin(positive(omega, "An angular frequency") * finite(t, "A time") + finite(phase, "A phase"));
90
+ }
91
+ /** Velocity at time t: v = ωA·cos(ωt + φ), m/s. */
92
+ function shmVelocity(amplitude, omega, t, phase = 0) {
93
+ const w = positive(omega, "An angular frequency");
94
+ return w * positive(amplitude, "An amplitude") * Math.cos(w * finite(t, "A time") + finite(phase, "A phase"));
95
+ }
96
+ /** Acceleration at time t: a = −ω²x, m/s². */
97
+ function shmAcceleration(amplitude, omega, t, phase = 0) {
98
+ const w = positive(omega, "An angular frequency");
99
+ return -(w * w) * shmDisplacement(amplitude, w, t, phase);
100
+ }
101
+ /**
102
+ * SPEED at a displacement, m/s: v = ω√(A² − x²).
103
+ *
104
+ * The workhorse. Independent of time and of where the motion started, so it
105
+ * answers "how fast at half amplitude" without anyone having to find t first.
106
+ * Returns the magnitude; the oscillator passes each point twice a cycle, once
107
+ * each way, and which one is a question about direction rather than speed.
108
+ */
109
+ function speedAtDisplacement(amplitude, omega, displacement) {
110
+ const A = positive(amplitude, "An amplitude");
111
+ const x = within(displacement, A);
112
+ return positive(omega, "An angular frequency") * Math.sqrt(A * A - x * x);
113
+ }
114
+ /** The displacement at which the oscillator reaches a given speed, m. */
115
+ function displacementAtSpeed(amplitude, omega, speed) {
116
+ const A = positive(amplitude, "An amplitude");
117
+ const w = positive(omega, "An angular frequency");
118
+ const s = finite(speed, "A speed");
119
+ const maximum = w * A;
120
+ if (Math.abs(s) > maximum * 1.000000000001) throw new RangeError(`This oscillator never exceeds ${maximum} m/s, so it is never moving at ${s} m/s.`);
121
+ return Math.sqrt(Math.max(0, A * A - (s / w) ** 2));
122
+ }
123
+ /** Greatest speed, at the centre: v_max = ωA, m/s. */
124
+ const maxSpeed = (amplitude, omega) => positive(omega, "An angular frequency") * positive(amplitude, "An amplitude");
125
+ /** Greatest acceleration, at the extremes: a_max = ω²A, m/s². */
126
+ const maxAcceleration = (amplitude, omega) => positive(omega, "An angular frequency") ** 2 * positive(amplitude, "An amplitude");
127
+ /**
128
+ * Displacement, velocity and acceleration at one instant, in one call.
129
+ *
130
+ * ## Why this exists rather than three calls
131
+ *
132
+ * Because the three are ONE object, and anything that draws them has to draw
133
+ * them from the same instant or the picture lies. A render loop asking for
134
+ * displacement, then velocity, then acceleration is three chances to pass a
135
+ * different `t`, and the symptom is a v–t curve that is no longer a quarter
136
+ * cycle ahead of the x–t one: a phase error that looks like a physics error.
137
+ *
138
+ * ## The chain the three form
139
+ *
140
+ * x = A·sin(ωt + φ)
141
+ * v = ωA·cos(ωt + φ) a quarter cycle AHEAD of x
142
+ * a = −ω²A·sin(ωt + φ) a quarter cycle ahead of v, so ANTIPHASE with x
143
+ *
144
+ * Each differentiation multiplies by ω and advances the phase by π/2. Two of
145
+ * them bring you back to a sine with a minus sign in front, which is the whole
146
+ * of a = −ω²x: the defining property of the motion falls out of differentiating
147
+ * twice and is not an extra assumption.
148
+ *
149
+ * `tests/waves/shm.test.ts` asserts each quarter-cycle lead against the others
150
+ * rather than against a formula, so the chain cannot be broken in one place
151
+ * only.
152
+ */
153
+ function oscillatorStateAt(amplitude, omega, t, phase = 0) {
154
+ const A = positive(amplitude, "An amplitude");
155
+ const w = positive(omega, "An angular frequency");
156
+ const angle = w * finite(t, "A time") + finite(phase, "A phase");
157
+ const displacement = A * Math.sin(angle);
158
+ return {
159
+ displacement,
160
+ velocity: w * A * Math.cos(angle),
161
+ acceleration: -(w * w) * displacement,
162
+ phase: angle
163
+ };
164
+ }
165
+ /**
166
+ * The energy split at a displacement.
167
+ *
168
+ * At x = 0 it is all kinetic, at x = ±A all potential, and at x = A/√2 exactly
169
+ * half each — which is the answer to "where is the energy shared equally" and
170
+ * is NOT at half amplitude, the usual guess.
171
+ */
172
+ function energyAt(mass, amplitude, omega, displacement) {
173
+ const m = positive(mass, "A mass");
174
+ const A = positive(amplitude, "An amplitude");
175
+ const w = positive(omega, "An angular frequency");
176
+ const x = within(displacement, A);
177
+ const half = .5 * m * w * w;
178
+ const kinetic = half * (A * A - x * x);
179
+ const potential = half * x * x;
180
+ const total = half * A * A;
181
+ return {
182
+ kinetic,
183
+ potential,
184
+ total,
185
+ residual: kinetic + potential - total,
186
+ kineticFraction: total === 0 ? 0 : kinetic / total
187
+ };
188
+ }
189
+ /** Total energy of the oscillation, J: E = ½mω²A². Independent of position. */
190
+ const totalEnergy = (mass, amplitude, omega) => .5 * positive(mass, "A mass") * positive(omega, "An angular frequency") ** 2 * positive(amplitude, "An amplitude") ** 2;
191
+ /**
192
+ * The displacement at which kinetic and potential are equal: x = A/√2.
193
+ *
194
+ * About 0.707 of the amplitude, not 0.5. The energies go as x², so the halfway
195
+ * point in ENERGY is not the halfway point in distance, and that gap is the
196
+ * whole lesson.
197
+ */
198
+ const equalEnergyDisplacement = (amplitude) => positive(amplitude, "An amplitude") / Math.SQRT2;
199
+ /**
200
+ * The energy split at a displacement, worked, in the form the question wants.
201
+ *
202
+ * Deliberately arrives at the same three numbers by TWO routes and shows both:
203
+ * ½mω²(A² − x²) directly, and ½mv² from the speed at that point. They must
204
+ * agree, and seeing them agree is the argument that the energy picture and the
205
+ * kinematic picture are one thing rather than two topics.
206
+ *
207
+ * The final step reports KE + PE against the total rather than asserting that
208
+ * they match, which is the same choice the energy ledger makes elsewhere in the
209
+ * package: conservation is evidence here, not a claim.
210
+ */
211
+ function energyAtSteps(mass, amplitude, omega, displacement, sf = 3) {
212
+ const m = positive(mass, "A mass");
213
+ const A = positive(amplitude, "An amplitude");
214
+ const w = positive(omega, "An angular frequency");
215
+ const x = within(displacement, A);
216
+ const split = energyAt(m, A, w, x);
217
+ const v = speedAtDisplacement(A, w, x);
218
+ const stiffness = m * w * w;
219
+ return calc().step(`v = \\omega\\sqrt{A^2 - x^2} = ${texSigFigs(w, sf)}\\sqrt{${texSigFigs(A, sf)}^2 - ${texSigFigs(x, sf)}^2} = ${texSigFigs(v, sf)}\\ \\mathrm{m\\,s^{-1}}`, "speed from POSITION, so the time never has to be found").step(`E_k = \\tfrac{1}{2}mv^2 = ${texSigFigs(split.kinetic, sf)}\\ \\mathrm{J}`, "the kinematic route").step(`E_k = \\tfrac{1}{2}m\\omega^2(A^2 - x^2) = ${texSigFigs(split.kinetic, sf)}\\ \\mathrm{J}`, "and the energy route, which is the same statement with v substituted").step(`E_p = \\tfrac{1}{2}m\\omega^2 x^2 = \\tfrac{1}{2}kx^2 = ${texSigFigs(split.potential, sf)}\\ \\mathrm{J}`, `with k = m\\omega^2 = ${texSigFigs(stiffness, sf)}\\ \\mathrm{N\\,m^{-1}}, the spring form of the same energy`).step(`E = \\tfrac{1}{2}m\\omega^2 A^2 = ${texSigFigs(split.total, sf)}\\ \\mathrm{J}`, "independent of x: this number is the same everywhere in the swing").step(`E_k + E_p - E = ${texNum(split.residual)}\\ \\mathrm{J}`, "the books balance, and the residual is shown rather than the balance claimed").done(split.total);
220
+ }
221
+ /**
222
+ * Period of a mass on a spring: T = 2π√(m/k), seconds.
223
+ *
224
+ * Independent of amplitude, which is the surprising part and the practical one:
225
+ * a spring clock keeps time even as the swing dies away.
226
+ */
227
+ const springPeriod = (mass, stiffness) => 2 * Math.PI * Math.sqrt(positive(mass, "A mass") / positive(stiffness, "A spring stiffness"));
228
+ /** Angular frequency of a mass on a spring: ω = √(k/m), rad/s. */
229
+ const springAngularFrequency = (mass, stiffness) => Math.sqrt(positive(stiffness, "A spring stiffness") / positive(mass, "A mass"));
230
+ /**
231
+ * The period of the ENERGY, seconds: half the period of the motion.
232
+ *
233
+ * The single most reliable trap in the topic. Kinetic energy goes as cos²(ωt),
234
+ * and a squared sinusoid repeats twice as often as the sinusoid does: the
235
+ * oscillator is at full speed at the centre going one way AND going the other,
236
+ * and the energy cannot tell those apart because it does not carry a sign.
237
+ *
238
+ * So a question that gives you an energy-against-time graph and asks for the
239
+ * period of the MOTION wants twice what the graph shows. Reading the graph's
240
+ * own period straight off is the wrong answer, and it is wrong by exactly the
241
+ * factor this function applies.
242
+ */
243
+ const energyPeriod = (period) => positive(period, "A period") / 2;
244
+ /**
245
+ * The amplitude implied by a displacement and a velocity at the same moment:
246
+ * A = √(x² + (v/ω)²).
247
+ *
248
+ * v = ω√(A² − x²) rearranged. Any snapshot of the motion fixes the amplitude,
249
+ * which is how a question that never mentions an amplitude can still be asking
250
+ * for the total energy.
251
+ */
252
+ function amplitudeFromState(omega, displacement, velocity) {
253
+ const w = positive(omega, "An angular frequency");
254
+ const x = finite(displacement, "A displacement");
255
+ const v = finite(velocity, "A velocity");
256
+ return Math.hypot(x, v / w);
257
+ }
258
+ /**
259
+ * The phase angle δ in x = A·sin(ωt + δ), from the state at t = 0.
260
+ *
261
+ * Returned in radians on (−π, π]. Uses `atan2` on (xω, v) rather than
262
+ * `asin(x₀/A)`, and that choice is the whole function: `asin` cannot tell a
263
+ * mass at +A/2 moving outward from one at +A/2 moving back, because they share
264
+ * a sine and differ only in the sign of the cosine. Half the answers from the
265
+ * `asin` route are the wrong one of the two, silently.
266
+ *
267
+ * The familiar special cases fall out: released from rest at full displacement
268
+ * gives π/2, so x = A·cos(ωt); started from the centre moving positive gives 0.
269
+ */
270
+ function phaseFromState(omega, displacement, velocity) {
271
+ const w = positive(omega, "An angular frequency");
272
+ const x = finite(displacement, "A displacement");
273
+ const v = finite(velocity, "A velocity");
274
+ if (x === 0 && v === 0) throw new RangeError("An oscillator at rest at the centre has no phase: it is not oscillating.");
275
+ return Math.atan2(x * w, v);
276
+ }
277
+
278
+ //#endregion
279
+ export { amplitudeFromState, angularFrequencyFromPeriod, displacementAtSpeed, energyAt, energyAtSteps, energyPeriod, equalEnergyDisplacement, maxAcceleration, maxSpeed, oscillatorStateAt, periodFromAngularFrequency, phaseFromState, shmAcceleration, shmDisplacement, shmVelocity, speedAtDisplacement, springAngularFrequency, springPeriod, totalEnergy };