1#ifndef VIENNASHE_DD_ASSEMBLE_HPP
2#define VIENNASHE_DD_ASSEMBLE_HPP
26#include "viennagrid/mesh/mesh.hpp"
27#include "viennagrid/mesh/coboundary_iteration.hpp"
28#include "viennagrid/algorithm/volume.hpp"
75 template <
typename CellType,
typename SpatialUnknownT,
typename SHEUnknownT,
typename MatrixType>
77 CellType
const & cell,
78 SpatialUnknownT
const & np_density,
79 SHEUnknownT
const & f_np,
80 MatrixType & A, std::size_t row_index,
double box_volume)
82 const double polarity = (f_np.get_carrier_type_id() ==
ELECTRON_TYPE_ID) ? -1.0 : 1.0;
87 const long np_index = np_density.get_unknown_index(cell);
94 for (std::size_t index_H = 1; index_H < f_np.get_value_H_size() - 1; ++index_H)
96 long col_index = f_np.get_unknown_index(cell, index_H);
99 double energy_mid = f_np.get_kinetic_energy(cell, index_H);
100 double energy_upper = (f_np.get_kinetic_energy(cell, index_H + 1) + energy_mid) / 2.0;
103 if (energy_upper <= 0.0)
109 A(row_index, std::size_t(col_index)) = polarity
126 template <
typename DeviceType,
typename CellType,
typename SpatialUnknownT,
typename SHEUnknownT>
128 CellType
const & cell,
129 SpatialUnknownT
const & np_density,
130 SHEUnknownT
const & f_np)
137 return np_density.get_value(cell);
142 return density_wrapper(cell);
162 template <
typename DeviceType,
171 typedef typename DeviceType::mesh_type MeshType;
173 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
174 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
176 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
177 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
179 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
180 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
206 CellContainer cells(mesh);
207 for (CellIterator cit = cells.begin();
212 const long row_index2 =
potential.get_unknown_index(*cit);
215 const std::size_t row_index = std::size_t(row_index2);
217 PointType centroid_cell = viennagrid::centroid(*cit);
219 const double potential_center =
potential.get_value(*cit);
224 A(row_index, row_index) = 0;
229 FacetOnCellContainer facets(*cit);
230 for (FacetOnCellIterator focit = facets.begin();
231 focit != facets.end();
236 if (!other_cell_ptr)
continue;
238 PointType centroid_other_cell = viennagrid::centroid(*other_cell_ptr);
239 PointType cell_connection = centroid_other_cell - centroid_cell;
240 PointType cell_connection_normalized = cell_connection / viennagrid::norm(cell_connection);
243 const long col_index =
potential.get_unknown_index(*other_cell_ptr);
245 const double weighted_interface_area = viennagrid::volume(*focit) * viennagrid::inner_prod(facet_unit_normal, cell_connection_normalized);
246 const double potential_outer =
potential.get_value(*other_cell_ptr);
251 PointType facet_center = viennagrid::centroid(*focit);
252 double connection_in_cell = viennagrid::norm(facet_center - centroid_cell);
253 double connection_in_other_cell = viennagrid::norm(facet_center - centroid_other_cell);
254 const double permittivity_mean = (connection_in_cell + connection_in_other_cell) /
255 (connection_in_cell/permittivity_center + connection_in_other_cell/
permittivity(*other_cell_ptr));
257 A(row_index, std::size_t(col_index)) = permittivity_mean * weighted_interface_area / connection_len;
258 A(row_index, row_index) -= permittivity_mean * weighted_interface_area / connection_len;
259 b[row_index] -= permittivity_mean * weighted_interface_area * (potential_outer - potential_center) / connection_len;
263 A(row_index, row_index) -= permittivity_center * weighted_interface_area / connection_len;
264 b[row_index] -= permittivity_center * weighted_interface_area / connection_len * (
potential.get_boundary_value(*other_cell_ptr) - potential_center);
268 const double cell_volume = viennagrid::volume(*cit);
270 const double value_n = detail::get_carrier_density_for_poisson<DeviceType>(conf, *cit, n_density, f_n);
271 const double value_p = detail::get_carrier_density_for_poisson<DeviceType>(conf, *cit, p_density, f_p);
288 if (with_full_newton)
305 b[row_index] += fixed_charge(*cit) * cell_volume;
311 typedef typename DeviceType::trap_level_container_type trap_level_container_type;
312 typedef typename trap_level_container_type::const_iterator trap_iterator_type;
318 if (num_trap_unknowns != traps.size())
319 throw viennashe::invalid_value_exception(
"The number of traps configured in the device does not match the number of unknowns for traps!",
static_cast<double>(num_trap_unknowns));
321 if (num_trap_unknowns != 0)
323 std::size_t index = 0;
324 for (trap_iterator_type tit = traps.begin(); tit != traps.end(); ++tit, ++index)
350 template <
typename DeviceType,
360 typedef typename DeviceType::mesh_type MeshType;
362 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
363 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
365 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
366 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
368 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
369 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
376 bnd_carrier_accessor bnd_carrier_density(
device, ctype);
387 double mobility = 1.0;
393 CellContainer cells(mesh);
394 for (CellIterator cit = cells.begin();
400 const long row_index2 = carrier_density.get_unknown_index(*cit);
403 const std::size_t row_index = std::size_t(row_index2);
406 const long pot_index_center =
potential.get_unknown_index(*cit);
407 double potential_center =
potential.get_value(*cit);
410 potential_center += quantum_corr.get_value(*cit);
412 const double carrier_center = carrier_density.get_value(*cit);
414 PointType centroid_cell = viennagrid::centroid(*cit);
416 A(row_index, row_index) = 0.0;
419 FacetOnCellContainer facets(*cit);
420 for (FacetOnCellIterator focit = facets.begin();
421 focit != facets.end();
426 if (!other_cell_ptr)
continue;
430 if ( (carrier_density.get_unknown_mask(*other_cell_ptr) || carrier_density.get_boundary_type(*other_cell_ptr) ==
BOUNDARY_DIRICHLET) )
432 PointType centroid_other_cell = viennagrid::centroid(*other_cell_ptr);
433 PointType cell_connection = centroid_other_cell - centroid_cell;
434 PointType cell_connection_normalized = cell_connection / viennagrid::norm(cell_connection);
437 const double connection_len =
viennagrid::norm_2(centroid_cell - centroid_other_cell);
438 const double weighted_interface_area = viennagrid::volume(*focit) * viennagrid::inner_prod(facet_unit_normal, cell_connection_normalized);
439 double potential_outer =
potential.get_value(*other_cell_ptr);
441 potential_outer += quantum_corr.get_value(*other_cell_ptr);
443 const long pot_index_other =
potential.get_unknown_index(*other_cell_ptr);
448 const long np_col_index = carrier_density.get_unknown_index(*other_cell_ptr);
449 if (np_col_index > -1)
451 A(row_index, std::size_t(np_col_index)) = weighted_interface_area * flux_approximator(0.0, 1.0,
452 potential_center, potential_outer,
453 connection_len, mobility, T);
456 A(row_index, row_index) += weighted_interface_area * flux_approximator(1.0, 0.0,
457 potential_center, potential_outer,
458 connection_len, mobility, T);
465 : carrier_density.get_value(*other_cell_ptr);
467 b[row_index] -= weighted_interface_area * flux_approximator(carrier_center, carrier_outer,
468 potential_center, potential_outer,
469 connection_len, mobility, T);
471 if (!with_full_newton)
481 const long corrpot_center_index = quantum_corr.get_unknown_index(*cit);
482 const long corrpot_outer_index = quantum_corr.get_unknown_index(*other_cell_ptr);
483 if (corrpot_center_index >= 0)
485 const double gamma_outer = quantum_corr.get_value(*other_cell_ptr);
486 const double gamma_center = quantum_corr.get_value(*cit);
487 A(row_index, std::size_t(corrpot_center_index)) = weighted_interface_area *
488 flux_approximator_dVj(carrier_center, carrier_outer,
489 gamma_center, gamma_outer,
490 connection_len, mobility, T);
492 if (corrpot_outer_index >= 0)
494 const double gamma_outer = quantum_corr.get_value(*other_cell_ptr);
495 const double gamma_center = quantum_corr.get_value(*cit);
496 A(row_index, std::size_t(corrpot_center_index)) = weighted_interface_area *
497 flux_approximator_dVj(carrier_center, carrier_outer,
498 gamma_center, gamma_outer,
499 connection_len, mobility, T);
504 if (pot_index_other >= 0)
506 A(row_index, std::size_t(pot_index_other)) = weighted_interface_area *
507 flux_approximator_dVj(carrier_center, carrier_outer,
508 potential_center, potential_outer,
509 connection_len, mobility, T);
513 A(row_index, std::size_t(pot_index_center)) += weighted_interface_area *
514 flux_approximator_dVi(carrier_center, carrier_outer,
515 potential_center, potential_outer,
516 connection_len, mobility, T);
538 inline double density_gradient_flux(
double E,
double pot_i,
double gamma_i,
double T_i,
double pot_j,
double gamma_j,
double T_j)
542 const double kbT_i = (kB * T_i) * 2.0;
543 const double kbT_j = (kB * T_j) * 2.0;
544 return ( (q * (pot_j + gamma_j) - E) / kbT_j) - ((q * (pot_i + gamma_i) - E) / kbT_i);
558 template <
typename DeviceType,
typename MatrixType,
typename VectorType>
566 typedef typename DeviceType::mesh_type MeshType;
568 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
569 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
571 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
572 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
574 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
575 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
597 CellContainer cells(mesh);
598 for (CellIterator cit = cells.begin();
602 const long row_index2 = quantum_corr.get_unknown_index(*cit);
603 if ( row_index2 < 0 )
605 const std::size_t row_index = std::size_t(row_index2);
607 const double potential_center =
potential.get_value(*cit);
608 const double gamma_center = quantum_corr.get_value(*cit);
611 A(row_index, row_index) = 0.0;
614 PointType centroid_cell = viennagrid::centroid(*cit);
615 const double box_volume = viennagrid::volume(*cit);
617 FacetOnCellContainer facets(*cit);
618 for (FacetOnCellIterator focit = facets.begin();
619 focit != facets.end();
624 if (!other_cell_ptr)
continue;
628 PointType centroid_other_cell = viennagrid::centroid(*other_cell_ptr);
629 PointType cell_connection = centroid_other_cell - centroid_cell;
630 PointType cell_connection_normalized = cell_connection / viennagrid::norm(cell_connection);
633 const double connection_len =
viennagrid::norm_2(centroid_cell - centroid_other_cell);
634 const double weighted_interface_area = viennagrid::volume(*focit) * viennagrid::inner_prod(facet_unit_normal, cell_connection_normalized);
636 const long col_index = quantum_corr.get_unknown_index(*other_cell_ptr);
638 const double c_ij = coeff_b * (weighted_interface_area / connection_len);
639 const double potential_outer =
potential.get_value(*other_cell_ptr);
642 if ( col_index >= 0 )
644 const double gamma_outer = quantum_corr.get_value(*other_cell_ptr);
646 A(row_index, std::size_t(col_index)) -= c_ij * q / (kB * T * 2.0);
647 A(row_index, row_index) += c_ij * q / (kB * T * 2.0);
653 const double gamma_outer = quantum_corr.get_boundary_value(*other_cell_ptr);
655 A(row_index, row_index) += c_ij * q / (kB * T * 2.0);
662 if ( with_full_newton )
664 const long pot_index_outer =
potential.get_unknown_index(*other_cell_ptr);
665 const long pot_index_center =
potential.get_unknown_index(*cit);
668 if ( pot_index_outer >= 0 )
669 A(row_index, std::size_t(pot_index_outer)) -= c_ij * q / (kB * T * 2.0);
672 A(row_index, std::size_t(pot_index_center)) += c_ij * q / (kB * T * 2.0);
675 if ( quantum_corr.get_boundary_type(*other_cell_ptr) ==
BOUNDARY_ROBIN )
679 const double alpha = robin_coeffs.
alpha;
680 const double beta = robin_coeffs.
beta;
683 A(row_index, row_index) -= alpha * weighted_interface_area ;
684 b[row_index] += (beta + alpha * gamma_center) * weighted_interface_area;
689 A(row_index, row_index) += box_volume;
690 b[row_index] -= box_volume * gamma_center;
704 template <
typename DeviceType,
typename MatrixType,
typename VectorType>
712 typedef typename DeviceType::mesh_type MeshType;
714 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
715 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
717 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
718 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
720 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
721 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
737 CellContainer cells(mesh);
738 for (CellIterator cit = cells.begin();
746 const std::size_t row_index = std::size_t(row_index2);
748 PointType centroid_cell = viennagrid::centroid(*cit);
752 const double kappa_center =
diffusivity(*cit, T_center);
755 A(row_index, row_index) = 0;
760 FacetOnCellContainer facets(*cit);
761 for (FacetOnCellIterator focit = facets.begin();
762 focit != facets.end();
767 if (!other_cell_ptr)
continue;
771 PointType centroid_other_cell = viennagrid::centroid(*other_cell_ptr);
772 PointType cell_connection = centroid_other_cell - centroid_cell;
773 PointType cell_connection_normalized = cell_connection / viennagrid::norm(cell_connection);
776 const double connection_len =
viennagrid::norm_2(centroid_cell - centroid_other_cell);
777 const double weighted_interface_area = viennagrid::volume(*focit) * viennagrid::inner_prod(facet_unit_normal, cell_connection_normalized);
784 PointType facet_center = viennagrid::centroid(*focit);
785 const double connection_in_cell = viennagrid::norm(facet_center - centroid_cell);
786 const double connection_in_other_cell = viennagrid::norm(facet_center - centroid_other_cell);
787 const double kappa_mean = (connection_in_cell + connection_in_other_cell) /
788 (connection_in_cell/kappa_center + connection_in_other_cell/
diffusivity(*other_cell_ptr, T_outer));
790 A(row_index, std::size_t(col_index)) = kappa_mean * weighted_interface_area / connection_len;
791 A(row_index, row_index) -= kappa_mean * weighted_interface_area / connection_len;
793 b[row_index] -= kappa_mean * weighted_interface_area * (T_outer - T_center) / connection_len;
797 A(row_index, row_index) -= kappa_center * weighted_interface_area / connection_len;
799 b[row_index] -= kappa_center * weighted_interface_area / connection_len * (
lattice_temperature.get_boundary_value(*other_cell_ptr) - T_center);
804 const double volume = viennagrid::volume(*cit);
807 b[row_index] += volume * quan_power_density(*cit);
825 template <
typename DeviceType,
826 typename TimeStepQuantitiesT,
831 TimeStepQuantitiesT & quantities,
Contains the definition of per-device accessors (read-only!) for various quantities.
Generic assembly of traps is implemented here.
Implementation of the Bernoulli function.
Defines a set of checker functors for micro-tests within ViennaSHE.
Exception thrown in the case that an equation assembler cannot be found.
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.
equation_id get_electron_equation() const
bool with_holes() const
Returns true if holes are considered in the simulation.
equation_id get_hole_equation() const
bool with_traps() const
Returns true if traps are considered in the simulation.
nonlinear_solver_config_type & nonlinear_solver()
Returns the configuration object for the nonlinear solver.
bool with_trap_selfconsistency() const
Returns true if traps are considered self-consistently in the simulation.
bool with_electrons() const
Returns true if electrons are considered in the simulation.
detail::density_gradient_config const & density_gradient(viennashe::carrier_type_id ctype) const
bool with_quantum_correction() const
double get_lattice_temperature(cell_type const &c) const
Returns the lattice temperature on a cell.
double get_doping_p(cell_type const &c) const
Returns the donator doping (in m^-3) in the specified cell.
long get_material(cell_type const &elem) const
Returns the material id of the provided cell.
MeshT const & mesh() const
Returns the underlying mesh.
double get_doping_n(cell_type const &c) const
Returns the donator doping (in m^-3) in the specified cell.
trap_level_container_type const & get_trap_levels(cell_type const &cell) const
Returns all the trap levels defined for the provided cell.
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Accessor to get the diffusivity. Used in the assembly of the heat diffusion equation.
Accessor for fixed charges.
Power density accessor. Used to get the power density in the assembly of the heat diffusion equation.
Exception for the case that an invalid value (depends on the method called) is encountered.
Accessor for obtaining the permittivity in the device.
double symmetry_factor() const
Generic dispatcher for partial derivatives of the Scharfetter-Gummel discretization of electron and h...
Generic dispatcher for Scharfetter-Gummel discretization of electron and hold fluxes.
Dispatcher for Scharfetter-Gummel discretization of electron and hold fluxes.
An accessor for the carrier density in the device.
The main SHE simulator controller class. Acts as an accessor for all SHE quantities needed for the si...
UnknownSHEQuantityType const & electron_distribution_function() const
UnknownQuantityType & get_unknown_quantity(std::string quantity_name)
Returns a reference to the unkown quantity identified by its name.
UnknownSHEQuantityType const & hole_distribution_function() const
double trap_occupancy(CellType const &c, std::size_t inner_index) const
std::size_t num_trap_unknown_indices(CellType const &c) const
Returns the number of inner unknown indices (aka. degree of freedom - dof) for traps associated with ...
long id() const
Returns the current linear solver ID.
std::string get_name() const
Contains the definition of a device class independent of the actual macroscopic model to be solved.
Helper routines for projecting normal components of a vector-valued quantity defined on edges to vert...
Defines several filter functors for the device. A filter functor returns true if the supplied argumen...
Contains forward declarations and definition of small classes that must be defined at an early stage.
Implementation of various utilities related to linear algebra.
A logging facility providing fine-grained control over logging in ViennaSHE.
A very simple material database. Needs to be replaced by something more versatile soon.
void assemble_poisson_carrier_coupling(viennashe::config const &conf, CellType const &cell, SpatialUnknownT const &np_density, SHEUnknownT const &f_np, MatrixType &A, std::size_t row_index, double box_volume)
Assembles, per cell, the carrier concentration coupling on the RHS of Poisson's equation.
double density_gradient_flux(double E, double pot_i, double gamma_i, double T_i, double pot_j, double gamma_j, double T_j)
Returns the quantum correction potential flux between two points (Density Gradient)
double get_carrier_density_for_poisson(viennashe::config const &conf, CellType const &cell, SpatialUnknownT const &np_density, SHEUnknownT const &f_np)
Returns the requested carrier concentration, calculated from a SHE or DD solution,...
bool is_semiconductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a semiconductor.
double permittivity(long material_id)
Convenience function for returning the permittivity of the material identified by the ID provided.
double diffusivity(long material_id)
bool is_conductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a metal.
VectorType::value_type norm_2(VectorType const &v)
double get_thermal_potential(double T)
Returns the thermal potential for the provided temperature.
double get_band_edge(viennashe::carrier_type_id const &ctype)
Returns the band edge relative to the reference energy (mid-gap)
std::string lattice_temperature()
std::string hole_density()
std::string density_gradient_hole_correction()
std::string density_gradient_electron_correction()
std::string electron_density()
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....
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)...
viennagrid::result_of::point< viennagrid::element< CellTagT, WrappedConfigT > >::type outer_cell_normal_at_facet(viennagrid::element< CellTagT, WrappedConfigT > const &cell, viennagrid::element< FacetTagT, WrappedConfigT > const &facet)
Returns the unit outer normal of a facet with respect to the provided cell.
CellT const * get_other_cell_of_facet(MeshT const &mesh, FacetT const &facet, CellT const &cell)
Helper function returning a const-pointer to the 'second cell' of a facet, or NULL if there is no sec...
The main ViennaSHE namespace. All functionality resides inside this namespace.
void assemble_poisson(DeviceType const &device, viennashe::she::timestep_quantities< DeviceType > const &quantities, viennashe::config const &conf, MatrixType &A, VectorType &b)
Assembles the potential block (i.e. the linear equations obtained from the discretization of the Pois...
carrier_type_id
Enumeration type for selecting the carrier type.
equation_id
An enumeration of all equation types ViennaSHE supports.
void assemble_density_gradient(DeviceType const &device, viennashe::she::timestep_quantities< DeviceType > const &quantities, viennashe::config const &conf, carrier_type_id ctype, MatrixType &A, VectorType &b)
Assembles the density gradient equation set for the given carrier type.
void assemble_heat(DeviceType const &device, viennashe::she::timestep_quantities< DeviceType > const &quantities, viennashe::config const &conf, MatrixType &A, VectorType &b)
Assembles the heat diffusion equation (HDE)
void assemble_dd(DeviceType const &device, viennashe::she::timestep_quantities< DeviceType > const &quantities, viennashe::config const &conf, carrier_type_id ctype, MatrixType &A, VectorType &b)
void assemble(DeviceType const &device, TimeStepQuantitiesT &quantities, viennashe::config const &conf, viennashe::unknown_quantity< VertexT > const &quan, MatrixType &A, VectorType &b)
Assemble a spatial quantity, where the equation is deduced from 'quan'.
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.
Scharfetter-Gummel stabilization of the continuity equations.
static const double q
Elementary charge.
static const double kB
Boltzmann constant.
static const double hbar
Modified Planck constant.
static const double mass_electron
Electron rest mass.
@ newton_nonlinear_solver
Gummel iteration.
A container of all quantities defined for a certain timestep t.
Defines the log keys used within the main viennashe:: namespace.