VTKWriter_grids_util.hpp 12.6 KB
Newer Older
incardon's avatar
incardon committed
1
2
3
4
/*
 * VTKWriter_grids_util.hpp
 *
 *  Created on: Aug 10, 2015
incardon's avatar
incardon committed
5
 *      Author: Pietro Incardona
incardon's avatar
incardon committed
6
7
8
9
10
 */

#ifndef SRC_VTKWRITER_GRIDS_UTIL_HPP_
#define SRC_VTKWRITER_GRIDS_UTIL_HPP_

incardon's avatar
incardon committed
11
#include "util/util_debug.hpp"
Pietro Incardona's avatar
Pietro Incardona committed
12
#include "is_vtk_writable.hpp"
incardon's avatar
incardon committed
13
#include "byteswap_portable.hpp"
incardon's avatar
incardon committed
14

15
/*! \brief Return the Attributes name from the type
incardon's avatar
incardon committed
16
17
18
 *
 *
 */
Pietro Incardona's avatar
Pietro Incardona committed
19
20
template<typename ele_g, bool has_attributes>
struct getAttrName
incardon's avatar
incardon committed
21
{
Pietro Incardona's avatar
Pietro Incardona committed
22
23
24
25
	/*! \brief Get attribute name
	 *
	 * \param i id of the attribute
	 * \param oprp post-fix to add
26
27
28
	 * \param prop_names properties name
	 *
	 * \return the string with the property name
Pietro Incardona's avatar
Pietro Incardona committed
29
30
	 *
	 */
31
	static inline std::string get(size_t i, const openfpm::vector<std::string> & prop_names, const std::string & oprp)
Pietro Incardona's avatar
Pietro Incardona committed
32
33
34
35
	{
		return ele_g::value_type::value_type::attributes::name[i] + oprp;
	}
};
incardon's avatar
incardon committed
36

37
38
39
40
41
/*! \brief Return the Attributes name from the type
 *
 * This is the case when the type has no name
 *
 */
Pietro Incardona's avatar
Pietro Incardona committed
42
43
44
45
template<typename ele_g>
struct getAttrName<ele_g,false>
{
	/*! \brief Get attribute name
incardon's avatar
incardon committed
46
	 *
Pietro Incardona's avatar
Pietro Incardona committed
47
48
	 * \param i id of the attribute
	 * \param oprp post-fix to add
49
50
51
	 * \param  prop_names properties name
	 *
	 * \return return the string with the property name
incardon's avatar
incardon committed
52
53
	 *
	 */
54
	static inline std::string get(size_t i, const openfpm::vector<std::string> & prop_names, const std::string & oprp)
Pietro Incardona's avatar
Pietro Incardona committed
55
	{
56
57
58
59
60
61
62
63
		if (i >= prop_names.size())
		{
			return std::string("attr" + std::to_string(i) + oprp);
		}
		else
		{
			return prop_names.get(i) + oprp;
		}
Pietro Incardona's avatar
Pietro Incardona committed
64
65
66
67
68
69
70
71
72
	}
};

/*! \brief Get the vtk properties header appending a prefix at the end
 *
 * \tparam has_attributes indicate if the properties have attributes name
 * \param oprp prefix
 *
 */
73
template<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)
Pietro Incardona's avatar
Pietro Incardona committed
74
75
76
77
78
79
80
81
82
{
	//! vertex node output string
	std::string v_out;

	typedef typename boost::mpl::at<typename ele_g::value_type::value_type::type,boost::mpl::int_<i>>::type ctype;

	// Check if T is a supported format
	// for now we support only scalar of native type
	if (std::rank<ctype>::value == 1)
incardon's avatar
incardon committed
83
	{
84
		if (std::extent<ctype>::value <= 3)
incardon's avatar
incardon committed
85
		{
86
87
88
89
90
91
			//Get type of the property
			std::string type = getType<typename std::remove_all_extents<ctype>::type>();

			// if the type is not supported skip-it
			if (type.size() == 0)
			{
incardon's avatar
incardon committed
92
#ifndef DISABLE_ALL_RTTI
93
				std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the type " << demangle(typeid(ctype).name()) << " is not supported by vtk\n";
incardon's avatar
incardon committed
94
#endif
95
96
				return "";
			}
incardon's avatar
incardon committed
97

98
			// Create point data properties
99
			v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
100
		}
Pietro Incardona's avatar
Pietro Incardona committed
101
102
103
104
105
106
107
108
109
110
111
	}
	else
	{
		std::string type = getType<typename std::remove_all_extents<ctype>::type>();

		// if the type is not supported return
		if (type.size() == 0)
		{
			// We check if is a custom vtk writable object

			if (is_vtk_writable<ctype>::value == true)
incardon's avatar
incardon committed
112
			{
Pietro Incardona's avatar
Pietro Incardona committed
113
				type = getType<typename vtk_type<ctype,is_custom_vtk_writable<ctype>::value>::type >();
incardon's avatar
incardon committed
114

Pietro Incardona's avatar
Pietro Incardona committed
115
116
				// We check if it is a vector or scalar like type
				if (vtk_dims<ctype>::value == 1)
117
					v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
Pietro Incardona's avatar
Pietro Incardona committed
118
				else
119
					v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
incardon's avatar
incardon committed
120
			}
Pietro Incardona's avatar
Pietro Incardona committed
121
122

			return v_out;
incardon's avatar
incardon committed
123
124
		}

Pietro Incardona's avatar
Pietro Incardona committed
125
		// Create point data properties
126
		v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,prop_names,oprp) + " " + type + "\n";
Pietro Incardona's avatar
Pietro Incardona committed
127
128
129
130

		// Default lookup table
		v_out += "LOOKUP_TABLE default\n";

incardon's avatar
incardon committed
131
132
	}

Pietro Incardona's avatar
Pietro Incardona committed
133
134
135
136
137
138
139
140
141
142
143
144
145
	// return the vertex list
	return v_out;
}

/*! \brief Write the vectror property
 *
 * \tparam dim Dimensionality of the property
 *
 */
template<unsigned int dim, typename T>
class prop_write_out
{
public:
incardon's avatar
incardon committed
146

incardon's avatar
incardon committed
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)
Pietro Incardona's avatar
Pietro Incardona committed
148
	{
incardon's avatar
incardon committed
149

incardon's avatar
incardon committed
150
		if (ft == file_type::ASCII)
Pietro Incardona's avatar
Pietro Incardona committed
151
		{
incardon's avatar
incardon committed
152
153
154
155
156
157
158
159
160
161
			// Print the properties
			for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++)
			{
				v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1)) + " ";
			}
			if (vtk_dims<T>::value == 2)
			{
				v_out += "0.0";
			}
			v_out += "\n";
incardon's avatar
incardon committed
162
		}
incardon's avatar
incardon committed
163
		else
164
		{
incardon's avatar
incardon committed
165
166
167
			typedef decltype(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(0)) ctype_;
			typedef typename std::remove_reference<ctype_>::type ctype;

incardon's avatar
incardon committed
168
169
170
			// Print the properties
			for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++)
			{
incardon's avatar
incardon committed
171
				typename is_vtk_writable<ctype>::base tmp = vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1);
incardon's avatar
incardon committed
172
173
174
175
176
				tmp = swap_endian_lt(tmp);
				v_out.append((const char *)&tmp,sizeof(tmp));
			}
			if (vtk_dims<T>::value == 2)
			{
incardon's avatar
incardon committed
177
				typename is_vtk_writable<ctype>::base zero = 0.0;
incardon's avatar
incardon committed
178
179
180
				zero = swap_endian_lt(zero);
				v_out.append((const char *)&zero,sizeof(zero));
			}
181
		}
incardon's avatar
incardon committed
182
	}
Pietro Incardona's avatar
Pietro Incardona committed
183
};
incardon's avatar
incardon committed
184

Pietro Incardona's avatar
Pietro Incardona committed
185
186
187
188
189
190
191
192
/*! \brief Write the scalar property
 *
 *
 */
template<typename T>
class prop_write_out<1,T>
{
public:
incardon's avatar
incardon committed
193

194
195
196
197
198
199
200
201
202
	/*! \brief Write the property
	 *
	 *  \param v_out output string of the property
	 *  \param vg vector of properties
	 *  \param k data-set to output
	 *  \param it iterator with the point to output
	 *  \param ft output type BINARY or ASCII
	 *
	 */
incardon's avatar
incardon committed
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)
incardon's avatar
incardon committed
204
	{
incardon's avatar
incardon committed
205
206
		typedef decltype(vg.get(k).g.template get<I::value>(it.get())) ctype_;
		typedef typename std::remove_const<typename std::remove_reference<ctype_>::type>::type ctype;
incardon's avatar
incardon committed
207

incardon's avatar
incardon committed
208
209
210
		if (ft == file_type::ASCII)
		{
			// Print the property
incardon's avatar
incardon committed
211
			v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())) + "\n";
incardon's avatar
incardon committed
212
213
214
		}
		else
		{
incardon's avatar
incardon committed
215
			typename is_vtk_writable<ctype>::base tmp = vg.get(k).g.template get<I::value>(it.get());
incardon's avatar
incardon committed
216
217
218
			tmp = swap_endian_lt(tmp);
			v_out.append((const char *)&tmp,sizeof(tmp));
		}
incardon's avatar
incardon committed
219
220
221
	}
};

Pietro Incardona's avatar
Pietro Incardona committed
222

incardon's avatar
incardon committed
223
224
/*! \brief This class is an helper to create properties output from scalar and compile-time array elements
 *
225
226
227
228
 * \tparam I It is an boost::mpl::int_ that indicate which property we are writing
 * \tparam ele_g element type that store the grid information
 * \tparam St type of space where the grid live
 * \tparam T the type of the property
Pietro Incardona's avatar
Pietro Incardona committed
229
 * \tparam is_writable flag that indicate if a property is writable
incardon's avatar
incardon committed
230
231
 *
 */
Pietro Incardona's avatar
Pietro Incardona committed
232
template<typename I, typename ele_g, typename St, typename T, bool is_writable>
incardon's avatar
incardon committed
233
234
struct meta_prop
{
incardon's avatar
incardon committed
235
236
237
238
	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
239
	 * \param prop_names property names
incardon's avatar
incardon committed
240
241
242
	 * \param ft ASCII or BINARY
	 *
	 */
243
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft)
incardon's avatar
incardon committed
244
245
246
247
248
	{
    	// actual string size
    	size_t sz = v_out.size();

		// 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);
incardon's avatar
incardon committed
250
251
252
253
254
255
256
257
258
259
260
261
262
263

		// If the output has changed, we have to write the properties
		if (v_out.size() != sz)
		{
			// Produce point data

			for (size_t k = 0 ; k < vg.size() ; k++)
			{
				//! Get a vertex iterator
				auto it = vg.get(k).g.getIterator();

				// if there is the next element
				while (it.isNext())
				{
incardon's avatar
incardon committed
264
					prop_write_out<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_out,vg,k,it,ft);
incardon's avatar
incardon committed
265
266
267
268
269

					// increment the iterator and counter
					++it;
				}
			}
incardon's avatar
incardon committed
270
271
272

			if (ft == file_type::BINARY)
				v_out += "\n";
incardon's avatar
incardon committed
273
274
275
276
277
		}
	}
};

//! Partial specialization for N=1 1D-Array
Pietro Incardona's avatar
Pietro Incardona committed
278
279
template<typename I, typename ele_g, typename St, typename T, size_t N1, bool is_writable>
struct meta_prop<I, ele_g,St,T[N1],is_writable>
incardon's avatar
incardon committed
280
{
incardon's avatar
incardon committed
281
282
283
284
	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
285
	 * \param prop_names properties name
incardon's avatar
incardon committed
286
287
288
	 * \param ft ASCII or BINARY
	 *
	 */
289
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names , file_type ft)
incardon's avatar
incardon committed
290
	{
291
292
	    // actual string size
	    size_t sz = v_out.size();
incardon's avatar
incardon committed
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);
incardon's avatar
incardon committed
296

297
298
299
300
301
302
		// If the output has changed, we have to write the properties
		if (v_out.size() != sz)
		{
			// Produce point data

			for (size_t k = 0 ; k < vg.size() ; k++)
incardon's avatar
incardon committed
303
			{
304
305
				//! Get a vertex iterator
				auto it = vg.get(k).g.getIterator();
incardon's avatar
incardon committed
306

307
308
				// if there is the next element
				while (it.isNext())
incardon's avatar
incardon committed
309
				{
incardon's avatar
incardon committed
310
					if (ft == file_type::ASCII)
incardon's avatar
incardon committed
311
					{
incardon's avatar
incardon committed
312
313
						// Print the properties
						for (size_t i1 = 0 ; i1 < N1 ; i1++)
incardon's avatar
incardon committed
314
						{v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1]) + " ";}
incardon's avatar
incardon committed
315

incardon's avatar
incardon committed
316
						if (N1 == 2)
incardon's avatar
incardon committed
317
						{v_out += std::to_string((decltype(vg.get(k).g.template get<I::value>(it.get())[0])) 0);}
incardon's avatar
incardon committed
318

incardon's avatar
incardon committed
319
						v_out += "\n";
incardon's avatar
incardon committed
320
					}
incardon's avatar
incardon committed
321
					else
322
					{
incardon's avatar
incardon committed
323
324
325
326
327
						T tmp;

						// Print the properties
						for (size_t i1 = 0 ; i1 < N1 ; i1++)
						{
incardon's avatar
incardon committed
328
							tmp = vg.get(k).g.template get<I::value>(it.get())[i1];
incardon's avatar
incardon committed
329
							tmp = swap_endian_lt(tmp);
incardon's avatar
incardon committed
330
331
332
333
334
335
336
337
							v_out.append((const char *)&tmp,sizeof(T));
						}
						if (N1 == 2)
						{
							tmp = 0.0;
							tmp = swap_endian_lt(tmp);
							v_out.append((const char *)&tmp,sizeof(T));
						}
338
339
340
341
					}

					// increment the iterator and counter
					++it;
incardon's avatar
incardon committed
342
343
				}
			}
incardon's avatar
incardon committed
344
			if (ft == file_type::BINARY)
incardon's avatar
incardon committed
345
			{v_out += "\n";}
incardon's avatar
incardon committed
346
347
348
349
350
		}
	}
};

//! Partial specialization for N=2 2D-Array
Pietro Incardona's avatar
Pietro Incardona committed
351
352
template<typename I, typename ele_g, typename St ,typename T,size_t N1,size_t N2, bool is_writable>
struct meta_prop<I, ele_g,St, T[N1][N2],is_writable>
incardon's avatar
incardon committed
353
{
incardon's avatar
incardon committed
354
355
356
357
358

	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
359
	 * \param prop_names property names
incardon's avatar
incardon committed
360
361
362
	 * \param ft ASCII or BINARY
	 *
	 */
363
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft)
incardon's avatar
incardon committed
364
365
366
367
368
369
370
371
372
	{
		for (size_t i1 = 0 ; i1 < N1 ; i1++)
		{
			for (size_t i2 = 0 ; i2 < N2 ; i2++)
			{
		    	// actual string size
		    	size_t sz = v_out.size();

				// 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);
incardon's avatar
incardon committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387

				// If the output has changed, we have to write the properties
				if (v_out.size() != sz)
				{
					// Produce point data

					for (size_t k = 0 ; k < vg.size() ; k++)
					{
						//! Get a vertex iterator
						auto it = vg.get(k).g.getIterator();

						// if there is the next element
						while (it.isNext())
						{
incardon's avatar
incardon committed
388
389
							T tmp;

incardon's avatar
incardon committed
390
391
392
							if (ft == file_type::ASCII)
							{
								// Print the property
incardon's avatar
incardon committed
393
								v_out += std::to_string(vg.get(k).g.template get<I::value>(it.get())[i1][i2]) + "\n";
incardon's avatar
incardon committed
394
395
396
							}
							else
							{
incardon's avatar
incardon committed
397
								tmp = vg.get(k).g.template get<I::value>(it.get())[i1][i2];
incardon's avatar
incardon committed
398
								tmp = swap_endian_lt(tmp);
incardon's avatar
incardon committed
399
								v_out.append((const char *)&tmp,sizeof(tmp));
incardon's avatar
incardon committed
400
							}
incardon's avatar
incardon committed
401
402
403
404
405

							// increment the iterator and counter
							++it;
						}
					}
incardon's avatar
incardon committed
406
407
408

					if (ft == file_type::BINARY)
						v_out += "\n";
incardon's avatar
incardon committed
409
410
411
412
413
414
				}
			}
		}
	}
};

Pietro Incardona's avatar
Pietro Incardona committed
415
416
417
418

//! Specialication when is not writable
template<typename I, typename ele_g, typename St, typename T>
struct meta_prop<I,ele_g,St,T,false>
incardon's avatar
incardon committed
419
{
incardon's avatar
incardon committed
420
421
422
423
424

	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
425
	 * \param prop_names properties name
incardon's avatar
incardon committed
426
427
428
	 * \param ft ASCII or BINARY
	 *
	 */
429
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, const openfpm::vector<std::string> & prop_names, file_type ft)
incardon's avatar
incardon committed
430
431
432
433
	{
	}
};

incardon's avatar
incardon committed
434
435
436
437
template<unsigned int dims,typename T> inline void output_point(Point<dims,T> & p,std::stringstream & v_out, file_type ft)
{
	if (ft == file_type::ASCII)
	{
incardon's avatar
incardon committed
438
439
440
441
442
		v_out << p.toString();
		size_t i = dims;
		for ( ; i < 3 ; i++)
		{v_out << " 0.0";}
		v_out << "\n";
incardon's avatar
incardon committed
443
444
445
	}
	else
	{
incardon's avatar
incardon committed
446
447
448
449
450
451
452
453
454
		size_t i = 0;
		for ( ; i < dims ; i++)
		{
			// we use float so we have to convert to float
			auto tmp = p.get(i);
			tmp = swap_endian_lt(tmp);
			v_out.write((const char *)&tmp,sizeof(tmp));
		}
		for ( ; i < 3 ; i++)
incardon's avatar
incardon committed
455
456
		{
			// we use float so we have to convert to float
incardon's avatar
incardon committed
457
458

			/* coverity[dead_error_begin] */
incardon's avatar
incardon committed
459
			T tmp = 0.0;
incardon's avatar
incardon committed
460
461
462
463
464
465
466
467
468
			tmp = swap_endian_lt(tmp);
			v_out.write((const char *)&tmp,sizeof(tmp));
		}
	}
}

inline void output_vertex(size_t k,std::string & v_out, file_type ft)
{
	if (ft == file_type::ASCII)
incardon's avatar
incardon committed
469
	{v_out += "1 " + std::to_string(k) + "\n";}
incardon's avatar
incardon committed
470
471
472
473
474
475
476
477
478
479
480
481
	else
	{
		int tmp;
		tmp = 1;
		tmp = swap_endian_lt(tmp);
		v_out.append((const char *)&tmp,sizeof(int));
		tmp = k;
		tmp = swap_endian_lt(tmp);
		v_out.append((const char *)&tmp,sizeof(int));
	}
}

incardon's avatar
incardon committed
482
#endif /* SRC_VTKWRITER_GRIDS_UTIL_HPP_ */