driftlet 0.1.1 → 0.3.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 +12 -2
- package/docs/alignment.md +146 -0
- package/docs/conventions.md +194 -0
- package/docs/data.md +120 -0
- package/docs/device.md +541 -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 +71 -9
- package/package.json +4 -1
- package/src/constants.js +11 -0
- package/src/describe.js +17 -2
- package/src/device.js +23 -8
- package/src/fermi.js +5 -3
- package/src/index.js +5 -2
- package/src/kit.js +1 -0
- package/src/plot.js +2 -1
- package/src/pow.js +24 -0
- package/src/solver.js +110 -22
- package/src/sources.js +103 -0
- package/src/statistics.js +4 -3
- package/src/types.js +6 -4
- package/types/constants.d.ts +10 -0
- package/types/index.d.ts +11 -2
- package/types/kit.d.ts +1 -0
- package/types/pow.d.ts +4 -0
- package/types/solver.d.ts +9 -3
- package/types/sources.d.ts +102 -0
- package/types/types.d.ts +11 -5
package/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
<h1>
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://markblundeberg.github.io/driftlet/docs/logo-dark.svg">
|
|
4
|
+
<img alt="driftlet" src="https://markblundeberg.github.io/driftlet/docs/logo.svg" width="300">
|
|
5
|
+
</picture>
|
|
6
|
+
</h1>
|
|
2
7
|
|
|
3
8
|
[](https://github.com/markblundeberg/driftlet/actions/workflows/test.yml)
|
|
4
9
|
[](https://www.npmjs.com/package/driftlet)
|
|
@@ -50,7 +55,7 @@ import { bandDiagram } from 'driftlet/plot'; // a level diagram as an SVG str
|
|
|
50
55
|
```
|
|
51
56
|
|
|
52
57
|
Or straight from a CDN in a page, pinned to a version:
|
|
53
|
-
`https://cdn.jsdelivr.net/npm/driftlet@0.
|
|
58
|
+
`https://cdn.jsdelivr.net/npm/driftlet@0.3.0/src/index.js` (and `src/kit.js`, `src/plot.js`).
|
|
54
59
|
TypeScript declarations ship in the package. Writing a demo with an LLM agent? Point it at
|
|
55
60
|
[`llms.txt`](llms.txt).
|
|
56
61
|
|
|
@@ -225,9 +230,12 @@ Every physics feature is tested against analytic results (`npm test`, node's bui
|
|
|
225
230
|
| Floating island | Gauss's law; conserved amounts through gate sweeps | 1e-12 |
|
|
226
231
|
| pn junction | exact built-in potential; depletion charge; short-diode J–V | 1e-12; 1%; 2e-3 |
|
|
227
232
|
| Long pn diode with recombination | Shockley J–V incl. depletion recombination | 2e-3 |
|
|
233
|
+
| Haynes–Shockley pulse | an injected hole packet's drift, spread and decay at the ambipolar μ*, D*, 1/τ*; nothing lost while it goes in | 2e-4; 1e-2; 2e-3 |
|
|
234
|
+
| A packet laid down as a `c0` profile | the same rates from a Gaussian at t = 0: μ*E t, σ₀² + 2D*t, e^(−t/τ*) | 3e-4; 1e-2; 1e-3 |
|
|
228
235
|
| Illuminated long pn diode | `J_sc = qG(L_n + L_p + W)` from a cold start; superposition at low injection | 5e-3; 1e-2 |
|
|
229
236
|
| Schottky barrier (metal region \| n-Si) | surface density from the alignment; depletion charge | 5e-3; 2% |
|
|
230
237
|
| Liquid junction, open circuit | cell EMF 2t₊(RT/F) ln(c₁/c₂); Planck diffusion potential | 1e-4 |
|
|
238
|
+
| Salt diffusion mode from a `c0` profile | c̄ + a·sin(πx/2L) decaying at π²D/4L², D = 2D₊D₋/(D₊ + D₋) | 2e-5 |
|
|
231
239
|
| Concentration polarization | `i = i_lim tanh(V/4V_T)`, incl. galvanostatic and load modes | 2e-4 |
|
|
232
240
|
| Butler–Volmer electrode | Nernst equilibrium; mixed kinetic/diffusion closed form | 5e-4 |
|
|
233
241
|
| Redox couple between inert electrodes | Nernst level of Fe³⁺/Fe²⁺; the couple's total conserved at equilibrium and under current | 1e-9; 1e-10 |
|
|
@@ -282,6 +290,8 @@ No dependencies. Tests use node's built-in runner (Node ≥ 22):
|
|
|
282
290
|
npm test # the validation suite
|
|
283
291
|
npm run bench # typical workloads against bench/baseline.json (--save to update it)
|
|
284
292
|
npm run types # TypeScript declarations from the JSDoc, into types/ (fetches TypeScript via npx)
|
|
293
|
+
npm run smoke # every demo in headless Chrome, every control to its extremes (CHROME=… to choose)
|
|
294
|
+
npm run shots # retake the demos' screenshots, each caught at a set state (tools/shots.js)
|
|
285
295
|
```
|
|
286
296
|
|
|
287
297
|
Design notes and plans: [numerics](docs/numerics.md), [conventions](docs/conventions.md),
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Band alignment from vacuum levels
|
|
2
|
+
|
|
3
|
+
driftlet never decides how levels line up across an interface. Each interface's alignment is
|
|
4
|
+
its own physical property, and you give it explicitly (see [conventions](conventions.md)). But
|
|
5
|
+
sometimes vacuum-level reasoning is the only estimate available, and it's a useful worked
|
|
6
|
+
reference. This page sets it out as one recipe with two ingredients, and lists what it
|
|
7
|
+
assumes.
|
|
8
|
+
|
|
9
|
+
**Before reaching for it,** ask whether you need an alignment at all. If only macroscopic,
|
|
10
|
+
bulk-neutral behaviour matters, a `phi: 'neutral'` interface makes the alignment drop out, and
|
|
11
|
+
none is needed.
|
|
12
|
+
|
|
13
|
+
## The recipe: an anchor and an offset per material
|
|
14
|
+
|
|
15
|
+
Every vacuum-level number in the literature describes **one material against vacuum**. It
|
|
16
|
+
picks a level inside the material (the **anchor**) and says how far above that level, in
|
|
17
|
+
electron energy, the vacuum level just outside the surface lies (the **offset**). In
|
|
18
|
+
driftlet's voltage units ($`V = -E/e`$ for electrons):
|
|
19
|
+
|
|
20
|
+
```math
|
|
21
|
+
V_{\mathrm{vac}} = V_{\mathrm{anchor}} - \mathtt{offset}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Quantity | Anchor | Offset |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| electron affinity $`\chi`$ | conduction band = the e⁻ standard level | $`\chi`$ |
|
|
27
|
+
| ionisation energy | valence band = the h⁺ standard level | $`\chi + E_g`$ |
|
|
28
|
+
| work function W | Fermi level | W |
|
|
29
|
+
| Trasatti's absolute SHE, ≈ 4.44 V | the SHE level of a solution | 4.44 V |
|
|
30
|
+
| surface potential $`\chi_s`$ | the inner potential $`\phi`$ | $`\chi_s`$ |
|
|
31
|
+
|
|
32
|
+
Two materials are then aligned by **assuming their vacuum levels coincide** across the
|
|
33
|
+
interface. That assumption is the whole heuristic: Anderson's rule, the Schottky–Mott rule, a
|
|
34
|
+
gate's flat-band voltage and the pzc estimate are all this one recipe applied to different
|
|
35
|
+
pairs. It can combine any pair, for example a semiconductor (electron affinity) against an
|
|
36
|
+
aqueous electrolyte (absolute SHE).
|
|
37
|
+
|
|
38
|
+
### The anchors in driftlet
|
|
39
|
+
|
|
40
|
+
An anchor has to be a level that driftlet knows in terms of a material's $`\phi`$:
|
|
41
|
+
|
|
42
|
+
- **A charged species' standard level**, $`V^\circ_i = \phi + \mu^\circ_i/(z_i F)`$. For e⁻ and h⁺
|
|
43
|
+
these are the band edges, which are electronic levels. For an ion, $`V^\circ_i`$ is simply that
|
|
44
|
+
ion's standard level: a fixed offset from $`\phi`$, not by itself the level of any electrons.
|
|
45
|
+
- **The SHE level**, the electronic level of the standard hydrogen electrode in a solution:
|
|
46
|
+
|
|
47
|
+
```math
|
|
48
|
+
V^\circ_{\mathrm{e}^-}(\mathrm{SHE}) = \phi + (\mu^\circ_{\mathrm{H}^+} - \tfrac{1}{2} \mu^\circ_{\mathrm{H}_2}) / F
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
As an anchor this is `'H+'` (its standard level $`\phi + \mu^\circ_{\mathrm{H}^+}/F`$), with the H₂
|
|
52
|
+
term folded into the offset: Trasatti's value becomes
|
|
53
|
+
`{ anchor: 'H+', offset: 4.44 + μ°_H₂/(2F) }`. On the usual conventions
|
|
54
|
+
($`\mu^\circ_{\mathrm{H}_2} = 0`$ for the element in its standard state, and
|
|
55
|
+
$`\mu^\circ_{\mathrm{H}^+} = 0`$ so that $`E^\circ(\mathrm{SHE}) = 0`$), that's just offset 4.44 V.
|
|
56
|
+
Trasatti's 4.44 V then works exactly like a semiconductor's electron affinity, with the SHE level
|
|
57
|
+
in place of the conduction band. It needs H⁺ among the species. Other half-reactions could be used
|
|
58
|
+
as anchors in principle, but each brings its own conventions (the neutral element's $`\mu`$,
|
|
59
|
+
$`E^\circ(\mathrm{SHE}) = 0`$), so they're not offered as shortcuts here.
|
|
60
|
+
- **The Fermi level** of a metal, the proper reference for a work function. It's taken by
|
|
61
|
+
`vacuumZeroCharge`, for a conductor region's face or a contact (below). A semiconductor's Fermi
|
|
62
|
+
level moves with doping and bias, so its work function isn't a material constant: use its
|
|
63
|
+
electron affinity instead.
|
|
64
|
+
- **$`\phi`$ itself** (`'phi'`), with a surface potential as the offset. That's discouraged, since
|
|
65
|
+
$`\phi`$ is bookkeeping: its value inside a material depends on how that material's $`\mu^\circ`$ were
|
|
66
|
+
anchored, and surface potentials are not measurable on their own. If you have settled that
|
|
67
|
+
bookkeeping to your own satisfaction, it's available.
|
|
68
|
+
|
|
69
|
+
## In the API
|
|
70
|
+
|
|
71
|
+
The recipe lives in `driftlet/kit`, as helpers that read a device definition and return the
|
|
72
|
+
spec value to put in it. The spec itself only takes the result (a `dipole` or a `zeroCharge`),
|
|
73
|
+
so what a device assumes stays visible in its definition.
|
|
74
|
+
|
|
75
|
+
```js nocheck
|
|
76
|
+
import { vacuumDipole, vacuumZeroCharge } from 'driftlet/kit';
|
|
77
|
+
|
|
78
|
+
// GaAs | AlGaAs: electron affinities on the e⁻ standard level (the conduction band)
|
|
79
|
+
def.interfaces = [{
|
|
80
|
+
dipole: vacuumDipole(def, { material: 'GaAs', anchor: 'e-', offset: 4.07 }, { material: 'AlGaAs', anchor: 'e-', offset: 3.8 }),
|
|
81
|
+
}];
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`vacuumDipole` gives $`\phi_R - \phi_L = (V_{\mathrm{vac}} - \phi)_L - (V_{\mathrm{vac}} - \phi)_R`$,
|
|
85
|
+
each side's $`V_{\mathrm{vac}} - \phi`$ coming from its anchor and offset (`vacuumLevel` gives one
|
|
86
|
+
side's).
|
|
87
|
+
|
|
88
|
+
Where a conductor meets a material, at a conductor region's face or at a contact's capacitive
|
|
89
|
+
or pinned law, the conductor's side is its work function W from its Fermi level, and the
|
|
90
|
+
helper gives `zeroCharge` ($`V_F - \phi_{\mathrm{edge}}`$ at zero charge):
|
|
91
|
+
|
|
92
|
+
```js nocheck
|
|
93
|
+
const zc = vacuumZeroCharge(def, 4.75, { material: 'Si', anchor: 'e-', offset: 4.05 }); // Au | n-Si
|
|
94
|
+
def.interfaces = [{ phi: { type: 'capacitive', C: 10 }, zeroCharge: zc }]; // Au as a region
|
|
95
|
+
Object.assign(def.contacts.left, { phi: { type: 'capacitive', C: 10 }, zeroCharge: zc }); // or as a contact
|
|
96
|
+
// zeroCharge = W + (V_vac − φ)_inside = W − χ − μ°_e/F
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Pairwise examples
|
|
100
|
+
|
|
101
|
+
**Semiconductor heterojunction (Anderson's rule).** Electron affinities on both sides,
|
|
102
|
+
`{ material, anchor: 'e-', offset: χ }`, give $`\Delta E_c = \chi_L - \chi_R`$. The valence-band offset
|
|
103
|
+
then follows from the two gaps, already in your holes' $`\mu^\circ`$. Ionisation energies on `'h+'`
|
|
104
|
+
give the same thing from the other band.
|
|
105
|
+
|
|
106
|
+
**Metal | semiconductor (Schottky–Mott).** Work function against electron affinity gives the
|
|
107
|
+
n-type barrier $`\phi_B = W - \chi`$. With the metal as a contact, a pinned law
|
|
108
|
+
`phi: 'pinned', zeroCharge: vacuumZeroCharge(def, W, { material, anchor: 'e-', offset: χ })`
|
|
109
|
+
puts the semiconductor's surface electron density at $`N_c e^{-\phi_B/kT}`$. With the metal as a
|
|
110
|
+
region, the face is capacitive with the same `zeroCharge`; a large C approaches the pinned
|
|
111
|
+
barrier.
|
|
112
|
+
|
|
113
|
+
**Gate | semiconductor (flat band).** The same with a capacitive law. Its `zeroCharge` is the
|
|
114
|
+
anchor-level form of the textbook $`V_{\mathrm{FB}} = (W_g - W_s)/e`$, which refers to the
|
|
115
|
+
semiconductor's bulk Fermi level instead. Fixed charge in a real insulator shifts flat band further.
|
|
116
|
+
|
|
117
|
+
**Metal | electrolyte (potential of zero charge).** Work function against the absolute SHE gives
|
|
118
|
+
$`\mathrm{pzc} \approx W/e - 4.44\,\mathrm{V}`$ on the SHE scale (on the usual conventions above):
|
|
119
|
+
`zeroCharge: vacuumZeroCharge(def, W, { material, anchor: 'H+', offset: 4.44 })`.
|
|
120
|
+
|
|
121
|
+
**Semiconductor | electrolyte.** Electron affinity against the absolute SHE places the band edges on
|
|
122
|
+
the SHE scale, $`E_c \approx -(\chi - 4.44)\,\mathrm{eV}`$ relative to SHE: the usual
|
|
123
|
+
photoelectrochemistry estimate:
|
|
124
|
+
`vacuumDipole(def, { material: 'TiO2', anchor: 'e-', offset: χ }, { material: 'water', anchor: 'H+', offset: 4.44 })`.
|
|
125
|
+
|
|
126
|
+
**Solvent | solvent.** Each solvent's own absolute-SHE-type value (its Trasatti-type offset)
|
|
127
|
+
aligns them, exactly as Anderson's rule aligns two semiconductors.
|
|
128
|
+
|
|
129
|
+
## What the heuristic assumes, and where it fails
|
|
130
|
+
|
|
131
|
+
1. **The vacuum level runs continuously through the interface.** In reality, the interface
|
|
132
|
+
forms its own dipole (charge transfer, bonding, solvent orientation, adsorbates) beyond
|
|
133
|
+
what the two free surfaces imply.
|
|
134
|
+
2. **Surface quantities are properties of the material.** They aren't: W, $`\chi`$ and 4.44 V are
|
|
135
|
+
barrier heights of particular surfaces, and change with termination, adsorbates and
|
|
136
|
+
preparation. The 4.44 V is itself the work function of a hydrogen electrode, not a
|
|
137
|
+
universal zero.
|
|
138
|
+
3. **Alignments add up transitively** around any set of materials, and are uniform along each
|
|
139
|
+
interface.
|
|
140
|
+
|
|
141
|
+
At covalent interfaces (common semiconductors, most metal–semiconductor contacts), measured
|
|
142
|
+
alignments often depart substantially from these rules, and Fermi-level pinning is common.
|
|
143
|
+
Ionic materials tend to follow them better. At metal–solution interfaces, the neglected
|
|
144
|
+
metal–solvent terms (orientation, chemisorption) are often a few tenths of a volt.
|
|
145
|
+
Whenever a measured offset, barrier, flat-band voltage or pzc exists, use it instead:
|
|
146
|
+
`step`, `dipole` and `zeroCharge` take measured values directly.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Conventions
|
|
2
|
+
|
|
3
|
+
Conventions are where users of any drift–diffusion code go wrong, so here they all are in one
|
|
4
|
+
place. driftlet's are chosen to be thermodynamically honest, and some of them are deliberately
|
|
5
|
+
stricter than you may be used to.
|
|
6
|
+
|
|
7
|
+
## Principles
|
|
8
|
+
|
|
9
|
+
1. **Every control and every measurable is an electrochemical potential** $`\bar\mu`$, or a
|
|
10
|
+
difference of them. A bias voltage sets a difference in $`\bar\mu`$ of electrons between
|
|
11
|
+
terminals, $`V = -\Delta\bar\mu_{\mathrm{e}^-}/F`$. A gate sets its metal's $`\bar\mu_{\mathrm{e}^-}`$.
|
|
12
|
+
Nothing you set is an electrostatic potential.
|
|
13
|
+
2. **$`\phi`$ is bookkeeping.** Any consistent $`\phi`$ gives identical physics. Each material's standard
|
|
14
|
+
chemical potentials fix where its $`\phi`$ sits relative to its own levels, so $`\phi`$ jumps at
|
|
15
|
+
every interface between different materials, by that interface's dipole. How big a dipole is
|
|
16
|
+
depends on how each material was anchored, which is why it's arbitrary, correctly so. If you
|
|
17
|
+
do have true mean inner potentials, you may anchor to them, but nothing requires it.
|
|
18
|
+
Extrathermodynamic conventions are one way people settle a "real" $`\phi`$ per material. TATB,
|
|
19
|
+
for instance, fixes single-ion transfer energies between solvents by assuming
|
|
20
|
+
$`\Delta G_{\mathrm{tr}}(\mathrm{Ph_4As}^+) = \Delta G_{\mathrm{tr}}(\mathrm{Ph_4B}^-)`$. That's a
|
|
21
|
+
statement about bulk single-ion energies, i.e. about how each solvent's $`\mu^\circ`$ are
|
|
22
|
+
anchored. It says nothing about the dipole at an actual interface, which stays a separate
|
|
23
|
+
input.
|
|
24
|
+
3. **Bulk standard potentials only mean something in neutral combinations**
|
|
25
|
+
($`\mu^\circ_{\mathrm{e}^-} + \mu^\circ_{\mathrm{h}^+}`$,
|
|
26
|
+
$`\mu^\circ_{\mathrm{Na}^+} + \mu^\circ_{\mathrm{Cl}^-}`$,
|
|
27
|
+
$`\mu^\circ_{\mathrm{Li}^+} + \mu^\circ_{\mathrm{e}^-}`$). How charged levels line up across a
|
|
28
|
+
boundary between different materials is a property of that interface, and you must give it.
|
|
29
|
+
There's no Anderson rule, no Schottky–Mott rule, and no implied common vacuum level. Each
|
|
30
|
+
interface's alignment is independent, even when the same pair of materials meets twice
|
|
31
|
+
(e.g. with different adsorbates). When vacuum-level estimates are all you have, helpers in
|
|
32
|
+
`driftlet/kit` turn anchors and offsets into an alignment (see the
|
|
33
|
+
[alignment guide](alignment.md)).
|
|
34
|
+
4. **A work function belongs to a surface, not a material.**
|
|
35
|
+
|
|
36
|
+
## Electrochemical potential and its views
|
|
37
|
+
|
|
38
|
+
For species *i* with charge number $`z_i`$, in a material where its standard chemical potential
|
|
39
|
+
is $`\mu^\circ_i`$, the electrochemical potential splits as
|
|
40
|
+
|
|
41
|
+
```math
|
|
42
|
+
\bar\mu_i = \mu^\circ_i + z_i F \phi + RT \zeta_i
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The reduced chemical potential $`\zeta_i`$ is what a material's **statistics** turn into a
|
|
46
|
+
concentration, $`c_i = c_i(\zeta)`$. The default is ideal (dilute) statistics,
|
|
47
|
+
|
|
48
|
+
```math
|
|
49
|
+
c_i = c_{\mathrm{ref},i} \cdot e^{\zeta_i}, \quad\text{i.e.}\quad \bar\mu_i = \mu^\circ_i + z_i F \phi + RT \ln(c_i / c_{\mathrm{ref},i})
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
with $`c_{\mathrm{ref},i}`$ the reference concentration that $`\mu^\circ_i`$ refers to. Non-ideal
|
|
53
|
+
statistics (degenerate carriers, crowding, intercalation hosts, activity coefficients) are chosen
|
|
54
|
+
per material; see [statistics](statistics.md). They all reduce to the ideal form in the dilute
|
|
55
|
+
limit, so $`\mu^\circ`$ and $`c_{\mathrm{ref}}`$ mean the same thing in every model: the dilute
|
|
56
|
+
(Henry's-law) reference.
|
|
57
|
+
|
|
58
|
+
The API speaks $`\bar\mu`$ in J/mol (`units.eV` converts per-particle energies). Two voltage views
|
|
59
|
+
are provided for charged species (what they show, and why they're drawn, is in
|
|
60
|
+
[reading level diagrams](visualization.md)):
|
|
61
|
+
|
|
62
|
+
- the **species voltage** $`V_i = \bar\mu_i / (z_i F)`$, which is what a voltmeter reads for
|
|
63
|
+
electrons, and the analogous quantity a reversible electrode reads for an ion;
|
|
64
|
+
- the **standard level** $`V^\circ_i = \phi + \mu^\circ_i / (z_i F)`$, which plays the part of a
|
|
65
|
+
band edge.
|
|
66
|
+
|
|
67
|
+
Plotted as voltages, a semiconductor's conduction-band level $`V^\circ_{\mathrm{e}^-}`$ sits
|
|
68
|
+
*below* its valence-band level $`V^\circ_{\mathrm{h}^+}`$. That's expected, since $`V = -E/e`$ for
|
|
69
|
+
electrons.
|
|
70
|
+
|
|
71
|
+
Electrons and holes are ordinary species: $`z = \mp 1`$, $`c_{\mathrm{ref}}`$ = effective density of
|
|
72
|
+
states, and $`\mu^\circ`$ = the band edges as molar energies (conduction band for e⁻, minus the
|
|
73
|
+
valence band for h⁺). With Fermi–Dirac statistics the same parameters give
|
|
74
|
+
$`c = N_c \mathcal{F}_{1/2}(\zeta)`$.
|
|
75
|
+
|
|
76
|
+
## Transport
|
|
77
|
+
|
|
78
|
+
Each species moves down its own electrochemical potential:
|
|
79
|
+
|
|
80
|
+
```math
|
|
81
|
+
\begin{aligned}
|
|
82
|
+
N_i &= -(D_i c_i / RT) \nabla\bar\mu_i && \quad\text{(particle flux, mol/(m}^2\cdot\text{s))} \\
|
|
83
|
+
J_i &= z_i F N_i = -\sigma_i \nabla V_i, \qquad \sigma_i = z_i^2 F^2 D_i c_i / RT
|
|
84
|
+
\end{aligned}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Drift and diffusion are one law, and the Einstein relation is automatic. $`D`$ is the coefficient
|
|
88
|
+
of $`c\nabla\bar\mu/RT`$, i.e. $`RT`$ times the mobility per mole, and it's the same parameter
|
|
89
|
+
whatever the statistics. For ideal statistics it's the ordinary diffusivity. With non-ideal
|
|
90
|
+
statistics the measured chemical diffusivity is $`D`$ times the thermodynamic factor,
|
|
91
|
+
$`\partial \ln a/\partial \ln c`$: the generalised Einstein relation, as for degenerate electrons.
|
|
92
|
+
|
|
93
|
+
Two optional transport terms describe a moving fluid:
|
|
94
|
+
|
|
95
|
+
- **Advection** by an imposed velocity $`v`$ adds $`v \cdot c_i`$ to every mobile species' flux.
|
|
96
|
+
- **Eddy mixing** adds $`-(D_{\mathrm{mix}}/RT) P \nabla\bar\mu`$, with
|
|
97
|
+
$`P = C - C z z^\mathsf{T} C / (z^\mathsf{T} C z)`$ and $`C = \mathrm{diag}(c)`$.
|
|
98
|
+
- It's an Onsager term: symmetric, positive semi-definite, and zero at equilibrium (flat
|
|
99
|
+
$`\bar\mu`$), so double layers at rest are untouched.
|
|
100
|
+
- The projection removes any current ($`z^\mathsf{T} P = 0`$). Eddies move neutral fluid, so
|
|
101
|
+
they mix salt and stir concentration gradients but conduct nothing.
|
|
102
|
+
- For a neutral dilute species it's exactly $`-D_{\mathrm{mix}} \nabla c`$. For a binary salt it
|
|
103
|
+
adds $`D_{\mathrm{mix}}`$ to the salt's ambipolar diffusivity and leaves diffusion potentials
|
|
104
|
+
unchanged.
|
|
105
|
+
|
|
106
|
+
## Materials, regions, interfaces
|
|
107
|
+
|
|
108
|
+
A **material** holds bulk properties ($`\varepsilon`$, and $`D`$, $`\mu^\circ`$, $`c_{\mathrm{ref}}`$ per
|
|
109
|
+
species). A **region** is a material plus a length, fixed charge and initial composition. Every
|
|
110
|
+
**interface** between different materials takes exactly one alignment (see principle 3), unless
|
|
111
|
+
its electrostatic law is `neutral`, in which case the alignment has no effect and is not allowed.
|
|
112
|
+
The three laws:
|
|
113
|
+
|
|
114
|
+
- `pinned`: $`\phi`$ jumps by exactly the alignment, and the double layers on either side are
|
|
115
|
+
resolved by the grid.
|
|
116
|
+
- `neutral`: the macroscopic idealisation. No charge sits at the face, and $`\phi`$ jumps by
|
|
117
|
+
whatever local neutrality on each side requires (a Donnan or Galvani step).
|
|
118
|
+
- `capacitive`: a Helmholtz layer of capacitance $`C`$, charged by any departure of the jump
|
|
119
|
+
from the alignment.
|
|
120
|
+
|
|
121
|
+
A **conductor** (a metal, or a fast ion conductor) is a material of its own kind: its one level
|
|
122
|
+
is its carrier's (a metal's Fermi level), it has no $`\phi`$, and a face beside it ties the other
|
|
123
|
+
side's $`\phi`$ to that level through a capacitance (see the
|
|
124
|
+
[device reference](device.md#faces-next-to-a-conductor)).
|
|
125
|
+
|
|
126
|
+
A face between a strictly neutral ($`\varepsilon = 0`$) material and one with $`\varepsilon > 0`$,
|
|
127
|
+
such as an electrode and an electrolyte, is naturally `pinned`. The neutral side holds the
|
|
128
|
+
surface charge, and the alignment plays the role of a potential of zero charge or work function.
|
|
129
|
+
|
|
130
|
+
## Contacts and terminals
|
|
131
|
+
|
|
132
|
+
A contact is an interface with an **outside phase** whose levels are known, like one more region
|
|
133
|
+
with a fully known node. The outside phase's charged levels form a rigid ladder,
|
|
134
|
+
$`V_i = V + \mathtt{offset}_i`$, which the external circuit slides by the **terminal voltage** $`V`$
|
|
135
|
+
(the voltage of a named terminal species). The laws joining it to the device (equilibrium,
|
|
136
|
+
blocked, conductance; and for $`\phi`$, bulk, neutral, capacitive, dipole) are the same as at
|
|
137
|
+
internal faces. Reactions sit at faces between regions: an electrode is a conductor region with
|
|
138
|
+
reactions at its face.
|
|
139
|
+
|
|
140
|
+
- **Species in equilibrium** with the outside phase sit at $`V_i = V + \mathtt{offset}_i`$. The
|
|
141
|
+
offset belongs to the outside phase: it's the chemical potential, per charge, of whatever
|
|
142
|
+
neutral combination the species forms with the terminal species there. It's 0 for the
|
|
143
|
+
terminal species itself. For an ion at a reversible electrode,
|
|
144
|
+
$`\mathrm{M}^{n+} + n\,\mathrm{e}^- \rightleftharpoons \mathrm{M(s)}`$ gives
|
|
145
|
+
$`\mu_{\mathrm{M}}/(nF)`$, which is 0 on the usual table convention: $`E^\circ`$ is carried by the
|
|
146
|
+
ion's $`\mu^\circ`$ in the solution, not by the offset. It's never defaulted for any other
|
|
147
|
+
species. Neutral species are fixed by an absolute $`\bar\mu`$.
|
|
148
|
+
- **Ohmic contacts** to a semiconductor are just $`V_{\mathrm{e}^-}`$ and/or $`V_{\mathrm{h}^+}`$ in
|
|
149
|
+
equilibrium with the metal:
|
|
150
|
+
- both, at the same metal, gives $`V_{\mathrm{h}^+} = V_{\mathrm{e}^-}`$, an
|
|
151
|
+
infinite-recombination contact ($`n \cdot p = n_i^2`$ there);
|
|
152
|
+
- one alone gives a selective contact.
|
|
153
|
+
- **Baths** are a shorthand. From a neutral composition and a reference species (the ion a
|
|
154
|
+
reversible reference electrode would sense, e.g. Cl⁻ for Ag/AgCl), driftlet works out every
|
|
155
|
+
species' equilibrium level.
|
|
156
|
+
- **Gates and Stern layers** are capacitive $`\phi`$ laws to a conductor at the terminal voltage.
|
|
157
|
+
Their `zeroCharge` is the value of $`V - \phi_{\mathrm{edge}}`$ at which the interface is
|
|
158
|
+
uncharged. For an electrode in a solution with table $`\mu^\circ`$ (where $`V - \phi`$ reads
|
|
159
|
+
against SHE) that's the potential of zero charge; for a gate it sets the flat-band voltage,
|
|
160
|
+
$`V_{\mathrm{FB}} = \mathtt{zeroCharge} + \phi_{\mathrm{bulk}}`$, with $`\phi_{\mathrm{bulk}}`$ in
|
|
161
|
+
the semiconductor's own anchoring (−1.00 V in p-type silicon at 1e17 cm⁻³ with
|
|
162
|
+
$`\mu^\circ_{\mathrm{e}^-} = 0`$). Like every alignment, it's a property of that interface. The
|
|
163
|
+
`pinned` law is the $`C \to \infty`$ limit (e.g. a Schottky barrier), which is what a
|
|
164
|
+
"fixed $`\phi`$" boundary honestly means.
|
|
165
|
+
- **`bulk`** says the end node is plain bulk (locally neutral, no double layer), while
|
|
166
|
+
**`neutral`** says no charge sits at the face ($`D = 0`$), as for internal faces.
|
|
167
|
+
- **Electrode reactions** take their electrons from the conductor region at its Fermi level,
|
|
168
|
+
which the contact behind it holds at $`\bar\mu_{\mathrm{e}^-} = -F \cdot V`$.
|
|
169
|
+
|
|
170
|
+
The electronic level of a standard hydrogen electrode in a solution is
|
|
171
|
+
$`V^\circ_{\mathrm{e}^-}(\mathrm{SHE}) = \phi + (\mu^\circ_{\mathrm{H}^+} - \tfrac{1}{2}\mu^\circ_{\mathrm{H_2}})/F`$.
|
|
172
|
+
The usual tables set $`\mu^\circ_{\mathrm{H}^+} = 0`$ (so that $`E^\circ(\mathrm{SHE}) = 0`$) and
|
|
173
|
+
$`\mu^\circ_{\mathrm{H_2}} = 0`$ for the element in its standard state, and then
|
|
174
|
+
$`V^\circ_{\mathrm{e}^-}(\mathrm{SHE}) = \phi`$. So with ion $`\mu^\circ`$ from such tables, $`V - \phi`$
|
|
175
|
+
in a solution is a potential against SHE. A metal's $`V - \phi_{\mathrm{edge}}`$ at zero charge (a
|
|
176
|
+
`zeroCharge`, i.e. a pzc) reads directly on the SHE scale.
|
|
177
|
+
|
|
178
|
+
## Terminals and signs
|
|
179
|
+
|
|
180
|
+
- A terminal's voltage $`V`$ is the shift of its outside phase's ladder, measured as the voltage of
|
|
181
|
+
its terminal species. Every voltage is absolute (no terminal is special), and at least one
|
|
182
|
+
terminal must be held at one.
|
|
183
|
+
- **A terminal's current is into the device** (conduction plus displacement), so in steady
|
|
184
|
+
state they sum to zero. $`V \cdot I`$ is the electrical work done through it; an outside phase
|
|
185
|
+
that exchanges several species also trades chemical free energy through its offsets.
|
|
186
|
+
- **`current` is positive toward +x** through the device (into it at the left, out at the
|
|
187
|
+
right). A forward-biased pn junction with its p side on the right carries negative current.
|
|
188
|
+
- `terminalVoltage` is $`V_{\mathrm{right}} - V_{\mathrm{left}}`$.
|
|
189
|
+
|
|
190
|
+
## Units
|
|
191
|
+
|
|
192
|
+
SI throughout: m, mol/m³, J/mol, V, A/m², F/m² (per-area capacitance), C/m³ (fixed charge),
|
|
193
|
+
C/m² (sheet charge), S/m² (interface conductance), mol/(m²·s) (surface rate constants),
|
|
194
|
+
s. Temperature is uniform (default 298.15 K).
|
package/docs/data.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Data library
|
|
2
|
+
|
|
3
|
+
`driftlet/kit` carries a small library of bulk properties, each with its source, so a demo can
|
|
4
|
+
start from vetted numbers. It's kept small on purpose, because a wrong library number is worse
|
|
5
|
+
than a wrong demo number. The ions and semiconductors are checked in the tests against
|
|
6
|
+
independent tables: $`\mu^\circ`$ against the electrochemical series, D against limiting conductivities,
|
|
7
|
+
band data against the quoted intrinsic concentrations.
|
|
8
|
+
|
|
9
|
+
The library holds **bulk properties only**. How levels line up at an interface, a surface's
|
|
10
|
+
work function, a pzc and rate constants all belong to a particular interface or surface, so
|
|
11
|
+
you give them yourself (see [conventions](conventions.md)).
|
|
12
|
+
|
|
13
|
+
## Aqueous ions, 25 °C
|
|
14
|
+
|
|
15
|
+
`aqueous(names, { epsr, material })` returns water holding the named ions, as a library piece
|
|
16
|
+
for `build()`: each ion a species with $`c_{\mathrm{ref}}`$ = 1000 mol/m³ (1 M), and the material
|
|
17
|
+
`water` with its D and $`\mu^\circ`$. `epsr` defaults to water's 78.30 at 25 °C (Malmberg and
|
|
18
|
+
Maryott 1956); `epsr: 0` makes the solution strictly neutral, for macroscopic models without
|
|
19
|
+
double layers. The data are in `IONS`, and $`\mu^\circ`$ of liquid water is `H2O`
|
|
20
|
+
(−237.129 kJ/mol), for reactions such as H₂O ⇌ H⁺ + OH⁻.
|
|
21
|
+
|
|
22
|
+
| Ion | z | D (10⁻⁹ m²/s) | $`\mu^\circ`$ (kJ/mol) |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| H+ | +1 | 9.311 | 0 |
|
|
25
|
+
| Li+ | +1 | 1.029 | −293.31 |
|
|
26
|
+
| Na+ | +1 | 1.334 | −261.905 |
|
|
27
|
+
| K+ | +1 | 1.957 | −283.27 |
|
|
28
|
+
| Ag+ | +1 | 1.648 | 77.107 |
|
|
29
|
+
| Cu2+ | +2 | 0.714 | 65.49 |
|
|
30
|
+
| Zn2+ | +2 | 0.703 | −147.06 |
|
|
31
|
+
| Fe2+ | +2 | 0.719 | −78.9 |
|
|
32
|
+
| Fe3+ | +3 | 0.604 | −4.7 |
|
|
33
|
+
| OH- | −1 | 5.273 | −157.244 |
|
|
34
|
+
| Cl- | −1 | 2.032 | −131.228 |
|
|
35
|
+
| NO3- | −1 | 1.902 | −111.25 |
|
|
36
|
+
| SO42- | −2 | 1.065 | −744.53 |
|
|
37
|
+
|
|
38
|
+
- **D**: diffusivities at infinite dilution, from the CRC Handbook of Chemistry and Physics,
|
|
39
|
+
"Ionic conductivity and diffusion at infinite dilution". They're limiting values, so at
|
|
40
|
+
real concentrations ions move somewhat slower.
|
|
41
|
+
- **$`\mu^\circ`$**: standard Gibbs energies of formation, from Wagman et al., "The NBS tables of
|
|
42
|
+
chemical thermodynamic properties" (J. Phys. Chem. Ref. Data 11, Suppl. 2, 1982), on the usual
|
|
43
|
+
table convention: $`\Delta_{\mathrm{f}} G^\circ(\mathrm{H}^+) = 0`$ and elements in their standard
|
|
44
|
+
states at 0. With these $`\mu^\circ`$, the electronic level of a standard hydrogen electrode in
|
|
45
|
+
the solution is $`\phi`$ itself (see [conventions](conventions.md)), so $`V - \phi`$ reads against
|
|
46
|
+
SHE.
|
|
47
|
+
- **Standard state**: the tables use 1 mol/kg, and the library uses 1 M. In dilute water at 25 °C
|
|
48
|
+
they differ by 0.3%, about 7 J/mol in $`\mu^\circ`$.
|
|
49
|
+
- **Iron**: Fe²⁺'s $`\Delta_{\mathrm{f}} G^\circ`$ gives $`E^\circ(\mathrm{Fe}^{2+}/\mathrm{Fe})`$ =
|
|
50
|
+
−0.41 V, where the CRC series lists −0.447 V; sources disagree on iron. The difference between
|
|
51
|
+
Fe³⁺ and Fe²⁺ gives $`E^\circ(\mathrm{Fe}^{3+}/\mathrm{Fe}^{2+})`$ = 0.769 V, against the
|
|
52
|
+
tabulated 0.771 V, which is what a Fe³⁺/Fe²⁺ redox demo needs.
|
|
53
|
+
|
|
54
|
+
## Semiconductors, 300 K
|
|
55
|
+
|
|
56
|
+
`semiconductor(name, { material })` returns electrons `e-` and holes `h+` and the material:
|
|
57
|
+
$`c_{\mathrm{ref}} = N_c`$ and $`N_v`$, D from the mobilities by the Einstein relation at 300 K,
|
|
58
|
+
$`\mu^\circ_{\mathrm{e}^-} = 0`$ (so $`\phi`$ sits at the conduction band) and
|
|
59
|
+
$`\mu^\circ_{\mathrm{h}^+} = E_g \cdot F`$. The data are for 300 K, so give the device `T: 300`.
|
|
60
|
+
Statistics are ideal (Boltzmann); add Fermi–Dirac statistics to the material for degenerate
|
|
61
|
+
doping. The data are in `SEMICONDUCTORS`, in the source's units (cm⁻³, cm²/(V·s), eV).
|
|
62
|
+
|
|
63
|
+
| | $`\varepsilon_r`$ | $`E_g`$ (eV) | $`\chi`$ (V) | $`N_c`$ (cm⁻³) | $`N_v`$ (cm⁻³) | $`\mu_n`$ (cm²/(V·s)) | $`\mu_p`$ (cm²/(V·s)) |
|
|
64
|
+
|---|---|---|---|---|---|---|---|
|
|
65
|
+
| Si | 11.9 | 1.12 | 4.05 | 2.8 × 10¹⁹ | 1.04 × 10¹⁹ | 1500 | 450 |
|
|
66
|
+
| Ge | 16.0 | 0.66 | 4.0 | 1.04 × 10¹⁹ | 6.0 × 10¹⁸ | 3900 | 1900 |
|
|
67
|
+
| GaAs | 13.1 | 1.424 | 4.07 | 4.7 × 10¹⁷ | 7.0 × 10¹⁸ | 8500 | 400 |
|
|
68
|
+
|
|
69
|
+
- Source: Sze, *Physics of Semiconductor Devices*, 2nd ed. (1981), appendix "Properties of Ge,
|
|
70
|
+
Si and GaAs at 300 K". The mobilities are for lightly doped material.
|
|
71
|
+
- The electron affinity $`\chi`$ is for vacuum-level estimates with `vacuumDipole` (anchor `'e-'`,
|
|
72
|
+
see the [alignment guide](alignment.md)). It isn't used otherwise, since an alignment is never
|
|
73
|
+
implied.
|
|
74
|
+
- **Silicon's intrinsic concentration**: these $`N_c`$, $`N_v`$ and $`E_g`$ give $`n_i`$ = 6.7 × 10⁹ cm⁻³.
|
|
75
|
+
Sze quotes 1.45 × 10¹⁰ (an older measurement), and the accepted value is 9.65 × 10⁹. The
|
|
76
|
+
library keeps the band data self-consistent rather than matching a quoted $`n_i`$. For Ge and
|
|
77
|
+
GaAs, the data reproduce the quoted $`n_i`$ (2.4 × 10¹³ and 1.79 × 10⁶) to within 10–15%.
|
|
78
|
+
|
|
79
|
+
## Metals, 20 °C
|
|
80
|
+
|
|
81
|
+
`metal(name, { material })` returns a conductor material carrying `e-`, with its conductivity
|
|
82
|
+
$`1/\rho`$ from the CRC Handbook's resistivities of pure metals at 293 K ("Electrical resistivity of
|
|
83
|
+
pure metals"). The data are in `METALS`, as `rho` (10⁻⁸ Ω·m) and `conductivity` (S/m). They
|
|
84
|
+
aren't cross-checked against a second table in the tests; a metal's conductivity only sets the
|
|
85
|
+
ohmic drop inside it, which is usually negligible.
|
|
86
|
+
|
|
87
|
+
| | Ag | Cu | Au | Al | Zn | Li | Pt |
|
|
88
|
+
|---|---|---|---|---|---|---|---|
|
|
89
|
+
| $`\rho`$ (10⁻⁸ Ω·m) | 1.587 | 1.678 | 2.214 | 2.65 | 5.90 | 9.28 | 10.5 |
|
|
90
|
+
| $`\sigma`$ (10⁷ S/m) | 6.30 | 5.96 | 4.52 | 3.77 | 1.69 | 1.08 | 0.952 |
|
|
91
|
+
|
|
92
|
+
There are no work functions: a work function belongs to a surface, not a metal, and it varies
|
|
93
|
+
by facet and adsorbate. Give a face's `zeroCharge` (or use `vacuumZeroCharge` with a work
|
|
94
|
+
function you've chosen for that surface).
|
|
95
|
+
|
|
96
|
+
## Example
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
import { Device } from 'driftlet';
|
|
100
|
+
import { build, layer, ohmic, half, level, SHE, aqueous, metal } from 'driftlet/kit';
|
|
101
|
+
|
|
102
|
+
// A platinum electrode in Fe³⁺/Fe²⁺ chloride at equilibrium: its Fermi level sits at the
|
|
103
|
+
// couple's redox level, E° against SHE when the two are equal: 0.769 V from the library's NBS values (tables list 0.771 V).
|
|
104
|
+
const iron = half('Fe3+ + e- = Fe2+');
|
|
105
|
+
const def = build({
|
|
106
|
+
library: [aqueous(['H+', 'Fe3+', 'Fe2+', 'Cl-'], { epsr: 0 }), metal('Pt')],
|
|
107
|
+
stack: [
|
|
108
|
+
ohmic(0, ['e-']),
|
|
109
|
+
layer('Pt', 1e-6),
|
|
110
|
+
{ reactions: [{ ...iron, k0: 1e-3 }] },
|
|
111
|
+
layer('water', 1e-6, { c0: { 'H+': 100, 'Fe3+': 10, 'Fe2+': 10, 'Cl-': 150 } }),
|
|
112
|
+
{ reactions: [{ ...iron, k0: 1e-3 }] },
|
|
113
|
+
layer('Pt', 1e-6),
|
|
114
|
+
ohmic(0, ['e-']),
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
const sol = new Device(def).solve();
|
|
118
|
+
const g = sol.x.length >> 1;
|
|
119
|
+
console.log(`V_e(Pt) − V°(SHE) = ${(sol.V['e-'][0] - level(sol, SHE, { standard: true })[g]).toFixed(4)} V`);
|
|
120
|
+
```
|