ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
current_density.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_DD_POSTPROC_CURRENT_HPP
2#define VIENNASHE_DD_POSTPROC_CURRENT_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
19// std
20#include <iostream>
21#include <fstream>
22#include <vector>
23
24// viennagrid
25#include "viennagrid/mesh/mesh.hpp"
26#include "viennagrid/algorithm/volume.hpp"
27#include "viennagrid/algorithm/interface.hpp"
28
29// viennashe
30#include "viennashe/forwards.h"
32
38
39#include "viennashe/log/log.hpp"
40
43
45
50namespace viennashe
51{
52
53 namespace detail
54 {
56 template <typename DeviceType,
57 typename PotentialAccessorType,
58 typename AccessorTypeCarrier,
59 typename MobilityModel>
61 {
62 typedef typename DeviceType::mesh_type MeshType;
63
64 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
65 typedef typename viennagrid::result_of::vertex<MeshType>::type VertexType;
66 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
67 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
68
69 typedef double value_type;
70
71 current_density_on_facet(DeviceType const & device,
73 PotentialAccessorType const & potential,
74 AccessorTypeCarrier const & carrier,
75 MobilityModel const & mobility_model)
76 : device_(device), carrier_type_id_(ctype), potential_(potential), carrier_(carrier), mobility_(mobility_model) { }
77
78 value_type operator()(FacetType const & facet) const
79 {
80 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
81 typedef typename viennagrid::result_of::iterator<CellOnFacetContainer>::type CellOnFacetIterator;
82
83 typename viennashe::contact_carrier_density_accessor<DeviceType> bnd_carrier_density(device_, carrier_type_id_);
84
85 scharfetter_gummel flux_approximator(carrier_type_id_);
86
87 CellOnFacetContainer cells_on_facet(device_.mesh(), viennagrid::handle(device_.mesh(), facet));
88
89 if (cells_on_facet.size() < 2)
90 return 0;
91
92 CellOnFacetIterator cofit = cells_on_facet.begin();
93 CellType const & c1 = *cofit;
94 ++cofit;
95 CellType const & c2 = *cofit;
96
97 if (viennashe::materials::is_insulator(device_.get_material(c1)) || viennashe::materials::is_insulator(device_.get_material(c2))) // no current into insulator
98 return 0;
99
100 // at least one of the two cells must be a semiconductor:
101 if (!viennashe::materials::is_semiconductor(device_.get_material(c1)) && !viennashe::materials::is_semiconductor(device_.get_material(c2)))
102 return 0;
103
104 const double potential_center = potential_(c1);
105 const double carrier_center = viennashe::materials::is_conductor(device_.get_material(c1))
106 ? bnd_carrier_density(c2, device_.get_lattice_temperature(c2))
107 : carrier_.get_value(c1);
108 const double T = device_.get_lattice_temperature(c1);
109
110 const double mobility = mobility_(c1, c2, potential_);
111
112 const double connection_len = viennagrid::norm_2(viennagrid::centroid(c2) - viennagrid::centroid(c1));
113 const double potential_outer = potential_(c2);
114 const double carrier_outer = viennashe::materials::is_conductor(device_.get_material(c2))
115 ? bnd_carrier_density(c1, device_.get_lattice_temperature(c1))
116 : carrier_.get_value(c2);
117
118 if ( carrier_outer <= 0 || carrier_center <= 0 ) return 0;
119
120 const double polarity = (carrier_type_id_ == viennashe::ELECTRON_TYPE_ID) ? -1.0 : 1.0;
121 const double charge_flux = flux_approximator(carrier_center, carrier_outer, potential_center, potential_outer, connection_len, mobility, T);
122 const double Jmag = polarity * mobility * charge_flux;
123
124 return Jmag;
125 } // operator()
126
127 private:
128 DeviceType const & device_;
129 viennashe::carrier_type_id carrier_type_id_;
130 PotentialAccessorType const & potential_;
131 AccessorTypeCarrier const & carrier_;
132 MobilityModel const & mobility_;
133
134 }; // current_density_on_edge
135
136 template <typename DeviceType, typename SimulatorQuantity>
138 {
139 typedef typename DeviceType::mesh_type MeshType;
140
141 public:
142 typedef typename viennagrid::result_of::cell<MeshType>::type cell_type;
143 typedef bool value_type;
144
145 macroscopic_carrier_mask_filter(SimulatorQuantity const & quan) : quantity_(quan) {}
146
147 value_type operator()(cell_type const & c) const { return quantity_.get_unknown_mask(c); } //TODO: Might need fixing!
148
149 private:
150 SimulatorQuantity const & quantity_;
151 };
152
153 } // namespace detail
154
155
159 template <typename DeviceType,
160 typename PotentialQuantityType,
161 typename CarrierQuantityType,
162 typename MobilityModel>
164 {
165 protected:
166 typedef typename DeviceType::mesh_type MeshType;
167
168 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
169 typedef typename viennagrid::result_of::vertex<MeshType>::type VertexType;
170 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
171 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
172
173 public:
174 typedef std::vector<double> value_type;
175
176 current_density_wrapper(DeviceType const & device,
178 PotentialQuantityType const & potential,
179 CarrierQuantityType const & carrier,
180 MobilityModel const & mobility_model)
181 : device_(device), carrier_type_id_(ctype), potential_(potential), carrier_(carrier), mobility_(mobility_model) { }
182
183 double operator()(FacetType const & facet) const
184 {
186 current_density_evaluator edge_evaluator(device_, carrier_type_id_, potential_, carrier_, mobility_);
187 return edge_evaluator(facet);
188 }
189
190 value_type operator()(CellType const & cell) const
191 {
192 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
194
196
197 std::vector<double> J(3);
198
199 if (!carrier_contribution_filter(cell)) return J;
200
202
203 current_density_evaluator facet_evaluator(device_, carrier_type_id_, potential_, carrier_, mobility_);
204
205 FacetOnCellContainer facets_on_cell(cell);
207 cell, facets_on_cell,
208 result, facet_evaluator);
209
210 return result();
211 }
212
213 private:
214 DeviceType const & device_;
215 viennashe::carrier_type_id carrier_type_id_;
216 PotentialQuantityType const & potential_;
217 CarrierQuantityType const & carrier_;
218 MobilityModel const & mobility_;
219 };
220
221
231 template <typename DeviceType,
232 typename PotentialQuantityType,
233 typename CarrierQuantityType,
234 typename MobilityModel,
235 typename ContainerType>
237 PotentialQuantityType const & potential,
238 CarrierQuantityType const & carrier,
240 MobilityModel const & mobility_model,
241 ContainerType & container)
242 {
244
246 }
247
248
254 template <typename DeviceT, typename CurrentDensityT>
255 void check_current_conservation(DeviceT const & device,
256 CurrentDensityT const & current_on_facet)
257 {
258 typedef typename DeviceT::mesh_type MeshType;
259
260 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
261 typedef typename viennagrid::result_of::facet<MeshType>::type FacetType;
262 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
263
264 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
265 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
266
267 typedef typename viennagrid::result_of::const_facet_range<CellType>::type FacetOnCellContainer;
268 typedef typename viennagrid::result_of::iterator<FacetOnCellContainer>::type FacetOnCellIterator;
269
270 typedef typename viennagrid::result_of::const_coboundary_range<MeshType, FacetType, CellType>::type CellOnFacetContainer;
271
272 CellContainer cells(device.mesh());
273 for (CellIterator cit = cells.begin();
274 cit != cells.end();
275 ++cit)
276 {
277 double net_box_flux = 0;
278 double partial_flux_max = 0;
279
280 PointType centroid_cell = viennagrid::centroid(*cit);
281
282 FacetOnCellContainer facets_on_cell(*cit);
283 for (FacetOnCellIterator focit = facets_on_cell.begin();
284 focit != facets_on_cell.end();
285 ++focit)
286 {
287 CellType const *other_cell_ptr = util::get_other_cell_of_facet(device.mesh(), *focit, *cit);
288
289 if (!other_cell_ptr) continue; //Facet is on the boundary of the simulation domain -> homogeneous Neumann conditions
290
291 PointType centroid_other_cell = viennagrid::centroid(*other_cell_ptr);
292 PointType cell_connection = centroid_other_cell - centroid_cell;
293 PointType cell_connection_normalized = cell_connection / viennagrid::norm(cell_connection);
294 PointType facet_unit_normal = viennashe::util::outer_cell_normal_at_facet(*cit, *focit);
295 const double weighted_interface_area = viennagrid::volume(*focit) * viennagrid::inner_prod(facet_unit_normal, cell_connection_normalized);
296 double contribution_from_facet = current_on_facet(*focit) * weighted_interface_area;
297 if (std::fabs(contribution_from_facet) > partial_flux_max)
298 partial_flux_max = std::fabs(contribution_from_facet);
299
300 CellOnFacetContainer cells_on_facet(device.mesh(), focit.handle());
301 if ( &(*cit) == &(cells_on_facet[0]) ) //reference direction is into box
302 net_box_flux -= contribution_from_facet;
303 else
304 net_box_flux += contribution_from_facet;
305 }// for facets
306
307 if (partial_flux_max > 0)
308 {
309 if ( std::fabs(net_box_flux / partial_flux_max) > 1e-10)
310 {
311 log::info() << "-- Box " << *cit << " --" << std::endl;
312 log::info() << "Net box flux (should be zero, unless at contact): " << net_box_flux << " with maximum " << partial_flux_max << std::endl;
313 }
314 }
315
316 } // for cells
317 }
318
319 template <typename DeviceType,
320 typename PotentialQuantityType,
321 typename CarrierQuantityType,
322 typename MobilityModel>
323 void check_current_conservation(DeviceType const & device,
325 PotentialQuantityType const & potential,
326 CarrierQuantityType const & carrier,
327 MobilityModel const & mobility_model)
328 {
330
332 }
333
334
335} //namespace viennashe
336
337#endif
Contains the definition of per-device accessors (read-only!) for various quantities.
Defines a set of checker functors for micro-tests within ViennaSHE.
An accessor to the current density on vertices and edges (drift diffusion only!)
viennagrid::result_of::point< MeshType >::type PointType
value_type operator()(CellType const &cell) const
viennagrid::result_of::cell< MeshType >::type CellType
viennagrid::result_of::vertex< MeshType >::type VertexType
viennagrid::result_of::facet< MeshType >::type FacetType
current_density_wrapper(DeviceType const &device, viennashe::carrier_type_id ctype, PotentialQuantityType const &potential, CarrierQuantityType const &carrier, MobilityModel const &mobility_model)
double operator()(FacetType const &facet) const
MeshT const & mesh() const
Returns the underlying mesh.
Definition: device.hpp:145
viennagrid::result_of::cell< MeshType >::type cell_type
value_type operator()(cell_type const &c) const
macroscopic_carrier_mask_filter(SimulatorQuantity const &quan)
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Definition: device.hpp:818
Dispatcher for Scharfetter-Gummel discretization of electron and hold fluxes.
A functor which holds a single value. Used in most of the postprocessing routines.
Definition: misc.hpp:59
Helper routines for projecting normal components of a vector-valued quantity defined on edges to vert...
Contains forward declarations and definition of small classes that must be defined at an early stage.
A logging facility providing fine-grained control over logging in ViennaSHE.
Writer for arbitrary macroscopic quantities.
A very simple material database. Needs to be replaced by something more versatile soon.
Miscellaneous utilities.
logger< true > info()
Used to log infos. The logging level is logINFO.
Definition: log.hpp:307
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_insulator(long material_id)
Convenience function for checking whether the supplied material ID refers to an oxide.
Definition: all.hpp:165
bool is_conductor(long material_id)
Convenience function for checking whether the supplied material ID refers to a metal.
Definition: all.hpp:147
VectorType::value_type norm_2(VectorType const &v)
Definition: linalg_util.hpp:37
void dual_box_flux_to_cell(DeviceT const &device, CellT const &cell, FacetContainerT const &facets, CellSetterT &cell_setter, FacetAccessorT const &facet_access)
Interpolates normal components of the flux defined on each facet to cells. Mostly used for visualizat...
viennagrid::result_of::point< viennagrid::element< CellTagT, WrappedConfigT > >::type outer_cell_normal_at_facet(viennagrid::element< CellTagT, WrappedConfigT > const &cell, viennagrid::element< FacetTagT, WrappedConfigT > const &facet)
Returns the unit outer normal of a facet with respect to the provided cell.
CellT const * get_other_cell_of_facet(MeshT const &mesh, FacetT const &facet, CellT const &cell)
Helper function returning a const-pointer to the 'second cell' of a facet, or NULL if there is no sec...
Definition: misc.hpp:196
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
void write_current_density_to_container(DeviceType const &device, PotentialQuantityType const &potential, CarrierQuantityType const &carrier, viennashe::carrier_type_id ctype, MobilityModel const &mobility_model, ContainerType &container)
Convenience function for writing the electric field to a container.
carrier_type_id
Enumeration type for selecting the carrier type.
Definition: forwards.h:185
@ ELECTRON_TYPE_ID
Definition: forwards.h:187
void check_current_conservation(DeviceT const &device, CurrentDensityT const &current_on_facet)
Checks current conservation for SHE. Writes information using log::info().
void write_macroscopic_quantity_to_container(DeviceType const &device, MacroscopicQuantityAccessor const &quantity, ContainerType &quantity_container)
Writes the provided macroscopic quantity to the container provided.
Definition: macroscopic.hpp:46
Provides a number of fundamental constants. All constants in SI units.
Returns a few helper routines for computing physical quantities. To be replaced in the future.
Scharfetter-Gummel stabilization of the continuity equations.
Returns the carrier density at contacts modelled as thermal baths (used by DD and SHE)
Definition: accessors.hpp:317
An accessor to the current density (drift diffusion only!) on edges.
value_type operator()(FacetType const &facet) const
current_density_on_facet(DeviceType const &device, viennashe::carrier_type_id ctype, PotentialAccessorType const &potential, AccessorTypeCarrier const &carrier, MobilityModel const &mobility_model)
viennagrid::result_of::facet< MeshType >::type FacetType
viennagrid::result_of::cell< MeshType >::type CellType
viennagrid::result_of::point< MeshType >::type PointType
viennagrid::result_of::vertex< MeshType >::type VertexType