@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,95 @@
1
+ //#region src/thermo/processes.d.ts
2
+ /**
3
+ * Quasi-static processes on an ideal gas, and the first law along each.
4
+ *
5
+ * THE MODEL. One ideal gas, pV = nRT, with a heat-capacity ratio γ = Cp/Cv. The
6
+ * first law ΔU = Q − W holds on every leg, with the sign convention that W is
7
+ * work done BY the gas and Q is heat added TO it:
8
+ *
9
+ * isothermal T const pV = const W = nRT·ln(V₂/V₁) Q = W ΔU = 0
10
+ * adiabatic Q = 0 pVᵞ = const W = (p₁V₁−p₂V₂)/(γ−1) = −ΔU ΔS = 0
11
+ * isobaric p const V/T = const W = pΔV Q = nCpΔT
12
+ * isochoric V const p/T = const W = 0 Q = ΔU = nCvΔT
13
+ * linear a straight line on the p–V diagram; W is the trapezium area
14
+ *
15
+ * WHY `linear` IS HERE. The four named processes are the ones with closed
16
+ * forms, but the cycles students are actually given are drawn on a p–V diagram
17
+ * with straight legs that are none of them. Without it, the commonest exercise
18
+ * in the topic ("complete the Q, W, ΔU table for A→B→C→A") cannot be expressed
19
+ * at all, and every lab has to compute its own trapezium.
20
+ *
21
+ * THE METHOD. Closed forms wherever one exists, because they are exact and they
22
+ * are what the answer is checked against. `linear` integrates ∫p dV by the
23
+ * trapezium rule over the sampled path, which is EXACT for a straight line
24
+ * rather than merely convergent: the integrand is a first-degree polynomial in
25
+ * V and the trapezium rule is exact to first degree. Q then comes from the
26
+ * first law rather than from a separate formula, which is the only way to keep
27
+ * the three quantities consistent on a path that has no heat-capacity of its
28
+ * own.
29
+ *
30
+ * UNITS: SI. Pressure in pascals, volume in m³, temperature in kelvin, energy
31
+ * in joules, entropy in J/K.
32
+ */
33
+ type ProcessKind = 'isothermal' | 'adiabatic' | 'isobaric' | 'isochoric' | 'linear';
34
+ interface GasState {
35
+ /** Pressure, Pa. */
36
+ P: number;
37
+ /** Volume, m³. */
38
+ V: number;
39
+ /** Temperature, K. */
40
+ T: number;
41
+ /** Amount, mol. */
42
+ n: number;
43
+ }
44
+ interface ProcessResult {
45
+ kind: ProcessKind;
46
+ start: GasState;
47
+ end: GasState;
48
+ /** Sampled states from start to end, for drawing the p–V curve. */
49
+ path: GasState[];
50
+ /** Work done BY the gas, J ( = ∫p dV, the area under the p–V curve). */
51
+ W: number;
52
+ /** Heat added TO the gas, J. */
53
+ Q: number;
54
+ /** Change in internal energy, J ( = nCvΔT). */
55
+ dU: number;
56
+ /** Change in entropy, J/K. */
57
+ dS: number;
58
+ }
59
+ /**
60
+ * Run one quasi-static process from `start` to a target.
61
+ *
62
+ * Give exactly one target coordinate the process can reach: a target volume for
63
+ * an isothermal or adiabatic expansion, a target temperature for isobaric or
64
+ * isochoric heating. `linear` is the exception and needs a full end state,
65
+ * since a straight line on the p–V diagram is fixed by its two ends and by
66
+ * nothing less.
67
+ */
68
+ declare function runProcess(start: GasState, kind: ProcessKind, target: {
69
+ V?: number;
70
+ P?: number;
71
+ T?: number;
72
+ }, gamma?: number, samples?: number): ProcessResult;
73
+ /**
74
+ * Work done by the gas along an arbitrary sampled path, J, by the trapezium
75
+ * rule over ∫p dV.
76
+ *
77
+ * For a path that came from somewhere other than `runProcess`: a measured
78
+ * indicator diagram, a path a student dragged out by hand, a cycle assembled
79
+ * from points. The sign follows the direction of travel, so a loop traversed
80
+ * clockwise gives positive net work and anticlockwise gives negative, which is
81
+ * the engine-versus-refrigerator distinction and not a convention to be fixed
82
+ * up afterwards.
83
+ */
84
+ declare function workAlongPathJ(path: readonly GasState[]): number;
85
+ /**
86
+ * The first law as a check rather than as a calculation: returns how far
87
+ * Q − W − ΔU is from zero, in joules.
88
+ *
89
+ * Exposed so a lab can SHOW conservation holding instead of asserting it in a
90
+ * test the student never sees. A number that is not zero here is a bug in the
91
+ * kernel, and it should be visible as one.
92
+ */
93
+ declare function firstLawResidualJ(result: ProcessResult): number;
94
+ //#endregion
95
+ export { GasState, ProcessKind, ProcessResult, firstLawResidualJ, runProcess, workAlongPathJ };
@@ -0,0 +1,154 @@
1
+ import { R, gammaMonatomic, molarHeatCapacities } from "./gas.mjs";
2
+
3
+ //#region src/thermo/processes.ts
4
+ /**
5
+ * Quasi-static processes on an ideal gas, and the first law along each.
6
+ *
7
+ * THE MODEL. One ideal gas, pV = nRT, with a heat-capacity ratio γ = Cp/Cv. The
8
+ * first law ΔU = Q − W holds on every leg, with the sign convention that W is
9
+ * work done BY the gas and Q is heat added TO it:
10
+ *
11
+ * isothermal T const pV = const W = nRT·ln(V₂/V₁) Q = W ΔU = 0
12
+ * adiabatic Q = 0 pVᵞ = const W = (p₁V₁−p₂V₂)/(γ−1) = −ΔU ΔS = 0
13
+ * isobaric p const V/T = const W = pΔV Q = nCpΔT
14
+ * isochoric V const p/T = const W = 0 Q = ΔU = nCvΔT
15
+ * linear a straight line on the p–V diagram; W is the trapezium area
16
+ *
17
+ * WHY `linear` IS HERE. The four named processes are the ones with closed
18
+ * forms, but the cycles students are actually given are drawn on a p–V diagram
19
+ * with straight legs that are none of them. Without it, the commonest exercise
20
+ * in the topic ("complete the Q, W, ΔU table for A→B→C→A") cannot be expressed
21
+ * at all, and every lab has to compute its own trapezium.
22
+ *
23
+ * THE METHOD. Closed forms wherever one exists, because they are exact and they
24
+ * are what the answer is checked against. `linear` integrates ∫p dV by the
25
+ * trapezium rule over the sampled path, which is EXACT for a straight line
26
+ * rather than merely convergent: the integrand is a first-degree polynomial in
27
+ * V and the trapezium rule is exact to first degree. Q then comes from the
28
+ * first law rather than from a separate formula, which is the only way to keep
29
+ * the three quantities consistent on a path that has no heat-capacity of its
30
+ * own.
31
+ *
32
+ * UNITS: SI. Pressure in pascals, volume in m³, temperature in kelvin, energy
33
+ * in joules, entropy in J/K.
34
+ */
35
+ /** State completed from any two of (p,V,T) via pV = nRT. */
36
+ const fromPV = (P, V, n) => ({
37
+ P,
38
+ V,
39
+ n,
40
+ T: P * V / (n * R)
41
+ });
42
+ /**
43
+ * Run one quasi-static process from `start` to a target.
44
+ *
45
+ * Give exactly one target coordinate the process can reach: a target volume for
46
+ * an isothermal or adiabatic expansion, a target temperature for isobaric or
47
+ * isochoric heating. `linear` is the exception and needs a full end state,
48
+ * since a straight line on the p–V diagram is fixed by its two ends and by
49
+ * nothing less.
50
+ */
51
+ function runProcess(start, kind, target, gamma = gammaMonatomic, samples = 64) {
52
+ const { n } = start;
53
+ const { cv: Cv, cp: Cp } = molarHeatCapacities(gamma);
54
+ let end;
55
+ if (kind === "isothermal") {
56
+ const T = start.T;
57
+ const V2 = target.V ?? (target.P != null ? n * R * T / target.P : start.V);
58
+ end = fromPV(n * R * T / V2, V2, n);
59
+ } else if (kind === "adiabatic") {
60
+ const K = start.P * start.V ** gamma;
61
+ const V2 = target.V ?? (target.T != null ? start.V * (start.T / target.T) ** (1 / (gamma - 1)) : start.V);
62
+ end = fromPV(K / V2 ** gamma, V2, n);
63
+ } else if (kind === "isobaric") {
64
+ const P = start.P;
65
+ end = fromPV(P, target.V ?? (target.T != null ? n * R * target.T / P : start.V), n);
66
+ } else if (kind === "linear") {
67
+ if (target.P == null || target.V == null) throw new RangeError("A linear leg on the p–V diagram is fixed by its two ends, so it needs both a target pressure and a target volume.");
68
+ end = fromPV(target.P, target.V, n);
69
+ } else {
70
+ const V = start.V;
71
+ end = fromPV(target.P ?? (target.T != null ? n * R * target.T / V : start.P), V, n);
72
+ }
73
+ const path = [];
74
+ for (let i = 0; i <= samples; i++) {
75
+ const u = i / samples;
76
+ let s;
77
+ if (kind === "isochoric") s = fromPV(start.P + (end.P - start.P) * u, start.V, n);
78
+ else {
79
+ const V = start.V + (end.V - start.V) * u;
80
+ if (kind === "isothermal") s = fromPV(n * R * start.T / V, V, n);
81
+ else if (kind === "adiabatic") s = fromPV(start.P * start.V ** gamma / V ** gamma, V, n);
82
+ else if (kind === "linear") s = fromPV(start.P + (end.P - start.P) * u, V, n);
83
+ else s = fromPV(start.P, V, n);
84
+ }
85
+ path.push(s);
86
+ }
87
+ const dU = n * Cv * (end.T - start.T);
88
+ let W, Q, dS;
89
+ if (kind === "isothermal") {
90
+ W = n * R * start.T * Math.log(end.V / start.V);
91
+ Q = W;
92
+ dS = n * R * Math.log(end.V / start.V);
93
+ } else if (kind === "adiabatic") {
94
+ W = (start.P * start.V - end.P * end.V) / (gamma - 1);
95
+ Q = 0;
96
+ dS = 0;
97
+ } else if (kind === "isobaric") {
98
+ W = start.P * (end.V - start.V);
99
+ Q = n * Cp * (end.T - start.T);
100
+ dS = n * Cp * Math.log(end.T / start.T);
101
+ } else if (kind === "linear") {
102
+ W = .5 * (start.P + end.P) * (end.V - start.V);
103
+ Q = dU + W;
104
+ dS = n * Cv * Math.log(end.T / start.T) + n * R * Math.log(end.V / start.V);
105
+ } else {
106
+ W = 0;
107
+ Q = dU;
108
+ dS = n * Cv * Math.log(end.T / start.T);
109
+ }
110
+ return {
111
+ kind,
112
+ start,
113
+ end,
114
+ path,
115
+ W,
116
+ Q,
117
+ dU,
118
+ dS
119
+ };
120
+ }
121
+ /**
122
+ * Work done by the gas along an arbitrary sampled path, J, by the trapezium
123
+ * rule over ∫p dV.
124
+ *
125
+ * For a path that came from somewhere other than `runProcess`: a measured
126
+ * indicator diagram, a path a student dragged out by hand, a cycle assembled
127
+ * from points. The sign follows the direction of travel, so a loop traversed
128
+ * clockwise gives positive net work and anticlockwise gives negative, which is
129
+ * the engine-versus-refrigerator distinction and not a convention to be fixed
130
+ * up afterwards.
131
+ */
132
+ function workAlongPathJ(path) {
133
+ let total = 0;
134
+ for (let i = 1; i < path.length; i++) {
135
+ const a = path[i - 1];
136
+ const b = path[i];
137
+ total += .5 * (a.P + b.P) * (b.V - a.V);
138
+ }
139
+ return total;
140
+ }
141
+ /**
142
+ * The first law as a check rather than as a calculation: returns how far
143
+ * Q − W − ΔU is from zero, in joules.
144
+ *
145
+ * Exposed so a lab can SHOW conservation holding instead of asserting it in a
146
+ * test the student never sees. A number that is not zero here is a bug in the
147
+ * kernel, and it should be visible as one.
148
+ */
149
+ function firstLawResidualJ(result) {
150
+ return result.Q - result.W - result.dU;
151
+ }
152
+
153
+ //#endregion
154
+ export { firstLawResidualJ, runProcess, workAlongPathJ };
@@ -0,0 +1,174 @@
1
+ //#region src/thermo/temperature.d.ts
2
+ /**
3
+ * Thermometry: temperature scales, and the thermometric property that any
4
+ * thermometer actually measures.
5
+ *
6
+ * THE MODEL. A thermometer never measures temperature. It measures some other
7
+ * quantity X that varies with it: the length of a mercury column, the pressure
8
+ * of a fixed volume of gas, the resistance of a platinum wire, the emf across a
9
+ * junction of two metals. Assume X is LINEAR in temperature, pin it at two
10
+ * reproducible fixed points, and the scale follows:
11
+ *
12
+ * θ X − X_ice
13
+ * ───── = ───────────────────── (θ in °C)
14
+ * 100 X_steam − X_ice
15
+ *
16
+ * Every scale in the table below is the same statement with a different pair of
17
+ * numbers at the fixed points, which is why the textbook chain
18
+ *
19
+ * C/5 = (F−32)/9 = (K−273.15)/5 = (Rn−492)/9 = R/4
20
+ *
21
+ * holds: each term is the same fraction of the same interval.
22
+ *
23
+ * WHAT MAKES A SCALE. A scale is affine in thermodynamic temperature, so two
24
+ * numbers fix it: how many of its degrees span one kelvin, and what it reads at
25
+ * absolute zero. Ice and steam points are DERIVED from those here rather than
26
+ * stored beside them, because a stored pair can drift out of step with the
27
+ * conversion that is supposed to reproduce it.
28
+ *
29
+ * SCOPE. Linear thermometry only. A real platinum resistance thermometer is
30
+ * quadratic and a thermocouple is worse; both have their own functions below,
31
+ * and the difference between them and the linear assumption is the reason
32
+ * different thermometers disagree away from the fixed points.
33
+ *
34
+ * Units: temperatures carry their scale explicitly. Anything named `...K` is
35
+ * kelvin, `...C` is Celsius. The thermometric property X is unitless here
36
+ * because the ratio cancels it.
37
+ */
38
+ type TemperatureScale = 'celsius' | 'fahrenheit' | 'kelvin' | 'rankine' | 'reaumur';
39
+ interface ScaleDefinition {
40
+ name: string;
41
+ /** The degree symbol as written, e.g. '°C', 'K'. */
42
+ symbol: string;
43
+ /** How many of this scale's degrees span one kelvin. */
44
+ degreesPerKelvin: number;
45
+ /** What this scale reads at absolute zero. */
46
+ absoluteZeroReading: number;
47
+ /** True for a scale whose zero IS absolute zero, so ratios of readings mean something. */
48
+ absolute: boolean;
49
+ }
50
+ /**
51
+ * The five scales, each defined by its slope against kelvin and its reading at
52
+ * absolute zero.
53
+ *
54
+ * Réaumur and Rankine are here because they appear in the fixed-point tables
55
+ * students are asked to complete, not because anyone uses them.
56
+ */
57
+ declare const TEMPERATURE_SCALES: Record<TemperatureScale, ScaleDefinition>;
58
+ /** A reading on any scale, as thermodynamic temperature in kelvin. */
59
+ declare function toKelvin(reading: number, scale: TemperatureScale): number;
60
+ /** Thermodynamic temperature in kelvin, as a reading on any scale. */
61
+ declare function fromKelvin(kelvin: number, scale: TemperatureScale): number;
62
+ /**
63
+ * Convert a temperature READING between scales, offsets included.
64
+ *
65
+ * This is the one to use for "a fever of 102 °F is what in Celsius". It is the
66
+ * WRONG one for "a rise of 10 °F is what in Celsius" — see
67
+ * `convertTemperatureInterval`.
68
+ */
69
+ declare function convertTemperature(value: number, from: TemperatureScale, to: TemperatureScale): number;
70
+ /**
71
+ * Convert a temperature DIFFERENCE between scales: slope only, no offset.
72
+ *
73
+ * Split out from `convertTemperature` because running a difference through the
74
+ * offset is the most common temperature mistake there is, and it is silent: a
75
+ * 10 °C rise comes back as 50 °F instead of 18 °F, and 50 is a perfectly
76
+ * plausible-looking number. Separate functions make the caller say which they
77
+ * meant.
78
+ */
79
+ declare function convertTemperatureInterval(delta: number, from: TemperatureScale, to: TemperatureScale): number;
80
+ /** What a scale reads at the ice point, derived rather than tabulated. */
81
+ declare const icePointOn: (scale: TemperatureScale) => number;
82
+ /** What a scale reads at the steam point, derived rather than tabulated. */
83
+ declare const steamPointOn: (scale: TemperatureScale) => number;
84
+ /** The number of this scale's degrees between the ice and steam points. */
85
+ declare const fundamentalInterval: (scale: TemperatureScale) => number;
86
+ /**
87
+ * The reading at which two scales agree, or `null` when they never do.
88
+ *
89
+ * Answers "at what temperature do the Celsius and Fahrenheit thermometers show
90
+ * the same number" (−40) directly, instead of by setting up the equation by
91
+ * hand each time. Two scales with equal slope and different zeros are parallel
92
+ * and never meet, which is the `null`: Celsius and Kelvin never read alike.
93
+ */
94
+ declare function scaleReadingsAgree(a: TemperatureScale, b: TemperatureScale): number | null;
95
+ interface FixedPointCalibration {
96
+ /** The thermometric property read at the unknown temperature. */
97
+ x: number;
98
+ /** The same property read in melting ice. */
99
+ xIce: number;
100
+ /** The same property read in steam at standard pressure. */
101
+ xSteam: number;
102
+ }
103
+ /**
104
+ * Temperature from any thermometric property, by linear interpolation between
105
+ * the two fixed points.
106
+ *
107
+ * Deliberately unitless in X: the ratio cancels it, so the SAME function reads
108
+ * a mercury column in centimetres, a gas pressure in N/m², a resistance in ohms
109
+ * and a thermocouple emf in millivolts. That cancellation is the physics, and
110
+ * writing one function per instrument would hide it.
111
+ *
112
+ * Throws when the two fixed points coincide, because a property that does not
113
+ * change between ice and steam is not a thermometric property and the
114
+ * interpolation would be a division by zero dressed up as a temperature.
115
+ */
116
+ declare function thermometricTemperatureC({
117
+ x,
118
+ xIce,
119
+ xSteam
120
+ }: FixedPointCalibration): number;
121
+ /** The inverse: what the property reads at a given Celsius temperature. */
122
+ declare function thermometricValue(celsius: number, xIce: number, xSteam: number): number;
123
+ /**
124
+ * Temperature from a thermometer calibrated at the triple point alone, in
125
+ * kelvin: T = 273.16 · X / X_triple.
126
+ *
127
+ * This is the constant-volume gas thermometer's defining relation, and it needs
128
+ * ONE fixed point rather than two because it uses a property that is
129
+ * proportional to thermodynamic temperature rather than merely linear in it.
130
+ * Pressure at fixed volume extrapolates to zero at absolute zero, so the origin
131
+ * is the second point and does not have to be measured.
132
+ *
133
+ * Throws on a non-positive `xTriple`, and on a negative `x`: a gas pressure
134
+ * below zero is not a cold reading, it is a broken instrument.
135
+ */
136
+ declare function triplePointTemperatureK(x: number, xTriple: number): number;
137
+ /**
138
+ * Resistance of a metal thermometer at θ °C, to second order:
139
+ *
140
+ * R_θ = R_0 · (1 + a·θ + b·θ²)
141
+ *
142
+ * Pass `b = 0` for the linear model. The quadratic term is why a platinum
143
+ * thermometer and a mercury one, both correct at 0 °C and 100 °C, disagree at
144
+ * 50 °C: the curvature is real, and the linear scale is the chord across it.
145
+ */
146
+ declare function resistanceAtC(r0: number, a: number, theta: number, b?: number): number;
147
+ /**
148
+ * Thermocouple emf against the cold junction, in the standard quadratic form:
149
+ *
150
+ * E = a·θ + b·θ²
151
+ *
152
+ * Kept as a named function rather than inlined because the two temperatures
153
+ * that fall out of it, below, are the whole reason a thermocouple has a usable
154
+ * range at all.
155
+ */
156
+ declare function thermocoupleEmf(theta: number, a: number, b: number): number;
157
+ /**
158
+ * The NEUTRAL temperature, where the emf peaks: θ_n = −a / 2b.
159
+ *
160
+ * Past it the emf falls again, so a single emf reading matches two
161
+ * temperatures and the thermocouple stops being a thermometer. That is the
162
+ * practical limit of the instrument, and it is a property of the metal pair
163
+ * rather than of the circuit.
164
+ */
165
+ declare function thermocoupleNeutralTemperatureC(a: number, b: number): number;
166
+ /**
167
+ * The INVERSION temperature, where the emf returns to zero: θ_i = −a / b.
168
+ *
169
+ * Exactly twice the neutral temperature when the cold junction is at 0 °C,
170
+ * which is the check a student is usually asked to make.
171
+ */
172
+ declare function thermocoupleInversionTemperatureC(a: number, b: number): number;
173
+ //#endregion
174
+ export { FixedPointCalibration, ScaleDefinition, TEMPERATURE_SCALES, TemperatureScale, convertTemperature, convertTemperatureInterval, fromKelvin, fundamentalInterval, icePointOn, resistanceAtC, scaleReadingsAgree, steamPointOn, thermocoupleEmf, thermocoupleInversionTemperatureC, thermocoupleNeutralTemperatureC, thermometricTemperatureC, thermometricValue, toKelvin, triplePointTemperatureK };
@@ -0,0 +1,236 @@
1
+ import { WATER_TRIPLE_POINT_K, ZERO_CELSIUS_K } from "../core/constants.mjs";
2
+
3
+ //#region src/thermo/temperature.ts
4
+ /**
5
+ * Thermometry: temperature scales, and the thermometric property that any
6
+ * thermometer actually measures.
7
+ *
8
+ * THE MODEL. A thermometer never measures temperature. It measures some other
9
+ * quantity X that varies with it: the length of a mercury column, the pressure
10
+ * of a fixed volume of gas, the resistance of a platinum wire, the emf across a
11
+ * junction of two metals. Assume X is LINEAR in temperature, pin it at two
12
+ * reproducible fixed points, and the scale follows:
13
+ *
14
+ * θ X − X_ice
15
+ * ───── = ───────────────────── (θ in °C)
16
+ * 100 X_steam − X_ice
17
+ *
18
+ * Every scale in the table below is the same statement with a different pair of
19
+ * numbers at the fixed points, which is why the textbook chain
20
+ *
21
+ * C/5 = (F−32)/9 = (K−273.15)/5 = (Rn−492)/9 = R/4
22
+ *
23
+ * holds: each term is the same fraction of the same interval.
24
+ *
25
+ * WHAT MAKES A SCALE. A scale is affine in thermodynamic temperature, so two
26
+ * numbers fix it: how many of its degrees span one kelvin, and what it reads at
27
+ * absolute zero. Ice and steam points are DERIVED from those here rather than
28
+ * stored beside them, because a stored pair can drift out of step with the
29
+ * conversion that is supposed to reproduce it.
30
+ *
31
+ * SCOPE. Linear thermometry only. A real platinum resistance thermometer is
32
+ * quadratic and a thermocouple is worse; both have their own functions below,
33
+ * and the difference between them and the linear assumption is the reason
34
+ * different thermometers disagree away from the fixed points.
35
+ *
36
+ * Units: temperatures carry their scale explicitly. Anything named `...K` is
37
+ * kelvin, `...C` is Celsius. The thermometric property X is unitless here
38
+ * because the ratio cancels it.
39
+ */
40
+ /**
41
+ * The five scales, each defined by its slope against kelvin and its reading at
42
+ * absolute zero.
43
+ *
44
+ * Réaumur and Rankine are here because they appear in the fixed-point tables
45
+ * students are asked to complete, not because anyone uses them.
46
+ */
47
+ const TEMPERATURE_SCALES = {
48
+ celsius: {
49
+ name: "Celsius",
50
+ symbol: "°C",
51
+ degreesPerKelvin: 1,
52
+ absoluteZeroReading: -ZERO_CELSIUS_K,
53
+ absolute: false
54
+ },
55
+ fahrenheit: {
56
+ name: "Fahrenheit",
57
+ symbol: "°F",
58
+ degreesPerKelvin: 1.8,
59
+ absoluteZeroReading: -459.67,
60
+ absolute: false
61
+ },
62
+ kelvin: {
63
+ name: "kelvin",
64
+ symbol: "K",
65
+ degreesPerKelvin: 1,
66
+ absoluteZeroReading: 0,
67
+ absolute: true
68
+ },
69
+ rankine: {
70
+ name: "Rankine",
71
+ symbol: "°Rn",
72
+ degreesPerKelvin: 1.8,
73
+ absoluteZeroReading: 0,
74
+ absolute: true
75
+ },
76
+ reaumur: {
77
+ name: "Réaumur",
78
+ symbol: "°R",
79
+ degreesPerKelvin: .8,
80
+ absoluteZeroReading: -218.52,
81
+ absolute: false
82
+ }
83
+ };
84
+ const definitionFor = (scale) => {
85
+ const found = TEMPERATURE_SCALES[scale];
86
+ if (!found) throw new RangeError(`Unknown temperature scale "${String(scale)}".`);
87
+ return found;
88
+ };
89
+ const finite = (value, what) => {
90
+ if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
91
+ return value;
92
+ };
93
+ /** A reading on any scale, as thermodynamic temperature in kelvin. */
94
+ function toKelvin(reading, scale) {
95
+ const s = definitionFor(scale);
96
+ return (finite(reading, "A temperature reading") - s.absoluteZeroReading) / s.degreesPerKelvin;
97
+ }
98
+ /** Thermodynamic temperature in kelvin, as a reading on any scale. */
99
+ function fromKelvin(kelvin, scale) {
100
+ const s = definitionFor(scale);
101
+ return finite(kelvin, "A temperature in kelvin") * s.degreesPerKelvin + s.absoluteZeroReading;
102
+ }
103
+ /**
104
+ * Convert a temperature READING between scales, offsets included.
105
+ *
106
+ * This is the one to use for "a fever of 102 °F is what in Celsius". It is the
107
+ * WRONG one for "a rise of 10 °F is what in Celsius" — see
108
+ * `convertTemperatureInterval`.
109
+ */
110
+ function convertTemperature(value, from, to) {
111
+ return fromKelvin(toKelvin(value, from), to);
112
+ }
113
+ /**
114
+ * Convert a temperature DIFFERENCE between scales: slope only, no offset.
115
+ *
116
+ * Split out from `convertTemperature` because running a difference through the
117
+ * offset is the most common temperature mistake there is, and it is silent: a
118
+ * 10 °C rise comes back as 50 °F instead of 18 °F, and 50 is a perfectly
119
+ * plausible-looking number. Separate functions make the caller say which they
120
+ * meant.
121
+ */
122
+ function convertTemperatureInterval(delta, from, to) {
123
+ return finite(delta, "A temperature interval") / definitionFor(from).degreesPerKelvin * definitionFor(to).degreesPerKelvin;
124
+ }
125
+ /** What a scale reads at the ice point, derived rather than tabulated. */
126
+ const icePointOn = (scale) => fromKelvin(ZERO_CELSIUS_K, scale);
127
+ /** What a scale reads at the steam point, derived rather than tabulated. */
128
+ const steamPointOn = (scale) => fromKelvin(ZERO_CELSIUS_K + 100, scale);
129
+ /** The number of this scale's degrees between the ice and steam points. */
130
+ const fundamentalInterval = (scale) => steamPointOn(scale) - icePointOn(scale);
131
+ /**
132
+ * The reading at which two scales agree, or `null` when they never do.
133
+ *
134
+ * Answers "at what temperature do the Celsius and Fahrenheit thermometers show
135
+ * the same number" (−40) directly, instead of by setting up the equation by
136
+ * hand each time. Two scales with equal slope and different zeros are parallel
137
+ * and never meet, which is the `null`: Celsius and Kelvin never read alike.
138
+ */
139
+ function scaleReadingsAgree(a, b) {
140
+ const sa = definitionFor(a);
141
+ const sb = definitionFor(b);
142
+ const slopeGap = sa.degreesPerKelvin - sb.degreesPerKelvin;
143
+ if (slopeGap === 0) return null;
144
+ return fromKelvin((sb.absoluteZeroReading - sa.absoluteZeroReading) / slopeGap, a);
145
+ }
146
+ /**
147
+ * Temperature from any thermometric property, by linear interpolation between
148
+ * the two fixed points.
149
+ *
150
+ * Deliberately unitless in X: the ratio cancels it, so the SAME function reads
151
+ * a mercury column in centimetres, a gas pressure in N/m², a resistance in ohms
152
+ * and a thermocouple emf in millivolts. That cancellation is the physics, and
153
+ * writing one function per instrument would hide it.
154
+ *
155
+ * Throws when the two fixed points coincide, because a property that does not
156
+ * change between ice and steam is not a thermometric property and the
157
+ * interpolation would be a division by zero dressed up as a temperature.
158
+ */
159
+ function thermometricTemperatureC({ x, xIce, xSteam }) {
160
+ const span = finite(xSteam, "The steam-point value") - finite(xIce, "The ice-point value");
161
+ if (span === 0) throw new RangeError("The ice-point and steam-point readings are equal, so this property does not vary with temperature.");
162
+ return (finite(x, "The measured value") - xIce) / span * 100;
163
+ }
164
+ /** The inverse: what the property reads at a given Celsius temperature. */
165
+ function thermometricValue(celsius, xIce, xSteam) {
166
+ return xIce + finite(celsius, "A temperature") / 100 * (xSteam - xIce);
167
+ }
168
+ /**
169
+ * Temperature from a thermometer calibrated at the triple point alone, in
170
+ * kelvin: T = 273.16 · X / X_triple.
171
+ *
172
+ * This is the constant-volume gas thermometer's defining relation, and it needs
173
+ * ONE fixed point rather than two because it uses a property that is
174
+ * proportional to thermodynamic temperature rather than merely linear in it.
175
+ * Pressure at fixed volume extrapolates to zero at absolute zero, so the origin
176
+ * is the second point and does not have to be measured.
177
+ *
178
+ * Throws on a non-positive `xTriple`, and on a negative `x`: a gas pressure
179
+ * below zero is not a cold reading, it is a broken instrument.
180
+ */
181
+ function triplePointTemperatureK(x, xTriple) {
182
+ if (finite(xTriple, "The triple-point value") <= 0) throw new RangeError("The triple-point reading must be positive.");
183
+ if (finite(x, "The measured value") < 0) throw new RangeError("A property proportional to absolute temperature cannot be negative.");
184
+ return WATER_TRIPLE_POINT_K * x / xTriple;
185
+ }
186
+ /**
187
+ * Resistance of a metal thermometer at θ °C, to second order:
188
+ *
189
+ * R_θ = R_0 · (1 + a·θ + b·θ²)
190
+ *
191
+ * Pass `b = 0` for the linear model. The quadratic term is why a platinum
192
+ * thermometer and a mercury one, both correct at 0 °C and 100 °C, disagree at
193
+ * 50 °C: the curvature is real, and the linear scale is the chord across it.
194
+ */
195
+ function resistanceAtC(r0, a, theta, b = 0) {
196
+ if (finite(r0, "The ice-point resistance") <= 0) throw new RangeError("The ice-point resistance must be positive.");
197
+ return r0 * (1 + a * finite(theta, "A temperature") + b * theta * theta);
198
+ }
199
+ /**
200
+ * Thermocouple emf against the cold junction, in the standard quadratic form:
201
+ *
202
+ * E = a·θ + b·θ²
203
+ *
204
+ * Kept as a named function rather than inlined because the two temperatures
205
+ * that fall out of it, below, are the whole reason a thermocouple has a usable
206
+ * range at all.
207
+ */
208
+ function thermocoupleEmf(theta, a, b) {
209
+ const t = finite(theta, "A temperature");
210
+ return a * t + finite(b, "The quadratic coefficient") * t * t;
211
+ }
212
+ /**
213
+ * The NEUTRAL temperature, where the emf peaks: θ_n = −a / 2b.
214
+ *
215
+ * Past it the emf falls again, so a single emf reading matches two
216
+ * temperatures and the thermocouple stops being a thermometer. That is the
217
+ * practical limit of the instrument, and it is a property of the metal pair
218
+ * rather than of the circuit.
219
+ */
220
+ function thermocoupleNeutralTemperatureC(a, b) {
221
+ if (finite(b, "The quadratic coefficient") === 0) throw new RangeError("With no quadratic term the emf never turns, so there is no neutral temperature.");
222
+ return -a / (2 * b);
223
+ }
224
+ /**
225
+ * The INVERSION temperature, where the emf returns to zero: θ_i = −a / b.
226
+ *
227
+ * Exactly twice the neutral temperature when the cold junction is at 0 °C,
228
+ * which is the check a student is usually asked to make.
229
+ */
230
+ function thermocoupleInversionTemperatureC(a, b) {
231
+ if (finite(b, "The quadratic coefficient") === 0) throw new RangeError("With no quadratic term the emf never returns to zero.");
232
+ return -a / b;
233
+ }
234
+
235
+ //#endregion
236
+ export { TEMPERATURE_SCALES, convertTemperature, convertTemperatureInterval, fromKelvin, fundamentalInterval, icePointOn, resistanceAtC, scaleReadingsAgree, steamPointOn, thermocoupleEmf, thermocoupleInversionTemperatureC, thermocoupleNeutralTemperatureC, thermometricTemperatureC, thermometricValue, toKelvin, triplePointTemperatureK };