Как решить уравнения, используя схему Шарфеттера-Гуммеля в FiPy?
Я пытаюсь использовать FiPy для моделирования солнечных элементов, но я изо всех сил пытаюсь получить разумные результаты даже для простых тестовых случаев.
Моя тестовая задача - резкий 1D pn гомопереход в темноте в равновесии. Управляющей системой уравнений являются уравнения полупроводников без дополнительной генерации или рекомбинации.
Уравнение Пуассона определяет электрическое поле (φ) в полупроводнике с диэлектрической проницаемостью & epsi;, учитывая плотности электронов (n), дырок (p), доноров (ND) и акцепторов (NA), где заряд электрона равен q:
∇²φ = q(p - n + ND - NA) / & epsi;
Электроны и дырки смещаются и диффундируют с плотностями тока, J, в зависимости от их подвижностей (μ) и констант диффузии (D):
Jn = qμn nE + qDn∇n
Jp = qμp pE - qDp∇n
Эволюция заряда в системе учитывается уравнениями неразрывности электронов и дырок:
∂n / ∂t = (∇ ·Jn) / q
∂p / ∂t = - (∇ ·Jp) / q
которая может быть выражена в канонической форме FiPy как:
∂n / ∂t = μn∇ · (-n∇φ) + Dn∇²n
∂p / ∂t = - (μp∇ · (-p∇φ) - Dp∇²n)
Чтобы попытаться решить проблему в FiPy, я сначала импортирую модули и определяю физические параметры.
from __future__ import print_function, division
import fipy
import numpy as np
import matplotlib.pyplot as plt
eps_0 = 8.8542e-12 # Permittivity of free space, F/m
q = 1.6022e-19 # Charge of an electron, C
k = 1.3807e-23 # Boltzmann constant, J/K
T = 300 # Temperature, K
Vth = (k*T)/q # Thermal voltage, eV
N_ap = 1e22 # Acceptor density in p-type layer, m^-3
N_an = 0 # Acceptor density in n-type layer, m^-3
N_dp = 0 # Donor density in p-type layer, m^-3
N_dn = 1e22 # Donor density in n-type layer, m^-3
mu_n = 1400.0e-4 # Mobilty of electrons, m^2/Vs
mu_p = 450.0e-4 # Mobilty of holes, m^2/Vs
D_p = k*T*mu_p/q # Hole diffusion constant, m^2/s
D_n = k*T*mu_n/q # Electron diffusion constant, m^2/s
eps_r = 11.8 # Relative dielectric constant
n_i = (5.29e19 * (T/300)**2.54 * np.exp(-6726/T))*1e6
V_bias = 0
Затем создайте сетку, переменные решения и профиль легирования.
nx = 20000
dx = 0.1e-9
mesh = fipy.Grid1D(dx=dx, nx=nx)
Ln = Lp = (nx/2) * dx
phi = fipy.CellVariable(mesh=mesh, hasOld=True, name='phi')
n = fipy.CellVariable(mesh=mesh, hasOld=True, name='n')
p = fipy.CellVariable(mesh=mesh, hasOld=True, name='p')
Na = fipy.CellVariable(mesh=mesh, name='Na')
Nd = fipy.CellVariable(mesh=mesh, name='Nd')
Затем я устанавливаю некоторые начальные значения для центров клеток и накладываю граничные условия Дирихле на все параметры.
x = mesh.cellCenters[0]
n0 = n_i**2 / N_ap
nL = N_dn
p0 = N_ap
pL = n_i**2 / N_dn
phi_min = -(Vth)*np.log(p0/n_i)
phi_max = (Vth)*np.log(nL/n_i) + V_bias
Na.setValue(N_an, where=(x >= Lp))
Na.setValue(N_ap, where=(x < Lp))
Nd.setValue(N_dn, where=(x >= Lp))
Nd.setValue(N_dp, where=(x < Lp))
n.setValue(N_dn, where=(x > Lp))
n.setValue(n_i**2 / N_ap, where=(x < Lp))
p.setValue(n_i**2 / N_dn, where=(x >= Lp))
p.setValue(N_ap, where=(x < Lp))
phi.setValue((phi_max - phi_min)*x/((Ln + Lp)) + phi_min)
phi.constrain(phi_min, mesh.facesLeft)
phi.constrain(phi_max, mesh.facesRight)
n.constrain(nL, mesh.facesRight)
n.constrain(n_i**2 / p0, mesh.facesLeft)
p.constrain(n_i**2 / nL, mesh.facesRight)
p.constrain(p0, mesh.facesLeft)
Я выражаю уравнение Пуассона как
eps = eps_0*eps_r
rho = q * (p - n + Nd - Na)
rho.name = 'rho'
poisson = fipy.ImplicitDiffusionTerm(coeff=eps, var=phi) == -rho
уравнения неразрывности как
cont_eqn_n = (fipy.TransientTerm(var=n) ==
(fipy.ExponentialConvectionTerm(coeff=-phi.faceGrad*mu_n, var=n)
+ fipy.ImplicitDiffusionTerm(coeff=D_n, var=n)))
cont_eqn_p = (fipy.TransientTerm(var=p) ==
- (fipy.ExponentialConvectionTerm(coeff=-phi.faceGrad*mu_p, var=p)
- fipy.ImplicitDiffusionTerm(coeff=D_p, var=p)))
и решить, связав уравнения и развертки:
eqn = poisson & cont_eqn_n & cont_eqn_p
dt = 1e-12
steps = 50
sweeps = 10
for step in range(steps):
phi.updateOld()
n.updateOld()
p.updateOld()
for sweep in range(sweeps):
eqn.sweep(dt=dt)
Я поиграл с разными значениями размера меша, временного шага, количества временных шагов, количества разверток и т. Д. Я вижу некоторые вариации, но мне не повезло найти набор условий, которые дают мне реалистичное решение. Я думаю, что проблема, вероятно, заключается в выражениях для текущих терминов.
Обычно при решении этих уравнений плотности тока аппроксимируются с использованием схемы дискретизации Шарфеттера-Гуммеля (SG), а не прямой дискретизации. В схеме SG плотность электронного тока (J) через поверхность ячейки аппроксимируется как функция значений потенциала (φ) и плотности заряда (n), определенных на центрах ячеек K и L с обеих сторон, как
Jn, KL=qμn VT[B(δφ / VT)nL - B(-δφ / VT)nK)
где q - заряд электрона, µn - подвижность электрона, VT - тепловое напряжение, δφ=φL-φK, а B(x) - функция Бернулли x/ (ex−1).
Для меня не очевидно, как реализовать схему в FiPy. Я видел, что есть scharfetterGummelFaceVariable
но я не могу понять из документации, подходит ли она или предназначена для этой проблемы. Глядя на код, кажется, что он вычисляет только функцию Бернулли, умноженную на коэффициент eφL. Можно ли напрямую использовать scharfetterGummelFaceVariable
решить этот тип проблемы? Если так, то как? Если нет, есть ли альтернативный подход, который позволит мне моделировать полупроводниковые устройства с использованием FiPy?