Пример #1
0
    def test_64_quantum_mechanics_schrodinger(self):
        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] +
            1 * [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
        self.assertTrue(Ehh and Elh and Ee)
        # Test over the absorption coefficent at a given energy
        for i, data in enumerate(out):
            self.assertAlmostEqual(out[i], my_absorption[i])
Пример #2
0
def test_TMM_ellipsometry():
    GaAs = material("GaAs")(T=300)

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

    wavelength = np.linspace(450, 1100, 300)
    idx = np.argmin(abs(wavelength - 800))

    angles = [60, 65, 70]
    out = calculate_ellipsometry(my_structure, wavelength, angle=angles)

    data = (
        22.2849089096,
        181.488417672,
        16.4604621886,
        182.277656469,
        9.10132195668,
        184.509752582,
    )

    for i in range(len(angles)):
        assert data[2 * i] == approx(out["psi"][idx, i])
        assert data[2 * i + 1] == approx(out["Delta"][idx, i])
def test_process_junction_pn():
    from solcore.analytic_solar_cells.depletion_approximation import identify_layers, identify_parameters
    from solcore import material
    from solcore.structure import Layer, Junction
    from solcore.state import State

    Na = np.power(10, np.random.uniform(22, 25))
    Nd = np.power(10, np.random.uniform(23, 26))

    options = State()
    options.T = np.random.uniform(250, 350)

    Lp = np.power(10, np.random.uniform(-9, -6))  # Diffusion length
    Ln = np.power(10, np.random.uniform(-9, -6))  # Diffusion length

    GaAs_n = material("GaAs")(Nd=Nd, hole_diffusion_length=Ln)
    GaAs_p = material("GaAs")(Na=Na, electron_diffusion_length=Lp)

    p_width = np.random.uniform(500, 1000)*1e-9
    n_width = np.random.uniform(3000, 5000)*1e-9

    test_junc = Junction([Layer(p_width, GaAs_p, role="emitter"), Layer(n_width, GaAs_n, role="base")])

    id_top, id_bottom, pRegion, nRegion, iRegion, pn_or_np = identify_layers(test_junc)
    xn, xp, xi, sn, sp, ln, lp, dn, dp, Nd_c, Na_c, ni, es = identify_parameters(test_junc, options.T, pRegion, nRegion, iRegion)

    ni_expect = GaAs_n.ni

    assert [id_top, id_bottom] == approx([0, 1])
    assert pn_or_np == 'pn'
    assert [xn, xp, xi, sn, sp, ln, lp, dn, dp, Nd_c, Na_c, ni, es] == approx([n_width, p_width, 0, 0, 0, Lp, Ln, GaAs_n.hole_mobility * kb * options.T / q,
                                    GaAs_p.electron_mobility * kb * options.T / q, Nd, Na, ni_expect, GaAs_n.permittivity])
def test_process_junction_set_in_junction():
    from solcore.analytic_solar_cells.depletion_approximation import identify_layers, identify_parameters
    from solcore import material
    from solcore.structure import Layer, Junction
    from solcore.state import State

    options = State()
    options.T = np.random.uniform(250, 350)

    Lp = np.power(10, np.random.uniform(-9, -6))  # Diffusion length
    Ln = np.power(10, np.random.uniform(-9, -6))  # Diffusion length

    sn = np.power(10, np.random.uniform(0, 3))
    sp = np.power(10, np.random.uniform(0, 3))

    se = np.random.uniform(1, 20) * vacuum_permittivity

    GaAs_n = material("GaAs")()
    GaAs_p = material("GaAs")()
    GaAs_i = material("GaAs")()

    p_width = np.random.uniform(500, 1000)
    n_width = np.random.uniform(3000, 5000)
    i_width = np.random.uniform(100, 300) * 1e-9

    mun = np.power(10, np.random.uniform(-5, 0))
    mup = np.power(10, np.random.uniform(-5, 0))

    Vbi = np.random.uniform(0, 3)

    test_junc = Junction([
        Layer(p_width, GaAs_p, role="emitter"),
        Layer(i_width, GaAs_i, role="intrinsic"),
        Layer(n_width, GaAs_n, role="base")
    ],
                         sn=sn,
                         sp=sp,
                         permittivity=se,
                         ln=Ln,
                         lp=Lp,
                         mup=mup,
                         mun=mun,
                         Vbi=Vbi)

    id_top, id_bottom, pRegion, nRegion, iRegion, pn_or_np = identify_layers(
        test_junc)
    xn, xp, xi, sn_c, sp_c, ln, lp, dn, dp, Nd_c, Na_c, ni, es = identify_parameters(
        test_junc, options.T, pRegion, nRegion, iRegion)

    ni_expect = GaAs_n.ni

    assert [id_top, id_bottom] == approx([0, 2])
    assert pn_or_np == 'pn'
    assert [xn, xp, xi, sn_c, sp_c, ln, lp, dn, dp, Nd_c, Na_c, ni,
            es] == approx([
                n_width, p_width, i_width, sn, sp, Ln, Lp,
                mun * kb * options.T / q, mup * kb * options.T / q, 1, 1,
                ni_expect, se
            ])
Пример #5
0
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)
Пример #6
0
def junction(nd_top, na_top, nd_bottom, na_bottom):
    from solcore.structure import Junction, Layer
    from solcore import si, material
    from solcore.solar_cell import SolarCell
    from solcore.constants import vacuum_permittivity
    from solcore.solar_cell_solver import prepare_solar_cell
    from solcore.optics import solve_beer_lambert

    Lp = np.power(10, np.random.uniform(-8, -6))
    Ln = np.power(10, np.random.uniform(-8, -6))

    AlInP = material("AlInP")
    InGaP = material("GaInP")
    window_material = AlInP(Al=0.52)
    top_cell_n_material = InGaP(
        In=0.48,
        Nd=nd_top,
        Na=na_top,
        hole_diffusion_length=Lp,
        electron_diffusion_length=Ln,
    )
    top_cell_p_material = InGaP(
        In=0.48,
        Nd=nd_bottom,
        Na=na_bottom,
        hole_diffusion_length=Lp,
        electron_diffusion_length=Ln,
    )

    rel_perm = np.random.uniform(1, 20)
    for mat in [top_cell_n_material, top_cell_p_material]:
        mat.permittivity = rel_perm * vacuum_permittivity

    n_width = np.random.uniform(500, 1000) * 1e-9
    p_width = np.random.uniform(3000, 5000) * 1e-9

    test_junc = SolarCell([
        Junction(
            [
                Layer(si("25nm"), material=window_material, role="window"),
                Layer(n_width, material=top_cell_n_material, role="emitter"),
                Layer(p_width, material=top_cell_p_material, role="base"),
            ],
            sn=1,
            sp=1,
            kind="DA",
        )
    ])

    options = da_options()
    options.light_source = da_light_source()
    prepare_solar_cell(test_junc, options)
    solve_beer_lambert(test_junc, options)

    return test_junc, options
def test_BL_correction():

    wl = np.linspace(800, 950, 4) * 1e-9

    GaAs = material("GaAs")()

    thick_cell = SolarCell([Layer(material=GaAs, width=si("20um"))])

    opts = State()
    opts.position = None
    prepare_solar_cell(thick_cell, opts)
    position = np.arange(0, thick_cell.width, 1e-9)
    opts.position = position
    opts.recalculate_absorption = True
    opts.no_back_reflexion = False

    opts.BL_correction = False
    opts.wavelength = wl
    solve_tmm(thick_cell, opts)

    no_corr = thick_cell.absorbed

    opts.BL_correction = True

    solve_tmm(thick_cell, opts)

    with_corr = thick_cell.absorbed

    assert with_corr == approx(
        np.array([6.71457872e-01, 6.75496354e-01, 2.09738887e-01, 0]))
    assert no_corr == approx(
        np.array([6.71457872e-01, 6.75496071e-01, 2.82306407e-01, 0]))
Пример #8
0
def test_calculate_absorption_profile_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": [70, 100],
            "angle": 30
        }],
    )
    np_struct = Structure([NP_layer])
    wl = np.linspace(300, 1000, 10)

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

    A_output = rat_np['A_pol']
    step_size = 2
    dist = np.arange(0, th, step_size)
    result = calculate_absorption_profile_rcwa(np_struct,
                                               size=((400, 0), (0, 400)),
                                               orders=10,
                                               wavelength=wl,
                                               rat_output_A=A_output,
                                               steps_size=step_size)

    parallel_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)

    assert sorted(list(result.keys())) == ["absorption", "position"]
    assert sorted(list(parallel_result.keys())) == ["absorption", "position"]

    assert len(result["position"]) == len(dist)
    assert len(parallel_result["position"]) == len(dist)

    assert result["absorption"] == approx(parallel_result["absorption"],
                                          abs=1e-5)
def test_TMM_absorption_profile():
    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_path = Path(__file__).parent / "data" / "absorption_profile.txt"
    data = tuple(np.loadtxt(data_path))

    assert all([d == approx(o) for d, o in zip(data, out["absorption"][0])])
    def evaluate(self, x):
        GaAs = material('GaAs_WVASE')()
        Air = material('Air')()

        InAlP = material('InAlP_WVASE')()
        InGaP = material('InGaP_WVASE')()

        Ag = material('Ag_Jiang')()

        # MgF2 = material('MgF2')()
        # Ta2O5 = material('410', nk_db=True)()
        SiN = material('SiN_SE')()
        # print('SiN thickness', x[2]*x[1], 'Ag th', (1-x[1])*x[2])

        grating1 = [Layer(si(x[2] * x[1], 'nm'), SiN)]

        grating2 = [
            Layer(si((1 - x[1]) * x[2], 'nm'),
                  SiN,
                  geometry=[{
                      'type': 'circle',
                      'mat': Ag,
                      'center': (0, 0),
                      'radius': x[3],
                      'angle': 0
                  }])
        ]

        solar_cell = SolarCell([
            Layer(material=InGaP, width=si('19nm')),
            Layer(material=GaAs, width=si(x[0], 'nm')),
            Layer(material=InAlP, width=si('18nm'))
        ] + grating1 + grating2,
                               substrate=Ag)

        S4_setup = rcwa_structure(solar_cell, self.size, self.orders,
                                  self.options, Air, Ag)

        RAT = S4_setup.calculate()
        EQE_sim = 0.9 * 100 * (RAT['A_layer'][:, 0] + RAT['A_layer'][:, 1])

        # least squares?
        residual = np.sum((EQE_sim - self.EQE_meas)**2)

        return residual
Пример #11
0
def test_substrate_presence_profile():
    wavelength = np.linspace(300, 800, 3) * 1e-9

    GaAs = material("GaAs")(T=300)

    my_structure = SolarCell([Layer(si(700, "nm"), material=GaAs)],
                             substrate=GaAs)

    solar_cell_solver(
        my_structure,
        "optics",
        user_options={
            "wavelength": wavelength,
            "optics_method": "TMM",
            "no_back_reflection": False,
        },
    )

    z_pos = np.linspace(0, my_structure.width, 10)

    profile_subs = my_structure[0].absorbed(z_pos)

    my_structure = SolarCell([Layer(si(700, "nm"), material=GaAs)])

    solar_cell_solver(
        my_structure,
        "optics",
        user_options={
            "wavelength": wavelength,
            "optics_method": "TMM",
            "no_back_reflection": False,
        },
    )

    profile_nosubs = my_structure[0].absorbed(z_pos)
    profile = np.vstack((profile_subs, profile_nosubs))

    data_path = Path(
        __file__).parent / "data" / "substrate_presence_profile.csv"
    expected = np.loadtxt(data_path, delimiter=",")

    assert profile.shape == expected.shape
    assert profile == approx(expected)
Пример #12
0
def default_GaAs(T):
    # We create the other materials we need for the device
    window = material('AlGaAs')(T=T, Na=5e24, Al=0.8)
    p_GaAs = material('GaAs')(T=T, Na=1e24)
    n_GaAs = material('GaAs')(T=T, Nd=8e22)
    bsf = material('GaAs')(T=T, Nd=2e24)

    output = Junction([
        Layer(width=si('30nm'), material=window, role="Window"),
        Layer(width=si('150nm'), material=p_GaAs, role="Emitter"),
        Layer(width=si('3000nm'), material=n_GaAs, role="Base"),
        Layer(width=si('200nm'), material=bsf, role="BSF")
    ],
                      sn=1e6,
                      sp=1e6,
                      T=T,
                      kind='PDD')

    return output
Пример #13
0
def test_substrate_presence_A():
    wavelength = np.linspace(300, 800, 3) * 1e-9

    GaAs = material("GaAs")(T=300)

    my_structure = SolarCell([Layer(si(700, "nm"), material=GaAs)],
                             substrate=GaAs)

    solar_cell_solver(
        my_structure,
        "optics",
        user_options={
            "wavelength": wavelength,
            "optics_method": "TMM",
            "no_back_reflexion": False,
        },
    )

    z_pos = np.linspace(0, my_structure.width, 10)

    A_subs = my_structure[0].layer_absorption

    my_structure = SolarCell([Layer(si(700, "nm"), material=GaAs)])

    solar_cell_solver(
        my_structure,
        "optics",
        user_options={
            "wavelength": wavelength,
            "optics_method": "TMM",
            "no_back_reflexion": False,
        },
    )

    A_nosubs = my_structure[0].layer_absorption

    A = np.vstack((A_subs, A_nosubs))

    A_data = np.array([[0.56610281, 0.62692985, 0.41923175],
                       [0.56610281, 0.62711355, 0.37837737]])

    assert all([d == approx(o) for d, o in zip(A, A_data)])
Пример #14
0
    def test_44_TMM_ellipsometry(self):
        GaAs = material('GaAs')(T=300)

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

        wavelength = np.linspace(450, 1100, 300)
        idx = np.argmin(abs(wavelength - 800))

        angles = [60, 65, 70]
        out = calculate_ellipsometry(my_structure, wavelength, angle=angles)

        data = (22.2849089096, 181.488417672, 16.4604621886, 182.277656469,
                9.10132195668, 184.509752582)

        for i in range(len(angles)):
            self.assertAlmostEqual(data[2 * i], out['psi'][idx, i])
            self.assertAlmostEqual(data[2 * i + 1], out['Delta'][idx, i])
Пример #15
0
def test_inc_coh_tmm():
    GaInP = material("GaInP")(In=0.5)
    GaAs = material("GaAs")()
    Ge = material("Ge")()

    optical_struct = SolarCell([
        Layer(material=GaInP, width=si("5000nm")),
        Layer(material=GaAs, width=si("200nm")),
        Layer(material=GaAs, width=si("5um")),
        Layer(material=Ge, width=si("50um")),
    ])

    wl = np.linspace(400, 1200, 5) * 1e-9

    options = State()
    options.wavelength = wl
    options.optics_method = "TMM"
    options.no_back_reflection = False
    options.BL_correction = True
    options.recalculate_absorption = True

    c_list = [
        ["c", "c", "c", "c"],
        ["c", "c", "c", "i"],
        ["c", "i", "i", "c"],
        ["i", "i", "i", "i"],
    ]

    results = []
    for i1, cl in enumerate(c_list):
        options.coherency_list = cl
        solar_cell_solver(optical_struct, "optics", options)
        results.append(optical_struct.absorbed)

    A_calc = np.stack(results)
    A_data = np.array(
        [[0.5742503, 0.67956899, 0.73481184, 0.725372, 0.76792856],
         [0.5742503, 0.67956899, 0.73481184, 0.725372, 0.76792856],
         [0.5742503, 0.67956899, 0.73474943, 0.70493469, 0.70361194],
         [0.5742503, 0.67956899, 0.70927724, 0.71509221, 0.71592772]])
    assert A_calc == approx(A_data)
Пример #16
0
def AlGaAs(T):
    # We create the other materials we need for the device
    window = material("AlGaAs")(T=T, Na=5e24, Al=0.8)
    p_AlGaAs = material("AlGaAs")(T=T, Na=1e24, Al=0.4)
    n_AlGaAs = material("AlGaAs")(T=T, Nd=8e22, Al=0.4)
    bsf = material("AlGaAs")(T=T, Nd=2e24, Al=0.6)

    output = Junction(
        [
            Layer(width=si("30nm"), material=window, role="Window"),
            Layer(width=si("150nm"), material=p_AlGaAs, role="Emitter"),
            Layer(width=si("1000nm"), material=n_AlGaAs, role="Base"),
            Layer(width=si("200nm"), material=bsf, role="BSF"),
        ],
        sn=1e6,
        sp=1e6,
        T=T,
        kind="PDD",
    )

    return output
def plot_R(obj, x, icol):

    cols = sns.cubehelix_palette(len(use_orders),
                                 start=.5,
                                 rot=-.9,
                                 reverse=True)
    GaAs = material('GaAs_WVASE')()
    Air = material('Air')()

    InAlP = material('InAlP_WVASE')()
    InGaP = material('InGaP_WVASE')()

    Ag = material('Ag_Jiang')()

    # MgF2 = material('MgF2')()
    # Ta2O5 = material('410', nk_db=True)()
    SiN = material('SiN_SE')()

    R_data = np.loadtxt('Talbot_precursor_R.csv', delimiter=',')

    grating1 = [Layer(si(x[2] * x[1], 'nm'), SiN)]

    grating2 = [
        Layer(si((1 - x[1]) * x[2], 'nm'),
              SiN,
              geometry=[{
                  'type': 'circle',
                  'mat': Ag,
                  'center': (0, 0),
                  'radius': x[3],
                  'angle': 0
              }])
    ]

    solar_cell = SolarCell([
        Layer(material=GaAs, width=si('25nm')),
        Layer(material=InGaP, width=si('19nm')),
        Layer(material=GaAs, width=si(x[0], 'nm')),
        Layer(material=InAlP, width=si('18nm'))
    ] + grating1 + grating2,
                           substrate=Ag)

    S4_setup = rcwa_structure(solar_cell, obj.size, obj.orders, obj.options,
                              Air, Ag)

    RAT = S4_setup.calculate()

    total_A = np.sum(RAT['A_layer'], axis=1)

    # plt.figure()

    plt.plot(S4_setup.wavelengths * 1e9,
             RAT['R'],
             label=str(obj.orders),
             color=cols[icol])

    return S4_setup.wavelengths * 1e9, interp1d(R_data[:, 0], R_data[:, 1])(
        S4_setup.wavelengths * 1e9)
Пример #18
0
def AlGaAs():
    from solcore import material
    from solcore.structure import Layer, Junction
    from solcore import si

    T = 298
    # We create the other materials we need for the device
    window = material("AlGaAs")(T=T, Na=5e24, Al=0.8)
    p_AlGaAs = material("AlGaAs")(T=T, Na=1e24, Al=0.4)
    n_AlGaAs = material("AlGaAs")(T=T, Nd=8e22, Al=0.4)
    bsf = material("AlGaAs")(T=T, Nd=2e24, Al=0.6)

    return Junction(
        [
            Layer(width=si("30nm"), material=window, role="Window"),
            Layer(width=si("150nm"), material=p_AlGaAs, role="Emitter"),
            Layer(width=si("1000nm"), material=n_AlGaAs, role="Base"),
            Layer(width=si("200nm"), material=bsf, role="BSF"),
        ],
        sn=1e6,
        sp=1e6,
        T=T,
        kind="PDD",
    )
Пример #19
0
def test_TMM_rat():
    GaAs = material("GaAs")(T=300)

    my_structure = Structure([Layer(si(3000, "nm"), material=GaAs)])

    wavelength = np.linspace(450, 1100, 300)
    idx = np.argmin(abs(wavelength - 800))

    out = calculate_rat(
        my_structure, wavelength, coherent=True, no_back_reflexion=False
    )
    out = (out["R"][idx], out["A"][idx], out["T"][idx])

    data = (0.33328918841743332, 0.65996607786373396, 0.0067447337188326914)

    assert all([d == approx(o) for d, o in zip(data, out)])
Пример #20
0
def prepare_test_cell():

    from solcore import material, si
    from solcore.structure import Junction, Layer, TunnelJunction
    from solcore.solar_cell import SolarCell

    GaAs = material("GaAs")()
    MgF2 = material("MgF2")()
    TiO2 = material("TiO2")()
    Ge = material("Ge")()

    widths = np.random.rand(9) * 200

    solar_cell = SolarCell([
        Layer(si(widths[0], "nm"), material=MgF2),
        Layer(si(widths[1], "nm"), material=TiO2),
        Junction(
            [
                Layer(si(widths[2], "nm"), material=GaAs, role="window"),
                Layer(si(widths[3], "nm"), material=GaAs, role="emitter"),
                Layer(si(widths[4], "nm"), material=GaAs, role="base"),
            ],
            kind="DA",
        ),
        TunnelJunction([
            Layer(si(widths[5], "nm"), material=GaAs),
            Layer(si(widths[6], "nm"), material=GaAs),
        ]),
        Junction(
            [
                Layer(si(widths[7], "nm"), material=Ge, role="emitter"),
                Layer(si(widths[8], "nm"), material=Ge, role="base"),
            ],
            kind="PDD",
        ),
    ])

    return solar_cell, widths
def test_identify_layers_exceptions():
    from solcore.analytic_solar_cells.depletion_approximation import identify_layers
    from solcore import material
    from solcore.structure import Layer, Junction

    Na = np.power(10, np.random.uniform(22, 25))
    Nd = np.power(10, np.random.uniform(22, 25))

    Lp = np.power(10, np.random.uniform(-9, -6))  # Diffusion length
    Ln = np.power(10, np.random.uniform(-9, -6))  # Diffusion length

    GaAs_n = material("GaAs")(Nd=Nd, hole_diffusion_length=Ln)
    GaAs_p = material("GaAs")(Na=Na, electron_diffusion_length=Lp)
    GaAs_i = material("GaAs")()
    Ge_n = material("Ge")(Nd=Nd, hole_diffusion_length=Ln)

    n_width = np.random.uniform(500, 1000) * 1e-9
    p_width = np.random.uniform(3000, 5000) * 1e-9
    i_width = np.random.uniform(300, 500) * 1e-9

    test_junc = Junction([
        Layer(n_width, GaAs_n, role="emitter"),
        Layer(p_width, GaAs_p, role="neither")
    ])

    with raises(RuntimeError):
        identify_layers(test_junc)

    test_junc = Junction([
        Layer(n_width, GaAs_n, role="emitter"),
        Layer(i_width, GaAs_i, role="intrinsic"),
        Layer(p_width, GaAs_p, role="nothing")
    ])

    with raises(RuntimeError):
        identify_layers(test_junc)

    test_junc = Junction([
        Layer(n_width, Ge_n, role="emitter"),
        Layer(p_width, GaAs_p, role="base")
    ])

    with raises(AssertionError):
        identify_layers(test_junc)
Пример #22
0
def assemble_qw_structure(repeats, well, bulk_l_top, bulk_l_bottom, barrier, well_interlayer=None,
                          structure_label="QW Structure", shift_wells=0):
    half_barrier = Layer(barrier.width / 2, barrier.material)
    qw_structure = Structure()
    # qw_structure.append(bulk, layer_label="bulk")
    qw_structure.append_multiple([bulk_l_top], layer_labels=["bulk"])
    qw_structure.append_multiple([half_barrier], layer_labels=["half barrier"])
    if well_interlayer:
        qw_structure.append_multiple([well_interlayer, well, well_interlayer, barrier], layer_labels=["interlayer",
                                                                                                      "well",
                                                                                                      "interlayer",
                                                                                                      "barrier"],
                                     repeats=repeats - 1)
        qw_structure.append_multiple([well_interlayer, well, well_interlayer, half_barrier, bulk_l_bottom],
                                     layer_labels=[
                                         "interlayer", "well", "interlayer", "half barrier", "bulk"])
    else:
        qw_structure.append_multiple([well, barrier], layer_labels=["well", "barrier"], repeats=repeats - 1)
        qw_structure.append_multiple([well, half_barrier, bulk_l_bottom], layer_labels=["well", "half barrier", "bulk"])

    return qw_structure
Пример #23
0
    def test_42_TMM_rat(self):
        GaAs = material('GaAs')(T=300)

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

        wavelength = np.linspace(450, 1100, 300)
        idx = np.argmin(abs(wavelength - 800))

        out = calculate_rat(my_structure,
                            wavelength,
                            coherent=True,
                            no_back_reflexion=False)
        out = (out['R'][idx], out['A'][idx], out['T'][idx])

        data = (0.33328918841743332, 0.65996607786373396,
                0.0067447337188326914)

        for i in range(3):
            self.assertAlmostEqual(data[i], out[i])
Пример #24
0
def test_calculate_rat_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

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

    NP_layer = Layer(
        si("50nm"),
        Air,
        geometry=[{
            "type": "circle",
            "mat": TiO2,
            "center": (200, 200),
            "radius": 50
        }],
    )
    np_struct = Structure([NP_layer])
    wl = np.linspace(300, 1000, 150)

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

    assert sorted(list(
        rat_np.keys())) == ["A", "A_per_layer", "A_pol", "R", "T"]
    for v in rat_np.values():
        assert v.shape[0] == len(wl)
d_vectors = ((x, 0), (0, x))
area_fill_factor = 0.36
hw = np.sqrt(area_fill_factor) * 500

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, size=5, upright=True)

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

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)

RAT = results[0]
results_per_pass = results[1]
Пример #26
0
d_vectors = ((x, 0),(0,x))
area_fill_factor = 0.36
hw = np.sqrt(area_fill_factor)*500


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('RCWA', layers=back_materials, name = 'crossed_grating_60', d_vectors=d_vectors, rcwa_orders=60)
#back_surf = Interface('TMM', layers=[], name = 'planar_back', coherent=True)

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)

RAT = results[0]
results_per_pass = results[1]
Пример #27
0
                                                       options['c_azimuth'])

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

group = RTgroup(textures=[surf])

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

Air = material('Air')()

#results_front = RT(group, Air, Si, 'test', options, 0, 'front', 0, False)

# lookup table:
layers = [Layer(500e-9, GaAs), Layer(200e-9, Ge)]

make_TMM_lookuptable(layers, Air, Si, 'test', options)

results_front = RT(group,
                   Air,
                   Si,
                   'test',
                   options,
                   1,
                   'front',
                   len(layers),
                   save=True)

full = results_front[0].todense()[n_wl - 1]
Пример #28
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
Пример #29
0
    mat.relative_permittivity = 16

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'),
Пример #30
0
def test_TMM_absorption_profile():
    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,
    )

    assert all([d == approx(o) for d, o in zip(data, out["absorption"][0])])