def test_self_interaction_energy(): a = Material(1.0, 0.0, 1.0, 1.0, 5.0) b = Material(1.0, -0.5, 1.0, 1.0, 10.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.65, 2.0, 2.0) # Type 2 CSNC. h/e structure. print(csnc1.self_interaction_energy())
def test_type_one(): """Tests for CSNC type-1. """ a = Material(2.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc = CoreShellParticle(b, a, 1.0, 1.0) assert csnc.type_one # This is a type 1 CSNC.
def main(): inp_effective_electron_mass = 0.073 InP = Material(1.34, 0, inp_effective_electron_mass, 0.64, 9.6, "InP") CdS = Material(2.20, -0.39, 0.21, 0.68, 5.3, "CdS") shell_widths = np.array([0.53, 1.05, 1.47, 1.90, 2.76, 3.84]) experimental_bandgaps = [1.78, 1.46, 1.37, 1.32, 1.26, 1.24] print("Using InP electron effective mass: {:0.2f}".format( inp_effective_electron_mass)) print( "Core \t Shell \tExp \t BG \t E(e): E(h): Coulomb: Polarization: Model(Exp-Model):" ) for i, shell_width in enumerate(shell_widths): csnc = CoreShellParticle(InP, CdS, 1.23, shell_width, 1.5) print(1.23, "\t", shell_width, end="\t") # print("Is CSNC type two? h/e?", csnc.type_two, csnc.h_e) energies = np.array(csnc.calculate_s1_energies()) # print(energies) plots = False col_energy_sectioned = csnc.coulomb_screening_energy( plot_integrand=plots) pol_energy_sectioned = csnc.polarization_screening_energy( plot_integrand=plots) self_energy = csnc.self_interaction_energy() # print(xx_coulomb_sectioned) # whole_integral_energy = ( # csnc.bandgap + np.sum(energies) + col_energy_whole[0] + pol_energy_whole[0] # ) sectioned_integral_energy = ( csnc.bandgap + np.sum(energies) + col_energy_sectioned[0] + pol_energy_sectioned[0] # + self_energy ) # + xx_coulomb_sectioned[0] # print("Col:", col_energy_whole, col_energy_sectioned, "Pol:", pol_energy) # print("NC bandgap:", csnc.bandgap) print(experimental_bandgaps[i], end="\t") # print( # "{:0.2f}({:0.2f})".format( # whole_integral_energy, # abs(experimental_bandgaps[i] - whole_integral_energy), # ), # end="\t", # ) print( "{:0.3f}\t{:0.3f}\t{:0.3f}\t{:0.3f}\t{:0.3f}\t{:0.3f}\t{:0.3f}". format( csnc.bandgap, energies[0], energies[1], col_energy_sectioned[0], pol_energy_sectioned[0], sectioned_integral_energy, experimental_bandgaps[i] - sectioned_integral_energy, ), end="\t", ) print()
def test_type_two_and_eh(): """Tests for CSNC type-2 and e/h structure. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc = CoreShellParticle(b, a, 1.0, 1.0) assert csnc.type_two # This is a type 2 CSNC. assert csnc.e_h # This is an h/e structure.
def test_energies_are_order_unity(): """Tests that energies are approximately around 1. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC. h/e structure. energies = csnc1.calculate_s1_energies() assert np.all(np.logical_and(1e-1 < energies, energies < 10))
def test_adaptive_energy_bracketing_for_high_energies(): """Tests that high energies are bracketed for extremely small CSNCs. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 0.1, 0.1) # Type 2 CSNC. h/e structure. energies = csnc1.calculate_s1_energies() # print(energies) assert np.isclose(energies[0], energies[1])
def test_asymptotic_shell_localization(): a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC. h/e structure. csnc2 = CoreShellParticle(b, a, 1.0, 1.0) # Type 2 CSNC. e/h structure. assert np.isclose( csnc1.localization_electron_shell(1e6), csnc1.localization_electron_shell(asymp=True), ) assert np.isclose(csnc2.localization_hole_shell(1e6), csnc2.localization_hole_shell(asymp=True))
def test_wavenumbers_are_order_unity(): """Tests that wavenumbers are approximately around 1. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC. h/e structure. wavenumbers = csnc1.calculate_wavenumbers() assert np.all( np.logical_and(1e-1 < abs(wavenumbers), abs(wavenumbers) < 10))
def test_thicker_core_requires_smaller_shell_for_localization_eh(): """Tests that a thicker core leads to carrier confinement in a thinner shell, in type-2 e/h CSNCs. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(b, a, 1.0, 1.0) # Type 2 CSNC. e/h structure. csnc2 = CoreShellParticle(b, a, 1.1, 1.0) # Type 2 CSNC. e/h structure. csnc1_shellloc = csnc1.localization_hole_shell() csnc2_shellloc = csnc2.localization_hole_shell() assert csnc2_shellloc < csnc1_shellloc
def test_thicker_shell_requires_smaller_core_for_localization_he(): """Tests that a thicker shell leads to carrier confinement in a smaller core, in type-2 h/e CSNCs. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC, h/e structure. csnc2 = CoreShellParticle(a, b, 1.0, 1.1) # Type 2 CSNC, h/e structure. csnc1_coreloc = csnc1.localization_hole_core() csnc2_coreloc = csnc2.localization_hole_core() assert csnc2_coreloc < csnc1_coreloc
def test_tighter_confinement_leads_to_higher_energy_states(): """Tests that a smaller CSNC leads to higher-energy eigenstates. """ a = Material(2.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(b, a, 1.0, 1.0) # Type 1 CSNC. csnc2 = CoreShellParticle(b, a, 0.9, 1.0) # Type 1 CSNC. csnc1_energies = csnc1.calculate_s1_energies() csnc2_energies = csnc2.calculate_s1_energies() assert np.all(csnc2_energies > csnc1_energies)
def test_equal_wavenumbers_for_type_two_eh(): """Tests if the wavenumbers of the electron/hole wavefunctions are equal, given all relevant variables are equal. """ a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc = CoreShellParticle(a, b, 1.0, 1.0) # Type 1 CSNC. electron_core_wavenumber, electron_shell_wavenumber, hole_core_wavenumber, hole_shell_wavenumber = ( csnc.calculate_wavenumbers()) test.assert_allclose(electron_core_wavenumber, hole_shell_wavenumber) test.assert_allclose(electron_shell_wavenumber, hole_core_wavenumber)
def test_core_localization_consistency_with_paper(): mass_ratio = np.linspace(0.01, 100, 10) for m in mass_ratio: a = Material(1.0, 0.0, m, m, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC. h/e structure. csnc2 = CoreShellParticle(b, a, 1.0, 1.0) # Type 2 CSNC. h/e structure. # This test doesn't really -test- anything, per se. It simply makes sure that a part of the code that will raise # a warning is not accessed. csnc1.localization_hole_core() csnc2.localization_electron_core()
import numpy as np from pyncband import Material, CoreShellParticle InP = Material(1.34, 0, 1.0, 0.64, 9.6, "InP") CdS = Material(2.20, -0.39, 0.21, 0.68, 5.3, "CdS") def inp_electron_mass_from_energy(e): alpha = -1.2 e_p = 20.6 e_g = 1.34 return 1 / (alpha + e_p / (e_g + e)) for energy in np.linspace(0.1, 1, 5): print(inp_electron_mass_from_energy(energy)) inp_eff_electron_mass = 1.0 mass_eps = 1.0 print("Iteratively figuring out InP electron effective mass:") while mass_eps > 1e-5: InP = Material(1.34, 0, inp_eff_electron_mass, 0.64, 9.6, "InP") csnc = CoreShellParticle(InP, CdS, 1.23, 1.90, 1.5) energy_e, energy_h = csnc.calculate_s1_energies() inp_eff_electron_mass_new = inp_electron_mass_from_energy(energy_e) mass_eps = abs(inp_eff_electron_mass_new - inp_eff_electron_mass) print(mass_eps, inp_eff_electron_mass, inp_eff_electron_mass_new) inp_eff_electron_mass = inp_eff_electron_mass_new
import matplotlib.pyplot as plt import numpy as np from pyncband import Material, CoreShellParticle mathigher = Material(1.0, 0.0, 0.1, 0.6, 4.0) matlower = Material(1.0, -0.5, 0.1, 0.6, 6.0) cseh = CoreShellParticle(matlower, mathigher, 1.0, 1.0) cshe = CoreShellParticle(mathigher, matlower, 1.0, 1.0) # ================================================================== # def overlap_integral_eh(core_width, shell_width): # cseh.set_core_width(core_width) # cseh.set_shell_width(shell_width) # return cseh.numerical_overlap_integral() # # vectorized_overlap_integral_eh = np.vectorize(overlap_integral_eh) # # def overlap_integral_he(core_width, shell_width): # cshe.set_core_width(core_width) # cshe.set_shell_width(shell_width) # return cshe.numerical_overlap_integral() # # vectorized_overlap_integral_he = np.vectorize(overlap_integral_he) # # ================================================================== core_radii = np.linspace(0.2, 10, 10) shell_radii = np.linspace(0.2, 10, 10) # # core_radii_mesh, shell_radii_mesh = np.meshgrid(core_radii, shell_radii)
import numpy.testing as test from pyncband import Material, CoreShellParticle if __name__ == "__main__": AlSb = Material(1.6, -2.9, 0.12, 0.98, 2, "AlSb") CdS = Material(2.4, -3.5, 0.21, 0.8, 3, "CdS") test.assert_almost_equal(AlSb.vbe, -4.5) test.assert_almost_equal(CdS.vbe, -5.9) CdS_AlSb = CoreShellParticle(CdS, AlSb, 5, 3) AlSb_CdS = CoreShellParticle(AlSb, CdS, 5, 3) assert CdS_AlSb.type_two, "CdS/AlSb is is a type 2 QD" assert CdS_AlSb.e_h, "CdS/AlSb should be e-h core-shell." assert AlSb_CdS.type_two, "AlSb/CdS is is a type 2 QD" assert AlSb_CdS.h_e, "AlSb/CdS should be h-e core-shell." print(CdS_AlSb.ue) print(CdS_AlSb.calculate_wavenumbers()) # print(CdS_AlSb.calculate_s1_energies()) # s1_e_CdS_AlSb, s1_h_CdS_AlSb = CdS_AlSb.calculate_s1_energies() # print("S1 energy:", s1_e_CdS_AlSb) # ke, qe = CdS_AlSb.calculate_wavenumbers() # print("Electron wavevector in core and shell:", ke, qe) """ x, dx = np.linspace(1e-14, 10, 1000, retstep=True) wf = CdS_AlSb.plot_electron_wavefunction(x, ke, qe) plt.plot(x, wf * wf) plt.show() print(CdS_AlSb.cmat.m_e, CdS_AlSb.smat.m_e) cme, sme = CdS_AlSb.cmat.m_e, CdS_AlSb.smat.m_e plt.plot(x, np.gradient(wf, dx) * np.where(x < CdS_AlSb.core_width, 1, 4)) # plt.xlim(4.8, 5.2)
def test_analytical_overlap_integral_is_at_or_below_one(): a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC. h/e structure. assert csnc1.analytical_overlap_integral() <= 1.0
def test_overlap_integrals_are_consistent(): a = Material(1.0, 0.0, 1.0, 1.0, 1.0) b = Material(1.0, -0.5, 1.0, 1.0, 1.0) # Lower band edges. csnc1 = CoreShellParticle(a, b, 1.0, 1.0) # Type 2 CSNC. h/e structure. assert np.isclose(csnc1.analytical_overlap_integral(), csnc1.numerical_overlap_integral())