ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
eliminate.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_SHE_ELIMINATE_HPP
2#define VIENNASHE_SHE_ELIMINATE_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#include <cassert>
21
22// viennashe
24#include "viennashe/log/log.hpp"
26
31namespace viennashe
32{
33 namespace she
34 {
35
36 namespace detail
37 {
38
39 template <typename FullMatrixType, typename VectorType>
40 void combine_lines(FullMatrixType & system_matrix, VectorType & rhs,
41 std::size_t line1, std::size_t line_to_add, std::size_t column_to_zero)
42 {
43
44 typedef typename FullMatrixType::row_type RowType;
45 typedef typename FullMatrixType::iterator2 AlongRowIterator;
46
47 const double s = system_matrix(line1, column_to_zero) / system_matrix(line_to_add, line_to_add);
48
49 if (!s) return;
50
51 RowType & values_to_add = system_matrix.row(line_to_add); // 'line_to_add'
52
53 // multiply 'line_to_add' with 's' and subtract it from the current line
54 rhs[line1] = rhs[line1] - rhs[line_to_add] * s;
55 // multiply 'line_to_add' with 's' and subtract it from the current line 'i'
56 for (AlongRowIterator iter = values_to_add.begin(); iter != values_to_add.end(); ++iter)
57 {
58 const double value = iter->second;
59 const std::size_t current_col = iter->first;
60
61 if (!value) continue;
62
63 system_matrix(line1, current_col) -= value * s ;
64 }
65
66 system_matrix.row(line1).erase(column_to_zero);
67
68 } // combine_lines
69 } // namespace detail
70
79 template <typename FullMatrixType, typename VectorType>
80 void diagonalise_odd2odd_coupling_matrix(FullMatrixType & system_matrix, VectorType & rhs, std::size_t num_even)
81 {
82 typedef typename FullMatrixType::row_type RowType;
83 typedef typename RowType::iterator AlongRowIterator;
84
85 const std::size_t N = rhs.size();
86
87 // avoid round off errors by dividing through large numbers!
88 //viennashe::math::row_normalize_system(system_matrix, rhs);
89
90 // for each line in S^oo ; starting at the TOP + 1
91 for ( std::size_t i = num_even + 1; i < N; ++i)
92 {
93 // get the line
94 RowType & line = system_matrix.row(i);
95 // get the off diagonal and add line
96 for (AlongRowIterator cit = line.begin(); cit != line.end(); ++cit)
97 {
98 const std::size_t column_id = cit->first;
99
100 if (column_id >= i)
101 break; // stay left to the diagonal
102
103 if ( column_id < num_even)
104 continue; // skip elements in S^oe
105 else
106 {
107 // column_id < i ... ok we are left to the diagonal
108 // now combine lines
109 const std::size_t line_to_add = i - (i - column_id);
110
111 //std::cout << "i = " << i << " # col = " << column_id << " # dist = " << i-column_id << " # line_to_add = " << line_to_add << std::endl;
112
113 if (line_to_add < num_even)
114 {
115 std::cerr << "Oh no! line_to_add < num_even " << std::endl;
116 std::cerr << "Oh no! " << i << " - " << column_id << " < " << num_even << std::endl;
117 throw "Oh no! line_to_add < num_even ";
118 }
119
120 viennashe::she::detail::combine_lines( system_matrix, rhs, i, line_to_add, column_id );
121
122 break; // done :)
123 }
124 }// get off diagonal
125
126 } // for each line in S^oo
127
128 for (std::size_t i = num_even - 1; i < N; ++i)
129 {
130 RowType & col = system_matrix.row(i);
131 for (AlongRowIterator cit = col.begin(); cit != col.end(); )
132 {
133 if (!cit->second)
134 {
135 AlongRowIterator cit_delete = cit;
136 ++cit;
137 col.erase(cit_delete);
138 }
139 else
140 {
141 ++cit;
142 }
143 } // for each column
144 } // for each row
145
146 // for each line in S^oo ; starting at the BOTTOM
147 for ( std::size_t i = N - 1 /* index origin 0 */;
148 i >= num_even; --i)
149 {
150 // get the line
151 RowType & line = system_matrix.row(i);
152 // get the off diagonal and add line
153 for (AlongRowIterator cit = line.begin(); cit != line.end(); ++cit)
154 {
155 const std::size_t column_id = cit->first;
156
157 if (column_id < i && column_id >= num_even)
158 {
159 std::cerr << "Oh no! There are still values left to the diagonal!" << std::endl;
160 std::cerr << " column_id = " << column_id << " # i = " << i << " # num_even = " << num_even << std::endl;
161 std::cerr << cit->second << std::endl;
162 throw "Oh no! There are still values left to the diagonal!";
163 }
164
165
166 if (column_id < num_even)
167 {
168 continue; // skip elements in S^oe
169 }
170 else if (column_id == i)
171 {
172 continue; // skip the diagonal element
173 }
174 else
175 {
176 // column_id > i ... ok we are *right* to the diagonal
177 // now combine lines
178 const std::size_t line_to_add = i + (column_id - i);
179
180 if (line_to_add >= N)
181 {
182 std::cerr << "Oh no! line_to_add >= N # " << line_to_add << " >= " << N << std::endl;
183 throw "Oh no! line_to_add >= N ";
184 }
185
186 viennashe::she::detail::combine_lines( system_matrix, rhs, i, line_to_add, column_id );
187
188 break; // done :)
189 }
190 }// get off diagonal
191
192 } // for each line in S^oo
193
194
195 // FINALLY: Heal the sparse matrix; find true zeros and eliminate
196 for (std::size_t i = num_even - 1; i < N; ++i)
197 {
198 RowType & col = system_matrix.row(i);
199 for (AlongRowIterator cit = col.begin(); cit != col.end(); )
200 {
201 if (!cit->second)
202 {
203 AlongRowIterator cit_delete = cit;
204 ++cit;
205 col.erase(cit_delete);
206 }
207 else
208 {
209 ++cit;
210 }
211 } // for each column
212 } // for each row
213
214 } // diagonalise_odd2odd_coupling_matrix
215
216
217
225 template <typename FullMatrixType, typename CompressedMatrixType, typename VectorType>
226 void eliminate_odd_unknowns(FullMatrixType & system_matrix, VectorType const & rhs,
227 CompressedMatrixType & compressed_matrix, VectorType & compressed_rhs)
228 {
229 typedef typename FullMatrixType::row_type RowType;
230 typedef typename FullMatrixType::iterator2 AlongRowIterator;
231
232 std::size_t num_even = compressed_matrix.size1();
233
234 for (std::size_t i=0; i<num_even; ++i)
235 {
236 //write new rhs entry:
237 compressed_rhs[i] = rhs[i];
238
239 RowType & row = system_matrix.row(i);
240 for ( AlongRowIterator iter = row.begin();
241 iter != row.end();
242 ++iter )
243 {
244 if ( iter->first < num_even ) //even unknown
245 {
246 compressed_matrix(i, iter->first) += iter->second;
247 }
248 else //odd unknown
249 {
250 //check for valid diagonal entry:
251 double odd_diagonal_entry = -1.0;
252
253 RowType & odd_row = system_matrix.row(iter->first);
254 for ( AlongRowIterator odd_iter = odd_row.begin();
255 odd_iter != odd_row.end();
256 ++odd_iter )
257 {
258 if (iter->first == odd_iter->first)
259 {
260 odd_diagonal_entry = odd_iter->second;
261 break;
262 }
263 }
264
265 if ( odd_diagonal_entry <= 0.0 )
266 {
267 log::error() << "ERROR in eliminate_odd_unknowns(): Diagonal entry " << iter->first
268 << " not positive or not existing: " << odd_diagonal_entry << std::endl;
269 throw viennashe::she::invalid_matrixelement_exception("eliminate_odd_unknowns(): Diagonal entry not positive or not existing!", odd_diagonal_entry);
270 }
271
272 for ( AlongRowIterator odd_iter = odd_row.begin();
273 odd_iter != odd_row.end();
274 ++odd_iter )
275 {
276 if (odd_iter->first < num_even)
277 {
278 compressed_matrix(i, odd_iter->first) -= iter->second * odd_iter->second / odd_diagonal_entry;
279 }
280 else if (iter->first != odd_iter->first)
281 {
282 log::error() << "WARNING in eliminate_odd_unknowns(): Odd2Odd block matrix has offdiagonal entry at ("
283 << iter->first << "," << odd_iter->first << ")" << std::endl;
284 }
285 }
286
287 //write RHS entry (pay attention to sign flips!)
288 compressed_rhs[i] -= iter->second * rhs[iter->first] / odd_diagonal_entry;
289 }
290 }
291 }
292
293 } //eliminate_odd_unknowns
294
304 template <typename MatrixT, typename VectorT>
305 VectorT recover_odd_unknowns(MatrixT const & full_matrix,
306 VectorT const & full_rhs,
307 VectorT const & compressed_result)
308 {
309 typedef typename MatrixT::row_type RowType;
310 typedef typename MatrixT::const_iterator2 AlongRowIterator;
311
312 VectorT full_result(full_rhs.size());
313 size_t num_even = compressed_result.size();
314
315 for (std::size_t i=0; i<full_matrix.size1(); ++i)
316 {
317 RowType const & row_i = full_matrix.row(i);
318
319 //write even coefficients:
320 if ( i < num_even )
321 full_result[i] = compressed_result[i];
322 else
323 {
324 //compute odd coefficients:
325 double diagonal_entry = 0.0;
326 full_result[i] = full_rhs[i];
327 for ( AlongRowIterator iter = row_i.begin();
328 iter != row_i.end();
329 ++iter )
330 {
331 if ( iter->first < num_even )
332 {
333 full_result[i] -= iter->second * full_result[iter->first];
334 }
335 else if ( i == iter->first )
336 {
337 diagonal_entry = iter->second;
338 }
339 else if( iter->second != 0.0) // check for *exactly* 0.0
340 {
341 log::warn() << "Non-diagonal entry found in odd-to-odd block!" << std::endl;
342 log::info<log_recover_odd_unknowns > () << "col_iter.index1() = " << i << std::endl;
343 log::info<log_recover_odd_unknowns > () << "col_iter.index2() = " << iter->first << std::endl;
344 log::info<log_recover_odd_unknowns > () << "*col_iter = " << iter->second << std::endl;
345 assert(bool("Non-diagonal entry found in odd-to-odd block!"));
346 }
347 }
348 assert(diagonal_entry > 0.0 && bool("FATAL ERROR: Diagonal entry missing when recovering odd coefficients!"));
349 full_result[i] /= diagonal_entry;
350 }
351 }
352
353 return full_result;
354 } //recover_odd_unknowns
355
356
357 } //namespace she
358} //namespace viennashe
359
360#endif
Exception for the case that invalid expansion order is accessed.
Definition: exception.hpp:92
A logging facility providing fine-grained control over logging in ViennaSHE.
logger< true > error()
Used to log errors. The logging level is logERROR.
Definition: log.hpp:301
logger< true > warn()
Used to log warnings. The logging level is logWARNING.
Definition: log.hpp:303
void combine_lines(FullMatrixType &system_matrix, VectorType &rhs, std::size_t line1, std::size_t line_to_add, std::size_t column_to_zero)
Definition: eliminate.hpp:40
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 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
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
Provides the exceptions used inside the viennashe::she namespace.
Defines the log keys used within the viennashe::she namespace.