Skrypty w języku Python
1. Wprowadzenie
W OghmaNano skrypty Pythona działają poprzez bezpośrednią modyfikację plików konfiguracyjnych symulacji, zapisanych na dysku, a następnie uruchamiają silnik symulacyjny (oghma_core.exe), aby uruchomić model. W tej sekcji szczegółowo opisano ten proces.
2. Uruchamianie plików symulacyjnych za pomocą języka Python.
Symulacja OghmaNano jest w pełni definiowana przez pojedynczy plik konfiguracyjny w formacie JSON, sim.json. Plik ten zawiera kompletny stan symulacji, w tym strukturę urządzenia, parametry materiałowe, ustawienia numeryczne i konfigurację wyjściową. W wielu przypadkach sim.json już istnieje jako zwykły plik w katalogu symulacji.
Podczas uruchamiania OghmaNano z poziomu Pythona, skrypt odczytuje dane sim.json do pamięci, korzystając ze standardowej biblioteki json Pythona, modyfikuje jeden lub więcej parametrów, a następnie zapisuje zaktualizowane dane JSON z powrotem na dysk.
Co najważniejsze, skrypt Pythona musi być uruchomiony z ustawionym katalogiem roboczym na katalog symulacji – czyli katalog, w którym znajdują się pliki sim.json i sim.oghma. Z tego katalogu uruchamiany jest program oghma_core.exe.
Po zaktualizowaniu pliku JSON skrypt uruchamia program oghma_core.exe z tego samego katalogu. Silnik symulacyjny zawsze odczytuje pliki wejściowe z aktualnego katalogu roboczego, dlatego jeśli katalog roboczy jest nieprawidłowy, symulacja zakończy się niepowodzeniem lub uruchomi nieprawidłowy model.
To rozdzielenie zadań jest celowe i wyraźnie określone: Python odpowiada za definiowanie zmian w symulacji, natomiast OghmaNano odpowiada za uruchamianie obliczeń fizycznych na podstawie plików znajdujących się w bieżącym katalogu.
Poniższy przykład ilustruje ten proces poprzez załadowanie sim.json, zmodyfikowanie mobilności nośników w pierwszej warstwie urządzenia, zapisanie zaktualizowanej konfiguracji na dysku, a następnie uruchomienie symulacji z katalogu symulacji.
import json
import os
import sys
f=open('sim.json') #open the sim.json file
lines=f.readlines()
f.close()
lines="".join(lines) #convert the text to a python json object
data = json.loads(lines)
#Edit a value (use firefox as a json viewer
# to help you figure out which value to edit)
# this time we are editing the mobility of layer 1
data['epitaxy']['segment1']['shape_dos']['mue_y']=1.0
#convert the json object back to a string
jstr = json.dumps(data, sort_keys=False, indent='\t')
#write it back to disk
f=open('sim.json',"w")
f.write(jstr)
f.close()
#run the simulation using oghma_core
os.system("oghma_core.exe")
Jeśli w programie sim.json ustawiono symulację mającą na celu wygenerowanie krzywej J–V, OghmaNano zapisze pliki wynikowe w katalogu symulacji, zawierające takie parametry, jak PCE, współczynnik wypełnienia, \(J_{sc}\) i \(V_{oc}\).
Poniższy przykład ilustruje, jak odczytać plik wyjściowy w formacie JSON i dodać wartość \(V_{oc}\) do oddzielnego pliku tekstowego.
f=open('sim_info.dat')
lines=f.readlines()
f.close()
lines="".join(lines)
data = json.loads(lines)
f=open('out.dat',"a")
f.write(str(data["Voc"])+"\n");
f.close()
3. Bardziej zaawansowane symulacje.
W wielu procesach tworzenia skryptów będziesz chciał uruchamiać tę samą podstawową symulację wielokrotnie, używając różnych wartości parametrów, i przechowywać wyniki każdego uruchomienia w oddzielnym folderze. Jest to najprostszy sposób na zachowanie porządku w wynikach i uniknięcie przypadkowego nadpisywania danych.
Poniższy przykład tworzy zestaw katalogów odpowiadających czterem różnym typom mobilności (1e-5, 1e-6, 1e-7, 1e-8). Dla każdego katalogu wykonuje następujące czynności:
- Tworzy katalog (jeśli taki katalog jeszcze nie istnieje).
- Kopiuje aktualną wersję
sim.jsondo tego katalogu. - Modyfikuje skopiowany element
sim.json, aby ustawić docelową wartość mobilności. - Zmienia bieżący katalog roboczy na wskazany katalog.
- Uruchamia program rozwiązujący w danym katalogu, generując wyniki, które są zapisywane lokalnie w tym katalogu.
Ten schemat stanowi podstawę skryptów wsadowych w OghmaNano: dla każdego uruchomienia tworzony jest oddzielny katalog, oddzielny plik konfiguracyjny oraz czysty folder wyjściowy dla każdej wartości parametru.
import json
import os
import shutil
# The script must be started in the base simulation directory
# (i.e. the directory containing the reference sim.json).
base_dir = os.getcwd()
mobilities = [1e-5, 1e-6, 1e-7, 1e-8]
for mu in mobilities:
# Create a directory name that is easy to read and sorts nicely
run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
os.makedirs(run_dir, exist_ok=True)
# Copy the base sim.json into the run directory
src_sim = os.path.join(base_dir, "sim.json")
dst_sim = os.path.join(run_dir, "sim.json")
shutil.copyfile(src_sim, dst_sim)
# Load the copied sim.json and edit the mobility in THAT copy
f = open(dst_sim)
lines = f.readlines()
f.close()
lines = "".join(lines)
data = json.loads(lines)
# Edit a value: set the mobility for the first device layer
data['epitaxy']['segment1']['shape_dos']['mue_y'] = mu
jstr = json.dumps(data, sort_keys=False, indent='\t')
f = open(dst_sim, "w")
f.write(jstr)
f.close()
# Change into the run directory and execute the solver there
os.chdir(run_dir)
# If your command is "augment.nano" instead, replace the string below.
os.system("oghma_core.exe")
# Return to the base directory for the next run
os.chdir(base_dir)
Po uruchomieniu każdego z programów, w każdym katalogu znajdą się wyniki odpowiadające danej wartości mobilności. W następnej sekcji rozszerzymy ten skrypt, aby zbierać najważniejsze wyniki z każdego uruchomienia i łączyć je w jeden plik podsumowujący.
Wykreślenie zależności \(V_{oc}\) od odwrotności ruchliwości.
Po uruchomieniu serii symulacji w oddzielnych katalogach, następnym krokiem jest zazwyczaj wyodrębnienie kluczowego wskaźnika z każdego przebiegu i przedstawienie go w formie graficznej, aby zobrazować tendencję. Typowym przykładem jest odczytanie wartości napięcia w obwodzie otwartym \(V_{oc}\) z pliku wyjściowego w formacie JSON (sim_info.dat) i przedstawienie go na wykresie w odniesieniu do odwrotności ruchliwości \(1/\mu\).
Poniższy skrypt przeszukuje zestaw katalogów (np. mu_1e-05, mu_1e-06, ...) i dla każdego z nich wykonuje następujące czynności:
- Wczytuje dane
sim_info.datw formacie JSON. - Fragmenty
Voc. - Oblicza wartość \(1/\mu\) na podstawie mobilności powiązanej z danym katalogiem.
- Tworzy mały plik podsumowujący (
voc_vs_inv_mobility.dat). - Porównanie fabuł \(V_{oc}\) i \(1/\mu\).
import json
import os
# Optional: plotting (requires matplotlib)
import matplotlib.pyplot as plt
base_dir = os.getcwd()
# Mobilities must match the run directories you generated earlier
mobilities = [1e-5, 1e-6, 1e-7, 1e-8]
inv_mu = []
vocs = []
for mu in mobilities:
run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
info_path = os.path.join(run_dir, "sim_info.dat")
# Read the JSON output file and extract Voc
f = open(info_path)
lines = f.readlines()
f.close()
lines = "".join(lines)
data = json.loads(lines)
voc = data["Voc"]
inv_mu.append(1.0 / mu)
vocs.append(voc)
# Write a small summary table to disk
out = open("voc_vs_inv_mobility.dat", "w")
out.write("# inv_mobility(1/mu) Voc(V)\n")
for x, y in zip(inv_mu, vocs):
out.write(f"{x:.6e} {y}\n")
out.close()
# Plot Voc against inverse mobility
plt.plot(inv_mu, vocs, "o-")
plt.xlabel("Inverse mobility (1/μ)")
plt.ylabel("Open-circuit voltage Voc (V)")
plt.title("Voc vs inverse mobility")
plt.grid(True)
plt.tight_layout()
plt.show()
📺 Powiązany film
Poniższy film pokazuje, jak można sterować OghmaNano za pomocą skryptów napisanych w języku Python.
Uwaga: interfejs API i wewnętrzny interfejs skryptowy, które można zobaczyć w filmie, są obecnie przestarzałe i nie są już dostępne, ponieważ okazało się, że trudno je utrzymywać. Obecnie zaleca się stosowanie zewnętrznego skryptu Pythona do bezpośredniej edycji plików JSON zawierających dane symulacji, a następnie uruchamiania oghma_core.exe. To podejście jest prostsze, bardziej niezawodne i łatwiejsze w utrzymaniu. Film może nadal być przydatny do zrozumienia ogólnego przepływu pracy i typowych przypadków użycia, ale w celu uzyskania informacji o aktualnej metodzie należy postępować zgodnie z opisanymi powyżej instrukcjami.