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_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_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_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 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 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_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)
} # We are going to calculate the absorption coefficient of InGaAs QWs of fixed thickness but different compositions comp = [0.05, 0.1, 0.15, 0.2, 0.25] colors = plt.cm.jet(np.linspace(0, 1, len(comp))) plt.figure(figsize=(4, 4.5)) for j, i in enumerate(comp): # We create the QW material at the given composition QW = material("InGaAs")(T=293, In=i, strained=True) # And the layer well_layer = Layer(width=si("7.2nm"), material=QW) # The following lines create the QW structure, with different number of QWs and interlayers test_structure = Structure( [barrier_layer, inter, well_layer, inter, barrier_layer]) test_structure.substrate = bulk # Finally, the quantum properties are claculated here output = QM.schrodinger(test_structure, quasiconfined=0, num_eigenvalues=20, alpha_params=alpha_params, calculate_absorption=True) alfa = output[0]['alphaE'](E) plt.plot(1240 / (E / q), alfa / 100, label='{}%'.format(int(i * 100))) alfas[:, j + 1] = alfa / 100 plt.xlim(826, 1100)
import solcore.quantum_mechanics as QM # First we create the materials we need bulk = material("GaAs")(T=293, strained=False) barrier = material("GaAsP")(T=293, P=0.1, strained=True) # As well as some of the layers top_layer = Layer(width=si("30nm"), material=barrier) inter = Layer(width=si("3nm"), material=bulk) barrier_layer = Layer(width=si("5nm"), material=barrier) bottom_layer = top_layer # We create the QW material at the given composition QW = material("InGaAs")(T=293, In=0.15, strained=True) # And the layer well_layer = Layer(width=si("7.2nm"), material=QW) # The following lines create the QW structure, with different number of QWs and interlayers. Indicating the substrate # material with the keyword "substrate" is essential in order to calculate correctly the strain. # A single QW with interlayers test_structure_1 = Structure([top_layer, inter, well_layer, inter, bottom_layer], substrate=bulk) output_1 = QM.schrodinger(test_structure_1, quasiconfined=0, graphtype='potentials', num_eigenvalues=20, show=True) # 10 QWs without interlayers test_structure_2 = Structure([top_layer, barrier_layer] + 10 * [well_layer, barrier_layer] + [bottom_layer], substrate=bulk) output_2 = QM.schrodinger(test_structure_2, quasiconfined=0.05, graphtype='potentialsLDOS', num_eigenvalues=200, show=True)
def test_arbitrary_pol_rcwa(): import numpy as np from solcore import material, si from solcore.structure import Layer, Structure from solcore.absorption_calculator.rigorous_coupled_wave import calculate_rat_rcwa, \ calculate_absorption_profile_rcwa T = 300 Air = material("Air")(T=T) TiO2 = material("TiO2", sopra=True)(T=T) # for the nanoparticles GaAs = material("GaAs")(T=T) th = 50 NP_layer = Layer( si(th, "nm"), Air, geometry=[{ "type": "ellipse", "mat": TiO2, "center": (200, 200), "halfwidths": [100, 70], "angle": 40 }], ) np_struct = Structure([NP_layer]) wl = np.linspace(300, 1000, 10) step_size = 2 rat_np = calculate_rat_rcwa(np_struct, size=((400, 0), (0, 400)), orders=10, wavelength=wl, substrate=GaAs, incidence=Air, pol=[1, 0]) A_output = rat_np['A_pol'] result = calculate_absorption_profile_rcwa(np_struct, size=((400, 0), (0, 400)), orders=10, wavelength=wl, rat_output_A=A_output, parallel=True, steps_size=step_size, pol=[1, 0]) rat_np_s = calculate_rat_rcwa(np_struct, size=((400, 0), (0, 400)), orders=10, wavelength=wl, substrate=GaAs, incidence=Air, pol='s') A_output_s = rat_np_s['A_pol'] result_s = calculate_absorption_profile_rcwa(np_struct, size=((400, 0), (0, 400)), orders=10, wavelength=wl, rat_output_A=A_output_s, parallel=True, steps_size=step_size, pol='s') assert approx(A_output == A_output_s) assert approx(result["absorption"] == result_s["absorption"])
return (energy, n_interp, k_interp) # Load nk data using nk_convert function... alinp_nk = nk_convert("AlInP_nk.csv", energy=E_eV) gainp_nk = nk_convert("GaInP_nk.csv", energy=E_eV) mgf_nk = nk_convert("MgF_nk.csv", energy=E_eV) sic_nk = nk_convert("SiCx_nk.csv", energy=E_eV) zns_nk = nk_convert("ZnS_nk.csv", energy=E_eV) # Build the optical stack... OptiStack = Structure([ [117, 1240/E_eV, mgf_nk[1], mgf_nk[2]], [80, 1240/E_eV, sic_nk[1], sic_nk[2]], [61, 1240/E_eV, zns_nk[1], zns_nk[2]], [25, 1240/E_eV, alinp_nk[1], alinp_nk[2]], [350000, 1240/E_eV, gainp_nk[1], gainp_nk[2]] ]) angles = np.linspace(0, 80, 10) RAT_angles = [] print("Calculate RAT ::") for theta in angles: rat_data = [] print("Calculating at angle :: %4.1f deg" % theta) # Calculate RAT data... rat_data = calculate_rat(OptiStack, angle=theta, wavelength=1240 / E_eV)
def test_structure(b_mat, layer1, layer2, layer3): structure1 = Structure([layer1, layer2], substrate=b_mat, T=t) assert structure1.__len__() == 2 assert structure1.__dict__ == { 'substrate': b_mat, 'T': t, 'labels': [None, None] } assert structure1.width() == approx(width1 + width2) assert structure1[0] == layer1 assert structure1[1] == layer2 structure2 = Structure([], substrate=b_mat, T=t) structure2.append(layer1, layer_label='layer1') assert structure2.__len__() == 1 assert structure2.__dict__ == { 'substrate': b_mat, 'T': t, 'labels': ['layer1'] } assert structure2[0] == layer1 structure2.append_multiple([layer2, layer3], layer_labels=['layer2', 'layer3']) assert structure2.__len__() == 3 assert structure2.__dict__ == { 'substrate': b_mat, 'T': t, 'labels': ['layer1', 'layer2', 'layer3'] } assert structure2[0] == layer1 assert structure2[1] == layer2 assert structure2[2] == layer3 assert structure2.width() == approx(width1 + width2 + width3) assert structure2.relative_widths()['layer1'] == approx(width1 / structure2.width()) assert structure2.relative_widths()['layer2'] == approx(width2 / structure2.width()) assert structure2.relative_widths()['layer3'] == approx(width3 / structure2.width()) structure3 = Structure([]) structure3.append(layer1, layer_label='layer1', repeats=2) assert structure3.__len__() == 2 assert structure3.__dict__ == {'labels': ['layer1', 'layer1']} assert structure3[0] == layer1 assert structure3[1] == layer1 assert structure3.width() == approx(width1 * 2) # Below currently fails due to a bug when specifying labels and repeating more than once # assert structure3.relative_widths()['layer1'] == width1 / structure3.width() structure4 = Structure([]) structure4.append_multiple([layer1, layer2], layer_labels=['layer1', 'layer2'], repeats=2) assert structure4.__len__() == 4 assert structure4.__dict__ == { 'labels': ['layer1', 'layer2', 'layer1', 'layer2'] } assert structure4[0] == layer1 assert structure4[1] == layer2 assert structure4[2] == layer1 assert structure4[3] == layer2 assert structure4.width() == approx(width1 * 2 + width2 * 2)
Air = material("Air")(T=T) TiO2 = material("TiO2", sopra=True)(T=T) # for the nanoparticles GaAs = material("GaAs")(T=T) # define a flat layer and another with circular discs with the same thickness Flat = Layer(si('50nm'), TiO2) NP_layer = Layer(si('50nm'), Air, geometry=[{ 'type': 'circle', 'mat': TiO2, 'center': (200, 200), 'radius': 50 }]) flat_struct = Structure([Flat]) np_struct = Structure([NP_layer]) # And the wavelength in which the solve the problem wl = np.linspace(300, 1000, 150) rat_flat = calculate_rat_rcwa(flat_struct, size=((400, 0), (0, 400)), orders=10, wavelength=wl, substrate=GaAs, incidence=Air) rat_np = calculate_rat_rcwa(np_struct, size=((400, 0), (0, 400)), orders=10, wavelength=wl,
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])])
def test_rcwa_polygon(): import numpy as np from solcore import material, si from solcore.structure import Layer, Structure from solcore.absorption_calculator.rigorous_coupled_wave import calculate_rat_rcwa, \ calculate_absorption_profile_rcwa T = 300 Air = material("Air")(T=T) TiO2 = material("TiO2", sopra=True)(T=T) # for the nanoparticles GaAs = material("GaAs")(T=T) th = 50 NP_layer_square = Layer( si(th, "nm"), Air, geometry=[{ "type": "rectangle", "mat": TiO2, "center": (200, 200), "halfwidths": [50, 50], "angle": 0 }], ) np_struct_square = Structure([NP_layer_square]) NP_layer_polygon = Layer( si(th, "nm"), Air, geometry=[{ "type": "polygon", "mat": TiO2, "center": (200, 200), "vertices": ((150, 150), (250, 150), (250, 250), (150, 250)), "angle": 0 }], ) np_struct_polygon = Structure([NP_layer_polygon]) wl = np.linspace(300, 1000, 10) step_size = 2 rat_np_sq = calculate_rat_rcwa(np_struct_square, size=((400, 0), (0, 400)), orders=10, wavelength=wl, substrate=GaAs, incidence=Air, pol=[1, 0]) A_output_sq = rat_np_sq['A_pol'] result_square = calculate_absorption_profile_rcwa(np_struct_square, size=((400, 0), (0, 400)), orders=10, wavelength=wl, rat_output_A=A_output_sq, parallel=True, steps_size=step_size, pol=[1, 0]) rat_np_pol = calculate_rat_rcwa(np_struct_polygon, size=((400, 0), (0, 400)), orders=10, wavelength=wl, substrate=GaAs, incidence=Air, pol=[1, 0]) A_output_pol = rat_np_pol['A_pol'] result_polygon = calculate_absorption_profile_rcwa( np_struct_polygon, size=((400, 0), (0, 400)), orders=10, wavelength=wl, rat_output_A=A_output_pol, parallel=True, steps_size=step_size, pol=[1, 0]) assert approx(A_output_sq == A_output_pol) assert approx(result_polygon["absorption"] == result_square["absorption"])
import matplotlib.pyplot as plt import numpy as np from solcore.absorption_calculator import calculate_ellipsometry from solcore import material, si from solcore.structure import Structure, Layer # First we defined a couple of materials, for example, GaAs and AlGAs GaAs = material('GaAs')(T=300) AlGaAs = material('AlGaAs')(T=300, Al=0.3) # Now, let's build the structure. We don't add a substrate and assume that there is an infinitely thick absorbing # material in the back. my_structure = Structure([ Layer(si(40, 'nm'), material=AlGaAs), Layer(si(3000, 'nm'), material=GaAs), ]) # We want to calculate the ellipsometry of this structure as a function of the wavelength for a few angles wavelength = np.linspace(400, 1000, 200) angles = [65, 70, 75] out = calculate_ellipsometry(my_structure, wavelength, angle=angles) # This results must be taken with care. As the ellipsometry routine can only deal with coherent light, there might be # strange oscillations related with intereference in thick layers, something that should not happen. # Setting no_back_reflection=True (the default) should take care of most of this effects, but might add other unexpected # ones. fig, ax1 = plt.subplots(1, 1) ax2 = ax1.twinx() ax1.plot(wavelength, out['psi'][:, 0], 'b', label=r'$\Psi$')
n_spline = InterpolatedUnivariateSpline(x=Ge_nk_Exp[::5, 0], y=Ge_nk_Exp[::5, 1], k=3)(E_eV) k_spline = InterpolatedUnivariateSpline(x=Ge_nk_Exp[::5, 2], y=Ge_nk_Exp[::5, 3], k=3)(E_eV) ## Step 1 :: n and k modelling... # First model the Ge02 layer with the Sellmeier model # Define Oscillator Structure GeO2 = Structure([ Oscillator(oscillator_type="Sellmeier", material_parameters=None, A1=0.80686642, L1=0.68972606E-1, A2=0.71815848, L2=0.15396605, A3=0.85416831, L3=0.11841931E2) ]) GeO2_nk = cppb().nk_calc(oscillator_structure=GeO2, energy_array=E_eV) # Step 2 :: use this modelled n and k to calculate the ellipsometry data... # Define a structure for the optical stack... stack = Structure([ [4.4, 1240 / E_eV, GeO2_nk["n"], GeO2_nk["k"]], # Layer 1 :: GeO2 native oxide layer [350000, 1240 / E_eV, n_spline, k_spline] # Layer 2/ Substrate :: Bulk Ge ])
def test_quantum_mechanics_schrodinger(): """ Testing schrodinger equation solver """ bulk = material("GaAs")(T=293) barrier = material("GaAsP")(T=293, P=0.1) bulk.strained = False barrier.strained = True top_layer = Layer(width=si("30nm"), material=bulk) inter = Layer(width=si("3nm"), material=bulk) barrier_layer = Layer(width=si("15nm"), material=barrier) bottom_layer = top_layer E = np.linspace(1.15, 1.5, 300) * q alfas = np.zeros((len(E), 6)) alfas[:, 0] = E / q alpha_params = { "well_width": si("7.2nm"), "theta": 0, "eps": 12.9 * vacuum_permittivity, "espace": E, "hwhm": si("6meV"), "dimensionality": 0.16, "line_shape": "Gauss", } QW = material("InGaAs")(T=293, In=0.2) QW.strained = True well_layer = Layer(width=si("7.2nm"), material=QW) my_structure = Structure( [ top_layer, barrier_layer, inter, well_layer, inter, barrier_layer, inter, bottom_layer, ], substrate=bulk, ) band_edge, bands = QM.schrodinger( my_structure, quasiconfined=0, num_eigenvalues=20, alpha_params=alpha_params, calculate_absorption=True, ) for key in band_edge["E"]: for i in range(len(band_edge["E"][key])): band_edge["E"][key][i] = solcore.asUnit(band_edge["E"][key][i], "eV") * 1000 band_edge["E"][key][i] = round(band_edge["E"][key][i]) Ehh = np.all(np.equal(band_edge["E"]["Ehh"], my_energies["Ehh"])) Elh = np.all(np.equal(band_edge["E"]["Elh"], my_energies["Elh"])) Ee = np.all(np.equal(band_edge["E"]["Ee"], my_energies["Ee"])) idx = 100 out = [band_edge["alpha"][0][idx] / q, band_edge["alpha"][1][idx]] # Test over the energies assert Ehh and Elh and Ee # Test over the absorption coefficent at a given energy for i, data in enumerate(out): assert out[i] == approx(my_absorption[i], rel=1e-4)
output['absorption'] = 0.5 * (data_s + data_p) return output if __name__ == '__main__': import matplotlib.pyplot as plt from solcore import material, si from solcore.structure import Layer, Structure GaAs = material('GaAs')(T=300) InGaAs = material('InGaAs')(T=300, In=0.1) my_structure = Structure([ Layer(si(3000, 'nm'), material=InGaAs), Layer(si(30, 'um'), material=GaAs), ]) wavelength = np.linspace(450, 1100, 300) out = calculate_rat(my_structure, wavelength, coherent=True, no_back_reflection=False) # # # plt.plot(wavelength, out['R'], 'b', label='Reflexion') # plt.plot(wavelength, out['A'], 'r', label='Absorption') # plt.plot(wavelength, out['T'], 'g', label='Transmission') # plt.legend() # plt.show()
MatParams["B1s"] = 1.0 MatParams["Gamma_Eg_ID"] = 0.3 MatParams["Alpha_Eg_ID"] = 0.0 MatParams["E1"] = 2.8 MatParams["E1_d1"] = 2.9 MatParams["Gamma_E1"] = 0.1 MatParams["E2"] = 4.72 MatParams["C"] = 3.0 MatParams["Alpha_E2"] = 0.04 MatParams["Gamma_E2"] = 0.19 # Must define a structure object containing the required oscillator functions. The oscillator type and material # parameters are both passed to individual 'Oscillators' in the structure... Adachi_GaAs = Structure([ Oscillator(oscillator_type="E0andE0_d0", material_parameters=MatParams), Oscillator(oscillator_type="E1andE1_d1", material_parameters=MatParams), Oscillator(oscillator_type="E_ID", material_parameters=MatParams), Oscillator(oscillator_type="E2", material_parameters=MatParams) ]) Output = CPPB_Model.eps_calc(Adachi_GaAs, E) # PLOT OUTPUT... fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(7, 4.5)) # Subplot I :: Real part of the dielectric function. ax1.set_yscale("linear") ax1.set_xlim(0, 5.3) ax1.set_ylim(-14, 27) ax1.plot(Palik_Eps1[:, 0], Palik_Eps1[:, 1], label="Exp. Data (Palik)", marker='o', ls='none', markerfacecolor='none', markeredgecolor=colours("Red"))
"dimensionality": 0.16, "line_shape": "Gauss" } # We create the QW material at the given composition QW = material("InGaAs")(T=293, In=0.15) QW.strained = True # And the layer well_layer = Layer(width=si("7.2nm"), material=QW) # The following lines create the QW structure, with different number of QWs and interlayers # test_structure = Structure([top_layer, barrier_layer, inter] + 10 * [well_layer, inter, barrier_layer, inter] + # [bottom_layer]) # test_structure = Structure([barrier_layer, inter] + 1 * [well_layer, inter] + # [barrier_layer]) test_structure = Structure([top_layer, barrier_layer] + 10 * [well_layer, barrier_layer] + [bottom_layer]) test_structure.substrate = bulk # Finally, the quantum properties are claculated here output = QM.schrodinger(test_structure, quasiconfined=0, graphtype='potentials', num_eigenvalues=50, alpha_params=alpha_params, calculate_absorption=True)
"line_shape": "Gauss" } comp = [0.05, 0.1, 0.15, 0.2, 0.25] colors = plt.cm.jet(np.linspace(0, 1, len(comp))) plt.figure(figsize=(6, 4.5)) for j, i in enumerate(comp): QW = material("InGaAs")(T=293, In=i) QW.strained = True well_layer = Layer(width=si("7.2nm"), material=QW) # test_structure = Structure([top_layer, barrier_layer, inter] + 1 * [well_layer, inter, barrier_layer, inter] + # [bottom_layer]) test_structure = Structure([barrier_layer, inter] + 1 * [well_layer, inter] + [barrier_layer]) # test_structure = Structure([top_layer, barrier_layer] + 10 * [well_layer, barrier_layer] + # [bottom_layer]) test_structure.substrate = bulk output = schrodinger(test_structure, quasiconfined=0, num_eigenvalues=20, alpha_params=alpha_params, calculate_absorption=True) alfa = output[0]['alphaE'](E) plt.plot(1240 / (E / q), alfa / 100, label='{}%'.format(int(i * 100))) alfas[:, j + 1] = alfa / 100
fill_value=(k[0], k[-1]))(energy) return (energy, n_interp, k_interp) # Load nk data using nk_convert function... alinp_nk = nk_convert("data/AlInP_nk.csv", energy=E_eV) gainp_nk = nk_convert("data/GaInP_nk.csv", energy=E_eV) mgf_nk = nk_convert("data/MgF_nk.csv", energy=E_eV) sic_nk = nk_convert("data/SiCx_nk.csv", energy=E_eV) zns_nk = nk_convert("data/ZnS_nk.csv", energy=E_eV) # Build the optical stack... stack = Structure([[117, 1240 / E_eV, mgf_nk[1], mgf_nk[2]], [80, 1240 / E_eV, sic_nk[1], sic_nk[2]], [61, 1240 / E_eV, zns_nk[1], zns_nk[2]], [25, 1240 / E_eV, alinp_nk[1], alinp_nk[2]], [350000, 1240 / E_eV, gainp_nk[1], gainp_nk[2]]]) angles = np.linspace(0, 80, 10) RAT_angles = [] print("Calculate RAT ::") for theta in angles: print("Calculating at angle :: %4.1f deg" % theta) # Calculate RAT data... rat_data = calculate_rat(stack, angle=theta, wavelength=1240 / E_eV) RAT_angles.append((theta, rat_data["R"], rat_data["A"])) colors = plt.cm.jet(np.linspace(1, 0, len(RAT_angles)))
"hwhm": si("6meV"), "dimensionality": 0.16, "line_shape": "Gauss" } # plt.figure(figsize=(4, 4.5)) for j, i in enumerate(comp): # We create the QW material at the given composition QW = material("InGaAs")(T=293, In=i, strained=True) # And the layer well_layer = Layer(width=si("7.2nm"), material=QW) # The following lines create the QW structure, with different number of QWs and interlayers test_structure = Structure( [barrier_layer, inter, well_layer, inter, barrier_layer], substrate=bulk) # Finally, the quantum properties are claculated here output = QM.schrodinger(test_structure, quasiconfined=0, num_eigenvalues=20, alpha_params=alpha_params, calculate_absorption=True) alfa = output[0]['alphaE'](E) plt.plot(1240 / (E / q), alfa / 100, label='{}%'.format(int(i * 100))) plt.xlim(826, 1100) plt.ylim(0, 23000) plt.xlabel('Wavelength (nm)')