An educational semiconductor device physics simulator in pure Python (NumPy + Matplotlib). Analytic models of a PN junction diode and a long-channel NMOS transistor with configurable materials (Si, Ge), doping, and temperature — numerical results plus publication-style plots of I-V curves and band diagrams.
This is an engineering-reference and teaching tool built on closed-form textbook equations (Sze, Pierret). It is deliberately not a mesh-based TCAD solver or a SPICE replacement; see Model limits.
git clone https://github.com/khachatryann/semisim.git
cd semisim
pip install . # or: pip install -e ".[dev]" for developmentDependencies: NumPy and Matplotlib only.
import numpy as np
from semisim import PNJunction, MOSFET, GERMANIUM
# --- Diode ---
d = PNJunction(na=1e17, nd=1e16, temperature=300.0)
print(d.built_in_potential) # 0.799 V
print(d.depletion_width() * 1e4) # 0.33 um
print(d.current(0.6)) # forward current at 0.6 V [A]
d_rs = PNJunction(na=1e17, nd=1e16, series_resistance=5.0) # exact Lambert-W I-V
d_ge = PNJunction(na=1e17, nd=1e16, material=GERMANIUM) # germanium diode
# --- MOSFET ---
m = MOSFET(na_substrate=1e17, tox=1e-6, width=1e-3, length=1e-4) # cm units
print(m.threshold_voltage()) # ~0.36 V
i_d = m.current(vgs=1.5, vds=np.linspace(0, 3, 100))Plotting:
import matplotlib.pyplot as plt
from semisim.plotting import plot_diode_iv, plot_band_diagram, plot_mosfet_output
plot_band_diagram(d, bias=0.3)
plot_mosfet_output(m, vgs_values=[1.0, 1.5, 2.0])
plt.show()Devices can also be defined in TOML (see examples/diode.toml):
from semisim import load_device
d = load_device("examples/diode.toml")python examples/01_diode_iv_temperature.py # diode I-V at 250/300/350 K
python examples/02_diode_si_vs_ge.py # Si vs Ge: Vbi, leakage, band diagrams
python examples/03_mosfet_characteristics.py # output/transfer curves, Vth extractionSemiconductor-textbook cm-based units throughout: densities in cm⁻³, lengths
in cm (10 nm oxide = 1e-6), mobility in cm²/(V·s), capacitance in F/cm².
Full derivations and references in docs/theory.md.
Materials — Varshni bandgap Eg(T) = Eg(0) − αT²/(T+β); intrinsic
concentration ni = √(Nc Nv) exp(−Eg/2kT) with Nc,Nv ∝ T^1.5; power-law
mobility temperature scaling; Einstein relation D = μ kT/q.
PN junction (abrupt, full-depletion approximation):
- Built-in potential:
Vbi = (kT/q) ln(Na Nd / ni²) - Depletion width:
W = √(2ε(Vbi−V)(Na+Nd)/(q Na Nd)), junction capacitanceCj = εA/W - Shockley I-V:
I = Is (exp(V/nVT) − 1)withIs = qA ni² (Dn/(Ln Na) + Dp/(Lp Nd)) - With series resistance the implicit equation is solved exactly via the
Lambert W function (evaluated in log space — no overflow at any bias):
I = (nVT/Rs) · W₀[(Is Rs/nVT) e^((V+Is Rs)/nVT)] − Is - Band diagrams in the depletion approximation, with quasi-Fermi splitting under bias (illustrative).
MOSFET (long-channel square law, NMOS):
- Threshold:
Vth = Vfb + 2φF + γ√(2φF + Vsb), withφF = VT ln(Na/ni),γ = √(2qεs Na)/Cox, andVfbdefaulting to an ideal n⁺-poly gate - Triode:
Id = μCox(W/L)(Vov − Vds/2)Vds; saturation:Id = (μCox/2)(W/L)Vov², both with optional channel-length modulation(1 + λVds) - Subthreshold: EKV-style softplus interpolation of the overdrive giving
Id ∝ exp((Vgs−Vth)/mVT)withm = 1 + γ/(2√(2φF))and a smooth handoff at threshold
Simplifications you should know about before trusting a number:
- Boltzmann statistics only — degenerate doping (> 10¹⁹ cm⁻³) triggers a warning.
- No avalanche/Zener breakdown; reverse characteristics are ideal.
- Single-diode model: no recombination-generation (n=2) current term (an ideality-factor knob is provided instead).
- Mobility is doping-independent (no Caughey-Thomas) with single power-law
temperature scaling; MOSFET default mobility is the bulk value
(surface mobility is ~2× lower — override
mobility=for quantitative work). - MOSFET is long-channel: no velocity saturation, DIBL, or Vth roll-off; NMOS only in v1.
- Band diagrams under bias use flat quasi-Fermi splits, not a solved drift-diffusion profile.
src/semisim/
├── constants.py # physical constants (CODATA), thermal voltage
├── materials.py # Material dataclass, Si/Ge presets
├── _math.py # pure-NumPy Lambert W (log-space)
├── config.py # TOML -> device instances
├── plotting.py # I-V, band diagram, output/transfer plots
└── devices/
├── base.py # abstract Device (terminals, current(), parameters)
├── diode.py # PNJunction
└── mosfet.py # MOSFET
All devices share the Device interface (named terminals, uniform
current(**bias)), so a SPICE-style netlist/nodal-analysis layer can be added
later without touching the physics classes. See
docs/architecture.md.
pip install -e ".[dev]"
ruff check .
pytestCI runs both on every push/PR across Python 3.10–3.12. Contributions welcome — see CONTRIBUTING.md.
- S. M. Sze, K. K. Ng, Physics of Semiconductor Devices, 3rd ed., Wiley, 2007.
- R. F. Pierret, Semiconductor Device Fundamentals, Addison-Wesley, 1996.
- T. C. Banwell, A. Jayakumar, "Exact analytical solution for current flow through diode with series resistance," Electron. Lett. 36(4), 2000.
- Y. Tsividis, C. McAndrew, Operation and Modeling of the MOS Transistor, 3rd ed., Oxford, 2011 (subthreshold interpolation).
MIT — see LICENSE.