From: Peter Munch Date: Wed, 18 Oct 2023 19:45:07 +0000 (+0200) Subject: Fix PBC in MGConstrainedDoFs X-Git-Tag: relicensing~377^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48fc5a6da7263f48e211a8ccf72815513dc7463f;p=dealii.git Fix PBC in MGConstrainedDoFs --- diff --git a/doc/news/changes/minor/20231019MunchPrietoSaavedra b/doc/news/changes/minor/20231019MunchPrietoSaavedra new file mode 100644 index 0000000000..a432826871 --- /dev/null +++ b/doc/news/changes/minor/20231019MunchPrietoSaavedra @@ -0,0 +1,6 @@ +Fixed: There was an inconsistency between the way +DoFTools::make_periodicity_constraints() and MGConstrainedDoFs +set up the constraints for periodic constraints. This is fixed +now. +
+(Peter Munch, Laura Prieto Saavedra, 2023/10/19) diff --git a/include/deal.II/dofs/dof_tools.h b/include/deal.II/dofs/dof_tools.h index 4989fbc0d3..e1dc5febd8 100644 --- a/include/deal.II/dofs/dof_tools.h +++ b/include/deal.II/dofs/dof_tools.h @@ -1163,6 +1163,46 @@ namespace DoFTools const ComponentMask &component_mask = {}, const number periodicity_factor = 1.); + namespace internal + { + /** + * Internally used in make_periodicity_constraints. + * + * Enter constraints for periodicity into the given AffineConstraints + * object. this function is called when at least one of the two face + * iterators corresponds to an active object without further children + * + * The matrix @p transformation maps degrees of freedom from one face + * to another. If the DoFs on the two faces are supposed to match exactly, + * then the matrix so provided will be the identity matrix. if face 2 is + * once refined from face 1, then the matrix needs to be the interpolation + * matrix from a face to this particular child + * + * @note: @p face_1 is supposed to be active. + * + * @note We have to be careful not to accidentally create constraint + * cycles when adding periodic constraints: For example, as the + * corresponding testcase bits/periodicity_05 demonstrates, we can + * occasionally get into trouble if we already have the constraint + * x1 == x2 and want to insert x2 == x1. We avoid this by skipping + * such "identity constraints" if the opposite constraint already + * exists. + */ + template + void + set_periodicity_constraints( + const FaceIterator &face_1, + const std_cxx20::type_identity_t &face_2, + const FullMatrix &transformation, + AffineConstraints &affine_constraints, + const ComponentMask &component_mask, + const bool face_orientation, + const bool face_flip, + const bool face_rotation, + const number periodicity_factor, + const unsigned int level = numbers::invalid_unsigned_int); + } // namespace internal + /** * @} */ diff --git a/include/deal.II/multigrid/mg_constrained_dofs.h b/include/deal.II/multigrid/mg_constrained_dofs.h index 84e55e9781..8e86b35c8a 100644 --- a/include/deal.II/multigrid/mg_constrained_dofs.h +++ b/include/deal.II/multigrid/mg_constrained_dofs.h @@ -21,6 +21,8 @@ #include #include +#include + #include #include @@ -309,58 +311,43 @@ MGConstrainedDoFs::initialize( level_constraints[l].reinit(dof.locally_owned_mg_dofs(l), relevant_dofs); } + } + + // TODO: currently we only consider very basic periodic constraints + const IdentityMatrix transformation(dof.get_fe().n_dofs_per_face()); + const ComponentMask component_mask; + const double periodicity_factor = 1.0; + + for (const auto &[first_cell, second_cell] : + dof.get_triangulation().get_periodic_face_map()) + { + // only consider non-artificial cells + if (first_cell.first->is_artificial_on_level()) + continue; + if (second_cell.first.first->is_artificial_on_level()) + continue; + + // consider cell pairs with the same level + if (first_cell.first->level() != second_cell.first.first->level()) + continue; + + DoFTools::internal::set_periodicity_constraints( + first_cell.first->as_dof_handler_level_iterator(dof)->face( + first_cell.second), + second_cell.first.first->as_dof_handler_level_iterator(dof)->face( + second_cell.first.second), + transformation, + level_constraints[first_cell.first->level()], + component_mask, + second_cell.second[0], + second_cell.second[1], + second_cell.second[2], + periodicity_factor, + first_cell.first->level()); + } - // Loop through relevant cells and faces finding those which are periodic - // neighbors. - for (const auto &cell : dof.cell_iterators_on_level(l)) - if (cell->is_artificial_on_level() == false) - for (auto f : cell->face_indices()) - if (cell->has_periodic_neighbor(f) && - cell->periodic_neighbor(f)->level() == cell->level()) - { - if (cell->is_locally_owned_on_level()) - { - Assert( - cell->periodic_neighbor(f)->level_subdomain_id() != - numbers::artificial_subdomain_id, - ExcMessage( - "Periodic neighbor of a locally owned cell must either be owned or ghost.")); - } - // Cell is a level-ghost and its neighbor is a - // level-artificial cell nothing to do here - else if (cell->periodic_neighbor(f)->level_subdomain_id() == - numbers::artificial_subdomain_id) - { - Assert(cell->is_locally_owned_on_level() == false, - ExcInternalError()); - continue; - } - - const unsigned int dofs_per_face = - dof.get_fe(0).n_dofs_per_face(f); - std::vector dofs_1(dofs_per_face); - std::vector dofs_2(dofs_per_face); - - cell->periodic_neighbor(f) - ->face(cell->periodic_neighbor_face_no(f)) - ->get_mg_dof_indices(l, dofs_1, 0); - cell->face(f)->get_mg_dof_indices(l, dofs_2, 0); - // Store periodicity information in the level - // AffineConstraints object. Skip DoFs for which we've - // previously entered periodicity constraints already; this - // can happen, for example, for a vertex dof at a periodic - // boundary that we visit from more than one cell - for (unsigned int i = 0; i < dofs_per_face; ++i) - if (level_constraints[l].can_store_line(dofs_2[i]) && - level_constraints[l].can_store_line(dofs_1[i]) && - !level_constraints[l].is_constrained(dofs_2[i]) && - !level_constraints[l].is_constrained(dofs_1[i])) - { - level_constraints[l].add_constraint(dofs_2[i], - {{dofs_1[i], 1.}}, - 0.); - } - } + for (unsigned int l = min_level; l <= max_level; ++l) + { level_constraints[l].close(); // Initialize with empty IndexSet of correct size diff --git a/source/dofs/dof_tools_constraints.cc b/source/dofs/dof_tools_constraints.cc index 635d4fb3e8..4d5aebe358 100644 --- a/source/dofs/dof_tools_constraints.cc +++ b/source/dofs/dof_tools_constraints.cc @@ -1850,33 +1850,8 @@ namespace DoFTools - namespace + namespace internal { - /** - * @internal - * - * Internally used in make_periodicity_constraints. - * - * enter constraints for periodicity into the given AffineConstraints - * object. this function is called when at least one of the two face - * iterators corresponds to an active object without further children - * - * @param transformation A matrix that maps degrees of freedom from one face - * to another. If the DoFs on the two faces are supposed to match exactly, - * then the matrix so provided will be the identity matrix. if face 2 is - * once refined from face 1, then the matrix needs to be the interpolation - * matrix from a face to this particular child - * - * @precondition: face_1 is supposed to be active - * - * @note We have to be careful not to accidentally create constraint - * cycles when adding periodic constraints: For example, as the - * corresponding testcase bits/periodicity_05 demonstrates, we can - * occasionally get into trouble if we already have the constraint - * x1 == x2 and want to insert x2 == x1. We avoid this by skipping - * such "identity constraints" if the opposite constraint already - * exists. - */ template void set_periodicity_constraints( @@ -1888,13 +1863,16 @@ namespace DoFTools const bool face_orientation, const bool face_flip, const bool face_rotation, - const number periodicity_factor) + const number periodicity_factor, + const unsigned int level) { static const int dim = FaceIterator::AccessorType::dimension; static const int spacedim = FaceIterator::AccessorType::space_dimension; + const bool use_mg = level != numbers::invalid_unsigned_int; + // we should be in the case where face_1 is active, i.e. has no children: - Assert(!face_1->has_children(), ExcInternalError()); + Assert(use_mg || (!face_1->has_children()), ExcInternalError()); Assert(face_1->n_active_fe_indices() == 1, ExcInternalError()); @@ -1909,7 +1887,7 @@ namespace DoFTools // If face_2 does have children, then we need to iterate over these // children and set periodic constraints in the inverse direction: - if (face_2->has_children()) + if ((!use_mg) && face_2->has_children()) { Assert(face_2->n_children() == GeometryInfo::max_children_per_face, @@ -1971,8 +1949,15 @@ namespace DoFTools std::vector dofs_1(dofs_per_face); std::vector dofs_2(dofs_per_face); - face_1->get_dof_indices(dofs_1, face_1_index); - face_2->get_dof_indices(dofs_2, face_2_index); + if (use_mg) + face_1->get_mg_dof_indices(level, dofs_1, face_1_index); + else + face_1->get_dof_indices(dofs_1, face_1_index); + + if (use_mg) + face_2->get_mg_dof_indices(level, dofs_2, face_2_index); + else + face_2->get_dof_indices(dofs_2, face_2_index); // If either of the two faces has an invalid dof index, stop. This is // so that there is no attempt to match artificial cells of parallel @@ -2232,9 +2217,11 @@ namespace DoFTools } } /* for dofs_per_face */ } + } // namespace internal - + namespace + { // Internally used in make_periodicity_constraints. // // Build up a (possibly rotated) interpolation matrix that is used in @@ -2539,30 +2526,30 @@ namespace DoFTools // matrix is the identity matrix. if (first_vector_components.empty() && matrix.m() == 0) { - set_periodicity_constraints(face_2, - face_1, - transformation, - affine_constraints, - component_mask, - face_orientation, - face_flip, - face_rotation, - periodicity_factor); + internal::set_periodicity_constraints(face_2, + face_1, + transformation, + affine_constraints, + component_mask, + face_orientation, + face_flip, + face_rotation, + periodicity_factor); } else { FullMatrix inverse(transformation.m()); inverse.invert(transformation); - set_periodicity_constraints(face_2, - face_1, - inverse, - affine_constraints, - component_mask, - face_orientation, - face_flip, - face_rotation, - periodicity_factor); + internal::set_periodicity_constraints(face_2, + face_1, + inverse, + affine_constraints, + component_mask, + face_orientation, + face_flip, + face_rotation, + periodicity_factor); } } else @@ -2575,17 +2562,17 @@ namespace DoFTools // the rotation when constraining face_2 to face_1. Therefore // face_flip has to be toggled if face_rotation is true: In case of // inverted orientation, nothing has to be done. - set_periodicity_constraints(face_1, - face_2, - transformation, - affine_constraints, - component_mask, - face_orientation, - face_orientation ? - face_rotation ^ face_flip : - face_flip, - face_rotation, - periodicity_factor); + internal::set_periodicity_constraints(face_1, + face_2, + transformation, + affine_constraints, + component_mask, + face_orientation, + face_orientation ? + face_rotation ^ face_flip : + face_flip, + face_rotation, + periodicity_factor); } } } diff --git a/source/dofs/dof_tools_constraints.inst.in b/source/dofs/dof_tools_constraints.inst.in index 6b11357f60..8517424588 100644 --- a/source/dofs/dof_tools_constraints.inst.in +++ b/source/dofs/dof_tools_constraints.inst.in @@ -30,6 +30,34 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS; const FullMatrix &, const std::vector &, const S); + + template void DoFTools::internal::set_periodicity_constraints( + const DoFHandler::face_iterator &face_1, + const DoFHandler::face_iterator &face_2, + const FullMatrix &transformation, + AffineConstraints &affine_constraints, + const ComponentMask &component_mask, + const bool face_orientation, + const bool face_flip, + const bool face_rotation, + const S periodicity_factor, + const unsigned int level); + + template void DoFTools::internal::set_periodicity_constraints( + const DoFHandler::level_face_iterator &face_1, + const DoFHandler::level_face_iterator &face_2, + const FullMatrix &transformation, + AffineConstraints &affine_constraints, + const ComponentMask &component_mask, + const bool face_orientation, + const bool face_flip, + const bool face_rotation, + const S periodicity_factor, + const unsigned int level); #endif } diff --git a/tests/multigrid-global-coarsening/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output b/tests/multigrid-global-coarsening/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output index 49963ec916..3a13121d1c 100644 --- a/tests/multigrid-global-coarsening/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output +++ b/tests/multigrid-global-coarsening/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output @@ -3,62 +3,62 @@ DEAL::FE: FE_Q<2>(1) DEAL::no. cells: 16 DEAL::Transfer matrices: Level 0 -(3,3) 0.250000 -(5,3) 0.500000 -(7,3) 0.500000 -(8,3) 1.00000 +(0,0) 1.00000 +(1,0) 0.500000 +(2,0) 0.500000 +(3,0) 0.250000 Level 1 +(0,0) 1.00000 +(1,0) 0.500000 +(1,1) 0.500000 +(2,0) 0.500000 +(2,2) 0.500000 +(3,0) 0.250000 +(3,1) 0.250000 +(3,2) 0.250000 (3,3) 0.250000 -(3,5) 0.250000 -(3,7) 0.250000 -(3,8) 0.250000 +(4,1) 1.00000 +(5,1) 0.500000 (5,3) 0.500000 -(5,7) 0.500000 +(6,2) 1.00000 +(7,2) 0.500000 (7,3) 0.500000 -(7,5) 0.500000 (8,3) 1.00000 +(9,0) 0.500000 +(9,1) 0.500000 +(10,0) 0.250000 +(10,1) 0.250000 +(10,2) 0.250000 (10,3) 0.250000 -(10,5) 0.250000 -(10,7) 0.250000 -(10,8) 0.250000 -(12,5) 0.500000 -(12,8) 0.500000 +(13,2) 0.500000 (13,3) 0.500000 -(13,5) 0.500000 -(14,5) 1.00000 +(15,0) 0.500000 +(15,2) 0.500000 +(16,0) 0.250000 +(16,1) 0.250000 +(16,2) 0.250000 (16,3) 0.250000 -(16,5) 0.250000 -(16,7) 0.250000 -(16,8) 0.250000 +(17,1) 0.500000 (17,3) 0.500000 -(17,7) 0.500000 -(19,7) 0.500000 -(19,8) 0.500000 -(20,7) 1.00000 +(21,0) 0.250000 +(21,1) 0.250000 +(21,2) 0.250000 (21,3) 0.250000 -(21,5) 0.250000 -(21,7) 0.250000 -(21,8) 0.250000 -(22,5) 0.500000 -(22,8) 0.500000 -(23,7) 0.500000 -(23,8) 0.500000 -(24,8) 1.00000 DEAL:: -DEAL::Diff prolongate l1: 0.823013 +DEAL::Diff prolongate l1: 0.866046 Process #0 Local range: [0, 9), global size: 9 Vector data: -0.000e+00 0.000e+00 0.000e+00 7.984e-01 0.000e+00 7.984e-01 0.000e+00 7.984e-01 7.984e-01 +8.402e-01 8.402e-01 8.402e-01 8.402e-01 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 Process #0 Local range: [0, 9), global size: 9 Vector data: -0.000e+00 0.000e+00 0.000e+00 -5.988e-01 0.000e+00 -3.992e-01 0.000e+00 -3.992e-01 0.000e+00 -DEAL::Diff prolongate l2: 0 -DEAL::Diff restrict l1: 0.555735 -DEAL::Diff restrict add l1: 0.555735 -DEAL::Diff restrict l2: 0 -DEAL::Diff restrict add l2: 0 +0.000e+00 -4.201e-01 -4.201e-01 -6.301e-01 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 +DEAL::Diff prolongate l2: 0.00000 +DEAL::Diff restrict l1: 1.41100 +DEAL::Diff restrict add l1: 1.41100 +DEAL::Diff restrict l2: 5.43896e-16 +DEAL::Diff restrict add l2: 4.44089e-16 DEAL:: diff --git a/tests/multigrid/constrained_dofs_05.output b/tests/multigrid/constrained_dofs_05.output index 69c842ba43..22e7da9cf7 100644 --- a/tests/multigrid/constrained_dofs_05.output +++ b/tests/multigrid/constrained_dofs_05.output @@ -8,8 +8,8 @@ DEAL:: Faces having periodic neighbors of same level: DEAL:: 0, 2 <-> 1, 3 via periodic boundary DEAL:: 1, 3 <-> 0, 2 via periodic boundary DEAL:: Constraint matrix: - 0 1: 1.00000 - 2 3: 1.00000 + 1 0: 1.00000 + 3 2: 1.00000 DEAL::Level 1: DEAL:: Faces neighboring coarser cells: DEAL:: Refinement edge DoFs: {} @@ -18,9 +18,9 @@ DEAL:: Faces having periodic neighbors of same level: DEAL:: 0, 2 <-> 4, 5 via periodic boundary DEAL:: 2, 6 <-> 5, 8 via periodic boundary DEAL:: Constraint matrix: - 0 4: 1.00000 - 2 5: 1.00000 - 6 8: 1.00000 + 4 0: 1.00000 + 5 2: 1.00000 + 8 6: 1.00000 DEAL::Level 2: DEAL:: Faces neighboring coarser cells: DEAL:: 0, 2 via periodic boundary @@ -42,10 +42,10 @@ DEAL:: Faces having periodic neighbors of same level: DEAL:: 0, 2, 4, 6 <-> 1, 3, 5, 7 via periodic boundary DEAL:: 1, 3, 5, 7 <-> 0, 2, 4, 6 via periodic boundary DEAL:: Constraint matrix: - 0 1: 1.00000 - 2 3: 1.00000 - 4 5: 1.00000 - 6 7: 1.00000 + 1 0: 1.00000 + 3 2: 1.00000 + 5 4: 1.00000 + 7 6: 1.00000 DEAL::Level 1: DEAL:: Faces neighboring coarser cells: DEAL:: Refinement edge DoFs: {} @@ -56,15 +56,15 @@ DEAL:: 2, 12, 6, 14 <-> 9, 16, 11, 17 via periodic boundary DEAL:: 4, 6, 18, 20 <-> 10, 11, 22, 23 via periodic boundary DEAL:: 6, 14, 20, 24 <-> 11, 17, 23, 26 via periodic boundary DEAL:: Constraint matrix: - 0 8: 1.00000 - 2 9: 1.00000 - 4 10: 1.00000 - 6 11: 1.00000 - 12 16: 1.00000 - 14 17: 1.00000 - 18 22: 1.00000 - 20 23: 1.00000 - 24 26: 1.00000 + 8 0: 1.00000 + 9 2: 1.00000 + 10 4: 1.00000 + 11 6: 1.00000 + 16 12: 1.00000 + 17 14: 1.00000 + 22 18: 1.00000 + 23 20: 1.00000 + 26 24: 1.00000 DEAL::Level 2: DEAL:: Faces neighboring coarser cells: DEAL:: 0, 2, 4, 6 via periodic boundary diff --git a/tests/multigrid/mg_constraints_pbc.cc b/tests/multigrid/mg_constraints_pbc.cc new file mode 100644 index 0000000000..cb23f82583 --- /dev/null +++ b/tests/multigrid/mg_constraints_pbc.cc @@ -0,0 +1,91 @@ +/* --------------------------------------------------------------------- + * + * Copyright (C) 2023 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. + * + * --------------------------------------------------------------------- + * + * Test that DoFTools::make_periodicity_constraints() and MGConstrainedDoFs + * creates the same constrains for periodic constraints in the case of + * globally refined meshes. + */ + +#include +#include + +#include + +#include +#include +#include + +#include + +#include "../tests.h" + +using namespace dealii; + +int +main() +{ + initlog(); + + const unsigned int dim = 2; + const unsigned int n_refinements = 2; + + Triangulation tria( + Triangulation::MeshSmoothing::limit_level_difference_at_vertices); + GridGenerator::hyper_cube(tria, 0, 1, true); + + std::vector< + GridTools::PeriodicFacePair::cell_iterator>> + periodic_faces; + + GridTools::collect_periodic_faces(tria, 0, 1, 0, periodic_faces); + + tria.add_periodicity(periodic_faces); + tria.refine_global(n_refinements); + + DoFHandler dof_handler(tria); + dof_handler.distribute_dofs(FE_Q(1)); + dof_handler.distribute_mg_dofs(); + + MGConstrainedDoFs mg_constraints; + mg_constraints.initialize(dof_handler); + + const auto &af_level = mg_constraints.get_level_constraints(n_refinements); + + AffineConstraints af; + DoFTools::make_periodicity_constraints( + dof_handler, 0, 1, 0, af); + + for (unsigned int i = 0; i < dof_handler.n_dofs(); ++i) + { + Assert(af_level.is_constrained(i) == af.is_constrained(i), + ExcInternalError()); + + if (af_level.is_constrained(i) == false) + continue; + + Assert(*af_level.get_constraint_entries(i) == + *af.get_constraint_entries(i), + ExcInternalError()); + } + +#if 0 + af_level.print(std::cout); + std::cout << std::endl; + af.print(std::cout); + std::cout << std::endl; +#endif + + deallog << "OK!" << std::endl; +} diff --git a/tests/multigrid/mg_constraints_pbc.output b/tests/multigrid/mg_constraints_pbc.output new file mode 100644 index 0000000000..5cfb783b8f --- /dev/null +++ b/tests/multigrid/mg_constraints_pbc.output @@ -0,0 +1,2 @@ + +DEAL::OK! diff --git a/tests/multigrid/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output b/tests/multigrid/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output index 49963ec916..ac694e0756 100644 --- a/tests/multigrid/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output +++ b/tests/multigrid/transfer_matrix_free_11.with_p4est=true.with_trilinos=true.mpirun=1.output @@ -3,62 +3,62 @@ DEAL::FE: FE_Q<2>(1) DEAL::no. cells: 16 DEAL::Transfer matrices: Level 0 -(3,3) 0.250000 -(5,3) 0.500000 -(7,3) 0.500000 -(8,3) 1.00000 +(0,0) 1.00000 +(1,0) 0.500000 +(2,0) 0.500000 +(3,0) 0.250000 Level 1 +(0,0) 1.00000 +(1,0) 0.500000 +(1,1) 0.500000 +(2,0) 0.500000 +(2,2) 0.500000 +(3,0) 0.250000 +(3,1) 0.250000 +(3,2) 0.250000 (3,3) 0.250000 -(3,5) 0.250000 -(3,7) 0.250000 -(3,8) 0.250000 +(4,1) 1.00000 +(5,1) 0.500000 (5,3) 0.500000 -(5,7) 0.500000 +(6,2) 1.00000 +(7,2) 0.500000 (7,3) 0.500000 -(7,5) 0.500000 (8,3) 1.00000 +(9,0) 0.500000 +(9,1) 0.500000 +(10,0) 0.250000 +(10,1) 0.250000 +(10,2) 0.250000 (10,3) 0.250000 -(10,5) 0.250000 -(10,7) 0.250000 -(10,8) 0.250000 -(12,5) 0.500000 -(12,8) 0.500000 +(13,2) 0.500000 (13,3) 0.500000 -(13,5) 0.500000 -(14,5) 1.00000 +(15,0) 0.500000 +(15,2) 0.500000 +(16,0) 0.250000 +(16,1) 0.250000 +(16,2) 0.250000 (16,3) 0.250000 -(16,5) 0.250000 -(16,7) 0.250000 -(16,8) 0.250000 +(17,1) 0.500000 (17,3) 0.500000 -(17,7) 0.500000 -(19,7) 0.500000 -(19,8) 0.500000 -(20,7) 1.00000 +(21,0) 0.250000 +(21,1) 0.250000 +(21,2) 0.250000 (21,3) 0.250000 -(21,5) 0.250000 -(21,7) 0.250000 -(21,8) 0.250000 -(22,5) 0.500000 -(22,8) 0.500000 -(23,7) 0.500000 -(23,8) 0.500000 -(24,8) 1.00000 DEAL:: -DEAL::Diff prolongate l1: 0.823013 +DEAL::Diff prolongate l1: 0.866046 Process #0 Local range: [0, 9), global size: 9 Vector data: -0.000e+00 0.000e+00 0.000e+00 7.984e-01 0.000e+00 7.984e-01 0.000e+00 7.984e-01 7.984e-01 +8.402e-01 8.402e-01 8.402e-01 8.402e-01 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 Process #0 Local range: [0, 9), global size: 9 Vector data: -0.000e+00 0.000e+00 0.000e+00 -5.988e-01 0.000e+00 -3.992e-01 0.000e+00 -3.992e-01 0.000e+00 -DEAL::Diff prolongate l2: 0 -DEAL::Diff restrict l1: 0.555735 -DEAL::Diff restrict add l1: 0.555735 -DEAL::Diff restrict l2: 0 -DEAL::Diff restrict add l2: 0 +0.000e+00 -4.201e-01 -4.201e-01 -6.301e-01 0.000e+00 0.000e+00 0.000e+00 0.000e+00 0.000e+00 +DEAL::Diff prolongate l2: 0.00000 +DEAL::Diff restrict l1: 1.41100 +DEAL::Diff restrict add l1: 1.41100 +DEAL::Diff restrict l2: 6.66134e-16 +DEAL::Diff restrict add l2: 6.28037e-16 DEAL::