formulab 0.37.0 → 0.38.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 (82) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/dist/automotive/evCharging.d.ts.map +1 -1
  3. package/dist/automotive/evCharging.js +3 -0
  4. package/dist/automotive/evCharging.js.map +1 -1
  5. package/dist/automotive/gearRatio.d.ts.map +1 -1
  6. package/dist/automotive/gearRatio.js +5 -0
  7. package/dist/automotive/gearRatio.js.map +1 -1
  8. package/dist/battery/batteryPackConfig.d.ts.map +1 -1
  9. package/dist/battery/batteryPackConfig.js +12 -0
  10. package/dist/battery/batteryPackConfig.js.map +1 -1
  11. package/dist/battery/bmsBalancing.d.ts.map +1 -1
  12. package/dist/battery/bmsBalancing.js +14 -0
  13. package/dist/battery/bmsBalancing.js.map +1 -1
  14. package/dist/battery/chargingProfile.d.ts.map +1 -1
  15. package/dist/battery/chargingProfile.js +14 -0
  16. package/dist/battery/chargingProfile.js.map +1 -1
  17. package/dist/battery/internalResistance.d.ts.map +1 -1
  18. package/dist/battery/internalResistance.js +3 -0
  19. package/dist/battery/internalResistance.js.map +1 -1
  20. package/dist/battery/selfDischarge.d.ts.map +1 -1
  21. package/dist/battery/selfDischarge.js +6 -0
  22. package/dist/battery/selfDischarge.js.map +1 -1
  23. package/dist/battery/stateOfHealth.d.ts.map +1 -1
  24. package/dist/battery/stateOfHealth.js +6 -0
  25. package/dist/battery/stateOfHealth.js.map +1 -1
  26. package/dist/battery/thermalRunaway.d.ts.map +1 -1
  27. package/dist/battery/thermalRunaway.js +8 -0
  28. package/dist/battery/thermalRunaway.js.map +1 -1
  29. package/dist/chemical/concentration.d.ts.map +1 -1
  30. package/dist/chemical/concentration.js +8 -0
  31. package/dist/chemical/concentration.js.map +1 -1
  32. package/dist/chemical/flowControl.d.ts.map +1 -1
  33. package/dist/chemical/flowControl.js +8 -0
  34. package/dist/chemical/flowControl.js.map +1 -1
  35. package/dist/chemical/reactor.d.ts.map +1 -1
  36. package/dist/chemical/reactor.js +4 -0
  37. package/dist/chemical/reactor.js.map +1 -1
  38. package/dist/chemical/reliefValve.d.ts.map +1 -1
  39. package/dist/chemical/reliefValve.js +8 -0
  40. package/dist/chemical/reliefValve.js.map +1 -1
  41. package/dist/construction/formwork.d.ts.map +1 -1
  42. package/dist/construction/formwork.js +22 -16
  43. package/dist/construction/formwork.js.map +1 -1
  44. package/dist/energy/pfCorrection.d.ts.map +1 -1
  45. package/dist/energy/pfCorrection.js +8 -0
  46. package/dist/energy/pfCorrection.js.map +1 -1
  47. package/dist/energy/vfdSavings.d.ts.map +1 -1
  48. package/dist/energy/vfdSavings.js +15 -0
  49. package/dist/energy/vfdSavings.js.map +1 -1
  50. package/dist/energy/windOutput.d.ts.map +1 -1
  51. package/dist/energy/windOutput.js +8 -0
  52. package/dist/energy/windOutput.js.map +1 -1
  53. package/dist/environmental/esgSummary.d.ts.map +1 -1
  54. package/dist/environmental/esgSummary.js +5 -0
  55. package/dist/environmental/esgSummary.js.map +1 -1
  56. package/dist/logistics/safetyStock.d.ts.map +1 -1
  57. package/dist/logistics/safetyStock.js +5 -0
  58. package/dist/logistics/safetyStock.js.map +1 -1
  59. package/dist/machining/boltCircle.d.ts.map +1 -1
  60. package/dist/machining/boltCircle.js +6 -0
  61. package/dist/machining/boltCircle.js.map +1 -1
  62. package/dist/machining/cuspHeight.d.ts +3 -0
  63. package/dist/machining/cuspHeight.d.ts.map +1 -1
  64. package/dist/machining/cuspHeight.js +12 -0
  65. package/dist/machining/cuspHeight.js.map +1 -1
  66. package/dist/machining/radialChipThinning.d.ts.map +1 -1
  67. package/dist/machining/radialChipThinning.js +9 -0
  68. package/dist/machining/radialChipThinning.js.map +1 -1
  69. package/dist/machining/triangleSolver.d.ts.map +1 -1
  70. package/dist/machining/triangleSolver.js +12 -0
  71. package/dist/machining/triangleSolver.js.map +1 -1
  72. package/dist/metal/kFactorReverse.d.ts.map +1 -1
  73. package/dist/metal/kFactorReverse.js +8 -0
  74. package/dist/metal/kFactorReverse.js.map +1 -1
  75. package/dist/quality/mtbf.d.ts +20 -0
  76. package/dist/quality/mtbf.d.ts.map +1 -1
  77. package/dist/quality/mtbf.js +38 -9
  78. package/dist/quality/mtbf.js.map +1 -1
  79. package/dist/safety/illuminance.d.ts.map +1 -1
  80. package/dist/safety/illuminance.js +8 -0
  81. package/dist/safety/illuminance.js.map +1 -1
  82. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,84 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.38.0] - 2026-09-09
9
+
10
+ ### Fixed
11
+
12
+ - **`construction/formwork()`** — the per-element contact area was rounded to two decimals
13
+ before being multiplied by the element quantity, which made that quantity the amplifier of
14
+ a display artefact. Half a square centimetre per element becomes six square metres over
15
+ twelve hundred of them, and `Math.ceil` then turns the drift into whole sheets of plywood
16
+ that would actually be ordered: a 0.3 x 0.25 x 4.15 m column at a quantity of 1200 reported
17
+ 1843 sheets over 5484 m2 against a true 1841 over 5478. Across a swept grid of plausible
18
+ inputs the sheet count differed in 81 of 1728 cases and the total area in 360. Every derived
19
+ figure now comes from the exact area and rounding happens once, on the way out; the reported
20
+ per-element area is unchanged.
21
+
22
+ - **Twenty-four functions returned `NaN` or `Infinity` in output fields** on degenerate input,
23
+ which `ERRORS.md` explicitly guarantees they will not. An execution-based audit — every
24
+ function called with each of its numeric inputs driven to zero and to minus one, every output
25
+ field checked for finiteness — found 44 such outputs. They now throw `RangeError` in line with
26
+ the documented error policy:
27
+
28
+ `batteryPackConfig`, `bmsBalancing`, `boltCircle`, `chargingProfile`, `concentration`,
29
+ `esgSummary`, `evCharging`, `flowControl`, `gearRatio`, `illuminance`, `internalResistance`,
30
+ `kFactorReverse` (and `kFactorReverseRange` through it), `pfCorrection`, `radialChipThinning`,
31
+ `reactor`, `reliefValve`, `safetyStock`, `selfDischarge`, `stateOfHealth`, `thermalRunaway`,
32
+ `triangleSolver`, `vfdSavings`, `windOutput`.
33
+
34
+ Two shapes recur. A function validated one parameter and not its neighbour — `gearRatio()`
35
+ checked the driving gear's tooth count while a driven gear of zero teeth spun infinitely fast.
36
+ Or nothing was validated at all and a divisor, a square root or a fractional exponent was left
37
+ to produce whatever it produced — `triangleSolver()` given a zero-length side divided by `2bc`
38
+ and returned all three angles as `NaN`, and `safetyStock()` at a service level of 0 or 1 took
39
+ the inverse normal CDF past its own asymptote.
40
+
41
+ Only inputs that actually produced a non-finite output are rejected. Finite results that are
42
+ physically odd are left alone, and existing zero-sentinel contracts are preserved — a formwork
43
+ reactor at `fillRatio: 0` still reports an empty vessel rather than throwing.
44
+
45
+ ### Changed
46
+
47
+ - **`ERRORS.md`** records the 2026-09-09 execution audit and why it found what a source reading
48
+ had cleared, and names `respiratorCalculate()`'s `Infinity` safety margin as an intentional
49
+ sentinel exempt from the no-`Infinity` rule.
50
+
51
+ ## [0.37.1] - 2026-09-09
52
+
53
+ ### Fixed
54
+
55
+ - **`quality/mtbf()`** — availability and the failure rate were derived from the rounded
56
+ MTBF and MTTR the function reports rather than from the times it was given. Rounding a
57
+ mean to two decimals and then dividing by it is not a rounding whisker: when short times
58
+ are spread over many failures the rounded mean is a large fraction of its own value. One
59
+ hour of operating time with half an hour of repair over 34 failures reported 75%
60
+ availability against a true 66.67%, and across a swept grid of plausible inputs a third
61
+ of the cases differed in the reported digits. Availability now reduces to the time-based
62
+ ratio of up time to total time (the failure count cancels), and the failure rate is taken
63
+ from the unrounded mean. The reported MTBF and MTTR are unchanged.
64
+ - **`quality/mtbf()`** — `reliabilityAtMtbf` returned 0 instead of e^-1 when the mean time
65
+ between failures rounded down to 0.00, and `totalRepairTime` was not validated. Reliability
66
+ at T = MTBF is e^-1 for any positive MTBF, and a negative repair time now throws
67
+ `RangeError` like the other invalid inputs.
68
+
69
+ - **`machining/cuspHeight()`** — returned `NaN` instead of rejecting impossible input. A
70
+ stepover wider than the tool diameter drove the square root negative, and non-positive
71
+ radii and stepovers were not checked at all, so a caller received a silent `NaN` and
72
+ rendered it. All three now throw `RangeError`. A stepover of exactly the tool diameter
73
+ stays valid: the passes just touch and the ridge is a full tool radius high.
74
+
75
+ ### Changed
76
+
77
+ - **`quality/mtbf()`** — documented which defined term each output corresponds to, with an
78
+ `@reference` to EN 13306:2017 (maintenance terminology): 11.3 mean time between failures,
79
+ 11.2 mean operating time between failures, 11.4 mean repair time, 9.18 time between
80
+ failures, 4.9 time based availability. The function had carried no citation since an
81
+ earlier, incorrect attribution was removed. Dividing operating time by the failure count
82
+ is strictly the mean *operating* time between failures (11.2); the name MTBF is kept
83
+ because that is what the figure is called in practice, and the distinction is now stated
84
+ rather than left implicit.
85
+
8
86
  ## [0.37.0] - 2026-09-07
9
87
 
10
88
  ### Added
@@ -1 +1 @@
1
- {"version":3,"file":"evCharging.d.ts","sourceRoot":"","sources":["../../src/automotive/evCharging.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAsB/D"}
1
+ {"version":3,"file":"evCharging.d.ts","sourceRoot":"","sources":["../../src/automotive/evCharging.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CA0B/D"}
@@ -24,6 +24,9 @@ export function evCharging(input) {
24
24
  if (chargerPowerKw <= 0) {
25
25
  throw new RangeError('chargerPowerKw must be greater than 0');
26
26
  }
27
+ if (!(efficiency > 0)) {
28
+ throw new RangeError('efficiency must be greater than 0');
29
+ }
27
30
  const socDiff = (socEndPercent - socStartPercent) / 100;
28
31
  const energyNeeded = batteryCapacityKwh * socDiff;
29
32
  const energyFromGrid = energyNeeded / efficiency;
@@ -1 +1 @@
1
- {"version":3,"file":"evCharging.js","sourceRoot":"","sources":["../../src/automotive/evCharging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,MAAM,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAEjG,IAAI,aAAa,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,IAAI,UAAU,CAAC,oDAAoD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,aAAa,GAAG,eAAe,CAAC,GAAG,GAAG,CAAC;IACxD,MAAM,YAAY,GAAG,kBAAkB,GAAG,OAAO,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,GAAG,UAAU,CAAC;IACjD,MAAM,iBAAiB,GAAG,cAAc,GAAG,cAAc,CAAC;IAC1D,MAAM,mBAAmB,GAAG,iBAAiB,GAAG,EAAE,CAAC;IAEnD,OAAO;QACL,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACtC,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1C,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAChD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;KACrD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"evCharging.js","sourceRoot":"","sources":["../../src/automotive/evCharging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,MAAM,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAEjG,IAAI,aAAa,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,IAAI,UAAU,CAAC,oDAAoD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAAC,mCAAmC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,aAAa,GAAG,eAAe,CAAC,GAAG,GAAG,CAAC;IACxD,MAAM,YAAY,GAAG,kBAAkB,GAAG,OAAO,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,GAAG,UAAU,CAAC;IACjD,MAAM,iBAAiB,GAAG,cAAc,GAAG,cAAc,CAAC;IAC1D,MAAM,mBAAmB,GAAG,iBAAiB,GAAG,EAAE,CAAC;IAEnD,OAAO;QACL,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACtC,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1C,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAChD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;KACrD,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"gearRatio.d.ts","sourceRoot":"","sources":["../../src/automotive/gearRatio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAoBhE"}
1
+ {"version":3,"file":"gearRatio.d.ts","sourceRoot":"","sources":["../../src/automotive/gearRatio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CA0BhE"}
@@ -17,6 +17,11 @@ export function gearRatio(input) {
17
17
  if (drivingTeeth <= 0) {
18
18
  throw new RangeError('drivingTeeth must be greater than 0');
19
19
  }
20
+ // The output speed divides by the ratio, so a driven gear with no teeth spins infinitely
21
+ // fast rather than describing a gear pair.
22
+ if (!(drivenTeeth > 0)) {
23
+ throw new RangeError('drivenTeeth must be greater than 0');
24
+ }
20
25
  const ratio = drivenTeeth / drivingTeeth;
21
26
  const outputSpeed = inputSpeed / ratio;
22
27
  const outputTorque = inputTorque * ratio * efficiency;
@@ -1 +1 @@
1
- {"version":3,"file":"gearRatio.js","sourceRoot":"","sources":["../../src/automotive/gearRatio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAEjF,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAAC,qCAAqC,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,GAAG,YAAY,CAAC;IACzC,MAAM,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC;IACvC,MAAM,YAAY,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;IACtD,MAAM,cAAc,GAAG,KAAK,GAAG,CAAC,CAAC;IACjC,MAAM,mBAAmB,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,WAAW,CAAC;IAE/E,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5B,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACtC,cAAc;QACd,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;KACrD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"gearRatio.js","sourceRoot":"","sources":["../../src/automotive/gearRatio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAEjF,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAAC,qCAAqC,CAAC,CAAC;IAC9D,CAAC;IAED,yFAAyF;IACzF,2CAA2C;IAC3C,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,UAAU,CAAC,oCAAoC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,GAAG,YAAY,CAAC;IACzC,MAAM,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC;IACvC,MAAM,YAAY,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;IACtD,MAAM,cAAc,GAAG,KAAK,GAAG,CAAC,CAAC;IACjC,MAAM,mBAAmB,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,WAAW,CAAC;IAE/E,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5B,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACtC,cAAc;QACd,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;KACrD,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"batteryPackConfig.d.ts","sourceRoot":"","sources":["../../src/battery/batteryPackConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAElF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,uBAAuB,CAqBxF"}
1
+ {"version":3,"file":"batteryPackConfig.d.ts","sourceRoot":"","sources":["../../src/battery/batteryPackConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAElF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,uBAAuB,CAkCxF"}
@@ -8,6 +8,18 @@ import { roundTo } from '../utils.js';
8
8
  */
9
9
  export function batteryPackConfig(input) {
10
10
  const { cellVoltage, cellCapacityAh, targetVoltage, targetCapacityAh } = input;
11
+ if (!(cellVoltage > 0)) {
12
+ throw new RangeError('cellVoltage must be greater than 0');
13
+ }
14
+ if (!(cellCapacityAh > 0)) {
15
+ throw new RangeError('cellCapacityAh must be greater than 0');
16
+ }
17
+ if (!(targetVoltage > 0)) {
18
+ throw new RangeError('targetVoltage must be greater than 0');
19
+ }
20
+ if (!(targetCapacityAh > 0)) {
21
+ throw new RangeError('targetCapacityAh must be greater than 0');
22
+ }
11
23
  const seriesCells = Math.ceil(targetVoltage / cellVoltage);
12
24
  const parallelCells = Math.ceil(targetCapacityAh / cellCapacityAh);
13
25
  const totalCells = seriesCells * parallelCells;
@@ -1 +1 @@
1
- {"version":3,"file":"batteryPackConfig.js","sourceRoot":"","sources":["../../src/battery/batteryPackConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAE/E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;IAE/C,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,gBAAgB,GAAG,OAAO,CAAC,aAAa,GAAG,cAAc,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAExD,OAAO;QACL,WAAW;QACX,aAAa;QACb,UAAU;QACV,aAAa;QACb,gBAAgB;QAChB,aAAa;QACb,cAAc;KACf,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"batteryPackConfig.js","sourceRoot":"","sources":["../../src/battery/batteryPackConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAE/E,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,UAAU,CAAC,oCAAoC,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAAC,yCAAyC,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;IAE/C,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,gBAAgB,GAAG,OAAO,CAAC,aAAa,GAAG,cAAc,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAExD,OAAO;QACL,WAAW;QACX,aAAa;QACb,UAAU;QACV,aAAa;QACb,gBAAgB;QAChB,aAAa;QACb,cAAc;KACf,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"bmsBalancing.d.ts","sourceRoot":"","sources":["../../src/battery/bmsBalancing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,CA+CzE"}
1
+ {"version":3,"file":"bmsBalancing.d.ts","sourceRoot":"","sources":["../../src/battery/bmsBalancing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,CA8DzE"}
@@ -9,6 +9,20 @@ import { roundTo } from '../utils.js';
9
9
  */
10
10
  export function bmsBalancing(input) {
11
11
  const { cellVoltages, balancingCurrentMA, cellCapacityAh } = input;
12
+ if (cellVoltages.length === 0) {
13
+ throw new RangeError('cellVoltages must not be empty');
14
+ }
15
+ // The balancing time divides by the pack average, so a cell at or below zero volts
16
+ // would drive it to infinity rather than describing a pack that can be balanced.
17
+ if (!cellVoltages.every((v) => v > 0)) {
18
+ throw new RangeError('every cell voltage must be greater than 0');
19
+ }
20
+ if (!(balancingCurrentMA > 0)) {
21
+ throw new RangeError('balancingCurrentMA must be greater than 0');
22
+ }
23
+ if (!(cellCapacityAh > 0)) {
24
+ throw new RangeError('cellCapacityAh must be greater than 0');
25
+ }
12
26
  const maxVoltage = Math.max(...cellVoltages);
13
27
  const minVoltage = Math.min(...cellVoltages);
14
28
  const voltageDelta = roundTo(maxVoltage - minVoltage, 4);
@@ -1 +1 @@
1
- {"version":3,"file":"bmsBalancing.js","sourceRoot":"","sources":["../../src/battery/bmsBalancing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAEnE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,cAAc,GAAG,OAAO,CAC5B,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,EACjE,CAAC,CACF,CAAC;IAEF,0BAA0B;IAC1B,MAAM,UAAU,GAAG,YAAY,IAAI,IAAI,CAAC;IAExC,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACtD,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,OAAO,GAAG,cAAc,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;QACzE,oEAAoE;QACpE,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,gEAAgE;YAChE,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,cAAc,GAAG,cAAc,GAAG,IAAI,CAAC;YACjF,gBAAgB,GAAG,OAAO,CAAC,SAAS,GAAG,kBAAkB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5B,YAAY;YACZ,gBAAgB;SACjB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,mBAAmB,GAAG,OAAO,CACjC,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,EACrD,CAAC,CACF,CAAC;IACF,MAAM,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAE/D,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAClC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAClC,YAAY;QACZ,cAAc;QACd,mBAAmB;QACnB,iBAAiB;QACjB,UAAU;QACV,WAAW;KACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"bmsBalancing.js","sourceRoot":"","sources":["../../src/battery/bmsBalancing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAEnE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAAC,gCAAgC,CAAC,CAAC;IACzD,CAAC;IACD,mFAAmF;IACnF,iFAAiF;IACjF,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,UAAU,CAAC,2CAA2C,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,CAAC,kBAAkB,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAAC,2CAA2C,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,cAAc,GAAG,OAAO,CAC5B,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,EACjE,CAAC,CACF,CAAC;IAEF,0BAA0B;IAC1B,MAAM,UAAU,GAAG,YAAY,IAAI,IAAI,CAAC;IAExC,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACtD,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,OAAO,GAAG,cAAc,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;QACzE,oEAAoE;QACpE,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,gEAAgE;YAChE,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,cAAc,GAAG,cAAc,GAAG,IAAI,CAAC;YACjF,gBAAgB,GAAG,OAAO,CAAC,SAAS,GAAG,kBAAkB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5B,YAAY;YACZ,gBAAgB;SACjB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,mBAAmB,GAAG,OAAO,CACjC,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,EACrD,CAAC,CACF,CAAC;IACF,MAAM,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAE/D,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAClC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAClC,YAAY;QACZ,cAAc;QACd,mBAAmB;QACnB,iBAAiB;QACjB,UAAU;QACV,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chargingProfile.d.ts","sourceRoot":"","sources":["../../src/battery/chargingProfile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE9E;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAsClF"}
1
+ {"version":3,"file":"chargingProfile.d.ts","sourceRoot":"","sources":["../../src/battery/chargingProfile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE9E;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAqDlF"}
@@ -9,6 +9,20 @@ import { roundTo } from '../utils.js';
9
9
  */
10
10
  export function chargingProfile(input) {
11
11
  const { capacityAh, chargingCurrentA, cutoffCurrentA, ccEndSocPercent = 80, } = input;
12
+ if (!(capacityAh > 0)) {
13
+ throw new RangeError('capacityAh must be greater than 0');
14
+ }
15
+ if (!(chargingCurrentA > 0)) {
16
+ throw new RangeError('chargingCurrentA must be greater than 0');
17
+ }
18
+ // The CV phase averages the charging and cutoff currents; a non-positive cutoff would
19
+ // make that average zero or negative and the phase time infinite.
20
+ if (!(cutoffCurrentA > 0)) {
21
+ throw new RangeError('cutoffCurrentA must be greater than 0');
22
+ }
23
+ if (!(ccEndSocPercent > 0) || ccEndSocPercent >= 100) {
24
+ throw new RangeError('ccEndSocPercent must be greater than 0 and less than 100');
25
+ }
12
26
  // CC phase delivers ccEndSocPercent of capacity
13
27
  const ccPhaseAh = roundTo(capacityAh * (ccEndSocPercent / 100), 2);
14
28
  const cvPhaseAh = roundTo(capacityAh - ccPhaseAh, 2);
@@ -1 +1 @@
1
- {"version":3,"file":"chargingProfile.js","sourceRoot":"","sources":["../../src/battery/chargingProfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,EACJ,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,GAAG,EAAE,GACrB,GAAG,KAAK,CAAC;IAEV,gDAAgD;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,EAAE,CAAC,CAAC,CAAC;IAErD,+BAA+B;IAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAErD,kEAAkE;IAClE,MAAM,YAAY,GAAG,CAAC,gBAAgB,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAErD,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAEjD,oCAAoC;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAExE,OAAO;QACL,YAAY;QACZ,cAAc;QACd,YAAY;QACZ,cAAc;QACd,UAAU;QACV,YAAY;QACZ,SAAS;QACT,SAAS;QACT,YAAY;KACb,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"chargingProfile.js","sourceRoot":"","sources":["../../src/battery/chargingProfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,EACJ,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,GAAG,EAAE,GACrB,GAAG,KAAK,CAAC;IAEV,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAAC,mCAAmC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAAC,yCAAyC,CAAC,CAAC;IAClE,CAAC;IACD,sFAAsF;IACtF,kEAAkE;IAClE,IAAI,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,IAAI,eAAe,IAAI,GAAG,EAAE,CAAC;QACrD,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAC;IACnF,CAAC;IAED,gDAAgD;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,EAAE,CAAC,CAAC,CAAC;IAErD,+BAA+B;IAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAErD,kEAAkE;IAClE,MAAM,YAAY,GAAG,CAAC,gBAAgB,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAErD,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAEjD,oCAAoC;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAExE,OAAO;QACL,YAAY;QACZ,cAAc;QACd,YAAY;QACZ,cAAc;QACd,UAAU;QACV,YAAY;QACZ,SAAS;QACT,SAAS;QACT,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"internalResistance.d.ts","sourceRoot":"","sources":["../../src/battery/internalResistance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEpF;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,wBAAwB,CAS3F"}
1
+ {"version":3,"file":"internalResistance.d.ts","sourceRoot":"","sources":["../../src/battery/internalResistance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEpF;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,wBAAwB,CAa3F"}
@@ -9,6 +9,9 @@ import { roundTo } from '../utils.js';
9
9
  */
10
10
  export function internalResistance(input) {
11
11
  const { openCircuitVoltage, loadVoltage, loadCurrentA } = input;
12
+ if (!(loadCurrentA > 0)) {
13
+ throw new RangeError('loadCurrentA must be greater than 0');
14
+ }
12
15
  const voltageDrop = roundTo(openCircuitVoltage - loadVoltage, 4);
13
16
  const resistanceOhm = roundTo(voltageDrop / loadCurrentA, 6);
14
17
  const resistanceMilliOhm = roundTo(resistanceOhm * 1000, 3);
@@ -1 +1 @@
1
- {"version":3,"file":"internalResistance.js","sourceRoot":"","sources":["../../src/battery/internalResistance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA8B;IAC/D,MAAM,EAAE,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAEhE,MAAM,WAAW,GAAG,OAAO,CAAC,kBAAkB,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;IACjE,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,kBAAkB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,YAAY,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC;IAE3E,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"internalResistance.js","sourceRoot":"","sources":["../../src/battery/internalResistance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA8B;IAC/D,MAAM,EAAE,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAEhE,IAAI,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAAC,qCAAqC,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,kBAAkB,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;IACjE,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,YAAY,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,kBAAkB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,YAAY,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC;IAE3E,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACxE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"selfDischarge.d.ts","sourceRoot":"","sources":["../../src/battery/selfDischarge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CAS5E"}
1
+ {"version":3,"file":"selfDischarge.d.ts","sourceRoot":"","sources":["../../src/battery/selfDischarge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CAgB5E"}
@@ -8,6 +8,12 @@ import { roundTo } from '../utils.js';
8
8
  */
9
9
  export function selfDischarge(input) {
10
10
  const { initialVoltage, finalVoltage, days, nominalVoltage } = input;
11
+ if (!(days > 0)) {
12
+ throw new RangeError('days must be greater than 0');
13
+ }
14
+ if (!(nominalVoltage > 0)) {
15
+ throw new RangeError('nominalVoltage must be greater than 0');
16
+ }
11
17
  const totalVoltageDrop = initialVoltage - finalVoltage;
12
18
  const voltageDropPerDay = roundTo(totalVoltageDrop / days, 6);
13
19
  const dailyRatePercent = roundTo((voltageDropPerDay / nominalVoltage) * 100, 4);
@@ -1 +1 @@
1
- {"version":3,"file":"selfDischarge.js","sourceRoot":"","sources":["../../src/battery/selfDischarge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAErE,MAAM,gBAAgB,GAAG,cAAc,GAAG,YAAY,CAAC;IACvD,MAAM,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,iBAAiB,GAAG,cAAc,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAE7D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;AACrE,CAAC"}
1
+ {"version":3,"file":"selfDischarge.js","sourceRoot":"","sources":["../../src/battery/selfDischarge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAErE,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,gBAAgB,GAAG,cAAc,GAAG,YAAY,CAAC;IACvD,MAAM,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,iBAAiB,GAAG,cAAc,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAE7D,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;AACrE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"stateOfHealth.d.ts","sourceRoot":"","sources":["../../src/battery/stateOfHealth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAa,MAAM,YAAY,CAAC;AAErF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CAqB5E"}
1
+ {"version":3,"file":"stateOfHealth.d.ts","sourceRoot":"","sources":["../../src/battery/stateOfHealth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAa,MAAM,YAAY,CAAC;AAErF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CA4B5E"}
@@ -9,6 +9,12 @@ import { roundTo } from '../utils.js';
9
9
  */
10
10
  export function stateOfHealth(input) {
11
11
  const { measuredCapacityAh, ratedCapacityAh } = input;
12
+ if (!(ratedCapacityAh > 0)) {
13
+ throw new RangeError('ratedCapacityAh must be greater than 0');
14
+ }
15
+ if (!(measuredCapacityAh >= 0)) {
16
+ throw new RangeError('measuredCapacityAh must not be negative');
17
+ }
12
18
  const sohPercent = roundTo((measuredCapacityAh / ratedCapacityAh) * 100, 2);
13
19
  const capacityLoss = roundTo(ratedCapacityAh - measuredCapacityAh, 2);
14
20
  const capacityLossPercent = roundTo(100 - sohPercent, 2);
@@ -1 +1 @@
1
- {"version":3,"file":"stateOfHealth.js","sourceRoot":"","sources":["../../src/battery/stateOfHealth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,kBAAkB,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEtD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,kBAAkB,GAAG,eAAe,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,mBAAmB,GAAG,OAAO,CAAC,GAAG,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;IAEzD,IAAI,MAAiB,CAAC;IACtB,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QACrB,MAAM,GAAG,WAAW,CAAC;IACvB,CAAC;SAAM,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;SAAM,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,UAAU,CAAC;IACtB,CAAC;SAAM,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"stateOfHealth.js","sourceRoot":"","sources":["../../src/battery/stateOfHealth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,kBAAkB,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEtD,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,UAAU,CAAC,yCAAyC,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,kBAAkB,GAAG,eAAe,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,mBAAmB,GAAG,OAAO,CAAC,GAAG,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;IAEzD,IAAI,MAAiB,CAAC;IACtB,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QACrB,MAAM,GAAG,WAAW,CAAC;IACvB,CAAC;SAAM,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;SAAM,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,UAAU,CAAC;IACtB,CAAC;SAAM,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAC;AACnE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"thermalRunaway.d.ts","sourceRoot":"","sources":["../../src/battery/thermalRunaway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CA0B/E"}
1
+ {"version":3,"file":"thermalRunaway.d.ts","sourceRoot":"","sources":["../../src/battery/thermalRunaway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAmC/E"}
@@ -9,6 +9,14 @@ import { roundTo } from '../utils.js';
9
9
  */
10
10
  export function thermalRunaway(input) {
11
11
  const { ambientTempC, currentA, internalResistanceOhm, heatTransferCoeff, surfaceAreaM2, runawayTempC, } = input;
12
+ // The steady-state rise divides the generated heat by hA; a non-positive coefficient
13
+ // or area describes a cell that cannot shed heat at all, which is not a temperature.
14
+ if (!(heatTransferCoeff > 0)) {
15
+ throw new RangeError('heatTransferCoeff must be greater than 0');
16
+ }
17
+ if (!(surfaceAreaM2 > 0)) {
18
+ throw new RangeError('surfaceAreaM2 must be greater than 0');
19
+ }
12
20
  const heatGenerationW = roundTo(currentA * currentA * internalResistanceOhm, 4);
13
21
  const hA = heatTransferCoeff * surfaceAreaM2;
14
22
  const temperatureRiseC = roundTo(heatGenerationW / hA, 2);
@@ -1 +1 @@
1
- {"version":3,"file":"thermalRunaway.js","sourceRoot":"","sources":["../../src/battery/thermalRunaway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,EACJ,YAAY,EACZ,QAAQ,EACR,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,YAAY,GACb,GAAG,KAAK,CAAC;IAEV,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,QAAQ,GAAG,qBAAqB,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,EAAE,GAAG,iBAAiB,GAAG,aAAa,CAAC;IAC7C,MAAM,gBAAgB,GAAG,OAAO,CAAC,eAAe,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IACrE,MAAM,gBAAgB,GAAG,OAAO,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,aAAa,GAAG,CAAC,CAAC;IAEjC,OAAO;QACL,gBAAgB;QAChB,gBAAgB;QAChB,eAAe;QACf,gBAAgB;QAChB,aAAa;QACb,MAAM;KACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"thermalRunaway.js","sourceRoot":"","sources":["../../src/battery/thermalRunaway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,EACJ,YAAY,EACZ,QAAQ,EACR,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,YAAY,GACb,GAAG,KAAK,CAAC;IAEV,qFAAqF;IACrF,qFAAqF;IACrF,IAAI,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,UAAU,CAAC,0CAA0C,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,QAAQ,GAAG,qBAAqB,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,EAAE,GAAG,iBAAiB,GAAG,aAAa,CAAC;IAC7C,MAAM,gBAAgB,GAAG,OAAO,CAAC,eAAe,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IACrE,MAAM,gBAAgB,GAAG,OAAO,CAAC,EAAE,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,aAAa,GAAG,CAAC,CAAC;IAEjC,OAAO;QACL,gBAAgB;QAChB,gBAAgB;QAChB,eAAe;QACf,gBAAgB;QAChB,aAAa;QACb,MAAM;KACP,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"concentration.d.ts","sourceRoot":"","sources":["../../src/chemical/concentration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CAqC5E"}
1
+ {"version":3,"file":"concentration.d.ts","sourceRoot":"","sources":["../../src/chemical/concentration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB,CA8C5E"}
@@ -12,6 +12,14 @@
12
12
  */
13
13
  export function concentration(input) {
14
14
  const { fromUnit, value, molecularWeight, solutionDensity } = input;
15
+ // Every conversion below divides by one or both of these, so a non-positive value
16
+ // returns an infinite concentration rather than describing a solution.
17
+ if (!(molecularWeight > 0)) {
18
+ throw new RangeError('molecularWeight must be greater than 0');
19
+ }
20
+ if (!(solutionDensity > 0)) {
21
+ throw new RangeError('solutionDensity must be greater than 0');
22
+ }
15
23
  let molPerL;
16
24
  let wtPercent;
17
25
  let ppm;
@@ -1 +1 @@
1
- {"version":3,"file":"concentration.js","sourceRoot":"","sources":["../../src/chemical/concentration.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEpE,IAAI,OAAe,CAAC;IACpB,IAAI,SAAiB,CAAC;IACtB,IAAI,GAAW,CAAC;IAEhB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,GAAG,KAAK,CAAC;YAChB,sCAAsC;YACtC,SAAS,GAAG,CAAC,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC;YACjE,oBAAoB;YACpB,GAAG,GAAG,SAAS,GAAG,KAAK,CAAC;YACxB,MAAM;QAER,KAAK,WAAW;YACd,SAAS,GAAG,KAAK,CAAC;YAClB,oBAAoB;YACpB,GAAG,GAAG,SAAS,GAAG,KAAK,CAAC;YACxB,8CAA8C;YAC9C,OAAO,GAAG,CAAC,SAAS,GAAG,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC;YACzE,MAAM;QAER,KAAK,KAAK;YACR,GAAG,GAAG,KAAK,CAAC;YACZ,oBAAoB;YACpB,SAAS,GAAG,GAAG,GAAG,KAAK,CAAC;YACxB,wCAAwC;YACxC,OAAO,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;YAC7D,MAAM;QAER;YACE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"concentration.js","sourceRoot":"","sources":["../../src/chemical/concentration.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEpE,kFAAkF;IAClF,uEAAuE;IACvE,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,OAAe,CAAC;IACpB,IAAI,SAAiB,CAAC;IACtB,IAAI,GAAW,CAAC;IAEhB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,GAAG,KAAK,CAAC;YAChB,sCAAsC;YACtC,SAAS,GAAG,CAAC,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC;YACjE,oBAAoB;YACpB,GAAG,GAAG,SAAS,GAAG,KAAK,CAAC;YACxB,MAAM;QAER,KAAK,WAAW;YACd,SAAS,GAAG,KAAK,CAAC;YAClB,oBAAoB;YACpB,GAAG,GAAG,SAAS,GAAG,KAAK,CAAC;YACxB,8CAA8C;YAC9C,OAAO,GAAG,CAAC,SAAS,GAAG,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC;YACzE,MAAM;QAER,KAAK,KAAK;YACR,GAAG,GAAG,KAAK,CAAC;YACZ,oBAAoB;YACpB,SAAS,GAAG,GAAG,GAAG,KAAK,CAAC;YACxB,wCAAwC;YACxC,OAAO,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;YAC7D,MAAM;QAER;YACE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"flowControl.d.ts","sourceRoot":"","sources":["../../src/chemical/flowControl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAkEtE"}
1
+ {"version":3,"file":"flowControl.d.ts","sourceRoot":"","sources":["../../src/chemical/flowControl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CA2EtE"}
@@ -12,6 +12,14 @@ import { roundTo } from '../utils.js';
12
12
  */
13
13
  export function flowControl(input) {
14
14
  const { flowRate, inletPressure, outletPressure, fluidDensity, fluidType, temperature = 20, molecularWeight, specificHeatRatio = 1.4, } = input;
15
+ // The pressure ratio divides by the inlet pressure and the sizing coefficient takes the
16
+ // square root of the specific gravity, so neither may be zero or negative.
17
+ if (!(inletPressure > 0)) {
18
+ throw new RangeError('inletPressure must be greater than 0');
19
+ }
20
+ if (!(fluidDensity > 0)) {
21
+ throw new RangeError('fluidDensity must be greater than 0');
22
+ }
15
23
  const pressureDrop = inletPressure - outletPressure; // kPa
16
24
  // Reference density: water = 999 kg/m³
17
25
  const sg = fluidDensity / 999;
@@ -1 +1 @@
1
- {"version":3,"file":"flowControl.js","sourceRoot":"","sources":["../../src/chemical/flowControl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flowControl.js","sourceRoot":"","sources":["../../src/chemical/flowControl.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"reactor.d.ts","sourceRoot":"","sources":["../../src/chemical/reactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG9D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CAmC1D;AAED;;GAEG"}
1
+ {"version":3,"file":"reactor.d.ts","sourceRoot":"","sources":["../../src/chemical/reactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG9D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CAuC1D;AAED;;GAEG"}
@@ -17,6 +17,10 @@ import { roundTo } from '../utils.js';
17
17
  */
18
18
  export function reactor(input) {
19
19
  const { shape, diameter, fillRatio } = input;
20
+ // A zero diameter gives zero volume over zero surface area, which is not a ratio.
21
+ if (!(diameter > 0)) {
22
+ throw new RangeError('diameter must be greater than 0');
23
+ }
20
24
  const radius = diameter / 2;
21
25
  let totalVolume;
22
26
  let surfaceArea;
@@ -1 +1 @@
1
- {"version":3,"file":"reactor.js","sourceRoot":"","sources":["../../src/chemical/reactor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,OAAO,CAAC,KAAmB;IACzC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAE7C,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC5B,IAAI,WAAmB,CAAC;IACxB,IAAI,WAAmB,CAAC;IAExB,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;QAC5B,sBAAsB;QACtB,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QACvB,mBAAmB;QACnB,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;QAC5C,gEAAgE;QAChE,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,oBAAoB;QACpB,uBAAuB;QACvB,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QAC3D,8BAA8B;QAC9B,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9C,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,CAAC;IAC9C,MAAM,iBAAiB,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC,gBAAgB;IAC9D,MAAM,mBAAmB,GAAG,aAAa,GAAG,IAAI,CAAC;IACjD,MAAM,oBAAoB,GAAG,WAAW,GAAG,WAAW,CAAC;IAEvD,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QACxC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAChD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACpD,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;KACvD,CAAC;AACJ,CAAC;AAED;;GAEG"}
1
+ {"version":3,"file":"reactor.js","sourceRoot":"","sources":["../../src/chemical/reactor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,OAAO,CAAC,KAAmB;IACzC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAE7C,kFAAkF;IAClF,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,UAAU,CAAC,iCAAiC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC5B,IAAI,WAAmB,CAAC;IACxB,IAAI,WAAmB,CAAC;IAExB,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;QAC5B,sBAAsB;QACtB,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QACvB,mBAAmB;QACnB,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;QAC5C,gEAAgE;QAChE,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,oBAAoB;QACpB,uBAAuB;QACvB,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QAC3D,8BAA8B;QAC9B,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9C,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,CAAC;IAC9C,MAAM,iBAAiB,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC,gBAAgB;IAC9D,MAAM,mBAAmB,GAAG,aAAa,GAAG,IAAI,CAAC;IACjD,MAAM,oBAAoB,GAAG,WAAW,GAAG,WAAW,CAAC;IAEvD,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QACxC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAChD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACpD,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACpC,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;KACvD,CAAC;AACJ,CAAC;AAED;;GAEG"}
@@ -1 +1 @@
1
- {"version":3,"file":"reliefValve.d.ts","sourceRoot":"","sources":["../../src/chemical/reliefValve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoBtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CA+FtE"}
1
+ {"version":3,"file":"reliefValve.d.ts","sourceRoot":"","sources":["../../src/chemical/reliefValve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoBtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAwGtE"}
@@ -37,6 +37,14 @@ const API_ORIFICES = [
37
37
  */
38
38
  export function reliefValve(input) {
39
39
  const { requiredCapacity, setPressure, backPressure, temperature, fluidType, molecularWeight = 29, specificGravity = 1.0, overpressure = 10, dischargeCoefficient, } = input;
40
+ // The gas/steam sizing equation divides by sqrt(M) after taking its square root, so a
41
+ // non-positive molecular weight gives an infinite or imaginary orifice area.
42
+ if (!(molecularWeight > 0)) {
43
+ throw new RangeError('molecularWeight must be greater than 0');
44
+ }
45
+ if (!(specificGravity > 0)) {
46
+ throw new RangeError('specificGravity must be greater than 0');
47
+ }
40
48
  // Atmospheric pressure
41
49
  const patm = 101.325; // kPa
42
50
  const P1 = setPressure + patm + (setPressure * overpressure / 100); // kPa absolute (relieving)
@@ -1 +1 @@
1
- {"version":3,"file":"reliefValve.js","sourceRoot":"","sources":["../../src/chemical/reliefValve.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reliefValve.js","sourceRoot":"","sources":["../../src/chemical/reliefValve.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"formwork.d.ts","sourceRoot":"","sources":["../../src/construction/formwork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA8E7E;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CA8B7D"}
1
+ {"version":3,"file":"formwork.d.ts","sourceRoot":"","sources":["../../src/construction/formwork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAgF7E;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAiC7D"}
@@ -9,25 +9,27 @@ const PLYWOOD_SHEET_AREA = 2.9768;
9
9
  * @param length - Length in meters
10
10
  * @param width - Width in meters
11
11
  * @param height - Height in meters
12
- * @returns Area in m²
12
+ * @returns Exact area in m², deliberately unrounded — the caller multiplies this by the
13
+ * element quantity and divides by the reuse count before anything is displayed, so a
14
+ * two-decimal value here would be scaled by the quantity rather than absorbed.
13
15
  */
14
16
  function calculateSingleArea(elementType, length, width, height) {
15
17
  switch (elementType) {
16
18
  case 'column':
17
19
  // Column: 4 sides = 2*(L+W) * H
18
- return roundTo(2 * (length + width) * height, 2);
20
+ return 2 * (length + width) * height;
19
21
  case 'beam':
20
22
  // Beam: 2 sides + bottom = 2*H*L + W*L
21
- return roundTo(2 * height * length + width * length, 2);
23
+ return 2 * height * length + width * length;
22
24
  case 'slab':
23
25
  // Slab: bottom only = L * W
24
- return roundTo(length * width, 2);
26
+ return length * width;
25
27
  case 'wall':
26
28
  // Wall: 2 sides = 2 * L * H
27
- return roundTo(2 * length * height, 2);
29
+ return 2 * length * height;
28
30
  case 'footing':
29
31
  // Footing: 4 sides = 2*(L+W) * H
30
- return roundTo(2 * (length + width) * height, 2);
32
+ return 2 * (length + width) * height;
31
33
  default:
32
34
  return 0;
33
35
  }
@@ -75,21 +77,25 @@ export function formwork(input) {
75
77
  if (quantity <= 0) {
76
78
  throw new RangeError('quantity must be greater than 0');
77
79
  }
78
- // Calculate area for single element
79
- const singleAreaSqm = calculateSingleArea(elementType, length, width, height);
80
- // Total area = single area × quantity
81
- const totalAreaSqm = roundTo(singleAreaSqm * quantity, 2);
80
+ // Every figure below derives from the exact contact area; rounding happens once, on
81
+ // the way out. Rounding the single-element area to two decimals and then multiplying
82
+ // by the quantity makes that quantity the amplifier of a display artefact: half a
83
+ // square centimetre per element becomes six square metres over twelve hundred of
84
+ // them, and Math.ceil then turns the drift into whole sheets of plywood that would
85
+ // actually be ordered.
86
+ const singleAreaExact = calculateSingleArea(elementType, length, width, height);
87
+ const totalAreaExact = singleAreaExact * quantity;
82
88
  // Effective area accounts for reuses
83
89
  const effectiveReuses = reuses > 0 ? reuses : 1;
84
- const effectiveAreaSqm = roundTo(totalAreaSqm / effectiveReuses, 2);
90
+ const effectiveAreaExact = totalAreaExact / effectiveReuses;
85
91
  // Number of plywood sheets needed (round up)
86
- const plywoodSheets = effectiveAreaSqm > 0
87
- ? Math.ceil(effectiveAreaSqm / PLYWOOD_SHEET_AREA)
92
+ const plywoodSheets = effectiveAreaExact > 0
93
+ ? Math.ceil(effectiveAreaExact / PLYWOOD_SHEET_AREA)
88
94
  : 0;
89
95
  return {
90
- singleAreaSqm,
91
- totalAreaSqm,
92
- effectiveAreaSqm,
96
+ singleAreaSqm: roundTo(singleAreaExact, 2),
97
+ totalAreaSqm: roundTo(totalAreaExact, 2),
98
+ effectiveAreaSqm: roundTo(effectiveAreaExact, 2),
93
99
  plywoodSheets,
94
100
  };
95
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"formwork.js","sourceRoot":"","sources":["../../src/construction/formwork.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"formwork.js","sourceRoot":"","sources":["../../src/construction/formwork.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pfCorrection.d.ts","sourceRoot":"","sources":["../../src/energy/pfCorrection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,CA4DzE"}
1
+ {"version":3,"file":"pfCorrection.d.ts","sourceRoot":"","sources":["../../src/energy/pfCorrection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,CAqEzE"}