Ejemplo n.º 1
0
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
    ####
    ds.set_node_values(device=device,
                       region=region,
                       name="Electrons",
                       init_from="IntrinsicElectrons")
    ds.set_node_values(device=device,
                       region=region,
                       name="Holes",
                       init_from="IntrinsicHoles")

    ###
    ### Set up equations
    ###
    CreateSiliconDriftDiffusion(device, region)
    for i in ds.get_contact_list(device=device):
        if circuit_contacts and i in circuit_contacts:
            CreateSiliconDriftDiffusionAtContact(device, region, i, True)
        else:
            CreateSiliconDriftDiffusionAtContact(device, region, i)
Ejemplo n.º 2
0
def get_ds_status():
    devices = ds.get_device_list()
    for device in devices:
        print("Device: " + device)
        regions = ds.get_region_list(device=device)
        for region in regions:
            print("\tRegion :" + region)
            params = ds.get_parameter_list(device=device, region=region)
            for param in params:
                val = ds.get_parameter(device=device,
                                       region=region,
                                       name=param)
                print(f"\t\t{param} = {val}")
            n_models = ds.get_node_model_list(device=device, region=region)
            for node_model in n_models:
                nmvals = ds.get_node_model_values(device=device,
                                                  region=region,
                                                  name=node_model)
                print(f"\t\t Node Model '{node_model}' = {nmvals!s}")
            e_models = ds.get_edge_model_list(device=device, region=region)
            for edge_model in e_models:
                emvals = ds.get_edge_model_values(device=device,
                                                  region=region,
                                                  name=edge_model)
                print(f"\t\t Edge Model '{edge_model}' = {emvals!s}")
        contacts = ds.get_contact_list(device=device)
        for contact in contacts:
            print("\tContact : " + contact)
            c_eqs = ds.get_contact_equation_list(device=device,
                                                 contact=contact)
            for ceq in c_eqs:
                print("\t\tContact Equation : " + ceq)
Ejemplo n.º 3
0
def get_ds_status(short=True):
    """
    Prints the status of the current devsim setup and all variables, solutions, node models and edge models
    :return:
    """
    for device in ds.get_device_list():
        print("Device: " + device)
        for region in ds.get_region_list(device=device):
            print("\tRegion :" + region)
            params = ds.get_parameter_list(device=device, region=region)
            for param in params:
                val = ds.get_parameter(device=device,
                                       region=region,
                                       name=param)
                print(f"\t\t{param} = {val}")
            for node_model in ds.get_node_model_list(device=device,
                                                     region=region):
                nmvals = ds.get_node_model_values(device=device,
                                                  region=region,
                                                  name=node_model)
                nmstr = ','.join([f'{val:.3g}' for val in nmvals])
                print(f"\t\tNode Model '{node_model}' = {nmstr!s}")
            e_models = ds.get_edge_model_list(device=device, region=region)
            for edge_model in e_models:
                emvals = ds.get_edge_model_values(device=device,
                                                  region=region,
                                                  name=edge_model)
                emstr = ','.join([f'{val:.3g}' for val in emvals])
                print(f"\t\tEdge Model '{edge_model}' = {emstr}")
        for interface in ds.get_interface_list(device=device):
            print("\tInterface: " + interface)
            for imodel in ds.get_interface_model_list(device=device,
                                                      interface=interface):
                intstr = ','.join([
                    f'{val:.3g}' for val in ds.get_interface_model_values(
                        device=device, interface=interface, name=imodel)
                ])
                print(f"\t\tInterface Model: '{imodel}' = {intstr}")
            for ieq in ds.get_interface_equation_list(device=device,
                                                      interface=interface):
                # comm = ds.get_interface_equation_command(device=device, interface=interface, name=ieq)
                print(f"\t\tInterface Equation: {ieq}")
        contacts = ds.get_contact_list(device=device)
        for contact in contacts:
            print("\tContact : " + contact)
            c_eqs = ds.get_contact_equation_list(device=device,
                                                 contact=contact)
            for ceq in c_eqs:
                print("\t\tContact Equation : " + ceq)
Ejemplo n.º 4
0
def get_voltage_current(device=None, contact=None, ece_name="ElectronContinuityEquation",
                        hce_name="HoleContinuityEquation"):
    '''
       Return voltage and current for the device
    '''
    if device is None:
        device = ds.get_device_list()[0]
        logger.warning(f"No device specified! Assuming '{device}'")
    if contact is None:
        contact = ds.get_contact_list(device)[0]
    electron_current = ds.get_contact_current(device=device, contact=contact, equation=ece_name)
    hole_current = ds.get_contact_current(device=device, contact=contact, equation=hce_name)
    total_current = electron_current + hole_current
    voltage = ds.get_parameter(device=device, name=f"{contact}_bias")
    return voltage, total_current
Ejemplo n.º 5
0
def get_ds_equations():
    devices = ds.get_device_list()
    for device in devices:
        print("Device: " + device)
        regions = ds.get_region_list(device=device)
        for region in regions:
            print("\tRegion :" + region)
            eqs = ds.get_equation_list(device=device, region=region)
            print(f"\t\t{eqs!s}")
            # params = ds.get_parameter_list(device=device, region=region)
            for eq in eqs:
                val = ds.get_equation_command(device=device,
                                              region=region,
                                              name=eq)
                print(f"\t\t{eq} = {val}")
        contacts = ds.get_contact_list(device=device)
        for contact in contacts:
            print("\tContact : " + contact)
            c_eqs = ds.get_contact_equation_list(device=device,
                                                 contact=contact)
            for ceq in c_eqs:
                print("\t\tContact Equation : " + ceq)
Ejemplo n.º 6
0
####
volts = []
current = []
v = 0.0
while v < 0.51:
    # plot_charge([region])
    set_parameter(device=device, name=GetContactBiasName("bot"), value=v)
    set_parameter(device=device, name=GetContactBiasName("top"), value=0.0)
    print(v)
    solve(type="dc",
          absolute_error=1e6,
          relative_error=1e-12,
          maximum_iterations=300)
    # PrintCurrents(device, "top")
    # PrintCurrents(device, "bot")
    for contact in ds.get_contact_list(device=device):
        e_current = abs(
            ds.get_contact_current(device=device,
                                   contact=contact,
                                   equation=ECE_NAME))
        e_current += abs(
            ds.get_contact_current(device=device,
                                   contact=contact,
                                   equation=HCE_NAME))
    current.append(e_current)
    volts.append(v)
    v += 0.02
# plt.show()
plt.figure()
plt.semilogy(volts, current)
plt.figure()
Ejemplo n.º 7
0
    def setup_drift_diffusion(self,
                              dielectric_const=11.9,
                              intrinsic_carriers=1E10,
                              work_function=4.05,
                              band_gap=1.124,
                              Ncond=3E19,
                              Nval=3E19,
                              mobility_n=1107,
                              mobility_p=424.6,
                              Nacceptors=0,
                              Ndonors=0):
        """
        Sets up equations for a drift-diffusion style of dc current transport.

        kwargs here are device-level parameters, imbuing all regions with these properties
        If a specific region or material is to have a different set of parameters, they can be set through the
        Region constructor.
        :param dielectric_const:
        :param intrinsic_carriers:
        :param work_function:
        :param band_gap:
        :param Ncond:
        :param Nval:
        :param mobility_n:
        :param mobility_p:
        :param Nacceptors:
        :param Ndonors:
        :return:
        """
        # Begin legacy copy-paste job
        # Set silicon parameters
        device = self.name
        region = self.regions[0].name
        eps_si = dielectric_const
        n_i = 1E10
        k = kb
        mu_n = mobility_n
        mu_p = mobility_p
        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=1e-5)
        set_parameter(device=device, region=region, name="taup", value=1e-5)
        # CreateNodeModel 3 times
        for name, value in [('Acceptors', "1.0e18*step(0.5e-5-x)"),
                            ('Donors', "1.0e18*step(x-0.5e-5)"),
                            ('NetDoping', "Donors-Acceptors")]:
            result = node_model(device=device,
                                region=region,
                                name=name,
                                equation=value)
            logger.debug(f"NODEMODEL {device} {region} {name} '{result}'")
        print_node_values(device=device, region=region, name="NetDoping")
        model_name = "Potential"
        node_solution(name=model_name, device=device, region=region)
        edge_from_node_model(node_model=model_name,
                             device=device,
                             region=region)
        # Create silicon potentialOnly
        if model_name not in get_node_model_list(device=device, region=region):
            logger.debug("Creating Node Solution Potential")
            node_solution(device=device, region=region, name=model_name)
            edge_from_node_model(node_model=model_name,
                                 device=device,
                                 region=region)

        # require NetDoping
        for name, eq in (
            ("IntrinsicElectrons", "n_i*exp(Potential/V_t)"),
            ("IntrinsicHoles", "n_i^2/IntrinsicElectrons"),
            ("IntrinsicCharge",
             "kahan3(IntrinsicHoles, -IntrinsicElectrons, NetDoping)"),
            ("PotentialIntrinsicCharge", "-ElectronCharge * IntrinsicCharge")):
            node_model(device=device, region=region, name=name, equation=eq)
            node_model(device=device,
                       region=region,
                       name=f"{name}:{model_name}",
                       equation=f"simplify(diff({eq},{model_name}))")
            # CreateNodeModelDerivative(device, region, name, eq, model_name)

        ### TODO: Edge Average Model
        for name, eq in (("ElectricField",
                          "(Potential@n0-Potential@n1)*EdgeInverseLength"),
                         ("PotentialEdgeFlux",
                          "Permittivity * ElectricField")):
            edge_model(device=device, region=region, name=name, equation=eq)
            edge_model(device=device,
                       region=region,
                       name=f"{name}:{model_name}@n0",
                       equation=f"simplify(diff({eq}, {model_name}@n0))")
            edge_model(device=device,
                       region=region,
                       name=f"{name}:{model_name}@n1",
                       equation=f"simplify(diff({eq}, {model_name}@n1))")

        equation(device=device,
                 region=region,
                 name="PotentialEquation",
                 variable_name=model_name,
                 node_model="PotentialIntrinsicCharge",
                 edge_model="PotentialEdgeFlux",
                 variable_update="log_damp")

        # Set up the contacts applying a bias
        is_circuit = False
        for contact_name in get_contact_list(device=device):
            set_parameter(device=device,
                          name=f"{contact_name}_bias",
                          value=0.0)
            # CreateSiliconPotentialOnlyContact(device, region, contact_name)
            # Start
            # Means of determining contact charge
            # Same for all contacts
            if not InNodeModelList(device, region, "contactcharge_node"):
                create_node_model(device, region, "contactcharge_node",
                                  "ElectronCharge*IntrinsicCharge")
            #### TODO: This is the same as D-Field
            if not InEdgeModelList(device, region, "contactcharge_edge"):
                CreateEdgeModel(device, region, "contactcharge_edge",
                                "Permittivity*ElectricField")
                create_edge_model_derivatives(device, region,
                                              "contactcharge_edge",
                                              "Permittivity*ElectricField",
                                              "Potential")
                #  set_parameter(device=device, region=region, name=GetContactBiasName(contact), value=0.0)
            contact_bias_name = f"{contact_name}_bias"
            contact_model_name = f"{contact_name}nodemodel"
            contact_model = f"Potential -{contact_bias_name} + ifelse(NetDoping > 0, -V_t*log({CELEC_MODEL!s}/n_i), V_t*log({CHOLE_MODEL!s}/n_i))"\

            CreateContactNodeModel(device, contact_name, contact_model_name,
                                   contact_model)
            # Simplify it too complicated
            CreateContactNodeModel(
                device, contact_name, "{0}:{1}".format(contact_model_name,
                                                       "Potential"), "1")
            if is_circuit:
                CreateContactNodeModel(
                    device, contact_name,
                    "{0}:{1}".format(contact_model_name,
                                     contact_bias_name), "-1")

            if is_circuit:
                contact_equation(device=device,
                                 contact=contact_name,
                                 name="PotentialEquation",
                                 variable_name="Potential",
                                 node_model=contact_model_name,
                                 edge_model="",
                                 node_charge_model="contactcharge_node",
                                 edge_charge_model="contactcharge_edge",
                                 node_current_model="",
                                 edge_current_model="",
                                 circuit_node=contact_bias_name)
            else:
                contact_equation(device=device,
                                 contact=contact_name,
                                 name="PotentialEquation",
                                 variable_name="Potential",
                                 node_model=contact_model_name,
                                 edge_model="",
                                 node_charge_model="contactcharge_node",
                                 edge_charge_model="contactcharge_edge",
                                 node_current_model="",
                                 edge_current_model="")
            # Biggie

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

        drift_diffusion_initial_solution(device, region)

        solve(type="dc",
              absolute_error=1e10,
              relative_error=1e-10,
              maximum_iterations=30)