/usr/include/deal.II/lac/petsc_parallel_sparse_matrix.h is in libdeal.ii-dev 6.3.1-1.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | //---------------------------------------------------------------------------
// $Id: petsc_parallel_sparse_matrix.h 20745 2010-03-07 12:50:06Z young $
// Version: $Name$
//
// Copyright (C) 2004, 2005, 2006, 2007, 2009 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__petsc_parallel_sparse_matrix_h
#define __deal2__petsc_parallel_sparse_matrix_h
#include <base/config.h>
#ifdef DEAL_II_USE_PETSC
# include <lac/exceptions.h>
# include <lac/petsc_matrix_base.h>
# include <vector>
DEAL_II_NAMESPACE_OPEN
// forward declaration
template <typename Matrix> class BlockMatrixBase;
namespace PETScWrappers
{
namespace MPI
{
/**
* Implementation of a parallel sparse matrix class based on PETSC, with rows
* of the matrix distributed across an MPI network. All the functionality is
* actually in the base class, except for the calls to generate a parallel
* sparse matrix. This is possible since PETSc only works on an abstract
* matrix type and internally distributes to functions that do the actual work
* depending on the actual matrix type (much like using virtual
* functions). Only the functions creating a matrix of specific type differ,
* and are implemented in this particular class.
*
* There are a number of comments on the communication model as well as access
* to individual elements in the documentation to the parallel vector
* class. These comments apply here as well.
*
*
* <h3>Partitioning of matrices</h3>
*
* PETSc partitions parallel matrices so that each MPI process "owns" a
* certain number of rows (i.e. only this process stores the respective
* entries in these rows). The number of rows each process owns has to be
* passed to the constructors and reinit() functions via the argument @p
* local_rows. The individual values passed as @p local_rows on all the MPI
* processes of course have to add up to the global number of rows of the
* matrix.
*
* In addition to this, PETSc also partitions the rectangular chunk of the
* matrix it owns (i.e. the @p local_rows times n() elements in the matrix),
* so that matrix vector multiplications can be performed efficiently. This
* column-partitioning therefore has to match the partitioning of the vectors
* with which the matrix is multiplied, just as the row-partitioning has to
* match the partitioning of destination vectors. This partitioning is passed
* to the constructors and reinit() functions through the @p local_columns
* variable, which again has to add up to the global number of columns in the
* matrix. The name @p local_columns may be named inappropriately since it
* does not reflect that only these columns are stored locally, but it
* reflects the fact that these are the columns for which the elements of
* incoming vectors are stored locally.
*
* To make things even more complicated, PETSc needs a very good estimate of
* the number of elements to be stored in each row to be efficient. Otherwise
* it spends most of the time with allocating small chunks of memory, a
* process that can slow down programs to a crawl if it happens to often. As
* if a good estimate of the number of entries per row isn't even, it even
* needs to split this as follows: for each row it owns, it needs an estimate
* for the number of elements in this row that fall into the columns that are
* set apart for this process (see above), and the number of elements that are
* in the rest of the columns.
*
* Since in general this information is not readily available, most of the
* initializing functions of this class assume that all of the number of
* elements you give as an argument to @p n_nonzero_per_row or by @p
* row_lengths fall into the columns "owned" by this process, and none into
* the other ones. This is a fair guess for most of the rows, since in a good
* domain partitioning, nodes only interact with nodes that are within the
* same subdomain. It does not hold for nodes on the interfaces of subdomain,
* however, and for the rows corresponding to these nodes, PETSc will have to
* allocate additional memory, a costly process.
*
* The only way to avoid this is to tell PETSc where the actual entries of the
* matrix will be. For this, there are constructors and reinit() functions of
* this class that take a CompressedSparsityPattern object containing all this
* information. While in the general case it is sufficient if the constructors
* and reinit() functions know the number of local rows and columns, the
* functions getting a sparsity pattern also need to know the number of local
* rows (@p local_rows_per_process) and columns (@p local_columns_per_process)
* for all other processes, in order to compute which parts of the matrix are
* which. Thus, it is not sufficient to just count the number of degrees of
* freedom that belong to a particular process, but you have to have the
* numbers for all processes available at all processes.
*
* @ingroup PETScWrappers
* @ingroup Matrix1
* @author Wolfgang Bangerth, 2004
*/
class SparseMatrix : public MatrixBase
{
public:
/**
* A structure that describes some of
* the traits of this class in terms
* of its run-time behavior. Some
* other classes (such as the block
* matrix classes) that take one or
* other of the matrix classes as its
* template parameters can tune their
* behavior based on the variables in
* this class.
*/
struct Traits
{
/**
* It is not safe to elide
* additions of zeros to
* individual elements of this
* matrix. The reason is that
* additions to the matrix may
* trigger collective operations
* synchronising buffers on
* multiple processes. If an
* addition is elided on one
* process, this may lead to
* other processes hanging in an
* infinite waiting loop.
*/
static const bool zero_addition_can_be_elided = false;
};
/**
* Default constructor. Create an
* empty matrix.
*/
SparseMatrix ();
/**
* Create a sparse matrix of
* dimensions @p m times @p n, with
* an initial guess of @p
* n_nonzero_per_row nonzero elements
* per row. PETSc is able to cope
* with the situation that more than
* this number of elements are later
* allocated for a row, but this
* involves copying data, and is thus
* expensive.
*
* For the meaning of the @p
* local_row and @p local_columns
* parameters, see the class
* documentation.
*
* The @p is_symmetric flag determines
* whether we should tell PETSc that
* the matrix is going to be symmetric
* (as indicated by the call
* <tt>MatSetOption(mat,
* MAT_SYMMETRIC)</tt>. Note that the
* PETSc documentation states that one
* cannot form an ILU decomposition of
* a matrix for which this flag has
* been set to @p true, only an
* ICC. The default value of this flag
* is @p false.
*/
SparseMatrix (const MPI_Comm &communicator,
const unsigned int m,
const unsigned int n,
const unsigned int local_rows,
const unsigned int local_columns,
const unsigned int n_nonzero_per_row,
const bool is_symmetric = false);
/**
* Initialize a rectangular matrix
* with @p m rows and @p n columns.
* The maximal number of nonzero
* entries for each row separately is
* given by the @p row_lengths array.
*
* For the meaning of the @p
* local_row and @p local_columns
* parameters, see the class
* documentation.
*
* Just as for the other
* constructors: PETSc is able to
* cope with the situation that more
* than this number of elements are
* later allocated for a row, but
* this involves copying data, and is
* thus expensive.
*
* The @p is_symmetric flag
* determines whether we should tell
* PETSc that the matrix is going to
* be symmetric (as indicated by the
* call <tt>MatSetOption(mat,
* MAT_SYMMETRIC)</tt>. Note that the
* PETSc documentation states that
* one cannot form an ILU
* decomposition of a matrix for
* which this flag has been set to @p
* true, only an ICC. The default
* value of this flag is @p false.
*/
SparseMatrix (const MPI_Comm &communicator,
const unsigned int m,
const unsigned int n,
const unsigned int local_rows,
const unsigned int local_columns,
const std::vector<unsigned int> &row_lengths,
const bool is_symmetric = false);
/**
* Initialize using the given
* sparsity pattern with
* communication happening over the
* provided @p communicator.
*
* For the meaning of the @p
* local_rows_per_process and @p
* local_columns_per_process
* parameters, see the class
* documentation.
*
* Note that PETSc can be very slow
* if you do not provide it with a
* good estimate of the lengths of
* rows. Using the present function
* is a very efficient way to do
* this, as it uses the exact number
* of nonzero entries for each row of
* the matrix by using the given
* sparsity pattern argument. If the
* @p preset_nonzero_locations flag
* is @p true, this function in
* addition not only sets the correct
* row sizes up front, but also
* pre-allocated the correct nonzero
* entries in the matrix.
*
* PETsc allows to later add
* additional nonzero entries to a
* matrix, by simply writing to these
* elements. However, this will then
* lead to additional memory
* allocations which are very
* inefficient and will greatly slow
* down your program. It is therefore
* significantly more efficient to
* get memory allocation right from
* the start.
*/
template <typename SparsityType>
SparseMatrix (const MPI_Comm &communicator,
const SparsityType &sparsity_pattern,
const std::vector<unsigned int> &local_rows_per_process,
const std::vector<unsigned int> &local_columns_per_process,
const unsigned int this_process,
const bool preset_nonzero_locations = true);
/**
* This operator assigns a scalar to
* a matrix. Since this does usually
* not make much sense (should we set
* all matrix entries to this value?
* Only the nonzero entries of the
* sparsity pattern?), this operation
* is only allowed if the actual
* value to be assigned is zero. This
* operator only exists to allow for
* the obvious notation
* <tt>matrix=0</tt>, which sets all
* elements of the matrix to zero,
* but keep the sparsity pattern
* previously used.
*/
SparseMatrix & operator = (const value_type d);
/**
* Throw away the present matrix and
* generate one that has the same
* properties as if it were created by
* the constructor of this class with
* the same argument list as the
* present function.
*/
void reinit (const MPI_Comm &communicator,
const unsigned int m,
const unsigned int n,
const unsigned int local_rows,
const unsigned int local_columns,
const unsigned int n_nonzero_per_row,
const bool is_symmetric = false);
/**
* Throw away the present matrix and
* generate one that has the same
* properties as if it were created by
* the constructor of this class with
* the same argument list as the
* present function.
*/
void reinit (const MPI_Comm &communicator,
const unsigned int m,
const unsigned int n,
const unsigned int local_rows,
const unsigned int local_columns,
const std::vector<unsigned int> &row_lengths,
const bool is_symmetric = false);
/**
* Initialize using the given
* sparsity pattern with
* communication happening over the
* provided @p communicator.
*
* Note that PETSc can be very slow
* if you do not provide it with a
* good estimate of the lengths of
* rows. Using the present function
* is a very efficient way to do
* this, as it uses the exact number
* of nonzero entries for each row of
* the matrix by using the given
* sparsity pattern argument. If the
* @p preset_nonzero_locations flag
* is @p true, this function in
* addition not only sets the correct
* row sizes up front, but also
* pre-allocated the correct nonzero
* entries in the matrix.
*
* PETsc allows to later add
* additional nonzero entries to a
* matrix, by simply writing to these
* elements. However, this will then
* lead to additional memory
* allocations which are very
* inefficient and will greatly slow
* down your program. It is therefore
* significantly more efficient to
* get memory allocation right from
* the start.
*/
template <typename SparsityType>
void reinit (const MPI_Comm &communicator,
const SparsityType &sparsity_pattern,
const std::vector<unsigned int> &local_rows_per_process,
const std::vector<unsigned int> &local_columns_per_process,
const unsigned int this_process,
const bool preset_nonzero_locations = true);
/**
* Return a reference to the MPI
* communicator object in use with
* this matrix.
*/
virtual const MPI_Comm & get_mpi_communicator () const;
/** @addtogroup Exceptions
* @{ */
/**
* Exception
*/
DeclException2 (ExcLocalRowsTooLarge,
int, int,
<< "The number of local rows " << arg1
<< " must be larger than the total number of rows " << arg2);
//@}
private:
/**
* Copy of the communicator object to
* be used for this parallel vector.
*/
MPI_Comm communicator;
/**
* Do the actual work for the
* respective reinit() function and
* the matching constructor,
* i.e. create a matrix. Getting rid
* of the previous matrix is left to
* the caller.
*/
void do_reinit (const unsigned int m,
const unsigned int n,
const unsigned int local_rows,
const unsigned int local_columns,
const unsigned int n_nonzero_per_row,
const bool is_symmetric = false);
/**
* Same as previous function.
*/
void do_reinit (const unsigned int m,
const unsigned int n,
const unsigned int local_rows,
const unsigned int local_columns,
const std::vector<unsigned int> &row_lengths,
const bool is_symmetric = false);
/**
* Same as previous functions.
*/
template <typename SparsityType>
void do_reinit (const SparsityType &sparsity_pattern,
const std::vector<unsigned int> &local_rows_per_process,
const std::vector<unsigned int> &local_columns_per_process,
const unsigned int this_process,
const bool preset_nonzero_locations);
/**
* To allow calling protected
* prepare_add() and
* prepare_set().
*/
friend class BlockMatrixBase<SparseMatrix>;
};
// -------- template and inline functions ----------
inline
const MPI_Comm &
SparseMatrix::get_mpi_communicator () const
{
return communicator;
}
}
}
DEAL_II_NAMESPACE_CLOSE
#endif // DEAL_II_USE_PETSC
/*---------------------------- petsc_parallel_sparse_matrix.h ---------------------------*/
#endif
/*---------------------------- petsc_parallel_sparse_matrix.h ---------------------------*/
|