Exemplo n.º 1
0
    def make_cell(self, x):

        #x[0]: total InGaP thickness
        #x[1]: total InGaAs thickness
        #x[2]: total SiGeSn thickness
        #x[3]: total Ge thickness

        #x[4]: InGaP n thickness
        #x[5]: InGaAs n thickness
        #x[6]: SiGeSn n thickness
        #x[7]: Ge n thickness

        e_charge = si('1eV')

        # materials
        SiGeSn = material('SiGeSn')

        GaAs = material('GaAs')
        InGaP = material('GaInP')
        Ge = material('Ge')
        MgF2 = material('MgF2')()
        Ta2O5 = material('410', nk_db=True)()
        AlInP = material("AlInP")

        window_material = AlInP(Al=0.52)

        GaInP_mobility_h = 0.03  #
        GaInP_lifetime_h = 1e-8
        GaInP_D_h = GaInP_mobility_h * kb * 300 / e_charge
        GaInP_L_h = np.sqrt(GaInP_D_h * GaInP_lifetime_h)
        GaInP_mobility_e = 0.015
        GaInP_lifetime_e = 1e-8
        GaInP_D_e = GaInP_mobility_e * kb * 300 / e_charge
        GaInP_L_e = np.sqrt(GaInP_D_e * GaInP_lifetime_e)

        top_cell_n_material = InGaP(In=0.5,
                                    Nd=si("2e18cm-3"),
                                    hole_diffusion_length=GaInP_L_h,
                                    relative_permittivity=11.75,
                                    hole_mobility=GaInP_mobility_h)
        top_cell_p_material = InGaP(In=0.5,
                                    Na=si("2e17cm-3"),
                                    electron_diffusion_length=GaInP_L_e,
                                    relative_permittivity=11.75,
                                    electron_mobility=GaInP_mobility_e)

        # MID CELL  - GaAs

        GaAs_mobility_h = 0.85  #
        GaAs_lifetime_h = 1e-8
        GaAs_D_h = GaAs_mobility_h * kb * 300 / e_charge
        GaAs_L_h = np.sqrt(GaAs_D_h * GaAs_lifetime_h)
        GaAs_mobility_e = 0.08
        GaAs_lifetime_e = 1e-8
        GaAs_D_e = GaAs_mobility_e * kb * 300 / e_charge
        GaAs_L_e = np.sqrt(GaAs_D_e * GaAs_lifetime_e)

        mid_cell_n_material = GaAs(Nd=si("1e18cm-3"),
                                   hole_diffusion_length=GaAs_L_h,
                                   relative_permittivity=13.1,
                                   hole_mobility=GaAs_mobility_h)
        mid_cell_p_material = GaAs(Na=si("1e17cm-3"),
                                   electron_diffusion_length=GaAs_L_e,
                                   relative_permittivity=13.1,
                                   electron_mobility=GaAs_mobility_e)

        SiGeSn.band_gap = si('0.77eV')  # from PL measurement
        SiGeSn_L_h = si('0.35um')
        SiGeSn_L_e = si('5um')
        SiGeSn_lifetime_e = 1e-6
        SiGeSn_lifetime_h = 1e-6
        SiGeSn_mobility_h = SiGeSn_L_h**2 * e_charge / (SiGeSn_lifetime_h *
                                                        kb * 300)
        SiGeSn_mobility_e = SiGeSn_L_e**2 * e_charge / (SiGeSn_lifetime_e *
                                                        kb * 300)

        pen_cell_n_material = SiGeSn(Nd=si("1e18cm-3"),
                                     hole_diffusion_length=SiGeSn_L_h,
                                     relative_permittivity=16,
                                     hole_mobility=SiGeSn_mobility_h)
        pen_cell_p_material = SiGeSn(Na=si("1e17cm-3"),
                                     electron_diffusion_length=SiGeSn_L_e,
                                     relative_permittivity=16,
                                     electron_mobility=SiGeSn_mobility_e)

        # Ge_mobility_h = 0.38 #
        Ge_lifetime_h = 1e-6
        # Ge_D_h = Ge_mobility_h*kb*300/e_charge
        # Ge_L_h = np.sqrt(Ge_D_h*Ge_lifetime_h)
        Ge_L_h = si('500nm')
        Ge_mobility_h = Ge_L_h**2 * e_charge / (Ge_lifetime_h * kb * 300)
        Ge_mobility_e = 0.18
        Ge_lifetime_e = 1e-6
        Ge_D_e = Ge_mobility_e * kb * 300 / e_charge
        Ge_L_e = np.sqrt(Ge_D_e * Ge_lifetime_e)

        bot_cell_n_material = Ge(Nd=si("2e18cm-3"),
                                 hole_diffusion_length=Ge_L_h,
                                 relative_permittivity=16,
                                 hole_mobility=Ge_mobility_h)
        bot_cell_p_material = Ge(Na=si("1e17cm-3"),
                                 electron_diffusion_length=Ge_L_e,
                                 relative_permittivity=16,
                                 electron_mobility=Ge_mobility_e)

        # And, finally, we put everything together, adding also the surface recombination velocities. We also add some shading
        # due to the metallisation of the cell = 8%, and indicate it has an area of 0.7x0.7 mm2 (converted to m2)
        solar_cell = SolarCell(
            [
                # Layer(si('110nm'), material = MgF2), Layer(si('55nm'), material = ZnS),
                Layer(si(self.ARC[0], 'nm'), material=MgF2),
                Layer(si(self.ARC[1], 'nm'), material=Ta2O5),
                Junction([
                    Layer(
                        si(25, 'nm'), material=window_material, role='window'),
                    Layer(si(x[4], 'nm'),
                          material=top_cell_n_material,
                          role='emitter'),
                    Layer(si(x[0] - x[4], 'nm'),
                          material=top_cell_p_material,
                          role='base'),
                ],
                         sn=1,
                         sp=1,
                         kind='DA'),
                Junction([
                    Layer(si(x[5], 'nm'),
                          material=mid_cell_n_material,
                          role='emitter'),
                    Layer(si(x[1] - x[5], 'nm'),
                          material=mid_cell_p_material,
                          role='base'),
                ],
                         sn=1,
                         sp=1,
                         kind='DA'),
                Junction([
                    Layer(si(x[6], 'nm'),
                          material=pen_cell_n_material,
                          role='emitter'),
                    Layer(si(x[2] - x[6], 'nm'),
                          material=pen_cell_p_material,
                          role='base'),
                ],
                         sn=1,
                         sp=1,
                         kind='DA'),
                Junction([
                    Layer(si(x[7], 'nm'),
                          material=bot_cell_n_material,
                          role='emitter'),
                    Layer(si(x[3] - x[7], 'nm'),
                          material=bot_cell_p_material,
                          role='base'),
                ],
                         sn=1,
                         sp=1,
                         kind='DA'),
            ],
            shading=0.0,
            substrate=bot_cell_n_material)

        return solar_cell
Exemplo n.º 2
0
def layer2(b_mat):
    return Layer(width2, b_mat, role2, wkt_box)
Exemplo n.º 3
0
        try:
            num = self.junction_indices[junction]
            self[num].__dict__.update(kwargs)
        except IndexError:
            print(
                'ERROR updating junction: The junction index must be {} or less.'
                .format(len(self.junction_indices)))

    def __call__(self, i):
        return self[self.junction_indices[i]]


if __name__ == '__main__':
    window = material('AlGaAs')(T=298, Na=1e24, Al=0.8)
    stack = [Layer(width=si("50nm"), material=window), default_GaAs(298)]

    # stack = [default_GaAs(298)]

    my_cell = SolarCell(layers=stack)
    #
    # my_cell.append_multiple([default_GaAs(298), default_GaAs(298), default_GaAs(298)])
    # print(my_cell)

    from solcore.poisson_drift_diffusion.DriftDiffusionUtilities import solve_pdd, default_photon_flux, \
        default_wavelengths
    import matplotlib.pyplot as plt

    solve_pdd(my_cell, 'QE', vfin=1.2, vstep=0.05, light=True)
    QE = my_cell(0).qe
Exemplo n.º 4
0
    return result_band_edge, bands


if __name__ == "__main__":
    from solcore import si, material
    from solcore.structure import Layer, Structure
    import matplotlib.pyplot as plt
    import numpy as np

    bulk = material("GaAs")(T=293)
    barrier = material("GaAsP")(T=293, P=0.1)

    bulk.strained = False
    barrier.strained = True

    top_layer = Layer(width=si("30nm"), material=bulk)
    inter = Layer(width=si("3nm"), material=bulk)
    barrier_layer = Layer(width=si("15nm"), material=barrier)
    bottom_layer = top_layer

    E = np.linspace(1.15, 1.5, 300) * q
    alfas = np.zeros((len(E), 6))

    alfas[:, 0] = E / q

    alpha_params = {
        "well_width": si("7.2nm"),
        "theta": 0,
        "eps": 12.9 * vacuum_permittivity,
        "espace": E,
        "hwhm": si("6meV"),
def initialise_S(stack, size, orders):
    S = S4.New(((size[0], 0), (0, size[1])), orders)

    geom_list = [layer.geometry for layer in stack]
    geom_list.insert(0, {})  # incidence medium
    geom_list.append({})  # transmission medium

    ## Materials for the shapes need to be defined before you can do .SetRegion
    shape_mats = necessary_materials(geom_list)
    Layers = []
    for x in shape_mats:
        Layers.append(Layer(0, x))

    shape_mats_OS = OptiStack(Layers)

    for i1 in range(len(shape_mats)
                    ):  # create the materials needed for all the shapes in S4
        S.SetMaterial('shape_mat_' + str(i1 + 1), 1)

    ## Make the layers
    stack_OS = OptiStack(stack)
    widths = stack_OS.get_widths()

    for i1 in range(
            len(widths)
    ):  # create 'dummy' materials for base layers including incidence and transmission media
        S.SetMaterial(
            'layer_' + str(i1 + 1), 1
        )  # This is not strictly necessary but it means S.SetExcitationPlanewave
        # can be done outside the wavelength loop in calculate_rat_rcwa
    for i1 in range(len(widths)):  # set base layers
        layer_name = 'layer_' + str(i1 + 1)
        if widths[i1] == float('Inf'):
            S.AddLayer(
                layer_name, 0, layer_name
            )  # Solcore4 has incidence and transmission media widths set to Inf;
            # in S4 they have zero width
        else:
            S.AddLayer(layer_name, widths[i1],
                       layer_name)  # keep base unit m, not nm

        geometry = geom_list[i1]

        if bool(geometry):
            for shape in geometry:
                mat_name = 'shape_mat_' + str(
                    shape_mats.index(shape['mat']) + 1)
                if shape['type'] == 'circle':
                    S.SetRegionCircle(layer_name, mat_name, shape['center'],
                                      shape['radius'])
                elif shape['type'] == 'ellipse':
                    S.SetRegionEllipse(layer_name, mat_name, shape['center'],
                                       shape['angle'], shape['halfwidths'])
                elif shape['type'] == 'rectangle':
                    S.SetRegionRectangle(layer_name, mat_name, shape['center'],
                                         shape['angle'], shape['halfwidths'])
                elif shape['type'] == 'polygon':
                    S.SetRegionPolygon(layer_name, mat_name, shape['center'],
                                       shape['angle'], shape['vertices'])

    return S, stack_OS, shape_mats_OS
Exemplo n.º 6
0
    def test_43_TMM_absorption_profile(self):
        GaAs = material('GaAs')(T=300)

        my_structure = Structure([
            Layer(si(3000, 'nm'), material=GaAs),
            Layer(si(300, 'um'), material=GaAs),
        ])

        out = calculate_absorption_profile(my_structure,
                                           np.array([800]),
                                           z_limit=3000,
                                           steps_size=20)

        data = (0.00093920198054733134, 0.00091329190431268755,
                0.00088809661793623094, 0.00086359640227330484,
                0.00083977208217782804, 0.00081660501149482764,
                0.0007940770584669893, 0.00077217059154379222,
                0.00075086846558214263, 0.00073015400842769127,
                0.00071001100786633451, 0.00069042369893569059,
                0.00067137675158661923, 0.00065285525868512457,
                0.00063484472434525627, 0.00061733105258387328,
                0.00060030053628839001, 0.00058373984648887986,
                0.00056763602192612503, 0.00055197645890746013,
                0.00053674890144246557, 0.0005219414316507909,
                0.00050754246043459913, 0.00049354071840833585,
                0.00047992524707871981, 0.00046668539026805409,
                0.0004538107857741483, 0.00044129135726031623,
                0.00042911730636911071, 0.00041727910505361793,
                0.00040576748812031177, 0.00039457344597762961,
                0.00038368821758459675, 0.00037310328359397839,
                0.00036281035968459497, 0.00035280139007758007,
                0.00034306854123150837, 0.00033360419571145685,
                0.00032440094622720458, 0.00031545158983589954,
                0.00030674912230466134, 0.00029828673262870248,
                0.00029005779770068137, 0.00028205587712711315,
                0.00027427470818778237, 0.00026670820093421067,
                0.00025935043342334711, 0.00025219564708274435,
                0.00024523824220360293, 0.00023847277355814448,
                0.00023189394613789383, 0.00022549661100952902,
                0.0002192757612850577, 0.00021322652820316562,
                0.00020734417731867015, 0.00020162410479709653,
                0.00019606183381147725, 0.00019065301103855347,
                0.0001853934032516379, 0.00018027889400747007,
                0.00017530548042447405, 0.00017046927004989423,
                0.00016576647781335848, 0.00016119342306448588,
                0.00015674652669221659, 0.00015242230832361372,
                0.00014821738359994165, 0.00014412846152789071,
                0.00014015234190387394, 0.00013628591280938143,
                0.00013252614817542982, 0.0001288701054142039,
                0.00012531492311603331, 0.00012185781880990432,
                0.00011849608678575335, 0.00011522709597683633,
                0.00011204828790051968, 0.00010895717465587773,
                0.00010595133697653208, 0.00010302842233720751,
                0.00010018614311252307, 9.7422274786577231e-05,
                9.4734654211925496e-05, 9.2121177916588886e-05,
                8.9579800457766819e-05, 8.7108532820967001e-05,
                8.470544086329888e-05, 8.2368643799712795e-05,
                8.009631273099949e-05, 7.7886669212397987e-05,
                7.573798386169243e-05, 7.3648575005706959e-05,
                7.1616807364140996e-05, 6.9641090769713272e-05,
                6.7719878923614451e-05, 6.5851668185292527e-05,
                6.4034996395625842e-05, 6.2268441732560816e-05,
                6.0550621598319883e-05, 5.8880191537308663e-05,
                5.7255844183874585e-05, 5.5676308239094561e-05,
                5.41403474757902e-05, 5.2646759770991723e-05,
                5.1194376165094236e-05, 4.9782059946968693e-05,
                4.8408705764312587e-05, 4.7073238758543685e-05,
                4.5774613723559514e-05, 4.4511814287704784e-05,
                4.3283852118305772e-05, 4.2089766148149713e-05,
                4.0928621823303459e-05, 3.9799510371682887e-05,
                3.8701548091800482e-05, 3.7633875661134488e-05,
                3.6595657463578247e-05, 3.5586080935443529e-05,
                3.4604355929505788e-05, 3.3649714096593824e-05,
                3.2721408284239568e-05, 3.1818711951917646e-05,
                3.0940918602416916e-05, 3.0087341228898868e-05,
                2.9257311777210295e-05, 2.8450180623029266e-05,
                2.7665316063435288e-05, 2.6902103822505617e-05,
                2.6159946570550893e-05, 2.5438263456613905e-05,
                2.4736489653865175e-05, 2.4054075917540213e-05,
                2.3390488155071715e-05, 2.2745207008081107e-05,
                2.211772744590139e-05, 2.1507558370314028e-05,
                2.0914222231189692e-05, 2.0337254652732693e-05,
                1.9776204070036316e-05, 1.9230631375664536e-05,
                1.8700109575983667e-05, 1.8184223456974879e-05,
                1.7682569259266036e-05, 1.7194754362128619e-05,
                1.6720396976192213e-05, 1.6259125844636267e-05,
                1.5810579952625165e-05, 1.5374408244759177e-05,
                1.4950269350320186e-05, 1.4537831316097222e-05)

        for i in range(len(out['absorption'][0])):
            self.assertAlmostEqual(data[i], out['absorption'][0][i])
Exemplo n.º 7
0
Air = material('Air')()

# materials with constant n, zero k
x = 1000

d_vectors = ((x, 0), (0, x))
area_fill_factor = 0.36
hw = np.sqrt(area_fill_factor) * 500

front_materials = []
back_materials = [
    Layer(si('120nm'),
          Si,
          geometry=[{
              'type': 'rectangle',
              'mat': Air,
              'center': (x / 2, x / 2),
              'halfwidths': (hw, hw),
              'angle': 45
          }])
]

# whether pyramids are upright or inverted is relative to front incidence.
# so if the same etch is applied to both sides of a slab of silicon, one surface
# will have 'upright' pyramids and the other side will have 'not upright' (inverted)
# pyramids in the model

front_surf = Interface('TMM',
                       layers=front_materials,
                       name='planar_front',
                       coherent=True)
Exemplo n.º 8
0
    def GetEffectiveQW(self,
                       calculate_absorption=True,
                       wavelengths=None,
                       periodic=True,
                       filter_strength=0.0,
                       blur=None,
                       blurmode="left",
                       mode='kp8x8_bulk',
                       use_Adachi=False,
                       alpha_params=None):
        """ Considers the device as a QW and solves its properties, including the modification of the bandeges due to strain, the efective mases and the absorption coefficient. The output is a list of layers made with materials with the effective properties after considering all these effects in addition to the quantum confinement.

        :param device: The device structure
        :param calculate_absorption: If absorption must be calculated
        :param WLsteps: wavelengths in which to calculate the absorption (input for np.linspace function)
        :param wavelengths: An array with the waveengths
        :param periodic: If it has to be assumed that the structure is perdiodic
        :param filter_strength:
        :param blur:
        :param blurmode:
        :param mode:
        :param use_Adachi:
        :param alpha_params:
        :return: A dictionary with the output of the Schrodinger solver.
        """
        print('Solving QW properties...')

        self.solve(calculate_absorption=calculate_absorption,
                   wavelengths=wavelengths,
                   T=self.T,
                   periodic=periodic,
                   filter_strength=filter_strength,
                   blur=blur,
                   blurmode=blurmode,
                   mode=mode,
                   use_Adachi=use_Adachi,
                   alpha_params=alpha_params)

        for i in range(len(self)):
            self[i].material.band_gap = self[i].eff_band_gap
            self[i].material.electron_affinity = self[i].eff_electron_affinity
            self[i].material.ni = np.sqrt(
                self[i].material.Nc * self[i].material.Nv *
                np.exp(-self[i].eff_band_gap / (kb * self.T)))

        # Finally, we re-build a list of layers with the effective properties
        new_QW = []
        for i in range(len(self)):
            # We recover the composition and thickness
            layer_mat = self[i].material
            width = self[i].width

            # In the end, we convert the absorption coefficient in extinction coefficient
            kk = self[i].material.absorption * self.wl / 4 / np.pi
            layer_mat.k = interp1d(self.wl,
                                   kk,
                                   bounds_error=False,
                                   fill_value=(0, 0))

            # And the radiative recombination parameter
            inter = lambda E: 1.0 / layer_mat.ni**2 * 2 * pi / (
                h**3 * c**2) * layer_mat.n(1240e-9 / (
                    E / q))**2 * layer_mat.alphaE(E) * np.exp(-E / (kb * self.T
                                                                    )) * E**2
            Br = -np.trapz(np.nan_to_num(inter(1240e-9 / self.wl * q)),
                           1240e-9 / self.wl * q)
            layer_mat.radiative_recombination = Br

            # And add the layer to the list of layers
            new_QW.append(Layer(width=width, material=layer_mat))

        # As the QW might be actually a MQW, we repeat this as many times as needed
        new_QW = self.repeat * new_QW
        return new_QW
Exemplo n.º 9
0
def test_quantum_mechanics_schrodinger():
    """ Testing schrodinger equation solver
    """
    bulk = material("GaAs")(T=293)
    barrier = material("GaAsP")(T=293, P=0.1)

    bulk.strained = False
    barrier.strained = True

    top_layer = Layer(width=si("30nm"), material=bulk)
    inter = Layer(width=si("3nm"), material=bulk)
    barrier_layer = Layer(width=si("15nm"), material=barrier)
    bottom_layer = top_layer

    E = np.linspace(1.15, 1.5, 300) * q
    alfas = np.zeros((len(E), 6))

    alfas[:, 0] = E / q

    alpha_params = {
        "well_width": si("7.2nm"),
        "theta": 0,
        "eps": 12.9 * vacuum_permittivity,
        "espace": E,
        "hwhm": si("6meV"),
        "dimensionality": 0.16,
        "line_shape": "Gauss",
    }

    QW = material("InGaAs")(T=293, In=0.2)
    QW.strained = True
    well_layer = Layer(width=si("7.2nm"), material=QW)

    my_structure = Structure(
        [
            top_layer,
            barrier_layer,
            inter,
            well_layer,
            inter,
            barrier_layer,
            inter,
            bottom_layer,
        ],
        substrate=bulk,
    )

    band_edge, bands = QM.schrodinger(
        my_structure,
        quasiconfined=0,
        num_eigenvalues=20,
        alpha_params=alpha_params,
        calculate_absorption=True,
    )

    for key in band_edge["E"]:
        for i in range(len(band_edge["E"][key])):
            band_edge["E"][key][i] = solcore.asUnit(band_edge["E"][key][i],
                                                    "eV") * 1000
            band_edge["E"][key][i] = round(band_edge["E"][key][i])

    Ehh = np.all(np.equal(band_edge["E"]["Ehh"], my_energies["Ehh"]))
    Elh = np.all(np.equal(band_edge["E"]["Elh"], my_energies["Elh"]))
    Ee = np.all(np.equal(band_edge["E"]["Ee"], my_energies["Ee"]))

    idx = 100
    out = [band_edge["alpha"][0][idx] / q, band_edge["alpha"][1][idx]]

    # Test over the energies
    assert Ehh and Elh and Ee

    # Test over the absorption coefficent at a given energy
    for i, data in enumerate(out):
        assert out[i] == approx(my_absorption[i], rel=1e-4)
Exemplo n.º 10
0
def test_rcwa_polygon():
    import numpy as np

    from solcore import material, si
    from solcore.structure import Layer, Structure
    from solcore.absorption_calculator.rigorous_coupled_wave import calculate_rat_rcwa, \
        calculate_absorption_profile_rcwa

    T = 300
    Air = material("Air")(T=T)
    TiO2 = material("TiO2", sopra=True)(T=T)  # for the nanoparticles
    GaAs = material("GaAs")(T=T)
    th = 50

    NP_layer_square = Layer(
        si(th, "nm"),
        Air,
        geometry=[{
            "type": "rectangle",
            "mat": TiO2,
            "center": (200, 200),
            "halfwidths": [50, 50],
            "angle": 0
        }],
    )
    np_struct_square = Structure([NP_layer_square])

    NP_layer_polygon = Layer(
        si(th, "nm"),
        Air,
        geometry=[{
            "type": "polygon",
            "mat": TiO2,
            "center": (200, 200),
            "vertices": ((150, 150), (250, 150), (250, 250), (150, 250)),
            "angle": 0
        }],
    )
    np_struct_polygon = Structure([NP_layer_polygon])

    wl = np.linspace(300, 1000, 10)

    step_size = 2

    rat_np_sq = calculate_rat_rcwa(np_struct_square,
                                   size=((400, 0), (0, 400)),
                                   orders=10,
                                   wavelength=wl,
                                   substrate=GaAs,
                                   incidence=Air,
                                   pol=[1, 0])

    A_output_sq = rat_np_sq['A_pol']
    result_square = calculate_absorption_profile_rcwa(np_struct_square,
                                                      size=((400, 0), (0,
                                                                       400)),
                                                      orders=10,
                                                      wavelength=wl,
                                                      rat_output_A=A_output_sq,
                                                      parallel=True,
                                                      steps_size=step_size,
                                                      pol=[1, 0])

    rat_np_pol = calculate_rat_rcwa(np_struct_polygon,
                                    size=((400, 0), (0, 400)),
                                    orders=10,
                                    wavelength=wl,
                                    substrate=GaAs,
                                    incidence=Air,
                                    pol=[1, 0])

    A_output_pol = rat_np_pol['A_pol']
    result_polygon = calculate_absorption_profile_rcwa(
        np_struct_polygon,
        size=((400, 0), (0, 400)),
        orders=10,
        wavelength=wl,
        rat_output_A=A_output_pol,
        parallel=True,
        steps_size=step_size,
        pol=[1, 0])

    assert approx(A_output_sq == A_output_pol)

    assert approx(result_polygon["absorption"] == result_square["absorption"])
Exemplo n.º 11
0
options.I_thresh = 1e-10
options.lookuptable_angles = 200
options.parallel = True
options.c_azimuth = 0.05
options.theta_in = 80 * np.pi / 180
options.phi_in = 0

Si = material('Si')()
GaAs = material('GaAs')()
GaInP = material('GaInP')(In=0.5)
Ag = material('Ag')()
SiN = material('Si3N4')()
Air = material('Air')()

# stack based on doi:10.1038/s41563-018-0115-4
front_materials = [Layer(60e-9, SiN), Layer(50E-9, GaInP), Layer(50e-9, GaAs)]
back_materials = [Layer(100E-9, GaInP), Layer(70e-9, GaAs)]

# whether pyramids are upright or inverted is relative to front incidence.
# so if the same etch is applied to both sides of a slab of silicon, one surface
# will have 'upright' pyramids and the other side will have 'not upright' (inverted)
# pyramids in the model

front_surf = Interface('TMM',
                       layers=front_materials,
                       name='GaInP_GaAs',
                       coherent=True)
back_surf = Interface('TMM',
                      layers=back_materials,
                      name='Si_Ag',
                      coherent=True)
Exemplo n.º 12
0
def test_arbitrary_pol_rcwa():
    import numpy as np

    from solcore import material, si
    from solcore.structure import Layer, Structure
    from solcore.absorption_calculator.rigorous_coupled_wave import calculate_rat_rcwa, \
        calculate_absorption_profile_rcwa

    T = 300
    Air = material("Air")(T=T)
    TiO2 = material("TiO2", sopra=True)(T=T)  # for the nanoparticles
    GaAs = material("GaAs")(T=T)
    th = 50
    NP_layer = Layer(
        si(th, "nm"),
        Air,
        geometry=[{
            "type": "ellipse",
            "mat": TiO2,
            "center": (200, 200),
            "halfwidths": [100, 70],
            "angle": 40
        }],
    )
    np_struct = Structure([NP_layer])
    wl = np.linspace(300, 1000, 10)

    step_size = 2

    rat_np = calculate_rat_rcwa(np_struct,
                                size=((400, 0), (0, 400)),
                                orders=10,
                                wavelength=wl,
                                substrate=GaAs,
                                incidence=Air,
                                pol=[1, 0])

    A_output = rat_np['A_pol']
    result = calculate_absorption_profile_rcwa(np_struct,
                                               size=((400, 0), (0, 400)),
                                               orders=10,
                                               wavelength=wl,
                                               rat_output_A=A_output,
                                               parallel=True,
                                               steps_size=step_size,
                                               pol=[1, 0])

    rat_np_s = calculate_rat_rcwa(np_struct,
                                  size=((400, 0), (0, 400)),
                                  orders=10,
                                  wavelength=wl,
                                  substrate=GaAs,
                                  incidence=Air,
                                  pol='s')

    A_output_s = rat_np_s['A_pol']
    result_s = calculate_absorption_profile_rcwa(np_struct,
                                                 size=((400, 0), (0, 400)),
                                                 orders=10,
                                                 wavelength=wl,
                                                 rat_output_A=A_output_s,
                                                 parallel=True,
                                                 steps_size=step_size,
                                                 pol='s')

    assert approx(A_output == A_output_s)

    assert approx(result["absorption"] == result_s["absorption"])
Exemplo n.º 13
0
import solcore.poisson_drift_diffusion as PDD

import numpy as np
import matplotlib.pyplot as plt

T = 298
wl = np.linspace(350, 1050, 601) * 1e-9

# First, we create the materials of the QW
QWmat = material('InGaAs')(T=T, In=0.2, strained=True)
Bmat = material('GaAsP')(T=T, P=0.1, strained=True)
i_GaAs = material('GaAs')(T=T)

# The QW is 7 nm wide, with GaAs interlayers 2 nm thick at each side and GaAsP barriers 10 nm thick.
# The final device will have 30 of these QWs.
QW = PDD.QWunit([Layer(width=10e-9, material=Bmat, role="barrier"),
                 Layer(width=2e-9, material=i_GaAs, role="well"),
                 Layer(width=7e-9, material=QWmat, role="well"),
                 Layer(width=2e-9, material=i_GaAs, role="well"),
                 Layer(width=10e-9, material=Bmat, role="barrier")], T=T, repeat=30, substrate=i_GaAs)

# We solve the quantum properties of the QW, leaving the default values of all parameters
QW_list = QW.GetEffectiveQW(wavelengths=wl)

# Materials for the BOTTOM junction
window_bottom = material('GaInP')(T=T, Nd=5e24, In=0.49)
n_GaAs = material('GaAs')(T=T, Nd=1e24)
p_GaAs = material('GaAs')(T=T, Na=8e22)
bsf_bottom = material('GaInP')(T=T, Na=5e24, In=0.49)

# If you want to test the code without QWs, to make ti a bit faster, comment the line with QW_list
Exemplo n.º 14
0
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)
Exemplo n.º 15
0
wl = np.linspace(350, 1050, 601) * 1e-9

# First, we create the materials of the QW
QWmat = material('InGaAs')(T=T, In=0.2, strained=True)
Bmat = material('GaAsP')(T=T, P=0.1, strained=True)
i_GaAs = material('GaAs')(T=T)

# The QW is 7 nm wide, with GaAs interlayers 2 nm thick at each side and GaAsP barriers 10 nm thick.
# The final device will have 30 of these QWs.
QW = PDD.CreateDeviceStructure('QW',
                               T=T,
                               repeat=30,
                               substrate=i_GaAs,
                               layers=[
                                   Layer(width=10e-9,
                                         material=Bmat,
                                         role="barrier"),
                                   Layer(width=2e-9,
                                         material=i_GaAs,
                                         role="interlayer"),
                                   Layer(width=7e-9,
                                         material=QWmat,
                                         role="well"),
                                   Layer(width=2e-9,
                                         material=i_GaAs,
                                         role="interlayer"),
                                   Layer(width=10e-9,
                                         material=Bmat,
                                         role="barrier")
                               ])
Exemplo n.º 16
0
ITO_back = material('ITO_lowdoping')()
Perovskite = material('Perovskite_CsBr')()
Ag = material('Ag_Jiang')()
aSi_i = material('aSi_i')()
aSi_p = material('aSi_p')()
aSi_n = material('aSi_n')()
LiF = material('LiF')()
IZO = material('IZO')()
C60 = material('C60')()

# materials with constant n, zero k
Spiro = [12e-9, np.array([0,1]), np.array([1.65, 1.65]), np.array([0,0])]
SnO2 = [10e-9, np.array([0,1]), np.array([2, 2]), np.array([0,0])]

# stack based on doi:10.1038/s41563-018-0115-4
front_materials = [Layer(100e-9, MgF2), Layer(110e-9, IZO),
                   SnO2,
                   Layer(15e-9, C60),
                   Layer(1e-9, LiF),
                   Layer(440e-9, Perovskite),
                   Spiro,
                   Layer(6.5e-9, aSi_n), Layer(6.5e-9, aSi_i)]
back_materials = [Layer(6.5e-9, aSi_i), Layer(6.5e-9, aSi_p), Layer(240e-9, ITO_back)]

# whether pyramids are upright or inverted is relative to front incidence.
# so if the same etch is applied to both sides of a slab of silicon, one surface
# will have 'upright' pyramids and the other side will have 'not upright' (inverted)
# pyramids in the model

surf = regular_pyramids(elevation_angle=55, upright=True)
surf_back = regular_pyramids(elevation_angle=55, upright=False)
Exemplo n.º 17
0
# materials with constant n, zero k
x = 1000

front_materials = []
back_materials = []

# whether pyramids are upright or inverted is relative to front incidence.
# so if the same etch is applied to both sides of a slab of silicon, one surface
# will have 'upright' pyramids and the other side will have 'not upright' (inverted)
# pyramids in the model
surf = regular_pyramids(elevation_angle=55, upright=False)

front_surf = Interface('RT_TMM',
                       texture=surf,
                       layers=[Layer(si('0.1nm'), Air)],
                       name='inv_pyramids' + str(options['n_rays']))
back_surf = Interface('TMM',
                      layers=[],
                      name='planar_back' + str(options['n_rays']))

bulk_Si = BulkLayer(200e-6, Si, name='Si_bulk')  # bulk thickness in m

SC = Structure([front_surf, bulk_Si, back_surf],
               incidence=Air,
               transmission=Air)

process_structure(SC, options)

results = calculate_RAT(SC, options)
Exemplo n.º 18
0
import numpy as np
import matplotlib.pyplot as plt

T = 298
wl = np.linspace(350, 1050, 301) * 1e-9

# First, we create the materials of the QW
QWmat = material("InGaAs")(T=T, In=0.2, strained=True)
Bmat = material("GaAsP")(T=T, P=0.1, strained=True)
i_GaAs = material("GaAs")(T=T)

# The QW is 7 nm wide, with GaAs interlayers 2 nm thick at each side and GaAsP barriers
# 10 nm thick. The final device will have 30 of these QWs.
QW = PDD.QWunit(
    [
        Layer(width=10e-9, material=Bmat, role="barrier"),
        Layer(width=2e-9, material=i_GaAs, role="well"),
        Layer(width=7e-9, material=QWmat, role="well"),
        Layer(width=2e-9, material=i_GaAs, role="well"),
        Layer(width=10e-9, material=Bmat, role="barrier"),
    ],
    T=T,
    repeat=30,
    substrate=i_GaAs,
)

# We solve the quantum properties of the QW, leaving the default values of all
# parameters
QW_list = QW.GetEffectiveQW(wavelengths=wl)

# Materials for the BOTTOM junction
Exemplo n.º 19
0

if __name__ == "__main__":
    from solcore import si, material
    from solcore.structure import Layer
    import matplotlib.pyplot as plt

    bulk = material("GaAs")(T=293)
    QW = material("InGaAs")(T=293, In=0.147)
    barrier = material("GaAsP")(T=293, P=0.1)

    bulk.strained = False
    QW.strained = True
    barrier.strained = True

    top_layer = Layer(width=si("50nm"), material=bulk)
    well_layer = Layer(width=si("7.2nm"), material=QW)
    barrier_layer = Layer(width=si("29nm"), material=barrier)
    bottom_layer = top_layer

    print("Here is a ASC_examples structure with no materials:")

    test_structure = assemble_qw_structure(
        repeats=3,
        well=well_layer,
        bulk_l_top=top_layer,
        bulk_l_bottom=bottom_layer,
        barrier=barrier_layer,
    )

    test_structure.substrate = bulk
plt.xlabel("Wavelength (nm)")
plt.ylabel("k")
plt.show()

# Compare performance as a back mirror on a GaAs 'cell'

# Solid line: absorption in GaAs
# Dashed line: absorption in Ag

GaAs = material('GaAs')()

colors = ['b', 'r', 'k', 'm', 'y']

plt.figure()
for c, Ag_mat in enumerate([Ag_Joh, Ag_McP, Ag_Hag, Ag_Rak, Ag_Sol]):
    my_solar_cell = SolarCell([Layer(width=si('50nm'), material=GaAs)] +
                              [Layer(width=si('100nm'), material=Ag_mat)])
    solar_cell_solver(my_solar_cell, 'optics', opts)
    GaAs_positions = np.linspace(
        my_solar_cell[0].offset,
        my_solar_cell[0].offset + my_solar_cell[0].width, 1000)
    Ag_positions = np.linspace(
        my_solar_cell[1].offset,
        my_solar_cell[1].offset + my_solar_cell[1].width, 1000)
    GaAs_abs = np.trapz(my_solar_cell[0].diff_absorption(GaAs_positions),
                        GaAs_positions)
    Ag_abs = np.trapz(my_solar_cell[1].diff_absorption(Ag_positions),
                      Ag_positions)
    plt.plot(wl * 1e9,
             GaAs_abs,
             color=colors[c],
Exemplo n.º 21
0
            output['absorption'] = 0.5 * (data_s + data_p)

    return output


if __name__ == '__main__':
    import matplotlib.pyplot as plt
    from solcore import material, si
    from solcore.structure import Layer, Structure

    GaAs = material('GaAs')(T=300)
    InGaAs = material('InGaAs')(T=300, In=0.1)

    my_structure = Structure([
        Layer(si(3000, 'nm'), material=InGaAs),
        Layer(si(30, 'um'), material=GaAs),
    ])

    wavelength = np.linspace(450, 1100, 300)

    out = calculate_rat(my_structure,
                        wavelength,
                        coherent=True,
                        no_back_reflexion=False)
    # #
    # plt.plot(wavelength, out['R'], 'b', label='Reflexion')
    # plt.plot(wavelength, out['A'], 'r', label='Absorption')
    # plt.plot(wavelength, out['T'], 'g', label='Transmission')
    # plt.legend()
    # plt.show()
Exemplo n.º 22
0
        Air = material('Air')()

        # materials with constant n, zero k
        x = 1000

        front_materials = []
        back_materials = []

        # whether pyramids are upright or inverted is relative to front incidence.
        # so if the same etch is applied to both sides of a slab of silicon, one surface
        # will have 'upright' pyramids and the other side will have 'not upright' (inverted)
        # pyramids in the model
        surf = regular_pyramids(elevation_angle=55, upright=False)


        front_surf = Interface('RT_TMM', texture = surf, layers=[Layer(si('0.01nm'), Air)],
                               name = 'inv_pyramids' + str(options['nx']) + str(random_pos))
        back_surf = Interface('TMM', layers=[], name = 'planar_back' + str(options['n_rays']))


        bulk_Si = BulkLayer(201.8e-6, Si, name = 'Si_bulk') # bulk thickness in m

        SC = Structure([front_surf, bulk_Si, back_surf], incidence=Air, transmission=Air)

        process_structure(SC, options)

        results = calculate_RAT(SC, options)

        results_per_pass = results[1]
        R_per_pass = np.sum(results_per_pass['r'][0], 2)
        R_0 = R_per_pass[0]
Exemplo n.º 23
0
p_GaAs = material('GaAs')(T=T, Na=si('4e18cm-3'))  # for the GaAs cell emitter
n_GaAs = material('GaAs')(T=T, Nd=si('2e17cm-3'))  # for the GaAs cell base
AlAs, GaAs = material('AlAs')(T=T), material('GaAs')(T=T)  # for the DBR
SiO2 = material('SiO2', sopra=True)(T=T)  # for the spacer layer
TiO2 = material('TiO2', sopra=True)(T=T)  # for the nanoparticles

# some parameters for the QE solver
for mat in [n_GaAs, p_GaAs]:
    mat.hole_mobility, mat.electron_mobility, mat.permittivity = 3.4e-3, 5e-2, 9
    n_GaAs.hole_diffusion_length, p_GaAs.electron_diffusion_length = si(
        "500nm"), si("5um")

# Define the different parts of the structure we will use. For the GaAs junction, we use the depletion approximation
GaAs_junction = [
    Junction([
        Layer(width=si('100nm'), material=p_GaAs, role="emitter"),
        Layer(width=si('400nm'), material=n_GaAs, role="base")
    ],
             T=T,
             kind='DA')
]

# this creates 10 repetitions of the AlAs and GaAs layers, to make the DBR structure
DBR = 10 * [
    Layer(width=si("73nm"), material=AlAs),
    Layer(width=si("60nm"), material=GaAs)
]

# The layer with nanoparticles
NP_layer = [
    Layer(si('50nm'),
Exemplo n.º 24
0
options.theta_in = 0*np.pi/180
options.phi_in = 'all'
options.only_incidence_angle = False

Ge = material('Ge')()
GaAs = material('GaAs')()
GaInP = material('GaInP')(In=0.5)
Ag = material('Ag')()
SiN = material('Si3N4')()
Air = material('Air')()
Ta2O5 = material('410', nk_db=True)()
MgF2 = material('203', nk_db=True)()
SiGeSn = material('SiGeSn')()

# stack based on doi:10.1038/s41563-018-0115-4
front_materials = [Layer(120e-9, MgF2), Layer(74e-9, Ta2O5), Layer(464e-9, GaInP), Layer(1682e-9, GaAs), Layer(1289e-9, SiGeSn)]
back_materials = [Layer(100E-9, SiN)]

# whether pyramids are upright or inverted is relative to front incidence.
# so if the same etch is applied to both sides of a slab of silicon, one surface
# will have 'upright' pyramids and the other side will have 'not upright' (inverted)
# pyramids in the model


## TMM, matrix framework

front_surf = Interface('TMM', layers=front_materials, name = 'GaInP_GaAs_SiGeSn_TMM',
                       coherent=True)
back_surf = Interface('TMM', layers=back_materials, name = 'SiN_Ag_TMM',
                      coherent=True)
Exemplo n.º 25
0
def layer1(qw_mat):
    return Layer(width1, qw_mat, role1, wkt_box, new_property='new_property')
Exemplo n.º 26
0
options.project_name = 'testing'

theta_intv, phi_intv, angle_vector = make_angle_vector(options['n_theta_bins'],
                                                       options['phi_symmetry'],
                                                       options['c_azimuth'])

surf = regular_pyramids(elevation_angle=0, upright=True)  # [texture, reverse]

GaAs = material('GaAs')()
Ge = material('Ge')()
Si = material('Si')()

Air = material('Air')()

layers = [Layer(500e-9, GaAs), Layer(200e-9, Ge)]
# optist = OptiStack(layers, False, Si, Air)
# lookup table:
size = ((500, 0), (0, 500))

results_front = RCWA(layers,
                     size,
                     orders,
                     options,
                     Air,
                     Si,
                     only_incidence_angle=False,
                     front_or_rear='front',
                     surf_name='testRCWA',
                     detail_layer=False,
                     save=True)
Exemplo n.º 27
0
def layer3(i_gaas):
    return Layer(width3, i_gaas, role3, wkt_box)
Exemplo n.º 28
0
all_materials.append(bot_cell_p_material)

# We add some other properties to the materials, assumed the same in all cases, for simplicity.
# If different, we should have added them above in the definition of the materials.
for mat in all_materials:
    mat.hole_mobility = 5e-2
    mat.electron_mobility = 3.4e-3
    mat.hole_mobility = 3.4e-3
    mat.electron_mobility = 5e-2
    mat.permittivity = 9

# And, finally, we put everything together, adding also the surface recombination velocities. We also add some shading
# due to the metallisation of the cell = 8%, and indicate it has an area of 0.7x0.7 mm2 (converted to m2)
solar_cell = SolarCell([
    Junction([
        Layer(si("25nm"), material=window_material, role='window'),
        Layer(si("100nm"), material=top_cell_n_material, role='emitter'),
        Layer(si("600nm"), material=top_cell_p_material, role='base'),
    ],
             sn=1,
             sp=1,
             kind='DA'),
    Junction([
        Layer(si("200nm"), material=mid_cell_n_material, role='emitter'),
        Layer(si("3000nm"), material=mid_cell_p_material, role='base'),
    ],
             sn=1,
             sp=1,
             kind='DA'),
    Junction([
        Layer(si("400nm"), material=bot_cell_n_material, role='emitter'),
Exemplo n.º 29
0
def run_solar_cell_model(task, model):
    """

    :param model:
    :return: a Solar cell object
    """

    # First, we take care of the options
    # ----------------------------------
    options = copy.copy(model['Global'])
    options.update(model['Electrical'])
    options.update(model['Optical'])
    T = float(options['T'])

    # We have to validate the options and check they have the correct format and type
    array_based_options = ['voltages', 'internal_voltages', 'position', 'wavelength']
    float_options = ['T', 'T_ambient']
    bool_options = ['mpp', 'light_iv', 'radiative_coupling']

    try:
        for p in options:
            # For the options that should be arrays, we create the arrays. The wavelength need ot be converted to meters
            if p in array_based_options:
                c = options[p].split(', ')
                ini = float(c[0])
                end = float(c[1])
                num = int(c[2])
                options[p] = np.linspace(ini, end, num) * 1e-9 ** (p == 'wavelength')

            # For the options that need to be floats
            elif p in float_options:
                options[p] = float(options[p])

            elif p in bool_options:
                options[p] = options[p].lower() in ['true', 'yes', 't', 1]

    except Exception as err:
        print('ERROR parsing the solver options: Option format not recognised')
        print(err)
        raise

    # Now we create the layers and junctions to the solar cell object
    # ---------------------------------------------------------------
    sc_data = model['Solar cell']
    all_layers = []
    all_materials = []

    for i in sc_data['structure']:
        current_element = sc_data[i[0]]

        # First the individual layers
        if 'Layer' in current_element['type']:
            layer_properties = {}
            width = current_element['width'] * 1e-9

            # Set the composition and get the properties, converting them to the correct units
            for key in current_element['options']:
                if key in ['element', 'x']:
                    layer_properties[current_element['options']['element']] = current_element['options']['x']
                else:
                    layer_properties[key] = current_element['options'][key] * conversion[key]

            all_materials.append(material(current_element['material'])(T=T, **layer_properties))

            all_layers.append(Layer(width, all_materials[-1], role=current_element['name']))
            continue

        # Unless it is an individual layer, we have junctions
        properties = {}
        for p in properties_junctions[current_element['type']]:
            properties[p] = default_junction_properties[p]

        properties.update(**current_element['options'])
        kind = current_element['type'].split('-')[-1]
        if 'TJ' in current_element['type']:
            new_junction = TunnelJunction(name=current_element['name'], kind=kind, T=T, **properties)
        else:
            new_junction = Junction(name=current_element['name'], kind=kind, T=T, **properties)

        # Now we add the layers, if any
        for l in i[1:]:
            current_child = sc_data[l]

            width = current_child['width'] * 1e-9
            layer_properties = {}

            # Set the composition and get the properties, converting them to the correct units
            for key in current_child['options']:
                if key in ['element', 'x']:
                    layer_properties[current_child['options']['element']] = current_child['options']['x']
                else:
                    layer_properties[key] = current_child['options'][key] * conversion[key]

            all_materials.append(material(current_child['material'])(T=T, **layer_properties))
            new_junction.append(Layer(width, all_materials[-1], role=current_child['name']))

        all_layers.append(new_junction)

    # Now we have to create the solar cell
    # ------------------------------------
    reflectivity = create_reflectivity(sc_data['reflectivity']) if sc_data['reflectivity'] != '' else None

    try:
        substrate = material(sc_data['substrate'])(T=T, **{sc_data['element']: sc_data['composition']})
    except KeyError:
        substrate = material(sc_data['substrate'])(T=T)

    sc = SolarCell(layers=all_layers, name=sc_data['name'], substrate=substrate, T=T, cell_area=sc_data['size'],
                   shading=sc_data['shading'], R_series=sc_data['r_series'], reflectivity=reflectivity)

    # With all said and done, we can run the solver
    # ---------------------------------------------
    solar_cell_solver(sc, task, user_options=options)
    print('Done!')

    return sc
Exemplo n.º 30
0
all_materials.append(bot_buffer_material)
all_materials.append(bot_nucleation_material)
all_materials.append(bot_cell_n_material)
all_materials.append(bot_cell_p_material)


# We add some other properties to the materials, assumed the same in all cases, for simplicity.
# If different, we should have added them above in the definition of the materials.

for mat in all_materials:

    mat.hole_mobility = 3.4e-3
    mat.electron_mobility = 5e-2


ARC = [Layer(si('80nm'), material = ARC1), Layer(si('33nm'), material = ARC2)]

top_junction = [Junction([Layer(si("18nm"), material=top_window_material, role='window'),
                  Layer(si("100nm"), material=top_cell_n_material, role='emitter'),
                  Layer(si("891.248nm"), material=top_cell_p_material, role='base'),
                  Layer(si("111.445nm"), material = top_cell_TJ_material, role = 'TJ')
                 ], sn=1, sp=1, kind='DA')]
middle_junction = [Junction([Layer(si("18nm"), material=mid_window_material, role='window'),
                  Layer(si("100nm"), material=mid_cell_n_material, role='emitter'),
                  Layer(si("1632.091nm"), material=mid_cell_p_material, role='base'),
                  Layer(si("10nm"), material = mid_BSF_material, role = 'BSF'),
                  Layer(si("91.084nm"), material=mid_cell_TJ_material, role='TJ')
                 ], sn=1, sp=1, kind='DA')]
DBRa = 16 * [Layer(width=si("62.638nm"), material=DBR1), Layer(width=si("71.980nm"), material=DBR2)]
DBRb = 16 * [Layer(width=si("68.919nm"), material=DBR1), Layer(width=si("78.725nm"), material=DBR2)]
DBRc = 16 * [Layer(width=si("75.838nm"), material=DBR1), Layer(width=si("86.805nm"), material=DBR2)]