ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
mobility_model.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_MODELS_MOBILITY_MODEL_HPP
2#define VIENNASHE_MODELS_MOBILITY_MODEL_HPP
3
4/* ============================================================================
5 Copyright (c) 2011-2022, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8
9 -----------------
10 ViennaSHE - The Vienna Spherical Harmonics Expansion Boltzmann Solver
11 -----------------
12
13 http://viennashe.sourceforge.net/
14
15 License: MIT (X11), see file LICENSE in the base directory
16=============================================================================== */
17
18
19// std
20#include <stdexcept>
21#include <utility>
22
23// viennashe
24#include "viennashe/forwards.h"
28
29// viennagrid
30#include "viennagrid/mesh/mesh.hpp"
31#include "viennagrid/algorithm/norm.hpp"
32#include "viennagrid/algorithm/centroid.hpp"
33#include "viennagrid/mesh/coboundary_iteration.hpp"
34
35
41namespace viennashe
42{
43 namespace models
44 {
45
47 namespace dd
48 {
49
50 namespace mobility_detail
51 {
52
54 {
55 public:
56
57 mobility_lattice_scattering(const lattice_scattering & params) : _params(params) { }
58
59 double operator()(double mu, double T) const
60 {
61 if ( _params.enabled )
62 {
63 return this->calculateMobilityLatticeScattering(mu, T);
64 }
65 else
66 {
67 return mu;
68 }
69 }
70
71 private:
72 lattice_scattering _params;
73
74 double calculateMobilityLatticeScattering(double mu, double T) const
75 {
76 if ( _params.T_ref == 0.0 )
77 throw viennashe::models::invalid_parameter_exception("params.T_ref = 0 and therefore invalid");
78
79 return mu * pow(T / _params.T_ref, -_params.alpha);
80 }
81 }; // mobility_lattice_scattering
82
84 {
85 public:
86
87 mobility_impurity_scattering(const impurity_scattering & params) : _params(params) { }
88
89 double operator()(double mu, double total_doping) const
90 {
91 if ( _params.enabled )
92 {
93 return this->calculateMobilityIonizedImpurityScattering(mu, total_doping);
94 }
95 else
96 {
97 return mu;
98 }
99 }
100
101 private:
102 impurity_scattering _params;
103
104 double calculateMobilityIonizedImpurityScattering(double mu, double total_doping) const
105 {
106 if ( _params.N_ref == 0.0 )
107 throw viennashe::models::invalid_parameter_exception("params.N_ref = 0 and therefore invalid");
108 if ( _params.mu_min < 0.0 )
109 throw viennashe::models::invalid_parameter_exception("params.mu_min < 0 and therefore invalid");
110 if ( total_doping <= 0.0 )
111 throw viennashe::models::invalid_parameter_exception("total_doping <= 0 and therefore invalid");
112
113 double N_sum = 1.0 * total_doping;
114
115 // Caughey and Thomas
116 double N_adjust = pow(N_sum / _params.N_ref, _params.alpha);
117 return _params.mu_min + (mu - _params.mu_min) / (1 + N_adjust);
118 }
119 }; // mobility_impurity_scattering
120
122 {
123 public:
124
125 mobility_surface_scattering(const surface_scattering & params) : _params(params) { }
126
127 double operator()(double mu, double distance_to_insulator, double E_n) const
128 {
129 if ( _params.enabled )
130 {
131 return this->calculateMobilitySurfaceScattering(mu, distance_to_insulator, E_n);
132 }
133 else
134 {
135 return mu;
136 }
137 }
138
139 private:
140 surface_scattering _params;
141
142 double calculateMobilitySurfaceScattering(double mu, double distance_to_insulator, double E_n) const
143 {
144 if ( _params.depth_ref == 0.0 )
145 throw viennashe::models::invalid_parameter_exception("params.depth_ref = 0 and therefore invalid");
146 if ( _params.E_ref == 0.0 )
147 throw viennashe::models::invalid_parameter_exception("params.E_ref = 0 and therefore invalid");
148 if ( _params.mu_ref < 0.0 )
149 throw viennashe::models::invalid_parameter_exception("params.mu_ref < 0 and therefore invalid");
150 if ( distance_to_insulator < 0.0 )
151 throw viennashe::models::invalid_parameter_exception("distance_to_next_insulator < 0 and therefore invalid");
152
153 double depth = distance_to_insulator;
154
155 // Selberherr-Formula
156 double depth_dependence = 2.0 * exp(-pow(depth / _params.depth_ref, 2)) / (1 + exp(-2.0 * pow(depth / _params.depth_ref, 2)));
157 double field_dependence = pow(E_n / _params.E_ref, _params.gamma_ref);
158 return ( _params.mu_ref + (mu - _params.mu_ref) * (1.0 - depth_dependence)) / (1.0 + depth_dependence * field_dependence);
159 }
160
161 }; // mobility_surface_scattering
162
164 {
165 public:
166
167 mobility_field_dependence(const field_dependence & params) : _params(params) { }
168
169 double operator()(double mu, double T, double E_n) const
170 {
171 if ( _params.enabled )
172 {
173 return this->calculateFieldDependentMobility(mu, T, E_n);
174 }
175 else
176 {
177 return mu;
178 }
179 }
180
181 private:
182 field_dependence _params;
183
184 double get_saturation_velocity(double T) const
185 {
186 return _params.vsat300 / (1.0 + _params.vsat300C * (T / 300.0 - 1.0));
187 }
188
189 double calculateFieldDependentMobility(double mu, double T, double E_n) const
190 {
191 double F = E_n;
192 double v_sat = this->get_saturation_velocity(T);
193 double beta = _params.beta;
194
195 if ( v_sat <= 0.0 )
196 throw viennashe::models::invalid_parameter_exception("v_sat <= 0 and therefore invalid");
197 if ( T <= 0.0 )
198 throw viennashe::models::invalid_parameter_exception("T <= 0 and therefore invalid");
199
200 double h = pow(pow(2.0 * F * mu / v_sat, beta) + 1.0, beta) + 1.0;
201
202 return 2.0 * mu / h;
203 }
204
205
206 }; // mobility_field_dependence
207
208 } // namespace mobility_detail
209
210
213 template < typename DeviceType >
215 {
216 private:
217 typedef typename DeviceType::mesh_type MeshType;
218 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
219 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
220 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
221
222 public:
223 typedef double value_type;
224
225 mobility(const DeviceType & device, const mobility_paramters & params) : _params(params), _device(device) { }
226
227 mobility(const mobility & mob) : _params(mob._params), _device(mob._device) { }
228
235 template < typename PotentialAccessor >
236 value_type operator()(const FacetType & facet, PotentialAccessor const & potential) const
237 {
238 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
239 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
240
241 CellOnFacetContainer cells_on_facet(_device.mesh(), viennagrid::handle(_device.mesh(), facet));
242
243 CellOnFacetIterator cofit = cells_on_facet.begin();
244 CellType const & c1 = *cofit;
245 ++cofit;
246 CellType const & c2 = *cofit;
247
248 return this->operator ()(c1, c2, potential);
249 }
250
258 template < typename PotentialAccessor >
259 value_type operator()(const CellType & c1, const CellType & c2, PotentialAccessor const & potential) const
260 {
261 mobility_detail::mobility_lattice_scattering lattice(_params.lattice);
262 mobility_detail::mobility_impurity_scattering impurity(_params.impurity);
263 //mobility_detail::mobility_surface_scattering surface(_params.surface);
265
266 const double TL = _device.get_lattice_temperature(c1);
267 const double total_doping_on_cell = (_device.get_doping_n(c1) + _device.get_doping_p(c1));
268 const double edge_len = viennagrid::norm_2( viennagrid::centroid(c2) - viennagrid::centroid(c1) );
269 const double Emag = ( -(potential(c2) - potential(c1)) / edge_len);
270
271 double mu = _params.mu0;
272 if (mu <= 0.0) throw viennashe::models::invalid_parameter_exception("The constant mobility parameter 'mu0' is smaller or equal 0!");
273
274 mu = lattice (mu, TL);
275 mu = impurity(mu, total_doping_on_cell );
276
277 /*if ( (_params.surface.enabled ) && _device.has_distance_to_next_insulator(vt))
278 {
279 const PointType n = ( viennagrid::centroid(c2) - viennagrid::centroid(c1) ) / edge_len;
280 const PointType E_edge = Emag * n;
281 const double distance = _device.distance_to_next_insulator(vt);
282 const PointType dist_vector_n = _device.vector_to_next_insulator(vt) / distance; // normalized distance vector
283
284 const double En = viennagrid::inner_prod(E_edge, dist_vector_n); // projection of E on distance to insulator vector
285
286 mu = surface (mu, distance, En);
287 }*/
288
289 mu = field (mu, TL, Emag);
290
291 return mu;
292 }
293
294 private:
295 const mobility_paramters _params;
296 const DeviceType & _device;
297
298 }; // mobility
299
300 } //namespace dd
301
302 } // namespace models
303
304} //namespace viennashe
305
306#endif
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Definition: device.hpp:818
double operator()(double mu, double T, double E_n) const
double operator()(double mu, double distance_to_insulator, double E_n) const
The main mobility model. Contains submodels for lattice, impurity, field and surface scattering relat...
value_type operator()(const CellType &c1, const CellType &c2, PotentialAccessor const &potential) const
Returns the mobility from a vertex to another vertex. Usage of the other, edge related,...
value_type operator()(const FacetType &facet, PotentialAccessor const &potential) const
Returns the mobility along a facet.
mobility(const DeviceType &device, const mobility_paramters &params)
Thrown whenever an invalid parameter to a model is given.
Definition: exception.hpp:32
Contains forward declarations and definition of small classes that must be defined at an early stage.
Contains PODs for the mobility parameters of the mobility models.
Contains exceptions for viennashe::models.
VectorType::value_type norm_2(VectorType const &v)
Definition: linalg_util.hpp:37
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
Provides a number of fundamental constants. All constants in SI units.
The combined POD for the mobility parameters.