Espectros de emissão em OghmaNano
Um espectro de emissão descreve como a luz emitida por um material é distribuída ao longo do comprimento de onda. A OghmaNano armazena estes espectros como parte da sua base de dados de Materiais, onde podem ser consultados, importados ou atualizados. Esta página explica o que representa um espectro de emissão, como é armazenado e importado, e, por fim, como gerar um espectro aproximado utilizando Python quando os dados medidos não estão disponíveis.
1. O que é um espectro de emissão?
Quando os eletrões e as lacunas se recombinam por emissão radiativa, são emitidos fotões numa gama de energias, em vez de num comprimento de onda específico. Um espetro de emissão descreve a intensidade relativa desta luz em função do comprimento de onda. Pode ser obtido a partir de um experimento, como a fotoluminescência (PL) ou a eletroluminescência (EL), ou de um modelo teórico. O espetro não é o mesmo que o coeficiente de absorção ou o índice de refração do material.
A forma do espectro depende da estrutura eletrónica do semicondutor, da temperatura, da composição e, num dispositivo real, das concentrações de portadores de carga e dos efeitos óticos. Um espectro de emissão normalizado representa a distribuição relativa do comprimento de onda, e não a potência ótica absoluta ou a eficiência do LED.
2. Espectros de emissão na base de dados de materiais
Cada material tem o seu próprio diretório na base de dados de Materiais OghmaNano. Quando os dados de emissão estão disponíveis, são armazenados num ficheiro denominado emission.csv, juntamente com ficheiros como alpha.csv e n.csv. Por exemplo, uma pasta de materiais pode conter:
materials/
GaAs/
emission.csv
alpha.csv
n.csv
A base de dados de materiais utilizada nas simulações encontra-se na pasta oghma_local/materials do utilizador. Para obter uma descrição da estrutura da pasta e dos formatos dos ficheiros de materiais, consulte Base de dados de materiais: Parte C – Como os materiais são armazenados. Para uma introdução à navegação e edição de materiais, consulte Base de dados de materiais: Parte A.
Um ficheiro emission.csv contém o comprimento de onda em metros e a intensidade de emissão relativa em unidades arbitrárias. Os ficheiros no formato OghmaNano também contêm um cabeçalho de metadados; o valor y_len do cabeçalho indica o número de pontos de dados de comprimento de onda e intensidade que se seguem.
3. Importar os espectros de emissão medidos.
Sempre que existirem dados de fotoluminescência (PL) ou eletroluminescência (EL), estes são preferíveis a um espectro gerado de forma aproximada, desde que as medições sejam adequadas para o material e para o dispositivo em questão. Abra o material relevante na base de dados de Materiais, selecione o seu espectro de emissão e utilize a ferramenta de importação de dados para importar a curva medida. O processo geral para importar um conjunto de dados com duas colunas, selecionar as unidades de comprimento de onda e verificar os valores convertidos está descrito em Base de dados de Materiais: Parte A – Importação de dados.
Unidades: Os valores de comprimento de onda armazenados estão em metros, mesmo que o gráfico seja exibido em nanómetros. Utilize a intensidade normalizada (u.a.) para os dados representativos da forma da emissão. Verifique os metadados do ficheiro e o número de pontos após importar ou gerar um espectro.
4. Estimativa dos espectros de emissão quando os dados medidos não estão disponíveis.
Caso não haja um espectro medido adequado disponível, o script Python abaixo pode gerar um espectro de emissão normalizado temporário para semicondutores. Ele utiliza um modelo térmico simplificado de transição de banda para materiais com banda de energia direta:
\(S_E(E) \propto \sqrt{E-E_g}\,\exp[-(E-E_g)/(k_B T)]\), para \(E \geq E_g\).
Aqui, \(E_g\) representa a largura da banda proibida e \(T\) representa a temperatura. O script converte o perfil de emissão calculado no domínio da energia para intensidade por unidade de comprimento de onda, normaliza o seu pico para um e grava emission.csv no mesmo formato de metadados e dados utilizado pelo OghmaNano. Por padrão, cria 2036 pontos de comprimento de onda e intensidade a 300 K.
O script fornecido cria uma pasta para cada um dos 29 tipos distintos de semicondutores, incluindo GaAs, AlGaAs, GaN, InGaN, InP e InGaAs. As diferenças de energia da banda dos materiais representam valores iniciais; para ligas cuja composição influencia as propriedades, o espectro gerado representa apenas uma composição nominal.
Em que situações é apropriado utilizá-las? Use estas curvas geradas como exemplos de perfis de emissão generalizados, especialmente para testar o processo de emissão ou até que dados mais precisos ou um cálculo baseado na estrutura de bandas estejam disponíveis. Não são espectros medidos e não devem ser apresentados como previsões quantitativas de um LED específico.
O modelo não inclui o confinamento em poços quânticos, a desordem da liga, as características excitônicas, a emissão de defeitos, a tensão ou o acoplamento óptico. É especialmente inadequado para transições de banda indireta, incluindo o caso do GaP: a curva gerada representa uma transição direta ilustrativa, em vez da emissão convencional de um LED de GaP.
5. Exemplo: geração de espectros de emissão com Python.
Guarde o código abaixo com o nome generate_emission_spectra.py e execute-o:
python3 generate_emission_spectra.py
O diretório de saída padrão é emission_generated. Para selecionar outro diretório ou alterar o número de pontos:
python3 generate_emission_spectra.py --output my_emission_database --points 2036
Para alterar a temperatura de funcionamento ou definir os seus próprios valores de referência:
python3 generate_emission_spectra.py --temperature 300 --bandgap-file bandgaps.json
Um exemplo de ficheiro bandgaps.json é:
{
"GaAs": 1.424,
"AlGaAs": 1.80,
"InGaN": 2.75
}
Analise os espectros resultantes antes de colocar os ficheiros emission.csv adequados nas respetivas pastas de materiais. Os valores de banda neste script são valores representativos especificados manualmente; o script não utiliza os scripts de materiais Lua para calcular esses valores.
6. Código-fonte completo em Python.
A seguir, apresentamos o código completo do gerador, utilizando apenas a biblioteca padrão do Python. Copie o código para um ficheiro Python local.
Mostre o gerador completo do espectro de emissão em 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()
Observação: os espectros de emissão gerados são uma solução provisória. Para simulações quantitativas de dispositivos, é preferível utilizar dados de emissão medidos ou espectros calculados com base em um modelo eletrônico de estrutura de bandas e de transições ópticas adequado, como um cálculo baseado em k·p.