class SparsityPattern;
class CompressedSparsityPattern;
class BlockSparsityPattern;
+class CompressedBlockSparsityPattern;
template <typename number> class SparseMatrix;
template <typename number> class BlockSparseMatrix;
class BlockIndices;
+
/**
* This class represents the matrix denoting the distribution of the degrees
* of freedom of hanging nodes.
* 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
* 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 <int dim, class SparsityPattern>
static
* 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 <int dim, class SparsityPattern>
static
* 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 <int dim, class SparsityPattern>
static void
+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<int> distribute (sparsity.n_rows(), -1);
+
+ for (unsigned int c=0; c<lines.size(); ++c)
+ distribute[lines[c].line] = static_cast<signed int>(c);
+
+ const unsigned int n_rows = sparsity.n_rows();
+ for (unsigned int row=0; row<n_rows; ++row)
+ {
+ // get index of this row
+ // within the blocks
+ const std::pair<unsigned int,unsigned int>
+ 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<n_blocks; ++block_col)
+ {
+ const CompressedSparsityPattern &
+ block_sparsity = sparsity.block(block_row, block_col);
+
+ for (unsigned int j=0; j<block_sparsity.row_length(local_row); ++j)
+ {
+ const unsigned int global_col
+ = index_mapping.local_to_global(block_col,
+ block_sparsity.column_number(local_row,j));
+
+ if (distribute[global_col] != -1)
+ // distribute entry at regular
+ // row @p{row} and irregular column
+ // global_col
+ {
+ for (unsigned int q=0;
+ q!=lines[distribute[global_col]]
+ .entries.size(); ++q)
+ sparsity.add (row,
+ lines[distribute[global_col]].entries[q].first);
+ };
+ };
+ };
+ }
+ else
+ {
+ // row must be
+ // distributed. split the
+ // whole row into the
+ // chunks defined by the
+ // blocks
+ for (unsigned int block_col=0; block_col<n_blocks; ++block_col)
+ {
+ const CompressedSparsityPattern &
+ block_sparsity = sparsity.block(block_row,block_col);
+
+ for (unsigned int j=0; j<block_sparsity.row_length(local_row); ++j)
+ {
+ const unsigned int global_col
+ = index_mapping.local_to_global (block_col,
+ block_sparsity.column_number(local_row,j));
+
+ if (distribute[global_col] == -1)
+ // distribute entry at irregular
+ // row @p{row} and regular column
+ // global_col.
+ {
+ for (unsigned int q=0; q!=lines[distribute[row]].entries.size(); ++q)
+ sparsity.add (lines[distribute[row]].entries[q].first,
+ global_col);
+ }
+ else
+ // distribute entry at irregular
+ // row @p{row} and irregular column
+ // @p{global_col}
+ {
+ for (unsigned int p=0; p!=lines[distribute[row]].entries.size(); ++p)
+ for (unsigned int q=0; q!=lines[distribute[global_col]].entries.size(); ++q)
+ sparsity.add (lines[distribute[row]].entries[p].first,
+ lines[distribute[global_col]].entries[q].first);
+ };
+ };
+ };
+ };
+ };
+};
+
+
+
unsigned int ConstraintMatrix::n_constraints () const
{
return lines.size();
DoFTools::make_boundary_sparsity_pattern (const DoFHandler<deal_II_dimension>& dof,
const std::vector<unsigned int> &,
BlockSparsityPattern &);
+template void
+DoFTools::make_boundary_sparsity_pattern (const DoFHandler<deal_II_dimension>& dof,
+ const std::vector<unsigned int> &,
+ CompressedBlockSparsityPattern &);
+
+
template void
DoFTools::make_boundary_sparsity_pattern (const DoFHandler<deal_II_dimension>& dof,
const FunctionMap<deal_II_dimension>::type &boundary_indicators,
const FunctionMap<deal_II_dimension>::type &boundary_indicators,
const std::vector<unsigned int> &dof_to_boundary_mapping,
BlockSparsityPattern &sparsity);
+template void
+DoFTools::make_boundary_sparsity_pattern (const DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<unsigned int> &dof_to_boundary_mapping,
+ CompressedBlockSparsityPattern &sparsity);
+
+
template void
DoFTools::make_sparsity_pattern (const DoFHandler<deal_II_dimension> &dof,
template void
DoFTools::make_sparsity_pattern (const DoFHandler<deal_II_dimension> &dof,
BlockSparsityPattern &sparsity);
+template void
+DoFTools::make_sparsity_pattern (const DoFHandler<deal_II_dimension> &dof,
+ CompressedBlockSparsityPattern &sparsity);
+
template void
DoFTools::make_sparsity_pattern (const DoFHandler<deal_II_dimension> &dof,
const std::vector<std::vector<bool> > &mask,
BlockSparsityPattern &sparsity);
+template void
+DoFTools::make_sparsity_pattern (const DoFHandler<deal_II_dimension> &dof,
+ const std::vector<std::vector<bool> > &mask,
+ CompressedBlockSparsityPattern &sparsity);
+
+
template
void
#include <base/subscriptor.h>
#include <base/smartpointer.h>
#include <lac/sparsity_pattern.h>
+#include <lac/compressed_sparsity_pattern.h>
#include <lac/block_indices.h>
+template <typename number> 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
* 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 SparsityPatternBase>
+class BlockSparsityPatternBase : public Subscriptor
{
public:
/**
* structure usable by calling
* the @p{reinit} function.
*/
- BlockSparsityPattern ();
+ BlockSparsityPatternBase ();
/**
* Initialize the matrix with the
* 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
* @p{SparsityPattern}, see there
* for the details.
*/
- BlockSparsityPattern (const BlockSparsityPattern &bsp);
+ BlockSparsityPatternBase (const BlockSparsityPatternBase &bsp);
/**
* Destructor.
*/
- ~BlockSparsityPattern ();
+ ~BlockSparsityPatternBase ();
/**
* Resize the matrix. This
* but the latter only for empty
* objects.
*/
- BlockSparsityPattern & operator = (const BlockSparsityPattern &);
+ BlockSparsityPatternBase & operator = (const BlockSparsityPatternBase &);
/**
* This function collects the
* Access the block with the
* given coordinates.
*/
- SparsityPattern &
+ SparsityPatternBase &
block (const unsigned int row,
const unsigned int column);
* given coordinates. Version for
* constant objects.
*/
- const SparsityPattern &
+ const SparsityPatternBase &
block (const unsigned int row,
const unsigned int column) const;
*/
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
*/
<< "The number of blocks " << arg1 << " and " << arg2
<< " are different.");
- private:
+ protected:
/**
* Number of block rows.
/**
* Array of sparsity patterns.
*/
- std::vector<std::vector<SmartPointer<SparsityPattern> > > sub_objects;
+ std::vector<std::vector<SmartPointer<SparsityPatternBase> > > sub_objects;
/**
* Object storing and managing
+/**
+ * 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<SparsityPattern>
+{
+ 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<CompressedSparsityPattern>
+{
+ 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 <class SparsityPatternBase>
inline
-SparsityPattern &
-BlockSparsityPattern::block (const unsigned int row,
- const unsigned int column)
+SparsityPatternBase &
+BlockSparsityPatternBase<SparsityPatternBase>::block (const unsigned int row,
+ const unsigned int column)
{
return *sub_objects[row][column];
};
+template <class SparsityPatternBase>
inline
-const SparsityPattern &
-BlockSparsityPattern::block (const unsigned int row,
+const SparsityPatternBase &
+BlockSparsityPatternBase<SparsityPatternBase>::block (const unsigned int row,
const unsigned int column) const
{
return *sub_objects[row][column];
+template <class SparsityPatternBase>
inline
const BlockIndices &
-BlockSparsityPattern::get_row_indices () const
+BlockSparsityPatternBase<SparsityPatternBase>::get_row_indices () const
{
return row_indices;
};
+template <class SparsityPatternBase>
inline
const BlockIndices &
-BlockSparsityPattern::get_column_indices () const
+BlockSparsityPatternBase<SparsityPatternBase>::get_column_indices () const
{
return column_indices;
};
+template <class SparsityPatternBase>
inline
void
-BlockSparsityPattern::add (const unsigned int i,
- const unsigned int j)
+BlockSparsityPatternBase<SparsityPatternBase>::add (const unsigned int i,
+ const unsigned int j)
{
// if you get an error here, are
// you sure you called
+template <class SparsityPatternBase>
inline
unsigned int
-BlockSparsityPattern::n_block_cols () const
+BlockSparsityPatternBase<SparsityPatternBase>::n_block_cols () const
{
return columns;
}
+template <class SparsityPatternBase>
inline
unsigned int
-BlockSparsityPattern::n_block_rows () const
+BlockSparsityPatternBase<SparsityPatternBase>::n_block_rows () const
{
return rows;
}
-BlockSparsityPattern::BlockSparsityPattern ()
+template <class SparsityPatternBase>
+BlockSparsityPatternBase<SparsityPatternBase>::BlockSparsityPatternBase ()
:
rows (0),
columns (0)
-BlockSparsityPattern::BlockSparsityPattern (const unsigned int r,
- const unsigned int c)
+template <class SparsityPatternBase>
+BlockSparsityPatternBase<SparsityPatternBase>::
+BlockSparsityPatternBase (const unsigned int r,
+ const unsigned int c)
:
rows (0),
columns (0)
-BlockSparsityPattern::~BlockSparsityPattern ()
+template <class SparsityPatternBase>
+BlockSparsityPatternBase<SparsityPatternBase>::~BlockSparsityPatternBase ()
{
// clear all memory
reinit (0,0);
+template <class SparsityPatternBase>
void
-BlockSparsityPattern::reinit (const unsigned int r,
- const unsigned int c)
+BlockSparsityPatternBase<SparsityPatternBase>::reinit (const unsigned int r,
+ const unsigned int c)
{
// delete previous content
for (unsigned int i=0; i<rows; ++i)
for (unsigned int j=0; j<columns; ++j)
{
- SparsityPattern * sp = sub_objects[i][j];
+ SparsityPatternBase * sp = sub_objects[i][j];
sub_objects[i][j] = 0;
delete sp;
};
// set new sizes
rows = r;
columns = c;
- sub_objects.resize (rows, std::vector<SmartPointer<SparsityPattern> > (columns));
+ sub_objects.resize (rows, std::vector<SmartPointer<SparsityPatternBase> > (columns));
// allocate new objects
for (unsigned int i=0; i<rows; ++i)
for (unsigned int j=0; j<columns; ++j)
- sub_objects[i][j] = new SparsityPattern;
+ sub_objects[i][j] = new SparsityPatternBase;
};
-BlockSparsityPattern &
-BlockSparsityPattern::operator = (const BlockSparsityPattern &bsp)
+template <class SparsityPatternBase>
+BlockSparsityPatternBase<SparsityPatternBase> &
+BlockSparsityPatternBase<SparsityPatternBase>::
+operator = (const BlockSparsityPatternBase<SparsityPatternBase> &bsp)
{
Assert (rows == bsp.rows, ExcIncompatibleSizes(rows, bsp.rows));
Assert (columns == bsp.columns, ExcIncompatibleSizes(columns, bsp.columns));
return *this;
};
-
+template <class SparsityPatternBase>
void
-BlockSparsityPattern::collect_sizes ()
+BlockSparsityPatternBase<SparsityPatternBase>::collect_sizes ()
{
std::vector<unsigned int> row_sizes (rows);
std::vector<unsigned int> col_sizes (columns);
+template <class SparsityPatternBase>
void
-BlockSparsityPattern::compress ()
+BlockSparsityPatternBase<SparsityPatternBase>::compress ()
{
for (unsigned int i=0; i<rows; ++i)
for (unsigned int j=0; j<columns; ++j)
+template <class SparsityPatternBase>
bool
-BlockSparsityPattern::empty () const
+BlockSparsityPatternBase<SparsityPatternBase>::empty () const
{
for (unsigned int i=0; i<rows; ++i)
for (unsigned int j=0; j<columns; ++j)
+template <class SparsityPatternBase>
unsigned int
-BlockSparsityPattern::max_entries_per_row () const
+BlockSparsityPatternBase<SparsityPatternBase>::max_entries_per_row () const
{
unsigned int max_entries = 0;
for (unsigned int block_row=0; block_row<rows; ++block_row)
};
+
+template <class SparsityPatternBase>
unsigned int
-BlockSparsityPattern::n_rows () const
+BlockSparsityPatternBase<SparsityPatternBase>::n_rows () const
{
// only count in first column, since
// all rows should be equivalent
+template <class SparsityPatternBase>
unsigned int
-BlockSparsityPattern::n_cols () const
+BlockSparsityPatternBase<SparsityPatternBase>::n_cols () const
{
// only count in first row, since
// all rows should be equivalent
-
-
+template <class SparsityPatternBase>
unsigned int
-BlockSparsityPattern::n_nonzero_elements () const
+BlockSparsityPatternBase<SparsityPatternBase>::n_nonzero_elements () const
{
unsigned int count = 0;
for (unsigned int i=0; i<rows; ++i)
+BlockSparsityPattern::BlockSparsityPattern ()
+{};
+
+
+
+BlockSparsityPattern::BlockSparsityPattern (const unsigned int n_rows,
+ const unsigned int n_columns)
+ :
+ BlockSparsityPatternBase<SparsityPattern>(n_rows,
+ n_columns)
+{};
+
+
+
bool
BlockSparsityPattern::is_compressed () const
{
};
+
unsigned int
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<rows; ++i)
+ for (unsigned int j=0; j<rows; ++j)
+ block(i,j).copy_from (csp.block(i,j));
+
+ // and finally enquire their new
+ // sizes
+ collect_sizes();
+};
+
+
+
+CompressedBlockSparsityPattern::CompressedBlockSparsityPattern ()
+{};
+
+
+
+CompressedBlockSparsityPattern::
+CompressedBlockSparsityPattern (const unsigned int n_rows,
+ const unsigned int n_columns)
+ :
+ BlockSparsityPatternBase<CompressedSparsityPattern>(n_rows,
+ n_columns)
+{};
+
+
+
+// explicit instantiations
+template class BlockSparsityPatternBase<SparsityPattern>;
+template class BlockSparsityPatternBase<CompressedSparsityPattern>;
#include <base/logstream.h>
#include <lac/sparsity_pattern.h>
+#include <lac/block_sparsity_pattern.h>
#include <lac/compressed_sparsity_pattern.h>
#include <grid/tria.h>
#include <grid/tria_iterator.h>
+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<sp1.n_block_rows(); ++i)
+ for (unsigned int j=0; j<sp1.n_block_cols(); ++j)
+ if (!(sp1.block(i,j) == sp2.block(i,j)))
+ return false;
+
+ return true;
+};
+
+
+
template <int dim>
void
check_boundary (const DoFHandler<dim> &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;
std::vector<std::vector<bool> > mask (2, std::vector<bool>(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);
};
-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