OpenFPM_io  0.2.0
Project that contain the implementation and interfaces for basic structure like vectors, grids, graph ... .
 All Data Structures Functions Variables Typedefs
VTKWriter_grids_st.hpp
1 /*
2  * VTKWriter_grids_st.hpp
3  *
4  * Created on: Sep 3, 2015
5  * Author: Pietro Incardona
6  */
7 
8 #ifndef SRC_VTKWRITER_GRIDS_ST_HPP_
9 #define SRC_VTKWRITER_GRIDS_ST_HPP_
10 
11 
12 #include <boost/mpl/pair.hpp>
13 #include "VTKWriter_grids_util.hpp"
14 #include "util/util_debug.hpp"
15 #include "util/convert.hpp"
16 
22 template <typename Grid>
23 struct cell_grid
24 {
25  // vector of fused grids
26  openfpm::vector<const Grid *> grids;
27 
28  // combination
29  comb<Grid::dims> cmb;
30 
31  cell_grid() {}
32 
34  cell_grid(const comb<Grid::dims> & cmb)
35  :cmb(cmb)
36  {}
37 
38  cell_grid(const cell_grid<Grid> & cg)
39  {
40  this->operator=(cg);
41  }
42 
44  {
45  this->operator=(cg);
46  }
47 
56  {
57  cmb = cg.cmb;
58  grids = cg.grids;
59 
60  return *this;
61  }
62 
71  {
72  cmb = cg.cmb;
73  grids = cg.grids;
74 
75  return *this;
76  }
77 };
78 
79 template <typename Grid, typename St>
80 class ele_g_st
81 {
82 public:
83 
84  typedef Grid value_type;
85 
86  ele_g_st(){};
87 
88  ele_g_st(const Point<Grid::dims,St> & offset, const Point<Grid::dims,St> & spacing, const Box<Grid::dims,St> & dom)
89  :offset(offset),spacing(spacing),dom(dom)
90  {}
91 
92  std::string dataset;
94  openfpm::vector<cell_grid<Grid>> g;
96  Point<Grid::dims,St> offset;
97  // spacing of the grid
98  Point<Grid::dims,St> spacing;
99  // Part of the grid that is real domain
100  Box<Grid::dims,size_t> dom;
101 
103  inline ele_g_st(const ele_g_st & ele)
104  {
105  this->operator=(ele);
106  }
107 
109  inline ele_g_st(ele_g_st && ele)
110  {
111  this->operator=(ele);
112  }
113 
120  {
121  dataset = ele.dataset;
122  g = ele.g;
123  offset = ele.offset;
124  spacing = ele.spacing;
125  dom = ele.dom;
126 
127  return *this;
128  }
129 
136  {
137  dataset = ele.dataset;
138  g = ele.g;
139  offset = ele.offset;
140  spacing = ele.spacing;
141  dom = ele.dom;
142 
143  return *this;
144  }
145 };
146 
156 template <typename pair>
157 class VTKWriter<pair,VECTOR_ST_GRIDS>
158 {
160  openfpm::vector< ele_g_st<typename pair::first,typename pair::second> > vg;
161 
167  size_t get_total()
168  {
169  size_t tot = 0;
170 
172  for (size_t i = 0 ; i < vg.size() ; i++)
173  {
174  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
175  {
176  if (vg.get(i).g.get(j).grids.size() != 0)
177  tot += vg.get(i).g.get(j).grids.get(0)->size();
178  }
179  }
180  return tot;
181  }
182 
192  {
194  std::string v_out;
195 
196  // write the number of vertex
197  v_out += "VERTICES " + std::to_string(get_total()) + " " + std::to_string(get_total() * 2) + "\n";
198 
199  // return the vertex properties string
200  return v_out;
201  }
202 
212  {
214  std::string v_out;
215 
216  // write the number of vertex
217  v_out += "POINTS " + std::to_string(get_total()) + " float" + "\n";
218 
219  // return the vertex properties string
220  return v_out;
221  }
222 
226  std::string get_point_list()
227  {
229  std::stringstream v_out;
230 
232  for (size_t i = 0 ; i < vg.size() ; i++)
233  {
234  // For each position in the cell
235  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
236  {
237  // If there are no grid in this position
238  if (vg.get(i).g.get(j).grids.size() == 0)
239  continue;
240 
242  auto it = vg.get(i).g.get(j).grids.get(0)->getIterator();
243 
245  Box<pair::first::dims,typename pair::second> dom;
246 
247  // Calculate the offset of the grid considering its cell position
248  Point<pair::first::dims,typename pair::second> middle = vg.get(i).spacing / 2;
249  Point<pair::first::dims,typename pair::second> one;
250  one.one();
251  one = one + toPoint<pair::first::dims,typename pair::second>::convert(vg.get(i).g.get(j).cmb);
252  Point<pair::first::dims,typename pair::second> offset = middle * one + vg.get(i).offset;
253 
254  // if there is the next element
255  while (it.isNext())
256  {
257  Point<pair::first::dims,typename pair::second> p;
258  p = it.get().toPoint();
259  p = p * vg.get(i).spacing + offset;
260 
261  if (pair::first::dims == 2)
262  v_out << p.toString() << " 0.0" << "\n";
263  else
264  v_out << p.toString() << "\n";
265 
266  // increment the iterator
267  ++it;
268  }
269  }
270  }
271 
272  // return the vertex list
273  return v_out.str();
274  }
275 
276  /* \brief Get the properties components
277  *
278  * \return the components printed
279  *
280  */
281  std::string get_prop_components(size_t k)
282  {
283  std::stringstream v_out;
284 
286  for (size_t i = 0 ; i < vg.size() ; i++)
287  {
288  // For each position in the cell
289  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
290  {
291  if (k < vg.get(i).g.get(j).grids.size())
292  {
293  // get the combination string
294  v_out << vg.get(i).g.get(j).cmb.to_string();
295  }
296  }
297  }
298 
299  return v_out.str();
300  }
301 
308  std::string get_properties_output(size_t k, std::string prop_name)
309  {
311  std::stringstream v_out;
312 
313  // Check if T is a supported format
314  // for now we support only scalar of native type
315 
316  typedef typename boost::mpl::at<typename pair::first::value_type::type,boost::mpl::int_<0>>::type ctype;
317 
318  std::string type = getType<ctype>();
319 
320  // if the type is not supported return
321  if (type.size() == 0)
322  {
323  std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the type " << demangle(typeid(ctype).name()) << " is not supported by vtk\n";
324  return "";
325  }
326 
327  std::string prp_cp = get_prop_components(k);
328 
329  // Create point data properties
330  v_out << "SCALARS " << prop_name << "_" << prp_cp << " " << type + "\n";
331 
332  // Default lookup table
333  v_out << "LOOKUP_TABLE default\n";
334 
336  for (size_t i = 0 ; i < vg.size() ; i++)
337  {
338  // For each position in the cell
339  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
340  {
341  // If there are no grid in this position
342  if (vg.get(i).g.get(j).grids.size() == 0)
343  continue;
344 
345  if (k < vg.get(i).g.get(j).grids.size())
346  {
347  // Grid source
348  auto & g_src = *vg.get(i).g.get(j).grids.get(k);
349 
351  auto it = g_src.getIterator();
352 
354  Box<pair::first::dims,typename pair::second> dom;
355 
356  // if there is the next element
357  while (it.isNext())
358  {
359  auto key = it.get();
360 
361  v_out << std::to_string(g_src.template get<0>(key)) << "\n";
362 
363  // increment the iterator
364  ++it;
365  }
366  }
367  else
368  {
369  // Grid source
370  auto & g_src = *vg.get(i).g.get(j).grids.get(0);
371 
373  auto it = g_src.getIterator();
374 
376  Box<pair::first::dims,typename pair::second> dom;
377 
378  // if there is the next element
379  while (it.isNext())
380  {
381  v_out << "0\n";
382 
383  // increment the iterator
384  ++it;
385  }
386  }
387  }
388  }
389 
390  // return the vertex list
391  return v_out.str();
392  }
393 
399  std::string lastProp()
400  {
402  std::stringstream v_out;
403 
404  // Create point data properties
405  v_out << "SCALARS domain float\n";
406 
407  // Default lookup table
408  v_out << "LOOKUP_TABLE default\n";
409 
411  for (size_t i = 0 ; i < vg.size() ; i++)
412  {
413  // For each position in the cell
414  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
415  {
416  // If there are no grid in this position
417  if (vg.get(i).g.get(j).grids.size() == 0)
418  continue;
419 
421  auto it = vg.get(i).g.get(j).grids.get(0)->getIterator();
422 
423  // if there is the next element
424  while (it.isNext())
425  {
426  if (vg.get(i).dom.isInside(it.get().toPoint()) == true)
427  v_out << "1.0\n";
428  else
429  v_out << "0.0\n";
430 
431  // increment the iterator and counter
432  ++it;
433  }
434  }
435  }
436 
437  return v_out.str();
438  }
439 
445  size_t getMaxFused()
446  {
447  size_t max = 0;
448 
450  for (size_t i = 0 ; i < vg.size() ; i++)
451  {
452  // For each position in the cell
453  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
454  {
455  // If there are no grid in this position
456  if (vg.get(i).g.get(j).grids.size() > max)
457  max = vg.get(i).g.get(j).grids.size();
458  }
459  }
460 
461  return max;
462  }
463 
467  std::string get_vertex_list()
468  {
470  std::string v_out;
471 
472  size_t k = 0;
473 
475  for (size_t i = 0 ; i < vg.size() ; i++)
476  {
477  // For each position in the cell
478  for (size_t j = 0 ; j < vg.get(i).g.size() ; j++)
479  {
480  // If there are no grid in this position
481  if (vg.get(i).g.get(j).grids.size() == 0)
482  continue;
484  auto it = vg.get(i).g.get(j).grids.get(0)->getIterator();
485 
486  while (it.isNext())
487  {
488  v_out += "1 " + std::to_string(k) + "\n";
489 
490  ++k;
491  ++it;
492  }
493  }
494  }
495  // return the vertex list
496  return v_out;
497  }
498 
505  std::string get_point_data_header()
506  {
507  std::string v_out;
508 
509  v_out += "POINT_DATA " + std::to_string(get_total()) + "\n";
510 
511  return v_out;
512  }
513 
523  void append_grid(size_t id, const typename pair::first & g, const comb<pair::first::dims> & cmb)
524  {
525  for(size_t i = 0 ; i < vg.get(id).g.size() ; i++)
526  {
527  // for each defined grid if exist the combination fuse
528  if (cmb == vg.get(id).g.get(i).cmb)
529  {
530  vg.get(id).g.get(i).grids.add(&g);
531  return;
532  }
533  }
534 
535  // if the combination does not exist add the grid
537  vg.get(id).g.add(cg);
538  vg.get(id).g.last().grids.add(&g);
539  }
540 
541 public:
542 
549  {}
550 
560  void add(size_t i, const typename pair::first & g, const Point<pair::first::dims,typename pair::second> & offset, const Point<pair::first::dims,typename pair::second> & spacing, const Box<pair::first::dims,typename pair::second> & dom, const comb<pair::first::dims> & cmb)
561  {
563  if (i >= vg.size())
564  vg.resize(i+1);
565 
566  vg.get(i).offset = offset;
567  vg.get(i).spacing = spacing;
568  vg.get(i).dom = dom;
569 
570  // append the grid
571  append_grid(i,g,cmb);
572  }
573 
584  template<int prp = -1> bool write(std::string file, std::string g_name = "grids" , file_type ft = file_type::ASCII)
585  {
586  // Header for the vtk
587  std::string vtk_header;
588  // Point list of the VTK
589  std::string point_list;
590  // Vertex list of the VTK
591  std::string vertex_list;
592  // Graph header
593  std::string vtk_binary_or_ascii;
594  // vertex properties header
595  std::string point_prop_header;
596  // edge properties header
597  std::string vertex_prop_header;
598  // Data point header
599  std::string point_data_header;
600  // Data point
601  std::string point_data;
602 
603  // VTK header
604  vtk_header = "# vtk DataFile Version 3.0\n"
605  + g_name + "\n";
606 
607  // Choose if binary or ASCII
608  if (ft == file_type::ASCII)
609  {vtk_header += "ASCII\n";}
610  else
611  {vtk_header += "BINARY\n";}
612 
613  // Data type for graph is DATASET POLYDATA
614  vtk_header += "DATASET POLYDATA\n";
615 
616  // point properties header
617  point_prop_header = get_point_properties_list();
618 
619  // Get point list
620  point_list = get_point_list();
621 
622  // vertex properties header
623  vertex_prop_header = get_vertex_properties_list();
624 
625  // Get vertex list
626  vertex_list = get_vertex_list();
627 
628  // Get the point data header
629  point_data_header = get_point_data_header();
630 
631  // Get the maximum number of fused grids
632  size_t mf = getMaxFused();
633 
634  // For each property in the vertex type produce a point data
635  for (size_t i = 0 ; i < mf ; i++)
636  point_data += get_properties_output(i,g_name);
637 
638  lastProp();
639 
640 
641  // write the file
642  std::ofstream ofs(file);
643 
644  // Check if the file is open
645  if (ofs.is_open() == false)
646  {std::cerr << "Error cannot create the VTK file: " + file + "\n";}
647 
648  ofs << vtk_header << point_prop_header << point_list <<
649  vertex_prop_header << vertex_list << point_data_header << point_data;
650 
651  // Close the file
652 
653  ofs.close();
654 
655  // Completed succefully
656  return true;
657  }
658 };
659 
660 
661 #endif /* SRC_VTKWRITER_GRIDS_ST_HPP_ */
openfpm::vector< cell_grid< Grid > > g
fused grids
ele_g_st< Grid, St > & operator=(ele_g_st &&ele)
Copy the object.
std::string get_point_list()
Create the VTK point definition.
std::string get_point_data_header()
Get the point data header.
std::string get_point_properties_list()
It get the vertex properties list.
size_t get_total()
Get the total number of points.
void add(size_t i, const typename pair::first &g, const Point< pair::first::dims, typename pair::second > &offset, const Point< pair::first::dims, typename pair::second > &spacing, const Box< pair::first::dims, typename pair::second > &dom, const comb< pair::first::dims > &cmb)
Add grid dataset.
ele_g_st< Grid, St > & operator=(const ele_g_st &ele)
Copy the object.
size_t getMaxFused()
Get the maximum number of fused grid.
cell_grid< Grid > & operator=(cell_grid< Grid > &&cg)
Copy the cell grid.
for each combination in the cell grid you can have different grids
std::string get_vertex_list()
Create the VTK vertex definition.
Point< Grid::dims, St > offset
offset where it start
cell_grid(const comb< Grid::dims > &cmb)
construct a cell grid
std::string lastProp()
Return the output of the domain property.
void append_grid(size_t id, const typename pair::first &g, const comb< pair::first::dims > &cmb)
Append the grid to the sub-domain, if for a sub-domain we have a grid that is overlapping fuse them...
openfpm::vector< ele_g_st< typename pair::first, typename pair::second > > vg
Vector of grids.
ele_g_st(ele_g_st &&ele)
Copy constructor.
std::string get_properties_output(size_t k, std::string prop_name)
Create the VTK properties output.
ele_g_st(const ele_g_st &ele)
Copy constructor.
std::string get_vertex_properties_list()
It get the vertex properties list.
bool write(std::string file, std::string g_name="grids", file_type ft=file_type::ASCII)
It write a VTK file from a graph.
cell_grid< Grid > & operator=(const cell_grid< Grid > &cg)
Copy the cell grid.