driftlet 0.1.0 → 0.2.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 +31 -17
- package/docs/alignment.md +146 -0
- package/docs/conventions.md +194 -0
- package/docs/data.md +120 -0
- package/docs/device.md +529 -0
- package/docs/kit.md +299 -0
- package/docs/logo-dark.svg +7 -0
- package/docs/logo.svg +7 -0
- package/docs/numerics.md +629 -0
- package/docs/statistics.md +226 -0
- package/docs/visualization.md +259 -0
- package/llms.txt +66 -12
- package/package.json +2 -1
- package/src/constants.js +11 -0
- package/src/index.js +5 -2
- package/src/kit.js +1 -0
- package/src/solver.js +66 -7
- package/src/sources.js +103 -0
- package/src/types.js +3 -2
- package/types/constants.d.ts +10 -0
- package/types/index.d.ts +11 -2
- package/types/kit.d.ts +1 -0
- package/types/solver.d.ts +6 -0
- package/types/sources.d.ts +102 -0
- package/types/types.d.ts +4 -2
package/docs/numerics.md
ADDED
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
# Numerics
|
|
2
|
+
|
|
3
|
+
How driftlet turns the physics into equations and solves them. The guiding constraint: every
|
|
4
|
+
equation couples a node only to its neighbours, so the Jacobian is **block-tridiagonal** and
|
|
5
|
+
each Newton iteration is a single block-Thomas sweep. That constraint is what makes
|
|
6
|
+
interactive speeds possible, so non-local physics is out of scope.
|
|
7
|
+
|
|
8
|
+
## The equations
|
|
9
|
+
|
|
10
|
+
In one dimension, inside each region, every species $`i`$ present there obeys a balance, a flux
|
|
11
|
+
law and its material's statistics, and the electrostatic potential obeys Poisson's equation:
|
|
12
|
+
|
|
13
|
+
```math
|
|
14
|
+
\begin{aligned}
|
|
15
|
+
&\frac{\partial c_i}{\partial t} + \frac{\partial N_i}{\partial x} = \sum_r \nu_{ir}\, r_r
|
|
16
|
+
&& \quad\text{(conservation, with bulk reactions } r\text{)} \\
|
|
17
|
+
&N_i = -\frac{D_i c_i}{RT}\frac{\partial\bar\mu_i}{\partial x} + v\, c_i
|
|
18
|
+
- \frac{D_{\mathrm{mix}}}{RT}\Big(P\,\frac{\partial\bar\mu}{\partial x}\Big)_i
|
|
19
|
+
&& \quad\text{(drift and diffusion, advection, eddy mixing)} \\
|
|
20
|
+
&\bar\mu_i = \mu^\circ_i + z_i F\phi + RT\zeta_i, \qquad c_i = c_i(\zeta)
|
|
21
|
+
&& \quad\text{(the material's statistics)} \\
|
|
22
|
+
&-\frac{\partial}{\partial x}\Big(\varepsilon\frac{\partial\phi}{\partial x}\Big) = F\sum_i z_i c_i + \rho_{\mathrm{fixed}}
|
|
23
|
+
&& \quad\text{(Poisson)}
|
|
24
|
+
\end{aligned}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Each reaction runs at $`r = k_f \prod c^\nu\,(1 - e^{-A/RT})`$, its affinity $`A`$ from the reactants'
|
|
28
|
+
and products' $`\bar\mu`$. In a strictly neutral material ($`\varepsilon = 0`$) Poisson's equation becomes
|
|
29
|
+
the constraint $`F\sum_i z_i c_i + \rho_{\mathrm{fixed}} = 0`$. Some materials need less:
|
|
30
|
+
|
|
31
|
+
- A **conductor region** (a metal, a fast ion conductor) has only its carrier, with no storage in
|
|
32
|
+
its bulk: $`\partial J/\partial x = 0`$ with Ohm's law $`J = -\sigma\,\partial V/\partial x`$, and no $`\phi`$.
|
|
33
|
+
- An **insertion host** holds its ion and carrier as one neutral combination, so $`\phi`$ cancels
|
|
34
|
+
from everything there and is left undefined.
|
|
35
|
+
- A species absent from a material has no equations in it.
|
|
36
|
+
|
|
37
|
+
At each interface the laws are local to the face: per species, continuity of $`\bar\mu`$, a
|
|
38
|
+
conductance, a blocked face, or face reactions with their own rates; for $`\phi`$, an alignment
|
|
39
|
+
(dipole), neutrality or a Helmholtz capacitance, with the displacement continuous apart from any
|
|
40
|
+
sheet charge. Contacts and ports join the device to outside phases with known levels, and the
|
|
41
|
+
terminals to their circuits ([the device reference](device.md) has every option). The rest of
|
|
42
|
+
this page is how these become a block-tridiagonal Newton system.
|
|
43
|
+
|
|
44
|
+
## Unknowns
|
|
45
|
+
|
|
46
|
+
At a node of an ordinary region (a dielectric, a semiconductor, a resolved electrolyte), the
|
|
47
|
+
unknowns are:
|
|
48
|
+
|
|
49
|
+
- $`\hat\phi = F\phi/RT`$, the dimensionless (bookkeeping) electrostatic potential;
|
|
50
|
+
- $`\eta_i = \bar\mu_i/RT`$, the dimensionless electrochemical potential of each species present.
|
|
51
|
+
|
|
52
|
+
Each block holds only the unknowns that exist at its node, up to $`1 + (\text{number of species})`$.
|
|
53
|
+
A conductor region's nodes hold its carrier's $`\eta`$ and the flux through its single segment
|
|
54
|
+
([metal regions](#metal-regions)); an insertion host has no $`\phi`$ ([statistics](#statistics)), nor
|
|
55
|
+
does a charge-free region that nothing fixes it in (an oxide between silicon and a gate keeps its
|
|
56
|
+
$`\phi`$); a species absent from a material has no $`\eta`$ there; and each
|
|
57
|
+
interface adds a block of its own, for what crosses it ([interfaces](#interfaces-doubled-nodes-plus-a-flux-node)).
|
|
58
|
+
|
|
59
|
+
Concentrations follow from these through each material's statistics, $`c = c(\zeta)`$ with
|
|
60
|
+
$`\zeta_i = \eta_i - \mu^\circ_i/RT - z_i \hat\phi`$ (ideal: $`c_i = c_{\mathrm{ref},i} \cdot e^{\zeta_i}`$;
|
|
61
|
+
see [Statistics](#statistics) below). Working in $`\bar\mu`$ rather than $`c`$ is a deliberate
|
|
62
|
+
trade-off:
|
|
63
|
+
|
|
64
|
+
- **For $`\bar\mu`$:** concentrations are positive automatically, with no clamping (which would itself
|
|
65
|
+
break conservation). Equilibrium is exactly flat $`\bar\mu`$. Contacts, alignments, affinities and
|
|
66
|
+
Butler–Volmer are all natural in $`\bar\mu`$.
|
|
67
|
+
- **Against $`\bar\mu`$:**
|
|
68
|
+
- Storage is nonlinear in the unknowns, so conservation holds to Newton's tolerance rather
|
|
69
|
+
than trivially (see [Conservation](#conservation)).
|
|
70
|
+
- A species' equations scale with its own concentration, so where it's scarce (minority
|
|
71
|
+
carriers), its $`\bar\mu`$ is weakly determined and Newton can swing it wildly. Damping and time-step
|
|
72
|
+
control deal with that.
|
|
73
|
+
|
|
74
|
+
Concentration variables (the usual TCAD choice) would conserve every iteration exactly, but
|
|
75
|
+
their positivity fixes are fiddly or non-conservative. Slotboom variables $`\exp(\eta)`$ overflow at
|
|
76
|
+
modest voltages.
|
|
77
|
+
|
|
78
|
+
### Extra precision where it matters: compensated μ̄
|
|
79
|
+
|
|
80
|
+
A majority carrier carrying a small current needs a quasi-Fermi step between neighbouring nodes
|
|
81
|
+
far below the resolution of $`\eta`$ itself. For example, holes in 1e16 cm⁻³ p-silicon carrying a
|
|
82
|
+
µA/m² reverse current need $`\Delta\eta \approx`$ 3e-19 across a cell, while $`\eta \approx 20`$ has an
|
|
83
|
+
ulp of 3.5e-15. In plain doubles that current would come out as exactly zero. (Concentration variables
|
|
84
|
+
hit the same wall, as cancellation between huge drift and diffusion terms.)
|
|
85
|
+
|
|
86
|
+
So every unknown is stored as a compensated double-double, `u + uLo`:
|
|
87
|
+
|
|
88
|
+
- Only *differences* of unknowns use the low part:
|
|
89
|
+
$`\Delta\eta = (\mathrm{hi}_R - \mathrm{hi}_L) + (\mathrm{lo}_R - \mathrm{lo}_L)`$. Neighbouring
|
|
90
|
+
values are close, so $`\mathrm{hi}_R - \mathrm{hi}_L`$ is exact (Sterbenz), and $`\Delta\eta`$ is
|
|
91
|
+
recovered to ~1e-30 absolute.
|
|
92
|
+
- Updates use an error-free two-sum.
|
|
93
|
+
- The Jacobian and linear solve stay in plain doubles. Newton's fixed point is set by the
|
|
94
|
+
residual, not the Jacobian, so an inexact Jacobian only slows convergence. This is the
|
|
95
|
+
standard mixed-precision idea: residual in high precision, correction in low.
|
|
96
|
+
|
|
97
|
+
The cost is a few flops per unknown per iteration, lost in the noise. With it, left and right
|
|
98
|
+
contact currents agree to ~1e-10 down to µA/m² leakage; without it they disagreed by 3%.
|
|
99
|
+
|
|
100
|
+
## Grid and geometry
|
|
101
|
+
|
|
102
|
+
Nodes sit at positions $`x_k`$, and segments join consecutive nodes. Each node owns a box reaching
|
|
103
|
+
halfway to each neighbour (a vertex-centred finite volume, the "box method"):
|
|
104
|
+
$`\mathrm{vol}_k = (h_{k-1} + h_k)/2`$.
|
|
105
|
+
|
|
106
|
+
Every region boundary is a **doubled node**: two nodes at the same $`x`$, one per region, each
|
|
107
|
+
owning only a half-box on its own side. So no segment ever straddles a material step, and every
|
|
108
|
+
box is entirely one material.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
region A region B
|
|
112
|
+
o-------o------o----o--o-o-o|o-o-o--o----o------o-------o
|
|
113
|
+
^ doubled node: L and R at the same x
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Grids grade geometrically from `hmin` at each region end up to `hmax`. They're never refined
|
|
117
|
+
automatically, to avoid performance surprises. Instead, solutions warn when a double layer the
|
|
118
|
+
model is meant to resolve is coarser than the local Debye length.
|
|
119
|
+
|
|
120
|
+
### What lives where
|
|
121
|
+
|
|
122
|
+
| Place | Holds |
|
|
123
|
+
|---|---|
|
|
124
|
+
| **Node** (box centre) | the unknowns $`\hat\phi`$, $`\eta_i`$, and hence $`c_i`$. The node's region supplies $`\mu^\circ`$, $`c_{\mathrm{ref}}`$, presence and fixed charge. Everything volumetric, times the box volume: storage $`\mathrm{vol}\cdot(c - c_{\mathrm{old}})/dt`$, space charge $`\mathrm{vol}\cdot(F\sum z c + \rho_{\mathrm{fixed}})`$, bulk reaction rates $`\mathrm{vol}\cdot\nu\cdot r`$. One Poisson row and one balance row per species. |
|
|
125
|
+
| **Segment** (always within one material) | particle fluxes $`N_i`$ (Scharfetter–Gummel, with the segment's $`D`$) and displacement $`D = -\varepsilon\Delta\phi/h`$ (the segment's $`\varepsilon`$). Each is computed **once** and added with + to the left box and − to the right box, which is what makes conservation telescope exactly. |
|
|
126
|
+
| **Interface** (zero width) | a zero-volume **flux node** between the doubled nodes (below). Its unknowns are what crosses ($`D_f`$ and each $`N_{f,i}`$); its rows are the surface's laws. |
|
|
127
|
+
| **Contact** | conditions on the outer face of the end node's half-box (below). |
|
|
128
|
+
|
|
129
|
+
Output arrays are indexed by node, so each interface $`x`$ appears twice and steps plot as true
|
|
130
|
+
vertical lines. Nothing is averaged across a material step: no harmonic means of $`D`$ or $`\varepsilon`$
|
|
131
|
+
across an interface, because no segment crosses one.
|
|
132
|
+
|
|
133
|
+
## Fluxes
|
|
134
|
+
|
|
135
|
+
Within a segment (constant $`D`$, $`\mu^\circ`$, $`\varepsilon`$), the Scharfetter–Gummel flux is the exact
|
|
136
|
+
constant-flux solution for a linear potential:
|
|
137
|
+
|
|
138
|
+
```math
|
|
139
|
+
N = \frac{D}{h} \left[ B(\Delta)\, c_L - B(-\Delta)\, c_R \right], \quad \Delta = z (\hat\phi_R - \hat\phi_L), \quad B(x) = \frac{x}{e^x - 1}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
It's evaluated in an algebraically identical, better-conditioned form. Using
|
|
143
|
+
$`B(-\Delta) = B(\Delta)e^\Delta`$ and $`c_R e^\Delta = c_L e^{\Delta\eta}`$:
|
|
144
|
+
|
|
145
|
+
```math
|
|
146
|
+
N = -\frac{D}{h} \cdot B(\Delta) \cdot c_L \cdot \mathrm{expm1}(\eta_R - \eta_L)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This is exactly zero at equilibrium (flat $`\bar\mu`$), and it's precise relative to the quasi-Fermi
|
|
150
|
+
difference instead of being a cancellation of two large terms. $`B`$ and $`B'`$ are evaluated from a
|
|
151
|
+
Taylor series near 0 and with `expm1` elsewhere, finite for all arguments.
|
|
152
|
+
|
|
153
|
+
**Advection** at velocity $`v`$ adds to the drift: in the segment's Scharfetter–Gummel flux, the
|
|
154
|
+
potential and the quasi-Fermi difference are both shifted by the cell Péclet number
|
|
155
|
+
$`\mathrm{Pe} = v h/D`$, $`\Delta \to \Delta - \mathrm{Pe}`$, $`\Delta\eta \to \Delta\eta - \mathrm{Pe}`$.
|
|
156
|
+
That's the exact constant-flux solution of $`N = v c - D(c' + c \psi')`$ across the cell, so pure
|
|
157
|
+
convection–diffusion is exact on any grid, upwinding itself automatically at large $`\mathrm{Pe}`$.
|
|
158
|
+
|
|
159
|
+
**Eddy mixing** is discretised on each segment as
|
|
160
|
+
$`N_i = -(D_{\mathrm{mix}}/h) \sum_j \bar P_{ij} \Delta\eta_j`$, where $`\bar P`$ is built from the
|
|
161
|
+
logarithmic mean of each concentration across the segment. The logarithmic mean makes a neutral
|
|
162
|
+
species' mixing flux exactly $`-D_{\mathrm{mix}} \Delta c/h`$. The flux is exactly zero at
|
|
163
|
+
equilibrium, and exactly current-free ($`z^\mathsf{T}\bar P = 0`$ for any $`\bar P`$ built this way). Its
|
|
164
|
+
full Jacobian, including the dependence of $`\bar P`$ on both ends, keeps Newton quadratic.
|
|
165
|
+
|
|
166
|
+
With non-ideal statistics, $`\ln c = \zeta - \mathrm{ex}`$, where the excess
|
|
167
|
+
$`\mathrm{ex} = \zeta - \ln(c/c_{\mathrm{ref}})`$ is zero for ideal statistics. The excess enters
|
|
168
|
+
exactly like an extra potential, taken linear along the segment as $`\phi`$ is, so the same formula
|
|
169
|
+
holds with $`\Delta = z(\hat\phi_R - \hat\phi_L) + \mathrm{ex}_R - \mathrm{ex}_L`$. That's the
|
|
170
|
+
excess-chemical-potential generalisation of Scharfetter–Gummel: still exactly zero at
|
|
171
|
+
equilibrium, since the expm1 factor is untouched. It's exact for a single diffusing species on
|
|
172
|
+
a lattice (whose excess is proportional to its grand potential, linear in $`x`$ at steady state)
|
|
173
|
+
and second order otherwise. Its Jacobian couples each flux to every species at both nodes through
|
|
174
|
+
$`K`$, which fills the blocks but keeps them tridiagonal.
|
|
175
|
+
|
|
176
|
+
## Interfaces: doubled nodes plus a flux node
|
|
177
|
+
|
|
178
|
+
In the linear system, a zero-volume flux node sits between the two sides' nodes:
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
… [node L] — [flux node f] — [node R] …
|
|
182
|
+
φ̂_L, η_L D_f, N_f,i φ̂_R, η_R
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Node L's balance rows treat $`D_f`$ and $`N_{f,i}`$ as outflow, and node R's treat them as inflow. The
|
|
186
|
+
flux node's own rows are the interface laws:
|
|
187
|
+
|
|
188
|
+
| Law | Row |
|
|
189
|
+
|---|---|
|
|
190
|
+
| $`\phi`$, `pinned` | $`\hat\phi_R - \hat\phi_L = \mathtt{dipole}/V_T`$ |
|
|
191
|
+
| $`\phi`$, `neutral` | $`D_f = 0`$ |
|
|
192
|
+
| $`\phi`$, `capacitive` | $`D_f + C \cdot V_T \cdot (\hat\phi_R - \hat\phi_L - \mathtt{dipole}/V_T) = 0`$ |
|
|
193
|
+
| species, equilibrium | $`\eta_R - \eta_L = 0`$ |
|
|
194
|
+
| species, blocked or absent on one side | $`N_f = 0`$ |
|
|
195
|
+
| species, conductance | $`N_f - G V_T (\eta_L - \eta_R)/(z^2 F) = 0`$ |
|
|
196
|
+
| face reaction $`k`$ | $`r_k - \mathrm{rate}_k(\mathrm{state}_L, \mathrm{state}_R) = 0`$, and each participant's edge node takes $`\nu \cdot r_k`$ |
|
|
197
|
+
|
|
198
|
+
Every row couples only neighbours, with no penalty terms. A face reaction's rate is an unknown
|
|
199
|
+
of the face block, so the two edge nodes it couples meet only through the block between them.
|
|
200
|
+
A species can take part in a reaction at a face and also cross it by a link (its flux slot)
|
|
201
|
+
at the same time; where it exists on both sides, that link must be given explicitly. A continuity
|
|
202
|
+
row has a zero diagonal block, but block Thomas still sees a non-singular block there once the
|
|
203
|
+
preceding elimination has run. Interface fluxes come out as unknowns, which is what the
|
|
204
|
+
solution reports per interface.
|
|
205
|
+
|
|
206
|
+
(An earlier design kept only the doubled nodes and put the flux in the right node's slot, with
|
|
207
|
+
the value read from the left node. That breaks tridiagonality, because the right node's other
|
|
208
|
+
segment then reaches two nodes back.)
|
|
209
|
+
|
|
210
|
+
A **sheet charge** at a face is booked in node R's Poisson row. With a `pinned` law that's
|
|
211
|
+
immaterial: the jump is fixed either way, and only the reported $`D_f`$ shifts by $`\sigma`$. With a
|
|
212
|
+
capacitive law it would matter, since the charge then sits on one plate or the other.
|
|
213
|
+
|
|
214
|
+
## Contacts
|
|
215
|
+
|
|
216
|
+
The end node's balance rows are complete except for the flux through the outer face. So
|
|
217
|
+
**before** a row is replaced by a contact condition, its residual *is* that flux (or
|
|
218
|
+
displacement). Contact fluxes and terminal currents are recovered exactly this way, with no
|
|
219
|
+
extra unknowns. Then:
|
|
220
|
+
|
|
221
|
+
- **Species in equilibrium with the outside phase:** the balance row becomes the Dirichlet row
|
|
222
|
+
$`\eta = \mathtt{target}`$ (the known outside level).
|
|
223
|
+
- **$`\phi`$ `bulk`:** the Poisson row becomes local neutrality (total charge, mobile plus fixed, is
|
|
224
|
+
zero). The recorded residual is the outside's surface charge.
|
|
225
|
+
- **$`\phi`$ `pinned`:** the Poisson row becomes the Dirichlet row
|
|
226
|
+
$`\phi_{\mathrm{edge}} = V - \mathtt{zeroCharge}`$, again with the residual recorded as the outside's
|
|
227
|
+
charge.
|
|
228
|
+
- **$`\phi`$ `capacitive`:** a term $`C \cdot ((V - \mathtt{zeroCharge}) - \phi_{\mathrm{edge}})`$ joins the
|
|
229
|
+
Poisson row.
|
|
230
|
+
- **$`\phi`$ `neutral`:** nothing is added ($`D = 0`$ at the face).
|
|
231
|
+
- **Conductance links** add their fluxes to the balance rows. (Contacts carry no reactions:
|
|
232
|
+
an electrode is a conductor region with reactions at its face.)
|
|
233
|
+
|
|
234
|
+
A left-end "contact flux node" would have a singular first block for block Thomas, which is why
|
|
235
|
+
contact fluxes are read from residuals instead. After each step these readouts (contact and port
|
|
236
|
+
fluxes, contact displacements, the last segment's current) are evaluated at the converged state
|
|
237
|
+
from only the boxes they come from, the two end nodes and the port windows with the segments and
|
|
238
|
+
faces that touch them, in the same order as a full assembly, so they're identical to one.
|
|
239
|
+
|
|
240
|
+
### Terminals
|
|
241
|
+
|
|
242
|
+
Every terminal (a contact, or a port) has a voltage $`V`$, held by its source or floating, and a
|
|
243
|
+
current into the device, $`I`$. Assembly records, for each:
|
|
244
|
+
- **$`B = \partial\,\mathrm{res}/\partial V`$**, a column: where its outside levels enter (Dirichlet
|
|
245
|
+
rows, conductance links, a gate's or pinned $`\phi`$ law);
|
|
246
|
+
- **$`I`$ and $`C = \partial I/\partial x`$**, a row. A contact's current is read from its end box
|
|
247
|
+
before the contact's own terms go in: the box's balance residuals are what must come through
|
|
248
|
+
the contact (as for the flux readouts), plus the displacement through its $`\phi`$ law,
|
|
249
|
+
$`(D_{\mathrm{in}} - D_{\mathrm{in},0})/dt`$. A port's is its sources over its window, with a held
|
|
250
|
+
level's read from the row it replaces.
|
|
251
|
+
|
|
252
|
+
A floating terminal's voltage is an extra unknown, with its circuit law as an extra row:
|
|
253
|
+
$`I - I_{\mathrm{set}} = 0`$ (driven by a current) or $`I - (V_{\mathrm{src}} - V)/R = 0`$ (behind a
|
|
254
|
+
resistance). These don't fit the block-tridiagonal matrix $`T`$ (a port couples to its whole
|
|
255
|
+
window), so they're solved by bordering, together with the spectators' conservation rows (see
|
|
256
|
+
[steady state](#steady-state)): with $`y = T^{-1}\,\mathrm{rhs}`$, $`X_k = T^{-1} B_k`$ and
|
|
257
|
+
$`Q_q = T^{-1} e_q`$ (the response to a unit pin), the update is
|
|
258
|
+
$`\delta = y + \sum Q_q \mu_q - \sum X_k\, \delta V_k`$, and the $`\mu`$ (pins) and $`\delta V`$ (terminals)
|
|
259
|
+
come from a small dense system of the extra rows. Each costs one more back-substitution per
|
|
260
|
+
Newton iteration.
|
|
261
|
+
|
|
262
|
+
Sources are read at the end of a step (implicit), or at the present time in a steady solve.
|
|
263
|
+
`advance()` lands on every waveform breakpoint and restarts its order there.
|
|
264
|
+
|
|
265
|
+
## Statistics
|
|
266
|
+
|
|
267
|
+
Each node evaluates its material's statistics once per Newton iteration: $`c(\zeta)`$, the Jacobian
|
|
268
|
+
$`K = \partial c/\partial\zeta`$ ($`n \times n`$, symmetric positive definite), and the excess. Every
|
|
269
|
+
$`c`$-dependent term then differentiates through $`K`$:
|
|
270
|
+
|
|
271
|
+
- storage and space charge: $`\partial c_i/\partial\eta_j = K_{ij}`$,
|
|
272
|
+
$`\partial c_i/\partial\hat\phi = -(Kz)_i`$;
|
|
273
|
+
- reaction prefactors: $`\partial \ln c_i/\partial\eta_j = K_{ij}/c_i`$;
|
|
274
|
+
- the $`\phi`$ row's response, and the Debye length in resolution warnings, use $`z^\mathsf{T} K z`$, the
|
|
275
|
+
charge capacitance, in place of $`\sum z^2 c`$.
|
|
276
|
+
|
|
277
|
+
Nodes of ideal materials keep a separate fast path with $`K = \mathrm{diag}(c)`$ implied.
|
|
278
|
+
|
|
279
|
+
Model evaluation:
|
|
280
|
+
|
|
281
|
+
- **Explicit models** (Fermi–Dirac, lattice gas, insertion) evaluate $`c(\zeta)`$ in closed form.
|
|
282
|
+
- **Implicit models** solve a small problem per node: Redlich–Kister and tabulated OCVs by
|
|
283
|
+
safeguarded Newton in $`\mathrm{logit}(x)`$; Debye–Hückel by Newton in $`\ln c`$, whose excess
|
|
284
|
+
Hessian is rank one, so each step is a Sherman–Morrison update.
|
|
285
|
+
- **Fermi–Dirac integrals** $`\mathcal{F}_{1/2}`$ and $`\mathcal{F}_{-1/2}`$ use:
|
|
286
|
+
- an alternating series below $`x = -2`$;
|
|
287
|
+
- Sommerfeld's expansion above 50;
|
|
288
|
+
- piecewise Chebyshev fits (degree 23, five intervals) in between, built on first use
|
|
289
|
+
(~4 ms) from a trapezoid quadrature in $`u = \sqrt{t}`$.
|
|
290
|
+
|
|
291
|
+
Relative error is ~6e-15.
|
|
292
|
+
|
|
293
|
+
Where a *concentration* is prescribed rather than a potential (bath compositions, spectators'
|
|
294
|
+
initial amounts), each model inverts itself for the $`\zeta`$ of those species, holding the others.
|
|
295
|
+
The lattice gas does this in closed form, and the others with the same scalar or small Newton
|
|
296
|
+
iterations.
|
|
297
|
+
|
|
298
|
+
An insertion host's species depend on $`\phi`$ only through their neutral combination, where it
|
|
299
|
+
cancels, so its $`\phi`$ rows are identity rows ($`\phi`$ undefined, like a region with no charged
|
|
300
|
+
species). The current-continuity constraint between ion and carrier comes from their balance rows.
|
|
301
|
+
|
|
302
|
+
## Metal regions
|
|
303
|
+
|
|
304
|
+
A metal node's only unknown is the carrier's $`\eta`$, its Fermi level. Its $`\phi`$ slot is free, and
|
|
305
|
+
it carries the carrier flux $`J`$ through the segment to the node's right instead. Each metal
|
|
306
|
+
segment then has two rows:
|
|
307
|
+
|
|
308
|
+
```math
|
|
309
|
+
\begin{aligned}
|
|
310
|
+
&\eta_R - \eta_L + J/g = 0 && \quad\text{(Ohm's law, } g = \sigma RT/(z^2F^2h)\text{)} \\
|
|
311
|
+
&\dots + J\ (\text{out of } L),\ -J\ (\text{into } R) && \quad\text{in the carrier balances}
|
|
312
|
+
\end{aligned}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
This mixed form matters. A floating metal, held only by weak conductances $`G`$ such as its
|
|
316
|
+
electrode reactions, has its overall level set by $`G`$ alone, while every entry of an $`\eta`$-only
|
|
317
|
+
Jacobian is of order $`g`$. Eliminating it then computes the last pivot as $`g - g^2/(g + G) \approx G`$
|
|
318
|
+
with an absolute error of order $`\varepsilon \cdot g`$: digits are lost in proportion to $`g/G`$, and
|
|
319
|
+
beyond $`g/G \approx`$ 1e15 the pivot is noise or zero. ($`G`$ is already lost when the diagonal
|
|
320
|
+
$`g + G`$ is stored.) In mixed form the matrix holds $`1/g`$ instead, every coefficient is O(1), and
|
|
321
|
+
the limit $`\sigma \to \infty`$ is simply the constraint $`\eta_R = \eta_L`$. A
|
|
322
|
+
Grassmann–Taksar–Heyman-style elimination, which carries each row's leakage separately so that
|
|
323
|
+
pivots are built as sums, would also keep $`\eta`$ alone exact, but it needs to know which rows form
|
|
324
|
+
a conductance network.
|
|
325
|
+
|
|
326
|
+
A metal region is a single cell. Nothing is stored in its bulk, so $`\eta`$ is linear across it in
|
|
327
|
+
transients too, and one segment is exact. That also keeps $`g = \sigma RT/(z^2F^2L)`$ as small as the
|
|
328
|
+
region allows.
|
|
329
|
+
|
|
330
|
+
A metal's bulk holds no charge. Its surface charge at a capacitive face is the face's
|
|
331
|
+
displacement, booked as a sheet of excess carriers in the edge node's half-box. That gives the
|
|
332
|
+
edge node a storage term in $`D_f`$ (the neighbouring block), so transients, conservation and
|
|
333
|
+
impedance all see the charging current. A `pinned` law isn't offered at a metal face.
|
|
334
|
+
With nothing on the metal side depending on $`D_f`$, the steady system's flux block would be
|
|
335
|
+
singular to left-to-right elimination, and the charging current would need the charge read two
|
|
336
|
+
blocks away.
|
|
337
|
+
|
|
338
|
+
Electrode reactions at a conductor's face take its carrier at its edge node, like any face
|
|
339
|
+
reaction. Whether a stretch is fed is decided by its conserved combinations: weightings $`w`$ of
|
|
340
|
+
the stretches' amounts that no reaction changes ($`w \cdot \nu = 0`$ for every face and bulk
|
|
341
|
+
reaction) and that nothing outside feeds ($`w = 0`$ on stretches reached by a contact or a port),
|
|
342
|
+
the null space of that stoichiometry. A stretch in none of them is fed. So Ag⁺ between silver
|
|
343
|
+
electrodes is fed (Ag⁺ + e⁻ ⇌ Ag(s), the electrons fed by the contacts), and the steady equations
|
|
344
|
+
are solved directly; Fe³⁺ and Fe²⁺ between platinum electrodes aren't, since Fe³⁺ + e⁻ ⇌ Fe²⁺
|
|
345
|
+
conserves the iron whatever the electrons do, so their total is kept by huge steps (below). A
|
|
346
|
+
floating conductor starts uncharged, with its carrier's level in equilibrium with the first
|
|
347
|
+
reaction on its left face that takes it.
|
|
348
|
+
|
|
349
|
+
## Internal ports
|
|
350
|
+
|
|
351
|
+
A port adds a source per volume to the balance rows of the nodes in its window, after every
|
|
352
|
+
other term at those nodes and before the contacts. A held (`'equilibrium'`) level replaces the
|
|
353
|
+
balance row with a Dirichlet row. The port's flux is then that row's residual, read just
|
|
354
|
+
before replacement, exactly as at a contact. Conductance and exchange links are linear in
|
|
355
|
+
$`(\bar\mu_{\mathrm{out}} - \bar\mu)`$. Everything stays on the node's own block. A contact's flux
|
|
356
|
+
readout at an end node already includes any port source there, so contact and port fluxes always
|
|
357
|
+
balance. A stretch reached by a port counts as fed, and its conservation intake includes the
|
|
358
|
+
port's flux. On a metal, a port spans both nodes of its single cell, with $`G`$ per area spread as
|
|
359
|
+
$`G/L`$ per volume, so each node gets half.
|
|
360
|
+
|
|
361
|
+
## Bulk reactions
|
|
362
|
+
|
|
363
|
+
$`r = k_f \prod c_R^\nu \cdot (-\mathrm{expm1}(-a))`$, with $`a = A/RT`$ computed from the
|
|
364
|
+
compensated $`\eta`$. That's mass action with the reverse rate implied by the standard potentials:
|
|
365
|
+
exactly zero at $`A = 0`$, and free of cancellation near equilibrium. Sources enter each balance as
|
|
366
|
+
$`\nu \cdot r`$, with one $`r`$ per reaction per node, so every moiety (a combination that no reaction
|
|
367
|
+
changes) telescopes exactly.
|
|
368
|
+
|
|
369
|
+
## Assembly
|
|
370
|
+
|
|
371
|
+
Each region is assembled by the kernel for its kind, over all its nodes and segments at once:
|
|
372
|
+
- **conductor:** its carrier's balance, and Ohm's law in mixed form (below);
|
|
373
|
+
- **dilute** (ideal statistics, the fast path): storage, space charge and Scharfetter–Gummel
|
|
374
|
+
fluxes, written straight into the blocks by local index; a dielectric is the case with no
|
|
375
|
+
species;
|
|
376
|
+
- **concentrated** (any statistics): the same through $`K = \partial c/\partial\zeta`$ and the
|
|
377
|
+
excess potential.
|
|
378
|
+
|
|
379
|
+
Faces, ports and contacts follow. Every kernel writes only the unknowns its region has.
|
|
380
|
+
|
|
381
|
+
## Linear algebra
|
|
382
|
+
|
|
383
|
+
Block Thomas with partial pivoting *within* each diagonal block (zero diagonal entries are
|
|
384
|
+
fine) but not *between* blocks. Rows are equilibrated (each divided by its largest Jacobian
|
|
385
|
+
entry) before factorisation. Storage is flat `Float64Array`s, and factor and solve allocate
|
|
386
|
+
nothing. For 300 nodes × 7 unknowns, one factor and solve takes ~0.4 ms in Node 22.
|
|
387
|
+
|
|
388
|
+
Block sizes differ from node to node: each block holds only the unknowns that exist there. A
|
|
389
|
+
node has $`M = 1 + n`$ slots ($`\hat\phi`$ and each species' $`\eta`$), but these aren't unknowns:
|
|
390
|
+
- a species absent from its material;
|
|
391
|
+
- $`\phi`$ where it's undefined;
|
|
392
|
+
- a conductor node's other species, and the flux slot of its last node;
|
|
393
|
+
- a blocked interface flux, or the displacement of a `'neutral'` face;
|
|
394
|
+
- a floating terminal's spare slots.
|
|
395
|
+
|
|
396
|
+
The state vector keeps every slot (one that isn't an unknown keeps its value), while the
|
|
397
|
+
residual, the update and the Jacobian are compact: assembly writes each entry straight into
|
|
398
|
+
blocks of $`m_b \times m_b`$, $`m_b \times m_{b-1}`$ and $`m_b \times m_{b+1}`$, through each slot's row
|
|
399
|
+
within its block, and drops terms in slots that aren't unknowns. Elimination costs $`\sum m_b^3`$
|
|
400
|
+
instead of $`n \cdot M^3`$, which pays wherever species are confined to some regions: for n-Si
|
|
401
|
+
against KCl, three unknowns of five at every node, it's a fifth of the work. A finite-difference
|
|
402
|
+
test checks the compact Jacobian column by column on devices that cover every assembly path.
|
|
403
|
+
|
|
404
|
+
## Newton
|
|
405
|
+
|
|
406
|
+
- The update of the device's potentials ($`\hat\phi`$, $`\eta`$) is limited to 10 thermal units per
|
|
407
|
+
iteration by uniform scaling, which scales a floating terminal voltage's update too. That
|
|
408
|
+
voltage doesn't count toward the limit: it enters only linearly (conductance links, held
|
|
409
|
+
levels, a capacitive face), so a large swing in it is safe. When it did count, a port driven by
|
|
410
|
+
a current pulse, its voltage collapsing by hundreds of volts as the current switched off,
|
|
411
|
+
dragged every unknown along 10 thermal units at a time (and a swing past 1e4 tripped the
|
|
412
|
+
divergence check): the strong-injection Haynes–Shockley benchmark took 55% more
|
|
413
|
+
factorisations.
|
|
414
|
+
- Converged when a full, undamped update is below 1e-10 (thermal units). Quadratic
|
|
415
|
+
convergence makes the remaining residual negligible.
|
|
416
|
+
- Or converged as far as round-off allows: updates already below 1e-6 thermal units (~26 nV)
|
|
417
|
+
that have stopped shrinking for two iterations. A badly conditioned system's round-off floor
|
|
418
|
+
can sit above 1e-10: a strictly neutral material on a short step, where $`\phi`$ is fixed only
|
|
419
|
+
through fluxes that the storage term dwarfs (a condition number of about $`h^2/(D \cdot dt)`$,
|
|
420
|
+
much reduced by the change of variables below), converges quadratically to ~1e-9 and then
|
|
421
|
+
rattles there. Short steps come right after every waveform breakpoint, so without this a
|
|
422
|
+
cyclic voltammogram in a neutral electrolyte stalled at its turns.
|
|
423
|
+
- Clear divergence (device updates beyond 1e4, or ten times the first after six iterations)
|
|
424
|
+
bails out early, so the caller can take a smaller step.
|
|
425
|
+
- When a steady solve fails, the solution's warnings say how nearly singular the system was,
|
|
426
|
+
and where. A running error bound through the factorisation compares each pivot with the
|
|
427
|
+
magnitudes it was formed from, $`\log_{10}(\sum|\mathrm{terms}| / |\mathrm{pivot}|)`$: the digits
|
|
428
|
+
lost. A part of the device held only weakly, such as a floating region coupled through tiny
|
|
429
|
+
conductances, loses about $`\log_{10}(g/G)`$ and fails near 15. It's not reported for solves that
|
|
430
|
+
converge, since digits can be lost harmlessly too (a saturated species whose $`\eta`$ nothing
|
|
431
|
+
depends on).
|
|
432
|
+
- The last iteration usually only confirms convergence (updates go like 4e-3, 7e-6, 3e-11).
|
|
433
|
+
Stopping one iteration early on a convergence-rate estimate would save a third of the work,
|
|
434
|
+
but leave ~1e-11 in $`\eta`$ per step, which shows up as conservation drift, so it isn't done.
|
|
435
|
+
- Tried and rejected for large jumps (the retry at 3 thermal units per iteration takes 30–50
|
|
436
|
+
iterations for a 1.4 V jump on a pn diode): per-component logarithmic damping, as in
|
|
437
|
+
SPICE junction limiting, and an adaptive limit that grows while updates shrink. Both
|
|
438
|
+
diverged more often and cost more overall.
|
|
439
|
+
|
|
440
|
+
## Time stepping
|
|
441
|
+
|
|
442
|
+
- **Backward Euler** is the default for `step(dt)`. It recursively halves the interval wherever
|
|
443
|
+
Newton fails, always landing exactly on $`t + dt`$. Minority carriers that must rise by many
|
|
444
|
+
orders of magnitude after a bias step are the typical cause.
|
|
445
|
+
- **Contact displacement** at the start of a step is carried over from the end of the previous
|
|
446
|
+
one, including across `set()`, so a step change in a gate voltage shows up as displacement
|
|
447
|
+
current.
|
|
448
|
+
- **BDF2** (`method: 'bdf2'`) is the variable-step second-order backward difference formula.
|
|
449
|
+
With $`\omega = dt/dt_{\mathrm{prev}}`$, its storage term is
|
|
450
|
+
$`[a_0 c - (1+\omega) c_n + \omega^2/(1+\omega)\, c_{n-1}]/dt`$, where $`a_0 = (1+2\omega)/(1+\omega)`$.
|
|
451
|
+
- It's written in backward-Euler form, $`(c - c^*)/(dt/a_0)`$ with the history reference
|
|
452
|
+
$`c^* = [(1+\omega) c_n - \omega^2/(1+\omega)\, c_{n-1}]/a_0`$. So assembly is shared, and the
|
|
453
|
+
displacement histories (for terminal currents) take the same combination.
|
|
454
|
+
- Conservation still telescopes. Closed amounts stay exact, since $`c^*`$ has the same amount
|
|
455
|
+
as $`c_n`$ when $`c_n`$ and $`c_{n-1}`$ did. Open stretches add the history term
|
|
456
|
+
$`\sum v (c^* - c_n)`$ to their intake.
|
|
457
|
+
- A step ratio above 2 falls back to backward Euler for that step, to stay safely within
|
|
458
|
+
variable-step BDF2's zero-stability limit ($`1 + \sqrt{2}`$).
|
|
459
|
+
- **Adaptive stepping** (`advance`):
|
|
460
|
+
- The local error of each step is estimated against an explicit predictor through the
|
|
461
|
+
previous states: quadratic after a BDF2 step, scaled by $`C_c/(C_c + C_p)`$, with
|
|
462
|
+
$`C_c = h^3(1+\omega)^2/(\omega(1+2\omega))`$ and $`C_p = h(h+h_1)(h+h_1+h_2)`$; linear after
|
|
463
|
+
backward Euler, scaled by $`h/(2h + h_1)`$. The first step, with no history, is checked by step
|
|
464
|
+
doubling.
|
|
465
|
+
- The error is measured in thermal units over every state potential ($`\hat\phi`$ where defined,
|
|
466
|
+
each present $`\eta`$, a floating terminal voltage). That includes species far below their
|
|
467
|
+
largest concentration, such as minority carriers ahead of a diffusion front. Weighting
|
|
468
|
+
them down (a mixed relative/absolute tolerance,
|
|
469
|
+
$`\delta\eta \cdot c/(c + 10^{-10} c_{\mathrm{max}})`$) took a third fewer steps on a pn turn-on,
|
|
470
|
+
but the tail's errors are swept into the front, and at matched accuracy of the terminal
|
|
471
|
+
current it cost 50% more.
|
|
472
|
+
- A step is rejected above `tol`. The next step size is
|
|
473
|
+
$`h \cdot \min(2, \max(0.2, 0.9\, (\mathtt{tol}/\mathrm{err})^{1/(p+1)}))`$.
|
|
474
|
+
- Newton failure quarters the step; on the first step after a start or a jump in a device
|
|
475
|
+
with a strictly neutral material, longer steps are tried first, since there shorter ones are
|
|
476
|
+
worse conditioned.
|
|
477
|
+
- A target within round-off of the present time (1e-10 relative), such as an animation
|
|
478
|
+
frame's that lands a hair past a breakpoint just reached, is snapped to rather than
|
|
479
|
+
stepped to: a step of 1e-13 s can't be resolved.
|
|
480
|
+
- Newton starts each step from the state extrapolated through the last three, which saves
|
|
481
|
+
about a third of the iterations.
|
|
482
|
+
- The wall-clock budget is checked between steps.
|
|
483
|
+
|
|
484
|
+
## Small-signal impedance
|
|
485
|
+
|
|
486
|
+
About a steady state, a small sinusoidal excitation at one terminal gives, to first order,
|
|
487
|
+
|
|
488
|
+
```math
|
|
489
|
+
\begin{aligned}
|
|
490
|
+
&(J + i\omega M)\, \delta x + \sum_k B_k\, \delta V_k = -B_T\, \delta V_T && \quad\text{(the grid's rows)} \\
|
|
491
|
+
&(C_k + i\omega C'_k)\, \delta x + (\partial I_k/\partial V_k + i\omega\dots)\, \delta V_k = \delta I_T\, \delta_{kT} && \quad\text{(each floating terminal's circuit row)}
|
|
492
|
+
\end{aligned}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
- **$`J`$** is the steady Jacobian, **$`M`$** the Jacobian of the time-derivative terms (storage
|
|
496
|
+
$`v \cdot K`$, displacement), and likewise $`C`$ and $`C'`$ for the terminal currents. The
|
|
497
|
+
time-derivative parts are read off two assemblies, $`J(dt) = J + M/dt`$, with a tiny $`dt`$ so that
|
|
498
|
+
the subtraction loses nothing.
|
|
499
|
+
- **At the measured terminal $`T`$,** a held voltage is perturbed ($`\delta V_T = 1`$, and $`\delta I_T`$
|
|
500
|
+
read from its $`C`$ row), or a driven current ($`\delta I_T = 1`$, and $`\delta V_T`$ solved for).
|
|
501
|
+
$`Z = \delta V_T/\delta I_T`$, with $`I`$ into the device. The other terminals keep their drives:
|
|
502
|
+
held ones at AC ground, driven ones open.
|
|
503
|
+
|
|
504
|
+
Each frequency costs one complex block-Thomas factorisation (rows scaled by their largest
|
|
505
|
+
entry), plus one back-substitution per floating terminal for the bordering. Conserved (blocked)
|
|
506
|
+
species make $`J`$ singular, but $`J + i\omega M`$ isn't for $`\omega > 0`$: at low frequency a blocking
|
|
507
|
+
device looks like a capacitor, as it should.
|
|
508
|
+
|
|
509
|
+
The factorised system is used as a preconditioner, not trusted alone: each solve runs GMRES with
|
|
510
|
+
$`J \cdot v`$ taken from the residual itself, by a central difference ($`\eta`$ perturbed in the
|
|
511
|
+
state's low word, $`\hat\phi`$ and the face unknowns in the high one). The assembled $`J`$ holds a
|
|
512
|
+
flux's dependence on $`\eta_L`$ and $`\eta_R`$ as two entries; in an inversion layer both are huge
|
|
513
|
+
(~1e11), and for a nearly uniform $`\delta\eta`$ they cancel to round-off of order 1e-5, while the
|
|
514
|
+
residual takes the $`\eta`$ difference first, in double-double. That round-off had given a MOS
|
|
515
|
+
capacitor's inversion layer, fed by minority diffusion from a bulk with ~1e3 electrons per cm³ (a
|
|
516
|
+
time constant of minutes), an exchange path that followed the gate at 1 Hz. Where the plain solve
|
|
517
|
+
is already accurate, one application of the operator confirms it; the bench's impedance cases
|
|
518
|
+
take about twice as long as before.
|
|
519
|
+
|
|
520
|
+
## Steady state
|
|
521
|
+
|
|
522
|
+
- **If every species stretch is fed by a contact,** nothing is conserved on its own, and the
|
|
523
|
+
true steady equations are solved directly ($`dt = \infty`$, no storage term). This matters
|
|
524
|
+
because slow physics can take seconds, far beyond any $`L^2/D`$ estimate, and stepping would
|
|
525
|
+
never finish. An example is exponentially scarce minority carriers slowly filling an inversion
|
|
526
|
+
layer behind a Schottky contact.
|
|
527
|
+
- **Spectators** (a species blocked all round, mobile throughout its stretch) are solved
|
|
528
|
+
directly too. In steady state the sum of a spectator's balance rows over its stretch is zero
|
|
529
|
+
identically, so one of them (the first node's) is redundant, and it's replaced by the
|
|
530
|
+
conservation of the amount, $`\sum v c = \mathtt{amount}`$. That row is dense, so the solve is
|
|
531
|
+
bordered: the matrix is factorised with a pin (an identity row) in its place, which makes the
|
|
532
|
+
stretch's level a well-conditioned unknown, and the response to a unit pin (one extra
|
|
533
|
+
back-substitution per spectator) is added in the amount that satisfies the constraint, from
|
|
534
|
+
a $`k \times k`$ system for $`k`$ spectators.
|
|
535
|
+
- **Conserved combinations** (moieties) of reacting stretches are solved the same way: the
|
|
536
|
+
total iron of Fe³⁺, Fe²⁺ and FeCl²⁺ in a closed cell with a complexation reaction, say. The
|
|
537
|
+
basis of combinations $`w`$ comes from the null space of the stoichiometry. In steady state the
|
|
538
|
+
$`w`$-weighted sum of their balance rows is zero identically (the reactions cancel by
|
|
539
|
+
$`w \cdot \nu = 0`$, and nothing crosses the stretches' ends), so one of them is replaced by
|
|
540
|
+
$`\sum_k w_k \sum v c_k =`$ the combination's amount, bordered like a spectator's. (Spectators
|
|
541
|
+
are the one-stretch case.)
|
|
542
|
+
|
|
543
|
+
Holding the amount through a storage term at huge $`dt`$ instead is badly conditioned: the
|
|
544
|
+
stretch's level is then held only by $`v \cdot c/dt`$, against internal conductances $`D \cdot c/h`$
|
|
545
|
+
larger by $`D \cdot dt/(hL)`$, around 1e12 for a micron-scale cell (see
|
|
546
|
+
[metal regions](#metal-regions) for the same cancellation). Newton then needs dozens of
|
|
547
|
+
iterations, or fails.
|
|
548
|
+
- **Otherwise** (immobile spectators, which conserve node by node, or a combination that
|
|
549
|
+
includes a floating conductor), backward-Euler steps at a huge $`dt`$ (10⁶ × the slowest
|
|
550
|
+
diffusion time) keep the storage term, which pins each conserved amount exactly: sum a
|
|
551
|
+
species' rows and the fluxes cancel. $`dt`$ grows ×10 (capped) while the state still moves.
|
|
552
|
+
Before each huge step, each spectator's level is shifted uniformly to restore its amount
|
|
553
|
+
exactly (in one step for ideal statistics, by Newton on the shift otherwise). It guards
|
|
554
|
+
against round-off creeping through the vanishing storage term. The solve finishes with one
|
|
555
|
+
step at the base giant $`dt`$, where pinning is tight.
|
|
556
|
+
- **If a direct solve diverges,** it's retried once with tighter damping (3 thermal units per
|
|
557
|
+
iteration). That's enough for most large jumps, such as a cold start at forward bias.
|
|
558
|
+
- **Generation continuation.** A device with generation reactions (species made only from, or
|
|
559
|
+
turned only into, fixed reservoirs, such as photogeneration from a photon reservoir) can be
|
|
560
|
+
held far from equilibrium even with its terminals level, where bias continuation can't help.
|
|
561
|
+
If a direct solve fails there, the generation rates are scaled down to 10⁻¹² and ramped back
|
|
562
|
+
up, ×100 a step while each solve converges (warm from the last) and by the square root of the
|
|
563
|
+
factor when one doesn't. An illuminated 80 µm silicon diode solves cold this way in about 80
|
|
564
|
+
iterations.
|
|
565
|
+
- **If that fails too,** source continuation ramps the right terminal's voltage to its target.
|
|
566
|
+
It ramps from the voltage of the last converged solve when the state is that solution, and
|
|
567
|
+
otherwise from level terminals, where a cold start is consistent. The ramp step starts at
|
|
568
|
+
1/8 of the way, grows ×1.5 on success and shrinks ×4 on failure.
|
|
569
|
+
- **If Newton still fails,** $`dt`$ ramps up from a small value (pseudo-transient continuation),
|
|
570
|
+
ending in the direct solve where applicable.
|
|
571
|
+
|
|
572
|
+
`solve()` does not advance the clock.
|
|
573
|
+
|
|
574
|
+
## Conservation
|
|
575
|
+
|
|
576
|
+
- **Discretely exact.** Face fluxes are computed once and added ± to both neighbours, the
|
|
577
|
+
interface flux unknowns do the same, and reactions are $`\nu \cdot r`$. So summed over boxes,
|
|
578
|
+
everything telescopes, and the *converged* discrete solution conserves every amount and total
|
|
579
|
+
charge to round-off.
|
|
580
|
+
- **The iterate conserves to Newton's tolerance.** Storage is nonlinear in $`\eta`$, so each step's
|
|
581
|
+
drift is its summed residual. Converging to 1e-10 in $`\eta`$ makes that ~1e-15 per step in
|
|
582
|
+
practice.
|
|
583
|
+
- **Reported.** Every solution's `conservation` lists each species stretch: its amount, its
|
|
584
|
+
reference, the time-integrated flux through its contacts, and the resulting drift.
|
|
585
|
+
|
|
586
|
+
## Strictly neutral materials and unresolved double layers
|
|
587
|
+
|
|
588
|
+
A material with $`\varepsilon = 0`$ has local neutrality in place of Poisson, and no displacement
|
|
589
|
+
along its segments. $`\phi`$ there is a bookkeeping multiplier, fixed by neutrality given the
|
|
590
|
+
$`\bar\mu`$'s. It's reported as NaN if no charged species is present and nothing couples the region
|
|
591
|
+
electrostatically. The bulk $`\varepsilon \to 0`$ limit is smooth: the Poisson row simply
|
|
592
|
+
degenerates into neutrality. The same Newton count holds from $`\varepsilon_r = 78.5`$ down to 1e-6,
|
|
593
|
+
as in a linear prototype that motivated the design.
|
|
594
|
+
|
|
595
|
+
Interfaces are where it gets subtle. With a `pinned` law and double layers the grid can't
|
|
596
|
+
resolve (because $`\varepsilon`$ is tiny, or the cells are coarse), the charge the interface needs is
|
|
597
|
+
crammed into the two half-boxes beside it. The bulk stays right, but the interface compositions
|
|
598
|
+
and $`D_f`$ become mesh-dependent. The true $`\varepsilon \to 0`$ limit has no interface charge and a
|
|
599
|
+
free Donnan-type jump, which is the `neutral` law. The defaults follow from this: `neutral`
|
|
600
|
+
between two $`\varepsilon = 0`$ materials, `pinned` otherwise (and `pinned` between two
|
|
601
|
+
$`\varepsilon = 0`$ materials is an error: with no field on either side, nothing would determine its
|
|
602
|
+
charge). Solutions warn when a resolved-model double layer is under-resolved.
|
|
603
|
+
|
|
604
|
+
On a transient step, strictly neutral nodes are solved in better-conditioned terms. There, a
|
|
605
|
+
change of $`\hat\phi`$ with every $`\eta_i`$ shifted by $`z_i`$ times it leaves every concentration as it
|
|
606
|
+
was, so storage and neutrality don't see it. Only the fluxes do. But in $`(\hat\phi, \eta)`$ storage
|
|
607
|
+
and neutrality see it as pairs of huge entries that cancel, and round-off in that cancellation, of
|
|
608
|
+
order storage/flux ~ $`h^2/(D \cdot dt)`$ times the range of concentrations, swamps the fluxes that
|
|
609
|
+
fix it: a trace ion beside 3 M KCl lost about ten digits, and Newton stalled. So at each node that
|
|
610
|
+
stays neutral (interior nodes, and edges at `neutral` faces; not the edge of a capacitive or
|
|
611
|
+
pinned face, which holds the face's charge), assembled without storage and neutrality:
|
|
612
|
+
- rows: the balance of the most abundant charged species (by $`z^2 c`$) becomes
|
|
613
|
+
$`\sum (z_i/z_k) \times`$ each balance, which without storage is current continuity;
|
|
614
|
+
- columns: the unknowns become $`\hat\phi'`$ and $`\eta'_i = \eta_i - z_i \hat\phi`$ (the update is
|
|
615
|
+
mapped back), in which storage and neutrality have no $`\hat\phi'`$ term at all;
|
|
616
|
+
- then storage (on the other balances) and neutrality go in, exactly, in those terms.
|
|
617
|
+
|
|
618
|
+
A start-of-step net charge (round-off in a solved state) isn't carried over: the neutrality row
|
|
619
|
+
holds the new state neutral. Steady solves and the impedance keep the plain rows (there's no
|
|
620
|
+
storage at $`dt = \infty`$, and the impedance reads the storage matrix from them).
|
|
621
|
+
|
|
622
|
+
A sub-grid Gouy–Chapman law, treating the diffuse layers analytically when $`\lambda_D \ll h`$, is on
|
|
623
|
+
the [roadmap](../ROADMAP.md). It would handle macroscopic devices with real double-layer charge at
|
|
624
|
+
any grid, and tends to `neutral` as $`\varepsilon \to 0`$.
|
|
625
|
+
|
|
626
|
+
At an $`\varepsilon = 0`$ | $`\varepsilon > 0`$ face, the neutral side's boundary half-box holds the
|
|
627
|
+
face's charge. That slightly perturbs the carrier density there, by an amount that depends on the
|
|
628
|
+
mesh (0.3% on a Schottky test with the metal as an $`\varepsilon = 0`$ region). For a metal, a metal
|
|
629
|
+
region avoids this: its surface charge is a sheet that leaves its Fermi level untouched.
|