@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,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
|
+
}
|