1#ifndef VIENNASHE_UTIL_SMOOTH_DOPING_HPP
2#define VIENNASHE_UTIL_SMOOTH_DOPING_HPP
26#include "viennagrid/forwards.hpp"
27#include "viennagrid/mesh/mesh.hpp"
28#include "viennagrid/mesh/neighbor_iteration.hpp"
41 template <
typename DeviceT>
44 typedef typename DeviceT::mesh_type MeshType;
46 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
47 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
49 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
50 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
52 typedef typename viennagrid::result_of::const_neighbor_range<MeshType, CellType, FacetType>::type NeighborRange;
53 typedef typename viennagrid::result_of::iterator<NeighborRange>::type NeighborIterator;
55 MeshType
const & mesh = d.mesh();
57 CellContainer cells(mesh);
70 std::vector<std::size_t> contact_id(cells.size());
71 std::set<std::size_t> cells_semiconductor;
73 std::size_t current_contact_id = 1;
75 for (CellIterator cit = cells.begin();
82 if (contact_id[std::size_t(cit->id().get())] == 0)
84 contact_id[std::size_t(cit->id().get())] = current_contact_id;
86 std::queue<std::size_t> cells_queue;
87 std::set<std::size_t> cells_discovered;
89 cells_queue.push(std::size_t(cit->id().get()));
90 cells_discovered.insert(std::size_t(cit->id().get()));
95 while (!cells_queue.empty())
97 std::size_t current_cell_id = cells_queue.front();
100 CellType
const & current_cell = cells[current_cell_id];
102 NeighborRange neighbors(mesh, viennagrid::handle(mesh, current_cell));
103 for (NeighborIterator nit = neighbors.begin(); nit != neighbors.end(); ++nit)
105 std::size_t neighbor_id = std::size_t(nit->id().get());
110 if (cells_discovered.find(neighbor_id) == cells_discovered.end())
112 cells_discovered.insert(neighbor_id);
113 cells_queue.push(neighbor_id);
114 contact_id[neighbor_id] = current_contact_id;
120 cells_semiconductor.insert(neighbor_id);
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;
125 contact_id[neighbor_id] = current_contact_id;
132 ++current_contact_id;
142 std::vector<double> avg_doping_n_values(current_contact_id-1);
143 std::vector<double> avg_doping_p_values(current_contact_id-1);
145 for (
typename std::set<std::size_t>::const_iterator it = cells_semiconductor.begin();
146 it != cells_semiconductor.end();
149 std::size_t cell_id = *it;
150 CellType
const & cell = cells[cell_id];
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]);
161 for (
typename std::set<std::size_t>::const_iterator it = cells_semiconductor.begin();
162 it != cells_semiconductor.end();
165 std::size_t cell_id = *it;
166 CellType
const & cell = cells[cell_id];
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);
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.
bool is_semiconductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a semiconductor.
bool is_conductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a metal.
The main ViennaSHE namespace. All functionality resides inside this namespace.