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.