コード例 #1
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])
コード例 #2
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)
コード例 #3
0
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]))
コード例 #4
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)
コード例 #5
0
ファイル: transfer_matrix.py プロジェクト: kudoshiji/solcore5
    def get_indices(self, wl):
        """ Returns the complex refractive index of the stack.

        :param wl: Wavelength of the light in nm.
        :return: A list with the complex refractive index of each layer, including the semi-infinite front and back
        layers and, opionally, the back absorbing layer used to suppress back surface relfexion.
        """

        out = []
        wl_m = solcore.si(wl, 'nm')

        if hasattr(wl, 'size'):
            n0 = np.ones_like(wl, dtype=complex)
        else:
            n0 = 1

        for i in range(self.num_layers):
            out.append(self.n_data[i](wl_m) + self.k_data[i](wl_m) * 1.0j)

        if self.no_back_reflexion:
            return [n0] + out + [
                self.n_data[-1](wl_m) + self._k_absorbing(wl_m) * 1.0j, n0
            ]
        else:
            return [n0] + out + [n0]
コード例 #6
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_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])])
コード例 #7
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
コード例 #8
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)
コード例 #9
0
ファイル: solar_cell.py プロジェクト: ylhe92/solcore5
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
コード例 #10
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
コード例 #11
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)])
コード例 #12
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])
コード例 #13
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)
コード例 #14
0
ファイル: test_pdd.py プロジェクト: spencercase/solcore5
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
コード例 #15
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])
コード例 #16
0
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)
コード例 #17
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",
    )
コード例 #18
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)])
コード例 #19
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
コード例 #20
0
ファイル: transfer_matrix.py プロジェクト: ylhe92/solcore5
    def _add_raw_nk_layer(self, layer):
        """ Adds a layer to the end (bottom) of the stack. The layer must be defined as a list containing the layer
        thickness in nm, the wavelength, the n and the k data as array-like objects.

        :param layer: The new layer to add as [thickness, wavelength, n, k]
        :return: None
        """
        # We make sure that the wavelengths are increasing, revering the arrays otherwise.
        if layer[1][0] > layer[1][-1]:
            layer[1] = layer[1][::-1]
            layer[2] = layer[2][::-1]
            layer[3] = layer[3][::-1]

        self.widths.append(layer[0])

        if len(layer) >= 5:
            self.models.append(layer[4])
            c = solcore.si(layer[5][0], 'nm')
            w = solcore.si(layer[5][1], 'nm')
            d = layer[5][2]  # = 0 for increasing, =1 for decreasing

            def mix(x):

                out = 1 + np.exp(-(x - c) / w)
                out = d + (-1)**d * 1 / out

                return out

            n_data = np_cache(lambda x: self.models[-1].n_and_k(x) * mix(x) + (
                1 - mix(x)) * interp1d(x=solcore.si(layer[1], 'nm'),
                                       y=layer[2],
                                       fill_value=layer[2][-1])(x))
            k_data = np_cache(lambda x: interp1d(x=solcore.si(layer[1], 'nm'),
                                                 y=layer[3],
                                                 fill_value=layer[3][-1])(x))

            self.n_data.append(n_data)
            self.k_data.append(k_data)

        else:
            self.models.append([])
            self.n_data.append(
                np_cache(
                    interp1d(x=solcore.si(layer[1], 'nm'),
                             y=layer[2],
                             fill_value=layer[2][-1])))
            self.k_data.append(
                np_cache(
                    interp1d(x=solcore.si(layer[1], 'nm'),
                             y=layer[3],
                             fill_value=layer[3][-1])))
コード例 #21
0
ファイル: transfer_matrix.py プロジェクト: ylhe92/solcore5
    def get_indices(self, wl):
        """ Returns the complex refractive index of the stack.

        :param wl: Wavelength of the light in nm.
        :return: A list with the complex refractive index of each layer, including the semi-infinite front and back
        layers and, opionally, the back absorbing layer used to suppress back surface relfexion.
        """

        out = []
        wl_m = solcore.si(wl, 'nm')

        if hasattr(self, 'n_sub'):
            n1 = self.n_sub(wl_m) + self.k_sub(wl_m) * 1.0j
        else:
            if hasattr(wl, 'size'):
                n1 = np.ones_like(wl, dtype=complex)
            else:
                n1 = 1

        # incidence medium!
        if hasattr(self, 'n_sup'):
            n0 = self.n_sup(
                wl_m
            )  #+ self.k_sup(wl_m)*1.0j ignore complex part for now to avoid errors
        else:
            if hasattr(wl, 'size'):
                n0 = np.ones_like(wl, dtype=complex)
            else:
                n0 = 1

        for i in range(self.num_layers):
            out.append(self.n_data[i](wl_m) + self.k_data[i](wl_m) * 1.0j)

        # substrate irrelevant if no_back_reflection = True
        if self.no_back_reflection:
            return [n0] + out + [
                self.n_data[-1](wl_m) + self._k_absorbing(wl_m) * 1.0j, n1
            ]  # look at last entry in stack,
            # make high;y absorbing layer based on it.

        else:

            return [n0] + out + [n1]
コード例 #22
0
def absorptance_detailed_balance(junction):
    """ Calculates the absorptance of the junction in the detailed balanced case. If it has not been calculated before, provided as input, it uses a "top hat" absorptance with the absorption edge at Eg and magnitude A.

    Note that while the junction.absorptance represents the potential fraction of light that can be absorbed at a given energy, the junction.absorbed represents the actual fraction of input light that is absorbed. For detailed balanced calculations, these two are equivalent to the IQE and EQE respectively because carrier collection is perfect, but that will not be the case, in general.

    :param junction: Junction object of kind "DB"
    """
    try:
        if not hasattr(junction, 'absorptance'):
            wlg = si(1240 / junction.Eg, 'nm')
            A = min(junction.A, 1)

            def absorptance(wl):
                return A * (wl < wlg)

            junction.absorptance = absorptance

    except AttributeError as err:
        raise AttributeError(
            'ERROR calculating absorptance for the detailed balance Junction kind.\nJunction is missing one essential argument: {}'
            .format(err))
コード例 #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
ファイル: test_optics.py プロジェクト: ylhe92/solcore5
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)
コード例 #25
0
size = 5
nxy = 21

calc = False
options = {
    'wavelengths': np.arange(300, 1201, 20) * 1e-9,
    'theta': 0 * np.pi / 180,
    'phi': 0,
    'I_thresh': 1e-2,
    'nx': nxy,
    'ny': nxy,
    'parallel': True,
    'pol': 'u',
    'n_rays': 2 * nxy**2,
    'depth_spacing': si('1um'),
    'random_ray_position': False
}

if calc:

    flat_surf = planar_surface()
    triangle_surf = regular_pyramids(55, upright=True, size=size)
    options['avoid_edges'] = False
    rtstr = rt_structure(textures=[triangle_surf, flat_surf],
                         materials=[Si],
                         widths=[si('200um')],
                         incidence=Air,
                         transmission=Air)

    start = time()
コード例 #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, 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]
コード例 #27
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]
コード例 #28
0
ファイル: solar_cell.py プロジェクト: ylhe92/solcore5
        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
TiO2 = material('TiO2')
AlInP = material("AlInP")
GaInP = material("GaInP")
GaAs = material('GaAs')
Ge = material("Ge")
Al02Ga08As = material('AlGaAs')
Al08Ga02As = material('AlGaAs')

# TOP CELL - GaInP
ARC1 = Al2O3()
ARC2 = TiO2()

top_window_material = AlInP(Al=0.5)
top_cell_n_material = GaInP(In=0.51,
                            Nd=siUnits(2e18, "cm-3"),
                            hole_diffusion_length=si("300nm"))
top_cell_p_material = GaInP(In=0.51,
                            Na=siUnits(1.5e17, "cm-3"),
                            electron_diffusion_length=si("2um"))
top_cell_TJ_material = Al08Ga02As(Al=0.8)

for mat in [top_cell_n_material, top_cell_p_material]:
    mat.band_gap = material('GaInP')(In=0.51).band_gap
    mat.eff_mass_hh_z = material('GaInP')(In=0.51).eff_mass_hh_z
    mat.eff_mass_electron = material('GaInP')(In=0.51).eff_mass_electron
    mat.relative_permittivity = 11.75

all_materials.append(ARC1)
all_materials.append(ARC2)
all_materials.append(top_window_material)
all_materials.append(top_cell_n_material)
コード例 #30
0
from solcore import si
from solcore import material
from solcore.solar_cell import SolarCell, Layer, Junction
from solcore.solar_cell_solver import solar_cell_solver, default_options
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

T = 300
wavelengths_optics = np.linspace(300, 1200, 800) * 1e-9

Si = material("Si")
SiO2 = material("SiO2")()

n_material = Si(T=T,
                Nd=si(1e21, "cm-3"),
                hole_diffusion_length=si("50um"),
                electron_mobility=50e-4,
                relative_permittivity=11.68)
p_material = Si(T=T,
                Na=si(1e16, "cm-3"),
                electron_diffusion_length=si("150um"),
                hole_mobility=400e-4,
                relative_permittivity=11.68)

ARC_width = si("100nm")
n_material_width = si("500nm")
p_material_width = si("50um")

solar_cell = SolarCell([
    Layer(width=ARC_width, material=SiO2),