@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,395 @@
1
+ import type { SubstanceRegistry } from '../substance/registry.ts';
2
+ import { type Tier } from './tier.ts';
3
+ import type { AppearanceModel } from '../substance/substance.ts';
4
+ import type { IgnitionModel } from '../ignition/criteria.ts';
5
+ /**
6
+ * A parcel made of more than one phase at once, which is most of them.
7
+ *
8
+ * Not a `Phase`, because it is not one: wet wood is a solid and a liquid together, and the design's
9
+ * `§20.3` gives it its own value rather than making a consumer guess which half was reported.
10
+ */
11
+ export declare const PHASE_MIXED = 3;
12
+ /**
13
+ * What a parcel is made of and how big it is. An object rather than seven positional arguments,
14
+ * which is how `PhysicsWorld.addBody` takes a body and for the same reason.
15
+ */
16
+ export interface ParcelSpec {
17
+ readonly substance: number;
18
+ readonly mass: number;
19
+ /** K. Every shell starts here. */
20
+ readonly temperature: number;
21
+ /**
22
+ * Exposed surface area, m². Optional, and **conduction refuses a parcel without one**, naming it:
23
+ * a characteristic depth is volume over area, so a parcel with no area has no depth and there is
24
+ * no honest default to invent. `parcelFromBounds` supplies it from a bounding box in CH-9.
25
+ */
26
+ readonly area?: number;
27
+ readonly x?: number;
28
+ readonly y?: number;
29
+ readonly z?: number;
30
+ }
31
+ export declare class ParcelStore {
32
+ private readonly substances;
33
+ private readonly species;
34
+ private substance;
35
+ private mass;
36
+ /** Strided by `MAX_SHELLS`: shell `s` of parcel `p` is at `p * MAX_SHELLS + s`, in joules. */
37
+ private enthalpy;
38
+ private area;
39
+ private x;
40
+ private y;
41
+ private z;
42
+ private live;
43
+ /** `FLAG_BURNING | FLAG_SMOULDERING | FLAG_PILOT`. */
44
+ private flags;
45
+ /** kg/(m²·s) of gas leaving the surface, and of the combustible part of it. */
46
+ private flux;
47
+ private fuelFlux;
48
+ /**
49
+ * Watts the reactions put into this parcel over the last `react`, and it is a *readout*.
50
+ *
51
+ * **A fire's size is its heat release rate**, not its temperature — every fire-engineering figure
52
+ * in the design is quoted in kilowatts — and it cannot be recovered from outside, because
53
+ * conduction and a radiative source change the same enthalpy in the same tick. So it is measured
54
+ * where only reactions are running, by summing the thermal enthalpy either side of them. That sum
55
+ * is one pass over at most sixteen shells, which is nothing against the reaction step it brackets.
56
+ */
57
+ private release;
58
+ /** Which of `§14`'s four tiers each parcel is being simulated at. */
59
+ private tier;
60
+ /** Shells actually resolved right now, which a tier may reduce below what the substance declared. */
61
+ private shells;
62
+ /** Seconds owed to a parcel its cadence has been skipping, handed over when its turn comes. */
63
+ private owed;
64
+ /** Consecutive ticks a parcel has been still. At `QUIET_TICKS` it sleeps. */
65
+ private quiet;
66
+ /**
67
+ * Where each parcel's composition block starts, and the block itself.
68
+ *
69
+ * A block is `shells × the substance's own species count` kilograms — **dense over the few
70
+ * species that substance can hold**, not a row over all sixty-eight. Blocks are appended and
71
+ * never moved, which is what makes an offset stable; compaction is a budget question and belongs
72
+ * with the rest of them in CH-6.
73
+ */
74
+ private compositionOffset;
75
+ private composition;
76
+ private compositionUsed;
77
+ private used;
78
+ constructor(substances: SubstanceRegistry, species?: import("../index.ts").SpeciesRegistry);
79
+ /** Handles ever issued, live or not. A destroyed parcel still occupies its index. */
80
+ get count(): number;
81
+ spawn(spec: ParcelSpec): number;
82
+ /** m², what the environment touches. Zero means the caller has not said, and conduction refuses. */
83
+ areaOf(parcel: number): number;
84
+ destroy(parcel: number): void;
85
+ alive(parcel: number): boolean;
86
+ substanceOf(parcel: number): number;
87
+ massOf(parcel: number): number;
88
+ /** m³, from mass and the substance's density. Shrinks as mass leaves, which is why a log burns down. */
89
+ volumeOf(parcel: number): number;
90
+ /** How many shells this parcel's substance divides it into. */
91
+ /**
92
+ * Shells resolved right now, which a level-of-detail tier may have reduced.
93
+ *
94
+ * Everything that walks a parcel's depth reads this rather than the substance's declared count, so
95
+ * a `Distant` log is one shell everywhere at once and nothing has to be told which tier it is at.
96
+ */
97
+ shellCount(parcel: number): number;
98
+ /** What the substance asked for, which is the resolution `Hero` restores to. */
99
+ declaredShellsOf(parcel: number): number;
100
+ tierOf(parcel: number): Tier;
101
+ /** Ticks between updates at this parcel's tier. `§14`'s cadence column. */
102
+ cadenceOf(parcel: number): number;
103
+ /** The most sub-steps a reaction solve will take at this parcel's tier. */
104
+ substepsOf(parcel: number): number;
105
+ /**
106
+ * Move a parcel to a tier, **conserving mass, every element and enthalpy exactly**.
107
+ *
108
+ * `§14`: "a tier change does not lose or gain mass or energy... which is the property that makes
109
+ * the LOD safe to apply to a burning object mid-burn." Shells are equal-mass by construction, so a
110
+ * fold is a proportional redistribution — target `j` takes source shells `[j·n/m, (j+1)·n/m)`,
111
+ * splitting one where the ratio is not an integer — and the targets come out equal-mass too.
112
+ *
113
+ * **What it loses is the profile inside a fold**, which is the point of a tier: two shells at
114
+ * 400 K and 300 K become one at their mass-weighted mean, and going back up hands each of them the
115
+ * same mean. Resolution in depth is what a distant object gives away.
116
+ */
117
+ setTier(parcel: number, tier: Tier): void;
118
+ /**
119
+ * Redistribute a parcel's `from` shells into `to`, exactly.
120
+ *
121
+ * One pass into scratch and one pass back, because a fold reads every source before it has written
122
+ * any target and doing it in place would read a slot it had already overwritten.
123
+ */
124
+ private refold;
125
+ /** Total joules held across every shell, not joules per kilogram. */
126
+ enthalpyOf(parcel: number): number;
127
+ shellEnthalpyOf(parcel: number, shell: number): number;
128
+ /**
129
+ * The temperature of one shell, K. Shell 0 is the surface and the last is the core.
130
+ *
131
+ * **`surfaceTemperatureOf` is what decides ignition and `coreTemperatureOf` is what decides
132
+ * doneness**, and the gap between them is the whole reason shells exist.
133
+ */
134
+ shellTemperatureOf(parcel: number, shell: number): number;
135
+ surfaceTemperatureOf(parcel: number): number;
136
+ coreTemperatureOf(parcel: number): number;
137
+ positionX(parcel: number): number;
138
+ positionY(parcel: number): number;
139
+ positionZ(parcel: number): number;
140
+ move(parcel: number, x: number, y: number, z: number): void;
141
+ /**
142
+ * The temperature this parcel would have if it were stirred, K.
143
+ *
144
+ * A read rather than a stored field, and that is the design. Nothing writes a temperature except
145
+ * `setTemperature`, which writes the enthalpy that produces one — so a parcel on a plateau simply
146
+ * does not move, and no code anywhere had to know a plateau exists.
147
+ *
148
+ * **The temperature of the total enthalpy**, not the mean of the shell temperatures. The two
149
+ * differ wherever the curve bends, and only this one has the property that matters: heat in,
150
+ * temperature out, with nothing lost between them.
151
+ */
152
+ temperatureOf(parcel: number): number;
153
+ /** Joules in, spread evenly through the depth. Negative cools. A microwave, or a stirred pot. */
154
+ addHeat(parcel: number, joules: number): void;
155
+ /**
156
+ * Joules into shell 0 alone, which is what a flux from outside actually does.
157
+ *
158
+ * Every radiative, convective and contact term in CH-5 lands here. The difference between this
159
+ * and `addHeat` is the difference between a log in front of a fire and a log in an oven.
160
+ */
161
+ addSurfaceHeat(parcel: number, joules: number): void;
162
+ /**
163
+ * Conduct heat inward one step of `dt` seconds.
164
+ *
165
+ * Conserves this parcel's total enthalpy exactly — the arithmetic is in `conduction.ts` and so is
166
+ * the reason.
167
+ */
168
+ conduct(parcel: number, dt: number): void;
169
+ /**
170
+ * Force a temperature by writing the enthalpy that produces it.
171
+ *
172
+ * For authoring and for tests. **Not for a tick**: it discards whatever enthalpy the parcel held,
173
+ * so a boiling parcel set to its own boiling point loses however much of the plateau it had
174
+ * crossed, and the energy budget does not close across the call.
175
+ */
176
+ setTemperature(parcel: number, temperature: number): void;
177
+ /** Force one shell's temperature. Authoring and tests only, for the reason above. */
178
+ setShellTemperature(parcel: number, shell: number, temperature: number): void;
179
+ /** Kilograms of one species in one shell. Zero where the substance cannot hold it at all. */
180
+ speciesMassOf(parcel: number, shell: number, species: number): number;
181
+ /** The same, summed over every shell. */
182
+ parcelSpeciesMass(parcel: number, species: number): number;
183
+ /** Kilograms in one shell, summed over its species. Invariant under reaction. */
184
+ shellMassOf(parcel: number, shell: number): number;
185
+ /** Moles of each element this parcel holds. Writes into `out`, allocates nothing. */
186
+ elementTotalsOf(parcel: number, out: Float64Array): void;
187
+ /**
188
+ * Energy locked in this parcel's chemical bonds, J.
189
+ *
190
+ * Neither this nor the thermal enthalpy is conserved on its own — a reaction moves energy between
191
+ * them. **Their sum is**, exactly, because the same number is added to one and taken from the
192
+ * other in `reactShell`.
193
+ */
194
+ chemicalEnergyOf(parcel: number): number;
195
+ /** Run this parcel's reactions in every shell for `dt` seconds. */
196
+ react(parcel: number, dt: number, transportFactor?: number): void;
197
+ /** Joules of sensible heat across a parcel's shells. One pass over at most sixteen doubles. */
198
+ private thermalEnthalpy;
199
+ /**
200
+ * Whether this parcel is being skipped entirely.
201
+ *
202
+ * `§14`'s thermal quiescence, and the vocabulary is deliberately Track B's. A cold stone floor is a
203
+ * thousand of these and costs a bounded scan.
204
+ */
205
+ sleeping(parcel: number): boolean;
206
+ /**
207
+ * Wake it, and reset the count that would put it back.
208
+ *
209
+ * **Called by everything that could change what a parcel is**: heat arriving, water poured on,
210
+ * mass added, a contact, or a source coming within range. Cheap enough — a flag and an integer —
211
+ * that a caller never has to decide whether it is worth it.
212
+ */
213
+ wake(parcel: number): void;
214
+ /**
215
+ * Decide whether this parcel is still enough to sleep, and put it to sleep if it has been for long
216
+ * enough. Returns whether it is now asleep.
217
+ *
218
+ * **A burning or smouldering parcel never sleeps, whatever its numbers say.** A steady flame is a
219
+ * *steady* parcel by every measure here, and sleeping one would put out a fire by optimising it.
220
+ */
221
+ settle(parcel: number): boolean;
222
+ /**
223
+ * Seconds this parcel is owed by its cadence, and whether its turn has come.
224
+ *
225
+ * A `Far` parcel is stepped every fourth tick with four ticks of `dt`, so the same seconds are
226
+ * integrated either way — which is what makes a cadence conserving for free rather than by care.
227
+ */
228
+ accrue(parcel: number, dt: number): number;
229
+ /** Whether a flame stands over this parcel. */
230
+ burning(parcel: number): boolean;
231
+ /** Whether its char is glowing, which needs no flame and far less oxygen. */
232
+ smouldering(parcel: number): boolean;
233
+ /** Whether a pilot is present this tick. */
234
+ piloted(parcel: number): boolean;
235
+ /**
236
+ * Supply a pilot for one tick. **This does not start a fire**, and `§11` is why.
237
+ *
238
+ * Ignition is five conditions, and a pilot is one of them. Holding a match to wet wood does
239
+ * exactly nothing here, which is correct and is the API telling the truth about what a match is.
240
+ */
241
+ ignite(parcel: number): void;
242
+ /** Put the flame out. Embers survive, which is the point — see `§12`. */
243
+ douse(parcel: number): void;
244
+ setBurning(parcel: number, burning: boolean): void;
245
+ setSmouldering(parcel: number, smouldering: boolean): void;
246
+ clearPilot(parcel: number): void;
247
+ /** kg/(m²·s) of gas leaving the surface, all of it. */
248
+ massFluxOf(parcel: number): number;
249
+ /**
250
+ * And of the part of it that can burn — which is the criterion ignition turns on.
251
+ *
252
+ * The two differ by exactly what a wet log gives off. Steam leaving a surface counts toward
253
+ * diluting the mixture above it and not toward feeding it, which is why 60% moisture stops a log
254
+ * catching in front of a fire that lights a seasoned one in eighty seconds.
255
+ */
256
+ fuelFluxOf(parcel: number): number;
257
+ setMassFlux(parcel: number, total: number, fuel: number): void;
258
+ /**
259
+ * Watts the reactions released last step: positive exothermic, negative endothermic.
260
+ *
261
+ * **A fire's size is its heat release rate**, which is what every figure in the design is quoted
262
+ * against and is not the temperature. A pyrolysing surface reads *negative* here while it is
263
+ * gasifying, which is right and is why a flame has to keep feeding heat back to sustain one.
264
+ */
265
+ heatReleaseOf(parcel: number): number;
266
+ /**
267
+ * Kilograms of water per kilogram of dry matter — **the dry basis, which is how it is quoted**.
268
+ *
269
+ * "12% moisture content" means twelve kilograms of water per hundred of dry wood, and
270
+ * `wetComposition` folded that into a wet-basis 0.107 to store it. Undoing the same conversion
271
+ * here is what makes a script comparing against the 0.25 that decides whether a log is worth
272
+ * burning read the quantity the author wrote.
273
+ *
274
+ * Ice counts as water. A frozen log is not a dry one.
275
+ */
276
+ moistureOf(parcel: number): number;
277
+ /**
278
+ * `PHASE_SOLID`, `PHASE_LIQUID`, `PHASE_GAS`, or `PHASE_MIXED` where no one of them dominates.
279
+ *
280
+ * Mixed is a real answer rather than a failure to decide: wet wood is wood and water at once, and
281
+ * calling it either would be a lie a consumer would then draw.
282
+ */
283
+ parcelPhaseOf(parcel: number): number;
284
+ /**
285
+ * Kilograms of **free** water on the surface, per square metre of it.
286
+ *
287
+ * **Free, meaning beyond what the material holds as its own moisture**, and that distinction is
288
+ * the whole reading. A seasoned oak log carries 12% water on a dry basis and is not glossy; a log
289
+ * somebody threw a bucket over is. Reporting the shell's total water would make the two identical
290
+ * and every piece of wood in a scene look rained on.
291
+ *
292
+ * **Derived rather than a column**, because `wet` puts real water in the surface shell rather than
293
+ * setting a flag — so `§17`'s wet-film roughness reads a quantity the boiling reaction is
294
+ * simultaneously consuming, which is what makes drying visible.
295
+ */
296
+ wetnessOf(parcel: number): number;
297
+ /**
298
+ * Pour water on it: liquid water into the surface shell, where the boiling reaction will find it.
299
+ *
300
+ * **Not a flag, and that is the whole point.** The heat sink `§12` describes is the same
301
+ * 2.44 MJ/kg every other drop of water in this model carries, so a doused fire goes out for the
302
+ * reason a real one does and a light sprinkling on a hot ember does not.
303
+ *
304
+ * Refused, naming the substance, where that substance cannot hold water at all — which means it
305
+ * declares no reaction that touches it. Silently doing nothing would make "I poured a bucket on
306
+ * it" and "this material has no water in its model" indistinguishable.
307
+ */
308
+ wet(parcel: number, kilograms: number): void;
309
+ /** Take surface water away: a cloth, a hot dry pan, or wind. Never below what is there. */
310
+ dry(parcel: number, kilograms: number): void;
311
+ /**
312
+ * Metres of char measured inward from the surface.
313
+ *
314
+ * The shells that are mostly carbon, summed by their own thickness. A shell counts once it is past
315
+ * half char, which is a threshold on a continuum and is said out loud: a finer answer needs a char
316
+ * *front* within a shell, which is a sub-shell quantity this model does not carry.
317
+ */
318
+ charDepthOf(parcel: number): number;
319
+ /**
320
+ * How much of this parcel is still load-bearing, 1 down to 0.
321
+ *
322
+ * **`§18` refuses structural failure in writing and this is the refusal reporting.** A beam whose
323
+ * char depth has eaten a fraction of its thickness has lost that fraction of its strength, and
324
+ * what happens next — a joint releasing, a body splitting, a building coming down — belongs to
325
+ * whoever owns the solver. This package writes the scalar, emits an event at a threshold, and
326
+ * breaks nothing.
327
+ */
328
+ structuralIntegrityOf(parcel: number): number;
329
+ /**
330
+ * Pour `from` into `into`; `from` is consumed. Mass, elements and enthalpy all conserved exactly.
331
+ *
332
+ * **Both must be the same substance, and two that are not are refused naming both.** Two
333
+ * substances are two species sets and two shell counts, so mixing them would silently discard
334
+ * whichever set was narrower — and a stew is not a substance change. What a consumer combining two
335
+ * genuinely different materials wants is a third substance that is the mixture, authored as one.
336
+ */
337
+ mix(from: number, into: number): void;
338
+ /**
339
+ * Joules into one named shell.
340
+ *
341
+ * The difference between this and `addSurfaceHeat` is a microwave and an oven: one deposits where
342
+ * the field penetrates to, the other at the surface. Nothing here decides which is physical.
343
+ */
344
+ addShellHeat(parcel: number, shell: number, joules: number): void;
345
+ /**
346
+ * What fraction of its original volume is left, as mass leaves it.
347
+ *
348
+ * **The number a shrinking log is drawn from.** A parcel's volume is its mass over its substance's
349
+ * density, and the density does not change — so this is simply what share of the mass is still
350
+ * here, which falls as volatiles leave and rises for nothing.
351
+ */
352
+ volumeShareOf(parcel: number): number;
353
+ /**
354
+ * Joules per kelvin of the surface shell, from what it is made of right now.
355
+ *
356
+ * **What every explicit surface term has to be bounded against.** A flux times an area times a
357
+ * step is joules, and joules into a small enough shell is an arbitrarily large temperature change
358
+ * — so a term that does not know this number cannot tell the difference between heating something
359
+ * and destroying it. `ChemistryWorld` uses it to stop a radiative or convective step carrying a
360
+ * surface past the thing driving it.
361
+ */
362
+ surfaceHeatCapacityOf(parcel: number): number;
363
+ /** What this parcel's substance looks like, or `null` where nobody said. */
364
+ appearanceOf(parcel: number): AppearanceModel | null;
365
+ /** Share of this parcel's mass that is char, 0..1. */
366
+ charFractionOf(parcel: number): number;
367
+ /** Add (or with a negative value, remove) mass of one species in one shell. */
368
+ addSpeciesMass(parcel: number, shell: number, species: number, kilograms: number): void;
369
+ /** How many substances this store's registry holds. `fingerprintChemistry` covers all of them. */
370
+ get substanceCount(): number;
371
+ /**
372
+ * A number standing for what a registered substance *is*, for the fingerprint.
373
+ *
374
+ * Its density, porosity, emissivity, shell count and the species it can hold — enough that two
375
+ * libraries differing anywhere disagree here, and cheap enough to compute once a tick. `§15` asks
376
+ * for the registry to be covered because two worlds with different substances are different
377
+ * worlds, and a replay crossing them should say so rather than diverge later.
378
+ */
379
+ substanceDigestOf(substance: number): number;
380
+ /** Global species indices this parcel's substance can hold. */
381
+ speciesSetOf(substance: number): Int32Array;
382
+ idOfSpecies(species: number): string;
383
+ phaseOf(species: number): number;
384
+ emissivityOf(parcel: number): number;
385
+ /** When this parcel's substance catches, or `null` where nobody said it does. */
386
+ ignitionOf(substance: number): IgnitionModel | null;
387
+ porosityOf(parcel: number): number;
388
+ /** W/(m·K) at a temperature, or zero where the substance never said. */
389
+ conductivityOf(parcel: number, temperature: number): number;
390
+ /** Metres from the outside of shell `shell` to the inside of it. */
391
+ shellDepthOf(parcel: number, shell: number): number;
392
+ private checkShell;
393
+ private grow;
394
+ private check;
395
+ }