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])
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 ])
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)
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]))
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
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)
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
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)])
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])
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)
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)
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", )
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)])
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)
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
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])
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]
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]
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]
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
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'),
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])])