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 setup_dg_equation(device, region, e_name, v_name, e_m, e_v_m, n_m): ds.equation(device=device, region=region, name=e_name, variable_name=v_name, edge_model=e_m, edge_volume_model=e_v_m, node_model=n_m, variable_update="default")
def createSiliconPotentialOnly(device, region): ie = devsim.node_model(device=device, region=region, name="IntrinsicElectrons", equation="n_i*exp(Potential/V_t)") res = devsim.node_model(device=device, region=region, name="IntrinsicElectrons:Potential", equation="diff(%s, Potential)" % ie) for name, equation in ( ("IntrinsicHoles", "n_i^2/IntrinsicElectrons"), ("IntrinsicHoles:Potential", "diff(n_i^2/IntrinsicElectrons, Potential)"), ("IntrinsicCharge", "IntrinsicHoles-IntrinsicElectrons + NetDoping"), ("IntrinsicCharge:Potential", "diff(IntrinsicHoles-IntrinsicElectrons, Potential)"), ("PotentialIntrinsicNodeCharge", "-ElectronCharge*IntrinsicCharge"), ("PotentialIntrinsicNodeCharge:Potential", "diff(-ElectronCharge*IntrinsicCharge, Potential)"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) for name, equation in ( ("ElectricField", "(Potential@n0-Potential@n1)*EdgeInverseLength"), ("ElectricField:Potential@n0", "EdgeInverseLength"), ("ElectricField:Potential@n1", "-ElectricField:Potential@n0"), ("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) devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", node_model="PotentialIntrinsicNodeCharge", edge_model="PotentialEdgeFlux", variable_update="log_damp")
def CreateSiliconPotentialOnly(device, region): ''' Creates the physical models for a Silicon region for equilibrium simulation. ''' variables = ("Potential", ) CreateVT(device, region, variables) CreateDensityOfStates(device, region, variables) SetSiliconParameters(device, region) # require NetDoping for i in ( ("IntrinsicElectrons", "NIE*exp(ifelse(((Potential-Le)/V_t) < 80, ((Potential-Le)/V_t), 80))" ), ("IntrinsicHoles", "NIE*exp(ifelse(((-Potential-Lh)/V_t) < 80, ((-Potential-Lh)/V_t), 80))" ), ("IntrinsicCharge", "kahan3(IntrinsicHoles, -IntrinsicElectrons, NetDoping)"), ("PotentialIntrinsicCharge", "-q * IntrinsicCharge")): n = i[0] e = i[1] CreateNodeModel(device, region, n, e) CreateNodeModelDerivative(device, region, n, e, 'Potential') CreateNodeModelDerivative(device, region, n, e, 'Le') CreateNodeModelDerivative(device, region, n, e, 'Lh') CreateQuasiFermiLevels(device, region, 'IntrinsicElectrons', 'IntrinsicHoles', variables) CreateEField(device, region) CreateDField(device, region) ds.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", node_model="PotentialIntrinsicCharge", edge_model="DField", variable_update="log_damp")
def createOxidePotentialOnly(device, region): 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) devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", edge_model="PotentialEdgeFlux", variable_update="log_damp")
def createPotentialOnly(device, region): for name, equation in ( ("IntrinsicElectrons", "n_i*exp(Potential/V_t)"), ("IntrinsicElectrons:Potential", "diff(n_i*exp(Potential/V_t), Potential)"), ("IntrinsicHoles", "n_i^2/IntrinsicElectrons"), ("IntrinsicHoles:Potential", "diff(n_i^2/IntrinsicElectrons, Potential)"), ("IntrinsicCharge", "IntrinsicHoles-IntrinsicElectrons + NetDoping"), ("IntrinsicCharge:Potential", "diff(IntrinsicHoles-IntrinsicElectrons, Potential)"), ("PotentialIntrinsicNodeCharge", "-ElectronCharge*IntrinsicCharge"), ("PotentialIntrinsicNodeCharge:Potential", "diff(-ElectronCharge*IntrinsicCharge, Potential)"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) for name, equation in ( ("EField", "(Potential@n0-Potential@n1)*EdgeInverseLength"), ("EField:Potential@n0", "EdgeInverseLength"), ("EField:Potential@n1", "-EField:Potential@n0"), ): devsim.edge_model(device=device, region=region, name=name, equation=equation) devsim.element_from_edge_model(edge_model="EField", device=device, region=region) devsim.element_from_edge_model(edge_model="EField", derivative="Potential", device=device, region=region) foo="dot2d(EField_x, EField_y, unitx, unity)" for name, equation in ( ("ElectricField", foo), ("ElectricField:Potential@en0", "diff(%s, Potential@en0)" % foo), ("ElectricField:Potential@en1", "diff(%s, Potential@en1)" % foo), ("ElectricField:Potential@en2", "diff(%s, Potential@en2)" % foo), ("PotentialEdgeFlux", "Permittivity*ElectricField"), ("PotentialEdgeFlux:Potential@en0", "diff(Permittivity*ElectricField,Potential@en0)"), ("PotentialEdgeFlux:Potential@en1", "diff(Permittivity*ElectricField,Potential@en1)"), ("PotentialEdgeFlux:Potential@en2", "diff(Permittivity*ElectricField,Potential@en2)"), ): devsim.element_model(device=device, region=region, name=name, equation=equation) devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", node_model="PotentialIntrinsicNodeCharge", element_model="PotentialEdgeFlux", variable_update="log_damp")
def CreateOxidePotentialOnly(device, region, update_type="default"): ''' Create electric field model in oxide Creates Potential solution variable if not available ''' if not InNodeModelList(device, region, "Potential"): print("Creating Node Solution Potential") CreateSolution(device, region, "Potential") efield = "(Potential@n0 - Potential@n1)*EdgeInverseLength" # this needs to remove derivatives w.r.t. independents CreateEdgeModel(device, region, "EField", efield) CreateEdgeModelDerivatives(device, region, "EField", efield, "Potential") dfield = "Permittivity*EField" CreateEdgeModel(device, region, "PotentialEdgeFlux", dfield) CreateEdgeModelDerivatives(device, region, "PotentialEdgeFlux", dfield, "Potential") ds.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", edge_model="PotentialEdgeFlux", variable_update=update_type)
### ### Model the D Field ### devsim.edge_model(device=device, region=region, name="DField", equation="Permittivity*ElectricField") devsim.edge_model(device=device, region=region, name="DField:Potential@n0", equation="diff(Permittivity*ElectricField, Potential@n0)") devsim.edge_model(device=device, region=region, name="DField:Potential@n1", equation="-DField:Potential@n0") ### ### Create the bulk equation ### devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", edge_model="DField", variable_update="default") # the topbias is a circuit node, and we want to prevent it from being overridden by a parameter devsim.set_parameter(device=device, region=region, name="botbias", value=0.0) for name, equation in ( ("topnode_model", "Potential - topbias"), ("topnode_model:Potential", "1"), ("topnode_model:topbias", "-1"), ("botnode_model", "Potential - botbias"), ("botnode_model:Potential", "1"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) # attached to circuit node devsim.contact_equation(device=device, contact="top", name="PotentialEquation", variable_name="Potential",
def createDriftDiffusion(device, region): for name, equation in ( ("PotentialNodeCharge" , "-ElectronCharge*(Holes -Electrons + NetDoping)"), ("PotentialNodeCharge:Electrons", "+ElectronCharge"), ("PotentialNodeCharge:Holes" , "-ElectronCharge"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", node_model="PotentialNodeCharge", element_model="PotentialEdgeFlux", variable_update="log_damp") for name, equation in ( ("vdiff" , "(Potential@n0 - Potential@n1)/V_t"), ("vdiff:Potential@n0" , "V_t^(-1)"), ("vdiff:Potential@n1" , "-V_t^(-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) Jn ="ElectronCharge*mu_n*EdgeInverseLength*V_t*(Electrons@n1*Bern10 - Electrons@n0*Bern01)" dJndn0 ="simplify(diff( %s, Electrons@n0))" % Jn dJndn1 ="simplify(diff( %s, Electrons@n1))" % Jn dJndpot0="simplify(diff( %s, Potential@n0))" % Jn dJndpot1="simplify(diff( %s, Potential@n1))" % Jn for name, equation in ( ("ElectronCurrent" , Jn), ("ElectronCurrent:Electrons@n0", dJndn0), ("ElectronCurrent:Electrons@n1", dJndn1), ("ElectronCurrent:Potential@n0", dJndpot0), ("ElectronCurrent:Potential@n1", dJndpot1), ): devsim.edge_model(device=device, region=region, name=name, equation=equation) Jp ="-ElectronCharge*mu_p*EdgeInverseLength*V_t*(Holes@n1*Bern01 - Holes@n0*Bern10)" dJpdp0 ="simplify(diff(%s, Holes@n0))" % Jp dJpdp1 ="simplify(diff(%s, Holes@n1))" % Jp dJpdpot0="simplify(diff(%s, Potential@n0))" % Jp dJpdpot1="simplify(diff(%s, Potential@n1))" % Jp for name, equation in ( ("HoleCurrent" , Jp), ("HoleCurrent:Holes@n0" , dJpdp0), ("HoleCurrent:Holes@n1" , dJpdp1), ("HoleCurrent:Potential@n0", dJpdpot0), ("HoleCurrent:Potential@n1", dJpdpot1), ): devsim.edge_model(device=device, region=region, name=name, equation=equation) NCharge="-ElectronCharge * Electrons" dNChargedn="-ElectronCharge" for name, equation in ( ("NCharge", NCharge), ("NCharge:Electrons", dNChargedn), ): devsim.node_model(device=device, region=region, name=name, equation=equation) PCharge="-ElectronCharge * Holes" dPChargedp="-ElectronCharge" for name, equation in ( ("PCharge", PCharge), ("PCharge:Holes", dPChargedp), ): devsim.node_model(device=device, region=region, name=name, equation=equation) ni=devsim.get_parameter(device=device, region=region, name="n_i") for name, value in ( ("n1", ni), ("p1", ni), ("taun", 1e-5), ("taup", 1e-5), ): devsim.set_parameter(device=device, region=region, name=name, value=value) USRH="-ElectronCharge*(Electrons*Holes - n_i^2)/(taup*(Electrons + n1) + taun*(Holes + p1))" dUSRHdn="simplify(diff($USRH, Electrons))" dUSRHdp="simplify(diff($USRH, Holes))" for name, equation in ( ("USRH", USRH), ("USRH:Electrons", dUSRHdn), ("USRH:Holes", dUSRHdp), ): devsim.node_model(device=device, region=region, name=name, equation=equation) devsim.equation(device=device, region=region, name="ElectronContinuityEquation", variable_name="Electrons", edge_model="ElectronCurrent", variable_update="positive", time_node_model="NCharge", node_model="USRH") devsim.equation(device=device, region=region, name="HoleContinuityEquation", variable_name="Holes", edge_model="HoleCurrent", variable_update="positive", time_node_model="PCharge", node_model="USRH")
def createSiliconDriftDiffusion(device, region): for name, equation in ( ("PotentialNodeCharge", "-ElectronCharge*(Holes -Electrons + NetDoping)"), ("PotentialNodeCharge:Electrons", "+ElectronCharge"), ("PotentialNodeCharge:Holes", "-ElectronCharge"), ): devsim.node_model(device=device, region=region, name=name, equation=equation) devsim.equation(device=device, region=region, name="PotentialEquation", variable_name="Potential", node_model="PotentialNodeCharge", edge_model="PotentialEdgeFlux", variable_update="log_damp") createBernoulli(device, region) createElectronCurrent(device, region) createHoleCurrent(device, region) NCharge = "-ElectronCharge * Electrons" dNChargedn = "-ElectronCharge" devsim.node_model(device=device, region=region, name="NCharge", equation=NCharge) devsim.node_model(device=device, region=region, name="NCharge:Electrons", equation=dNChargedn) PCharge = "-ElectronCharge * Holes" dPChargedp = "-ElectronCharge" devsim.node_model(device=device, region=region, name="PCharge", equation=PCharge) devsim.node_model(device=device, region=region, name="PCharge:Holes", equation=dPChargedp) ni = devsim.get_parameter(device=device, region=region, name="n_i") devsim.set_parameter(device=device, region=region, name="n1", value=ni) devsim.set_parameter(device=device, region=region, name="p1", value=ni) devsim.set_parameter(device=device, region=region, name="taun", value=1e-5) devsim.set_parameter(device=device, region=region, name="taup", value=1e-5) USRH = "-ElectronCharge*(Electrons*Holes - n_i^2)/(taup*(Electrons + n1) + taun*(Holes + p1))" dUSRHdn = "simplify(diff(%s, Electrons))" % USRH dUSRHdp = "simplify(diff(%s, Holes))" % USRH devsim.node_model(device=device, region=region, name="USRH", equation=USRH) devsim.node_model(device=device, region=region, name="USRH:Electrons", equation=dUSRHdn) devsim.node_model(device=device, region=region, name="USRH:Holes", equation=dUSRHdp) devsim.equation(device=device, region=region, name="ElectronContinuityEquation", variable_name="Electrons", edge_model="ElectronCurrent", variable_update="positive", time_node_model="NCharge", node_model="USRH") devsim.equation(device=device, region=region, name="HoleContinuityEquation", variable_name="Holes", edge_model="HoleCurrent", variable_update="positive", time_node_model="PCharge", node_model="USRH")
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")