#include <lac/sparsity_pattern.h>
#include <lac/compressed_sparsity_pattern.h>
#include <lac/compressed_set_sparsity_pattern.h>
+#include <lac/compressed_simple_sparsity_pattern.h>
#include <lac/vector.h>
#include <lac/block_vector.h>
#include <lac/sparse_matrix.h>
CompressedSetSparsityPattern &,
const bool) const;
+template void ConstraintMatrix::
+add_entries_local_to_global<CompressedSimpleSparsityPattern> (const std::vector<unsigned int> &,
+ CompressedSimpleSparsityPattern &,
+ const bool) const;
+
template void ConstraintMatrix::
add_entries_local_to_global<BlockSparsityPattern> (const std::vector<unsigned int> &,
BlockSparsityPattern &,
BlockCompressedSetSparsityPattern &,
const bool) const;
+template void ConstraintMatrix::
+add_entries_local_to_global<BlockCompressedSimpleSparsityPattern> (const std::vector<unsigned int> &,
+ BlockCompressedSimpleSparsityPattern &,
+ const bool) const;
DEAL_II_NAMESPACE_CLOSE
#include <lac/sparsity_pattern.h>
#include <lac/compressed_sparsity_pattern.h>
#include <lac/compressed_set_sparsity_pattern.h>
+#include <lac/compressed_simple_sparsity_pattern.h>
#include <lac/block_sparsity_pattern.h>
#include <lac/vector.h>
CompressedSetSparsityPattern &sparsity,
const ConstraintMatrix &);
template void
+DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
+ CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof,
+ CompressedSimpleSparsityPattern &sparsity,
+ const ConstraintMatrix &);
+template void
DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
BlockSparsityPattern>
(const DoFHandler<deal_II_dimension> &dof,
(const DoFHandler<deal_II_dimension> &dof,
BlockCompressedSetSparsityPattern &sparsity,
const ConstraintMatrix &);
+template void
+DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
+ BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof,
+ BlockCompressedSimpleSparsityPattern &sparsity,
+ const ConstraintMatrix &);
template void
DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
CompressedSetSparsityPattern &sparsity,
const ConstraintMatrix &);
+template void
+DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
+ CompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension> &dof,
+ CompressedSimpleSparsityPattern &sparsity,
+ const ConstraintMatrix &);
+
template void
DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
(const hp::DoFHandler<deal_II_dimension> &dof,
BlockCompressedSetSparsityPattern &sparsity,
const ConstraintMatrix &);
+template void
+DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
+ BlockCompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension> &dof,
+ BlockCompressedSimpleSparsityPattern &sparsity,
+ const ConstraintMatrix &);
template void
const Table<2,Coupling>&,
CompressedSetSparsityPattern&);
template void
+DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
+ CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ CompressedSimpleSparsityPattern&);
+template void
DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
BlockSparsityPattern>
(const DoFHandler<deal_II_dimension>&,
(const DoFHandler<deal_II_dimension>&,
const Table<2,Coupling>&,
BlockCompressedSetSparsityPattern&);
-
+template void
+DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
+ BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ BlockCompressedSimpleSparsityPattern&);
template void
DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
const Table<2,Coupling>&,
CompressedSetSparsityPattern&);
template void
+DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
+ CompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ CompressedSimpleSparsityPattern&);
+template void
DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
BlockSparsityPattern>
(const hp::DoFHandler<deal_II_dimension>&,
(const hp::DoFHandler<deal_II_dimension>&,
const Table<2,Coupling>&,
BlockCompressedSetSparsityPattern&);
+template void
+DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
+ BlockCompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension>&,
+ const Table<2,Coupling>&,
+ BlockCompressedSimpleSparsityPattern&);
template void
const DoFHandler<deal_II_dimension> &dof_col,
CompressedSetSparsityPattern &sparsity);
template void
+DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
+ CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof_row,
+ const DoFHandler<deal_II_dimension> &dof_col,
+ CompressedSimpleSparsityPattern &sparsity);
+template void
DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
BlockSparsityPattern>
(const DoFHandler<deal_II_dimension> &dof_row,
(const DoFHandler<deal_II_dimension> &dof_row,
const DoFHandler<deal_II_dimension> &dof_col,
BlockCompressedSetSparsityPattern &sparsity);
+template void
+DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension>,
+ BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof_row,
+ const DoFHandler<deal_II_dimension> &dof_col,
+ BlockCompressedSimpleSparsityPattern &sparsity);
template void
DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
const hp::DoFHandler<deal_II_dimension> &dof_col,
CompressedSetSparsityPattern &sparsity);
template void
+DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
+ CompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension> &dof_row,
+ const hp::DoFHandler<deal_II_dimension> &dof_col,
+ CompressedSimpleSparsityPattern &sparsity);
+
+template void
DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
BlockSparsityPattern>
(const hp::DoFHandler<deal_II_dimension> &dof_row,
(const hp::DoFHandler<deal_II_dimension> &dof_row,
const hp::DoFHandler<deal_II_dimension> &dof_col,
BlockCompressedSetSparsityPattern &sparsity);
-
+template void
+DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,
+ BlockCompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension> &dof_row,
+ const hp::DoFHandler<deal_II_dimension> &dof_col,
+ BlockCompressedSimpleSparsityPattern &sparsity);
// #if deal_II_dimension > 1
template void
const std::vector<unsigned int> &,
CompressedSetSparsityPattern &);
template void
+DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension>& dof,
+ const std::vector<unsigned int> &,
+ CompressedSimpleSparsityPattern &);
+template void
DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(const DoFHandler<deal_II_dimension>& dof,
const std::vector<unsigned int> &,
(const DoFHandler<deal_II_dimension>& dof,
const std::vector<unsigned int> &,
BlockCompressedSetSparsityPattern &);
+template void
+DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension>& dof,
+ const std::vector<unsigned int> &,
+ BlockCompressedSimpleSparsityPattern &);
template void
DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SparsityPattern>
const std::vector<unsigned int> &,
CompressedSetSparsityPattern &);
template void
+DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension>& dof,
+ const std::vector<unsigned int> &,
+ CompressedSimpleSparsityPattern &);
+template void
DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(const hp::DoFHandler<deal_II_dimension>& dof,
const std::vector<unsigned int> &,
(const hp::DoFHandler<deal_II_dimension>& dof,
const std::vector<unsigned int> &,
BlockCompressedSetSparsityPattern &);
+template void
+DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension>& dof,
+ const std::vector<unsigned int> &,
+ BlockCompressedSimpleSparsityPattern &);
template void
const std::vector<unsigned int> &dof_to_boundary_mapping,
CompressedSetSparsityPattern &sparsity);
template void
+DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<unsigned int> &dof_to_boundary_mapping,
+ CompressedSimpleSparsityPattern &sparsity);
+template void
DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(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,
BlockCompressedSetSparsityPattern &sparsity);
+template void
+DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<unsigned int> &dof_to_boundary_mapping,
+ BlockCompressedSimpleSparsityPattern &sparsity);
template void
DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SparsityPattern>
const std::vector<unsigned int> &dof_to_boundary_mapping,
CompressedSetSparsityPattern &sparsity);
template void
+DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<unsigned int> &dof_to_boundary_mapping,
+ CompressedSimpleSparsityPattern &sparsity);
+template void
DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(const hp::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,
BlockCompressedSetSparsityPattern &sparsity);
+template void
+DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension>& dof,
+ const FunctionMap<deal_II_dimension>::type &boundary_indicators,
+ const std::vector<unsigned int> &dof_to_boundary_mapping,
+ BlockCompressedSimpleSparsityPattern &sparsity);
template void
(const DoFHandler<deal_II_dimension> &dof,
CompressedSetSparsityPattern &sparsity);
template void
+DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof,
+ CompressedSimpleSparsityPattern &sparsity);
+template void
DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(const DoFHandler<deal_II_dimension> &dof,
BlockSparsityPattern &sparsity);
DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockCompressedSetSparsityPattern>
(const DoFHandler<deal_II_dimension> &dof,
BlockCompressedSetSparsityPattern &sparsity);
+template void
+DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof,
+ BlockCompressedSimpleSparsityPattern &sparsity);
template void
DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SparsityPattern>
(const hp::DoFHandler<deal_II_dimension> &dof,
CompressedSetSparsityPattern &sparsity);
template void
+DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension> &dof,
+ CompressedSimpleSparsityPattern &sparsity);
+template void
DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(const hp::DoFHandler<deal_II_dimension> &dof,
BlockSparsityPattern &sparsity);
DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockCompressedSetSparsityPattern>
(const hp::DoFHandler<deal_II_dimension> &dof,
BlockCompressedSetSparsityPattern &sparsity);
+template void
+DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const hp::DoFHandler<deal_II_dimension> &dof,
+ BlockCompressedSimpleSparsityPattern &sparsity);
#if deal_II_dimension > 1
const Table<2,Coupling>&,
const Table<2,Coupling>&);
template void
+DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,CompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof,
+ CompressedSimpleSparsityPattern &,
+ const Table<2,Coupling>&,
+ const Table<2,Coupling>&);
+template void
DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockSparsityPattern>
(const DoFHandler<deal_II_dimension> &dof,
BlockSparsityPattern &,
BlockCompressedSetSparsityPattern &,
const Table<2,Coupling>&,
const Table<2,Coupling>&);
+template void
+DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,BlockCompressedSimpleSparsityPattern>
+(const DoFHandler<deal_II_dimension> &dof,
+ BlockCompressedSimpleSparsityPattern &,
+ const Table<2,Coupling>&,
+ const Table<2,Coupling>&);
#endif
<li><em>Ivan Christov:</em>
Step-25 tutorial program.
+<li><em>Timo Heister:</em>
+ CompressedSimpleSparsityPattern class.
+
<li><em>Luca Heltai:</em>
Gmsh format mesh reader and writer;
some of the meshes in the GridGenerator class;
* memory often also takes significant compute time. The tradeoff to avoid
* excessive memory allocation cannot be avoided, however.
*
- * In deal.II, the CompressedSparsityPattern and CompressedSetSparsityPattern
- * classes implement this "dynamic" memory scheme. They use different storage
- * schemes and appear to both have use cases where they are better than the
- * respective other. In either case, these classes are typically used in the
- * following way:
+ * The following classes implement this "dynamic" memory scheme in deal.II:
+ * - CompressedSparsityPattern
+ * - CompressedSimpleSparsityPattern
+ * - CompressedSetSparsityPattern
+ *
+ * These classes have different performance characteristics and memory
+ * requirements. Which one is the "best" changes from case to case because
+ * it is dependent on the number of dofs, the number of couplings per dof,
+ * the strategy used to insert and the amount of memory available.
+ *
+ * CompressedSparsityPattern and CompressedSimpleSparsityPattern are very
+ * similar, where CompressedSimpleSparsityPattern trades some memory (requires
+ * up to twice the memory in the worst case) for additional speed which is
+ * noticeable in cases with many nonzero entries. CompressedSetSparsityPattern
+ * on the other hand uses a lot more memory but may perform better in cases with
+ * many nonzero entries per row. See for example the @ref step_27 "step-27"
+ * and @ref step_22 "step-22" tutorial programs.
+ *
+ * As a guideline you should start using CompressedSparsityPattern and try the
+ * other variants if you run into problems. Switching between them should be as
+ * simple as changing the class name because all classes have the same interface
+ * for adding entries.
+ * In either case, these classes are typically used in the following way
+ * (replace the class CompressedSparsityPattern with a different one from above):
* @verbatim
* CompressedSparsityPattern compressed_pattern (dof_handler.n_dofs());
* DoFTools::make_sparsity_pattern (dof_handler,
* compressed_pattern);
* constraints.condense (compressed_pattern);
*
- * SparsityPattern finaly_sparsity_pattern;
+ * SparsityPattern final_sparsity_pattern;
* final_sparsity_pattern.copy_from (compressed_pattern);
* @endverbatim
*
* The intermediate, compressed sparsity pattern is directly copied into the
* "compressed" form of the final static pattern.
*
+ * <h4>Dynamic block sparsity patterns</h4>
+ *
+ * The following classes implement an array of dynamic sparsity patterns:
+ * - BlockCompressedSparsityPattern
+ * - BlockCompressedSetSparsityPattern
+ * - BlockCompressedSimpleSparsityPattern
+ *
+ * These classes inherit the same tradeoffs regarding their efficiency from
+ * their non-block classes (see above). See their documentation and
+ * @ref step_22 "step-22" for more information.
+ *
* @ingroup Matrices
*/
#include <lac/sparsity_pattern.h>
#include <lac/compressed_sparsity_pattern.h>
#include <lac/compressed_set_sparsity_pattern.h>
+#include <lac/compressed_simple_sparsity_pattern.h>
#include <lac/block_indices.h>
DEAL_II_NAMESPACE_OPEN
template <typename number> class BlockSparseMatrix;
class BlockSparsityPattern;
class BlockCompressedSparsityPattern;
+class BlockCompressedSimpleSparsityPattern;
class BlockCompressedSetSparsityPattern;
/*! @addtogroup Sparsity
* of this object is lost.
*/
void copy_from (const BlockCompressedSetSparsityPattern &csp);
+
+ /**
+ * Copy data from an object of
+ * type
+ * BlockCompressedSimpleSparsityPattern,
+ * 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 BlockCompressedSimpleSparsityPattern &csp);
+
+
+
};
* 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. The
- * individual blocks are based on the CompressedSparistyPattern class.
+ * individual blocks are based on the CompressedSparsityPattern class.
*
* This class is an example of the "dynamic" type of @ref Sparsity.
*
- * <b>Note:</b> This class inherits the same tradeoffs regarding its
- * efficiency as CompressedSparsityPattern and as opposed to
- * CompressedSetSparsity. Since the two classes (and consequently
- * BlockCompressedSparsityPattern and
- * BlockCompressedSetSparsityPattern) are interface-compatible it is
- * frequently worth checking which version is more efficient.
+ * <b>Note:</b>
+ * There are several, exchangeable variations of this class, see @ref Sparsity,
+ * section 'Dynamic block sparsity patterns' for more information.
*
* <b>Note:</b> This class used to be called
* CompressedBlockSparsityPattern. However, since it's a block wrapper around
*
* This class is an example of the "dynamic" type of @ref Sparsity.
*
- * <b>Note:</b> This class inherits the same tradeoffs regarding its
- * efficiency as CompressedSparsityPattern and as opposed to
- * CompressedSetSparsity. Since the two classes (and consequently
- * BlockCompressedSparsityPattern and
- * BlockCompressedSetSparsityPattern) are interface-compatible it is
- * frequently worth checking which version is more efficient.
+ * <b>Note:</b>
+ * There are several, exchangeable variations of this class, see @ref Sparsity,
+ * section 'Dynamic block sparsity patterns' for more information.
*
* This class is used in @ref step_22 "step-22".
*
};
+
+
+
+/**
+ * This class extends the base class to implement an array of compressed
+ * sparsity patterns that can be used to initialize objects of type
+ * BlockSparsityPattern. It is used in the same way as the
+ * BlockCompressedSparsityPattern except that it builds upon the
+ * CompressedSimpleSparsityPattern instead of the CompressedSparsityPattern. See
+ * the documentation of the BlockCompressedSparsityPattern for examples.
+ *
+ * This class is an example of the "dynamic" type of @ref Sparsity.
+ *
+ * <b>Note:</b>
+ * There are several, exchangeable variations of this class, see @ref Sparsity,
+ * section 'Dynamic block sparsity patterns' for more information.
+ *
+ * @author Timo Heister, 2008
+ */
+class BlockCompressedSimpleSparsityPattern : public BlockSparsityPatternBase<CompressedSimpleSparsityPattern>
+{
+ 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 reinit() function.
+ */
+ BlockCompressedSimpleSparsityPattern ();
+
+ /**
+ * Initialize the matrix with the
+ * given number of block rows and
+ * columns. The blocks themselves
+ * are still empty, and you have
+ * to call collect_sizes() after
+ * you assign them sizes.
+ */
+ BlockCompressedSimpleSparsityPattern (const unsigned int n_rows,
+ const unsigned int n_columns);
+
+ /**
+ * Initialize the pattern with
+ * two BlockIndices for the block
+ * structures of matrix rows and
+ * columns. This function is
+ * equivalent to calling the
+ * previous constructor with the
+ * length of the two index vector
+ * and then entering the index
+ * values.
+ */
+ BlockCompressedSimpleSparsityPattern (const std::vector<unsigned int>& row_block_sizes,
+ const std::vector<unsigned int>& col_block_sizes);
+
+ /**
+ * Resize the matrix to a tensor
+ * product of matrices with
+ * dimensions defined by the
+ * arguments.
+ *
+ * The matrix will have as many
+ * block rows and columns as
+ * there are entries in the two
+ * arguments. The block at
+ * position (<i>i,j</i>) will
+ * have the dimensions
+ * <tt>row_block_sizes[i]</tt>
+ * times <tt>col_block_sizes[j]</tt>.
+ */
+ void reinit (const std::vector< unsigned int > &row_block_sizes,
+ const std::vector< unsigned int > &col_block_sizes);
+
+ /**
+ * Allow the use of the reinit
+ * functions of the base class as
+ * well.
+ */
+ using BlockSparsityPatternBase<CompressedSimpleSparsityPattern>::reinit;
+};
+
+
+
/*@}*/
/*---------------------- Template functions -----------------------------------*/
*
* <h3>Notes</h3>
*
+ * There are several, exchangeable variations of this class, see @ref Sparsity,
+ * section '"Dynamic" or "compressed" sparsity patterns' for more information.
+ *
* This class is a variation of the CompressedSparsityPattern class.
* Instead of using sorted vectors together with a caching algorithm
* for storing the column indices of nonzero entries, the std::set
--- /dev/null
+//---------------------------------------------------------------------------
+// $Id$
+// Version: $Name$
+//
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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.
+//
+//---------------------------------------------------------------------------
+#ifndef __deal2__compressed_simple_sparsity_pattern_h
+#define __deal2__compressed_simple_sparsity_pattern_h
+
+
+#include <base/config.h>
+#include <base/subscriptor.h>
+#include <lac/exceptions.h>
+
+#include <vector>
+#include <algorithm>
+
+DEAL_II_NAMESPACE_OPEN
+
+template <typename number> class SparseMatrix;
+
+
+/*! @addtogroup Sparsity
+ *@{
+ */
+
+
+/**
+ * This class acts as an intermediate form of the
+ * SparsityPattern class. From the interface it mostly
+ * represents a 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
+ * 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. An extensive description
+ * of sparsity patterns can be found in the documentation of the @ref Sparsity
+ * module.
+ *
+ * This class is an example of the "dynamic" type of @ref Sparsity.
+ *
+ * <h3>Interface</h3>
+ *
+ * Since this class is intended as an intermediate replacement of the
+ * SparsityPattern class, it has mostly the same interface, with
+ * small changes where necessary. In particular, the add()
+ * function, and the functions inquiring properties of the sparsity
+ * pattern are the same.
+ *
+ *
+ * <h3>Usage</h3>
+ *
+ * Use this class as follows:
+ * @verbatim
+ * CompressedSimpleSparsityPattern 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);
+ * @endverbatim
+ *
+ *
+ * <h3>Notes</h3>
+ *
+ * There are several, exchangeable variations of this class, see @ref Sparsity,
+ * section '"Dynamic" or "compressed" sparsity patterns' for more information.
+ *
+ * @author Timo Heister, 2008
+ */
+class CompressedSimpleSparsityPattern : 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 reinit() function.
+ */
+ CompressedSimpleSparsityPattern ();
+
+ /**
+ * 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 <tt>v.push_back
+ * (CompressedSparsityPattern());</tt>,
+ * with @p v a vector of @p
+ * CompressedSparsityPattern objects.
+ */
+ CompressedSimpleSparsityPattern (const CompressedSimpleSparsityPattern &);
+
+ /**
+ * Initialize a rectangular
+ * matrix with @p m rows and
+ * @p n columns.
+ */
+ CompressedSimpleSparsityPattern (const unsigned int m,
+ const unsigned int n);
+
+ /**
+ * Initialize a square matrix of
+ * dimension @p n.
+ */
+ CompressedSimpleSparsityPattern (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.
+ */
+ CompressedSimpleSparsityPattern & operator = (const CompressedSimpleSparsityPattern &);
+
+ /**
+ * Reallocate memory and set up
+ * data structures for a new
+ * matrix with @p m rows and
+ * @p n columns, with at most
+ * max_entries_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
+ * 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);
+
+ /**
+ * Check if a value at a certain
+ * position may be non-zero.
+ */
+ bool exists (const unsigned int i,
+ const unsigned int j) const;
+
+ /**
+ * 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. The output consists of
+ * one line per row of the format
+ * <tt>[i,j1,j2,j3,...]</tt>. <i>i</i>
+ * is the row number and
+ * <i>jn</i> are the allocated
+ * columns in this row.
+ */
+ void print (std::ostream &out) const;
+
+ /**
+ * 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 <tt>i j</tt> 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
+ * <tt>(0,0)</tt> 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 indexth 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
+ * allocated through this sparsity pattern.
+ */
+ unsigned int n_nonzero_elements () const;
+
+ /**
+ * Return whether this object stores only
+ * those entries that have been added
+ * explicitly, or if the sparsity pattern
+ * contains elements that have been added
+ * through other means (implicitly) while
+ * building it. For the current class,
+ * the result is always true.
+ *
+ * This function mainly serves the
+ * purpose of describing the current
+ * class in cases where several kinds of
+ * sparsity patterns can be passed as
+ * template arguments.
+ */
+ static
+ bool stores_only_added_elements ();
+
+
+
+ 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;
+
+ /**
+ * Store some data for each row
+ * describing which entries of this row
+ * are nonzero. Data is stored sorted in
+ * the @p entries std::vector.
+ * The vector per row is dynamically
+ * growing upon insertion doubling its
+ * memory each time.
+ */
+ struct Line
+ {
+ public:
+ /**
+ * Storage for the column indices of
+ * this row. This array is always
+ * kept sorted.
+ */
+ std::vector<unsigned int> entries;
+
+ /**
+ * Constructor.
+ */
+ Line ();
+
+ /**
+ * Add the given column number to
+ * this line.
+ */
+ void add (const unsigned int col_num);
+
+ };
+
+
+ /**
+ * Actual data: store for each
+ * row the set of nonzero
+ * entries.
+ */
+ std::vector<Line> lines;
+};
+
+/*@}*/
+/*---------------------- Inline functions -----------------------------------*/
+
+
+inline
+void
+CompressedSimpleSparsityPattern::Line::add (const unsigned int j)
+{
+ /* first check the last element (or if line is still empty) */
+ if ( (entries.size()==0) || ( *(--entries.end()) < j) )
+ {
+ entries.push_back(j);
+ return;
+ }
+
+ /* do a binary search to find the place where to insert: */
+ std::vector<unsigned int>::iterator it = std::lower_bound(entries.begin(),
+ entries.end(),
+ j);
+
+ /* If this entry is a duplicate, exit immediately */
+ if (*it == j)
+ return;
+
+ /* Insert at the right place in the vector.
+ Vector grows automatically to fit
+ elements. Always doubles its size.*/
+ entries.insert(it, j);
+}
+
+
+
+inline
+unsigned int
+CompressedSimpleSparsityPattern::n_rows () const
+{
+ return rows;
+}
+
+
+
+inline
+unsigned int
+CompressedSimpleSparsityPattern::n_cols () const
+{
+ return cols;
+}
+
+
+
+inline
+void
+CompressedSimpleSparsityPattern::add (const unsigned int i,
+ const unsigned int j)
+{
+ Assert (i<rows, ExcIndexRange(i, 0, rows));
+ Assert (j<cols, ExcIndexRange(j, 0, cols));
+
+ lines[i].add (j);
+}
+
+
+
+inline
+CompressedSimpleSparsityPattern::Line::Line ()
+{}
+
+
+
+inline
+unsigned int
+CompressedSimpleSparsityPattern::row_length (const unsigned int row) const
+{
+ Assert (row < n_rows(), ExcIndexRange (row, 0, n_rows()));
+
+ return lines[row].entries.size();
+}
+
+
+
+inline
+unsigned int
+CompressedSimpleSparsityPattern::column_number (const unsigned int row,
+ const unsigned int index) const
+{
+ Assert (row < n_rows(), ExcIndexRange (row, 0, n_rows()));
+ Assert (index < lines[row].entries.size(),
+ ExcIndexRange (index, 0, lines[row].entries.size()));
+
+ return lines[row].entries[index];
+}
+
+
+inline
+bool
+CompressedSimpleSparsityPattern::stores_only_added_elements ()
+{
+ return true;
+}
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
*
* <h3>Notes</h3>
*
- * A variation of this class is the CompressedSetSparsityPattern class
- * that appears to be more efficient in some situations, in particular
- * when using hp finite elements or, more generally, in cases with
- * many nonzero entries. See for example the @ref step_27 "step-27"
- * and @ref step_22 "step-22" tutorial programs.
+ * There are several, exchangeable variations of this class, see @ref Sparsity,
+ * section '"Dynamic" or "compressed" sparsity patterns' for more information.
*
* @author Wolfgang Bangerth, 2001
*/
class CompressedSparsityPattern;
class CompressedSetSparsityPattern;
+class CompressedSimpleSparsityPattern;
const bool optimize_diagonal = true);
+ /**
+ * Copy data from an object of
+ * type
+ * CompressedSetSparsityPattern.
+ * Previous content of this
+ * object is lost, and the
+ * sparsity pattern is in
+ * compressed mode afterwards.
+ */
+ void copy_from (const CompressedSetSparsityPattern &csp,
+ const bool optimize_diagonal = true);
+
/**
* Copy data from an object of
* type
- * CompressedSetSparsityPattern.
+ * CompressedSimpleSparsityPattern.
* Previous content of this
* object is lost, and the
* sparsity pattern is in
* compressed mode afterwards.
*/
- void copy_from (const CompressedSetSparsityPattern &csp,
+ void copy_from (const CompressedSimpleSparsityPattern &csp,
const bool optimize_diagonal = true);
template class BlockSparsityPatternBase<SparsityPattern>;
template class BlockSparsityPatternBase<CompressedSparsityPattern>;
+template class BlockSparsityPatternBase<CompressedSimpleSparsityPattern>;
template class BlockSparsityPatternBase<CompressedSetSparsityPattern>;
collect_sizes();
}
+void
+BlockSparsityPattern::copy_from (const BlockCompressedSimpleSparsityPattern &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();
+}
void
BlockSparsityPattern::copy_from (const BlockCompressedSetSparsityPattern &csp)
this->collect_sizes();
}
+BlockCompressedSimpleSparsityPattern::BlockCompressedSimpleSparsityPattern ()
+{}
+
+
+
+BlockCompressedSimpleSparsityPattern::
+BlockCompressedSimpleSparsityPattern (const unsigned int n_rows,
+ const unsigned int n_columns)
+ :
+ BlockSparsityPatternBase<CompressedSimpleSparsityPattern>(n_rows,
+ n_columns)
+{}
+
+
+BlockCompressedSimpleSparsityPattern::
+BlockCompressedSimpleSparsityPattern (const std::vector<unsigned int>& row_indices,
+ const std::vector<unsigned int>& col_indices)
+ :
+ BlockSparsityPatternBase<CompressedSimpleSparsityPattern>(row_indices.size(),
+ col_indices.size())
+{
+ for (unsigned int i=0;i<row_indices.size();++i)
+ for (unsigned int j=0;j<col_indices.size();++j)
+ this->block(i,j).reinit(row_indices[i],col_indices[j]);
+ this->collect_sizes();
+}
+
+
+void
+BlockCompressedSimpleSparsityPattern::reinit (
+ const std::vector< unsigned int > &row_block_sizes,
+ const std::vector< unsigned int > &col_block_sizes)
+{
+ BlockSparsityPatternBase<CompressedSimpleSparsityPattern>::reinit(row_block_sizes.size(), col_block_sizes.size());
+ for (unsigned int i=0;i<row_block_sizes.size();++i)
+ for (unsigned int j=0;j<col_block_sizes.size();++j)
+ this->block(i,j).reinit(row_block_sizes[i],col_block_sizes[j]);
+ this->collect_sizes();
+}
+
BlockCompressedSetSparsityPattern::BlockCompressedSetSparsityPattern ()
--- /dev/null
+//---------------------------------------------------------------------------
+// $Id$
+// Version: $Name$
+//
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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.
+//
+//---------------------------------------------------------------------------
+
+
+#include <lac/compressed_simple_sparsity_pattern.h>
+
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+#include <cmath>
+#include <numeric>
+#include <functional>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+CompressedSimpleSparsityPattern::CompressedSimpleSparsityPattern ()
+ :
+ rows(0),
+ cols(0)
+{}
+
+
+
+CompressedSimpleSparsityPattern::
+CompressedSimpleSparsityPattern (const CompressedSimpleSparsityPattern &s)
+ :
+ Subscriptor(),
+ rows(0),
+ cols(0)
+{
+ Assert (s.rows == 0, ExcInvalidConstructorCall());
+ Assert (s.cols == 0, ExcInvalidConstructorCall());
+}
+
+
+
+CompressedSimpleSparsityPattern::CompressedSimpleSparsityPattern (const unsigned int m,
+ const unsigned int n)
+ :
+ rows(0),
+ cols(0)
+{
+ reinit (m,n);
+}
+
+
+
+CompressedSimpleSparsityPattern::CompressedSimpleSparsityPattern (const unsigned int n)
+ :
+ rows(0),
+ cols(0)
+{
+ reinit (n,n);
+}
+
+
+
+CompressedSimpleSparsityPattern &
+CompressedSimpleSparsityPattern::operator = (const CompressedSimpleSparsityPattern &s)
+{
+ Assert (s.rows == 0, ExcInvalidConstructorCall());
+ Assert (s.cols == 0, ExcInvalidConstructorCall());
+
+ Assert (rows == 0, ExcInvalidConstructorCall());
+ Assert (cols == 0, ExcInvalidConstructorCall());
+
+ return *this;
+}
+
+
+
+void
+CompressedSimpleSparsityPattern::reinit (const unsigned int m,
+ const unsigned int n)
+{
+ rows = m;
+ cols = n;
+
+ std::vector<Line> new_lines (rows);
+ lines.swap (new_lines);
+}
+
+
+
+void
+CompressedSimpleSparsityPattern::compress ()
+{}
+
+
+
+bool
+CompressedSimpleSparsityPattern::empty () const
+{
+ return ((rows==0) && (cols==0));
+}
+
+
+
+unsigned int
+CompressedSimpleSparsityPattern::max_entries_per_row () const
+{
+ unsigned int m = 0;
+ for (unsigned int i=0; i<rows; ++i)
+ {
+ m = std::max (m, static_cast<unsigned int>(lines[i].entries.size()));
+ }
+
+ return m;
+}
+
+
+
+bool
+CompressedSimpleSparsityPattern::exists (const unsigned int i,
+ const unsigned int j) const
+{
+ Assert (i<rows, ExcIndexRange(i, 0, rows));
+ Assert (j<cols, ExcIndexRange(j, 0, cols));
+
+ return std::binary_search (lines[i].entries.begin(),
+ lines[i].entries.end(),
+ j);
+}
+
+
+
+void
+CompressedSimpleSparsityPattern::symmetrize ()
+{
+ Assert (rows==cols, ExcNotQuadratic());
+
+ // loop over all elements presently
+ // in the sparsity pattern and add
+ // the transpose element. note:
+ //
+ // 1. that the sparsity pattern
+ // changes which we work on, but
+ // not the present row
+ //
+ // 2. that the @p{add} function can
+ // be called on elements that
+ // already exist without any harm
+ for (unsigned int row=0; row<rows; ++row)
+ {
+ for (std::vector<unsigned int>::const_iterator
+ j=lines[row].entries.begin();
+ j != lines[row].entries.end();
+ ++j)
+ // add the transpose entry if
+ // this is not the diagonal
+ if (row != *j)
+ add (*j, row);
+ }
+}
+
+
+
+void
+CompressedSimpleSparsityPattern::print (std::ostream &out) const
+{
+ for (unsigned int row=0; row<rows; ++row)
+ {
+ out << '[' << row;
+
+ for (std::vector<unsigned int>::const_iterator
+ j=lines[row].entries.begin();
+ j != lines[row].entries.end(); ++j)
+ out << ',' << *j;
+
+ out << ']' << std::endl;
+ }
+
+ AssertThrow (out, ExcIO());
+}
+
+
+
+void
+CompressedSimpleSparsityPattern::print_gnuplot (std::ostream &out) const
+{
+ for (unsigned int row=0; row<rows; ++row)
+ {
+ for (std::vector<unsigned int>::const_iterator
+ j=lines[row].entries.begin();
+ j != lines[row].entries.end(); ++j)
+ // 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 << *j << " " << -static_cast<signed int>(row) << std::endl;
+ }
+
+
+ AssertThrow (out, ExcIO());
+}
+
+
+
+unsigned int
+CompressedSimpleSparsityPattern::bandwidth () const
+{
+ unsigned int b=0;
+ for (unsigned int row=0; row<rows; ++row)
+ {
+ for (std::vector<unsigned int>::const_iterator
+ j=lines[row].entries.begin();
+ j != lines[row].entries.end(); ++j)
+ if (static_cast<unsigned int>(std::abs(static_cast<int>(row-*j))) > b)
+ b = std::abs(static_cast<signed int>(row-*j));
+ }
+
+ return b;
+}
+
+
+
+unsigned int
+CompressedSimpleSparsityPattern::n_nonzero_elements () const
+{
+ unsigned int n=0;
+ for (unsigned int i=0; i<rows; ++i)
+ {
+ n += lines[i].entries.size();
+ }
+
+ return n;
+}
+
+DEAL_II_NAMESPACE_CLOSE
#include <lac/full_matrix.h>
#include <lac/compressed_sparsity_pattern.h>
#include <lac/compressed_set_sparsity_pattern.h>
+#include <lac/compressed_simple_sparsity_pattern.h>
#include <iostream>
#include <iomanip>
compress ();
}
+void
+SparsityPattern::copy_from (const CompressedSimpleSparsityPattern &csp,
+ const bool optimize_diag)
+{
+ // first determine row lengths for
+ // each row. if the matrix is
+ // quadratic, then we might have to
+ // add an additional entry for the
+ // diagonal, if that is not yet
+ // present. as we have to call
+ // compress anyway later on, don't
+ // bother to check whether that
+ // diagonal entry is in a certain
+ // row or not
+ const bool is_square = optimize_diag && (csp.n_rows() == csp.n_cols());
+ std::vector<unsigned int> row_lengths (csp.n_rows());
+ for (unsigned int i=0; i<csp.n_rows(); ++i)
+ row_lengths[i] = csp.row_length(i) +
+ (is_square ? 1 : 0);
+ reinit (csp.n_rows(), csp.n_cols(), row_lengths, is_square);
+
+ // now enter all the elements into
+ // the matrix. note that if the
+ // matrix is quadratic, then we
+ // already have the diagonal
+ // element preallocated
+ for (unsigned int row = 0; row<csp.n_rows(); ++row)
+ {
+ unsigned int *cols = &colnums[rowstart[row]] + (is_square ? 1 : 0);
+ for (unsigned int j=0; j<csp.row_length(row); ++j)
+ {
+ const unsigned int col = csp.column_number(row,j);
+ Assert (col < csp.n_cols(), ExcInvalidIndex(col,csp.n_cols()));
+
+ if ((col!=row) || !is_square)
+ *cols++ = col;
+ }
+ }
+
+ // finally compress
+ // everything. this also sorts the
+ // entries within each row
+ compress ();
+}