Startseite Beispiele Screenshots Benutzerhandbuch Bluesky-Logo YouTube ☰
OghmaNano Simulation von organischen/Perowskit-Solarzellen, OFETs und OLEDs DOWNLOAD Quick Start guide

Emissionsspektren in OghmaNano

Ein Emissionsspektrum beschreibt, wie sich das von einem Material emittierte Licht über die Wellenlänge verteilt. OghmaNano speichert diese Spektren als Teil seiner Materialdatenbank, wo sie eingesehen, importiert oder aktualisiert werden können. Auf dieser Seite wird erläutert, was ein Emissionsspektrum darstellt, wie es gespeichert und importiert wird und schließlich, wie man mit Python ein ungefähres Spektrum generieren kann, wenn keine Messdaten verfügbar sind.

1. Was ist ein Emissionsspektrum?

Wenn sich Elektronen und Löcher durch Strahlung rekombinieren, werden Photonen über einen bestimmten Energiebereich emittiert, anstatt bei einer exakten Wellenlänge. Ein Emissionsspektrum beschreibt die relative Intensität dieses Lichts in Abhängigkeit von der Wellenlänge. Es kann aus einem Experiment stammen, wie z. B. Photolumineszenz (PL) oder Elektrolumineszenz (EL), oder aus einem theoretischen Modell. Das Spektrum ist nicht dasselbe wie der Absorptionskoeffizient oder der Brechungsindex des Materials.

Die spektrale Form hängt von der elektronischen Struktur des Halbleiters, der Temperatur, der Zusammensetzung und in einem realen Bauelement von den Trägerkonzentrationen und den optischen Effekten ab. Ein normalisiertes Emissionsspektrum stellt die relative Wellenlängenverteilung dar und nicht die absolute optische Leistung oder die LED-Effizienz.

2. Emissionsspektren in der Materialdatenbank

Jedes Material hat ein eigenes Verzeichnis in der OghmaNano-Materialdatenbank. Wenn Emissionsdaten verfügbar sind, werden diese in einer Datei mit dem Namen emission.csv zusammen mit Dateien wie alpha.csv und n.csv gespeichert. Ein Materialordner kann beispielsweise Folgendes enthalten:

materials/
  GaAs/
    emission.csv
    alpha.csv
    n.csv

Die Materialdatenbank, die von den Simulationen verwendet wird, befindet sich im Benutzerverzeichnis oghma_local/materials. Eine Beschreibung der Verzeichnisstruktur und der Dateiformate für Materialien finden Sie unter Materialdatenbank: Teil C – Wie Materialien gespeichert werden. Eine Einführung in die Navigation und Bearbeitung von Materialien finden Sie unter Materialdatenbank: Teil A.

Eine emission.csv-Datei enthält die Wellenlänge in Metern und die relative Emissionsintensität in beliebigen Einheiten. Dateien im OghmaNano-Format enthalten außerdem einen Metadaten-Header; der y_len-Wert des Headers gibt die Anzahl der nachfolgenden Datenpunkte für Wellenlänge und Intensität an.

3. Einlesen der gemessenen Emissionsspektren

Wenn Messdaten zur Photolumineszenz (PL) oder Elektrolumineszenz (EL) vorliegen, sind diese einem approximativ erstellten Spektrum vorzuziehen, vorausgesetzt, die Messungen sind für das jeweilige Material und das vorgesehene Bauelement geeignet. Öffnen Sie das entsprechende Material in der Materialdatenbank, wählen Sie dessen Emissionsspektrum aus und verwenden Sie die Datenimportfunktion, um die gemessene Kurve zu importieren. Der allgemeine Prozess zum Importieren eines Datensatzes mit zwei Spalten, zum Auswählen von Wellenlängeneinheiten und zum Überprüfen der konvertierten Werte wird in Materialdatenbank: Teil A – Daten importieren beschrieben.

Einheiten: Die gespeicherten Wellenlängenwerte werden in Metern angegeben, auch wenn das Diagramm in Nanometern dargestellt wird. Verwenden Sie normalisierte Intensität (willkürliche Einheiten) für repräsentative Daten zur Emissionsform. Überprüfen Sie die Metadaten der Datei und die Anzahl der Datenpunkte, nachdem Sie ein Spektrum importiert oder generiert haben.

4. Schätzung von Emissionsspektren, wenn keine Messdaten verfügbar sind.

Wenn kein geeignetes, gemessenes Spektrum verfügbar ist, kann das folgende Python-Skript ein vorläufiges, normalisiertes Emissionsspektrum für Halbleitermaterialien generieren. Es verwendet ein vereinfachtes thermisches Band-zu-Band-Modell für Materialien mit direkter Bandlücke:

\(S_E(E) \propto \sqrt{E-E_g}\,\exp[-(E-E_g)/(k_B T)]\) für \(E \geq E_g\).

Hierbei steht \(E_g\) für die Bandlücke und \(T\) für die Temperatur. Das Skript wandelt das berechnete Emissionsprofil im Energiebereich in die Intensität pro Wellenlängeneinheit um, normalisiert seinen Maximalwert auf eins und schreibt emission.csv im gleichen Metadaten- und Datenformat, das von OghmaNano verwendet wird. Standardmäßig werden 2.036 Wellenlängen-Intensitätspunkte bei 300 K erzeugt.

Das mitgelieferte Skript erstellt für jede der 29 verschiedenen Halbleitermaterialien ein separates Verzeichnis, darunter GaAs, AlGaAs, GaN, InGaN, InP und InGaAs. Die angegebenen Bandlücken der Materialien stellen repräsentative Ausgangswerte dar; bei Legierungen, deren Eigenschaften von der Zusammensetzung abhängen, stellt das generierte Spektrum nur eine typische Zusammensetzung dar.

Wann ist dies angemessen? Verwenden Sie diese generierten Kurven als veranschaulichende Beispiele für typische Emissionsprofile, insbesondere zum Testen der Emissionspipeline oder bis bessere Daten oder eine auf der Bandstruktur basierende Berechnung verfügbar sind. Es handelt sich nicht um gemessene Spektren, und sie sollten nicht als quantitative Vorhersagen für eine bestimmte LED dargestellt werden.

Das Modell berücksichtigt weder die Quantenwellen-Einschränkung, die Legierungsstörung, die Eigenschaften von Exzitonen, die Defektemission, die Verspannung noch die optische Auskopplung. Es ist besonders ungeeignet für indirekte Bandübergänge, einschließlich des GaP-Eintrags: Die daraus resultierende Kurve stellt eher einen schematischen direkten Übergang dar als die konventionelle GaP-LED-Emission.

5. Beispiel: Erzeugung von Emissionsspektren mit Python

Speichern Sie den folgenden Code unter dem Namen generate_emission_spectra.py und führen Sie ihn aus:

python3 generate_emission_spectra.py

Das Standardausgabeverzeichnis ist emission_generated. Um ein anderes Verzeichnis auszuwählen oder die Anzahl der Punkte zu ändern:

python3 generate_emission_spectra.py --output my_emission_database --points 2036

Um die Betriebstemperatur zu ändern oder eigene Bandlückenwerte einzugeben:

python3 generate_emission_spectra.py --temperature 300 --bandgap-file bandgaps.json

Ein Beispiel für eine bandgaps.json-Datei ist:

{
  "GaAs": 1.424,
  "AlGaAs": 1.80,
  "InGaN": 2.75
}

Überprüfen Sie die resultierenden Spektren, bevor Sie die entsprechenden emission.csv-Dateien in die jeweiligen Materialordner einfügen. Die in diesem Skript verwendeten Bandlücken sind manuell festgelegte, repräsentative Werte; das Skript ruft die Lua-Materialskripte nicht auf, um diese zu berechnen.

6. Vollständiger Python-Quellcode

Im Folgenden finden Sie den vollständigen Generator, der ausschließlich die Standardbibliothek von Python verwendet. Kopieren Sie den Quellcode, um ihn in eine lokale Python-Datei einzufügen.

Zeigen Sie den vollständigen Python-Code für den Generator des Emissionsspektrums an.
#!/usr/bin/env python3
"""Generate illustrative bulk band-edge emission.csv files for OghmaNano.

No external Python dependencies. Each directory contains a 2036-point
OghmaNano-format emission.csv. Spectra are normalised per wavelength and
are NOT measured or k.p-calculated spectra. Alloy bandgaps below represent
one nominal composition only; edit MATERIALS or use --bandgap-file.
"""
import argparse
import json
import math
from pathlib import Path

# Representative, approximate 300 K bulk DIRECT-transition gaps (eV).
# NOT universal values for alloys. Entries such as AlInP and AlInAs may be
# indirect at common compositions: their curves are illustrative ONLY.
# One directory per unique material; InSb was duplicated in the supplied list.
MATERIALS = {
    "InP":       (1.344, "InP/InP.lua"),
    "GaP":       (2.78,  "GaP/GaP.lua"),  # direct transition; GaP fundamental gap is indirect!
    "AlGaInP":   (2.05,  "AlGaInP.lua"),
    "GaAs":      (1.424, "GaAs/GaAs.lua"),
    "AlInP":     (2.35,  "AlInP.lua"),  # illustrative; verify direct-gap composition
    "InSb":      (0.17,  "InSb/InSb.lua"),
    "GaSb":      (0.726, "GaSb/GaSb.lua"),
    "CdS":       (2.42,  "CdS/CdS.lua"),
    "GaN":       (3.40,  "GaN/GaN.lua"),
    "AlN":       (6.03,  "AlN.lua"),
    "ZnS":       (3.68,  "ZnS.lua"),
    "InAs":      (0.354, "InAs/InAs.lua"),
    "AlGaAs":    (1.80,  "AlGaAs/AlGaAs.lua"),  # nominal Al x~0.3
    "InAsP":     (0.95,  "InAsP.lua"),
    "InGaAsP":   (0.80,  "InGaAsP.lua"),
    "AlInAs":    (1.45,  "AlInAs.lua"), # composition-dependent and possibly indirect
    "GaAsP":     (1.90,  "GaAsP.lua"),
    "InGaAs":    (0.75,  "InGaAs/InGaAs.lua"), # nominal In0.53Ga0.47As
    "ZnTe":      (2.26,  "ZnTe.lua"),
    "InGaN":     (2.75,  "InGaN.lua"),
    "GaInNAs":   (0.95,  "GaInNAs.lua"),
    "InGaP":     (1.90,  "InGaP.lua"),
    "GaInAs":    (0.75,  "GaInAs.lua"),
    "InN":       (0.69,  "InN.lua"),
    "AlGaN":     (4.43,  "AlGaN.lua"),
    "AlGaInAs":  (0.80,  "AlGaInAs.lua"),
    "CdSe":      (1.74,  "CdSe.lua"),
    "ZnSe":      (2.70,  "ZnSe.lua"),
    "CdTe":      (1.50,  "CdTe/CdTe.lua"),
}

HC_EV_NM = 1239.8419843320026
KB_EV_K = 8.617333262145e-5


def make_spectrum(eg, temp, points):
    """3D nondegenerate direct-gap model, intensity per unit wavelength.

    S_E(E) ~ sqrt(E-Eg)*exp(-(E-Eg)/kT), E>=Eg.
    Convert using dE/dlambda ~ 1/lambda**2, then peak-normalise.
    Span covers Eg to Eg + max(0.35 eV, 12 kT); wavelength increases.
    """
    kt = KB_EV_K * temp
    upper = eg + max(0.35, 12.0 * kt)
    lo_nm = HC_EV_NM / upper
    hi_nm = HC_EV_NM / eg
    values = []
    for i in range(points):
        wavelength_nm = lo_nm + (hi_nm - lo_nm) * i / (points - 1)
        e = HC_EV_NM / wavelength_nm
        de = max(0.0, e - eg)
        intensity = math.sqrt(de) * math.exp(-de / kt) / (wavelength_nm * wavelength_nm)
        values.append((wavelength_nm * 1e-9, intensity))
    top = max(v for _, v in values)
    return [(lam, value / top) for lam, value in values]


def generate(out, material, eg, lua_path, temp, points):
    folder = out / material
    folder.mkdir(parents=True, exist_ok=True)
    metadata = {
        "title": "Illustrative band-edge emission of " + material,
        "type": "xy",
        "y_label": "Wavelength",
        "data_label": "Intensity",
        "y_units": "nm",
        "y_mul": 1e9,
        "data_units": "au",
        "icon": "spectra_file",
        "time ": 0.0,
        "Vexternal": 0.0,
        "x_len": 1,
        "y_len": points,
        "z_len": 1,
        "cols": "yd",
    }
    values = make_spectrum(eg, temp, points)
    path = folder / "emission.csv"
    with path.open("w", encoding="utf-8", newline="\n") as f:
        f.write("#oghma_csv " + json.dumps(metadata, ensure_ascii=False, separators=(",", ":")) + "*\n")
        for lam, value in values:
            f.write(f"{lam:.12e}\t{value:.12e}\n")
    return path


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--output", type=Path, default=Path("emission_generated"))
    parser.add_argument("--points", type=int, default=2036)
    parser.add_argument("--temperature", type=float, default=300.0)
    parser.add_argument("--bandgap-file", type=Path,
                        help='Optional JSON map e.g. {"GaAs":1.424,"AlGaAs":1.80} to override nominal gaps')
    args = parser.parse_args()
    if args.points < 3 or args.temperature <= 0:
        parser.error("--points must be >=3 and --temperature must be positive")
    gap_overrides = {}
    if args.bandgap_file:
        gap_overrides = json.loads(args.bandgap_file.read_text(encoding="utf-8"))
        unknown = set(gap_overrides) - set(MATERIALS)
        if unknown:
            parser.error("Unknown material(s): " + ", ".join(sorted(unknown)))
    args.output.mkdir(parents=True, exist_ok=True)
    for material, (nominal_eg, lua_path) in MATERIALS.items():
        eg = float(gap_overrides.get(material, nominal_eg))
        if not math.isfinite(eg) or eg <= 0:
            parser.error(f"Invalid bandgap for {material}: {eg}")
        path = generate(args.output, material, eg, lua_path, args.temperature, args.points)
        print(f"{path}  Eg={eg:g} eV  (source: {lua_path})")
    print(f"Generated {len(MATERIALS)} unique material directories with {args.points} points each.")
    print("CAUTION: nominal/illustrative bulk direct-transition profiles; validate alloy composition and gap type.")


if __name__ == "__main__":
    main()

Hinweis: Die generierten Emissionsspektren stellen eine Übergangslösung dar. Für quantitative Geräte­simulationen sollten Sie vorzugsweise gemessene Emissionsdaten oder Spektren verwenden, die mithilfe eines geeigneten elektronischen Bandstruktur- und optischen Übergangsmodells berechnet wurden, beispielsweise einer auf der k·p-Methode basierenden Berechnung.