Ejemplo n.º 1
0
    def __init__(
        self,
        coefficient,
        x=None,
        quantum_yield=1.0,
        phase_function=None,
        hist=False,
        name="Scatterer",
    ):
        """ 
        Parameters
        ----------
        coefficient: float, list, tuple or numpy.ndarray
            Specifies the scattering coefficient per unit length. Constant values
            can be supplied or a spectrum per nanometer per unit length. 
        x: list, tuple of numpy.ndarray (optional)
            Wavelength values in nanometers. Required when specifying a the
            `coefficient` with an list or tuple.
        quantum_yield: float (optional)
            Default value is 1.0. To include non-radiative scattering use values
            between less than 1.0.
        phase_function callable (optional)
            Determines the direction of scattering. If None is supplied scattering
            is isotropic.
        hist: Bool
            Specifies how the coefficient spectrum is sampled. If `True` the values
            are treated as a histogram. If `False` the values are linearly 
            interpolated.
        name: str
            A user-defined identifier string
        """
        super(Scatterer, self).__init__(name=name)

        # Make absorption/scattering spectrum distribution
        self._coefficient = coefficient
        if coefficient is None:
            raise ValueError("Coefficient must be specified.")
        elif isinstance(coefficient, (float, np.float)):
            self._abs_dist = Distribution(x=None, y=coefficient, hist=hist)
        elif isinstance(coefficient, np.ndarray):
            self._abs_dist = Distribution(x=coefficient[:, 0],
                                          y=coefficient[:, 1],
                                          hist=hist)
        elif isinstance(coefficient, (list, tuple)):
            if x is None:
                raise ValueError("Requires `x`.")
            self._abs_dist = Distribution.from_functions(x,
                                                         coefficient,
                                                         hist=hist)

        self.quantum_yield = quantum_yield
        self.phase_function = (phase_function
                               if phase_function is not None else isotropic)
Ejemplo n.º 2
0
def test2():
    x = np.arange(400, 801, dtype=np.float)
    size = (l, w, d) = (4.8, 1.8, 0.250)  # cm-1
    lsc = LSC(size, wavelength_range=x)

    lsc.add_luminophore(
        "Fluro Red",
        np.column_stack((x, fluro_red.absorption(x) * 11.387815)),  # cm-1
        np.column_stack((x, fluro_red.emission(x))),
        quantum_yield=0.95,
    )

    lsc.add_absorber("PMMA", 0.02)  # cm-1

    def lamp_spectrum(x):
        """ Fit to an experimentally measured lamp spectrum with long wavelength filter.
        """
        def g(x, a, p, w):
            return a * np.exp(-(((p - x) / w)**2))

        a1 = 0.53025700136646192
        p1 = 512.91400020614333
        w1 = 93.491838802960473
        a2 = 0.63578999789955015
        p2 = 577.63100003089369
        w2 = 66.031706473985736
        return g(x, a1, p1, w1) + g(x, a2, p2, w2)

    lamp_dist = Distribution(x, lamp_spectrum(x))
    wavelength_callable = lambda: lamp_dist.sample(np.random.uniform())
    position_callable = lambda: rectangular_mask(l / 2, w / 2)
    lsc.add_light(
        "Oriel Lamp + Filter",
        (0.0, 0.0, 0.5 * d + 0.01),  # put close to top surface
        rotation=(np.radians(180), (1, 0,
                                    0)),  # normal and into the top surface
        wavelength=wavelength_callable,  # wavelength delegate callable
        position=position_callable,  # uniform surface illumination
    )

    lsc.add_solar_cell({"left", "right", "near", "far"})
    lsc.add_air_gap_mirror(lambertian=False)

    lsc.show()
    throw = 300
    lsc.simulate(throw, emit_method="redshift")
    lsc.report()
Ejemplo n.º 3
0
 def __init__(self, emission_spectrum, quantum_yield, *args, **kwargs):
     super(Emissive, self).__init__(*args, **kwargs)
     check_spectrum_like(emission_spectrum)
     self._emission_dist = Distribution(
         x=emission_spectrum[:, 0],
         y=emission_spectrum[:, 1]
     )
     self._quantum_yield = quantum_yield
Ejemplo n.º 4
0
 def test_step_sample(self):
     """ Sampling a step function should only return two value.
     """
     nmedge = 600.0
     nmmin, nmmax = (400.0, 800.0)
     spacing = 1.0
     x = np.arange(nmmin, nmmax + spacing, spacing)
     abs_spec = np.column_stack((x, bandgap(x, nmedge, 1.0)))  # ends a mid range.
     dist = Distribution(abs_spec[:, 0], abs_spec[:, 1], hist=True)
     xmin = dist.sample(0)
     assert np.isclose(xmin, nmmin)
     xmax = dist.sample(1)  # The probabiliity of getting a value > nmedge is zero
     assert np.isclose(xmax, nmedge)
     pmin = dist.lookup(nmmin)
     pmax = dist.lookup(nmmax)
     assert pmin >= 0.0 and pmin <= dist.lookup(nmmin+spacing)
     assert pmax == 1.0
     values = dist.sample(np.linspace(dist.lookup(599-spacing), dist.lookup(600+spacing), 10000))
     assert len(set(values)) == 3
Ejemplo n.º 5
0
 def test_sample_range(self):
     x = np.linspace(400, 1010, 2000)
     abs_spec = np.column_stack((x, bandgap(x, 600, 1000)))
     ems_spec = thermodynamic_emission(abs_spec, T=300, mu=0.1)
     dist = Distribution(ems_spec[:, 0], ems_spec[:, 1])
     xmin = dist.sample(0)
     assert np.isclose(xmin, x.min())
     xmax = dist.sample(1)
     assert np.isclose(xmax, x.max())
     y_at_xmin = dist.lookup(xmin)
     assert np.isclose(y_at_xmin, 0.0)
     y_at_xmax = dist.lookup(xmax)
     assert np.isclose(y_at_xmin, 0.0)
Ejemplo n.º 6
0
    def __init__(
        self,
        coefficient,
        emission=None,
        x=None,
        hist=False,
        quantum_yield=1.0,
        phase_function=None,
        name="Luminophore",
    ):
        """ coefficient: float, list, tuple or numpy.ndarray
                Specifies the absorption coefficient per unit length. Constant values
                can be supplied or a spectrum per nanometer per unit length. 
                
                If using a list of tuple you should also specify the wavelengths using
                the `x` keyword.

                If using a numpy array use `column_stack` to supply a single array with 
                a wavelength and coefficient values.

            emission: float, list, tuple or numpy.ndarray (optional)
                Specifies the emission line-shape per nanometer.
        
                If `None` will use a Gaussian centred at 600nm.
        
                If using a list of tuple you should also specify the wavelengths using
                the `x` keyword.
    
                If using a numpy array use `column_stack` to supply a single array with 
                a wavelength and coefficient values.

            x: list, tuple of numpy.ndarray (optional)
                Wavelength values in nanometers. Required when specifying a the
                `coefficient` with an list or tuple.
            quantum_yield: float (optional)
                The probability of re-emitting a ray.
            phase_function callable (optional)
                Specifies the direction of emitted rays.
            hist: Bool
                Specifies how the absorption and emission spectra are sampled. If `True`
                the values are treated as a histogram. If `False` the values are 
                linearly interpolated.
            name: str
                A user-defined identifier string
        """
        super(Luminophore, self).__init__(
            coefficient,
            x=x,
            quantum_yield=quantum_yield,
            phase_function=phase_function,
            hist=hist,
            name=name,
        )

        # Make emission spectrum distribution
        self._emission = emission
        if emission is None:
            self._ems_dist = Distribution.from_functions(
                x, [lambda x: gaussian(x, 1.0, 600.0, 40.0)], hist=hist)
        elif isinstance(emission, np.ndarray):
            self._ems_dist = Distribution(x=emission[:, 0],
                                          y=emission[:, 1],
                                          hist=hist)
        elif isinstance(emission, (tuple, list)):
            if x is None:
                raise ValueError("Requires `x`.")
            self._ems_dist = Distribution.from_functions(x,
                                                         emission,
                                                         hist=hist)
        else:
            raise ValueError("Luminophore `emission` arg has wrong type.")
Ejemplo n.º 7
0
def test1():
    x = np.arange(400, 801, dtype=np.float)
    size = (l, w, d) = (4.8, 1.8, 0.250)  # cm-1
    lsc = LSC(size, wavelength_range=x)

    lsc.add_luminophore(
        "Fluro Red",
        np.column_stack((x, fluro_red.absorption(x) * 11.387815)),  # cm-1
        np.column_stack((x, fluro_red.emission(x))),
        quantum_yield=0.95,
    )

    lsc.add_absorber("PMMA", 0.02)  # cm-1

    def lamp_spectrum(x):
        """ Fit to an experimentally measured lamp spectrum with long wavelength filter.
        """
        def g(x, a, p, w):
            return a * np.exp(-(((p - x) / w)**2))

        a1 = 0.53025700136646192
        p1 = 512.91400020614333
        w1 = 93.491838802960473
        a2 = 0.63578999789955015
        p2 = 577.63100003089369
        w2 = 66.031706473985736
        return g(x, a1, p1, w1) + g(x, a2, p2, w2)

    lamp_dist = Distribution(x, lamp_spectrum(x))
    wavelength_callable = lambda: lamp_dist.sample(np.random.uniform())
    position_callable = lambda: rectangular_mask(l / 2, w / 2)
    lsc.add_light(
        "Oriel Lamp + Filter",
        (0.0, 0.0, 0.5 * d + 0.01),  # put close to top surface
        rotation=(np.radians(180), (1, 0,
                                    0)),  # normal and into the top surface
        wavelength=wavelength_callable,  # wavelength delegate callable
        position=position_callable,  # uniform surface illumination
    )

    lsc.show()
    throw = 2500
    lsc.simulate(throw, emit_method="redshift")
    edge = lsc.spectrum(facets={"left", "right", "near", "far"}, source="all")
    escape = lsc.spectrum(facets={"top", "bottom"}, source="all")
    lost = lsc.spectrum(source="all", events={"absorb"})

    import matplotlib.pyplot as plt

    plt.hist(edge, bins=np.linspace(400, 800, 10), label="edge")
    plt.hist(escape, bins=np.linspace(400, 800, 10), label="escape")
    plt.hist(lost, bins=np.linspace(400, 800, 10), label="lost")
    plt.show()
    # number of lamp rays hitting the top surface
    incident = lsc.spectrum(source={"Oriel Lamp + Filter"},
                            kind="first",
                            facets={"top"})
    hitting = len(incident)
    counts = {"edge": len(edge), "escape": len(escape), "lost": len(lost)}
    fractions = {
        "edge": counts["edge"] / hitting,
        "escape": counts["escape"] / hitting,
        "lost": counts["lost"] / hitting,
    }
    print(counts, "sum", np.sum(list(counts.values())))
    print(fractions, "sum", np.sum(list(fractions.values())))
Ejemplo n.º 8
0
    def __init__(self,
                 coefficient,
                 x=None,
                 quantum_yield=1.0,
                 phase_function=None,
                 hist=False,
                 name="Scatterer"):
        """ coefficient: float, list, tuple or numpy.ndarray
                Specifies the scattering coefficient per unit length. Constant values
                can be supplied or a spectrum per nanometer per unit length. 
                
                If using a list of tuple you should also specify the wavelengths using
                the `x` keyword::
                    
                    x = numpy.linspace(600, 800)  # nanometer values
                    coefficient = list(numpy.ones(x.shape) * 1.5) # per nm per unit length
                    Scatterer(
                        coefficient,
                        x=x
                    )
            
                If using a numpy array use `column_stack` to supply a single array with 
                a wavelength and coefficient values::

                    Scatterer(
                        coefficient=numpy.column_stack((x, y))
                    )
            x: list, tuple of numpy.ndarray (optional)
                Wavelength values in nanometers. Required when specifying a the
                `coefficient` with an list or tuple.
            quantum_yield: float (optional)
                Default value is 1.0. To include non-radiative scattering use values
                between less than 1.0.
            phase_function callable (optional)
                Determines the direction of scattering. If None is supplied scattering
                is isotropic.
            hist: Bool
                Specifies how the coefficient spectrum is sampled. If `True` the values
                are treated as a histogram. If `False` the values are linearly 
                interpolated.
            name: str
                A user-defined identifier string
        """
        super(Scatterer, self).__init__(name=name)

        # Make absorption/scattering spectrum distribution
        self._coefficient = coefficient
        if coefficient is None:
            raise ValueError("Coefficient must be specified.")
        elif isinstance(coefficient, (float, np.float)):
            self._abs_dist = Distribution(x=None, y=coefficient, hist=hist)
        elif isinstance(coefficient, np.ndarray):
            self._abs_dist = Distribution(x=coefficient[:, 0],
                                          y=coefficient[:, 1],
                                          hist=hist)
        elif isinstance(coefficient, (list, tuple)):
            if x is None:
                raise ValueError("Requires `x`.")
            self._abs_dist = Distribution.from_functions(x,
                                                         coefficient,
                                                         hist=hist)

        self.quantum_yield = quantum_yield
        self.phase_function = phase_function if phase_function is not None else isotropic