def plot(self, x):
        # x is a list with all the layer thicknesses, except for the Ge (which is kept as a thick substrate)

        # this does basically what evaluate() does, but plots the results
        SC = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, [x[2]] + self.InGaP,
              [x[3]] + self.GaAs, [x[4]] + self.SiGeSn, [300e3] + self.Ge]

        full_stack = OptiStack(SC, no_back_reflection=False)

        RAT = calculate_rat(full_stack,
                            self.wl,
                            no_back_reflection=False,
                            coherent=False,
                            coherency_list=['c', 'c', 'c', 'c', 'c', 'i'])

        A_InGaP = RAT['A_per_layer'][3]
        A_GaAs = RAT['A_per_layer'][4]
        A_SiGeSn = RAT['A_per_layer'][5]
        A_Ge = RAT['A_per_layer'][6]

        plt.figure()
        plt.plot(self.wl, A_InGaP, label='InGaP')
        plt.plot(self.wl, A_GaAs, label='A_GaAs')
        plt.plot(self.wl, A_SiGeSn, label='SiGeSn')
        plt.plot(self.wl, A_Ge, label='Ge')
        plt.plot(self.wl, RAT['T'], label='T')
        plt.plot(self.wl, RAT['R'], label='R')
        plt.legend()
        plt.xlabel('Wavelength (nm)')
        plt.show()
def test_tmm_rcwa_structure_comparison(pol, angle):
    import numpy as np
    from solcore import si, material
    from solcore.structure import Layer
    from solcore.solar_cell import SolarCell
    from solcore.optics.tmm import calculate_rat, OptiStack
    from solcore.optics.rcwa import calculate_rat_rcwa

    InGaP = material('GaInP')(In=0.5)
    GaAs = material('GaAs')()
    Ge = material('Ge')()
    Ag = material('Ag')()
    Air = material('Air')()

    Al2O3 = material('Al2O3')()

    wavelengths = np.linspace(250, 1900, 500)

    size = ((100, 0), (0, 100))

    ARC = [Layer(si('80nm'), Al2O3)]

    solar_cell = SolarCell(ARC + [
        Layer(material=InGaP, width=si('400nm')),
        Layer(material=GaAs, width=si('4000nm')),
        Layer(material=Ge, width=si('3000nm'))
    ],
                           substrate=Ag)

    solar_cell_OS = OptiStack(solar_cell,
                              no_back_reflection=False,
                              substrate=solar_cell.substrate)

    rcwa_result = calculate_rat_rcwa(solar_cell,
                                     size,
                                     2,
                                     wavelengths,
                                     Air,
                                     Ag,
                                     theta=angle,
                                     phi=angle,
                                     pol=pol,
                                     parallel=True)
    tmm_result = calculate_rat(solar_cell_OS,
                               wavelengths,
                               angle,
                               pol,
                               no_back_reflection=False)

    assert tmm_result['A_per_layer'][1:-1] == approx(
        rcwa_result['A_per_layer'].T)
    assert tmm_result['R'] == approx(rcwa_result['R'])
    assert tmm_result['T'] == approx(rcwa_result['T'])

    assert np.sum(tmm_result['A_per_layer'][1:-1].T,
                  1) + tmm_result['R'] + tmm_result['T'] == approx(1)
    assert np.sum(rcwa_result['A_per_layer'],
                  1) + rcwa_result['R'] + rcwa_result['T'] == approx(1)
Example #3
0
    def plot_weighted(self, x):
        # this does basically what evaluate() does, but plots the reflectivity weighted by the AM0 solar spectrum
        ARC = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, self.GaAs]

        full_stack = OptiStack(ARC, no_back_reflection=True)

        RAT = calculate_rat(full_stack, self.wl, no_back_reflection=True)
        spect_n = self.spectrum / np.max(self.spectrum)
        plt.figure()
        plt.plot(self.wl, RAT['R'] * spect_n)
        plt.xlabel('Wavelength (nm)')
        plt.ylabel('R weighted by AM0')
        plt.show()
Example #4
0
    def plot(self, x):
        # this does basically what evaluate() does, but plots the reflectivity

        ARC = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, self.GaAs]

        full_stack = OptiStack(ARC, no_back_reflection=True)

        RAT = calculate_rat(full_stack, self.wl, no_back_reflection=True)
        plt.figure()
        plt.plot(self.wl, RAT['R'])
        plt.xlabel('Wavelength (nm)')
        plt.ylabel('R')
        plt.show()
    def reflectance(self, x: Sequence[float]) -> float:
        """ Create a list with the format [thickness, wavelengths, n_data, k_data] for
        each layer.

        This is one of the acceptable formats in which OptiStack can take information
        (look at the Solcore documentation or at the OptiStack code for more info)
        We set no_back_reflection to True because we DO  NOT want to include reflection
        at the back surface (assume GaAs is infinitely thick)

        :param x: List with the thicknesses of the two layers in the ARC.
        :return: Array with the reflection at each wavelength
        """
        arc = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, self.GaAs]
        full_stack = OptiStack(arc, no_back_reflection=True)
        return calculate_rat(full_stack, self.wl, no_back_reflection=True)["R"]
Example #6
0
    def evaluate(self, x):

        # x[0] = MgF2 thickness (anti-reflection coating)
        # x[1] = Ta2O5 thickness (anti-reflection coating)
        # x[2]  = InGaP (top junction) thickness
        # x[3] = GaAs (second junction) thickness
        # x[4] = SiGeSn (third junction) thickness

        # keep the thickness of the bottom cell constant; from an optical point of view, this should be infinitely thick

        SC = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, [x[2]] + self.InGaP,
              [x[3]] + self.GaAs, [x[4]] + self.SiGeSn,
              [300e3] + self.Ge]  #, [x[5]] + self.Ge]

        # create the OptiStack
        full_stack = OptiStack(SC, no_back_reflection=False)

        # calculate reflection, transmission, and absorption in each layer. We are specifying that the last layer,
        # a very thick Ge substrate, should be treated incoherently, otherwise we would see very narrow, unphysical oscillations
        # in the R/A/T spectra.
        RAT = calculate_rat(full_stack,
                            self.wl,
                            no_back_reflection=False,
                            coherent=False,
                            coherency_list=['c', 'c', 'c', 'c', 'c', 'i'])

        # extract absorption per layer
        A_InGaP = RAT['A_per_layer'][3]
        A_GaAs = RAT['A_per_layer'][4]
        A_SiGeSn = RAT['A_per_layer'][5]
        A_Ge = RAT['A_per_layer'][6]

        ## calculate photo-generated currents using the AM1.5 G spectrum for each layer
        Jsc_InGaP = 0.1 * q * np.trapz(A_InGaP * self.spectr, self.wl)
        Jsc_GaAs = 0.1 * q * np.trapz(A_GaAs * self.spectr, self.wl)
        Jsc_SiGeSn = 0.1 * q * np.trapz(A_SiGeSn * self.spectr, self.wl)
        Jsc_Ge = 0.1 * q * np.trapz(A_Ge * self.spectr, self.wl)

        # find the limiting current by checking which junction has the lowest current. Then take the negative since
        # we need to minimize (not maximize)
        limiting_Jsc = -min([Jsc_InGaP, Jsc_GaAs, Jsc_SiGeSn, Jsc_Ge])

        return limiting_Jsc
Example #7
0
    def evaluate(self, x):
        # create a list of layers with the format [thickness, wavelengths, n_data, k_data] for each layer.
        # This is one of the acceptable formats in which OptiStack can take information (look at the Solcore documentation
        # or at the OptiStack code for more info

        ARC = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, self.GaAs]

        # create the OptiStack. We set no_back_reflection to True because we DO  NOT want to include reflection at the back surface
        # (assume GaAs is infinitely thick)

        full_stack = OptiStack(ARC, no_back_reflection=True)

        # calculate reflection, transmission, and absorption in each layer.

        RAT = calculate_rat(full_stack, self.wl, no_back_reflection=True)

        R_weighted = RAT['R'] * self.spectrum

        # 'evaluate' should return a single number. The DE algorithm tries to minimize this number.

        return sum(R_weighted)
    def evaluate(self, x):
        # create a list of layers with the format [thickness, wavelengths, n_data, k_data] for each layer.
        # This is one of the acceptable formats in which OptiStack can take information (look at the Solcore documentation
        # or at the OptiStack code for more info

        SC = [[x[0]] + self.MgF2, [x[1]] + self.Ta2O5, [x[2]] + self.InGaP,
              [x[3]] + self.GaAs, [x[4]] + self.SiGeSn,
              [300e3] + self.Ge]  #, [x[5]] + self.Ge]

        # create the OptiStack. We set no_back_reflection to False because we DO want to include reflection at the back surface
        # (thin-film interference due to reflection at the SiGeSn/Ge interface)
        full_stack = OptiStack(SC, no_back_reflection=False)

        # calculate reflection, transmission, and absorption in each layer. We are specifying that the last layer,
        # a very thick Ge substrate, should be treated incoherently, otherwise we would see very narrow, unphysical oscillations
        # in the R/A/T spectra.
        RAT = calculate_rat(full_stack,
                            self.wl,
                            no_back_reflection=False,
                            coherent=False,
                            coherency_list=['c', 'c', 'c', 'c', 'c', 'i'])

        # extract absorption per layer
        A_InGaP = RAT['A_per_layer'][3]
        A_GaAs = RAT['A_per_layer'][4]
        A_SiGeSn = RAT['A_per_layer'][5]
        A_Ge = RAT['A_per_layer'][6]

        ## calculate currents using the AM1.5 G spectrum for each layer
        Jsc_InGaP = 0.1 * q * np.trapz(A_InGaP * self.spectr, self.wl)
        Jsc_GaAs = 0.1 * q * np.trapz(A_GaAs * self.spectr, self.wl)
        Jsc_SiGeSn = 0.1 * q * np.trapz(A_SiGeSn * self.spectr, self.wl)
        Jsc_Ge = 0.1 * q * np.trapz(A_Ge * self.spectr, self.wl)

        # find the limiting current by checking which junction has the lowest current. Then take the negative since
        # we need to minimize (not maximize)
        limiting_Jsc = -min([Jsc_InGaP, Jsc_GaAs, Jsc_SiGeSn, Jsc_Ge])

        return limiting_Jsc
def test_tmm_rcwa_structure_profile_comparison(pol, angle):
    import numpy as np
    from solcore import si, material
    from solcore.structure import Layer
    from solcore.solar_cell import SolarCell
    from solcore.optics.tmm import calculate_rat, calculate_absorption_profile, OptiStack
    from solcore.optics.rcwa import calculate_rat_rcwa, calculate_absorption_profile_rcwa

    InGaP = material('GaInP')(In=0.5)
    GaAs = material('GaAs')()
    Ge = material('Ge')()
    Ag = material('Ag')()
    Air = material('Air')()

    wavelengths = np.linspace(250, 1900, 8)

    size = ((100, 0), (0, 100))

    solar_cell = SolarCell([
        Layer(material=InGaP, width=si('400.5nm')),
        Layer(material=GaAs, width=si('500nm')),
        Layer(material=Ge, width=si('1000nm'))
    ],
                           substrate=Ag)

    solar_cell_OS = OptiStack(solar_cell,
                              no_back_reflection=False,
                              substrate=solar_cell.substrate)

    rcwa_result = calculate_rat_rcwa(solar_cell,
                                     size,
                                     2,
                                     wavelengths,
                                     Air,
                                     Ag,
                                     theta=angle,
                                     phi=angle,
                                     pol=pol,
                                     parallel=True)
    tmm_result = calculate_rat(solar_cell_OS,
                               wavelengths,
                               angle,
                               pol,
                               no_back_reflection=False)

    tmm_profile = calculate_absorption_profile(solar_cell_OS,
                                               wavelengths,
                                               no_back_reflection=False,
                                               angle=angle,
                                               pol=pol,
                                               RAT_out=tmm_result,
                                               steps_size=2)

    rcwa_profile = calculate_absorption_profile_rcwa(
        solar_cell,
        size,
        2,
        wavelengths,
        rcwa_result['A_pol'],
        theta=angle,
        phi=angle,
        pol=pol,
        incidence=Air,
        substrate=solar_cell.substrate,
        parallel=True,
        steps_size=2)

    assert tmm_profile['position'] == approx(rcwa_profile['position'],
                                             abs=2e-6)
    assert tmm_profile['absorption'] == approx(rcwa_profile['absorption'],
                                               abs=2e-6)