driftlet 0.8.0 → 0.10.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/README.md +5 -3
- package/docs/device.md +169 -57
- package/docs/kit.md +7 -2
- package/docs/numerics.md +17 -5
- package/llms.txt +106 -7
- package/package.json +2 -1
- package/src/checks.js +27 -23
- package/src/describe.js +18 -10
- package/src/device.js +90 -21
- package/src/index.js +18 -4
- package/src/polarization.js +59 -12
- package/src/solution.js +32 -2
- package/src/solver.js +308 -59
- package/src/stack.js +3 -2
- package/src/types.js +14 -3
- package/types/checks.d.ts +3 -3
- package/types/index.d.ts +1 -0
- package/types/live.d.ts +1 -0
- package/types/polarization.d.ts +8 -2
- package/types/solver.d.ts +35 -4
- package/types/stack.d.ts +1 -1
- package/types/types.d.ts +31 -1
package/src/stack.js
CHANGED
|
@@ -100,7 +100,7 @@ export function bath(c, reference, d = 0, { offset } = {}) {
|
|
|
100
100
|
return { ...drive(d, 'bath'), bath: { c: { ...c }, reference, ...(offset === undefined ? {} : { offset }) } };
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
const STACK_FIELDS = ['T', 'library', 'species', 'materials', 'stack', 'bulkReactions', 'ports', 'grid'];
|
|
103
|
+
const STACK_FIELDS = ['T', 'library', 'species', 'materials', 'stack', 'bulkReactions', 'ports', 'grid', 'geometry'];
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Build a plain device definition from a stack:
|
|
@@ -112,7 +112,7 @@ const STACK_FIELDS = ['T', 'library', 'species', 'materials', 'stack', 'bulkReac
|
|
|
112
112
|
* between them get the default face. Nested lists are flattened.
|
|
113
113
|
* - Layers may give doping as `donors` and `acceptors` (mol/m³) in place of `fixedCharge`.
|
|
114
114
|
* - `library`: pieces with species and materials, merged with `species` and `materials`.
|
|
115
|
-
* - `T`, `grid`, `ports` pass through.
|
|
115
|
+
* - `T`, `grid`, `ports`, `geometry` pass through.
|
|
116
116
|
* @param {object} def
|
|
117
117
|
* @returns {object} a device definition for `new Device`
|
|
118
118
|
*/
|
|
@@ -168,5 +168,6 @@ export function build(def) {
|
|
|
168
168
|
if (def.bulkReactions !== undefined) out.bulkReactions = def.bulkReactions;
|
|
169
169
|
if (def.ports !== undefined) out.ports = def.ports;
|
|
170
170
|
if (def.grid !== undefined) out.grid = def.grid;
|
|
171
|
+
if (def.geometry !== undefined) out.geometry = def.geometry;
|
|
171
172
|
return out;
|
|
172
173
|
}
|
package/src/types.js
CHANGED
|
@@ -157,10 +157,16 @@
|
|
|
157
157
|
* @property {string} [terminal] species whose offset defaults to 0; with reactions, the electrode's carrier
|
|
158
158
|
* @property {Record<string, 'blocked' | 'equilibrium' | { type: 'equilibrium', offset?: number, mu?: number }
|
|
159
159
|
* | { type: 'conductance', G: number, offset?: number } | { type: 'exchange', k: number, mu: number }>} [species]
|
|
160
|
-
* @property {{ equation: string, fixed?: Record<string, number>, k0: number, alpha: number }[]} [reactions] an
|
|
160
|
+
* @property {{ equation: string, fixed?: Record<string, number>, k0: number, alpha: number, bare?: boolean }[]} [reactions] an
|
|
161
161
|
* electrode spread through the window: Butler–Volmer per area (k0 in mol/(m²·s)) between the region's
|
|
162
162
|
* species and the terminal species at the port's level
|
|
163
|
-
* @property {
|
|
163
|
+
* @property {Record<string, { mu0: number, capacity: number, theta0?: number }>} [surface] with reactions: species
|
|
164
|
+
* on the electrode's sites, Langmuir (μ = μ° + RT ln(θ/θ₀)), capacity in mol of sites per m² of electrode,
|
|
165
|
+
* shared; a reaction with `bare: true` runs only on the bare fraction θ₀ = 1 − Σθ
|
|
166
|
+
* @property {{ C: number, zeroCharge?: number }} [capacitance] a capacitance spread through the window (F/m² of
|
|
167
|
+
* electrode): σ = C (V − zeroCharge − φ) on the port's side, aσ in each node's charge balance; a gate
|
|
168
|
+
* along a channel, a double layer
|
|
169
|
+
* @property {number | { x: number[], values: number[] }} [area] with reactions or a capacitance: electrode area per volume,
|
|
164
170
|
* m²/m³ (1/h for a film of thickness h), or a profile against the device's x
|
|
165
171
|
*/
|
|
166
172
|
|
|
@@ -191,6 +197,10 @@
|
|
|
191
197
|
*/
|
|
192
198
|
|
|
193
199
|
/**
|
|
200
|
+
* The device's totals through its cross-section (currents, fluxes through contacts and ports,
|
|
201
|
+
* charges, amounts, reaction totals, impedance) are per m² of a planar device, as below, and
|
|
202
|
+
* whole (A, mol/s, C, mol, Ω; per metre of a cylinder) for one with a `geometry`. Rates at a
|
|
203
|
+
* face or an electrode are always per m² of it.
|
|
194
204
|
* @typedef {object} Solution
|
|
195
205
|
* @property {Float64Array} x node positions, m (interface positions appear twice)
|
|
196
206
|
* @property {Int32Array} region region index per node
|
|
@@ -209,7 +219,8 @@
|
|
|
209
219
|
* @property {{ left: ContactResult, right: ContactResult }} contacts
|
|
210
220
|
* @property {{ left?: { V: number, D: number, charge: number }, right?: { V: number, D: number, charge: number } }} gates
|
|
211
221
|
* @property {{ name: string, V: number, flux: Record<string, number>, current: number, x?: Float64Array,
|
|
212
|
-
* area?: Float64Array, rates?: Float64Array[]
|
|
222
|
+
* area?: Float64Array, rates?: Float64Array[], coverage?: Record<string, Float64Array>, bare?: Float64Array,
|
|
223
|
+
* sigma?: Float64Array, charge?: number }[]} ports what each internal port brings into the device;
|
|
213
224
|
* with reactions, also its window's nodes (x, m), area per volume there, and each reaction's rate per area
|
|
214
225
|
* at each node (mol/(m²·s), forward)
|
|
215
226
|
* @property {{ left: string, right: string, dipole: number, sheetCharge: number, D: number, N: Record<string, number>, rates: number[] }[]} interfaces
|
package/types/checks.d.ts
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* - **warnings**: the solution's warnings (unresolved double layers, steep profiles, weakly held
|
|
14
14
|
* parts) and the definition's likely unit slips.
|
|
15
15
|
* - **balance** (a steady state): each species' ledger, what comes in through each terminal and
|
|
16
|
-
* what each reaction (bulk or at a face) makes or uses, in mol/(m²·s)
|
|
17
|
-
* species, as a current F·|z|·rate. The terms must sum to
|
|
18
|
-
* and it says where every carrier went.
|
|
16
|
+
* what each reaction (bulk or at a face) makes or uses, in mol/(m²·s) (mol/s if the device
|
|
17
|
+
* isn't planar) and, for a charged species, as a current F·|z|·rate. The terms must sum to
|
|
18
|
+
* zero; under light it's J = F(G − R), and it says where every carrier went.
|
|
19
19
|
* - **conservation** (a transient): every closed, unreacting stretch keeps what it held plus
|
|
20
20
|
* what came in.
|
|
21
21
|
* - **grid** (a steady state, with `refine`, the default): the device solved again on a grid
|
package/types/index.d.ts
CHANGED
package/types/live.d.ts
CHANGED
package/types/polarization.d.ts
CHANGED
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* @param {{ face: number } | { port: string | number, x?: number }} where a face's index, or a port
|
|
10
10
|
* (name or index) and the position in its window (m, the device's x; default its first node)
|
|
11
11
|
* @param {number | ArrayLike<number>} V the metal's level(s), V
|
|
12
|
-
* @
|
|
12
|
+
* @param {{ surface?: 'held' | 'equilibrium' }} [opts] an electrode port's surface coverages: held as
|
|
13
|
+
* in `sol` (the default: this instant's curves), or in equilibrium at each V (the steady-state
|
|
14
|
+
* curve, with a passive film's active–passive peak), each species by the reaction that makes it
|
|
15
|
+
* @returns {{ V: Float64Array, current: Float64Array, bare?: Float64Array, reactions: { equation: string, level: number,
|
|
13
16
|
* rate: Float64Array, current: Float64Array }[] }} per reaction: its equilibrium level here (where
|
|
14
17
|
* its rate is zero), its rate (mol/(m²·s) of electrode, forward) and its current (A/m², anodic
|
|
15
18
|
* positive: into the solution); and their sum
|
|
@@ -19,9 +22,12 @@ export function polarization(device: import("./index.js").Device, sol: object, w
|
|
|
19
22
|
} | {
|
|
20
23
|
port: string | number;
|
|
21
24
|
x?: number;
|
|
22
|
-
}, V: number | ArrayLike<number
|
|
25
|
+
}, V: number | ArrayLike<number>, opts?: {
|
|
26
|
+
surface?: "held" | "equilibrium";
|
|
27
|
+
}): {
|
|
23
28
|
V: Float64Array;
|
|
24
29
|
current: Float64Array;
|
|
30
|
+
bare?: Float64Array;
|
|
25
31
|
reactions: {
|
|
26
32
|
equation: string;
|
|
27
33
|
level: number;
|
package/types/solver.d.ts
CHANGED
|
@@ -8,12 +8,21 @@ export class Solver {
|
|
|
8
8
|
n: any;
|
|
9
9
|
M: any;
|
|
10
10
|
nRx: any;
|
|
11
|
+
nSurf: any;
|
|
11
12
|
nNodes: any;
|
|
12
13
|
nFaces: number;
|
|
13
14
|
nB: any;
|
|
14
15
|
VT: number;
|
|
15
16
|
blockOfNode: Int32Array<any>;
|
|
16
17
|
blockOfFace: Int32Array<ArrayBuffer>;
|
|
18
|
+
surfPort: Int32Array<any>;
|
|
19
|
+
surfW: Int32Array<any>;
|
|
20
|
+
surfCols: any;
|
|
21
|
+
surfColOf: any;
|
|
22
|
+
th: Float64Array<ArrayBuffer>;
|
|
23
|
+
thOld: Float64Array<ArrayBuffer>;
|
|
24
|
+
th0: Float64Array<any>;
|
|
25
|
+
th0Old: Float64Array<any>;
|
|
17
26
|
present: Uint8Array<ArrayBuffer>;
|
|
18
27
|
cRef: Float64Array<ArrayBuffer>;
|
|
19
28
|
mu0hat: Float64Array<ArrayBuffer>;
|
|
@@ -54,6 +63,13 @@ export class Solver {
|
|
|
54
63
|
left: number;
|
|
55
64
|
right: number;
|
|
56
65
|
};
|
|
66
|
+
portQ: Float64Array<any>;
|
|
67
|
+
portQStart: Float64Array<any>;
|
|
68
|
+
portQOld: Float64Array<any>;
|
|
69
|
+
portQEnd: any;
|
|
70
|
+
qg: Float64Array<any>;
|
|
71
|
+
qgSlope: Float64Array<any>;
|
|
72
|
+
qgTerms: any[][];
|
|
57
73
|
contactDOld: {
|
|
58
74
|
left: number;
|
|
59
75
|
right: number;
|
|
@@ -83,12 +99,17 @@ export class Solver {
|
|
|
83
99
|
generationScale: number;
|
|
84
100
|
hasGeneration: any;
|
|
85
101
|
rxsIn: any;
|
|
102
|
+
closedEnd: {
|
|
103
|
+
left: any;
|
|
104
|
+
right: any;
|
|
105
|
+
};
|
|
86
106
|
chargeNode: Uint8Array<any>;
|
|
87
107
|
chargeNodes: Int32Array<ArrayBuffer>;
|
|
88
108
|
combining: boolean;
|
|
89
109
|
bookkeeping: any;
|
|
90
110
|
bookkeepingFaces: number[];
|
|
91
111
|
referenceAmounts: number[];
|
|
112
|
+
surfaceRef: Float64Array<ArrayBuffer>;
|
|
92
113
|
boundaryIntake: Float64Array<ArrayBuffer>;
|
|
93
114
|
_activeSlots(): void;
|
|
94
115
|
active: Uint8Array<ArrayBuffer>;
|
|
@@ -104,18 +125,20 @@ export class Solver {
|
|
|
104
125
|
_findStretches(): void;
|
|
105
126
|
stretches: any[];
|
|
106
127
|
stretchOf: Int32Array<ArrayBuffer>;
|
|
107
|
-
moieties: Float64Array<
|
|
128
|
+
moieties: Float64Array<any>[];
|
|
108
129
|
constraints: any[];
|
|
109
130
|
localConstraints: any[];
|
|
110
131
|
constrained: boolean;
|
|
111
132
|
_captureLocal(): void;
|
|
112
133
|
_applyLocalConstraints(): void;
|
|
113
|
-
_conservedMoieties(): Float64Array<
|
|
134
|
+
_conservedMoieties(): Float64Array<any>[];
|
|
114
135
|
_directSteady(): boolean;
|
|
115
136
|
_applyConstraints(): void;
|
|
116
137
|
_solveBordered(rhs: any, delta: any, deltaV: any, pins: any): void;
|
|
117
138
|
dWork: Float64Array<ArrayBuffer>;
|
|
118
139
|
borderCols: any[];
|
|
140
|
+
/** Amount (mol per unit area) of surface column j's species, Γ Σ v·a·θ, in the current state. */
|
|
141
|
+
surfaceAmount(j: any): number;
|
|
119
142
|
/** Total amount (mol per unit area) of a stretch's species in the current state. */
|
|
120
143
|
amount(stretch: any): number;
|
|
121
144
|
redrive(): void;
|
|
@@ -133,6 +156,7 @@ export class Solver {
|
|
|
133
156
|
initFromComposition(): void;
|
|
134
157
|
_portRate(port: any, rx: any, g: any): number;
|
|
135
158
|
_materialAt(mat: any, background: any, eta: any, mode: any, cFix: any, ph: any, zeta: any, cc: any): void;
|
|
159
|
+
_coverages(): void;
|
|
136
160
|
computeConcentrations(): void;
|
|
137
161
|
_work(md: any): any;
|
|
138
162
|
_nodeStatistics(g: any, b: any, phiHat: any): void;
|
|
@@ -172,8 +196,10 @@ export class Solver {
|
|
|
172
196
|
_terminals(dt: any): void;
|
|
173
197
|
_circuit(k: any): void;
|
|
174
198
|
_captureRow(b: any, s: any, w: any, into: any): number;
|
|
175
|
-
_port(port: any, flux: any, k: any): void;
|
|
199
|
+
_port(port: any, flux: any, k: any, dt: any, holds: any): void;
|
|
176
200
|
_portReaction(port: any, rx: any, area: any, rates: any, flux: any, k: any): void;
|
|
201
|
+
_portCapacitance(port: any, k: any, dt: any): void;
|
|
202
|
+
_surfaceStorage(port: any, dt: any): void;
|
|
177
203
|
_contact(side: any, dt: any): void;
|
|
178
204
|
_replaceRow(b: any, rs: any): void;
|
|
179
205
|
_equilibrate(): void;
|
|
@@ -222,7 +248,7 @@ export class Solver {
|
|
|
222
248
|
/**
|
|
223
249
|
* Adaptive time stepping to tEnd: variable-step BDF2 (or backward Euler), with the local error
|
|
224
250
|
* estimated against an explicit predictor through the previous states, and controlled to
|
|
225
|
-
* `tol` thermal units per step in every potential (φ̂, each η, a
|
|
251
|
+
* `tol` thermal units per step in every potential (φ̂, each η, a surface's coverages as η). The first
|
|
226
252
|
* step is checked by step doubling. Stops early when `budgetMs` of wall time is used, so an
|
|
227
253
|
* animation can call it once per frame; the step size carries over between calls.
|
|
228
254
|
*/
|
|
@@ -257,6 +283,8 @@ export class Solver {
|
|
|
257
283
|
u: Float64Array<ArrayBuffer>;
|
|
258
284
|
uLo: Float64Array<ArrayBuffer>;
|
|
259
285
|
cOld: Float64Array<ArrayBuffer>;
|
|
286
|
+
thOld: Float64Array<ArrayBuffer>;
|
|
287
|
+
th0Old: Float64Array<ArrayBuffer>;
|
|
260
288
|
time: number;
|
|
261
289
|
lastDt: number;
|
|
262
290
|
atSteady: boolean;
|
|
@@ -269,6 +297,9 @@ export class Solver {
|
|
|
269
297
|
right: number;
|
|
270
298
|
};
|
|
271
299
|
contactDEnd: any;
|
|
300
|
+
portQStart: Float64Array<any>;
|
|
301
|
+
portQOld: Float64Array<any>;
|
|
302
|
+
portQEnd: any;
|
|
272
303
|
boundaryIntake: Float64Array<ArrayBuffer>;
|
|
273
304
|
history: any[];
|
|
274
305
|
termV: Float64Array<ArrayBuffer>;
|
package/types/stack.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export function bath(c: Record<string, number>, reference: string, d?: number, {
|
|
|
53
53
|
* between them get the default face. Nested lists are flattened.
|
|
54
54
|
* - Layers may give doping as `donors` and `acceptors` (mol/m³) in place of `fixedCharge`.
|
|
55
55
|
* - `library`: pieces with species and materials, merged with `species` and `materials`.
|
|
56
|
-
* - `T`, `grid`, `ports` pass through.
|
|
56
|
+
* - `T`, `grid`, `ports`, `geometry` pass through.
|
|
57
57
|
* @param {object} def
|
|
58
58
|
* @returns {object} a device definition for `new Device`
|
|
59
59
|
*/
|
package/types/types.d.ts
CHANGED
|
@@ -380,9 +380,29 @@ export type PortDef = {
|
|
|
380
380
|
fixed?: Record<string, number>;
|
|
381
381
|
k0: number;
|
|
382
382
|
alpha: number;
|
|
383
|
+
bare?: boolean;
|
|
383
384
|
}[];
|
|
384
385
|
/**
|
|
385
|
-
* with reactions:
|
|
386
|
+
* with reactions: species
|
|
387
|
+
* on the electrode's sites, Langmuir (μ = μ° + RT ln(θ/θ₀)), capacity in mol of sites per m² of electrode,
|
|
388
|
+
* shared; a reaction with `bare: true` runs only on the bare fraction θ₀ = 1 − Σθ
|
|
389
|
+
*/
|
|
390
|
+
surface?: Record<string, {
|
|
391
|
+
mu0: number;
|
|
392
|
+
capacity: number;
|
|
393
|
+
theta0?: number;
|
|
394
|
+
}>;
|
|
395
|
+
/**
|
|
396
|
+
* a capacitance spread through the window (F/m² of
|
|
397
|
+
* electrode): σ = C (V − zeroCharge − φ) on the port's side, aσ in each node's charge balance; a gate
|
|
398
|
+
* along a channel, a double layer
|
|
399
|
+
*/
|
|
400
|
+
capacitance?: {
|
|
401
|
+
C: number;
|
|
402
|
+
zeroCharge?: number;
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* with reactions or a capacitance: electrode area per volume,
|
|
386
406
|
* m²/m³ (1/h for a film of thickness h), or a profile against the device's x
|
|
387
407
|
*/
|
|
388
408
|
area?: number | {
|
|
@@ -451,6 +471,12 @@ export type ContactResult = {
|
|
|
451
471
|
*/
|
|
452
472
|
current: number;
|
|
453
473
|
};
|
|
474
|
+
/**
|
|
475
|
+
* The device's totals through its cross-section (currents, fluxes through contacts and ports,
|
|
476
|
+
* charges, amounts, reaction totals, impedance) are per m² of a planar device, as below, and
|
|
477
|
+
* whole (A, mol/s, C, mol, Ω; per metre of a cylinder) for one with a `geometry`. Rates at a
|
|
478
|
+
* face or an electrode are always per m² of it.
|
|
479
|
+
*/
|
|
454
480
|
export type Solution = {
|
|
455
481
|
/**
|
|
456
482
|
* node positions, m (interface positions appear twice)
|
|
@@ -545,6 +571,10 @@ export type Solution = {
|
|
|
545
571
|
x?: Float64Array;
|
|
546
572
|
area?: Float64Array;
|
|
547
573
|
rates?: Float64Array[];
|
|
574
|
+
coverage?: Record<string, Float64Array>;
|
|
575
|
+
bare?: Float64Array;
|
|
576
|
+
sigma?: Float64Array;
|
|
577
|
+
charge?: number;
|
|
548
578
|
}[];
|
|
549
579
|
interfaces: {
|
|
550
580
|
left: string;
|