Exemple #1
0
    def solve(self, E, solution_start):
        self._reset_to_default_units()
        E.convert_to(E.units_default)
        lattice_potential = spsc_data.Potential(
            self.potential[:self.well_start], self.potential.units)
        flat_lattice_potential = self._flatten_potential(lattice_potential)
        lattice_length = spsc_data.LengthValue(
            self.length.value * (len(flat_lattice_potential) - 1) /
            (len(self.potential) - 1), self.length.units)
        iteration = SolutionIterationFlatPotential(flat_lattice_potential,
                                                   self.mass, lattice_length)
        lattice_solution = iteration.solve(E, solution_start)

        well_solution_start = (lattice_solution[0][-1],
                               lattice_solution[1][-1])
        well_potential = spsc_data.Potential(
            self.potential[self.well_start:self.well_end],
            self.potential.units)
        well_length = spsc_data.LengthValue(
            self.length.value * len(well_potential) /
            (len(self.potential) - 1), self.length.units)
        iteration = SolutionIterationRungeKutt(well_potential, self.mass,
                                               well_length)
        well_solution = iteration.solve(E, well_solution_start)

        N = len(self.potential)
        solution = (spsc_data.WaveFunction(np.zeros(
            (N, ))), spsc_data.WaveFunction(np.zeros((N, ))))
        solution[0][:len(lattice_solution[0])] = lattice_solution[0]
        solution[0][len(lattice_solution[0]) - 1:len(lattice_solution[0]) +
                    len(well_solution[0]) - 1] = well_solution[0]
        solution[1][:len(lattice_solution[1])] = lattice_solution[1]
        solution[1][len(lattice_solution[1]) - 1:len(lattice_solution[1]) +
                    len(well_solution[1]) - 1] = well_solution[1]
        return solution
Exemple #2
0
    def solve(self):
        symmetry_solver = LatticeSymmetrySolver(self.state)
        symmetry_solver.solve()

        # for j in xrange(5):
        #     self.__gamma_shrod()
        #     self.__x_shrod()
        #     self.state.density_potential = self.__solve_puass()

        E_start = spsc_data.EnergyValue(0.001, "eV")
        E_end = spsc_data.EnergyValue(0.3, "eV")
        dE = spsc_data.EnergyValue(0.0001, "eV")

        meta_info = self.state.electron_states[1].static_potential.meta_info
        self.state.electron_states[1].static_potential.convert_to('eV')
        self.state.density_potential.convert_to('eV')
        static_potential_arr = self.state.electron_states[
            1].static_potential.value[
                meta_info['x_solution_start']:meta_info['x_solution_end']]
        density_potential_arr = self.state.density_potential.value[
            meta_info['x_solution_start']:meta_info['x_solution_end']]

        potential_arr = static_potential_arr + density_potential_arr
        potential = spsc_data.Potential(potential_arr, "eV")
        potential_offset = spsc_data.EnergyValue(np.amin(potential_arr), 'eV')
        potential = potential - spsc_data.Potential(
            potential_offset.value * np.ones(
                (len(potential), ), "float64"), potential_offset.units)
        potential.meta_info = meta_info

        mass = self.state.electron_states[1].mass
        length = self.state.length
        iteration_factory = spsc_shrod.SolutionIterationRungeKuttFactory()
        solution_strategy = spsc_shrod.IterableSolutionStrategyNonSymmetricWell(
            E_start, E_end, dE, 1, iteration_factory)
        solutions = solution_strategy.solve(potential, mass, length,
                                            (10.0**-20, 0, 10.0**-25, 0))

        wave_function = solutions[0][1]
        zeros = np.zeros((len(self.state.density_potential), ))
        wave_function_full_arr = np.concatenate(
            (zeros[:meta_info['x_solution_start']], wave_function.value,
             zeros[meta_info['x_solution_end']:]))
        wave_function = spsc_data.WaveFunction(wave_function_full_arr)
        wave_function.mirror()
        wave_function.normalize()
        self.state.electron_states[1].wave_functions.append(wave_function)

        energy_level = solutions[0][0]
        energy_level = energy_level + potential_offset
        self.state.electron_states[1].energy_levels.append(energy_level)
Exemple #3
0
def superlattice_well_sloped(periods_num, well_length, lattice_well_length,
                             lattice_barrier_length, slope):
    state = superlattice_well(periods_num, well_length, lattice_well_length,
                              lattice_barrier_length)
    slope.convert_to(slope.units_default)
    state.length.convert_to(state.length.units_default)
    energy_diff = slope.value * state.length.value * constants.e
    energy_diff = spsc_data.EnergyValue(energy_diff)
    energy_diff.convert_to("eV")

    state.electron_states[0].static_potential.convert_to("eV")
    potential_arr = state.electron_states[0].static_potential.value
    slope_arr = np.zeros((len(potential_arr), ))
    dE = energy_diff.value / (len(slope_arr) - 1)
    for i in range(len(slope_arr)):
        slope_arr[i] = dE * i
    potential_arr = potential_arr + slope_arr
    well_min_index = potential_arr.argmin()
    well_min_value = potential_arr[well_min_index]
    potential_arr = potential_arr - np.full(
        (len(potential_arr), ), well_min_value)
    meta_info = state.electron_states[0].static_potential.meta_info
    state.electron_states[0].static_potential = spsc_data.Potential(
        potential_arr, "eV")
    state.electron_states[0].static_potential.meta_info = meta_info
    return state
Exemple #4
0
def single_well(well_length):
    state = spsc_core.StateSimple()
    granularity = well_length.value * 10
    length = well_length * 3
    length.convert_to("nm")
    potential = spsc_data.Potential(np.ones((granularity, ), "float64"), "eV")
    potential.append(
        spsc_data.Potential(np.zeros((granularity, ), "float64"), "eV"))
    potential.append(
        spsc_data.Potential(np.ones((granularity + 1, ), "float64"), "eV"))
    electron_state = spsc_core.ElectronStateSimple()
    electron_state.static_potential = potential
    electron_state.mass = spsc_data.MassValue(0.068 * constants.m_e)
    state.electron_states = [electron_state]
    state.length = length
    return state
Exemple #5
0
    def solve(self, E, solution_start):
        iteration_factory = SolutionIterationSymmetryLatticeFactory()
        iteration = iteration_factory.get_iteration(self.potential, self.mass,
                                                    self.length)
        left_solution = iteration.solve(E,
                                        (solution_start[0], solution_start[1]))

        potential_turned = spsc_data.Potential(self.potential.value[::-1],
                                               self.potential.units)
        potential_turned.meta_info = {
            "well_start":
            len(potential_turned) - self.potential.meta_info["well_end"] - 1,
            "well_end":
            len(potential_turned) - self.potential.meta_info["well_start"] - 1,
            "lattice_bar_width":
            self.potential.meta_info["lattice_bar_width"],
            "lattice_well_width":
            self.potential.meta_info["lattice_well_width"]
        }
        iteration = iteration_factory.get_iteration(potential_turned,
                                                    self.mass, self.length)
        right_solution = iteration.solve(
            E, (solution_start[2], solution_start[3]))
        right_solution[0].value = right_solution[0].value[::-1]
        right_solution[1].value = right_solution[1].value[::-1] * -1

        return left_solution[0], left_solution[1], right_solution[
            0], right_solution[1]
Exemple #6
0
    def solve(self, E, solution_start):
        self._reset_to_default_units()
        E.convert_to(E.units_default)
        N = len(self.potential)
        solution = (spsc_data.WaveFunction(np.zeros(
            (N, ))), spsc_data.WaveFunction(np.zeros((N, ))))
        solution[0][0] = solution_start[0]
        solution[1][0] = solution_start[1]
        h = 1.0 / (N - 1)
        h1 = h / 6
        for i in xrange(1, N):
            (k, q) = self._k_q(i, solution[0][i - 1], solution[1][i - 1], E)
            solution[0][i] = solution[0][i - 1] + h1 * (k[0] + 2 * k[1] +
                                                        2 * k[2] + k[3])
            solution[1][i] = solution[1][i - 1] + h1 * (q[0] + 2 * q[1] +
                                                        2 * q[2] + q[3])

        if len(solution_start) == 4:
            potential_turned = spsc_data.Potential(self.potential.value[::-1],
                                                   self.potential.units)
            iteration_turned = self.__class__(potential_turned, self.mass,
                                              self.length)
            solution_turned = iteration_turned.solve(
                E, (solution_start[2], solution_start[3]))
            reverse_solution = (spsc_data.WaveFunction(
                solution_turned[0].value[::-1]),
                                spsc_data.WaveFunction(
                                    solution_turned[1].value[::-1]))
            solution = (solution[0], solution[1], reverse_solution[0],
                        reverse_solution[1])

        return solution
Exemple #7
0
 def __init__(self, potential, mass, length):
     super(SolutionIterationRungeKutt,
           self).__init__(potential, mass, length)
     self.expanded_potential = spsc_data.Potential(
         np.zeros((2 * len(self.potential) - 1, ), "float64"),
         self.potential.units)
     self.expanded_potential.value[0::2] = self.potential.value
     self.expanded_potential.value[1::2] = (self.potential.value[0:-1:] +
                                            self.potential.value[1::]) / 2
Exemple #8
0
    def solve(self, E, solution_start):
        self._reset_to_default_units()
        E.convert_to(E.units_default)
        lattice_potential = spsc_data.Potential(
            self.potential[:self.well_start], self.potential.units)
        flat_lattice_potential = self._flatten_potential(lattice_potential)
        lattice_length = spsc_data.LengthValue(
            self.length.value * (len(flat_lattice_potential) - 1) /
            (len(self.potential) - 1), self.length.units)
        lattice_mass = spsc_data.MassArray(
            self.mass[:len(flat_lattice_potential)])
        # Need this because the last point in the lattice potential is artificial,
        # and we need to keep the same mass as it was in the last point.
        lattice_mass.value[-1] = lattice_mass.value[-2]
        iteration = SolutionIterationFlatPotentialDiffMass(
            flat_lattice_potential, lattice_mass, lattice_length)
        lattice_solution = iteration.solve(E, solution_start)

        well_solution_start = (lattice_solution[0][-1],
                               lattice_solution[1][-1])
        well_potential = spsc_data.Potential(
            self.potential[self.well_start:self.well_end],
            self.potential.units)
        well_length = spsc_data.LengthValue(
            self.length.value * len(well_potential) /
            (len(self.potential) - 1), self.length.units)
        well_mass = spsc_data.MassValue(self.mass.value[self.well_start])
        iteration = SolutionIterationRungeKutt(well_potential, well_mass,
                                               well_length)
        well_solution = iteration.solve(E, well_solution_start)

        N = len(self.potential)
        solution = (spsc_data.WaveFunction(np.zeros(
            (N, ))), spsc_data.WaveFunction(np.zeros((N, ))))
        solution[0][:len(lattice_solution[0])] = lattice_solution[0]
        solution[0][len(lattice_solution[0]) - 1:len(lattice_solution[0]) +
                    len(well_solution[0]) - 1] = well_solution[0]
        solution[1][:len(lattice_solution[1])] = lattice_solution[1]
        solution[1][len(lattice_solution[1]) - 1:len(lattice_solution[1]) +
                    len(well_solution[1]) - 1] = well_solution[1]
        return solution
Exemple #9
0
 def solve(self):
     E_start = spsc_data.EnergyValue(0.0001, "eV")
     E_end = spsc_data.EnergyValue(0.2, "eV")
     dE = spsc_data.EnergyValue(0.0001, "eV")
     static_potential = self.state.electron_states[0].static_potential
     meta_info = static_potential.meta_info
     iteration_factory = spsc_shrod.SolutionIterationSlopedLatticeFactory()
     solution_strategy = spsc_shrod.IterableSolutionStrategyNonSymmetricWell(
         E_start, E_end, dE, 1, iteration_factory)
     density_potential = self.state.density_potential
     mass = self.state.electron_states[0].mass
     length = self.state.length
     electron_state = self.state.electron_states[0]
     for j in xrange(10):
         potential = static_potential + density_potential
         potential_offset = spsc_data.EnergyValue(
             potential[meta_info["well_start"]], potential.units)
         potential = potential - spsc_data.Potential(
             potential_offset.value * np.ones(
                 (len(potential), ), "float64"), potential_offset.units)
         potential.meta_info = meta_info
         solutions = solution_strategy.solve(potential, mass, length,
                                             (10.0**-20, 0, 10.0**-25, 0))
         for i in xrange(len(solutions)):
             solution = solutions[i]
             if len(electron_state.wave_functions) > i:
                 electron_state.wave_functions[i] = solution[1]
             else:
                 electron_state.wave_functions.append(solution[1])
             energy_level = solution[0] + potential_offset
             if len(electron_state.energy_levels) > i:
                 electron_state.energy_levels[i] = energy_level
             else:
                 electron_state.energy_levels.append(energy_level)
         h = 1.0 / (len(self.state.electron_states[0].wave_functions[0]) -
                    1)
         electron_density = spsc_data.Density(
             electron_state.sum_density.value * h *
             (electron_state.wave_functions[0].value**2),
             electron_state.sum_density.units)
         self.state.static_density.convert_to("m^-2")
         density = self.state.static_density - electron_density
         puass_solution_strategy = spsc_puass.GaussSolutionStrategy()
         prev_density_potential = density_potential
         density_potential = puass_solution_strategy.solve(
             density, 12, self.state.length)
         density_potential.convert_to(prev_density_potential.units)
         density_potential.value = (density_potential.value +
                                    prev_density_potential.value) / 2
     self.state.density_potential = density_potential
Exemple #10
0
 def solve(self, density, eps, length):
     N = len(density)
     h = 1.0 / (N - 1)
     length.convert_to(length.units_default)
     density.convert_to(density.units_default)
     potential = spsc_data.Potential(np.zeros((N, ), "float64"))
     k = 2.0 * np.pi * (constants.e**2) * length.value * h / eps
     for i in xrange(N):
         for j in xrange(N):
             if i > j:
                 potential[i] += k * density[j] * (i - 2 * j)
             else:
                 potential[i] += -k * density[j] * i
     return potential
Exemple #11
0
 def _flatten_potential(self, potential):
     current_index = 0
     flat_potential = spsc_data.Potential([], potential.units)
     # Start from bar.
     is_bar = True
     mean_value = 0
     while current_index < len(potential):
         if is_bar:
             potential_piece = potential[current_index:current_index +
                                         self.lattice_bar_width]
             current_index += self.lattice_bar_width
         else:
             potential_piece = potential[current_index:current_index +
                                         self.lattice_well_width]
             current_index += self.lattice_well_width
         mean_value = np.mean(potential_piece)
         flat_potential.append(
             spsc_data.Potential(mean_value *
                                 np.ones(len(potential_piece))))
         is_bar = not is_bar
     # This last point is needed for clue potential and solutions and keeping length consistent.
     flat_potential.append(spsc_data.Potential(mean_value * np.ones(1)))
     return flat_potential
Exemple #12
0
    def solve(self):
        # 30 nm well
        E_start = spsc_data.EnergyValue(0.001, "eV")
        E_end = spsc_data.EnergyValue(0.4, "eV")
        # 13 nm well
        # E_start = spsc_data.EnergyValue(0.01, "eV")
        # E_end = spsc_data.EnergyValue(0.08, "eV")
        dE = spsc_data.EnergyValue(0.0001, "eV")
        static_potential = self.state.electron_states[0].static_potential
        meta_info = static_potential.meta_info
        mass = self.state.electron_states[0].mass
        if isinstance(mass, spsc_data.APhysValueArray):
            iteration_factory = spsc_shrod.SolutionIterationSymmetryLatticeDiffMassFactory(
            )
        else:
            iteration_factory = spsc_shrod.SolutionIterationSymmetryLatticeFactory(
            )
        solution_strategy = spsc_shrod.IterableSolutionStrategySymmetricWell(
            E_start, E_end, dE, 1, iteration_factory)
        density_potential = self.state.density_potential
        length = self.state.length
        electron_state = self.state.electron_states[0]
        for j in xrange(5):
            potential = static_potential + density_potential
            potential_offset = spsc_data.EnergyValue(
                potential[meta_info["well_start"]], potential.units)
            potential = potential - spsc_data.Potential(
                potential_offset.value * np.ones(
                    (len(potential), ), "float64"), potential_offset.units)
            potential.meta_info = meta_info
            solutions = solution_strategy.solve(potential, mass, length,
                                                (10.0**-20, 0))
            for i in xrange(len(solutions)):
                solution = solutions[i]
                if len(electron_state.wave_functions) > i:
                    electron_state.wave_functions[i] = solution[1]
                else:
                    electron_state.wave_functions.append(solution[1])
                energy_level = solution[0] + potential_offset
                if len(electron_state.energy_levels) > i:
                    electron_state.energy_levels[i] = energy_level
                else:
                    electron_state.energy_levels.append(energy_level)

            density_potential = self.__solve_puass()
            # density_potential = self.__solve_puass() + density_potential
            # density_potential.value = density_potential.value / 2
        self.state.density_potential = density_potential
Exemple #13
0
def superlattice_well(periods_num, well_length, lattice_well_length,
                      lattice_barrier_length):
    well_length.convert_to("nm")
    lattice_well_length.convert_to("nm")
    lattice_barrier_length.convert_to("nm")
    state = spsc_core.StateSimple()
    electron_state = spsc_core.ElectronStateSimple()
    length = spsc_data.LengthValue(0, "nm")
    lattice_length = spsc_data.LengthValue(0, "nm")
    for i in range(periods_num):
        lattice_length += lattice_well_length + lattice_barrier_length
    length += lattice_barrier_length * 2 + well_length + lattice_length * 2
    potential = spsc_data.Potential(
        np.ones((int(lattice_barrier_length.value * DOTS_PER_NM), ),
                "float64"), "eV")
    next_index = lattice_barrier_length.value * DOTS_PER_NM
    for i in range(periods_num):
        potential.append(
            spsc_data.Potential(
                np.zeros((int(lattice_well_length.value * DOTS_PER_NM), ),
                         "float64"), "eV"))
        potential.append(
            spsc_data.Potential(
                np.ones((int(lattice_barrier_length.value * DOTS_PER_NM), ),
                        "float64"), "eV"))
        next_index += lattice_well_length.value * DOTS_PER_NM + lattice_barrier_length.value * DOTS_PER_NM
    meta_info = {
        "well_start": int(next_index),
        "lattice_bar_width": int(lattice_barrier_length.value * DOTS_PER_NM),
        "lattice_well_width": int(lattice_well_length.value * DOTS_PER_NM)
    }
    potential.append(
        spsc_data.Potential(
            np.zeros((int(well_length.value * DOTS_PER_NM), ), "float64"),
            "eV"))
    next_index += well_length.value * DOTS_PER_NM
    meta_info["well_end"] = int(next_index)
    empty_dots = int(length.value * DOTS_PER_NM) + 1 - len(potential)
    potential.append(
        spsc_data.Potential(np.zeros((empty_dots, ), "float64"), "eV"))
    potential.mirror()
    potential.meta_info = meta_info
    electron_state.static_potential = potential
    electron_state.mass = spsc_data.MassValue(constants.m_e)
    electron_state.sum_density = spsc_data.DensityValue(0, "m^-2")
    state.electron_states = [electron_state]
    state.length = length
    state.static_density = spsc_data.Density(
        np.zeros((len(potential, )), "float64"), "m^-2")
    state.density_potential = spsc_data.Potential(
        np.zeros((len(potential, )), "float64"))
    return state
Exemple #14
0
def single_well_sloped(well_length, slope):
    state = single_well(well_length)
    length = well_length * 3
    slope.convert_to(slope.units_default)
    length.convert_to(length.units_default)
    energy_diff = slope.value * length.value * constants.e
    energy_diff = spsc_data.EnergyValue(energy_diff)
    energy_diff.convert_to("eV")

    state.electron_states[0].static_potential.convert_to("eV")
    potential_arr = state.electron_states[0].static_potential.value
    slope_arr = np.zeros((len(potential_arr), ))
    dE = energy_diff.value / (len(slope_arr) - 1)
    for i in range(len(slope_arr)):
        slope_arr[i] = dE * i
    potential_arr = potential_arr + slope_arr
    well_min_index = potential_arr.argmin()
    well_min_value = potential_arr[well_min_index]
    potential_arr = potential_arr - np.full(
        (len(potential_arr), ), well_min_value)
    state.electron_states[0].static_potential = spsc_data.Potential(
        potential_arr, "eV")
    return state
Exemple #15
0
 def __init__(self):
     self.electron_states = []
     self.static_density = spsc_data.Density([])
     self.density_potential = spsc_data.Potential([])
     self.length = spsc_data.LengthValue(0)
Exemple #16
0
 def __init__(self):
     self.wave_functions = []
     self.energy_levels = []
     self.static_potential = spsc_data.Potential([])
     self.mass = spsc_data.MassValue(0)
     self.sum_density = spsc_data.DensityValue(0)