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
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)
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
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
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]
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
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
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
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
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
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
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
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
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
def __init__(self): self.electron_states = [] self.static_density = spsc_data.Density([]) self.density_potential = spsc_data.Potential([]) self.length = spsc_data.LengthValue(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)