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, 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 solve(self, E, solution_start): self._reset_to_default_units() E.convert_to(E.units_default) E = E.value N = len(self.potential) solution = (spsc_data.WaveFunction(np.zeros( (N, ))), spsc_data.WaveFunction(np.zeros((N, )))) gamma = 2.0 * (self.length.value**2) / (constants.h_plank**2) (A, B) = self._get_initial_AB(E, solution_start) potential_level = self.potential[0] for i in xrange(N): x = float(i) / (N - 1) if self.potential[i] != potential_level: AB_transition_matrix = self._get_AB_transition_matrix(E, i) (A, B) = np.dot(AB_transition_matrix, np.array([A, B])) potential_level = self.potential[i] if E < potential_level: k = np.sqrt((potential_level - E) * gamma * self.mass.value[i]) solution[0][i] = A * np.exp(k * x) + B * np.exp(-k * x) solution[1][i] = A * k * np.exp(k * x) - B * k * np.exp(-k * x) else: k = np.sqrt((E - potential_level) * gamma * self.mass.value[i]) solution[0][i] = A * np.sin(k * x) + B * np.cos(k * x) solution[1][i] = A * k * np.cos(k * x) - B * k * np.sin(k * x) return solution
def _prepare_wave_function(self, solution_candidate): middle_index = self._get_middle_index() k = solution_candidate[0][middle_index] / solution_candidate[2][ middle_index] wave_function_arr = np.concatenate( (solution_candidate[0].value[:middle_index + 1], k * solution_candidate[2].value[middle_index + 1:])) wave_function = spsc_data.WaveFunction(wave_function_arr) wave_function.normalize() return wave_function
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, 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, ))), spsc_data.WaveFunction(np.zeros( (N, ))), spsc_data.WaveFunction(np.zeros((N, )))) potential_threshold = abs(2.0 * constants.e * self.slope.value * self.length.value / (len(self.potential) - 1)) (A, B) = self._get_initial_left_AB(E, solution_start[0], solution_start[1]) U = self._get_U(0) U.convert_to("eV") for i in xrange(N * 2 / 3): if i > 0 and abs(self.potential[i] - self.potential[i - 1]) > potential_threshold: (A, B) = self._get_AB(E, i - 1, i, solution[0][i - 1], solution[1][i - 1]) U = self._get_U(i) airy_argument = self._get_airy_argument(E, U, i) airy = special.airy(airy_argument) solution[0][i] = A * airy[0] + B * airy[2] solution[1][i] = A * airy[1] + B * airy[3] (A, B) = self._get_initial_right_AB(E, solution_start[2], solution_start[3]) U = self._get_U(N - 1) for i in xrange(N - 1, N / 3, -1): if i < N - 1 and abs(self.potential[i] - self.potential[i + 1]) > potential_threshold: (A, B) = self._get_AB(E, i + 1, i, solution[2][i + 1], solution[3][i + 1]) U = self._get_U(i) airy_argument = self._get_airy_argument(E, U, i) airy = special.airy(airy_argument) solution[2][i] = A * airy[0] + B * airy[2] solution[3][i] = A * airy[1] + B * airy[3] 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)