Skip to content
Snippets Groups Projects
Commit b37d1f14 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Change VTKWriter to produce binary data

This generally does not reduces the file sizes, but it reduces the
writing and reading times (no encoding/decoding is required)
parent ca70212f
No related branches found
No related tags found
1 merge request!80Feature/writers improvement
......@@ -113,6 +113,16 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif()
endif()
#------------------------------------------------------
include (TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
set(PUGS_LITTLE_ENDIAN FALSE)
else()
set(PUGS_LITTLE_ENDIAN TRUE)
endif()
#------------------------------------------------------
# defaults use of MPI
set(PUGS_ENABLE_MPI AUTO CACHE STRING
......
......@@ -6,6 +6,7 @@
#include <mesh/MeshDataManager.hpp>
#include <utils/Messenger.hpp>
#include <utils/RevisionInfo.hpp>
#include <utils/pugs_config.hpp>
#include <ctime>
#include <fstream>
......@@ -13,6 +14,99 @@
#include <sstream>
#include <unordered_map>
class ICharArrayEmbedder
{
public:
ICharArrayEmbedder() = default;
ICharArrayEmbedder(const ICharArrayEmbedder&) = default;
ICharArrayEmbedder(ICharArrayEmbedder&&) = default;
virtual size_t size() const = 0;
virtual void write(std::ostream&) const = 0;
virtual ~ICharArrayEmbedder() = default;
};
template <typename InputDataT>
class CharArrayEmbedder : public ICharArrayEmbedder
{
CastArray<InputDataT, char> m_char_cast_array;
public:
size_t
size() const final
{
return m_char_cast_array.size();
}
void
write(std::ostream& os) const final
{
os.write(&(m_char_cast_array[0]), m_char_cast_array.size());
}
CharArrayEmbedder(Array<InputDataT> array) : m_char_cast_array{array} {}
CharArrayEmbedder() = default;
CharArrayEmbedder(const CharArrayEmbedder&) = default;
CharArrayEmbedder(CharArrayEmbedder&&) = default;
~CharArrayEmbedder() = default;
};
class VTKWriter::SerializedDataList
{
private:
std::vector<std::shared_ptr<ICharArrayEmbedder>> m_serialized_data_list;
size_t m_offset = 0;
public:
size_t
offset() const
{
return m_offset;
}
template <typename DataT>
void
add(Array<DataT> array)
{
auto array_data = std::make_shared<CharArrayEmbedder<DataT>>(array);
auto size_data = std::make_shared<CharArrayEmbedder<int>>([&] {
Array<int> size_array(1);
size_array[0] = array_data->size();
return size_array;
}());
m_serialized_data_list.push_back(size_data);
m_serialized_data_list.push_back(array_data);
m_offset += size_data->size() + array_data->size();
}
template <typename DataT, ItemType item_type, typename ConnectivityT>
void
add(const ItemValue<DataT, item_type, ConnectivityT>& item_value)
{
Array<std::remove_const_t<DataT>> array(item_value.numberOfItems());
parallel_for(
item_value.numberOfItems(), PUGS_LAMBDA(ItemIdT<item_type> item_id) { array[item_id] = item_value[item_id]; });
this->add(array);
}
void
write(std::ostream& os) const
{
for (auto serialized_data : m_serialized_data_list) {
serialized_data->write(os);
}
}
SerializedDataList() = default;
~SerializedDataList() = default;
};
std::string
VTKWriter::_getFilenamePVTU() const
{
......@@ -134,141 +228,114 @@ struct VTKWriter::VTKType
template <typename DataType>
void
VTKWriter::_write_array(std::ofstream& os, const std::string& name, const Array<DataType>& item_value) const
VTKWriter::_write_array(std::ofstream& os,
const std::string& name,
const Array<DataType>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\">\n";
for (typename Array<DataType>::index_type i = 0; i < item_value.size(); ++i) {
// The following '+' enforces integer output for char types
os << +item_value[i] << ' ';
}
os << "\n</DataArray>\n";
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" offset=\""
<< serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <size_t N, typename DataType>
void
VTKWriter::_write_array(std::ofstream& os,
const std::string& name,
const Array<TinyVector<N, DataType>>& item_value) const
const Array<TinyVector<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" NumberOfComponents=\"" << N
<< "\">\n";
for (typename Array<DataType>::index_type i = 0; i < item_value.size(); ++i) {
for (size_t j = 0; j < N; ++j) {
// The following '+' enforces integer output for char types
os << +item_value[i][j] << ' ';
}
}
os << "\n</DataArray>\n";
<< "\" offset=\"" << serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <typename DataType>
void
VTKWriter::_write_node_value(std::ofstream& os,
const std::string& name,
const NodeValue<const DataType>& item_value) const
const NodeValue<const DataType>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\">\n";
for (NodeId i = 0; i < item_value.size(); ++i) {
// The following '+' enforces integer output for char types
os << +item_value[i] << ' ';
}
os << "\n</DataArray>\n";
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" offset=\""
<< serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <size_t N, typename DataType>
void
VTKWriter::_write_node_value(std::ofstream& os,
const std::string& name,
const NodeValue<const TinyVector<N, DataType>>& item_value) const
const NodeValue<const TinyVector<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" NumberOfComponents=\"" << N
<< "\">\n";
for (NodeId i = 0; i < item_value.size(); ++i) {
for (size_t j = 0; j < N; ++j) {
// The following '+' enforces integer output for char types
os << +item_value[i][j] << ' ';
}
}
os << "\n</DataArray>\n";
<< "\" offset=\"" << serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <size_t N, typename DataType>
void
VTKWriter::_write_node_value(std::ofstream& os,
const std::string& name,
const NodeValue<const TinyMatrix<N, DataType>>& item_value) const
const NodeValue<const TinyMatrix<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" NumberOfComponents=\"" << N * N
<< "\">\n";
for (NodeId i = 0; i < item_value.size(); ++i) {
for (size_t j = 0; j < N; ++j) {
for (size_t k = 0; k < N; ++k) {
// The following '+' enforces integer output for char types
os << +item_value[i](j, k) << ' ';
}
}
}
os << "\n</DataArray>\n";
<< "\" offset=\"" << serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <typename DataType>
void
VTKWriter::_write_node_value(std::ofstream&, const std::string&, const CellValue<const DataType>&) const
VTKWriter::_write_node_value(std::ofstream&,
const std::string&,
const CellValue<const DataType>&,
SerializedDataList&) const
{}
template <typename DataType>
void
VTKWriter::_write_cell_value(std::ofstream& os,
const std::string& name,
const CellValue<const DataType>& item_value) const
const CellValue<const DataType>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\">\n";
for (CellId i = 0; i < item_value.size(); ++i) {
// The following '+' enforces integer output for char types
os << +item_value[i] << ' ';
}
os << "\n</DataArray>\n";
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" offset=\""
<< serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <size_t N, typename DataType>
void
VTKWriter::_write_cell_value(std::ofstream& os,
const std::string& name,
const CellValue<const TinyVector<N, DataType>>& item_value) const
const CellValue<const TinyVector<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" NumberOfComponents=\"" << N
<< "\">\n";
for (CellId i = 0; i < item_value.size(); ++i) {
for (size_t j = 0; j < N; ++j) {
// The following '+' enforces integer output for char types
os << +item_value[i][j] << ' ';
}
}
os << "\n</DataArray>\n";
<< "\" offset=\"" << serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <size_t N, typename DataType>
void
VTKWriter::_write_cell_value(std::ofstream& os,
const std::string& name,
const CellValue<const TinyMatrix<N, DataType>>& item_value) const
const CellValue<const TinyMatrix<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const
{
os << "<DataArray type=\"" << VTKType<DataType>::name << "\" Name=\"" << name << "\" NumberOfComponents=\"" << N * N
<< "\">\n";
for (CellId i = 0; i < item_value.size(); ++i) {
for (size_t j = 0; j < N; ++j) {
for (size_t k = 0; k < N; ++k) {
// The following '+' enforces integer output for char types
os << +item_value[i](j, k) << ' ';
}
}
}
os << "\n</DataArray>\n";
<< "\" offset=\"" << serialized_data_list.offset() << "\" format=\"appended\"/>\n";
serialized_data_list.add(item_value);
}
template <typename DataType>
void
VTKWriter::_write_cell_value(std::ofstream&, const std::string&, const NodeValue<const DataType>&) const
VTKWriter::_write_cell_value(std::ofstream&,
const std::string&,
const NodeValue<const DataType>&,
SerializedDataList&) const
{}
template <typename MeshType>
......@@ -329,23 +396,34 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh,
fout << "</VTKFile>\n";
}
{ // write VTK files
{
SerializedDataList serialize_data_list;
// write VTK files
std::ofstream fout(_getFilenameVTU(parallel::rank()));
fout << "<?xml version=\"1.0\"?>\n";
fout << _getDateAndVersionComment();
fout << "<VTKFile type=\"UnstructuredGrid\">\n";
fout << "<VTKFile type=\"UnstructuredGrid\"";
#if defined(PUGS_LITTLE_ENDIAN)
fout << " byte_order=\"LittleEndian\"";
#else
fout << " byte_order=\"BigEndian\"";
#endif
fout << ">\n";
fout << "<UnstructuredGrid>\n";
fout << "<Piece NumberOfPoints=\"" << mesh->numberOfNodes() << "\" NumberOfCells=\"" << mesh->numberOfCells()
<< "\">\n";
fout << "<CellData>\n";
for (const auto& [name, item_value_variant] : output_named_item_value_set) {
std::visit([&, name = name](auto&& item_value) { return this->_write_cell_value(fout, name, item_value); },
std::visit([&, name = name](
auto&& item_value) { return this->_write_cell_value(fout, name, item_value, serialize_data_list); },
item_value_variant);
}
fout << "</CellData>\n";
fout << "<PointData>\n";
for (const auto& [name, item_value_variant] : output_named_item_value_set) {
std::visit([&, name = name](auto&& item_value) { return this->_write_node_value(fout, name, item_value); },
std::visit([&, name = name](
auto&& item_value) { return this->_write_node_value(fout, name, item_value, serialize_data_list); },
item_value_variant);
}
fout << "</PointData>\n";
......@@ -363,7 +441,7 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh,
positions[r][i] = 0;
}
});
_write_array(fout, "Positions", positions);
_write_array(fout, "Positions", positions, serialize_data_list);
}
fout << "</Points>\n";
......@@ -371,7 +449,7 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh,
{
const auto& cell_to_node_matrix = mesh->connectivity().cellToNodeMatrix();
_write_array(fout, "connectivity", cell_to_node_matrix.entries());
_write_array(fout, "connectivity", cell_to_node_matrix.entries(), serialize_data_list);
}
{
......@@ -383,7 +461,7 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh,
offset += cell_nodes.size();
offsets[j] = offset;
}
_write_array(fout, "offsets", offsets);
_write_array(fout, "offsets", offsets, serialize_data_list);
}
{
......@@ -437,7 +515,7 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh,
}
}
});
_write_array(fout, "types", types);
_write_array(fout, "types", types, serialize_data_list);
if constexpr (MeshType::Dimension == 3) {
const bool has_general_polyhedron = [&] {
for (size_t i = 0; i < types.size(); ++i) {
......@@ -507,6 +585,11 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh,
fout << "</Cells>\n";
fout << "</Piece>\n";
fout << "</UnstructuredGrid>\n";
fout << "<AppendedData encoding=\"raw\">\n";
fout << "_";
serialize_data_list.write(fout);
fout << '\n';
fout << "</AppendedData>\n";
fout << "</VTKFile>\n";
}
......
......@@ -14,6 +14,8 @@ class IMesh;
class VTKWriter : public WriterBase
{
private:
class SerializedDataList;
std::string _getDateAndVersionComment() const;
std::string _getFilenamePVTU() const;
......@@ -56,42 +58,64 @@ class VTKWriter : public WriterBase
struct VTKType;
template <typename DataType>
void _write_array(std::ofstream& os, const std::string& name, const Array<DataType>& item_value) const;
void _write_array(std::ofstream& os,
const std::string& name,
const Array<DataType>& item_value,
SerializedDataList& serialized_data_list) const;
template <size_t N, typename DataType>
void _write_array(std::ofstream& os, const std::string& name, const Array<TinyVector<N, DataType>>& item_value) const;
void _write_array(std::ofstream& os,
const std::string& name,
const Array<TinyVector<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const;
template <typename DataType>
void _write_node_value(std::ofstream& os, const std::string& name, const NodeValue<const DataType>& item_value) const;
void _write_node_value(std::ofstream& os,
const std::string& name,
const NodeValue<const DataType>& item_value,
SerializedDataList& serialized_data_list) const;
template <size_t N, typename DataType>
void _write_node_value(std::ofstream& os,
const std::string& name,
const NodeValue<const TinyVector<N, DataType>>& item_value) const;
const NodeValue<const TinyVector<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const;
template <size_t N, typename DataType>
void _write_node_value(std::ofstream& os,
const std::string& name,
const NodeValue<const TinyMatrix<N, DataType>>& item_value) const;
const NodeValue<const TinyMatrix<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const;
template <typename DataType>
void _write_node_value(std::ofstream&, const std::string&, const CellValue<const DataType>&) const;
void _write_node_value(std::ofstream&,
const std::string&,
const CellValue<const DataType>&,
SerializedDataList&) const;
template <typename DataType>
void _write_cell_value(std::ofstream& os, const std::string& name, const CellValue<const DataType>& item_value) const;
void _write_cell_value(std::ofstream& os,
const std::string& name,
const CellValue<const DataType>& item_value,
SerializedDataList& serialized_data_list) const;
template <size_t N, typename DataType>
void _write_cell_value(std::ofstream& os,
const std::string& name,
const CellValue<const TinyVector<N, DataType>>& item_value) const;
const CellValue<const TinyVector<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const;
template <size_t N, typename DataType>
void _write_cell_value(std::ofstream& os,
const std::string& name,
const CellValue<const TinyMatrix<N, DataType>>& item_value) const;
const CellValue<const TinyMatrix<N, DataType>>& item_value,
SerializedDataList& serialized_data_list) const;
template <typename DataType>
void _write_cell_value(std::ofstream&, const std::string&, const NodeValue<const DataType>&) const;
void _write_cell_value(std::ofstream&,
const std::string&,
const NodeValue<const DataType>&,
SerializedDataList&) const;
template <typename MeshType>
void _write(const std::shared_ptr<const MeshType>& mesh,
......
......@@ -9,6 +9,8 @@
#cmakedefine SYSTEM_IS_DARWIN
#cmakedefine SYSTEM_IS_WINDOWS
#cmakedefine PUGS_LITTLE_ENDIAN
#define PUGS_BUILD_TYPE "@CMAKE_BUILD_TYPE@"
#define PUGS_BINARY_DIR "@PUGS_BINARY_DIR@"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment