#coding: utf8
import plask


class FreeCarrier2D(plask.Solver):
    """
    FreeCarrier2D(name="")
    
    Quantum-well gain using free-carrier approximation for two-dimensional Cartesian geometry.
    """
    class Spectrum(object):
        """
        Gain spectrum object. You can call it like a function to get gains for different vavelengths.
        """
        def __call__(self, lam):
            """
            __call__(self, lam)
            
                Get gain at specified wavelength.
                
                Args:
                    lam (float): Wavelength to get the gain at.
            """


    T0 = None
    """
    Reference temperature.
    
    In this temperature levels estimates are computed.
    """

    geometry = None
    """
    Geometry provided to the solver
    """

    def get_energy_levels(self, T=None):
        """
        get_energy_levels(self, T=None)
        
            Get energy levels in quantum wells.
            
            Compute energy levels in quantum wells for electrons, heavy holes and
            light holes.
            
            Args:
                T (float or ``None``): Temperature to get the levels. If this argument is
                                       ``None``, the estimates for temperature :py:attr:`T0`
                                       are returned.
            
            Returns:
                list: List with dictionaries with keys `el`, `hh`, and `lh` with levels for
                      electrons, heavy holes and light holes. Each list element corresponds
                      to one active region.
        """

    def get_fermi_levels(self, n, T=None, reg=0):
        """
        get_fermi_levels(self, n, T=None, reg=0)
        
            Get quasi Fermi levels.
            
            Compute quasi-Fermi levels in specified active region.
            Args:
                n (float): Carriers concentration to determine the levels for
                           [1/cm\ :sup:`3`\ ].
                T (float or ``None``): Temperature to get the levels. If this argument is
                                       ``None``, the estimates for temperature :py:attr:`T0`
                                       are returned.
            
                reg (int): Active region number.
            Returns:
                tuple: Two-element tuple with quasi-Fermi levels for electrons and holes.
        """

    id = None
    """
    Id of the solver object. (read only)
    
    Example:
        >>> mysolver.id
        mysolver:category.type
    """

    inCarriersConcentration = None
    """
    Receiver of the carriers concentration required for computations [1/cm³].
    
    
    You will find usage details in the documentation of the receiver class
    :class:`~plask.flow.CarriersConcentrationReceiver2D`.
    
    Example:
       Connect the reveiver to a provider from some other solver:
    
       >>> solver.inCarriersConcentration = other_solver.outCarriersConcentration
    
    See also:
    
       Receciver class: :class:`plask.flow.CarriersConcentrationReceiver2D`
    
       Provider class: :class:`plask.flow.CarriersConcentrationProvider2D`
    
       Data filter: :class:`plask.filter.CarriersConcentrationFilter2D`
    """

    inTemperature = None
    """
    Receiver of the temperature required for computations [K].
    
    
    You will find usage details in the documentation of the receiver class
    :class:`~plask.flow.TemperatureReceiver2D`.
    
    Example:
       Connect the reveiver to a provider from some other solver:
    
       >>> solver.inTemperature = other_solver.outTemperature
    
    See also:
    
       Receciver class: :class:`plask.flow.TemperatureReceiver2D`
    
       Provider class: :class:`plask.flow.TemperatureProvider2D`
    
       Data filter: :class:`plask.filter.TemperatureFilter2D`
    """

    def initialize(self):
        """
        initialize(self)
        
            Initialize solver.
            
            This method manually initialized the solver and sets :attr:`initialized` to
            *True*. Normally calling it is not necessary, as each solver automatically
            initializes itself when needed.
            
            Returns:
                bool: solver :attr:`initialized` state prior to this method call.
        """

    initialized = None
    """
    True if the solver has been initialized. (read only)
    
    Solvers usually get initialized at the beginning of the computations.
    You can clean the initialization state and free the memory by calling
    the :meth:`invalidate` method.
    """

    def invalidate(self):
        """
        invalidate(self)
        
            Set the solver back to uninitialized state.
            
            This method frees the memory allocated by the solver and sets
            :attr:`initialized` to *False*.
        """

    lifetime = None
    """
    Average carriers lifetime.
    
    This parameter is used for gain spectrum broadening. (float [ps])
    """

    def load_xpl(self, xpl, manager):
        """
        load_xpl(self, xpl, manager)
        
            Load configuration from XPL reader.
            
            This method should be overriden in custom Python solvers.
            
            Example:
              .. code-block:: python
            
                 def load_xpl(self, xpl, manager):
                     for tag in xpl:
                         if tag == 'config':
                             self.a = tag['a']
                             self.b = tag.get('b', 0)
                             if 'c' in tag:
                                 self.c = tag['c']
                         if tag == 'combined':
                             for subtag in tag:
                                 if subtag == 'withtext':
                                     self.data = subtag.attrs
                                     # Text must be read last
                                     self.text = subtag.text
                         elif tag == 'geometry':
                             self.geometry = tag.getitem(manager.geo, 'ref')
        """

    matrix_element = None
    """
    Momentum matrix element.
    
    Value of the squared matrix element in gain computations. If it is not set it
    is estimated automatically. (float [eV×m0])
    """

    mesh = None
    """
    Mesh provided to the solver
    """

    outGain = None
    """
    Provider of the computed material gain [1/cm].
    
    
    outGain(n=0, mesh, wavelength, interpolation='default')
    
    :param str deriv: Gain derivative to return. can be '' (empty) or 'conc'.
                      In the latter case, the gain derivative over carriers
                      concentration is returned.
    :param mesh mesh: Target mesh to get the field at.
    :param str interpolation: Requested interpolation method.
    :param float wavelength: The wavelength at which the gain is computed [nm].
    
    :return: Data with the material gain on the specified mesh **[1/cm]**.
    
    You may obtain the number of different values this provider can return by
    testing its length.
    
    Example:
       Connect the provider to a receiver in some other solver:
    
       >>> other_solver.inGain = solver.outGain
    
       Obtain the provided field:
    
       >>> solver.outGain(0, mesh, wavelength)
       <plask.Data at 0x1234567>
    
       Test the number of provided values:
    
       >>> len(solver.outGain)
       3
    
    See also:
    
       Provider class: :class:`plask.flow.GainProvider2D`
    
       Receciver class: :class:`plask.flow.GainReceiver2D`
    """

    def spectrum(*args, **kwargs):
        """
        spectrum(self, point)
        spectrum(self, c0, c1)
        
            Get gain spectrum at given point.
            
            Args:
                point (vec): Point to get gain at.
                c0, c1 (float): Coordinates of the point to get gain at.
            
            Returns:
                :class:`FreeCarrier2D.Spectrum`: Spectrum object.
        """

    strained = None
    """
    Boolean attribute indicating if the solver should consider strain in the active
    region.
    
    If set to ``True`` then there must a layer with the role *substrate* in
    the geometry. The strain is computed by comparing the atomic lattice constants
    of the substrate and the quantum wells.
    """



class FreeCarrierCyl(plask.Solver):
    """
    FreeCarrierCyl(name="")
    
    Quantum-well gain using free-carrier approximation for cylindrical geometry.
    """
    class Spectrum(object):
        """
        Gain spectrum object. You can call it like a function to get gains for different vavelengths.
        """
        def __call__(self, lam):
            """
            __call__(self, lam)
            
                Get gain at specified wavelength.
                
                Args:
                    lam (float): Wavelength to get the gain at.
            """


    T0 = None
    """
    Reference temperature.
    
    In this temperature levels estimates are computed.
    """

    geometry = None
    """
    Geometry provided to the solver
    """

    def get_energy_levels(self, T=None):
        """
        get_energy_levels(self, T=None)
        
            Get energy levels in quantum wells.
            
            Compute energy levels in quantum wells for electrons, heavy holes and
            light holes.
            
            Args:
                T (float or ``None``): Temperature to get the levels. If this argument is
                                       ``None``, the estimates for temperature :py:attr:`T0`
                                       are returned.
            
            Returns:
                list: List with dictionaries with keys `el`, `hh`, and `lh` with levels for
                      electrons, heavy holes and light holes. Each list element corresponds
                      to one active region.
        """

    def get_fermi_levels(self, n, T=None, reg=0):
        """
        get_fermi_levels(self, n, T=None, reg=0)
        
            Get quasi-Fermi levels.
            
            Compute quasi-Fermi levels in specified active region.
            Args:
                n (float): Carriers concentration to determine the levels for
                           [1/cm\ :sup:`3`\ ].
                T (float or ``None``): Temperature to get the levels. If this argument is
                                       ``None``, the estimates for temperature :py:attr:`T0`
                                       are returned.
            
                reg (int): Active region number.
            Returns:
                tuple: Two-element tuple with quasi-Fermi levels for electrons and holes.
        """

    id = None
    """
    Id of the solver object. (read only)
    
    Example:
        >>> mysolver.id
        mysolver:category.type
    """

    inBandEdges = None
    """
    Receiver of the conduction and valence band edges required for computations [eV].
    
    
    You will find usage details in the documentation of the receiver class
    :class:`~plask.flow.BandEdgesReceiverCyl`.
    
    Example:
       Connect the reveiver to a provider from some other solver:
    
       >>> solver.inBandEdges = other_solver.outBandEdges
    
    See also:
    
       Receciver class: :class:`plask.flow.BandEdgesReceiverCyl`
    
       Provider class: :class:`plask.flow.BandEdgesProviderCyl`
    
       Data filter: :class:`plask.filter.BandEdgesFilterCyl`
    """

    inCarriersConcentration = None
    """
    Receiver of the carriers concentration required for computations [1/cm³].
    
    
    You will find usage details in the documentation of the receiver class
    :class:`~plask.flow.CarriersConcentrationReceiverCyl`.
    
    Example:
       Connect the reveiver to a provider from some other solver:
    
       >>> solver.inCarriersConcentration = other_solver.outCarriersConcentration
    
    See also:
    
       Receciver class: :class:`plask.flow.CarriersConcentrationReceiverCyl`
    
       Provider class: :class:`plask.flow.CarriersConcentrationProviderCyl`
    
       Data filter: :class:`plask.filter.CarriersConcentrationFilterCyl`
    """

    inFermiLevels = None
    """
    Receiver of the quasi-Fermi levels for electrons and holes required for computations [eV].
    
    
    You will find usage details in the documentation of the receiver class
    :class:`~plask.flow.FermiLevelsReceiverCyl`.
    
    Example:
       Connect the reveiver to a provider from some other solver:
    
       >>> solver.inFermiLevels = other_solver.outFermiLevels
    
    See also:
    
       Receciver class: :class:`plask.flow.FermiLevelsReceiverCyl`
    
       Provider class: :class:`plask.flow.FermiLevelsProviderCyl`
    
       Data filter: :class:`plask.filter.FermiLevelsFilterCyl`
    """

    inTemperature = None
    """
    Receiver of the temperature required for computations [K].
    
    
    You will find usage details in the documentation of the receiver class
    :class:`~plask.flow.TemperatureReceiverCyl`.
    
    Example:
       Connect the reveiver to a provider from some other solver:
    
       >>> solver.inTemperature = other_solver.outTemperature
    
    See also:
    
       Receciver class: :class:`plask.flow.TemperatureReceiverCyl`
    
       Provider class: :class:`plask.flow.TemperatureProviderCyl`
    
       Data filter: :class:`plask.filter.TemperatureFilterCyl`
    """

    def initialize(self):
        """
        initialize(self)
        
            Initialize solver.
            
            This method manually initialized the solver and sets :attr:`initialized` to
            *True*. Normally calling it is not necessary, as each solver automatically
            initializes itself when needed.
            
            Returns:
                bool: solver :attr:`initialized` state prior to this method call.
        """

    initialized = None
    """
    True if the solver has been initialized. (read only)
    
    Solvers usually get initialized at the beginning of the computations.
    You can clean the initialization state and free the memory by calling
    the :meth:`invalidate` method.
    """

    def invalidate(self):
        """
        invalidate(self)
        
            Set the solver back to uninitialized state.
            
            This method frees the memory allocated by the solver and sets
            :attr:`initialized` to *False*.
        """

    lifetime = None
    """
    Average carriers lifetime.
    
    This parameter is used for gain spectrum broadening. (float [ps])
    """

    def load_xpl(self, xpl, manager):
        """
        load_xpl(self, xpl, manager)
        
            Load configuration from XPL reader.
            
            This method should be overriden in custom Python solvers.
            
            Example:
              .. code-block:: python
            
                 def load_xpl(self, xpl, manager):
                     for tag in xpl:
                         if tag == 'config':
                             self.a = tag['a']
                             self.b = tag.get('b', 0)
                             if 'c' in tag:
                                 self.c = tag['c']
                         if tag == 'combined':
                             for subtag in tag:
                                 if subtag == 'withtext':
                                     self.data = subtag.attrs
                                     # Text must be read last
                                     self.text = subtag.text
                         elif tag == 'geometry':
                             self.geometry = tag.getitem(manager.geo, 'ref')
        """

    matrix_element = None
    """
    Momentum matrix element.
    
    Value of the squared matrix element in gain computations. If it is not set it
    is estimated automatically. (float [eV×m0])
    """

    mesh = None
    """
    Mesh provided to the solver
    """

    outEnergyLevels = None
    """
    Provider of the computed energy levels for electrons and holes [eV].
    
    
    outEnergyLevels(n=0, mesh, interpolation='default')
    
    :param int n: Value number.
    :param mesh mesh: Target mesh to get the field at.
    :param str interpolation: Requested interpolation method.
    
    :return: Data with the energy levels for electrons and holes on the specified mesh **[eV]**.
    
    You may obtain the number of different values this provider can return by
    testing its length.
    
    Example:
       Connect the provider to a receiver in some other solver:
    
       >>> other_solver.inEnergyLevels = solver.outEnergyLevels
    
       Obtain the provided field:
    
       >>> solver.outEnergyLevels(0, mesh)
       <plask.Data at 0x1234567>
    
       Test the number of provided values:
    
       >>> len(solver.outEnergyLevels)
       3
    
    See also:
    
       Provider class: :class:`plask.flow.EnergyLevelsProviderCyl`
    
       Receciver class: :class:`plask.flow.EnergyLevelsReceiverCyl`
    """

    outGain = None
    """
    Provider of the computed material gain [1/cm].
    
    
    outGain(n=0, mesh, wavelength, interpolation='default')
    
    :param str deriv: Gain derivative to return. can be '' (empty) or 'conc'.
                      In the latter case, the gain derivative over carriers
                      concentration is returned.
    :param mesh mesh: Target mesh to get the field at.
    :param str interpolation: Requested interpolation method.
    :param float wavelength: The wavelength at which the gain is computed [nm].
    
    :return: Data with the material gain on the specified mesh **[1/cm]**.
    
    You may obtain the number of different values this provider can return by
    testing its length.
    
    Example:
       Connect the provider to a receiver in some other solver:
    
       >>> other_solver.inGain = solver.outGain
    
       Obtain the provided field:
    
       >>> solver.outGain(0, mesh, wavelength)
       <plask.Data at 0x1234567>
    
       Test the number of provided values:
    
       >>> len(solver.outGain)
       3
    
    See also:
    
       Provider class: :class:`plask.flow.GainProviderCyl`
    
       Receciver class: :class:`plask.flow.GainReceiverCyl`
    """

    def spectrum(*args, **kwargs):
        """
        spectrum(self, point)
        spectrum(self, c0, c1)
        
            Get gain spectrum at given point.
            
            Args:
                point (vec): Point to get gain at.
                c0, c1 (float): Coordinates of the point to get gain at.
            
            Returns:
                :class:`FreeCarrierCyl.Spectrum`: Spectrum object.
        """

    strained = None
    """
    Boolean attribute indicating if the solver should consider strain in the active
    region.
    
    If set to ``True`` then there must a layer with the role *substrate* in
    the geometry. The strain is computed by comparing the atomic lattice constants
    of the substrate and the quantum wells.
    """

