ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
smooth_doping.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_UTIL_SMOOTH_DOPING_HPP
2#define VIENNASHE_UTIL_SMOOTH_DOPING_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
22#include <set>
23#include <queue>
24#include <vector>
25
26#include "viennagrid/forwards.hpp"
27#include "viennagrid/mesh/mesh.hpp"
28#include "viennagrid/mesh/neighbor_iteration.hpp"
29
30#include "viennashe/device.hpp"
32
33namespace viennashe
34{
35 namespace detail
36 {
41 template <typename DeviceT>
42 void smooth_doping_at_contacts(DeviceT & d)
43 {
44 typedef typename DeviceT::mesh_type MeshType;
45
46 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
47 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
48
49 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
50 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
51
52 typedef typename viennagrid::result_of::const_neighbor_range<MeshType, CellType, FacetType>::type NeighborRange;
53 typedef typename viennagrid::result_of::iterator<NeighborRange>::type NeighborIterator;
54
55 MeshType const & mesh = d.mesh();
56
57 CellContainer cells(mesh);
58
59 //
60 // Step 1: Enumerate contacts (not relying on segments)
61 //
62
63 //
64 // Enumerates the contacts starting from value 1.
65 // The first contact cell encountered is assigned a value of 1, which is propagated to all its neighbors (reachable via other conductor cells).
66 // Second contact cell not part of first contact is assigned 2, followed by propagation to all other cells of the same contact.
67 // Same for other contacts.
68 // Non-contact cells remain at a contact ID 0.
69 //
70 std::vector<std::size_t> contact_id(cells.size());
71 std::set<std::size_t> cells_semiconductor;
72
73 std::size_t current_contact_id = 1;
74
75 for (CellIterator cit = cells.begin();
76 cit != cells.end();
77 ++cit)
78 {
79 if (viennashe::materials::is_conductor(d.get_material(*cit)))
80 {
81 // Only consider further if contact ID not yet assigned
82 if (contact_id[std::size_t(cit->id().get())] == 0)
83 {
84 contact_id[std::size_t(cit->id().get())] = current_contact_id;
85
86 std::queue<std::size_t> cells_queue;
87 std::set<std::size_t> cells_discovered;
88
89 cells_queue.push(std::size_t(cit->id().get()));
90 cells_discovered.insert(std::size_t(cit->id().get()));
91
92 //
93 // Iteration over all conductor cells attached to this cell (breadth-first iteration)
94 //
95 while (!cells_queue.empty())
96 {
97 std::size_t current_cell_id = cells_queue.front();
98 cells_queue.pop();
99
100 CellType const & current_cell = cells[current_cell_id];
101
102 NeighborRange neighbors(mesh, viennagrid::handle(mesh, current_cell));
103 for (NeighborIterator nit = neighbors.begin(); nit != neighbors.end(); ++nit)
104 {
105 std::size_t neighbor_id = std::size_t(nit->id().get());
106
107 // conductor cells are added to the queue to be revisited later
108 if (viennashe::materials::is_conductor(d.get_material(*nit)))
109 {
110 if (cells_discovered.find(neighbor_id) == cells_discovered.end())
111 {
112 cells_discovered.insert(neighbor_id);
113 cells_queue.push(neighbor_id);
114 contact_id[neighbor_id] = current_contact_id;
115 }
116 }
117 else if (viennashe::materials::is_semiconductor(d.get_material(*nit)))
118 {
119 // Remember this cell for later averaging of the doping
120 cells_semiconductor.insert(neighbor_id);
121
122 if (contact_id[neighbor_id] != 0 && contact_id[neighbor_id] != current_contact_id)
123 log::warning() << "Warning: Cell " << neighbor_id << " is attached to at least two different contacts. Doping smoother might give inconsistent results!" << std::endl;
124
125 contact_id[neighbor_id] = current_contact_id;
126 }
127
128 } //for
129 } // while
130
131 // all (multi-hop) conducting neighbors tagged, increase contact_id:
132 ++current_contact_id;
133
134 } // if no contact ID assigned yet
135 } // if conductor
136 } // for cells
137
138
139 //
140 // Step 2: Compute doping averages over semiconductor cells attached to contact cells:
141 //
142 std::vector<double> avg_doping_n_values(current_contact_id-1);
143 std::vector<double> avg_doping_p_values(current_contact_id-1);
144
145 for (typename std::set<std::size_t>::const_iterator it = cells_semiconductor.begin();
146 it != cells_semiconductor.end();
147 ++it)
148 {
149 std::size_t cell_id = *it;
150 CellType const & cell = cells[cell_id];
151
152 std::size_t corrected_contact_id = contact_id[cell_id] - 1;
153 avg_doping_n_values[corrected_contact_id] = std::max(d.get_doping_n(cell), avg_doping_n_values[corrected_contact_id]);
154 avg_doping_p_values[corrected_contact_id] = std::max(d.get_doping_p(cell), avg_doping_p_values[corrected_contact_id]);
155 }
156
157
158 //
159 // Step 3: Set new doping:
160 //
161 for (typename std::set<std::size_t>::const_iterator it = cells_semiconductor.begin();
162 it != cells_semiconductor.end();
163 ++it)
164 {
165 std::size_t cell_id = *it;
166 CellType const & cell = cells[cell_id];
167
168 std::size_t corrected_contact_id = contact_id[cell_id] - 1;
169 d.set_doping_n(avg_doping_n_values[corrected_contact_id], cell);
170 d.set_doping_p(avg_doping_p_values[corrected_contact_id], cell);
171 }
172
173 }
174 }
175
176
177} //namespace viennashe
178
179
180#endif
Contains the definition of a device class independent of the actual macroscopic model to be solved.
A very simple material database. Needs to be replaced by something more versatile soon.
void smooth_doping_at_contacts(DeviceT &d)
Utility function for smoothing the doping next to contacts.
logger< true > warning()
Used to log warnings. The logging level is logWARNING.
Definition: log.hpp:305
bool is_semiconductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a semiconductor.
Definition: all.hpp:156
bool is_conductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a metal.
Definition: all.hpp:147
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40