From: wolf Date: Sat, 23 Jun 2001 20:14:03 +0000 (+0000) Subject: Implement CompressedBlockSparsityPattern, use it, test it. X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4184ae60a31c97e2886c36a9d1647c6a4ca4f5d3;p=dealii-svn.git Implement CompressedBlockSparsityPattern, use it, test it. git-svn-id: https://svn.dealii.org/trunk@4751 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/deal.II/include/dofs/dof_constraints.h b/deal.II/deal.II/include/dofs/dof_constraints.h index 9cca92fac6..6b78a04660 100644 --- a/deal.II/deal.II/include/dofs/dof_constraints.h +++ b/deal.II/deal.II/include/dofs/dof_constraints.h @@ -22,10 +22,12 @@ class SparsityPattern; class CompressedSparsityPattern; class BlockSparsityPattern; +class CompressedBlockSparsityPattern; template class SparseMatrix; template class BlockSparseMatrix; class BlockIndices; + /** * This class represents the matrix denoting the distribution of the degrees * of freedom of hanging nodes. @@ -290,6 +292,13 @@ class ConstraintMatrix : public Subscriptor * sparsity patterns. */ void condense (CompressedSparsityPattern &sparsity) const; + + /** + * Same function as above, but + * condenses square compressed + * sparsity patterns. + */ + void condense (CompressedBlockSparsityPattern &sparsity) const; /** * Condense a given matrix. The associated diff --git a/deal.II/deal.II/include/dofs/dof_tools.h b/deal.II/deal.II/include/dofs/dof_tools.h index aca12523be..8a315a0aa9 100644 --- a/deal.II/deal.II/include/dofs/dof_tools.h +++ b/deal.II/deal.II/include/dofs/dof_tools.h @@ -193,20 +193,22 @@ class DoFTools * sparsity pattern may be * @ref{SparsityPattern}, * @ref{CompressedSparsityPattern}, - * @ref{BlockSparsityPattern}, or - * any other class that satisfies - * similar requirements. It is - * assumed that the size of the - * sparsity pattern matches the - * number of degrees of freedom - * and that enough unused nonzero - * entries are left to fill the - * sparsity pattern. The nonzero - * entries generated by this - * function are overlaid to - * possible previous content of - * the object, that is previously - * added entries are not deleted. + * @ref{BlockSparsityPattern}, + * @ref{CompressedBlockSparsityPattern}, + * or any other class that + * satisfies similar + * requirements. It is assumed + * that the size of the sparsity + * pattern matches the number of + * degrees of freedom and that + * enough unused nonzero entries + * are left to fill the sparsity + * pattern. The nonzero entries + * generated by this function are + * overlaid to possible previous + * content of the object, that is + * previously added entries are + * not deleted. */ template static @@ -274,9 +276,11 @@ class DoFTools * sparsity pattern may be * @ref{SparsityPattern}, * @ref{CompressedSparsityPattern}, - * @ref{BlockSparsityPattern}, or - * any other class that satisfies - * similar requirements. + * @ref{BlockSparsityPattern}, + * @ref{CompressedBlockSparsityPattern}, + * or any other class that + * satisfies similar + * requirements. */ template static @@ -310,20 +314,22 @@ class DoFTools * sparsity pattern may be * @ref{SparsityPattern}, * @ref{CompressedSparsityPattern}, - * @ref{BlockSparsityPattern}, or - * any other class that satisfies - * similar requirements. It is - * assumed that the size of the - * sparsity pattern matches the - * number of degrees of freedom - * and that enough unused nonzero - * entries are left to fill the - * sparsity pattern. The nonzero - * entries generated by this - * function are overlaid to - * possible previous content of - * the object, that is previously - * added entries are not deleted. + * @ref{BlockSparsityPattern}, + * @ref{CompressedBlockSparsityPattern}, + * or any other class that + * satisfies similar + * requirements. It is assumed + * that the size of the sparsity + * pattern matches the number of + * degrees of freedom and that + * enough unused nonzero entries + * are left to fill the sparsity + * pattern. The nonzero entries + * generated by this function are + * overlaid to possible previous + * content of the object, that is + * previously added entries are + * not deleted. */ template static void diff --git a/deal.II/deal.II/source/dofs/dof_constraints.cc b/deal.II/deal.II/source/dofs/dof_constraints.cc index e3cc3f26bd..96884c75f5 100644 --- a/deal.II/deal.II/source/dofs/dof_constraints.cc +++ b/deal.II/deal.II/source/dofs/dof_constraints.cc @@ -792,6 +792,138 @@ void ConstraintMatrix::condense (BlockSparsityPattern &sparsity) const +void ConstraintMatrix::condense (CompressedBlockSparsityPattern &sparsity) const +{ + Assert (sorted == true, ExcMatrixNotClosed()); + Assert (sparsity.n_rows() == sparsity.n_cols(), + ExcMatrixNotSquare()); + Assert (sparsity.n_block_rows() == sparsity.n_block_cols(), + ExcMatrixNotSquare()); + Assert (sparsity.get_column_indices() == sparsity.get_row_indices(), + ExcMatrixNotSquare()); + + const BlockIndices & + index_mapping = sparsity.get_column_indices(); + + const unsigned int n_blocks = sparsity.n_block_rows(); + + // store for each index whether it + // must be distributed or not. If entry + // is -1, no distribution is necessary. + // otherwise, the number states which + // line in the constraint matrix handles + // this index + std::vector distribute (sparsity.n_rows(), -1); + + for (unsigned int c=0; c(c); + + const unsigned int n_rows = sparsity.n_rows(); + for (unsigned int row=0; row + block_index = index_mapping.global_to_local(row); + const unsigned int block_row = block_index.first; + const unsigned int local_row = block_index.second; + + if (distribute[row] == -1) + // regular line. loop over + // all columns and see + // whether this column must + // be distributed. note that + // as we proceed to + // distribute cols, the loop + // over cols may get longer. + // + // don't try to be clever + // here as in the algorithm + // for the + // CompressedSparsityPattern, + // as that would be much more + // complicated here. after + // all, we know that + // compressed patterns are + // inefficient... + { + + // to loop over all entries + // in this row, we have to + // loop over all blocks in + // this blockrow and the + // corresponding row + // therein + for (unsigned int block_col=0; block_col& dof, const std::vector &, BlockSparsityPattern &); +template void +DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof, + const std::vector &, + CompressedBlockSparsityPattern &); + + template void DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof, const FunctionMap::type &boundary_indicators, @@ -2197,6 +2203,13 @@ DoFTools::make_boundary_sparsity_pattern (const DoFHandler& d const FunctionMap::type &boundary_indicators, const std::vector &dof_to_boundary_mapping, BlockSparsityPattern &sparsity); +template void +DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof, + const FunctionMap::type &boundary_indicators, + const std::vector &dof_to_boundary_mapping, + CompressedBlockSparsityPattern &sparsity); + + template void DoFTools::make_sparsity_pattern (const DoFHandler &dof, @@ -2209,6 +2222,10 @@ DoFTools::make_sparsity_pattern (const DoFHandler &dof, template void DoFTools::make_sparsity_pattern (const DoFHandler &dof, BlockSparsityPattern &sparsity); +template void +DoFTools::make_sparsity_pattern (const DoFHandler &dof, + CompressedBlockSparsityPattern &sparsity); + template void DoFTools::make_sparsity_pattern (const DoFHandler &dof, @@ -2225,6 +2242,12 @@ DoFTools::make_sparsity_pattern (const DoFHandler &dof, const std::vector > &mask, BlockSparsityPattern &sparsity); +template void +DoFTools::make_sparsity_pattern (const DoFHandler &dof, + const std::vector > &mask, + CompressedBlockSparsityPattern &sparsity); + + template void diff --git a/deal.II/lac/include/lac/block_sparsity_pattern.h b/deal.II/lac/include/lac/block_sparsity_pattern.h index ca38ead500..d7480cd448 100644 --- a/deal.II/lac/include/lac/block_sparsity_pattern.h +++ b/deal.II/lac/include/lac/block_sparsity_pattern.h @@ -18,22 +18,31 @@ #include #include #include +#include #include +template class BlockSparseMatrix; +class BlockSparsityPattern; +class CompressedBlockSparsityPattern; + + /** - * This is a block version of the sparsity pattern class. It has not - * much functionality, but only administrated an array of sparsity - * pattern objects and delegates work to them. It has mostly the same - * interface as has the @p{SparsityPattern} class, and simply transforms + * This is the base class for block versions of the sparsity pattern + * and compressed sparsity pattern classes. It has not much + * functionality, but only administrates an array of sparsity pattern + * objects and delegates work to them. It has mostly the same + * interface as has the @ref{SparsityPattern} and + * @ref{CompressedSparsityPattern} classes, and simply transforms * calls to its member functions to calls to the respective member * functions of the member sparsity patterns. * - * The largest difference between the @p{SparsityPattern} class and - * this class is that mostly, the matrices have different properties - * and you will want to work on the blocks making up the matrix rather - * than the whole matrix. You can access the different blocks using - * the @p{block(row,col)} function. + * The largest difference between the @ref{SparsityPattern} and + * @ref{CompressedSparsityPattern} classes and this class is that + * mostly, the matrices have different properties and you will want to + * work on the blocks making up the matrix rather than the whole + * matrix. You can access the different blocks using the + * @p{block(row,col)} function. * * Attention: this object is not automatically notified if the size of * one of its subobjects' size is changed. After you initialize the @@ -43,9 +52,13 @@ * that all sub-matrices in a column have to have the same number of * columns. * - * @author Wolfgang Bangerth, 2000 + * You will in general not want to use this class, but one of the + * derived classes. + * + * @author Wolfgang Bangerth, 2000, 2001 */ -class BlockSparsityPattern : public Subscriptor +template +class BlockSparsityPatternBase : public Subscriptor { public: /** @@ -72,7 +85,7 @@ class BlockSparsityPattern : public Subscriptor * structure usable by calling * the @p{reinit} function. */ - BlockSparsityPattern (); + BlockSparsityPatternBase (); /** * Initialize the matrix with the @@ -82,8 +95,8 @@ class BlockSparsityPattern : public Subscriptor * to call @p{collect_args} after * you assign them sizes. */ - BlockSparsityPattern (const unsigned int n_rows, - const unsigned int n_columns); + BlockSparsityPatternBase (const unsigned int n_rows, + const unsigned int n_columns); /** * Copy constructor. This @@ -96,12 +109,12 @@ class BlockSparsityPattern : public Subscriptor * @p{SparsityPattern}, see there * for the details. */ - BlockSparsityPattern (const BlockSparsityPattern &bsp); + BlockSparsityPatternBase (const BlockSparsityPatternBase &bsp); /** * Destructor. */ - ~BlockSparsityPattern (); + ~BlockSparsityPatternBase (); /** * Resize the matrix. This @@ -140,7 +153,7 @@ class BlockSparsityPattern : public Subscriptor * but the latter only for empty * objects. */ - BlockSparsityPattern & operator = (const BlockSparsityPattern &); + BlockSparsityPatternBase & operator = (const BlockSparsityPatternBase &); /** * This function collects the @@ -160,7 +173,7 @@ class BlockSparsityPattern : public Subscriptor * Access the block with the * given coordinates. */ - SparsityPattern & + SparsityPatternBase & block (const unsigned int row, const unsigned int column); @@ -170,7 +183,7 @@ class BlockSparsityPattern : public Subscriptor * given coordinates. Version for * constant objects. */ - const SparsityPattern & + const SparsityPatternBase & block (const unsigned int row, const unsigned int column) const; @@ -290,21 +303,6 @@ class BlockSparsityPattern : public Subscriptor */ unsigned int n_nonzero_elements () const; - /** - * Return whether the structure - * is compressed or not, - * i.e. whether all sub-matrices - * are compressed. - */ - bool is_compressed () const; - - /** - * Determine an estimate for the - * memory consumption (in bytes) - * of this object. - */ - unsigned int memory_consumption () const; - /** * Exception */ @@ -334,7 +332,7 @@ class BlockSparsityPattern : public Subscriptor << "The number of blocks " << arg1 << " and " << arg2 << " are different."); - private: + protected: /** * Number of block rows. @@ -349,7 +347,7 @@ class BlockSparsityPattern : public Subscriptor /** * Array of sparsity patterns. */ - std::vector > > sub_objects; + std::vector > > sub_objects; /** * Object storing and managing @@ -379,23 +377,132 @@ class BlockSparsityPattern : public Subscriptor +/** + * This class extends the base class to implement an array of sparsity + * patterns that can be used by block sparse matrix objects. It only + * adds a few additional member functions, but the main interface + * stems from the base class, see there for more information. + * + * @author Wolfgang Bangerth, 2000, 2001 + */ +class BlockSparsityPattern : public BlockSparsityPatternBase +{ + public: + + /** + * Initialize the matrix empty, + * that is with no memory + * allocated. This is useful if + * you want such objects as + * member variables in other + * classes. You can make the + * structure usable by calling + * the @p{reinit} function. + */ + BlockSparsityPattern (); + + /** + * Initialize the matrix with the + * given number of block rows and + * columns. The blocks themselves + * are still empty, and you have + * to call @p{collect_args} after + * you assign them sizes. + */ + BlockSparsityPattern (const unsigned int n_rows, + const unsigned int n_columns); + + /** + * Return whether the structure + * is compressed or not, + * i.e. whether all sub-matrices + * are compressed. + */ + bool is_compressed () const; + + /** + * Determine an estimate for the + * memory consumption (in bytes) + * of this object. + */ + unsigned int memory_consumption () const; + + /** + * Copy data from an object of + * type + * @ref{CompressedBlockSparsityPattern}, + * i.e. resize this object to the + * size of the given argument, + * and copy over the contents of + * each of the + * subobjects. Previous content + * of this object is lost. + */ + void copy_from (const CompressedBlockSparsityPattern &csp); +}; + + + +/** + * This class extends the base class to implement an array of + * compressed sparsity patterns that can be used to initialize objects + * of type @ref{BlockSparsityPattern}. It does not add additional + * member functions, but rather acts as a @p{typedef} to introduce the + * name of this class, without requiring the user to specify the + * templated name of the base class. For information on the interface + * of this class refer to the base class. + * + * @author Wolfgang Bangerth, 2000, 2001 + */ +class CompressedBlockSparsityPattern : public BlockSparsityPatternBase +{ + public: + + /** + * Initialize the matrix empty, + * that is with no memory + * allocated. This is useful if + * you want such objects as + * member variables in other + * classes. You can make the + * structure usable by calling + * the @p{reinit} function. + */ + CompressedBlockSparsityPattern (); + + /** + * Initialize the matrix with the + * given number of block rows and + * columns. The blocks themselves + * are still empty, and you have + * to call @p{collect_args} after + * you assign them sizes. + */ + CompressedBlockSparsityPattern (const unsigned int n_rows, + const unsigned int n_columns); +}; + + + /*---------------------- Template functions -----------------------------------*/ +template inline -SparsityPattern & -BlockSparsityPattern::block (const unsigned int row, - const unsigned int column) +SparsityPatternBase & +BlockSparsityPatternBase::block (const unsigned int row, + const unsigned int column) { return *sub_objects[row][column]; }; +template inline -const SparsityPattern & -BlockSparsityPattern::block (const unsigned int row, +const SparsityPatternBase & +BlockSparsityPatternBase::block (const unsigned int row, const unsigned int column) const { return *sub_objects[row][column]; @@ -403,28 +510,31 @@ BlockSparsityPattern::block (const unsigned int row, +template inline const BlockIndices & -BlockSparsityPattern::get_row_indices () const +BlockSparsityPatternBase::get_row_indices () const { return row_indices; }; +template inline const BlockIndices & -BlockSparsityPattern::get_column_indices () const +BlockSparsityPatternBase::get_column_indices () const { return column_indices; }; +template inline void -BlockSparsityPattern::add (const unsigned int i, - const unsigned int j) +BlockSparsityPatternBase::add (const unsigned int i, + const unsigned int j) { // if you get an error here, are // you sure you called @@ -438,18 +548,20 @@ BlockSparsityPattern::add (const unsigned int i, +template inline unsigned int -BlockSparsityPattern::n_block_cols () const +BlockSparsityPatternBase::n_block_cols () const { return columns; } +template inline unsigned int -BlockSparsityPattern::n_block_rows () const +BlockSparsityPatternBase::n_block_rows () const { return rows; } diff --git a/deal.II/lac/source/block_sparsity_pattern.cc b/deal.II/lac/source/block_sparsity_pattern.cc index 3ffa3bb07a..f6ef2959aa 100644 --- a/deal.II/lac/source/block_sparsity_pattern.cc +++ b/deal.II/lac/source/block_sparsity_pattern.cc @@ -16,7 +16,8 @@ -BlockSparsityPattern::BlockSparsityPattern () +template +BlockSparsityPatternBase::BlockSparsityPatternBase () : rows (0), columns (0) @@ -24,8 +25,10 @@ BlockSparsityPattern::BlockSparsityPattern () -BlockSparsityPattern::BlockSparsityPattern (const unsigned int r, - const unsigned int c) +template +BlockSparsityPatternBase:: +BlockSparsityPatternBase (const unsigned int r, + const unsigned int c) : rows (0), columns (0) @@ -35,7 +38,8 @@ BlockSparsityPattern::BlockSparsityPattern (const unsigned int r, -BlockSparsityPattern::~BlockSparsityPattern () +template +BlockSparsityPatternBase::~BlockSparsityPatternBase () { // clear all memory reinit (0,0); @@ -43,15 +47,16 @@ BlockSparsityPattern::~BlockSparsityPattern () +template void -BlockSparsityPattern::reinit (const unsigned int r, - const unsigned int c) +BlockSparsityPatternBase::reinit (const unsigned int r, + const unsigned int c) { // delete previous content for (unsigned int i=0; i > (columns)); + sub_objects.resize (rows, std::vector > (columns)); // allocate new objects for (unsigned int i=0; i +BlockSparsityPatternBase & +BlockSparsityPatternBase:: +operator = (const BlockSparsityPatternBase &bsp) { Assert (rows == bsp.rows, ExcIncompatibleSizes(rows, bsp.rows)); Assert (columns == bsp.columns, ExcIncompatibleSizes(columns, bsp.columns)); @@ -84,12 +91,12 @@ BlockSparsityPattern::operator = (const BlockSparsityPattern &bsp) return *this; }; - +template void -BlockSparsityPattern::collect_sizes () +BlockSparsityPatternBase::collect_sizes () { std::vector row_sizes (rows); std::vector col_sizes (columns); @@ -126,8 +133,9 @@ BlockSparsityPattern::collect_sizes () +template void -BlockSparsityPattern::compress () +BlockSparsityPatternBase::compress () { for (unsigned int i=0; i bool -BlockSparsityPattern::empty () const +BlockSparsityPatternBase::empty () const { for (unsigned int i=0; i unsigned int -BlockSparsityPattern::max_entries_per_row () const +BlockSparsityPatternBase::max_entries_per_row () const { unsigned int max_entries = 0; for (unsigned int block_row=0; block_row unsigned int -BlockSparsityPattern::n_rows () const +BlockSparsityPatternBase::n_rows () const { // only count in first column, since // all rows should be equivalent @@ -178,8 +190,9 @@ BlockSparsityPattern::n_rows () const +template unsigned int -BlockSparsityPattern::n_cols () const +BlockSparsityPatternBase::n_cols () const { // only count in first row, since // all rows should be equivalent @@ -191,10 +204,9 @@ BlockSparsityPattern::n_cols () const - - +template unsigned int -BlockSparsityPattern::n_nonzero_elements () const +BlockSparsityPatternBase::n_nonzero_elements () const { unsigned int count = 0; for (unsigned int i=0; i(n_rows, + n_columns) +{}; + + + bool BlockSparsityPattern::is_compressed () const { @@ -216,6 +242,7 @@ BlockSparsityPattern::is_compressed () const }; + unsigned int BlockSparsityPattern::memory_consumption () const { @@ -231,3 +258,43 @@ BlockSparsityPattern::memory_consumption () const return mem; }; + + + +void +BlockSparsityPattern::copy_from (const CompressedBlockSparsityPattern &csp) +{ + // delete old content, set block + // sizes anew + reinit (csp.n_block_rows(), csp.n_block_cols()); + + // copy over blocks + for (unsigned int i=0; i(n_rows, + n_columns) +{}; + + + +// explicit instantiations +template class BlockSparsityPatternBase; +template class BlockSparsityPatternBase; diff --git a/tests/deal.II/sparsity_pattern.cc b/tests/deal.II/sparsity_pattern.cc index ec18708351..de8c17e376 100644 --- a/tests/deal.II/sparsity_pattern.cc +++ b/tests/deal.II/sparsity_pattern.cc @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -56,6 +57,25 @@ bool operator == (const SparsityPattern &sp1, +bool operator == (const BlockSparsityPattern &sp1, + const BlockSparsityPattern &sp2) +{ + if (sp1.n_block_rows() != sp2.n_block_rows()) + return false; + + if (sp1.n_block_cols() != sp2.n_block_cols()) + return false; + + for (unsigned int i=0; i void check_boundary (const DoFHandler &dof) @@ -84,7 +104,7 @@ check_boundary (const DoFHandler &dof) // patterns is checked in other // tests, so only make sure that // sparsity_[12] are equal - deallog << __PRETTY_FUNCTION__ + deallog << "Check boundary" << " -- " << (sparsity_1 == sparsity_2 ? "ok" : "failed") << std::endl; @@ -127,29 +147,76 @@ check () std::vector > mask (2, std::vector(2, false)); mask[0][0] = mask[1][1] = true; + +//--------------- Regular sparsity pattern checks ----------------- + // first way: directly SparsityPattern sparsity_1 (dof.n_dofs(), dof.n_dofs()); DoFTools::make_sparsity_pattern (dof, mask, sparsity_1); constraints.condense (sparsity_1); sparsity_1.compress (); - // second way: via CompressedSparsityPattern + // second way: via + // CompressedSparsityPattern SparsityPattern sparsity_2; - CompressedSparsityPattern csp (dof.n_dofs()); - DoFTools::make_sparsity_pattern (dof, mask, csp); - constraints.condense (csp); - sparsity_2.copy_from (csp); + CompressedSparsityPattern csp_2 (dof.n_dofs()); + DoFTools::make_sparsity_pattern (dof, mask, csp_2); + constraints.condense (csp_2); + sparsity_2.copy_from (csp_2); // the exact content of sparsity // patterns is checked in other // tests, so only make sure that // sparsity_[12] are equal - deallog << __PRETTY_FUNCTION__ + deallog << "Check 1:" << " -- " << (sparsity_1 == sparsity_2 ? "ok" : "failed") << std::endl; + + + +//--------------- Block sparsity pattern checks ----------------- + + const unsigned int n = dof.n_dofs(); + const unsigned int n1 = n/3; + const unsigned int n2 = n - n1; + + BlockSparsityPattern sparsity_3(2,2); + sparsity_3.block(0,0).reinit (n1,n1,n); + sparsity_3.block(1,0).reinit (n2,n1,n); + sparsity_3.block(0,1).reinit (n1,n2,n); + sparsity_3.block(1,1).reinit (n2,n2,n); + sparsity_3.collect_sizes (); + + DoFTools::make_sparsity_pattern (dof, sparsity_3); + constraints.condense (sparsity_3); + sparsity_3.compress (); + + BlockSparsityPattern sparsity_4; + CompressedBlockSparsityPattern csp_4(2,2); + csp_4.block(0,0).reinit (n1,n1); + csp_4.block(1,0).reinit (n2,n1); + csp_4.block(0,1).reinit (n1,n2); + csp_4.block(1,1).reinit (n2,n2); + csp_4.collect_sizes (); + + DoFTools::make_sparsity_pattern (dof, csp_4); + constraints.condense (csp_4); + csp_4.compress (); + + sparsity_4.copy_from (csp_4); + + deallog << "Check 2:" + << " -- " + << (sparsity_3 == sparsity_4 ? "ok" : "failed") + << std::endl; + +//--------------- Sparsity pattern checks for +// boundary sparsity generators ----------------- + + // check boundary matrices check_boundary (dof); }; diff --git a/tests/deal.II/sparsity_pattern.checked b/tests/deal.II/sparsity_pattern.checked index 5caca2e119..76b2767418 100644 --- a/tests/deal.II/sparsity_pattern.checked +++ b/tests/deal.II/sparsity_pattern.checked @@ -1,7 +1,10 @@ -DEAL:1d::void check<1>() -- ok -DEAL:1d::void check_boundary<1>(const DoFHandler<1> &) -- ok -DEAL:2d::void check<2>() -- ok -DEAL:2d::void check_boundary<2>(const DoFHandler<2> &) -- ok -DEAL:3d::void check<3>() -- ok -DEAL:3d::void check_boundary<3>(const DoFHandler<3> &) -- ok +DEAL:1d::Check 1: -- ok +DEAL:1d::Check 2: -- ok +DEAL:1d::Check boundary -- ok +DEAL:2d::Check 1: -- ok +DEAL:2d::Check 2: -- ok +DEAL:2d::Check boundary -- ok +DEAL:3d::Check 1: -- ok +DEAL:3d::Check 2: -- ok +DEAL:3d::Check boundary -- ok