From 87e3c60964667e5434c95a975c502d4645224154 Mon Sep 17 00:00:00 2001 From: David Wells Date: Mon, 13 Jan 2020 23:21:45 -0500 Subject: [PATCH] Implement GridGenerator::replicate_triangulation(). --- doc/doxygen/images/replicated_tria_2d.png | Bin 0 -> 8761 bytes doc/doxygen/images/replicated_tria_3d.png | Bin 0 -> 40080 bytes .../minor/20200113DavidWellsVictorZheng | 5 + include/deal.II/grid/grid_generator.h | 53 ++++ source/grid/grid_generator.cc | 226 ++++++++++++++++++ source/grid/grid_generator.inst.in | 6 + tests/grid/replicate_triangulation_01.cc | 76 ++++++ tests/grid/replicate_triangulation_01.output | 105 ++++++++ tests/grid/replicate_triangulation_02.cc | 81 +++++++ tests/grid/replicate_triangulation_02.output | 59 +++++ 10 files changed, 611 insertions(+) create mode 100644 doc/doxygen/images/replicated_tria_2d.png create mode 100644 doc/doxygen/images/replicated_tria_3d.png create mode 100644 doc/news/changes/minor/20200113DavidWellsVictorZheng create mode 100644 tests/grid/replicate_triangulation_01.cc create mode 100644 tests/grid/replicate_triangulation_01.output create mode 100644 tests/grid/replicate_triangulation_02.cc create mode 100644 tests/grid/replicate_triangulation_02.output diff --git a/doc/doxygen/images/replicated_tria_2d.png b/doc/doxygen/images/replicated_tria_2d.png new file mode 100644 index 0000000000000000000000000000000000000000..a80aeab963d4a688734c28e0b90abd62cb1c9aa2 GIT binary patch literal 8761 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%0D%xu&<+*u_gg&g@uJ>P|5c?I{nM~%Pt1X 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

|oa;M*lQ0h(M*B1I1M6~yp*DvijBf;p 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 X9`gSS809w00s)Ajt{J9W2Oset)DYV8 literal 0 HcmV?d00001 diff --git a/doc/news/changes/minor/20200113DavidWellsVictorZheng b/doc/news/changes/minor/20200113DavidWellsVictorZheng new file mode 100644 index 0000000000..4ec53922b8 --- /dev/null +++ b/doc/news/changes/minor/20200113DavidWellsVictorZheng @@ -0,0 +1,5 @@ +New: Added a new function GridGenerator::replicate_triangulation() for creating +a new triangulation by copying a given triangulation repeatedly along the +coordinate axes. +
+(David Wells, Victor Zheng, 2020/01/13) diff --git a/include/deal.II/grid/grid_generator.h b/include/deal.II/grid/grid_generator.h index 8126aae9f5..21b0cd4087 100644 --- a/include/deal.II/grid/grid_generator.h +++ b/include/deal.II/grid/grid_generator.h @@ -1551,6 +1551,59 @@ namespace GridGenerator const double duplicated_vertex_tolerance = 1.0e-12, const bool copy_manifold_ids = false); + /** + * \brief Replicate a given triangulation in multiple coordinate axes + * + * @param input The triangulation which will be replicated along the + * coordinate axes. + * + * @param extents A vector with dim entries specifying how many + * copies of a triangulation should be present along each coordinate axis. + * + * @param result The triangulation to be created. It needs to be empty upon + * calling this function. + * + * This function creates a new Triangulation equal to a + * dim-dimensional array of copies of @p input. Copies of @p input + * are created by translating @p input along the coordinate axes. Boundary + * ids of faces (but not lines in 3D) and all manifold ids are copied but + * Manifold objects are not since most Manifold objects do not work + * correctly when a Triangulation has been translated. + * + * To see how this works, consider the following code: + * @code + * Triangulation<2> input; + * GridGenerator::hyper_cube_with_cylindrical_hole(input); + * Triangulation<2> output; + * GridGenerator::replicate_triangulation(input, {3, 2}, output); + * @endcode + * results in + * + * @image html replicated_tria_2d.png + * + * And, similarly, in 3D: + * @code + * Triangulation<3> input; + * GridGenerator::hyper_cross(1, 1, 1, 2, 1, 2); + * Triangulation<3> output; + * GridGenerator::replicate_triangulation(input, {3, 2, 1}, output); + * @endcode + * results in + * + * @image html replicated_tria_3d.png + * + * @note This function determines the spacing of the copies of @p input + * based on the BoundingBox of @p input. If the boundary faces of @p input + * are not aligned with the coordinate axes then the copies might not share + * common faces; i.e., this function is intended for simple geometries with + * boundary faces aligned along the coordinate axes. + */ + template + void + replicate_triangulation(const Triangulation &input, + const std::vector & extents, + Triangulation & result); + /** * Given the two triangulations specified as the first two arguments, create * the triangulation that contains the finest cells of both triangulation diff --git a/source/grid/grid_generator.cc b/source/grid/grid_generator.cc index a09b1c086c..9e19f3f724 100644 --- a/source/grid/grid_generator.cc +++ b/source/grid/grid_generator.cc @@ -5845,6 +5845,232 @@ namespace GridGenerator + namespace + { + /** + * Merging or replicating triangulations usually results in duplicated + * boundary objects - in particular, faces that used to be boundary faces + * will now be internal faces. + * + * This function modifies @p subcell_data by detecting duplicated objects, + * marking said duplicates as internal faces, and then deleting all but + * one of the duplicates. + * + * This function relies on some implementation details of + * create_triangulation to uniquify objects in SubCellData - in + * particular, quadrilaterals are only identified by their lines and not + * by their orientation or volume, so rotating and flipping a + * quadrilateral doesn't effect the way said quadrilateral is read by that + * function. + * + * @warning even though this function is implemented for structdim 1 and + * structdim 2, it will produce wrong results when called for + * boundary lines in 3D in most cases since a boundary line can be shared + * by an arbitrary number of cells in 3D. + */ + template + void + delete_duplicated_objects(std::vector> &subcell_data) + { + static_assert(structdim == 1 || structdim == 2, + "This function is only implemented for lines and " + "quadrilaterals."); + // start by making sure that all objects representing the same vertices + // are numbered in the same way by canonicalizing the numberings. This + // makes it possible to detect duplicates. + for (CellData &cell_data : subcell_data) + { + if (structdim == 1) + std::sort(std::begin(cell_data.vertices), + std::end(cell_data.vertices)); + else if (structdim == 2) + { + // rotate the vertex numbers so that the lowest one is first + std::array renumbering; + std::copy(std::begin(cell_data.vertices), + std::end(cell_data.vertices), + renumbering.begin()); + + // convert to old style vertex numbering. This makes the + // permutations easy since the valid configurations are + // + // 3 2 2 1 1 0 0 3 + // 0 1 3 0 2 3 1 2 + // (0123) (3012) (2310) (1230) + // + // rather than the lexical ordering which is harder to permute + // by rotation. + std::swap(renumbering[2], renumbering[3]); + std::rotate(renumbering.begin(), + std::min_element(renumbering.begin(), + renumbering.end()), + renumbering.end()); + // convert to new style + std::swap(renumbering[2], renumbering[3]); + // deal with cases where we might have + // + // 3 2 1 2 + // 0 1 0 3 + // + // by forcing the second vertex (in lexical ordering) to be + // smaller than the third + if (renumbering[1] > renumbering[2]) + std::swap(renumbering[1], renumbering[2]); + std::copy(renumbering.begin(), + renumbering.end(), + std::begin(cell_data.vertices)); + } + } + + // Now that all cell objects have been canonicalized they can be sorted: + auto compare = [](const CellData &a, + const CellData &b) { + return std::lexicographical_compare(std::begin(a.vertices), + std::end(a.vertices), + std::begin(b.vertices), + std::end(b.vertices)); + }; + std::sort(subcell_data.begin(), subcell_data.end(), compare); + + // Finally, determine which objects are duplicates. Duplicates are + // assumed to be interior objects, so delete all but one and change the + // boundary id: + auto left = subcell_data.begin(); + while (left != subcell_data.end()) + { + const auto right = + std::upper_bound(left, subcell_data.end(), *left, compare); + // if the range has more than one item, then there are duplicates - + // set all boundary ids in the range to the internal boundary id + if (left + 1 != right) + for (auto it = left; it != right; ++it) + { + it->boundary_id = numbers::internal_face_boundary_id; + Assert(it->manifold_id == left->manifold_id, + ExcMessage( + "In the process of grid generation a single " + "line or quadrilateral has been assigned two " + "different manifold ids. This can happen when " + "a Triangulation is copied, e.g., via " + "GridGenerator::replicate_triangulation() and " + "not all external boundary faces have the same " + "manifold id. Double check that all faces " + "which you expect to be merged together have " + "the same manifold id.")); + } + left = right; + } + + subcell_data.erase(std::unique(subcell_data.begin(), subcell_data.end()), + subcell_data.end()); + } + } // namespace + + + + template + void + replicate_triangulation(const Triangulation &input, + const std::vector & extents, + Triangulation & result) + { + AssertDimension(dim, extents.size()); +#ifdef DEBUG + for (const auto &extent : extents) + Assert(0 < extent, + ExcMessage("The Triangulation must be copied at least one time in " + "each coordinate dimension.")); +#endif + const BoundingBox bbox(input.get_vertices()); + const auto & min = bbox.get_boundary_points().first; + const auto & max = bbox.get_boundary_points().second; + + std::array, dim> offsets; + for (unsigned int d = 0; d < dim; ++d) + offsets[d][d] = max[d] - min[d]; + + Triangulation tria_to_replicate; + tria_to_replicate.copy_triangulation(input); + for (unsigned int d = 0; d < dim; ++d) + { + std::vector> input_vertices; + std::vector> input_cell_data; + SubCellData input_subcell_data; + std::tie(input_vertices, input_cell_data, input_subcell_data) = + GridTools::get_coarse_mesh_description(tria_to_replicate); + std::vector> output_vertices = input_vertices; + std::vector> output_cell_data = input_cell_data; + SubCellData output_subcell_data = input_subcell_data; + + for (unsigned int k = 1; k < extents[d]; ++k) + { + const std::size_t vertex_offset = k * input_vertices.size(); + // vertices + for (const Point &point : input_vertices) + output_vertices.push_back(point + double(k) * offsets[d]); + // cell data + for (const CellData &cell_data : input_cell_data) + { + output_cell_data.push_back(cell_data); + for (unsigned int &vertex : output_cell_data.back().vertices) + vertex += vertex_offset; + } + // subcell data + for (const CellData<1> &boundary_line : + input_subcell_data.boundary_lines) + { + output_subcell_data.boundary_lines.push_back(boundary_line); + for (unsigned int &vertex : + output_subcell_data.boundary_lines.back().vertices) + vertex += vertex_offset; + } + for (const CellData<2> &boundary_quad : + input_subcell_data.boundary_quads) + { + output_subcell_data.boundary_quads.push_back(boundary_quad); + for (unsigned int &vertex : + output_subcell_data.boundary_quads.back().vertices) + vertex += vertex_offset; + } + } + // check all vertices: since the grid is coarse, most will be on the + // boundary anyway + std::vector boundary_vertices; + GridTools::delete_duplicated_vertices( + output_vertices, + output_cell_data, + output_subcell_data, + boundary_vertices, + 1e-6 * input.begin_active()->diameter()); + // delete_duplicated_vertices also deletes any unused vertices + // deal with any reordering issues created by delete_duplicated_vertices + GridReordering::reorder_cells(output_cell_data, true); + // clean up the boundary ids of the boundary objects: note that we + // have to do this after delete_duplicated_vertices so that boundary + // objects are actually duplicated at this point + if (dim == 2) + delete_duplicated_objects(output_subcell_data.boundary_lines); + else if (dim == 3) + { + delete_duplicated_objects(output_subcell_data.boundary_quads); + for (CellData<1> &boundary_line : + output_subcell_data.boundary_lines) + // set boundary lines to the default value - let + // create_triangulation figure out the rest. + boundary_line.boundary_id = numbers::internal_face_boundary_id; + } + + tria_to_replicate.clear(); + tria_to_replicate.create_triangulation(output_vertices, + output_cell_data, + output_subcell_data); + } + + result.copy_triangulation(tria_to_replicate); + } + + + template void create_union_triangulation( diff --git a/source/grid/grid_generator.inst.in b/source/grid/grid_generator.inst.in index 76522efd9f..0e6c15512d 100644 --- a/source/grid/grid_generator.inst.in +++ b/source/grid/grid_generator.inst.in @@ -97,6 +97,12 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS) const double duplicated_vertex_tolerance, const bool copy_manifold_ids); + template void + replicate_triangulation( + const Triangulation &input, + const std::vector & extents, + Triangulation &result); + template void create_union_triangulation( const Triangulation diff --git a/tests/grid/replicate_triangulation_01.cc b/tests/grid/replicate_triangulation_01.cc new file mode 100644 index 0000000000..f89acb70c8 --- /dev/null +++ b/tests/grid/replicate_triangulation_01.cc @@ -0,0 +1,76 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2018 - 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 at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +// test GridGenerator::replicate_triangulation + +#include +#include +#include +#include + +#include "../tests.h" + +void +test() +{ + { + Triangulation<1, 1> tr1; + GridGenerator::hyper_cube(tr1); + std::vector reps1 = {2}; + Triangulation<1> res1; + GridGenerator::replicate_triangulation(tr1, reps1, res1); + deallog << "1d triangulation has the following cell centers:" << std::endl; + for (const auto &cell : res1.active_cell_iterators()) + deallog << '(' << cell->center() << ')' << std::endl; + + deallog << "Number of global vertices: " << res1.n_vertices() << std::endl; + } + + { + Triangulation<2, 2> tr2; + GridGenerator::hyper_cube_with_cylindrical_hole(tr2, 0.3, 0.5); + const std::vector reps2 = {{2, 2}}; + Triangulation<2, 2> res2; + GridGenerator::replicate_triangulation(tr2, reps2, res2); + deallog << "2d triangulation has the following cell centers:" << std::endl; + for (const auto &cell : res2.active_cell_iterators()) + deallog << '(' << cell->center() << ')' << std::endl; + + deallog << "Number of global vertices: " << res2.n_vertices() << std::endl; + } + + { + Triangulation<3, 3> tr3; + std::vector reps3 = {2, 2, 2}; + GridGenerator::subdivided_hyper_rectangle(tr3, + reps3, + Point<3>(-0.7, -0.5, -1.5), + Point<3>(0.5, 0.5, 2.)); + Triangulation<3, 3> res3; + GridGenerator::replicate_triangulation(tr3, reps3, res3); + deallog << "3d triangulation has the following cell centers:" << std::endl; + for (const auto &cell : res3.active_cell_iterators()) + deallog << '(' << cell->center() << ')' << std::endl; + + deallog << "Number of global vertices: " << res3.n_vertices() << std::endl; + } +} + +int +main() +{ + initlog(); + test(); +} diff --git a/tests/grid/replicate_triangulation_01.output b/tests/grid/replicate_triangulation_01.output new file mode 100644 index 0000000000..1a154bf5e2 --- /dev/null +++ b/tests/grid/replicate_triangulation_01.output @@ -0,0 +1,105 @@ + +DEAL::1d triangulation has the following cell centers: +DEAL::(0.500000) +DEAL::(1.50000) +DEAL::Number of global vertices: 3 +DEAL::2d triangulation has the following cell centers: +DEAL::(0.378033 0.178033) +DEAL::(0.178033 0.378033) +DEAL::(-0.178033 0.378033) +DEAL::(-0.378033 0.178033) +DEAL::(-0.378033 -0.178033) +DEAL::(-0.178033 -0.378033) +DEAL::(0.178033 -0.378033) +DEAL::(0.378033 -0.178033) +DEAL::(1.37803 0.178033) +DEAL::(1.17803 0.378033) +DEAL::(0.821967 0.378033) +DEAL::(0.621967 0.178033) +DEAL::(0.621967 -0.178033) +DEAL::(0.821967 -0.378033) +DEAL::(1.17803 -0.378033) +DEAL::(1.37803 -0.178033) +DEAL::(0.378033 1.17803) +DEAL::(0.178033 1.37803) +DEAL::(-0.178033 1.37803) +DEAL::(-0.378033 1.17803) +DEAL::(-0.378033 0.821967) +DEAL::(-0.178033 0.621967) +DEAL::(0.178033 0.621967) +DEAL::(0.378033 0.821967) +DEAL::(1.37803 1.17803) +DEAL::(1.17803 1.37803) +DEAL::(0.821967 1.37803) +DEAL::(0.621967 1.17803) +DEAL::(0.621967 0.821967) +DEAL::(0.821967 0.621967) +DEAL::(1.17803 0.621967) +DEAL::(1.37803 0.821967) +DEAL::Number of global vertices: 53 +DEAL::3d triangulation has the following cell centers: +DEAL::(-0.400000 -0.250000 -0.625000) +DEAL::(0.200000 -0.250000 -0.625000) +DEAL::(-0.400000 0.250000 -0.625000) +DEAL::(0.200000 0.250000 -0.625000) +DEAL::(-0.400000 -0.250000 1.12500) +DEAL::(0.200000 -0.250000 1.12500) +DEAL::(-0.400000 0.250000 1.12500) +DEAL::(0.200000 0.250000 1.12500) +DEAL::(0.800000 -0.250000 -0.625000) +DEAL::(1.40000 -0.250000 -0.625000) +DEAL::(0.800000 0.250000 -0.625000) +DEAL::(1.40000 0.250000 -0.625000) +DEAL::(0.800000 -0.250000 1.12500) +DEAL::(1.40000 -0.250000 1.12500) +DEAL::(0.800000 0.250000 1.12500) +DEAL::(1.40000 0.250000 1.12500) +DEAL::(-0.400000 0.750000 -0.625000) +DEAL::(0.200000 0.750000 -0.625000) +DEAL::(-0.400000 1.25000 -0.625000) +DEAL::(0.200000 1.25000 -0.625000) +DEAL::(-0.400000 0.750000 1.12500) +DEAL::(0.200000 0.750000 1.12500) +DEAL::(-0.400000 1.25000 1.12500) +DEAL::(0.200000 1.25000 1.12500) +DEAL::(0.800000 0.750000 -0.625000) +DEAL::(1.40000 0.750000 -0.625000) +DEAL::(0.800000 1.25000 -0.625000) +DEAL::(1.40000 1.25000 -0.625000) +DEAL::(0.800000 0.750000 1.12500) +DEAL::(1.40000 0.750000 1.12500) +DEAL::(0.800000 1.25000 1.12500) +DEAL::(1.40000 1.25000 1.12500) +DEAL::(-0.400000 -0.250000 2.87500) +DEAL::(0.200000 -0.250000 2.87500) +DEAL::(-0.400000 0.250000 2.87500) +DEAL::(0.200000 0.250000 2.87500) +DEAL::(-0.400000 -0.250000 4.62500) +DEAL::(0.200000 -0.250000 4.62500) +DEAL::(-0.400000 0.250000 4.62500) +DEAL::(0.200000 0.250000 4.62500) +DEAL::(0.800000 -0.250000 2.87500) +DEAL::(1.40000 -0.250000 2.87500) +DEAL::(0.800000 0.250000 2.87500) +DEAL::(1.40000 0.250000 2.87500) +DEAL::(0.800000 -0.250000 4.62500) +DEAL::(1.40000 -0.250000 4.62500) +DEAL::(0.800000 0.250000 4.62500) +DEAL::(1.40000 0.250000 4.62500) +DEAL::(-0.400000 0.750000 2.87500) +DEAL::(0.200000 0.750000 2.87500) +DEAL::(-0.400000 1.25000 2.87500) +DEAL::(0.200000 1.25000 2.87500) +DEAL::(-0.400000 0.750000 4.62500) +DEAL::(0.200000 0.750000 4.62500) +DEAL::(-0.400000 1.25000 4.62500) +DEAL::(0.200000 1.25000 4.62500) +DEAL::(0.800000 0.750000 2.87500) +DEAL::(1.40000 0.750000 2.87500) +DEAL::(0.800000 1.25000 2.87500) +DEAL::(1.40000 1.25000 2.87500) +DEAL::(0.800000 0.750000 4.62500) +DEAL::(1.40000 0.750000 4.62500) +DEAL::(0.800000 1.25000 4.62500) +DEAL::(1.40000 1.25000 4.62500) +DEAL::Number of global vertices: 125 diff --git a/tests/grid/replicate_triangulation_02.cc b/tests/grid/replicate_triangulation_02.cc new file mode 100644 index 0000000000..5968abf381 --- /dev/null +++ b/tests/grid/replicate_triangulation_02.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 at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +// test GridGenerator::replicate_triangulation's ability to copy boundary ids +// correctly + +#include +#include +#include +#include + +#include "../tests.h" + +void +test() +{ + // no subcell data in 1D so nothing to test + + { + Triangulation<2, 2> tr2; + GridGenerator::hyper_cube(tr2, 0.0, 1.0, true); + const std::vector reps2 = {{2, 2}}; + Triangulation<2, 2> res2; + GridGenerator::replicate_triangulation(tr2, reps2, res2); + for (const auto &face : res2.active_face_iterators()) + if (face->at_boundary()) + deallog << "face: " << face->center() + << " boundary id: " << face->boundary_id() << std::endl; + } + + { + Triangulation<3, 3> tr3; + GridGenerator::hyper_cube(tr3, 0.0, 1.0, true); + // actually set some boundary line boundary ids to something besides zero + // for testing purposes + for (auto &face : tr3.active_face_iterators()) + { + if (face->boundary_id() == 4) + face->set_all_boundary_ids(4); + else if (face->boundary_id() == 5) + face->set_all_boundary_ids(5); + } + // set all (i.e., overwrite two set above) lines on the x = 1 face to + // boundary id 1 + for (auto &face : tr3.active_face_iterators()) + if (face->boundary_id() == 1) + face->set_all_boundary_ids(1); + std::vector reps3 = {2, 1, 1}; + Triangulation<3, 3> res3; + GridGenerator::replicate_triangulation(tr3, reps3, res3); + for (const auto &face : res3.active_face_iterators()) + if (face->at_boundary()) + { + deallog << "face: " << face->center() + << " boundary id: " << face->boundary_id() << std::endl; + for (unsigned int l = 0; l < GeometryInfo<2>::lines_per_cell; ++l) + deallog << "line: " << face->line(l)->center() + << " boundary id: " << face->line(l)->boundary_id() + << std::endl; + } + } +} + +int +main() +{ + initlog(); + test(); +} diff --git a/tests/grid/replicate_triangulation_02.output b/tests/grid/replicate_triangulation_02.output new file mode 100644 index 0000000000..2fc72ee282 --- /dev/null +++ b/tests/grid/replicate_triangulation_02.output @@ -0,0 +1,59 @@ + +DEAL::face: 0.500000 0.00000 boundary id: 2 +DEAL::face: 0.00000 0.500000 boundary id: 0 +DEAL::face: 1.50000 0.00000 boundary id: 2 +DEAL::face: 0.00000 1.50000 boundary id: 0 +DEAL::face: 2.00000 0.500000 boundary id: 1 +DEAL::face: 2.00000 1.50000 boundary id: 1 +DEAL::face: 0.500000 2.00000 boundary id: 3 +DEAL::face: 1.50000 2.00000 boundary id: 3 +DEAL::face: 0.500000 0.00000 0.500000 boundary id: 2 +DEAL::line: 0.500000 0.00000 0.00000 boundary id: 0 +DEAL::line: 0.500000 0.00000 1.00000 boundary id: 0 +DEAL::line: 0.00000 0.00000 0.500000 boundary id: 0 +DEAL::line: 1.00000 0.00000 0.500000 boundary id: 0 +DEAL::face: 0.500000 0.500000 0.00000 boundary id: 4 +DEAL::line: 0.00000 0.500000 0.00000 boundary id: 0 +DEAL::line: 1.00000 0.500000 0.00000 boundary id: 0 +DEAL::line: 0.500000 0.00000 0.00000 boundary id: 0 +DEAL::line: 0.500000 1.00000 0.00000 boundary id: 0 +DEAL::face: 0.00000 0.500000 0.500000 boundary id: 0 +DEAL::line: 0.00000 0.00000 0.500000 boundary id: 0 +DEAL::line: 0.00000 1.00000 0.500000 boundary id: 0 +DEAL::line: 0.00000 0.500000 0.00000 boundary id: 0 +DEAL::line: 0.00000 0.500000 1.00000 boundary id: 0 +DEAL::face: 1.50000 0.500000 0.00000 boundary id: 4 +DEAL::line: 1.00000 0.500000 0.00000 boundary id: 0 +DEAL::line: 2.00000 0.500000 0.00000 boundary id: 0 +DEAL::line: 1.50000 0.00000 0.00000 boundary id: 0 +DEAL::line: 1.50000 1.00000 0.00000 boundary id: 0 +DEAL::face: 1.50000 0.00000 0.500000 boundary id: 2 +DEAL::line: 1.50000 0.00000 0.00000 boundary id: 0 +DEAL::line: 1.50000 0.00000 1.00000 boundary id: 0 +DEAL::line: 1.00000 0.00000 0.500000 boundary id: 0 +DEAL::line: 2.00000 0.00000 0.500000 boundary id: 0 +DEAL::face: 0.500000 1.00000 0.500000 boundary id: 3 +DEAL::line: 0.500000 1.00000 0.00000 boundary id: 0 +DEAL::line: 0.500000 1.00000 1.00000 boundary id: 0 +DEAL::line: 0.00000 1.00000 0.500000 boundary id: 0 +DEAL::line: 1.00000 1.00000 0.500000 boundary id: 0 +DEAL::face: 1.50000 1.00000 0.500000 boundary id: 3 +DEAL::line: 1.50000 1.00000 0.00000 boundary id: 0 +DEAL::line: 1.50000 1.00000 1.00000 boundary id: 0 +DEAL::line: 1.00000 1.00000 0.500000 boundary id: 0 +DEAL::line: 2.00000 1.00000 0.500000 boundary id: 0 +DEAL::face: 0.500000 0.500000 1.00000 boundary id: 5 +DEAL::line: 0.00000 0.500000 1.00000 boundary id: 0 +DEAL::line: 1.00000 0.500000 1.00000 boundary id: 0 +DEAL::line: 0.500000 0.00000 1.00000 boundary id: 0 +DEAL::line: 0.500000 1.00000 1.00000 boundary id: 0 +DEAL::face: 1.50000 0.500000 1.00000 boundary id: 5 +DEAL::line: 1.00000 0.500000 1.00000 boundary id: 0 +DEAL::line: 2.00000 0.500000 1.00000 boundary id: 0 +DEAL::line: 1.50000 0.00000 1.00000 boundary id: 0 +DEAL::line: 1.50000 1.00000 1.00000 boundary id: 0 +DEAL::face: 2.00000 0.500000 0.500000 boundary id: 1 +DEAL::line: 2.00000 0.00000 0.500000 boundary id: 0 +DEAL::line: 2.00000 1.00000 0.500000 boundary id: 0 +DEAL::line: 2.00000 0.500000 0.00000 boundary id: 0 +DEAL::line: 2.00000 0.500000 1.00000 boundary id: 0 -- 2.39.5