Examples

All examples are available as Jupyter notebooks in examples/notebooks/. Each notebook can be run on nanoHUB or locally with PADRE installed.

Jupyter Notebooks

#

Notebook

Description

00

00_Introduction.ipynb

Overview and setup

01

01_Library_Overview.ipynb

Component-by-component tour of the API

02

02_PN_Diode.ipynb

I-V characteristics, band diagrams, ideality factor

03

03_Schottky_Diode.ipynb

Schottky barrier, forward/reverse I-V, workfunction effects

04

04_MOSFET.ipynb

Transfer and output characteristics, threshold voltage

05

05_BJT.ipynb

Gummel plot, β extraction, common-emitter output curves

06

06_MOS_Capacitor.ipynb

C-V analysis, band bending, single- and double-gate configurations

07

07_MESFET.ipynb

Output and transfer characteristics, doping and workfunction effects

Using Device Factory Functions

The simplest workflow uses factory functions that handle mesh, regions, doping, contacts, materials, and solve commands automatically:

from nanohubpadre import create_mos_capacitor

sim = create_mos_capacitor(
    oxide_thickness=0.1,
    silicon_thickness=5.0,
    substrate_doping=1e15,
    substrate_type="p",
    gate_type="n_poly",
    log_cv=True,
    log_cv_lf=True,
    log_bands_eq=True,
    log_profiles_eq=True,
    vg_sweep=(-3.0, 5.0, 0.08),
)

result = sim.run()
if result.returncode != 0:
    raise RuntimeError(f"Simulation failed:\n{result.stderr}")

# All visualization through sim methods — no manual parsing
sim.plot_band_diagram(suffix="eq")
sim.plot_carriers(suffix="eq", log_scale=True)
sim.plot_electrostatics(suffix="eq")
sim.plot_cv()

MOS Capacitor (Rappture Reference)

The following reproduces the nanoHUB MOSCap Rappture tool defaults exactly.

from nanohubpadre import create_mos_capacitor

sim = create_mos_capacitor(
    oxide_thickness=0.1,         # 100 nm (Rappture default)
    ny_oxide=100,
    silicon_thickness=5.0,
    ny_silicon=200,
    substrate_doping=1e15,       # Na = 1e15 /cm³
    substrate_type="p",
    gate_type="n_poly",          # n+ poly silicon gate
    oxide_permittivity=3.9,
    taun0=1e-9,                  # 1 ns carrier lifetimes
    taup0=1e-9,
    temperature=300,
    log_cv=True,
    cv_file="cv_hf",
    ac_frequency=1e6,            # HF: 1 MHz
    log_cv_lf=True,
    cv_lf_file="cv_lf",
    ac_frequency_lf=1.0,         # LF: 1 Hz
    log_bands_eq=True,
    log_qf_eq=True,
    log_profiles_eq=True,
    vg_sweep=(-3.0, 5.0, 0.08),  # -3V to +5V, 100 steps
)

result = sim.run()
if result.returncode != 0:
    raise RuntimeError(f"Simulation failed:\n{result.stderr}")

sim.plot_band_diagram(suffix="eq", title="Band Diagram at Equilibrium (Vg=0)")
sim.plot_carriers(suffix="eq", log_scale=True)
sim.plot_electrostatics(suffix="eq")
sim.plot_cv(title="MOS Capacitor C-V (HF 1 MHz + LF 1 Hz)")

Double-Gate MOS Capacitor

from nanohubpadre import create_mos_capacitor

sim = create_mos_capacitor(
    oxide_thickness=0.005,
    silicon_thickness=0.02,
    substrate_doping=1e17,
    substrate_type="p",
    gate_type="n_poly",
    gate_config="double",
    back_oxide_thickness=0.005,
    back_gate_type="n_poly",
    log_cv=True,
    log_bands_eq=True,
    vg_sweep=(-2.0, 2.0, 0.1),
)

result = sim.run()
if result.returncode != 0:
    raise RuntimeError(f"Simulation failed:\n{result.stderr}")

sim.plot_band_diagram(title="Double-Gate — Equilibrium")
sim.plot_cv(title="Double-Gate C-V")

PN Diode

from nanohubpadre import create_pn_diode

sim = create_pn_diode(
    length=2.0,
    p_doping=1e17,
    n_doping=1e17,
    temperature=300,
    log_iv=True,
    forward_sweep=(0.0, 1.0, 0.05),
    log_bands_eq=True,
)

result = sim.run()
if result.returncode != 0:
    raise RuntimeError(f"Simulation failed:\n{result.stderr}")

sim.plot_iv(title="PN Diode I-V", log_scale=True)
sim.plot_band_diagram(title="PN Diode Band Diagram")

MOSFET

from nanohubpadre import create_mosfet

sim = create_mosfet(channel_length=0.025, device_type="nmos")

result = sim.run()
if result.returncode != 0:
    raise RuntimeError(f"Simulation failed:\n{result.stderr}")

sim.plot_transfer(gate_electrode=3, drain_electrode=2,
                  title="NMOS Transfer Characteristic")

Low-Level (Manual) Example

For full control over the device structure, build the simulation from scratch:

examples/moscap.py — Manual MOS capacitor
  1#!/usr/bin/env python3
  2"""
  3Python equivalent of moscap.in for PADRE simulation.
  4
  5This script generates the same PADRE input deck as moscap.in
  6MOS Capacitor structure with oxide-silicon-oxide
  7"""
  8
  9from nanohubpadre import (
 10    Simulation, Mesh, Region, Electrode, Doping, Contact,
 11    Material, Models, System, Solve, Log, Plot1D
 12)
 13
 14
 15def create_moscap_simulation():
 16    """Create the MOS capacitor simulation equivalent to moscap.in"""
 17
 18    sim = Simulation()
 19
 20    # Mesh Specification
 21    sim.mesh = Mesh(nx=3, ny=41)
 22    sim.mesh.add_y_mesh(1, 0)
 23    sim.mesh.add_y_mesh(10, 0.002, ratio=0.8)
 24    sim.mesh.add_y_mesh(21, 0.032, ratio=1.25)
 25    sim.mesh.add_y_mesh(31, 0.062, ratio=0.8)
 26    sim.mesh.add_y_mesh(41, 0.064, ratio=1.25)
 27    sim.mesh.add_x_mesh(1, 0.001)
 28    sim.mesh.add_x_mesh(3, 1, ratio=1)
 29
 30    # Regions specification
 31    sim.add_region(Region(1, ix_low=1, ix_high=3, iy_low=1, iy_high=10,
 32                          material="sio2", insulator=True))
 33    sim.add_region(Region(2, ix_low=1, ix_high=3, iy_low=10, iy_high=31,
 34                          material="silicon", semiconductor=True))
 35    sim.add_region(Region(3, ix_low=1, ix_high=3, iy_low=31, iy_high=41,
 36                          material="sio2", insulator=True))
 37
 38    # Electrodes specification
 39    sim.add_electrode(Electrode(1, ix_low=1, ix_high=3, iy_low=1, iy_high=1))
 40    sim.add_electrode(Electrode(2, ix_low=1, ix_high=3, iy_low=41, iy_high=41))
 41
 42    # Doping specification
 43    sim.add_doping(Doping(region=2, p_type=True, concentration=1e18, uniform=True))
 44
 45    # Contact specification
 46    sim.add_contact(Contact(all_contacts=True, neutral=True))
 47    sim.add_contact(Contact(number=1, n_polysilicon=True))
 48    sim.add_contact(Contact(number=2, n_polysilicon=True))
 49
 50    # Material lifetime specification
 51    sim.add_material(Material(name="silicon"))
 52    sim.add_material(Material(name="sio2", permittivity=3.9, qf=0))
 53
 54    # Specify models
 55    sim.models = Models(temperature=300, conmob=True, fldmob=True)
 56    sim.system = System(electrons=True, holes=True, newton=True)
 57
 58    # Solve for initial conditions
 59    sim.add_solve(Solve(initial=True))
 60    sim.add_command(Plot1D(potential=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 61                           ascii=True, outfile="pot"))
 62    sim.add_command(Plot1D(qfn=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 63                           ascii=True, outfile="qfn"))
 64    sim.add_command(Plot1D(qfp=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 65                           ascii=True, outfile="qfp"))
 66    sim.add_command(Plot1D(band_val=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 67                           ascii=True, outfile="val"))
 68    sim.add_command(Plot1D(band_con=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 69                           ascii=True, outfile="con"))
 70    sim.add_command(Plot1D(electrons=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 71                           ascii=True, outfile="ele"))
 72    sim.add_command(Plot1D(holes=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 73                           ascii=True, outfile="hole"))
 74    sim.add_command(Plot1D(net_charge=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 75                           ascii=True, outfile="ro"))
 76    sim.add_command(Plot1D(e_field=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 77                           ascii=True, outfile="efield"))
 78
 79    # Solve for applied bias
 80    sim.add_solve(Solve(v1=0, vstep=-0.2, nsteps=10, electrode=[1, 2]))
 81    sim.add_log(Log(acfile="ac"))
 82    sim.add_solve(Solve(v1=-2.0, vstep=0.2, nsteps=20, electrode=[1, 2],
 83                        ac_analysis=True, frequency=1e7))
 84    sim.add_log(Log(off=True))
 85
 86    # Final plots after bias
 87    sim.add_command(Plot1D(potential=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 88                           ascii=True, outfile="potiv"))
 89    sim.add_command(Plot1D(qfn=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 90                           ascii=True, outfile="qfniv"))
 91    sim.add_command(Plot1D(qfp=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 92                           ascii=True, outfile="qfpiv"))
 93    sim.add_command(Plot1D(band_val=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 94                           ascii=True, outfile="valiv"))
 95    sim.add_command(Plot1D(band_con=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 96                           ascii=True, outfile="coniv"))
 97    sim.add_command(Plot1D(electrons=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
 98                           ascii=True, outfile="eleiv"))
 99    sim.add_command(Plot1D(holes=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
100                           ascii=True, outfile="holeiv"))
101    sim.add_command(Plot1D(net_charge=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
102                           ascii=True, outfile="roiv"))
103    sim.add_command(Plot1D(e_field=True, y_start=0, y_end=0.064, x_start=0.5, x_end=0.5,
104                           ascii=True, outfile="efieldiv"))
105
106    return sim
107
108
109if __name__ == "__main__":
110    sim = create_moscap_simulation()
111    deck = sim.generate_deck()
112    print(deck)

Running the Examples

To run a Python example script:

cd padre
PYTHONPATH=. python3 examples/moscap.py

To run a notebook on nanoHUB, upload it and select the PADRE kernel. To run locally, ensure PADRE is in your PATH and start Jupyter:

jupyter notebook examples/notebooks/06_MOS_Capacitor.ipynb