From 8eddcc39a4ff6cf851219e812abe7ac77ed5d86d Mon Sep 17 00:00:00 2001 From: Luca Heltai Date: Fri, 17 Jan 2020 18:23:15 +0100 Subject: [PATCH] Write and read VTU format that contains serialized triangulation. --- .../20200117LucaHeltaiNicolaGiuliani_bis | 4 + include/deal.II/grid/grid_in.h | 22 +++++ include/deal.II/grid/grid_out.h | 15 +++- source/grid/grid_in.cc | 43 +++++++++- source/grid/grid_out.cc | 23 +++++- tests/grid/grid_in_out_vtu_01.cc | 81 +++++++++++++++++++ tests/grid/grid_in_out_vtu_01.output | 2 + 7 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 doc/news/changes/minor/20200117LucaHeltaiNicolaGiuliani_bis create mode 100644 tests/grid/grid_in_out_vtu_01.cc create mode 100644 tests/grid/grid_in_out_vtu_01.output diff --git a/doc/news/changes/minor/20200117LucaHeltaiNicolaGiuliani_bis b/doc/news/changes/minor/20200117LucaHeltaiNicolaGiuliani_bis new file mode 100644 index 0000000000..4fb5d3e9d0 --- /dev/null +++ b/doc/news/changes/minor/20200117LucaHeltaiNicolaGiuliani_bis @@ -0,0 +1,4 @@ +New: GridOut::write_vtu() and GridIn::read_vtu() allow to save and restore a locally refined triangulation, +using a xml section in the vtu file that is ignored by vtu readers. +
+(Luca Heltai, Nicola Giuliani, 2020/01/17) diff --git a/include/deal.II/grid/grid_in.h b/include/deal.II/grid/grid_in.h index 04dadbf15a..84e2f35634 100644 --- a/include/deal.II/grid/grid_in.h +++ b/include/deal.II/grid/grid_in.h @@ -333,6 +333,8 @@ public: tecplot, /// Use read_vtk() vtk, + /// Use read_vtu() + vtu, /// Use read_assimp() assimp, }; @@ -404,6 +406,26 @@ public: void read_vtk(std::istream &in); + /** + * Read grid data from a unstructured vtu file, saved by deal.II using + * GridOut::write_vtu(), with the flag + * GridOutFlags::Vtu::serialize_triangulation set to true. + * + * Notice that this function does not support reading in arbitrary vtu files, + * but only files that were written by deal.II itself, using the function + * GridOut::write_vtu and setting GridOutFlags::Vtu::serialize_triangulation + * to true. + * + * When this flag is set to true, the generated vtu file contains the + * triangulation in a xml section which is ignored by vtu general vtu readers. + * If this section is absent, an exception is thrown. + * + * @author Luca Heltai, Nicola Giuliani, 2020 + */ + void + read_vtu(std::istream &in); + + /** * Read grid data from an unv file as generated by the Salome mesh * generator. Numerical data is ignored. diff --git a/include/deal.II/grid/grid_out.h b/include/deal.II/grid/grid_out.h index 22c8472c72..3dc7ef5168 100644 --- a/include/deal.II/grid/grid_out.h +++ b/include/deal.II/grid/grid_out.h @@ -921,12 +921,23 @@ namespace GridOutFlags /** * Flags for grid output in Vtu format. These flags are the same as those - * declared in DataOutBase::VtkFlags. + * declared in DataOutBase::VtkFlags, with the addition of a flag that + * determines if you want to add a entry in the vtu file (which is really + * a xml file) containing the entire serialization of the triangulation. * * @ingroup output */ struct Vtu : public DataOutBase::VtkFlags - {}; + { + Vtu(const bool serialize_triangulation = false) + : serialize_triangulation(serialize_triangulation) + {} + + /** + * Add to the vtu file also the serialized triangulation. + */ + bool serialize_triangulation; + }; } // namespace GridOutFlags diff --git a/source/grid/grid_in.cc b/source/grid/grid_in.cc index 105ce03f79..bbff7456d8 100644 --- a/source/grid/grid_in.cc +++ b/source/grid/grid_in.cc @@ -23,7 +23,11 @@ #include #include +#include #include +#include +#include +#include #include #include @@ -495,6 +499,34 @@ GridIn::read_vtk(std::istream &in) } + +template +void +GridIn::read_vtu(std::istream &in) +{ + namespace pt = boost::property_tree; + pt::ptree tree; + pt::read_xml(in, tree); + auto section = tree.get_optional("VTKFile.dealiiData"); + + AssertThrow(section, + ExcMessage( + "While reading a VTU file, failed to find dealiiData section. " + "Notice that we can only read grid files in .vtu format that " + "were created by the deal.II library, using a call to " + "GridOut::write_vtu(), where the flag " + "GridOutFlags::Vtu::serialize_triangulation is set to true.")); + + const auto decoded = + Utilities::decode_base64({section->begin(), section->end() - 1}); + const auto string_archive = + Utilities::decompress({decoded.begin(), decoded.end()}); + std::istringstream in_stream(string_archive); + boost::archive::binary_iarchive ia(in_stream); + tria->load(ia, 0); +} + + template void GridIn::read_unv(std::istream &in) @@ -3376,6 +3408,10 @@ GridIn::read(std::istream &in, Format format) read_vtk(in); return; + case vtu: + read_vtu(in); + return; + case unv: read_unv(in); return; @@ -3430,6 +3466,8 @@ GridIn::default_suffix(const Format format) return ".msh"; case vtk: return ".vtk"; + case vtu: + return ".vtu"; case unv: return ".unv"; case ucd: @@ -3467,6 +3505,9 @@ GridIn::parse_format(const std::string &format_name) if (format_name == "vtk") return vtk; + if (format_name == "vtu") + return vtu; + // This is also the typical extension of Abaqus input files. if (format_name == "inp") return ucd; @@ -3512,7 +3553,7 @@ template std::string GridIn::get_format_names() { - return "dbmesh|msh|unv|vtk|ucd|abaqus|xda|netcdf|tecplot|assimp"; + return "dbmesh|msh|unv|vtk|vtu|ucd|abaqus|xda|netcdf|tecplot|assimp"; } diff --git a/source/grid/grid_out.cc b/source/grid/grid_out.cc index e2f173a744..f03760be66 100644 --- a/source/grid/grid_out.cc +++ b/source/grid/grid_out.cc @@ -29,6 +29,9 @@ #include +#include +#include + #include #include #include @@ -38,7 +41,6 @@ #include #include - DEAL_II_NAMESPACE_OPEN @@ -3369,7 +3371,9 @@ GridOut::write_vtu(const Triangulation &tria, std::vector> patches; patches.reserve(tria.n_active_cells()); generate_triangulation_patches(patches, tria.begin_active(), tria.end()); - DataOutBase::write_vtu( + + DataOutBase::write_vtu_header(out, vtu_flags); + DataOutBase::write_vtu_main( patches, triangulation_patch_data_names(), std::vector< @@ -3379,7 +3383,22 @@ GridOut::write_vtu(const Triangulation &tria, DataComponentInterpretation::DataComponentInterpretation>>(), vtu_flags, out); + if (vtu_flags.serialize_triangulation) + { + out << " \n"; + out << ""; + std::stringstream outstring; + boost::archive::binary_oarchive ia(outstring); + tria.save(ia, 0); + const auto compressed = Utilities::compress(outstring.str()); + out << Utilities::encode_base64({compressed.begin(), compressed.end()}); + out << "\n\n"; + out << "\n"; + } + else + DataOutBase::write_vtu_footer(out); + out << std::flush; AssertThrow(out, ExcIO()); } diff --git a/tests/grid/grid_in_out_vtu_01.cc b/tests/grid/grid_in_out_vtu_01.cc new file mode 100644 index 0000000000..483829d503 --- /dev/null +++ b/tests/grid/grid_in_out_vtu_01.cc @@ -0,0 +1,81 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2020 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + +// read and write a 2d file in the VTU format + +#include +#include +#include +#include + +#include + +#include + +#include "../tests.h" + +int +main() +{ + initlog(); + + Triangulation<2> tria; + Triangulation<2> tria2; + GridGenerator::hyper_ball(tria); + + for (const auto cell : tria.active_cell_iterators()) + { + if (cell->center()[0] < 0) + cell->set_refine_flag(); + } + tria.execute_coarsening_and_refinement(); + + for (const auto cell : tria.active_cell_iterators()) + { + if (cell->center()[1] < 0) + cell->set_refine_flag(); + } + tria.execute_coarsening_and_refinement(); + + { + std::ofstream out("grid.vtu"); + GridOut go; + GridOutFlags::Vtu vtu_flags(true); + go.set_flags(vtu_flags); + go.write_vtu(tria, out); + } + { + std::ifstream in("grid.vtu"); + GridIn<2> gi; + gi.attach_triangulation(tria2); + gi.read_vtu(in); + } + std::stringstream stream1; + std::stringstream stream2; + { + boost::archive::text_oarchive oa(stream1); + tria.save(oa, 0); + } + { + boost::archive::text_oarchive oa(stream2); + tria2.save(oa, 0); + } + if (stream1.str() == stream2.str()) + deallog << "OK" << std::endl; + else + deallog << "Not OK" << std::endl; + std::remove("grid.vtu"); +} \ No newline at end of file diff --git a/tests/grid/grid_in_out_vtu_01.output b/tests/grid/grid_in_out_vtu_01.output new file mode 100644 index 0000000000..0fd8fc12f0 --- /dev/null +++ b/tests/grid/grid_in_out_vtu_01.output @@ -0,0 +1,2 @@ + +DEAL::OK -- 2.39.5