@driftengine/chemistry 3.61.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 (142) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +9 -0
  3. package/README.md +194 -0
  4. package/dist/conservation.d.ts +9 -0
  5. package/dist/conservation.js +38 -0
  6. package/dist/element/elements.d.ts +31 -0
  7. package/dist/element/elements.js +73 -0
  8. package/dist/element/matrix.d.ts +27 -0
  9. package/dist/element/matrix.js +80 -0
  10. package/dist/field/ambient.d.ts +49 -0
  11. package/dist/field/ambient.js +82 -0
  12. package/dist/field/atmosphere.d.ts +308 -0
  13. package/dist/field/atmosphere.js +1033 -0
  14. package/dist/ignition/criteria.d.ts +97 -0
  15. package/dist/ignition/criteria.js +135 -0
  16. package/dist/ignition/events.d.ts +56 -0
  17. package/dist/ignition/events.js +90 -0
  18. package/dist/index.d.ts +84 -0
  19. package/dist/index.js +66 -0
  20. package/dist/library/biological.d.ts +6 -0
  21. package/dist/library/biological.js +229 -0
  22. package/dist/library/common.d.ts +26 -0
  23. package/dist/library/common.js +208 -0
  24. package/dist/library/food.d.ts +9 -0
  25. package/dist/library/food.js +272 -0
  26. package/dist/library/fuel.d.ts +19 -0
  27. package/dist/library/fuel.js +290 -0
  28. package/dist/library/library.d.ts +45 -0
  29. package/dist/library/library.js +29 -0
  30. package/dist/library/metal.d.ts +6 -0
  31. package/dist/library/metal.js +181 -0
  32. package/dist/library/mineral.d.ts +4 -0
  33. package/dist/library/mineral.js +177 -0
  34. package/dist/library/organic.d.ts +12 -0
  35. package/dist/library/organic.js +489 -0
  36. package/dist/library/polymer.d.ts +4 -0
  37. package/dist/library/polymer.js +237 -0
  38. package/dist/parcel/conduction.d.ts +20 -0
  39. package/dist/parcel/conduction.js +160 -0
  40. package/dist/parcel/shells.d.ts +49 -0
  41. package/dist/parcel/shells.js +73 -0
  42. package/dist/parcel/store.d.ts +395 -0
  43. package/dist/parcel/store.js +1152 -0
  44. package/dist/parcel/tier.d.ts +48 -0
  45. package/dist/parcel/tier.js +51 -0
  46. package/dist/present/audio.d.ts +41 -0
  47. package/dist/present/audio.js +50 -0
  48. package/dist/present/blackbody.d.ts +55 -0
  49. package/dist/present/blackbody.js +112 -0
  50. package/dist/present/flame.d.ts +34 -0
  51. package/dist/present/flame.js +103 -0
  52. package/dist/present/index.d.ts +25 -0
  53. package/dist/present/index.js +22 -0
  54. package/dist/present/install.d.ts +87 -0
  55. package/dist/present/install.js +157 -0
  56. package/dist/present/smoke.d.ts +63 -0
  57. package/dist/present/smoke.js +85 -0
  58. package/dist/present/surface.d.ts +40 -0
  59. package/dist/present/surface.js +76 -0
  60. package/dist/reaction/localise.d.ts +16 -0
  61. package/dist/reaction/localise.js +95 -0
  62. package/dist/reaction/rates.d.ts +59 -0
  63. package/dist/reaction/rates.js +101 -0
  64. package/dist/reaction/reaction.d.ts +178 -0
  65. package/dist/reaction/reaction.js +104 -0
  66. package/dist/reaction/registry.d.ts +47 -0
  67. package/dist/reaction/registry.js +215 -0
  68. package/dist/reaction/solver.d.ts +51 -0
  69. package/dist/reaction/solver.js +277 -0
  70. package/dist/species/registry.d.ts +26 -0
  71. package/dist/species/registry.js +97 -0
  72. package/dist/species/species.d.ts +48 -0
  73. package/dist/species/species.js +20 -0
  74. package/dist/species/standard.d.ts +30 -0
  75. package/dist/species/standard.js +436 -0
  76. package/dist/species/thermal.d.ts +18 -0
  77. package/dist/species/thermal.js +72 -0
  78. package/dist/substance/boiling.d.ts +29 -0
  79. package/dist/substance/boiling.js +54 -0
  80. package/dist/substance/composition.d.ts +34 -0
  81. package/dist/substance/composition.js +53 -0
  82. package/dist/substance/registry.d.ts +86 -0
  83. package/dist/substance/registry.js +187 -0
  84. package/dist/substance/substance.d.ts +94 -0
  85. package/dist/substance/substance.js +48 -0
  86. package/dist/testing/drift.d.ts +15 -0
  87. package/dist/testing/drift.js +29 -0
  88. package/dist/transport/contacts.d.ts +22 -0
  89. package/dist/transport/contacts.js +50 -0
  90. package/dist/transport/radiation.d.ts +101 -0
  91. package/dist/transport/radiation.js +199 -0
  92. package/dist/transport/world.d.ts +92 -0
  93. package/dist/transport/world.js +381 -0
  94. package/dist/world/fingerprint.d.ts +31 -0
  95. package/dist/world/fingerprint.js +70 -0
  96. package/package.json +100 -0
  97. package/src/conservation.ts +44 -0
  98. package/src/element/elements.ts +80 -0
  99. package/src/element/matrix.ts +89 -0
  100. package/src/field/ambient.ts +111 -0
  101. package/src/field/atmosphere.ts +1159 -0
  102. package/src/ignition/criteria.ts +177 -0
  103. package/src/ignition/events.ts +100 -0
  104. package/src/index.ts +213 -0
  105. package/src/library/biological.ts +252 -0
  106. package/src/library/common.ts +224 -0
  107. package/src/library/food.ts +302 -0
  108. package/src/library/fuel.ts +299 -0
  109. package/src/library/library.ts +62 -0
  110. package/src/library/metal.ts +186 -0
  111. package/src/library/mineral.ts +194 -0
  112. package/src/library/organic.ts +545 -0
  113. package/src/library/polymer.ts +243 -0
  114. package/src/parcel/conduction.ts +188 -0
  115. package/src/parcel/shells.ts +100 -0
  116. package/src/parcel/store.ts +1270 -0
  117. package/src/parcel/tier.ts +60 -0
  118. package/src/present/audio.ts +54 -0
  119. package/src/present/blackbody.ts +118 -0
  120. package/src/present/flame.ts +111 -0
  121. package/src/present/index.ts +25 -0
  122. package/src/present/install.ts +209 -0
  123. package/src/present/smoke.ts +139 -0
  124. package/src/present/surface.ts +107 -0
  125. package/src/reaction/localise.ts +126 -0
  126. package/src/reaction/rates.ts +153 -0
  127. package/src/reaction/reaction.ts +235 -0
  128. package/src/reaction/registry.ts +257 -0
  129. package/src/reaction/solver.ts +326 -0
  130. package/src/species/registry.ts +117 -0
  131. package/src/species/species.ts +53 -0
  132. package/src/species/standard.ts +449 -0
  133. package/src/species/thermal.ts +74 -0
  134. package/src/substance/boiling.ts +64 -0
  135. package/src/substance/composition.ts +81 -0
  136. package/src/substance/registry.ts +223 -0
  137. package/src/substance/substance.ts +148 -0
  138. package/src/testing/drift.ts +28 -0
  139. package/src/transport/contacts.ts +56 -0
  140. package/src/transport/radiation.ts +238 -0
  141. package/src/transport/world.ts +437 -0
  142. package/src/world/fingerprint.ts +106 -0
@@ -0,0 +1,489 @@
1
+ /**
2
+ * `@driftengine/chemistry/library/organic` — wood, and the things made out of plants and hides.
3
+ *
4
+ * **Wood does not burn.** It decomposes into gas, and the gas burns; the log itself only glows where
5
+ * the char is oxidising. `§8.3` is the argument, and everything here follows from it: three
6
+ * polymers with three kinetics, a competition inside cellulose that decides char yield, and a flame
7
+ * that is somewhere else.
8
+ *
9
+ * **Three species are registered here rather than in `species/standard.ts`.** `tar` is meaningless
10
+ * outside a wood fire, `tar(l)` outside a wood fire that is cooling, and `cellulose(active)` outside
11
+ * this scheme, so putting any of them in the standard table would charge every consumer of the
12
+ * engine for all three.
13
+ */
14
+ import { PHASE_GAS, PHASE_LIQUID, PHASE_SOLID, } from '../species/species.js';
15
+ import { KIND_COMBUSTION, KIND_PYROLYSIS, condensation, phaseChange, } from '../reaction/reaction.js';
16
+ import { SHAPE_CYLINDER, SHAPE_SLAB } from '../parcel/shells.js';
17
+ import { massFractions } from '../substance/composition.js';
18
+ import { wetComposition } from '../substance/substance.js';
19
+ import { BOIL_WATER, COMMON_REACTIONS, GAS_REACTIONS, OXIDISE_CHAR, OXIDISE_CHAR_RICH, } from './common.js';
20
+ export const BURN_TAR = 'burn-tar';
21
+ export const SOOT_TAR = 'soot-tar';
22
+ export const CONDENSE_TAR = 'condense-tar';
23
+ export const EVAPORATE_TAR = 'evaporate-tar';
24
+ /**
25
+ * The gas-phase steps a wood fire needs: the common five, plus the four this library invents.
26
+ *
27
+ * A consumer hands these to `AtmosphereField`, which runs them through the same solver a shell uses.
28
+ */
29
+ export const ORGANIC_GAS_REACTIONS = [
30
+ ...GAS_REACTIONS,
31
+ BURN_TAR,
32
+ SOOT_TAR,
33
+ CONDENSE_TAR,
34
+ EVAPORATE_TAR,
35
+ ];
36
+ /**
37
+ * K. Where wood tar stops being a vapour, and it is a dew point rather than a boiling point.
38
+ *
39
+ * **Levoglucosan boils near 658 K and this is 135 K below that, which is the difference between a
40
+ * pure liquid and a trace vapour in air.** Condensation happens where the tar's partial pressure
41
+ * reaches its saturation pressure, and a plume carrying tens of grams of tar per cubic metre is
42
+ * nowhere near a pure atmosphere of the stuff. Clausius-Clapeyron over the vaporisation enthalpy
43
+ * this library already derives — 104,987 J/mol, the gap between the two tar species below — puts the
44
+ * dew point at 547 K for 100 g/m³ and 497 K for 10, so a smoke-scale loading condenses somewhere in
45
+ * the low five hundreds. 523 K is 250 °C, sits inside that band, and is the figure biomass
46
+ * gasification quotes for when a producer gas starts fouling its own pipework with tar.
47
+ *
48
+ * **What it separates is the whole point.** A flame is 1,200 K and up, so the gate is shut there and
49
+ * the tar burns or cracks to soot: a flaming fire's smoke is black. A smouldering surface pushes tar
50
+ * into air a few hundred kelvin, the gate is open, and it condenses to droplets: a smouldering
51
+ * fire's smoke is pale. Nothing chooses between them and no equivalence ratio is read — the two are
52
+ * Arrhenius rates that need heat and this is a gate that needs the absence of it.
53
+ *
54
+ * **What would make it wrong** is a consumer whose cells are large enough to dilute a plume well
55
+ * below smoke-scale loadings, where the true dew point drops toward 450 K and this would condense
56
+ * tar that should still be flying. The fix then is a partial-pressure gate, which `ReactionGates`
57
+ * cannot express — it is temperature only, which is the same limit that keeps rusting from being
58
+ * gated on humidity.
59
+ */
60
+ const TAR_DEW_POINT = 523.15;
61
+ /**
62
+ * K over which the dew point opens, and it is a band because tar is not one molecule.
63
+ *
64
+ * `PHASE_GATE_WIDTH`'s half a kelvin is right for water, which is a pure substance with a plateau of
65
+ * zero width. Pyrolysis tar is levoglucosan plus anhydrosugars plus phenolics plus whatever the
66
+ * lignin gave up, and a mixture condenses over a range the way a distillation cut boils over one —
67
+ * which is the same argument `fuel/`'s diesel and kerosene take their twenty-kelvin widths from.
68
+ * Twenty-five kelvin here, so the heaviest fraction is already droplets while the lightest is still
69
+ * vapour, and a plume greys rather than switching.
70
+ */
71
+ const TAR_DEW_BAND = 25;
72
+ /**
73
+ * Cellulose's activated intermediate, and its enthalpy is cellulose's **exactly**.
74
+ *
75
+ * Broido-Shafizadeh's first step is a depolymerisation that leaves the repeat unit intact, and no
76
+ * measurement separates the two states thermochemically. Giving the intermediate a different
77
+ * formation enthalpy would put a number into the model that nothing measured, and Hess's law would
78
+ * then spend it on every gram of cellulose that ever pyrolyses. Equal is the honest value, and it
79
+ * makes the activation step cost nothing — which is what "the same molecule, rearranged" means.
80
+ */
81
+ const ACTIVE_CELLULOSE = {
82
+ id: 'cellulose(active)',
83
+ formula: { C: 6, H: 10, O: 5 },
84
+ phase: PHASE_SOLID,
85
+ formationEnthalpy: -968957,
86
+ cpA: 1340,
87
+ cpB: 4.9,
88
+ pseudo: true,
89
+ };
90
+ /**
91
+ * Wood pyrolysis tar, as the levoglucosan it mostly is — a gas, because it leaves as a vapour.
92
+ *
93
+ * **Its formation enthalpy is back-derived from two measurements, neither of which is a pyrolysis
94
+ * heat.** The higher heating value of wood pyrolysis oil is 17.0 MJ/kg, which fixes the condensed
95
+ * value at −1,033.8 kJ/mol; the sublimation enthalpy of levoglucosan is 105 kJ/mol, which lifts it
96
+ * to the vapour. That the volatile branch then comes out at the *third* measured quantity —
97
+ * +248 kJ/kg against `§8.3`'s +255 — is the check, and `organic.test.ts` is where it is made.
98
+ *
99
+ * The same formula as cellulose, and that is not a coincidence: fast cellulose pyrolysis is
100
+ * depolymerisation, so the tar carries the repeat unit away whole. The endotherm is the vaporisation
101
+ * and nothing else, which is why a pyrolysing surface cools itself.
102
+ */
103
+ const TAR = {
104
+ id: 'tar',
105
+ formula: { C: 6, H: 10, O: 5 },
106
+ phase: PHASE_GAS,
107
+ formationEnthalpy: -928813,
108
+ cpA: 1600,
109
+ cpB: 1.2,
110
+ pseudo: true,
111
+ };
112
+ /**
113
+ * The same tar as droplets, and **its enthalpy is the measured number rather than a derived one**.
114
+ *
115
+ * Read `TAR` above and this falls out of it. That comment back-derives the vapour from two
116
+ * measurements: pyrolysis oil's higher heating value of 17.0 MJ/kg, which fixes the **condensed**
117
+ * value at −1,033,800 J/mol, and levoglucosan's 105 kJ/mol of sublimation, which lifts it to the
118
+ * gas. So the condensed species is where the measurement actually lands, and the vapour that shipped
119
+ * first was the derived one — a gas because a wood fire's tar leaves as a vapour, and nothing had
120
+ * anywhere to put it once it cooled.
121
+ *
122
+ * Nothing new is asserted by writing it down: `-1033800` burns to 6 CO₂ and 5 H₂O(l) at exactly
123
+ * 17.0 MJ/kg over 162.14 g/mol, which is where it came from, and the gap to `TAR` is the 104,987
124
+ * J/mol that `TAR_DEW_POINT` is computed against. Two species, one measurement, and Hess's law
125
+ * carries the latent heat between them without it being stored anywhere.
126
+ *
127
+ * **A liquid rather than a solid, and the field reads the phase.** Condensed tar is micrometre
128
+ * droplets suspended in gas — an aerosol — and `AtmosphereField.aerosolAt` sums every carried
129
+ * species in the liquid phase for that reason, which is what makes this the pale half of smoke
130
+ * without either file naming the other. Real tar is a glassy semi-solid at room temperature; a
131
+ * `PHASE_SOLID` here would file it with soot, which is the black half, and get the colour backwards.
132
+ *
133
+ * `cpA` is bio-oil's, near 1,900 J/kg·K, above its own vapour's the way a condensed organic's
134
+ * usually is.
135
+ */
136
+ const CONDENSED_TAR = {
137
+ id: 'tar(l)',
138
+ formula: { C: 6, H: 10, O: 5 },
139
+ phase: PHASE_LIQUID,
140
+ formationEnthalpy: -1033800,
141
+ cpA: 1900,
142
+ cpB: 2.0,
143
+ pseudo: true,
144
+ };
145
+ const REACTIONS = [
146
+ ...COMMON_REACTIONS,
147
+ /*
148
+ * Broido-Shafizadeh, as `§8.3` draws it. The activation energies are the published ones; the
149
+ * pre-exponentials are too, and together they put cellulose's peak at 350-380 °C where it is
150
+ * measured.
151
+ */
152
+ {
153
+ id: 'activate-cellulose',
154
+ reactants: [{ species: 'cellulose', moles: 1 }],
155
+ products: [{ species: 'cellulose(active)', moles: 1 }],
156
+ kinetics: { type: 'arrhenius', A: 2.8e19, activationEnergy: 242400 },
157
+ kind: KIND_PYROLYSIS,
158
+ },
159
+ {
160
+ /*
161
+ * **The high-`Ea` branch, and it wins when heating is fast.** That single fact is the most
162
+ * useful thing in the whole model: kindling thrown on a hot fire is consumed to fine ash, and a
163
+ * log at the edge of one chars deeply and barely flames. Nothing chooses; the rates do.
164
+ */
165
+ id: 'cellulose-to-tar',
166
+ reactants: [{ species: 'cellulose(active)', moles: 1 }],
167
+ products: [{ species: 'tar', moles: 1 }],
168
+ kinetics: { type: 'arrhenius', A: 3.28e14, activationEnergy: 196500 },
169
+ kind: KIND_PYROLYSIS,
170
+ },
171
+ {
172
+ /*
173
+ * **The low-`Ea` branch, and it wins when heating is slow.** A quarter of the mass stays behind
174
+ * as carbon and the step is exothermic, which is how a covered pit turns wood into charcoal
175
+ * without anybody implementing charcoal.
176
+ */
177
+ id: 'cellulose-to-char',
178
+ reactants: [{ species: 'cellulose(active)', moles: 1 }],
179
+ products: [
180
+ { species: 'C(char)', moles: 3.5 },
181
+ { species: 'CO', moles: 1 },
182
+ { species: 'CO2', moles: 0.5 },
183
+ { species: 'CH4', moles: 1 },
184
+ { species: 'H2O(g)', moles: 3 },
185
+ ],
186
+ kinetics: { type: 'arrhenius', A: 1.3e10, activationEnergy: 150500 },
187
+ kind: KIND_PYROLYSIS,
188
+ },
189
+ {
190
+ /* First to go, at about 250 °C, and CO₂-rich — which is why the first smoke off a fresh log is
191
+ thin and pale and does not want to catch. */
192
+ id: 'pyrolyse-hemicellulose',
193
+ reactants: [{ species: 'hemicellulose', moles: 1 }],
194
+ products: [
195
+ { species: 'C(char)', moles: 2 },
196
+ { species: 'CO', moles: 1 },
197
+ { species: 'CO2', moles: 0.75 },
198
+ { species: 'CH4', moles: 1.25 },
199
+ { species: 'H2O(g)', moles: 1.5 },
200
+ ],
201
+ kinetics: { type: 'arrhenius', A: 2e16, activationEnergy: 186700 },
202
+ kind: KIND_PYROLYSIS,
203
+ },
204
+ {
205
+ /* Slow, broad, and the main char source: 43% of it stays behind as carbon, which is most of
206
+ what a bed of embers is made of. */
207
+ id: 'pyrolyse-lignin',
208
+ reactants: [{ species: 'lignin', moles: 1 }],
209
+ products: [
210
+ { species: 'C(char)', moles: 6 },
211
+ { species: 'CO2', moles: 1 },
212
+ { species: 'CH4', moles: 2 },
213
+ { species: 'H2O(g)', moles: 1 },
214
+ ],
215
+ kinetics: { type: 'arrhenius', A: 9.55e8, activationEnergy: 108000 },
216
+ kind: KIND_PYROLYSIS,
217
+ },
218
+ {
219
+ /*
220
+ * Resin and terpenes cracking, and **this is why pine flares and oak does not**. There is no
221
+ * single published pair for a lump this broad, so the rate is set to peak in the 150-250 °C band
222
+ * that terpene volatilisation is measured in — which is well below any of the three polymers,
223
+ * so a resinous wood gives off something combustible before it is properly hot.
224
+ */
225
+ id: 'pyrolyse-extractives',
226
+ reactants: [{ species: 'extractives', moles: 1 }],
227
+ products: [
228
+ { species: 'C(char)', moles: 4 },
229
+ { species: 'CH4', moles: 2 },
230
+ { species: 'C2H4', moles: 2 },
231
+ ],
232
+ kinetics: { type: 'arrhenius', A: 1e8, activationEnergy: 100000 },
233
+ kind: KIND_PYROLYSIS,
234
+ },
235
+ {
236
+ /*
237
+ * Protein chars heavily and gives up its nitrogen as ammonia and hydrogen cyanide, because that
238
+ * is where 1.3 nitrogens per residue have to go. Nothing here knows that burning hides is
239
+ * dangerous; the formula does.
240
+ */
241
+ id: 'pyrolyse-collagen',
242
+ reactants: [{ species: 'collagen', moles: 1 }],
243
+ products: [
244
+ { species: 'C(char)', moles: 2.9 },
245
+ { species: 'NH3', moles: 1 },
246
+ { species: 'HCN', moles: 0.3 },
247
+ { species: 'CO', moles: 0.6 },
248
+ { species: 'CH4', moles: 0.5 },
249
+ { species: 'H2O(g)', moles: 0.9 },
250
+ ],
251
+ kinetics: { type: 'arrhenius', A: 1e13, activationEnergy: 175000 },
252
+ kind: KIND_PYROLYSIS,
253
+ },
254
+ {
255
+ /*
256
+ * Tar cracking to soot, which is where most of a wood fire's smoke comes from. Needs no oxygen,
257
+ * so it is what happens to tar that reaches a starved region — and `C₆H₁₀O₅ → 6 C + 5 H₂O` is
258
+ * balanced exactly, because a cellulose repeat unit *is* six carbons and five waters.
259
+ */
260
+ id: SOOT_TAR,
261
+ reactants: [{ species: 'tar', moles: 1 }],
262
+ products: [
263
+ { species: 'C(soot)', moles: 6 },
264
+ { species: 'H2O(g)', moles: 5 },
265
+ ],
266
+ kinetics: { type: 'arrhenius', A: 1e11, activationEnergy: 200000 },
267
+ kind: KIND_COMBUSTION,
268
+ },
269
+ /*
270
+ * **The third thing tar can do, and it is what the pale smoke is.**
271
+ *
272
+ * The two above need heat: cracking to soot has a 200 kJ/mol barrier and burning has 125.5 plus an
273
+ * oxygen it has to find. A smouldering surface supplies neither — there is no flame over it, the
274
+ * gas a few centimetres away is a few hundred kelvin, and the oxygen is going into the char. So
275
+ * the tar coming off it did nothing at all until this pair existed: it sat in the cell as an
276
+ * invisible vapour, drifted, and vented to the far field.
277
+ *
278
+ * Now it cools past its dew point and becomes droplets, which is what smoke *is* in every fire
279
+ * that is not flaming. And the competition needs no arbiter, because the three are already
280
+ * exclusive: two rates that climb with temperature against one gate that closes with it. A flame
281
+ * blackens its own smoke and a smoulder whitens its own, out of the same three entries.
282
+ *
283
+ * The reverse is here rather than left out because a one-way condensation is a sink: aerosol
284
+ * carried back over a fire would stay pale, and a plume that greys as it cools would never darken
285
+ * again where it is drawn back in. `EVAPORATE_TAR` is the same transition read upward, sharing the
286
+ * dew point and the band, so the pair is an equilibrium rather than a trap.
287
+ */
288
+ condensation(CONDENSE_TAR, 'tar', 'tar(l)', TAR_DEW_POINT, TAR_DEW_BAND),
289
+ phaseChange(EVAPORATE_TAR, 'tar(l)', 'tar', TAR_DEW_POINT, TAR_DEW_BAND),
290
+ {
291
+ id: BURN_TAR,
292
+ reactants: [
293
+ { species: 'tar', moles: 1 },
294
+ { species: 'O2', moles: 6 },
295
+ ],
296
+ products: [
297
+ { species: 'CO2', moles: 6 },
298
+ { species: 'H2O(g)', moles: 5 },
299
+ ],
300
+ kinetics: { type: 'arrhenius', A: 5e11, activationEnergy: 125500 },
301
+ kind: KIND_COMBUSTION,
302
+ },
303
+ ];
304
+ /** Everything a lignocellulosic solid does: dry, pyrolyse three ways, then glow. */
305
+ const WOOD_REACTIONS = [
306
+ BOIL_WATER,
307
+ 'activate-cellulose',
308
+ 'cellulose-to-tar',
309
+ 'cellulose-to-char',
310
+ 'pyrolyse-hemicellulose',
311
+ 'pyrolyse-lignin',
312
+ 'pyrolyse-extractives',
313
+ OXIDISE_CHAR,
314
+ OXIDISE_CHAR_RICH,
315
+ ];
316
+ /**
317
+ * The criteria a cellulosic solid catches by: 350 °C with a pilot, 500 °C without, 3.5 g/m²·s.
318
+ *
319
+ * Shared because they are a property of *cellulose* rather than of a shape — paper and a log have
320
+ * the same surface chemistry and differ in how fast they reach it, which is the depth stack's job
321
+ * and not this one's. `§11` says why the mass flux is the real criterion and why both are stored.
322
+ */
323
+ const CELLULOSIC_IGNITION = { pilotedSurfaceK: 623, autoSurfaceK: 773, criticalMassFlux: 0.0035 };
324
+ export const ORGANIC = {
325
+ id: 'organic',
326
+ species: [ACTIVE_CELLULOSE, TAR, CONDENSED_TAR],
327
+ reactions: REACTIONS,
328
+ substances: (species) => [
329
+ {
330
+ /* `§5`'s worked substance, and the one `§21`'s whole scene is about. */
331
+ id: 'oak',
332
+ composition: wetComposition(species, massFractions(species, {
333
+ cellulose: 0.43,
334
+ hemicellulose: 0.26,
335
+ lignin: 0.26,
336
+ extractives: 0.04,
337
+ ash: 0.01,
338
+ }), 0.12),
339
+ density: 700,
340
+ conductivity: { k0: 0.16, k1: 0.0002 },
341
+ shells: 4,
342
+ shape: SHAPE_CYLINDER,
343
+ porosity: 0.55,
344
+ emissivity: 0.9,
345
+ reactions: WOOD_REACTIONS,
346
+ ignition: CELLULOSIC_IGNITION,
347
+ appearance: {
348
+ albedo: [0.32, 0.22, 0.13],
349
+ charAlbedo: [0.03, 0.03, 0.03],
350
+ sootYield: 0.015,
351
+ },
352
+ },
353
+ {
354
+ /* Softwood: lighter, more resinous, and it is the resin that makes it catch first. Six percent
355
+ extractives against oak's four, cracking a hundred and fifty degrees earlier than cellulose. */
356
+ id: 'pine',
357
+ composition: wetComposition(species, massFractions(species, {
358
+ cellulose: 0.41,
359
+ hemicellulose: 0.24,
360
+ lignin: 0.28,
361
+ extractives: 0.06,
362
+ ash: 0.01,
363
+ }), 0.12),
364
+ density: 500,
365
+ conductivity: { k0: 0.12, k1: 0.0002 },
366
+ shells: 4,
367
+ shape: SHAPE_CYLINDER,
368
+ porosity: 0.62,
369
+ emissivity: 0.9,
370
+ reactions: WOOD_REACTIONS,
371
+ ignition: CELLULOSIC_IGNITION,
372
+ appearance: {
373
+ albedo: [0.45, 0.33, 0.2],
374
+ charAlbedo: [0.03, 0.03, 0.03],
375
+ sootYield: 0.02,
376
+ },
377
+ },
378
+ {
379
+ /* Two shells, not four: a sheet is thermally thin, so its far side is its near side and the
380
+ depth stack has nothing to resolve. That is the whole difference between paper and a log. */
381
+ id: 'paper',
382
+ composition: wetComposition(species, massFractions(species, {
383
+ cellulose: 0.85,
384
+ hemicellulose: 0.05,
385
+ lignin: 0.02,
386
+ ash: 0.08,
387
+ }), 0.06),
388
+ density: 800,
389
+ conductivity: { k0: 0.05, k1: 0.0001 },
390
+ shells: 2,
391
+ shape: SHAPE_SLAB,
392
+ porosity: 0.35,
393
+ emissivity: 0.92,
394
+ reactions: WOOD_REACTIONS,
395
+ ignition: CELLULOSIC_IGNITION,
396
+ appearance: {
397
+ albedo: [0.82, 0.8, 0.75],
398
+ charAlbedo: [0.04, 0.04, 0.04],
399
+ sootYield: 0.011,
400
+ },
401
+ },
402
+ {
403
+ /* Fabric bulk density rather than fibre density — 300 against cellulose's 1,540 — because what
404
+ a flame meets is the cloth and not the thread. The porosity is what lets it smoulder. */
405
+ id: 'cotton',
406
+ composition: wetComposition(species, massFractions(species, {
407
+ cellulose: 0.94,
408
+ hemicellulose: 0.03,
409
+ extractives: 0.02,
410
+ ash: 0.01,
411
+ }), 0.07),
412
+ density: 300,
413
+ conductivity: { k0: 0.04, k1: 0.0001 },
414
+ shells: 2,
415
+ shape: SHAPE_SLAB,
416
+ porosity: 0.72,
417
+ emissivity: 0.9,
418
+ reactions: WOOD_REACTIONS,
419
+ ignition: CELLULOSIC_IGNITION,
420
+ appearance: {
421
+ albedo: [0.86, 0.85, 0.82],
422
+ charAlbedo: [0.04, 0.04, 0.04],
423
+ sootYield: 0.011,
424
+ },
425
+ },
426
+ {
427
+ /*
428
+ * Collagen rather than cellulose, so it chars instead of flaming and gives up cyanide on the
429
+ * way. Its limiting oxygen index is genuinely higher than wood's — protein is a poor fuel —
430
+ * which is one number here and is why a leather coat is a better thing to be wearing.
431
+ */
432
+ id: 'leather',
433
+ composition: wetComposition(species, massFractions(species, {
434
+ collagen: 0.88,
435
+ extractives: 0.08,
436
+ ash: 0.04,
437
+ }), 0.14),
438
+ density: 900,
439
+ conductivity: { k0: 0.15, k1: 0.0002 },
440
+ shells: 3,
441
+ shape: SHAPE_SLAB,
442
+ porosity: 0.3,
443
+ emissivity: 0.93,
444
+ reactions: [
445
+ BOIL_WATER,
446
+ 'pyrolyse-collagen',
447
+ 'pyrolyse-extractives',
448
+ OXIDISE_CHAR,
449
+ OXIDISE_CHAR_RICH,
450
+ ],
451
+ ignition: {
452
+ pilotedSurfaceK: 673,
453
+ autoSurfaceK: 823,
454
+ criticalMassFlux: 0.0045,
455
+ limitingOxygen: 0.21,
456
+ },
457
+ appearance: {
458
+ albedo: [0.2, 0.12, 0.07],
459
+ charAlbedo: [0.03, 0.03, 0.03],
460
+ sootYield: 0.03,
461
+ },
462
+ },
463
+ {
464
+ /* Fifteen percent ash, which is silica, and it is why straw leaves so much behind and why a
465
+ straw fire is fast and poor. Baled density and high porosity: it breathes, so it smoulders. */
466
+ id: 'straw',
467
+ composition: wetComposition(species, massFractions(species, {
468
+ cellulose: 0.36,
469
+ hemicellulose: 0.28,
470
+ lignin: 0.16,
471
+ extractives: 0.05,
472
+ ash: 0.15,
473
+ }), 0.1),
474
+ density: 130,
475
+ conductivity: { k0: 0.05, k1: 0.0001 },
476
+ shells: 3,
477
+ shape: SHAPE_CYLINDER,
478
+ porosity: 0.8,
479
+ emissivity: 0.9,
480
+ reactions: WOOD_REACTIONS,
481
+ ignition: CELLULOSIC_IGNITION,
482
+ appearance: {
483
+ albedo: [0.62, 0.52, 0.28],
484
+ charAlbedo: [0.04, 0.04, 0.04],
485
+ sootYield: 0.015,
486
+ },
487
+ },
488
+ ],
489
+ };
@@ -0,0 +1,4 @@
1
+ import type { SubstanceLibrary } from './library.ts';
2
+ /** Nothing new: everything these polymers give off is already in the common set. */
3
+ export declare const POLYMER_GAS_REACTIONS: readonly string[];
4
+ export declare const POLYMER: SubstanceLibrary;