driftlet 1.2.4 → 1.3.2
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 +1 -1
- package/docs/conventions.md +8 -3
- package/docs/device.md +38 -9
- package/docs/internals.md +33 -14
- package/docs/numerics.md +65 -15
- package/docs/reliability.md +25 -16
- package/docs/statistics.md +13 -0
- package/llms.txt +11 -8
- package/package.json +1 -1
- package/src/assemble.js +206 -0
- package/src/bernoulli.js +32 -0
- package/src/boundaries.js +795 -0
- package/src/describe.js +2 -0
- package/src/device.js +32 -6
- package/src/impedance.js +857 -0
- package/src/index.js +25 -1
- package/src/newton.js +605 -0
- package/src/regions.js +1009 -0
- package/src/solution.js +24 -2
- package/src/solver.js +178 -3643
- package/src/start.js +508 -0
- package/src/steady.js +817 -0
- package/src/timeSteps.js +17 -2
- package/src/types.js +3 -0
- package/types/assemble.d.ts +18 -0
- package/types/bernoulli.d.ts +9 -0
- package/types/boundaries.d.ts +24 -0
- package/types/impedance.d.ts +53 -0
- package/types/newton.d.ts +7 -0
- package/types/regions.d.ts +61 -0
- package/types/solver.d.ts +14 -220
- package/types/start.d.ts +14 -0
- package/types/steady.d.ts +81 -0
- package/types/types.d.ts +6 -0
package/src/describe.js
CHANGED
|
@@ -114,6 +114,8 @@ export function unitWarnings(def) {
|
|
|
114
114
|
if (!isObject(p)) return;
|
|
115
115
|
capacitance(`ports[${k}].capacitance.C`, p.capacitance?.C);
|
|
116
116
|
kinetics(`ports[${k}]`, p.reactions);
|
|
117
|
+
// (an area per volume typed in cm²/cm³ is 100 times too small: a mesh at 10 cm²/cm³ went by)
|
|
118
|
+
if (typeof p.area === 'number' && p.area > 0 && p.area < 100) warn(`ports[${k}].area`, `${num(p.area)} m²/m³ is under 1 cm² of electrode per cm³; area is m²/m³ (1 cm²/cm³ = 100 m²/m³)`);
|
|
117
119
|
});
|
|
118
120
|
for (const side of ['left', 'right']) {
|
|
119
121
|
const c = def.contacts?.[side];
|
package/src/device.js
CHANGED
|
@@ -415,16 +415,42 @@ export function normalizeDevice(def) {
|
|
|
415
415
|
'geometry: the cross-section vanishes inside the device; only an end may have A = 0',
|
|
416
416
|
);
|
|
417
417
|
|
|
418
|
-
// Port windows
|
|
418
|
+
// Port windows, [from, to] of the region's left end: the nodes of the port's region whose boxes
|
|
419
|
+
// reach into it, each with the part of its box inside (fill, by length) and that part's ends
|
|
420
|
+
// (lo, hi), so a window holds to − from of electrode, capacitance or exchange however the grid
|
|
421
|
+
// falls. A held level holds the nodes inside the window (inside). A window of no width is the
|
|
422
|
+
// node there, its whole box.
|
|
419
423
|
ports.forEach((port, k) => {
|
|
420
|
-
const nodes = [];
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
424
|
+
const nodes = [], fill = [], lo = [], hi = [], inside = [];
|
|
425
|
+
const r0 = grid.regionStart[port.region], r1 = grid.regionEnd[port.region], x0 = grid.x[r0];
|
|
426
|
+
const tol = 1e-15 * port.span, a = x0 + port.from, b = x0 + port.to;
|
|
427
|
+
for (let g = r0; g <= r1; g++) {
|
|
428
|
+
const x = grid.x[g], bl = g > r0 ? x - grid.segLength[g - 1] / 2 : x, br = g < r1 ? x + grid.segLength[g] / 2 : x;
|
|
429
|
+
const isIn = x >= a - tol && x <= b + tol;
|
|
430
|
+
const l = Math.max(bl, a), h = Math.min(br, b);
|
|
431
|
+
if (b - a <= tol ? !isIn : !(h - l > tol)) continue;
|
|
432
|
+
nodes.push(g);
|
|
433
|
+
inside.push(isIn ? 1 : 0);
|
|
434
|
+
if (b - a <= tol) {
|
|
435
|
+
fill.push(1);
|
|
436
|
+
lo.push(bl);
|
|
437
|
+
hi.push(br);
|
|
438
|
+
} else {
|
|
439
|
+
fill.push(br > bl ? (h - l) / (br - bl) : 1);
|
|
440
|
+
lo.push(l);
|
|
441
|
+
hi.push(h);
|
|
442
|
+
}
|
|
425
443
|
}
|
|
426
444
|
need(nodes.length > 0, `ports[${k}]: the window [${port.from}, ${port.to}] m holds no grid node; widen it or refine the grid`);
|
|
427
445
|
port.nodes = Int32Array.from(nodes);
|
|
446
|
+
port.fill = Float64Array.from(fill);
|
|
447
|
+
port.lo = Float64Array.from(lo);
|
|
448
|
+
port.hi = Float64Array.from(hi);
|
|
449
|
+
port.inside = Uint8Array.from(inside);
|
|
450
|
+
need(
|
|
451
|
+
!port.species.some((l) => l.type === 'equilibrium') || inside.some((v) => v),
|
|
452
|
+
`ports[${k}]: the window [${port.from}, ${port.to}] m holds no grid node for its held level; widen it or refine the grid`,
|
|
453
|
+
);
|
|
428
454
|
});
|
|
429
455
|
// A node's surface belongs to one electrode, and its gates to one membrane.
|
|
430
456
|
const surfaced = new Int32Array(grid.nNodes).fill(-1);
|