Commit fd804149 authored by incardon's avatar incardon

Adding binary format for VTK_WRITER

parent 5dfcba90
......@@ -9,7 +9,7 @@ io_LDADD = $(LINKLIBS)
nobase_include_HEADERS = CSVWriter/csv_multiarray.hpp CSVWriter/CSVWriter.hpp CSVWriter/is_csv_writable.hpp \
GraphMLWriter/GraphMLWriter.hpp util.hpp \
VTKWriter/VTKWriter.hpp VTKWriter/VTKWriter_dist_graph.hpp VTKWriter/VTKWriter_graph.hpp VTKWriter/VTKWriter_point_set.hpp VTKWriter/VTKWriter_grids.hpp VTKWriter/VTKWriter_grids_st.hpp VTKWriter/VTKWriter_grids_util.hpp VTKWriter/VTKWriter_vector_box.hpp VTKWriter/is_vtk_writable.hpp HDF5_XdmfWriter/HDF5_XdmfWriter.hpp HDF5_XdmfWriter/HDF5_XdmfWriter_point_set.hpp HDF5_XdmfWriter/HDF5_XdmfWriter_util.hpp \
VTKWriter/VTKWriter.hpp VTKWriter/byteswap_portable.hpp VTKWriter/VTKWriter_dist_graph.hpp VTKWriter/VTKWriter_graph.hpp VTKWriter/VTKWriter_point_set.hpp VTKWriter/VTKWriter_grids.hpp VTKWriter/VTKWriter_grids_st.hpp VTKWriter/VTKWriter_grids_util.hpp VTKWriter/VTKWriter_vector_box.hpp VTKWriter/is_vtk_writable.hpp HDF5_XdmfWriter/HDF5_XdmfWriter.hpp HDF5_XdmfWriter/HDF5_XdmfWriter_point_set.hpp HDF5_XdmfWriter/HDF5_XdmfWriter_util.hpp \
Plot/GoogleChart.hpp Plot/util.hpp
......
......@@ -101,6 +101,8 @@ enum file_type
#define DIST_GRAPH 5
#define VECTOR_POINTS 6
#define VTK_WRITER 0x10000
#define FORMAT_ASCII 0x0
#define FORMAT_BINARY 0x10000000
template <typename Object, unsigned int imp>
class VTKWriter
......
......@@ -57,15 +57,16 @@ public:
template<typename ele_g, typename St>
struct prop_out_g
{
// property output string
//! property output string
std::string & v_out;
// grid that we are processing
//! grid that we are processing
const openfpm::vector_std< ele_g > & vg;
/*! \brief constructor
*
* \param v_out string to fill with the vertex properties
* \param vg vector of elements to write
*
*/
prop_out_g(std::string & v_out, const openfpm::vector_std< ele_g > & vg)
......@@ -79,7 +80,7 @@ struct prop_out_g
typedef typename boost::mpl::at<typename ele_g::value_type::value_type::type,boost::mpl::int_<T::value>>::type ptype;
typedef typename std::remove_all_extents<ptype>::type base_ptype;
meta_prop<boost::mpl::int_<T::value> ,ele_g,St, ptype, is_vtk_writable<base_ptype>::value > m(vg,v_out);
meta_prop<boost::mpl::int_<T::value> ,ele_g,St, ptype, is_vtk_writable<base_ptype>::value > m(vg,v_out,file_type::ASCII);
}
void lastProp()
......
......@@ -31,18 +31,30 @@ struct cell_grid
cell_grid() {}
//! construct a cell grid
/*! \brief construct a cell grid
*
* \param cmb in which position this grid live
*
*/
cell_grid(const comb<Grid::dims> & cmb)
:cmb(cmb)
{}
//! copy contructor
/*! \brief copy contructor
*
* \param cg element to copy
*
*/
cell_grid(const cell_grid<Grid> & cg)
{
this->operator=(cg);
}
//! copy constructor
/*! \brief copy constructor
*
* \param cg element to copy
*
*/
cell_grid(cell_grid<Grid> && cg)
{
this->operator=(cg);
......@@ -100,7 +112,7 @@ public:
*
* \param offset shift of the staggered element
* \param spacing of the grid
* \param Part of the grid that is real domain
* \param dom Part of the grid that is real domain
*
*/
ele_g_st(const Point<Grid::dims,St> & offset,
......@@ -120,13 +132,21 @@ public:
//! Part of the grid that is real domain
Box<Grid::dims,size_t> dom;
//! Copy constructor
/*! \brief Copy constructor
*
* \param ele element to copy
*
*/
inline ele_g_st(const ele_g_st & ele)
{
this->operator=(ele);
}
//! Copy constructor
/*! \brief Copy constructor
*
* \param ele element to copy
*
*/
inline ele_g_st(ele_g_st && ele)
{
this->operator=(ele);
......@@ -300,7 +320,7 @@ class VTKWriter<pair,VECTOR_ST_GRIDS>
return v_out.str();
}
/* \brief It generate a name for the property cell component
/*! \brief It generate a name for the property cell component
*
* \param k component in the cell
*
......@@ -331,7 +351,7 @@ class VTKWriter<pair,VECTOR_ST_GRIDS>
/*! \brief Create the VTK properties output
*
* \param k component
* \param prop property name
* \param prop_name property name
*
* \return the property output string for the grid
*
......
......@@ -10,6 +10,7 @@
#include "util/util_debug.hpp"
#include "is_vtk_writable.hpp"
#include "byteswap_portable.hpp"
/*! \brief Return the Attributes name (if they have)
*
......@@ -113,40 +114,6 @@ template<unsigned int i, typename ele_g, bool has_attributes> std::string get_po
return v_out;
}
#if 0
/*! \brief This class specialize functions in the case the type T
* has or not defined attributes
*
* In C++ partial specialization of a function is not allowed so we have to
* encapsulate this function in a class
*
* \tparam has_attributes parameter that specialize the function in case the grid
* define or not attributes name
*
* \tparam Grid type we are processing
* \tparam i the property we are going to write
*
*/
template<bool has_attributes, typename St, typename ele_g, unsigned int i>
class prop_output_g
{
public:
/*! \brief Return the VTK point data header for a typename T
*
* \tparam T type to write
* \param n_node number of the node
*
*/
static std::string get_point_property_header(const std::string & oprp)
{
return get_point_property_header_impl<i,ele_g,has_attributes>(oprp);
}
};
#endif
/*! \brief Write the vectror property
*
* \tparam dim Dimensionality of the property
......@@ -157,19 +124,38 @@ class prop_write_out
{
public:
template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it)
template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it, file_type ft)
{
// Print the properties
for (size_t i1 = 0 ; i1 < vtk_dims<T>::value ; i1++)
if (ft == file_type::ASCII)
{
v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>().get_vtk(i1)) + " ";
// 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";
}
if (vtk_dims<T>::value == 2)
else
{
v_out += "0.0";
// 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));
}
}
v_out += "\n";
}
};
......@@ -182,45 +168,22 @@ class prop_write_out<1,T>
{
public:
template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it)
{
// Print the property
v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>()) + "\n";
}
};
#if 0
/*! \brief This class specialize functions in the case the type T
* has not defined attributes
*
* In C++ partial specialization of a function is not allowed so we have to
* encapsulate this function in a class
*
* \tparam has_attributes parameter that specialize the function in case the vertex
* define or not attributes name
*
* \tparam i id of the property we are going to write
*
*/
template<typename ele_g, typename St, unsigned int i>
class prop_output_g<false,St,ele_g,i>
{
public:
/*! \brief Get the vtk properties header appending a prefix at the end
*
* \param oprp prefix
*
*/
static std::string get_point_property_header(const std::string & oprp)
template<typename vector, typename iterator, typename I> static void write(std::string & v_out, vector & vg, size_t k, iterator & it, file_type ft)
{
return get_point_property_header_impl<i,ele_g,false>(oprp);
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));
}
}
};
#endif
/*! \brief This class is an helper to create properties output from scalar and compile-time array elements
*
......@@ -234,7 +197,14 @@ public:
template<typename I, typename ele_g, typename St, typename T, bool is_writable>
struct meta_prop
{
inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out)
/*! \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)
{
// actual string size
size_t sz = v_out.size();
......@@ -255,12 +225,15 @@ struct meta_prop
// if there is the next element
while (it.isNext())
{
prop_write_out<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_out,vg,k,it);
prop_write_out<vtk_dims<T>::value,T>::template write<decltype(vg),decltype(it),I>(v_out,vg,k,it,ft);
// increment the iterator and counter
++it;
}
}
if (ft == file_type::BINARY)
v_out += "\n";
}
}
};
......@@ -269,7 +242,14 @@ struct meta_prop
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>
{
inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out)
/*! \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)
{
// actual string size
size_t sz = v_out.size();
......@@ -290,21 +270,44 @@ struct meta_prop<I, ele_g,St,T[N1],is_writable>
// if there is the next element
while (it.isNext())
{
// Print the properties
for (size_t i1 = 0 ; i1 < N1 ; i1++)
if (ft == file_type::ASCII)
{
v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>()[i1]) + " ";
// 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";
}
if (N1 == 2)
else
{
v_out += "0.0";
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));
}
}
v_out += "\n";
// increment the iterator and counter
++it;
}
}
if (ft == file_type::BINARY)
v_out += "\n";
}
}
};
......@@ -313,7 +316,15 @@ struct meta_prop<I, ele_g,St,T[N1],is_writable>
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>
{
inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out)
/*! \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)
{
for (size_t i1 = 0 ; i1 < N1 ; i1++)
{
......@@ -338,8 +349,17 @@ struct meta_prop<I, ele_g,St, T[N1][N2],is_writable>
// if there is the next element
while (it.isNext())
{
// Print the property
v_out += std::to_string(vg.get(k).g.get_o(it.get()).template get<I::value>()[i1][i2]) + "\n";
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));
}
// increment the iterator and counter
++it;
......@@ -356,7 +376,15 @@ struct meta_prop<I, ele_g,St, T[N1][N2],is_writable>
template<typename I, typename ele_g, typename St, typename T>
struct meta_prop<I,ele_g,St,T,false>
{
inline meta_prop(const openfpm::vector< ele_g > & vg, std::string & v_out)
/*! \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)
{
}
};
......
......@@ -13,6 +13,7 @@
#include "VTKWriter_grids_util.hpp"
#include "is_vtk_writable.hpp"
#include <string>
#include "byteswap_portable.hpp"
/*! \brief Store a reference to the vector position
*
......@@ -81,6 +82,9 @@ public:
template<typename ele_v, typename St>
struct prop_out_v
{
//! Binary or ASCII
file_type ft;
//! property output string
std::string & v_out;
......@@ -91,10 +95,11 @@ struct prop_out_v
*
* \param v_out string to fill with the vertex properties
* \param vv vector we are processing
* \param ft ASCII or BINARY format
*
*/
prop_out_v(std::string & v_out, const openfpm::vector_std< ele_v > & vv)
:v_out(v_out),vv(vv)
prop_out_v(std::string & v_out, const openfpm::vector_std< ele_v > & vv, file_type ft)
:ft(ft),v_out(v_out),vv(vv)
{};
//! It produce an output for each property
......@@ -104,7 +109,7 @@ struct prop_out_v
typedef typename boost::mpl::at<typename ele_v::value_type::value_type::type,boost::mpl::int_<T::value>>::type ptype;
typedef typename std::remove_all_extents<ptype>::type base_ptype;
meta_prop<boost::mpl::int_<T::value> ,ele_v,St, ptype, is_vtk_writable<base_ptype>::value > m(vv,v_out);
meta_prop<boost::mpl::int_<T::value> ,ele_v,St, ptype, is_vtk_writable<base_ptype>::value > m(vv,v_out,ft);
}
void lastProp()
......@@ -124,10 +129,28 @@ struct prop_out_v
// if there is the next element
while (it.isNext())
{
if (it.get() < vv.get(k).mark)
v_out += "1.0\n";
if (ft == file_type::ASCII)
{
if (it.get() < vv.get(k).mark)
v_out += "1.0\n";
else
v_out += "0.0\n";
}
else
v_out += "0.0\n";
{
if (it.get() < vv.get(k).mark)
{
int one = 1;
one = swap_endian_lt(one);
v_out.append((const char *)&one,sizeof(int));
}
else
{
int zero = 0;
zero = swap_endian_lt(zero);
v_out.append((const char *)&zero,sizeof(int));
}
}
// increment the iterator and counter
++it;
......@@ -210,10 +233,14 @@ class VTKWriter<pair,VECTOR_POINTS>
return v_out;
}
/*! \brief Create the VTK point definition
/*! \brief Create the VTK point list
*
* \param ft file_type
*
* \return the list of points
*
*/
std::string get_point_list()
std::string get_point_list(file_type ft)
{
//! vertex node output string
std::stringstream v_out;
......@@ -231,26 +258,47 @@ class VTKWriter<pair,VECTOR_POINTS>
Point<pair::first::value_type::dims,typename pair::first::value_type::coord_type> p;
p = vps.get(i).g.get(it.get());
if (pair::first::value_type::dims == 2)
v_out << p.toString() << " 0.0" << "\n";
if (ft == file_type::ASCII)
{
if (pair::first::value_type::dims == 2)
v_out << p.toString() << " 0.0" << "\n";
else
v_out << p.toString() << "\n";
}
else
v_out << p.toString() << "\n";
{
for (size_t i = 0 ; i < pair::first::value_type::dims ; i++)
{
// we use float so we have to convert to float
float tmp = p.get(i);
tmp = swap_endian_lt(tmp);
v_out.write((const char *)&tmp,sizeof(tmp));
}
}
// increment the iterator and counter
++it;
}
}
//! In case of binary we have to add a new line at the end of the list
if (ft == file_type::BINARY)
v_out << std::endl;
// return the vertex list
return v_out.str();
}
/*! \brief Create the VTK vertex definition
/*! \brief Create the VTK vertex list
*
* \param ft file_type
*
* \return the list of vertices
*
*/
std::string get_vertex_list()
std::string get_vertex_list(file_type ft)
{
//! vertex node output string
// vertex node output string
std::string v_out;
size_t k = 0;
......@@ -262,12 +310,28 @@ class VTKWriter<pair,VECTOR_POINTS>
while (it.isNext())
{
v_out += "1 " + std::to_string(k) + "\n";
if (ft == file_type::ASCII)
v_out += "1 " + std::to_string(k) + "\n";
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));
}
++k;
++it;
}
}
//! In case of binary we have to add a new line at the end of the list
if (ft == file_type::BINARY)
v_out += "\n";
// return the vertex list
return v_out;
}
......@@ -358,20 +422,20 @@ public:
point_prop_header = get_point_properties_list();
// Get point list
point_list = get_point_list();
point_list = get_point_list(ft);
// vertex properties header
vertex_prop_header = get_vertex_properties_list();
// Get vertex list
vertex_list = get_vertex_list();
vertex_list = get_vertex_list(ft);
// Get the point data header
point_data_header = get_point_data_header();
// For each property in the vertex type produce a point data
prop_out_v< ele_vpp<typename pair::second>, typename pair::first::value_type::coord_type> pp(point_data, vpp);
prop_out_v< ele_vpp<typename pair::second>, typename pair::first::value_type::coord_type> pp(point_data, vpp, ft);
if (prp == -1)
boost::mpl::for_each< boost::mpl::range_c<int,0, pair::second::value_type::max_prop> >(pp);
......
......@@ -903,6 +903,94 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set )
}
}
BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary )
{
{
// Create 3 vectors with random particles
openfpm::vector<Point<3,double>> v1ps;
openfpm::vector<Point<3,double>> v2ps;
openfpm::vector<Point<3,double>> v3ps;
openfpm::vector<aggregate<float,float[3]>> v1pp;
openfpm::vector<aggregate<float,float[3]>> v2pp;
openfpm::vector<aggregate<float,float[3]>> v3pp;
openfpm::vector<aggregate<float,Point<3,float>>> v4pp;
// set the seed
// create the random generator engine
SimpleRNG rng;
// fill the vector with random data
v1ps.resize(100);
v2ps.resize(100);
v3ps.resize(100);
v1pp.resize(100);
v2pp.resize(100);
v3pp.resize(100);
v4pp.resize(100);
for (size_t i = 0 ; i < v1ps.size(); i++)
{
v1ps.template get<0>(i)[0] = rng.GetUniform();
v1ps.template get<0>(i)[1] = rng.GetUniform();
v1ps.template get<0>(i)[2] = rng.GetUniform();
v2ps.template get<0>(i)[0] = rng.GetUniform()*0.5;
v2ps.template get<0>(i)[1] = rng.GetUniform()*0.5;
v2ps.template get<0>(i)[2] = rng.GetUniform()*0.5;
v3ps.template get<0>(i)[0] = rng.GetUniform()*0.3;
v3ps.template get<0>(i)[1] = rng.GetUniform()*0.3;
v3ps.template get<0>(i)[2] = rng.GetUniform()*0.3;
v1pp.template get<0>(i) = rng.GetUniform();
v1pp.template get<1>(i)[0] = rng.GetUniform();
v1pp.template get<1>(i)[1] = rng.GetUniform();
v1pp.template get<1>(i)[2] = rng.GetUniform();
v2pp.template get<0>(i) = rng.GetUniform();
v2pp.template get<1>(i)[0] = rng.GetUniform();
v2pp.template get<1>(i)[1] = rng.GetUniform();
v2pp.template get<1>(i)[2] = rng.GetUniform();
v3pp.template get<0>(i) = rng.GetUniform();
v3pp.template get<1>(i)[0] = rng.GetUniform();
v3pp.template get<1>(i)[1] = rng.GetUniform();
v3pp.template get<1>(i)[2] = rng.GetUniform();
v4pp.template get<0>(i) = rng.GetUniform();
v4pp.template get<1>(i).get(0) = rng.GetUniform();
v4pp.template get<1>(i).get(1) = rng.GetUniform();
v4pp.template get<1>(i).get(2) = rng.GetUniform();
}
// Create a writer and write
VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,float[3]>>>,VECTOR_POINTS> vtk_v;
vtk_v.add(v1ps,v1pp,75);
vtk_v.add(v2ps,v2pp,88);
vtk_v.add(v3ps,v3pp,90);
vtk_v.write("vtk_points_bin.vtk","vtk output",file_type::BINARY);
// Check that match
bool test = compare("vtk_points_bin.vtk","vtk_points_bin_test.vtk");
BOOST_REQUIRE_EQUAL(test,true);
// Create a writer and write
VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,Point<3,float>>>>,VECTOR_POINTS> vtk_v2;
vtk_v2.add(v1ps,v4pp,75);
vtk_v2.write("vtk_points_pp_bin.vtk","vtk output",file_type::BINARY);
// Check that match
test = compare("vtk_points_pp_bin.vtk","vtk_points_pp_bin_test.vtk");
BOOST_REQUIRE_EQUAL(test,true);
}