From 26c34f6b45bdd540aaf70c158ca3f4653d3e8a7d Mon Sep 17 00:00:00 2001
From: wolf
Date: Fri, 22 Jun 2001 10:36:46 +0000
Subject: [PATCH] New class CompressedSparsityPattern. Use it. New test.
git-svn-id: https://svn.dealii.org/trunk@4749 0785d39b-7218-0410-832d-ea1e28bc413d
---
.../deal.II/include/dofs/dof_constraints.h | 8 +
deal.II/deal.II/include/dofs/dof_tools.h | 113 ++++--
.../deal.II/source/dofs/dof_constraints.cc | 256 +++++++++---
deal.II/deal.II/source/dofs/dof_tools.cc | 74 +++-
deal.II/doc/news/2001/c-3-1.html | 21 +
.../include/lac/compressed_sparsity_pattern.h | 366 ++++++++++++++++++
deal.II/lac/include/lac/sparsity_pattern.h | 10 +
.../lac/source/compressed_sparsity_pattern.cc | 219 +++++++++++
deal.II/lac/source/sparsity_pattern.cc | 24 +-
tests/deal.II/Makefile.in | 3 +-
tests/deal.II/matrices.cc | 4 +-
tests/deal.II/sparsity_pattern.cc | 175 +++++++++
12 files changed, 1164 insertions(+), 109 deletions(-)
create mode 100644 deal.II/lac/include/lac/compressed_sparsity_pattern.h
create mode 100644 deal.II/lac/source/compressed_sparsity_pattern.cc
create mode 100644 tests/deal.II/sparsity_pattern.cc
diff --git a/deal.II/deal.II/include/dofs/dof_constraints.h b/deal.II/deal.II/include/dofs/dof_constraints.h
index ea0a522b89..9cca92fac6 100644
--- a/deal.II/deal.II/include/dofs/dof_constraints.h
+++ b/deal.II/deal.II/include/dofs/dof_constraints.h
@@ -20,6 +20,7 @@
#include
class SparsityPattern;
+class CompressedSparsityPattern;
class BlockSparsityPattern;
template class SparseMatrix;
template class BlockSparseMatrix;
@@ -282,6 +283,13 @@ class ConstraintMatrix : public Subscriptor
* patterns.
*/
void condense (BlockSparsityPattern &sparsity) const;
+
+ /**
+ * Same function as above, but
+ * condenses square compressed
+ * sparsity patterns.
+ */
+ void condense (CompressedSparsityPattern &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 7d537ca869..aca12523be 100644
--- a/deal.II/deal.II/include/dofs/dof_tools.h
+++ b/deal.II/deal.II/include/dofs/dof_tools.h
@@ -192,33 +192,44 @@ class DoFTools
* The actual type of the
* sparsity pattern may be
* @ref{SparsityPattern},
- * @ref{BlockSparsityPattern}, or any
- * other class that satisfies
- * similar requirements.
+ * @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.
*/
template
- static void make_sparsity_pattern (const DoFHandler &dof,
- SparsityPattern &sparsity_pattern);
+ static
+ void
+ make_sparsity_pattern (const DoFHandler &dof,
+ SparsityPattern &sparsity_pattern);
/**
* Locate non-zero entries for
- * mixed methods. This function
- * does mostly the same as the
- * other @p{make_sparsity_pattern},
- * but it is specialized for
- * mixed finite elements and
- * allows to specify which
- * variables couple in which
- * equation. For example, if
- * wanted to solve the Stokes
- * equations,
- *
- *
+ * ector valued finite elements.
+ * This function does mostly the
+ * same as the previous
+ * @p{make_sparsity_pattern}, but
+ * it is specialized for vector
+ * finite elements and allows to
+ * specify which variables couple
+ * in which equation. For
+ * example, if wanted to solve
+ * the Stokes equations,
* @begin{verbatim}
* -\Delta \vec u + \nabla p = 0,
* \div u = 0
* @end{verbatim}
- *
* in two space dimensions,
* using stable Q2/Q1 mixed
* elements (using the @ref{FESystem}
@@ -228,7 +239,6 @@ class DoFTools
* rather may want to give the
* following pattern of
* couplings:
- *
* @begin{verbatim}
* 1 0 1
* 0 1 1
@@ -263,15 +273,18 @@ class DoFTools
* The actual type of the
* sparsity pattern may be
* @ref{SparsityPattern},
- * @ref{BlockSparsityPattern}, or any
- * other class that satisfies
+ * @ref{CompressedSparsityPattern},
+ * @ref{BlockSparsityPattern}, or
+ * any other class that satisfies
* similar requirements.
*/
- template
- static void make_sparsity_pattern (const DoFHandler &dof,
- const std::vector > &mask,
- SparsityPattern &sparsity_pattern);
-
+ template
+ static
+ void
+ make_sparsity_pattern (const DoFHandler &dof,
+ const std::vector > &mask,
+ SparsityPattern &sparsity_pattern);
+
/**
* Write the sparsity structure
* of the matrix composed of the
@@ -293,12 +306,26 @@ class DoFTools
* matrix yourself, using
* @ref{SparsityPattern}@p{::compress()}.
*
- * Since this function is
- * obviously useless in one
- * spatial dimension, it is not
- * implemented.
+ * The actual type of the
+ * 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.
*/
- template
+ template
static void
make_boundary_sparsity_pattern (const DoFHandler &dof,
const std::vector &dof_to_boundary_mapping,
@@ -306,8 +333,13 @@ class DoFTools
/**
* Declaration of same function
- * for different space dimension.
+ * for one space dimension. The
+ * resulting sparsity pattern
+ * couples all dofs of the
+ * specified end points to each
+ * other.
*/
+ template
static void
make_boundary_sparsity_pattern (const DoFHandler<1> &dof,
const std::vector &dof_to_boundary_mapping,
@@ -340,22 +372,27 @@ class DoFTools
* the function pointers to null
* pointers.
*
- * Since this function is
- * obviously useless in one
- * spatial dimension, it is not
- * implemented.
+ * For the type of the sparsity
+ * pattern, the same holds as
+ * said above.
*/
- template
+ template
static void
make_boundary_sparsity_pattern (const DoFHandler &dof,
const typename FunctionMap::type &boundary_indicators,
const std::vector &dof_to_boundary_mapping,
SparsityPattern &sparsity);
+
/**
* Declaration of same function
- * for different space dimension.
+ * for one space dimension. The
+ * resulting sparsity pattern
+ * couples all dofs of the
+ * specified end points to each
+ * other.
*/
+ template
static void
make_boundary_sparsity_pattern (const DoFHandler<1> &dof,
const FunctionMap<1>::type &boundary_indicators,
diff --git a/deal.II/deal.II/source/dofs/dof_constraints.cc b/deal.II/deal.II/source/dofs/dof_constraints.cc
index 9538c3407c..e3cc3f26bd 100644
--- a/deal.II/deal.II/source/dofs/dof_constraints.cc
+++ b/deal.II/deal.II/source/dofs/dof_constraints.cc
@@ -17,6 +17,7 @@
#include
#include
+#include
#include
#include
#include
@@ -423,60 +424,227 @@ void ConstraintMatrix::condense (SparsityPattern &sparsity) const
for (unsigned int row=0; row 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
#include
#include
+#include
#include
#include
@@ -68,6 +69,7 @@ DoFTools::make_sparsity_pattern (const DoFHandler &dof,
}
+
template
void
DoFTools::make_sparsity_pattern (const DoFHandler &dof,
@@ -115,8 +117,10 @@ DoFTools::make_sparsity_pattern (const DoFHandler &dof,
}
+
#if deal_II_dimension == 1
+template
void
DoFTools::make_boundary_sparsity_pattern (const DoFHandler<1> &dof_handler,
const FunctionMap<1>::type &function_map,
@@ -160,6 +164,7 @@ DoFTools::make_boundary_sparsity_pattern (const DoFHandler<1> &dof_h
+template
void DoFTools::make_boundary_sparsity_pattern (const DoFHandler<1> &dof_handler,
const std::vector &dof_to_boundary_mapping,
SparsityPattern &sparsity)
@@ -179,7 +184,7 @@ void DoFTools::make_boundary_sparsity_pattern (const DoFHandler<1> &dof_handler,
#endif
-template
+template
void
DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
const std::vector &dof_to_boundary_mapping,
@@ -192,9 +197,19 @@ DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
ExcDimensionMismatch (sparsity.n_rows(), dof.n_boundary_dofs()));
Assert (sparsity.n_cols() == dof.n_boundary_dofs(),
ExcDimensionMismatch (sparsity.n_cols(), dof.n_boundary_dofs()));
- Assert (*max_element(dof_to_boundary_mapping.begin(),
- dof_to_boundary_mapping.end()) == sparsity.n_rows()-1,
- ExcInternalError());
+#ifdef DEBUG
+ if (true)
+ {
+ unsigned int max_element = 0;
+ for (std::vector::const_iterator i=dof_to_boundary_mapping.begin();
+ i!=dof_to_boundary_mapping.end(); ++i)
+ if ((*i != DoFHandler::invalid_dof_index) &&
+ (*i > max_element))
+ max_element = *i;
+ Assert (max_element == sparsity.n_rows()-1,
+ ExcInternalError());
+ };
+#endif
const unsigned int dofs_per_face = dof.get_fe().dofs_per_face;
std::vector dofs_on_this_face(dofs_per_face);
@@ -216,12 +231,6 @@ DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
{
face->get_dof_indices (dofs_on_this_face);
- // make sure all dof indices have a
- // boundary index
- Assert (*min_element(dofs_on_this_face.begin(),
- dofs_on_this_face.end()) != DoFHandler::invalid_dof_index,
- ExcInternalError());
-
// make sparsity pattern for this cell
for (unsigned int i=0; i& dof,
};
-template
+
+template
void DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
const typename FunctionMap::type &boundary_indicators,
const std::vector &dof_to_boundary_mapping,
@@ -270,11 +280,6 @@ void DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
{
face->get_dof_indices (dofs_on_this_face);
- // make sure all dof indices have a
- // boundary index
- Assert (*min_element(dofs_on_this_face.begin(),
- dofs_on_this_face.end()) != DoFHandler::invalid_dof_index,
- ExcInternalError());
// make sparsity pattern for this cell
for (unsigned int i=0; i& dof,
SparsityPattern &,
const FullMatrix&,
const FullMatrix&);
+#endif
+
template void
DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
const std::vector &,
SparsityPattern &);
template void
+DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
+ const std::vector &,
+ CompressedSparsityPattern &);
+template void
+DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
+ const std::vector &,
+ BlockSparsityPattern &);
+template void
DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
const FunctionMap::type &boundary_indicators,
const std::vector &dof_to_boundary_mapping,
SparsityPattern &sparsity);
-#endif
+template void
+DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
+ const FunctionMap::type &boundary_indicators,
+ const std::vector &dof_to_boundary_mapping,
+ CompressedSparsityPattern &sparsity);
+template void
+DoFTools::make_boundary_sparsity_pattern (const DoFHandler& dof,
+ const FunctionMap::type &boundary_indicators,
+ const std::vector &dof_to_boundary_mapping,
+ BlockSparsityPattern &sparsity);
template void
-DoFTools::make_sparsity_pattern (const DoFHandler& dof,
+DoFTools::make_sparsity_pattern (const DoFHandler &dof,
SparsityPattern &sparsity);
+template void
+DoFTools::make_sparsity_pattern (const DoFHandler &dof,
+ CompressedSparsityPattern &sparsity);
+
template void
DoFTools::make_sparsity_pattern (const DoFHandler &dof,
BlockSparsityPattern &sparsity);
template void
-DoFTools::make_sparsity_pattern (const DoFHandler& dof,
+DoFTools::make_sparsity_pattern (const DoFHandler &dof,
const std::vector > &mask,
SparsityPattern &sparsity);
template void
-DoFTools::make_sparsity_pattern (const DoFHandler& dof,
+DoFTools::make_sparsity_pattern (const DoFHandler &dof,
+ const std::vector > &mask,
+ CompressedSparsityPattern &sparsity);
+
+template void
+DoFTools::make_sparsity_pattern (const DoFHandler &dof,
const std::vector > &mask,
BlockSparsityPattern &sparsity);
+
template
void
DoFTools::distribute_cell_to_dof_vector (const DoFHandler &dof_handler,
diff --git a/deal.II/doc/news/2001/c-3-1.html b/deal.II/doc/news/2001/c-3-1.html
index 4f3d503521..2a35c76891 100644
--- a/deal.II/doc/news/2001/c-3-1.html
+++ b/deal.II/doc/news/2001/c-3-1.html
@@ -305,6 +305,16 @@ documentation, etc.
lac
+ -
+ New: Class CompressedSparsityPattern
+ may be used as an intermediate form of the SparsityPattern
class if memory
+ requirements are tight during construction of the sparsity
+ pattern.
+
+ (WB 2001/06/22)
+
+
-
New: There are now functions
SparsityPattern::copy_from
and
@@ -441,6 +451,17 @@ documentation, etc.
deal.II
+ -
+ New: Implement
+ DoFTools::make_sparsity_pattern
,
+ DoFTools::make_boundary_sparsity_pattern
,
+ and
+ ConstraintMatrix::condense
to work on
+ the CompressedSparsityPattern
class.
+
+ (WB 2001/06/22)
+
+
New: FE*Values::get_quadrature
returns a reference to the quadrature formula used by a
diff --git a/deal.II/lac/include/lac/compressed_sparsity_pattern.h b/deal.II/lac/include/lac/compressed_sparsity_pattern.h
new file mode 100644
index 0000000000..c5212885e5
--- /dev/null
+++ b/deal.II/lac/include/lac/compressed_sparsity_pattern.h
@@ -0,0 +1,366 @@
+//---------------------------- compressed_sparsity_pattern.h ---------------------------
+// $Id$
+// Version: $Name$
+//
+// Copyright (C) 2001 by the deal.II authors
+//
+// This file is subject to QPL and may not be distributed
+// without copyright and license information. Please refer
+// to the file deal.II/doc/license.html for the text and
+// further information on this license.
+//
+//---------------------------- compressed_sparsity_pattern.h ---------------------------
+#ifndef __deal2__compressed_sparsity_pattern_h
+#define __deal2__compressed_sparsity_pattern_h
+
+
+#include
+#include
+
+template class SparseMatrix;
+
+#include
+#include
+
+
+/**
+ * This class acts as an intermediate form of the
+ * @ref{SparsityPattern} class. From the interface it mostly
+ * represents a @ref{SparsityPattern} object that is kept compressed
+ * at all times. However, since the final sparsity pattern is not
+ * known while constructing it, keeping the pattern compressed at all
+ * times can only be achieved at the expense of either increased
+ * memory or run time consumption upon use. The main purpose of this
+ * class is to avoid some memory bottlenecks, so we chose to implement
+ * it memory conservative, but the chosen data format is too unsuited
+ * to be used for actual matrices. It is therefore necessary to first
+ * copy the data of this object over to an object of type
+ * @ref{SparsityPattern} before using it in actual matrices.
+ *
+ * Another viewpoint is that this class does not need up front
+ * allocation of a certain amount of memory, but grows as necessary.
+ *
+ *
+ * @sect3{Rationale}
+ *
+ * When constructing the sparsity pattern of a matrix, you usually
+ * first have to provide an empty sparsity pattern object with a fixed
+ * maximal number of entries per row. To find out about this maximal
+ * row length, one usually calls the function
+ * @ref{DoFHandler}@p{::max_couplings_per_dof} which returns an
+ * estimate for that quantity. While this estimate is usually quite
+ * good in 2d and exact in 1d, it is often significantly too large in
+ * 3d and especially for higher order elements. Furthermore, normally
+ * only a small fraction of the rows of a matrix will end up having
+ * the maximal number of nonzero entries per row (usually those nodes
+ * adjacent to hanging nodes), most have much less. In effect, the
+ * empty @ref{SparsityPattern} object has allocated much too much
+ * memory. Although this unnecessarily allocated memory is later freed
+ * when @ref{SparsityPattern}@p{::compress} is called, this
+ * overallocation has, with higher order elements and in 3d, sometimes
+ * been so large that the program aborted due to lack of memory.
+ *
+ * This class therefore provides an alternative representation of a
+ * sparsity pattern: we don't specify a maximal row length initially,
+ * but store a set of column indices indicating possible nonzero
+ * entries in the sparsity pattern for each row. This is very much
+ * like the final "compressed" format used in the
+ * @ref{SparsityPattern} object after compression, but uses a less
+ * compact memory storage format, since the exact number of entries
+ * per row is only known a posteriori and since it may change (for the
+ * @ref{SparsityPattern} class, no more changes are allowed after
+ * compressing it). We can therefore not store all the column indices
+ * in a big array, but have to use a vector of sets. This can later be
+ * used to actually initialize a @ref{SparsityPattern} object with the
+ * then final set of necessary indices.
+ *
+ *
+ * @sect3{Interface}
+ *
+ * Since this class is intended as an intermediate replacement of the
+ * @ref{SparsityPattern} class, it has mostly the same interface, with
+ * small changes where necessary. In particular, the @ref{add}
+ * function, and the functions inquiring properties of the sparsity
+ * pattern are the same.
+ *
+ *
+ * @sect3{Usage}
+ *
+ * Use this class as follows:
+ * @begin{verbatim}
+ * CompressedSparsityPattern compressed_pattern (dof_handler.n_dofs());
+ * DoFTools::make_sparsity_pattern (dof_handler,
+ * compressed_pattern);
+ * constraints.condense (compressed_pattern);
+ *
+ * SparsityPattern sp;
+ * sp.copy_from (compressed_pattern);
+ * @end{verbatim}
+ *
+ *
+ * @author Wolfgang Bangerth, 2001
+ */
+class CompressedSparsityPattern : public Subscriptor
+{
+ 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.
+ */
+ CompressedSparsityPattern ();
+
+ /**
+ * Copy constructor. This constructor is
+ * only allowed to be called if the matrix
+ * structure to be copied is empty. This is
+ * so in order to prevent involuntary
+ * copies of objects for temporaries, which
+ * can use large amounts of computing time.
+ * However, copy constructors are needed
+ * if yo want to use the STL data types
+ * on classes like this, e.g. to write
+ * such statements like
+ * @p{v.push_back (CompressedSparsityPattern());},
+ * with @p{v} a vector of @p{CompressedSparsityPattern}
+ * objects.
+ *
+ * Usually, it is sufficient to
+ * use the explicit keyword to
+ * disallow unwanted temporaries,
+ * but for the STL vectors, this
+ * does not work. Since copying a
+ * structure like this is not
+ * useful anyway because multiple
+ * matrices can use the same
+ * sparsity structure, copies are
+ * only allowed for empty
+ * objects, as described above.
+ */
+ CompressedSparsityPattern (const CompressedSparsityPattern &);
+
+ /**
+ * Initialize a rectangular
+ * matrix with @p{m} rows and
+ * @p{n} columns.
+ */
+ CompressedSparsityPattern (const unsigned int m,
+ const unsigned int n);
+
+ /**
+ * Initialize a square matrix of
+ * dimension @p{n}.
+ */
+ CompressedSparsityPattern (const unsigned int n);
+
+ /**
+ * Copy operator. For this the
+ * same holds as for the copy
+ * constructor: it is declared,
+ * defined and fine to be called,
+ * but the latter only for empty
+ * objects.
+ */
+ CompressedSparsityPattern & operator = (const CompressedSparsityPattern &);
+
+ /**
+ * Reallocate memory and set up
+ * data structures for a new
+ * matrix with @p{m} rows and
+ * @p{n} columns, with at most
+ * @p{max_per_row} nonzero
+ * entries per row.
+ */
+ void reinit (const unsigned int m,
+ const unsigned int n);
+
+ /**
+ * Since this object is kept
+ * compressed at all times anway,
+ * this function does nothing,
+ * but is declared to make the
+ * interface of this class as
+ * much alike as that of the
+ * @ref{SparsityPattern} class.
+ */
+ void compress ();
+
+ /**
+ * Return whether the object is
+ * empty. It is empty if no
+ * memory is allocated, which is
+ * the same as that both
+ * dimensions are zero.
+ */
+ bool empty () const;
+
+ /**
+ * Return the maximum number of
+ * entries per row. Note that
+ * this number may change as
+ * entries are added.
+ */
+ unsigned int max_entries_per_row () const;
+
+ /**
+ * Add a nonzero entry to the
+ * matrix. If the entry already
+ * exists, nothing bad happens.
+ */
+ void add (const unsigned int i,
+ const unsigned int j);
+
+ /**
+ * Make the sparsity pattern
+ * symmetric by adding the
+ * sparsity pattern of the
+ * transpose object.
+ *
+ * This function throws an
+ * exception if the sparsity
+ * pattern does not represent a
+ * square matrix.
+ */
+ void symmetrize ();
+
+ /**
+ * Print the sparsity of the matrix
+ * in a format that @p{gnuplot} understands
+ * and which can be used to plot the
+ * sparsity pattern in a graphical
+ * way. The format consists of pairs
+ * @p{i j} of nonzero elements, each
+ * representing one entry of this
+ * matrix, one per line of the output
+ * file. Indices are counted from
+ * zero on, as usual. Since sparsity
+ * patterns are printed in the same
+ * way as matrices are displayed, we
+ * print the negative of the column
+ * index, which means that the
+ * @p{(0,0)} element is in the top left
+ * rather than in the bottom left
+ * corner.
+ *
+ * Print the sparsity pattern in
+ * gnuplot by setting the data style
+ * to dots or points and use the
+ * @p{plot} command.
+ */
+ void print_gnuplot (std::ostream &out) const;
+
+ /**
+ * Return number of rows of this
+ * matrix, which equals the dimension
+ * of the image space.
+ */
+ unsigned int n_rows () const;
+
+ /**
+ * Return number of columns of this
+ * matrix, which equals the dimension
+ * of the range space.
+ */
+ unsigned int n_cols () const;
+
+ /**
+ * Number of entries in a specific row.
+ */
+ unsigned int row_length (const unsigned int row) const;
+
+ /**
+ * Access to column number field.
+ * Return the column number of
+ * the @p{index}th entry in @p{row}.
+ */
+ unsigned int column_number (const unsigned int row,
+ const unsigned int index) const;
+
+ /**
+ * Compute the bandwidth of the matrix
+ * represented by this structure. The
+ * bandwidth is the maximum of
+ * $|i-j|$ for which the index pair
+ * $(i,j)$ represents a nonzero entry
+ * of the matrix.
+ */
+ unsigned int bandwidth () const;
+
+ /**
+ * Return the number of nonzero elements of
+ * this matrix. Actually, it returns the
+ * number of entries in the sparsity
+ * pattern; if any of the entries should
+ * happen to be zero, it is counted
+ * anyway.
+ *
+ * This function may only be called if the
+ * matrix struct is compressed. It does not
+ * make too much sense otherwise anyway.
+ */
+ unsigned int n_nonzero_elements () const;
+
+ /**
+ * Exception
+ */
+ DeclException2 (ExcInvalidIndex,
+ int, int,
+ << "The given index " << arg1
+ << " should be less than " << arg2 << ".");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcInvalidConstructorCall);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNotSquare);
+
+ private:
+ /**
+ * Number of rows that this sparsity
+ * structure shall represent.
+ */
+ unsigned int rows;
+
+ /**
+ * Number of columns that this sparsity
+ * structure shall represent.
+ */
+ unsigned int cols;
+
+ /**
+ * Actual data: store for each
+ * row the set of nonzero
+ * entries.
+ */
+ std::vector > column_indices;
+
+ friend class SparsityPattern;
+};
+
+
+/*---------------------- Inline functions -----------------------------------*/
+
+
+inline
+unsigned int
+CompressedSparsityPattern::n_rows () const
+{
+ return rows;
+};
+
+
+inline
+unsigned int
+CompressedSparsityPattern::n_cols () const
+{
+ return cols;
+};
+
+#endif
diff --git a/deal.II/lac/include/lac/sparsity_pattern.h b/deal.II/lac/include/lac/sparsity_pattern.h
index d4baa0cdf3..2940dbf3fc 100644
--- a/deal.II/lac/include/lac/sparsity_pattern.h
+++ b/deal.II/lac/include/lac/sparsity_pattern.h
@@ -18,6 +18,7 @@
#include
template class SparseMatrix;
+class CompressedSparsityPattern;
#include
#include
@@ -460,6 +461,15 @@ class SparsityPattern : public Subscriptor
const unsigned int n_cols,
const ForwardIterator begin,
const ForwardIterator end);
+
+ /**
+ * Copy data from an object of
+ * type
+ * @ref{CompressedSparsityPattern}. Previous
+ * content of this object is
+ * lost.
+ */
+ void copy_from (const CompressedSparsityPattern &csp);
/**
* Return whether the object is empty. It
diff --git a/deal.II/lac/source/compressed_sparsity_pattern.cc b/deal.II/lac/source/compressed_sparsity_pattern.cc
new file mode 100644
index 0000000000..34f27f8f8f
--- /dev/null
+++ b/deal.II/lac/source/compressed_sparsity_pattern.cc
@@ -0,0 +1,219 @@
+//---------------------------- compressed_sparsity_pattern.cc ---------------------------
+// $Id$
+// Version: $Name$
+//
+// Copyright (C) 2001 by the deal.II authors
+//
+// This file is subject to QPL and may not be distributed
+// without copyright and license information. Please refer
+// to the file deal.II/doc/license.html for the text and
+// further information on this license.
+//
+//---------------------------- compressed_sparsity_pattern.cc ---------------------------
+
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+CompressedSparsityPattern::CompressedSparsityPattern () :
+ rows(0),
+ cols(0)
+{};
+
+
+
+CompressedSparsityPattern::CompressedSparsityPattern (const CompressedSparsityPattern &s) :
+ Subscriptor(),
+ rows(0),
+ cols(0)
+{
+ Assert (s.rows == 0, ExcInvalidConstructorCall());
+ Assert (s.cols == 0, ExcInvalidConstructorCall());
+};
+
+
+
+CompressedSparsityPattern::CompressedSparsityPattern (const unsigned int m,
+ const unsigned int n)
+ : rows(0),
+ cols(0)
+{
+ reinit (m,n);
+};
+
+
+
+CompressedSparsityPattern::CompressedSparsityPattern (const unsigned int n)
+ : rows(0),
+ cols(0)
+{
+ reinit (n,n);
+};
+
+
+
+CompressedSparsityPattern &
+CompressedSparsityPattern::operator = (const CompressedSparsityPattern &s)
+{
+ Assert (s.rows == 0, ExcInvalidConstructorCall());
+ Assert (s.cols == 0, ExcInvalidConstructorCall());
+
+ Assert (rows == 0, ExcInvalidConstructorCall());
+ Assert (cols == 0, ExcInvalidConstructorCall());
+
+ return *this;
+};
+
+
+
+void
+CompressedSparsityPattern::reinit (const unsigned int m,
+ const unsigned int n)
+{
+ rows = m;
+ cols = n;
+
+ std::vector > new_column_indices (rows);
+ column_indices.swap (new_column_indices);
+}
+
+
+
+void
+CompressedSparsityPattern::compress ()
+{};
+
+
+
+bool
+CompressedSparsityPattern::empty () const
+{
+ return ((rows==0) && (cols==0));
+};
+
+
+
+unsigned int
+CompressedSparsityPattern::max_entries_per_row () const
+{
+ unsigned int m = 0;
+ for (unsigned int i=1; i::const_iterator i=column_indices[row].begin();
+ i!=column_indices[row].end(); ++i)
+ // add the transpose entry if
+ // this is not the diagonal
+ if (row != *i)
+ add (*i, row);
+};
+
+
+
+void
+CompressedSparsityPattern::print_gnuplot (std::ostream &out) const
+{
+ for (unsigned int row=0; row::const_iterator i=column_indices[row].begin();
+ i!=column_indices[row].end(); ++i)
+ // while matrix entries are
+ // usually written (i,j),
+ // with i vertical and j
+ // horizontal, gnuplot output
+ // is x-y, that is we have to
+ // exchange the order of
+ // output
+ out << *i << " " << -static_cast(row) << std::endl;
+
+ AssertThrow (out, ExcIO());
+}
+
+
+
+unsigned int
+CompressedSparsityPattern::row_length (const unsigned int row) const
+{
+ return column_indices[row].size();
+};
+
+
+
+unsigned int
+CompressedSparsityPattern::column_number (const unsigned int row,
+ const unsigned int index) const
+{
+ Assert (index < column_indices[row].size(),
+ ExcIndexRange (index, 0, column_indices[row].size()));
+ std::set::const_iterator p = column_indices[row].begin();
+ std::advance (p, index);
+ return *p;
+};
+
+
+
+unsigned int
+CompressedSparsityPattern::bandwidth () const
+{
+ unsigned int b=0;
+ for (unsigned int row=0; row::const_iterator i=column_indices[row].begin();
+ i!=column_indices[row].end(); ++i)
+ if (static_cast(abs(static_cast(row-*i))) > b)
+ b = abs(static_cast(row-*i));
+
+ return b;
+};
+
+
+
+unsigned int
+CompressedSparsityPattern::n_nonzero_elements () const
+{
+ unsigned int n=0;
+ for (unsigned int i=0; i
+#include
+#include
#include
#include
@@ -447,6 +448,16 @@ SparsityPattern::compress ()
+void
+SparsityPattern::copy_from (const CompressedSparsityPattern &csp)
+{
+ copy_from (csp.n_rows(), csp.n_cols(),
+ csp.column_indices.begin(),
+ csp.column_indices.end());
+};
+
+
+
bool
SparsityPattern::empty () const
{
@@ -583,7 +594,8 @@ SparsityPattern::symmetrize ()
// the transpose element. note:
//
// 1. that the sparsity pattern
- // changes which we work on
+ // changes which we work on, but
+ // not the present row
//
// 2. that the @p{add} function can
// be called on elements that
@@ -599,8 +611,12 @@ SparsityPattern::symmetrize ()
break;
// otherwise add the
- // transpose entry
- add (colnums[k], row);
+ // transpose entry if this is
+ // not the diagonal (that
+ // would not harm, only take
+ // time to check up)
+ if (colnums[k] != row)
+ add (colnums[k], row);
};
};
diff --git a/tests/deal.II/Makefile.in b/tests/deal.II/Makefile.in
index 761b1be944..4cb007ae05 100644
--- a/tests/deal.II/Makefile.in
+++ b/tests/deal.II/Makefile.in
@@ -42,12 +42,13 @@ wave-test-3.exe : wave-test-3.go $(lib-2d)
support_point_map.exe : support_point_map.go $(lib-1d) $(lib-2d) $(lib-3d) $(libraries)
filtered_matrix.exe : filtered_matrix.go $(lib-1d) $(lib-2d) $(lib-3d) $(libraries)
boundaries.exe : boundaries.go $(lib-1d) $(lib-2d) $(lib-3d) $(libraries)
+sparsity_pattern.exe : sparsity_pattern.go $(lib-1d) $(lib-2d) $(lib-1d) $(libraries)
tests = grid_test grid_transform dof_test data_out derivatives gradients constraints mg \
mglocal block_matrices second_derivatives derivative_approximation \
matrices error_estimator intergrid_constraints intergrid_map \
wave-test-3 dof_renumbering support_point_map filtered_matrix \
- boundaries
+ boundaries sparsity_pattern
############################################################
diff --git a/tests/deal.II/matrices.cc b/tests/deal.II/matrices.cc
index 19d526c181..97e2551f2e 100644
--- a/tests/deal.II/matrices.cc
+++ b/tests/deal.II/matrices.cc
@@ -1,4 +1,4 @@
-//---------------------------- derivative_approximation.cc ---------------------------
+//---------------------------- matrices.cc ---------------------------
// $Id$
// Version: $Name$
//
@@ -9,7 +9,7 @@
// to the file deal.II/doc/license.html for the text and
// further information on this license.
//
-//---------------------------- derivative_approximation.cc ---------------------------
+//---------------------------- matrices.cc ---------------------------
/* Author: Wolfgang Bangerth, University of Heidelberg, 2001 */
diff --git a/tests/deal.II/sparsity_pattern.cc b/tests/deal.II/sparsity_pattern.cc
new file mode 100644
index 0000000000..ec18708351
--- /dev/null
+++ b/tests/deal.II/sparsity_pattern.cc
@@ -0,0 +1,175 @@
+//---------------------------- sparsity_pattern.cc ---------------------------
+// $Id$
+// Version: $Name$
+//
+// Copyright (C) 2000, 2001 by the deal.II authors
+//
+// This file is subject to QPL and may not be distributed
+// without copyright and license information. Please refer
+// to the file deal.II/doc/license.html for the text and
+// further information on this license.
+//
+//---------------------------- sparsity_pattern.cc ---------------------------
+
+
+/* Author: Wolfgang Bangerth, University of Heidelberg, 2001 */
+
+// check that the direct generation of the sparsity pattern and that
+// via the CompressedSparsityPattern result in the same
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+
+bool operator == (const SparsityPattern &sp1,
+ const SparsityPattern &sp2)
+{
+ if (sp1.n_nonzero_elements() != sp2.n_nonzero_elements())
+ return false;
+
+ for (unsigned int i=0; i
+void
+check_boundary (const DoFHandler &dof)
+{
+ std::vector dof_to_boundary_mapping;
+ DoFTools::map_dof_to_boundary_indices (dof,
+ dof_to_boundary_mapping);
+
+ // first way: direct generation
+ SparsityPattern sparsity_1(dof.n_boundary_dofs(),
+ dof.max_couplings_between_boundary_dofs());
+ DoFTools::make_boundary_sparsity_pattern (dof,
+ dof_to_boundary_mapping,
+ sparsity_1);
+ sparsity_1.compress ();
+
+ // second way: via a CompressedSparsityPattern
+ SparsityPattern sparsity_2;
+ CompressedSparsityPattern csp(dof.n_boundary_dofs());
+ DoFTools::make_boundary_sparsity_pattern (dof,
+ dof_to_boundary_mapping,
+ csp);
+ sparsity_2.copy_from (csp);
+
+ // the exact content of sparsity
+ // patterns is checked in other
+ // tests, so only make sure that
+ // sparsity_[12] are equal
+ deallog << __PRETTY_FUNCTION__
+ << " -- "
+ << (sparsity_1 == sparsity_2 ? "ok" : "failed")
+ << std::endl;
+};
+
+
+
+
+template
+void
+check ()
+{
+ Triangulation tr;
+ if (dim==2)
+ GridGenerator::hyper_ball(tr, Point(), 1);
+ else
+ GridGenerator::hyper_cube(tr, -1,1);
+ tr.refine_global (1);
+ tr.begin_active()->set_refine_flag ();
+ tr.execute_coarsening_and_refinement ();
+ tr.begin_active(2)->set_refine_flag ();
+ tr.execute_coarsening_and_refinement ();
+ if (dim==1)
+ tr.refine_global(2);
+
+ // create a system element composed
+ // of one Q1 and one Q2 element
+ FESystem element(FE_Q(1), 1,
+ FE_Q(2), 1);
+ DoFHandler dof(tr);
+ dof.distribute_dofs(element);
+
+ ConstraintMatrix constraints;
+ DoFTools::make_hanging_node_constraints (dof, constraints);
+ constraints.close ();
+
+ // create sparsity pattern. note
+ // that different components should
+ // not couple, so use pattern
+ std::vector > mask (2, std::vector(2, false));
+ mask[0][0] = mask[1][1] = true;
+
+ // 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
+ SparsityPattern sparsity_2;
+ CompressedSparsityPattern csp (dof.n_dofs());
+ DoFTools::make_sparsity_pattern (dof, mask, csp);
+ constraints.condense (csp);
+ sparsity_2.copy_from (csp);
+
+
+ // the exact content of sparsity
+ // patterns is checked in other
+ // tests, so only make sure that
+ // sparsity_[12] are equal
+ deallog << __PRETTY_FUNCTION__
+ << " -- "
+ << (sparsity_1 == sparsity_2 ? "ok" : "failed")
+ << std::endl;
+
+ check_boundary (dof);
+};
+
+
+
+int main ()
+{
+ std::ofstream logfile ("sparsity_pattern.output");
+ logfile.precision (2);
+ logfile.setf(std::ios::fixed);
+ deallog.attach(logfile);
+ deallog.depth_console (0);
+
+ deallog.push ("1d");
+ check<1> ();
+ deallog.pop ();
+ deallog.push ("2d");
+ check<2> ();
+ deallog.pop ();
+ deallog.push ("3d");
+ check<3> ();
+ deallog.pop ();
+}
--
2.39.5