ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
chain.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_MODELS_MARKOVCHAIN_CHAIN_HPP
2#define VIENNASHE_MODELS_MARKOVCHAIN_CHAIN_HPP
3/* ============================================================================
4 Copyright (c) 2011-2022, Institute for Microelectronics,
5 Institute for Analysis and Scientific Computing,
6 TU Wien.
7
8 -----------------
9 ViennaSHE - The Vienna Spherical Harmonics Expansion Boltzmann Solver
10 -----------------
11
12 http://viennashe.sourceforge.net/
13
14 License: MIT (X11), see file LICENSE in the base directory
15=============================================================================== */
16
17// std
18#include <map>
19
20// viennashe
24#include "viennashe/log/log.hpp"
27
28
33namespace viennashe
34{
35 namespace models
36 {
37
40 {
41 public:
42 typedef std::size_t index_type; // The index type used to uniquely identify states
43
44 state_base(index_type id, std::string const & name ) : id_(id), name_(name), occ_(0) { }
45
46 state_base(state_base const & s) : id_(s.id_), name_(s.name_), occ_(s.occ_) { }
47
48 virtual ~state_base() { }
49
51 index_type id() const { return id_; }
53 std::string name() const { return name_; }
54
56 double occupancy() const { return occ_; }
57
61 void occupancy(double o)
62 {
63 if (o < 0.0)
64 throw viennashe::invalid_value_exception("state_base.occpuancy(doule o): The occupancy must be greater or equal 0!", o);
65 else if (o > 1.0)
66 throw viennashe::invalid_value_exception("state_base.occpuancy(doule o): The occupancy must be less or equal 1!", o);
67
68 occ_ = o;
69 }
70
74 virtual state_base * clone() const { return new state_base(*this); }
75
76 private:
77 index_type id_;
78 std::string name_;
79 double occ_;
80 };
81
82
84 class chain
85 {
86 public:
87 typedef state_base::index_type index_type; // The basic index type to identify states
88
89 private:
90
91 typedef rate_base* rate_ptr_type;
92
93 typedef std::map<index_type, rate_ptr_type > rate_map_type;
94
95 typedef std::map<index_type, rate_map_type > transition_map_type;
96
98 typedef std::map< index_type, state_ptr_type > state_map_type;
99
100 public:
101
103 void add_state(state_base const & st)
104 {
105 if(states_.count(st.id()) <= 0)
106 {
107 chainmap_[st.id()] = rate_map_type();
108 states_[st.id()] = st.clone();
109 }
110 }
111
113 void add_rate(state_base const & from, state_base const & to, rate_base const & r)
114 {
115 this->add_rate(from.id(), to.id(), r);
116 if(states_.count(from.id()) <= 0) states_[from.id()] = from.clone();
117 if(states_.count(to.id()) <= 0) states_[to.id()] = to.clone();
118 }
119
121 rate_base const & rate(state_base const & from, state_base const & to) const
122 {
123 return this->rate(from.id(), to.id());
124 }
125
127 rate_base const & rate(index_type from, index_type to) const
128 {
129 transition_map_type::const_iterator chainmap_it = chainmap_.find(from);
130 if (chainmap_it == chainmap_.end())
131 throw std::runtime_error("Unknown from-state");
132 rate_map_type const & frommap = chainmap_it->second;
133 rate_map_type::const_iterator frommap_it = frommap.find(to);
134 if (frommap_it == frommap.end())
135 throw std::runtime_error("Unknown to-state");
136 return *(frommap_it->second);
137 }
138
140 double get_rate(state_base const & from, state_base const & to) const
141 {
142 return this->get_rate(from.id(), to.id());
143 }
144
146 index_type size1() const { return chainmap_.size(); }
148 index_type size2() const { return chainmap_.size(); }
149
151 double get_rate(index_type from, index_type to) const
152 {
153 transition_map_type::const_iterator chainmap_it = chainmap_.find(from);
154 if (chainmap_it == chainmap_.end())
155 throw std::runtime_error("Unknown from-state");
156 rate_map_type const & frommap = chainmap_it->second;
157 rate_map_type::const_iterator frommap_it = frommap.find(to);
158 if (frommap_it == frommap.end())
159 return 0;
160 return frommap_it->second->value();
161 }
162
164 void print_rate_matrix() const
165 {
166 std::vector<index_type> ids(chainmap_.size());
167 std::size_t i = 0;
168 viennashe::log::info() << std::setw(10) << " " << " | ";
169 for (transition_map_type::const_iterator cit = chainmap_.begin();
170 cit != chainmap_.end(); ++cit)
171 {
172 viennashe::log::info() << "to " << std::setw(5) << cit->first << " | ";
173 ids[i++] = cit->first;
174 }
175 viennashe::log::info() << std::endl;
176
177 for (transition_map_type::const_iterator cit = chainmap_.begin();
178 cit != chainmap_.end(); ++cit)
179 {
180 viennashe::log::info() << "from " << std::setw(5) << cit->first << " | ";
181 for (index_type j = 0; j < ids.size(); ++j)
182 {
183 bool found = false;
184 for (rate_map_type::const_iterator rit = cit->second.begin();
185 rit != cit->second.end(); ++rit)
186 {
187 if (rit->first == j)
188 {
189 viennashe::log::info() << std::setw(8) << rit->second->value() << " | ";
190 found = true;
191 break;
192 }
193 }
194 if (! found)
195 {
196 viennashe::log::info() << std::setw(8) << 0 << " | ";
197 }
198 }
199 viennashe::log::info() << std::endl;
200 }
201 } // print_rate_matrix()
202
207 template < typename MatrixT >
208 void get_rate_matrix(MatrixT & rate_matrix) const
209 {
210 if (rate_matrix.size1() != this->size1())
211 throw viennashe::models::invalid_parameter_exception("chain.get_rate_matrix(): Invalid matrix row size!");
212 if (rate_matrix.size2() != this->size2())
213 throw viennashe::models::invalid_parameter_exception("chain.get_rate_matrix(): Invalid matrix column size!");
214
215 for (transition_map_type::const_iterator cit = chainmap_.begin();
216 cit != chainmap_.end(); ++cit)
217 {
218 for (rate_map_type::const_iterator rit = cit->second.begin();
219 rit != cit->second.end(); ++rit)
220 {
221 rate_matrix(cit->first, rit->first) = rit->second->value();
222 }
223 }
224 } // get_rate_matrix()
225
227 void print_occupancies() const
228 {
229 viennashe::log::info() << std::setw(10) << "States ";
230 for (state_map_type::const_iterator sit = states_.begin();
231 sit != states_.end(); ++sit)
232 {
233 viennashe::log::info() << std::setw(10) << sit->first << " | ";
234 }
235 viennashe::log::info() << std::endl;
236 viennashe::log::info() << "Occupancy ";
237 for (state_map_type::const_iterator sit = states_.begin();
238 sit != states_.end(); ++sit)
239 {
240 viennashe::log::info() << std::setw(10) << sit->second->occupancy() << " | ";
241 }
242 viennashe::log::info() << std::endl;
243
244 }
245
247 bool has_state(index_type idx) const { return (states_.count(idx) > 0 ); }
248
250 {
251 if (states_.count(idx) <= 0)
252 throw std::runtime_error("State not registered!");
253 return *(states_[idx]);
254 }
255 state_base const & get_state(index_type idx) const
256 {
257 state_map_type::const_iterator states_it = states_.find(idx);
258 if (states_it == states_.end())
259 throw std::runtime_error("Unknown state");
260 return *(states_it->second);
261 }
262
264 {
265 // clean up pointers in transition map:
266 for (transition_map_type::const_iterator cit = chainmap_.begin(); cit != chainmap_.end(); ++cit)
267 for (rate_map_type::const_iterator rit = cit->second.begin(); rit != cit->second.end(); ++rit)
268 delete rit->second;
269
270 // clean up pointers in state map:
271 for (state_map_type::const_iterator sit = states_.begin(); sit != states_.end(); ++sit)
272 delete sit->second;
273 }
274
275 protected:
276
277 void add_rate(index_type from, index_type to, rate_base const & r)
278 {
279 if (chainmap_.count(from) > 0)
280 {
281 rate_map_type & frommap = chainmap_[from];
282 frommap[to] = r.clone();
283 }
284 else
285 {
286 rate_map_type frommap;
287 chainmap_[from] = frommap;
288 delete chainmap_[from][to]; //safe to call
289 chainmap_[from][to] = r.clone();
290 }
291 }
292
293 private:
294 transition_map_type chainmap_;
295 state_map_type states_;
296 };
297
304 {
305 typedef viennashe::math::dense_matrix<double> MatrixType;
306 typedef std::vector<double> VectorType;
307
308 typedef MatrixType::size_type size_type;
309
310 size_type num_rows = c.size1();
311
312 MatrixType A(num_rows, num_rows);
313 VectorType b(num_rows);
314 VectorType x(num_rows);
315
316 // Set RHS to zero
317 for (size_type i = 0; i < num_rows; ++i)
318 {
319 b[i] = 0.0;
320 for (size_type j = 0; j < num_rows; ++j)
321 A(i,j) = 0.0;
322 }
323
324 // Fill dense matrix
325 for (size_type i = 0; i < num_rows; ++i)
326 {
327 if (! c.has_state(i))
328 throw viennashe::models::invalid_state_exception("set_chain_to_equilibrium_expectation(): State does not exist!", i);
329
330 for (size_type j = 0; j < num_rows; ++j)
331 {
332 const double kij = c.get_rate(i, j);
333 A(i,i) -= kij;
334 A(j,i) += kij;
335 }
336 }
337 // Reset last row to contain the normalization condition sum_i f_i = 1
338 b[num_rows-1] = 1.0;
339 for (size_type j = 0; j < num_rows; ++j)
340 A(num_rows-1, j) = 1.0;
341
342 // DEBUG
343 /*
344 for (size_type i = 0; i < num_rows; ++i)
345 {
346 for (size_type j = 0; j < num_rows; ++j)
347 {
348 viennashe::log::debug() << std::setw(7) << A(i,j) << " ";
349 }
350 viennashe::log::debug() << std::endl;
351 }
352 */
353
354 // Solve
356 // Check solution
357 double total = 0;
358 for (size_type i = 0; i < num_rows; ++i)
359 {
360 total += x[i];
361 }
362 // FUZZY CHECK
363 if (total - 1e-4 > 1.0 || total + 1e-4 < 0.0)
364 throw viennashe::models::model_evaluation_exception("set_chain_to_equilibrium_expectation(): The sum of all occupancies is not 1.0!");
365 // Set solution
366 for (size_type i = 0; i < num_rows; ++i)
367 {
368 c.get_state(i).occupancy(x[i]);
369 }
370
371 } // set_chain_to_equilibrium_expectation
372
381 inline void solve_for_expectation_occupancies(chain & c, double dt)
382 {
383 if(dt <= 0.0) throw viennashe::invalid_value_exception("solve_for_expectation_occupancies(): dt must be greater zero!", dt);
384
385 typedef viennashe::math::dense_matrix<double> MatrixType;
386 typedef std::vector<double> VectorType;
387
388 typedef MatrixType::size_type size_type;
389
390 const size_type num_rows = c.size1();
391 const double rtime = 1.0/dt;
392
393 MatrixType A(num_rows, num_rows);
394 VectorType b(num_rows);
395 VectorType x(num_rows);
396
397 // Set RHS to f_old/dt
398 for (size_type i = 0; i < num_rows; ++i)
399 {
400 if (! c.has_state(i))
401 throw viennashe::models::invalid_state_exception("solve_for_expectation_occupancies(): State does not exist!", i);
402
403 b[i] = rtime * c.get_state(i).occupancy(); // f_old/dt
404 for (size_type j = 0; j < num_rows; ++j)
405 A(i,j) = 0.0;
406 }
407
408 // Fill dense matrix
409 for (size_type i = 0; i < num_rows; ++i)
410 {
411 if (! c.has_state(i))
412 throw viennashe::models::invalid_state_exception("solve_for_expectation_occupancies(): State does not exist!", i);
413
414 A(i,i) += rtime;
415
416 for (size_type j = 0; j < num_rows; ++j)
417 {
418 const double kij = c.get_rate(i, j);
419 A(i,i) -= kij;
420 A(j,i) += kij;
421 }
422 }
423 // Reset last row to contain the normalization condition sum_i f_i = 1
424 b[num_rows-1] = 1.0;
425 for (size_type j = 0; j < num_rows; ++j)
426 A(num_rows-1, j) = 1.0;
427
428 // DEBUG
429 /*
430 for (size_type i = 0; i < num_rows; ++i)
431 {
432 for (size_type j = 0; j < num_rows; ++j)
433 {
434 viennashe::log::debug() << std::setw(7) << A(i,j) << " ";
435 }
436 viennashe::log::debug() << std::endl;
437 }
438 */
439
440 // Solve
442 // Check solution
443 double total = 0;
444 for (size_type i = 0; i < num_rows; ++i)
445 {
446 total += x[i];
447 }
448 // FUZZY CHECK
449 if (total - 1e-4 > 1.0 || total + 1e-4 < 0.0)
450 throw viennashe::models::model_evaluation_exception("solve_for_expectation_occupancies(): The sum of all occupancies is not 1.0!");
451 // Set solution
452 for (size_type i = 0; i < num_rows; ++i)
453 {
454 c.get_state(i).occupancy(x[i]);
455 }
456
457 } // solve_for_expectation_occupancies()
458
459 } // namespace models
460} // namespace viennashe
461
462
463#endif /* VIENNASHE_MODELS_MARKOVCHAIN_CHAIN_HPP */
464
Exception for the case that an invalid value (depends on the method called) is encountered.
Definition: exception.hpp:76
Implementation of Markov-Chains.
Definition: chain.hpp:85
index_type size2() const
Returns the column size of the rate-matrix.
Definition: chain.hpp:148
void add_rate(state_base const &from, state_base const &to, rate_base const &r)
Adds a rate between to states. Additionally adds the given states if necessary.
Definition: chain.hpp:113
void print_occupancies() const
Prints the occupancies of each state in the chain onto screen (log::info). Usefull for debugging.
Definition: chain.hpp:227
void print_rate_matrix() const
Prints the rate matrix onto screen (log::info). Usefull for debugging.
Definition: chain.hpp:164
state_base & get_state(index_type idx)
Definition: chain.hpp:249
void add_rate(index_type from, index_type to, rate_base const &r)
Definition: chain.hpp:277
double get_rate(index_type from, index_type to) const
Returns the acutal rate (double value!) between to states identified by their resp....
Definition: chain.hpp:151
rate_base const & rate(state_base const &from, state_base const &to) const
Returns a constant reference to a rate between the given states.
Definition: chain.hpp:121
state_base const & get_state(index_type idx) const
Definition: chain.hpp:255
state_base::index_type index_type
Definition: chain.hpp:87
double get_rate(state_base const &from, state_base const &to) const
Returns the actual rate (double value!) between to states.
Definition: chain.hpp:140
void get_rate_matrix(MatrixT &rate_matrix) const
Fills the given rate_matrix.
Definition: chain.hpp:208
bool has_state(index_type idx) const
Returns true if a state identified by its id is in the chain.
Definition: chain.hpp:247
index_type size1() const
Returns the row size of the rate-matrix.
Definition: chain.hpp:146
void add_state(state_base const &st)
Adds a single state to the chain.
Definition: chain.hpp:103
rate_base const & rate(index_type from, index_type to) const
Returns a constant reference to a rate between to states identified by their resp....
Definition: chain.hpp:127
Thrown whenever an invalid parameter to a model is given.
Definition: exception.hpp:32
Thrown whenever a markov chain model finds an invalid or non-existing state.
Definition: exception.hpp:33
Exception for the case that the evaluation of a model fails.
Definition: exception.hpp:89
The basic concept of a state in Markov-Chains.
Definition: chain.hpp:40
std::string name() const
Returns the name of the state for convenience and debugability.
Definition: chain.hpp:53
virtual state_base * clone() const
Basic interface to get a clone (uses new operator!) of the current object for storage....
Definition: chain.hpp:74
state_base(index_type id, std::string const &name)
Definition: chain.hpp:44
index_type id() const
Returns the unique id of the state.
Definition: chain.hpp:51
void occupancy(double o)
Sets the states occupancy.
Definition: chain.hpp:61
double occupancy() const
Returns the occupancy f or p of the state. It has to be a number in [0,1].
Definition: chain.hpp:56
state_base(state_base const &s)
Definition: chain.hpp:46
Provides the exceptions used in the main viennashe namespace.
Implementation of various utilities related to linear algebra.
A logging facility providing fine-grained control over logging in ViennaSHE.
Contains exceptions for markov-models in viennashe::models.
logger< true > info()
Used to log infos. The logging level is logINFO.
Definition: log.hpp:307
void set_chain_to_equilibrium_expectation(chain &c)
Solves the time averaged set of equilibrium (dt->infty) equations for the given Markov-Chain and sets...
Definition: chain.hpp:303
void solve_for_expectation_occupancies(chain &c, double dt)
Solves the time averaged set of equations (including time derivatives) for the occupancies f_i in a g...
Definition: chain.hpp:381
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
Contains the basic reaction rate interface.
Forward declarations for a generic solver layer, providing bindings to a native Gauss solver,...
The basic rate interface.
virtual rate_base * clone() const =0