Convergece failure in reverse bias region - 1D diode

Hi Juan,

I am writing to request assistance with a challenging issue I’m experiencing in the dynamic simulation of a 1D diode. Static simulations with the DC Ramp function work seamlessly, but I’m encountering a significant problem during dynamic simulations in the time domain.

The diode is connected in series to a voltage source and a 1.23 Ohm*cm^2 resistor. After switching the driving voltage from 5 V to -5 V the diode voltage decreases smoothly, but an issue occurs when the diode voltage falls to approx. 0.2 V.

At this point, as the simulation approaches the reverse-bias region, it consistently results in a Convergence Error. This happens regardless of the approach I take with voltage ranges, whether it’s transitioning from 5V to -5V or simulating directly within the reverse-bias region from -4.9V to -5V or from -1.0V to -0.5V. The error occurs regardless of the speed of the driving voltage transient.

Why is the simulation in my case unable to smoothly navigate through the reverse-bias region dynamically. Is this a limitation inherent in the software, or is there a possibility that I am missing a crucial step or setting in the simulation setup?

In the following is my example code (can be executed when added to examples/diode):

import devsim
from devsim.python_packages.simple_physics import *
import diode_common

def print_circuit_solution():
    for node in get_circuit_node_list():
        r = get_circuit_node_value(solution='dcop', node=node)
        print("%s\t%1.15e" % (node, r))

def CreateMesh(device, region):
    '''
      Meshing
    '''
    create_1d_mesh(mesh="dio")
    # 1e-7 cm = 1 nm, 1e-4 cm = 1 um
    add_1d_mesh_line(mesh="dio", pos=0, ps=0.5e-4, tag="top")
    add_1d_mesh_line(mesh="dio", pos=10e-4, ps=1e-7, tag="mid")
    add_1d_mesh_line(mesh="dio", pos=20e-4, ps=0.5e-4, tag="bot")
    add_1d_contact(mesh="dio", name="top", tag="top", material="metal")
    add_1d_contact(mesh="dio", name="bot", tag="bot", material="metal")
    add_1d_region(mesh="dio", material="Si", region=region, tag1="top", tag2="bot")
    finalize_mesh(mesh="dio")
    create_device(mesh="dio", device=device)

def SetParameters(device, region):
    '''
      Set parameters for 300 K
    '''
    SetSiliconParameters(device, region, 300)
    set_parameter(device=device, region=region, name="taun", value=1.0e-8)  
    set_parameter(device=device, region=region, name="taup", value=1.0e-8)  
    # Electron-mobility
    set_parameter(device=device, region=region, name="mu_n", value="400")
    # Hole-mobility
    set_parameter(device=device, region=region, name="mu_p", value="200")


def SetNetDoping(device, region):
    '''
      NetDoping
    '''
    CreateNodeModel(device, region, "Acceptors", "1.0e17*step(10e-4-x)")
    CreateNodeModel(device, region, "Donors",    "4.0e17*step(x-10e-4)")
    CreateNodeModel(device, region, "NetDoping", "Donors-Acceptors")

device = "MyDevice"
region = "MyRegion"

# Set extended parameters
set_parameter(name="extended_solver", value=True)
set_parameter(name="extended_model", value=True)
set_parameter(name="extended_equation", value=True)

# Definition of V1(t)
start_voltage = 5.0 
initial_step_voltage = 0.7
end_voltage = -5.0
ramp_time = 500e-9 
start_time = 0.0
end_time = 450e-9
time_step = 2.0e-9

# Circuit
resistor = 1.23 # ohm/cm^2

circuit_element(name="V1", n1=1, n2=0, value=initial_step_voltage)
circuit_element(name="R1", n1=1, n2=GetContactBiasName("top"), value=resistor)

CreateMesh(device=device, region=region)
SetParameters(device=device, region=region)
SetNetDoping(device=device, region=region)
diode_common.InitialSolution(device, region, circuit_contacts="top")

# Initial DC solution (Poisson)
devsim.solve(type="dc", absolute_error=1.0, relative_error=1e-9, maximum_iterations=30)

diode_common.DriftDiffusionInitialSolution(device, region, circuit_contacts=["top"])
devsim.solve(type="transient_dc", absolute_error=1.0, relative_error=1e-9, maximum_iterations=30)

# Now Set the start voltage
circuit_alter(name="V1", value = start_voltage)
devsim.solve(type="transient_dc", absolute_error=1.0, relative_error=1e-14, maximum_iterations=30)

# ramp up
current_time = start_time

while current_time < end_time:
   
    if current_time <= ramp_time:
        output_voltage = start_voltage - ((start_voltage - end_voltage) / ramp_time) * current_time
    
    circuit_alter(name="V1", value=output_voltage)    
    devsim.solve(type="transient_bdf1", absolute_error=1e10, relative_error=1e-9, maximum_iterations=100, tdelta=time_step, charge_error=1)
    
    print_circuit_solution()

    current_time += time_step

I would greatly appreciate your insights or suggestions on how to resolve these issues.
Thanks a ton for any help or insights you can provide!

Viviana

Hello,

Thanks for sharing your detailed example. I will annotate some differences in getting your example to run:

I installed the numpy module to use for ramping the initial bias for the simulation:

3a4
> import numpy as np

Make the extended stuff optional:

50,52c51,54
< set_parameter(name="extended_solver", value=True)
< set_parameter(name="extended_model", value=True)
< set_parameter(name="extended_equation", value=True)
---
> if False:
>     set_parameter(name="extended_solver", value=True)
>     set_parameter(name="extended_model", value=True)
>     set_parameter(name="extended_equation", value=True)
  • The initial dc drift diffusion biases were failing since they were not at equilibrium to start.
  • The circuit_contacts option needed a list instead of a string.
  • Using absolute_error=1e5 to give double precision a reasonable chance of converging:
66c68
< circuit_element(name="V1", n1=1, n2=0, value=initial_step_voltage)
---
> circuit_element(name="V1", n1=1, n2=0, value=0.0)
72c74
< diode_common.InitialSolution(device, region, circuit_contacts="top")
---
> diode_common.InitialSolution(device, region, circuit_contacts=["top"])
78c80,83
< devsim.solve(type="transient_dc", absolute_error=1.0, relative_error=1e-9, maximum_iterations=30)
---
> devsim.solve(type="dc", absolute_error=1e5, relative_error=1e-9, maximum_iterations=30)
> for i in np.linspace(0, start_voltage, 20):
>     circuit_alter(name="V1", value = float(i))
>     devsim.solve(type="dc", absolute_error=1e5, relative_error=1e-9, maximum_iterations=30)
82c87
< devsim.solve(type="transient_dc", absolute_error=1.0, relative_error=1e-14, maximum_iterations=30)
---
> devsim.solve(type="transient_dc", absolute_error=1e5, relative_error=1e-14, maximum_iterations=30)

Runtime comparison double precision:

real	0m3.320s
user	0m19.253s
sys	0m1.100s

extended precision:

real	0m6.892s
user	0m40.406s
sys	0m1.348s

I hope this resolves the issue you are seeing.

The full script below:

import devsim
from devsim.python_packages.simple_physics import *
import diode_common
import numpy as np

def print_circuit_solution():
    for node in get_circuit_node_list():
        r = get_circuit_node_value(solution='dcop', node=node)
        print("%s\t%1.15e" % (node, r))

def CreateMesh(device, region):
    '''
      Meshing
    '''
    create_1d_mesh(mesh="dio")
    # 1e-7 cm = 1 nm, 1e-4 cm = 1 um
    add_1d_mesh_line(mesh="dio", pos=0, ps=0.5e-4, tag="top")
    add_1d_mesh_line(mesh="dio", pos=10e-4, ps=1e-7, tag="mid")
    add_1d_mesh_line(mesh="dio", pos=20e-4, ps=0.5e-4, tag="bot")
    add_1d_contact(mesh="dio", name="top", tag="top", material="metal")
    add_1d_contact(mesh="dio", name="bot", tag="bot", material="metal")
    add_1d_region(mesh="dio", material="Si", region=region, tag1="top", tag2="bot")
    finalize_mesh(mesh="dio")
    create_device(mesh="dio", device=device)

def SetParameters(device, region):
    '''
      Set parameters for 300 K
    '''
    SetSiliconParameters(device, region, 300)
    set_parameter(device=device, region=region, name="taun", value=1.0e-8)  
    set_parameter(device=device, region=region, name="taup", value=1.0e-8)  
    # Electron-mobility
    set_parameter(device=device, region=region, name="mu_n", value="400")
    # Hole-mobility
    set_parameter(device=device, region=region, name="mu_p", value="200")


def SetNetDoping(device, region):
    '''
      NetDoping
    '''
    CreateNodeModel(device, region, "Acceptors", "1.0e17*step(10e-4-x)")
    CreateNodeModel(device, region, "Donors",    "4.0e17*step(x-10e-4)")
    CreateNodeModel(device, region, "NetDoping", "Donors-Acceptors")

device = "MyDevice"
region = "MyRegion"

# Set extended parameters
if False:
    set_parameter(name="extended_solver", value=True)
    set_parameter(name="extended_model", value=True)
    set_parameter(name="extended_equation", value=True)

# Definition of V1(t)
start_voltage = 5.0 
initial_step_voltage = 0.7
end_voltage = -5.0
ramp_time = 500e-9 
start_time = 0.0
end_time = 450e-9
time_step = 2.0e-9

# Circuit
resistor = 1.23 # ohm/cm^2

circuit_element(name="V1", n1=1, n2=0, value=0.0)
circuit_element(name="R1", n1=1, n2=GetContactBiasName("top"), value=resistor)

CreateMesh(device=device, region=region)
SetParameters(device=device, region=region)
SetNetDoping(device=device, region=region)
diode_common.InitialSolution(device, region, circuit_contacts=["top"])

# Initial DC solution (Poisson)
devsim.solve(type="dc", absolute_error=1.0, relative_error=1e-9, maximum_iterations=30)

diode_common.DriftDiffusionInitialSolution(device, region, circuit_contacts=["top"])
devsim.solve(type="dc", absolute_error=1e5, relative_error=1e-9, maximum_iterations=30)
for i in np.linspace(0, start_voltage, 20):
    circuit_alter(name="V1", value = float(i))
    devsim.solve(type="dc", absolute_error=1e5, relative_error=1e-9, maximum_iterations=30)

# Now Set the start voltage
circuit_alter(name="V1", value = start_voltage)
devsim.solve(type="transient_dc", absolute_error=1e5, relative_error=1e-14, maximum_iterations=30)

# ramp up
current_time = start_time

while current_time < end_time:
   
    if current_time <= ramp_time:
        output_voltage = start_voltage - ((start_voltage - end_voltage) / ramp_time) * current_time
    
    circuit_alter(name="V1", value=output_voltage)    
    devsim.solve(type="transient_bdf1", absolute_error=1e10, relative_error=1e-9, maximum_iterations=100, tdelta=time_step, charge_error=1)
    
    print_circuit_solution()

    current_time += time_step

Hello Juan,

Thank you so much for your quick and detailed reply!

Unfortunately, I am still encountering an error:

Iteration: 29
  Device: "MyDevice"    RelError: 2.32958e+03   AbsError: 1.78514e+109
    Region: "MyRegion"  RelError: 2.32958e+03   AbsError: 1.78514e+109
      Equation: "ElectronContinuityEquation"    RelError: 9.99000e+02   AbsError: 8.92570e+108
      Equation: "HoleContinuityEquation"        RelError: 9.99000e+02   AbsError: 8.92570e+108
      Equation: "PotentialEquation"     RelError: 3.31577e+02   AbsError: 2.34536e+00
  Circuit:      RelError: 1.00000e+00   AbsError: 9.29042e+36
Iteration: 30
  Device: "MyDevice"    RelError: 2.00029e+03   AbsError: 3.38183e+147
    Region: "MyRegion"  RelError: 2.00029e+03   AbsError: 3.38183e+147
      Equation: "ElectronContinuityEquation"    RelError: 9.99000e+02   AbsError: 1.69092e+147
      Equation: "HoleContinuityEquation"        RelError: 9.99000e+02   AbsError: 1.69092e+147
      Equation: "PotentialEquation"     RelError: 2.28800e+00   AbsError: 4.92567e+00
  Circuit:      RelError: 1.00000e+00   AbsError: 1.44793e+79
Iteration: 31
  Device: "MyDevice"    RelError: 2.00396e+03   AbsError: 5.57711e+228
    Region: "MyRegion"  RelError: 2.00396e+03   AbsError: 5.57711e+228
      Equation: "ElectronContinuityEquation"    RelError: 9.99000e+02   AbsError: 2.78856e+228
      Equation: "HoleContinuityEquation"        RelError: 9.99000e+02   AbsError: 2.78856e+228
      Equation: "PotentialEquation"     RelError: 5.95784e+00   AbsError: 9.80675e+00
  Circuit:      RelError: 1.00000e+00   AbsError: 1.29577e+163
There was a floating point exception of type "Invalid"  during LU Back Substitution
Matrix solve failed
Traceback (most recent call last):
  File "c:\Users\vivia\anaconda3\envs\devsim-env\devsim_win64_v2.4.0\examples\diode\diode_1d_107_slow_copy.py", line 99, in <module>
    devsim.solve(type="transient_bdf1", absolute_error=1e10, relative_error=1e-9, maximum_iterations=100, tdelta=time_step, charge_error=1)
devsim_py3.error: Convergence failure!

In the last successful iteration of the while loop (#30) I had the following results:

print_circuit_soultuion:
1       -1.039999999999987e+00
V1.I    1.043678876379476e+00
top_bias        2.437250179467687e-01

current_time: 3.0199999999999934e-07

Did your code run without any errors or are you encountering the same problems?
Do you have any idea why these errors occur in my case?

Thank you in advance for any insights or advice you can provide.

Best regards,
Viviana

Are you using the script I sent you back?

I am running on Linux.

Did you install mkl?

conda install mkl

Please share the value of:

get_parameter(name="info")

Hello,

I am able to run my script that is at the end of my message above. The final step is:

Charge Relative Error 8.13643e-01
1       -3.999999999999973e+00
V1.I    1.050290018441870e+00
top_bias        -2.708143277316474e+00

If your simulation is having some success, then please consider using smaller time steps.

It looks like your run directory is labeled version 2.4. The most recent version of devsim is 2.7.

Please note a critical transient issue was fixed in version 2.6.1:
https://devsim.net/releasenotes.html#version-2-6-1