ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
device_reader_vtk.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_IO_DEVICE_READER_VTK_HPP
2#define VIENNASHE_IO_DEVICE_READER_VTK_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// std
19#include <math.h>
20#include <fstream>
21#include <iostream>
22
23// viennagrid
24#include "viennagrid/forwards.hpp"
25#include "viennagrid/topology/simplex.hpp"
26#include "viennagrid/io/vtk_reader.hpp"
27
28// viennashe
29#include "viennashe/forwards.h"
30#include "viennashe/log/log.hpp"
33
35
36
37namespace viennashe
38{
39 namespace io
40 {
41
42 namespace detail
43 {
44
45 template < typename MeshT >
47 {
48 typedef typename viennagrid::io::vtk_reader<MeshT> vtk_reader_type;
49
50 mesh_generator_vtk(std::string filename) : filename_(filename) {}
51
52 template < typename SegT>
53 void operator()(MeshT & mesh, SegT & seg)
54 {
55 this->mesh_reader_(mesh, seg, this->filename_);
56 }
57
58 vtk_reader_type & reader() { return this->mesh_reader_; }
59
60 private:
61 vtk_reader_type mesh_reader_;
62 std::string filename_;
63 };
64
65 }
66
76 template < typename DeviceType >
77 bool read_device_vtk(DeviceType & device,
78 std::string filename,
79 std::string doping_n_key,
80 std::string doping_p_key,
81 std::string material_key)
82 {
83 typedef typename DeviceType::mesh_type MeshType;
84 typedef typename DeviceType::segment_type SegmentType;
85
86 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
87 typedef typename viennagrid::result_of::vertex<MeshType>::type VertexType;
88
89 //typedef typename viennagrid::result_of::const_vertex_range<SegmentType>::type VertexContainer;
90 //typedef typename viennagrid::result_of::iterator<VertexContainer>::type VertexIterator;
91
92 typedef typename viennagrid::result_of::const_cell_range<SegmentType>::type CellContainer;
93 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
94
95 typedef typename viennagrid::result_of::const_vertex_range<CellType>::type VertexOnCellContainer;
96 typedef typename viennagrid::result_of::iterator<VertexOnCellContainer>::type VertexOnCellIterator;
97
98
99 typedef typename viennagrid::result_of::field<const std::deque<double>, CellType >::type scalar_cell_data;
100 typedef typename viennagrid::result_of::field<const std::deque<double>, VertexType >::type scalar_vertex_data;
101
102 if (doping_n_key.empty() || doping_p_key.empty())
103 {
104 viennashe::log::error() << "* read_device(): One of the doping keys is empty! Unable to proceed." << std::endl;
105 return false;
106 }
107
108 detail::mesh_generator_vtk<MeshType> my_vtk_reader(filename);
109
110 device.load_device(my_vtk_reader); // basic init of mesh and device
111
112 typename detail::mesh_generator_vtk<MeshType>::vtk_reader_type & mesh_reader = my_vtk_reader.reader();
113
114
115 const std::size_t num_segments = device.segmentation().size();
116 log::info() << "* read_device_vtk(): There are " << num_segments << " segments." << std::endl;
117
118 // DEBUG INFORMATION:
119 for (std::size_t j = 0; j < num_segments; ++j)
120 {
121 log::debug() << "* read_device():" << std::endl;
122
123 if(mesh_reader.scalar_cell_data_names(j).size() > 0)
124 log::debug() << " Segment " << j << " has the following scalar CELL quantities: " << std::endl;
125 for(std::size_t i = 0; i < mesh_reader.scalar_cell_data_names(j).size(); ++i)
126 log::debug() << "\t" << mesh_reader.scalar_cell_data_names(j)[i] << std::endl;
127
128 if(mesh_reader.scalar_vertex_data_names(j).size() > 0)
129 log::debug() << " Segment " << j << " has the following scalar VERTEX quantities: " << std::endl;
130 for(std::size_t i = 0; i < mesh_reader.scalar_vertex_data_names(j).size(); ++i)
131 log::debug() << "\t" << mesh_reader.scalar_vertex_data_names(j)[i] << std::endl;
132
133 log::debug() << std::endl;
134 }
135
136 //
137 // Set the material per cell on each segment
138 if (!material_key.empty())
139 {
140 viennashe::log::info() << "* read_device(): Setting materials ..." << std::endl;
141 log::debug()<< "* read_device(): Using '" << material_key << "' as material ID per cell." << std::endl;
142
143 for (std::size_t j = 0; j < num_segments; ++j)
144 {
145 bool has_material_information = false;
146 std::vector<std::string> cell_data_names = mesh_reader.scalar_cell_data_names(j);
147 for (std::size_t n=0; n<cell_data_names.size(); ++n)
148 {
149 if (cell_data_names[n] == material_key)
150 has_material_information = true;
151 }
152
153 if (!has_material_information)
154 {
155 viennashe::log::error() << "* read_device(): WARNING: Unable to find material for segment " << j << "! Skipping..." << std::endl;
156 continue;
157 }
158
159 scalar_cell_data const & mat_data = mesh_reader.cell_scalar_field(material_key, j);
160 CellContainer cells(device.segment(j));
161 for ( CellIterator cit = cells.begin(); cit != cells.end(); ++cit )
162 {
163 const long material_id = mat_data.at(*cit);
164 device.set_material(material_id, *cit);
165 } // for cells
166 }
167 }
168 else
169 {
170 viennashe::log::warning() << "* read_device(): Empty material key found! Assuming the material is being set by the user ... " << std::endl;
171 }
172
173
174 viennashe::log::info() << "* read_device(): Setting doping ..." << std::endl;
175
176 for (std::size_t j = 0; j < num_segments; ++j)
177 {
178 bool doping_on_cells = false;
179
180 std::vector<std::string> cell_data_names = mesh_reader.scalar_cell_data_names(j);
181 for (std::size_t n=0; n<cell_data_names.size(); ++n)
182 {
183 if (cell_data_names[n] == doping_n_key)
184 doping_on_cells = true;
185 }
186
187 if (doping_on_cells && mesh_reader.cell_scalar_field(doping_n_key, j).is_valid() ) // look for doping on cells
188 {
189 log::debug()<< "* read_device(): Using '" << doping_n_key << "' as donor doping per cell on segment " << j << "." << std::endl;
190 log::debug()<< "* read_device(): Using '" << doping_p_key << "' as acceptor doping per cell on segment " << j << "." << std::endl;
191
192 scalar_cell_data const & data_n = mesh_reader.cell_scalar_field(doping_n_key, j);
193 scalar_cell_data const & data_p = mesh_reader.cell_scalar_field(doping_p_key, j);
194
195 if (!data_n.is_valid() || !data_p.is_valid())
196 {
197 log::error() << "* read_device(): Invalid doping key on cells !" << std::endl;
198 return false;
199 }
200
201 CellContainer cells(device.segment(j));
202 for ( CellIterator cit = cells.begin(); cit != cells.end(); ++cit )
203 {
204 device.set_doping_n(data_n.at(*cit), *cit);
205 device.set_doping_p(data_p.at(*cit), *cit);
206 } // for cells
207 }
208 else if (!doping_on_cells && mesh_reader.vertex_scalar_field(doping_n_key, j).is_valid() ) // doping on vertices
209 {
210 log::debug()<< "* read_device(): Using '" << doping_n_key << "' as donor doping per vertex." << std::endl;
211 log::debug()<< "* read_device(): Using '" << doping_p_key << "' as acceptor doping per vertex." << std::endl;
212
213 scalar_vertex_data const & data_n = mesh_reader.vertex_scalar_field(doping_n_key, j);
214 scalar_vertex_data const & data_p = mesh_reader.vertex_scalar_field(doping_p_key, j);
215
216 if (!data_n.is_valid() || !data_p.is_valid())
217 {
218 log::error() << "* read_device(): Invalid doping key on vertices !" << std::endl;
219 return false;
220 }
221
222 CellContainer cells(device.segment(j));
223 for ( CellIterator cit = cells.begin(); cit != cells.end(); ++cit )
224 {
225 double doping_n = 1.0;
226 double doping_p = 1.0;
227 VertexOnCellContainer vertices(*cit);
228 double N_n = 0;
229 double N_p = 0;
230 for ( VertexOnCellIterator vocit = vertices.begin(); vocit != vertices.end(); ++vocit )
231 {
232 if (data_n.at(*vocit))
233 {
234 doping_n *= data_n.at(*vocit);
235 ++N_n;
236 }
237 if (data_p.at(*vocit))
238 {
239 doping_p *= data_p.at(*vocit);
240 ++N_p;
241 }
242 }
243 if (N_n > 0)
244 device.set_doping_n(std::pow(doping_n, 1.0/N_n), *cit);
245 if (N_p > 0)
246 device.set_doping_p(std::pow(doping_p, 1.0/N_p), *cit);
247 } // for cells
248 }
249 else
250 {
251 viennashe::log::error() << "* read_device(): None or inconsistent (cells,vertices) donor doping found! " << std::endl;
252 return false;
253 }
254 }
255
256 return true;
257 } // read_device
258
259 template <typename DeviceT, typename SimulatorT>
260 bool read_initial_guess_vtk(DeviceT const & device,
261 SimulatorT & simulator,
262 std::string filename,
263 std::string quantity_name,
264 std::string vtk_quantity_key)
265 {
266 typedef typename DeviceT::mesh_type MeshType;
267 typedef typename DeviceT::segment_type SegmentType;
268
269 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
270 typedef typename viennagrid::result_of::vertex<MeshType>::type VertexType;
271
272 typedef typename viennagrid::result_of::const_cell_range<SegmentType>::type CellContainer;
273 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
274
275 typedef typename viennagrid::result_of::const_vertex_range<CellType>::type VertexOnCellContainer;
276 typedef typename viennagrid::result_of::iterator<VertexOnCellContainer>::type VertexOnCellIterator;
277
278 typedef typename viennagrid::result_of::field<const std::deque<double>, CellType >::type scalar_cell_data;
279 typedef typename viennagrid::result_of::field<const std::deque<double>, VertexType >::type scalar_vertex_data;
280
281 detail::mesh_generator_vtk<MeshType> my_vtk_reader(filename);
282
283 typename detail::mesh_generator_vtk<MeshType>::vtk_reader_type & mesh_reader = my_vtk_reader.reader();
284
285 DeviceT dummy_device;
286 dummy_device.load_device(my_vtk_reader); // basic init of mesh and device
287
288 const std::size_t num_segments = dummy_device.segmentation().size();
289 log::info() << "* read_initial_guess_vtk(): There are " << num_segments << " segments." << std::endl;
290
291 // DEBUG INFORMATION:
292 for (std::size_t j = 0; j < num_segments; ++j)
293 {
294 log::debug() << "* read_initial_guess_vtk():" << std::endl;
295
296 if(mesh_reader.scalar_cell_data_names(j).size() > 0)
297 log::debug() << " Segment " << j << " has the following scalar CELL quantities: " << std::endl;
298 for(std::size_t i = 0; i < mesh_reader.scalar_cell_data_names(j).size(); ++i)
299 log::debug() << "\t" << mesh_reader.scalar_cell_data_names(j)[i] << std::endl;
300
301 if(mesh_reader.scalar_vertex_data_names(j).size() > 0)
302 log::debug() << " Segment " << j << " has the following scalar VERTEX quantities: " << std::endl;
303 for(std::size_t i = 0; i < mesh_reader.scalar_vertex_data_names(j).size(); ++i)
304 log::debug() << "\t" << mesh_reader.scalar_vertex_data_names(j)[i] << std::endl;
305
306 log::debug() << std::endl;
307 }
308
309 viennashe::log::info() << "* read_initial_guess_vtk(): Setting quantity as initial guess ..." << std::endl;
310
311 std::deque<double> cell_data(viennagrid::cells(device.mesh()).size());
312 for (std::size_t j = 0; j < num_segments; ++j)
313 {
314 bool quantity_on_cells = false;
315
316 std::vector<std::string> cell_data_names = mesh_reader.scalar_cell_data_names(j);
317 for (std::size_t n=0; n<cell_data_names.size(); ++n)
318 {
319 if (cell_data_names[n] == vtk_quantity_key)
320 quantity_on_cells = true;
321 }
322
323 if (quantity_on_cells && mesh_reader.cell_scalar_field(vtk_quantity_key, j).is_valid() ) // look for quantity on cells
324 {
325 log::debug()<< "* read_initial_guess_vtk(): Using '" << vtk_quantity_key << "' as VTK quantity key for " << quantity_name << " per cell on segment " << j << "." << std::endl;
326
327 scalar_cell_data const & data = mesh_reader.cell_scalar_field(vtk_quantity_key, j);
328
329 if (!data.is_valid())
330 {
331 log::error() << "* read_initial_guess_vtk(): Invalid quantity key on cells !" << std::endl;
332 return false;
333 }
334
335 CellContainer cells(dummy_device.segment(j));
336 for ( CellIterator cit = cells.begin(); cit != cells.end(); ++cit )
337 cell_data.at(cit->id().get()) = data.at(*cit);
338 }
339 else if (!quantity_on_cells && mesh_reader.vertex_scalar_field(vtk_quantity_key, j).is_valid() ) // doping on vertices
340 {
341 log::debug()<< "* read_initial_guess_vtk(): Using '" << vtk_quantity_key << "' as VTK quantity key for " << quantity_name << " per vertex on segment " << j << "." << std::endl;
342
343 scalar_vertex_data const & data = mesh_reader.vertex_scalar_field(vtk_quantity_key, j);
344
345 if (!data.is_valid())
346 {
347 log::error() << "* read_device(): Invalid quantity key on vertices !" << std::endl;
348 return false;
349 }
350
351 CellContainer cells(dummy_device.segment(j));
352 for ( CellIterator cit = cells.begin(); cit != cells.end(); ++cit )
353 {
354 double value = 0.0;
355 VertexOnCellContainer vertices(*cit);
356 const double N = static_cast<double>( vertices.size() );
357 for ( VertexOnCellIterator vocit = vertices.begin(); vocit != vertices.end(); ++vocit )
358 value += data.at(*vocit);
359 cell_data.at(cit->id().get()) = value / N;
360 } // for cells
361 }
362 else
363 {
364 viennashe::log::error() << "* read_initial_guess_vtk(): None or inconsistent (cells,vertices) quantity data for " << quantity_name << " found! " << std::endl;
365 return false;
366 }
367 }
368
369 typename viennagrid::result_of::accessor<std::deque<double>, CellType>::type cell_data_wrapper(cell_data);
370 simulator.set_initial_guess(quantity_name, cell_data_wrapper);
371
372 return true;
373 } // read_device
374
381 template < typename DeviceType >
382 void read_device_vtk(DeviceType & device, const std::string filename)
383 {
384 read_device(device, filename, "doping_n", "doping_p", "material");
385 } // read_device
386
387 } // io
388} // viennashe
389
390#endif /* VIENNASHE_IO_DEVICE_READER_VTK_HPP */
391
void set_material(long material_id, cell_type const &elem)
Sets the material ID on a cell.
Definition: device.hpp:448
void load_device(DeviceLoaderType &loader)
Definition: device.hpp:121
segmentation_type const & segmentation() const
Definition: device.hpp:156
segment_type const & segment(segment_id_type id) const
Definition: device.hpp:167
void set_doping_p(double value, cell_type const &c)
Sets the acceptor doping (in m^-3) in the specified cell.
Definition: device.hpp:365
MeshT const & mesh() const
Returns the underlying mesh.
Definition: device.hpp:145
void set_doping_n(double value, cell_type const &c)
Sets the donator doping (in m^-3) in the specified cell.
Definition: device.hpp:292
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Definition: device.hpp:818
Class for self-consistent SHE simulations.
Definition: simulator.hpp:675
void set_initial_guess(std::string quan_name, QuantityAccessorT const &quan_acc)
Transfers the inital guess for the given quantity.
Definition: simulator.hpp:866
Contains forward declarations and definition of small classes that must be defined at an early stage.
All the exceptions used within the viennashe::io namespace.
A logging facility providing fine-grained control over logging in ViennaSHE.
A very simple material database. Needs to be replaced by something more versatile soon.
bool read_device_vtk(DeviceType &device, std::string filename, std::string doping_n_key, std::string doping_p_key, std::string material_key)
Reads and initalises a device from a VTK file. If material_key is empty the material IDs will not be ...
bool read_initial_guess_vtk(DeviceT const &device, SimulatorT &simulator, std::string filename, std::string quantity_name, std::string vtk_quantity_key)
logger< true > error()
Used to log errors. The logging level is logERROR.
Definition: log.hpp:301
logger< true > debug()
Used to log debug output. The logging level is logDEBUG.
Definition: log.hpp:309
logger< true > warning()
Used to log warnings. The logging level is logWARNING.
Definition: log.hpp:305
logger< true > info()
Used to log infos. The logging level is logINFO.
Definition: log.hpp:307
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
Provides a number of fundamental constants. All constants in SI units.
viennagrid::io::vtk_reader< MeshT > vtk_reader_type