ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
she_quantity.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_SHE_SHE_QUANTITY_HPP
2#define VIENNASHE_SHE_SHE_QUANTITY_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
23#include <vector>
24#include <string>
25
26#include "viennagrid/mesh/mesh.hpp"
27
28#include "viennashe/forwards.h"
29
30namespace viennashe
31{
32 namespace she
33 {
35 inline long even_unknowns_on_node(long L)
36 {
37 long num = 0;
38 for (long l=0; l<=L; l+=2)
39 num += 2*l + 1;
40
41 return num;
42 }
43
45 inline long odd_unknowns_on_node(long L)
46 {
47 long num = 0;
48 for (long l=1; l<=L; l+=2)
49 num += 2*l + 1;
50
51 return num;
52 }
53
55 template<typename AssociatedT1,
56 typename AssociatedT2,
57 typename ValueT = double>
59 {
60 std::size_t get_id(AssociatedT1 const & elem) const { return static_cast<std::size_t>(elem.id().get()); }
61 std::size_t get_id(AssociatedT2 const & elem) const { return static_cast<std::size_t>(elem.id().get()); }
62
63 public:
64 typedef ValueT value_type;
65
66 unknown_she_quantity() {} // to fulfill default constructible concept!
67
68 unknown_she_quantity(std::string const & quan_name,
70 equation_id quan_equation)
71 : name_(quan_name),
72 ctype_(ctype),
73 equation_(quan_equation),
74 log_damping_(false)
75 {}
76
77 void resize(std::size_t num_values_1, std::size_t num_values_2)
78 {
79 boundary_types1_.resize(num_values_1, BOUNDARY_NONE);
80 boundary_types2_.resize(num_values_2, BOUNDARY_NONE);
81 spatial_mask1_.resize(num_values_1, false);
82 spatial_mask2_.resize(num_values_2, false);
83 expansion_order_adaption_.resize(num_values_1);
84 bandedge_shift1_.resize(num_values_1);
85 bandedge_shift2_.resize(num_values_2);
86 }
87
88 void resize(std::size_t num_values_1, std::size_t num_values_2, std::size_t size_index_H)
89 {
90 resize(num_values_1, num_values_2);
91 values1_.resize(num_values_1 * size_index_H);
92 values2_.resize(num_values_2 * size_index_H);
93 boundary_values1_.resize(num_values_1 * size_index_H);
94 boundary_values2_.resize(num_values_2 * size_index_H);
95 defined_but_unknown_mask1_.resize(num_values_1 * size_index_H, false);
96 defined_but_unknown_mask2_.resize(num_values_2 * size_index_H, false);
97 unknowns_indices1_.resize(num_values_1 * size_index_H, -1);
98 unknowns_indices2_.resize(num_values_2 * size_index_H, -1);
99 expansion_order1_.resize(num_values_1 * size_index_H);
100 expansion_order2_.resize(num_values_2 * size_index_H);
101 values_H_.resize(size_index_H);
102 }
103
104 std::string get_name() const { return name_; }
105
106 equation_id get_equation() const { return equation_; }
107
108 ValueT const * get_values(AssociatedT1 const & elem, std::size_t index_H) const { return &(values1_.at(array_index(get_id(elem), index_H)).at(0)); }
109 ValueT const * get_values(AssociatedT2 const & elem, std::size_t index_H) const { return &(values2_.at(array_index(get_id(elem), index_H)).at(0)); }
110
111 void set_values(AssociatedT1 const & elem, std::size_t index_H, ValueT const * values)
112 {
113 for (std::size_t i=0; i < this->get_unknown_num(elem, index_H); ++i)
114 values1_.at(array_index(get_id(elem), index_H)).at(i) = values[i];
115 }
116 void set_values(AssociatedT2 const & elem, std::size_t index_H, ValueT const * values)
117 {
118 for (std::size_t i=0; i < this->get_unknown_num(elem, index_H); ++i)
119 values2_.at(array_index(get_id(elem), index_H)).at(i) = values[i];
120 }
121
122 // Dirichlet and Neumann
123 ValueT get_boundary_value(AssociatedT1 const & elem, std::size_t index_H) const { return boundary_values1_.at(array_index(get_id(elem), index_H)); }
124 ValueT get_boundary_value(AssociatedT2 const & elem, std::size_t index_H) const { return boundary_values2_.at(array_index(get_id(elem), index_H)); }
125
126 void set_boundary_value(AssociatedT1 const & elem, std::size_t index_H, ValueT value) { boundary_values1_.at(array_index(get_id(elem), index_H)) = value; }
127 void set_boundary_value(AssociatedT2 const & elem, std::size_t index_H, ValueT value) { boundary_values2_.at(array_index(get_id(elem), index_H)) = value; }
128
129 boundary_type_id get_boundary_type(AssociatedT1 const & elem) const { return boundary_types1_.at(get_id(elem)); }
130 boundary_type_id get_boundary_type(AssociatedT2 const & elem) const { return boundary_types2_.at(get_id(elem)); }
131
132 void set_boundary_type(AssociatedT1 const & elem, boundary_type_id value) { boundary_types1_.at(get_id(elem)) = value; }
133 void set_boundary_type(AssociatedT2 const & elem, boundary_type_id value) { boundary_types2_.at(get_id(elem)) = value; }
134
135 // Unknown handling
136 bool get_unknown_mask(AssociatedT1 const & elem, std::size_t index_H) const { return defined_but_unknown_mask1_.at(array_index(get_id(elem), index_H)); }
137 bool get_unknown_mask(AssociatedT2 const & elem, std::size_t index_H) const { return defined_but_unknown_mask2_.at(array_index(get_id(elem), index_H)); }
138
139 void set_unknown_mask(AssociatedT1 const & elem, std::size_t index_H, bool value) { defined_but_unknown_mask1_.at(array_index(get_id(elem), index_H)) = value; }
140 void set_unknown_mask(AssociatedT2 const & elem, std::size_t index_H, bool value) { defined_but_unknown_mask2_.at(array_index(get_id(elem), index_H)) = value; }
141
142 bool get_unknown_mask(AssociatedT1 const & elem) const { return spatial_mask1_.at(get_id(elem)); }
143 bool get_unknown_mask(AssociatedT2 const & elem) const { return spatial_mask2_.at(get_id(elem)); }
144
145 void set_unknown_mask(AssociatedT1 const & elem, bool value) { spatial_mask1_.at(get_id(elem)) = value; }
146 void set_unknown_mask(AssociatedT2 const & elem, bool value) { spatial_mask2_.at(get_id(elem)) = value; }
147
148 long get_unknown_index(AssociatedT1 const & elem, std::size_t index_H) const { return unknowns_indices1_.at(array_index(get_id(elem), index_H)); }
149 long get_unknown_index(AssociatedT2 const & elem, std::size_t index_H) const { return unknowns_indices2_.at(array_index(get_id(elem), index_H)); }
150
151 void set_unknown_index(AssociatedT1 const & elem, std::size_t index_H, long value) { unknowns_indices1_.at(array_index(get_id(elem), index_H)) = value; }
152 void set_unknown_index(AssociatedT2 const & elem, std::size_t index_H, long value) { unknowns_indices2_.at(array_index(get_id(elem), index_H)) = value; }
153
154 std::size_t get_expansion_order(AssociatedT1 const & elem, std::size_t index_H) const { return expansion_order1_.at(array_index(get_id(elem), index_H)); }
155 std::size_t get_expansion_order(AssociatedT2 const & elem, std::size_t index_H) const { return expansion_order2_.at(array_index(get_id(elem), index_H)); }
156
157 void set_expansion_order(AssociatedT1 const & elem, std::size_t index_H, std::size_t value)
158 {
159 expansion_order1_.at(array_index(get_id(elem), index_H)) = value;
160 if (value > 0)
161 values1_.at(array_index(get_id(elem), index_H)).resize(static_cast<std::size_t>(even_unknowns_on_node(static_cast<long>(this->get_expansion_order(elem, index_H)))));
162 else
163 values1_.at(array_index(get_id(elem), index_H)) = std::vector<ValueT>();
164 }
165 void set_expansion_order(AssociatedT2 const & elem, std::size_t index_H, std::size_t value)
166 {
167 expansion_order2_.at(array_index(get_id(elem), index_H)) = value;
168 if (value > 0)
169 values2_.at(array_index(get_id(elem), index_H)).resize(static_cast<std::size_t>(odd_unknowns_on_node(static_cast<long>(this->get_expansion_order(elem, index_H)))));
170 else
171 values2_.at(array_index(get_id(elem), index_H)) = std::vector<ValueT>();
172 }
173
174 std::size_t get_unknown_num(AssociatedT1 const & elem, std::size_t index_H) const
175 {
176 if ( this->get_unknown_index(elem, index_H) >= 0 )
177 return static_cast<std::size_t>(even_unknowns_on_node(static_cast<long>(get_expansion_order(elem, index_H))));
178 else
179 return 0;
180 }
181 std::size_t get_unknown_num(AssociatedT2 const & elem, std::size_t index_H) const
182 {
183 if ( this->get_unknown_index(elem, index_H) >= 0 )
184 return static_cast<std::size_t>(odd_unknowns_on_node(static_cast<long>(get_expansion_order(elem, index_H))));
185 else
186 return 0;
187 }
188
189 bool get_expansion_adaption(AssociatedT1 const & elem) const { return expansion_order_adaption_.at(get_id(elem)); }
190 void set_expansion_adaption(AssociatedT1 const & elem, bool b) { expansion_order_adaption_.at(get_id(elem)) = b; }
191
192
193
194 // total energy
195 ValueT get_value_H(std::size_t index_H) const { return values_H_.at(index_H); }
196 void set_value_H(std::size_t index_H, ValueT value) { values_H_.at(index_H) = value; }
197
198 std::size_t get_value_H_size() const { return values_H_.size(); }
199
200 // band gap center
201 ValueT get_bandedge_shift(AssociatedT1 const & elem) const { return bandedge_shift1_.at(get_id(elem)); }
202 ValueT get_bandedge_shift(AssociatedT2 const & elem) const { return bandedge_shift2_.at(get_id(elem)); }
203
204 void set_bandedge_shift(AssociatedT1 const & elem, ValueT value) { bandedge_shift1_.at(get_id(elem)) = value; }
205 void set_bandedge_shift(AssociatedT2 const & elem, ValueT value) { bandedge_shift2_.at(get_id(elem)) = value; }
206
207 ValueT get_kinetic_energy(AssociatedT1 const & elem, std::size_t index_H) const
208 {
209 return (ctype_ == ELECTRON_TYPE_ID) ? get_value_H(index_H) - bandedge_shift1_.at(get_id(elem))
210 : bandedge_shift1_.at(get_id(elem)) - get_value_H(index_H);
211 }
212 ValueT get_kinetic_energy(AssociatedT2 const & elem, std::size_t index_H) const
213 {
214 return (ctype_ == ELECTRON_TYPE_ID) ? get_value_H(index_H) - bandedge_shift2_.at(get_id(elem))
215 : bandedge_shift2_.at(get_id(elem)) - get_value_H(index_H);
216 }
217
218 carrier_type_id get_carrier_type_id() const { return ctype_; }
219
220 /*
221 std::size_t get_unknown_num() const
222 {
223 std::size_t num = 0;
224 for (std::size_t i=0; i<unknowns_indices_.size(); ++i)
225 {
226 if (unknowns_indices_[i] >= 0)
227 ++num;
228 }
229 return num;
230 }*/
231
232 // possible design flaws:
233 bool get_logarithmic_damping() const { return log_damping_; }
234 void set_logarithmic_damping(bool b) { log_damping_ = b; }
235
236 private:
237 std::size_t array_index(std::size_t element_id, std::size_t index_H) const { return element_id * values_H_.size() + index_H; }
238
239 std::string name_;
240 carrier_type_id ctype_;
241 equation_id equation_;
242
243 std::vector< std::vector<ValueT> > values1_;
244 std::vector< std::vector<ValueT> > values2_;
245 std::vector<std::size_t> values1_offsets_;
246 std::vector<std::size_t> values2_offsets_;
247 std::vector<boundary_type_id> boundary_types1_;
248 std::vector<boundary_type_id> boundary_types2_;
249 std::vector<ValueT> boundary_values1_;
250 std::vector<ValueT> boundary_values2_;
251 std::vector<bool> defined_but_unknown_mask1_;
252 std::vector<bool> defined_but_unknown_mask2_;
253 std::vector<bool> spatial_mask1_;
254 std::vector<bool> spatial_mask2_;
255 std::vector<long> unknowns_indices1_;
256 std::vector<long> unknowns_indices2_;
257 std::vector<std::size_t> expansion_order1_;
258 std::vector<std::size_t> expansion_order2_;
259 std::vector< bool > expansion_order_adaption_;
260
261 energy_vector_type values_H_;
262 std::vector<ValueT> bandedge_shift1_;
263 std::vector<ValueT> bandedge_shift2_;
264
265 bool log_damping_;
266 };
267
268
270 template<typename AssociatedT1, typename AssociatedT2,
271 typename ValueT = double>
273 {
274 std::size_t get_id(AssociatedT1 const & elem) const { return static_cast<std::size_t>(elem.id().get()); }
275 std::size_t get_id(AssociatedT2 const & elem) const { return static_cast<std::size_t>(elem.id().get()); }
276
277 public:
278 typedef ValueT value_type;
279
281 : name_(quan.get_name()),
282 values1_(quan.values1()),
283 values2_(quan.values2()),
284 expansion_order1_(quan.expansion_orders1()),
285 expansion_order2_(quan.expansion_orders2())
286 {}
287
288 ValueT const * get_values(AssociatedT1 const & elem, std::size_t index_H) const { return &(values1_.at(get_id(elem)).at(index_H)); }
289 ValueT const * get_values(AssociatedT2 const & elem, std::size_t index_H) const { return &(values2_.at(get_id(elem)).at(index_H)); }
290
291 short get_expansion_order(AssociatedT1 const & elem, std::size_t index_H) const { return expansion_order1_.at(get_id(elem)).at(index_H); }
292 short get_expansion_order(AssociatedT2 const & elem, std::size_t index_H) const { return expansion_order2_.at(get_id(elem)).at(index_H); }
293
294 short get_unknown_num(AssociatedT1 const & elem, std::size_t index_H) const { return even_unknowns_on_node(get_expansion_order(elem, index_H)); }
295 short get_unknown_num(AssociatedT2 const & elem, std::size_t index_H) const { return odd_unknowns_on_node(get_expansion_order(elem, index_H)); }
296
297 ValueT operator()(AssociatedT1 const & elem, std::size_t index_H) const { return values1_.at(get_id(elem)).at(index_H); }
298 ValueT operator()(AssociatedT2 const & elem, std::size_t index_H) const { return values2_.at(get_id(elem)).at(index_H); }
299
300 std::string name() const { return name_; }
301
302 private:
303 std::string name_;
304 std::vector<std::vector<ValueT> > values1_;
305 std::vector<std::vector<ValueT> > values2_;
306 std::vector<std::vector<short> > expansion_order1_;
307 std::vector<std::vector<short> > expansion_order2_;
308 };
309
310 } //namespace she
311} //namespace viennashe
312
313#endif
Common representation of any quantity associated with two objects of a certain type and an index.
short get_expansion_order(AssociatedT2 const &elem, std::size_t index_H) const
ValueT operator()(AssociatedT1 const &elem, std::size_t index_H) const
ValueT const * get_values(AssociatedT2 const &elem, std::size_t index_H) const
short get_expansion_order(AssociatedT1 const &elem, std::size_t index_H) const
ValueT operator()(AssociatedT2 const &elem, std::size_t index_H) const
short get_unknown_num(AssociatedT1 const &elem, std::size_t index_H) const
short get_unknown_num(AssociatedT2 const &elem, std::size_t index_H) const
ValueT const * get_values(AssociatedT1 const &elem, std::size_t index_H) const
const_she_quantity(unknown_she_quantity< AssociatedT1, AssociatedT2 > const &quan)
General representation of any solver quantity defined on two different element types (e....
std::size_t get_unknown_num(AssociatedT1 const &elem, std::size_t index_H) const
void set_unknown_mask(AssociatedT1 const &elem, bool value)
bool get_expansion_adaption(AssociatedT1 const &elem) const
void set_bandedge_shift(AssociatedT1 const &elem, ValueT value)
void set_boundary_value(AssociatedT2 const &elem, std::size_t index_H, ValueT value)
long get_unknown_index(AssociatedT1 const &elem, std::size_t index_H) const
ValueT get_bandedge_shift(AssociatedT1 const &elem) const
ValueT get_boundary_value(AssociatedT2 const &elem, std::size_t index_H) const
void resize(std::size_t num_values_1, std::size_t num_values_2, std::size_t size_index_H)
void set_expansion_order(AssociatedT2 const &elem, std::size_t index_H, std::size_t value)
carrier_type_id get_carrier_type_id() const
void set_unknown_mask(AssociatedT2 const &elem, std::size_t index_H, bool value)
void set_bandedge_shift(AssociatedT2 const &elem, ValueT value)
void set_values(AssociatedT2 const &elem, std::size_t index_H, ValueT const *values)
unknown_she_quantity(std::string const &quan_name, viennashe::carrier_type_id ctype, equation_id quan_equation)
bool get_unknown_mask(AssociatedT2 const &elem, std::size_t index_H) const
std::size_t get_expansion_order(AssociatedT1 const &elem, std::size_t index_H) const
void set_unknown_mask(AssociatedT2 const &elem, bool value)
ValueT const * get_values(AssociatedT2 const &elem, std::size_t index_H) const
bool get_unknown_mask(AssociatedT1 const &elem) const
ValueT get_kinetic_energy(AssociatedT2 const &elem, std::size_t index_H) const
void resize(std::size_t num_values_1, std::size_t num_values_2)
bool get_unknown_mask(AssociatedT2 const &elem) const
void set_expansion_order(AssociatedT1 const &elem, std::size_t index_H, std::size_t value)
ValueT get_value_H(std::size_t index_H) const
void set_value_H(std::size_t index_H, ValueT value)
ValueT get_bandedge_shift(AssociatedT2 const &elem) const
ValueT get_kinetic_energy(AssociatedT1 const &elem, std::size_t index_H) const
bool get_unknown_mask(AssociatedT1 const &elem, std::size_t index_H) const
void set_unknown_index(AssociatedT1 const &elem, std::size_t index_H, long value)
void set_unknown_index(AssociatedT2 const &elem, std::size_t index_H, long value)
ValueT get_boundary_value(AssociatedT1 const &elem, std::size_t index_H) const
ValueT const * get_values(AssociatedT1 const &elem, std::size_t index_H) const
std::size_t get_unknown_num(AssociatedT2 const &elem, std::size_t index_H) const
void set_boundary_value(AssociatedT1 const &elem, std::size_t index_H, ValueT value)
void set_boundary_type(AssociatedT2 const &elem, boundary_type_id value)
long get_unknown_index(AssociatedT2 const &elem, std::size_t index_H) const
void set_unknown_mask(AssociatedT1 const &elem, std::size_t index_H, bool value)
void set_values(AssociatedT1 const &elem, std::size_t index_H, ValueT const *values)
boundary_type_id get_boundary_type(AssociatedT2 const &elem) const
std::size_t get_expansion_order(AssociatedT2 const &elem, std::size_t index_H) const
void set_boundary_type(AssociatedT1 const &elem, boundary_type_id value)
boundary_type_id get_boundary_type(AssociatedT1 const &elem) const
void set_expansion_adaption(AssociatedT1 const &elem, bool b)
Contains forward declarations and definition of small classes that must be defined at an early stage.
long odd_unknowns_on_node(long L)
Returns the number of odd spherical harmonics up to (including) order L.
long even_unknowns_on_node(long L)
Returns the number of even spherical harmonics up to (including) order L.
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
carrier_type_id
Enumeration type for selecting the carrier type.
Definition: forwards.h:185
@ ELECTRON_TYPE_ID
Definition: forwards.h:187
equation_id
An enumeration of all equation types ViennaSHE supports.
Definition: forwards.h:114
boundary_type_id
An enumeration of all boundary conditions ViennaSHE supports.
Definition: forwards.h:125
@ BOUNDARY_NONE
Definition: forwards.h:126
std::vector< double > energy_vector_type
Type for storing the discrete energies.
Definition: forwards.h:178