@classytic/stage 0.3.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 (431) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/atomic/aufbau.d.mts +144 -0
  3. package/dist/atomic/aufbau.mjs +384 -0
  4. package/dist/atomic/elements.d.mts +67 -0
  5. package/dist/atomic/elements.mjs +785 -0
  6. package/dist/atomic/emission.d.mts +112 -0
  7. package/dist/atomic/emission.mjs +179 -0
  8. package/dist/atomic/index.d.mts +8 -0
  9. package/dist/atomic/index.mjs +9 -0
  10. package/dist/atomic/periodic.d.mts +82 -0
  11. package/dist/atomic/periodic.mjs +231 -0
  12. package/dist/atomic/properties.d.mts +100 -0
  13. package/dist/atomic/properties.mjs +574 -0
  14. package/dist/atomic/shells.d.mts +137 -0
  15. package/dist/atomic/shells.mjs +170 -0
  16. package/dist/atomic/trends.d.mts +148 -0
  17. package/dist/atomic/trends.mjs +225 -0
  18. package/dist/chem/chromatography.d.mts +66 -0
  19. package/dist/chem/chromatography.mjs +63 -0
  20. package/dist/chem/complex.d.mts +114 -0
  21. package/dist/chem/complex.mjs +234 -0
  22. package/dist/chem/cycle.d.mts +75 -0
  23. package/dist/chem/cycle.mjs +145 -0
  24. package/dist/chem/equation.d.mts +86 -0
  25. package/dist/chem/equation.mjs +168 -0
  26. package/dist/chem/formula.d.mts +90 -0
  27. package/dist/chem/formula.mjs +201 -0
  28. package/dist/chem/functional-groups.d.mts +31 -0
  29. package/dist/chem/functional-groups.mjs +187 -0
  30. package/dist/chem/hazard.d.mts +94 -0
  31. package/dist/chem/hazard.mjs +329 -0
  32. package/dist/chem/index.d.mts +34 -33
  33. package/dist/chem/index.mjs +34 -28
  34. package/dist/chem/ionic.d.mts +98 -0
  35. package/dist/chem/ionic.mjs +156 -0
  36. package/dist/chem/layout.d.mts +46 -0
  37. package/dist/chem/layout.mjs +342 -0
  38. package/dist/chem/lewis.d.mts +79 -0
  39. package/dist/chem/lewis.mjs +163 -0
  40. package/dist/chem/molecular-orbital.d.mts +114 -0
  41. package/dist/chem/molecular-orbital.mjs +201 -0
  42. package/dist/chem/molecule.d.mts +154 -0
  43. package/dist/chem/molecule.mjs +282 -0
  44. package/dist/chem/nmr.d.mts +153 -0
  45. package/dist/chem/nmr.mjs +165 -0
  46. package/dist/chem/polymer.d.mts +65 -0
  47. package/dist/chem/polymer.mjs +179 -0
  48. package/dist/chem/redox.d.mts +138 -0
  49. package/dist/chem/redox.mjs +328 -0
  50. package/dist/chem/relations.d.mts +183 -0
  51. package/dist/chem/relations.mjs +299 -0
  52. package/dist/chem/skeleton.d.mts +51 -0
  53. package/dist/chem/skeleton.mjs +186 -0
  54. package/dist/chem/solution.d.mts +116 -0
  55. package/dist/chem/solution.mjs +186 -0
  56. package/dist/chem/species.d.mts +47 -0
  57. package/dist/chem/species.mjs +128 -0
  58. package/dist/chem/stereo.d.mts +108 -0
  59. package/dist/chem/stereo.mjs +286 -0
  60. package/dist/chem/stoichiometry.d.mts +95 -0
  61. package/dist/chem/stoichiometry.mjs +145 -0
  62. package/dist/chem/synthesis.d.mts +113 -0
  63. package/dist/chem/synthesis.mjs +281 -0
  64. package/dist/chem/vsepr.d.mts +80 -0
  65. package/dist/chem/vsepr.mjs +247 -0
  66. package/dist/circuit/ac.d.mts +163 -0
  67. package/dist/circuit/ac.mjs +452 -0
  68. package/dist/circuit/dc.d.mts +92 -0
  69. package/dist/circuit/dc.mjs +333 -0
  70. package/dist/circuit/index.d.mts +5 -92
  71. package/dist/circuit/index.mjs +5 -332
  72. package/dist/circuit/network.d.mts +99 -0
  73. package/dist/circuit/network.mjs +440 -0
  74. package/dist/circuit/topology.d.mts +102 -0
  75. package/dist/circuit/topology.mjs +143 -0
  76. package/dist/colour/absorption.d.mts +79 -0
  77. package/dist/colour/absorption.mjs +137 -0
  78. package/dist/colour/index.d.mts +6 -0
  79. package/dist/colour/index.mjs +7 -0
  80. package/dist/colour/name.d.mts +14 -0
  81. package/dist/colour/name.mjs +76 -0
  82. package/dist/colour/observer.d.mts +31 -0
  83. package/dist/colour/observer.mjs +46 -0
  84. package/dist/colour/spectrum.d.mts +61 -0
  85. package/dist/colour/spectrum.mjs +108 -0
  86. package/dist/colour/srgb.d.mts +49 -0
  87. package/dist/colour/srgb.mjs +108 -0
  88. package/dist/core/constants.d.mts +138 -0
  89. package/dist/core/constants.mjs +139 -0
  90. package/dist/core/index.d.mts +3 -1
  91. package/dist/core/index.mjs +3 -1
  92. package/dist/core/vec3.d.mts +94 -0
  93. package/dist/core/vec3.mjs +123 -0
  94. package/dist/core/worked.d.mts +35 -0
  95. package/dist/core/worked.mjs +44 -0
  96. package/dist/electro/cell.d.mts +102 -0
  97. package/dist/electro/cell.mjs +170 -0
  98. package/dist/electro/conductivity.d.mts +157 -0
  99. package/dist/electro/conductivity.mjs +156 -0
  100. package/dist/electro/couples.d.mts +114 -0
  101. package/dist/electro/couples.mjs +334 -0
  102. package/dist/electro/electrolysis.d.mts +96 -0
  103. package/dist/electro/electrolysis.mjs +274 -0
  104. package/dist/electro/faraday.d.mts +150 -0
  105. package/dist/electro/faraday.mjs +118 -0
  106. package/dist/electro/index.d.mts +6 -0
  107. package/dist/electro/index.mjs +7 -0
  108. package/dist/finance/accounting/adjustments.d.mts +17 -0
  109. package/dist/finance/accounting/adjustments.mjs +202 -0
  110. package/dist/finance/accounting/analysis.d.mts +8 -0
  111. package/dist/finance/accounting/analysis.mjs +205 -0
  112. package/dist/finance/accounting/clubs.d.mts +21 -0
  113. package/dist/finance/accounting/clubs.mjs +217 -0
  114. package/dist/finance/accounting/company-statements.d.mts +7 -0
  115. package/dist/finance/accounting/company-statements.mjs +150 -0
  116. package/dist/finance/accounting/harness.d.mts +7 -0
  117. package/dist/finance/accounting/harness.mjs +45 -0
  118. package/dist/finance/accounting/index.d.mts +18 -0
  119. package/dist/finance/accounting/index.mjs +18 -0
  120. package/dist/finance/accounting/journalize.d.mts +16 -0
  121. package/dist/finance/accounting/journalize.mjs +128 -0
  122. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  123. package/dist/finance/accounting/manufacturing.mjs +236 -0
  124. package/dist/finance/accounting/partnership.d.mts +7 -0
  125. package/dist/finance/accounting/partnership.mjs +152 -0
  126. package/dist/finance/accounting/period-case.d.mts +6 -0
  127. package/dist/finance/accounting/period-case.mjs +71 -0
  128. package/dist/finance/accounting/post.d.mts +9 -0
  129. package/dist/finance/accounting/post.mjs +84 -0
  130. package/dist/finance/accounting/precision.d.mts +9 -0
  131. package/dist/finance/accounting/precision.mjs +15 -0
  132. package/dist/finance/accounting/rules.d.mts +21 -0
  133. package/dist/finance/accounting/rules.mjs +37 -0
  134. package/dist/finance/accounting/solve.d.mts +28 -0
  135. package/dist/finance/accounting/solve.mjs +92 -0
  136. package/dist/finance/accounting/statements.d.mts +7 -0
  137. package/dist/finance/accounting/statements.mjs +142 -0
  138. package/dist/finance/accounting/types.d.mts +649 -0
  139. package/dist/finance/accounting/validate.d.mts +7 -0
  140. package/dist/finance/accounting/validate.mjs +67 -0
  141. package/dist/finance/accounting/verification.d.mts +24 -0
  142. package/dist/finance/accounting/verification.mjs +386 -0
  143. package/dist/finance/bizsim.d.mts +21 -39
  144. package/dist/finance/bizsim.mjs +276 -97
  145. package/dist/finance/index.d.mts +20 -43
  146. package/dist/finance/index.mjs +19 -77
  147. package/dist/finance/investment-math.d.mts +7 -0
  148. package/dist/finance/investment-math.mjs +18 -0
  149. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  150. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  151. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  152. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  153. package/dist/finance/management-accounting/costing.d.mts +8 -0
  154. package/dist/finance/management-accounting/costing.mjs +175 -0
  155. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  156. package/dist/finance/management-accounting/decisions.mjs +164 -0
  157. package/dist/finance/management-accounting/index.d.mts +13 -0
  158. package/dist/finance/management-accounting/index.mjs +13 -0
  159. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  160. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  161. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  162. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  163. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  164. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  165. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  166. package/dist/finance/management-accounting/management-case.mjs +91 -0
  167. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  168. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  169. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  170. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  171. package/dist/finance/management-accounting/types.d.mts +644 -0
  172. package/dist/finance/management-accounting/variances.d.mts +7 -0
  173. package/dist/finance/management-accounting/variances.mjs +150 -0
  174. package/dist/index.d.mts +6 -6
  175. package/dist/index.mjs +1 -1
  176. package/dist/math/analysis.d.mts +61 -0
  177. package/dist/math/analysis.mjs +187 -0
  178. package/dist/math/answer-check.d.mts +50 -0
  179. package/dist/math/answer-check.mjs +106 -0
  180. package/dist/math/calculus.d.mts +4 -9
  181. package/dist/math/calculus.mjs +216 -7
  182. package/dist/math/complex.d.mts +93 -0
  183. package/dist/math/complex.mjs +239 -0
  184. package/dist/math/expr.d.mts +23 -0
  185. package/dist/math/expr.mjs +36 -0
  186. package/dist/math/index.d.mts +8 -22
  187. package/dist/math/index.mjs +8 -37
  188. package/dist/math/latex.mjs +2 -1
  189. package/dist/math/parse.mjs +1 -1
  190. package/dist/math/poly.d.mts +55 -0
  191. package/dist/math/poly.mjs +273 -0
  192. package/dist/math/rearrange.d.mts +14 -0
  193. package/dist/math/rearrange.mjs +125 -0
  194. package/dist/math/solve.d.mts +21 -0
  195. package/dist/math/solve.mjs +75 -0
  196. package/dist/networking/addressing.d.mts +26 -0
  197. package/dist/networking/addressing.mjs +33 -0
  198. package/dist/networking/cloud/access.d.mts +36 -0
  199. package/dist/networking/cloud/access.mjs +95 -0
  200. package/dist/networking/cloud/containers.d.mts +43 -0
  201. package/dist/networking/cloud/containers.mjs +54 -0
  202. package/dist/networking/cloud/edge.d.mts +17 -0
  203. package/dist/networking/cloud/edge.mjs +31 -0
  204. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  205. package/dist/networking/cloud/failure-domains.mjs +22 -0
  206. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  207. package/dist/networking/cloud/geo-routing.mjs +64 -0
  208. package/dist/networking/cloud/index.d.mts +18 -0
  209. package/dist/networking/cloud/index.mjs +19 -0
  210. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  211. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  212. package/dist/networking/cloud/inference.d.mts +118 -0
  213. package/dist/networking/cloud/inference.mjs +179 -0
  214. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  215. package/dist/networking/cloud/infrastructure.mjs +96 -0
  216. package/dist/networking/cloud/observability.d.mts +24 -0
  217. package/dist/networking/cloud/observability.mjs +34 -0
  218. package/dist/networking/cloud/orchestration.d.mts +32 -0
  219. package/dist/networking/cloud/orchestration.mjs +38 -0
  220. package/dist/networking/cloud/recovery.d.mts +21 -0
  221. package/dist/networking/cloud/recovery.mjs +27 -0
  222. package/dist/networking/cloud/releases.d.mts +42 -0
  223. package/dist/networking/cloud/releases.mjs +135 -0
  224. package/dist/networking/cloud/scaling.d.mts +25 -0
  225. package/dist/networking/cloud/scaling.mjs +65 -0
  226. package/dist/networking/cloud/secrets.d.mts +39 -0
  227. package/dist/networking/cloud/secrets.mjs +68 -0
  228. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  229. package/dist/networking/cloud/server-deployment.mjs +72 -0
  230. package/dist/networking/cloud/storage.d.mts +16 -0
  231. package/dist/networking/cloud/storage.mjs +58 -0
  232. package/dist/networking/cloud/vpc.d.mts +18 -0
  233. package/dist/networking/cloud/vpc.mjs +100 -0
  234. package/dist/networking/delivery.d.mts +34 -0
  235. package/dist/networking/delivery.mjs +52 -0
  236. package/dist/networking/index.d.mts +47 -0
  237. package/dist/networking/index.mjs +47 -0
  238. package/dist/networking/ipv6.d.mts +28 -0
  239. package/dist/networking/ipv6.mjs +17 -0
  240. package/dist/networking/journeys.d.mts +83 -0
  241. package/dist/networking/journeys.mjs +161 -0
  242. package/dist/networking/models/airtime.d.mts +87 -0
  243. package/dist/networking/models/airtime.mjs +130 -0
  244. package/dist/networking/models/cellular.d.mts +157 -0
  245. package/dist/networking/models/cellular.mjs +252 -0
  246. package/dist/networking/models/encapsulation.d.mts +98 -0
  247. package/dist/networking/models/encapsulation.mjs +132 -0
  248. package/dist/networking/models/handover.d.mts +116 -0
  249. package/dist/networking/models/handover.mjs +209 -0
  250. package/dist/networking/models/handshake.d.mts +90 -0
  251. package/dist/networking/models/handshake.mjs +122 -0
  252. package/dist/networking/models/index.d.mts +14 -0
  253. package/dist/networking/models/index.mjs +15 -0
  254. package/dist/networking/models/media.d.mts +82 -0
  255. package/dist/networking/models/media.mjs +188 -0
  256. package/dist/networking/models/satellite.d.mts +86 -0
  257. package/dist/networking/models/satellite.mjs +121 -0
  258. package/dist/networking/models/spectrum.d.mts +83 -0
  259. package/dist/networking/models/spectrum.mjs +235 -0
  260. package/dist/networking/models/switch.d.mts +80 -0
  261. package/dist/networking/models/switch.mjs +155 -0
  262. package/dist/networking/models/vlan.d.mts +62 -0
  263. package/dist/networking/models/vlan.mjs +100 -0
  264. package/dist/networking/models/vpn.d.mts +66 -0
  265. package/dist/networking/models/vpn.mjs +125 -0
  266. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  267. package/dist/networking/models/wifi-privacy.mjs +130 -0
  268. package/dist/networking/models/wifi.d.mts +240 -0
  269. package/dist/networking/models/wifi.mjs +562 -0
  270. package/dist/networking/nat-traversal.d.mts +24 -0
  271. package/dist/networking/nat-traversal.mjs +38 -0
  272. package/dist/networking/protocols.d.mts +17 -0
  273. package/dist/networking/protocols.mjs +57 -0
  274. package/dist/networking/queue.d.mts +12 -0
  275. package/dist/networking/queue.mjs +18 -0
  276. package/dist/networking/route-learning.d.mts +23 -0
  277. package/dist/networking/route-learning.mjs +43 -0
  278. package/dist/networking/routing.d.mts +11 -0
  279. package/dist/networking/routing.mjs +25 -0
  280. package/dist/networking/signals.d.mts +26 -0
  281. package/dist/networking/signals.mjs +35 -0
  282. package/dist/networking/subnet.d.mts +49 -0
  283. package/dist/networking/subnet.mjs +89 -0
  284. package/dist/networking/tcp-reliability.d.mts +24 -0
  285. package/dist/networking/tcp-reliability.mjs +38 -0
  286. package/dist/networking/topology/contract.d.mts +123 -0
  287. package/dist/networking/topology/index.d.mts +4 -0
  288. package/dist/networking/topology/index.mjs +4 -0
  289. package/dist/networking/topology/presets.d.mts +7 -0
  290. package/dist/networking/topology/presets.mjs +302 -0
  291. package/dist/networking/topology/simulation.d.mts +8 -0
  292. package/dist/networking/topology/simulation.mjs +179 -0
  293. package/dist/networking/wireless.d.mts +11 -0
  294. package/dist/networking/wireless.mjs +17 -0
  295. package/dist/optics/imaging.d.mts +218 -0
  296. package/dist/optics/imaging.mjs +276 -0
  297. package/dist/optics/index.d.mts +7 -0
  298. package/dist/optics/index.mjs +8 -0
  299. package/dist/optics/laws.d.mts +70 -0
  300. package/dist/optics/laws.mjs +195 -0
  301. package/dist/optics/prism.d.mts +148 -0
  302. package/dist/optics/prism.mjs +197 -0
  303. package/dist/optics/refraction.d.mts +201 -0
  304. package/dist/optics/refraction.mjs +270 -0
  305. package/dist/optics/wave-optics.d.mts +171 -0
  306. package/dist/optics/wave-optics.mjs +259 -0
  307. package/dist/physics/ac/index.d.mts +183 -0
  308. package/dist/physics/ac/index.mjs +203 -0
  309. package/dist/physics/dynamics/forces.d.mts +98 -0
  310. package/dist/physics/dynamics/forces.mjs +153 -0
  311. package/dist/physics/dynamics/friction.d.mts +76 -0
  312. package/dist/physics/dynamics/friction.mjs +119 -0
  313. package/dist/physics/dynamics/system.d.mts +68 -0
  314. package/dist/physics/dynamics/system.mjs +125 -0
  315. package/dist/physics/electrostatics/index.d.mts +169 -0
  316. package/dist/physics/electrostatics/index.mjs +249 -0
  317. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  318. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  319. package/dist/physics/energy/conservation.d.mts +81 -0
  320. package/dist/physics/energy/conservation.mjs +129 -0
  321. package/dist/physics/energy/power.d.mts +90 -0
  322. package/dist/physics/energy/power.mjs +167 -0
  323. package/dist/physics/energy/spring.d.mts +73 -0
  324. package/dist/physics/energy/spring.mjs +129 -0
  325. package/dist/physics/energy/store.d.mts +63 -0
  326. package/dist/physics/energy/store.mjs +108 -0
  327. package/dist/physics/energy/theorem.d.mts +65 -0
  328. package/dist/physics/energy/theorem.mjs +113 -0
  329. package/dist/physics/energy/work.d.mts +114 -0
  330. package/dist/physics/energy/work.mjs +219 -0
  331. package/dist/physics/gravitation/body.d.mts +85 -0
  332. package/dist/physics/gravitation/body.mjs +168 -0
  333. package/dist/physics/gravitation/kepler.d.mts +127 -0
  334. package/dist/physics/gravitation/kepler.mjs +216 -0
  335. package/dist/physics/gravitation/law.d.mts +117 -0
  336. package/dist/physics/gravitation/law.mjs +175 -0
  337. package/dist/physics/gravitation/orbit.d.mts +119 -0
  338. package/dist/physics/gravitation/orbit.mjs +202 -0
  339. package/dist/physics/gravitation/potential.d.mts +114 -0
  340. package/dist/physics/gravitation/potential.mjs +202 -0
  341. package/dist/physics/gravitation/variation.d.mts +97 -0
  342. package/dist/physics/gravitation/variation.mjs +175 -0
  343. package/dist/physics/index.d.mts +35 -0
  344. package/dist/physics/index.mjs +36 -0
  345. package/dist/physics/integral-sweep.d.mts +63 -0
  346. package/dist/physics/integral-sweep.mjs +126 -0
  347. package/dist/physics/kinematics/equations.d.mts +47 -0
  348. package/dist/physics/kinematics/equations.mjs +126 -0
  349. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  350. package/dist/physics/kinematics/free-fall.mjs +71 -0
  351. package/dist/physics/kinematics/given.d.mts +16 -0
  352. package/dist/physics/kinematics/given.mjs +55 -0
  353. package/dist/physics/kinematics/roots.d.mts +41 -0
  354. package/dist/physics/kinematics/roots.mjs +72 -0
  355. package/dist/physics/kinematics/solve.d.mts +52 -0
  356. package/dist/physics/kinematics/solve.mjs +172 -0
  357. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  358. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  359. package/dist/physics/magnetism/flux.d.mts +94 -0
  360. package/dist/physics/magnetism/flux.mjs +313 -0
  361. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  362. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  363. package/dist/physics/magnetism/index.d.mts +12 -0
  364. package/dist/physics/magnetism/index.mjs +74 -0
  365. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  366. package/dist/physics/magnetism/lorentz.mjs +88 -0
  367. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  368. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  369. package/dist/physics/momentum/collide.d.mts +77 -0
  370. package/dist/physics/momentum/collide.mjs +115 -0
  371. package/dist/physics/momentum/impulse.d.mts +89 -0
  372. package/dist/physics/momentum/impulse.mjs +159 -0
  373. package/dist/physics/momentum/planar.d.mts +60 -0
  374. package/dist/physics/momentum/planar.mjs +110 -0
  375. package/dist/physics/projectile.d.mts +107 -0
  376. package/dist/physics/projectile.mjs +185 -0
  377. package/dist/physics/rotation/angular.d.mts +85 -0
  378. package/dist/physics/rotation/angular.mjs +130 -0
  379. package/dist/physics/rotation/circular.d.mts +79 -0
  380. package/dist/physics/rotation/circular.mjs +131 -0
  381. package/dist/physics/rotation/inertia.d.mts +164 -0
  382. package/dist/physics/rotation/inertia.mjs +332 -0
  383. package/dist/physics/rotation/torque.d.mts +65 -0
  384. package/dist/physics/rotation/torque.mjs +134 -0
  385. package/dist/physics/vectors.d.mts +64 -0
  386. package/dist/physics/vectors.mjs +114 -0
  387. package/dist/quantity/index.d.mts +119 -0
  388. package/dist/quantity/index.mjs +417 -0
  389. package/dist/relation/derive.d.mts +74 -0
  390. package/dist/relation/derive.mjs +73 -0
  391. package/dist/relation/index.d.mts +56 -0
  392. package/dist/relation/index.mjs +234 -0
  393. package/dist/scene/evaluators.mjs +1 -1
  394. package/dist/sim/thermal.mjs +45 -20
  395. package/dist/thermo/calorimetry.d.mts +207 -0
  396. package/dist/thermo/calorimetry.mjs +345 -0
  397. package/dist/thermo/cycles.d.mts +142 -0
  398. package/dist/thermo/cycles.mjs +256 -0
  399. package/dist/thermo/entropy.d.mts +87 -0
  400. package/dist/thermo/entropy.mjs +140 -0
  401. package/dist/thermo/expansion.d.mts +130 -0
  402. package/dist/thermo/expansion.mjs +178 -0
  403. package/dist/thermo/gas.d.mts +197 -0
  404. package/dist/thermo/gas.mjs +279 -0
  405. package/dist/thermo/heat-transfer.d.mts +164 -0
  406. package/dist/thermo/heat-transfer.mjs +217 -0
  407. package/dist/thermo/index.d.mts +9 -82
  408. package/dist/thermo/index.mjs +9 -132
  409. package/dist/thermo/processes.d.mts +95 -0
  410. package/dist/thermo/processes.mjs +154 -0
  411. package/dist/thermo/temperature.d.mts +174 -0
  412. package/dist/thermo/temperature.mjs +236 -0
  413. package/dist/waves/damping.d.mts +224 -0
  414. package/dist/waves/damping.mjs +317 -0
  415. package/dist/waves/doppler.d.mts +72 -0
  416. package/dist/waves/doppler.mjs +125 -0
  417. package/dist/waves/index.d.mts +10 -0
  418. package/dist/waves/index.mjs +10 -0
  419. package/dist/waves/pendulum.d.mts +130 -0
  420. package/dist/waves/pendulum.mjs +211 -0
  421. package/dist/waves/pitch.d.mts +125 -0
  422. package/dist/waves/pitch.mjs +158 -0
  423. package/dist/waves/shm.d.mts +170 -0
  424. package/dist/waves/shm.mjs +279 -0
  425. package/dist/waves/springs.d.mts +103 -0
  426. package/dist/waves/springs.mjs +176 -0
  427. package/dist/waves/superposition.d.mts +124 -0
  428. package/dist/waves/superposition.mjs +196 -0
  429. package/dist/waves/wave.d.mts +154 -0
  430. package/dist/waves/wave.mjs +178 -0
  431. package/package.json +74 -2
@@ -0,0 +1,74 @@
1
+ import { __exportAll } from "../../_virtual/_rolldown/runtime.mjs";
2
+ import { MIN_DISTANCE_M, MU_0, arcCentreT, circularArc, coilAxisT, coilCentreT, fieldAt, finiteWireT, flatCoil, helmholtzPair, longWire, longWireT, pathField, rectangularLoop, segmentField, solenoid, solenoidRings, solenoidT, straightWire, toroidT, traceFieldLine, traceFullFieldLine } from "./biot-savart.mjs";
3
+ import { MIN_LOOP_CLEARANCE_M, emfFromMutualInductance, emfFromSelfInductance, fluxBesideWire, fluxLinkage, fluxThroughLoop, fluxThroughUniform, inducedEmfV, loopArea, magneticEnergyJ, mutualInductanceH, selfInductanceH, solenoidInductanceH } from "./flux.mjs";
4
+ import { angleFromPlaneDeg, coilTorqueNm, forceOnPath, forcePerMetreOnWire, magneticMomentAm2, momentOfLoop, parallelWireForce, torqueFromMoment } from "./magnetic-force.mjs";
5
+ import { EARTH_DIPOLE_MOMENT_AM2, EARTH_RADIUS_M, GEOMAGNETIC_NORTH_POLE, apparentDipDeg, compassBearingDeg, dipFromMagneticLatitude, dipoleFieldAt, dipoleFieldLine, earthComponents, earthFromComponents, fieldAtPlace, footLatitudeDeg, magneticLatitudeFromDip, trueBearingDeg, trueDipFromTwo } from "./geomagnetism.mjs";
6
+ import { fieldsFor, lorentzForce3D, traceLorentz } from "./lorentz.mjs";
7
+
8
+ //#region src/physics/magnetism/index.ts
9
+ var magnetism_exports = /* @__PURE__ */ __exportAll({
10
+ EARTH_DIPOLE_MOMENT_AM2: () => EARTH_DIPOLE_MOMENT_AM2,
11
+ EARTH_RADIUS_M: () => EARTH_RADIUS_M,
12
+ GEOMAGNETIC_NORTH_POLE: () => GEOMAGNETIC_NORTH_POLE,
13
+ MIN_DISTANCE_M: () => MIN_DISTANCE_M,
14
+ MIN_LOOP_CLEARANCE_M: () => MIN_LOOP_CLEARANCE_M,
15
+ MU_0: () => MU_0,
16
+ angleFromPlaneDeg: () => angleFromPlaneDeg,
17
+ apparentDipDeg: () => apparentDipDeg,
18
+ arcCentreT: () => arcCentreT,
19
+ circularArc: () => circularArc,
20
+ coilAxisT: () => coilAxisT,
21
+ coilCentreT: () => coilCentreT,
22
+ coilTorqueNm: () => coilTorqueNm,
23
+ compassBearingDeg: () => compassBearingDeg,
24
+ dipFromMagneticLatitude: () => dipFromMagneticLatitude,
25
+ dipoleFieldAt: () => dipoleFieldAt,
26
+ dipoleFieldLine: () => dipoleFieldLine,
27
+ earthComponents: () => earthComponents,
28
+ earthFromComponents: () => earthFromComponents,
29
+ emfFromMutualInductance: () => emfFromMutualInductance,
30
+ emfFromSelfInductance: () => emfFromSelfInductance,
31
+ fieldAt: () => fieldAt,
32
+ fieldAtPlace: () => fieldAtPlace,
33
+ fieldsFor: () => fieldsFor,
34
+ finiteWireT: () => finiteWireT,
35
+ flatCoil: () => flatCoil,
36
+ fluxBesideWire: () => fluxBesideWire,
37
+ fluxLinkage: () => fluxLinkage,
38
+ fluxThroughLoop: () => fluxThroughLoop,
39
+ fluxThroughUniform: () => fluxThroughUniform,
40
+ footLatitudeDeg: () => footLatitudeDeg,
41
+ forceOnPath: () => forceOnPath,
42
+ forcePerMetreOnWire: () => forcePerMetreOnWire,
43
+ helmholtzPair: () => helmholtzPair,
44
+ inducedEmfV: () => inducedEmfV,
45
+ longWire: () => longWire,
46
+ longWireT: () => longWireT,
47
+ loopArea: () => loopArea,
48
+ lorentzForce3D: () => lorentzForce3D,
49
+ magneticEnergyJ: () => magneticEnergyJ,
50
+ magneticLatitudeFromDip: () => magneticLatitudeFromDip,
51
+ magneticMomentAm2: () => magneticMomentAm2,
52
+ momentOfLoop: () => momentOfLoop,
53
+ mutualInductanceH: () => mutualInductanceH,
54
+ parallelWireForce: () => parallelWireForce,
55
+ pathField: () => pathField,
56
+ rectangularLoop: () => rectangularLoop,
57
+ segmentField: () => segmentField,
58
+ selfInductanceH: () => selfInductanceH,
59
+ solenoid: () => solenoid,
60
+ solenoidInductanceH: () => solenoidInductanceH,
61
+ solenoidRings: () => solenoidRings,
62
+ solenoidT: () => solenoidT,
63
+ straightWire: () => straightWire,
64
+ toroidT: () => toroidT,
65
+ torqueFromMoment: () => torqueFromMoment,
66
+ traceFieldLine: () => traceFieldLine,
67
+ traceFullFieldLine: () => traceFullFieldLine,
68
+ traceLorentz: () => traceLorentz,
69
+ trueBearingDeg: () => trueBearingDeg,
70
+ trueDipFromTwo: () => trueDipFromTwo
71
+ });
72
+
73
+ //#endregion
74
+ export { EARTH_DIPOLE_MOMENT_AM2, EARTH_RADIUS_M, GEOMAGNETIC_NORTH_POLE, MIN_DISTANCE_M, MIN_LOOP_CLEARANCE_M, MU_0, angleFromPlaneDeg, apparentDipDeg, arcCentreT, circularArc, coilAxisT, coilCentreT, coilTorqueNm, compassBearingDeg, dipFromMagneticLatitude, dipoleFieldAt, dipoleFieldLine, earthComponents, earthFromComponents, emfFromMutualInductance, emfFromSelfInductance, fieldAt, fieldAtPlace, fieldsFor, finiteWireT, flatCoil, fluxBesideWire, fluxLinkage, fluxThroughLoop, fluxThroughUniform, footLatitudeDeg, forceOnPath, forcePerMetreOnWire, helmholtzPair, inducedEmfV, longWire, longWireT, loopArea, lorentzForce3D, magneticEnergyJ, magneticLatitudeFromDip, magneticMomentAm2, magnetism_exports, momentOfLoop, mutualInductanceH, parallelWireForce, pathField, rectangularLoop, segmentField, selfInductanceH, solenoid, solenoidInductanceH, solenoidRings, solenoidT, straightWire, toroidT, torqueFromMoment, traceFieldLine, traceFullFieldLine, traceLorentz, trueBearingDeg, trueDipFromTwo };
@@ -0,0 +1,28 @@
1
+ import { Vec3 } from "../../core/vec3.mjs";
2
+
3
+ //#region src/physics/magnetism/lorentz.d.ts
4
+ type SpatialFieldMode = 'electric' | 'magnetic' | 'crossed';
5
+ /**
6
+ * The Lorentz force on a point charge: F = q(E + v x B).
7
+ *
8
+ * Both halves in one expression on purpose. A velocity selector works because
9
+ * the two can cancel, and splitting them into separate functions makes that
10
+ * cancellation something a lab has to arrange rather than something the law
11
+ * already says.
12
+ */
13
+ declare function lorentzForce3D(q: number, v: Vec3, e: Vec3, b: Vec3): Vec3;
14
+ /**
15
+ * RK4 trajectory for constant fields, in normalised teaching units.
16
+ *
17
+ * Not SI: the point of this one is the SHAPE of the path (a circle in a pure
18
+ * magnetic field, a helix when the velocity has a component along it, a
19
+ * straight line when E and v x B cancel), and real electron masses would put
20
+ * every interesting radius outside any sensible viewport.
21
+ */
22
+ declare function traceLorentz(q: number, m: number, v0: Vec3, e: Vec3, b: Vec3, steps?: number, dt?: number): Vec3[];
23
+ declare function fieldsFor(mode: SpatialFieldMode, strength: number): {
24
+ e: Vec3;
25
+ b: Vec3;
26
+ };
27
+ //#endregion
28
+ export { SpatialFieldMode, fieldsFor, lorentzForce3D, traceLorentz };
@@ -0,0 +1,88 @@
1
+ import { add3, cross3, scale3 } from "../../core/vec3.mjs";
2
+
3
+ //#region src/physics/magnetism/lorentz.ts
4
+ /**
5
+ * @classytic/stage/physics/magnetism/lorentz — the force a field puts on a
6
+ * moving CHARGE, and the path that follows.
7
+ *
8
+ * The companion to `magnetic-force.ts`, which does the same for a current.
9
+ * They are the same physics at two scales: a current is drifting charge, so
10
+ * `F = qv x B` summed over the carriers in a wire IS `F = I l x B`.
11
+ */
12
+ const add = (a, b, s = 1) => add3(a, scale3(b, s));
13
+ /**
14
+ * The Lorentz force on a point charge: F = q(E + v x B).
15
+ *
16
+ * Both halves in one expression on purpose. A velocity selector works because
17
+ * the two can cancel, and splitting them into separate functions makes that
18
+ * cancellation something a lab has to arrange rather than something the law
19
+ * already says.
20
+ */
21
+ function lorentzForce3D(q, v, e, b) {
22
+ const c = cross3(v, b);
23
+ return {
24
+ x: q * (e.x + c.x),
25
+ y: q * (e.y + c.y),
26
+ z: q * (e.z + c.z)
27
+ };
28
+ }
29
+ /**
30
+ * RK4 trajectory for constant fields, in normalised teaching units.
31
+ *
32
+ * Not SI: the point of this one is the SHAPE of the path (a circle in a pure
33
+ * magnetic field, a helix when the velocity has a component along it, a
34
+ * straight line when E and v x B cancel), and real electron masses would put
35
+ * every interesting radius outside any sensible viewport.
36
+ */
37
+ function traceLorentz(q, m, v0, e, b, steps = 180, dt = .025) {
38
+ let p = {
39
+ x: 0,
40
+ y: 0,
41
+ z: 0
42
+ }, v = { ...v0 };
43
+ const out = [p];
44
+ for (let i = 0; i < steps; i++) {
45
+ const a = (x) => {
46
+ const f = lorentzForce3D(q, x, e, b);
47
+ return {
48
+ x: f.x / m,
49
+ y: f.y / m,
50
+ z: f.z / m
51
+ };
52
+ };
53
+ const k1 = a(v), k2 = a(add(v, k1, dt / 2)), k3 = a(add(v, k2, dt / 2)), k4 = a(add(v, k3, dt));
54
+ v = add(v, {
55
+ x: (k1.x + 2 * k2.x + 2 * k3.x + k4.x) / 6,
56
+ y: (k1.y + 2 * k2.y + 2 * k3.y + k4.y) / 6,
57
+ z: (k1.z + 2 * k2.z + 2 * k3.z + k4.z) / 6
58
+ }, dt);
59
+ p = add(p, v, dt);
60
+ out.push(p);
61
+ }
62
+ return out;
63
+ }
64
+ function fieldsFor(mode, strength) {
65
+ return {
66
+ e: mode === "magnetic" ? {
67
+ x: 0,
68
+ y: 0,
69
+ z: 0
70
+ } : {
71
+ x: 0,
72
+ y: strength,
73
+ z: 0
74
+ },
75
+ b: mode === "electric" ? {
76
+ x: 0,
77
+ y: 0,
78
+ z: 0
79
+ } : {
80
+ x: 0,
81
+ y: 0,
82
+ z: strength
83
+ }
84
+ };
85
+ }
86
+
87
+ //#endregion
88
+ export { fieldsFor, lorentzForce3D, traceLorentz };
@@ -0,0 +1,102 @@
1
+ import { Vec3 } from "../../core/vec3.mjs";
2
+ import { CurrentPath } from "./biot-savart.mjs";
3
+
4
+ //#region src/physics/magnetism/magnetic-force.d.ts
5
+ interface ForceOnPathOptions {
6
+ /** A uniform background field, added to whatever the current sources make. */
7
+ uniformT?: Vec3;
8
+ /** Point the torque is taken about. Defaults to the origin. */
9
+ about?: Vec3;
10
+ /**
11
+ * Quadrature points per segment of the test path.
12
+ *
13
+ * A straight segment in a slowly varying field needs one; a segment that is
14
+ * part of a polygon approximating a circle, sitting close to another
15
+ * conductor, needs several.
16
+ */
17
+ samplesPerSegment?: number;
18
+ }
19
+ interface PathForce {
20
+ /** Net force on the test path, in newtons. */
21
+ force: Vec3;
22
+ /** Its magnitude, in newtons. */
23
+ newtons: number;
24
+ /** Net torque about `about`, in newton metres. */
25
+ torque: Vec3;
26
+ /**
27
+ * Where the force acts, segment by segment.
28
+ *
29
+ * Kept because the interesting thing about a coil in a uniform field is that
30
+ * the net force is zero while the individual forces are not: a lesson has to
31
+ * be able to draw the parts to make the couple visible.
32
+ */
33
+ contributions: Array<{
34
+ at: Vec3;
35
+ force: Vec3;
36
+ }>;
37
+ }
38
+ /**
39
+ * Force and torque on one current path, in the field of any others plus an
40
+ * optional uniform background.
41
+ *
42
+ * The test path is NOT a source of its own field. A filament's self-force is
43
+ * divergent and, for a rigid circuit, is not what anybody means by "the force
44
+ * on the coil" anyway.
45
+ */
46
+ declare function forceOnPath(sources: readonly CurrentPath[], test: CurrentPath, options?: ForceOnPathOptions): PathForce;
47
+ /**
48
+ * Force per unit length on a long straight test wire, for comparing against the
49
+ * textbook result.
50
+ *
51
+ * Measured over a short span at the MIDDLE of the test wire, because the ends of
52
+ * any finite wire feel less than the middle does and averaging over the whole
53
+ * thing would quietly build that end effect into the answer.
54
+ */
55
+ declare function forcePerMetreOnWire(sources: readonly CurrentPath[], through: Vec3, direction: Vec3, currentA: number, spanM?: number): Vec3;
56
+ /** Torque on a closed circuit from its magnetic moment: tau = m x B. */
57
+ declare function torqueFromMoment(momentAm2: Vec3, fieldT: Vec3): Vec3;
58
+ /**
59
+ * Magnetic moment of a planar closed loop, as a vector: m = I A n.
60
+ *
61
+ * Computed from the loop's own geometry by the surface-vector form of the
62
+ * shoelace formula, so it needs no separate area argument and gets the normal's
63
+ * direction from the order the loop is walked. That is the right-hand rule made
64
+ * arithmetic.
65
+ */
66
+ declare function momentOfLoop(loop: CurrentPath): Vec3;
67
+ interface WireForce {
68
+ /** Force per unit length, in newtons per metre. Always positive. */
69
+ newtonsPerMetre: number;
70
+ /** Currents the same way attract; opposite ways repel. */
71
+ sense: 'attract' | 'repel';
72
+ }
73
+ /**
74
+ * Force per metre between two long parallel wires: mu0 I1 I2 / 2 pi d.
75
+ *
76
+ * This is the definition of the ampere, and it is the cleanest demonstration
77
+ * that a current both makes a field and feels one: wire 1's field at wire 2,
78
+ * times wire 2's I L.
79
+ */
80
+ declare function parallelWireForce(current1A: number, current2A: number, separationM: number): WireForce;
81
+ /** Magnetic dipole moment of a coil: M = N I A, in A m^2. */
82
+ declare function magneticMomentAm2(turns: number, currentA: number, areaM2: number): number;
83
+ /**
84
+ * Torque on a current-carrying coil in a uniform field: tau = N I A B sin(theta),
85
+ * where theta is the angle between the coil's NORMAL and the field.
86
+ *
87
+ * The angle is the standard trap. A question almost always states the angle the
88
+ * coil's PLANE makes with the field, which is the complement. Rather than pick
89
+ * a convention and hope, this takes the physically correct angle and
90
+ * `angleFromPlaneDeg` does the conversion in the open.
91
+ */
92
+ declare function coilTorqueNm(fieldT: number, turns: number, currentA: number, areaM2: number, normalToFieldDeg: number): number;
93
+ /**
94
+ * Convert "the coil's plane makes this angle with B" into the normal-to-field
95
+ * angle that `coilTorqueNm` wants.
96
+ *
97
+ * A coil whose plane lies along the field (0 degrees) has its normal across the
98
+ * field (90 degrees), which is where the torque is greatest.
99
+ */
100
+ declare const angleFromPlaneDeg: (planeToFieldDeg: number) => number;
101
+ //#endregion
102
+ export { ForceOnPathOptions, PathForce, WireForce, angleFromPlaneDeg, coilTorqueNm, forceOnPath, forcePerMetreOnWire, magneticMomentAm2, momentOfLoop, parallelWireForce, torqueFromMoment };
@@ -0,0 +1,169 @@
1
+ import { ZERO3, add3, cross3, mag3, scale3, sub3 } from "../../core/vec3.mjs";
2
+ import { MU_0, fieldAt } from "./biot-savart.mjs";
3
+
4
+ //#region src/physics/magnetism/magnetic-force.ts
5
+ /**
6
+ * @classytic/stage/field/magnetic-force — the force a magnetic field puts on a
7
+ * current, over arbitrary geometry.
8
+ *
9
+ * `parallelWireForce` answers one case in closed form: two infinite straight
10
+ * wires. Everything else a real circuit does -- a loop beside a wire, a coil
11
+ * inside another coil, a rectangular armature in a magnet's gap -- needs the
12
+ * line integral that case was derived from:
13
+ *
14
+ * F = integral of I dl x B
15
+ *
16
+ * With that, the closed form stops being a separate fact and becomes a check.
17
+ *
18
+ * ── A uniform background field is a first-class source ────────────────────────
19
+ * Almost every exam question puts a conductor in "a uniform field of 0.35 T"
20
+ * without saying what makes it. Demanding a current geometry for that would be
21
+ * pedantry: the uniform field is the idealisation the question is posed in. So
22
+ * it is an explicit option, added to whatever the current sources contribute.
23
+ *
24
+ * ── Why the torque needs an origin, and when it does not ──────────────────────
25
+ * Torque is about a point, so `about` has to be given. The exception is the
26
+ * case that matters most: when the NET FORCE is zero, as it is for any closed
27
+ * circuit in a uniform field, the torque is the same about every point. That is
28
+ * what makes "the torque on a coil" a well-posed phrase at all, and it is
29
+ * asserted in the tests rather than assumed.
30
+ */
31
+ const radians = (deg) => deg * Math.PI / 180;
32
+ const segmentsOf = (path) => {
33
+ const pairs = [];
34
+ const points = path.points;
35
+ for (let i = 0; i + 1 < points.length; i += 1) {
36
+ const from = points[i];
37
+ const to = points[i + 1];
38
+ if (from && to) pairs.push([from, to]);
39
+ }
40
+ if (path.closed && points.length > 2) {
41
+ const last = points[points.length - 1];
42
+ const first = points[0];
43
+ if (last && first) pairs.push([last, first]);
44
+ }
45
+ return pairs;
46
+ };
47
+ /**
48
+ * Force and torque on one current path, in the field of any others plus an
49
+ * optional uniform background.
50
+ *
51
+ * The test path is NOT a source of its own field. A filament's self-force is
52
+ * divergent and, for a rigid circuit, is not what anybody means by "the force
53
+ * on the coil" anyway.
54
+ */
55
+ function forceOnPath(sources, test, options = {}) {
56
+ const { uniformT = ZERO3, about = ZERO3, samplesPerSegment = 4 } = options;
57
+ if (samplesPerSegment < 1) throw new RangeError("A segment needs at least one sample.");
58
+ if (sources.some((s) => s.id === test.id)) throw new RangeError("A path cannot be its own source: a filament self-force diverges.");
59
+ let force = ZERO3;
60
+ let torque = ZERO3;
61
+ const contributions = [];
62
+ for (const [from, to] of segmentsOf(test)) {
63
+ const along = sub3(to, from);
64
+ const piece = scale3(along, 1 / samplesPerSegment);
65
+ let segmentForce = ZERO3;
66
+ let segmentTorque = ZERO3;
67
+ let segmentMidpoint = ZERO3;
68
+ for (let k = 0; k < samplesPerSegment; k += 1) {
69
+ const at = add3(from, scale3(along, (k + .5) / samplesPerSegment));
70
+ const dF = scale3(cross3(piece, add3(uniformT, fieldAt(sources, at).field)), test.currentA);
71
+ segmentForce = add3(segmentForce, dF);
72
+ segmentTorque = add3(segmentTorque, cross3(sub3(at, about), dF));
73
+ segmentMidpoint = add3(segmentMidpoint, scale3(at, 1 / samplesPerSegment));
74
+ }
75
+ force = add3(force, segmentForce);
76
+ torque = add3(torque, segmentTorque);
77
+ contributions.push({
78
+ at: segmentMidpoint,
79
+ force: segmentForce
80
+ });
81
+ }
82
+ return {
83
+ force,
84
+ newtons: mag3(force),
85
+ torque,
86
+ contributions
87
+ };
88
+ }
89
+ /**
90
+ * Force per unit length on a long straight test wire, for comparing against the
91
+ * textbook result.
92
+ *
93
+ * Measured over a short span at the MIDDLE of the test wire, because the ends of
94
+ * any finite wire feel less than the middle does and averaging over the whole
95
+ * thing would quietly build that end effect into the answer.
96
+ */
97
+ function forcePerMetreOnWire(sources, through, direction, currentA, spanM = .001) {
98
+ const len = mag3(direction);
99
+ if (len === 0) throw new RangeError("A wire needs a direction.");
100
+ const half = scale3(direction, spanM / (2 * len));
101
+ return scale3(forceOnPath(sources, {
102
+ id: "force-probe",
103
+ currentA,
104
+ points: [sub3(through, half), add3(through, half)]
105
+ }, { samplesPerSegment: 8 }).force, 1 / spanM);
106
+ }
107
+ /** Torque on a closed circuit from its magnetic moment: tau = m x B. */
108
+ function torqueFromMoment(momentAm2, fieldT) {
109
+ return cross3(momentAm2, fieldT);
110
+ }
111
+ /**
112
+ * Magnetic moment of a planar closed loop, as a vector: m = I A n.
113
+ *
114
+ * Computed from the loop's own geometry by the surface-vector form of the
115
+ * shoelace formula, so it needs no separate area argument and gets the normal's
116
+ * direction from the order the loop is walked. That is the right-hand rule made
117
+ * arithmetic.
118
+ */
119
+ function momentOfLoop(loop) {
120
+ const points = loop.points;
121
+ if (points.length < 3) throw new RangeError("A loop needs at least three vertices.");
122
+ const origin = points[0];
123
+ let area = ZERO3;
124
+ const pairs = segmentsOf(loop);
125
+ for (const [from, to] of pairs) area = add3(area, scale3(cross3(sub3(from, origin), sub3(to, origin)), .5));
126
+ return scale3(area, loop.currentA);
127
+ }
128
+ /**
129
+ * Force per metre between two long parallel wires: mu0 I1 I2 / 2 pi d.
130
+ *
131
+ * This is the definition of the ampere, and it is the cleanest demonstration
132
+ * that a current both makes a field and feels one: wire 1's field at wire 2,
133
+ * times wire 2's I L.
134
+ */
135
+ function parallelWireForce(current1A, current2A, separationM) {
136
+ if (separationM <= 0) throw new RangeError("Two wires need a positive separation.");
137
+ return {
138
+ newtonsPerMetre: MU_0 * Math.abs(current1A * current2A) / (2 * Math.PI * separationM),
139
+ sense: current1A * current2A >= 0 ? "attract" : "repel"
140
+ };
141
+ }
142
+ /** Magnetic dipole moment of a coil: M = N I A, in A m^2. */
143
+ function magneticMomentAm2(turns, currentA, areaM2) {
144
+ if (turns < 0 || areaM2 < 0) throw new RangeError("Turns and area cannot be negative.");
145
+ return turns * currentA * areaM2;
146
+ }
147
+ /**
148
+ * Torque on a current-carrying coil in a uniform field: tau = N I A B sin(theta),
149
+ * where theta is the angle between the coil's NORMAL and the field.
150
+ *
151
+ * The angle is the standard trap. A question almost always states the angle the
152
+ * coil's PLANE makes with the field, which is the complement. Rather than pick
153
+ * a convention and hope, this takes the physically correct angle and
154
+ * `angleFromPlaneDeg` does the conversion in the open.
155
+ */
156
+ function coilTorqueNm(fieldT, turns, currentA, areaM2, normalToFieldDeg) {
157
+ return magneticMomentAm2(turns, currentA, areaM2) * fieldT * Math.sin(radians(normalToFieldDeg));
158
+ }
159
+ /**
160
+ * Convert "the coil's plane makes this angle with B" into the normal-to-field
161
+ * angle that `coilTorqueNm` wants.
162
+ *
163
+ * A coil whose plane lies along the field (0 degrees) has its normal across the
164
+ * field (90 degrees), which is where the torque is greatest.
165
+ */
166
+ const angleFromPlaneDeg = (planeToFieldDeg) => 90 - planeToFieldDeg;
167
+
168
+ //#endregion
169
+ export { angleFromPlaneDeg, coilTorqueNm, forceOnPath, forcePerMetreOnWire, magneticMomentAm2, momentOfLoop, parallelWireForce, torqueFromMoment };
@@ -0,0 +1,77 @@
1
+ import { Worked } from "../../core/worked.mjs";
2
+
3
+ //#region src/physics/momentum/collide.d.ts
4
+ interface CollisionInput {
5
+ readonly m1: number;
6
+ readonly u1: number;
7
+ readonly m2: number;
8
+ readonly u2: number;
9
+ /**
10
+ * Coefficient of restitution, 0 to 1. Defaults to 1, perfectly elastic.
11
+ *
12
+ * Not clamped silently: a value outside the range means the bodies separate faster than they
13
+ * approached, which needs an energy source the collision does not have, and that is a mistake
14
+ * worth reporting rather than rounding away.
15
+ */
16
+ readonly restitution?: number;
17
+ }
18
+ interface CollisionOutcome {
19
+ readonly v1: number;
20
+ readonly v2: number;
21
+ readonly restitution: number;
22
+ readonly momentumBefore: number;
23
+ readonly momentumAfter: number;
24
+ readonly kineticBefore: number;
25
+ readonly kineticAfter: number;
26
+ /** Energy turned into heat, sound and deformation. Zero only at `e = 1`. */
27
+ readonly kineticLost: number;
28
+ /** The closing speed, and the separating speed, whose ratio IS `e`. */
29
+ readonly approachSpeed: number;
30
+ readonly separationSpeed: number;
31
+ readonly worked: Worked;
32
+ }
33
+ /**
34
+ * Solve a head-on collision.
35
+ *
36
+ * ```ts
37
+ * collide({ m1: 5, u1: 2, m2: 3, u2: 0 }); // elastic
38
+ * collide({ m1: 0.025, u1: 400, m2: 1.975, u2: 0, restitution: 0 }); // bullet into a block
39
+ * ```
40
+ */
41
+ declare function collide(input: CollisionInput, sf?: number): CollisionOutcome;
42
+ /**
43
+ * The restitution a collision actually had, measured from what happened.
44
+ *
45
+ * The inverse, and the one an experiment produces: drop a ball, measure the bounce, divide. Worth
46
+ * having because it turns `e` from a number in a formula into something a learner has measured.
47
+ */
48
+ declare function restitutionOf(u1: number, u2: number, v1: number, v2: number): number;
49
+ /**
50
+ * A ball bouncing on the ground: `e = √(h_bounce / h_drop)`.
51
+ *
52
+ * The standard measurement, and the square root is the part that surprises people. Restitution is a
53
+ * ratio of SPEEDS and height goes as speed squared, so a ball returning to half its height has
54
+ * `e = 0.71`, not 0.5.
55
+ */
56
+ declare function restitutionFromBounce(dropHeight: number, bounceHeight: number, sf?: number): {
57
+ value: number;
58
+ worked: Worked;
59
+ };
60
+ /**
61
+ * Bodies that start together and fly apart: an explosion, a recoiling gun, a person stepping off a
62
+ * boat.
63
+ *
64
+ * Not a different law. Total momentum before is whatever it was, usually zero, and it is still that
65
+ * afterwards, so the fragments' momenta must cancel. Give every fragment's velocity except one and
66
+ * this returns the missing one.
67
+ */
68
+ declare function separateFrom(initialMomentum: number, known: readonly {
69
+ label: string;
70
+ mass: number;
71
+ velocity: number;
72
+ }[], unknownMass: number, sf?: number): {
73
+ velocity: number;
74
+ worked: Worked;
75
+ };
76
+ //#endregion
77
+ export { CollisionInput, CollisionOutcome, collide, restitutionFromBounce, restitutionOf, separateFrom };
@@ -0,0 +1,115 @@
1
+ import { calc, texSigFigs } from "../../core/worked.mjs";
2
+
3
+ //#region src/physics/momentum/collide.ts
4
+ /**
5
+ * Collisions in one dimension, with elastic and perfectly inelastic as the ENDS OF ONE SCALE.
6
+ *
7
+ * Textbooks present two types with two sets of formulas, and students memorise which to use. They
8
+ * are the same collision with one number changed. That number is the coefficient of restitution,
9
+ *
10
+ * e = (speed of separation) / (speed of approach) = (v₂ − v₁) / (u₁ − u₂)
11
+ *
12
+ * and it runs from 1 (perfectly elastic, nothing lost, they separate as fast as they closed) to 0
13
+ * (perfectly inelastic, they move off together). Every real collision is somewhere in between, and
14
+ * no real collision is either. A slider from 0 to 1 is a better teaching object than two formulas,
15
+ * because it shows the kinetic energy draining away continuously as `e` falls and being exactly
16
+ * conserved only at the single point `e = 1`.
17
+ *
18
+ * TWO EQUATIONS, TWO UNKNOWNS, always. Momentum is conserved in every collision without exception,
19
+ * which gives one equation; restitution gives the second; and the pair solves for both final
20
+ * velocities. Energy is NOT an input, it is a RESULT, and the amount lost is what `e` is really
21
+ * telling you.
22
+ *
23
+ * Signs matter and are not negotiable: velocities are along one axis, positive one way. Two bodies
24
+ * approaching each other have opposite signs.
25
+ *
26
+ * Pure: no React, no pixels.
27
+ */
28
+ const kinetic = (m, v) => .5 * m * v * v;
29
+ /**
30
+ * Solve a head-on collision.
31
+ *
32
+ * ```ts
33
+ * collide({ m1: 5, u1: 2, m2: 3, u2: 0 }); // elastic
34
+ * collide({ m1: 0.025, u1: 400, m2: 1.975, u2: 0, restitution: 0 }); // bullet into a block
35
+ * ```
36
+ */
37
+ function collide(input, sf = 3) {
38
+ const { m1, u1, m2, u2 } = input;
39
+ const e = input.restitution ?? 1;
40
+ if (m1 <= 0 || m2 <= 0) throw new Error("Both masses must be positive.");
41
+ if (e < 0 || e > 1) throw new Error(`A coefficient of restitution of ${e} is not physical: it must lie between 0 (they stay together) and 1 (nothing is lost). Above 1 the bodies would leave faster than they arrived.`);
42
+ const total = m1 + m2;
43
+ const v1 = (m1 * u1 + m2 * u2 + m2 * e * (u2 - u1)) / total;
44
+ const v2 = (m1 * u1 + m2 * u2 + m1 * e * (u1 - u2)) / total;
45
+ const momentumBefore = m1 * u1 + m2 * u2;
46
+ const momentumAfter = m1 * v1 + m2 * v2;
47
+ const kineticBefore = kinetic(m1, u1) + kinetic(m2, u2);
48
+ const kineticAfter = kinetic(m1, v1) + kinetic(m2, v2);
49
+ const approachSpeed = u1 - u2;
50
+ const separationSpeed = v2 - v1;
51
+ const w = calc().step("m_1u_1 + m_2u_2 = m_1v_1 + m_2v_2", "momentum is conserved in EVERY collision, elastic or not. This is the equation that never changes").step("e = \\frac{v_2 - v_1}{u_1 - u_2}", `restitution supplies the second equation. Here e = ${texSigFigs(e, sf)}${e === 1 ? ", perfectly elastic" : e === 0 ? ", perfectly inelastic: they move off together" : ""}`).step(`u_1 = ${texSigFigs(u1, sf)},\\quad u_2 = ${texSigFigs(u2, sf)}\\ \\mathrm{m\\,s^{-1}}`, "signed along one axis: bodies approaching each other have opposite signs").step(`v_1 = ${texSigFigs(v1, sf)},\\quad v_2 = ${texSigFigs(v2, sf)}\\ \\mathrm{m\\,s^{-1}}`, "two equations, two unknowns").step(`E_k: ${texSigFigs(kineticBefore, sf)} \\to ${texSigFigs(kineticAfter, sf)}\\ \\mathrm{J}`, kineticBefore - kineticAfter < 1e-9 ? "nothing lost, which happens at e = 1 and nowhere else" : `${texSigFigs(kineticBefore - kineticAfter, sf)} J became heat, sound and deformation. Energy is a RESULT here, not an input`);
52
+ return {
53
+ v1,
54
+ v2,
55
+ restitution: e,
56
+ momentumBefore,
57
+ momentumAfter,
58
+ kineticBefore,
59
+ kineticAfter,
60
+ kineticLost: kineticBefore - kineticAfter,
61
+ approachSpeed,
62
+ separationSpeed,
63
+ worked: w.done(v1)
64
+ };
65
+ }
66
+ /**
67
+ * The restitution a collision actually had, measured from what happened.
68
+ *
69
+ * The inverse, and the one an experiment produces: drop a ball, measure the bounce, divide. Worth
70
+ * having because it turns `e` from a number in a formula into something a learner has measured.
71
+ */
72
+ function restitutionOf(u1, u2, v1, v2) {
73
+ const approach = u1 - u2;
74
+ if (Math.abs(approach) < 1e-12) throw new Error("They were not approaching each other, so there is no collision to measure.");
75
+ return (v2 - v1) / approach;
76
+ }
77
+ /**
78
+ * A ball bouncing on the ground: `e = √(h_bounce / h_drop)`.
79
+ *
80
+ * The standard measurement, and the square root is the part that surprises people. Restitution is a
81
+ * ratio of SPEEDS and height goes as speed squared, so a ball returning to half its height has
82
+ * `e = 0.71`, not 0.5.
83
+ */
84
+ function restitutionFromBounce(dropHeight, bounceHeight, sf = 3) {
85
+ if (dropHeight <= 0) throw new Error("The drop height must be positive.");
86
+ if (bounceHeight < 0 || bounceHeight > dropHeight) throw new Error("The bounce cannot be higher than the drop, or negative.");
87
+ const value = Math.sqrt(bounceHeight / dropHeight);
88
+ return {
89
+ value,
90
+ worked: calc().step("v = \\sqrt{2gh}", "the speed at the ground, from the drop and from the rebound").step("e = \\frac{v_{up}}{v_{down}} = \\sqrt{\\frac{h_{bounce}}{h_{drop}}}", "the g and the 2 cancel").step(`e = \\sqrt{\\frac{${texSigFigs(bounceHeight, sf)}}{${texSigFigs(dropHeight, sf)}}} = ${texSigFigs(value, sf)}`, "a ratio of SPEEDS, so the height ratio is squared: half the height is e = 0.707, not 0.5").done(value)
91
+ };
92
+ }
93
+ /**
94
+ * Bodies that start together and fly apart: an explosion, a recoiling gun, a person stepping off a
95
+ * boat.
96
+ *
97
+ * Not a different law. Total momentum before is whatever it was, usually zero, and it is still that
98
+ * afterwards, so the fragments' momenta must cancel. Give every fragment's velocity except one and
99
+ * this returns the missing one.
100
+ */
101
+ function separateFrom(initialMomentum, known, unknownMass, sf = 3) {
102
+ if (unknownMass <= 0) throw new Error("The remaining mass must be positive.");
103
+ const accounted = known.reduce((p, k) => p + k.mass * k.velocity, 0);
104
+ const velocity = (initialMomentum - accounted) / unknownMass;
105
+ const w = calc().step("\\sum p_{\\text{before}} = \\sum p_{\\text{after}}", initialMomentum === 0 ? "it started at rest, so the pieces’ momenta must cancel exactly" : "total momentum is unchanged, however many pieces there now are");
106
+ for (const k of known) w.step(`${k.label}: ${texSigFigs(k.mass, sf)} \\times ${texSigFigs(k.velocity, sf)} = ${texSigFigs(k.mass * k.velocity, sf)}\\ \\mathrm{kg\\,m\\,s^{-1}}`);
107
+ w.step(`v = \\frac{${texSigFigs(initialMomentum, sf)} - ${texSigFigs(accounted, sf)}}{${texSigFigs(unknownMass, sf)}} = ${texSigFigs(velocity, sf)}\\ \\mathrm{m\\,s^{-1}}`, "the sign says which way it goes, and it is opposite to whatever the others did");
108
+ return {
109
+ velocity,
110
+ worked: w.done(velocity)
111
+ };
112
+ }
113
+
114
+ //#endregion
115
+ export { collide, restitutionFromBounce, restitutionOf, separateFrom };