1#ifndef VIENNASHE_SHE_ASSEMBLE_COMMON_HPP
2#define VIENNASHE_SHE_ASSEMBLE_COMMON_HPP
20#include "viennagrid/mesh/mesh.hpp"
21#include "viennagrid/algorithm/norm.hpp"
22#include "viennagrid/algorithm/volume.hpp"
23#include "viennagrid/algorithm/voronoi.hpp"
55 template <
typename PotentialAccessorType,
56 typename ConfigType,
typename TagType>
58 viennagrid::element<TagType, ConfigType>
const & elem)
60 std::vector<long> ret;
61 for (std::size_t i=0; i<viennagrid::vertices(elem).size(); ++i)
63 if (potential_index(viennagrid::vertices(elem)[i]) >= 0)
64 ret.push_back(potential_index(viennagrid::vertices(elem)[i]));
69 template <
typename PotentialAccessorType,
72 viennagrid::element<viennagrid::vertex_tag, ConfigType>
const & elem)
74 std::vector<long> ret;
75 if (potential_index(elem) >= 0)
76 ret.push_back(potential_index(elem));
87 template <
typename T,
typename U>
97 template <
typename MeshT,
typename CellT>
100 assert(
bool(
"Logic error: cell_connection_length() for cell called!"));
108 template <
typename MeshT,
typename FacetT,
typename CellT>
111 typedef typename viennagrid::result_of::const_coboundary_range<MeshT, FacetT, CellT>::type CellOnFacetContainer;
112 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
114 CellOnFacetContainer cells_on_facet(mesh, viennagrid::handle(mesh, facet));
116 if (cells_on_facet.size() < 2)
118 assert(
bool(
"Logic error: cell_connection_length() called for facet on boundary!"));
121 CellOnFacetIterator cofit = cells_on_facet.begin();
122 CellT
const & c1 = *cofit;
124 CellT
const & c2 = *cofit;
129 template <
typename DeviceType>
135 template <
typename DeviceType,
typename ElementType>
152 template <
typename DispersionRelation>
153 double integral_Z_over_hk(
double energy_minus,
double energy_plus, DispersionRelation
const & dispersion)
155 if (energy_plus < energy_minus)
157 std::stringstream ss;
158 ss <<
"Invalid interval in integral_Z_over_hk(): [" << energy_minus <<
", " << energy_plus <<
"]";
162 return 0.5 * ( dispersion.density_of_states(energy_plus) * dispersion.velocity(energy_plus)
163 - dispersion.density_of_states(energy_minus) * dispersion.velocity(energy_minus) );
176 template <
typename MatrixType,
typename CellType,
typename PolarityTag>
178 CellType
const & c1, CellType
const & c2, PolarityTag
const & polarity,
179 viennagrid::cartesian_cs<1>)
181 typedef typename viennagrid::result_of::point<CellType>::type PointType;
184 PointType p3 = viennagrid::centroid(c2) - viennagrid::centroid(c1);
185 p3 /= viennagrid::norm(p3);
190 log::debug<log_coupling_matrix_in_direction>() << c1 << std::endl;
191 log::debug<log_coupling_matrix_in_direction>() << c2 << std::endl;
199 MatrixType result = m1 * (p3[0] * sqrt(m_d / m_t));
213 template <
typename MatrixType,
typename CellType,
typename PolarityTag>
215 CellType
const & c1, CellType
const & c2, PolarityTag
const & polarity,
216 viennagrid::cartesian_cs<2>)
218 typedef typename viennagrid::result_of::point<CellType>::type PointType;
221 PointType p3 = viennagrid::centroid(c2) - viennagrid::centroid(c1);
222 p3 /= viennagrid::norm(p3);
224 if (!p3[0] && !p3[1])
227 log::debug<log_coupling_matrix_in_direction>() << c1 << std::endl;
228 log::debug<log_coupling_matrix_in_direction>() << c2 << std::endl;
236 MatrixType result = m1 * (p3[0] * sqrt(m_d / m_t));
237 result += m2 * (p3[1] * sqrt(m_d / m_t));
251 template <
typename MatrixType,
typename CellType,
typename PolarityTag>
253 CellType
const & c1, CellType
const & c2, PolarityTag
const & polarity,
254 viennagrid::cartesian_cs<3>)
256 typedef typename viennagrid::result_of::point<CellType>::type PointType;
258 PointType p3 = viennagrid::centroid(c2) - viennagrid::centroid(c1);
259 p3 /= viennagrid::norm(p3);
265 MatrixType result = m1 * (p3[0] * sqrt(m_d / m_t));
266 result += m2 * (p3[1] * sqrt(m_d / m_t));
267 result += m3 * (p3[2] * sqrt(m_d / m_l));
283 template <
typename MatrixType,
typename VertexType,
typename PolarityTag>
285 VertexType
const & v1, VertexType
const & v2, PolarityTag
const & polarity)
287 typedef typename viennagrid::result_of::point<VertexType>::type PointType;
288 typedef typename viennagrid::result_of::coordinate_system<PointType>::type CoordinateSystemTag;
301 template <
typename MatrixType,
typename VectorType,
typename IteratorType>
303 std::size_t row_start,
305 MatrixType
const & coupling_matrix,
306 IteratorType row_iter)
308 assert(prefactor == prefactor &&
bool(
"Writing nan to boundary!"));
312 std::size_t row = row_start;
313 for (; row_iter.valid(); ++row_iter)
315 rhs[row] -= prefactor * coupling_matrix(std::size_t(*row_iter), 0);
324 template <
typename DeviceType,
typename SHEQuantity,
typename FacetType>
326 SHEQuantity
const & quan,
327 FacetType
const & facet,
330 typedef typename DeviceType::mesh_type MeshType;
332 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
334 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
335 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
339 CellOnFacetIterator cofit = cells_on_facet.begin();
340 CellType
const & c1 = *cofit;
343 if (cofit == cells_on_facet.end())
344 return quan.get_kinetic_energy(c1, index_H);
346 CellType
const & c2 = *cofit;
349 return quan.get_kinetic_energy(c1, index_H) + quan.get_kinetic_energy(c2, index_H) / 2.0;
351 return ( quan.get_kinetic_energy(c1, index_H - 1) + quan.get_kinetic_energy(c2, index_H - 1)
352 + quan.get_kinetic_energy(c1, index_H) + quan.get_kinetic_energy(c2, index_H)
358 template <
typename DeviceType,
typename SHEQuantity,
typename FacetType>
360 SHEQuantity
const & quan,
361 FacetType
const & facet,
364 typedef typename DeviceType::mesh_type MeshType;
366 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
368 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
369 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
373 CellOnFacetIterator cofit = cells_on_facet.begin();
374 CellType
const & c1 = *cofit;
377 if (cofit == cells_on_facet.end())
378 return quan.get_kinetic_energy(c1, index_H);
380 CellType
const & c2 = *cofit;
382 if (index_H == quan.get_value_H_size() - 1)
383 return quan.get_kinetic_energy(c1, index_H) + quan.get_kinetic_energy(c2, index_H) / 2.0;
385 return ( quan.get_kinetic_energy(c1, index_H + 1) + quan.get_kinetic_energy(c2, index_H + 1)
386 + quan.get_kinetic_energy(c1, index_H) + quan.get_kinetic_energy(c2, index_H)
394 template <
typename SHEQuantity,
typename CellType>
398 std::size_t index_H)
const
400 const double distance =
viennagrid::norm_2(viennagrid::centroid(c1) - viennagrid::centroid(c2));
402 const double ekin_v2 = quan.get_kinetic_energy(c2, index_H);
403 const double ekin_v1 = quan.get_kinetic_energy(c1, index_H);
405 return (ekin_v2 - ekin_v1) / distance;
411 template <
typename SHEQuantity,
typename ElementType>
413 ElementType
const & elem,
418 double energy_height = 0;
421 energy_height = std::fabs(quan.get_kinetic_energy(elem, index_H) - quan.get_kinetic_energy(elem, index_H-1));
423 if (index_H < quan.get_value_H_size() - 1)
424 energy_height += std::fabs(quan.get_kinetic_energy(elem, index_H+1) - quan.get_kinetic_energy(elem, index_H));
426 return energy_height / 2.0;
431 template <
typename SHEQuantity,
432 typename CellFacetType>
435 CellFacetType
const & cell_facet,
440 double Z = dispersion.
density_of_states(quan.get_kinetic_energy(cell_facet, index_H));
441 double num_contributions = 1;
443 if (index_H < quan.get_value_H_size() - 1)
446 double kin_energy = (quan.get_kinetic_energy(cell_facet, index_H)
447 + quan.get_kinetic_energy(cell_facet, index_H + 1)) / 2.0;
454 double kin_energy = (quan.get_kinetic_energy(cell_facet, index_H)
455 + quan.get_kinetic_energy(cell_facet, index_H - 1)) / 2.0;
459 Z /= num_contributions;
475 template <
typename SHEQuantity,
476 typename CellFacetType>
479 CellFacetType
const & cell_facet,
484 double v = dispersion.
velocity(quan.get_kinetic_energy(cell_facet, index_H));
485 double num_contributions = 1;
487 if (index_H < quan.get_value_H_size() - 1)
490 double kin_energy = (quan.get_kinetic_energy(cell_facet, index_H)
491 + quan.get_kinetic_energy(cell_facet, index_H + 1)) / 2.0;
492 v += dispersion.
velocity(kin_energy);
498 double kin_energy = (quan.get_kinetic_energy(cell_facet, index_H)
499 + quan.get_kinetic_energy(cell_facet, index_H - 1)) / 2.0;
500 v += dispersion.
velocity(kin_energy);
503 v /= num_contributions;
505 return v *
box_height(quan, cell_facet, index_H);
519 template <
typename SHEQuantity,
520 typename CellFacetType>
523 CellFacetType
const & cell_facet,
528 double kin_energy_center = quan.get_kinetic_energy(cell_facet, index_H);
530 double num_contributions = 1;
532 if (index_H < quan.get_value_H_size() - 1)
535 double kin_energy = (quan.get_kinetic_energy(cell_facet, index_H)
536 + quan.get_kinetic_energy(cell_facet, index_H + 1)) / 2.0;
543 double kin_energy = (quan.get_kinetic_energy(cell_facet, index_H)
544 + quan.get_kinetic_energy(cell_facet, index_H - 1)) / 2.0;
548 vZ /= num_contributions;
550 return vZ *
box_height(quan, cell_facet, index_H);
554 template <
typename SHEQuantity,
typename CellType>
559 double kin_energy = 0.0;
561 kin_energy = quan.get_kinetic_energy(c, index_H);
563 if (kin_energy <= 0.0)
565 if (index_H < quan.get_value_H_size() - 1)
566 return quan.get_kinetic_energy(c, index_H + 1) / 2.0;
Writes a possibly scaled block matrix to the system matrix. Includes similar functionality for comput...
bool has_contact_potential(cell_type const &c) const
Returns true if a contact potential has been set for the respective vertex.
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...
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)
double velocity(double ekin, double theta=0, double phi=0) const
Returns the velocity as a function of kinetic energy (and angles, eventually)
Exception for the case that a vertex has a coupling with itself.
double operator()(SHEQuantity const &quan, CellType const &c1, CellType const &c2, std::size_t index_H) const
Exception for the case that neither electrons nor holes are selected for the simulation.
The SHE configuration class is defined here.
Contains the dispersion relations for different materials and different polarities.
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.
logger< true > error()
Used to log errors. The logging level is logERROR.
VectorType::value_type norm_2(VectorType const &v)
std::vector< long > get_potential_indices(PotentialAccessorType const &potential_index, viennagrid::element< TagType, ConfigType > const &elem)
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....
bool has_contact_potential(DeviceType const &device, typename viennagrid::result_of::cell< typename DeviceType::mesh_type >::type const &c)
double integral_Z_over_hk(double energy_minus, double energy_plus, DispersionRelation const &dispersion)
Computes \int_a^b Z/(hbar * k) dE, where a and b are the energy boundaries, Z is the density of state...
double integral_v(SHEQuantity const &quan, viennashe::config::dispersion_relation_type const &dispersion, CellFacetType const &cell_facet, std::size_t index_H)
Computes \int v dH using a Simpson rule, where v is velocity.
double lower_kinetic_energy_at_facet(DeviceType const &device, SHEQuantity const &quan, FacetType const &facet, std::size_t index_H)
Returns the lower kinetic energy for the discretization box associated with the edge 'edge'.
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....
MatrixType coupling_matrix_in_direction(MatrixType const &m1, MatrixType const &m2, MatrixType const &m3, VertexType const &v1, VertexType const &v2, PolarityTag const &polarity)
Returns dot(M, n), where M=(m1, m2, m3) is the vector of coupling matrices, and n = v2 - v1 is the di...
MatrixType coupling_matrix_in_direction_impl(MatrixType const &m1, MatrixType const &m2, MatrixType const &m3, CellType const &c1, CellType const &c2, PolarityTag const &polarity, viennagrid::cartesian_cs< 1 >)
Returns dot(M, n), where M=(m1, m2, m3) is the vector of coupling matrices, and n = v2 - v1 is the di...
double integral_vZ(SHEQuantity const &quan, viennashe::config::dispersion_relation_type const &dispersion, CellFacetType const &cell_facet, std::size_t index_H)
Computes \int v Z dH using a Simpson rule, where v is velocity and Z is the density of states.
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)...
void write_boundary(VectorType &rhs, std::size_t row_start, double prefactor, MatrixType const &coupling_matrix, IteratorType row_iter)
Write Dirichlet boundary conditions to right hand side.
double upper_kinetic_energy_at_facet(DeviceType const &device, SHEQuantity const &quan, FacetType const &facet, std::size_t index_H)
Returns the upper kinetic energy of the discretization box for the edge 'edge'.
double averaged_kinetic_energy(SHEQuantity const &quan, CellType const &c, std::size_t index_H)
Returns the averaged kinetic energy in the box centered at a vertex v with total energy index index_H...
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.
Implementation of spherical harmonics plus helper functions.
static double longitudinal_effective_mass(viennashe::carrier_type_id ctype)
static double transverse_effective_mass(viennashe::carrier_type_id ctype)
static double dos_effective_mass(viennashe::carrier_type_id ctype)
Defines the log keys used within the viennashe::she namespace.