Dear Juan,
thank you for your replay and I appreciate your time.
I build a Si pin diode model which works very well when the diode is forward biased as can be seen from the attached figures.
However, when the diode is reversed biased I get the following error at -10V:
error: DEVSIM FATAL: while evaluating node model IntrinsicHoles:Potential on Device: Si_PiN on Region: Region
There was a Overflow floating point exception while evaluating pow(IntrinsicElectrons,(-2))
while evaluating model IntrinsicHoles:Potential: expression (-pow(IntrinsicElectrons,(-2)) * pow(n_i,2) * IntrinsicElectrons:Potential) evaluates to invalid
I did not implement the impact ionization following the example you kindly sent and I don’t think that this error is related to impact ionization because the reverse bias voltage is relativity low (-10V). The introduced pin diode model is supposed to block more that 1200V. I am trying to plot the electric field and potential in the n- drift layer. By the why, the error happens only when trying to use write_devices(file="pin_si_diode_rb", type="vtk")
. I am not sure if this information is helpful.
For completeness I am attaching the simulation script. I hope you can advice on what I am missing here.
My best,
Said
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 18 21:41:49 2024
@author: seb
"""
from devsim import *
from devsim.python_packages.simple_physics import *
from devsim.python_packages.ramp import *
from devsim.python_packages.model_create import CreateSolution
import numpy as np
import matplotlib.pyplot as plt
reset_devsim()
contactcharge_edge = "contactcharge_edge"
ece_name = "ElectronContinuityEquation"
hce_name = "HoleContinuityEquation"
# celec_model = "(0.5*abs(NetDoping+(NetDoping^2 + 4 * n_i^2)^(0.5)))"
# chole_model = "(0.5*abs(-NetDoping+(NetDoping^2 + 4 * n_i^2)^(0.5)))"
celec_model = "(1e-9 + 0.5*abs(NetDoping+(NetDoping^2 + 4 * n_i^2)^(0.5)))"
chole_model = "(1e-9 + 0.5*abs(-NetDoping+(NetDoping^2 + 4 * n_i^2)^(0.5)))"
q = 1.6e-19 # coul
k = 1.3806503e-23 # J/K
eps_0 = 8.85e-14 # F/cm^2
eps_si = 11.1
eps_ox = 3.9
n_i = 1.0e10 # #/cm^3
mu_n = 400 #1350 #400
mu_p = 200 #480 #200
tau_n = 2e-6
tau_p = tau_n/3
# Doping
Na_body = 1e+19
Nd_drift= 2e+14
Nd_subs = 1e+19
W_d = 140e-6
name="Si_PiN_Diode"
#All values in cm
def Create2DMesh(device, region):
create_2d_mesh(mesh="dio")
add_2d_mesh_line(mesh="dio", dir="x", pos=0, ps=1e-4) # P_bode
add_2d_mesh_line(mesh="dio", dir="x", pos=10e-4, ps=0.8e-6) # P body
add_2d_mesh_line(mesh="dio", dir="x", pos=80e-4, ps=1e-4) # N_minus
add_2d_mesh_line(mesh="dio", dir="x", pos=150e-4, ps=0.8e-6) # N_minus
add_2d_mesh_line(mesh="dio", dir="x", pos=210e-4, ps=1e-4) # N_plus
add_2d_mesh_line(mesh="dio", dir="y", pos=0, ps=0.5e-4) # y
add_2d_mesh_line(mesh="dio", dir="y", pos=30e-4, ps=0.5e-4) # y
add_2d_mesh_line(mesh="dio", dir="x", pos=-1e-4, ps=1e-4) # top metal
add_2d_mesh_line(mesh="dio", dir="x", pos= 211e-4,ps=1e-4) # bot metal
add_2d_region(mesh="dio", material="Si", region=region)
add_2d_region(mesh="dio", material="SiC", region="air1", xl=-1e-4, xh=0)
add_2d_region(mesh="dio", material="SiC", region="air2", xl=210e-4, xh=211e-4)
add_2d_contact(mesh="dio", name="top", material="metal", region=region, yl=0, yh=30e-4, xl=-1e-4, xh=0, bloat=1e-10)
add_2d_contact(mesh="dio", name="bot", material="metal", region=region, xl=210e-4, xh=211e-4, bloat=1e-10)
finalize_mesh(mesh="dio")
create_device(mesh="dio", device=device)
write_devices(file="si_pin_diode_mesh", type="vtk")
def SetNetDoping(device, region):
'''
NetDoping
'''
CreateNodeModel(device, region, "Acceptors", str(Na_body)+"*step(10e-4-x)") # P doping
CreateNodeModel(device, region, "Donors", str(Nd_drift) + "*(step(-10e-4+x)+step(150e-4-x))" + "+" + str(Nd_subs) + "*step(-150e-4+x)") # N- doping
CreateNodeModel(device, region, "NetDoping", "Donors-Acceptors")
def InitialSolution(device, region, circuit_contacts=None):
# Create Potential, Potential@n0, Potential@n1
CreateSolution(device, region, "Potential")
# Create potential only physical models
CreateSiliconPotentialOnly(device, region)
# Set up the contacts applying a bias
for i in get_contact_list(device=device):
if circuit_contacts and i in circuit_contacts:
CreateSiliconPotentialOnlyContact(device, region, i, True)
else:
###print "FIX THIS"
### it is more correct for the bias to be 0, and it looks like there is side effects
set_parameter(device=device, name=GetContactBiasName(i), value=0.0)
CreateSiliconPotentialOnlyContact(device, region, i)
def DriftDiffusionInitialSolution(device, region, circuit_contacts=None):
####
#### drift diffusion solution variables
####
CreateSolution(device, region, "Electrons")
CreateSolution(device, region, "Holes")
####
#### create initial guess from dc only solution
####
set_node_values(device=device, region=region, name="Electrons", init_from="IntrinsicElectrons")
set_node_values(device=device, region=region, name="Holes", init_from="IntrinsicHoles")
###
### Set up equations
###
CreateSiliconDriftDiffusion(device, region)
for i in get_contact_list(device=device):
if circuit_contacts and i in circuit_contacts:
CreateSiliconDriftDiffusionAtContact(device, region, i, True)
else:
CreateSiliconDriftDiffusionAtContact(device, region, i)
def SetSiliconParameters_my(device, region, T):
"""
Sets physical parameters assuming constants
"""
#### TODO: make T a free parameter and T dependent parameters as models
set_parameter(
device=device, region=region, name="Permittivity", value=eps_si * eps_0
)
set_parameter(device=device, region=region, name="ElectronCharge", value=q)
set_parameter(device=device, region=region, name="n_i", value=n_i)
set_parameter(device=device, region=region, name="T", value=T)
set_parameter(device=device, region=region, name="kT", value=k * T)
set_parameter(device=device, region=region, name="V_t", value=k * T / q)
set_parameter(device=device, region=region, name="mu_n", value=mu_n)
set_parameter(device=device, region=region, name="mu_p", value=mu_p)
# default SRH parameters
set_parameter(device=device, region=region, name="n1", value=n_i)
set_parameter(device=device, region=region, name="p1", value=n_i)
set_parameter(device=device, region=region, name="taun", value=tau_n) #0.2e-6
set_parameter(device=device, region=region, name="taup", value=tau_p) #0.045e-6
set_parameter(device=device, region=region, name="bot", value=0.0) #0.045e-6
if __name__=='__main__':
dev='Si_PiN'
region='Region'
Create2DMesh(dev,region)
SetSiliconParameters_my(dev, region, 300)
# set_parameter(name = "extended_solver", value=True)
# set_parameter(name = "extended_model", value=True)
# set_parameter(name = "extended_equation", value=True)
SetNetDoping(dev, region=region)
InitialSolution(dev, region)
solve(type="dc", absolute_error=1e5, relative_error=1e-12, maximum_iterations=50)
write_devices(file="si_diode_e", type="vtk")
DriftDiffusionInitialSolution(dev, region)
solve(type="dc", absolute_error=1e5, relative_error=1e-12, maximum_iterations=100)
FWB=False # False for reverse bias
fw_voltage=1
bw_voltage=-10
if FWB==True:
rampbias(dev, "top",fw_voltage,0.2,0.001, 60, 1e-12, 1e5, printAllCurrents)
write_devices(file="pin_si_diode_fw", type="vtk")
else:
rampbias(dev, "top",bw_voltage,2,0.01, 60, 1e-12, 1e5, printAllCurrents)
# delete_node_model(device=dev, region=region, name="IntrinsicElectrons")
# delete_node_model(device=dev, region=region, name="IntrinsicHoles")
# for i in np.linspace(0, 10, 20):
# print(f'############### {-i:2.2f} ################')
# set_parameter(device=dev, name=GetContactBiasName("top"), value=-i)
# solve(type="dc", absolute_error=1e5, relative_error=1e-9, maximum_iterations=100)
print('############### finished ################')
write_devices(file="pin_si_diode_rb", type="vtk")
#%%
fig,ax=plt.subplots(2,1,figsize=(8,9))
x=get_node_model_values(device=dev, region=region, name="x")
if FWB==True:
fig.suptitle('Simulation - Plasma and Doping')
y_e=get_node_model_values(device=dev, region=region, name="Electrons")
y_h=get_node_model_values(device=dev, region=region, name="Holes")
y_d=get_node_model_values(device=dev, region=region, name="Donors")
y_a=get_node_model_values(device=dev, region=region, name="Acceptors")
ax[0].set_title(f'Plasma @ {fw_voltage}V forward voltage')
ax[0].semilogy(x,y_e,label='Electrons')
ax[0].semilogy(x,y_h,label='Holes')
ax[0].set_ylim([1e14,2e19])
ax[0].set(ylabel='n and h concentration [$cm^{-3}$]')
ax[0].legend()
ax[0].grid(which='both')
ax[1].set_title('Doping')
ax[1].semilogy(x,y_d,label='$N_d$')
ax[1].semilogy(x,y_a,label='$N_a$')
ax[1].set_ylim([1e14,2e19])
ax[1].set(ylabel='doping concentration profile [$cm^{-3}$]')
ax[1].set(xlabel='x [cm]')
ax[1].legend()
ax[1].grid(which='both')
fig.savefig(f'{name}_at{fw_voltage}V.png')
else:
fig.suptitle('Simulation - Plasma and Doping')
# y_E=get_node_model_values(device=dev, region=region, name="ElectricField")
y_phi=get_node_model_values(device=dev, region=region, name="Potential")
ax[0].set_title('Plasma')
# ax[0].plot(x,y_E,label='E-Field')
ax[0].plot(x,y_phi,label='Potentia.')
# ax[0].set_ylim([1e14,2e19])
ax[0].set(ylabel='n and h concentration [$cm^{-3}$]')
ax[0].legend()
ax[0].grid(which='both')
# ax[1].set_title('Doping')
# ax[1].semilogy(x,y_d,label='$N_d$')
# ax[1].semilogy(x,y_a,label='$N_a$')
# ax[1].set_ylim([1e14,2e19])
# ax[1].set(ylabel='doping concentration profile [$cm^{-3}$]')
# ax[1].set(xlabel='x [cm]')
# ax[1].legend()
# ax[1].grid(which='both')