ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
linalg_util.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_MATH_LINALG_UTIL_HPP
2#define VIENNASHE_MATH_LINALG_UTIL_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
19#include <vector>
20#include <map>
21#include <cmath>
22#include <assert.h>
23#include <bitset>
24#include "viennashe/forwards.h"
25
30namespace viennashe
31{
32 namespace math
33 {
34
35 template<typename VectorType>
36 typename VectorType::value_type
37 norm_2 (VectorType const &v)
38 {
39 typename VectorType::value_type result = 0;
40 for (std::size_t i = 0; i < v.size (); ++i)
41 result += v[i] * v[i];
42 return std::sqrt (result);
43 }
44
49 template<typename VectorType>
50 VectorType
51 subtract (VectorType const &x, VectorType const &y)
52 {
53 assert(
54 x.size () == y.size ()
55 && bool ("Size mismatch for subtracting y from x"));
56
57 VectorType result (x.size ());
58 for (std::size_t i = 0; i < x.size (); ++i)
59 result[i] = x[i] - y[i];
60 return result;
61 }
62
67 template<typename NumericT>
69 {
71
72 public:
73 typedef std::size_t size_type;
75
76 private:
77 typedef std::map<size_type, NumericT> MapType;
78 typedef std::vector<MapType> DataContainerType;
79
80 public:
81 typedef typename MapType::iterator iterator2;
82 typedef typename MapType::const_iterator const_iterator2;
83
84 typedef MapType row_type;
85 typedef MapType RowType;
86
88 zero_ (0)
89 {
90 }
91 sparse_matrix (size_type num_rows, size_type num_cols) :
92 data_ (num_rows), zero_ (0)
93 {
94 assert(
95 num_cols == num_rows && bool ("Only square matrices supported."));
96 (void) num_cols;
97 }
98
100 size1 () const
101 {
102 return data_.size ();
103 }
105 size2 () const
106 {
107 return data_.size ();
108 }
109
111 NumericT&
113 {
114 assert(
115 i < data_.size () && j < data_.size ()
116 && bool ("Access to matrix out of range!"));
117 return data_.at (i)[j];
118 }
119
120 NumericT const&
122 {
123 assert(
124 i < data_.size () && j < data_.size ()
125 && bool ("Access to matrix out of range!"));
126 const_iterator2 it = data_.at (i).find (j);
127 if (it == data_.at (i).end ())
128 return zero_;
129 else
130 return it->second;
131 }
132
133 MapType const&
134 row (size_t i) const
135 {
136 return data_.at (i);
137 }
138 MapType&
139 row (size_t i)
140 {
141 return data_.at (i);
142 }
143
145 nnz () const
146 {
147 size_type result = 0;
148 for (size_type i = 0; i < data_.size (); ++i)
149 result += data_[i].size ();
150 return result;
151 }
152
153 self_type
154 trans () const
155 {
156 self_type A_trans (data_.size (), data_.size ());
157
158 for (size_type i = 0; i < data_.size (); ++i)
159 {
160 for (const_iterator2 it = data_[i].begin ();
161 it != data_[i].end (); ++it)
162 A_trans (it->first, i) = it->second;
163 }
164 return A_trans;
165 }
166
167 self_type
168 operator* (NumericT factor) const
169 {
170 self_type result = *this;
171 for (size_type i = 0; i < data_.size (); ++i)
172 {
173 for (const_iterator2 it = data_[i].begin ();
174 it != data_[i].end (); ++it)
175 result (it->first, i) *= factor;
176 }
177 return result;
178 }
179
180 self_type&
182 {
183 for (size_type i = 0; i < B.size1 (); ++i)
184 {
185 row_type row_i = B.row (i);
186 for (const_iterator2 it = row_i.begin (); it != row_i.end ();
187 ++it)
188 data_[i][it->first] += it->second;
189 }
190 return *this;
191 }
192
193 private:
194 DataContainerType data_;
195 NumericT zero_; //helper member for implementing operator() const
196 };
197
198
200 template<typename NumericT, typename VectorT>
201 VectorT
203 VectorT &rhs)
204 {
205 typedef typename sparse_matrix<NumericT>::row_type RowType;
206 typedef typename sparse_matrix<NumericT>::iterator2 AlongRowIterator;
207
208 /*
209 * Count types of Double types
210 * */
211 //check_types (system_matrix, rhs);
212 VectorT scale_factors (rhs.size (), 1.0);
213
214 // columm-scaling
215 sparse_matrix<NumericT> system_matrixc = system_matrix.trans ();
216 for (std::size_t i = 0; i < system_matrixc.size1 (); ++i)
217 {
218 RowType &col_i = system_matrixc.row (i);
219
220 // log-scale
221 double row_norm = 0.0;
222 // double size = col_i.size();
223 for (AlongRowIterator iter = col_i.begin (); iter != col_i.end ();
224 ++iter)
225 {
226 double temp = std::log (std::fabs (iter->second));
227 row_norm += temp;
228 }
229 row_norm = std::exp (row_norm / col_i.size ());
230 // normalize such that diagonal entry becomes positive:
231 if (system_matrixc (i, i) < 0.0)
232 row_norm *= -1.0;
233
234 // scale col accordingly:
235 for (AlongRowIterator iter = col_i.begin (); iter != col_i.end ();
236 ++iter)
237 {
238 iter->second /= row_norm;
239 }
240 //rhs[i] /= row_norm;
241
242 // remember scaling factor:
243 scale_factors[i] /= row_norm;
244 }
245 system_matrix = system_matrixc.trans ();
246
247 // row-scaling
248 for (std::size_t i = 0; i < system_matrix.size1 (); ++i)
249 {
250 RowType &row_i = system_matrix.row (i);
251
252 // obtain current norm of row:
253 double row_norm = 0.0;
254 for (AlongRowIterator iter = row_i.begin (); iter != row_i.end ();
255 ++iter)
256 {
257 row_norm += iter->second * iter->second;
258 }
259
260 row_norm = sqrt (row_norm);
261
262 // normalize such that diagonal entry becomes positive:
263 if (system_matrix (i, i) < 0.0)
264 row_norm *= -1.0;
265
266 // scale row accordingly:
267 for (AlongRowIterator iter = row_i.begin (); iter != row_i.end ();
268 ++iter)
269 {
270 iter->second /= row_norm;
271 }
272 rhs[i] /= row_norm;
273
274 // remember scaling factor:
275 // scale_factors[i] = 1.0 / row_norm;
276 }
277
278// std::cout << "After Scaling \n";
279// check_types (system_matrix, rhs);
280
281 return scale_factors;
282 }
284 template<typename NumericT>
285 std::ostream&
286 operator<< (std::ostream &os,
287 sparse_matrix<NumericT> const &system_matrix)
288 {
289 typedef typename sparse_matrix<NumericT>::const_iterator2 AlongRowIterator;
290
291 for (std::size_t i = 0; i < system_matrix.size1 (); ++i)
292 {
293 os << std::endl << "Row " << i << ": ";
294 for (AlongRowIterator iter = system_matrix.row (i).begin ();
295 iter != system_matrix.row (i).end (); ++iter)
296 {
297 os << "(" << iter->first << ", " << iter->second << "), ";
298 }
299 }
300
301 return os;
302 }
303 /*
304 * Check types of Numeric to find the value denormal and others
305 * */
306 template<typename NumericT, typename VectorType>
307 void
309 VectorType const &x)
310 {
311 typedef typename sparse_matrix<NumericT>::const_iterator2 Iterator2;
312 typedef typename sparse_matrix<NumericT>::row_type RowType;
313 double minimaldenormal, minimalnormal;
314 int Total, Inf, NaN, subnor, nor, zero;
315 int Total2, Inf2, NaN2, subnor2, nor2, zero2;
316 Total = Inf = NaN = subnor = nor = zero = 0;
317 Total2 = Inf2 = NaN2 = subnor2 = nor2 = zero2 = 0;
318 minimaldenormal = minimalnormal = 1.0;
319 for (std::size_t i = 0; i < system_matrix.size1 (); ++i)
320 {
321 RowType const &row_i = system_matrix.row (i);
322 for (Iterator2 iter2 = row_i.begin (); iter2 != row_i.end ();
323 ++iter2)
324 {
325 switch (std::fpclassify (iter2->second))
326 {
327 case FP_INFINITE:
328 Inf++, Total++;
329 break;
330 case FP_NAN:
331 NaN++, Total++;
332 break;
333 case FP_SUBNORMAL:
334 subnor++, Total++, minimaldenormal =
335 iter2->second > minimaldenormal ?
336 minimaldenormal : iter2->second;
337 break;
338 case FP_NORMAL:
339 nor++, Total++, minimalnormal =
340 iter2->second > minimalnormal ?
341 minimalnormal : iter2->second;
342 break;
343 case FP_ZERO:
344 zero++, Total++;
345 break;
346 }
347 }
348 switch (std::fpclassify (x[i]))
349 {
350 case FP_INFINITE:
351 Inf2++, Total2++;
352 break;
353 case FP_NAN:
354 NaN2++, Total2++;
355 break;
356 case FP_SUBNORMAL:
357 subnor2++, Total2++;
358 break;
359 case FP_NORMAL:
360 nor2++, Total2++;
361 break;
362 case FP_ZERO:
363 zero2++, Total2++;
364 break;
365 }
366 }
367
368 std::cout << "Matrix: Total:" << Total << " Subnormal " << subnor
369 << " normal " << nor << " Zero " << zero << " Inf " << Inf
370 << " Nan " << NaN << std::endl;
371 std::cout << "Vector: Total:" << Total2 << " Subnormal " << subnor2
372 << " normal " << nor2 << " Zero " << zero2 << " Inf " << Inf2
373 << " Nan " << NaN2 << std::endl;
374 printf ("minimaldenormal: %f %A | minimalnormal: %f %A ",
375 minimaldenormal, minimaldenormal, minimalnormal, minimalnormal);
376 //std::cout << "minimaldenormal :" << minimaldenormal <<" " << std::bitset<64>(minimaldenormal) << " minimalnormal :" << minimaldenormal << std::bitset<64>(minimalnormal) << std::endl;
377 }
378
383 template<typename NumericT, typename VectorType>
384 VectorType
385 prod (sparse_matrix<NumericT> const &system_matrix, VectorType const &x)
386 {
387 typedef typename sparse_matrix<NumericT>::const_iterator2 Iterator2;
388 typedef typename sparse_matrix<NumericT>::row_type RowType;
389
390 VectorType result (system_matrix.size1 ());
391 for (std::size_t i = 0; i < system_matrix.size1 (); ++i)
392 {
393 RowType const &row_i = system_matrix.row (i);
394 double val = 0.0;
395 for (Iterator2 iter2 = row_i.begin (); iter2 != row_i.end ();
396 ++iter2)
397 {
398 val += iter2->second * x[iter2->first];
399 }
400 result[i] = val;
401 }
402
403 return result;
404 }
405
407
408 template<typename NumericT>
410 {
412 public:
413 typedef std::size_t size_type;
415
417 data_ (rows * cols + 1), size1_ (rows), size2_ (cols)
418 {
419 assert(
420 rows == cols && bool ("Only square dense matrices supported!"));
421 }
422
424 size1 () const
425 {
426 return size1_;
427 }
429 size2 () const
430 {
431 return size2_;
432 }
433
434 NumericT const&
436 {
437 assert(i < size1_ && j < size2_ && bool ("Index out of bounds!"));
438 return data_.at (i * size2_ + j);
439 }
440
441 NumericT&
443 {
444 assert(i < size1_ && j < size2_ && bool ("Index out of bounds!"));
445 return data_.at (i * size2_ + j);
446 }
447
448 private:
449 std::vector<NumericT> data_;
450 size_type size1_;
451 size_type size2_;
452 };
453
454 } //namespace math
455} //namespace viennashe
456#endif
NumericT const & operator()(size_type i, size_type j) const
dense_matrix(size_type rows, size_type cols)
Sparse matrix class based on a vector of binary trees for holding the entries.
Definition: linalg_util.hpp:69
MapType const & row(size_t i) const
sparse_matrix(size_type num_rows, size_type num_cols)
Definition: linalg_util.hpp:91
self_type & operator+=(self_type B)
NumericT & operator()(size_type i, size_type j)
Non-const access to the entries of the matrix. Use this for assembly.
MapType::const_iterator const_iterator2
Definition: linalg_util.hpp:82
self_type operator*(NumericT factor) const
Contains forward declarations and definition of small classes that must be defined at an early stage.
std::ostream & operator<<(std::ostream &os, sparse_matrix< NumericT > const &system_matrix)
Converts a sparse matrix (ublas, ViennaCL) to a string. Handy debugging facility.
VectorType::value_type norm_2(VectorType const &v)
Definition: linalg_util.hpp:37
void check_types(sparse_matrix< NumericT > const &system_matrix, VectorType const &x)
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...
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40