@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
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright 2026 Drift Technologies
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
DriftEngine
|
|
2
|
+
Copyright 2026 Drift Technologies
|
|
3
|
+
|
|
4
|
+
This product includes software developed at Drift Technologies
|
|
5
|
+
(https://github.com/drftrun/driftengine).
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0. Section 4(d) of that licence
|
|
8
|
+
requires this NOTICE to be reproduced in any derivative work you distribute,
|
|
9
|
+
in the source, the documentation, or a display generated by the work.
|
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# @driftengine/chemistry
|
|
2
|
+
|
|
3
|
+
Thermochemistry of bulk matter: what a material is made of, what temperature it is, and what it
|
|
4
|
+
turns into. **18.0 KB gzipped**, standalone — it imports no other engine package, so a consumer who
|
|
5
|
+
wants matter and no renderer pays for matter and no renderer.
|
|
6
|
+
|
|
7
|
+
**This is the whole of Track P, CH-0 through CH-10.**
|
|
8
|
+
|
|
9
|
+
## What ships today
|
|
10
|
+
|
|
11
|
+
| | |
|
|
12
|
+
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
13
|
+
| **Fifteen elements** | `C H O N S Cl Si Ca Fe Al Mg Cu Na K P`, with IUPAC conventional atomic weights. A closed set, so every matrix has a fixed width and a totals vector is fifteen doubles |
|
|
14
|
+
| **Sixty-eight species** | Atmospheric and combustion gases, condensed water, three forms of carbon, the wood polymers, the biopolymers, sugars, lipids, fuel surrogates, polymers, minerals and metals. Ten more arrive with the families that need them — wood tar as vapour and as droplets, molten fat, five fuel vapours — rather than being carried by everyone |
|
|
15
|
+
| **Molar mass, derived** | A species carries a _formula_; its mass is that formula against the atomic weights. There is no molar-mass field to disagree with it |
|
|
16
|
+
| **The species-by-element matrix** | Moles of each element per mole of each species, dense, `Float64Array`, with a scaled-row reduction that allocates nothing |
|
|
17
|
+
| **`Composition`** | Mass fractions that must sum to one, stored sorted by species index so two spellings of the same material reduce bit-identically |
|
|
18
|
+
| **`elementTotals`** | Kilograms of species to moles of elements, into a caller-owned vector, allocating nothing |
|
|
19
|
+
| **Enthalpy is the state** | A parcel holds joules and mass; its temperature is **derived from what it is made of right now**. `h = A·ΔT + B·ΔT²/2` inverts in closed form with one square root — no table, no search, and composition-aware by construction |
|
|
20
|
+
| **A phase change is a reaction** | Melting and boiling are gated reactions whose enthalpy Hess's law already supplies, and **the plateau emerges from the solver** rather than from a curve. Nothing branches on melting and nothing has to |
|
|
21
|
+
| **`boilingPoint`** | Clausius-Clapeyron, so a stew at 3,000 m is pinned at 90 °C and cannot brown. Authoring-time only until CH-4 tabulates it |
|
|
22
|
+
| **`ParcelStore`** | Structure-of-arrays `Float64Array` columns: substance, mass, enthalpy, position. `addHeat` is one addition and `temperatureOf` is one search |
|
|
23
|
+
| **A parcel has depth** | Nested shells of **equal mass**, so a large object's surface shell is thin and its core is fat. Heat enters shell 0 and conducts inward, and the interface conductivity is the **harmonic mean**, because a boundary is a series resistance |
|
|
24
|
+
| **Thin catches, thick does not** | Under 20 kW/m², a 2 mm slab's surface passes 300 °C in 29 s and an 80 mm one takes 400 s — and the 80 mm log's _core_ is five hundredths of a kelvin above the room while its surface chars |
|
|
25
|
+
| **Reactions that balance** | Checked against the element matrix at registration and **refused naming the element and the gap**. Enthalpies derived by Hess's law, never typed in: methane comes out at its published heating values without either being written down |
|
|
26
|
+
| **Rates as tables** | `exp` never runs on a tick. Knots uniform in `1/T`, where `ln k` is exactly linear, measured under 0.5% against the closed form |
|
|
27
|
+
| **A solver that cannot go negative** | Sub-stepped by stiffness, then clamped: where demand exceeds what is present, every reaction drawing on that species is cut **by the same factor**, so the answer does not depend on registration order |
|
|
28
|
+
| **One atmosphere** | Sparse chunks, and empty air costs nothing. Conservative flux transport on the one wind plus buoyancy, a connectivity that makes a sealed room sealed, and a far-field ledger that balances |
|
|
29
|
+
| **Gas-phase combustion** | The **same solver** a shell uses, given a cell — which is what lets a flame stand off a surface rather than sit on it |
|
|
30
|
+
| **Radiation, and `1/r²`** | A source is declared and every parcel works out what reaches it. Move a log twice as far from a fire and it takes four times as long — one line of arithmetic, and the whole reason distance means anything |
|
|
31
|
+
| **The parcels meet the air** | A burning parcel draws the oxygen its reactions want out of the cell it sits in and pushes the gas they make into it. One relaxation, both directions |
|
|
32
|
+
| **Ignition is a criterion** | Five conditions, and `ignite` supplies one of them. **Holding a match to wet wood does nothing**, which is the API telling the truth about what a match is |
|
|
33
|
+
| **Extinction is four** | Fuel gone, oxygen below the limiting index, surface cooled, or blown off — and a smoulder survives air a flame cannot, which is why smothering leaves embers |
|
|
34
|
+
| **An event buffer** | Twenty-one kinds, drained per tick, in the shape `drift/physics`'s contact buffer established |
|
|
35
|
+
| **Char glows for an hour** | Above about 800 K the chemistry outruns oxygen delivery, so the rate is transport, not kinetics. The two combine as a series resistance — and **blowing on an ember brightens it** |
|
|
36
|
+
| **A smoulder's smoke is pale** | Tar leaving a surface cracks to soot and burns where it is hot, and **condenses to droplets where it is not** — a 523 K dew point, which is Clausius-Clapeyron at the loading a plume carries rather than levoglucosan's 658 K boiling point. Two rates that climb with temperature against one gate that closes with it, so a flame blackens its own smoke and a smoulder whitens its own with nothing choosing. `aerosolAt` sums every carried species in the **liquid phase**, so the field never names a species this library invented |
|
|
37
|
+
| **A log dries, smokes and catches** | The whole of `§21`, asserted: the surface pins at the boiling point while the core stays cold, gas comes off, and it lights. **A green log at the same fire does not** |
|
|
38
|
+
| **Thirty-nine substances** | Across seven entry points — organic, food, fuel, polymer, mineral, metal, biological — each with real compositions, thermophysics and reactions, and **each family costs 625 bytes to 1.3 kilobytes**, so a consumer who wants a campfire pays for a campfire |
|
|
39
|
+
|
|
40
|
+
## The substance library, and what it costs
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import {
|
|
44
|
+
installLibrary,
|
|
45
|
+
ReactionRegistry,
|
|
46
|
+
SpeciesRegistry,
|
|
47
|
+
SubstanceRegistry,
|
|
48
|
+
} from '@driftengine/chemistry';
|
|
49
|
+
import { ORGANIC } from '@driftengine/chemistry/library/organic';
|
|
50
|
+
|
|
51
|
+
installLibrary(ORGANIC, species, reactions, substances);
|
|
52
|
+
const log = parcels.spawn({
|
|
53
|
+
substance: substances.indexOf('oak'),
|
|
54
|
+
mass: 8,
|
|
55
|
+
temperature: 293.15,
|
|
56
|
+
area: 0.2,
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
| Entry point | Substances | Cost over three you wrote yourself |
|
|
61
|
+
| -------------------- | ---------------------------------------------------------------------- | ---------------------------------- |
|
|
62
|
+
| `library/organic` | oak, pine, paper, cotton, leather, straw | 1,279 B |
|
|
63
|
+
| `library/food` | water, ice, butter, beef-muscle, potato, egg-white, sugar | 1,062 B |
|
|
64
|
+
| `library/fuel` | ethanol, petrol, diesel, kerosene, paraffin-wax | 926 B |
|
|
65
|
+
| `library/biological` | compost, hay, flesh, must | 845 B |
|
|
66
|
+
| `library/polymer` | polyethylene, polypropylene, pvc, polystyrene, pmma, polyurethane-foam | 734 B |
|
|
67
|
+
| `library/mineral` | limestone, gypsum-board, sand, clay, concrete, glass | 703 B |
|
|
68
|
+
| `library/metal` | iron, steel, aluminium, copper, magnesium | 625 B |
|
|
69
|
+
|
|
70
|
+
Installing several is ordinary: they share the water phase changes, the five gas-phase combustion
|
|
71
|
+
steps and the two char oxidations, and `installLibrary` skips what is already registered.
|
|
72
|
+
|
|
73
|
+
**Some things the library does that nothing in it decides.** A candle is wax melting, then boiling,
|
|
74
|
+
then burning — three gated reactions in series, and the word "candle" appears nowhere. A steak
|
|
75
|
+
cannot brown while it is wet, because Maillard needs 140 °C and a wet surface is pinned at 100.
|
|
76
|
+
PVC self-extinguishes in air and PMMA does not, on one number each. Char makes mostly CO₂ when it
|
|
77
|
+
smoulders cool and mostly CO when it smoulders hot, because two activation energies differ by
|
|
78
|
+
`6240·R` and that ratio **is** Arthur's relation. A hay bale respires, warms itself out of the
|
|
79
|
+
mesophilic band and is picked up by the thermophiles above it. And burning leather gives off
|
|
80
|
+
hydrogen cyanide, because collagen carries 1.3 nitrogens per residue and they have to go somewhere.
|
|
81
|
+
|
|
82
|
+
**One bias, stated rather than buried.** Pyrolysis endotherms derived over this species set run
|
|
83
|
+
high, because the volatile slate stops at C₂ and char is pure carbon where real volatiles are
|
|
84
|
+
C₁₀–C₄₀ and real char keeps some hydrogen and oxygen. What is _not_ biased is the total: Hess's law
|
|
85
|
+
over the whole path reproduces each material's measured heating value exactly, so what the cap
|
|
86
|
+
distorts is the split between the gasification and the flame, not the heat. It bites hardest on the
|
|
87
|
+
polyolefins and barely at all on wood, whose aggregate lands inside the measured band.
|
|
88
|
+
|
|
89
|
+
## The one thing worth knowing before reading the code
|
|
90
|
+
|
|
91
|
+
**A species stores a formation enthalpy and a heat capacity, and nothing reads them yet.** That is
|
|
92
|
+
not an oversight. CH-3 builds the reaction network, and it derives every reaction's `ΔH` from these
|
|
93
|
+
by Hess's law rather than taking a typed-in number — because a reaction enthalpy that disagreed
|
|
94
|
+
with its own species would conserve energy _in the code_ and lose it _against the world_, with no
|
|
95
|
+
symptom anywhere.
|
|
96
|
+
|
|
97
|
+
So the numbers are checked here instead, where they are written: `standard.test.ts` reconstructs
|
|
98
|
+
eighteen published higher heating values from the stored enthalpies and the element rows, and holds
|
|
99
|
+
them to two percent, which is inside the spread of the published figures themselves.
|
|
100
|
+
|
|
101
|
+
**Pseudo-species carry a back-derived enthalpy.** Cellulose, lignin, a protein residue and a diesel
|
|
102
|
+
surrogate have never been in a calorimeter; what has been measured is what a kilogram of them gives
|
|
103
|
+
off. Their formation enthalpies are derived from that, so Hess's law reproduces the heat the world
|
|
104
|
+
actually releases. They are marked `pseudo: true`, so a reader can tell an exact number from a mean
|
|
105
|
+
over a population.
|
|
106
|
+
|
|
107
|
+
## Using it
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import {
|
|
111
|
+
ELEMENT_COUNT,
|
|
112
|
+
SpeciesRegistry,
|
|
113
|
+
elementTotals,
|
|
114
|
+
massFractions,
|
|
115
|
+
registerStandardSpecies,
|
|
116
|
+
} from '@driftengine/chemistry';
|
|
117
|
+
|
|
118
|
+
const registry = new SpeciesRegistry();
|
|
119
|
+
registerStandardSpecies(registry);
|
|
120
|
+
|
|
121
|
+
// Seasoned oak, dry basis, as mass fractions that must sum to one.
|
|
122
|
+
const oak = massFractions(registry, {
|
|
123
|
+
cellulose: 0.43,
|
|
124
|
+
hemicellulose: 0.26,
|
|
125
|
+
lignin: 0.26,
|
|
126
|
+
extractives: 0.04,
|
|
127
|
+
ash: 0.01,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Ten kilograms of it, reduced to moles of each of the fifteen elements.
|
|
131
|
+
const mass = new Float64Array(registry.count);
|
|
132
|
+
for (let i = 0; i < oak.species.length; i++) {
|
|
133
|
+
mass[oak.species[i]!] = oak.fraction[i]! * 10;
|
|
134
|
+
}
|
|
135
|
+
const elements = new Float64Array(ELEMENT_COUNT);
|
|
136
|
+
elementTotals(registry, mass, elements);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Registration fails fast and never warns.** An unknown element, a duplicate id, a negative
|
|
140
|
+
subscript, an empty formula, a composition that does not sum to one: each throws at init naming the
|
|
141
|
+
offending value. Nothing here runs in a frame, so checking thoroughly costs nothing and not
|
|
142
|
+
checking costs a `NaN` that surfaces twenty ticks into a burn.
|
|
143
|
+
|
|
144
|
+
## Drawing it
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { installChemistry, writeSurface, emitSmoke } from '@driftengine/chemistry/present';
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**`present/` imports nothing and names no core type.** Every target is described structurally by
|
|
151
|
+
what it must have — core's `ParticleInstances` satisfies `SmokeTarget` exactly, and neither package
|
|
152
|
+
knows the other exists. Six mappings, and every one is a physical quantity rather than an art
|
|
153
|
+
direction: smoke colour from the soot-to-aerosol ratio, flame height from `L ≈ 0.235·Q^(2/5) −
|
|
154
|
+
1.02·D`, glow from Planck at the surface temperature, albedo lerped by char fraction, roughness from
|
|
155
|
+
the surface water film, and a scale from the cube root of what is left of the volume. Plus three
|
|
156
|
+
audio scalars, and the package never touches `@driftengine/audio`.
|
|
157
|
+
|
|
158
|
+
**Emissive in this engine is gated on `nightFactor`.** Embers written by `writeSurface` look right at
|
|
159
|
+
dusk and dead at noon. That is `AGENTS.md`'s standing trap and it is said here because this is where
|
|
160
|
+
a consumer meets it.
|
|
161
|
+
|
|
162
|
+
`demo/dev/chemistry.html` is the scene: a hearth where the kettle sits at 99 °C, the green log sits
|
|
163
|
+
at 100 °C, the ice core sits at −1 °C, the iron nail reaches 611 °C and the copper coin beside it
|
|
164
|
+
reaches 75, and a panel in the corner reports element drift at 2.6e-10 over the whole run.
|
|
165
|
+
|
|
166
|
+
## Budgets, tiers, and the fingerprint
|
|
167
|
+
|
|
168
|
+
**A cold stone sleeps.** A parcel whose surface flux and reaction output have both been still for
|
|
169
|
+
thirty ticks is skipped entirely, and wakes on heat, water, mass, a contact, or a fire coming within
|
|
170
|
+
range — the last through a coarse scan spread round-robin over four ticks, so a thousand sleepers
|
|
171
|
+
cost two hundred and fifty range comparisons a tick.
|
|
172
|
+
|
|
173
|
+
**Four tiers, and every one conserves.** `Hero` is the resolution the substance declared, down to one
|
|
174
|
+
shell every sixteenth tick at `Distant`. Shells are equal-mass by construction, so a fold is a
|
|
175
|
+
proportional redistribution and mass, every element and enthalpy come through exactly — which is what
|
|
176
|
+
makes a tier change safe mid-burn. What it costs is measured and stated: over five hundred seconds of
|
|
177
|
+
fire, `Near` is exact, `Far` drifts 21% and `Distant` 43%, and the coarser tiers char _more_, because
|
|
178
|
+
a lumped parcel has no cold core to hide behind.
|
|
179
|
+
|
|
180
|
+
**`fingerprintChemistry`** is sixteen hexadecimal digits over parcel compositions, enthalpies, the
|
|
181
|
+
field's elements and the substance registry — order-insensitive over parcels, because a handle is
|
|
182
|
+
the order something was spawned in. Two libraries are two worlds and it says so.
|
|
183
|
+
|
|
184
|
+
## What is absent
|
|
185
|
+
|
|
186
|
+
**Nothing the design specified.** Condensed tar was the last of it and closed:
|
|
187
|
+
`tar(l)` is carried the way `C(soot)` is, its formation enthalpy is the number pyrolysis oil's
|
|
188
|
+
heating value measures directly, and the vapour that shipped first turns out to be the derived one.
|
|
189
|
+
|
|
190
|
+
One thing inside CH-3 is knowingly approximate and is CH-5's gate: a substance's enthalpy curve is
|
|
191
|
+
built from its _initial_ composition, so as reactions run, the temperature read back drifts by
|
|
192
|
+
however much the true heat capacity has moved. Energy stays exact — the joules are added and
|
|
193
|
+
subtracted directly — and the fix is written down in that phase's plan. See `ROADMAP.md`'s Track P row for the
|
|
194
|
+
order, and the design's `§26` for the nine things the track refuses outright.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SpeciesRegistry } from './species/registry.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Reduce kilograms per species into moles per element.
|
|
4
|
+
*
|
|
5
|
+
* `out` is **overwritten**, not accumulated into, so a caller may hold one vector for the life of a
|
|
6
|
+
* world and re-derive totals every tick without clearing it first. `speciesMass` is indexed by
|
|
7
|
+
* species, so it is the registry's width; a species with no mass costs one comparison.
|
|
8
|
+
*/
|
|
9
|
+
export declare function elementTotals(registry: SpeciesRegistry, speciesMass: Float64Array, out: Float64Array): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moles of each element held by a set of species masses.
|
|
3
|
+
*
|
|
4
|
+
* **This is the law `§6` of the design calls the most valuable test in the track**, and it is one
|
|
5
|
+
* reduction: kilograms of a species become moles through its derived molar mass, and moles of a
|
|
6
|
+
* species become moles of its elements through the species-by-element matrix.
|
|
7
|
+
*
|
|
8
|
+
* A chemistry model that does not conserve elements invents or destroys matter, and every symptom
|
|
9
|
+
* of that is subtle — fires that will not go out, mass that quietly grows, smoke that never clears.
|
|
10
|
+
* One assertion catches all of them, which is why this function exists before there is anything to
|
|
11
|
+
* conserve through.
|
|
12
|
+
*
|
|
13
|
+
* Writes into a caller-owned vector and allocates nothing, so it is affordable on a tick rather
|
|
14
|
+
* than only in a test.
|
|
15
|
+
*/
|
|
16
|
+
import { ELEMENT_COUNT } from './element/elements.js';
|
|
17
|
+
/**
|
|
18
|
+
* Reduce kilograms per species into moles per element.
|
|
19
|
+
*
|
|
20
|
+
* `out` is **overwritten**, not accumulated into, so a caller may hold one vector for the life of a
|
|
21
|
+
* world and re-derive totals every tick without clearing it first. `speciesMass` is indexed by
|
|
22
|
+
* species, so it is the registry's width; a species with no mass costs one comparison.
|
|
23
|
+
*/
|
|
24
|
+
export function elementTotals(registry, speciesMass, out) {
|
|
25
|
+
if (speciesMass.length !== registry.count) {
|
|
26
|
+
throw new Error(`a mass vector is ${registry.count} wide, not ${speciesMass.length}`);
|
|
27
|
+
}
|
|
28
|
+
if (out.length !== ELEMENT_COUNT) {
|
|
29
|
+
throw new Error(`a totals vector is ${ELEMENT_COUNT} wide, not ${out.length}`);
|
|
30
|
+
}
|
|
31
|
+
out.fill(0);
|
|
32
|
+
for (let species = 0; species < speciesMass.length; species++) {
|
|
33
|
+
const kilograms = speciesMass[species];
|
|
34
|
+
if (kilograms === 0)
|
|
35
|
+
continue;
|
|
36
|
+
registry.elements.addScaledRow(species, kilograms / registry.molarMass(species), out);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed element set, and the atomic weights every molar mass is derived from.
|
|
3
|
+
*
|
|
4
|
+
* Fifteen elements, and the set is closed deliberately rather than for want of typing. Every
|
|
5
|
+
* species this package can hold is built from these, so the species-by-element matrix has a fixed
|
|
6
|
+
* width, `elementTotals` reduces into a fixed-length array, and the conservation assertion that
|
|
7
|
+
* `§6` of the design calls the most valuable test in the track is a comparison of two vectors of
|
|
8
|
+
* fifteen doubles rather than a walk over a dictionary.
|
|
9
|
+
*
|
|
10
|
+
* **Adding a sixteenth is a deliberate act with a cost**: every `Float64Array` sized by
|
|
11
|
+
* `ELEMENT_COUNT` grows, and a stored conservation baseline taken before the change no longer
|
|
12
|
+
* compares. That is the right amount of friction for a decision that widens the model's universe.
|
|
13
|
+
*
|
|
14
|
+
* The values are IUPAC conventional atomic weights in g/mol. They are *conventional* rather than
|
|
15
|
+
* the interval form the tables now publish, because a molar mass is arithmetic here and an interval
|
|
16
|
+
* would make every derived mass an interval too — which is honest and useless.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The elements, in the order the design lists them: organic first, then the rest.
|
|
20
|
+
*
|
|
21
|
+
* The order is the wire format of every matrix row and every totals vector in this package, so it
|
|
22
|
+
* is frozen. Reordering it invalidates any baseline a consumer has stored, in exactly the way
|
|
23
|
+
* `AGENTS.md` says the RNG sequence is frozen.
|
|
24
|
+
*/
|
|
25
|
+
export declare const ELEMENTS: readonly ['C', 'H', 'O', 'N', 'S', 'Cl', 'Si', 'Ca', 'Fe', 'Al', 'Mg', 'Cu', 'Na', 'K', 'P'];
|
|
26
|
+
export type ElementSymbol = (typeof ELEMENTS)[number];
|
|
27
|
+
export declare const ELEMENT_COUNT: 15;
|
|
28
|
+
/** Conventional atomic weights, g/mol, indexed the way `ELEMENTS` is. */
|
|
29
|
+
export declare const ATOMIC_MASS: Float64Array<ArrayBuffer>;
|
|
30
|
+
/** The index of an element symbol, or `-1` for anything this package does not carry. */
|
|
31
|
+
export declare function elementIndex(symbol: string): number;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed element set, and the atomic weights every molar mass is derived from.
|
|
3
|
+
*
|
|
4
|
+
* Fifteen elements, and the set is closed deliberately rather than for want of typing. Every
|
|
5
|
+
* species this package can hold is built from these, so the species-by-element matrix has a fixed
|
|
6
|
+
* width, `elementTotals` reduces into a fixed-length array, and the conservation assertion that
|
|
7
|
+
* `§6` of the design calls the most valuable test in the track is a comparison of two vectors of
|
|
8
|
+
* fifteen doubles rather than a walk over a dictionary.
|
|
9
|
+
*
|
|
10
|
+
* **Adding a sixteenth is a deliberate act with a cost**: every `Float64Array` sized by
|
|
11
|
+
* `ELEMENT_COUNT` grows, and a stored conservation baseline taken before the change no longer
|
|
12
|
+
* compares. That is the right amount of friction for a decision that widens the model's universe.
|
|
13
|
+
*
|
|
14
|
+
* The values are IUPAC conventional atomic weights in g/mol. They are *conventional* rather than
|
|
15
|
+
* the interval form the tables now publish, because a molar mass is arithmetic here and an interval
|
|
16
|
+
* would make every derived mass an interval too — which is honest and useless.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The elements, in the order the design lists them: organic first, then the rest.
|
|
20
|
+
*
|
|
21
|
+
* The order is the wire format of every matrix row and every totals vector in this package, so it
|
|
22
|
+
* is frozen. Reordering it invalidates any baseline a consumer has stored, in exactly the way
|
|
23
|
+
* `AGENTS.md` says the RNG sequence is frozen.
|
|
24
|
+
*/
|
|
25
|
+
export const ELEMENTS = [
|
|
26
|
+
'C',
|
|
27
|
+
'H',
|
|
28
|
+
'O',
|
|
29
|
+
'N',
|
|
30
|
+
'S',
|
|
31
|
+
'Cl',
|
|
32
|
+
'Si',
|
|
33
|
+
'Ca',
|
|
34
|
+
'Fe',
|
|
35
|
+
'Al',
|
|
36
|
+
'Mg',
|
|
37
|
+
'Cu',
|
|
38
|
+
'Na',
|
|
39
|
+
'K',
|
|
40
|
+
'P',
|
|
41
|
+
];
|
|
42
|
+
export const ELEMENT_COUNT = ELEMENTS.length;
|
|
43
|
+
/** Conventional atomic weights, g/mol, indexed the way `ELEMENTS` is. */
|
|
44
|
+
export const ATOMIC_MASS = new Float64Array([
|
|
45
|
+
12.011, // C
|
|
46
|
+
1.008, // H
|
|
47
|
+
15.999, // O
|
|
48
|
+
14.007, // N
|
|
49
|
+
32.06, // S
|
|
50
|
+
35.45, // Cl
|
|
51
|
+
28.085, // Si
|
|
52
|
+
40.078, // Ca
|
|
53
|
+
55.845, // Fe
|
|
54
|
+
26.9815384, // Al
|
|
55
|
+
24.305, // Mg
|
|
56
|
+
63.546, // Cu
|
|
57
|
+
22.98976928, // Na
|
|
58
|
+
39.0983, // K
|
|
59
|
+
30.973761998, // P
|
|
60
|
+
]);
|
|
61
|
+
/*
|
|
62
|
+
* A map rather than an `indexOf`, and case-sensitive rather than folded.
|
|
63
|
+
*
|
|
64
|
+
* Case is load-bearing in chemical notation: `Co` is cobalt and `CO` is carbon monoxide, so a
|
|
65
|
+
* lookup that folded case would accept a molecule where an element was wanted and silently produce
|
|
66
|
+
* a molar mass for the wrong thing. Nothing here runs in a frame, so the map is for legibility
|
|
67
|
+
* rather than speed.
|
|
68
|
+
*/
|
|
69
|
+
const INDEX = new Map(ELEMENTS.map((symbol, at) => [symbol, at]));
|
|
70
|
+
/** The index of an element symbol, or `-1` for anything this package does not carry. */
|
|
71
|
+
export function elementIndex(symbol) {
|
|
72
|
+
return INDEX.get(symbol) ?? -1;
|
|
73
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare class SpeciesElementMatrix {
|
|
2
|
+
private store;
|
|
3
|
+
private used;
|
|
4
|
+
get rows(): number;
|
|
5
|
+
/** Append a zeroed row and return its index. */
|
|
6
|
+
addRow(): number;
|
|
7
|
+
set(row: number, element: number, moles: number): void;
|
|
8
|
+
at(row: number, element: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* A row as a view of fifteen, sharing storage rather than copying.
|
|
11
|
+
*
|
|
12
|
+
* **A view is invalidated by a later `addRow` that grows the table**, because growth reallocates.
|
|
13
|
+
* Every caller in this package takes a view inside a loop that registers nothing, which is the
|
|
14
|
+
* only safe pattern and is why this is not handed out as a promise.
|
|
15
|
+
*/
|
|
16
|
+
rowView(row: number): Float64Array;
|
|
17
|
+
/**
|
|
18
|
+
* `out[e] += scale * this[row][e]`, for all fifteen. Allocates nothing.
|
|
19
|
+
*
|
|
20
|
+
* The primitive every conservation check is built from, and it exists rather than a loop over
|
|
21
|
+
* `at` for one reason: `rowView` would be the natural way to write that loop and `subarray`
|
|
22
|
+
* allocates a view object per call, which is an allocation per species per tick. It adds rather
|
|
23
|
+
* than replaces so a caller sums a whole world into one vector without a second accumulator.
|
|
24
|
+
*/
|
|
25
|
+
addScaledRow(row: number, scale: number, out: Float64Array): void;
|
|
26
|
+
private check;
|
|
27
|
+
}
|