1/*
2 * VTKWriter_grids_util.hpp
3 *
4 * Created on: Aug 10, 2015
5 * Author: Pietro Incardona
6 */
7
8#ifndef SRC_VTKWRITER_GRIDS_UTIL_HPP_
9#define SRC_VTKWRITER_GRIDS_UTIL_HPP_
10
11#include "util/util_debug.hpp"
12#include "is_vtk_writable.hpp"
13#include "byteswap_portable.hpp"
14
15/*! \brief Return the Attributes name from the type
16 *
17 *
18 */
19template<typename ele_g, bool has_attributes>
20struct getAttrName
21{
22 /*! \brief Get attribute name
23 *
24 * \param i id of the attribute
25 * \param oprp post-fix to add
26 * \param prop_names properties name
27 *
28 * \return the string with the property name
29 *
30 */
31 static inline std::string get(size_t i, const openfpm::vector<std::string> & prop_names, const std::string & oprp)
32 {
33 return ele_g::value_type::value_type::attributes::name[i] + oprp;
34 }
35};
36
37/*! \brief Return the Attributes name from the type
38 *
39 * This is the case when the type has no name
40 *
41 */
42template<typename ele_g>
43struct getAttrName<ele_g,false>
44{
45 /*! \brief Get attribute name
46 *
47 * \param i id of the attribute
48 * \param oprp post-fix to add
49 * \param prop_names properties name
50 *
51 * \return return the string with the property name
52 *
53 */
54 static inline std::string get(size_t i, const openfpm::vector<std::string> & prop_names, const std::string & oprp)
55 {
56 if (i >= prop_names.size())
57 {
58 return std::string("attr" + std::to_string(i) + oprp);
59 }
60 else
61 {
62 return prop_names.get(i) + oprp;
63 }
64 }
65};
66
67/*! \brief Get the vtk properties header appending a prefix at the end
68 *
69 * \tparam has_attributes indicate if the properties have attributes name
70 * \param oprp prefix
71 *
72 */
73template<unsigned int i, typename ele_g, bool has_attributes> std::string get_point_property_header_impl(const std::string & oprp, const openfpm::vector<std::string> & prop_names)
74{
75 //! vertex node output string
76 std::string v_out;
77
78 typedef typename boost::mpl::at<typename ele_g::value_type::value_type::type,boost::mpl::int_<i>>::type ctype;
79
80 // Check if T is a supported format
81 // for now we support only scalar of native type
82 if (std::rank<ctype>::value == 1)
83 {
84 if (std::extent<ctype>::value <= 3)
85 {
86 //Get type of the property
87 std::string type = getType<typename std::remove_all_extents<ctype>::type>();
88
89 // if the type is not supported skip-it
90 if (type.size() == 0)
91 {
92#ifndef DISABLE_ALL_RTTI
93 std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the type " << demangle(typeid(ctype).name()) << " is not supported by vtk\n";
94#endif
95 return "";
96 }
97
98 // Create point data properties
99 v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
100 }
101 }
102 else
103 {
104 std::string type = getType<typename std::remove_all_extents<ctype>::type>();
105
106 // if the type is not supported return
107 if (type.size() == 0)
108 {
109 // We check if is a custom vtk writable object
110
111 if (is_vtk_writable<ctype>::value == true)
112 {
113 type = getType<typename vtk_type<ctype,is_custom_vtk_writable<ctype>::value>::type >();
114
115 // We check if it is a vector or scalar like type
116 if (vtk_dims<ctype>::value == 1)
117 v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
118 else
119 v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
120 }
121
122 return v_out;
123 }
124
125 // Create point data properties
126 v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
127
128 // Default lookup table
129 v_out += "LOOKUP_TABLE default\n";
130
131 }
132
133 // return the vertex list
134 return v_out;
135}
136
137/*! \brief Write the vectror property
138 *
139 * \tparam dim Dimensionality of the property
140 *
141 */
142template<unsigned int dim, typename T>
143class prop_write_out
144{
145public:
146
147 template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it, file_type ft)
148 {
149
150 if (ft == file_type::ASCII)
151 {
152 // Print the properties
153 for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++)
154 {
155 v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1)) + " ";
156 }
157 if (vtk_dims<T>::value == 2)
158 {
159 v_out += "0.0";
160 }
161 v_out += "\n";
162 }
163 else
164 {
165 typedef decltype(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(0)) ctype_;
166 typedef typename std::remove_reference<ctype_>::type ctype;
167
168 // Print the properties
169 for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++)
170 {
171 typename is_vtk_writable<ctype>::base tmp = vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1);
172 tmp = swap_endian_lt(tmp);
173 v_out.append((const char *)&tmp,sizeof(tmp));
174 }
175 if (vtk_dims<T>::value == 2)
176 {
177 typename is_vtk_writable<ctype>::base zero = 0.0;
178 zero = swap_endian_lt(zero);
179 v_out.append((const char *)&zero,sizeof(zero));
180 }
181 }
182 }
183};
184
185/*! \brief Write the scalar property
186 *
187 *
188 */
189template<typename T>
190class prop_write_out<1,T>
191{
192public:
193
194 /*! \brief Write the property
195 *
196 * \param v_out output string of the property
197 * \param vg vector of properties
198 * \param k data-set to output
199 * \param it iterator with the point to output
200 * \param ft output type BINARY or ASCII
201 *
202 */
203 template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it, file_type ft)
204 {
205 typedef decltype(vg.get(k).g.template get<I::value>(it.get())) ctype_;
206 typedef typename std::remove_const<typename std::remove_reference<ctype_>::type>::type ctype;
207
208 if (ft == file_type::ASCII)
209 {
210 // Print the property
211 v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())) + "\n";
212 }
213 else
214 {
215 typename is_vtk_writable<ctype>::base tmp = vg.get(k).g.template get<I::value>(it.get());
216 tmp = swap_endian_lt(tmp);
217 v_out.append((const char *)&tmp,sizeof(tmp));
218 }
219 }
220};
221
222
223/*! \brief This class is an helper to create properties output from scalar and compile-time array elements
224 *
225 * \tparam I It is an boost::mpl::int_ that indicate which property we are writing
226 * \tparam ele_g element type that store the grid information
227 * \tparam St type of space where the grid live
228 * \tparam T the type of the property
229 * \tparam is_writable flag that indicate if a property is writable
230 *
231 */
232template<typename I, typename ele_g, typename St, typename T, bool is_writable>
233struct meta_prop
234{
235 /*! \brief Write a vtk compatible type into vtk format
236 *
237 * \param vg array of elements to write
238 * \param v_out string containing the string
239 * \param prop_names property names
240 * \param ft ASCII or BINARY
241 *
242 */
243 inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft)
244 {
245 // actual string size
246 size_t sz = v_out.size();
247
248 // Produce the point properties header
249 v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names);
250
251 // If the output has changed, we have to write the properties
252 if (v_out.size() != sz)
253 {
254 // Produce point data
255
256 for (size_t k = 0 ; k < vg.size() ; k++)
257 {
258 //! Get a vertex iterator
259 auto it = vg.get(k).g.getIterator();
260
261 // if there is the next element
262 while (it.isNext())
263 {
264 prop_write_out<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_out,vg,k,it,ft);
265
266 // increment the iterator and counter
267 ++it;
268 }
269 }
270
271 if (ft == file_type::BINARY)
272 v_out += "\n";
273 }
274 }
275};
276
277//! Partial specialization for N=1 1D-Array
278template<typename I, typename ele_g, typename St, typename T, size_t N1, bool is_writable>
279struct meta_prop<I, ele_g,St,T[N1],is_writable>
280{
281 /*! \brief Write a vtk compatible type into vtk format
282 *
283 * \param vg array of elements to write
284 * \param v_out string containing the string
285 * \param prop_names properties name
286 * \param ft ASCII or BINARY
287 *
288 */
289 inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names , file_type ft)
290 {
291 // actual string size
292 size_t sz = v_out.size();
293
294 // Produce the point properties header
295 v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("",prop_names);
296
297 // If the output has changed, we have to write the properties
298 if (v_out.size() != sz)
299 {
300 // Produce point data
301
302 for (size_t k = 0 ; k < vg.size() ; k++)
303 {
304 //! Get a vertex iterator
305 auto it = vg.get(k).g.getIterator();
306
307 // if there is the next element
308 while (it.isNext())
309 {
310 if (ft == file_type::ASCII)
311 {
312 // Print the properties
313 for (size_t i1 = 0 ; i1 < N1 ; i1++)
314 {v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1]) + " ";}
315
316 if (N1 == 2)
317 {v_out += std::to_string((decltype(vg.get(k).g.template get<I::value>(it.get())[0])) 0);}
318
319 v_out += "\n";
320 }
321 else
322 {
323 T tmp;
324
325 // Print the properties
326 for (size_t i1 = 0 ; i1 < N1 ; i1++)
327 {
328 tmp = vg.get(k).g.template get<I::value>(it.get())[i1];
329 tmp = swap_endian_lt(tmp);
330 v_out.append((const char *)&tmp,sizeof(T));
331 }
332 if (N1 == 2)
333 {
334 tmp = 0.0;
335 tmp = swap_endian_lt(tmp);
336 v_out.append((const char *)&tmp,sizeof(T));
337 }
338 }
339
340 // increment the iterator and counter
341 ++it;
342 }
343 }
344 if (ft == file_type::BINARY)
345 {v_out += "\n";}
346 }
347 }
348};
349
350//! Partial specialization for N=2 2D-Array
351template<typename I, typename ele_g, typename St ,typename T,size_t N1,size_t N2, bool is_writable>
352struct meta_prop<I, ele_g,St, T[N1][N2],is_writable>
353{
354
355 /*! \brief Write a vtk compatible type into vtk format
356 *
357 * \param vg array of elements to write
358 * \param v_out string containing the string
359 * \param prop_names property names
360 * \param ft ASCII or BINARY
361 *
362 */
363 inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft)
364 {
365 for (size_t i1 = 0 ; i1 < N1 ; i1++)
366 {
367 for (size_t i2 = 0 ; i2 < N2 ; i2++)
368 {
369 // actual string size
370 size_t sz = v_out.size();
371
372 // Produce the point properties header
373 v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("_" + std::to_string(i1) + "_" + std::to_string(i2),prop_names);
374
375 // If the output has changed, we have to write the properties
376 if (v_out.size() != sz)
377 {
378 // Produce point data
379
380 for (size_t k = 0 ; k < vg.size() ; k++)
381 {
382 //! Get a vertex iterator
383 auto it = vg.get(k).g.getIterator();
384
385 // if there is the next element
386 while (it.isNext())
387 {
388 T tmp;
389
390 if (ft == file_type::ASCII)
391 {
392 // Print the property
393 v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1][i2]) + "\n";
394 }
395 else
396 {
397 tmp = vg.get(k).g.template get<I::value>(it.get())[i1][i2];
398 tmp = swap_endian_lt(tmp);
399 v_out.append((const char *)&tmp,sizeof(tmp));
400 }
401
402 // increment the iterator and counter
403 ++it;
404 }
405 }
406
407 if (ft == file_type::BINARY)
408 v_out += "\n";
409 }
410 }
411 }
412 }
413};
414
415
416//! Specialication when is not writable
417template<typename I, typename ele_g, typename St, typename T>
418struct meta_prop<I,ele_g,St,T,false>
419{
420
421 /*! \brief Write a vtk compatible type into vtk format
422 *
423 * \param vg array of elements to write
424 * \param v_out string containing the string
425 * \param prop_names properties name
426 * \param ft ASCII or BINARY
427 *
428 */
429 inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft)
430 {
431 }
432};
433
434template<unsigned int dims,typename T> inline void output_point(Point<dims,T> & p,std::stringstream & v_out, file_type ft)
435{
436 if (ft == file_type::ASCII)
437 {
438 v_out << p.toString();
439 size_t i = dims;
440 for ( ; i < 3 ; i++)
441 {v_out << " 0.0";}
442 v_out << "\n";
443 }
444 else
445 {
446 size_t i = 0;
447 for ( ; i < dims ; i++)
448 {
449 // we use float so we have to convert to float
450 auto tmp = p.get(i);
451 tmp = swap_endian_lt(tmp);
452 v_out.write((const char *)&tmp,sizeof(tmp));
453 }
454 for ( ; i < 3 ; i++)
455 {
456 // we use float so we have to convert to float
457
458 /* coverity[dead_error_begin] */
459 T tmp = 0.0;
460 tmp = swap_endian_lt(tmp);
461 v_out.write((const char *)&tmp,sizeof(tmp));
462 }
463 }
464}
465
466inline void output_vertex(size_t k,std::string & v_out, file_type ft)
467{
468 if (ft == file_type::ASCII)
469 {v_out += "1 " + std::to_string(k) + "\n";}
470 else
471 {
472 int tmp;
473 tmp = 1;
474 tmp = swap_endian_lt(tmp);
475 v_out.append((const char *)&tmp,sizeof(int));
476 tmp = k;
477 tmp = swap_endian_lt(tmp);
478 v_out.append((const char *)&tmp,sizeof(int));
479 }
480}
481
482#endif /* SRC_VTKWRITER_GRIDS_UTIL_HPP_ */
483