Спектри випромінювання в OghmaNano.
Емісійний спектр описує, як розподіляється світло, що випромінюється матеріалом, за довжиною хвилі. OghmaNano зберігає ці спектри в рамках своєї бази даних матеріалів, де їх можна переглядати, імпортувати або оновлювати. На цій сторінці пояснюється, що являє собою емісійний спектр, як він зберігається та імпортується, і, нарешті, як створити приблизний спектр за допомогою Python, коли виміряні дані недоступні.
1. Що таке спектр випромінювання?
Коли електрони та дірки радіаційно рекомбінують, випромінюються фотони в широкому діапазоні енергій, а не на одній конкретній довжині хвилі. Спектр випромінювання описує відносну інтенсивність цього світла як функцію довжини хвилі. Він може бути отриманий в результаті експерименту, наприклад, фотолюмінесценції (ФЛ) або електролюмінесценції (ЕЛ), або з теоретичної моделі. Цей спектр відрізняється від коефіцієнта поглинання або показника заломлення матеріалу.
Спектральна форма залежить від електронної структури напівпровідника, температури, складу, а в реальному пристрої – від концентрації носіїв заряду та оптичних ефектів. Нормалізований спектр випромінювання відображає відносну розподілену залежність довжини хвилі, а не абсолютну оптичну потужність або ефективність світлодіода.
2. Спектри випромінювання в базі даних матеріалів
Для кожного матеріалу в базі даних OghmaNano Materials передбачено окрему папку. Якщо наявні дані про випромінювання, їх зберігають у файлі під назвою emission.csv разом із файлами, такими як alpha.csv і n.csv. Наприклад, папка матеріалу може містити таке:
materials/
GaAs/
emission.csv
alpha.csv
n.csv
База даних матеріалів, яка використовується в симуляціях, розташована в папці користувача oghma_local/materials. Опис структури папки та форматів файлів матеріалів можна знайти в База даних матеріалів: Частина C – Як зберігаються матеріали. Інформацію про перегляд і редагування матеріалів можна знайти в База даних матеріалів: Частина A.
Файл emission.csv містить значення довжини хвилі в метрах і відносну інтенсивність випромінювання у довільних одиницях. Файли у форматі OghmaNano також містять заголовок метаданих; значення y_len у заголовку вказує на кількість пар даних, що складаються зі значень довжини хвилі та інтенсивності, які йдуть після нього.
3. Імпорт виміряних спектрів випромінювання.
Якщо наявні дані про виміряну фотолюмінесценцію (ФЛ) або електролюмінесценцію (ЕЛ), їх слід використовувати замість приблизного змодельованого спектра, за умови, що вимірювання відповідають матеріалу та призначеному пристрою. Відкрийте відповідний матеріал у базі даних матеріалів, виберіть його спектр випромінювання та скористайтеся функцією імпорту даних, щоб імпортувати виміряну криву. Загальний процес імпорту набору даних із двома стовпцями, вибору одиниць вимірювання довжини хвилі та перегляду перетворених значень описано в База даних матеріалів: Частина A – Імпорт даних.
Одиниці вимірювання: збережені значення довжини хвилі вказано в метрах, навіть якщо графік відображається в нанометрах. Для представлення даних про форму спектру емісії використовуйте нормалізовану інтенсивність (умовні одиниці). Перевірте метадані файлу та кількість точок після імпорту або створення спектру.
4. Оцінювання спектрів випромінювання за відсутності наявних даних вимірювань.
Якщо немає доступного відповідного виміряного спектра, наведений нижче скрипт Python може створити тимчасовий, нормалізований спектр випромінювання об’ємного напівпровідника. Він використовує спрощену теплову модель міжзонних переходів для матеріалів із прямою забороненою зоною:
\(S_E(E) \propto \sqrt{E-E_g}\,\exp[-(E-E_g)/(k_B T)]\) для \(E \geq E_g\).
Тут \(E_g\) – ширина забороненої зони, а \(T\) – температура. Скрипт перетворює обчислений профіль випромінювання в енергетичній області на інтенсивність на одиницю довжини хвилі, нормалізує його пік до значення один і записує emission.csv в тому ж форматі метаданих і даних, який використовується OghmaNano. За замовчуванням він створює 2036 точок, що відображають залежність довжини хвилі від інтенсивності, при температурі 300 K.
Наданий скрипт створює окрему папку для кожного з 29 різних типів напівпровідникових матеріалів, зокрема GaAs, AlGaAs, GaN, InGaN, InP та InGaAs. Значення ширини забороненої зони матеріалу є типовими початковими значеннями; для сплавів, склад яких впливає на їхні властивості, згенерований спектр відображає лише один номінальний склад.
У яких випадках це доцільно? Використовуйте ці згенеровані криві як ілюстративні приклади загальних профілів випромінювання, особливо для тестування системи обробки даних про випромінювання або до отримання більш точних даних чи результатів розрахунків на основі зонної структури. Це не виміряні спектри, і їх не слід представляти як кількісні прогнози для конкретного світлодіода.
У цій моделі не враховано квантово-ямове обмеження, дефекти в сплаві, екзитонні властивості, випромінювання дефектів, напруження або оптичне випромінювання. Вона особливо не підходить для непрямих переходів, зокрема для GaP: отримана крива ілюструє прямий перехід, а не звичайне випромінювання світлодіода GaP.
5. Приклад: створення спектрів випромінювання за допомогою Python.
Збережіть наведений нижче код під назвою generate_emission_spectra.py і запустіть його:
python3 generate_emission_spectra.py
За замовчуванням вихідні дані зберігаються в папці emission_generated. Щоб вибрати іншу папку або змінити кількість точок:
python3 generate_emission_spectra.py --output my_emission_database --points 2036
Щоб змінити робочу температуру або використати власні параметри смугової ширини:
python3 generate_emission_spectra.py --temperature 300 --bandgap-file bandgaps.json
Приклад файлу bandgaps.json:
{
"GaAs": 1.424,
"AlGaAs": 1.80,
"InGaN": 2.75
}
Перевірте отримані спектри, перш ніж розмістити відповідні файли emission.csv у відповідних папках матеріалів. У цьому скрипті значення ширини забороненої зони вказуються вручну; скрипт не використовує Lua-скрипти матеріалів для їх обчислення.
6. Повний вихідний код Python.
Нижче наведено повний код генератора, який використовує лише стандартну бібліотеку Python. Скопіюйте цей код у локальний файл Python, щоб розширити його.
Відобразіть повний генератор спектру випромінювання 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()
Примітка: отримані спектри випромінювання є тимчасовим рішенням. Для кількісного моделювання роботи пристрою краще використовувати виміряні дані про випромінювання або спектри, розраховані за допомогою відповідної моделі електронної зонної структури та оптичних переходів, наприклад, на основі обчислень k·p.