اسکریپتنویسی Python
1. مقدمه
در OghmaNano، اسکریپتنویسی Python با ویرایش مستقیم فایلهای پیکربندی شبیهسازی روی دیسک
و سپس فراخوانی موتور شبیهسازی (oghma_core.exe) برای اجرای مدل انجام میشود.
این بخش این جریان کاری را با جزئیات شرح میدهد.
2. اجرای فایلهای شبیهسازی با Python
یک شبیهسازی OghmaNano بهطور کامل توسط یک فایل پیکربندی JSON منفرد،
sim.json، تعریف میشود.
این فایل شامل وضعیت کامل شبیهسازی است، از جمله ساختار دستگاه،
پارامترهای مواد، تنظیمات عددی، و پیکربندی خروجی.
در بسیاری از موارد، sim.json از قبل بهصورت یک فایل عادی در دایرکتوری شبیهسازی وجود دارد.
هنگام کنترل OghmaNano از طریق Python، اسکریپت با استفاده از
کتابخانه استاندارد json در Python فایل sim.json را در حافظه میخواند،
یک یا چند پارامتر را تغییر میدهد، و JSON بهروزشده را
دوباره روی دیسک مینویسد.
نکته کلیدی این است که اسکریپت Python باید با دایرکتوری کاری برابر با
دایرکتوری شبیهسازی اجرا شود — یعنی دایرکتوریای که شامل
sim.json (و
sim.oghma) است.
این همان دایرکتوریای است که oghma_core.exe از آن اجرا میشود.
پس از بهروزرسانی فایل JSON، اسکریپت oghma_core.exe را
از همان دایرکتوری اجرا میکند.
موتور شبیهسازی همیشه فایلهای ورودی خود را از دایرکتوری کاری فعلی میخواند،
بنابراین اگر دایرکتوری کاری نادرست باشد، شبیهسازی شکست میخورد یا مدل اشتباهی را اجرا میکند.
این تفکیک مسئولیتها عمدی و صریح است: Python مسئول تعریف این است که چه چیزی در شبیهسازی تغییر میکند، در حالی که OghmaNano مسئول اجرای فیزیک با استفاده از فایلهای موجود در دایرکتوری فعلی است.
مثال زیر این فرایند را با بارگذاری sim.json، تغییر تحرکپذیری حامل
در اولین لایه دستگاه، نوشتن پیکربندی بهروزشده روی دیسک، و سپس
اجرای شبیهسازی از دایرکتوری شبیهسازی نشان میدهد.
import json
import os
import sys
f=open('sim.json') # فایل sim.json را باز کن
lines=f.readlines()
f.close()
lines="".join(lines) # متن را به یک شیء json در Python تبدیل کن
data = json.loads(lines)
# یک مقدار را ویرایش کن (از firefox بهعنوان نمایشگر json استفاده کن
# تا به شما کمک کند بفهمید کدام مقدار را باید ویرایش کنید)
# این بار ما در حال ویرایش تحرکپذیری لایه 1 هستیم
data['epitaxy']['segment1']['shape_dos']['mue_y']=1.0
# شیء json را دوباره به یک رشته تبدیل کن
jstr = json.dumps(data, sort_keys=False, indent='\t')
# آن را دوباره روی دیسک بنویس
f=open('sim.json',"w")
f.write(jstr)
f.close()
# شبیهسازی را با استفاده از oghma_core اجرا کن
os.system("oghma_core.exe")
اگر شبیهسازی در sim.json طوری تنظیم شده باشد که یک منحنی J–V را اجرا کند، OghmaNano فایلهای خروجی را در
دایرکتوری شبیهسازی خواهد نوشت که شامل کمیتهایی مانند PCE، fill factor، \(J_{sc}\) و
\(V_{oc}\) هستند.
مثال زیر نشان میدهد چگونه یک فایل خروجی JSON را بخوانید و مقدار \(V_{oc}\) را به یک فایل متنی جداگانه اضافه کنید.
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. شبیهسازیهای پیچیدهتر
در بسیاری از جریانهای کاری اسکریپتنویسی، شما میخواهید همان شبیهسازی پایه را چندین بار با مقادیر متفاوت پارامتر اجرا کنید و هر اجرا را در دایرکتوری مخصوص خودش نگه دارید. این سادهترین روش برای تمیز نگه داشتن خروجیها و جلوگیری از بازنویسی تصادفی نتایج است.
مثال زیر مجموعهای از دایرکتوریها را متناظر با چهار تحرکپذیری
(1e-5، 1e-6، 1e-7، 1e-8) ایجاد میکند. برای هر دایرکتوری، این کارها انجام میشوند:
- دایرکتوری را ایجاد میکند (اگر از قبل وجود نداشته باشد).
sim.jsonفعلی را به آن دایرکتوری کپی میکند.sim.jsonکپیشده را ویرایش میکند تا تحرکپذیری هدف تنظیم شود.- دایرکتوری کاری را به آن دایرکتوری تغییر میدهد.
- حلگر را در همان دایرکتوری اجرا میکند و خروجیهای محلی همان اجرا را تولید میکند.
این الگو، مبنای اسکریپتنویسی دستهای در OghmaNano است: یک دایرکتوری برای هر اجرا، یک فایل پیکربندی برای هر اجرا، و یک پوشه خروجی تمیز برای هر مقدار پارامتر.
import json
import os
import shutil
# اسکریپت باید در دایرکتوری پایه شبیهسازی شروع شود
# (یعنی دایرکتوریای که حاوی sim.json مرجع است).
base_dir = os.getcwd()
mobilities = [1e-5, 1e-6, 1e-7, 1e-8]
for mu in mobilities:
# یک نام دایرکتوری بساز که خوانا باشد و مرتبسازی خوبی داشته باشد
run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
os.makedirs(run_dir, exist_ok=True)
# sim.json پایه را به دایرکتوری اجرا کپی کن
src_sim = os.path.join(base_dir, "sim.json")
dst_sim = os.path.join(run_dir, "sim.json")
shutil.copyfile(src_sim, dst_sim)
# sim.json کپیشده را بارگذاری کن و تحرکپذیری را در همان کپی ویرایش کن
f = open(dst_sim)
lines = f.readlines()
f.close()
lines = "".join(lines)
data = json.loads(lines)
# یک مقدار را ویرایش کن: تحرکپذیری اولین لایه دستگاه را تنظیم کن
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()
# به دایرکتوری اجرا برو و حلگر را همانجا اجرا کن
os.chdir(run_dir)
# اگر فرمان شما "augment.nano" است، رشته زیر را جایگزین کنید.
os.system("oghma_core.exe")
# برای اجرای بعدی به دایرکتوری پایه بازگرد
os.chdir(base_dir)
پس از اجرا، هر دایرکتوری شامل خروجیهای متناظر با همان مقدار تحرکپذیری خواهد بود. در بخش بعدی، این اسکریپت را گسترش میدهیم تا نتایج کلیدی هر اجرا را جمعآوری کرده و آنها را در یک فایل خلاصه واحد ادغام کنیم.
رسم \(V_{oc}\) بر حسب معکوس تحرکپذیری
پس از آنکه یک دسته از شبیهسازیها را در دایرکتوریهای جداگانه اجرا کردید، گام بعدی معمولاً استخراج یک شاخص کلیدی
از هر اجرا و بصریسازی روند آن است. یک مثال رایج این است که ولتاژ مدار باز
\(V_{oc}\) را از فایل خروجی JSON (sim_info.dat) بخوانید و آن را بر حسب
معکوس تحرکپذیری \(1/\mu\) رسم کنید.
اسکریپت زیر مجموعهای از دایرکتوریهای اجرا (برای مثال mu_1e-05، mu_1e-06، ...)
را پیمایش میکند و برای هر دایرکتوری:
sim_info.datرا بهعنوان JSON بارگذاری میکند.Vocرا استخراج میکند.- \(1/\mu\) را با استفاده از تحرکپذیری متناظر با آن دایرکتوری محاسبه میکند.
- یک فایل خلاصه کوچک (
voc_vs_inv_mobility.dat) مینویسد. - \(V_{oc}\) را بر حسب \(1/\mu\) رسم میکند.
import json
import os
# اختیاری: رسم نمودار (به matplotlib نیاز دارد)
import matplotlib.pyplot as plt
base_dir = os.getcwd()
# تحرکپذیریها باید با دایرکتوریهای اجرای ساختهشده قبلی مطابقت داشته باشند
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")
# فایل خروجی JSON را بخوان و 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)
# یک جدول خلاصه کوچک روی دیسک بنویس
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()
# Voc را بر حسب معکوس تحرکپذیری رسم کن
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()
📺 ویدئوی مرتبط
ویدئوی زیر نشان میدهد چگونه میتوان OghmaNano را با استفاده از اسکریپتنویسی Python کنترل کرد.
توجه: API و رابط اسکریپتنویسی داخلی که در این ویدئو نشان داده شدهاند اکنون منسوخ شدهاند و دیگر
ارائه نمیشوند، زیرا نگهداری از آنها دشوار بود. جریان کاری فعلی و توصیهشده این است که از یک اسکریپت Python خارجی
برای ویرایش مستقیم فایلهای JSON شبیهسازی استفاده کنید و سپس oghma_core.exe را فراخوانی کنید. این رویکرد
سادهتر، پایدارتر، و نگهداری آن آسانتر است. با این حال ممکن است این ویدئو همچنان برای درک جریان کاری کلی و موارد استفاده معمول مفید باشد، اما برای
روش بهروز، لطفاً مراحل شرحدادهشده در بالا را دنبال کنید.