ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
expansion_order.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_SHE_EXPANSION_ORDER_HPP
2#define VIENNASHE_SHE_EXPANSION_ORDER_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// std
19#include <iostream>
20
21// viennagrid
22#include "viennagrid/element/element.hpp"
23#include "viennagrid/mesh/mesh.hpp"
24#include "viennagrid/mesh/coboundary_iteration.hpp"
25
26// viennashe
28#include "viennashe/forwards.h"
31#include "viennashe/config.hpp"
36
38
40
41#include "viennashe/log/log.hpp"
43
48namespace viennashe
49{
50 namespace she
51 {
52
53
59 template <typename DeviceType, typename SHEQuantity>
60 void lower_expansion_order_near_bandedge(DeviceType const & device, SHEQuantity & quan)
61 {
62 typedef typename DeviceType::mesh_type MeshType;
63
64 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
65
66 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
67 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
68
69 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
70 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
71
72 MeshType const & mesh = device.mesh();
73
74 CellContainer cells(mesh);
75 for (CellIterator cit = cells.begin();
76 cit != cells.end();
77 ++cit)
78 {
79
80 for (std::size_t index_H = 1; index_H < quan.get_value_H_size() - 1; ++index_H)
81 {
82 if (quan.get_kinetic_energy(*cit, index_H) <= 0) // In forbidden band there is expansion order 1
83 {
84 quan.set_expansion_order(*cit, index_H, 1);
85 continue;
86 }
87
88
89 //
90 // Make sure that there is no vertex close (w.r.t. energy and space) to the band edge with order above 1
91 //
92
93 bool all_neighbors_have_positive_kinetic_energy = true;
94 //bring all neighbors of the vertex to order 1
95 FacetOnCellContainer facets_on_cell(*cit);
96 for (FacetOnCellIterator focit = facets_on_cell.begin();
97 focit != facets_on_cell.end();
98 ++focit)
99 {
100 CellType const *other_cell = viennashe::util::get_other_cell_of_facet(mesh, *focit, *cit);
101 if (!other_cell)
102 continue;
103
104 if (quan.get_kinetic_energy(*other_cell, index_H-1) <= 0) // In forbidden band there is expansion order 1
105 all_neighbors_have_positive_kinetic_energy = false;
106 }
107
108
109 if (all_neighbors_have_positive_kinetic_energy)
110 break;
111 else
112 {
113 //set expansion order of all neighbors to one:
114 quan.set_expansion_order(*cit, index_H, 1);
115
116 for (FacetOnCellIterator focit = facets_on_cell.begin();
117 focit != facets_on_cell.end();
118 ++focit)
119 {
120 CellType const *other_cell = viennashe::util::get_other_cell_of_facet(mesh, *focit, *cit);
121 if (!other_cell)
122 continue;
123
124 quan.set_expansion_order(*other_cell, index_H, 1);
125 }
126 }
127 }
128 }
129 }
130
131
132
138 template <typename DeviceType,
139 typename SHEQuantity>
140 void smooth_expansion_order(DeviceType const & device,
141 SHEQuantity & quan)
142 {
143 typedef typename DeviceType::mesh_type MeshType;
144
145 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
146 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
147
148 typedef typename viennagrid::result_of::const_facet_range<MeshType>::type FacetContainer;
149 typedef typename viennagrid::result_of::iterator<FacetContainer>::type FacetIterator;
150
151 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
152 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
153
154
155 MeshType const & mesh = device.mesh();
156
157 //
158 // Ensure that expansion order between vertices does not vary too much. If difference is too large, reduce order of 'higher' vertex.
159 //
160 for (long i=0; i<10; ++i)
161 {
162 //log::info<log_smooth_expansion_order>() << "* smooth_expansion_order(): Vertex expansion order smoothing, run " << i+1 << "..." << std::endl;
163 bool something_changed = false;
164
165 FacetContainer facets(mesh);
166 for (FacetIterator fit = facets.begin();
167 fit != facets.end();
168 ++fit)
169 {
170 CellOnFacetContainer cells_on_facet(device.mesh(), viennagrid::handle(device.mesh(), fit.handle()));
171
172 CellOnFacetIterator cofit = cells_on_facet.begin();
173 CellType const & c1 = *cofit;
174 ++cofit;
175
176 if (cofit == cells_on_facet.end())
177 continue;
178
179 CellType const *c2_ptr = &(*cofit);
180
181 for (size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
182 {
183 if ( quan.get_expansion_order(c1, index_H) > quan.get_expansion_order(*c2_ptr, index_H) + 2)
184 {
185 something_changed = true;
186 quan.set_expansion_order(c1, index_H, quan.get_expansion_order(*c2_ptr, index_H) + 2);
187 }
188 if ( quan.get_expansion_order(*c2_ptr, index_H) > quan.get_expansion_order(*c2_ptr, index_H) + 2)
189 {
190 something_changed = true;
191 quan.set_expansion_order(*c2_ptr, index_H, quan.get_expansion_order(*c2_ptr, index_H) + 2);
192 }
193 } //for index_H
194 } //for eit
195
196 if (!something_changed)
197 break;
198 }
199 }
200
206 template <typename DeviceType,
207 typename SHEQuantity>
209 SHEQuantity & quan)
210 {
211 typedef typename DeviceType::mesh_type MeshType;
212
213 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
214 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
215
216 typedef typename viennagrid::result_of::const_facet_range<MeshType>::type FacetContainer;
217 typedef typename viennagrid::result_of::iterator<FacetContainer>::type FacetIterator;
218
219 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
220 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
221
222 MeshType const & mesh = device.mesh();
223
224 FacetContainer facets(mesh);
225 for (FacetIterator fit = facets.begin();
226 fit != facets.end();
227 ++fit)
228 {
229 CellOnFacetContainer cells_on_facet(device.mesh(), viennagrid::handle(device.mesh(), fit.handle()));
230
231 CellOnFacetIterator cofit = cells_on_facet.begin();
232 CellType const & c1 = *cofit;
233 ++cofit;
234 CellType const *c2_ptr = NULL;
235
236 if (cofit != cells_on_facet.end())
237 c2_ptr = &(*cofit);
238
239 for (size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
240 {
241 std::size_t order = quan.get_expansion_order(c1, index_H);
242
243 if (c2_ptr != NULL)
244 order = std::max<std::size_t>(order, quan.get_expansion_order(*c2_ptr, index_H));
245 quan.set_expansion_order(*fit, index_H, order);
246 }
247 }
248
249 }
250
251
252 namespace detail
253 {
254
261 template <typename DeviceType, typename VertexT, typename EdgeT>
264 viennashe::config const & conf)
265 {
266 typedef typename DeviceType::mesh_type MeshType;
267
268 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
269 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
270
271 typedef typename viennagrid::result_of::const_facet_range<MeshType>::type FacetContainer;
272 typedef typename viennagrid::result_of::iterator<FacetContainer>::type FacetIterator;
273
274 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
275 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
276
277 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
278 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
279
280 MeshType const & mesh = device.mesh();
281
282 std::size_t Lmax = static_cast<std::size_t>(conf.max_expansion_order());
283
284 //
285 // write expansion order on cells (even unknowns)
286 //
287 CellContainer cells(mesh);
288 for (CellIterator cit = cells.begin();
289 cit != cells.end();
290 ++cit)
291 {
292 if ( (conf.adaptive_expansions() == false)
293 || (Lmax == 1) )
294 {
295 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
296 quan.set_expansion_order(*cit, index_H, Lmax);
297 }
298 }
299
300 //
301 // Write expansion order on facets (odd unknowns)
302 //
303 FacetContainer facets(mesh);
304 for (FacetIterator fit = facets.begin();
305 fit != facets.end();
306 ++fit)
307 {
308 CellOnFacetContainer cells_on_facet(device.mesh(), viennagrid::handle(device.mesh(), fit.handle()));
309
310 CellOnFacetIterator cofit = cells_on_facet.begin();
311 CellType const & c1 = *cofit;
312 ++cofit;
313 CellType const *c2_ptr = NULL;
314
315 if (cofit != cells_on_facet.end())
316 c2_ptr = &(*cofit);
317
318 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
319 {
320 if ( conf.adaptive_expansions() )
321 {
322 std::size_t order = quan.get_expansion_order(c1, index_H);
323
324 if (c2_ptr != NULL)
325 order = std::max<std::size_t>(order, quan.get_expansion_order(*c2_ptr, index_H));
326 quan.set_expansion_order(*fit, index_H, order);
327 }
328 else
329 quan.set_expansion_order(*fit, index_H, Lmax);
330 }
331 }
332
333 } //distribute_expansion_orders_impl
334
335
336
337
338 } //namespace detail
339
340
347 template <typename DeviceType,
348 typename VertexT, typename EdgeT>
351 viennashe::config const & conf)
352 {
354
355 //
356 // At band edge use first order expansions
357 //
359
360 //
361 // Bring edges in consistent state:
362 //
364 }
365
366 template <typename DeviceType>
367 void distribute_expansion_orders(DeviceType const & device,
369 viennashe::config const & conf)
370 {
372
373 SHEUnknownType & f_n = quantities.electron_distribution_function();
374 SHEUnknownType & f_p = quantities.hole_distribution_function();
375
376 // Setup energies for electrons:
377 if (conf.with_electrons() && conf.get_electron_equation() == EQUATION_SHE)
379
380 // Setup energies for holes:
381 if (conf.with_holes() && conf.get_hole_equation() == EQUATION_SHE)
383 }
384
385
386 }
387}
388
389#endif
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
long max_expansion_order() const
Returns the current maximum expansion order.
Definition: config.hpp:369
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
bool adaptive_expansions() const
Returns the flag for the use of adaptive expansions.
Definition: config.hpp:379
bool with_electrons() const
Returns true if electrons are considered in the simulation.
Definition: config.hpp:226
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
The main SHE simulator controller class. Acts as an accessor for all SHE quantities needed for the si...
UnknownSHEQuantityType const & electron_distribution_function() const
UnknownSHEQuantityType const & hole_distribution_function() const
General representation of any solver quantity defined on two different element types (e....
std::size_t get_expansion_order(AssociatedT1 const &elem, std::size_t index_H) const
void set_expansion_order(AssociatedT1 const &elem, std::size_t index_H, std::size_t value)
The SHE configuration class is defined here.
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.
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.
Miscellaneous utilities.
void distribute_expansion_orders_impl(DeviceType const &device, viennashe::she::unknown_she_quantity< VertexT, EdgeT > &quan, viennashe::config const &conf)
Assigns the various expansion orders to the device. This is the implementation.
void smooth_expansion_order(DeviceType const &device, SHEQuantity &quan)
Smoothes the expansion order over the device such that neighboring vertices differ in their expansion...
void lower_expansion_order_near_bandedge(DeviceType const &device, SHEQuantity &quan)
Assigns the various expansion orders to the device. Uniform expansion order implemented here.
void distribute_expansion_orders(DeviceType &device, viennashe::she::unknown_she_quantity< VertexT, EdgeT > &quan, viennashe::config const &conf)
Assigns the various expansion orders to the device. This is the public interface.
void write_expansion_order_to_facets(DeviceType &device, SHEQuantity &quan)
Writes expansion orders on edges. Edge expansion order is given as max(order(v1), order(v2)),...
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...
Definition: misc.hpp:196
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
@ EQUATION_SHE
Definition: forwards.h:118
Provides a number of fundamental constants. All constants in SI units.
Provides the exceptions used inside the viennashe::she namespace.
Defines a SHE quantity in (x, H)-space for use within the solvers of ViennaSHE.
Defines a generic simulator quantity for use within the solvers of ViennaSHE.
A container of all quantities defined for a certain timestep t.
Defines the log keys used within the viennashe::she namespace.