1#ifndef VIENNASHE_SHE_ASSEMBLE_SCATTERING_HPP
2#define VIENNASHE_SHE_ASSEMBLE_SCATTERING_HPP
21#include "viennagrid/mesh/mesh.hpp"
22#include "viennagrid/algorithm/voronoi.hpp"
64 template <
typename SHEQuantity,
typename ElementType>
66 ElementType
const & elem,
68 double kinetic_energy)
70 long result_index = index_H_hint;
72 if ( kinetic_energy < quan.get_kinetic_energy(elem, std::size_t(result_index))
73 || kinetic_energy > quan.get_kinetic_energy(elem, std::size_t(result_index)) )
77 double diff = kinetic_energy - quan.get_kinetic_energy(elem, std::size_t(result_index));
78 double diff_init = diff;
83 while ( (result_index <
static_cast<long>(quan.get_value_H_size() - 1)) && (result_index > 0)
84 && (diff * diff_init > 0) )
86 result_index += increment;
87 diff = kinetic_energy - quan.get_kinetic_energy(elem, std::size_t(result_index));
90 if (diff * diff_init > 0)
94 double error_1 = std::abs(diff);
95 double error_2 = error_1;
96 if ( (result_index - increment >= 0)
97 && (result_index - increment <
static_cast<long>(quan.get_value_H_size())) )
98 error_2 = std::abs(kinetic_energy - quan.get_kinetic_energy(elem, std::size_t(result_index - increment)));
100 if (error_2 < error_1)
101 return result_index - increment;
108 template <
typename ScatterProcessesT,
111 typename SHEQuantity,
114 typename ElementType,
115 typename CouplingMatrix>
117 DeviceType
const &
device,
119 SHEQuantity
const & quan,
120 MatrixType & A, VectorType & b,
121 ElementType
const & elem, std::size_t index_H,
122 CouplingMatrix
const & coupling_in_scatter,
123 CouplingMatrix
const & coupling_out_scatter)
125 typedef typename viennagrid::result_of::point<typename DeviceType::mesh_type>::type PointType;
136 const long row_index = quan.get_unknown_index(elem, index_H);
141 double kinetic_energy = quan.get_kinetic_energy(elem, index_H);
143 typedef typename ScatterProcessType::value_type scatter_descriptors_type;
145 const long expansion_order_mid =
static_cast<long>(quan.get_expansion_order(elem, index_H));
149 double box_volume = viennagrid::volume(elem);
156 for (
typename ScatterProcessesT::const_iterator scatter_process_it = scatter_processes.begin();
157 scatter_process_it != scatter_processes.end();
158 ++scatter_process_it)
160 ScatterProcessType
const & scatter_process = *(*scatter_process_it);
163 log::debug<log_assemble_scattering_operator>() <<
"* assemble_scattering_operator_on_box(): Assembling scattering process with ID " << scatter_process.id() << std::endl;
165 scatter_descriptors_type scatter_events = scatter_process(elem, kinetic_energy, quan.get_carrier_type_id());
170 for (std::size_t scatter_index = 0; scatter_index < scatter_events.size(); ++scatter_index)
172 const double initial_kinetic_energy = scatter_events[scatter_index].initial_energy();
173 const double final_kinetic_energy = scatter_events[scatter_index].final_energy();
174 const double rate = scatter_events[scatter_index].rate();
175 const double generation_rate = scatter_events[scatter_index].generation_rate();
178 if (rate <= 0 && generation_rate <= 0)
181 long initial_state_index_H =
energy_index_H(quan, elem,
static_cast<long>(index_H), initial_kinetic_energy);
182 long final_state_index_H =
energy_index_H(quan, elem,
static_cast<long>(index_H), final_kinetic_energy);
186 if ( (initial_state_index_H == -1) || (final_state_index_H == -1))
195 const double energy_height = std::min(
box_height(quan, elem,
static_cast<std::size_t
>(initial_state_index_H)),
196 box_height(quan, elem,
static_cast<std::size_t
>(final_state_index_H)));
198 const bool elastic_scattering_roundoff_error_prevention = (initial_state_index_H == final_state_index_H) && !odd_assembly;
203 if (initial_kinetic_energy <= kinetic_energy && initial_kinetic_energy >= kinetic_energy)
205 const long col_index = quan.get_unknown_index(elem,
static_cast<std::size_t
>(final_state_index_H));
210 double coefficient = 0;
214 coefficient = 2.0 * pi * rate * Z_initial * Z_final * box_volume * energy_height;
217 coefficient = 2.0 * pi * rate * Z_final * box_volume * energy_height;
220 throw std::runtime_error(
"assemble_scattering_operator_on_box(): Unknown SHE discretization type!");
223 static_cast<std::size_t
>(row_index),
static_cast<std::size_t
>(row_index),
225 coupling_out_scatter,
228 elastic_scattering_roundoff_error_prevention
233 log::debug<log_assemble_scattering_operator>() <<
"* assemble_scattering_operator_on_box(): out-scattering contribution: " << std::endl;
234 log::debug<log_assemble_scattering_operator>() <<
" 2.0 * pi * rate * Z_initial * Z_final * box_volume * energy_height " << std::endl;
235 log::debug<log_assemble_scattering_operator>() <<
" at (" << row_index <<
", " << row_index <<
")" << std::endl;
236 log::debug<log_assemble_scattering_operator>() <<
" rate = " << rate << std::endl;
237 log::debug<log_assemble_scattering_operator>() <<
" Z_initial = " << Z_initial << std::endl;
238 log::debug<log_assemble_scattering_operator>() <<
" Z_final = " << Z_final << std::endl;
239 log::debug<log_assemble_scattering_operator>() <<
" box_volume = " << box_volume << std::endl;
240 log::debug<log_assemble_scattering_operator>() <<
" energy_height = " << energy_height << std::endl;
243 if (with_full_newton)
249 throw std::runtime_error(
"assemble_scattering_operator_on_box(): Newton not available!");
251 static_cast<std::size_t
>(row_index),
252 2.0 * pi * rate * Z_initial * Z_final * box_volume * energy_height,
253 coupling_out_scatter,
256 quan.get_values(elem, index_H));
268 if (final_kinetic_energy <= kinetic_energy && final_kinetic_energy >= kinetic_energy)
270 const long col_index = quan.get_unknown_index(elem,
static_cast<std::size_t
>(initial_state_index_H));
275 double coefficient = 0;
279 coefficient = -2.0 * pi * rate * Z_initial * Z_final * box_volume * energy_height
280 - generation_rate * Z_initial * box_volume * energy_height;
283 coefficient = -2.0 * pi * rate * Z_final * box_volume * energy_height
284 - generation_rate * box_volume * energy_height;
287 throw std::runtime_error(
"assemble_scattering_operator_on_box(): Unknown SHE discretization type!");
290 static_cast<std::size_t
>(row_index),
static_cast<std::size_t
>(col_index),
295 elastic_scattering_roundoff_error_prevention
300 log::debug<log_assemble_scattering_operator>() <<
"* assemble_scattering_operator_on_box(): in-scattering contribution:" << std::endl;
301 log::debug<log_assemble_scattering_operator>() <<
" - 2.0 * pi * rate * Z_initial * Z_final * box_volume * energy_height" << std::endl;
302 log::debug<log_assemble_scattering_operator>() <<
" - generation_rate * Z_initial * box_volume * energy_height" << std::endl;
303 log::debug<log_assemble_scattering_operator>() <<
" at (" << row_index <<
", " << col_index <<
")" << std::endl;
304 log::debug<log_assemble_scattering_operator>() <<
" rate = " << rate << std::endl;
305 log::debug<log_assemble_scattering_operator>() <<
" Z_initial = " << Z_initial << std::endl;
306 log::debug<log_assemble_scattering_operator>() <<
" Z_final = " << Z_final << std::endl;
307 log::debug<log_assemble_scattering_operator>() <<
" box_volume = " << box_volume << std::endl;
308 log::debug<log_assemble_scattering_operator>() <<
" energy_height = " << energy_height << std::endl;
309 log::debug<log_assemble_scattering_operator>() <<
" generation_rate = " << generation_rate << std::endl;
312 if (with_full_newton)
318 throw std::runtime_error(
"assemble_scattering_operator_on_box(): Newton not available!");
320 static_cast<std::size_t
>(row_index),
321 - 2.0 * pi * rate * Z_initial * Z_final * box_volume * energy_height
322 - generation_rate * Z_initial * box_volume * energy_height,
326 quan.get_values(elem, index_H));
Common routines for the assembly of SHE equations.
Writes a possibly scaled block matrix to the system matrix. Includes similar functionality for comput...
Defines a set of checker functors for micro-tests within ViennaSHE.
The main SHE configuration class. To be adjusted by the user for his/her needs.
viennashe::physics::dispersion_proxy dispersion_relation(viennashe::carrier_type_id ctype) const
Returns the dispersion relation for electrons.
nonlinear_solver_config_type & nonlinear_solver()
Returns the configuration object for the nonlinear solver.
she_discretization_type_id she_discretization_type() const
MeshT const & mesh() const
Returns the underlying mesh.
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Iteration over all spherical harmonics indices up to order L, with increasing indices l and m.
long id() const
Returns the current linear solver ID.
Contains the dispersion relations for different materials and different polarities.
Defines several filter functors for the device. A filter functor returns true if the supplied argumen...
Provides the SHE coupling matrices and computes higher-order coupling matrices if required....
Implementation of numerical integration routines.
A logging facility providing fine-grained control over logging in ViennaSHE.
Provides a number of fundamental math constants.
harmonics_iteration_type
An enumeration of spherical harmonics types (all, even, odd) ViennaSHE supports.
@ EVEN_HARMONICS_ITERATION_ID
@ ODD_HARMONICS_ITERATION_ID
bool is_odd_assembly(T const &, T const &)
double cell_connection_length(MeshT const &, CellT const &, CellT const &)
Static dispatcher for computing the connection between two cells adjacent to a facet....
double averaged_density_of_states(SHEQuantity const &quan, viennashe::config::dispersion_relation_type const &dispersion, CellFacetType const &cell_facet, std::size_t index_H)
Returns the density of states around a vertex or an edge at total energy specified by index_H....
void assemble_scattering_operator_on_box(ScatterProcessesT const &scatter_processes, DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, MatrixType &A, VectorType &b, ElementType const &elem, std::size_t index_H, CouplingMatrix const &coupling_in_scatter, CouplingMatrix const &coupling_out_scatter)
double box_height(SHEQuantity const &quan, ElementType const &elem, std::size_t index_H)
Returns the height of the control box with respect to energy at the provided element (vertex or edge)...
long energy_index_H(SHEQuantity const &quan, ElementType const &elem, long index_H_hint, double kinetic_energy)
Finds the closest H-index for the provided kinetic energy.
void add_block_matrix(SystemMatrixType &system_matrix, std::size_t row_index, std::size_t col_index, double prefactor, BlockMatrixType const &coupling_matrix, RowIndexIterator row_iter, ColumnIndexIterator const &col_iter_init, bool elastic_scattering_roundoff_error_prevention=false)
Writes a sub-matrix of a block matrix 'coupling_matrix' into the global system matrix,...
void subtract_folded_block_vector(VectorType &residual, std::size_t row_index, double prefactor, BlockMatrixType const &coupling_matrix, RowIndexIterator row_iter, ColumnIndexIterator const &col_iter_init, double const *fold_vector)
Writes a sub-matrix of a block matrix 'coupling_matrix' to the residual vector. The columns are 'fold...
The main ViennaSHE namespace. All functionality resides inside this namespace.
@ SHE_DISCRETIZATION_EVEN_ODD_ORDER_GENERALIZED_DF
@ SHE_DISCRETIZATION_EVEN_ODD_ORDER_DF
Provides a number of fundamental constants. All constants in SI units.
Returns a few helper routines for computing physical quantities. To be replaced in the future.
File to gather all scattering operators.
Implementation of spherical harmonics plus helper functions.
static const double pi
Pi.
@ newton_nonlinear_solver
Gummel iteration.
Defines the log keys used within the viennashe::she namespace.