@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.
- package/LICENSE +202 -0
- package/NOTICE +9 -0
- package/README.md +194 -0
- package/dist/conservation.d.ts +9 -0
- package/dist/conservation.js +38 -0
- package/dist/element/elements.d.ts +31 -0
- package/dist/element/elements.js +73 -0
- package/dist/element/matrix.d.ts +27 -0
- package/dist/element/matrix.js +80 -0
- package/dist/field/ambient.d.ts +49 -0
- package/dist/field/ambient.js +82 -0
- package/dist/field/atmosphere.d.ts +308 -0
- package/dist/field/atmosphere.js +1033 -0
- package/dist/ignition/criteria.d.ts +97 -0
- package/dist/ignition/criteria.js +135 -0
- package/dist/ignition/events.d.ts +56 -0
- package/dist/ignition/events.js +90 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +66 -0
- package/dist/library/biological.d.ts +6 -0
- package/dist/library/biological.js +229 -0
- package/dist/library/common.d.ts +26 -0
- package/dist/library/common.js +208 -0
- package/dist/library/food.d.ts +9 -0
- package/dist/library/food.js +272 -0
- package/dist/library/fuel.d.ts +19 -0
- package/dist/library/fuel.js +290 -0
- package/dist/library/library.d.ts +45 -0
- package/dist/library/library.js +29 -0
- package/dist/library/metal.d.ts +6 -0
- package/dist/library/metal.js +181 -0
- package/dist/library/mineral.d.ts +4 -0
- package/dist/library/mineral.js +177 -0
- package/dist/library/organic.d.ts +12 -0
- package/dist/library/organic.js +489 -0
- package/dist/library/polymer.d.ts +4 -0
- package/dist/library/polymer.js +237 -0
- package/dist/parcel/conduction.d.ts +20 -0
- package/dist/parcel/conduction.js +160 -0
- package/dist/parcel/shells.d.ts +49 -0
- package/dist/parcel/shells.js +73 -0
- package/dist/parcel/store.d.ts +395 -0
- package/dist/parcel/store.js +1152 -0
- package/dist/parcel/tier.d.ts +48 -0
- package/dist/parcel/tier.js +51 -0
- package/dist/present/audio.d.ts +41 -0
- package/dist/present/audio.js +50 -0
- package/dist/present/blackbody.d.ts +55 -0
- package/dist/present/blackbody.js +112 -0
- package/dist/present/flame.d.ts +34 -0
- package/dist/present/flame.js +103 -0
- package/dist/present/index.d.ts +25 -0
- package/dist/present/index.js +22 -0
- package/dist/present/install.d.ts +87 -0
- package/dist/present/install.js +157 -0
- package/dist/present/smoke.d.ts +63 -0
- package/dist/present/smoke.js +85 -0
- package/dist/present/surface.d.ts +40 -0
- package/dist/present/surface.js +76 -0
- package/dist/reaction/localise.d.ts +16 -0
- package/dist/reaction/localise.js +95 -0
- package/dist/reaction/rates.d.ts +59 -0
- package/dist/reaction/rates.js +101 -0
- package/dist/reaction/reaction.d.ts +178 -0
- package/dist/reaction/reaction.js +104 -0
- package/dist/reaction/registry.d.ts +47 -0
- package/dist/reaction/registry.js +215 -0
- package/dist/reaction/solver.d.ts +51 -0
- package/dist/reaction/solver.js +277 -0
- package/dist/species/registry.d.ts +26 -0
- package/dist/species/registry.js +97 -0
- package/dist/species/species.d.ts +48 -0
- package/dist/species/species.js +20 -0
- package/dist/species/standard.d.ts +30 -0
- package/dist/species/standard.js +436 -0
- package/dist/species/thermal.d.ts +18 -0
- package/dist/species/thermal.js +72 -0
- package/dist/substance/boiling.d.ts +29 -0
- package/dist/substance/boiling.js +54 -0
- package/dist/substance/composition.d.ts +34 -0
- package/dist/substance/composition.js +53 -0
- package/dist/substance/registry.d.ts +86 -0
- package/dist/substance/registry.js +187 -0
- package/dist/substance/substance.d.ts +94 -0
- package/dist/substance/substance.js +48 -0
- package/dist/testing/drift.d.ts +15 -0
- package/dist/testing/drift.js +29 -0
- package/dist/transport/contacts.d.ts +22 -0
- package/dist/transport/contacts.js +50 -0
- package/dist/transport/radiation.d.ts +101 -0
- package/dist/transport/radiation.js +199 -0
- package/dist/transport/world.d.ts +92 -0
- package/dist/transport/world.js +381 -0
- package/dist/world/fingerprint.d.ts +31 -0
- package/dist/world/fingerprint.js +70 -0
- package/package.json +100 -0
- package/src/conservation.ts +44 -0
- package/src/element/elements.ts +80 -0
- package/src/element/matrix.ts +89 -0
- package/src/field/ambient.ts +111 -0
- package/src/field/atmosphere.ts +1159 -0
- package/src/ignition/criteria.ts +177 -0
- package/src/ignition/events.ts +100 -0
- package/src/index.ts +213 -0
- package/src/library/biological.ts +252 -0
- package/src/library/common.ts +224 -0
- package/src/library/food.ts +302 -0
- package/src/library/fuel.ts +299 -0
- package/src/library/library.ts +62 -0
- package/src/library/metal.ts +186 -0
- package/src/library/mineral.ts +194 -0
- package/src/library/organic.ts +545 -0
- package/src/library/polymer.ts +243 -0
- package/src/parcel/conduction.ts +188 -0
- package/src/parcel/shells.ts +100 -0
- package/src/parcel/store.ts +1270 -0
- package/src/parcel/tier.ts +60 -0
- package/src/present/audio.ts +54 -0
- package/src/present/blackbody.ts +118 -0
- package/src/present/flame.ts +111 -0
- package/src/present/index.ts +25 -0
- package/src/present/install.ts +209 -0
- package/src/present/smoke.ts +139 -0
- package/src/present/surface.ts +107 -0
- package/src/reaction/localise.ts +126 -0
- package/src/reaction/rates.ts +153 -0
- package/src/reaction/reaction.ts +235 -0
- package/src/reaction/registry.ts +257 -0
- package/src/reaction/solver.ts +326 -0
- package/src/species/registry.ts +117 -0
- package/src/species/species.ts +53 -0
- package/src/species/standard.ts +449 -0
- package/src/species/thermal.ts +74 -0
- package/src/substance/boiling.ts +64 -0
- package/src/substance/composition.ts +81 -0
- package/src/substance/registry.ts +223 -0
- package/src/substance/substance.ts +148 -0
- package/src/testing/drift.ts +28 -0
- package/src/transport/contacts.ts +56 -0
- package/src/transport/radiation.ts +238 -0
- package/src/transport/world.ts +437 -0
- 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
|
+
};
|