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)
def setup_poisson(device, region, variable_update='log_damp', **kwargs): """ Sets up poisson equation solution Requires: setup physical constants and setup poisson parameters :param kwargs: :return: """ logger.debug("Setting up Poisson Equation") # These are variables that are to be solved during the simulation # for sol_variable in [hole_density, electron_density, potential, qfn, qfp]: for sol_variable in [potential, electron_density, hole_density]: create_solution(device, region, sol_variable) total_charge_eq = f'kahan3({hole_density},-{electron_density},{p_doping})' #f'{hole_density}-{electron_density}+{p_doping}-{n_doping}' #f'-{q}*kahan4({hole_density}, -{electron_density}, {p_doping}, -{n_doping})' int_chg_eq = '1e11'# f'({Nc}*{Nv})^(1/2)*exp(-{bandgap}/(2*k*T))' # Order matters! for name, eq in zip([intrinsic_charge, total_charge, ], [int_chg_eq, total_charge_eq,]): create_node_and_derivatives(device, region, name, eq, [potential, electron_density, hole_density]) ds.edge_from_node_model(device=device, region=region,node_model=electron_density) ds.edge_from_node_model(device=device, region=region, node_model=hole_density) e_field_eq = f"({potential}@n0-{potential}@n1)*EdgeInverseLength" d_field_eq = f'{e_field}*{permittivity}*{eps_0}' for name, eq in zip([e_field, d_field],[e_field_eq, d_field_eq]): create_edge_and_derivatives(device, region, name, eq, [potential]) # Lastly, setup the equation to solve for 'potential' # TODO check initial values ds.set_node_values(device=device, region=region, name=electron_density, init_from=intrinsic_charge) ds.set_node_values(device=device, region=region, name=hole_density, init_from=intrinsic_charge) ds.equation(device=device, region=region, name='PoissonEq', variable_name=potential, node_model=total_charge, edge_model=d_field, variable_update=variable_update)
def drift_diffusion_initial_solution(self): # TODO: move it to somewhere else # drift diffusion solution variables self.create_solution_variable("Electrons") self.create_solution_variable("Holes") for region in self.mesh.regions: # Create initial guess from DC only solution set_node_values(device=self.name, region=region.name, name="Electrons", init_from="IntrinsicElectrons") set_node_values(device=self.name, region=region.name, name="Holes", init_from="IntrinsicHoles") # Set up equations CreateSiliconDriftDiffusion(self.name, region.name) for c in self.mesh.contacts: CreateSiliconDriftDiffusionAtContact(self.name, region.name, c)
def set_dd_parameters(device, region, permittivity=11.1, n_i=1E10, T=300, mu_n=400, mu_p=200, taun=1E-5, taup=1E-5): names = [ 'permittivity', 'q', 'n_i', 'T', 'k', 'kT', 'V_t', 'mobility_n', 'mobility_p', 'n1', 'p1', 'taun', 'taup' ] values = [ permittivity * eps_0, q, n_i, T, k, k * T, k * T / q, mu_n, mu_p, n_i, n_i, taun, taup ] for name, value in zip(names, values): ds.set_parameter(device=device, region=region, name=name, value=value) # Setup the solutions for the potential, electron and hole densities pot = 'potential' electron_density = 'electron_density' hole_density = 'hole_density' for var in [pot, electron_density, hole_density]: create_solution(device=device, region=region, name=var) # Now for some poisson's equation # Create some nodemodels n_ie = 'n_ie', f"n_i*exp(q*{pot}/k*T)" # Intrinsic electron density n_ih = 'n_ih', f'n_i^2/{n_ie[0]}' # Intrinsic hole density net_n_i = 'net_n_i', f'kahan4(-{n_ie[0]}, {n_ih[0]}, p_doping, -n_doping)' # Net intrinsic charge net_n_i_charge = 'net_n_i_charge', f'q*{net_n_i[0]}' #PotentialIntrinsicCharge for name, eq in [n_ie, n_ih, net_n_i, net_n_i_charge]: ds.node_model(device=device, region=region, name=name, equation=eq) create_derivatives(device, region, name, eq, pot) E_field = 'E_field', f'({pot}@n0-{pot}@n1)*EdgeInverseLength' D_field = 'D_field', 'E_field * permittivity' #PotentialEdgeFlux ?? wtf # Initialize the electron and hole densities for carrier, init in zip([electron_density, hole_density], [n_ie, n_ih]): ds.set_node_values(device=device, region=region, name=carrier, init_from=init[0]) # setup edge nodes for edge_name, eq in [E_field, D_field]: ds.edge_model(device=device, region=region, name=edge_name, equation=eq) create_derivatives(device, region, edge_name, eq, pot) # Create PE poisson_RHS = 'PoissonRHS', f'({hole_density} - {electron_density} + p_doping - n_doping)' #*q/(permittivity)' # AKA pne ds.node_model(device=device, region=region, name=poisson_RHS[0], equation=poisson_RHS[1]) create_derivatives(device, region, poisson_RHS[0], poisson_RHS[1], hole_density, electron_density) ds.equation(device=device, region=region, name="PoissonEquation", variable_name=pot, node_model=poisson_RHS[0], edge_model=D_field[0]) # Use stupid bernouli formalism # Check if exists? ds.edge_from_node_model(device=device, region=region, node_model=pot) beta_vdiff = 'beta_vdiff', f'({pot}@n0 - {pot}@n1)*q/kT' ds.edge_model(device=device, region=region, name=beta_vdiff[0], equation=beta_vdiff[1]) bernouli = 'bern', f'B({beta_vdiff[0]})' ds.edge_model(device=device, region=region, name=bernouli[0], equation=bernouli[1]) # Create continuity equations E_qf_n = ( 'quasi_fermi_n', f'q*({pot}-electron_affinity) + k*T*log({electron_density}/N_cond)') E_qf_p = ( 'quasi_fermi_p', f'q*({pot}-electron_affinity) - k*T*log({hole_density}/N_val) - band_gap' ) J_e = 'e_current', f'q*mobility_n*{electron_density}*EdgeInverseLength*({E_qf_n[0]}@n0-{E_qf_n[0]}@n1)' J_h = 'h_current', f'q*mobility_p*{hole_density}*EdgeInverseLength*({E_qf_p[0]}@n0-{E_qf_p[0]}@n1)' for J in [E_qf_n, E_qf_p, J_e, J_h]: ds.edge_model(device=device, region=region, name=J[0], equation=J[1]) ds.node_model(device=device, region=region, name=J[0], equation=J[1]) for node_model in [pot, electron_density, hole_density]: # Check if exists?! ds.edge_from_node_model(device=device, region=region, node_model=node_model) create_derivatives(device, region, J[0], J[1], node_model) for node_model in [n_ie, n_ih, net_n_i, net_n_i_charge]: ds.print_node_values(device=device, region=region, name=node_model[0]) for edge_model in [E_qf_n, E_qf_p, J_e, J_h]: ds.print_edge_values(device=device, region=region, name=edge_model[0])