From: Wolfgang Bangerth Date: Thu, 27 Aug 1998 14:25:00 +0000 (+0000) Subject: Next round of multigrid implementation. X-Git-Tag: v8.0.0~22727 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a5624d6a434901db6c1a89df7f91caaefa8d07c5;p=dealii.git Next round of multigrid implementation. git-svn-id: https://svn.dealii.org/trunk@527 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/deal.II/include/dofs/mg_dof_handler.h b/deal.II/deal.II/include/dofs/mg_dof_handler.h index eeeea98ecc..4a0bf6c411 100644 --- a/deal.II/deal.II/include/dofs/mg_dof_handler.h +++ b/deal.II/deal.II/include/dofs/mg_dof_handler.h @@ -178,6 +178,34 @@ class MGDoFHandler : public DoFHandler { void make_sparsity_pattern (const unsigned int level, dSMatrixStruct &sparsity) const; + /** + * Make up the constraint matrix which + * is used to condensate the + * system matrices and to prolong + * the solution vectors from the true + * degrees of freedom also to the + * constraint nodes. The constraints + * apply only to the given level. + * + * Since this method does not make sense in + * one dimension, the functions returns + * immediately after clearing the + * constraint matrix. + * For more than one dimension, the matrix + * is cleared before usage. The constraint + * matrix is closed anyway, no matter of the + * dimension. + * + * To condense a given sparsity pattern, + * use #ConstraintMatrix::condense#. + * + * This function uses the user flags for + * the faces. If you need the user flags, + * store them beforehand. + */ + void make_constraint_matrix (const unsigned int level, + ConstraintMatrix &cm) const; + /*--------------------------------------*/ /** @@ -680,7 +708,7 @@ class MGDoFHandler : public DoFHandler { * set all indices to #-1#. */ void init (const unsigned int coarsest_level, - const unsigned int n_levels, + const unsigned int finest_level, const unsigned int dofs_per_vertex); /** @@ -724,6 +752,18 @@ class MGDoFHandler : public DoFHandler { int get_index (const unsigned int level, const unsigned int dof_number, const unsigned int dofs_per_vertex) const; + + /** + * Return the index of the coarsest + * level this vertex lives on. + */ + unsigned int get_coarsest_level () const; + + /** + * Return the index of the finest + * level this vertex lives on. + */ + unsigned int get_finest_level () const; /** * Exception. @@ -739,8 +779,8 @@ class MGDoFHandler : public DoFHandler { */ DeclException1 (ExcInvalidLevel, int, - << "The given level number " << arg1 << " is below the " - << "coarsest level this vertex lives on."); + << "The given level number " << arg1 << " is outside " + << "the range of levels this vertex lives on."); /** * Exception. */ @@ -755,18 +795,20 @@ class MGDoFHandler : public DoFHandler { */ unsigned int coarsest_level; + /** + * Finest level this level lives on. + * This is mostly used for error + * checking but can also be accessed + * by the function #get_finest_level#. + */ + unsigned int finest_level; + /** * Array holding the indices. */ int *indices; }; - - /** - * Reserve enough space for the MG dof - * indices for a given triangulation. - */ - void reserve_space (); /** * Distribute dofs on the given cell, @@ -784,6 +826,28 @@ class MGDoFHandler : public DoFHandler { */ unsigned int distribute_dofs_on_cell (active_cell_iterator &cell, unsigned int next_free_dof); + + /** + * Actually do the renumbering prepared + * by the #renumber_dofs# function on + * the given #level#. Since + * this is dimension specific, we + * need to have another function. + * + * #new_numbers# is an array of integers + * with size equal to the number of dofs + * on the present level. It stores the new + * indices after renumbering in the + * order of the old indices. + */ + void do_renumbering (const unsigned int level, + const vector &new_numbers); + + /** + * Reserve enough space for the MG dof + * indices for a given triangulation. + */ + void reserve_space (); /** * Space to store the DoF numbers for the @@ -830,7 +894,8 @@ void MGDoFHandler::MGVertexDoFs::set_index (const unsigned int level, const unsigned int dof_number, const unsigned int dofs_per_vertex, const unsigned int index) { - Assert (level >= coarsest_level, ExcInvalidLevel(level)); + Assert ((level >= coarsest_level) && (level <= finest_level), + ExcInvalidLevel(level)); Assert (dof_number < dofs_per_vertex, ExcInvalidIndex ()); indices[(level-coarsest_level)*dofs_per_vertex + dof_number] = index; @@ -844,7 +909,8 @@ inline int MGDoFHandler::MGVertexDoFs::get_index (const unsigned int level, const unsigned int dof_number, const unsigned int dofs_per_vertex) const { - Assert (level >= coarsest_level, ExcInvalidLevel(level)); + Assert ((level >= coarsest_level) && (level <= finest_level), + ExcInvalidLevel(level)); Assert (dof_number < dofs_per_vertex, ExcInvalidIndex ()); return indices[(level-coarsest_level)*dofs_per_vertex + dof_number]; diff --git a/deal.II/deal.II/include/multigrid/mg_dof_handler.h b/deal.II/deal.II/include/multigrid/mg_dof_handler.h index eeeea98ecc..4a0bf6c411 100644 --- a/deal.II/deal.II/include/multigrid/mg_dof_handler.h +++ b/deal.II/deal.II/include/multigrid/mg_dof_handler.h @@ -178,6 +178,34 @@ class MGDoFHandler : public DoFHandler { void make_sparsity_pattern (const unsigned int level, dSMatrixStruct &sparsity) const; + /** + * Make up the constraint matrix which + * is used to condensate the + * system matrices and to prolong + * the solution vectors from the true + * degrees of freedom also to the + * constraint nodes. The constraints + * apply only to the given level. + * + * Since this method does not make sense in + * one dimension, the functions returns + * immediately after clearing the + * constraint matrix. + * For more than one dimension, the matrix + * is cleared before usage. The constraint + * matrix is closed anyway, no matter of the + * dimension. + * + * To condense a given sparsity pattern, + * use #ConstraintMatrix::condense#. + * + * This function uses the user flags for + * the faces. If you need the user flags, + * store them beforehand. + */ + void make_constraint_matrix (const unsigned int level, + ConstraintMatrix &cm) const; + /*--------------------------------------*/ /** @@ -680,7 +708,7 @@ class MGDoFHandler : public DoFHandler { * set all indices to #-1#. */ void init (const unsigned int coarsest_level, - const unsigned int n_levels, + const unsigned int finest_level, const unsigned int dofs_per_vertex); /** @@ -724,6 +752,18 @@ class MGDoFHandler : public DoFHandler { int get_index (const unsigned int level, const unsigned int dof_number, const unsigned int dofs_per_vertex) const; + + /** + * Return the index of the coarsest + * level this vertex lives on. + */ + unsigned int get_coarsest_level () const; + + /** + * Return the index of the finest + * level this vertex lives on. + */ + unsigned int get_finest_level () const; /** * Exception. @@ -739,8 +779,8 @@ class MGDoFHandler : public DoFHandler { */ DeclException1 (ExcInvalidLevel, int, - << "The given level number " << arg1 << " is below the " - << "coarsest level this vertex lives on."); + << "The given level number " << arg1 << " is outside " + << "the range of levels this vertex lives on."); /** * Exception. */ @@ -755,18 +795,20 @@ class MGDoFHandler : public DoFHandler { */ unsigned int coarsest_level; + /** + * Finest level this level lives on. + * This is mostly used for error + * checking but can also be accessed + * by the function #get_finest_level#. + */ + unsigned int finest_level; + /** * Array holding the indices. */ int *indices; }; - - /** - * Reserve enough space for the MG dof - * indices for a given triangulation. - */ - void reserve_space (); /** * Distribute dofs on the given cell, @@ -784,6 +826,28 @@ class MGDoFHandler : public DoFHandler { */ unsigned int distribute_dofs_on_cell (active_cell_iterator &cell, unsigned int next_free_dof); + + /** + * Actually do the renumbering prepared + * by the #renumber_dofs# function on + * the given #level#. Since + * this is dimension specific, we + * need to have another function. + * + * #new_numbers# is an array of integers + * with size equal to the number of dofs + * on the present level. It stores the new + * indices after renumbering in the + * order of the old indices. + */ + void do_renumbering (const unsigned int level, + const vector &new_numbers); + + /** + * Reserve enough space for the MG dof + * indices for a given triangulation. + */ + void reserve_space (); /** * Space to store the DoF numbers for the @@ -830,7 +894,8 @@ void MGDoFHandler::MGVertexDoFs::set_index (const unsigned int level, const unsigned int dof_number, const unsigned int dofs_per_vertex, const unsigned int index) { - Assert (level >= coarsest_level, ExcInvalidLevel(level)); + Assert ((level >= coarsest_level) && (level <= finest_level), + ExcInvalidLevel(level)); Assert (dof_number < dofs_per_vertex, ExcInvalidIndex ()); indices[(level-coarsest_level)*dofs_per_vertex + dof_number] = index; @@ -844,7 +909,8 @@ inline int MGDoFHandler::MGVertexDoFs::get_index (const unsigned int level, const unsigned int dof_number, const unsigned int dofs_per_vertex) const { - Assert (level >= coarsest_level, ExcInvalidLevel(level)); + Assert ((level >= coarsest_level) && (level <= finest_level), + ExcInvalidLevel(level)); Assert (dof_number < dofs_per_vertex, ExcInvalidIndex ()); return indices[(level-coarsest_level)*dofs_per_vertex + dof_number]; diff --git a/deal.II/deal.II/source/dofs/mg_dof_handler.cc b/deal.II/deal.II/source/dofs/mg_dof_handler.cc index d9f1a8b213..bffa94f52e 100644 --- a/deal.II/deal.II/source/dofs/mg_dof_handler.cc +++ b/deal.II/deal.II/source/dofs/mg_dof_handler.cc @@ -12,12 +12,16 @@ #include #include +#include + + /* ------------------------ MGVertexDoFs ----------------------------------- */ template MGDoFHandler::MGVertexDoFs::MGVertexDoFs () : coarsest_level (1<<30), + finest_level (0), indices (0) {}; @@ -25,11 +29,14 @@ MGDoFHandler::MGVertexDoFs::MGVertexDoFs () : template void MGDoFHandler::MGVertexDoFs::init (const unsigned int cl, - const unsigned int n_levels, + const unsigned int fl, const unsigned int dofs_per_vertex) { Assert (indices == 0, ExcInternalError()); coarsest_level = cl; + finest_level = fl; + + const unsigned int n_levels = finest_level-coarsest_level + 1; indices = new int[n_levels * dofs_per_vertex]; Assert (indices != 0, ExcNoMemory ()); @@ -49,6 +56,21 @@ MGDoFHandler::MGVertexDoFs::~MGVertexDoFs () { +template +inline +unsigned int MGDoFHandler::MGVertexDoFs::get_coarsest_level () const { + return coarsest_level; +}; + + + +template +inline +unsigned int MGDoFHandler::MGVertexDoFs::get_finest_level () const { + return finest_level; +}; + + @@ -997,6 +1019,261 @@ void MGDoFHandler::make_sparsity_pattern (const unsigned int level, +template +void MGDoFHandler::renumber_dofs (const unsigned int level, + const RenumberingMethod method, + const bool use_constraints, + const vector &starting_points) { + // make the connection graph + dSMatrixStruct sparsity (n_dofs(level), max_couplings_between_dofs()); + make_sparsity_pattern (level, sparsity); + + if (use_constraints) + { + ConstraintMatrix constraints; + make_constraint_matrix (level, constraints); + constraints.condense (sparsity); + }; + + int n_dofs = sparsity.n_rows(); + // store the new dof numbers; -1 means + // that no new number was chosen yet + // + // the commented line is what would be the + // correct way to do, but gcc2.8 chokes + // over that. The other lines are a + // workaround +// vector new_number(n_dofs, -1); + vector new_number; + new_number.resize (n_dofs, -1); + + // store the indices of the dofs renumbered + // in the last round. Default to starting + // points + vector last_round_dofs (starting_points); + + // delete disallowed elements + for (unsigned int i=0; i=n_dofs)) + last_round_dofs[i] = -1; + + remove_if (last_round_dofs.begin(), last_round_dofs.end(), + bind2nd(equal_to(), -1)); + + // now if no valid points remain: + // find dof with lowest coordination + // number + + if (last_round_dofs.size() == 0) + { + int starting_point = -1; + unsigned int min_coordination = n_dofs; + for (int row=0; row next_round_dofs; + + // find all neighbors of the + // dofs numbered in the last + // round + for (unsigned int i=0; i::iterator end_sorted; + end_sorted = unique (next_round_dofs.begin(), next_round_dofs.end()); + next_round_dofs.erase (end_sorted, next_round_dofs.end()); + + // eliminate dofs which are + // already numbered + for (int s=next_round_dofs.size()-1; s>=0; --s) + if (new_number[next_round_dofs[s]] != -1) + next_round_dofs.erase (&next_round_dofs[s]); + + // check whether there are any new + // dofs + all_dofs_renumbered = (next_round_dofs.size() == 0); + if (all_dofs_renumbered) + // end loop if possible + continue; + + + // store for each coordination + // number the dofs with these + // coordination number + multimap dofs_by_coordination; + + // find coordination number for + // each of these dofs + for (vector::iterator s=next_round_dofs.begin(); + s!=next_round_dofs.end(); ++s) + { + unsigned int coordination = 0; + for (unsigned int j=sparsity.get_rowstart_indices()[*s]; + j new_entry (coordination, *s); + dofs_by_coordination.insert (new_entry); + }; + + //// + multimap::iterator i; + for (i = dofs_by_coordination.begin(); i!=dofs_by_coordination.end(); ++i) + new_number[i->second] = next_free_number++; + + // after that: copy this round's + // dofs for the next round + last_round_dofs = next_round_dofs; + }; + +#ifdef DEBUG + // test for all indices numbered + if (find (new_number.begin(), new_number.end(), -1) != new_number.end()) + Assert (false, ExcRenumberingIncomplete()); + Assert (next_free_number == n_dofs, + ExcRenumberingIncomplete()); +#endif + + switch (method) + { + case Cuthill_McKee: + break; + case reverse_Cuthill_McKee: + { + for (vector::iterator i=new_number.begin(); i!=new_number.end(); ++i) + *i = n_dofs-*i; + break; + }; + default: + Assert (false, ExcNotImplemented()); + }; + + // actually perform renumbering; + // this is dimension specific and + // thus needs an own function + do_renumbering (level, new_number); +}; + + + +#if deal_II_dimension == 1 + +template <> +void MGDoFHandler<1>::do_renumbering (const unsigned int level, + const vector &new_numbers) { + Assert (new_numbers.size() == n_dofs(level), ExcRenumberingIncomplete()); + + // note that we can not use cell iterators + // in this function since then we would + // renumber the dofs on the interface of + // two cells more than once. Anyway, this + // ways it's not only more correct but also + // faster + for (vector::iterator i=mg_vertex_dofs.begin(); + i!=mg_vertex_dofs.end(); ++i) + // if the present vertex lives on + // the present level + if ((i->get_coarsest_level() <= level) && + (i->get_finest_level() >= level)) + for (unsigned int d=0; ddofs_per_vertex; ++d) + i->set_index (level, d, selected_fe->dofs_per_vertex, + new_numbers[i->get_index (level, d, + selected_fe->dofs_per_vertex)]); + + for (vector::iterator i=mg_levels[level]->line_dofs.begin(); + i!=mg_levels[level]->line_dofs.end(); ++i) + { + Assert (*i != -1, ExcInternalError()); + *i = new_numbers[*i]; + }; +}; + +#endif + + +#if deal_II_dimension == 2 + +template <> +void MGDoFHandler<2>::do_renumbering (const unsigned int level, + const vector &new_numbers) { + Assert (new_numbers.size() == n_dofs(level), ExcRenumberingIncomplete()); + + for (vector::iterator i=mg_vertex_dofs.begin(); + i!=mg_vertex_dofs.end(); ++i) + // if the present vertex lives on + // the present level + if ((i->get_coarsest_level() <= level) && + (i->get_finest_level() >= level)) + for (unsigned int d=0; ddofs_per_vertex; ++d) + i->set_index (level, d, selected_fe->dofs_per_vertex, + new_numbers[i->get_index (level, d, + selected_fe->dofs_per_vertex)]); + + for (vector::iterator i=mg_levels[level]->line_dofs.begin(); + i!=mg_levels[level]->line_dofs.end(); ++i) + { + Assert (*i != -1, ExcInternalError()); + *i = new_numbers[*i]; + }; + for (vector::iterator i=mg_levels[level]->quad_dofs.begin(); + i!=mg_levels[level]->quad_dofs.end(); ++i) + { + Assert (*i != -1, ExcInternalError()); + *i = new_numbers[*i]; + }; +}; + +#endif + + + #if deal_II_dimension == 1 @@ -1074,7 +1351,7 @@ void MGDoFHandler<1>::reserve_space () { Assert (max_level[vertex] >= min_level[vertex], ExcInternalError()); mg_vertex_dofs[vertex].init (min_level[vertex], - max_level[vertex]-min_level[vertex]+1, + max_level[vertex], selected_fe->dofs_per_vertex); }; }; @@ -1162,7 +1439,7 @@ void MGDoFHandler<2>::reserve_space () { Assert (max_level[vertex] >= min_level[vertex], ExcInternalError()); mg_vertex_dofs[vertex].init (min_level[vertex], - max_level[vertex]-min_level[vertex]+1, + max_level[vertex], selected_fe->dofs_per_vertex); }; }; diff --git a/deal.II/deal.II/source/multigrid/mg_dof_handler.cc b/deal.II/deal.II/source/multigrid/mg_dof_handler.cc index d9f1a8b213..bffa94f52e 100644 --- a/deal.II/deal.II/source/multigrid/mg_dof_handler.cc +++ b/deal.II/deal.II/source/multigrid/mg_dof_handler.cc @@ -12,12 +12,16 @@ #include #include +#include + + /* ------------------------ MGVertexDoFs ----------------------------------- */ template MGDoFHandler::MGVertexDoFs::MGVertexDoFs () : coarsest_level (1<<30), + finest_level (0), indices (0) {}; @@ -25,11 +29,14 @@ MGDoFHandler::MGVertexDoFs::MGVertexDoFs () : template void MGDoFHandler::MGVertexDoFs::init (const unsigned int cl, - const unsigned int n_levels, + const unsigned int fl, const unsigned int dofs_per_vertex) { Assert (indices == 0, ExcInternalError()); coarsest_level = cl; + finest_level = fl; + + const unsigned int n_levels = finest_level-coarsest_level + 1; indices = new int[n_levels * dofs_per_vertex]; Assert (indices != 0, ExcNoMemory ()); @@ -49,6 +56,21 @@ MGDoFHandler::MGVertexDoFs::~MGVertexDoFs () { +template +inline +unsigned int MGDoFHandler::MGVertexDoFs::get_coarsest_level () const { + return coarsest_level; +}; + + + +template +inline +unsigned int MGDoFHandler::MGVertexDoFs::get_finest_level () const { + return finest_level; +}; + + @@ -997,6 +1019,261 @@ void MGDoFHandler::make_sparsity_pattern (const unsigned int level, +template +void MGDoFHandler::renumber_dofs (const unsigned int level, + const RenumberingMethod method, + const bool use_constraints, + const vector &starting_points) { + // make the connection graph + dSMatrixStruct sparsity (n_dofs(level), max_couplings_between_dofs()); + make_sparsity_pattern (level, sparsity); + + if (use_constraints) + { + ConstraintMatrix constraints; + make_constraint_matrix (level, constraints); + constraints.condense (sparsity); + }; + + int n_dofs = sparsity.n_rows(); + // store the new dof numbers; -1 means + // that no new number was chosen yet + // + // the commented line is what would be the + // correct way to do, but gcc2.8 chokes + // over that. The other lines are a + // workaround +// vector new_number(n_dofs, -1); + vector new_number; + new_number.resize (n_dofs, -1); + + // store the indices of the dofs renumbered + // in the last round. Default to starting + // points + vector last_round_dofs (starting_points); + + // delete disallowed elements + for (unsigned int i=0; i=n_dofs)) + last_round_dofs[i] = -1; + + remove_if (last_round_dofs.begin(), last_round_dofs.end(), + bind2nd(equal_to(), -1)); + + // now if no valid points remain: + // find dof with lowest coordination + // number + + if (last_round_dofs.size() == 0) + { + int starting_point = -1; + unsigned int min_coordination = n_dofs; + for (int row=0; row next_round_dofs; + + // find all neighbors of the + // dofs numbered in the last + // round + for (unsigned int i=0; i::iterator end_sorted; + end_sorted = unique (next_round_dofs.begin(), next_round_dofs.end()); + next_round_dofs.erase (end_sorted, next_round_dofs.end()); + + // eliminate dofs which are + // already numbered + for (int s=next_round_dofs.size()-1; s>=0; --s) + if (new_number[next_round_dofs[s]] != -1) + next_round_dofs.erase (&next_round_dofs[s]); + + // check whether there are any new + // dofs + all_dofs_renumbered = (next_round_dofs.size() == 0); + if (all_dofs_renumbered) + // end loop if possible + continue; + + + // store for each coordination + // number the dofs with these + // coordination number + multimap dofs_by_coordination; + + // find coordination number for + // each of these dofs + for (vector::iterator s=next_round_dofs.begin(); + s!=next_round_dofs.end(); ++s) + { + unsigned int coordination = 0; + for (unsigned int j=sparsity.get_rowstart_indices()[*s]; + j new_entry (coordination, *s); + dofs_by_coordination.insert (new_entry); + }; + + //// + multimap::iterator i; + for (i = dofs_by_coordination.begin(); i!=dofs_by_coordination.end(); ++i) + new_number[i->second] = next_free_number++; + + // after that: copy this round's + // dofs for the next round + last_round_dofs = next_round_dofs; + }; + +#ifdef DEBUG + // test for all indices numbered + if (find (new_number.begin(), new_number.end(), -1) != new_number.end()) + Assert (false, ExcRenumberingIncomplete()); + Assert (next_free_number == n_dofs, + ExcRenumberingIncomplete()); +#endif + + switch (method) + { + case Cuthill_McKee: + break; + case reverse_Cuthill_McKee: + { + for (vector::iterator i=new_number.begin(); i!=new_number.end(); ++i) + *i = n_dofs-*i; + break; + }; + default: + Assert (false, ExcNotImplemented()); + }; + + // actually perform renumbering; + // this is dimension specific and + // thus needs an own function + do_renumbering (level, new_number); +}; + + + +#if deal_II_dimension == 1 + +template <> +void MGDoFHandler<1>::do_renumbering (const unsigned int level, + const vector &new_numbers) { + Assert (new_numbers.size() == n_dofs(level), ExcRenumberingIncomplete()); + + // note that we can not use cell iterators + // in this function since then we would + // renumber the dofs on the interface of + // two cells more than once. Anyway, this + // ways it's not only more correct but also + // faster + for (vector::iterator i=mg_vertex_dofs.begin(); + i!=mg_vertex_dofs.end(); ++i) + // if the present vertex lives on + // the present level + if ((i->get_coarsest_level() <= level) && + (i->get_finest_level() >= level)) + for (unsigned int d=0; ddofs_per_vertex; ++d) + i->set_index (level, d, selected_fe->dofs_per_vertex, + new_numbers[i->get_index (level, d, + selected_fe->dofs_per_vertex)]); + + for (vector::iterator i=mg_levels[level]->line_dofs.begin(); + i!=mg_levels[level]->line_dofs.end(); ++i) + { + Assert (*i != -1, ExcInternalError()); + *i = new_numbers[*i]; + }; +}; + +#endif + + +#if deal_II_dimension == 2 + +template <> +void MGDoFHandler<2>::do_renumbering (const unsigned int level, + const vector &new_numbers) { + Assert (new_numbers.size() == n_dofs(level), ExcRenumberingIncomplete()); + + for (vector::iterator i=mg_vertex_dofs.begin(); + i!=mg_vertex_dofs.end(); ++i) + // if the present vertex lives on + // the present level + if ((i->get_coarsest_level() <= level) && + (i->get_finest_level() >= level)) + for (unsigned int d=0; ddofs_per_vertex; ++d) + i->set_index (level, d, selected_fe->dofs_per_vertex, + new_numbers[i->get_index (level, d, + selected_fe->dofs_per_vertex)]); + + for (vector::iterator i=mg_levels[level]->line_dofs.begin(); + i!=mg_levels[level]->line_dofs.end(); ++i) + { + Assert (*i != -1, ExcInternalError()); + *i = new_numbers[*i]; + }; + for (vector::iterator i=mg_levels[level]->quad_dofs.begin(); + i!=mg_levels[level]->quad_dofs.end(); ++i) + { + Assert (*i != -1, ExcInternalError()); + *i = new_numbers[*i]; + }; +}; + +#endif + + + #if deal_II_dimension == 1 @@ -1074,7 +1351,7 @@ void MGDoFHandler<1>::reserve_space () { Assert (max_level[vertex] >= min_level[vertex], ExcInternalError()); mg_vertex_dofs[vertex].init (min_level[vertex], - max_level[vertex]-min_level[vertex]+1, + max_level[vertex], selected_fe->dofs_per_vertex); }; }; @@ -1162,7 +1439,7 @@ void MGDoFHandler<2>::reserve_space () { Assert (max_level[vertex] >= min_level[vertex], ExcInternalError()); mg_vertex_dofs[vertex].init (min_level[vertex], - max_level[vertex]-min_level[vertex]+1, + max_level[vertex], selected_fe->dofs_per_vertex); }; };