hetero1d 0.1.0__tar.gz
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.
Potentially problematic release.
This version of hetero1d might be problematic. Click here for more details.
- hetero1d-0.1.0/LICENSE +21 -0
- hetero1d-0.1.0/PKG-INFO +273 -0
- hetero1d-0.1.0/README.md +250 -0
- hetero1d-0.1.0/pyproject.toml +34 -0
- hetero1d-0.1.0/setup.cfg +4 -0
- hetero1d-0.1.0/src/hetero1d/__init__.py +21 -0
- hetero1d-0.1.0/src/hetero1d/core.py +1052 -0
- hetero1d-0.1.0/src/hetero1d/examples.py +87 -0
- hetero1d-0.1.0/src/hetero1d.egg-info/PKG-INFO +273 -0
- hetero1d-0.1.0/src/hetero1d.egg-info/SOURCES.txt +13 -0
- hetero1d-0.1.0/src/hetero1d.egg-info/dependency_links.txt +1 -0
- hetero1d-0.1.0/src/hetero1d.egg-info/entry_points.txt +2 -0
- hetero1d-0.1.0/src/hetero1d.egg-info/requires.txt +6 -0
- hetero1d-0.1.0/src/hetero1d.egg-info/top_level.txt +1 -0
- hetero1d-0.1.0/tests/test_basic.py +31 -0
hetero1d-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ravi Kumar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
hetero1d-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hetero1d
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 1D semiconductor heterostructure solver: quantum wells, superlattices, electric and magnetic fields
|
|
5
|
+
Author-email: Ravi Kumar <rkravi365@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/erw-del/hetero1d
|
|
8
|
+
Keywords: semiconductor,quantum well,heterostructure,superlattice,Schrodinger,Poisson,physics
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: numpy>=1.20
|
|
18
|
+
Requires-Dist: scipy>=1.7
|
|
19
|
+
Requires-Dist: matplotlib>=3.3
|
|
20
|
+
Provides-Extra: test
|
|
21
|
+
Requires-Dist: pytest; extra == "test"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# hetero1d
|
|
25
|
+
|
|
26
|
+
**A complete 1D semiconductor heterostructure solver in Python.**
|
|
27
|
+
Design quantum wells, multiple wells, superlattices or any layer stack from
|
|
28
|
+
III-V materials and compute electronic, optical, transport and magneto-optical
|
|
29
|
+
properties: under electric and magnetic fields, at any temperature, with or
|
|
30
|
+
without doping.
|
|
31
|
+
|
|
32
|
+
Method: effective-mass envelope-function approximation, BenDaniel-Duke
|
|
33
|
+
finite differences with position-dependent mass.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What it can compute
|
|
38
|
+
|
|
39
|
+
| Category | Quantities |
|
|
40
|
+
|---|---|
|
|
41
|
+
| **Structure** | Band profile Ec(z), Ev(z); band gaps, offsets, masses, g-factors of every layer; lattice-mismatch warning |
|
|
42
|
+
| **Quantum states** | Electron, heavy-hole and light-hole subband energies and wavefunctions; bound/continuum classification |
|
|
43
|
+
| **State analysis** | Probability in each layer, mean position ⟨z⟩, spatial spread, effective mass of each state |
|
|
44
|
+
| **Intersubband optics** | Transition energies and wavelengths, dipole matrix elements z_ij, oscillator strengths, **absolute absorption spectrum** (per pass) |
|
|
45
|
+
| **Interband optics** | e-hh and e-lh transition energies and wavelengths, electron-hole overlaps, absorption spectrum (TE) |
|
|
46
|
+
| **Carrier statistics** | 2D density of states, Fermi level, population of each subband (Fermi-Dirac, any temperature) |
|
|
47
|
+
| **Scattering** | LO-phonon intersubband scattering rates and lifetimes (Fröhlich interaction) |
|
|
48
|
+
| **Transport / tunnelling** | Transmission coefficient T(E), resonant tunnelling, resonance widths |
|
|
49
|
+
| **Superlattices** | Miniband energies and widths, Bloch dispersion E(q) |
|
|
50
|
+
| **Doped structures** | Self-consistent Schrödinger-Poisson: band bending, electron density, Fermi level |
|
|
51
|
+
| **Electric field** | Stark shifts, quantum-confined Stark effect (QCSE), field-dependent overlaps, dipoles and intersubband energies |
|
|
52
|
+
| **Magnetic field ∥ z** | Landau levels, spin Zeeman splitting, Landau fan, Landau-level DOS, filling factor, Fermi level vs B (Shubnikov-de Haas-like oscillations) |
|
|
53
|
+
| **Magnetic field ∥ plane** | Diamagnetic shift, in-plane dispersion E_n(k_y) |
|
|
54
|
+
| **Materials** | 12 binaries, 17 ternaries, 4 quaternaries, temperature-dependent band gaps, lattice matching, user-defined materials |
|
|
55
|
+
|
|
56
|
+
**Materials included**
|
|
57
|
+
- Binaries: GaAs, AlAs, InAs, InP, GaSb, AlSb, GaP, AlP, InSb, GaN, AlN, InN (nitrides: zinc-blende, approximate)
|
|
58
|
+
- Ternaries: AlGaAs, InGaAs, InAlAs, GaAsSb, AlGaSb, InGaP, InAsSb, InGaSb, InAlSb, AlAsSb, InAsP, GaAsP, AlGaP, InAlP, AlGaN, InGaN, InAlN
|
|
59
|
+
- Quaternaries: InGaAsP, InGaAsSb, AlGaInAs, AlGaInP
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
Directly from GitHub:
|
|
65
|
+
```bash
|
|
66
|
+
pip install git+https://github.com/erw-del/hetero1d.git
|
|
67
|
+
```
|
|
68
|
+
or download the code, then inside the folder:
|
|
69
|
+
```bash
|
|
70
|
+
pip install -e .
|
|
71
|
+
```
|
|
72
|
+
Requires Python ≥ 3.8, numpy, scipy, matplotlib (installed automatically).
|
|
73
|
+
|
|
74
|
+
Run all built-in examples (saves 8 figures):
|
|
75
|
+
```bash
|
|
76
|
+
hetero1d-demo
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Quick start
|
|
82
|
+
```python
|
|
83
|
+
import numpy as np
|
|
84
|
+
from hetero1d import Structure, Solver
|
|
85
|
+
|
|
86
|
+
# Al0.3Ga0.7As 40 nm | GaAs 20 nm | Al0.3Ga0.7As 40 nm
|
|
87
|
+
s = Structure.single_well(well="GaAs", barrier=("AlGaAs", 0.3), Lw=20, Lb=40)
|
|
88
|
+
s.describe() # band edges, masses, g-factors of each layer
|
|
89
|
+
|
|
90
|
+
sol = Solver(s, T=300).solve(n_e=6, n_h=6)
|
|
91
|
+
sol.report(n2d_cm2=5e11) # all results as tables
|
|
92
|
+
sol.plot_summary("result.png") # 6-panel figure
|
|
93
|
+
```
|
|
94
|
+
Energies are on an absolute scale (GaAs conduction-band edge = 0.6225 eV at 300 K).
|
|
95
|
+
The report's "E-edge" column gives each level measured from the well bottom.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 1. Building structures
|
|
100
|
+
|
|
101
|
+
Change `Lw` (well width) and `Lb` (barrier width), in nm.
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# single well
|
|
105
|
+
s = Structure.single_well(well="GaAs", barrier=("AlGaAs", 0.3), Lw=20, Lb=40)
|
|
106
|
+
|
|
107
|
+
# several wells with different widths (Lb = inner barriers, Lb_out = outer barriers)
|
|
108
|
+
s = Structure.multi_well(3, well="GaAs", barrier=("AlGaAs", 0.3),
|
|
109
|
+
Lw=[15, 10, 20], Lb=[5, 8], Lb_out=30)
|
|
110
|
+
|
|
111
|
+
# superlattice, 10 periods
|
|
112
|
+
s = Structure.superlattice(10, well="GaAs", barrier=("AlGaAs", 0.3), Lw=5, Lb=2)
|
|
113
|
+
|
|
114
|
+
# any layer stack, layer by layer (thickness nm, optional doping cm^-3)
|
|
115
|
+
s = Structure()
|
|
116
|
+
s.add("AlGaAs", 40, x=0.3).add("GaAs", 20).add("AlGaAs", 5, x=0.3)
|
|
117
|
+
s.add("GaAs", 10).add("AlGaAs", 40, x=0.3, doping=1e17)
|
|
118
|
+
|
|
119
|
+
# other materials and substrates
|
|
120
|
+
s = Structure.single_well(well=("InGaAs", 0.53), barrier=("InAlAs", 0.52),
|
|
121
|
+
Lw=8, Lb=20, substrate="InP")
|
|
122
|
+
|
|
123
|
+
# quaternary: Ga_x In_(1-x) As_y P_(1-y)
|
|
124
|
+
s = Structure.single_well(well=("InGaAsP", 0.39, 0.85), barrier="InP",
|
|
125
|
+
Lw=8, Lb=20, substrate="InP")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 2. Materials
|
|
129
|
+
```python
|
|
130
|
+
from hetero1d import material, list_materials, lattice_matched, add_material
|
|
131
|
+
|
|
132
|
+
list_materials() # all materials and what x, y mean
|
|
133
|
+
m = material("AlGaAs", x=0.3, T=300) # all parameters as a dict
|
|
134
|
+
print(m["Eg"], m["Ec"], m["Ev"], m["me"], m["g"])
|
|
135
|
+
|
|
136
|
+
x = lattice_matched("InGaAs", "InP") # -> 0.534
|
|
137
|
+
x = lattice_matched("InGaAsP", "InP", fixed=("y", 0.85))
|
|
138
|
+
|
|
139
|
+
add_material("MyMat", Ec=0.70, Ev=-0.75, me=0.07, mhh=0.4, mlh=0.08, eps_s=12.5)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 3. Energies, wavefunctions and state analysis
|
|
143
|
+
```python
|
|
144
|
+
sol = Solver(s, T=300).solve(n_e=6, n_h=6)
|
|
145
|
+
|
|
146
|
+
sol.Ee, sol.psi_e # electron energies (eV) and wavefunctions on grid sol.z (nm)
|
|
147
|
+
sol.Ehh, sol.psi_hh # heavy holes
|
|
148
|
+
sol.Elh, sol.psi_lh # light holes
|
|
149
|
+
sol.e_bound # True for bound states
|
|
150
|
+
E_meV = (sol.Ee - sol.Ec.min()) * 1000 # energies above the well bottom
|
|
151
|
+
|
|
152
|
+
sol.layer_probabilities(sol.psi_e[:, 0]) # probability in each layer
|
|
153
|
+
zmean, spread = sol.expect_z(sol.psi_e[:, 0]) # <z> and spatial spread (nm)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Save to CSV** (opens in Excel / Origin):
|
|
157
|
+
```python
|
|
158
|
+
data = np.column_stack([sol.z, sol.Ec, sol.Ev, sol.psi_e, sol.psi_hh])
|
|
159
|
+
header = "z_nm,Ec_eV,Ev_eV," + \
|
|
160
|
+
",".join(f"psi_e{i}" for i in range(sol.psi_e.shape[1])) + "," + \
|
|
161
|
+
",".join(f"psi_hh{i}" for i in range(sol.psi_hh.shape[1]))
|
|
162
|
+
np.savetxt("wavefunctions.csv", data, delimiter=",", header=header, comments="")
|
|
163
|
+
|
|
164
|
+
np.savetxt("energies.csv",
|
|
165
|
+
np.column_stack([np.arange(len(E_meV)), sol.Ee, E_meV, sol.e_bound]),
|
|
166
|
+
delimiter=",", header="n,E_eV,E_above_well_meV,bound", comments="")
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 4. Intersubband optics (quantum-well infrared photodetectors, cascade lasers)
|
|
170
|
+
```python
|
|
171
|
+
for t in sol.intersubband(): # i, j, dE (eV), lam_um, z (nm), f
|
|
172
|
+
print(t["i"], "->", t["j"], t["dE"]*1000, "meV", t["lam_um"], "um", "f =", t["f"])
|
|
173
|
+
|
|
174
|
+
E = np.linspace(0.01, 0.3, 1000) # photon energy (eV)
|
|
175
|
+
A = sol.isb_absorption(E, n2d_cm2=5e11, gamma=0.005) # absorption per pass (fraction)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## 5. Interband optics (lasers, LEDs, photoluminescence)
|
|
179
|
+
```python
|
|
180
|
+
for t in sol.interband()[:5]: # e, h, band ('hh'/'lh'), E (eV), lam_nm, overlap2
|
|
181
|
+
print(f"e{t['e']}-{t['band']}{t['h']}: {t['E']:.4f} eV, {t['lam_nm']:.1f} nm")
|
|
182
|
+
|
|
183
|
+
E = np.linspace(1.4, 1.7, 1000)
|
|
184
|
+
A = sol.interband_absorption(E, gamma=0.005) # relative units
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 6. Carrier statistics
|
|
188
|
+
```python
|
|
189
|
+
EF, populations = sol.fermi_level(5e11) # Fermi level (eV), cm^-2 in each subband
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 7. LO-phonon scattering
|
|
193
|
+
```python
|
|
194
|
+
for t in sol.lo_phonon_rates(): # i, f, dE, rate (1/s), tau_ps
|
|
195
|
+
print(t["i"], "->", t["f"], f"{t['tau_ps']:.3f} ps")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 8. Tunnelling and transmission
|
|
199
|
+
```python
|
|
200
|
+
rtd = Structure() # double-barrier resonant tunnelling diode
|
|
201
|
+
rtd.add("GaAs", 20).add("AlGaAs", 5, x=0.3).add("GaAs", 6).add("AlGaAs", 5, x=0.3).add("GaAs", 20)
|
|
202
|
+
r = Solver(rtd, dz=0.02)
|
|
203
|
+
E = np.linspace(0.67, 0.70, 20000)
|
|
204
|
+
T = r.transmission(E) # T(E) between 0 and 1
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## 9. Superlattice minibands
|
|
208
|
+
```python
|
|
209
|
+
sl = Structure.superlattice(10, well="GaAs", barrier=("AlGaAs", 0.3), Lw=5, Lb=2)
|
|
210
|
+
q, d, bands = Solver(sl).minibands(np.linspace(0.62, 1.22, 6000))
|
|
211
|
+
print(bands) # list of (E_min, E_max) for each miniband
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 10. Doped structures: Schrödinger-Poisson
|
|
215
|
+
```python
|
|
216
|
+
s = Structure()
|
|
217
|
+
s.add("AlGaAs", 30, x=0.3).add("AlGaAs", 10, x=0.3, doping=3e17).add("AlGaAs", 10, x=0.3)
|
|
218
|
+
s.add("GaAs", 15).add("AlGaAs", 10, x=0.3).add("AlGaAs", 10, x=0.3, doping=3e17).add("AlGaAs", 30, x=0.3)
|
|
219
|
+
sol = Solver(s, T=77).schrodinger_poisson()
|
|
220
|
+
sol.solve()
|
|
221
|
+
sol.VH, sol.n3d, sol.EF # Hartree potential, electron density, Fermi level
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## 11. Electric field
|
|
225
|
+
```python
|
|
226
|
+
sol = Solver(s, field=50).solve() # 50 kV/cm along z
|
|
227
|
+
r = sol.stark_sweep(np.linspace(-80, 80, 33)) # dict: E_e0hh0, ov_e0hh0, E01, z01, ...
|
|
228
|
+
sol.plot_stark("stark.png", np.linspace(-80, 80, 33)) # QCSE, overlap, intersubband vs field
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## 12. Magnetic field
|
|
232
|
+
```python
|
|
233
|
+
# B along the growth axis: Landau levels and Zeeman splitting
|
|
234
|
+
sol = Solver(s, T=4.2, Bz=5).solve()
|
|
235
|
+
sol.g_factor(0) # electron g-factor of subband 0
|
|
236
|
+
sol.zeeman() # spin splitting of each subband (eV)
|
|
237
|
+
sol.landau_levels(N_max=10) # list of Landau levels
|
|
238
|
+
sol.fermi_level_B(3e11) # Fermi level in the field
|
|
239
|
+
sol.plot_magnetic("landau.png", np.linspace(0.5, 10, 200), n2d_cm2=3e11)
|
|
240
|
+
|
|
241
|
+
# B in the layer plane: diamagnetic shift and dispersion
|
|
242
|
+
sol = Solver(s, T=4.2, Bpar=10).solve()
|
|
243
|
+
E_ky = sol.inplane_dispersion(np.linspace(-0.2, 0.2, 41))
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## 13. Other options
|
|
247
|
+
```python
|
|
248
|
+
Solver(s, T=77) # temperature (K), band gaps follow Varshni law
|
|
249
|
+
Solver(s, dz=0.05) # finer grid (nm), default 0.1
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Validation
|
|
255
|
+
| Test | Reference | hetero1d |
|
|
256
|
+
|---|---|---|
|
|
257
|
+
| 10 nm GaAs/Al0.3Ga0.7As, E1 | 30.842 meV (exact analytic) | 30.850 meV |
|
|
258
|
+
| Double-barrier resonance | 61.95 meV (well level) | T = 1.0000 at 61.91 meV |
|
|
259
|
+
| In0.53Ga0.47As/In0.52Al0.48As ΔEc | ≈ 0.52 eV (literature) | 0.522 eV |
|
|
260
|
+
| Landau spacing, 5 T | ħeB/m* | exact |
|
|
261
|
+
| In-plane diamagnetic shift, 1 T | 2nd-order perturbation theory | 0.0235 meV (identical) |
|
|
262
|
+
|
|
263
|
+
## Model limits
|
|
264
|
+
Single-band effective mass (no k·p band mixing, no non-parabolicity), Γ valley only
|
|
265
|
+
(X/L valleys not included), no strain, nitrides without polarisation fields,
|
|
266
|
+
Zeeman and Landau levels for electrons only.
|
|
267
|
+
|
|
268
|
+
## Parameters
|
|
269
|
+
I. Vurgaftman, J. R. Meyer, L. R. Ram-Mohan, J. Appl. Phys. 89, 5815 (2001);
|
|
270
|
+
nitrides: I. Vurgaftman, J. R. Meyer, J. Appl. Phys. 94, 3675 (2003).
|
|
271
|
+
|
|
272
|
+
## Author
|
|
273
|
+
Ravi Kumar, 2026. MIT License.
|
hetero1d-0.1.0/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# hetero1d
|
|
2
|
+
|
|
3
|
+
**A complete 1D semiconductor heterostructure solver in Python.**
|
|
4
|
+
Design quantum wells, multiple wells, superlattices or any layer stack from
|
|
5
|
+
III-V materials and compute electronic, optical, transport and magneto-optical
|
|
6
|
+
properties: under electric and magnetic fields, at any temperature, with or
|
|
7
|
+
without doping.
|
|
8
|
+
|
|
9
|
+
Method: effective-mass envelope-function approximation, BenDaniel-Duke
|
|
10
|
+
finite differences with position-dependent mass.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What it can compute
|
|
15
|
+
|
|
16
|
+
| Category | Quantities |
|
|
17
|
+
|---|---|
|
|
18
|
+
| **Structure** | Band profile Ec(z), Ev(z); band gaps, offsets, masses, g-factors of every layer; lattice-mismatch warning |
|
|
19
|
+
| **Quantum states** | Electron, heavy-hole and light-hole subband energies and wavefunctions; bound/continuum classification |
|
|
20
|
+
| **State analysis** | Probability in each layer, mean position ⟨z⟩, spatial spread, effective mass of each state |
|
|
21
|
+
| **Intersubband optics** | Transition energies and wavelengths, dipole matrix elements z_ij, oscillator strengths, **absolute absorption spectrum** (per pass) |
|
|
22
|
+
| **Interband optics** | e-hh and e-lh transition energies and wavelengths, electron-hole overlaps, absorption spectrum (TE) |
|
|
23
|
+
| **Carrier statistics** | 2D density of states, Fermi level, population of each subband (Fermi-Dirac, any temperature) |
|
|
24
|
+
| **Scattering** | LO-phonon intersubband scattering rates and lifetimes (Fröhlich interaction) |
|
|
25
|
+
| **Transport / tunnelling** | Transmission coefficient T(E), resonant tunnelling, resonance widths |
|
|
26
|
+
| **Superlattices** | Miniband energies and widths, Bloch dispersion E(q) |
|
|
27
|
+
| **Doped structures** | Self-consistent Schrödinger-Poisson: band bending, electron density, Fermi level |
|
|
28
|
+
| **Electric field** | Stark shifts, quantum-confined Stark effect (QCSE), field-dependent overlaps, dipoles and intersubband energies |
|
|
29
|
+
| **Magnetic field ∥ z** | Landau levels, spin Zeeman splitting, Landau fan, Landau-level DOS, filling factor, Fermi level vs B (Shubnikov-de Haas-like oscillations) |
|
|
30
|
+
| **Magnetic field ∥ plane** | Diamagnetic shift, in-plane dispersion E_n(k_y) |
|
|
31
|
+
| **Materials** | 12 binaries, 17 ternaries, 4 quaternaries, temperature-dependent band gaps, lattice matching, user-defined materials |
|
|
32
|
+
|
|
33
|
+
**Materials included**
|
|
34
|
+
- Binaries: GaAs, AlAs, InAs, InP, GaSb, AlSb, GaP, AlP, InSb, GaN, AlN, InN (nitrides: zinc-blende, approximate)
|
|
35
|
+
- Ternaries: AlGaAs, InGaAs, InAlAs, GaAsSb, AlGaSb, InGaP, InAsSb, InGaSb, InAlSb, AlAsSb, InAsP, GaAsP, AlGaP, InAlP, AlGaN, InGaN, InAlN
|
|
36
|
+
- Quaternaries: InGaAsP, InGaAsSb, AlGaInAs, AlGaInP
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
Directly from GitHub:
|
|
42
|
+
```bash
|
|
43
|
+
pip install git+https://github.com/erw-del/hetero1d.git
|
|
44
|
+
```
|
|
45
|
+
or download the code, then inside the folder:
|
|
46
|
+
```bash
|
|
47
|
+
pip install -e .
|
|
48
|
+
```
|
|
49
|
+
Requires Python ≥ 3.8, numpy, scipy, matplotlib (installed automatically).
|
|
50
|
+
|
|
51
|
+
Run all built-in examples (saves 8 figures):
|
|
52
|
+
```bash
|
|
53
|
+
hetero1d-demo
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick start
|
|
59
|
+
```python
|
|
60
|
+
import numpy as np
|
|
61
|
+
from hetero1d import Structure, Solver
|
|
62
|
+
|
|
63
|
+
# Al0.3Ga0.7As 40 nm | GaAs 20 nm | Al0.3Ga0.7As 40 nm
|
|
64
|
+
s = Structure.single_well(well="GaAs", barrier=("AlGaAs", 0.3), Lw=20, Lb=40)
|
|
65
|
+
s.describe() # band edges, masses, g-factors of each layer
|
|
66
|
+
|
|
67
|
+
sol = Solver(s, T=300).solve(n_e=6, n_h=6)
|
|
68
|
+
sol.report(n2d_cm2=5e11) # all results as tables
|
|
69
|
+
sol.plot_summary("result.png") # 6-panel figure
|
|
70
|
+
```
|
|
71
|
+
Energies are on an absolute scale (GaAs conduction-band edge = 0.6225 eV at 300 K).
|
|
72
|
+
The report's "E-edge" column gives each level measured from the well bottom.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 1. Building structures
|
|
77
|
+
|
|
78
|
+
Change `Lw` (well width) and `Lb` (barrier width), in nm.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# single well
|
|
82
|
+
s = Structure.single_well(well="GaAs", barrier=("AlGaAs", 0.3), Lw=20, Lb=40)
|
|
83
|
+
|
|
84
|
+
# several wells with different widths (Lb = inner barriers, Lb_out = outer barriers)
|
|
85
|
+
s = Structure.multi_well(3, well="GaAs", barrier=("AlGaAs", 0.3),
|
|
86
|
+
Lw=[15, 10, 20], Lb=[5, 8], Lb_out=30)
|
|
87
|
+
|
|
88
|
+
# superlattice, 10 periods
|
|
89
|
+
s = Structure.superlattice(10, well="GaAs", barrier=("AlGaAs", 0.3), Lw=5, Lb=2)
|
|
90
|
+
|
|
91
|
+
# any layer stack, layer by layer (thickness nm, optional doping cm^-3)
|
|
92
|
+
s = Structure()
|
|
93
|
+
s.add("AlGaAs", 40, x=0.3).add("GaAs", 20).add("AlGaAs", 5, x=0.3)
|
|
94
|
+
s.add("GaAs", 10).add("AlGaAs", 40, x=0.3, doping=1e17)
|
|
95
|
+
|
|
96
|
+
# other materials and substrates
|
|
97
|
+
s = Structure.single_well(well=("InGaAs", 0.53), barrier=("InAlAs", 0.52),
|
|
98
|
+
Lw=8, Lb=20, substrate="InP")
|
|
99
|
+
|
|
100
|
+
# quaternary: Ga_x In_(1-x) As_y P_(1-y)
|
|
101
|
+
s = Structure.single_well(well=("InGaAsP", 0.39, 0.85), barrier="InP",
|
|
102
|
+
Lw=8, Lb=20, substrate="InP")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 2. Materials
|
|
106
|
+
```python
|
|
107
|
+
from hetero1d import material, list_materials, lattice_matched, add_material
|
|
108
|
+
|
|
109
|
+
list_materials() # all materials and what x, y mean
|
|
110
|
+
m = material("AlGaAs", x=0.3, T=300) # all parameters as a dict
|
|
111
|
+
print(m["Eg"], m["Ec"], m["Ev"], m["me"], m["g"])
|
|
112
|
+
|
|
113
|
+
x = lattice_matched("InGaAs", "InP") # -> 0.534
|
|
114
|
+
x = lattice_matched("InGaAsP", "InP", fixed=("y", 0.85))
|
|
115
|
+
|
|
116
|
+
add_material("MyMat", Ec=0.70, Ev=-0.75, me=0.07, mhh=0.4, mlh=0.08, eps_s=12.5)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 3. Energies, wavefunctions and state analysis
|
|
120
|
+
```python
|
|
121
|
+
sol = Solver(s, T=300).solve(n_e=6, n_h=6)
|
|
122
|
+
|
|
123
|
+
sol.Ee, sol.psi_e # electron energies (eV) and wavefunctions on grid sol.z (nm)
|
|
124
|
+
sol.Ehh, sol.psi_hh # heavy holes
|
|
125
|
+
sol.Elh, sol.psi_lh # light holes
|
|
126
|
+
sol.e_bound # True for bound states
|
|
127
|
+
E_meV = (sol.Ee - sol.Ec.min()) * 1000 # energies above the well bottom
|
|
128
|
+
|
|
129
|
+
sol.layer_probabilities(sol.psi_e[:, 0]) # probability in each layer
|
|
130
|
+
zmean, spread = sol.expect_z(sol.psi_e[:, 0]) # <z> and spatial spread (nm)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Save to CSV** (opens in Excel / Origin):
|
|
134
|
+
```python
|
|
135
|
+
data = np.column_stack([sol.z, sol.Ec, sol.Ev, sol.psi_e, sol.psi_hh])
|
|
136
|
+
header = "z_nm,Ec_eV,Ev_eV," + \
|
|
137
|
+
",".join(f"psi_e{i}" for i in range(sol.psi_e.shape[1])) + "," + \
|
|
138
|
+
",".join(f"psi_hh{i}" for i in range(sol.psi_hh.shape[1]))
|
|
139
|
+
np.savetxt("wavefunctions.csv", data, delimiter=",", header=header, comments="")
|
|
140
|
+
|
|
141
|
+
np.savetxt("energies.csv",
|
|
142
|
+
np.column_stack([np.arange(len(E_meV)), sol.Ee, E_meV, sol.e_bound]),
|
|
143
|
+
delimiter=",", header="n,E_eV,E_above_well_meV,bound", comments="")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 4. Intersubband optics (quantum-well infrared photodetectors, cascade lasers)
|
|
147
|
+
```python
|
|
148
|
+
for t in sol.intersubband(): # i, j, dE (eV), lam_um, z (nm), f
|
|
149
|
+
print(t["i"], "->", t["j"], t["dE"]*1000, "meV", t["lam_um"], "um", "f =", t["f"])
|
|
150
|
+
|
|
151
|
+
E = np.linspace(0.01, 0.3, 1000) # photon energy (eV)
|
|
152
|
+
A = sol.isb_absorption(E, n2d_cm2=5e11, gamma=0.005) # absorption per pass (fraction)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 5. Interband optics (lasers, LEDs, photoluminescence)
|
|
156
|
+
```python
|
|
157
|
+
for t in sol.interband()[:5]: # e, h, band ('hh'/'lh'), E (eV), lam_nm, overlap2
|
|
158
|
+
print(f"e{t['e']}-{t['band']}{t['h']}: {t['E']:.4f} eV, {t['lam_nm']:.1f} nm")
|
|
159
|
+
|
|
160
|
+
E = np.linspace(1.4, 1.7, 1000)
|
|
161
|
+
A = sol.interband_absorption(E, gamma=0.005) # relative units
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 6. Carrier statistics
|
|
165
|
+
```python
|
|
166
|
+
EF, populations = sol.fermi_level(5e11) # Fermi level (eV), cm^-2 in each subband
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 7. LO-phonon scattering
|
|
170
|
+
```python
|
|
171
|
+
for t in sol.lo_phonon_rates(): # i, f, dE, rate (1/s), tau_ps
|
|
172
|
+
print(t["i"], "->", t["f"], f"{t['tau_ps']:.3f} ps")
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 8. Tunnelling and transmission
|
|
176
|
+
```python
|
|
177
|
+
rtd = Structure() # double-barrier resonant tunnelling diode
|
|
178
|
+
rtd.add("GaAs", 20).add("AlGaAs", 5, x=0.3).add("GaAs", 6).add("AlGaAs", 5, x=0.3).add("GaAs", 20)
|
|
179
|
+
r = Solver(rtd, dz=0.02)
|
|
180
|
+
E = np.linspace(0.67, 0.70, 20000)
|
|
181
|
+
T = r.transmission(E) # T(E) between 0 and 1
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 9. Superlattice minibands
|
|
185
|
+
```python
|
|
186
|
+
sl = Structure.superlattice(10, well="GaAs", barrier=("AlGaAs", 0.3), Lw=5, Lb=2)
|
|
187
|
+
q, d, bands = Solver(sl).minibands(np.linspace(0.62, 1.22, 6000))
|
|
188
|
+
print(bands) # list of (E_min, E_max) for each miniband
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 10. Doped structures: Schrödinger-Poisson
|
|
192
|
+
```python
|
|
193
|
+
s = Structure()
|
|
194
|
+
s.add("AlGaAs", 30, x=0.3).add("AlGaAs", 10, x=0.3, doping=3e17).add("AlGaAs", 10, x=0.3)
|
|
195
|
+
s.add("GaAs", 15).add("AlGaAs", 10, x=0.3).add("AlGaAs", 10, x=0.3, doping=3e17).add("AlGaAs", 30, x=0.3)
|
|
196
|
+
sol = Solver(s, T=77).schrodinger_poisson()
|
|
197
|
+
sol.solve()
|
|
198
|
+
sol.VH, sol.n3d, sol.EF # Hartree potential, electron density, Fermi level
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 11. Electric field
|
|
202
|
+
```python
|
|
203
|
+
sol = Solver(s, field=50).solve() # 50 kV/cm along z
|
|
204
|
+
r = sol.stark_sweep(np.linspace(-80, 80, 33)) # dict: E_e0hh0, ov_e0hh0, E01, z01, ...
|
|
205
|
+
sol.plot_stark("stark.png", np.linspace(-80, 80, 33)) # QCSE, overlap, intersubband vs field
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## 12. Magnetic field
|
|
209
|
+
```python
|
|
210
|
+
# B along the growth axis: Landau levels and Zeeman splitting
|
|
211
|
+
sol = Solver(s, T=4.2, Bz=5).solve()
|
|
212
|
+
sol.g_factor(0) # electron g-factor of subband 0
|
|
213
|
+
sol.zeeman() # spin splitting of each subband (eV)
|
|
214
|
+
sol.landau_levels(N_max=10) # list of Landau levels
|
|
215
|
+
sol.fermi_level_B(3e11) # Fermi level in the field
|
|
216
|
+
sol.plot_magnetic("landau.png", np.linspace(0.5, 10, 200), n2d_cm2=3e11)
|
|
217
|
+
|
|
218
|
+
# B in the layer plane: diamagnetic shift and dispersion
|
|
219
|
+
sol = Solver(s, T=4.2, Bpar=10).solve()
|
|
220
|
+
E_ky = sol.inplane_dispersion(np.linspace(-0.2, 0.2, 41))
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## 13. Other options
|
|
224
|
+
```python
|
|
225
|
+
Solver(s, T=77) # temperature (K), band gaps follow Varshni law
|
|
226
|
+
Solver(s, dz=0.05) # finer grid (nm), default 0.1
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Validation
|
|
232
|
+
| Test | Reference | hetero1d |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| 10 nm GaAs/Al0.3Ga0.7As, E1 | 30.842 meV (exact analytic) | 30.850 meV |
|
|
235
|
+
| Double-barrier resonance | 61.95 meV (well level) | T = 1.0000 at 61.91 meV |
|
|
236
|
+
| In0.53Ga0.47As/In0.52Al0.48As ΔEc | ≈ 0.52 eV (literature) | 0.522 eV |
|
|
237
|
+
| Landau spacing, 5 T | ħeB/m* | exact |
|
|
238
|
+
| In-plane diamagnetic shift, 1 T | 2nd-order perturbation theory | 0.0235 meV (identical) |
|
|
239
|
+
|
|
240
|
+
## Model limits
|
|
241
|
+
Single-band effective mass (no k·p band mixing, no non-parabolicity), Γ valley only
|
|
242
|
+
(X/L valleys not included), no strain, nitrides without polarisation fields,
|
|
243
|
+
Zeeman and Landau levels for electrons only.
|
|
244
|
+
|
|
245
|
+
## Parameters
|
|
246
|
+
I. Vurgaftman, J. R. Meyer, L. R. Ram-Mohan, J. Appl. Phys. 89, 5815 (2001);
|
|
247
|
+
nitrides: I. Vurgaftman, J. R. Meyer, J. Appl. Phys. 94, 3675 (2003).
|
|
248
|
+
|
|
249
|
+
## Author
|
|
250
|
+
Ravi Kumar, 2026. MIT License.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hetero1d" # must be unique on PyPI !
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "1D semiconductor heterostructure solver: quantum wells, superlattices, electric and magnetic fields"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "Ravi Kumar", email = "rkravi365@gmail.com"}]
|
|
13
|
+
keywords = ["semiconductor", "quantum well", "heterostructure", "superlattice",
|
|
14
|
+
"Schrodinger", "Poisson", "physics"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
20
|
+
"Intended Audience :: Science/Research",
|
|
21
|
+
]
|
|
22
|
+
dependencies = ["numpy>=1.20", "scipy>=1.7", "matplotlib>=3.3"]
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
test = ["pytest"]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/erw-del/hetero1d"
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
hetero1d-demo = "hetero1d.examples:main"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
where = ["src"]
|
hetero1d-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
hetero1d - 1D semiconductor heterostructure solver
|
|
3
|
+
(quantum wells, multiple wells, superlattices; electric and magnetic fields)
|
|
4
|
+
|
|
5
|
+
Quick start
|
|
6
|
+
-----------
|
|
7
|
+
>>> from hetero1d import Structure, Solver
|
|
8
|
+
>>> s = Structure.single_well(well="GaAs", barrier=("AlGaAs", 0.3), Lw=20, Lb=40)
|
|
9
|
+
>>> sol = Solver(s, T=300).solve()
|
|
10
|
+
>>> sol.report()
|
|
11
|
+
"""
|
|
12
|
+
from .core import (
|
|
13
|
+
Structure, Layer, Solver,
|
|
14
|
+
material, add_material, list_materials, lattice_matched,
|
|
15
|
+
BINARIES, TERNARIES, QUATERNARIES,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
__version__ = "0.1.0"
|
|
19
|
+
__all__ = ["Structure", "Layer", "Solver", "material", "add_material",
|
|
20
|
+
"list_materials", "lattice_matched", "BINARIES", "TERNARIES",
|
|
21
|
+
"QUATERNARIES", "__version__"]
|