ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
assemble_all.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_SHE_ASSEMBLE_ALL_HPP
2#define VIENNASHE_SHE_ASSEMBLE_ALL_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
25
26#include "viennashe/log/log.hpp"
28
30
35namespace viennashe
36{
37 namespace she
38 {
39
40 template <typename DeviceType,
41 typename TimeStepQuantitiesT,
42 typename VertexT,
43 typename EdgeT,
44 typename MatrixType,
45 typename VectorType>
46 void assemble( DeviceType & device,
47 TimeStepQuantitiesT & old_quantities,
48 TimeStepQuantitiesT & quantities,
49 viennashe::config const & conf,
51 MatrixType & A,
52 VectorType & b,
53 bool use_timedependence, bool quan_valid)
54 {
55 typedef typename DeviceType::mesh_type MeshType;
56
57 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
58 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
59
60 typedef typename viennagrid::result_of::const_facet_range<MeshType>::type FacetContainer;
61 typedef typename viennagrid::result_of::iterator<FacetContainer>::type FacetIterator;
62
63 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
64 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
65
66 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
67 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
68
69 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
70 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
71
72 typedef viennashe::math::sparse_matrix<double> CouplingMatrixType;
73
75
76 std::vector< scattering_base<DeviceType> * > scattering_processes;
77
78 if (conf.with_traps())
79 {
80 if (! conf.with_electrons() || ! conf.with_holes())
81 throw viennashe::unavailable_feature_exception("Trapping without considering electrons or holes is not supported!");
83 throw viennashe::unavailable_feature_exception("Trapping without SHE for electrons is not supported!");
85 throw viennashe::unavailable_feature_exception("Trapping without SHE for holes is not supported!");
86 }
87
88// try
89// {
90 MeshType const & mesh = device.mesh();
91
92 SpatialUnknownType const & potential = quantities.get_unknown_quantity(viennashe::quantity::potential());
93 SpatialUnknownType const & old_potential = old_quantities.get_unknown_quantity(viennashe::quantity::potential()); //TODO: Take old timestep
94
95 viennashe::she::unknown_she_quantity<VertexT, EdgeT> const & old_quan = old_quantities.she_quantity(quan.get_name());
96
97 //
98 // Set up scatter matrices:
99 //
100 const std::size_t L_max = static_cast<std::size_t>(conf.max_expansion_order());
101 const std::size_t num_harmonics = std::size_t(L_max+1) * std::size_t(L_max+1);
102 CouplingMatrixType scatter_op_in(num_harmonics, num_harmonics);
103 CouplingMatrixType scatter_op_out(num_harmonics, num_harmonics);
104
105 for (std::size_t i=0; i < std::size_t(L_max+1) * std::size_t(L_max+1); ++i)
106 scatter_op_out(i,i) += 1.0;
107 scatter_op_in(0,0) += 1.0;
108
110 std::size_t Lmax = static_cast<std::size_t>(conf.max_expansion_order()); //maximum expansion order
111 std::size_t coupling_rows = static_cast<std::size_t>((Lmax+1) * (Lmax+1));
112 std::size_t coupling_cols = coupling_rows;
113
114 log::debug<log_assemble_all>() << "* assemble_all(): Computing coupling matrices..." << std::endl;
115 CouplingMatrixType identity(coupling_rows, coupling_cols);
116 for (std::size_t i=0; i<coupling_rows; ++i)
117 for (std::size_t j=0; j<coupling_cols; ++j)
118 identity(i,j) = (i == j) ? 1.0 : 0.0;
119
120 CouplingMatrixType a_x(coupling_rows, coupling_cols);
121 CouplingMatrixType a_y(coupling_rows, coupling_cols);
122 CouplingMatrixType a_z(coupling_rows, coupling_cols);
123
124
125 CouplingMatrixType b_x(coupling_rows, coupling_cols);
126 CouplingMatrixType b_y(coupling_rows, coupling_cols);
127 CouplingMatrixType b_z(coupling_rows, coupling_cols);
128
129 //note: interchanged coordinates
130 fill_coupling_matrices(a_x, a_y, a_z,
131 b_x, b_y, b_z,
132 static_cast<int>(Lmax));
133
134 CouplingMatrixType a_x_transposed = a_x.trans();
135 CouplingMatrixType a_y_transposed = a_y.trans();
136 CouplingMatrixType a_z_transposed = a_z.trans();
137
138 CouplingMatrixType b_x_transposed = b_x.trans();
139 CouplingMatrixType b_y_transposed = b_y.trans();
140 CouplingMatrixType b_z_transposed = b_z.trans();
141
143 {
144 log::debug<log_assemble_all>() << "a_x: " << a_x << std::endl;
145 log::debug<log_assemble_all>() << "a_y: " << a_y << std::endl;
146 log::debug<log_assemble_all>() << "a_z: " << a_z << std::endl;
147 log::debug<log_assemble_all>() << "b_x: " << b_x << std::endl;
148 log::debug<log_assemble_all>() << "b_y: " << b_y << std::endl;
149 log::debug<log_assemble_all>() << "b_z: " << b_z << std::endl;
150
151 log::debug<log_assemble_all>() << "identity: " << identity << std::endl;
152
153 log::debug<log_assemble_all>() << "scatter_op_out: " << scatter_op_out << std::endl;
154 log::debug<log_assemble_all>() << "scatter_op_in: " << scatter_op_in << std::endl;
155 }
156
157 //
158 // Setup vector of scattering processes:
159 //
160
161
162 if (conf.scattering().acoustic_phonon().enabled())
163 {
164 log::debug<log_assemble_all>() << "assemble(): Acoustic phonon scattering is ENABLED!" << std::endl;
165 scattering_processes.push_back(new acoustic_phonon_scattering<DeviceType>(device, conf));
166 }
167
168 if (conf.scattering().optical_phonon().enabled())
169 {
170 log::debug<log_assemble_all>() << "assemble(): Optical phonon scattering is ENABLED!" << std::endl;
171 scattering_processes.push_back(new optical_phonon_scattering<DeviceType>(device, conf, conf.energy_spacing()));
172 }
173
174 if (conf.scattering().ionized_impurity().enabled())
175 {
176 log::debug<log_assemble_all>() << "assemble(): Ionized impurity scattering is ENABLED!" << std::endl;
177 scattering_processes.push_back(new ionized_impurity_scattering<DeviceType>(device, conf));
178 }
179
180 if (conf.scattering().impact_ionization().enabled())
181 {
182 // Warn the user if we already know that he/she is going to simulate bullshit.
183 if ( ! conf.with_holes() || conf.get_hole_equation() != viennashe::EQUATION_SHE )
184 log::warn() << std::endl << "WARNING: II scattering enabled, but 'BTE for holes' is disabled! Expect inconsistent results!" << std::endl;
186 log::warn() << std::endl << "WARNING: II scattering enabled, but 'BTE for electrons' is disabled! Expect inconsistent results!" << std::endl;
187
188 scattering_processes.push_back(new impact_ionization_scattering<DeviceType>(device, conf));
189 }
190
191 if (conf.with_traps() && conf.scattering().trapped_charge().enabled())
192 {
193 log::debug<log_assemble_all>() << "assemble(): Trapped charge scattering is ENABLED!" << std::endl;
194 scattering_processes.push_back(new trapped_charge_scattering<DeviceType, TimeStepQuantitiesT>(device, conf, quantities));
195 }
196
197 typedef typename viennashe::electric_field_wrapper<DeviceType, SpatialUnknownType> ElectricFieldAccessor;
198 ElectricFieldAccessor Efield(device, potential);
199
200 if (conf.scattering().surface().enabled())
201 {
202 log::debug<log_assemble_all>() << "assemble(): Surface roughness scattering is ENABLED!" << std::endl;
203 scattering_processes.push_back(new surface_scattering<DeviceType, ElectricFieldAccessor>(device, conf, Efield));
204 }
205
206
207 //
208 // Assemble SHE system:
209 // - scattering operators on vertices
210 // - free streaming operator on vertices
211 // - scattering operators on edges
212 // - free streaming operator on edges
213 // - any other stuff (traps on cells, etc.)
214 //
215
216 if (quan_valid && conf.scattering().electron_electron() && conf.with_electrons())
217 {
218 log::debug<log_assemble_all>() << "assemble(): Electron electron scattering is ENABLED!" << std::endl;
219 assemble_ee_scattering(device, conf, quan, old_quan, A, b);
220 }
221
222 //
223 // Step 1: Assemble on even nodes
224 //
225 log::debug<log_assemble_all>() << "* assemble_all(): Even unknowns..." << std::endl;
226
227 CellContainer cells(mesh);
228 for (CellIterator cit = cells.begin();
229 cit != cells.end();
230 ++cit)
231 {
232 log::debug<log_assemble_all>() << "* assemble_all(): Assembling on cell " << *cit << std::endl;
233
234 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
235 {
237 log::debug<log_assemble_all>() << "* assemble_all(): Assembling on energy index " << index_H << std::endl;
238
240 A, b,
241 *cit, index_H,
242 identity);
243
245 continue;
246
247 //
248 // Scattering operator Q{f}
249 //
250 assemble_scattering_operator_on_box( scattering_processes,
251 device, conf, quan,
252 A, b,
253 *cit, index_H,
254 scatter_op_in, scatter_op_out);
255 }
256
257 //
258 // Free streaming operator L{f}
259 //
260
261 // iterate over neighbor cells holding the odd unknowns:
262 FacetOnCellContainer facets_on_cell(*cit);
263 for (FacetOnCellIterator focit = facets_on_cell.begin();
264 focit != facets_on_cell.end();
265 ++focit)
266 {
268 log::debug<log_assemble_all>() << "* assemble_all(): Assembling coupling with facet " << *focit << std::endl;
269
270 CellType const *other_cell_ptr = util::get_other_cell_of_facet(mesh, *focit, *cit);
271 if (!other_cell_ptr) continue; //Facet is on the boundary of the simulation domain -> homogeneous Neumann conditions
272
273 CouplingMatrixType coupling_matrix_diffusion = coupling_matrix_in_direction(a_x, a_y, a_z,
274 *cit,
275 *other_cell_ptr,
276 quan.get_carrier_type_id());
277
278 // note that the sign change due to MEDS is included in the choice of the normal vector direction (order of vertex vs. other_vertex):
279 // - B \cdot n for even unknowns,
280 // + B \cdot n for odd unknowns
281 CouplingMatrixType coupling_matrix_drift = coupling_matrix_in_direction(b_x, b_y, b_z, *other_cell_ptr, *cit, quan.get_carrier_type_id());
282
283 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
284 {
286 A, b,
287 *cit, *focit, index_H,
288 coupling_matrix_diffusion,
289 coupling_matrix_drift,
290 false);
291 }
292 } //for edges
293
294 //
295 // Time dependence df/dt (and possibly df/dH * dH/dt)
296 //
297 if (use_timedependence)
298 {
299 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
300 {
302 A, b,
303 *cit, index_H,
304 identity,
305 potential,
306 old_potential);
307 }
308 }
309 } //for cells
310
311
312 //
313 // Step 2: Assemble on odd 'nodes' (i.e. facets). TODO: Resolve code duplication w.r.t. above
314 //
315 log::info<log_assemble_all>() << "* assemble_all(): Odd unknowns..." << std::endl;
316
317 FacetContainer facets(mesh);
318 for (FacetIterator fit = facets.begin();
319 fit != facets.end();
320 ++fit)
321 {
323 log::debug<log_assemble_all>() << "* assemble_all(): Assembling on facet " << *fit << std::endl;
324
325 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
326 {
328 log::debug<log_assemble_all>() << "* assemble_all(): Assembling on energy index " << index_H << std::endl;
329
330 //
331 // Scattering operator Q{f}
332 //
333 assemble_scattering_operator_on_box(scattering_processes,
334 device, conf, quan,
335 A, b,
336 *fit, index_H,
337 scatter_op_in, scatter_op_out);
338 }
339
340 //
341 // Free streaming operator L{f}
342 //
343
344 // iterate over cells of facet
345 CellOnFacetContainer cells_on_facet(mesh, fit.handle());
346 for (CellOnFacetIterator cofit = cells_on_facet.begin();
347 cofit != cells_on_facet.end();
348 ++cofit)
349 {
351 log::debug<log_assemble_all>() << "* assemble_all(): Assembling coupling with cell " << *cofit << std::endl;
352
353 CellType const *other_cell_ptr = util::get_other_cell_of_facet(mesh, *fit, *cofit);
354 if (!other_cell_ptr) continue; //Facet is on the boundary of the simulation domain -> homogeneous Neumann conditions
355
356 CouplingMatrixType coupling_matrix_diffusion = coupling_matrix_in_direction(a_x_transposed, a_y_transposed, a_z_transposed,
357 *other_cell_ptr,
358 *cofit,
359 quan.get_carrier_type_id());
360
361 // note that the sign change due to MEDS is included in the choice of the normal vector direction (order of vertex vs. other_vertex):
362 // - B \cdot n for even unknowns,
363 // + B \cdot n for odd unknowns
364 CouplingMatrixType coupling_matrix_drift = coupling_matrix_in_direction(b_x_transposed, b_y_transposed, b_z_transposed, *other_cell_ptr, *cofit, quan.get_carrier_type_id());
365
366 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
367 {
369 A, b,
370 *cofit, *fit, index_H,
371 coupling_matrix_diffusion,
372 coupling_matrix_drift,
373 true);
374 }
375 } //for vertices
376
377 //
378 // Time dependence df/dt (and possibly df/dH * dH/dt)
379 //
380 if (use_timedependence)
381 {
382 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
383 {
385 A, b,
386 *fit, index_H,
387 identity,
388 potential,
389 old_potential);
390 }
391 }
392
393 } //for facets
394
395
396 // Assemble traps on cells (to be integrated into the assembly above):
397 if (conf.with_traps())
398 {
399 log::debug<log_assemble_all>() << "assemble(): Assembly for traps ..." << std::endl;
400 viennashe::she::assemble_traps(device, quantities, conf, quan, A, b);
401 }
402
403 //
404 // Cleanup:
405 //
406 for (std::size_t i=0; i<scattering_processes.size(); ++i)
407 {
408 if ( scattering_processes[i] ) delete scattering_processes[i];
409 scattering_processes[i] = 0;
410 }
411/* }
412 catch (...)
413 {
414 //
415 // Cleanup:
416 //
417 for (std::size_t i=0; i<scattering_processes.size(); ++i)
418 if ( scattering_processes[i] ) delete scattering_processes[i];
419 // Rethrow
420 throw;
421 }
422*/
423
424 }
425 } //namespace she
426} //namespace viennashe
427
428#endif
Common routines for the assembly of SHE equations.
Implements the assembly for electron-electron scattering.
Generic assembly of the scattering operator(s) is implemented here.
Assembly of the free-streaming operator is implemented here.
Generic assembly of traps is implemented here. At the moment only SRH type traps are supported.
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 with_traps() const
Returns true if traps are considered in the simulation.
Definition: config.hpp:243
double energy_spacing() const
Returns the uniform energy spacing of discrete energies.
Definition: config.hpp:460
bool with_electrons() const
Returns true if electrons are considered in the simulation.
Definition: config.hpp:226
viennashe::she::scatter_config & scattering()
Returns the configuration object for scattering.
Definition: config.hpp:475
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
Ionized impurity scattering process.
ionized_impurity_scattering_parameters const & ionized_impurity() const
Returns the parameters for ionized impurity scattering. Const-version.
Definition: config.hpp:377
impact_ionization_scattering_parameters const & impact_ionization() const
Returns the parameters for impact ionization scattering. Const-version.
Definition: config.hpp:382
surface_scattering_parameters const & surface() const
Returns the parameters for surface scattering. Const-version.
Definition: config.hpp:402
acoustic_phonon_scattering_parameters const & acoustic_phonon() const
Returns the parameters for acoustic phonon scattering. Const-version.
Definition: config.hpp:367
trapped_charge_scattering_parameters const & trapped_charge() const
Returns the parameters for fixed charge scattering. Const-version.
Definition: config.hpp:397
optical_phonon_scattering_parameters const & optical_phonon() const
Returns the parameters for optical phonon scattering. Const-version.
Definition: config.hpp:372
bool electron_electron() const
Returns true if electron-electron scattering is activated.
Definition: config.hpp:387
General representation of any solver quantity defined on two different element types (e....
carrier_type_id get_carrier_type_id() const
Exception for the case that a requested feature is not available (due to configuration or due to not ...
Definition: exception.hpp:103
Computes the electric field from a potential.
A logging facility providing fine-grained control over logging in ViennaSHE.
logger< true > warn()
Used to log warnings. The logging level is logWARNING.
Definition: log.hpp:303
bool is_conductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a metal.
Definition: all.hpp:147
void assemble_traps(DeviceType const &device, TimeStepQuantitiesT &quantities, viennashe::config const &conf, SHEQuantity const &quan, MatrixType &matrix, VectorType &rhs)
void fill_coupling_matrices(MatrixType &a_x, MatrixType &a_y, MatrixType &a_z, MatrixType &b_x, MatrixType &b_y, MatrixType &b_z, int L_max)
Public interface for filling coupling matrices.
void assemble_scattering_operator_on_box(ScatterProcessesT const &scatter_processes, DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, MatrixType &A, VectorType &b, ElementType const &elem, std::size_t index_H, CouplingMatrix const &coupling_in_scatter, CouplingMatrix const &coupling_out_scatter)
void assemble(DeviceType &device, TimeStepQuantitiesT &old_quantities, TimeStepQuantitiesT &quantities, viennashe::config const &conf, viennashe::she::unknown_she_quantity< VertexT, EdgeT > const &quan, MatrixType &A, VectorType &b, bool use_timedependence, bool quan_valid)
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...
void assemble_ee_scattering(DeviceType const &device, viennashe::config const &conf, SHEQuantityT const &quan, SHEQuantityT const &quan_old, MatrixType &matrix, VectorType &rhs)
Interface function for electron-electron scattering. Differs significantly from ac,...
void assemble_timederivative(DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, SHEQuantity const &quan_old, MatrixType &A, VectorType &b, ElementType const &elem, std::size_t index_H, CouplingMatrixType const &identity_matrix, QuantityPotential const &quan_pot, QuantityPotentialOld const &quan_pot_old)
void assemble_boundary_on_box(DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, MatrixType &A, VectorType &b, CellType const &cell, std::size_t index_H, CouplingMatrixType const &coupling_identity)
Worker function for the assembly of the free streaming operator. Handles the assembly of both even an...
void assemble_free_streaming_operator_on_box(DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, MatrixType &A, VectorType &, CellType const &cell, FacetType const &facet, std::size_t index_H, CouplingMatrixType const &coupling_matrix_diffusion, CouplingMatrixType const &coupling_matrix_drift, bool odd_assembly)
Worker function for the assembly of the free streaming operator. Handles the assembly of both even an...
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
An accessor to the electric field on vertices and edges. Potential requiered.
Defines the log keys used within the viennashe::she namespace.