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 Quick Start guide

Implementação de scripts Lua para o solucionador elétrico de Newton no OghmaNano.

1. Introdução

O OghmaNano inclui uma interface de script Lua integrada que permite modificar o solucionador numérico interno em tempo de execução. Isso possibilita um controlo avançado, como ativar ou desativar equações, alterar o solucionador de Newton 3D, congelar parâmetros físicos selecionados durante transientes ou análises J–V, ou implementar estratégias iterativas personalizadas.

Isto difere da utilização de scripts externos. Linguagens como Python funcionam através da modificação de sim.json e do lançamento do solucionador, o que as torna adequadas para a realização de análises de parâmetros, execução em lote e pós-processamento.

Em contraste, a Lua funciona dentro do solucionador, permitindo a intervenção direta no fluxo de trabalho numérico, sem modificar o código C subjacente.

2. O que é Lua?

Lua é uma linguagem de script leve e de alto desempenho, concebida para ser integrada em aplicações maiores. É amplamente utilizada em áreas como motores de jogos e software científico, onde é necessário modificar o comportamento interno sem recompilar o código principal. Comparada com Python, Lua tem uma pegada muito menor e um menor custo de execução, o que a torna mais adequada para ser executada em ciclos críticos para o desempenho. Comparada com C, é significativamente mais fácil de escrever e modificar, ao mesmo tempo que oferece um controlo preciso sobre o comportamento do programa. Estas características tornam Lua particularmente adequada para o OghmaNano, onde é utilizada para influenciar diretamente o solucionador numérico durante a execução.

Para que tenha uma ideia de como funciona a linguagem Lua, caso ainda não a tenha utilizado, apresento aqui uma implementação do clássico algoritmo de ordenação por bolha.

Electrical ribbon in OghmaNano showing the drift diffusion solver control
Fita elétrica no OghmaNano que mostra o acesso aos controlos do solucionador de difusão por deriva.
Dropdown menu in the electrical ribbon showing the edit microcode option
Menu suspenso da faixa elétrica que exibe a opção «Editar microcódigo».
Lua scripting editor in OghmaNano
O editor de scripts Lua no OghmaNano.

a = {5, 3, 8, 1, 2}
n = #a
for i = 1, n do
  for j = 1, n - i do
    if a[j] > a[j+1] then
      a[j], a[j+1] = a[j+1], a[j]
    end
  end
end

2. Aceder ao editor de scripts Lua

O editor de scripts Lua pode ser acessado através da barra de ferramentas elétrica da janela principal, conforme mostrado em ??. Clique na pequena seta para baixo ao lado do controlo do solucionador de derivação-difusão para abrir o menu, que é exibido em ??. Em seguida, clique em Editar microcódigo para abrir o editor Lua, que é exibido em ??.

Pressione Ctrl+S para guardar o script ou utilize o botão de guardar na barra de ferramentas do editor. Para ativar o microcódigo, o botão de ativação deve ser pressionado, conforme mostrado em ??.

3. Um exemplo simples: células solares de perovskite com iões congelados.

Um exemplo simples de utilização de scripts Lua é na simulação de dispositivos de perovskite, onde pode ser necessário impedir o movimento dos iões durante uma varredura de corrente-tensão (J–V). As perovskites contêm iões móveis que se deslocam relativamente lentamente. Experimentalmente, um dispositivo é, muitas vezes, mantido inicialmente sob uma polarização negativa, de modo a que os iões se movam para uma configuração específica, e, em seguida, é realizada uma varredura de corrente-tensão muito rápida, antes que tenham tempo de reagir de forma significativa.

No OghmaNano, quando o modelo de iões de perovskite é ativado, o solucionador elétrico normalmente permite que os iões se estabilizem em cada etapa de tensão. Isto equivale a uma varredura J–V muito lenta ou quase em estado estacionário. Isso pode ser útil em alguns casos, mas não reproduz experimentos em que a tensão é variada de forma muito mais rápida. Para simular este tipo de medição, o script Lua abaixo pode ser usado para impedir o movimento dos iões quando o ciclo elétrico principal começa. A simulação ainda pode atingir a tensão inicial desejada da forma habitual, permitindo que os iões se movam durante a preparação, mas, uma vez que o ciclo principal é iniciado, a equação dos iões é desativada.


-- Initialise solver
a = dd_solver()
a.verbose = false              -- Suppress solver output

-- Apply logic only in the main electrical loop
if (a.problem_type & ELEC_PROB_MAIN_LOOP) ~= 0 then
    a.solve_nion = false       -- Disable ion equation (freeze ions)
    print("ion solver off")
else
    print("ion solver on")     -- Keep ions active during initialisation
end

a:run()                        -- Execute solver step

Neste exemplo, o objeto solucionador é criado primeiro e a saída de diagnóstico é reduzida. Em seguida, o script verifica se a fase atual do solucionador corresponde ao circuito elétrico principal. Se corresponder, a equação dos iões móveis é desativada, definindo o valor de solve_nion=false, e o solucionador é executado com esse conjunto de equações modificado. Existe um exemplo de simulação que utiliza os exemplos incluídos no modelo, em "Células de perovskite/Célula solar de perovskite - iões congelados (MAPI)".

5. Exemplo: digitalização ADI (método implícito de varredura com direção alternada)

Um exemplo mais avançado de programação em Lua é a implementação de uma estratégia de direção alternada para resolver problemas tridimensionais complexos. Esta abordagem está intimamente relacionada com o método Implícito de Direção Alternada (ADI), no qual um problema multidimensional é decomposto numa sequência de problemas de dimensão inferior.

Na OghmaNano, esta ideia pode ser implementada diretamente ao nível do solucionador, ativando e desativando seletivamente os acoplamentos direcionais. Em vez de resolver o sistema 3D totalmente acoplado numa única etapa, o domínio é percorrido em direções alternadas. Isto pode melhorar significativamente a estabilidade e a convergência para problemas complexos de deriva-difusão em 3D.

A estratégia utilizada consiste em dividir o problema tridimensional em etapas direcionais. Na primeira etapa, o solucionador opera em seções ao longo do eixo x, resolvendo o problema em toda a extensão dos eixos y e z, ao mesmo tempo que elimina as interdependências na direção do eixo x. Na segunda etapa, o solucionador passa a operar em seções ao longo do eixo z e realiza a operação complementar. O erro total é acumulado e utilizado para definir um critério de convergência personalizado.

O exemplo abaixo ilustra como um processo de análise no estilo ADI pode ser construído utilizando Lua:


-- Initialise solver and control variables
a = dd_solver()
cont = true
count = 0

-- Main ADI-style iteration loop
while cont == true do

-- ===== X-slice pass =====
a.set_newton_state("x")      -- Use/store Newton state for x-pass
tot_error = 0.0

a.step_z = -1                -- Full domain in z
a.step_x = 1                 -- Slice-by-slice in x
a.step_y = -1                -- Full domain in y

a.solve_pos_x = false        -- Disable x-direction Poisson coupling
a.solve_pos_y = true
a.solve_pos_z = true

a.solve_je_x = 0             -- Disable x-direction electron current
a.solve_jh_x = 0             -- Disable x-direction hole current
a.solve_je_y = true
a.solve_jh_y = true
a.solve_je_z = true
a.solve_jh_z = true

a.solve_srh_e = true         -- Keep SRH recombination active
a.solve_srh_h = true

a.solve_nion = 0             -- Disable ions
a.solve_singlet = false      -- Disable excited-state physics

error = a:run()              -- Execute x-slice solve
tot_error = tot_error + error


-- ===== Z-slice pass =====
a.set_newton_state("z")      -- Switch to z-pass Newton state

a.step_z = 1                 -- Slice-by-slice in z
a.step_x = -1                -- Full domain in x
a.step_y = -1                -- Full domain in y

a.solve_pos_x = true
a.solve_pos_y = true
a.solve_pos_z = false        -- Disable z-direction Poisson coupling

a.solve_je_y = true
a.solve_jh_y = true
a.solve_je_x = true
a.solve_jh_x = true
a.solve_je_z = false         -- Disable z-direction transport
a.solve_jh_z = false

a.solve_srh_e = true
a.solve_srh_h = true
a.solve_nion = false
a.solve_singlet = false

error = a:run()              -- Execute z-slice solve
tot_error = tot_error + error


-- ===== Convergence logic =====
if (error < 1e-3) then       -- Local convergence check
    if (count > 2) then      -- Ensure minimum iterations
        cont = false
    end
end

print("count", count, "tot error:", error)

count = count + 1

if (tot_error < 1e-7) then   -- Global convergence criterion
    cont = false
end

if (count > 10) then         -- Safety iteration limit
    cont = false
end

end

Nesta implementação, são realizadas duas passagens direcionais em cada iteração. Na primeira passagem, os termos de transporte de Poisson e de portadores na direção x são desativados, resolvendo efetivamente o sistema em segmentos ao longo do eixo x. Na segunda passagem, os termos correspondentes na direção z são desativados, produzindo uma passagem complementar.

São mantidos estados de Newton distintos para cada passagem direcional, utilizando set_newton_state(), o que permite que o solucionador preserve variáveis internas independentes, como o potencial eletrostático, as densidades de portadores e os níveis de ocupação das armadilhas.

A convergência é controlada explicitamente no script Lua. O ciclo termina quando a condição de limite é satisfeita, seja através do erro por iteração e do número de iterações, seja quando o erro acumulado fica abaixo de uma tolerância especificada, ou quando é atingido o número máximo de iterações.

Este exemplo demonstra como a linguagem de script Lua pode ser utilizada para criar fluxos de trabalho de resolução totalmente personalizados. Em vez de depender de um esquema numérico fixo, o utilizador pode definir diretamente como o sistema multidimensional é decomposto, como os estados intermédios são geridos e como a convergência é avaliada. Isto é particularmente útil para simulações 3D complexas, onde abordagens totalmente acopladas podem ser instáveis ou computacionalmente ineficientes.

3. O objeto dd_solver()

O ponto de entrada para o controlo da resolução de equações elétricas através da linguagem Lua é o objeto dd_solver(). Este permite o acesso direto ao algoritmo interno de resolução de equações de deriva/difusão/Newton, possibilitando a modificação, em tempo de execução, tanto do conjunto de equações como da estratégia de resolução.

Na prática, o objeto «solver» permite a realização de três operações fundamentais:

  1. Verifique o contexto atual do solucionador (por exemplo, o tipo de problema ou o viés aplicado).
  2. Ative ou desative equações e acoplamentos direcionais individuais.
  3. Execute uma etapa do solucionador e obtenha uma métrica de convergência/erro.

Os campos mais utilizados estão resumidos na Tabela ??.

Campo Significado Utilização comum/típica
step_x, step_y, step_z Controla a extensão espacial que é resolvida em cada direção. -1 resolve todo o domínio; 1 processa por secções. Decomposição direcional e solucionadores baseados em fatias.
solve_pos_x, solve_pos_y, solve_pos_z Ativa ou desativa o acoplamento de Poisson em cada direção. Desacoplamento da eletrostática ao longo de eixos selecionados.
solve_je_x, solve_je_y, solve_je_z Controla a equação da continuidade dos eletrões em cada direção. Controlo do transporte direcional.
solve_jh_x, solve_jh_y, solve_jh_z Controla a equação da continuidade do furo em cada direção. Controlo do transporte direcional.
solve_srh_e, solve_srh_h Permite a captura de eletrões e lacunas através do mecanismo de Shockley–Read–Hall. Preservando a dinâmica das armadilhas em sistemas reduzidos.
solve_nion Ativa ou desativa a equação de iões móveis. Imobilização do movimento iónico em simulações de perovskites.
solve_singlet Controla o solucionador do estado excitado (estado singuleto). Desativar os princípios físicos relacionados aos excitões/OLED durante as simulações elétricas.
verbose Controla a saída dos resultados do diagnóstico do solucionador. Execução em modo de depuração ou em modo silencioso.
problem_type Indica a fase atual do solucionador. Aplicar a lógica de forma seletiva (por exemplo, apenas no ciclo principal).
Vapplied Retorna a tensão terminal aplicada. Lógica de controlo dependente do tipo de polarização.
scale_dphi_for_Bfree Parâmetro de escala para atualizações do potencial interno. Ajuste numérico avançado.

Além do acesso ao campo, o solucionador disponibiliza um pequeno número de métodos essenciais:

Método Função/Papel
a:run() Executa o passo do solucionador configurado e retorna uma métrica de erro.
a.set_newton_state("x") Seleciona ou cria um estado de Newton armazenado. Isso permite que cópias independentes das variáveis da solução (potencial, densidades de portadores, ocupação de armadilhas) sejam mantidas para diferentes iterações direcionais.

8. Resumo

A utilização de scripts Lua no OghmaNano permite o controlo direto do solucionador interno de derivação-difusão, possibilitando que o utilizador modifique o sistema matemático que está a ser resolvido em tempo real. Ao contrário das abordagens de script externas, que atuam em ficheiros de entrada, a Lua opera dentro do próprio ciclo do solucionador e, portanto, pode alterar conjuntos de equações, acoplamentos direcionais e o comportamento de convergência de forma gradual. Esta capacidade é particularmente valiosa em situações em que a formulação padrão totalmente acoplada não é fisicamente adequada ou numericamente eficiente. Exemplos incluem a fixação de graus de liberdade lentos, como iões móveis, ou a decomposição de problemas complexos em 3D em passos direcionais, utilizando estratégias do tipo ADI.

Os exemplos apresentados aqui ilustram dois casos de utilização importantes. O primeiro demonstra uma intervenção mínima, em que a equação iónica é desativada apenas no circuito elétrico principal, de forma a reproduzir as condições experimentais de varredura rápida. O segundo mostra como o Lua pode ser utilizado para criar um fluxo de trabalho de resolução personalizado, alternando entre secções direcionais e aplicando critérios de convergência definidos pelo utilizador.

De forma mais geral, a Lua deve ser encarada como uma estrutura para o desenvolvimento de métodos numéricos dentro do OghmaNano. Ela permite que o utilizador vá além de configurações fixas de resolução e, em vez disso, defina estratégias de resolução personalizadas, que estejam alinhadas tanto com a física do problema quanto com as propriedades numéricas do sistema que está a ser resolvido.