Reference documentation for deal.II version 8.4.2
petsc_parallel_sparse_matrix.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/lac/petsc_parallel_sparse_matrix.h>
17 
18 #ifdef DEAL_II_WITH_PETSC
19 
20 # include <deal.II/lac/petsc_vector.h>
21 # include <deal.II/lac/sparsity_pattern.h>
22 # include <deal.II/lac/dynamic_sparsity_pattern.h>
23 
24 DEAL_II_NAMESPACE_OPEN
25 
26 namespace PETScWrappers
27 {
28  namespace MPI
29  {
30 
32  {
33  // just like for vectors: since we
34  // create an empty matrix, we can as
35  // well make it sequential
36  const int m=0, n=0, n_nonzero_per_row=0;
37  const int ierr
38  = MatCreateSeqAIJ(PETSC_COMM_SELF, m, n, n_nonzero_per_row,
39  0, &matrix);
40  AssertThrow (ierr == 0, ExcPETScError(ierr));
41  }
42 
43 
45  {
46  int ierr;
47 
48 #if DEAL_II_PETSC_VERSION_LT(3,2,0)
49  ierr = MatDestroy (matrix);
50 #else
51  ierr = MatDestroy (&matrix);
52 #endif
53  AssertThrow (ierr == 0, ExcPETScError(ierr));
54  }
55 
57  const size_type m,
58  const size_type n,
59  const size_type local_rows,
60  const size_type local_columns,
61  const size_type n_nonzero_per_row,
62  const bool is_symmetric,
63  const size_type n_offdiag_nonzero_per_row)
64  :
65  communicator (communicator)
66  {
67  do_reinit (m, n, local_rows, local_columns,
68  n_nonzero_per_row, is_symmetric,
69  n_offdiag_nonzero_per_row);
70  }
71 
72 
73 
75  const size_type m,
76  const size_type n,
77  const size_type local_rows,
78  const size_type local_columns,
79  const std::vector<size_type> &row_lengths,
80  const bool is_symmetric,
81  const std::vector<size_type> &offdiag_row_lengths)
82  :
83  communicator (communicator)
84  {
85  do_reinit (m, n, local_rows, local_columns,
86  row_lengths, is_symmetric, offdiag_row_lengths);
87  }
88 
89 
90 
91  template <typename SparsityPatternType>
93  SparseMatrix (const MPI_Comm &communicator,
94  const SparsityPatternType &sparsity_pattern,
95  const std::vector<size_type> &local_rows_per_process,
96  const std::vector<size_type> &local_columns_per_process,
97  const unsigned int this_process,
98  const bool preset_nonzero_locations)
99  :
100  communicator (communicator)
101  {
102  do_reinit (sparsity_pattern, local_rows_per_process,
103  local_columns_per_process, this_process,
104  preset_nonzero_locations);
105  }
106 
107 
108  void
110  reinit (const SparseMatrix &other)
111  {
112  if (&other == this)
113  return;
114 
115  this->communicator = other.communicator;
116 
117  int ierr;
118 #if DEAL_II_PETSC_VERSION_LT(3,2,0)
119  ierr = MatDestroy (matrix);
120 #else
121  ierr = MatDestroy (&matrix);
122 #endif
123  AssertThrow (ierr == 0, ExcPETScError(ierr));
124 
125  ierr = MatDuplicate(other.matrix, MAT_DO_NOT_COPY_VALUES, &matrix);
126  AssertThrow (ierr == 0, ExcPETScError(ierr));
127  }
128 
129 
130  SparseMatrix &
132  {
134  return *this;
135  }
136 
137  void
139  {
140  if (&other == this)
141  return;
142 
143  this->communicator = other.communicator;
144 
145  int ierr = MatCopy(other.matrix, matrix, SAME_NONZERO_PATTERN);
146  AssertThrow (ierr == 0, ExcPETScError(ierr));
147  }
148 
149  void
151  const size_type m,
152  const size_type n,
153  const size_type local_rows,
154  const size_type local_columns,
155  const size_type n_nonzero_per_row,
156  const bool is_symmetric,
157  const size_type n_offdiag_nonzero_per_row)
158  {
159  this->communicator = communicator;
160 
161  // get rid of old matrix and generate a
162  // new one
163 #if DEAL_II_PETSC_VERSION_LT(3,2,0)
164  const int ierr = MatDestroy (matrix);
165 #else
166  const int ierr = MatDestroy (&matrix);
167 #endif
168  AssertThrow (ierr == 0, ExcPETScError(ierr));
169 
170  do_reinit (m, n, local_rows, local_columns,
171  n_nonzero_per_row, is_symmetric,
172  n_offdiag_nonzero_per_row);
173  }
174 
175 
176 
177  void
179  const size_type m,
180  const size_type n,
181  const size_type local_rows,
182  const size_type local_columns,
183  const std::vector<size_type> &row_lengths,
184  const bool is_symmetric,
185  const std::vector<size_type> &offdiag_row_lengths)
186  {
187  this->communicator = communicator;
188 
189  // get rid of old matrix and generate a
190  // new one
191 #if DEAL_II_PETSC_VERSION_LT(3,2,0)
192  const int ierr = MatDestroy (matrix);
193 #else
194  const int ierr = MatDestroy (&matrix);
195 #endif
196  AssertThrow (ierr == 0, ExcPETScError(ierr));
197 
198  do_reinit (m, n, local_rows, local_columns,
199  row_lengths, is_symmetric, offdiag_row_lengths);
200  }
201 
202 
203 
204  template <typename SparsityPatternType>
205  void
207  reinit (const MPI_Comm &communicator,
208  const SparsityPatternType &sparsity_pattern,
209  const std::vector<size_type> &local_rows_per_process,
210  const std::vector<size_type> &local_columns_per_process,
211  const unsigned int this_process,
212  const bool preset_nonzero_locations)
213  {
214  this->communicator = communicator;
215 
216  // get rid of old matrix and generate a
217  // new one
218 #if DEAL_II_PETSC_VERSION_LT(3,2,0)
219  const int ierr = MatDestroy (matrix);
220 #else
221  const int ierr = MatDestroy (&matrix);
222 #endif
223  AssertThrow (ierr == 0, ExcPETScError(ierr));
224 
225  do_reinit (sparsity_pattern, local_rows_per_process,
226  local_columns_per_process, this_process,
227  preset_nonzero_locations);
228  }
229 
230  template <typename SparsityPatternType>
231  void
233  reinit (const IndexSet &local_rows,
234  const IndexSet &local_columns,
235  const SparsityPatternType &sparsity_pattern,
236  const MPI_Comm &communicator)
237  {
238  this->communicator = communicator;
239 
240  // get rid of old matrix and generate a
241  // new one
242 #if DEAL_II_PETSC_VERSION_LT(3,2,0)
243  const int ierr = MatDestroy (matrix);
244 #else
245  const int ierr = MatDestroy (&matrix);
246 #endif
247  AssertThrow (ierr == 0, ExcPETScError(ierr));
248 
249  do_reinit (local_rows, local_columns, sparsity_pattern);
250  }
251 
252  void
254  const size_type n,
255  const size_type local_rows,
256  const size_type local_columns,
257  const size_type n_nonzero_per_row,
258  const bool is_symmetric,
259  const size_type n_offdiag_nonzero_per_row)
260  {
261  Assert (local_rows <= m, ExcLocalRowsTooLarge (local_rows, m));
262 
263  // use the call sequence indicating only
264  // a maximal number of elements per row
265  // for all rows globally
266  int ierr;
267 
268 #if DEAL_II_PETSC_VERSION_LT(3,3,0)
269  ierr
270  = MatCreateMPIAIJ (communicator,
271  local_rows, local_columns,
272  m, n,
273  n_nonzero_per_row, 0,
274  n_offdiag_nonzero_per_row, 0,
275  &matrix);
276 #else
277  ierr
278  = MatCreateAIJ (communicator,
279  local_rows, local_columns,
280  m, n,
281  n_nonzero_per_row, 0,
282  n_offdiag_nonzero_per_row, 0,
283  &matrix);
284  AssertThrow (ierr == 0, ExcPETScError(ierr));
285 
286  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
287 #endif
288  AssertThrow (ierr == 0, ExcPETScError(ierr));
289 
290  // set symmetric flag, if so requested
291  if (is_symmetric == true)
292  {
293 #if DEAL_II_PETSC_VERSION_LT(3,0,0)
294  const int ierr
295  = MatSetOption (matrix, MAT_SYMMETRIC);
296 #else
297  const int ierr
298  = MatSetOption (matrix, MAT_SYMMETRIC, PETSC_TRUE);
299 #endif
300 
301  AssertThrow (ierr == 0, ExcPETScError(ierr));
302  }
303  }
304 
305 
306 
307  void
309  const size_type n,
310  const size_type local_rows,
311  const size_type local_columns,
312  const std::vector<size_type> &row_lengths,
313  const bool is_symmetric,
314  const std::vector<size_type> &offdiag_row_lengths)
315  {
316  Assert (local_rows <= m, ExcLocalRowsTooLarge (local_rows, m));
317 
318  Assert (row_lengths.size() == m,
319  ExcDimensionMismatch (row_lengths.size(), m));
320 
321  // For the case that
322  // local_columns is smaller
323  // than one of the row lengths
324  // MatCreateMPIAIJ throws an
325  // error. In this case use a
326  // PETScWrappers::SparseMatrix
327  for (size_type i=0; i<row_lengths.size(); ++i)
328  Assert(row_lengths[i]<=local_columns,
329  ExcIndexRange(row_lengths[i], 1, local_columns+1));
330 
331  // use the call sequence indicating a
332  // maximal number of elements for each
333  // row individually. annoyingly, we
334  // always use unsigned ints for cases
335  // like this, while PETSc wants to see
336  // signed integers. so we have to
337  // convert, unless we want to play dirty
338  // tricks with conversions of pointers
339  const std::vector<PetscInt> int_row_lengths (row_lengths.begin(),
340  row_lengths.end());
341  const std::vector<PetscInt> int_offdiag_row_lengths (offdiag_row_lengths.begin(),
342  offdiag_row_lengths.end());
343 
344 //TODO: There must be a significantly better way to provide information about the off-diagonal blocks of the matrix. this way, petsc keeps allocating tiny chunks of memory, and gets completely hung up over this
345 
346  int ierr;
347 
348 #if DEAL_II_PETSC_VERSION_LT(3,3,0)
349  ierr
350  = MatCreateMPIAIJ (communicator,
351  local_rows, local_columns,
352  m, n,
353  0, &int_row_lengths[0],
354  0, offdiag_row_lengths.size() ? &int_offdiag_row_lengths[0] : 0,
355  &matrix);
356 #else
357  ierr
358  = MatCreateAIJ (communicator,
359  local_rows, local_columns,
360  m, n,
361  0, &int_row_lengths[0],
362  0, offdiag_row_lengths.size() ? &int_offdiag_row_lengths[0] : 0,
363  &matrix);
364  AssertThrow (ierr == 0, ExcPETScError(ierr));
365 
366 //TODO: Sometimes the actual number of nonzero entries allocated is greater than the number of nonzero entries, which petsc will complain about unless explicitly disabled with MatSetOption. There is probably a way to prevent a different number nonzero elements being allocated in the first place. (See also previous TODO).
367 
368  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
369 #endif
370  AssertThrow (ierr == 0, ExcPETScError(ierr));
371 
372  // set symmetric flag, if so requested
373  if (is_symmetric == true)
374  {
375 #if DEAL_II_PETSC_VERSION_LT(3,0,0)
376  const int ierr
377  = MatSetOption (matrix, MAT_SYMMETRIC);
378 #else
379  const int ierr
380  = MatSetOption (matrix, MAT_SYMMETRIC, PETSC_TRUE);
381 #endif
382 
383  AssertThrow (ierr == 0, ExcPETScError(ierr));
384  }
385  }
386 
387 
388  template <typename SparsityPatternType>
389  void
391  do_reinit (const IndexSet &local_rows,
392  const IndexSet &local_columns,
393  const SparsityPatternType &sparsity_pattern)
394  {
395  Assert(sparsity_pattern.n_rows()==local_rows.size(),
396  ExcMessage("SparsityPattern and IndexSet have different number of rows"));
397  Assert(sparsity_pattern.n_cols()==local_columns.size(),
398  ExcMessage("SparsityPattern and IndexSet have different number of columns"));
399  Assert(local_rows.is_contiguous() && local_columns.is_contiguous(),
400  ExcMessage("PETSc only supports contiguous row/column ranges"));
401 
402 #ifdef DEBUG
403  {
404  // check indexsets
407  Assert(row_owners == sparsity_pattern.n_rows(),
408  ExcMessage(std::string("Each row has to be owned by exactly one owner (n_rows()=")
409  + Utilities::to_string(sparsity_pattern.n_rows())
410  + " but sum(local_rows.n_elements())="
411  + Utilities::to_string(row_owners)
412  + ")"));
413  Assert(col_owners == sparsity_pattern.n_cols(),
414  ExcMessage(std::string("Each column has to be owned by exactly one owner (n_cols()=")
415  + Utilities::to_string(sparsity_pattern.n_cols())
416  + " but sum(local_columns.n_elements())="
417  + Utilities::to_string(col_owners)
418  + ")"));
419  }
420 #endif
421 
422 
423  // create the matrix. We do not set row length but set the
424  // correct SparsityPattern later.
425  int ierr;
426 
427  ierr = MatCreate(communicator,&matrix);
428  AssertThrow (ierr == 0, ExcPETScError(ierr));
429 
430  ierr = MatSetSizes(matrix,
431  local_rows.n_elements(),
432  local_columns.n_elements(),
433  sparsity_pattern.n_rows(),
434  sparsity_pattern.n_cols());
435  AssertThrow (ierr == 0, ExcPETScError(ierr));
436 
437  ierr = MatSetType(matrix,MATMPIAIJ);
438  AssertThrow (ierr == 0, ExcPETScError(ierr));
439 
440 
441  // next preset the exact given matrix
442  // entries with zeros. this doesn't avoid any
443  // memory allocations, but it at least
444  // avoids some searches later on. the
445  // key here is that we can use the
446  // matrix set routines that set an
447  // entire row at once, not a single
448  // entry at a time
449  //
450  // for the usefulness of this option
451  // read the documentation of this
452  // class.
453  //if (preset_nonzero_locations == true)
454  if (local_rows.n_elements()>0)
455  {
456  Assert(local_columns.n_elements()>0, ExcInternalError());
457  // MatMPIAIJSetPreallocationCSR
458  // can be used to allocate the sparsity
459  // pattern of a matrix
460 
461  const PetscInt local_row_start = local_rows.nth_index_in_set(0);
462  const PetscInt
463  local_row_end = local_row_start + local_rows.n_elements();
464 
465 
466  // first set up the column number
467  // array for the rows to be stored
468  // on the local processor. have one
469  // dummy entry at the end to make
470  // sure petsc doesn't read past the
471  // end
472  std::vector<PetscInt>
473 
474  rowstart_in_window (local_row_end - local_row_start + 1, 0),
475  colnums_in_window;
476  {
477  unsigned int n_cols = 0;
478  for (PetscInt i=local_row_start; i<local_row_end; ++i)
479  {
480  const PetscInt row_length = sparsity_pattern.row_length(i);
481  rowstart_in_window[i+1-local_row_start]
482  = rowstart_in_window[i-local_row_start] + row_length;
483  n_cols += row_length;
484  }
485  colnums_in_window.resize (n_cols+1, -1);
486  }
487 
488  // now copy over the information
489  // from the sparsity pattern.
490  {
491  PetscInt *ptr = & colnums_in_window[0];
492  for (PetscInt i=local_row_start; i<local_row_end; ++i)
493  for (typename SparsityPatternType::iterator p=sparsity_pattern.begin(i);
494  p != sparsity_pattern.end(i); ++p, ++ptr)
495  *ptr = p->column();
496  }
497 
498 
499  // then call the petsc function
500  // that summarily allocates these
501  // entries:
502  MatMPIAIJSetPreallocationCSR (matrix,
503  &rowstart_in_window[0],
504  &colnums_in_window[0],
505  0);
506  }
507  else
508  {
509  PetscInt i=0;
510  MatMPIAIJSetPreallocationCSR (matrix,
511  &i,
512  &i,
513  0);
514 
515 
516  }
517  compress (::VectorOperation::insert);
518 
519  {
520 
521  // Tell PETSc that we are not
522  // planning on adding new entries
523  // to the matrix. Generate errors
524  // in debug mode.
525  int ierr;
526 #if DEAL_II_PETSC_VERSION_LT(3,0,0)
527 #ifdef DEBUG
528  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_LOCATION_ERR);
529  AssertThrow (ierr == 0, ExcPETScError(ierr));
530 #else
531  ierr = MatSetOption (matrix, MAT_NO_NEW_NONZERO_LOCATIONS);
532  AssertThrow (ierr == 0, ExcPETScError(ierr));
533 #endif
534 #else
535 #ifdef DEBUG
536  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);
537  AssertThrow (ierr == 0, ExcPETScError(ierr));
538 #else
539  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
540  AssertThrow (ierr == 0, ExcPETScError(ierr));
541 #endif
542 #endif
543 
544  // Tell PETSc to keep the
545  // SparsityPattern entries even if
546  // we delete a row with
547  // clear_rows() which calls
548  // MatZeroRows(). Otherwise one can
549  // not write into that row
550  // afterwards.
551 #if DEAL_II_PETSC_VERSION_LT(3,0,0)
552  ierr = MatSetOption (matrix, MAT_KEEP_ZEROED_ROWS);
553  AssertThrow (ierr == 0, ExcPETScError(ierr));
554 #elif DEAL_II_PETSC_VERSION_LT(3,1,0)
555  ierr = MatSetOption (matrix, MAT_KEEP_ZEROED_ROWS, PETSC_TRUE);
556  AssertThrow (ierr == 0, ExcPETScError(ierr));
557 #else
558  ierr = MatSetOption (matrix, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE);
559  AssertThrow (ierr == 0, ExcPETScError(ierr));
560 #endif
561 
562  }
563 
564  }
565 
566 
567  template <typename SparsityPatternType>
568  void
570  do_reinit (const SparsityPatternType &sparsity_pattern,
571  const std::vector<size_type> &local_rows_per_process,
572  const std::vector<size_type> &local_columns_per_process,
573  const unsigned int this_process,
574  const bool preset_nonzero_locations)
575  {
576  Assert (local_rows_per_process.size() == local_columns_per_process.size(),
577  ExcDimensionMismatch (local_rows_per_process.size(),
578  local_columns_per_process.size()));
579  Assert (this_process < local_rows_per_process.size(),
580  ExcInternalError());
582 
583  // for each row that we own locally, we
584  // have to count how many of the
585  // entries in the sparsity pattern lie
586  // in the column area we have locally,
587  // and how many arent. for this, we
588  // first have to know which areas are
589  // ours
590  size_type local_row_start = 0;
591  size_type local_col_start = 0;
592  for (unsigned int p=0; p<this_process; ++p)
593  {
594  local_row_start += local_rows_per_process[p];
595  local_col_start += local_columns_per_process[p];
596  }
597  const size_type
598  local_row_end = local_row_start + local_rows_per_process[this_process];
599 
600 #if DEAL_II_PETSC_VERSION_LT(2,3,3)
601  //old version to create the matrix, we
602  //can skip calculating the row length
603  //at least starting from 2.3.3 (tested,
604  //see below)
605 
606  const size_type
607  local_col_end = local_col_start + local_columns_per_process[this_process];
608 
609  // then count the elements in- and
610  // out-of-window for the rows we own
611  std::vector<PetscInt>
612 
613  row_lengths_in_window (local_row_end - local_row_start),
614  row_lengths_out_of_window (local_row_end - local_row_start);
615  for (size_type row = local_row_start; row<local_row_end; ++row)
616  for (size_type c=0; c<sparsity_pattern.row_length(row); ++c)
617  {
618  const size_type column = sparsity_pattern.column_number(row,c);
619 
620  if ((column >= local_col_start) &&
621  (column < local_col_end))
622  ++row_lengths_in_window[row-local_row_start];
623  else
624  ++row_lengths_out_of_window[row-local_row_start];
625  }
626 
627 
628  // create the matrix. completely
629  // confusingly, PETSc wants us to pass
630  // arrays for the local number of
631  // elements that starts with zero for
632  // the first _local_ row, i.e. it
633  // doesn't index into an array for
634  // _all_ rows.
635  const int ierr
636  = MatCreateMPIAIJ(communicator,
637  local_rows_per_process[this_process],
638  local_columns_per_process[this_process],
639  sparsity_pattern.n_rows(),
640  sparsity_pattern.n_cols(),
641  0, &row_lengths_in_window[0],
642  0, &row_lengths_out_of_window[0],
643  &matrix);
644  AssertThrow (ierr == 0, ExcPETScError(ierr));
645 
646 #else //PETSC_VERSION>=2.3.3
647  // create the matrix. We
648  // do not set row length but set the
649  // correct SparsityPattern later.
650  int ierr;
651 
652  ierr = MatCreate(communicator,&matrix);
653  AssertThrow (ierr == 0, ExcPETScError(ierr));
654 
655  ierr = MatSetSizes(matrix,
656  local_rows_per_process[this_process],
657  local_columns_per_process[this_process],
658  sparsity_pattern.n_rows(),
659  sparsity_pattern.n_cols());
660  AssertThrow (ierr == 0, ExcPETScError(ierr));
661 
662  ierr = MatSetType(matrix,MATMPIAIJ);
663  AssertThrow (ierr == 0, ExcPETScError(ierr));
664 #endif
665 
666 
667  // next preset the exact given matrix
668  // entries with zeros, if the user
669  // requested so. this doesn't avoid any
670  // memory allocations, but it at least
671  // avoids some searches later on. the
672  // key here is that we can use the
673  // matrix set routines that set an
674  // entire row at once, not a single
675  // entry at a time
676  //
677  // for the usefulness of this option
678  // read the documentation of this
679  // class.
680  if (preset_nonzero_locations == true)
681  {
682  // MatMPIAIJSetPreallocationCSR
683  // can be used to allocate the sparsity
684  // pattern of a matrix if it is already
685  // available:
686 
687  // first set up the column number
688  // array for the rows to be stored
689  // on the local processor. have one
690  // dummy entry at the end to make
691  // sure petsc doesn't read past the
692  // end
693  std::vector<PetscInt>
694 
695  rowstart_in_window (local_row_end - local_row_start + 1, 0),
696  colnums_in_window;
697  {
698  size_type n_cols = 0;
699  for (size_type i=local_row_start; i<local_row_end; ++i)
700  {
701  const size_type row_length = sparsity_pattern.row_length(i);
702  rowstart_in_window[i+1-local_row_start]
703  = rowstart_in_window[i-local_row_start] + row_length;
704  n_cols += row_length;
705  }
706  colnums_in_window.resize (n_cols+1, -1);
707  }
708 
709  // now copy over the information
710  // from the sparsity pattern.
711  {
712  PetscInt *ptr = & colnums_in_window[0];
713  for (size_type i=local_row_start; i<local_row_end; ++i)
714  for (typename SparsityPatternType::iterator p=sparsity_pattern.begin(i);
715  p != sparsity_pattern.end(i); ++p, ++ptr)
716  *ptr = p->column();
717  }
718 
719 
720  // then call the petsc function
721  // that summarily allocates these
722  // entries:
723  MatMPIAIJSetPreallocationCSR (matrix,
724  &rowstart_in_window[0],
725  &colnums_in_window[0],
726  0);
727 
728 #if DEAL_II_PETSC_VERSION_LT(2,3,3)
729  // this is only needed for old
730  // PETSc versions:
731 
732  // for some reason, it does not
733  // seem to be possible to force
734  // actual allocation of actual
735  // entries by using the last
736  // arguments to the call above. if
737  // we don't initialize the entries
738  // like in the following loop, then
739  // the program is unbearably slow
740  // because elements are allocated
741  // and accessed in random order,
742  // which is not what PETSc likes
743  //
744  // note that we actually have to
745  // set the entries to something
746  // non-zero! do the allocation one
747  // row at a time
748  {
749  const std::vector<PetscScalar>
750  values (sparsity_pattern.max_entries_per_row(),
751  1.);
752 
753  for (size_type i=local_row_start; i<local_row_end; ++i)
754  {
755  PetscInt petsc_i = i;
756  MatSetValues (matrix, 1, &petsc_i,
757  sparsity_pattern.row_length(i),
758  &colnums_in_window[rowstart_in_window[i-local_row_start]],
759  &values[0], INSERT_VALUES);
760  }
761  }
762 
763  compress (VectorOperation::insert);
764 
765  // set the dummy entries set above
766  // back to zero
767  *this = 0;
768 #endif // version <=2.3.3
769 
770 
771  // Tell PETSc that we are not
772  // planning on adding new entries
773  // to the matrix. Generate errors
774  // in debug mode.
775  int ierr;
776 #if DEAL_II_PETSC_VERSION_LT(3,0,0)
777 #ifdef DEBUG
778  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_LOCATION_ERR);
779  AssertThrow (ierr == 0, ExcPETScError(ierr));
780 #else
781  ierr = MatSetOption (matrix, MAT_NO_NEW_NONZERO_LOCATIONS);
782  AssertThrow (ierr == 0, ExcPETScError(ierr));
783 #endif
784 #else
785 #ifdef DEBUG
786  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);
787  AssertThrow (ierr == 0, ExcPETScError(ierr));
788 #else
789  ierr = MatSetOption (matrix, MAT_NEW_NONZERO_LOCATIONS, PETSC_FALSE);
790  AssertThrow (ierr == 0, ExcPETScError(ierr));
791 #endif
792 #endif
793 
794  // Tell PETSc to keep the
795  // SparsityPattern entries even if
796  // we delete a row with
797  // clear_rows() which calls
798  // MatZeroRows(). Otherwise one can
799  // not write into that row
800  // afterwards.
801 #if DEAL_II_PETSC_VERSION_LT(3,0,0)
802  ierr = MatSetOption (matrix, MAT_KEEP_ZEROED_ROWS);
803  AssertThrow (ierr == 0, ExcPETScError(ierr));
804 #elif DEAL_II_PETSC_VERSION_LT(3,1,0)
805  ierr = MatSetOption (matrix, MAT_KEEP_ZEROED_ROWS, PETSC_TRUE);
806  AssertThrow (ierr == 0, ExcPETScError(ierr));
807 #else
808  ierr = MatSetOption (matrix, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE);
809  AssertThrow (ierr == 0, ExcPETScError(ierr));
810 #endif
811 
812  }
813  }
814 
815  // explicit instantiations
816  //
817  template
818  SparseMatrix::SparseMatrix (const MPI_Comm &,
819  const SparsityPattern &,
820  const std::vector<size_type> &,
821  const std::vector<size_type> &,
822  const unsigned int,
823  const bool);
824  template
825  SparseMatrix::SparseMatrix (const MPI_Comm &,
826  const DynamicSparsityPattern &,
827  const std::vector<size_type> &,
828  const std::vector<size_type> &,
829  const unsigned int,
830  const bool);
831 
832  template void
833  SparseMatrix::reinit (const MPI_Comm &,
834  const SparsityPattern &,
835  const std::vector<size_type> &,
836  const std::vector<size_type> &,
837  const unsigned int,
838  const bool);
839  template void
840  SparseMatrix::reinit (const MPI_Comm &,
841  const DynamicSparsityPattern &,
842  const std::vector<size_type> &,
843  const std::vector<size_type> &,
844  const unsigned int,
845  const bool);
846 
847  template void
849  reinit (const IndexSet &,
850  const IndexSet &,
851  const DynamicSparsityPattern &,
852  const MPI_Comm &);
853 
854  template void
856  const std::vector<size_type> &,
857  const std::vector<size_type> &,
858  const unsigned int ,
859  const bool);
860  template void
862  const std::vector<size_type> &,
863  const std::vector<size_type> &,
864  const unsigned int ,
865  const bool);
866 
867  template void
869  do_reinit (const IndexSet &,
870  const IndexSet &,
871  const DynamicSparsityPattern &);
872 
873 
874  PetscScalar
876  {
877  Vector tmp (v);
878  vmult (tmp, v);
879  // note, that v*tmp returns sum_i conjugate(v)_i * tmp_i
880  return v*tmp;
881  }
882 
883  PetscScalar
885  const Vector &v) const
886  {
887  Vector tmp (v);
888  vmult (tmp, v);
889  // note, that v*tmp returns sum_i conjugate(v)_i * tmp_i
890  return u*tmp;
891  }
892 
893  }
894 }
895 
896 
897 DEAL_II_NAMESPACE_CLOSE
898 
899 #endif // DEAL_II_WITH_PETSC
void copy_from(const SparseMatrix &other)
size_type nth_index_in_set(const unsigned int local_index) const
Definition: index_set.h:1432
void vmult(VectorBase &dst, const VectorBase &src) const
::ExceptionBase & ExcMessage(std::string arg1)
void do_reinit(const size_type m, const size_type n, const size_type local_rows, const size_type local_columns, const size_type n_nonzero_per_row, const bool is_symmetric=false, const size_type n_offdiag_nonzero_per_row=0)
size_type row_length(const size_type row) const
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:89
PetscBool is_symmetric(const double tolerance=1.e-12)
size_type size() const
Definition: index_set.h:1247
void compress(const VectorOperation::values operation)
SparseMatrix & operator=(const value_type d)
PetscScalar matrix_scalar_product(const Vector &u, const Vector &v) const
T sum(const T &t, const MPI_Comm &mpi_communicator)
Definition: mpi.h:611
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:294
MatrixBase & operator=(const value_type d)
types::global_dof_index size_type
void reinit(const MPI_Comm &communicator, const size_type m, const size_type n, const size_type local_rows, const size_type local_columns, const size_type n_nonzero_per_row, const bool is_symmetric=false, const size_type n_offdiag_nonzero_per_row=0)
bool is_contiguous() const
Definition: index_set.h:1370
PetscScalar matrix_norm_square(const Vector &v) const
size_type n_elements() const
Definition: index_set.h:1380