1#ifndef VIENNASHE_SHE_ASSEMBLE_EE_SCATTERING_HPP
2#define VIENNASHE_SHE_ASSEMBLE_EE_SCATTERING_HPP
18#include "viennagrid/mesh/mesh.hpp"
54 template <
typename DispersionRelation>
55 double ee_scattering_rate(DispersionRelation
const & dispersion,
double kinetic_energy,
double n,
double T)
62 double lambda_sq = 0.0;
63 double scattering_rate = 0.0;
65 const double prefactor = (2.0 * pi * n * q * q * q * q) / (hbar * eps_Si * eps_Si);
67 double norm_k = dispersion.norm_k(kinetic_energy);
72 lambda_sq = (eps_Si * kB * T) / (q * q * n);
73 double a = 4.0 * lambda_sq * norm_k * norm_k;
75 scattering_rate = prefactor
76 * 0.5 * (std::log(1.0 + a) - (a / (1.0 + a)) ) / 4.0 / std::pow(norm_k, 4.0);
78 return scattering_rate;
94 template <
typename DeviceType,
typename SHEQuantityT,
typename MatrixType,
typename VectorType>
97 SHEQuantityT
const & quan,
98 SHEQuantityT
const & quan_old,
99 MatrixType & matrix, VectorType & rhs
102 typedef typename DeviceType::mesh_type MeshType;
104 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
105 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
107 typedef typename viennagrid::result_of::const_facet_range<MeshType>::type FacetContainer;
108 typedef typename viennagrid::result_of::iterator<FacetContainer>::type FacetIterator;
110 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
111 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
113 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
114 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
130 double damping = 1e-4;
137 density_n(conf, quan_old);
145 const std::size_t num_harmonics = (L_max+1) * (L_max+1);
146 CouplingMatrixType scatter_op_in(num_harmonics, num_harmonics);
147 CouplingMatrixType scatter_op_out(num_harmonics, num_harmonics);
149 for (std::size_t i = 0; i < (L_max+1) * (L_max+1); ++i)
150 scatter_op_out(i,i) += 1.0;
151 scatter_op_in(0,0) += 1.0;
157 CellContainer cells(mesh);
158 for (CellIterator cit = cells.begin();
163 const double carrier_density = density_n(*cit);
164 const double kinetic_energy_star = energy_n(*cit);
168 for (std::size_t index_H = 1; index_H < quan.get_value_H_size() - 1; ++index_H)
171 const long row_index = quan.get_unknown_index(*cit, index_H);
176 const double kinetic_energy = quan.get_kinetic_energy(*cit, index_H);
178 if (kinetic_energy <= 0.0)
181 if (carrier_density <= 0)
183 log::warn() <<
"* assemble_ee_scattering(): Warning: Carrier_density zero!" << std::endl;
185 if (kinetic_energy_star <= 0)
187 log::warn() <<
"* assemble_ee_scattering(): Warning: kinetic_energy_star zero or less ! kinetic_energy_star = " << kinetic_energy_star << std::endl;
190 const double box_volume = viennagrid::volume(*cit);
191 const long expansion_order_mid =
static_cast<long>(quan.get_expansion_order(*cit, index_H));
192 const double energy_height =
box_height(quan, *cit, index_H);
197 std::size_t Estar_index = 1;
198 for ( ; Estar_index < quan_old.get_value_H_size() - 1; ++Estar_index)
200 if (quan_old.get_kinetic_energy(*cit, Estar_index) > kinetic_energy_star)
204 double f_Estar = quan_old.get_values(*cit, Estar_index)[0] / carrier_density;
207 const double dos_norm = dispersion_relation.
density_of_states(quan_old.get_kinetic_energy(*cit, Estar_index));
211 std::cout <<
"kinetic_energy = " << quan_old.get_kinetic_energy(*cit, Estar_index) << std::endl;
212 std::cout <<
"dos_norm = " << dos_norm << std::endl;
214 else f_Estar = f_Estar / dos_norm;
219 log::warn() <<
"* assemble_ee_scattering(): Warning: f_Estar is smaller or equal to zero!" << std::endl;
223 double out_scattering_coeff = 0.0;
224 double kinetic_energy_max = quan.get_kinetic_energy(*cit, quan_old.get_value_H_size() - 2);
226 double prefactor = pow(1.0 / Y_00(0, 0), 3) / 2.0;
228 for (std::size_t index_H_prime = 1; index_H_prime < quan.get_value_H_size() - 1; ++index_H_prime)
230 const double kinetic_energy_prime = quan.get_kinetic_energy(*cit, index_H_prime);
232 if (kinetic_energy_prime <= 0)
236 const double energy_argument = kinetic_energy + kinetic_energy_star - kinetic_energy_prime;
237 if (energy_argument < 0)
240 if (energy_argument > kinetic_energy_max)
244 std::abs(kinetic_energy - kinetic_energy_prime),
251 double f_00_prime = (quan_old.get_values(*cit, index_H_prime)[0]) / carrier_density;
253 const double dos_norm = dispersion_relation.
density_of_states(kinetic_energy_prime);
254 if (dos_norm <= 0.0) f_00_prime = 0;
255 else f_00_prime = f_00_prime / dos_norm;
259 std::size_t energy_index = 1;
260 for ( ; energy_index < quan.get_value_H_size() - 1; ++energy_index)
262 if (quan.get_kinetic_energy(*cit, energy_index) > energy_argument)
266 if (energy_index == quan.get_value_H_size() - 2)
269 double in_scattering_coeff = prefactor
276 if (quan.get_unknown_index(*cit, energy_index) >= 0)
278 std::size_t(row_index), std::size_t(quan.get_unknown_index(*cit, energy_index)),
279 - damping * in_scattering_coeff * f_00_prime * box_volume * energy_height,
288 out_scattering_coeff += prefactor
296 double coeff = damping * out_scattering_coeff * f_Estar * box_volume * energy_height;
299 std::size_t(row_index), std::size_t(row_index),
313 FacetContainer facets(mesh);
314 for (FacetIterator fit = facets.begin();
318 CellOnFacetContainer cells_on_facet(
device.
mesh(), fit.handle());
320 if (cells_on_facet.size() < 2)
323 CellOnFacetIterator cofit = cells_on_facet.begin();
324 CellType
const & c1 = *cofit;
326 CellType
const & c2 = *cofit;
328 double connection_len =
viennagrid::norm_2(viennagrid::centroid(c1) - viennagrid::centroid(c2));
332 for (std::size_t index_H = 1; index_H < quan.get_value_H_size() - 1; ++index_H)
334 const long row_index = quan.get_unknown_index(*fit, index_H);
339 const double box_volume = viennagrid::volume(*fit) * connection_len;
341 const long expansion_order_mid =
static_cast<long>(quan.get_expansion_order(*fit, index_H));
346 const double kinetic_energy_at_edge = quan.get_kinetic_energy(*fit, index_H);
347 const double energy_height =
box_height(quan, *fit, index_H);
353 double carrier_density = std::sqrt(density_n(c1) * density_n(c2));
354 if (carrier_density <= 0)
355 log::warn() <<
"* assemble_ee_scattering(): Warning: carrier_density zero!" << std::endl;
359 double kinetic_energy_star = (energy_n(c1) + energy_n(c2)) / 2.0;
360 if (kinetic_energy_star <= 0)
361 log::warn() <<
"* assemble_ee_scattering(): Warning: kinetic_energy_star zero!" << std::endl;
363 std::size_t Estar_index = 1;
364 for ( ; Estar_index < quan_old.get_value_H_size(); ++Estar_index)
366 if (quan_old.get_kinetic_energy(*fit, Estar_index) > kinetic_energy_star)
374 if ( quan_old.get_unknown_mask(c1) ) f_Estar += quan_old.get_boundary_value(c1, Estar_index);
375 else f_Estar += quan_old.get_values(c1, Estar_index)[0];
377 if ( quan_old.get_unknown_mask(c2) ) f_Estar += quan_old.get_boundary_value(c2, Estar_index);
378 else f_Estar += quan_old.get_values(c2, Estar_index)[0];
380 f_Estar = f_Estar / (2.0 * carrier_density);
386 const double dos_norm = dispersion_relation.
density_of_states(quan_old.get_kinetic_energy(*fit, Estar_index));
387 if (dos_norm <= 0.0) f_Estar = 0.0;
388 else f_Estar = f_Estar / dos_norm;
392 double kinetic_energy_max = quan.get_kinetic_energy(*fit, quan_old.get_value_H_size() - 2);
393 double out_scattering_coeff = 0.0;
395 double prefactor = pow(1.0 / Y_00(0, 0), 3);
397 for (std::size_t index_H_prime = 1; index_H_prime < quan.get_value_H_size() - 1; ++index_H_prime)
399 double kinetic_energy_prime = quan.get_kinetic_energy(*fit, index_H_prime);
400 if (kinetic_energy_prime < 0)
404 const double energy_argument = kinetic_energy_at_edge + kinetic_energy_star - kinetic_energy_prime;
405 if (energy_argument < 0)
408 if (energy_argument > kinetic_energy_max)
412 std::abs(kinetic_energy_at_edge - kinetic_energy_prime),
424 out_scattering_coeff += prefactor
432 const double coeff = damping * out_scattering_coeff * f_Estar * box_volume * energy_height;
435 std::size_t(row_index), std::size_t(row_index),
Generic assembly of the scattering operator(s) is implemented here.
Writes a possibly scaled block matrix to the system matrix. Includes similar functionality for comput...
Provides an accessor for the carrier density.
Provides an accessor for the average carrier energy.
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.
long max_expansion_order() const
Returns the current maximum expansion order.
double get_lattice_temperature(cell_type const &c) const
Returns the lattice temperature on a cell.
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.
A proxy object for a dispersion relation. Does NOT take ownership of the provided pointer!
double density_of_states(double ekin, double theta=0, double phi=0) const
Returns the density of states as a function of kinetic energy (and angles, eventually)
An accessor for the average carrier energy at each point inside the device.
An accessor for the carrier density in the device by reference
Provides a convenience wrapper for accessing the distribution function coefficients over the device.
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.
logger< true > warn()
Used to log warnings. The logging level is logWARNING.
@ EVEN_HARMONICS_ITERATION_ID
@ ODD_HARMONICS_ITERATION_ID
VectorType::value_type norm_2(VectorType const &v)
void assemble_ee_scattering(DeviceType const &device, viennashe::config const &conf, SHEQuantityT const &quan, SHEQuantityT const &quan_old, MatrixType &matrix, VectorType &rhs)
Interface function for electron-electron scattering. Differs significantly from ac,...
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)...
double ee_scattering_rate(DispersionRelation const &dispersion, double kinetic_energy, double n, double T)
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,...
The main ViennaSHE namespace. All functionality resides inside this namespace.
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.
Provides the exceptions used inside the viennashe::she namespace.
File to gather all scattering operators.
Implementation of spherical harmonics plus helper functions.
static double permittivity()
static const double pi
Pi.
static const double q
Elementary charge.
static const double kB
Boltzmann constant.
static const double hbar
Modified Planck constant.
Defines the log keys used within the viennashe::she namespace.