driftlet 0.13.0 → 0.16.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/alignment.md +6 -3
- package/docs/data.md +3 -1
- package/docs/device.md +97 -33
- package/docs/kit.md +95 -8
- package/docs/logo-dark.svg +3 -2
- package/docs/logo.svg +3 -2
- package/docs/numerics.md +193 -114
- package/docs/reliability.md +16 -10
- package/docs/statistics.md +28 -4
- package/llms.txt +325 -335
- package/package.json +1 -1
- package/src/blockTridiagonal.js +12 -6
- package/src/checks.js +16 -5
- package/src/describe.js +46 -5
- package/src/device.js +88 -10
- package/src/index.js +19 -7
- package/src/kit.js +1 -0
- package/src/particles.js +407 -0
- package/src/solution.js +171 -10
- package/src/solver.js +797 -262
- package/src/sources.js +10 -2
- package/src/stack.js +16 -6
- package/src/statistics.js +7 -3
- package/types/checks.d.ts +2 -1
- package/types/kit.d.ts +1 -0
- package/types/particles.d.ts +39 -0
- package/types/solution.d.ts +1 -0
- package/types/solver.d.ts +47 -29
- package/types/stack.d.ts +6 -4
package/docs/numerics.md
CHANGED
|
@@ -275,13 +275,30 @@ current into the device, $`I`$. Assembly records, for each:
|
|
|
275
275
|
A floating terminal's voltage is an extra unknown, with its circuit law as an extra row:
|
|
276
276
|
$`I - I_{\mathrm{set}} = 0`$ (driven by a current) or $`I - (V_{\mathrm{src}} - V)/R = 0`$ (behind a
|
|
277
277
|
resistance). These don't fit the block-tridiagonal matrix $`T`$ (a port couples to its whole
|
|
278
|
-
window), so they're solved by bordering, together with
|
|
279
|
-
[steady
|
|
280
|
-
$`Q_q = T^{-1} e_q`$ (the response to a unit
|
|
278
|
+
window), so they're solved by bordering, together with a steady solve's dense rows, the
|
|
279
|
+
conserved amounts' and islands' (see [the steady system](#the-steady-system)): with
|
|
280
|
+
$`y = T^{-1}\,\mathrm{rhs}`$, $`X_k = T^{-1} B_k`$ and $`Q_q = T^{-1} e_q`$ (the response to a unit
|
|
281
|
+
pin; for a flat stretch's amount, to its shift), the update is
|
|
281
282
|
$`\delta = y + \sum Q_q \mu_q - \sum X_k\, \delta V_k`$, and the $`\mu`$ (pins) and $`\delta V`$ (terminals)
|
|
282
283
|
come from a small dense system of the extra rows. Each costs one more back-substitution per
|
|
283
284
|
Newton iteration.
|
|
284
285
|
|
|
286
|
+
A floating terminal (driven by a current, or behind a resistance) that alone feeds a conserved
|
|
287
|
+
combination (a host's electrons behind an open circuit, a gate's metal) can read its current
|
|
288
|
+
another way in a time step: as the combination's change, $`F\,(S - S^*)/(\lambda\, dt)`$, which the step's balance rows
|
|
289
|
+
sum to exactly (λ is its weight over the terminal's charge, $`w/z`$). Both readings are exact;
|
|
290
|
+
they differ in round-off, and in what Newton can see. Through a metal, the flux is $`G\,\Delta\eta`$
|
|
291
|
+
with its two $`\eta`$ all but equal: a floating gate's charging current fell below that at steps
|
|
292
|
+
of ~0.03 s, and the bordered system came out exactly singular (a gate at rest took 5000 steps
|
|
293
|
+
per 100 s, half rejected, where a held one takes 44). Over long steps the flux lets a closed host
|
|
294
|
+
drift from its charge (3 mV over 5e11 s, and steps failed by 4e12 s), where the change keeps
|
|
295
|
+
it. Over short ones the change is the amount's round-off over $`dt`$ (a cathode's 0.04 mol/m² of
|
|
296
|
+
electrons, 1e-6 A/m² at 1 µs), and the flux, its levels carried in two words, is far cleaner. So
|
|
297
|
+
a step reads the change where its round-off, $`\varepsilon F S/(\lambda\, dt)`$, is below 1e-6 of
|
|
298
|
+
the flux's estimate, $`\varepsilon\,\max|C|`$, and a step read by the flux that fails is tried once
|
|
299
|
+
more read by the change. (A gate charged through a resistance, read by its flux, was 0.9% off
|
|
300
|
+
backward Euler's exact RC response, silently; read by its change, it's exact to round-off.)
|
|
301
|
+
|
|
285
302
|
Sources are read at the end of a step (implicit), or at the present time in a steady solve.
|
|
286
303
|
`advance()` lands on every waveform breakpoint and restarts its order there.
|
|
287
304
|
|
|
@@ -638,78 +655,118 @@ only resolved to ~1e-4 of $`|Z|`$.
|
|
|
638
655
|
|
|
639
656
|
## Steady state
|
|
640
657
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
658
|
+
A steady state is where a transient from the present state ends. `solve()` finds it without
|
|
659
|
+
stepping there, as the solution of the steady equations ($`dt = \infty`$, no storage term): slow
|
|
660
|
+
physics can take seconds or hours, far beyond any $`L^2/D`$ estimate (exponentially scarce
|
|
661
|
+
minority carriers slowly filling an inversion layer behind a Schottky contact), and stepping
|
|
662
|
+
would never finish. Three things make that more than one Newton solve: without the storage term,
|
|
663
|
+
the steady equations say nothing of what the transient conserved; some levels are held so weakly
|
|
664
|
+
that a factorisation loses them; and Newton needs a start near enough. `solve()` does not advance
|
|
665
|
+
the clock. Nor does it ask whether the steady state is stable: an axon held at a current that
|
|
666
|
+
makes it fire over and over has a resting point all the same, which `solve()` returns, and only
|
|
667
|
+
a transient leaves it.
|
|
668
|
+
|
|
669
|
+
### The steady system
|
|
670
|
+
|
|
671
|
+
Every row of a steady solve that differs from a time step's is a sum of balance rows. It's
|
|
672
|
+
written out in its telescoped form, never added up from the rows themselves, so what the sum
|
|
673
|
+
leaves is exact, however small beside the terms that cancel:
|
|
674
|
+
|
|
675
|
+
- **A conserved amount.** A combination of stretches (weights $`w`$) that no reaction changes and
|
|
676
|
+
nothing outside feeds has balance rows that sum to zero identically in a steady state: the
|
|
677
|
+
fluxes cancel across its stretches, and the reactions by $`w \cdot \nu = 0`$. One of those rows
|
|
678
|
+
is redundant, and the combination's amount, $`\sum_k w_k \sum v c_k`$, stands in for it. That's
|
|
679
|
+
what a time step's own sum, $`w \cdot (S - S_0)/dt = 0`$, says at any $`dt`$.
|
|
680
|
+
|
|
681
|
+
The combinations are the null space of the stoichiometry (a row per reaction, over the
|
|
682
|
+
stretches it touches) together with what the terminals feed, worked out once and again after a
|
|
683
|
+
change of drive. A terminal held at a voltage (or behind a resistance, which holds it at steady
|
|
684
|
+
state) feeds each stretch it links freely. One driven by a current feeds its charged species
|
|
685
|
+
only as that current allows, in proportion to their charges. So:
|
|
686
|
+
- a **spectator** (a species blocked all round) keeps its amount;
|
|
687
|
+
- so does each **moiety**: the total iron of Fe³⁺, Fe²⁺ and FeCl²⁺ in a closed cell with a
|
|
688
|
+
complexation reaction;
|
|
689
|
+
- so does what a **terminal at no current** alone feeds. A closed battery at open circuit
|
|
690
|
+
has one steady state per state of charge, and a solve that imposed only I = 0 had converged
|
|
691
|
+
to another (4.145 V where its start said 3.958 V). A terminal that passes current only by
|
|
692
|
+
charging a capacitance (a gate, a port's capacitance) is the same, its charge in place of an
|
|
693
|
+
amount; and an electrode port's reactions draw on what the electrode holds, its charge
|
|
694
|
+
$`Q/(zF)`$ a column of its own under a current, so a port at no current reducing a closed
|
|
695
|
+
M⁺ (M⁺ + e⁻ = M(s)) keeps M⁺ + Q/F, or with no capacitance, M⁺ alone. At any other current such a terminal only stores what comes in, which has no steady
|
|
696
|
+
state, and the solve says so at once.
|
|
697
|
+
- an **immobile** combination (trap states X⁰ and X⁻ under e⁻ + X⁰ = X⁻, with D = 0) keeps it
|
|
698
|
+
node by node, since nothing carries it anywhere, as do an electrode's surface species
|
|
699
|
+
(adsorbates that only turn into each other keep their total on every site), its row local,
|
|
700
|
+
one per node in its own block. (The null space is taken with the immobile columns first, so
|
|
701
|
+
that these come out apart from the combinations that move.) A combination of immobile
|
|
702
|
+
stretches with a moving one (the electrons the traps hold, $`e^- - X^0`$, in a closed film) is
|
|
703
|
+
an amount like any other, its immobile parts summed over their nodes;
|
|
704
|
+
- a **floating metal** keeps the charge on its faces, its sheets' displacement.
|
|
705
|
+
|
|
706
|
+
A closed stretch keeps the amount it was given (its `c0`, or what it held when `set()`
|
|
707
|
+
closed it); a combination behind a terminal at no current keeps what the state holds when the
|
|
708
|
+
solve begins. The amount's row is dense, so it's bordered (see [terminals](#terminals)): the
|
|
709
|
+
factorised matrix gets a pin, an identity row, in place of the balance row, which makes the
|
|
710
|
+
stretch's level a well-conditioned unknown, and the response to a unit pin (one more
|
|
711
|
+
back-substitution) goes in at whatever weight satisfies the amount. Behind a terminal at no
|
|
712
|
+
current, the amount stands in for the terminal's circuit row instead: at no current that row is
|
|
713
|
+
the sum of the combination's balance rows, so it says nothing new. (An electrode's charge, which
|
|
714
|
+
moves with the terminal's voltage, goes only there.) The rows replaced must be independent:
|
|
715
|
+
each combination's weights over them a nonsingular matrix, or one balance is said twice and
|
|
716
|
+
another not at all. Picked one combination at a time, two complexations sharing A
|
|
717
|
+
(A + B = AB, A + C = AC) had −A + B + C in place of B's row, B + AB of AB's and A − B + AC of
|
|
718
|
+
A's, and the solve converged to a state that wasn't steady, depending on the order the species
|
|
719
|
+
were listed in. So they're chosen by elimination.
|
|
720
|
+
|
|
721
|
+
Holding an amount through a storage term at a huge $`dt`$ instead is badly conditioned: the
|
|
722
|
+
stretch's level is then held only by $`v \cdot c/dt`$, against internal conductances
|
|
723
|
+
$`D \cdot c/h`$ larger by $`D \cdot dt/(hL)`$, around 1e12 for a micron-scale cell (see
|
|
694
724
|
[metal regions](#metal-regions) for the same cancellation). Newton then needs dozens of
|
|
695
|
-
iterations, or fails.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
725
|
+
iterations, or fails. It's left only where a species is still in one region and moves in the
|
|
726
|
+
next: there, backward-Euler steps at a huge $`dt`$ (10⁶ × the slowest diffusion time) keep
|
|
727
|
+
the storage term, growing ×10 (capped) while the state still moves, each spectator's level
|
|
728
|
+
first shifted uniformly to restore its amount exactly (round-off creeps through the vanishing
|
|
729
|
+
storage term), and one last step at the base huge $`dt`$, where pinning is tight.
|
|
730
|
+
- **A flat level.** A species that no reaction or port touches, reached by one contact at most,
|
|
731
|
+
carries no flux in a steady state: every sum of its balance rows from its closed end is the
|
|
732
|
+
flux through one segment, zero. In an ideal region without flow or mixing that's a level flat
|
|
733
|
+
across the segment, so its level is flat throughout: its contact's, or reaching none (a
|
|
734
|
+
spectator), the level its amount fixes. Steady solves (not the impedance, where it carries a
|
|
735
|
+
current) hold it there in place of its balances, rather than find it through its own
|
|
736
|
+
conduction, which can be all but nothing. A level found that way can't be moved: a MOS
|
|
737
|
+
capacitor's inversion electrons reach the back contact only through a bulk with ~1e3 of them
|
|
738
|
+
per cm³, and with that contact moved, each solve failed through ~90 pseudo-transient steps;
|
|
739
|
+
past a closed zinc cell's limiting current, extended space charge at the cathode excludes the
|
|
740
|
+
blocked sulfate to ~1e-25 mol/m³, and the chain of conductances through it had lost the steady
|
|
741
|
+
system 14 digits (steady solves failed from 0.7 V, and took 37,000 iterations at 0.6 V). (A
|
|
742
|
+
level that starts flat stays exactly so either way: carrying nothing, the flux's expm1 form is
|
|
743
|
+
exactly zero, whatever $`\phi`$ does.) A spectator's first node keeps its amount's row, a pin
|
|
744
|
+
whose response is the whole stretch's shift, so the stretch moves as a whole. At a face inside
|
|
745
|
+
the stretch whose link holds the level continuous, the face's flux, which only the replaced edge
|
|
746
|
+
balances set, is pinned to zero too. (Not through flow or mixing, nor a concentrated material's
|
|
747
|
+
cross-diffusion, where zero flux isn't a flat level.) Species that react only among themselves
|
|
748
|
+
are held flat the same way where each reaches the same one contact and nothing else, their
|
|
749
|
+
reactions balanced at its levels: one reservoir drives nothing, so in a steady state they're at
|
|
750
|
+
equilibrium. A MOS capacitor's electrons and the holes they recombine with reach only its back
|
|
751
|
+
contact; moved, slow generation through a bulk of GaAs with ~1e-4 electrons per cm³ couldn't
|
|
752
|
+
carry the inversion layer's level with it (of 500 random MOS capacitors, 38 failed and 5
|
|
753
|
+
converged to a gate charge up to 2× off).
|
|
754
|
+
- **An island's balance.** A piece of a stretch between its faces that nothing else feeds (no
|
|
755
|
+
contact, port or reaction) holds its level only through its faces' fluxes, which can be far
|
|
756
|
+
weaker than its own conduction: a face conductance of 1e-15 S/m² against a region conducting
|
|
757
|
+
~4e2 S/m, or neighbours that conduct 1e20 times less than it. Eliminated, the level was lost to
|
|
758
|
+
round-off below anything Newton could see (the plain solves gave no update along it, so nothing
|
|
759
|
+
stalled), and solves converged to a wrong one silently: currents 2× or 16× off. Summed over the
|
|
760
|
+
piece's nodes, its balance rows are its faces' flux unknowns alone, $`A_R u_R - A_L u_L`$: the
|
|
761
|
+
internal fluxes cancel exactly, by construction rather than in round-off. Across a face that
|
|
762
|
+
holds $`\bar\mu`$ level, $`u`$ is set only by the edge balances, and eliminated it can come out
|
|
763
|
+
of the piece's own, as $`G\,\Delta\eta`$ with its two $`\eta`$ all but equal; so there the
|
|
764
|
+
outside edge node's balance is added too, $`u`$ cancels, and the outside's first segment
|
|
765
|
+
carries the flux. (Seen through one face of two, a level behind neighbours 1e20 times less
|
|
766
|
+
conductive was overshot twofold, and Newton swung it from one contact's level to the other's.)
|
|
767
|
+
That sum replaces the first node's row, bordered like an amount. The response to the unit pin
|
|
768
|
+
is the island's uniform shift, with whatever $`\hat\phi`$ and the other species do along with
|
|
769
|
+
it, so no mode needs guessing; refined solves carry the pinned rows too.
|
|
713
770
|
|
|
714
771
|
Newton exact along such a level can be worse than Newton blind to it, far from the solution
|
|
715
772
|
(cold at bias, a bipolar stack's floating base took 1e5 thermal units in its first update), so
|
|
@@ -723,45 +780,66 @@ only resolved to ~1e-4 of $`|Z|`$.
|
|
|
723
780
|
minority carriers, whose own rows rest on static pivots, at 1e-17 A/m² of noise), the plain
|
|
724
781
|
solution stands; and a steady solve that fails outright is tried once more with the summed rows
|
|
725
782
|
in from the start. Such devices now solve directly, their currents right to ~1e-15.
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
783
|
+
|
|
784
|
+
All three move a weakly held level as a whole, where a factorisation can't: an amount's or an
|
|
785
|
+
island's pin by a shift it solves for, a flat level by holding every node to one. What the
|
|
786
|
+
factorisation still loses elsewhere, Newton's refined solves recover ([Newton](#newton)).
|
|
787
|
+
|
|
788
|
+
### Reaching it
|
|
789
|
+
|
|
790
|
+
A solve that fails falls back stage by stage:
|
|
791
|
+
|
|
792
|
+
1. **Newton from here.** If it diverges, it's retried once with tighter damping (3 thermal units
|
|
793
|
+
per iteration), enough for most large jumps, such as a cold start at forward bias. Where no
|
|
794
|
+
continuation applies, the first stage goes straight on into the pseudo-transient ramp (3).
|
|
795
|
+
Where the state is a transient's, it can be a worse start than a cold one (a nanosecond after
|
|
796
|
+
a lit MOS capacitor's gate jumps, its surface is in deep depletion, minority carriers ten
|
|
797
|
+
orders below where they end): if Newton fails from there, the solve goes on as a cold device
|
|
798
|
+
would, from the layout for the drives, keeping what it took from the state (its amounts and
|
|
799
|
+
charges). Nor does a continuation start from the last steady solve's voltages once a
|
|
800
|
+
transient has moved the state.
|
|
801
|
+
2. **Continuation from a solved state, along the drives,** each step a steady solve warm from
|
|
802
|
+
the last:
|
|
803
|
+
- **The light.** A device with generation reactions (species made only from, or turned only
|
|
804
|
+
into, fixed reservoirs, such as photogeneration from a photon reservoir) can be held far
|
|
805
|
+
from equilibrium even with its terminals level, where a voltage ramp can't help; nor can a
|
|
806
|
+
time step, since light flooding minority carriers 20 orders below their lit level makes even
|
|
807
|
+
a step of 1e-16 s a jump Newton can't take. The generation rates are scaled down to 10⁻³⁰ and
|
|
808
|
+
ramped back up, ×100 a step while each solve converges and by the square root of the factor
|
|
809
|
+
when one doesn't, giving up when that factor falls below 1.5 (crawling, which time steps do
|
|
810
|
+
better); the pseudo-transient ramp then starts from the dimmer light's solution rather than
|
|
811
|
+
cold. (At 10⁻¹², a GaAs layer's generation still exceeded its equilibrium recombination,
|
|
812
|
+
~3e-24 mol/m³ of minority electrons, a billionfold: the first step was the whole jump.) An
|
|
813
|
+
illuminated 80 µm silicon diode solves cold this way in about 80 iterations. (A lit n⁺pn
|
|
814
|
+
stack with a floating base crawled for 20,000 iterations: at a trillionth of the light, the
|
|
815
|
+
base's level is held by couplings of ~1e-17.)
|
|
816
|
+
- **A current.** A cold steady solve at open circuit can fail where the same state is easy
|
|
817
|
+
warm (a solar cell in dim light on a fine grid). The terminal is held at a voltage instead,
|
|
818
|
+
its steady solves having their own continuation, and the voltage marched from the start's,
|
|
819
|
+
the step growing, until the current crosses its target: up where the current is below it,
|
|
820
|
+
since raising a terminal's voltage raises the current into a passive device (the other way
|
|
821
|
+
if 20 V brings no crossing). Bisection narrows the crossing to 0.1 mV, and the terminal is
|
|
822
|
+
floated from beside it. Floated, the system can lose what held it doesn't (a closed
|
|
823
|
+
Fe³⁺/Fe²⁺ cell driven near its limit, Fe³⁺ 20 orders below Fe²⁺: 33 digits short), but the
|
|
824
|
+
current-driven steady state is the held one at the voltage that passes the target, so where
|
|
825
|
+
the floated solve fails, held solves find that voltage instead, by regula falsi within the
|
|
826
|
+
bracket, to 1e-10 of the current. (Not a terminal at no current that keeps an amount or a
|
|
827
|
+
charge: every voltage passes nothing there.)
|
|
828
|
+
- **The voltages.** The right terminal's voltage ramped to its target: from the contacts'
|
|
829
|
+
voltages at the last converged solve when the state is that solution (the left one first,
|
|
830
|
+
where it moved), and otherwise from level terminals, where a cold start is consistent. (A
|
|
831
|
+
device first solved after a `set()` was laid out for its new voltages; if the level start
|
|
832
|
+
fails from there, it's laid out again, level, and retried.) The step starts at 1/8 of the
|
|
833
|
+
way, grows ×1.5 on success and shrinks ×4 on failure. The ramp's own start, with the
|
|
834
|
+
terminals level, ramps the light up when there is some.
|
|
835
|
+
3. **The pseudo-transient ramp.** $`dt`$ ramps up from a small value, through time, ending in
|
|
836
|
+
the direct solve. After a failed step it grows ×2, then ×1.5 more each success, back to ×10.
|
|
837
|
+
Once steps reach the slowest diffusion time, the direct solve is tried from there, once a
|
|
838
|
+
decade of $`dt`$ (the state kept if it fails): with immobile traps and ions of D = 1e-17 m²/s,
|
|
839
|
+
steps from 1e8 to 1e9 s kept failing on the way to the end.
|
|
840
|
+
|
|
841
|
+
Each of these carries cases that nothing else does (switched off one at a time, each fails
|
|
842
|
+
tests or stress cases the others pass).
|
|
765
843
|
|
|
766
844
|
## Conservation
|
|
767
845
|
|
|
@@ -771,7 +849,8 @@ only resolved to ~1e-4 of $`|Z|`$.
|
|
|
771
849
|
charge to round-off.
|
|
772
850
|
- **The iterate conserves to Newton's tolerance.** Storage is nonlinear in $`\eta`$, so each step's
|
|
773
851
|
drift is its summed residual. Converging to 1e-10 in $`\eta`$ makes that ~1e-15 per step in
|
|
774
|
-
practice
|
|
852
|
+
practice; but over steps of 1e10 s, the residual times $`dt`$ adds up, which is why a terminal
|
|
853
|
+
at no current reads its current there by what it keeps ([terminals](#terminals)).
|
|
775
854
|
- **Reported.** Every solution's `conservation` lists each species stretch: its amount, its
|
|
776
855
|
reference, the time-integrated flux through its contacts, and the resulting drift.
|
|
777
856
|
|
package/docs/reliability.md
CHANGED
|
@@ -64,7 +64,7 @@ recipes.
|
|
|
64
64
|
| Cell membrane (a capacitive face with permeabilities) | GHK resting potential (neutral or resolved solutions) and current–voltage curve; the same as a resolved 5 nm lipid layer; charging at I/C; with the Na⁺/K⁺ pump in a closed cell, Mullins–Noda, the static head 3Δμ̄_Na − 2Δμ̄_K = ΔG_ATP, and Donnan with the pump off | 1e-5 V; 3e-3; 2e-5 V; 1%; 1e-9 |
|
|
65
65
|
| Voltage-gated channels (Hodgkin–Huxley gates on a membrane face) | each gate at α/(α + β) under a voltage clamp, and relaxing at α + β after a step; HH's voltage clamp with their linear channels between baths, the K⁺ current g_K n∞⁴ (V − E_K); a squid axon's action potential against the space-clamped HH equations with GHK currents; its impedance at rest (inductive, resonant) against the linearised equations | 1e-12; 2e-4; 2e-3; 1 mV; 5e-4 |
|
|
66
66
|
| A propagating action potential (a squid axon along x: gated membrane port, ions drifting in the axoplasm) | rest at HH's −65 mV and gate values; conduction velocity against the cable equation solved directly, and HH's 18.8 m/s; a myelinated axon's saltatory conduction, node by node, against a compartmental cable | 0.01 mV, 1e-4; 2e-3; 1%; 1 µs of ~25 per node |
|
|
67
|
-
| Liquid junctions in mixtures | Henderson's formula against JPCalc's published values; driftlet's steady junction against Planck by shooting and the stationary Nernst–Planck codes LJPcalc and JLJP, a patch pipette's K-gluconate among them; a free-diffusion junction constant in time, between the two | 0.015 mV; 2e-4 and 0.02 mV; 5e-3 mV |
|
|
67
|
+
| Liquid junctions in mixtures | Henderson's formula against JPCalc's published values; driftlet's steady junction against Planck by shooting and the stationary Nernst–Planck codes LJPcalc and JLJP, a patch pipette's K-gluconate among them; a free-diffusion junction constant in time, between the two for the mixtures tested | 0.015 mV; 2e-4 and 0.02 mV; 5e-3 mV |
|
|
68
68
|
| Liquid junction, open circuit | cell EMF 2t₊(RT/F) ln(c₁/c₂); Planck diffusion potential | 1e-4 |
|
|
69
69
|
| Salt diffusion mode from a `c0` profile | c̄ + a·sin(πx/2L) decaying at π²D/4L², D = 2D₊D₋/(D₊ + D₋) | 2e-5 |
|
|
70
70
|
| Concentration polarization | `i = i_lim tanh(V/4V_T)`, incl. galvanostatic and load modes | 2e-4 |
|
|
@@ -84,7 +84,7 @@ recipes.
|
|
|
84
84
|
| Electrodes spread through a port | transmission line with the reaction's linear kinetics as the conductance (O(h²)), rates along it; Wagner–Traud mixed potential of two Butler–Volmer couples, floating | 1e-4, 2e-3; 1e-6 V |
|
|
85
85
|
| Impedance | Macdonald blocking-electrode spectrum, 100 Hz–1 GHz; finite-length Warburg (Ag \| AgNO₃ \| Ag); DC limit = differential resistance; a p⁺n⁺ junction without recombination, Re Y → dI/dV and C = dQ/dV; a redox electrode against a bath at its open circuit, Re Y → dI/dV; a MOS capacitor with a metal gate and a channel port, C = dQ/dV at the gate, passive at the back | 3e-4; 3e-5; 1e-6; 1e-4, 1e-6; 1e-4; 1e-3 |
|
|
86
86
|
| Conservation | per step, and against time-integrated contact fluxes | 1e-11 relative |
|
|
87
|
-
| Strictly neutral limit (ε = 0) | Planck EMF; polarization with no overlimiting; Donnan at neutral faces | 1e-5; 1e-4; 1e-9 |
|
|
87
|
+
| Strictly neutral limit (ε = 0) | Planck EMF; polarization with no overlimiting; Donnan at neutral faces; an ion exchanger between baths (Donnan at the contacts, Teorell–Meyer–Sievers salt flux); a capacitive face's edge cell as a diffuse layer in series | 1e-5; 1e-4; 1e-9; 1e-9, 1e-6; 2e-3 |
|
|
88
88
|
| Fermi–Dirac statistics | `𝓕_{±1/2}` vs quadrature; degenerate bulk; accumulation charge via `𝓕_{3/2}` | 1e-13; 1e-12; 1e-3 |
|
|
89
89
|
| Crowded double layer (lattice gas) | Kilic–Bazant–Ajdari charge, up to `ψ = 40 V_T`; custom function reproduces it | 5e-4; 1e-10 |
|
|
90
90
|
| Non-ideal transport | steady flux −(D/L)ΔP of the grand potential (lattice exact, Redlich–Kister O(h²)) | 1e-12; 1e-4 |
|
|
@@ -108,26 +108,29 @@ devices in five families:
|
|
|
108
108
|
|
|
109
109
|
Each device goes through what a user would do with it: a cold solve at no bias, and one at a
|
|
110
110
|
bias; a warm sweep to that bias; open circuit, where it's lit; a current drive (a fraction of
|
|
111
|
-
what passes at 1 V); a
|
|
112
|
-
|
|
111
|
+
what passes at 1 V); a MOS capacitor's back contact moved under its biased gate; a transient
|
|
112
|
+
after a voltage step; and the impedance about equilibrium, from far below its slowest relaxation
|
|
113
|
+
to 1 GHz. Every result is judged by `check()`, and by what must hold whatever the device:
|
|
113
114
|
levels flat at equilibrium with no current, warm and cold solves agreeing, the current driven
|
|
114
115
|
being the one passed, the impedance passive (to 1e-3 of |Z|) and, at low frequency, equal to
|
|
115
|
-
the steady dI/dV,
|
|
116
|
-
|
|
116
|
+
the steady dI/dV, a MOS capacitance never above its oxide's, and its gate charge with the back
|
|
117
|
+
contact moved what it is with the gate moved the other way. Each case is seeded from its family and index, so
|
|
117
118
|
any failure reruns alone (`npm run stress -- semi 79`).
|
|
118
119
|
|
|
119
|
-
At 500 devices per family (about three minutes on a desktop), 11,
|
|
120
|
+
At 500 devices per family (about three minutes on a desktop), 11,880 of 11,881 scenarios pass:
|
|
120
121
|
|
|
121
|
-
| Family | Cold at 0 V | Cold at bias | Warm sweep | Open circuit or
|
|
122
|
+
| Family | Cold at 0 V | Cold at bias | Warm sweep | Open circuit, current or back contact | Transient | Impedance |
|
|
122
123
|
|---|---|---|---|---|---|---|
|
|
123
124
|
| Semiconductor stacks | 500/500 | 500/500 | 500/500 | 105/105 | 500/500 | 395/395 |
|
|
124
|
-
| MOS capacitors | 500/500 | 500/500 | 500/500 | | 500/500 | 500/500 |
|
|
125
|
+
| MOS capacitors | 500/500 | 500/500 | 500/500 | 500/500 | 500/500 | 500/500 |
|
|
125
126
|
| Electrolyte cells | 500/500 | 500/500 | 500/500 | | 500/500 | 381/381 |
|
|
126
127
|
| Electrodes | 500/500 | 500/500 | 500/500 | 500/500 | 500/500 | 500/500 |
|
|
127
128
|
| Liquid junctions | | | | 500/500 | 499/500 | |
|
|
128
129
|
|
|
129
130
|
(Impedance only where the device has an equilibrium to linearise about; open circuit only for
|
|
130
|
-
lit cells.) The
|
|
131
|
+
lit cells.) The MOS back contact came last: before steady solves held a group of reacting
|
|
132
|
+
carriers flat where it reaches one contact alone, 43 of the 500 failed it, 5 of them silently
|
|
133
|
+
(a gate charge up to 2× off). The one that fails is among the known limits below: a junction on a grid far too
|
|
131
134
|
coarse for its double layers.
|
|
132
135
|
`bench/stress.json` keeps the summary.
|
|
133
136
|
|
|
@@ -169,6 +172,9 @@ so a change that makes one worse shows.
|
|
|
169
172
|
- **A surface covered to a bare fraction below ~1e-10** barely affects anything any more, and
|
|
170
173
|
the solver struggles with it (the hard corpus's passivating drop without a double layer stops
|
|
171
174
|
partway through its hour); the solution warns, and suggests a less stable film.
|
|
175
|
+
- **A double layer across more than ~350 thermal voltages** (between 9 and 9.25 V at 25 °C, in a
|
|
176
|
+
crowded lattice-gas electrolyte) doesn't solve, from a cold start or warm, and its warning
|
|
177
|
+
doesn't say why. Ionic-liquid windows (a few volts) are well inside it.
|
|
172
178
|
- **Currents below ~0.1 nA/m²** (a GaAs junction's leakage without recombination) aren't resolved
|
|
173
179
|
between solves; such a current is zero for any practical purpose.
|
|
174
180
|
- **A failed solve says so:** `converged: false`, with a warning naming where the system lost
|
package/docs/statistics.md
CHANGED
|
@@ -53,6 +53,8 @@ most one model.
|
|
|
53
53
|
|
|
54
54
|
### Fermi–Dirac
|
|
55
55
|
|
|
56
|
+
Where electrons or holes under ideal (Boltzmann) statistics exceed $`c_{\mathrm{ref}}`$, the effective
|
|
57
|
+
density of states, the solution warns: they're degenerate, and this is the statistics to give.
|
|
56
58
|
For electrons and holes, $`c_{\mathrm{ref}}`$ is the effective density of states and $`\mu^\circ`$ the
|
|
57
59
|
band edge, as for ideal statistics, and $`c = N_c \mathcal{F}_{1/2}(\zeta)`$ with the normalised
|
|
58
60
|
Fermi–Dirac integral ($`\mathcal{F}_j \to e^\zeta`$ for $`\zeta \to -\infty`$). driftlet evaluates
|
|
@@ -135,7 +137,20 @@ A flat plateau means phase separation, which isn't supported yet. The table is r
|
|
|
135
137
|
$`\zeta = \ln(x/(1-x)) + r(x)`$: the residual $`r`$, the host's non-ideality, is a shape-preserving
|
|
136
138
|
cubic between points and continues linearly beyond them. Ideal and regular-solution curves are
|
|
137
139
|
therefore reproduced exactly, and $`x`$ stays within $`(0, 1)`$ at any potential. The interpolated
|
|
138
|
-
curve is checked for monotonicity at construction.
|
|
140
|
+
curve is checked for monotonicity at construction. A curve far flatter than the ideal term near
|
|
141
|
+
an end (E falling by millivolts over the last few percent of x) can fail that check however
|
|
142
|
+
many points it has, since r then changes as steeply as the logarithm: give the ends some of the
|
|
143
|
+
ideal slope (adding −0.5 (RT/F) ln(x/(1−x)) there passes).
|
|
144
|
+
|
|
145
|
+
With `A` instead, the curve is the isotherm's, against a reference where the combination's
|
|
146
|
+
chemical potential is 0, with $`g`$ the excess chemical potential ($`\Omega(1-2x)`$ for `A: [Ω]`):
|
|
147
|
+
|
|
148
|
+
```math
|
|
149
|
+
E(x) = -\frac{\mu^\circ_{\mathrm{ion}} + \nu\mu^\circ_{\mathrm{carrier}} + RT\ln\frac{x}{1-x} + RT\ln\frac{c_{\mathrm{max}}}{c_{\mathrm{ref}}} + g(x) - g(0)}{zF}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
So an ideal host given `cRef` = `cMax`, the ion's `mu0` $`= -zFE^\circ`$ and the carrier's 0 sits at
|
|
153
|
+
$`E^\circ`$ half full.
|
|
139
154
|
|
|
140
155
|
Because every charged species sits in a neutral combination, **$`\phi`$ is undefined** in such a
|
|
141
156
|
host and is reported as `NaN`. Its faces must be `neutral` (the default next to such a host),
|
|
@@ -147,14 +162,23 @@ the ions. The carrier's `cRef` plays no part (only the combination's $`\mu^\circ
|
|
|
147
162
|
`cRef` enter), but it must still be given.
|
|
148
163
|
|
|
149
164
|
The ion's `D` is its dilute-limit coefficient, as everywhere: the chemical diffusivity, $`D`$
|
|
150
|
-
times the thermodynamic factor, follows from the OCV's slope
|
|
165
|
+
times the thermodynamic factor, follows from the OCV's slope (with the carrier far faster than
|
|
166
|
+
the ion, as usual; else the two combine as $`D_i D_e/(D_i + D_e)`$, ambipolar diffusion). For an ideal-solution curve,
|
|
151
167
|
$`E = E^\circ - (RT/F)\ln(x/(1-x))`$, it's $`D/(1-x)`$, so a host filling toward $`x = 1`$
|
|
152
168
|
diffuses ever faster, and a $`D`$ measured mid-range isn't the one to give. (A constant chemical
|
|
153
169
|
diffusivity isn't expressible.) A host that only stores what comes in, filling at a constant
|
|
154
|
-
current through its collector, has no steady state: `advance()` it from its `c0`.
|
|
170
|
+
current through its collector, has no steady state: `advance()` it from its `c0`. At no
|
|
171
|
+
current it has one per state of charge, and a steady solve keeps the charge it holds, so in a
|
|
172
|
+
titration (GITT) each rest's OCV is a `solve()` at `I: 0` after the pulse's `advance()`, with no
|
|
173
|
+
need to wait out the relaxation. What a pulse measures is the chemical diffusivity, and the
|
|
174
|
+
textbook estimate from it assumes a small pulse: over $`\Delta x \approx 0.1`$ it's off by up to
|
|
175
|
+
×7 near an end of the curve, against a host that has exactly the diffusivity it's given. In a sphere,
|
|
155
176
|
`geometry: { type: 'spherical', r0: 0 }`, with the centre sealed (`{ phi: 'neutral' }`, every
|
|
156
177
|
species blocked), the ion held at the surface by its reference and the electrons fed by a port
|
|
157
|
-
there (a current into the device: negative, to fill a cathode).
|
|
178
|
+
there (a current into the device: negative, to fill a cathode). A port's `conductance` link
|
|
179
|
+
adds its ohmic drop, about $`I/(G w)`$, to the voltage read, which is no part of the host: give it
|
|
180
|
+
a large $`G`$ (1e15 S/m³ over a window of 2% of the radius), and see that the voltage doesn't move
|
|
181
|
+
with it.
|
|
158
182
|
|
|
159
183
|
An insertion host belongs with [conductor regions](device.md#materials) more than with the other
|
|
160
184
|
statistics here. Both are conductors with no $`\phi`$ of their own:
|