Reference documentation for deal.II version 9.1.0-pre
trilinos_sparsity_pattern.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2018 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/lac/trilinos_index_access.h>
17 #include <deal.II/lac/trilinos_sparsity_pattern.h>
18 
19 #ifdef DEAL_II_WITH_TRILINOS
20 
21 # include <deal.II/base/mpi.h>
22 # include <deal.II/base/utilities.h>
23 
24 # include <deal.II/lac/dynamic_sparsity_pattern.h>
25 # include <deal.II/lac/sparsity_pattern.h>
26 # include <deal.II/lac/trilinos_index_access.h>
27 
28 # include <Epetra_Export.h>
29 
30 DEAL_II_NAMESPACE_OPEN
31 
32 namespace TrilinosWrappers
33 {
34  namespace SparsityPatternIterators
35  {
36  void
38  {
39  // if we are asked to visit the past-the-end line, then simply
40  // release all our caches and go on with life
41  if (this->a_row == sparsity_pattern->n_rows())
42  {
43  colnum_cache.reset();
44  return;
45  }
46 
47  // otherwise first flush Trilinos caches if necessary
50 
51  colnum_cache = std::make_shared<std::vector<size_type>>(
53 
54  if (colnum_cache->size() > 0)
55  {
56  // get a representation of the present row
57  int ncols;
58  const int ierr = sparsity_pattern->graph->ExtractGlobalRowCopy(
59  (TrilinosWrappers::types::int_type)this->a_row,
60  colnum_cache->size(),
61  ncols,
62  (TrilinosWrappers::types::int_type *)&(*colnum_cache)[0]);
63  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
64  AssertThrow(static_cast<std::vector<size_type>::size_type>(ncols) ==
65  colnum_cache->size(),
67  }
68  }
69  } // namespace SparsityPatternIterators
70 
71 
72  // The constructor is actually the
73  // only point where we have to check
74  // whether we build a serial or a
75  // parallel Trilinos matrix.
76  // Actually, it does not even matter
77  // how many threads there are, but
78  // only if we use an MPI compiler or
79  // a standard compiler. So, even one
80  // thread on a configuration with
81  // MPI will still get a parallel
82  // interface.
84  {
85  column_space_map =
86  std_cxx14::make_unique<Epetra_Map>(TrilinosWrappers::types::int_type(0),
87  TrilinosWrappers::types::int_type(0),
89  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(View,
90  *column_space_map,
91  *column_space_map,
92  0);
93  graph->FillComplete();
94  }
95 
96 
97  SparsityPattern::SparsityPattern(const Epetra_Map &input_map,
98  const size_type n_entries_per_row)
99  {
100  reinit(input_map, input_map, n_entries_per_row);
101  }
102 
103 
104 
106  const Epetra_Map & input_map,
107  const std::vector<size_type> &n_entries_per_row)
108  {
109  reinit(input_map, input_map, n_entries_per_row);
110  }
111 
112 
113 
114  SparsityPattern::SparsityPattern(const Epetra_Map &input_row_map,
115  const Epetra_Map &input_col_map,
116  const size_type n_entries_per_row)
117  {
118  reinit(input_row_map, input_col_map, n_entries_per_row);
119  }
120 
121 
122 
124  const Epetra_Map & input_row_map,
125  const Epetra_Map & input_col_map,
126  const std::vector<size_type> &n_entries_per_row)
127  {
128  reinit(input_row_map, input_col_map, n_entries_per_row);
129  }
130 
131 
132 
134  const size_type n,
135  const size_type n_entries_per_row)
136  {
137  reinit(m, n, n_entries_per_row);
138  }
139 
140 
141 
143  const size_type m,
144  const size_type n,
145  const std::vector<size_type> &n_entries_per_row)
146  {
147  reinit(m, n, n_entries_per_row);
148  }
149 
150 
151 
153  : Subscriptor(std::move(other))
154  , column_space_map(std::move(other.column_space_map))
155  , graph(std::move(other.graph))
156  , nonlocal_graph(std::move(other.nonlocal_graph))
157  {}
158 
159 
160 
161  // Copy function only works if the
162  // sparsity pattern is empty.
164  : Subscriptor()
165  , column_space_map(new Epetra_Map(TrilinosWrappers::types::int_type(0),
166  TrilinosWrappers::types::int_type(0),
167  Utilities::Trilinos::comm_self()))
168  , graph(
169  new Epetra_FECrsGraph(View, *column_space_map, *column_space_map, 0))
170  {
171  (void)input_sparsity;
172  Assert(input_sparsity.n_rows() == 0,
173  ExcMessage(
174  "Copy constructor only works for empty sparsity patterns."));
175  }
176 
177 
178 
179  SparsityPattern::SparsityPattern(const IndexSet &parallel_partitioning,
180  const MPI_Comm &communicator,
181  const size_type n_entries_per_row)
182  {
183  reinit(parallel_partitioning,
184  parallel_partitioning,
185  communicator,
186  n_entries_per_row);
187  }
188 
189 
190 
192  const IndexSet & parallel_partitioning,
193  const MPI_Comm & communicator,
194  const std::vector<size_type> &n_entries_per_row)
195  {
196  reinit(parallel_partitioning,
197  parallel_partitioning,
198  communicator,
199  n_entries_per_row);
200  }
201 
202 
203 
204  SparsityPattern::SparsityPattern(const IndexSet &row_parallel_partitioning,
205  const IndexSet &col_parallel_partitioning,
206  const MPI_Comm &communicator,
207  const size_type n_entries_per_row)
208  {
209  reinit(row_parallel_partitioning,
210  col_parallel_partitioning,
211  communicator,
212  n_entries_per_row);
213  }
214 
215 
216 
218  const IndexSet & row_parallel_partitioning,
219  const IndexSet & col_parallel_partitioning,
220  const MPI_Comm & communicator,
221  const std::vector<size_type> &n_entries_per_row)
222  {
223  reinit(row_parallel_partitioning,
224  col_parallel_partitioning,
225  communicator,
226  n_entries_per_row);
227  }
228 
229 
230 
231  SparsityPattern::SparsityPattern(const IndexSet &row_parallel_partitioning,
232  const IndexSet &col_parallel_partitioning,
233  const IndexSet &writable_rows,
234  const MPI_Comm &communicator,
235  const size_type n_max_entries_per_row)
236  {
237  reinit(row_parallel_partitioning,
238  col_parallel_partitioning,
239  writable_rows,
240  communicator,
241  n_max_entries_per_row);
242  }
243 
244 
245 
246  void
248  const size_type n,
249  const size_type n_entries_per_row)
250  {
251  reinit(complete_index_set(m),
252  complete_index_set(n),
253  MPI_COMM_SELF,
254  n_entries_per_row);
255  }
256 
257 
258 
259  void
261  const size_type n,
262  const std::vector<size_type> &n_entries_per_row)
263  {
264  reinit(complete_index_set(m),
265  complete_index_set(n),
266  MPI_COMM_SELF,
267  n_entries_per_row);
268  }
269 
270 
271 
272  namespace
273  {
275 
276  void
277  reinit_sp(const Epetra_Map & row_map,
278  const Epetra_Map & col_map,
279  const size_type n_entries_per_row,
280  std::unique_ptr<Epetra_Map> & column_space_map,
281  std::unique_ptr<Epetra_FECrsGraph> &graph,
282  std::unique_ptr<Epetra_CrsGraph> & nonlocal_graph)
283  {
284  Assert(row_map.IsOneToOne(),
285  ExcMessage("Row map must be 1-to-1, i.e., no overlap between "
286  "the maps of different processors."));
287  Assert(col_map.IsOneToOne(),
288  ExcMessage("Column map must be 1-to-1, i.e., no overlap between "
289  "the maps of different processors."));
290 
291  nonlocal_graph.reset();
292  graph.reset();
293  column_space_map = std_cxx14::make_unique<Epetra_Map>(col_map);
294 
295  // for more than one processor, need to specify only row map first and
296  // let the matrix entries decide about the column map (which says which
297  // columns are present in the matrix, not to be confused with the
298  // col_map that tells how the domain dofs of the matrix will be
299  // distributed). for only one processor, we can directly assign the
300  // columns as well. If we use a recent Trilinos version, we can also
301  // require building a non-local graph which gives us thread-safe
302  // initialization.
303  if (row_map.Comm().NumProc() > 1)
304  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(
305  Copy, row_map, n_entries_per_row, false
306  // TODO: Check which new Trilinos version supports this...
307  // Remember to change tests/trilinos/assemble_matrix_parallel_07, too.
308  //#if DEAL_II_TRILINOS_VERSION_GTE(11,14,0)
309  // , true
310  //#endif
311  );
312  else
313  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(
314  Copy, row_map, col_map, n_entries_per_row, false);
315  }
316 
317 
318 
319  void
320  reinit_sp(const Epetra_Map & row_map,
321  const Epetra_Map & col_map,
322  const std::vector<size_type> & n_entries_per_row,
323  std::unique_ptr<Epetra_Map> & column_space_map,
324  std::unique_ptr<Epetra_FECrsGraph> &graph,
325  std::unique_ptr<Epetra_CrsGraph> & nonlocal_graph)
326  {
327  Assert(row_map.IsOneToOne(),
328  ExcMessage("Row map must be 1-to-1, i.e., no overlap between "
329  "the maps of different processors."));
330  Assert(col_map.IsOneToOne(),
331  ExcMessage("Column map must be 1-to-1, i.e., no overlap between "
332  "the maps of different processors."));
333 
334  // release memory before reallocation
335  nonlocal_graph.reset();
336  graph.reset();
337  AssertDimension(n_entries_per_row.size(),
338  static_cast<size_type>(
340 
341  column_space_map = std_cxx14::make_unique<Epetra_Map>(col_map);
342  std::vector<int> local_entries_per_row(
345  for (unsigned int i = 0; i < local_entries_per_row.size(); ++i)
346  local_entries_per_row[i] =
347  n_entries_per_row[TrilinosWrappers::min_my_gid(row_map) + i];
348 
349  if (row_map.Comm().NumProc() > 1)
350  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(
351  Copy, row_map, local_entries_per_row.data(), false
352  // TODO: Check which new Trilinos version supports this...
353  // Remember to change tests/trilinos/assemble_matrix_parallel_07, too.
354  //#if DEAL_II_TRILINOS_VERSION_GTE(11,14,0)
355  // , true
356  //#endif
357  );
358  else
359  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(
360  Copy, row_map, col_map, local_entries_per_row.data(), false);
361  }
362 
363 
364 
365  template <typename SparsityPatternType>
366  void
367  reinit_sp(const Epetra_Map & row_map,
368  const Epetra_Map & col_map,
369  const SparsityPatternType & sp,
370  const bool exchange_data,
371  std::unique_ptr<Epetra_Map> & column_space_map,
372  std::unique_ptr<Epetra_FECrsGraph> &graph,
373  std::unique_ptr<Epetra_CrsGraph> & nonlocal_graph)
374  {
375  nonlocal_graph.reset();
376  graph.reset();
377 
378  AssertDimension(sp.n_rows(),
379  static_cast<size_type>(
381  AssertDimension(sp.n_cols(),
382  static_cast<size_type>(
384 
385  column_space_map = std_cxx14::make_unique<Epetra_Map>(col_map);
386 
387  Assert(row_map.LinearMap() == true,
388  ExcMessage(
389  "This function only works if the row map is contiguous."));
390 
391  const size_type first_row = TrilinosWrappers::min_my_gid(row_map),
392  last_row = TrilinosWrappers::max_my_gid(row_map) + 1;
393  std::vector<int> n_entries_per_row(last_row - first_row);
394 
395  // Trilinos wants the row length as an int this is hopefully never going
396  // to be a problem.
397  for (size_type row = first_row; row < last_row; ++row)
398  n_entries_per_row[row - first_row] =
399  static_cast<int>(sp.row_length(row));
400 
401  if (row_map.Comm().NumProc() > 1)
402  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(
403  Copy, row_map, n_entries_per_row.data(), false);
404  else
405  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(
406  Copy, row_map, col_map, n_entries_per_row.data(), false);
407 
408  AssertDimension(sp.n_rows(),
409  static_cast<size_type>(n_global_rows(*graph)));
410 
411  std::vector<TrilinosWrappers::types::int_type> row_indices;
412 
413  // Include possibility to exchange data since DynamicSparsityPattern is
414  // able to do so
415  if (exchange_data == false)
416  for (size_type row = first_row; row < last_row; ++row)
417  {
418  const TrilinosWrappers::types::int_type row_length =
419  sp.row_length(row);
420  if (row_length == 0)
421  continue;
422 
423  row_indices.resize(row_length, -1);
424  {
425  typename SparsityPatternType::iterator p = sp.begin(row);
426  // avoid incrementing p over the end of the current row because
427  // it is slow for DynamicSparsityPattern in parallel
428  for (int col = 0; col < row_length;)
429  {
430  row_indices[col++] = p->column();
431  if (col < row_length)
432  ++p;
433  }
434  }
435  graph->Epetra_CrsGraph::InsertGlobalIndices(row,
436  row_length,
437  row_indices.data());
438  }
439  else
440  for (size_type row = 0; row < sp.n_rows(); ++row)
441  {
442  const TrilinosWrappers::types::int_type row_length =
443  sp.row_length(row);
444  if (row_length == 0)
445  continue;
446 
447  row_indices.resize(row_length, -1);
448  {
449  typename SparsityPatternType::iterator p = sp.begin(row);
450  // avoid incrementing p over the end of the current row because
451  // it is slow for DynamicSparsityPattern in parallel
452  for (int col = 0; col < row_length;)
453  {
454  row_indices[col++] = p->column();
455  if (col < row_length)
456  ++p;
457  }
458  }
459  graph->InsertGlobalIndices(
460  1,
461  reinterpret_cast<TrilinosWrappers::types::int_type *>(&row),
462  row_length,
463  row_indices.data());
464  }
465 
466  int ierr = graph->GlobalAssemble(*column_space_map,
467  static_cast<const Epetra_Map &>(
468  graph->RangeMap()),
469  true);
470  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
471 
472  ierr = graph->OptimizeStorage();
473  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
474  }
475  } // namespace
476 
477 
478  void
479  SparsityPattern::reinit(const Epetra_Map &input_map,
480  const size_type n_entries_per_row)
481  {
482  reinit_sp(input_map,
483  input_map,
484  n_entries_per_row,
486  graph,
488  }
489 
490 
491 
492  void
493  SparsityPattern::reinit(const Epetra_Map &input_row_map,
494  const Epetra_Map &input_col_map,
495  const size_type n_entries_per_row)
496  {
497  reinit_sp(input_row_map,
498  input_col_map,
499  n_entries_per_row,
501  graph,
503  }
504 
505 
506 
507  void
508  SparsityPattern::reinit(const Epetra_Map & input_map,
509  const std::vector<size_type> &n_entries_per_row)
510  {
511  reinit_sp(input_map,
512  input_map,
513  n_entries_per_row,
515  graph,
517  }
518 
519 
520 
521  void
522  SparsityPattern::reinit(const Epetra_Map & input_row_map,
523  const Epetra_Map & input_col_map,
524  const std::vector<size_type> &n_entries_per_row)
525  {
526  reinit_sp(input_row_map,
527  input_col_map,
528  n_entries_per_row,
530  graph,
532  }
533 
534 
535 
536  void
537  SparsityPattern::reinit(const IndexSet &parallel_partitioning,
538  const MPI_Comm &communicator,
539  const size_type n_entries_per_row)
540  {
541  Epetra_Map map =
542  parallel_partitioning.make_trilinos_map(communicator, false);
543  reinit_sp(
544  map, map, n_entries_per_row, column_space_map, graph, nonlocal_graph);
545  }
546 
547 
548 
549  void
550  SparsityPattern::reinit(const IndexSet & parallel_partitioning,
551  const MPI_Comm & communicator,
552  const std::vector<size_type> &n_entries_per_row)
553  {
554  Epetra_Map map =
555  parallel_partitioning.make_trilinos_map(communicator, false);
556  reinit_sp(
557  map, map, n_entries_per_row, column_space_map, graph, nonlocal_graph);
558  }
559 
560 
561 
562  void
563  SparsityPattern::reinit(const IndexSet &row_parallel_partitioning,
564  const IndexSet &col_parallel_partitioning,
565  const MPI_Comm &communicator,
566  const size_type n_entries_per_row)
567  {
568  Epetra_Map row_map =
569  row_parallel_partitioning.make_trilinos_map(communicator, false);
570  Epetra_Map col_map =
571  col_parallel_partitioning.make_trilinos_map(communicator, false);
572  reinit_sp(row_map,
573  col_map,
574  n_entries_per_row,
576  graph,
578  }
579 
580 
581 
582  void
583  SparsityPattern::reinit(const IndexSet &row_parallel_partitioning,
584  const IndexSet &col_parallel_partitioning,
585  const MPI_Comm &communicator,
586  const std::vector<size_type> &n_entries_per_row)
587  {
588  Epetra_Map row_map =
589  row_parallel_partitioning.make_trilinos_map(communicator, false);
590  Epetra_Map col_map =
591  col_parallel_partitioning.make_trilinos_map(communicator, false);
592  reinit_sp(row_map,
593  col_map,
594  n_entries_per_row,
596  graph,
598  }
599 
600 
601 
602  void
603  SparsityPattern::reinit(const IndexSet &row_parallel_partitioning,
604  const IndexSet &col_parallel_partitioning,
605  const IndexSet &writable_rows,
606  const MPI_Comm &communicator,
607  const size_type n_entries_per_row)
608  {
609  Epetra_Map row_map =
610  row_parallel_partitioning.make_trilinos_map(communicator, false);
611  Epetra_Map col_map =
612  col_parallel_partitioning.make_trilinos_map(communicator, false);
613  reinit_sp(row_map,
614  col_map,
615  n_entries_per_row,
617  graph,
619 
620  IndexSet nonlocal_partitioner = writable_rows;
621  AssertDimension(nonlocal_partitioner.size(),
622  row_parallel_partitioning.size());
623 # ifdef DEBUG
624  {
625  IndexSet tmp = writable_rows & row_parallel_partitioning;
626  Assert(tmp == row_parallel_partitioning,
627  ExcMessage(
628  "The set of writable rows passed to this method does not "
629  "contain the locally owned rows, which is not allowed."));
630  }
631 # endif
632  nonlocal_partitioner.subtract_set(row_parallel_partitioning);
633  if (Utilities::MPI::n_mpi_processes(communicator) > 1)
634  {
635  Epetra_Map nonlocal_map =
636  nonlocal_partitioner.make_trilinos_map(communicator, true);
638  std_cxx14::make_unique<Epetra_CrsGraph>(Copy, nonlocal_map, 0);
639  }
640  else
641  Assert(nonlocal_partitioner.n_elements() == 0, ExcInternalError());
642  }
643 
644 
645 
646  template <typename SparsityPatternType>
647  void
649  const IndexSet & row_parallel_partitioning,
650  const IndexSet & col_parallel_partitioning,
651  const SparsityPatternType &nontrilinos_sparsity_pattern,
652  const MPI_Comm & communicator,
653  const bool exchange_data)
654  {
655  Epetra_Map row_map =
656  row_parallel_partitioning.make_trilinos_map(communicator, false);
657  Epetra_Map col_map =
658  col_parallel_partitioning.make_trilinos_map(communicator, false);
659  reinit_sp(row_map,
660  col_map,
661  nontrilinos_sparsity_pattern,
662  exchange_data,
664  graph,
666  }
667 
668 
669 
670  template <typename SparsityPatternType>
671  void
673  const IndexSet & parallel_partitioning,
674  const SparsityPatternType &nontrilinos_sparsity_pattern,
675  const MPI_Comm & communicator,
676  const bool exchange_data)
677  {
678  Epetra_Map map =
679  parallel_partitioning.make_trilinos_map(communicator, false);
680  reinit_sp(map,
681  map,
682  nontrilinos_sparsity_pattern,
683  exchange_data,
685  graph,
687  }
688 
689 
690 
691  template <typename SparsityPatternType>
692  void
693  SparsityPattern::reinit(const Epetra_Map & input_map,
694  const SparsityPatternType &sp,
695  const bool exchange_data)
696  {
697  reinit_sp(input_map,
698  input_map,
699  sp,
700  exchange_data,
702  graph,
704  }
705 
706 
707 
708  template <typename SparsityPatternType>
709  void
710  SparsityPattern::reinit(const Epetra_Map & input_row_map,
711  const Epetra_Map & input_col_map,
712  const SparsityPatternType &sp,
713  const bool exchange_data)
714  {
715  reinit_sp(input_row_map,
716  input_col_map,
717  sp,
718  exchange_data,
720  graph,
722  compress();
723  }
724 
725 
726 
729  {
730  Assert(false, ExcNotImplemented());
731  return *this;
732  }
733 
734 
735 
736  void
738  {
739  column_space_map = std_cxx14::make_unique<Epetra_Map>(*sp.column_space_map);
740  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(*sp.graph);
741 
742  if (sp.nonlocal_graph.get() != nullptr)
744  std_cxx14::make_unique<Epetra_CrsGraph>(*sp.nonlocal_graph);
745  else
746  nonlocal_graph.reset();
747  }
748 
749 
750 
751  template <typename SparsityPatternType>
752  void
753  SparsityPattern::copy_from(const SparsityPatternType &sp)
754  {
755  const Epetra_Map rows(TrilinosWrappers::types::int_type(sp.n_rows()),
756  0,
758  const Epetra_Map columns(TrilinosWrappers::types::int_type(sp.n_cols()),
759  0,
761 
762  reinit_sp(
763  rows, columns, sp, false, column_space_map, graph, nonlocal_graph);
764  }
765 
766 
767 
768  void
770  {
771  // When we clear the matrix, reset
772  // the pointer and generate an
773  // empty sparsity pattern.
775  std_cxx14::make_unique<Epetra_Map>(TrilinosWrappers::types::int_type(0),
776  TrilinosWrappers::types::int_type(0),
778  graph = std_cxx14::make_unique<Epetra_FECrsGraph>(View,
781  0);
782  graph->FillComplete();
783 
784  nonlocal_graph.reset();
785  }
786 
787 
788 
789  void
791  {
792  int ierr;
793  Assert(column_space_map.get() != nullptr, ExcInternalError());
794  if (nonlocal_graph.get() != nullptr)
795  {
796  if (nonlocal_graph->IndicesAreGlobal() == false &&
797  nonlocal_graph->RowMap().NumMyElements() > 0)
798  {
799  // insert dummy element
800  TrilinosWrappers::types::int_type row =
801  nonlocal_graph->RowMap().MyGID(
802  static_cast<TrilinosWrappers::types::int_type>(0));
803  nonlocal_graph->InsertGlobalIndices(row, 1, &row);
804  }
805  Assert(nonlocal_graph->RowMap().NumMyElements() == 0 ||
806  nonlocal_graph->IndicesAreGlobal() == true,
807  ExcInternalError());
808  nonlocal_graph->FillComplete(*column_space_map,
809  static_cast<const Epetra_Map &>(
810  graph->RangeMap()));
811  nonlocal_graph->OptimizeStorage();
812  Epetra_Export exporter(nonlocal_graph->RowMap(), graph->RowMap());
813  ierr = graph->Export(*nonlocal_graph, exporter, Add);
814  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
815  ierr = graph->FillComplete(*column_space_map,
816  static_cast<const Epetra_Map &>(
817  graph->RangeMap()));
818  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
819  }
820  else
821  {
822  ierr = graph->GlobalAssemble(*column_space_map,
823  static_cast<const Epetra_Map &>(
824  graph->RangeMap()),
825  true);
826  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
827  }
828 
829  ierr = graph->OptimizeStorage();
830  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
831  }
832 
833 
834 
835  bool
837  {
838  return graph->RowMap().LID(
839  static_cast<TrilinosWrappers::types::int_type>(i)) != -1;
840  }
841 
842 
843 
844  bool
846  {
847  if (!row_is_stored_locally(i))
848  {
849  return false;
850  }
851  else
852  {
853  // Extract local indices in
854  // the matrix.
855  int trilinos_i =
856  graph->LRID(static_cast<TrilinosWrappers::types::int_type>(i)),
857  trilinos_j =
858  graph->LCID(static_cast<TrilinosWrappers::types::int_type>(j));
859 
860  // Check whether the matrix
861  // already is transformed to
862  // local indices.
863  if (graph->Filled() == false)
864  {
865  int nnz_present = graph->NumGlobalIndices(i);
866  int nnz_extracted;
867  TrilinosWrappers::types::int_type *col_indices;
868 
869  // Generate the view and make
870  // sure that we have not generated
871  // an error.
872  // TODO: trilinos_i is the local row index -> it is an int but
873  // ExtractGlobalRowView requires trilinos_i to be the global row
874  // index and thus it should be a long long int
875  int ierr = graph->ExtractGlobalRowView(
876  static_cast<TrilinosWrappers::types::int_type>(trilinos_i),
877  nnz_extracted,
878  col_indices);
879  (void)ierr;
880  Assert(ierr == 0, ExcTrilinosError(ierr));
881  Assert(nnz_present == nnz_extracted,
882  ExcDimensionMismatch(nnz_present, nnz_extracted));
883 
884  // Search the index
885  TrilinosWrappers::types::int_type *el_find =
886  std::find(col_indices, col_indices + nnz_present, trilinos_j);
887 
888  TrilinosWrappers::types::int_type local_col_index =
889  (TrilinosWrappers::types::int_type)(el_find - col_indices);
890 
891  if (local_col_index == nnz_present)
892  return false;
893  }
894  else
895  {
896  // Prepare pointers for extraction
897  // of a view of the row.
898  int nnz_present = graph->NumGlobalIndices(
899  static_cast<TrilinosWrappers::types::int_type>(i));
900  int nnz_extracted;
901  int *col_indices;
902 
903  // Generate the view and make
904  // sure that we have not generated
905  // an error.
906  int ierr =
907  graph->ExtractMyRowView(trilinos_i, nnz_extracted, col_indices);
908  (void)ierr;
909  Assert(ierr == 0, ExcTrilinosError(ierr));
910 
911  Assert(nnz_present == nnz_extracted,
912  ExcDimensionMismatch(nnz_present, nnz_extracted));
913 
914  // Search the index
915  int *el_find = std::find(col_indices,
916  col_indices + nnz_present,
917  static_cast<int>(trilinos_j));
918 
919  int local_col_index = (int)(el_find - col_indices);
920 
921  if (local_col_index == nnz_present)
922  return false;
923  }
924  }
925 
926  return true;
927  }
928 
929 
930 
933  {
934  size_type local_b = 0;
935  TrilinosWrappers::types::int_type global_b = 0;
936  for (int i = 0; i < (int)local_size(); ++i)
937  {
938  int *indices;
939  int num_entries;
940  graph->ExtractMyRowView(i, num_entries, indices);
941  for (unsigned int j = 0; j < (unsigned int)num_entries; ++j)
942  {
943  if (static_cast<size_type>(
944  std::abs(static_cast<TrilinosWrappers::types::int_type>(
945  i - indices[j]))) > local_b)
946  local_b = std::abs(
947  static_cast<TrilinosWrappers::types::int_type>(i - indices[j]));
948  }
949  }
950  graph->Comm().MaxAll((TrilinosWrappers::types::int_type *)&local_b,
951  &global_b,
952  1);
953  return static_cast<size_type>(global_b);
954  }
955 
956 
957 
960  {
961  const TrilinosWrappers::types::int_type n_rows = n_global_rows(*graph);
962  return n_rows;
963  }
964 
965 
966 
969  {
970  TrilinosWrappers::types::int_type n_cols;
971  if (graph->Filled() == true)
972  n_cols = n_global_cols(*graph);
973  else
975 
976  return n_cols;
977  }
978 
979 
980 
981  unsigned int
983  {
984  int n_rows = graph->NumMyRows();
985 
986  return n_rows;
987  }
988 
989 
990 
991  std::pair<SparsityPattern::size_type, SparsityPattern::size_type>
993  {
995  begin = TrilinosWrappers::min_my_gid(graph->RowMap());
996  end = TrilinosWrappers::max_my_gid(graph->RowMap()) + 1;
997 
998  return std::make_pair(begin, end);
999  }
1000 
1001 
1002 
1005  {
1006  TrilinosWrappers::types::int_type nnz = n_global_entries(*graph);
1007 
1008  return static_cast<size_type>(nnz);
1009  }
1010 
1011 
1012 
1013  unsigned int
1015  {
1016  int nnz = graph->MaxNumIndices();
1017 
1018  return static_cast<unsigned int>(nnz);
1019  }
1020 
1021 
1022 
1025  {
1026  Assert(row < n_rows(), ExcInternalError());
1027 
1028  // Get a representation of the where the present row is located on
1029  // the current processor
1030  TrilinosWrappers::types::int_type local_row =
1031  graph->LRID(static_cast<TrilinosWrappers::types::int_type>(row));
1032 
1033  // On the processor who owns this row, we'll have a non-negative
1034  // value for `local_row` and can ask for the length of the row.
1035  if (local_row >= 0)
1036  return graph->NumMyIndices(local_row);
1037  else
1038  return static_cast<size_type>(-1);
1039  }
1040 
1041 
1042 
1043  const Epetra_Map &
1045  {
1046  return static_cast<const Epetra_Map &>(graph->DomainMap());
1047  }
1048 
1049 
1050 
1051  const Epetra_Map &
1053  {
1054  return static_cast<const Epetra_Map &>(graph->RangeMap());
1055  }
1056 
1057 
1058 
1059  const Epetra_Map &
1061  {
1062  return static_cast<const Epetra_Map &>(graph->RowMap());
1063  }
1064 
1065 
1066 
1067  const Epetra_Map &
1069  {
1070  return static_cast<const Epetra_Map &>(graph->ColMap());
1071  }
1072 
1073 
1074 
1075  const Epetra_Comm &
1077  {
1078  return graph->RangeMap().Comm();
1079  }
1080 
1081 
1082 
1083  MPI_Comm
1085  {
1086 # ifdef DEAL_II_WITH_MPI
1087 
1088  const Epetra_MpiComm *mpi_comm =
1089  dynamic_cast<const Epetra_MpiComm *>(&graph->RangeMap().Comm());
1090  Assert(mpi_comm != nullptr, ExcInternalError());
1091  return mpi_comm->Comm();
1092 # else
1093 
1094  return MPI_COMM_SELF;
1095 
1096 # endif
1097  }
1098 
1099 
1100 
1101  void
1103  {
1104  Assert(false, ExcNotImplemented());
1105  }
1106 
1107 
1108 
1109  // As of now, no particularly neat
1110  // output is generated in case of
1111  // multiple processors.
1112  void
1113  SparsityPattern::print(std::ostream &out,
1114  const bool write_extended_trilinos_info) const
1115  {
1116  if (write_extended_trilinos_info)
1117  out << *graph;
1118  else
1119  {
1120  int *indices;
1121  int num_entries;
1122 
1123  for (int i = 0; i < graph->NumMyRows(); ++i)
1124  {
1125  graph->ExtractMyRowView(i, num_entries, indices);
1126  for (int j = 0; j < num_entries; ++j)
1127  out << "(" << TrilinosWrappers::global_index(graph->RowMap(), i)
1128  << ","
1129  << TrilinosWrappers::global_index(graph->ColMap(), indices[j])
1130  << ") " << std::endl;
1131  }
1132  }
1133 
1134  AssertThrow(out, ExcIO());
1135  }
1136 
1137 
1138 
1139  void
1140  SparsityPattern::print_gnuplot(std::ostream &out) const
1141  {
1142  Assert(graph->Filled() == true, ExcInternalError());
1143  for (::types::global_dof_index row = 0; row < local_size(); ++row)
1144  {
1145  int *indices;
1146  int num_entries;
1147  graph->ExtractMyRowView(row, num_entries, indices);
1148 
1149  Assert(num_entries >= 0, ExcInternalError());
1150  // avoid sign comparison warning
1151  const ::types::global_dof_index num_entries_ = num_entries;
1152  for (::types::global_dof_index j = 0; j < num_entries_; ++j)
1153  // while matrix entries are usually
1154  // written (i,j), with i vertical and
1155  // j horizontal, gnuplot output is
1156  // x-y, that is we have to exchange
1157  // the order of output
1158  out << static_cast<int>(
1159  TrilinosWrappers::global_index(graph->ColMap(), indices[j]))
1160  << " "
1161  << -static_cast<int>(
1162  TrilinosWrappers::global_index(graph->RowMap(), row))
1163  << std::endl;
1164  }
1165 
1166  AssertThrow(out, ExcIO());
1167  }
1168 
1169  // TODO: Implement!
1170  std::size_t
1172  {
1173  Assert(false, ExcNotImplemented());
1174  return 0;
1175  }
1176 
1177 
1178  // explicit instantiations
1179  //
1180  template void
1181  SparsityPattern::copy_from(const ::SparsityPattern &);
1182  template void
1183  SparsityPattern::copy_from(const ::DynamicSparsityPattern &);
1184 
1185 
1186  template void
1187  SparsityPattern::reinit(const Epetra_Map &,
1188  const ::SparsityPattern &,
1189  bool);
1190  template void
1191  SparsityPattern::reinit(const Epetra_Map &,
1192  const ::DynamicSparsityPattern &,
1193  bool);
1194 
1195  template void
1196  SparsityPattern::reinit(const Epetra_Map &,
1197  const Epetra_Map &,
1198  const ::SparsityPattern &,
1199  bool);
1200  template void
1201  SparsityPattern::reinit(const Epetra_Map &,
1202  const Epetra_Map &,
1203  const ::DynamicSparsityPattern &,
1204  bool);
1205 
1206 
1207  template void
1209  const ::SparsityPattern &,
1210  const MPI_Comm &,
1211  bool);
1212  template void
1214  const ::DynamicSparsityPattern &,
1215  const MPI_Comm &,
1216  bool);
1217 
1218 
1219  template void
1221  const IndexSet &,
1222  const ::SparsityPattern &,
1223  const MPI_Comm &,
1224  bool);
1225  template void
1227  const IndexSet &,
1228  const ::DynamicSparsityPattern &,
1229  const MPI_Comm &,
1230  bool);
1231 
1232 } // namespace TrilinosWrappers
1233 
1234 DEAL_II_NAMESPACE_CLOSE
1235 
1236 #endif // DEAL_II_WITH_TRILINOS
static::ExceptionBase & ExcTrilinosError(int arg1)
void print_gnuplot(std::ostream &out) const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
const_iterator end() const
std::shared_ptr< const std::vector< size_type > > colnum_cache
static::ExceptionBase & ExcIO()
size_type row_length(const size_type row) const
size_type n_elements() const
Definition: index_set.h:1743
TrilinosWrappers::types::int_type min_my_gid(const Epetra_BlockMap &map)
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
size_type size() const
Definition: index_set.h:1611
const Epetra_Comm & comm_self()
Definition: utilities.cc:779
std::unique_ptr< Epetra_CrsGraph > nonlocal_graph
unsigned long long int global_dof_index
Definition: types.h:72
static::ExceptionBase & ExcTrilinosError(int arg1)
static::ExceptionBase & ExcMessage(std::string arg1)
const_iterator begin() const
TrilinosWrappers::types::int_type n_global_rows(const Epetra_CrsGraph &graph)
Definition: types.h:31
std::unique_ptr< Epetra_Map > column_space_map
const Epetra_Map & domain_partitioner() const
void subtract_set(const IndexSet &other)
Definition: index_set.cc:265
#define Assert(cond, exc)
Definition: exceptions.h:1227
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
TrilinosWrappers::types::int_type n_global_cols(const Epetra_CrsGraph &graph)
void print(std::ostream &out, const bool write_extended_trilinos_info=false) const
TrilinosWrappers::types::int_type n_global_entries(const Epetra_CrsGraph &graph)
bool row_is_stored_locally(const size_type i) const
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:523
const Epetra_Comm & trilinos_communicator() const
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:69
TrilinosWrappers::types::int_type n_global_elements(const Epetra_BlockMap &map)
SparsityPattern & operator=(const SparsityPattern &input_sparsity_pattern)
Definition: cuda.h:32
void copy_from(const SparsityPattern &input_sparsity_pattern)
bool exists(const size_type i, const size_type j) const
TrilinosWrappers::types::int_type max_my_gid(const Epetra_BlockMap &map)
const Epetra_Map & range_partitioner() const
static::ExceptionBase & ExcNotImplemented()
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
std::pair< size_type, size_type > local_range() const
void reinit(const size_type m, const size_type n, const size_type n_entries_per_row=0)
std::unique_ptr< Epetra_FECrsGraph > graph
static::ExceptionBase & ExcInternalError()