VTKWriter_grids_util.hpp 9.99 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

Pietro Incardona's avatar
Pietro Incardona committed
15
/*! \brief Return the Attributes name (if they have)
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
26
27
28
29
30
31
32
	/*! \brief Get attribute name
	 *
	 * \param i id of the attribute
	 * \param oprp post-fix to add
	 *
	 */
	static inline std::string get(size_t i, const std::string & oprp)
	{
		return ele_g::value_type::value_type::attributes::name[i] + oprp;
	}
};
incardon's avatar
incardon committed
33

Pietro Incardona's avatar
Pietro Incardona committed
34
35
36
37
template<typename ele_g>
struct getAttrName<ele_g,false>
{
	/*! \brief Get attribute name
incardon's avatar
incardon committed
38
	 *
Pietro Incardona's avatar
Pietro Incardona committed
39
40
	 * \param i id of the attribute
	 * \param oprp post-fix to add
incardon's avatar
incardon committed
41
42
	 *
	 */
Pietro Incardona's avatar
Pietro Incardona committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	static inline std::string get(size_t i, const std::string & oprp)
	{
		return std::string("attr" + std::to_string(i) + oprp);
	}
};

/*! \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
 *
 */
template<unsigned int i, typename ele_g, bool has_attributes> std::string get_point_property_header_impl(const std::string & oprp)
{
	//! 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
65
	{
66
		if (std::extent<ctype>::value <= 3)
incardon's avatar
incardon committed
67
		{
68
69
70
71
72
73
74
75
76
			//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)
			{
				std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the type " << demangle(typeid(ctype).name()) << " is not supported by vtk\n";
				return "";
			}
incardon's avatar
incardon committed
77

78
79
80
			// Create point data properties
			v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,oprp) + " " + type + "\n";
		}
Pietro Incardona's avatar
Pietro Incardona committed
81
82
83
84
85
86
87
88
89
90
91
	}
	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
92
			{
Pietro Incardona's avatar
Pietro Incardona committed
93
				type = getType<typename vtk_type<ctype,is_custom_vtk_writable<ctype>::value>::type >();
incardon's avatar
incardon committed
94

Pietro Incardona's avatar
Pietro Incardona committed
95
96
97
98
99
				// We check if it is a vector or scalar like type
				if (vtk_dims<ctype>::value == 1)
					v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,oprp) + " " + type + "\n";
				else
					v_out += "VECTORS " + getAttrName<ele_g,has_attributes>::get(i,oprp) + " " + type + "\n";
incardon's avatar
incardon committed
100
			}
Pietro Incardona's avatar
Pietro Incardona committed
101
102

			return v_out;
incardon's avatar
incardon committed
103
104
		}

Pietro Incardona's avatar
Pietro Incardona committed
105
106
107
108
109
110
		// Create point data properties
		v_out += "SCALARS " + getAttrName<ele_g,has_attributes>::get(i,oprp) + " " + type + "\n";

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

incardon's avatar
incardon committed
111
112
	}

Pietro Incardona's avatar
Pietro Incardona committed
113
114
115
116
117
118
119
120
121
122
123
124
125
	// 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
126

incardon's avatar
incardon committed
127
	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
128
	{
incardon's avatar
incardon committed
129

incardon's avatar
incardon committed
130
		if (ft == file_type::ASCII)
Pietro Incardona's avatar
Pietro Incardona committed
131
		{
incardon's avatar
incardon committed
132
133
134
135
136
137
138
139
140
141
			// 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
142
		}
incardon's avatar
incardon committed
143
		else
144
		{
incardon's avatar
incardon committed
145
146
147
148
149
150
151
152
153
154
155
156
157
			// Print the properties
			for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++)
			{
				auto tmp = vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1);
				tmp = swap_endian_lt(tmp);
				v_out.append((const char *)&tmp,sizeof(tmp));
			}
			if (vtk_dims<T>::value == 2)
			{
				decltype(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(0)) zero = 0.0;
				zero = swap_endian_lt(zero);
				v_out.append((const char *)&zero,sizeof(zero));
			}
158
		}
incardon's avatar
incardon committed
159
	}
Pietro Incardona's avatar
Pietro Incardona committed
160
};
incardon's avatar
incardon committed
161

Pietro Incardona's avatar
Pietro Incardona committed
162
163
164
165
166
167
168
169
/*! \brief Write the scalar property
 *
 *
 */
template<typename T>
class prop_write_out<1,T>
{
public:
incardon's avatar
incardon committed
170

incardon's avatar
incardon committed
171
	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
172
	{
incardon's avatar
incardon committed
173
174
175
176
177
178
179
180
181
182
183
		if (ft == file_type::ASCII)
		{
			// Print the property
			v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>()) + "\n";
		}
		else
		{
			auto tmp = vg.get(k).g.get_o(it.get()).template get<I::value>();
			tmp = swap_endian_lt(tmp);
			v_out.append((const char *)&tmp,sizeof(tmp));
		}
incardon's avatar
incardon committed
184
185
186
	}
};

Pietro Incardona's avatar
Pietro Incardona committed
187

incardon's avatar
incardon committed
188
189
/*! \brief This class is an helper to create properties output from scalar and compile-time array elements
 *
190
191
192
193
 * \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
194
 * \tparam is_writable flag that indicate if a property is writable
incardon's avatar
incardon committed
195
196
 *
 */
Pietro Incardona's avatar
Pietro Incardona committed
197
template<typename I, typename ele_g, typename St, typename T, bool is_writable>
incardon's avatar
incardon committed
198
199
struct meta_prop
{
incardon's avatar
incardon committed
200
201
202
203
204
205
206
207
	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
	 * \param ft ASCII or BINARY
	 *
	 */
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, file_type ft)
incardon's avatar
incardon committed
208
209
210
211
212
	{
    	// actual string size
    	size_t sz = v_out.size();

		// Produce the point properties header
Pietro Incardona's avatar
Pietro Incardona committed
213
    	v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("");
incardon's avatar
incardon committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227

		// 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
228
					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
229
230
231
232
233

					// increment the iterator and counter
					++it;
				}
			}
incardon's avatar
incardon committed
234
235
236

			if (ft == file_type::BINARY)
				v_out += "\n";
incardon's avatar
incardon committed
237
238
239
240
241
		}
	}
};

//! Partial specialization for N=1 1D-Array
Pietro Incardona's avatar
Pietro Incardona committed
242
243
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
244
{
incardon's avatar
incardon committed
245
246
247
248
249
250
251
252
	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
	 * \param ft ASCII or BINARY
	 *
	 */
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, file_type ft)
incardon's avatar
incardon committed
253
	{
254
255
	    // actual string size
	    size_t sz = v_out.size();
incardon's avatar
incardon committed
256

257
		// Produce the point properties header
Pietro Incardona's avatar
Pietro Incardona committed
258
		v_out += get_point_property_header_impl<I::value,ele_g,has_attributes<typename ele_g::value_type::value_type>::value>("");
incardon's avatar
incardon committed
259

260
261
262
263
264
265
		// 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
266
			{
267
268
				//! Get a vertex iterator
				auto it = vg.get(k).g.getIterator();
incardon's avatar
incardon committed
269

270
271
				// if there is the next element
				while (it.isNext())
incardon's avatar
incardon committed
272
				{
incardon's avatar
incardon committed
273
					if (ft == file_type::ASCII)
incardon's avatar
incardon committed
274
					{
incardon's avatar
incardon committed
275
276
277
278
279
280
281
282
283
284
						// Print the properties
						for (size_t i1 = 0 ; i1 < N1 ; i1++)
						{
							v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>()[i1]) + " ";
						}
						if (N1 == 2)
						{
							v_out += "0.0";
						}
						v_out += "\n";
incardon's avatar
incardon committed
285
					}
incardon's avatar
incardon committed
286
					else
287
					{
incardon's avatar
incardon committed
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
						T tmp;

						// Print the properties
						for (size_t i1 = 0 ; i1 < N1 ; i1++)
						{
							tmp = vg.get(k).g.get_o(it.get()).template get<I::value>()[i1];
							swap_endian_lt(tmp);
							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));
						}
303
304
305
306
					}

					// increment the iterator and counter
					++it;
incardon's avatar
incardon committed
307
308
				}
			}
incardon's avatar
incardon committed
309
310
			if (ft == file_type::BINARY)
				v_out += "\n";
incardon's avatar
incardon committed
311
312
313
314
315
		}
	}
};

//! Partial specialization for N=2 2D-Array
Pietro Incardona's avatar
Pietro Incardona committed
316
317
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
318
{
incardon's avatar
incardon committed
319
320
321
322
323
324
325
326
327

	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
	 * \param ft ASCII or BINARY
	 *
	 */
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, file_type ft)
incardon's avatar
incardon committed
328
329
330
331
332
333
334
335
336
	{
		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
Pietro Incardona's avatar
Pietro Incardona committed
337
				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));
incardon's avatar
incardon committed
338
339
340
341
342
343
344
345
346
347
348
349
350
351

				// 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
352
353
354
355
356
357
358
359
360
361
362
							if (ft == file_type::ASCII)
							{
								// Print the property
								v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>()[i1][i2]) + "\n";
							}
							else
							{
								auto tmp = vg.get(k).g.get_o(it.get()).template get<I::value>()[i1][i2];
								tmp = swap_endian_lt(tmp);
								v_out.append(tmp,sizeof(tmp));
							}
incardon's avatar
incardon committed
363
364
365
366
367
368
369
370
371
372
373

							// increment the iterator and counter
							++it;
						}
					}
				}
			}
		}
	}
};

Pietro Incardona's avatar
Pietro Incardona committed
374
375
376
377

//! 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
378
{
incardon's avatar
incardon committed
379
380
381
382
383
384
385
386
387

	/*! \brief Write a vtk compatible type into vtk format
	 *
	 * \param vg array of elements to write
	 * \param v_out string containing the string
	 * \param ft ASCII or BINARY
	 *
	 */
	inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out, file_type ft)
incardon's avatar
incardon committed
388
389
390
391
392
	{
	}
};

#endif /* SRC_VTKWRITER_GRIDS_UTIL_HPP_ */