ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
linear_solver.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_SHE_LINEAR_SOLVER_HPP
2#define VIENNASHE_SHE_LINEAR_SOLVER_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// viennashe
19#include "viennashe/forwards.h"
26#include "viennashe/config.hpp"
27
28#include "viennashe/log/log.hpp"
30
31
36namespace viennashe
37{
38 namespace she
39 {
40
42 template <typename DeviceType,
43 typename SHEQuantity>
44 void fill_block_indices(DeviceType const & device,
45 SHEQuantity const & quan,
46 std::size_t system_size,
47 std::vector<std::pair<std::size_t, std::size_t> > & indices)
48 {
49 typedef typename DeviceType::mesh_type MeshType;
50
51 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
52 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
53
54 indices.resize(quan.get_value_H_size());
55
56 std::size_t last_found = 0;
57
58 CellContainer cells(device.mesh());
59 for (std::size_t index_H = 0; index_H < indices.size(); ++index_H)
60 {
61 indices[index_H].first = last_found;
62
63 for (CellIterator cit = cells.begin();
64 cit != cells.end();
65 ++cit)
66 {
67 if (quan.get_unknown_index(*cit, index_H) > -1)
68 {
69 last_found = std::size_t(quan.get_unknown_index(*cit, index_H));
70 indices[index_H].first = last_found;
71 if (index_H > 0)
72 indices[index_H-1].second = last_found;
73 break;
74 }
75 }
76
77 // make sure .second is always set:
78 if (indices[index_H].second < indices[index_H].first)
79 indices[index_H].second = indices[index_H].first;
80 }
81
82 indices[indices.size()-1].second = system_size;
83 }
84
85
86
96 template <typename DeviceType,
97 typename SHEQuantity,
98 typename MatrixType,
99 typename VectorType>
100 VectorType solve(DeviceType const & device,
101 SHEQuantity const & quan,
102 viennashe::config const & configuration,
103 MatrixType & full_matrix,
104 VectorType & full_rhs,
105 std::size_t reduced_unknowns)
106 {
107 typedef typename VectorType::value_type NumericType;
108
109 //
110 // Eliminate odd unknowns
111 //
112 //log::debug<log_linear_solver>() << "Eliminate odd unknowns..." << std::endl;
113 viennashe::math::sparse_matrix<NumericType> compressed_matrix(reduced_unknowns, reduced_unknowns);
114 VectorType compressed_rhs(reduced_unknowns);
115 compressed_rhs.clear();
116 compressed_rhs.resize(reduced_unknowns);
118
119 //
120 // Eliminate odd unknowns
121 //
122
123 //log::info<log_linear_solver>() << "* solve(): Diagonalising odd unknowns... " << std::endl;
124 viennashe::she::diagonalise_odd2odd_coupling_matrix(full_matrix, full_rhs, reduced_unknowns);
125
126 //log::debug<log_linear_solver>() << "Full matrix: " << viennashe::util::sparse_to_string(full_matrix) << std::endl;
127 //log::debug<log_linear_solver>() << "Full rhs: " << full_rhs << std::endl;
128
129 //log::info<log_linear_solver>() << "* solve(): Eliminating odd unknowns... " << std::endl;
130 eliminate_odd_unknowns(full_matrix, full_rhs,
131 compressed_matrix, compressed_rhs);
132
133 //log::debug<log_linear_solver>() << "Reduced matrix: " << viennashe::util::sparse_to_string(compressed_matrix) << std::endl;
134 //log::debug<log_linear_solver>() << "Reduced rhs: " << compressed_rhs << std::endl;
135
136 //
137 // Check matrix for M-matrix structure (debug)
138 // Makes sense for L=1 only!
139 // Full system matrix is M-matrix only if no inelastic scattering is included.
140 //
141 //viennashe::util::m_matrix_check(compressed_matrix);
142
143 std::vector<double> scaling_vector(compressed_matrix.size1(), 1.0);
144 if (conf.scale())
145 {
146 setup_unknown_scaling(device, configuration, quan, scaling_vector);
147 rescale_system(compressed_matrix, scaling_vector);
148 }
149
150 //
151 // Normalize equation system (solver will be thankful)
152 //
153 VectorType scale_factors = viennashe::math::row_normalize_system(compressed_matrix, compressed_rhs);
154
155 //log::debug<log_linear_solver>() << "Reduced matrix: " << viennashe::util::sparse_to_string(compressed_matrix) << std::endl;
156 //log::debug<log_linear_solver>() << "Reduced rhs: " << compressed_rhs << std::endl;
157
158
159 // set up preconditioner information:
160 fill_block_indices(device, quan, compressed_rhs.size(), conf.block_preconditioner_boundaries());
161
162 //
163 // Solve equation system
164 //
165 VectorType compressed_result = viennashe::solvers::solve(compressed_matrix,
166 compressed_rhs,
167 conf);
168
169 //
170 // Scale unknowns back:
171 //
172 if (conf.scale())
173 {
174 for (std::size_t i=0; i<compressed_result.size(); ++i)
175 compressed_result[i] *= scaling_vector[i]*scale_factors[i];
176 }
177
178 //
179 // Recover full solution of even and odd unknowns
180 //
181 VectorType she_result = recover_odd_unknowns(full_matrix, full_rhs, compressed_result);
182
183 double relative_residual = viennashe::math::norm_2(viennashe::math::subtract(viennashe::math::prod(full_matrix, she_result), full_rhs));
184 relative_residual /= viennashe::math::norm_2(full_rhs);
185 if (relative_residual > 1e-7)
186 log::info<log_linear_solver>() << "* solve(): Relative linear solver residual of full system: " << relative_residual << std::endl;
187
188 return she_result;
189 }
190 }
191}
192
193#endif
Defines a set of checker functors for micro-tests within ViennaSHE.
The main SHE configuration class. To be adjusted by the user for his/her needs.
Definition: config.hpp:124
linear_solver_config_type & linear_solver()
Returns the configuration object for the linear solver.
Definition: config.hpp:485
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
Sparse matrix class based on a vector of binary trees for holding the entries.
Definition: linalg_util.hpp:69
A configuration class holding options for use within the different linear solvers.
Definition: config.hpp:57
void scale(bool value)
Controls the scaling of unkowns. Give "false" to disable unkown scaling.
Definition: config.hpp:68
block_preconditioner_boundaries_container & block_preconditioner_boundaries()
Definition: config.hpp:188
The SHE configuration class is defined here.
Implements the elimination and the recovery of odd-order unknowns from the discrete system of equatio...
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.
VectorType::value_type norm_2(VectorType const &v)
Definition: linalg_util.hpp:37
VectorType subtract(VectorType const &x, VectorType const &y)
Helper routine for the generic vector subtraction z = x - y;.
Definition: linalg_util.hpp:51
VectorType prod(sparse_matrix< NumericT > const &system_matrix, VectorType const &x)
Computes A * x for a sparse A and a vector x.
VectorT row_normalize_system(sparse_matrix< NumericT > &system_matrix, VectorT &rhs)
Normalizes an equation system such that all diagonal entries are non-negative, and such that all 2-no...
VectorT recover_odd_unknowns(MatrixT const &full_matrix, VectorT const &full_rhs, VectorT const &compressed_result)
Recovers the odd-order unknowns from the even-order unknowns.
Definition: eliminate.hpp:305
void eliminate_odd_unknowns(FullMatrixType &system_matrix, VectorType const &rhs, CompressedMatrixType &compressed_matrix, VectorType &compressed_rhs)
Eliminates all odd spherical harmonics expansion coefficients from the system matrix.
Definition: eliminate.hpp:226
void rescale_system(MatrixType &system_matrix, VectorType const &scaling)
Scales the system matrix (right-preconditioner) with respect to the rescaled unknowns.
Definition: rescaling.hpp:91
void setup_unknown_scaling(DeviceType const &device, viennashe::config const &conf, SHEQuantity &quan, VectorType &scaling_vector)
Initializes the unknown scaling. Returns a vector holding the scaling factors.
Definition: rescaling.hpp:50
void diagonalise_odd2odd_coupling_matrix(FullMatrixType &system_matrix, VectorType &rhs, std::size_t num_even)
Eliminates all odd spherical harmonics expansion coefficients in the off diagonals of S^oo from the s...
Definition: eliminate.hpp:80
void fill_block_indices(DeviceType const &device, SHEQuantity const &quan, std::size_t system_size, std::vector< std::pair< std::size_t, std::size_t > > &indices)
Writes an array of block indices.
VectorType solve(DeviceType const &device, SHEQuantity const &quan, viennashe::config const &configuration, MatrixType &full_matrix, VectorType &full_rhs, std::size_t reduced_unknowns)
Public interface for solving the provided system of discretized SHE equations.
std::vector< double > solve(viennashe::math::sparse_matrix< double > &A, std::vector< double > const &b, linear_solver_config const &config)
Public interface for solving a system of linear equations represented using a sparse matrix.
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
Rescales the linear system such that unknowns are approximately the same order of magnitude.
Provides the exceptions used inside the viennashe::she namespace.
Forward declarations for a generic solver layer, providing bindings to a native Gauss solver,...
Defines the log keys used within the viennashe::she namespace.