ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
she_vtk_writer.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_IO_SHE_VTK_WRITER_HPP
2#define VIENNASHE_IO_SHE_VTK_WRITER_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 <math.h>
21#include <fstream>
22#include <iostream>
23#include <vector>
24
25// viennagrid
26#include "viennagrid/forwards.hpp"
27#include "viennagrid/mesh/mesh.hpp"
28#include "viennagrid/io/vtk_writer.hpp"
29
30// viennashe
31#include "viennashe/forwards.h"
32#include "viennashe/config.hpp"
42
43#include "viennashe/log/log.hpp"
46
47
53namespace viennashe
54{
55 namespace io
56 {
57
59 namespace result_of
60 {
66 template <typename T>
68 {
69 //enum{ value = -1 }; //force invalid value...
70 typedef typename T::ERROR_NO_SHE_VTK_WRITER_FOR_THIS_ELEMENT_TYPE_AVAILABLE error_type;
71 };
72
74 template <>
75 struct she_vtk_type<viennagrid::simplex_tag<1> >
76 {
77 enum{ value = 9 }; //VTK_quad
78 };
79
81 template <>
82 struct she_vtk_type<viennagrid::hypercube_tag<1> >
83 {
84 enum{ value = 9 }; //VTK_quad
85 };
86
88 template <>
89 struct she_vtk_type<viennagrid::quadrilateral_tag>
90 {
91 enum{ value = 12 }; //VTK_hexahedron
92 };
93
95 template <>
96 struct she_vtk_type<viennagrid::triangle_tag>
97 {
98 enum{ value = 13 }; //VTK_wedge
99 };
100
101 }
102
103
105
107 template < typename SHEDeviceType,
108 typename CoordSystem = typename viennagrid::result_of::coordinate_system<typename viennagrid::result_of::point<typename SHEDeviceType::mesh_type>::type>::type >
110 {
111 protected:
112
113 typedef typename SHEDeviceType::mesh_type MeshType;
114
115 typedef typename viennagrid::result_of::cell_tag<MeshType>::type CellTag;
116
117 typedef typename viennagrid::result_of::point<MeshType>::type PointType;
118 typedef typename viennagrid::result_of::vertex<MeshType>::type VertexType;
119 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
120
122 template <typename DeviceType, typename SHEQuantity, typename CellType>
123 bool is_valid(DeviceType const & device, SHEQuantity const & quan, CellType const & cell, std::size_t index_H)
124 {
125 if ( quan.get_unknown_index(cell, index_H) >= 0 && viennashe::materials::is_semiconductor(device.get_material(cell)) )
126 return true;
127
128 if (write_segments() && quan.get_kinetic_energy(cell, index_H) > 0 && !viennashe::materials::is_semiconductor(device.get_material(cell)))
129 return true;
130
131 return false;
132 }
133
135 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
136 long get_cell_num(DeviceType const & device, SegmentType const & segment, SHEQuantity const & quan)
137 {
138 typedef typename viennagrid::result_of::const_vertex_range<SegmentType>::type VertexContainer;
139 typedef typename viennagrid::result_of::iterator<VertexContainer>::type VertexIterator;
140
141 typedef typename viennagrid::result_of::const_cell_range<SegmentType>::type CellContainer;
142 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
143
144 typedef typename viennagrid::result_of::const_vertex_range<CellType>::type VertexOnCellContainer;
145 typedef typename viennagrid::result_of::iterator<VertexOnCellContainer>::type VertexOnCellIterator;
146
147 long total_cell_num = 0;
148
149 //
150 // Step 1: init write flag on vertices:
151 //
152 VertexContainer vertices(segment);
153 vertex_write_mask_.resize(viennagrid::vertices(device.mesh()).size());
154 for (VertexIterator vit = vertices.begin();
155 vit != vertices.end();
156 ++vit)
157 {
158 vertex_write_mask_[static_cast<std::size_t>(vit->id().get())].resize(quan.get_value_H_size());
159 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
160 {
161 vertex_write_mask_[static_cast<std::size_t>(vit->id().get())].at(index_H) = -1;
162 }
163 }
164
165 //
166 // Step 2: Now tag all cells where all vertices are in the conduction or valence band
167 //
168 CellContainer cells(segment);
169 for (CellIterator cit = cells.begin();
170 cit != cells.end();
171 ++cit)
172 {
173
174 for (std::size_t index_H = 0; index_H < quan.get_value_H_size()-1; ++index_H)
175 {
176 if (is_valid(device, quan, *cit, index_H))
177 {
178 ++total_cell_num;
179
180 //tag all vertices:
181 VertexOnCellContainer vertices_on_cell(*cit);
182 for (VertexOnCellIterator vocit = vertices_on_cell.begin();
183 vocit != vertices_on_cell.end();
184 ++vocit)
185 {
186 vertex_write_mask_[static_cast<std::size_t>(vocit->id().get())].at(index_H) = 0;
187 vertex_write_mask_[static_cast<std::size_t>(vocit->id().get())].at(index_H+1) = 0;
188 }
189 }
190 }
191 }
192
193 return total_cell_num;
194 }
195
197 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
198 long get_point_num(DeviceType const & device, SegmentType const & segment, SHEQuantity const & quan)
199 {
200 typedef typename viennagrid::result_of::const_vertex_range<SegmentType>::type VertexContainer;
201 typedef typename viennagrid::result_of::iterator<VertexContainer>::type VertexIterator;
202
203 (void)device;
204 long point_num = 0;
205
206 VertexContainer vertices(segment);
207 for (VertexIterator vit = vertices.begin();
208 vit != vertices.end();
209 ++vit)
210 {
211 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
212 {
213 if (vertex_write_mask_[static_cast<std::size_t>(vit->id().get())].at(index_H) >= 0)
214 {
215 vertex_write_mask_[static_cast<std::size_t>(vit->id().get())].at(index_H) = point_num;
216 ++point_num;
217 }
218 }
219 }
220
221 return point_num;
222 } //writePointData
223
224
225
227 void writeHeader(std::ofstream & writer)
228 {
229 writer << "<?xml version=\"1.0\"?>" << std::endl;
230 writer << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << std::endl;
231 writer << " <UnstructuredGrid>" << std::endl;
232 }
233
235 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
236 void writePoints(DeviceType const & device, SegmentType const & segment, SHEQuantity const & quan, std::ofstream & writer)
237 {
238 typedef typename viennagrid::result_of::const_vertex_range<SegmentType>::type VertexContainer;
239 typedef typename viennagrid::result_of::iterator<VertexContainer>::type VertexIterator;
240
241 (void)device;
242 writer << " <Points>" << std::endl;
243 writer << " <DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;
244
245 VertexContainer vertices(segment);
246 for (VertexIterator vit = vertices.begin();
247 vit != vertices.end();
248 ++vit)
249 {
250 for (std::size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
251 {
252 if (vertex_write_mask_[static_cast<std::size_t>(vit->id().get())].at(index_H) >= 0)
253 {
254 writer << viennagrid::point(*vit)[0] << " ";
255 if (viennagrid::point(*vit).size() == 1)
256 writer << "0 ";
257 else
258 writer << viennagrid::point(*vit)[1] << " ";
259 writer << quan.get_value_H(index_H) << " ";
260 }
261 }
262 writer << std::endl;
263 }
264 writer << std::endl;
265 writer << " </DataArray>" << std::endl;
266 writer << " </Points> " << std::endl;
267 } //writePoints()
268
270 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
271 void writeCells(DeviceType const & device, SegmentType const & segment, SHEQuantity const & quan, std::ofstream & writer)
272 {
273 typedef typename viennagrid::result_of::const_cell_range<SegmentType>::type CellContainer;
274 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
275
276 typedef typename viennagrid::result_of::const_vertex_range<CellType>::type VertexOnCellContainer;
277 typedef typename viennagrid::result_of::iterator<VertexOnCellContainer>::type VertexOnCellIterator;
278
279 writer << " <Cells> " << std::endl;
280 writer << " <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << std::endl;
281 CellContainer cells(segment);
282
283 //write prisms:
284 std::size_t num_cells = 0;
285 for (std::size_t index_H = 0; index_H < quan.get_value_H_size() - 1; ++index_H)
286 {
287 std::size_t index_H_other = index_H + 1;
288
289 for (CellIterator cit = cells.begin();
290 cit != cells.end();
291 ++cit)
292 {
293 if (!is_valid(device, quan, *cit, index_H))
294 continue;
295
296 VertexOnCellContainer vertices_on_cell(*cit);
297
298 if (vertices_on_cell.size() == 2) //line segments need special treatment
299 {
300 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[0].id().get())].at(index_H) << " ";
301 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[1].id().get())].at(index_H) << " ";
302
303 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[1].id().get())].at(index_H_other) << " ";
304 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[0].id().get())].at(index_H_other) << " ";
305 ++num_cells;
306 }
307 else if (vertices_on_cell.size() == 4) //quadrilaterals need special treatment
308 {
309 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[0].id().get())].at(index_H) << " ";
310 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[1].id().get())].at(index_H) << " ";
311 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[3].id().get())].at(index_H) << " ";
312 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[2].id().get())].at(index_H) << " ";
313
314 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[0].id().get())].at(index_H_other) << " ";
315 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[1].id().get())].at(index_H_other) << " ";
316 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[3].id().get())].at(index_H_other) << " ";
317 writer << vertex_write_mask_[static_cast<std::size_t>(vertices_on_cell[2].id().get())].at(index_H_other) << " ";
318 ++num_cells;
319 }
320 else
321 {
322 for (VertexOnCellIterator vocit = vertices_on_cell.begin();
323 vocit != vertices_on_cell.end();
324 ++vocit)
325 {
326 writer << vertex_write_mask_[static_cast<std::size_t>(vocit->id().get())].at(index_H) << " ";
327 }
328
329 for (VertexOnCellIterator vocit = vertices_on_cell.begin();
330 vocit != vertices_on_cell.end();
331 ++vocit)
332 {
333 writer << vertex_write_mask_[static_cast<std::size_t>(vocit->id().get())].at(index_H_other) << " ";
334 }
335
336 ++num_cells;
337 }
338 writer << std::endl;
339 }
340 }
341
342 writer << std::endl;
343 writer << " </DataArray>" << std::endl;
344
345 writer << " <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << std::endl;
346 for (std::size_t offsets = 1;
347 offsets <= num_cells;
348 ++offsets)
349 {
350 writer << (offsets * viennagrid::boundary_elements<CellTag, viennagrid::vertex_tag>::num * 2) << " ";
351 }
352 writer << std::endl;
353 writer << " </DataArray>" << std::endl;
354
355 writer << " <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << std::endl;
356 for (std::size_t offsets = 1;
357 offsets <= num_cells;
358 ++offsets)
359 {
360 writer << result_of::she_vtk_type<CellTag>::value << " ";
361 }
362 writer << std::endl;
363 writer << " </DataArray>" << std::endl;
364 writer << " </Cells>" << std::endl;
365 }
366
368 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
369 void writePointData(DeviceType const & device,
370 SegmentType const & segment,
371 SHEQuantity const & quan,
372 std::ofstream & writer, std::string name_in_file = "result")
373 {
374 typedef typename viennagrid::result_of::const_vertex_range<SegmentType>::type VertexContainer;
375 typedef typename viennagrid::result_of::iterator<VertexContainer>::type VertexIterator;
376
377 (void)device;
378 writer << " <PointData Scalars=\"scalars\">" << std::endl;
379 writer << " <DataArray type=\"Float64\" Name=\"" << name_in_file << "\" format=\"ascii\">" << std::endl;
380
381 VertexContainer vertices(segment);
382 for (VertexIterator vit = vertices.begin();
383 vit != vertices.end();
384 ++vit)
385 {
386 for (size_t index_H = 0; index_H < quan.get_value_H_size(); ++index_H)
387 {
388 if (vertex_write_mask_[vit->id().get()].at(index_H) >= 0)
389 {
390 writer << quan.get_values(*vit, index_H)[0] << " ";
391 }
392 }
393 writer << std::endl;
394 }
395 writer << std::endl;
396 writer << " </DataArray>" << std::endl;
397 writer << " </PointData>" << std::endl;
398 } //writePointData
399
412 };
413
415 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
416 void writeCellDataArray(DeviceType const & device,
417 SegmentType const & segment,
418 viennashe::config const & conf,
419 SHEQuantity const & quan,
420 std::ofstream & writer,
421 quantity_ids quan_id)
422 {
423 typedef typename viennagrid::result_of::const_cell_range<SegmentType>::type CellContainer;
424 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
425
426 std::string quantity_name = quan.get_name();
427 switch (quan_id)
428 {
429 case VIENNASHE_SHE_VTK_QUAN_GENERALIZED_DISTRIBUTION_FUNCTION: quantity_name += " (Generalized DF)"; break;
430 case VIENNASHE_SHE_VTK_QUAN_DISTRIBUTION_FUNCTION: quantity_name += " (DF)"; break;
431 case VIENNASHE_SHE_VTK_QUAN_DENSITY_OF_STATES: quantity_name += " (density of states)"; break;
432 case VIENNASHE_SHE_VTK_QUAN_GROUP_VELOCITY: quantity_name += " (group velocity)"; break;
433 case VIENNASHE_SHE_VTK_QUAN_KINETIC_ENERGY: quantity_name += " (kinetic energy)"; break;
434 case VIENNASHE_SHE_VTK_QUAN_EXPANSION_ORDER: quantity_name += " (expansion order)"; break;
435 case VIENNASHE_SHE_VTK_QUAN_UNKNOWN_INDEX: quantity_name += " (unknown index)"; break;
436 case VIENNASHE_SHE_VTK_QUAN_UNKNOWN_MASK: quantity_name += " (unknown mask)"; break;
437 case VIENNASHE_SHE_VTK_QUAN_UNKNOWN_NUM: quantity_name += " (unknown number)"; break;
438 default: throw std::runtime_error("Internal error: Unknown quan_id in she_vtk_writer::writeCellDataArray()");
439 }
440
441 typename viennashe::config::dispersion_relation_type dispersion = conf.dispersion_relation(quan.get_carrier_type_id());
442
443 writer << " <DataArray type=\"Float64\" Name=\"Generalized " << quantity_name << "\" format=\"ascii\">" << std::endl;
444
445 CellContainer cells(segment);
446
447 //write prisms:
448 for (std::size_t index_H = 0; index_H < quan.get_value_H_size() - 1; ++index_H)
449 {
450 double value = 0;
451 double dos;
452
453 for (CellIterator cit = cells.begin();
454 cit != cells.end();
455 ++cit)
456 {
457 if (!is_valid(device, quan, *cit, index_H))
458 continue;
459
460 switch (quan_id)
461 {
463 switch (conf.she_discretization_type())
464 {
466 dos = averaged_density_of_states(quan, dispersion, *cit, index_H);
467 value = quan.get_values(*cit, index_H)[0] * dos;
468 break;
470 value = quan.get_values(*cit, index_H)[0];
471 break;
472 }
473 break;
474
476 switch (conf.she_discretization_type())
477 {
479 value = quan.get_values(*cit, index_H)[0];
480 break;
482 dos = averaged_density_of_states(quan, dispersion, *cit, index_H);
483 value = (dos > 0) ? quan.get_values(*cit, index_H)[0] / dos : 0; //constant continuation of DF towards zero
484 break;
485 }
486 break;
487 case VIENNASHE_SHE_VTK_QUAN_DENSITY_OF_STATES: value = dispersion.density_of_states(quan.get_kinetic_energy(*cit, index_H)); break;
488 case VIENNASHE_SHE_VTK_QUAN_GROUP_VELOCITY: value = dispersion.velocity(quan.get_kinetic_energy(*cit, index_H)); break;
489 case VIENNASHE_SHE_VTK_QUAN_KINETIC_ENERGY: value = quan.get_kinetic_energy(*cit, index_H); break;
490 case VIENNASHE_SHE_VTK_QUAN_EXPANSION_ORDER: value = static_cast<double>(quan.get_expansion_order(*cit, index_H)); break;
491 case VIENNASHE_SHE_VTK_QUAN_UNKNOWN_INDEX: value = static_cast<double>(quan.get_unknown_index(*cit, index_H)); break;
492 case VIENNASHE_SHE_VTK_QUAN_UNKNOWN_MASK: value = static_cast<double>(quan.get_unknown_mask(*cit, index_H)); break;
493 case VIENNASHE_SHE_VTK_QUAN_UNKNOWN_NUM: value = static_cast<double>(quan.get_unknown_num(*cit, index_H)); break;
494 default: throw std::runtime_error("Internal error: Unknown quan_id in she_vtk_writer::writeCellDataArray()");
495 }
496
497 writer << value << " ";
498 }
499 writer << std::endl;
500 }
501 writer << " </DataArray>" << std::endl;
502 } //writeCellDataArray
503
505 template <typename DeviceType, typename SegmentType, typename SHEQuantity>
506 void writeCellData(DeviceType const & device,
507 SegmentType const & segment,
508 viennashe::config const & conf,
509 SHEQuantity const & quan,
510 std::ofstream & writer)
511 {
512 writer << " <CellData Scalars=\"scalars\">" << std::endl;
513
521 {
524 writeCellDataArray(device, segment, conf, quan, writer, VIENNASHE_SHE_VTK_QUAN_UNKNOWN_NUM);
525 }
526
527 writer << " </CellData>" << std::endl;
528 } //writeCellData
529
530 void writeFooter(std::ofstream & writer)
531 {
532 writer << " </UnstructuredGrid>" << std::endl;
533 writer << "</VTKFile>" << std::endl;
534 }
535
536 template <typename DeviceType, typename SegmentType>
537 bool segment_is_semiconductor_only(DeviceType const & device, SegmentType const & segment)
538 {
539 typedef typename viennagrid::result_of::const_cell_range<SegmentType>::type CellSegmentContainer;
540 typedef typename viennagrid::result_of::iterator<CellSegmentContainer>::type CellSegmentIterator;
541
542 CellSegmentContainer cells(segment);
543 for (CellSegmentIterator cit = cells.begin();
544 cit != cells.end();
545 ++cit)
546 {
548 return false;
549 }
550 return true;
551 }
552
553 template <typename DeviceType, typename SegmentType, typename SHEQuantityT>
554 void write_segment(DeviceType const & device,
555 SegmentType const & segment,
556 viennashe::config const & conf,
557 SHEQuantityT const & quan,
558 std::string filename)
559 {
560 std::ofstream writer(filename.c_str());
561
562 if (!writer)
563 throw cannot_open_file_exception(filename);
564
565 writeHeader(writer);
566
567 long cell_num = get_cell_num(device, segment, quan); //important: get_cell_num() prior to get_point_num()!!
568 long point_num = get_point_num(device, segment, quan);
569
570 writer << " <Piece NumberOfPoints=\""
571 << point_num
572 << "\" NumberOfCells=\""
573 << cell_num
574 << "\">" << std::endl;
575
576
577 writePoints(device, segment, quan, writer);
578 if ( (write_segments_ && segment_is_semiconductor_only(device, segment)) || !write_segments_)
579 writeCellData(device, segment, conf, quan, writer);
580 writeCells(device, segment, quan, writer);
581
582 writer << " </Piece>" << std::endl;
583
584 writeFooter(writer);
585
586 }
587
588 public:
589
590 she_vtk_writer() : write_segments_(false), with_debug_quantities_(false) {}
591
599 template <typename DeviceType, typename SHEQuantityT>
600 void operator()(DeviceType const & device,
601 viennashe::config const & conf,
602 SHEQuantityT const & quan,
603 std::string const & filename)
604 {
605 typedef typename viennagrid::result_of::segmentation<MeshType>::type SegmentationType;
606 typedef typename SegmentationType::segment_handle_type SegmentHandleType;
607
608 if (write_segments_)
609 {
610 //
611 // Step 1: Write meta information (pvd file)
612 //
613 std::stringstream ss;
614 ss << filename << "_main.pvd";
615 std::ofstream writer(ss.str().c_str());
616
617 std::string short_filename = filename;
618 std::string::size_type pos = filename.rfind("/");
619 if (pos == std::string::npos)
620 pos = filename.rfind("\\"); //A tribute to Windows
621
622 if (pos != std::string::npos)
623 short_filename = filename.substr(pos+1, filename.size());
624
625 writer << "<?xml version=\"1.0\"?>" << std::endl;
626 writer << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\" compressor=\"vtkZLibDataCompressor\">" << std::endl;
627 writer << "<Collection>" << std::endl;
628
629 for (typename SegmentationType::const_iterator it = device.segmentation().begin(); it != device.segmentation().end(); ++it)
630 {
631 SegmentHandleType const & seg = *it;
632 writer << " <DataSet part=\"" << seg.id() << "\" file=\"" << short_filename << "_" << seg.id() << ".vtu\" name=\"Segment_" << seg.id() << "\"/>" << std::endl;
633 }
634
635 writer << " </Collection>" << std::endl;
636 writer << "</VTKFile>" << std::endl;
637 writer.close();
638
639 //
640 // Step 2: Write each segment to a separate .vtu file:
641 //
642 for (typename SegmentationType::const_iterator it = device.segmentation().begin(); it != device.segmentation().end(); ++it)
643 {
644 SegmentHandleType const & seg = *it;
645
646 ss.str("");
647 ss << filename << "_" << seg.id() << ".vtu";
648 write_segment(device, *it, conf, quan, ss.str());
649 }
650 }
651 else
652 {
653 //
654 // Write full mesh to a single .vtu file:
655 //
656 write_segment(device, device.mesh(), conf, quan, filename + ".vtu");
657 }
658
659 }
660
661 bool write_segments() const { return write_segments_; }
662 void write_segments(bool b) { write_segments_ = b; }
663
664 bool with_debug_quantities() const { return with_debug_quantities_; }
665 void with_debug_quantities(bool b) { with_debug_quantities_ = b; }
666
667 private:
668 std::vector<viennashe::she_index_vector_type> vertex_write_mask_;
669 bool write_segments_;
670 bool with_debug_quantities_;
671
672 }; //she_vtk_writer
673
674
676
677
679 template < typename DeviceType >
680 class she_vtk_writer<DeviceType, viennagrid::cartesian_cs<3> >
681 {
682 public:
683 template <typename DataType>
684 void operator()(DeviceType const & device,
685 DataType const & data,
686 std::string const & filename, std::string name_in_file = "result")
687 {
688 (void)device; (void)data; (void)filename; (void)name_in_file;
689 log::warning() << "* she_vtk_writer::operator(): Cannot write distribution function for 3d devices. Skipping..." << std::endl;
690 }
691 };
692
700 template <typename QuantityType,
701 typename DeviceType>
702 void write_vertex_quantity_to_VTK_file(QuantityType const & quantity,
703 DeviceType const & device,
704 std::string filename,
705 std::string name_in_file = "viennashe_quantity")
706 {
707 typedef typename DeviceType::mesh_type MeshType;
708
709 typedef typename viennagrid::result_of::vertex<MeshType>::type VertexType;
710 typedef typename viennagrid::result_of::const_vertex_range<MeshType>::type VertexContainer;
711 typedef typename viennagrid::result_of::iterator<VertexContainer>::type VertexIterator;
712
713 MeshType const & mesh = device.mesh();
714
715 VertexContainer vertices(mesh);
716 std::vector<double> vtk_data(vertices.size());
717 for (VertexIterator vit = vertices.begin();
718 vit != vertices.end();
719 ++vit)
720 {
721 vtk_data[vit->id().get()] = quantity(*vit);
722 }
723
724 log::info<log_she_vtk_writer>() << "* write_quantity_to_VTK_file(): Writing data to '"
725 << filename
726 << "' (can be viewed with e.g. ParaView)" << std::endl;
727
728 viennagrid::io::vtk_writer<MeshType> my_vtk_writer;
729 my_vtk_writer.add_scalar_data_on_vertices(viennagrid::make_accessor<VertexType>(vtk_data), name_in_file);
730 my_vtk_writer(mesh, device.segmentation(), filename);
731 }
732
733
741 template <typename QuantityType,
742 typename DeviceType>
743 void write_cell_quantity_to_VTK_file(QuantityType const & quantity,
744 DeviceType const & device,
745 std::string filename,
746 std::string name_in_file = "viennashe_quantity")
747 {
748 typedef typename DeviceType::mesh_type MeshType;
749
750 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
751 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
752 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
753
754 MeshType const & mesh = device.mesh();
755
756 CellContainer cells(mesh);
757 std::vector<double> vtk_data(cells.size());
758 for (CellIterator cit = cells.begin();
759 cit != cells.end();
760 ++cit)
761 {
762 vtk_data[static_cast<std::size_t>(cit->id().get())] = quantity(*cit);
763 }
764
765 log::info<log_she_vtk_writer>() << "* write_quantity_to_VTK_file(): Writing data to '"
766 << filename
767 << "' (can be viewed with e.g. ParaView)" << std::endl;
768
769 viennagrid::io::vtk_writer<MeshType> my_vtk_writer;
770 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(vtk_data), name_in_file);
771 my_vtk_writer(mesh, device.segmentation(), filename);
772 }
773
774 namespace result_of
775 {
777 template <typename T>
778 struct topology_tag //by default, every quantity is assumed to write to a vertex.
779 {
780 typedef viennagrid::vertex_tag type;
781 };
782
783 template <typename DeviceType, typename TagT>
785 {
786 typedef TagT type;
787 };
788
789 }
790
792 namespace detail
793 {
794 template <typename QuantityType,
795 typename DeviceType>
796 void write_quantity_to_VTK_file(QuantityType const & quantity,
797 DeviceType const & device,
798 std::string filename,
799 std::string name_in_file,
800 viennagrid::vertex_tag)
801 {
802 write_cell_quantity_to_VTK_file(quantity, device, filename, name_in_file);
803 }
804
805 template <typename QuantityType,
806 typename DeviceType,
807 typename Tag>
808 void write_quantity_to_VTK_file(QuantityType const & quantity,
809 DeviceType const & device,
810 std::string filename,
811 std::string name_in_file,
812 Tag)
813 {
814 write_cell_quantity_to_VTK_file(quantity, device, filename, name_in_file);
815 }
816 }
817
822 template <typename QuantityType,
823 typename DeviceType>
824 void write_quantity_to_VTK_file(QuantityType const & quantity,
825 DeviceType const & device,
826 std::string filename,
827 std::string name_in_file = "viennashe_quantity")
828 {
829 write_cell_quantity_to_VTK_file(quantity, device, filename, name_in_file);
830 }
831
832
833
834 namespace detail
835 {
836 template <typename ContainerType, typename KeyType, typename ValueType>
838 {
839 public:
840 typedef ValueType value_type;
841
842 container_accessor(ContainerType const & container) : container_(container) {}
843
844 value_type const & operator()(KeyType const & key) const { cached_value_ = container_.at(static_cast<std::size_t>(key.id().get())); return cached_value_; }
845 value_type const & operator[](KeyType const & key) const { cached_value_ = container_.at(static_cast<std::size_t>(key.id().get())); return cached_value_; }
846 value_type const & at(KeyType const & key) const { cached_value_ = container_.at(static_cast<std::size_t>(key.id().get())); return cached_value_; }
847
848 value_type const * find(KeyType const &) const { return NULL; }
849 /*{
850 return &(container_[key.id().get()]);
851 }*/
852
853 private:
854 ContainerType const & container_;
855 mutable value_type cached_value_;
856 };
857
858 template <typename KeyType, typename ValueType, typename ContainerType>
860 {
862 }
863
864 } // namespace detail
865
867 template <typename DeviceType>
869 std::string filename,
870 bool include_debug_information = false)
871 {
872 typedef typename viennashe::simulator<DeviceType> SimulatorType;
873 typedef typename DeviceType::mesh_type MeshType;
874 typedef typename viennagrid::result_of::cell<MeshType>::type CellType;
875
876 typedef typename SimulatorType::unknown_quantity_type UnknownQuantityType;
877
878 DeviceType const & device = simulator_obj.device();
879
880 viennagrid::io::vtk_writer<MeshType> my_vtk_writer;
881
882 std::deque<std::vector<double> > electric_field(viennagrid::cells(device.mesh()).size(), std::vector<double>(3));
883 std::deque<std::vector<double> > current_n(viennagrid::cells(device.mesh()).size(), std::vector<double>(3));
884 std::deque<std::vector<double> > current_p(viennagrid::cells(device.mesh()).size(), std::vector<double>(3));
885 std::deque<std::vector<double> > carrier_velocity_n(viennagrid::cells(device.mesh()).size(), std::vector<double>(3));
886 std::deque<std::vector<double> > carrier_velocity_p(viennagrid::cells(device.mesh()).size(), std::vector<double>(3));
887 std::deque<double> pwr_density_container(viennagrid::cells(device.mesh()).size());
888 std::deque<double> avg_energy_n(viennagrid::cells(device.mesh()).size());
889 std::deque<double> avg_energy_p(viennagrid::cells(device.mesh()).size());
890 std::deque<double> avg_trap_occupancy(viennagrid::cells(device.mesh()).size());
891
892 //
893 // Device data
894 //
895 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(device.doping_n()), "Donator Doping");
896 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(device.doping_p()), "Acceptor Doping");
897 my_vtk_writer.add_scalar_data_on_cells( detail::make_accessor<CellType, double>(device.material()), "Material IDs");
898
899
900 //
901 // Simulator data
902 //
903 std::deque<UnknownQuantityType> const & unknown_quans = simulator_obj.quantity_history(0).unknown_quantities();
904
905 for (std::size_t quan_index = 0; quan_index < unknown_quans.size(); ++quan_index)
906 {
907 UnknownQuantityType const & quan = unknown_quans.at(quan_index);
908
909 bool quantity_is_from_she = false;
910
911 // electric field
912 if (quan.get_name() == viennashe::quantity::potential())
913 {
915 simulator_obj.quantities().potential(),
916 electric_field);
917 my_vtk_writer.add_vector_data_on_cells(viennagrid::make_accessor<CellType>(electric_field), "Electric Field");
918 }
919
920 // electron current
921 if (quan.get_name() == viennashe::quantity::electron_density())
922 {
924 {
925 quantity_is_from_she = true;
927 simulator_obj.config(),
929 current_n);
931 simulator_obj.config(),
933 carrier_velocity_n);
934 my_vtk_writer.add_vector_data_on_cells(viennagrid::make_accessor<CellType>(carrier_velocity_n), "Electron avg. carrier drift velocity");
936 simulator_obj.config(),
938 avg_energy_n);
939 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(avg_energy_n), "Electron avg. energy");
940 }
941 else
942 {
944 simulator_obj.potential(),
947 current_n);
948 }
949 my_vtk_writer.add_vector_data_on_cells(viennagrid::make_accessor<CellType>(current_n), "Electron current density");
950 }
951
952 // hole current
953 if (quan.get_name() == viennashe::quantity::hole_density())
954 {
955 if (simulator_obj.config().get_hole_equation() == viennashe::EQUATION_SHE)
956 {
957 quantity_is_from_she = true;
959 simulator_obj.config(),
960 simulator_obj.quantities().hole_distribution_function(),
961 current_p);
963 simulator_obj.config(),
964 simulator_obj.quantities().hole_distribution_function(),
965 carrier_velocity_p);
966 my_vtk_writer.add_vector_data_on_cells(viennagrid::make_accessor<CellType>(carrier_velocity_p), "Hole avg. carrier drift velocity");
968 simulator_obj.config(),
969 simulator_obj.quantities().hole_distribution_function(),
970 avg_energy_p);
971 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(avg_energy_p), "Hole avg. energy");
972 }
973 else
974 {
976 simulator_obj.potential(),
979 current_p);
980 }
981 my_vtk_writer.add_vector_data_on_cells(viennagrid::make_accessor<CellType>(current_p), "Hole current density");
982 }
983
984
985 // lattice temperature
986 if (quan.get_name() == viennashe::quantity::lattice_temperature())
987 {
988 typedef typename SimulatorType::SHETimeStepQuantitiesT QuantitiesType;
989 typedef typename viennashe::hde::power_density_accessor<DeviceType, QuantitiesType> PowerDensityAccessorType;
990
991 PowerDensityAccessorType pdacc(device,
992 simulator_obj.quantities(),
993 simulator_obj.config());
994
995 viennashe::write_macroscopic_quantity_to_container(device, pdacc, pwr_density_container);
996
997 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(pwr_density_container), "Joule heating power density");
998 }
999
1000
1001 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(quan.values()), quan.get_name());
1002 if (!quantity_is_from_she && include_debug_information)
1003 {
1004 my_vtk_writer.add_scalar_data_on_cells(detail::make_accessor<CellType, double>(quan.boundary_types()), quan.get_name() + " boundary types");
1005 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(quan.boundary_values()), quan.get_name() + " boundary values");
1006 my_vtk_writer.add_scalar_data_on_cells(detail::make_accessor<CellType, double>(quan.defined_but_unknown_mask()), quan.get_name() + " mask");
1007 my_vtk_writer.add_scalar_data_on_cells(detail::make_accessor<CellType, double>(quan.unknowns_indices()), quan.get_name() + " indices");
1008 }
1009 } // for unkown quans
1010
1011
1012 if (simulator_obj.config().with_traps())
1013 {
1014 typedef typename viennagrid::result_of::const_cell_range<MeshType>::type CellContainer;
1015 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator;
1016
1017 CellContainer cells(device.mesh());
1018 for (CellIterator cit = cells.begin();
1019 cit != cells.end();
1020 ++cit)
1021 {
1022 avg_trap_occupancy[static_cast<std::size_t>(cit->id().get())] = 0;
1023 // Average ...
1024 double ft = 0.0;
1025
1026 const std::size_t num_traps = simulator_obj.quantities().num_trap_unknown_indices(*cit);
1027
1028 if (num_traps == 0) continue;
1029
1030 for (std::size_t i = 0; i < num_traps; ++i)
1031 {
1032 ft += simulator_obj.quantities().trap_occupancy(*cit, i);
1033 }
1034
1035 ft = ft / num_traps;
1036 avg_trap_occupancy[static_cast<std::size_t>(cit->id().get())] = ft;
1037
1038 }
1039 my_vtk_writer.add_scalar_data_on_cells(viennagrid::make_accessor<CellType>(avg_trap_occupancy), "Average trap occupancy");
1040 } // traps
1041
1042 my_vtk_writer(device.mesh(), device.segmentation(), filename);
1043
1044 }
1045
1046 } //namespace io
1047} //namespace viennashe
1048
1049#endif
The main SHE configuration class. To be adjusted by the user for his/her needs.
Definition: config.hpp:124
viennashe::physics::dispersion_proxy dispersion_relation(viennashe::carrier_type_id ctype) const
Returns the dispersion relation for electrons.
Definition: config.hpp:266
equation_id get_electron_equation() const
Definition: config.hpp:230
equation_id get_hole_equation() const
Definition: config.hpp:238
bool with_traps() const
Returns true if traps are considered in the simulation.
Definition: config.hpp:243
she_discretization_type_id she_discretization_type() const
Definition: config.hpp:360
segmentation_type const & segmentation() const
Definition: device.hpp:156
long get_material(cell_type const &elem) const
Returns the material id of the provided cell.
Definition: device.hpp:502
std::vector< double > const & doping_p() const
Definition: device.hpp:431
std::vector< material_id_type > const & material() const
Definition: device.hpp:508
MeshT const & mesh() const
Returns the underlying mesh.
Definition: device.hpp:145
std::vector< double > const & doping_n() const
Definition: device.hpp:358
Defines the physical properties of a device, e.g. doping. This is the implementation for 2d and highe...
Definition: device.hpp:818
Power density accessor. Used to get the power density in the assembly of the heat diffusion equation.
Exception which is thrown if a file cannot be opened.
Definition: exception.hpp:38
value_type const & at(KeyType const &key) const
value_type const & operator[](KeyType const &key) const
container_accessor(ContainerType const &container)
value_type const & operator()(KeyType const &key) const
value_type const * find(KeyType const &) const
void operator()(DeviceType const &device, DataType const &data, std::string const &filename, std::string name_in_file="result")
void operator()(DeviceType const &device, viennashe::config const &conf, SHEQuantityT const &quan, std::string const &filename)
Triggers the write process.
void writePointData(DeviceType const &device, SegmentType const &segment, SHEQuantity const &quan, std::ofstream &writer, std::string name_in_file="result")
Implementation for writing the data (that is usually the energy distribution function) to the vertice...
long get_cell_num(DeviceType const &device, SegmentType const &segment, SHEQuantity const &quan)
Determines the number of cells in the output mesh in (x, H)-space.
viennagrid::result_of::point< MeshType >::type PointType
void writeCellDataArray(DeviceType const &device, SegmentType const &segment, viennashe::config const &conf, SHEQuantity const &quan, std::ofstream &writer, quantity_ids quan_id)
Writes data defined on cells to file.
void writeCells(DeviceType const &device, SegmentType const &segment, SHEQuantity const &quan, std::ofstream &writer)
Implementation for writing the cells in (x, H)-space (derived from a mesh in x-space)
viennagrid::result_of::cell< MeshType >::type CellType
void writeFooter(std::ofstream &writer)
SHEDeviceType::mesh_type MeshType
void writeCellData(DeviceType const &device, SegmentType const &segment, viennashe::config const &conf, SHEQuantity const &quan, std::ofstream &writer)
Writes data defined on cells to file.
viennagrid::result_of::vertex< MeshType >::type VertexType
void writePoints(DeviceType const &device, SegmentType const &segment, SHEQuantity const &quan, std::ofstream &writer)
Implementation for writing the vertex coordinates in (x, H)-space.
void write_segment(DeviceType const &device, SegmentType const &segment, viennashe::config const &conf, SHEQuantityT const &quan, std::string filename)
void writeHeader(std::ofstream &writer)
Writes the VTK XML file header for the unstructured grid file format.
bool segment_is_semiconductor_only(DeviceType const &device, SegmentType const &segment)
viennagrid::result_of::cell_tag< MeshType >::type CellTag
bool is_valid(DeviceType const &device, SHEQuantity const &quan, CellType const &cell, std::size_t index_H)
Checks whether a certain cell in x-space is inside the conduction band or the valence band at total e...
long get_point_num(DeviceType const &device, SegmentType const &segment, SHEQuantity const &quan)
Determines the number of vertices of the output mesh in (x, H)-space.
A proxy object for a dispersion relation. Does NOT take ownership of the provided pointer!
Definition: dispersion.hpp:69
double density_of_states(double ekin, double theta=0, double phi=0) const
Returns the density of states as a function of kinetic energy (and angles, eventually)
Definition: dispersion.hpp:75
double velocity(double ekin, double theta=0, double phi=0) const
Returns the velocity as a function of kinetic energy (and angles, eventually)
Definition: dispersion.hpp:82
UnknownSHEQuantityType const & electron_distribution_function() const
UnknownSHEQuantityType const & hole_distribution_function() const
std::deque< UnknownQuantityType > & unknown_quantities()
double trap_occupancy(CellType const &c, std::size_t inner_index) const
std::size_t num_trap_unknown_indices(CellType const &c) const
Returns the number of inner unknown indices (aka. degree of freedom - dof) for traps associated with ...
Class for self-consistent SHE simulations.
Definition: simulator.hpp:675
viennashe::config const & config() const
Returns the config object used by the simulator controller.
Definition: simulator.hpp:1210
SHETimeStepQuantitiesT const & quantity_history(std::size_t index) const
Returns a wrapper for the trap occupancy, which can be evaluated in every vertex of the mesh.
Definition: simulator.hpp:1194
DeviceType const & device() const
Definition: simulator.hpp:1213
SHETimeStepQuantitiesT const & quantities() const
Returns the controller object. Const version.
Definition: simulator.hpp:1139
potential_type potential() const
Returns a wrapper for the potential, which can be evaluated in every vertex of the mesh.
Definition: simulator.hpp:1167
A functor-style wrapper for a spatial quantity (typically potential, electron density or hole density...
Definition: misc.hpp:273
The SHE configuration class is defined here.
Computes the electric field from a potential.
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.
Miscellaneous utilities.
container_accessor< ContainerType, KeyType, ValueType > make_accessor(ContainerType const &c)
void write_quantity_to_VTK_file(QuantityType const &quantity, DeviceType const &device, std::string filename, std::string name_in_file, viennagrid::vertex_tag)
void write_vertex_quantity_to_VTK_file(QuantityType const &quantity, DeviceType const &device, std::string filename, std::string name_in_file="viennashe_quantity")
Convenience routine for writing a single macroscopic quantity to a VTK file.
void write_quantities_to_VTK_file(viennashe::simulator< DeviceType > const &simulator_obj, std::string filename, bool include_debug_information=false)
Generic interface function for writing simulated quantities to a VTK file.
void write_cell_quantity_to_VTK_file(QuantityType const &quantity, DeviceType const &device, std::string filename, std::string name_in_file="viennashe_quantity")
Convenience routine for writing a single macroscopic quantity to a VTK file.
void write_quantity_to_VTK_file(QuantityType const &quantity, DeviceType const &device, std::string filename, std::string name_in_file="viennashe_quantity")
Generic interface function for writing a quantity to a VTK file. Automatically dispatches between ver...
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
viennashe::models::dd::mobility< DeviceType > create_constant_mobility_model(DeviceType const &device, double mu)
Returns a mobility model, which always yields the same mobility.
Definition: mobility.hpp:61
std::string lattice_temperature()
std::string electron_density()
double averaged_density_of_states(SHEQuantity const &quan, viennashe::config::dispersion_relation_type const &dispersion, CellFacetType const &cell_facet, std::size_t index_H)
Returns the density of states around a vertex or an edge at total energy specified by index_H....
void write_kinetic_carrier_energy_to_container(DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, ContainerType &container)
Convenience function for writing the average kinetic carrier energy to the container provided.
void write_current_density_to_container(DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, ContainerType &container)
Convenience function for writing the current density to the container provided.
void write_carrier_velocity_to_container(DeviceType const &device, viennashe::config const &conf, SHEQuantity const &quan, ContainerType &container)
Convenience function for writing the average expansion order to the container provided.
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.
@ SHE_DISCRETIZATION_EVEN_ODD_ORDER_GENERALIZED_DF
Definition: forwards.h:146
@ SHE_DISCRETIZATION_EVEN_ODD_ORDER_DF
Definition: forwards.h:145
@ HOLE_TYPE_ID
Definition: forwards.h:188
@ ELECTRON_TYPE_ID
Definition: forwards.h:187
@ EQUATION_SHE
Definition: forwards.h:118
void write_electric_field_to_container(DeviceType const &device, PotentialAccessor const &potential, ContainerType &container)
Convenience function for writing the electric field to a container.
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.
Computes the current density (both Jn and Jp) after using a drift diffusion solution.
Convenience header, which includes all postprocessing quantities available.
Defines a generic simulator quantity for use within the solvers of ViennaSHE.
Meta function which translates element tags to VTK type identifiers (taking extra energy coordinate i...
T::ERROR_NO_SHE_VTK_WRITER_FOR_THIS_ELEMENT_TYPE_AVAILABLE error_type
Helper routine for extracting the ViennaGrid topology tag from a quantity wrapper....
Defines the log keys used within the viennashe::io namespace.