Spectres d’émission dans OghmaNano
Un spectre d’émission décrit la manière dont la lumière émise par un matériau est répartie en fonction de la longueur d’onde. OghmaNano enregistre ces spectres dans le cadre de sa base de données de matériaux, où ils peuvent être consultés, importés ou mis à jour. Cette page explique ce qu’est un spectre d’émission, comment il est enregistré et importé, et enfin comment générer un spectre approximatif à l’aide de Python lorsque les données mesurées ne sont pas disponibles.
1. Qu’est-ce qu’un spectre d’émission ?
Lorsque les électrons et les trous s’ recombinent par rayonnement, des photons sont émis sur une plage d’énergies plutôt qu’à une longueur d’onde précise. Un spectre d’émission décrit l’intensité relative de cette lumière en fonction de la longueur d’onde. Il peut provenir d’une expérience, comme la photoluminescence (PL) ou l’électroluminescence (EL), ou d’un modèle théorique. Le spectre n’est pas identique au coefficient d’absorption ou à l’indice de réfraction du matériau.
La forme du spectre dépend de la structure électronique du semi-conducteur, de sa température, de sa composition et, dans un dispositif réel, des concentrations de porteurs et des effets optiques. Un spectre d’émission normalisé représente la distribution relative des longueurs d’onde, et non la puissance optique absolue ou le rendement du dispositif électroluminescent (DEL).
2. Spectres d’émission dans la base de données des matériaux.
Chaque matériau possède son propre répertoire dans la base de données OghmaNano Materials. Lorsque des données d’émission sont disponibles, elles sont enregistrées dans un fichier nommé emission.csv, aux côtés de fichiers tels que alpha.csv et n.csv. Par exemple, un dossier de matériau peut contenir :
materials/
GaAs/
emission.csv
alpha.csv
n.csv
La base de données de matériaux utilisée par les simulations se trouve dans le dossier de l’utilisateur.
oghma_local/materials répertoire. Pour obtenir une description de la
structure du répertoire et des formats de fichiers, consultez
Base de données sur les matériaux : partie C – Comment les matériaux sont stockés.Pour une introduction à la navigation et à la modification de documents, consultez
Base de données sur les matériaux : partie A.
Un fichier emission.csv contient la longueur d’onde en mètres et l’intensité d’émission relative, exprimée en unités arbitraires. Les fichiers au format OghmaNano contiennent également un en-tête de métadonnées ; la valeur y_len de l’en-tête indique le nombre de points de données correspondant aux paires longueur d’onde-intensité qui suivent.
3. Importer les spectres d’émission mesurés.
Dans les cas où des données de photoluminescence (PL) ou d’électroluminescence (EL) mesurées sont disponibles, il est préférable de les utiliser plutôt qu’un spectre généré de manière approximative, à condition que les mesures soient appropriées pour le matériau et le dispositif concernés. Ouvrez le matériau correspondant dans la base de données des matériaux, sélectionnez son spectre d’émission et utilisez la fonction d’importation de données pour importer la courbe mesurée. Le processus général d’importation d’un ensemble de données à deux colonnes, de sélection des unités de longueur d’onde et de vérification des valeurs converties est décrit dans Base de données des matériaux : partie A – Importation des données.
Unités : les valeurs de longueur d’onde enregistrées sont exprimées en mètres, même si le graphique est affiché en nanomètres. Utilisez l’intensité normalisée (u.a.) pour les données représentatives de la forme du spectre d’émission. Vérifiez les métadonnées du fichier et le nombre de points après avoir importé ou généré un spectre.
4. Estimation des spectres d’émission lorsque les données mesurées ne sont pas disponibles.
Si aucun spectre mesuré approprié n’est disponible, le script Python ci-dessous peut générer un spectre d’émission normalisé temporaire pour un semi-conducteur. Il utilise un modèle thermique simplifié de transition bande à bande pour les matériaux à bande interdite directe :
\(S_E(E) \propto \sqrt{E-E_g}\,\exp[-(E-E_g)/(k_B T)]\) pour \(E \geq E_g\).
Ici, \(E_g\) représente la largeur de la bande interdite et \(T\) la température. Le script convertit le profil d’émission calculé dans le domaine énergétique en intensité par unité de longueur d’onde, normalise son pic à une valeur de 1, et enregistre emission.csv dans le même format de métadonnées et de données utilisé par OghmaNano. Par défaut, il crée 2 036 points représentant la longueur d’onde et l’intensité à 300 K.
Le script fourni crée un répertoire pour chacun des 29 types de semi-conducteurs différents, notamment le GaAs, l’AlGaAs, le GaN, l’InGaN, l’InP et l’InGaAs. Les valeurs de la bande interdite des matériaux représentent des valeurs de départ représentatives ; pour les alliages dont les propriétés dépendent de la composition, le spectre généré ne représente qu’une seule composition nominale.
Dans quelles circonstances est-il approprié de les utiliser ? Utilisez ces courbes générées comme exemples de profils d’émission globaux, en particulier pour tester la chaîne de traitement des émissions ou jusqu’à ce que de meilleures données ou un calcul basé sur la structure de bande soient disponibles. Il ne s’agit pas de spectres mesurés et ils ne doivent pas être présentés comme des prédictions quantitatives concernant une LED particulière.
Le modèle ne prend pas en compte le confinement quantique, le désordre d’alliage, les propriétés excitoniques, l’émission due aux défauts, la contrainte ou le couplage optique. Il est particulièrement inadapté aux transitions à bande interdite indirecte, y compris pour le matériau GaP : la courbe qu’il génère représente plutôt une transition directe à titre d’illustration qu’une émission conventionnelle d’une LED en GaP.
5. Exemple : génération de spectres d’émission à l’aide de Python.
Enregistrez le code ci-dessous sous le nom generate_emission_spectra.py et exécutez-le :
python3 generate_emission_spectra.py
Le répertoire de destination par défaut est emission_generated. Pour choisir un autre répertoire ou modifier le nombre de points :
python3 generate_emission_spectra.py --output my_emission_database --points 2036
Pour modifier la température de fonctionnement ou utiliser vos propres valeurs de référence :
python3 generate_emission_spectra.py --temperature 300 --bandgap-file bandgaps.json
Voici un exemple de fichier bandgaps.json :
{
"GaAs": 1.424,
"AlGaAs": 1.80,
"InGaN": 2.75
}
Examinez les spectres obtenus avant de placer les fichiers emission.csv appropriés dans les dossiers correspondants aux différents matériaux. Dans ce script, les valeurs des bandes interdites sont spécifiées manuellement et servent de valeurs représentatives ; le script n’appelle pas les scripts Lua relatifs aux matériaux pour les calculer.
6. Code source Python complet.
Voici le code complet du générateur, qui utilise uniquement les bibliothèques standard de Python. Copiez le code source et enregistrez-le dans un fichier Python local.
Affichez le générateur complet du spectre d’émission Python.
#!/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()
Remarque : les spectres d’émission générés ne constituent qu’une solution temporaire. Pour les simulations quantitatives de dispositifs, il est préférable d’utiliser des données d’émission mesurées ou des spectres calculés à l’aide d’un modèle approprié de structure de bande électronique et de transition optique, tel qu’un calcul basé sur le modèle k·p.