Início Exemplos Capturas de ecrã Manual do utilizador Logótipo Bluesky YouTube ☰
OghmaNano Platforma symulacji wielofizycznych dla urządzeń optoelektronicznych i systemów fotonicznych DESCARREGAR Guia de início rápido

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.