ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
checks.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_UTIL_CHECKS_HPP
2#define VIENNASHE_UTIL_CHECKS_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 <limits>
21#include <vector>
22#include <cmath>
23
24// viennashe
27
28#include "viennashe/log/log.hpp"
30
31
36namespace viennashe
37{
38 namespace util
39 {
40
41
42 //
43 // Checker primitives (returns false if check fails)
44 //
45
48 {
49 template <typename T>
50 bool operator()(T const &) const { return true; }
51 };
52
53
55 template <typename ValueType = double>
57 {
58 public:
59 range_checker(ValueType const & a, ValueType const & b) : lower_bound_(a), upper_bound_(b)
60 {
61 if (! (a < b) )
62 {
63 std::stringstream ss;
64 ss << "Invalid range [" << a << ", " << b << ")";
65 throw invalid_range_bounds_exception(ss.str());
66 }
67 }
68
69 bool operator()(ValueType const & v) const
70 {
71 return (v >= lower_bound_) && (v < upper_bound_);
72 }
73
74 private:
75 ValueType lower_bound_;
76 ValueType upper_bound_;
77 };
78
79
82 {
83 template <typename T>
84 bool operator()(T const & t) const { return t != t; }
85 };
86
89 {
90 template <typename T>
91 bool operator()(T const & t) const { return t - t != 0; }
92 };
93
94
96 template < typename ValueType >
97 bool is_NaN(const ValueType & val) { return (val != val); }
98
100 template < typename ValueType >
101 bool is_Inf(const ValueType & val) { return std::fabs(val - val) > 0; }
102
104 template < typename ValueType >
105 bool is_negative(const ValueType & val) { return (val < 0); }
106
107
108
110 template <typename VectorType>
111 void check_vector_for_valid_entries(VectorType const & vec, std::string message = "Location not specified")
112 {
113 for (std::size_t i=0; i<vec.size(); ++i)
114 {
115 if ( viennashe::util::is_NaN(vec[i]) )
116 {
117 std::stringstream ss;
118 ss << message << ": Found NaN in vector at index " << i << std::endl;
119 throw invalid_value_exception(ss.str());
120 }
121
122 if ( viennashe::util::is_Inf(vec[i]) )
123 {
124 std::stringstream ss;
125 ss << message << ": Found infinity in vector at index " << i << std::endl;
126 throw invalid_value_exception(ss.str());
127 }
128 }
129 }
130
131
132 //
133 // Checkers with exceptions
134 //
135
137 template <typename BasicChecker, typename ExceptionType>
139 {
140 public:
141 checker_with_exception(BasicChecker const & c,
142 ExceptionType const & e) : checker_(c), exception_(e) {}
143
144 template <typename T>
145 bool operator()(T const & t) const
146 {
147 if (!checker_(t))
148 throw exception_;
149
150 return true;
151 }
152
153 private:
154 BasicChecker const & checker_;
155 ExceptionType const & exception_;
156 };
157
158
160 template <typename CheckerType, typename ExceptionType>
161 checker_with_exception<CheckerType, ExceptionType> make_checker_with_exception(CheckerType const & checker, ExceptionType const & ex)
162 {
164 }
165
173 template <typename MatrixType>
174 void m_matrix_check(MatrixType const & A)
175 {
176 bool is_m_matrix = true;
177
178 for (std::size_t row_index = 0;
179 row_index != A.size1();
180 ++row_index)
181 {
182 typedef typename MatrixType::const_iterator2 AlongRowIterator;
183 typedef typename MatrixType::row_type RowType;
184
185 RowType const & row_i = A.row(row_index);
186
187 double abs_offdiagonal = 0.0;
188 double abs_diagonal = 0.0;
189
190 for (AlongRowIterator col_it = row_i.begin();
191 col_it != row_i.end();
192 ++col_it)
193 {
194 std::size_t col_index = col_it->first;
195 double entry = col_it->second;
196
197 //col_buffer.set(data_index, col_it->first);
198 //elements[data_index] = col_it->second;
199 //++data_index;
200
201 if (row_index != col_index)
202 {
203 if (entry > 0.0)
204 {
205 is_m_matrix = false;
206 log::warn() << "* WARNING in m_matrix_check(): Entry (" << row_index << "," << col_index << ") is positive: " << entry << std::endl;
207 }
208 else
209 abs_offdiagonal += std::fabs(col_it->second);
210 }
211 else
212 {
213 if (entry <= 0.0)
214 {
215 is_m_matrix = false;
216 log::warn() << "* WARNING in m_matrix_check(): Entry (" << row_index << "," << col_index << ") is non-positive: " << entry << std::endl;
217 }
218
219 abs_diagonal = entry;
220 }
221 }
222
223 if (abs_offdiagonal > abs_diagonal * 1.0001) //allow some numerical noise
224 {
225 is_m_matrix = false;
226 log::warn() << "* WARNING in m_matrix_check(): Row " << row_index << " imbalanced! "
227 << "fabs(offdiagonals): " << abs_offdiagonal << ", diagonal: " << abs_diagonal << std::endl;
228 }
229 }
230
231 if (is_m_matrix)
232 log::info<log_m_matrix_check>() << "* m_matrix_check(): Matrix is M-matrix!" << std::endl;
233
234 }
235
236
237
238
239
245 template <typename MatrixType>
246 long matrix_consistency_check(MatrixType const & matrix)
247 {
248 typedef typename MatrixType::const_iterator1 RowIterator;
249 typedef typename MatrixType::const_iterator2 ColumnIterator;
250
251 //long last_failed_index = -1; // [MB] unused variable
252
253 for (RowIterator row_iter = matrix.begin1();
254 row_iter != matrix.end1();
255 ++row_iter)
256 {
257 bool has_row = false;
258 for (ColumnIterator col_iter = row_iter.begin();
259 col_iter != row_iter.end();
260 ++col_iter)
261 {
262 if (*col_iter != 0)
263 has_row = true;
264 }
265
266 if (has_row == false)
267 {
268 log::error() << "* FATAL ERROR in check_matrix_consistency(): System matrix has empty row " << row_iter.index1() << "!" << std::endl;
269 //last_failed_index = row_iter.index1(); // [MB] row_iter.index1() has no side effects, right?
270 }
271 }
272
273 return -1;
274 }
275
276
282 template <typename NumericT>
284 {
285 typedef typename viennashe::math::sparse_matrix<NumericT>::const_iterator2 AlongRowIterator;
286
287 for (std::size_t i = 0; i < matrix.size1(); ++i)
288 {
289 bool has_row = false;
290 for (AlongRowIterator col_iter = matrix.row(i).begin();
291 col_iter != matrix.row(i).end();
292 ++col_iter)
293 {
294 if (col_iter->second)
295 {
296 has_row = true;
297 break;
298 }
299 }
300
301 if (has_row == false)
302 {
303 log::error() << "* FATAL ERROR in check_matrix_consistency(): System matrix has empty row " << i << "!" << std::endl;
304 //last_failed_index = row_iter.index1(); // [MB] row_iter.index1() has no side effects, right?
305 }
306 }
307
308 return -1;
309 }
310
311
314 template <typename MatrixType>
315 void check_vanishing_column_sums(MatrixType const & matrix, std::size_t num_cols)
316 {
317 typedef typename MatrixType::const_iterator1 RowIterator;
318 typedef typename MatrixType::const_iterator2 ColumnIterator;
319 typedef typename MatrixType::value_type ScalarType;
320
321 std::size_t size = std::min<std::size_t>(matrix.size2(), num_cols);
322 std::vector<ScalarType> col_sums(size);
323 std::vector<ScalarType> col_maximums(size);
324
325 //
326 // Step 1: Sum into column-sum array and remember maximium in each column
327 //
328 for (RowIterator row_iter = matrix.begin1();
329 row_iter != matrix.end1();
330 ++row_iter)
331 {
332 if (row_iter.index1() >= size)
333 break;
334
335 for (ColumnIterator col_iter = row_iter.begin();
336 col_iter != row_iter.end();
337 ++col_iter)
338 {
339 col_sums[col_iter.index2()] += *col_iter;
340 if (std::abs(*col_iter) > col_maximums[col_iter.index2()])
341 col_maximums[col_iter.index2()] = std::abs(*col_iter);
342 }
343
344 }
345
346 //
347 // Step 2: Perform the tests
348 //
349 for (std::size_t i=0; i<col_sums.size(); ++i)
350 {
351 if (col_maximums[i] == 0) //Note: If there is no inelastic scattering, column maximums are supposed to be zero!
352 {
353 }
354 else if (std::abs(col_sums[i]) / col_maximums[i] > 1e-10)
355 {
356 log::error() << "* CHECK FAILED in check_vanishing_column_sums(): Column " << i << " does not vanish: " << col_sums[i] << " with maximum " << col_maximums[i] << std::endl;
357 // TODO: Think about throwing an exception here? Maybe in debug mode only?
358 }
359 }
360 }
361
362
363 } //namespace util
364} //namespace viennashe
365
366#endif
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
MapType::const_iterator const_iterator2
Definition: linalg_util.hpp:82
A checker class that throws a user-provided exception rather than returning false on its functor inte...
Definition: checks.hpp:139
checker_with_exception(BasicChecker const &c, ExceptionType const &e)
Definition: checks.hpp:141
bool operator()(T const &t) const
Definition: checks.hpp:145
Exception thrown if for a range(a,b) the check a < b fails.
Definition: exception.hpp:46
Exception which is thrown if an invalid value is found.
Definition: exception.hpp:52
Checker for values inside a half-open interval [a, b), where 'a' is included, while 'b' is not.
Definition: checks.hpp:57
range_checker(ValueType const &a, ValueType const &b)
Definition: checks.hpp:59
bool operator()(ValueType const &v) const
Definition: checks.hpp:69
Implementation of various utilities related to linear algebra.
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
checker_with_exception< CheckerType, ExceptionType > make_checker_with_exception(CheckerType const &checker, ExceptionType const &ex)
Convenience creator routine for creating a checker with exception from checker returning a bool only.
Definition: checks.hpp:161
void check_vanishing_column_sums(MatrixType const &matrix, std::size_t num_cols)
Checks that the first 'num_cols' column sums of the provided matrix vanish (up to round-off) or a col...
Definition: checks.hpp:315
bool is_Inf(const ValueType &val)
Checks if a value of type ValueType is Inf using (value - value) != 0.
Definition: checks.hpp:101
bool is_negative(const ValueType &val)
Checks if a value of type ValueType is negative using value < 0.
Definition: checks.hpp:105
long matrix_consistency_check(MatrixType const &matrix)
Checks a matrix for empty rows.
Definition: checks.hpp:246
void check_vector_for_valid_entries(VectorType const &vec, std::string message="Location not specified")
Checks a vector for valid entries (i.e. no NaN).
Definition: checks.hpp:111
bool is_NaN(const ValueType &val)
Checks if a value of type ValueType is NaN using value != value.
Definition: checks.hpp:97
void m_matrix_check(MatrixType const &A)
Checks a matrix for being an M matrix.
Definition: checks.hpp:174
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
A checker that never complains. Can be used instead of overly picky/erroneous checkers (just for debu...
Definition: checks.hpp:48
bool operator()(T const &) const
Definition: checks.hpp:50
bool operator()(T const &t) const
Definition: checks.hpp:91
bool operator()(T const &t) const
Definition: checks.hpp:84
Defines all exceptions used/thrown in the viennashe/util/ namespace.
Defines the log keys used within the viennashe::util namespace.