def SetOxideParameters(device, region): ''' Sets physical parameters ''' SetUniversalParameters(device, region) ds.set_parameter( device=device, region=region, name="Permittivity", value=3.9 * ds.get_parameter(device=device, region=region, name='Permittivity_0'))
def simulate_charge(device, contact, equation, solver_params): #charge_factor=1e7 #from F/cm^2 to fF/um^2 dv = 0.001 v1 = ds.get_parameter(device=device, name=GetContactBiasName(contact)) q1 = ds.get_contact_charge(device=device, contact=contact, equation="PotentialEquation") v2 = v1 + dv ds.set_parameter(name=GetContactBiasName(contact), value=v2) ds.solve(**solver_params) q2 = ds.get_contact_charge(device=device, contact=contact, equation="PotentialEquation") return (v1, (charge_factor * (q2 - q1) / dv))
def rampparam(device, region, param, stop, step_size, min_step, solver_params=None, callback=None): ''' Ramps param with assignable callback function ''' start_param=ds.get_parameter(device=device, region=region, name=param) if (start_param < stop): step_sign=1 else: step_sign=-1 last_param=start_param while(abs(last_param - stop) > min_step): print("last end %e %e" % (last_param, stop)) next_param=last_param + step_sign * step_size if next_param < stop: next_step_sign=1 else: next_step_sign=-1 if next_step_sign != step_sign: next_param=stop print("setting to last param %e" % (stop)) print("setting next param %e" % (next_param)) ds.set_parameter(device=device, region=region, name=param, value=next_param) try: ds.solve(**solver_params) except ds.error as msg: if str(msg).find("Convergence failure") != 0: raise ds.set_parameter(device=device, region=region, name=param, value=last_param) step_size *= 0.5 print("setting new step size %e" % (step_size)) #raise NameError("STOP") if step_size < min_step: raise RuntimeError("Min step size too small") continue last_param=next_param if callback: callback()
def format_value(value): if isinstance(value, str): ret = '"%s"' % value elif isinstance(value, float): ret = "%g" % value else: ret = value return ret with open("mos_2d_params.py", "w") as ofh: ofh.write('import devsim\n') for p in devsim.get_parameter_list(): v = format_value(devsim.get_parameter(name=p)) ofh.write('devsim.set_parameter(name="%s", value=%s)\n' % (p, v)) for i in devsim.get_device_list(): for p in devsim.get_parameter_list(device=i): v = format_value(devsim.get_parameter(device=i, name=p)) ofh.write( 'devsim.set_parameter(device="%s", name="%s", value=%s)\n' % (i, p, v)) for i in devsim.get_device_list(): for j in devsim.get_region_list(device=i): for p in devsim.get_parameter_list(device=i, region=j): v = format_value( devsim.get_parameter(device=i, region=j, name=p)) ofh.write( 'devsim.set_parameter(device="%s", region="%s", name="%s", value=%s)\n'
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")
devsim.set_node_values(device=device, region="bulk", name="Holes", init_from="IntrinsicHoles") createSiliconDriftDiffusion(device, "bulk") createSiliconDriftDiffusionAtContact(device, "bulk", "drain") createSiliconDriftDiffusionAtContact(device, "bulk", "source") createSiliconDriftDiffusionAtContact(device, "bulk", "body") devsim.solve(type="dc", absolute_error=1.0e30, relative_error=1e-5, maximum_iterations=30) devsim.element_from_edge_model(edge_model="ElectricField", device=device, region="bulk") devsim.write_devices(file="mos_2d_dd.msh", type="devsim") with open("mos_2d_params.py", "w", encoding="utf-8") as ofh: ofh.write('import devsim\n') for p in devsim.get_parameter_list(): v=repr(devsim.get_parameter(name=p)) ofh.write('devsim.set_parameter(name="%s", value=%s)\n' % (p, v)) for i in devsim.get_device_list(): for p in devsim.get_parameter_list(device=i): v=repr(devsim.get_parameter(device=i, name=p)) ofh.write('devsim.set_parameter(device="%s", name="%s", value=%s)\n' % (i, p, v)) for i in devsim.get_device_list(): for j in devsim.get_region_list(device=i): for p in devsim.get_parameter_list(device=i, region=j): v=repr(devsim.get_parameter(device=i, region=j, name=p)) ofh.write('devsim.set_parameter(device="%s", region="%s", name="%s", value=%s)\n' % (i, j, p, v))
# Copyright 2020 Devsim LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #### #### info.py #### print features for this build #### import devsim print(devsim.get_parameter(name="info"))
def SetSiliconParameters(device, region): ''' Sets Silicon device parameters on the specified region. ''' SetUniversalParameters(device, region) ##D. B. M. Klaassen, J. W. Slotboom, and H. C. de Graaff, "Unified apparent bandgap narrowing in n- and p-type Silicon," Solid-State Electronics, vol. 35, no. 2, pp. 125-29, 1992. par = { 'Permittivity': 11.1 * ds.get_parameter(device=device, region=region, name='Permittivity_0'), 'NC300': 2.8e19, # '1/cm^3' 'NV300': 3.1e19, # '1/cm^3' 'EG300': 1.12, # 'eV' 'EGALPH': 2.73e-4, # 'eV/K' 'EGBETA': 0, # 'K' 'Affinity': 4.05, # 'K' # Canali model 'BETAN0': 2.57e-2, # '1' 'BETANE': 0.66, # '1' 'BETAP0': 0.46, # '1' 'BETAPE': 0.17, # '1' 'VSATN0': 1.43e9, 'VSATNE': -0.87, 'VSATP0': 1.62e8, 'VSATPE': -0.52, # Arora model 'MUMN': 88, 'MUMEN': -0.57, 'MU0N': 7.4e8, 'MU0EN': -2.33, 'NREFN': 1.26e17, 'NREFNE': 2.4, 'ALPHA0N': 0.88, 'ALPHAEN': -0.146, 'MUMP': 54.3, 'MUMEP': -0.57, 'MU0P': 1.36e8, 'MU0EP': -2.23, 'NREFP': 2.35e17, 'NREFPE': 2.4, 'ALPHA0P': 0.88, 'ALPHAEP': -0.146, # SRH "taun": 1e-5, "taup": 1e-5, "n1": 1e10, "p1": 1e10, # TEMP # "T" : 300 } for k, v in par.items(): ds.set_parameter(device=device, region=region, name=k, value=v)