Source code for nanohubpadre.models

"""
Physical models configuration for PADRE simulations.

Controls recombination, mobility, and other physical models.
"""

from typing import Optional, Union, List
from .base import PadreCommand


[docs] class Models(PadreCommand): """ Configure physical models for the simulation. Parameters ---------- temperature : float Ambient temperature in Kelvin (default 300K) Recombination models: srh : bool Shockley-Read-Hall recombination auger : bool Auger recombination direct : bool Direct radiative recombination deeptrap : bool Deep-level traps conlife : bool Concentration-dependent lifetimes impact : bool Impact ionization generation tunneling : bool Band-to-band tunneling laser : bool Stimulated emission Band structure: bgn : bool Band-gap narrowing statistics : str Carrier statistics ("boltzmann", "fermi", "2dgas") incomplete : bool Incomplete ionization Mobility models: conmob : bool Concentration-dependent mobility (ionized impurity scattering) ccmob : bool Carrier-carrier scattering fldmob : bool Field-dependent mobility (velocity saturation) gatmob : bool Gate-field dependent mobility flddif : bool Field-dependent diffusivity neutral : bool Neutral impurity scattering Region selection: e_region : int or list Regions for velocity saturation model g_region : int or list Regions for gate-field model d_region : int or list Regions for diffusivity model Driving force specification: e_drive : str Parallel field drive term g_drive : str Gate field drive term d_drive : str Diffusivity drive term i_drive : str Impact ionization drive term print_models : bool Print model status and coefficients Example ------- >>> # Basic drift-diffusion with SRH >>> models = Models(temperature=300, srh=True, conmob=True, fldmob=True) >>> >>> # Energy balance simulation >>> models = Models(srh=True, auger=True, bgn=True, ... statistics="fermi", fldmob=True) """ command_name = "MODELS" # Valid drive term options DRIVE_OPTIONS = ["eoj", "eoqf", "ex", "ey", "emag", "qf", "qfb"] G_DRIVE_OPTIONS = ["exj", "exqf", "ex", "ey", "emag"]
[docs] def __init__( self, temperature: float = 300.0, # Recombination srh: bool = False, auger: bool = False, direct: bool = False, deeptrap: bool = False, conlife: bool = False, impact: bool = False, tunneling: bool = False, laser: bool = False, # Band structure bgn: bool = False, statistics: str = "boltzmann", incomplete: bool = False, # Mobility conmob: bool = False, ccmob: bool = False, fldmob: bool = False, gatmob: bool = False, flddif: bool = False, neutral: bool = False, # Region selection e_region: Optional[Union[int, List[int]]] = None, g_region: Optional[Union[int, List[int]]] = None, d_region: Optional[Union[int, List[int]]] = None, # Driving forces e_drive: Optional[str] = None, g_drive: Optional[str] = None, d_drive: Optional[str] = None, i_drive: Optional[str] = None, i_current: Optional[str] = None, # Energy transport jtherm: bool = True, et_form: bool = False, # Carrier forms c1_sign: Optional[int] = None, c2_sign: Optional[int] = None, c1_type: Optional[int] = None, c2_type: Optional[int] = None, # Noise gen_nois: bool = False, diff_noi: bool = False, one_over_f_n: bool = False, # Misc print_models: bool = False, ): super().__init__() self.temperature = temperature # Recombination self.srh = srh self.auger = auger self.direct = direct self.deeptrap = deeptrap self.conlife = conlife self.impact = impact self.tunneling = tunneling self.laser = laser # Band structure self.bgn = bgn self.statistics = statistics self.incomplete = incomplete # Mobility self.conmob = conmob self.ccmob = ccmob self.fldmob = fldmob self.gatmob = gatmob self.flddif = flddif self.neutral = neutral # Regions self.e_region = e_region self.g_region = g_region self.d_region = d_region # Drives self.e_drive = e_drive self.g_drive = g_drive self.d_drive = d_drive self.i_drive = i_drive self.i_current = i_current # Energy transport self.jtherm = jtherm self.et_form = et_form # Carrier forms self.c1_sign = c1_sign self.c2_sign = c2_sign self.c1_type = c1_type self.c2_type = c2_type # Noise self.gen_nois = gen_nois self.diff_noi = diff_noi self.one_over_f_n = one_over_f_n # Misc self.print_models = print_models
def _format_region(self, region: Union[int, List[int]]) -> str: """Format region specification as concatenated integers.""" if isinstance(region, list): return "".join(str(r) for r in region) return str(region)
[docs] def to_padre(self) -> str: params = {"TEMP": self.temperature} flags = [] # Recombination if self.srh: flags.append("SRH") if self.auger: flags.append("AUGER") if self.direct: flags.append("DIRECT") if self.deeptrap: flags.append("DEEPTRAP") if self.conlife: flags.append("CONLIFE") if self.impact: flags.append("IMPACT") if self.tunneling: flags.append("TUNNELING") if self.laser: flags.append("LASER") # Band structure if self.bgn: flags.append("BGN") if self.statistics != "boltzmann": params["STATISTICS"] = self.statistics if self.incomplete: flags.append("INCOMPLETE") # Mobility if self.conmob: flags.append("CONMOB") if self.ccmob: flags.append("CCMOB") if self.fldmob: flags.append("FLDMOB") if self.gatmob: flags.append("GATMOB") if self.flddif: flags.append("FLDDIF") if self.neutral: flags.append("NEUTRAL") # Regions if self.e_region is not None: params["E.REGION"] = self._format_region(self.e_region) if self.g_region is not None: params["G.REGION"] = self._format_region(self.g_region) if self.d_region is not None: params["D.REGION"] = self._format_region(self.d_region) # Drives if self.e_drive: params["E.DRIVE"] = self.e_drive if self.g_drive: params["G.DRIVE"] = self.g_drive if self.d_drive: params["D.DRIVE"] = self.d_drive if self.i_drive: params["I.DRIVE"] = self.i_drive if self.i_current: params["I.CURRENT"] = self.i_current # Energy transport if not self.jtherm: params["JTHERM"] = False if self.et_form: flags.append("ET.FORM") # Carrier forms if self.c1_sign is not None: params["C1.SIGN"] = self.c1_sign if self.c2_sign is not None: params["C2.SIGN"] = self.c2_sign if self.c1_type is not None: params["C1.TYPE"] = self.c1_type if self.c2_type is not None: params["C2.TYPE"] = self.c2_type # Noise if self.gen_nois: flags.append("GEN.NOIS") if self.diff_noi: flags.append("DIFF.NOI") if self.one_over_f_n: flags.append("1OVERF.N") # Misc if self.print_models: flags.append("PRINT") return self._build_command(params, flags)
[docs] @classmethod def drift_diffusion(cls, temperature: float = 300, srh: bool = True, auger: bool = False, conmob: bool = True, fldmob: bool = True, **kwargs) -> "Models": """Configure standard drift-diffusion simulation.""" return cls(temperature=temperature, srh=srh, auger=auger, conmob=conmob, fldmob=fldmob, **kwargs)
[docs] @classmethod def energy_balance(cls, temperature: float = 300, srh: bool = True, auger: bool = True, bgn: bool = True, **kwargs) -> "Models": """Configure energy balance simulation.""" return cls(temperature=temperature, srh=srh, auger=auger, bgn=bgn, statistics="fermi", **kwargs)