def CreateSolution(device, region, name): ''' Creates solution variables As well as their entries on each edge ''' ds.node_solution(name=name, device=device, region=region) ds.edge_from_node_model(node_model=name, device=device, region=region)
def setup_log_ox(device, region): ds.edge_from_node_model(device=device, region=region, node_model="Le") ds.edge_from_node_model(device=device, region=region, node_model="Lh") # # Need the V_t models # CreateVT(device, region, ()) # # log_n, log_p # em = ( # could use gradient model ("d_l_n", "EdgeInverseLength*(Le@n1 - Le@n0)/V_t_edge"), ("d_l_n:Le@n0", "-EdgeInverseLength/V_t_edge"), ("d_l_n:Le@n1", "EdgeInverseLength/V_t_edge"), #("d_l_n:Potential@n0", "0"), #("d_l_n:Potential@n1", "0"), #("d_l_n:Le@n0", "0"), #("d_l_n:Le@n1", "0"), ("d_l_p", "EdgeInverseLength*(Lh@n1 - Lh@n0)/V_t_edge"), ("d_l_p:Lh@n0", "-EdgeInverseLength/V_t_edge"), ("d_l_p:Lh@n1", "EdgeInverseLength/V_t_edge"), #("d_l_p:Potential@n0", "0"), #("d_l_p:Potential@n1", "0"), #("d_l_p:Lh@n0", "0"), #("d_l_p:Lh@n1", "0"), ) for e in em: ds.edge_model(device=device, region=region, name=e[0], equation=e[1])
def set_default_models(): for r in (region_si, region_ox): ds.edge_from_node_model(device=device, region=r, node_model="x") CreateEdgeModel(device=device, region=r, model="xmid", expression="0.5*(x@n0 + x@n1)") ds.set_parameter(name="T", value=300.0) CreateSolution(device=device, region=region_si, name="Potential") CreateSolution(device=device, region=region_ox, name="Potential") # # need Le and Lh for the Si Equation # setup_dg_variable(device, region_si, "Le") setup_dg_variable(device, region_si, "Lh") setup_dg_variable(device, region_ox, "Le") setup_dg_variable(device, region_ox, "Lh") CreateNodeModel(device=device, region=region_si, model="NetDoping", expression="Nconstant") #set the bias ds.set_parameter(name=GetContactBiasName("bot"), value=0.0) ds.set_parameter(name=GetContactBiasName("top"), value=0.0) #available solution reset ds.node_solution(name='zero', device=device, region=region_ox) ds.node_solution(name='zero', device=device, region=region_si)
def SetupInitialResistorSystem(device, region, net_doping=1e16): ''' resistor physics ''' devsim.set_parameter(device=device, region=region, name='net_doping', value=net_doping) devsim.node_solution(device=device, region=region, name='Potential') devsim.edge_from_node_model(device=device, region=region, node_model='Potential') # node models for name, equation in ( ("NetDoping", "net_doping"), ("IntrinsicElectrons", "NetDoping"), ("IntrinsicCharge", "-IntrinsicElectrons + NetDoping"), ("IntrinsicCharge:Potential", "-IntrinsicElectrons:Potential"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) # edge models for name, equation in ( ("ElectricField", "(Potential@n0 - Potential@n1)*EdgeInverseLength"), ("ElectricField:Potential@n0", "EdgeInverseLength"), ("ElectricField:Potential@n1", "-EdgeInverseLength"), ("PotentialEdgeFlux", "Permittivity*ElectricField"), ("PotentialEdgeFlux:Potential@n0", "diff(Permittivity*ElectricField, Potential@n0)"), ("PotentialEdgeFlux:Potential@n1", "-PotentialEdgeFlux:Potential@n0"), ): devsim.edge_model(device=device, region=region, name=name, equation=equation) #### #### PotentialEquation #### devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", edge_model="PotentialEdgeFlux", variable_update="log_damp")
def EnsureEdgeFromNodeModelExists(device, region, nodemodel): ''' Checks if the edge models exists ''' if not InNodeModelList(device, region, nodemodel): raise "{} must exist" emlist = get_edge_model_list(device=device, region=region) emtest = ("{0}@n0".format(nodemodel) and "{0}@n1".format(nodemodel)) if not emtest: if debug: print("INFO: Creating ${0}@n0 and ${0}@n1".format(nodemodel)) ds.edge_from_node_model(device=device, region=region, node_model=nodemodel)
def setup_log_si_potential_only(device, region): ds.edge_from_node_model(device=device, region=region, node_model="Le") ds.edge_from_node_model(device=device, region=region, node_model="Lh") ds.edge_from_node_model(device=device, region=region, node_model="NIE") # # Need the V_t models # CreateVT(device, region, ()) # # log_n, log_p # em = ( # could use gradient model #("d_l_n", "EdgeInverseLength*((Le@n1 - Le@n0)/V_t_edge)"), #("d_l_n", "EdgeInverseLength*((-V_t_edge*log(NIE_edge) + (Le@n1 - Le@n0))/V_t_edge)"), #("d_l_n", "EdgeInverseLength*((-V_t_edge*log(NIE_edge) + (Potential@n0 - Potential@n1))/V_t_edge)"), #TODO: add band edge element later (NIE) ("d_l_n", "EdgeInverseLength*(((Potential@n1 - Potential@n0) + (Le@n0 - Le@n1))/V_t_edge)" ), #("d_l_n", "EdgeInverseLength*((V_t_edge*log(NIE@n0/NIE@n1) + (Potential@n0 - Potential@n1) + (Le@n1 - Le@n0))/V_t_edge)"), #("d_l_n", "EdgeInverseLength*((V_t_edge*log(NIE_edge) + (Potential@n0 - Potential@n1) + (Le@n1 - Le@n0))/V_t_edge)"), ("d_l_n:Potential@n0", "-EdgeInverseLength/V_t_edge"), ("d_l_n:Potential@n1", "EdgeInverseLength/V_t_edge"), ("d_l_n:Le@n0", "EdgeInverseLength/V_t_edge"), ("d_l_n:Le@n1", "-EdgeInverseLength/V_t_edge"), #("d_l_p", "EdgeInverseLength*((Lh@n1 - Lh@n0)/V_t_edge)"), ("d_l_p", "EdgeInverseLength*(((Potential@n0 - Potential@n1) + (Lh@n0 - Lh@n1))/V_t_edge)" ), #("d_l_p", "EdgeInverseLength*((Potential@n1 - Potential@n0) + (Lh@n1 - Lh@n0))/V_t_edge"), ("d_l_p:Potential@n0", "EdgeInverseLength/V_t_edge"), ("d_l_p:Potential@n1", "-EdgeInverseLength/V_t_edge"), ("d_l_p:Lh@n0", "EdgeInverseLength/V_t_edge"), ("d_l_p:Lh@n1", "-EdgeInverseLength/V_t_edge"), ) for e in em: ds.edge_model(device=device, region=region, name=e[0], equation=e[1])
test_common.CreateSimpleMesh(device, region) ### ### Set parameters on the region ### devsim.set_parameter(device=device, region=region, name="Permittivity", value=3.9*8.85e-14) ### ### Create the Potential solution variable ### devsim.node_solution(device=device, region=region, name="Potential") ### ### Creates the Potential@n0 and Potential@n1 edge model ### devsim.edge_from_node_model(device=device, region=region, node_model="Potential") ### ### Electric field on each edge, as well as its derivatives with respect to ### the potential at each node ### devsim.edge_model(device=device, region=region, name="ElectricField", equation="(Potential@n0 - Potential@n1)*EdgeInverseLength") devsim.edge_model(device=device, region=region, name="ElectricField:Potential@n0", equation="EdgeInverseLength") devsim.edge_model(device=device, region=region, name="ElectricField:Potential@n1", equation="-EdgeInverseLength") ###
def createSolution(device, region, name): devsim.node_solution(device=device, region=region, name=name) devsim.edge_from_node_model(device=device, region=region, node_model=name)
def setup_dg_variable(device, region, variable): CreateSolution(device, region, variable) ds.edge_from_node_model(device=device, region=region, node_model=variable)
def SetupCarrierResistorSystem(device, region): ''' This adds electron continuity ''' devsim.node_solution(device=device, region=region, name='Electrons') devsim.edge_from_node_model(device=device, region=region, node_model='Electrons') devsim.set_node_values(device=device, region=region, name='Electrons', init_from='IntrinsicElectrons') #### #### PotentialNodeCharge #### for name, equation in ( ("PotentialNodeCharge", "-ElectronCharge*(-Electrons + NetDoping)"), ("PotentialNodeCharge:Electrons", "+ElectronCharge"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) #### #### PotentialEquation modified for carriers present #### devsim.equation(device=device, region=region, name='PotentialEquation', variable_name='Potential', node_model='PotentialNodeCharge', edge_model="PotentialEdgeFlux", variable_update="default") #### #### vdiff, Bern01, Bern10 #### for name, equation in ( ("vdiff", "(Potential@n0 - Potential@n1)/ThermalVoltage"), ("vdiff:Potential@n0", "ThermalVoltage^(-1)"), ("vdiff:Potential@n1", "-ThermalVoltage^(-1)"), ("Bern01", "B(vdiff)"), ("Bern01:Potential@n0", "dBdx(vdiff)*vdiff:Potential@n0"), ("Bern01:Potential@n1", "dBdx(vdiff)*vdiff:Potential@n1"), ("Bern10", "Bern01 + vdiff"), ("Bern10:Potential@n0", "Bern01:Potential@n0 + vdiff:Potential@n0"), ("Bern10:Potential@n1", "Bern01:Potential@n1 + vdiff:Potential@n1"), ): devsim.edge_model(device=device, region=region, name=name, equation=equation) #### #### Electron Current #### current_equation = "ElectronCharge*mu_n*EdgeInverseLength*ThermalVoltage*(Electrons@n1*Bern10 - Electrons@n0*Bern01)" for name, equation in ( ("ElectronCurrent", current_equation), ("ElectronCurrent:Electrons@n0", "simplify(diff(%s, Electrons@n0))" % current_equation), ("ElectronCurrent:Electrons@n1", "simplify(diff(%s, Electrons@n1))" % current_equation), ("ElectronCurrent:Potential@n0", "simplify(diff(%s, Potential@n0))" % current_equation), ("ElectronCurrent:Potential@n1", "simplify(diff(%s, Potential@n1))" % current_equation), ): devsim.edge_model(device=device, region=region, name=name, equation=equation) #### #### Time derivative term #### for name, equation in ( ("NCharge", "-ElectronCharge * Electrons"), ("NCharge:Electrons", "-ElectronCharge"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) #### #### Electron Continuity Equation #### devsim.equation(device=device, region=region, name="ElectronContinuityEquation", variable_name="Electrons", edge_model="ElectronCurrent", time_node_model="NCharge", variable_update="positive")
def debug_plot(device, region): nodes = numpy.array( ds.get_node_model_values(device=device, region=region, name='node_index')) node_volume = numpy.array( ds.get_node_model_values(device=device, region=region, name='NodeVolume')) num_nodes = len(nodes) flux_term = numpy.zeros(num_nodes) edge_vol_term = numpy.zeros(num_nodes) x = abs( numpy.array( ds.get_node_model_values(device=device, region=region, name="x"))) * 1e7 node_vol_term = numpy.array( ds.get_node_model_values(device=device, region=region, name="volume_term")) pos_edge = [] neg_edge = [] for i in range(num_nodes): pos_edge.append([]) neg_edge.append([]) # edge based quantities ds.edge_from_node_model(device=device, region=region, node_model='node_index') n0_indexes = ds.get_edge_model_values(device=device, region=region, name='node_index@n0') n1_indexes = ds.get_edge_model_values(device=device, region=region, name='node_index@n1') # need to get sign based on index num_edges = len(n0_indexes) zero_earray = [0.0] * num_edges # populate edges for ei in range(num_edges): pos_edge[int(n0_indexes[ei])].append(ei) neg_edge[int(n1_indexes[ei])].append(ei) ft = ds.get_edge_model_values(device=device, region=region, name="surface_term") st = ds.get_edge_model_values(device=device, region=region, name="edge_volume_term") for ni in range(num_nodes): # don't want a boundary yet for v in pos_edge[ni]: flux_term[ni] += ft[v] edge_vol_term[ni] += st[v] for v in neg_edge[ni]: flux_term[ni] -= ft[v] edge_vol_term[ni] += st[v] node_vol_term = node_vol_term / node_volume edge_vol_term = edge_vol_term / node_volume flux_term = flux_term / node_volume net_sum = flux_term + edge_vol_term + node_vol_term fig = plt.figure() plt.plot(x, node_vol_term, label="node vol") plt.plot(x, edge_vol_term, label="edge vol") plt.plot(x, flux_term, label="flux") plt.plot(x, net_sum, 'k+-', label="sum") plt.legend(loc='best') plt.ylim(-1, 1.0) plt.xlim(0, 20) plt.xlabel(xstring) plt.ylabel('eq terms (eV)') return fig