Ssac and transient in generation term

Hi Juan,

To model the AC behaviour of photodetectors, one typically perturbs (SSAC) or pulses (transient) a carrier generation term corresponding to some illumination profile

Since all the AC examples only involves going through the device contacts, I’m wondering if there is any proper practice to do this before going down the rabbit hole :slight_smile:

Hi,

devsim is capable of the Impedance Field Method. Which is used to perturb sources inside of the device, and results in an external current. Is that the type of transfer function you need? You end up with a transfer function from each node to an external contact current. This transfer function is at a given frequency.

I have used this method for noise simulation of both generation-recombination and diffusion. It can also used it for variability, including random dopant fluctuations.

It seems like it would be a fit to your application, and I would be very interested in hearing if that is being used in the photodetector simulation.

1 Like

Hi @simbilod,

for my simulations I attach an extra generation term to SRH to emulate optical generation. It might not be best practice but it works for my transient simulations.

Modify SRH Equation:

def CreateSRHOptical(device, region):
    """
    Modified SRH model to include constant carrier generation, used to emulate optical generation
    :param device:
    :param region:
    :return:
    """
    # init optical generation to 0.0 on all nodes
    ds.set_parameter(device=device, name="OptScale", value=0.0)
    ds.node_solution(device=device, region=region, name="OptGen")
    xpos = ds.get_node_model_values(device=device, region=region, name="x")
    optical_generation = [0.0] * len(xpos)
    ds.set_node_values(device=device, region=region, name="OptGen", values=optical_generation)

    USRH = "(Electrons*Holes - n_i^2)/(taup*(Electrons + n1) + taun*(Holes + p1))"
    Gn = "-ElectronCharge * (USRH - OptGen * OptScale)"
    Gp = "+ElectronCharge * (USRH - OptGen * OptScale)"
    CreateNodeModel(device, region, "USRH", USRH)
    CreateNodeModel(device, region, "ElectronGeneration", Gn)
    CreateNodeModel(device, region, "HoleGeneration", Gp)
    for i in ("Electrons", "Holes"):
        CreateNodeModelDerivative(device, region, "USRH", USRH, i)
        CreateNodeModelDerivative(device, region, "ElectronGeneration", Gn, i)
        CreateNodeModelDerivative(device, region, "HoleGeneration", Gp, i)

Change OptGen Term to some value on all mesh points within a circle. Constant values in z-Direction in this examples:

def OpticalGenerationCircular(device, region, center: tuple = (0, 0), radius: float = 1.0,
                              genrate: float = 0.0) -> None:
    """
    Define constant cylindrical illumination profile
    """

    xpos = ds.get_node_model_values(device=device, region=region, name="x")
    ypos = ds.get_node_model_values(device=device, region=region, name="y")
    zpos = ds.get_node_model_values(device=device, region=region, name="z")

    optical_generation = [0.0] * len(xpos)

    for i in range(len(xpos)):
        if (xpos[i]*1e4 - center[0]) ** 2 + (ypos[i]*1e4 - center[1]) ** 2 <= radius ** 2:
            value = float(genrate)
            optical_generation[i] = value

    ds.set_node_values(device=device, region=region, name="OptGen", values=optical_generation)

With this you can now modify the global ‘OptScale’ Parameter to switch the light on and off:

//On
ds.set_parameter(device=self.device, name="OptScale", value=0.0)
//Off
ds.set_parameter(device=self.device, name="OptScale", value=1.0)
2 Likes

Thank you both! The global turn-on turn-off parameter is very clever, I will give it a shot.

1 Like