Example #1
0
 def c(self, ctx, eq, Ef, numeric_parameters=False):
     Ef_raw = Ef
     if self.Ef_max is not None:
         Ef = where(Ef < self.Ef_max, Ef, self.Ef_max)
         if self.logger.isEnabledFor(logging.INFO):
             if np.any(nvalue(Ef) != nvalue(Ef_raw)):
                 self.logger.info(
                     'c(%r): clipping Ef>%r, max(Ef)=%r' %
                     (eq.prefix, self.Ef_max, np.amax(
                         nvalue(Ef_raw))))
     N0 = self.N0(ctx, eq)
     if numeric_parameters:
         N0 = nvalue(N0)
     Vt = ctx.varsOf(eq.thermal)['Vt']
     if numeric_parameters:
         Vt = nvalue(Vt)
     v = Ef / Vt
     if self.c_limit:
         v_raw = v
         v = where(v <= 0., v, 0.)
         if self.logger.isEnabledFor(logging.INFO):
             if np.any(nvalue(v_raw) != nvalue(v)):
                 self.logger.info(
                     'c(%r): clipping Ef/kT>0, max(Ef/kT)=%r' %
                     (eq.prefix, np.amax(
                         nvalue(v_raw))))
     c = exp(v) * N0
     return c
Example #2
0
 def solve_analytical(self, ctx, eq, fixed):
     hole, = eq.hole
     electron, = eq.electron
     C = fixed
     Nc = electron.dos.N0(ctx, electron)
     Nv = hole.dos.N0(ctx, hole)
     Vt = ctx.varsOf(eq.thermal)['Vt']
     Ec = ctx.varsOf(electron)['Ebandv']
     Ev = ctx.varsOf(hole)['Ebandv']
     uc = exp(Ec/Vt)
     uv = exp(Ev/Vt)
     # TODO: rewrite to avoid overflow, reference to middle of bandgap
     Ef = Vt*log((C*uc + sqrt((C*C*uc + 4*Nc*Nv*uv)*uc))/(2*Nc))
     n = Nc*exp((Ef-Ec)/Vt)
     p = Nv*exp((Ev-Ef)/Vt)
     return Ef, dict({id(hole): p, id(electron): n})
Example #3
0
 def evaluate(self, ctx, eq):
     if ctx.solver.poissonOnly:
         return
     transportenergy = ctx.param(eq.transport_eq, 'energy')
     trate = ctx.param(eq.trap_eq, 'trate')
     if self.rrate_param:
         rrate = ctx.param(eq.trap_eq, 'rrate')
     else:
         trapenergy = ctx.param(eq.trap_eq, 'energy')
         depth = (trapenergy - transportenergy) * eq.transport_eq.z
         rrate = trate * \
             exp(-depth / ctx.varsOf(eq.transport_eq.thermal)['Vt'])
     transportN0 = ctx.param(eq.transport_eq, 'N0')
     trapN0 = ctx.param(eq.trap_eq, 'N0')
     ctransport = ctx.varsOf(eq.transport_eq)['c']
     ctrap = ctx.varsOf(eq.trap_eq)['c']
     if self.fill_trap:
         a = trate * (trapN0 - ctrap)
     else:
         a = trate * trapN0
     if self.fill_transport:
         b = rrate * (transportN0 - ctransport)
     else:
         b = rrate * transportN0
     g = a * ctransport - b * ctrap
     self.add(ctx, g, plus=[eq.trap_eq], minus=[eq.transport_eq])
Example #4
0
def Aux2(x):
    """
    Auxiliary function Aux2(x) = 1./(exp(x)+1)
    Properties: Aux2(x)+Aux2(-x)=1
    """
    xn = ad.where(x < 700., x, 700.)
    return 1. / (ad.exp(xn) + 1.)
Example #5
0
def B(x):
    """
    Bernoulli function B(x)=x/(exp(x)-1), implemented for double precision
    calculation
    """

    # For small x, Taylor expansion should be used instead of direct
    # formula which will is not even defined for x=0.
    BP = 0.0031769106669272879

    # Taylor series
    x2 = x**2.
    taylor = 1. - x / 2. + x2 / 12. - x2**2 / 720.

    # Direct calculation
    # 1e-20 is added to avoid NaN for small x. It only modifies
    # the result if abs(x)<BP. In such a case, the direct formula
    # is not used anyway.
    # In order to avoid overflow errors, maximum x is limited to 700
    # to ensure that exp(xn) is always representable in double precision.
    # Anyway xn/(exp(xn)-1.) is almost 0. for large x
    xn = ad.where(x < 700., x, 700.)
    direct = xn / ((ad.exp(xn) - 1.) + 1e-20)

    # Breakpoint BP is chosen so that Taylor series and direct
    # calculation coincide in double precision.
    return ad.where(abs(x) < BP, taylor, direct)
Example #6
0
File: egdm.py Project: mzszym/oedes
def g2_En2(nsigma, En2):
    """
    EGDM g2(En2)
    nsigma=sigma/kT, recommended 3<=nsigma<=6
    En2=(E*a/sigma)**2, recommended En2<4.
    """
    return ad.exp(0.44 * (nsigma**(3. / 2.) - 2.2)
                  * (ad.sqrt(1 + 0.8 * En2) - 1))
Example #7
0
File: egdm.py Project: mzszym/oedes
def g1(nsigma, c):
    """
    EGDM g1
    nsigma=sigma/kT: must be nsigma>=1.
    c must be 0<=c<=1, recommended c<0.1
    """
    delta = 2.0 * (ad.log(nsigma**2 - nsigma) -
                   ad.log(ad.log(4))) / (nsigma**2)
    return ad.exp(0.5 * (nsigma**2 - nsigma) * (2 * c)**delta)
Example #8
0
File: srh.py Project: mzszym/oedes
 def evaluate(self, ctx, eq):
     assert eq.hole_eq.thermal is eq.electron_eq.thermal
     if ctx.solver.poissonOnly:
         return
     Vt = ctx.varsOf(eq.electron_eq.thermal)['Vt']
     Et = ctx.param(eq, 'energy')
     ni = ctx.param(eq.electron_eq, 'N0') * \
         exp((Et - ctx.param(eq.electron_eq, 'energy')) / Vt)
     pi = ctx.param(eq.hole_eq, 'N0') * \
         exp((ctx.param(eq.hole_eq, 'energy') - Et) / Vt)
     Cn = ctx.param(eq.electron_eq, self.name, 'trate')
     Cp = ctx.param(eq.hole_eq, self.name, 'trate')
     n = ctx.varsOf(eq.electron_eq)['c']
     p = ctx.varsOf(eq.hole_eq)['c']
     g = Cn * Cp * ctx.param(eq, 'N0') * \
         (n * p - ni * pi) / (Cn * (n + ni) + Cp * (p + pi))
     ctx.outputCell([eq, 'G'],
                    g,
                    mesh=eq.electron_eq.mesh,
                    unit=ctx.units.dconcentration_dt)
     self.add(ctx, g, minus=[eq.electron_eq, eq.hole_eq])
Example #9
0
File: gdos.py Project: mzszym/oedes
    def dIdb(self, a, b):
        v = self._nevaluate(
            nvalue(a), nvalue(b), need_value=True, need_da=not isnvalue(a), need_db=True, need_d2ab=not isnvalue(a), need_d2bb=not isnvalue(b))
        i = ad.exp(v['value'])

        def _dIdb(a, _):
            return i * v['db']

        def _dIdb_deriv(args, value):
            yield lambda: i * (v['d2ab'] + v['da'] * v['db'])
            yield lambda: i * (v['d2bb'] + v['db'] * v['db'])
        return ad.apply(asdifferentiable(_dIdb, _dIdb_deriv), (a, b))
Example #10
0
File: band.py Project: mzszym/oedes
 def mobility(self, parent, ctx, eq):
     mu0 = ctx.param(eq, 'mu0')
     gamma = ctx.param(eq, 'gamma')
     v = gamma * sqrt(ctx.varsOf(eq.poisson)['Ecellm'] + 1e-10)
     v_max = log(1e10)
     v_min = -v_max
     v = where(v < v_max, v, v_max)
     v = where(v > v_min, v, v_min)
     mu = mu0 * exp(v)
     mu_face = eq.mesh.faceaverage(mu)
     ctx.varsOf(eq)['mu_face'] = mu_face
     ctx.varsOf(eq)['mu_cell'] = mu
Example #11
0
    def dIdb(self, a, b):
        v = self._nevaluate(ad.nvalue(a),
                            ad.nvalue(b),
                            need_value=True,
                            need_da=isinstance(a, ad.forward.value),
                            need_db=True,
                            need_d2ab=isinstance(a, ad.forward.value),
                            need_d2bb=isinstance(b, ad.forward.value))
        i = ad.exp(v['value'])

        def _dIdb(a, _):
            return i * v['db']

        def _dIdb_deriv(args, value):
            yield lambda: i * (v['d2ab'] + v['da'] * v['db'])
            yield lambda: i * (v['d2bb'] + v['db'] * v['db'])

        return ad.custom_function(_dIdb, _dIdb_deriv)(a, b)
Example #12
0
    def evaluate(self, ctx, eq):
        if ctx.solver.poissonOnly:
            return
        assert eq.electron_eq.poisson is eq.hole_eq.poisson
        assert eq.electron_eq.thermal is eq.hole_eq.thermal
        poissonvars = ctx.varsOf(eq.electron_eq.poisson)
        epsilon = poissonvars['epsilon']
        Vt = ctx.varsOf(eq.electron_eq.thermal)['Vt']
        nvars = ctx.varsOf(eq.electron_eq)
        pvars = ctx.varsOf(eq.hole_eq)
        evars = ctx.varsOf(eq.eq)

        if self.binding_energy_param:
            Eb = ctx.param(eq.eq, 'binding_energy')
            a = scipy.constants.elementary_charge / \
                (Eb * 4 * np.pi * epsilon)
        else:
            a = ctx.param(eq.eq, 'distance')
            Eb = scipy.constants.elementary_charge / \
                (4 * np.pi * epsilon * a)
        u = 3. / (4. * np.pi * a**3)  # m^-3
        v = exp(-Eb / Vt)  # 1
        b = (scipy.constants.elementary_charge / (8 * np.pi)) * \
            poissonvars['Ecellm'] / (epsilon * Vt**2)  # 1
        # b=0.
        t = functions.OnsagerFunction(
            where(b < self.b_max, b, self.b_max) + self.b_eps)  # 1
        gamma = scipy.constants.elementary_charge * \
            (nvars['mu_cell'] + pvars['mu_cell']) / \
            epsilon  # m^3 /s
        r = gamma * (nvars['c'] * pvars['c'] - ctx.common_param(
            [eq.electron_eq, eq.hole_eq], 'npi'))  # 1/(m^3 s) # TODO
        d = gamma * evars['c'] * u * v * t
        ctx.outputCell([eq.eq, self.name, 'recombination'],
                       r,
                       unit=ctx.units.dconcentration_dt)
        ctx.output([eq.eq, self.name, 'dissociation'],
                   d,
                   unit=ctx.units.dconcentration_dt)
        f = r - d
        self.add(ctx, f, plus=[eq.eq], minus=[eq.hole_eq, eq.electron_eq])
Example #13
0
File: gdos.py Project: mzszym/oedes
 def I(self, a, b):
     v = self._value(a, b)
     l_max = np.log(self.I_max)
     v = ad.where(v <= l_max, v, l_max)
     return ad.exp(v)
Example #14
0
File: egdm.py Project: mzszym/oedes
def mu0t_inverse(nsigma, mu0t):
    return mu0t / (1.8e-9 * ad.exp(-0.42 * nsigma**2))
Example #15
0
File: egdm.py Project: mzszym/oedes
def mu0t(nsigma, mu0):
    """EGDM mu_0(T) - temperature dependent mobility prefactor in
    function of temperature independent prefactor"""
    return mu0 * 1.8e-9 * ad.exp(-0.42 * nsigma**2)