ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
srh_kinetics.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_SRH_KINETICS_HPP
2#define VIENNASHE_SRH_KINETICS_HPP
3/* ============================================================================
4 Copyright (c) 2011-2022, Institute for Microelectronics,
5 Institute for Analysis and Scientific Computing,
6 TU Wien.
7
8 -----------------
9 ViennaSHE - The Vienna Spherical Harmonics Expansion Boltzmann Solver
10 -----------------
11
12 http://viennashe.sourceforge.net/
13
14 License: MIT (X11), see file LICENSE in the base directory
15=============================================================================== */
16
17
18// viennashe
19#include "viennashe/forwards.h"
20#include "viennashe/log/log.hpp"
21
24
25namespace viennashe
26{
27 namespace models
28 {
29
30 namespace srh
31 {
32
33 namespace detail
34 {
35
36 template < typename DeviceType, typename TimeStepQuantitiesT >
37 double get_carrier_concentration(DeviceType const & device,
38 typename DeviceType::cell_type const & cell,
39 TimeStepQuantitiesT const & quantities,
41 {
42 (void)device;
43 if (ctype == viennashe::ELECTRON_TYPE_ID)
44 return quantities.electron_density().at(cell);
45 else
46 return quantities.hole_density().at(cell);
47 }
48
49 template < typename DeviceType, typename TimeStepQuantitiesT >
50 double get_carrier_concentration(DeviceType const & device,
51 typename DeviceType::facet_type const & facet,
52 TimeStepQuantitiesT const & quantities,
54 {
55 typedef typename DeviceType::mesh_type mesh_type;
56 typedef typename DeviceType::facet_type facet_type;
57 typedef typename DeviceType::cell_type cell_type;
58 typedef typename viennagrid::result_of::const_coboundary_range<mesh_type, facet_type, cell_type>::type CellOnFacetContainer;
59 CellOnFacetContainer cells_on_facet(device.mesh(), viennagrid::handle(device.mesh(), facet));
60
61 if (ctype == viennashe::ELECTRON_TYPE_ID)
62 {
64 return quantities.electron_density().at(cells_on_facet[1]);
65 else if (! viennashe::materials::is_semiconductor(device.get_material(cells_on_facet[1])))
66 return quantities.electron_density().at(cells_on_facet[0]);
67 else
68 return std::sqrt(quantities.electron_density().at(cells_on_facet[0]) * quantities.electron_density().at(cells_on_facet[1]));
69 }
70 else
71 {
73 return quantities.hole_density().at(cells_on_facet[1]);
74 else if (! viennashe::materials::is_semiconductor(device.get_material(cells_on_facet[1])))
75 return quantities.hole_density().at(cells_on_facet[0]);
76 else
77 return std::sqrt(quantities.hole_density().at(cells_on_facet[0]) * quantities.hole_density().at(cells_on_facet[1]));
78 }
79 }
80
92 template < typename DeviceType, typename ElementType, typename TimeStepQuantitiesT >
94 DeviceType const & device,
95 ElementType const & el,
96 viennashe::config const & conf,
97 TimeStepQuantitiesT const & quantities,
99 std::size_t index_H = 0)
100 {
101 const double collision_cs = trap.collision_cross_section();
102
104 {
106 {
107 for (std::size_t i = 0; i < quantities.unknown_she_quantities().size(); ++i)
108 {
109 // TODO: The following is a rather ugly dispatch:
110 if (quantities.unknown_she_quantities()[i].get_name() != viennashe::quantity::electron_distribution_function())
111 continue;
112
113 const double kinetic_energy = quantities.unknown_she_quantities()[i].get_kinetic_energy(el, index_H);
114 const double velocity = conf.dispersion_relation(ctype).velocity(kinetic_energy);
115 double gamma_recombination = collision_cs * velocity;
116 return gamma_recombination;
117 }
118 }
120 {
121 const double T = device.get_lattice_temperature(el);
123 const double sigma_n = vth * collision_cs;
124
125 return sigma_n * get_carrier_concentration(device, el, quantities, viennashe::ELECTRON_TYPE_ID);
126 }
127 }
128 else if (ctype == viennashe::HOLE_TYPE_ID && conf.with_holes())
129 {
131 {
132 for (std::size_t i = 0; i < quantities.unknown_she_quantities().size(); ++i)
133 {
134 // TODO: The following is a rather ugly dispatch:
135 if (quantities.unknown_she_quantities()[i].get_name() != viennashe::quantity::hole_distribution_function())
136 continue;
137
138 const double kinetic_energy = quantities.unknown_she_quantities()[i].get_kinetic_energy(el, index_H);
139 const double velocity = conf.dispersion_relation(ctype).velocity(kinetic_energy);
140 double gamma_recombination = collision_cs * velocity;
141
142 return gamma_recombination;
143 }
144 }
146 {
147 const double T = device.get_lattice_temperature(el);
149 const double sigma_p = vth * collision_cs;
150
151 return sigma_p * get_carrier_concentration(device, el, quantities, viennashe::HOLE_TYPE_ID);
152 }
153 }
154
155 throw viennashe::unavailable_feature_exception("SRH-trap evaluation needs the electron and hole EDF or electron and hole concentrations!");
156
157 return 0;
158 }
159
171 template < typename DeviceType, typename ElementType, typename TimeStepQuantitiesT >
173 DeviceType const & device,
174 ElementType const & el,
175 viennashe::config const & conf,
176 TimeStepQuantitiesT const & quantities,
178 std::size_t index_H = 0)
179 {
180 const double collision_cs = trap.collision_cross_section();
181 const double cell_temperature = device.get_lattice_temperature(el);
182 const double kBT = viennashe::physics::constants::kB * cell_temperature;
183
184 if (ctype == viennashe::ELECTRON_TYPE_ID && conf.with_electrons())
185 {
187 {
188 for (std::size_t i = 0; i < quantities.unknown_she_quantities().size(); ++i)
189 {
190 // TODO: The following is a rather ugly dispatch:
191 if (quantities.unknown_she_quantities()[i].get_name() != viennashe::quantity::electron_distribution_function())
192 continue;
193
194 double total_trap_energy = trap.energy() + quantities.unknown_she_quantities()[i].get_bandedge_shift(el) - viennashe::physics::get_band_edge(viennashe::ELECTRON_TYPE_ID); //total trap energy
195 const double kinetic_energy = quantities.unknown_she_quantities()[i].get_kinetic_energy(el, index_H);
196 const double velocity = conf.dispersion_relation(ctype).velocity(kinetic_energy);
197 const double total_energy = quantities.unknown_she_quantities()[i].get_value_H(index_H);
198 double gamma_generation = collision_cs * velocity * std::exp( (total_trap_energy - total_energy) / kBT );
199
200 return gamma_generation;
201 }
202 }
204 {
205 const double vth = viennashe::physics::get_thermal_velocity(cell_temperature, viennashe::ELECTRON_TYPE_ID);
206
207 const double sigma_n = vth * collision_cs;
209
210 return sigma_n * n_aux * std::exp( + trap.energy() / kBT);
211 }
212 }
213 else if (ctype == viennashe::HOLE_TYPE_ID && conf.with_holes())
214 {
216 {
217 for (std::size_t i = 0; i < quantities.unknown_she_quantities().size(); ++i)
218 {
219 // TODO: The following is a rather ugly dispatch:
220 if (quantities.unknown_she_quantities()[i].get_name() != viennashe::quantity::hole_distribution_function())
221 continue;
222
223 double total_trap_energy = trap.energy() + quantities.unknown_she_quantities()[i].get_bandedge_shift(el) - viennashe::physics::get_band_edge(viennashe::HOLE_TYPE_ID); //total trap energy
224 const double kinetic_energy = quantities.unknown_she_quantities()[i].get_kinetic_energy(el, index_H);
225 const double velocity = conf.dispersion_relation(ctype).velocity(kinetic_energy);
226 const double total_energy = quantities.unknown_she_quantities()[i].get_value_H(index_H);
227 double gamma_generation = collision_cs * velocity * std::exp( (total_energy - total_trap_energy) / kBT ) ;
228
229 return gamma_generation;
230 }
231 }
233 {
234 const double vth = viennashe::physics::get_thermal_velocity(cell_temperature, viennashe::HOLE_TYPE_ID);
235
236 const double sigma_p = vth * collision_cs;
237 const double p_aux = viennashe::physics::get_auxilary_concentration(cell_temperature, viennashe::HOLE_TYPE_ID);
238
239 return sigma_p * p_aux * std::exp( - trap.energy() / kBT);
240 }
241 }
242
243 throw viennashe::unavailable_feature_exception("SRH-trap evaluation needs the electron and hole EDF!");
244
245 return 0;
246 }
247
248 } // namespace detail
249
258 template < typename DeviceType, typename ElementType, typename TimeStepQuantitiesT >
259 double evaluate(viennashe::trap_level const & trap,
260 DeviceType const & device,
261 ElementType const & el,
262 viennashe::config const & conf,
263 TimeStepQuantitiesT const & quantities)
264 {
266
267 // TODO: We assume SHE in here !
268
270 throw viennashe::quantity_not_found_exception("SRH-trap evaluation needs the electron EDF!");
272 throw viennashe::quantity_not_found_exception("SRH-trap evaluation needs the hole EDF!");
273
274 // Check for Newton
275 if (with_full_newton)
276 {
277 throw viennashe::unavailable_feature_exception("SRH-trap evaluation not impelemented for Newton!");
278 }
279 else // GUMMEL SOLVER
280 {
281 double electron_rec_rate = 0;
282 double electron_gen_rate = 0;
283
284 double hole_rec_rate = 0;
285 double hole_gen_rate = 0;
286
287 const double box_volume = viennagrid::volume(el);
288
289 typedef typename viennashe::config::dispersion_relation_type DispersionRelation;
290
291 DispersionRelation dispersion_n = conf.dispersion_relation(viennashe::ELECTRON_TYPE_ID);
292 DispersionRelation dispersion_p = conf.dispersion_relation(viennashe::HOLE_TYPE_ID);
293
294 for (std::size_t i = 0; i < quantities.unknown_she_quantities().size(); ++i)
295 {
296 for (std::size_t index_H = 1; index_H < quantities.unknown_she_quantities()[i].get_value_H_size()-1; ++index_H)
297 {
298 const long f00_index = quantities.unknown_she_quantities()[i].get_unknown_index(el, index_H);
299 if (f00_index < 0) //no DOF here
300 continue;
301
302 const double energy_spacing = viennashe::she::box_height(quantities.unknown_she_quantities()[i], el, index_H);
303 const bool assemble_electrons = (quantities.unknown_she_quantities()[i].get_carrier_type_id() == viennashe::ELECTRON_TYPE_ID);
304 const double kinetic_energy = quantities.unknown_she_quantities()[i].get_kinetic_energy(el, index_H);
305
306 const double f00 = quantities.unknown_she_quantities()[i].get_values(el, index_H)[0];
307
308 if (assemble_electrons)
309 {
310 const double gamma_recombination = detail::gamma_recombination_impl(trap, device, el, conf, quantities, viennashe::ELECTRON_TYPE_ID, index_H);
311 const double gamma_generation = detail::gamma_generation_impl(trap, device, el, conf, quantities, viennashe::ELECTRON_TYPE_ID, index_H);
312
313 electron_rec_rate += box_volume * energy_spacing * gamma_recombination * f00 * dispersion_n.density_of_states(kinetic_energy);
314 electron_gen_rate += box_volume * energy_spacing * gamma_generation * f00 * dispersion_n.density_of_states(kinetic_energy);
315 }
316 else
317 {
318 const double gamma_recombination = detail::gamma_recombination_impl(trap, device, el, conf, quantities, viennashe::HOLE_TYPE_ID, index_H);
319 const double gamma_generation = detail::gamma_generation_impl(trap, device, el, conf, quantities, viennashe::HOLE_TYPE_ID, index_H);
320
321 hole_rec_rate += box_volume * energy_spacing * gamma_recombination * f00 * dispersion_p.density_of_states(kinetic_energy);
322 hole_gen_rate += box_volume * energy_spacing * gamma_generation * f00 * dispersion_p.density_of_states(kinetic_energy);
323 }
324 } // for index_H
325 }
326 // Explicit formula for trap occupancy, cf. SISPAD paper 'Bipolar Spherical Harmonics Expansions of the BTE' by Rupp et al. (2012)
327 // Set the trap occupancy
328 double ft = 0.0;
329 double denominator = electron_rec_rate + electron_gen_rate + hole_rec_rate + hole_gen_rate;
330 if (denominator > 0)
331 ft = (electron_rec_rate + hole_gen_rate) / denominator;
332
333 // A bit of over- and underflowing occupancy is ok
334 if (ft > 1.0 && ft < 1.001) ft = 1.0;
335 if (ft < 0 && ft > -0.001) ft = 0.0;
336
337 //std::cout << el << " => " << ft << std::endl;
338
339 return ft;
340 }
341 }
342
355 template < typename DeviceType, typename ElementType, typename TimeStepQuantitiesT >
356 double gamma_recombination(viennashe::trap_level const & trap, DeviceType const & device, ElementType const & el, viennashe::config const & conf,
357 TimeStepQuantitiesT const & quantities,
359 double occupancy,
360 std::size_t index_H = 0)
361 {
362 if (ctype == viennashe::ELECTRON_TYPE_ID)
363 return detail::gamma_recombination_impl(trap, device, el, conf, quantities, ctype, index_H) * (1.0 - occupancy);
364 else
365 return detail::gamma_recombination_impl(trap, device, el, conf, quantities, ctype, index_H) * occupancy;
366 }
367
380 template < typename DeviceType, typename ElementType, typename TimeStepQuantitiesT >
381 double gamma_generation(viennashe::trap_level const & trap, DeviceType const & device, ElementType const & el, viennashe::config const & conf,
382 TimeStepQuantitiesT const & quantities,
384 double occupancy,
385 std::size_t index_H = 0)
386 {
387 if (ctype == viennashe::ELECTRON_TYPE_ID)
388 return detail::gamma_generation_impl(trap, device, el, conf, quantities, ctype, index_H) * occupancy;
389 else
390 return detail::gamma_generation_impl(trap, device, el, conf, quantities, ctype, index_H) * (1.0 - occupancy);
391 }
392
393
394 } // namespace models
395
396 } // namespace srh
397
398} // namespace viennashe
399
400
401#endif /* VIENNASHE_SRH_KINETICS_HPP */
402
Common routines for the assembly of SHE equations.
The main SHE configuration class. To be adjusted by the user for his/her needs.
Definition: config.hpp:124
viennashe::physics::dispersion_proxy dispersion_relation(viennashe::carrier_type_id ctype) const
Returns the dispersion relation for electrons.
Definition: config.hpp:266
equation_id get_electron_equation() const
Definition: config.hpp:230
bool with_holes() const
Returns true if holes are considered in the simulation.
Definition: config.hpp:234
equation_id get_hole_equation() const
Definition: config.hpp:238
nonlinear_solver_config_type & nonlinear_solver()
Returns the configuration object for the nonlinear solver.
Definition: config.hpp:495
bool with_electrons() const
Returns true if electrons are considered in the simulation.
Definition: config.hpp:226
double get_lattice_temperature(cell_type const &c) const
Returns the lattice temperature on a cell.
Definition: device.hpp:255
long get_material(cell_type const &elem) const
Returns the material id of the provided cell.
Definition: device.hpp:502
MeshT const & mesh() const
Returns the underlying mesh.
Definition: device.hpp:145
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Definition: device.hpp:818
A proxy object for a dispersion relation. Does NOT take ownership of the provided pointer!
Definition: dispersion.hpp:69
double velocity(double ekin, double theta=0, double phi=0) const
Returns the velocity as a function of kinetic energy (and angles, eventually)
Definition: dispersion.hpp:82
Exception in case a (requested) quantity cannot be found.
Definition: exception.hpp:133
long id() const
Returns the current linear solver ID.
Definition: config.hpp:262
Describes a SRH trap.
Definition: trap_level.hpp:31
void energy(double e)
Returns the trap energy in Joule (zero energy refers to the center of the band gap.
Definition: trap_level.hpp:77
void collision_cross_section(double ccs)
Sets the collision cross section (SI units)
Definition: trap_level.hpp:42
Exception for the case that a requested feature is not available (due to configuration or due to not ...
Definition: exception.hpp:103
Contains forward declarations and definition of small classes that must be defined at an early stage.
A logging facility providing fine-grained control over logging in ViennaSHE.
bool is_semiconductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a semiconductor.
Definition: all.hpp:156
double get_carrier_concentration(DeviceType const &device, typename DeviceType::cell_type const &cell, TimeStepQuantitiesT const &quantities, viennashe::carrier_type_id ctype)
double gamma_recombination_impl(viennashe::trap_level const &trap, DeviceType const &device, ElementType const &el, viennashe::config const &conf, TimeStepQuantitiesT const &quantities, viennashe::carrier_type_id ctype, std::size_t index_H=0)
Implementation of the recombination term without any occupancies considered.
double gamma_generation_impl(viennashe::trap_level const &trap, DeviceType const &device, ElementType const &el, viennashe::config const &conf, TimeStepQuantitiesT const &quantities, viennashe::carrier_type_id ctype, std::size_t index_H=0)
Implementation of the generation term without any occupancies considered.
double gamma_generation(viennashe::trap_level const &trap, DeviceType const &device, ElementType const &el, viennashe::config const &conf, TimeStepQuantitiesT const &quantities, viennashe::carrier_type_id ctype, double occupancy, std::size_t index_H=0)
Returns the carrier generation, where the occupancies have been considered!
double evaluate(viennashe::trap_level const &trap, DeviceType const &device, ElementType const &el, viennashe::config const &conf, TimeStepQuantitiesT const &quantities)
Returns the trap occupancy based on a bipolar SHE or DD solution.
double gamma_recombination(viennashe::trap_level const &trap, DeviceType const &device, ElementType const &el, viennashe::config const &conf, TimeStepQuantitiesT const &quantities, viennashe::carrier_type_id ctype, double occupancy, std::size_t index_H=0)
Returns the carrier recombination, where the occupancies have been considered!
double get_thermal_velocity(double temperature, viennashe::carrier_type_id ctype)
Returns the thermal velocity at the given lattice temperature for a given carrier type.
Definition: physics.hpp:110
double get_band_edge(viennashe::carrier_type_id const &ctype)
Returns the band edge relative to the reference energy (mid-gap)
Definition: physics.hpp:98
double get_auxilary_concentration(double temperature, viennashe::carrier_type_id ctype)
Returns the auxilary carrier concentration.
Definition: physics.hpp:124
std::string electron_distribution_function()
std::string hole_distribution_function()
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)...
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
carrier_type_id
Enumeration type for selecting the carrier type.
Definition: forwards.h:185
@ HOLE_TYPE_ID
Definition: forwards.h:188
@ ELECTRON_TYPE_ID
Definition: forwards.h:187
@ EQUATION_SHE
Definition: forwards.h:118
@ EQUATION_CONTINUITY
Definition: forwards.h:117
static const double kB
Boltzmann constant.
Definition: constants.hpp:46
@ newton_nonlinear_solver
Gummel iteration.
Definition: config.hpp:244
Contains the definition of a trap level.