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.