Início Exemplos Capturas de ecrã Manual do utilizador Logótipo Bluesky YouTube
OghmaNano Simular células solares orgânicas/Perovskita, OFETs e OLEDs DESCARREGAR

Scripting em MATLAB

1. Introdução

No OghmaNano, o scripting em MATLAB funciona editando diretamente os arquivos de configuração da simulação em disco e então invocando o mecanismo de simulação (oghma_core.exe) para executar o modelo. Esta seção descreve esse fluxo de trabalho em detalhes.

2. Executando arquivos de simulação com MATLAB

Uma simulação do OghmaNano é definida inteiramente por um único arquivo de configuração JSON, sim.json. Este arquivo contém o estado completo da simulação, incluindo a estrutura do dispositivo, parâmetros de material, configurações numéricas e configuração de saída. Em muitos casos, sim.json já existe como um arquivo normal dentro do diretório da simulação.

Ao controlar o OghmaNano a partir do MATLAB, o script lê sim.json na memória usando o suporte JSON do MATLAB, modifica um ou mais parâmetros e grava o JSON atualizado de volta em disco.

Crucialmente, o MATLAB deve executar oghma_core.exe com seu diretório de trabalho definido como o diretório da simulação — isto é, o diretório que contém sim.json (e sim.oghma). O mecanismo de simulação sempre lê seus arquivos de entrada a partir do diretório de trabalho atual, então, se o diretório de trabalho estiver incorreto, a simulação falhará ou executará o modelo errado.

Essa separação de responsabilidades é intencional e explícita: o MATLAB é responsável por definir o que muda na simulação, enquanto o OghmaNano é responsável por executar a física usando os arquivos presentes no diretório atual.

O exemplo abaixo demonstra esse processo carregando sim.json, modificando a mobilidade do portador da primeira camada do dispositivo, gravando a configuração atualizada de volta em disco e, então, executando a simulação a partir do diretório da simulação.


% Defina isto como a pasta da sua simulação (deve conter sim.json / sim.oghma)
sim_dir = "C:\path\to\your\simulation";

% Ler sim.json
sim_path = fullfile(sim_dir, "sim.json");
txt = fileread(sim_path);
data = jsondecode(txt);

% Editar um valor: mobilidade de segment1 (mesmo caminho JSON da página Python)
data.epitaxy.segment1.shape_dos.mue_y = 1.0;

% Gravar sim.json de volta em disco
out = jsonencode(data);
fid = fopen(sim_path, "w");
fprintf(fid, "%s", out);
fclose(fid);

% Executar a simulação (o diretório de trabalho deve ser a pasta da simulação)
orig_dir = pwd;
cd(sim_dir);
system("oghma_core.exe");
cd(orig_dir);

Se a simulação em sim.json estiver configurada para executar uma curva J–V, o OghmaNano gravará arquivos de saída no diretório da simulação contendo quantidades como PCE, fator de preenchimento, \(J_{sc}\) e \(V_{oc}\).

3. Extraindo resultados

Muitos arquivos de saída do OghmaNano são gravados em formato JSON. Um padrão comum é ler sim_info.dat, extrair uma figura de mérito escalar (por exemplo Voc) e anexá-la a um arquivo de texto para análise posterior.

O exemplo abaixo lê sim_info.dat e acrescenta o valor de \(V_{oc}\) a um arquivo de texto separado.


% Deve ser executado a partir de (ou apontando para) um diretório de simulação concluída
sim_dir = "C:\path\to\your\simulation";
info_path = fullfile(sim_dir, "sim_info.dat");

txt = fileread(info_path);
info = jsondecode(txt);
voc = info.Voc;

% Acrescentar a um arquivo de texto (um Voc por linha)
out_path = fullfile(sim_dir, "out.dat");
fid = fopen(out_path, "a");
fprintf(fid, "%g\n", voc);
fclose(fid);

3. Simulações mais complexas

Em muitos fluxos de trabalho de scripting, você desejará executar a mesma simulação base várias vezes com diferentes valores de parâmetro e manter cada execução isolada em seu próprio diretório. Essa é a forma mais simples de manter as saídas limpas e evitar sobrescrever resultados acidentalmente.

O exemplo abaixo cria um conjunto de diretórios correspondentes a quatro mobilidades (1e-5, 1e-6, 1e-7, 1e-8). Para cada diretório, ele:

  1. Cria o diretório (caso ele ainda não exista).
  2. Copia o sim.json atual para esse diretório.
  3. Edita o sim.json copiado para definir a mobilidade alvo.
  4. Altera o diretório de trabalho para esse diretório.
  5. Executa o solver nesse diretório, produzindo saídas locais para essa execução.

Esse padrão é a base do scripting em lote no OghmaNano: um diretório por execução, um arquivo de configuração por execução, e uma pasta de saída limpa para cada valor de parâmetro.


% O script deve ser iniciado no diretório base da simulação
% (isto é, o diretório que contém o sim.json de referência).
base_dir = pwd;

mobilities = [1e-5, 1e-6, 1e-7, 1e-8];
src_sim = fullfile(base_dir, "sim.json");

for k = 1:numel(mobilities)
    mu = mobilities(k);
    run_name = sprintf("mu_%.0e", mu);
    run_dir = fullfile(base_dir, run_name);
    if ~exist(run_dir, "dir")
        mkdir(run_dir);
    end

    % Copiar o sim.json base para o diretório da execução
    dst_sim = fullfile(run_dir, "sim.json");
    copyfile(src_sim, dst_sim);

    % Carregar o sim.json copiado e editar a mobilidade NESSA cópia
    txt = fileread(dst_sim);
    data = jsondecode(txt);
    data.epitaxy.segment1.shape_dos.mue_y = mu;

    out = jsonencode(data);
    fid = fopen(dst_sim, "w");
    fprintf(fid, "%s", out);
    fclose(fid);

    % Mudar para o diretório da execução e executar o solver ali
    cd(run_dir);
    system("oghma_core.exe");
    cd(base_dir);
end

4. Extraindo resultados

Depois de executar um lote de simulações em diretórios de execução separados (por exemplo mu_1e-05, mu_1e-06, ...), o próximo passo é extrair uma figura de mérito chave de cada execução e visualizar a tendência. Um exemplo comum é ler a tensão de circuito aberto \(V_{oc}\) de sim_info.dat em cada diretório e plotá-la em função da mobilidade inversa \(1/\mu\).

O script abaixo percorre um conjunto fixo de diretórios de execução correspondentes às mobilidades 1e-5, 1e-6, 1e-7, 1e-8 e, para cada diretório:

  1. Carrega sim_info.dat como JSON.
  2. Extrai Voc.
  3. Calcula \(1/\mu\) usando a mobilidade associada àquele diretório.
  4. Grava um pequeno arquivo de resumo (voc_vs_inv_mobility.dat).
  5. Plota \(V_{oc}\) vs \(1/\mu\).

% Execute isto a partir do diretório BASE que contém as pastas de execução
% (mu_1e-05, mu_1e-06, ...). Caso contrário, defina base_dir explicitamente.
base_dir = pwd;

% As mobilidades devem corresponder aos diretórios de execução gerados anteriormente
mobilities = [1e-5, 1e-6, 1e-7, 1e-8];

inv_mu = zeros(size(mobilities));
vocs   = zeros(size(mobilities));

for k = 1:numel(mobilities)
    mu = mobilities(k);
    run_dir = fullfile(base_dir, sprintf("mu_%.0e", mu));
    info_path = fullfile(run_dir, "sim_info.dat");

    if ~exist(info_path, "file")
        error("Missing sim_info.dat in: %s", run_dir);
    end

    txt = fileread(info_path);
    info = jsondecode(txt);

    vocs(k) = info.Voc;
    inv_mu(k) = 1.0 / mu;
end

% Gravar uma pequena tabela-resumo em disco
out_path = fullfile(base_dir, "voc_vs_inv_mobility.dat");
fid = fopen(out_path, "w");
fprintf(fid, "# inv_mobility(1/mu)    Voc(V)\n");
for k = 1:numel(inv_mu)
    fprintf(fid, "%.6e    %g\n", inv_mu(k), vocs(k));
end
fclose(fid);

% Plotar Voc em função da mobilidade inversa
figure;
plot(inv_mu, vocs, "o-");
xlabel("Mobilidade inversa (1/\mu)");
ylabel("Tensão de circuito aberto V_{oc} (V)");
title("V_{oc} vs mobilidade inversa");
grid on;