Reference documentation for deal.II version 9.1.0-pre
trilinos_sparse_matrix.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_sparse_matrix.h>
18 
19 #ifdef DEAL_II_WITH_TRILINOS
20 
21 # include <deal.II/base/utilities.h>
22 
23 # include <deal.II/lac/dynamic_sparsity_pattern.h>
24 # include <deal.II/lac/la_parallel_vector.h>
25 # include <deal.II/lac/sparse_matrix.h>
26 # include <deal.II/lac/sparsity_pattern.h>
27 # include <deal.II/lac/sparsity_tools.h>
28 # include <deal.II/lac/trilinos_index_access.h>
29 # include <deal.II/lac/trilinos_precondition.h>
30 # include <deal.II/lac/trilinos_sparsity_pattern.h>
31 
32 # include <boost/container/small_vector.hpp>
33 
34 # include <Epetra_Export.h>
35 # include <Teuchos_RCP.hpp>
36 # include <ml_epetra_utils.h>
37 # include <ml_struct.h>
38 
39 # include <memory>
40 
41 DEAL_II_NAMESPACE_OPEN
42 
43 namespace TrilinosWrappers
44 {
45  namespace internal
46  {
47  template <typename VectorType>
48  double *
49  begin(VectorType &V)
50  {
51  return V.begin();
52  }
53 
54  template <typename VectorType>
55  const double *
56  begin(const VectorType &V)
57  {
58  return V.begin();
59  }
60 
61  template <typename VectorType>
62  double *
63  end(VectorType &V)
64  {
65  return V.end();
66  }
67 
68  template <typename VectorType>
69  const double *
70  end(const VectorType &V)
71  {
72  return V.end();
73  }
74 
75 # ifdef DEAL_II_WITH_MPI
76  template <>
77  double *
79  {
80  return V.trilinos_vector()[0];
81  }
82 
83  template <>
84  const double *
86  {
87  return V.trilinos_vector()[0];
88  }
89 
90  template <>
91  double *
93  {
94  return V.trilinos_vector()[0] + V.trilinos_vector().MyLength();
95  }
96 
97  template <>
98  const double *
100  {
101  return V.trilinos_vector()[0] + V.trilinos_vector().MyLength();
102  }
103 # endif
104  } // namespace internal
105 
106 
107  namespace SparseMatrixIterators
108  {
109  void
110  AccessorBase::visit_present_row()
111  {
112  // if we are asked to visit the past-the-end line, then simply
113  // release all our caches and go on with life.
114  //
115  // do the same if the row we're supposed to visit is not locally
116  // owned. this is simply going to make non-locally owned rows
117  // look like they're empty
118  if ((this->a_row == matrix->m()) ||
119  (matrix->in_local_range(this->a_row) == false))
120  {
121  colnum_cache.reset();
122  value_cache.reset();
123 
124  return;
125  }
126 
127  // get a representation of the present row
128  int ncols;
129  TrilinosWrappers::types::int_type colnums = matrix->n();
130  if (value_cache.get() == nullptr)
131  {
132  value_cache =
133  std::make_shared<std::vector<TrilinosScalar>>(matrix->n());
134  colnum_cache = std::make_shared<std::vector<size_type>>(matrix->n());
135  }
136  else
137  {
138  value_cache->resize(matrix->n());
139  colnum_cache->resize(matrix->n());
140  }
141 
142  int ierr = matrix->trilinos_matrix().ExtractGlobalRowCopy(
143  (TrilinosWrappers::types::int_type)this->a_row,
144  colnums,
145  ncols,
146  &((*value_cache)[0]),
147  reinterpret_cast<TrilinosWrappers::types::int_type *>(
148  &((*colnum_cache)[0])));
149  value_cache->resize(ncols);
150  colnum_cache->resize(ncols);
151  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
152 
153  // copy it into our caches if the
154  // line isn't empty. if it is, then
155  // we've done something wrong, since
156  // we shouldn't have initialized an
157  // iterator for an empty line (what
158  // would it point to?)
159  }
160  } // namespace SparseMatrixIterators
161 
162 
163  // The constructor is actually the
164  // only point where we have to check
165  // whether we build a serial or a
166  // parallel Trilinos matrix.
167  // Actually, it does not even matter
168  // how many threads there are, but
169  // only if we use an MPI compiler or
170  // a standard compiler. So, even one
171  // thread on a configuration with
172  // MPI will still get a parallel
173  // interface.
175  : column_space_map(new Epetra_Map(0, 0, Utilities::Trilinos::comm_self()))
176  , matrix(
177  new Epetra_FECrsMatrix(View, *column_space_map, *column_space_map, 0))
178  , last_action(Zero)
179  , compressed(true)
180  {
181  matrix->FillComplete();
182  }
183 
184 
185 
186  SparseMatrix::SparseMatrix(const Epetra_Map &input_map,
187  const size_type n_max_entries_per_row)
188  : column_space_map(new Epetra_Map(input_map))
189  , matrix(new Epetra_FECrsMatrix(Copy,
191  TrilinosWrappers::types::int_type(
192  n_max_entries_per_row),
193  false))
194  , last_action(Zero)
195  , compressed(false)
196  {}
197 
198 
199 
200  SparseMatrix::SparseMatrix(const Epetra_Map & input_map,
201  const std::vector<unsigned int> &n_entries_per_row)
202  : column_space_map(new Epetra_Map(input_map))
203  , matrix(new Epetra_FECrsMatrix(Copy,
205  (int *)const_cast<unsigned int *>(
206  &(n_entries_per_row[0])),
207  false))
208  , last_action(Zero)
209  , compressed(false)
210  {}
211 
212 
213 
214  SparseMatrix::SparseMatrix(const Epetra_Map &input_row_map,
215  const Epetra_Map &input_col_map,
216  const size_type n_max_entries_per_row)
217  : column_space_map(new Epetra_Map(input_col_map))
218  , matrix(new Epetra_FECrsMatrix(Copy,
219  input_row_map,
220  TrilinosWrappers::types::int_type(
221  n_max_entries_per_row),
222  false))
223  , last_action(Zero)
224  , compressed(false)
225  {}
226 
227 
228 
229  SparseMatrix::SparseMatrix(const Epetra_Map & input_row_map,
230  const Epetra_Map & input_col_map,
231  const std::vector<unsigned int> &n_entries_per_row)
232  : column_space_map(new Epetra_Map(input_col_map))
233  , matrix(new Epetra_FECrsMatrix(Copy,
234  input_row_map,
235  (int *)const_cast<unsigned int *>(
236  &(n_entries_per_row[0])),
237  false))
238  , last_action(Zero)
239  , compressed(false)
240  {}
241 
242 
243 
245  const size_type n,
246  const unsigned int n_max_entries_per_row)
248  new Epetra_Map(static_cast<TrilinosWrappers::types::int_type>(n),
249  0,
250  Utilities::Trilinos::comm_self()))
251  ,
252 
253  // on one processor only, we know how the
254  // columns of the matrix will be
255  // distributed (everything on one
256  // processor), so we can hand in this
257  // information to the constructor. we
258  // can't do so in parallel, where the
259  // information from columns is only
260  // available when entries have been added
261  matrix(new Epetra_FECrsMatrix(
262  Copy,
263  Epetra_Map(static_cast<TrilinosWrappers::types::int_type>(m),
264  0,
265  Utilities::Trilinos::comm_self()),
267  n_max_entries_per_row,
268  false))
269  , last_action(Zero)
270  , compressed(false)
271  {}
272 
273 
274 
276  const size_type n,
277  const std::vector<unsigned int> &n_entries_per_row)
279  new Epetra_Map(static_cast<TrilinosWrappers::types::int_type>(n),
280  0,
281  Utilities::Trilinos::comm_self()))
282  , matrix(new Epetra_FECrsMatrix(
283  Copy,
284  Epetra_Map(static_cast<TrilinosWrappers::types::int_type>(m),
285  0,
286  Utilities::Trilinos::comm_self()),
288  (int *)const_cast<unsigned int *>(&(n_entries_per_row[0])),
289  false))
290  , last_action(Zero)
291  , compressed(false)
292  {}
293 
294 
295 
296  SparseMatrix::SparseMatrix(const IndexSet & parallel_partitioning,
297  const MPI_Comm & communicator,
298  const unsigned int n_max_entries_per_row)
299  : column_space_map(new Epetra_Map(
300  parallel_partitioning.make_trilinos_map(communicator, false)))
301  , matrix(new Epetra_FECrsMatrix(Copy,
303  n_max_entries_per_row,
304  false))
305  , last_action(Zero)
306  , compressed(false)
307  {}
308 
309 
310 
311  SparseMatrix::SparseMatrix(const IndexSet &parallel_partitioning,
312  const MPI_Comm &communicator,
313  const std::vector<unsigned int> &n_entries_per_row)
314  : column_space_map(new Epetra_Map(
315  parallel_partitioning.make_trilinos_map(communicator, false)))
316  , matrix(new Epetra_FECrsMatrix(Copy,
318  (int *)const_cast<unsigned int *>(
319  &(n_entries_per_row[0])),
320  false))
321  , last_action(Zero)
322  , compressed(false)
323  {}
324 
325 
326 
327  SparseMatrix::SparseMatrix(const IndexSet &row_parallel_partitioning,
328  const IndexSet &col_parallel_partitioning,
329  const MPI_Comm &communicator,
330  const size_type n_max_entries_per_row)
331  : column_space_map(new Epetra_Map(
332  col_parallel_partitioning.make_trilinos_map(communicator, false)))
333  , matrix(new Epetra_FECrsMatrix(
334  Copy,
335  row_parallel_partitioning.make_trilinos_map(communicator, false),
336  n_max_entries_per_row,
337  false))
338  , last_action(Zero)
339  , compressed(false)
340  {}
341 
342 
343 
344  SparseMatrix::SparseMatrix(const IndexSet &row_parallel_partitioning,
345  const IndexSet &col_parallel_partitioning,
346  const MPI_Comm &communicator,
347  const std::vector<unsigned int> &n_entries_per_row)
348  : column_space_map(new Epetra_Map(
349  col_parallel_partitioning.make_trilinos_map(communicator, false)))
350  , matrix(new Epetra_FECrsMatrix(
351  Copy,
352  row_parallel_partitioning.make_trilinos_map(communicator, false),
353  (int *)const_cast<unsigned int *>(&(n_entries_per_row[0])),
354  false))
355  , last_action(Zero)
356  , compressed(false)
357  {}
358 
359 
360 
362  : column_space_map(new Epetra_Map(sparsity_pattern.domain_partitioner()))
363  , matrix(
364  new Epetra_FECrsMatrix(Copy,
365  sparsity_pattern.trilinos_sparsity_pattern(),
366  false))
367  , last_action(Zero)
368  , compressed(true)
369  {
370  Assert(sparsity_pattern.trilinos_sparsity_pattern().Filled() == true,
371  ExcMessage(
372  "The Trilinos sparsity pattern has not been compressed."));
374  }
375 
376 
377 
379  : column_space_map(std::move(other.column_space_map))
380  , matrix(std::move(other.matrix))
381  , nonlocal_matrix(std::move(other.nonlocal_matrix))
383  , last_action(other.last_action)
384  , compressed(other.compressed)
385  {
386  other.last_action = Zero;
387  other.compressed = false;
388  }
389 
390 
391 
392  void
394  {
395  if (this == &rhs)
396  return;
397 
398  nonlocal_matrix.reset();
399  nonlocal_matrix_exporter.reset();
400 
401  // check whether we need to update the whole matrix layout (we have
402  // different maps or if we detect a row where the columns of the two
403  // matrices do not match)
404  bool needs_deep_copy =
405  !matrix->RowMap().SameAs(rhs.matrix->RowMap()) ||
406  !matrix->ColMap().SameAs(rhs.matrix->ColMap()) ||
407  !matrix->DomainMap().SameAs(rhs.matrix->DomainMap()) ||
409  if (!needs_deep_copy)
410  {
411  // Try to copy all the rows of the matrix one by one. In case of error
412  // (i.e., the column indices are different), we need to abort and blow
413  // away the matrix.
414  for (const auto row : locally_owned_range_indices())
415  {
416  const int row_local = matrix->RowMap().LID(
417  static_cast<TrilinosWrappers::types::int_type>(row));
418  Assert((row_local >= 0), ExcAccessToNonlocalRow(row));
419 
420  int n_entries, rhs_n_entries;
421  TrilinosScalar *value_ptr, *rhs_value_ptr;
422  int * index_ptr, *rhs_index_ptr;
423  int ierr = rhs.matrix->ExtractMyRowView(row_local,
424  rhs_n_entries,
425  rhs_value_ptr,
426  rhs_index_ptr);
427  (void)ierr;
428  Assert(ierr == 0, ExcTrilinosError(ierr));
429 
430  ierr = matrix->ExtractMyRowView(row_local,
431  n_entries,
432  value_ptr,
433  index_ptr);
434  Assert(ierr == 0, ExcTrilinosError(ierr));
435 
436  if (n_entries != rhs_n_entries ||
437  std::memcmp(static_cast<void *>(index_ptr),
438  static_cast<void *>(rhs_index_ptr),
439  sizeof(int) * n_entries) != 0)
440  {
441  needs_deep_copy = true;
442  break;
443  }
444 
445  for (int i = 0; i < n_entries; ++i)
446  value_ptr[i] = rhs_value_ptr[i];
447  }
448  }
449 
450  if (needs_deep_copy)
451  {
453  std_cxx14::make_unique<Epetra_Map>(rhs.domain_partitioner());
454 
455  // release memory before reallocation
456  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(*rhs.matrix);
457 
458  matrix->FillComplete(*column_space_map, matrix->RowMap());
459  }
460 
461  if (rhs.nonlocal_matrix.get() != nullptr)
463  std_cxx14::make_unique<Epetra_CrsMatrix>(Copy,
464  rhs.nonlocal_matrix->Graph());
465  }
466 
467 
468 
469  namespace
470  {
472 
473  template <typename SparsityPatternType>
474  void
475  reinit_matrix(const Epetra_Map & input_row_map,
476  const Epetra_Map & input_col_map,
477  const SparsityPatternType & sparsity_pattern,
478  const bool exchange_data,
479  std::unique_ptr<Epetra_Map> & column_space_map,
480  std::unique_ptr<Epetra_FECrsMatrix> &matrix,
481  std::unique_ptr<Epetra_CrsMatrix> & nonlocal_matrix,
482  std::unique_ptr<Epetra_Export> & nonlocal_matrix_exporter)
483  {
484  // release memory before reallocation
485  matrix.reset();
486  nonlocal_matrix.reset();
487  nonlocal_matrix_exporter.reset();
488 
489  if (input_row_map.Comm().MyPID() == 0)
490  {
491  AssertDimension(sparsity_pattern.n_rows(),
492  static_cast<size_type>(
494  input_row_map)));
495  AssertDimension(sparsity_pattern.n_cols(),
496  static_cast<size_type>(
498  input_col_map)));
499  }
500 
501  column_space_map = std_cxx14::make_unique<Epetra_Map>(input_col_map);
502 
503  // if we want to exchange data, build a usual Trilinos sparsity pattern
504  // and let that handle the exchange. otherwise, manually create a
505  // CrsGraph, which consumes considerably less memory because it can set
506  // correct number of indices right from the start
507  if (exchange_data)
508  {
509  SparsityPattern trilinos_sparsity;
510  trilinos_sparsity.reinit(input_row_map,
511  input_col_map,
512  sparsity_pattern,
513  exchange_data);
514  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(
515  Copy, trilinos_sparsity.trilinos_sparsity_pattern(), false);
516 
517  return;
518  }
519 
520  const size_type first_row = TrilinosWrappers::min_my_gid(input_row_map),
521  last_row =
522  TrilinosWrappers::max_my_gid(input_row_map) + 1;
523  std::vector<int> n_entries_per_row(last_row - first_row);
524 
525  for (size_type row = first_row; row < last_row; ++row)
526  n_entries_per_row[row - first_row] = sparsity_pattern.row_length(row);
527 
528  // The deal.II notation of a Sparsity pattern corresponds to the Epetra
529  // concept of a Graph. Hence, we generate a graph by copying the
530  // sparsity pattern into it, and then build up the matrix from the
531  // graph. This is considerable faster than directly filling elements
532  // into the matrix. Moreover, it consumes less memory, since the
533  // internal reordering is done on ints only, and we can leave the
534  // doubles aside.
535 
536  // for more than one processor, need to specify only row map first and
537  // let the matrix entries decide about the column map (which says which
538  // columns are present in the matrix, not to be confused with the
539  // col_map that tells how the domain dofs of the matrix will be
540  // distributed). for only one processor, we can directly assign the
541  // columns as well. Compare this with bug # 4123 in the Sandia Bugzilla.
542  std::unique_ptr<Epetra_CrsGraph> graph;
543  if (input_row_map.Comm().NumProc() > 1)
544  graph = std_cxx14::make_unique<Epetra_CrsGraph>(
545  Copy, input_row_map, n_entries_per_row.data(), true);
546  else
547  graph = std_cxx14::make_unique<Epetra_CrsGraph>(
548  Copy, input_row_map, input_col_map, n_entries_per_row.data(), true);
549 
550  // This functions assumes that the sparsity pattern sits on all
551  // processors (completely). The parallel version uses an Epetra graph
552  // that is already distributed.
553 
554  // now insert the indices
555  std::vector<TrilinosWrappers::types::int_type> row_indices;
556 
557  for (size_type row = first_row; row < last_row; ++row)
558  {
559  const int row_length = sparsity_pattern.row_length(row);
560  if (row_length == 0)
561  continue;
562 
563  row_indices.resize(row_length, -1);
564  {
565  typename SparsityPatternType::iterator p =
566  sparsity_pattern.begin(row);
567  for (size_type col = 0; p != sparsity_pattern.end(row); ++p, ++col)
568  row_indices[col] = p->column();
569  }
570  graph->Epetra_CrsGraph::InsertGlobalIndices(row,
571  row_length,
572  row_indices.data());
573  }
574 
575  // Eventually, optimize the graph structure (sort indices, make memory
576  // contiguous, etc). note that the documentation of the function indeed
577  // states that we first need to provide the column (domain) map and then
578  // the row (range) map
579  graph->FillComplete(input_col_map, input_row_map);
580  graph->OptimizeStorage();
581 
582  // check whether we got the number of columns right.
583  AssertDimension(sparsity_pattern.n_cols(),
584  static_cast<size_type>(
586  (void)n_global_cols;
587 
588  // And now finally generate the matrix.
589  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(Copy, *graph, false);
590  }
591 
592 
593 
594  // for the non-local graph, we need to circumvent the problem that some
595  // processors will not add into the non-local graph at all: We do not want
596  // to insert dummy elements on >5000 processors because that gets very
597  // slow. Thus, we set a flag in Epetra_CrsGraph that sets the correct
598  // flag. Since it is protected, we need to expose this information by
599  // deriving a class from Epetra_CrsGraph for the purpose of creating the
600  // data structure
601  class Epetra_CrsGraphMod : public Epetra_CrsGraph
602  {
603  public:
604  Epetra_CrsGraphMod(const Epetra_Map &row_map,
605  const int * n_entries_per_row)
606  : Epetra_CrsGraph(Copy, row_map, n_entries_per_row, true){};
607 
608  void
609  SetIndicesAreGlobal()
610  {
611  this->Epetra_CrsGraph::SetIndicesAreGlobal(true);
612  }
613  };
614 
615 
616  // specialization for DynamicSparsityPattern which can provide us with
617  // more information about the non-locally owned rows
618  template <>
619  void
620  reinit_matrix(const Epetra_Map & input_row_map,
621  const Epetra_Map & input_col_map,
622  const DynamicSparsityPattern & sparsity_pattern,
623  const bool exchange_data,
624  std::unique_ptr<Epetra_Map> & column_space_map,
625  std::unique_ptr<Epetra_FECrsMatrix> &matrix,
626  std::unique_ptr<Epetra_CrsMatrix> & nonlocal_matrix,
627  std::unique_ptr<Epetra_Export> & nonlocal_matrix_exporter)
628  {
629  matrix.reset();
630  nonlocal_matrix.reset();
631  nonlocal_matrix_exporter.reset();
632 
633  AssertDimension(sparsity_pattern.n_rows(),
634  static_cast<size_type>(
635  TrilinosWrappers::n_global_elements(input_row_map)));
636  AssertDimension(sparsity_pattern.n_cols(),
637  static_cast<size_type>(
638  TrilinosWrappers::n_global_elements(input_col_map)));
639 
640  column_space_map = std_cxx14::make_unique<Epetra_Map>(input_col_map);
641 
642  IndexSet relevant_rows(sparsity_pattern.row_index_set());
643  // serial case
644  if (relevant_rows.size() == 0)
645  {
646  relevant_rows.set_size(
647  TrilinosWrappers::n_global_elements(input_row_map));
648  relevant_rows.add_range(
649  0, TrilinosWrappers::n_global_elements(input_row_map));
650  }
651  relevant_rows.compress();
652  Assert(relevant_rows.n_elements() >=
653  static_cast<unsigned int>(input_row_map.NumMyElements()),
654  ExcMessage(
655  "Locally relevant rows of sparsity pattern must contain "
656  "all locally owned rows"));
657 
658  // check whether the relevant rows correspond to exactly the same map as
659  // the owned rows. In that case, do not create the nonlocal graph and
660  // fill the columns by demand
661  bool have_ghost_rows = false;
662  {
663  std::vector<::types::global_dof_index> indices;
664  relevant_rows.fill_index_vector(indices);
665  Epetra_Map relevant_map(
666  TrilinosWrappers::types::int_type(-1),
667  TrilinosWrappers::types::int_type(relevant_rows.n_elements()),
668  (indices.empty() ?
669  nullptr :
670  reinterpret_cast<TrilinosWrappers::types::int_type *>(
671  indices.data())),
672  0,
673  input_row_map.Comm());
674  if (relevant_map.SameAs(input_row_map))
675  have_ghost_rows = false;
676  else
677  have_ghost_rows = true;
678  }
679 
680  const unsigned int n_rows = relevant_rows.n_elements();
681  std::vector<TrilinosWrappers::types::int_type> ghost_rows;
682  std::vector<int> n_entries_per_row(input_row_map.NumMyElements());
683  std::vector<int> n_entries_per_ghost_row;
684  for (unsigned int i = 0, own = 0; i < n_rows; ++i)
685  {
686  const TrilinosWrappers::types::int_type global_row =
687  relevant_rows.nth_index_in_set(i);
688  if (input_row_map.MyGID(global_row))
689  n_entries_per_row[own++] = sparsity_pattern.row_length(global_row);
690  else if (sparsity_pattern.row_length(global_row) > 0)
691  {
692  ghost_rows.push_back(global_row);
693  n_entries_per_ghost_row.push_back(
694  sparsity_pattern.row_length(global_row));
695  }
696  }
697 
698  Epetra_Map off_processor_map(-1,
699  ghost_rows.size(),
700  (ghost_rows.size() > 0) ?
701  (ghost_rows.data()) :
702  nullptr,
703  0,
704  input_row_map.Comm());
705 
706  std::unique_ptr<Epetra_CrsGraph> graph;
707  std::unique_ptr<Epetra_CrsGraphMod> nonlocal_graph;
708  if (input_row_map.Comm().NumProc() > 1)
709  {
710  graph = std_cxx14::make_unique<Epetra_CrsGraph>(
711  Copy,
712  input_row_map,
713  (n_entries_per_row.size() > 0) ? (n_entries_per_row.data()) :
714  nullptr,
715  exchange_data ? false : true);
716  if (have_ghost_rows == true)
717  nonlocal_graph = std_cxx14::make_unique<Epetra_CrsGraphMod>(
718  off_processor_map, n_entries_per_ghost_row.data());
719  }
720  else
721  graph = std_cxx14::make_unique<Epetra_CrsGraph>(
722  Copy,
723  input_row_map,
724  input_col_map,
725  (n_entries_per_row.size() > 0) ? (n_entries_per_row.data()) : nullptr,
726  true);
727 
728  // now insert the indices, select between the right matrix
729  std::vector<TrilinosWrappers::types::int_type> row_indices;
730 
731  for (unsigned int i = 0; i < n_rows; ++i)
732  {
733  const TrilinosWrappers::types::int_type global_row =
734  relevant_rows.nth_index_in_set(i);
735  const int row_length = sparsity_pattern.row_length(global_row);
736  if (row_length == 0)
737  continue;
738 
739  row_indices.resize(row_length, -1);
740  for (int col = 0; col < row_length; ++col)
741  row_indices[col] = sparsity_pattern.column_number(global_row, col);
742 
743  if (input_row_map.MyGID(global_row))
744  graph->InsertGlobalIndices(global_row,
745  row_length,
746  row_indices.data());
747  else
748  {
749  Assert(nonlocal_graph.get() != nullptr, ExcInternalError());
750  nonlocal_graph->InsertGlobalIndices(global_row,
751  row_length,
752  row_indices.data());
753  }
754  }
755 
756  // finalize nonlocal graph and create nonlocal matrix
757  if (nonlocal_graph.get() != nullptr)
758  {
759  // must make sure the IndicesAreGlobal flag is set on all processors
760  // because some processors might not call InsertGlobalIndices (and
761  // we do not want to insert dummy indices on all processors for
762  // large-scale simulations due to the bad impact on performance)
763  nonlocal_graph->SetIndicesAreGlobal();
764  Assert(nonlocal_graph->IndicesAreGlobal() == true,
765  ExcInternalError());
766  nonlocal_graph->FillComplete(input_col_map, input_row_map);
767  nonlocal_graph->OptimizeStorage();
768 
769  // insert data from nonlocal graph into the final sparsity pattern
770  if (exchange_data)
771  {
772  Epetra_Export exporter(nonlocal_graph->RowMap(), input_row_map);
773  int ierr = graph->Export(*nonlocal_graph, exporter, Add);
774  (void)ierr;
775  Assert(ierr == 0, ExcTrilinosError(ierr));
776  }
777 
778  nonlocal_matrix =
779  std_cxx14::make_unique<Epetra_CrsMatrix>(Copy, *nonlocal_graph);
780  }
781 
782  graph->FillComplete(input_col_map, input_row_map);
783  graph->OptimizeStorage();
784 
785  AssertDimension(sparsity_pattern.n_cols(),
786  static_cast<size_type>(
788 
789  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(Copy, *graph, false);
790  }
791  } // namespace
792 
793 
794 
795  template <typename SparsityPatternType>
796  void
797  SparseMatrix::reinit(const SparsityPatternType &sparsity_pattern)
798  {
799  const Epetra_Map rows(static_cast<TrilinosWrappers::types::int_type>(
800  sparsity_pattern.n_rows()),
801  0,
803  const Epetra_Map columns(static_cast<TrilinosWrappers::types::int_type>(
804  sparsity_pattern.n_cols()),
805  0,
807 
808  reinit_matrix(rows,
809  columns,
810  sparsity_pattern,
811  false,
813  matrix,
816  }
817 
818 
819 
820  template <typename SparsityPatternType>
821  void
822  SparseMatrix::reinit(const Epetra_Map & input_map,
823  const SparsityPatternType &sparsity_pattern,
824  const bool exchange_data)
825  {
826  reinit_matrix(input_map,
827  input_map,
828  sparsity_pattern,
829  exchange_data,
831  matrix,
834  }
835 
836 
837 
838  template <typename SparsityPatternType>
839  inline void
840  SparseMatrix::reinit(const IndexSet & row_parallel_partitioning,
841  const IndexSet & col_parallel_partitioning,
842  const SparsityPatternType &sparsity_pattern,
843  const MPI_Comm & communicator,
844  const bool exchange_data)
845  {
846  Epetra_Map row_map =
847  row_parallel_partitioning.make_trilinos_map(communicator, false);
848  Epetra_Map col_map =
849  col_parallel_partitioning.make_trilinos_map(communicator, false);
850  reinit_matrix(row_map,
851  col_map,
852  sparsity_pattern,
853  exchange_data,
855  matrix,
858 
859  // In the end, the matrix needs to be compressed in order to be really
860  // ready.
861  last_action = Zero;
863  }
864 
865 
866 
867  template <typename SparsityPatternType>
868  inline void
869  SparseMatrix::reinit(const Epetra_Map & row_map,
870  const Epetra_Map & col_map,
871  const SparsityPatternType &sparsity_pattern,
872  const bool exchange_data)
873  {
874  reinit_matrix(row_map,
875  col_map,
876  sparsity_pattern,
877  exchange_data,
879  matrix,
882 
883  // In the end, the matrix needs to be compressed in order to be really
884  // ready.
885  last_action = Zero;
887  }
888 
889 
890 
891  void
892  SparseMatrix::reinit(const SparsityPattern &sparsity_pattern)
893  {
894  matrix.reset();
895  nonlocal_matrix_exporter.reset();
896 
897  // reinit with a (parallel) Trilinos sparsity pattern.
899  std_cxx14::make_unique<Epetra_Map>(sparsity_pattern.domain_partitioner());
900  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(
901  Copy, sparsity_pattern.trilinos_sparsity_pattern(), false);
902 
903  if (sparsity_pattern.nonlocal_graph.get() != nullptr)
904  nonlocal_matrix = std_cxx14::make_unique<Epetra_CrsMatrix>(
905  Copy, *sparsity_pattern.nonlocal_graph);
906  else
907  nonlocal_matrix.reset();
908 
909  last_action = Zero;
911  }
912 
913 
914 
915  void
916  SparseMatrix::reinit(const SparseMatrix &sparse_matrix)
917  {
918  if (this == &sparse_matrix)
919  return;
920 
922  std_cxx14::make_unique<Epetra_Map>(sparse_matrix.domain_partitioner());
923  matrix.reset();
924  nonlocal_matrix_exporter.reset();
925  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(
926  Copy, sparse_matrix.trilinos_sparsity_pattern(), false);
927 
928  if (sparse_matrix.nonlocal_matrix != nullptr)
929  nonlocal_matrix = std_cxx14::make_unique<Epetra_CrsMatrix>(
930  Copy, sparse_matrix.nonlocal_matrix->Graph());
931  else
932  nonlocal_matrix.reset();
933 
934  last_action = Zero;
936  }
937 
938 
939 
940  template <typename number>
941  inline void
943  const IndexSet & row_parallel_partitioning,
944  const IndexSet & col_parallel_partitioning,
945  const ::SparseMatrix<number> &dealii_sparse_matrix,
946  const MPI_Comm & communicator,
947  const double drop_tolerance,
948  const bool copy_values,
949  const ::SparsityPattern * use_this_sparsity)
950  {
951  if (copy_values == false)
952  {
953  // in case we do not copy values, just
954  // call the other function.
955  if (use_this_sparsity == nullptr)
956  reinit(row_parallel_partitioning,
957  col_parallel_partitioning,
958  dealii_sparse_matrix.get_sparsity_pattern(),
959  communicator,
960  false);
961  else
962  reinit(row_parallel_partitioning,
963  col_parallel_partitioning,
964  *use_this_sparsity,
965  communicator,
966  false);
967  return;
968  }
969 
970  const size_type n_rows = dealii_sparse_matrix.m();
971 
972  AssertDimension(row_parallel_partitioning.size(), n_rows);
973  AssertDimension(col_parallel_partitioning.size(), dealii_sparse_matrix.n());
974 
975  const ::SparsityPattern &sparsity_pattern =
976  (use_this_sparsity != nullptr) ?
977  *use_this_sparsity :
978  dealii_sparse_matrix.get_sparsity_pattern();
979 
980  if (matrix.get() == nullptr || m() != n_rows ||
981  n_nonzero_elements() != sparsity_pattern.n_nonzero_elements())
982  {
983  reinit(row_parallel_partitioning,
984  col_parallel_partitioning,
985  sparsity_pattern,
986  communicator,
987  false);
988  }
989 
990  // fill the values. the same as above: go through all rows of the
991  // matrix, and then all columns. since the sparsity patterns of the
992  // input matrix and the specified sparsity pattern might be different,
993  // need to go through the row for both these sparsity structures
994  // simultaneously in order to really set the correct values.
995  size_type maximum_row_length = matrix->MaxNumEntries();
996  std::vector<size_type> row_indices(maximum_row_length);
997  std::vector<TrilinosScalar> values(maximum_row_length);
998 
999  for (size_type row = 0; row < n_rows; ++row)
1000  // see if the row is locally stored on this processor
1001  if (row_parallel_partitioning.is_element(row) == true)
1002  {
1003  ::SparsityPattern::iterator select_index =
1004  sparsity_pattern.begin(row);
1005  typename ::SparseMatrix<number>::const_iterator it =
1006  dealii_sparse_matrix.begin(row);
1007  size_type col = 0;
1008  if (sparsity_pattern.n_rows() == sparsity_pattern.n_cols())
1009  {
1010  // optimized diagonal
1011  AssertDimension(it->column(), row);
1012  if (std::fabs(it->value()) > drop_tolerance)
1013  {
1014  values[col] = it->value();
1015  row_indices[col++] = it->column();
1016  }
1017  ++select_index;
1018  ++it;
1019  }
1020 
1021  while (it != dealii_sparse_matrix.end(row) &&
1022  select_index != sparsity_pattern.end(row))
1023  {
1024  while (select_index->column() < it->column() &&
1025  select_index != sparsity_pattern.end(row))
1026  ++select_index;
1027  while (it->column() < select_index->column() &&
1028  it != dealii_sparse_matrix.end(row))
1029  ++it;
1030 
1031  if (it == dealii_sparse_matrix.end(row))
1032  break;
1033  if (std::fabs(it->value()) > drop_tolerance)
1034  {
1035  values[col] = it->value();
1036  row_indices[col++] = it->column();
1037  }
1038  ++select_index;
1039  ++it;
1040  }
1041  set(row,
1042  col,
1043  reinterpret_cast<size_type *>(row_indices.data()),
1044  values.data(),
1045  false);
1046  }
1048  }
1049 
1050 
1051 
1052  template <typename number>
1053  void
1055  const ::SparseMatrix<number> &dealii_sparse_matrix,
1056  const double drop_tolerance,
1057  const bool copy_values,
1058  const ::SparsityPattern * use_this_sparsity)
1059  {
1060  reinit(complete_index_set(dealii_sparse_matrix.m()),
1061  complete_index_set(dealii_sparse_matrix.n()),
1062  dealii_sparse_matrix,
1063  MPI_COMM_SELF,
1064  drop_tolerance,
1065  copy_values,
1066  use_this_sparsity);
1067  }
1068 
1069 
1070 
1071  template <typename number>
1072  void
1074  const Epetra_Map & input_map,
1075  const ::SparseMatrix<number> &dealii_sparse_matrix,
1076  const double drop_tolerance,
1077  const bool copy_values,
1078  const ::SparsityPattern * use_this_sparsity)
1079  {
1080  reinit(IndexSet(input_map),
1081  IndexSet(input_map),
1082  dealii_sparse_matrix,
1083  MPI_COMM_SELF,
1084  drop_tolerance,
1085  copy_values,
1086  use_this_sparsity);
1087  }
1088 
1089 
1090 
1091  template <typename number>
1092  void
1094  const Epetra_Map & input_row_map,
1095  const Epetra_Map & input_col_map,
1096  const ::SparseMatrix<number> &dealii_sparse_matrix,
1097  const double drop_tolerance,
1098  const bool copy_values,
1099  const ::SparsityPattern * use_this_sparsity)
1100  {
1101  reinit(IndexSet(input_row_map),
1102  IndexSet(input_col_map),
1103  dealii_sparse_matrix,
1104  MPI_COMM_SELF,
1105  drop_tolerance,
1106  copy_values,
1107  use_this_sparsity);
1108  }
1109 
1110 
1111 
1112  void
1113  SparseMatrix::reinit(const Epetra_CrsMatrix &input_matrix,
1114  const bool copy_values)
1115  {
1116  Assert(input_matrix.Filled() == true,
1117  ExcMessage("Input CrsMatrix has not called FillComplete()!"));
1118 
1120  std_cxx14::make_unique<Epetra_Map>(input_matrix.DomainMap());
1121 
1122  const Epetra_CrsGraph *graph = &input_matrix.Graph();
1123 
1124  nonlocal_matrix.reset();
1125  nonlocal_matrix_exporter.reset();
1126  matrix.reset();
1127  matrix = std_cxx14::make_unique<Epetra_FECrsMatrix>(Copy, *graph, false);
1128 
1129  matrix->FillComplete(*column_space_map, input_matrix.RangeMap(), true);
1130 
1131  if (copy_values == true)
1132  {
1133  // point to the first data entry in the two
1134  // matrices and copy the content
1135  const TrilinosScalar *in_values = input_matrix[0];
1136  TrilinosScalar * values = (*matrix)[0];
1137  const size_type my_nonzeros = input_matrix.NumMyNonzeros();
1138  std::memcpy(values, in_values, my_nonzeros * sizeof(TrilinosScalar));
1139  }
1140 
1141  last_action = Zero;
1143  }
1144 
1145 
1146 
1147  void
1149  {
1150  Epetra_CombineMode mode = last_action;
1151  if (last_action == Zero)
1152  {
1153  if ((operation == ::VectorOperation::add) ||
1154  (operation == ::VectorOperation::unknown))
1155  mode = Add;
1156  else if (operation == ::VectorOperation::insert)
1157  mode = Insert;
1158  else
1159  Assert(
1160  false,
1161  ExcMessage(
1162  "compress() can only be called with VectorOperation add, insert, or unknown"));
1163  }
1164  else
1165  {
1166  Assert(((last_action == Add) &&
1167  (operation != ::VectorOperation::insert)) ||
1168  ((last_action == Insert) &&
1169  (operation != ::VectorOperation::add)),
1170  ExcMessage("Operation and argument to compress() do not match"));
1171  }
1172 
1173  // flush buffers
1174  int ierr;
1175  if (nonlocal_matrix.get() != nullptr && mode == Add)
1176  {
1177  // do only export in case of an add() operation, otherwise the owning
1178  // processor must have set the correct entry
1179  nonlocal_matrix->FillComplete(*column_space_map, matrix->RowMap());
1180  if (nonlocal_matrix_exporter.get() == nullptr)
1182  std_cxx14::make_unique<Epetra_Export>(nonlocal_matrix->RowMap(),
1183  matrix->RowMap());
1184  ierr =
1186  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1187  ierr = matrix->FillComplete(*column_space_map, matrix->RowMap());
1188  nonlocal_matrix->PutScalar(0);
1189  }
1190  else
1191  ierr =
1192  matrix->GlobalAssemble(*column_space_map, matrix->RowMap(), true, mode);
1193 
1194  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1195 
1196  ierr = matrix->OptimizeStorage();
1197  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1198 
1199  last_action = Zero;
1200 
1201  compressed = true;
1202  }
1203 
1204 
1205 
1206  void
1208  {
1209  // When we clear the matrix, reset
1210  // the pointer and generate an
1211  // empty matrix.
1213  std_cxx14::make_unique<Epetra_Map>(0,
1214  0,
1216  matrix =
1217  std_cxx14::make_unique<Epetra_FECrsMatrix>(View, *column_space_map, 0);
1218  nonlocal_matrix.reset();
1219  nonlocal_matrix_exporter.reset();
1220 
1221  matrix->FillComplete();
1222 
1223  compressed = true;
1224  }
1225 
1226 
1227 
1228  void
1230  const TrilinosScalar new_diag_value)
1231  {
1232  Assert(matrix->Filled() == true, ExcMatrixNotCompressed());
1233 
1234  // Only do this on the rows owned
1235  // locally on this processor.
1236  int local_row =
1237  matrix->LRID(static_cast<TrilinosWrappers::types::int_type>(row));
1238  if (local_row >= 0)
1239  {
1240  TrilinosScalar *values;
1241  int * col_indices;
1242  int num_entries;
1243  const int ierr =
1244  matrix->ExtractMyRowView(local_row, num_entries, values, col_indices);
1245  (void)ierr;
1246 
1247  Assert(ierr == 0, ExcTrilinosError(ierr));
1248 
1249  int *diag_find =
1250  std::find(col_indices, col_indices + num_entries, local_row);
1251  int diag_index = (int)(diag_find - col_indices);
1252 
1253  for (TrilinosWrappers::types::int_type j = 0; j < num_entries; ++j)
1254  if (diag_index != j || new_diag_value == 0)
1255  values[j] = 0.;
1256 
1257  if (diag_find && std::fabs(values[diag_index]) == 0.0 &&
1258  new_diag_value != 0.0)
1259  values[diag_index] = new_diag_value;
1260  }
1261  }
1262 
1263 
1264 
1265  void
1266  SparseMatrix::clear_rows(const std::vector<size_type> &rows,
1267  const TrilinosScalar new_diag_value)
1268  {
1269  for (size_type row = 0; row < rows.size(); ++row)
1270  clear_row(rows[row], new_diag_value);
1271  }
1272 
1273 
1274 
1275  TrilinosScalar
1277  {
1278  // Extract local indices in
1279  // the matrix.
1280  int trilinos_i =
1281  matrix->LRID(static_cast<TrilinosWrappers::types::int_type>(i)),
1282  trilinos_j =
1283  matrix->LCID(static_cast<TrilinosWrappers::types::int_type>(j));
1284  TrilinosScalar value = 0.;
1285 
1286  // If the data is not on the
1287  // present processor, we throw
1288  // an exception. This is one of
1289  // the two tiny differences to
1290  // the el(i,j) call, which does
1291  // not throw any assertions.
1292  if (trilinos_i == -1)
1293  {
1294  Assert(false,
1296  i, j, local_range().first, local_range().second));
1297  }
1298  else
1299  {
1300  // Check whether the matrix has
1301  // already been transformed to local
1302  // indices.
1303  Assert(matrix->Filled(), ExcMatrixNotCompressed());
1304 
1305  // Prepare pointers for extraction
1306  // of a view of the row.
1307  int nnz_present = matrix->NumMyEntries(trilinos_i);
1308  int nnz_extracted;
1309  int * col_indices;
1310  TrilinosScalar *values;
1311 
1312  // Generate the view and make
1313  // sure that we have not generated
1314  // an error.
1315  // TODO Check that col_indices are int and not long long
1316  int ierr = matrix->ExtractMyRowView(trilinos_i,
1317  nnz_extracted,
1318  values,
1319  col_indices);
1320  (void)ierr;
1321  Assert(ierr == 0, ExcTrilinosError(ierr));
1322 
1323  Assert(nnz_present == nnz_extracted,
1324  ExcDimensionMismatch(nnz_present, nnz_extracted));
1325 
1326  // Search the index where we
1327  // look for the value, and then
1328  // finally get it.
1329 
1330  int *el_find =
1331  std::find(col_indices, col_indices + nnz_present, trilinos_j);
1332 
1333  int local_col_index = (int)(el_find - col_indices);
1334 
1335  // This is actually the only
1336  // difference to the el(i,j)
1337  // function, which means that
1338  // we throw an exception in
1339  // this case instead of just
1340  // returning zero for an
1341  // element that is not present
1342  // in the sparsity pattern.
1343  if (local_col_index == nnz_present)
1344  {
1345  Assert(false, ExcInvalidIndex(i, j));
1346  }
1347  else
1348  value = values[local_col_index];
1349  }
1350 
1351  return value;
1352  }
1353 
1354 
1355 
1356  TrilinosScalar
1357  SparseMatrix::el(const size_type i, const size_type j) const
1358  {
1359  // Extract local indices in
1360  // the matrix.
1361  int trilinos_i =
1362  matrix->LRID(static_cast<TrilinosWrappers::types::int_type>(i)),
1363  trilinos_j =
1364  matrix->LCID(static_cast<TrilinosWrappers::types::int_type>(j));
1365  TrilinosScalar value = 0.;
1366 
1367  // If the data is not on the
1368  // present processor, we can't
1369  // continue. Just print out zero
1370  // as discussed in the
1371  // documentation of this
1372  // function. if you want error
1373  // checking, use operator().
1374  if ((trilinos_i == -1) || (trilinos_j == -1))
1375  return 0.;
1376  else
1377  {
1378  // Check whether the matrix
1379  // already is transformed to
1380  // local indices.
1381  Assert(matrix->Filled(), ExcMatrixNotCompressed());
1382 
1383  // Prepare pointers for extraction
1384  // of a view of the row.
1385  int nnz_present = matrix->NumMyEntries(trilinos_i);
1386  int nnz_extracted;
1387  int * col_indices;
1388  TrilinosScalar *values;
1389 
1390  // Generate the view and make
1391  // sure that we have not generated
1392  // an error.
1393  int ierr = matrix->ExtractMyRowView(trilinos_i,
1394  nnz_extracted,
1395  values,
1396  col_indices);
1397  (void)ierr;
1398  Assert(ierr == 0, ExcTrilinosError(ierr));
1399 
1400  Assert(nnz_present == nnz_extracted,
1401  ExcDimensionMismatch(nnz_present, nnz_extracted));
1402 
1403  // Search the index where we
1404  // look for the value, and then
1405  // finally get it.
1406  int *el_find =
1407  std::find(col_indices, col_indices + nnz_present, trilinos_j);
1408 
1409  int local_col_index = (int)(el_find - col_indices);
1410 
1411 
1412  // This is actually the only
1413  // difference to the () function
1414  // querying (i,j), where we throw an
1415  // exception instead of just
1416  // returning zero for an element
1417  // that is not present in the
1418  // sparsity pattern.
1419  if (local_col_index == nnz_present)
1420  value = 0;
1421  else
1422  value = values[local_col_index];
1423  }
1424 
1425  return value;
1426  }
1427 
1428 
1429 
1430  TrilinosScalar
1432  {
1433  Assert(m() == n(), ExcNotQuadratic());
1434 
1435 # ifdef DEBUG
1436  // use operator() in debug mode because
1437  // it checks if this is a valid element
1438  // (in parallel)
1439  return operator()(i, i);
1440 # else
1441  // Trilinos doesn't seem to have a
1442  // more efficient way to access the
1443  // diagonal than by just using the
1444  // standard el(i,j) function.
1445  return el(i, i);
1446 # endif
1447  }
1448 
1449 
1450 
1451  unsigned int
1453  {
1454  Assert(row < m(), ExcInternalError());
1455 
1456  // get a representation of the
1457  // present row
1458  int ncols = -1;
1459  int local_row =
1460  matrix->LRID(static_cast<TrilinosWrappers::types::int_type>(row));
1461  Assert((local_row >= 0), ExcAccessToNonlocalRow(row));
1462 
1463  // on the processor who owns this
1464  // row, we'll have a non-negative
1465  // value.
1466  if (local_row >= 0)
1467  {
1468  int ierr = matrix->NumMyRowEntries(local_row, ncols);
1469  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1470  }
1471 
1472  return static_cast<unsigned int>(ncols);
1473  }
1474 
1475 
1476 
1477  void
1478  SparseMatrix::set(const std::vector<size_type> & row_indices,
1479  const std::vector<size_type> & col_indices,
1480  const FullMatrix<TrilinosScalar> &values,
1481  const bool elide_zero_values)
1482  {
1483  Assert(row_indices.size() == values.m(),
1484  ExcDimensionMismatch(row_indices.size(), values.m()));
1485  Assert(col_indices.size() == values.n(),
1486  ExcDimensionMismatch(col_indices.size(), values.n()));
1487 
1488  for (size_type i = 0; i < row_indices.size(); ++i)
1489  set(row_indices[i],
1490  col_indices.size(),
1491  col_indices.data(),
1492  &values(i, 0),
1493  elide_zero_values);
1494  }
1495 
1496 
1497 
1498  void
1500  const std::vector<size_type> & col_indices,
1501  const std::vector<TrilinosScalar> &values,
1502  const bool elide_zero_values)
1503  {
1504  Assert(col_indices.size() == values.size(),
1505  ExcDimensionMismatch(col_indices.size(), values.size()));
1506 
1507  set(row,
1508  col_indices.size(),
1509  col_indices.data(),
1510  values.data(),
1511  elide_zero_values);
1512  }
1513 
1514 
1515 
1516  void
1518  const size_type n_cols,
1519  const size_type * col_indices,
1520  const TrilinosScalar *values,
1521  const bool elide_zero_values)
1522  {
1523  AssertIndexRange(row, this->m());
1524 
1525  int ierr;
1526  if (last_action == Add)
1527  {
1528  ierr =
1529  matrix->GlobalAssemble(*column_space_map, matrix->RowMap(), true);
1530 
1531  Assert(ierr == 0, ExcTrilinosError(ierr));
1532  }
1533 
1534  last_action = Insert;
1535 
1536  TrilinosWrappers::types::int_type *col_index_ptr;
1537  TrilinosScalar * col_value_ptr;
1538  TrilinosWrappers::types::int_type n_columns;
1539 
1540  boost::container::small_vector<TrilinosScalar, 200> local_value_array(
1541  n_cols);
1542  boost::container::small_vector<TrilinosWrappers::types::int_type, 200>
1543  local_index_array(n_cols);
1544 
1545  // If we don't elide zeros, the pointers are already available... need to
1546  // cast to non-const pointers as that is the format taken by Trilinos (but
1547  // we will not modify const data)
1548  if (elide_zero_values == false)
1549  {
1550  col_index_ptr = (TrilinosWrappers::types::int_type *)col_indices;
1551  col_value_ptr = const_cast<TrilinosScalar *>(values);
1552  n_columns = n_cols;
1553  }
1554  else
1555  {
1556  // Otherwise, extract nonzero values in each row and get the
1557  // respective indices.
1558  col_index_ptr = local_index_array.data();
1559  col_value_ptr = local_value_array.data();
1560 
1561  n_columns = 0;
1562  for (size_type j = 0; j < n_cols; ++j)
1563  {
1564  const double value = values[j];
1565  AssertIsFinite(value);
1566  if (value != 0)
1567  {
1568  col_index_ptr[n_columns] = col_indices[j];
1569  col_value_ptr[n_columns] = value;
1570  n_columns++;
1571  }
1572  }
1573 
1574  Assert(n_columns <= (TrilinosWrappers::types::int_type)n_cols,
1575  ExcInternalError());
1576  }
1577 
1578 
1579  // If the calling matrix owns the row to which we want to insert values,
1580  // we can directly call the Epetra_CrsMatrix input function, which is much
1581  // faster than the Epetra_FECrsMatrix function. We distinguish between two
1582  // cases: the first one is when the matrix is not filled (i.e., it is
1583  // possible to add new elements to the sparsity pattern), and the second
1584  // one is when the pattern is already fixed. In the former case, we add
1585  // the possibility to insert new values, and in the second we just replace
1586  // data.
1587  if (matrix->RowMap().MyGID(
1588  static_cast<TrilinosWrappers::types::int_type>(row)) == true)
1589  {
1590  if (matrix->Filled() == false)
1591  {
1592  ierr = matrix->Epetra_CrsMatrix::InsertGlobalValues(
1593  static_cast<TrilinosWrappers::types::int_type>(row),
1594  static_cast<int>(n_columns),
1595  const_cast<double *>(col_value_ptr),
1596  col_index_ptr);
1597 
1598  // When inserting elements, we do not want to create exceptions in
1599  // the case when inserting non-local data (since that's what we
1600  // want to do right now).
1601  if (ierr > 0)
1602  ierr = 0;
1603  }
1604  else
1605  ierr = matrix->Epetra_CrsMatrix::ReplaceGlobalValues(row,
1606  n_columns,
1607  col_value_ptr,
1608  col_index_ptr);
1609  }
1610  else
1611  {
1612  // When we're at off-processor data, we have to stick with the
1613  // standard Insert/ReplaceGlobalValues function. Nevertheless, the way
1614  // we call it is the fastest one (any other will lead to repeated
1615  // allocation and deallocation of memory in order to call the function
1616  // we already use, which is very inefficient if writing one element at
1617  // a time).
1618  compressed = false;
1619 
1620  if (matrix->Filled() == false)
1621  {
1622  ierr = matrix->InsertGlobalValues(
1623  1,
1624  (TrilinosWrappers::types::int_type *)&row,
1625  n_columns,
1626  col_index_ptr,
1627  &col_value_ptr,
1628  Epetra_FECrsMatrix::ROW_MAJOR);
1629  if (ierr > 0)
1630  ierr = 0;
1631  }
1632  else
1633  ierr = matrix->ReplaceGlobalValues(
1634  1,
1635  (TrilinosWrappers::types::int_type *)&row,
1636  n_columns,
1637  col_index_ptr,
1638  &col_value_ptr,
1639  Epetra_FECrsMatrix::ROW_MAJOR);
1640  // use the FECrsMatrix facilities for set even in the case when we
1641  // have explicitly set the off-processor rows because that only works
1642  // properly when adding elements, not when setting them (since we want
1643  // to only touch elements that have been set explicitly, and there is
1644  // no way on the receiving processor to identify them otherwise)
1645  }
1646 
1647  Assert(ierr <= 0, ExcAccessToNonPresentElement(row, col_index_ptr[0]));
1648  AssertThrow(ierr >= 0, ExcTrilinosError(ierr));
1649  }
1650 
1651 
1652 
1653  void
1654  SparseMatrix::add(const std::vector<size_type> & indices,
1655  const FullMatrix<TrilinosScalar> &values,
1656  const bool elide_zero_values)
1657  {
1658  Assert(indices.size() == values.m(),
1659  ExcDimensionMismatch(indices.size(), values.m()));
1660  Assert(values.m() == values.n(), ExcNotQuadratic());
1661 
1662  for (size_type i = 0; i < indices.size(); ++i)
1663  add(indices[i],
1664  indices.size(),
1665  indices.data(),
1666  &values(i, 0),
1667  elide_zero_values);
1668  }
1669 
1670 
1671 
1672  void
1673  SparseMatrix::add(const std::vector<size_type> & row_indices,
1674  const std::vector<size_type> & col_indices,
1675  const FullMatrix<TrilinosScalar> &values,
1676  const bool elide_zero_values)
1677  {
1678  Assert(row_indices.size() == values.m(),
1679  ExcDimensionMismatch(row_indices.size(), values.m()));
1680  Assert(col_indices.size() == values.n(),
1681  ExcDimensionMismatch(col_indices.size(), values.n()));
1682 
1683  for (size_type i = 0; i < row_indices.size(); ++i)
1684  add(row_indices[i],
1685  col_indices.size(),
1686  col_indices.data(),
1687  &values(i, 0),
1688  elide_zero_values);
1689  }
1690 
1691 
1692 
1693  void
1695  const std::vector<size_type> & col_indices,
1696  const std::vector<TrilinosScalar> &values,
1697  const bool elide_zero_values)
1698  {
1699  Assert(col_indices.size() == values.size(),
1700  ExcDimensionMismatch(col_indices.size(), values.size()));
1701 
1702  add(row,
1703  col_indices.size(),
1704  col_indices.data(),
1705  values.data(),
1706  elide_zero_values);
1707  }
1708 
1709 
1710 
1711  void
1713  const size_type n_cols,
1714  const size_type * col_indices,
1715  const TrilinosScalar *values,
1716  const bool elide_zero_values,
1717  const bool /*col_indices_are_sorted*/)
1718  {
1719  AssertIndexRange(row, this->m());
1720  int ierr;
1721  if (last_action == Insert)
1722  {
1723  // TODO: this could lead to a dead lock when only one processor
1724  // calls GlobalAssemble.
1725  ierr =
1726  matrix->GlobalAssemble(*column_space_map, matrix->RowMap(), false);
1727 
1728  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1729  }
1730 
1731  last_action = Add;
1732 
1733  TrilinosWrappers::types::int_type *col_index_ptr;
1734  TrilinosScalar * col_value_ptr;
1735  TrilinosWrappers::types::int_type n_columns;
1736 
1737  boost::container::small_vector<TrilinosScalar, 100> local_value_array(
1738  n_cols);
1739  boost::container::small_vector<TrilinosWrappers::types::int_type, 100>
1740  local_index_array(n_cols);
1741 
1742  // If we don't elide zeros, the pointers are already available... need to
1743  // cast to non-const pointers as that is the format taken by Trilinos (but
1744  // we will not modify const data)
1745  if (elide_zero_values == false)
1746  {
1747  col_index_ptr = (TrilinosWrappers::types::int_type *)col_indices;
1748  col_value_ptr = const_cast<TrilinosScalar *>(values);
1749  n_columns = n_cols;
1750 # ifdef DEBUG
1751  for (size_type j = 0; j < n_cols; ++j)
1752  AssertIsFinite(values[j]);
1753 # endif
1754  }
1755  else
1756  {
1757  // Otherwise, extract nonzero values in each row and the corresponding
1758  // index.
1759  col_index_ptr = local_index_array.data();
1760  col_value_ptr = local_value_array.data();
1761 
1762  n_columns = 0;
1763  for (size_type j = 0; j < n_cols; ++j)
1764  {
1765  const double value = values[j];
1766 
1767  AssertIsFinite(value);
1768  if (value != 0)
1769  {
1770  col_index_ptr[n_columns] = col_indices[j];
1771  col_value_ptr[n_columns] = value;
1772  n_columns++;
1773  }
1774  }
1775 
1776  Assert(n_columns <= (TrilinosWrappers::types::int_type)n_cols,
1777  ExcInternalError());
1778  }
1779  // Exit early if there is nothing to do
1780  if (n_columns == 0)
1781  {
1782  return;
1783  }
1784 
1785  // If the calling processor owns the row to which we want to add values, we
1786  // can directly call the Epetra_CrsMatrix input function, which is much
1787  // faster than the Epetra_FECrsMatrix function.
1788  if (matrix->RowMap().MyGID(
1789  static_cast<TrilinosWrappers::types::int_type>(row)) == true)
1790  {
1791  ierr = matrix->Epetra_CrsMatrix::SumIntoGlobalValues(row,
1792  n_columns,
1793  col_value_ptr,
1794  col_index_ptr);
1795  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1796  }
1797  else if (nonlocal_matrix.get() != nullptr)
1798  {
1799  compressed = false;
1800  // this is the case when we have explicitly set the off-processor rows
1801  // and want to create a separate matrix object for them (to retain
1802  // thread-safety)
1803  Assert(nonlocal_matrix->RowMap().LID(
1804  static_cast<TrilinosWrappers::types::int_type>(row)) != -1,
1805  ExcMessage("Attempted to write into off-processor matrix row "
1806  "that has not be specified as being writable upon "
1807  "initialization"));
1808  ierr = nonlocal_matrix->SumIntoGlobalValues(row,
1809  n_columns,
1810  col_value_ptr,
1811  col_index_ptr);
1812  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1813  }
1814  else
1815  {
1816  // When we're at off-processor data, we have to stick with the
1817  // standard SumIntoGlobalValues function. Nevertheless, the way we
1818  // call it is the fastest one (any other will lead to repeated
1819  // allocation and deallocation of memory in order to call the function
1820  // we already use, which is very inefficient if writing one element at
1821  // a time).
1822  compressed = false;
1823 
1824  ierr =
1825  matrix->SumIntoGlobalValues(1,
1826  (TrilinosWrappers::types::int_type *)&row,
1827  n_columns,
1828  col_index_ptr,
1829  &col_value_ptr,
1830  Epetra_FECrsMatrix::ROW_MAJOR);
1831  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1832  }
1833 
1834 # ifdef DEBUG
1835  if (ierr > 0)
1836  {
1837  std::cout << "------------------------------------------" << std::endl;
1838  std::cout << "Got error " << ierr << " in row " << row << " of proc "
1839  << matrix->RowMap().Comm().MyPID()
1840  << " when trying to add the columns:" << std::endl;
1841  for (TrilinosWrappers::types::int_type i = 0; i < n_columns; ++i)
1842  std::cout << col_index_ptr[i] << " ";
1843  std::cout << std::endl << std::endl;
1844  std::cout << "Matrix row "
1845  << (matrix->RowMap().MyGID(
1846  static_cast<TrilinosWrappers::types::int_type>(row)) ==
1847  false ?
1848  "(nonlocal part)" :
1849  "")
1850  << " has the following indices:" << std::endl;
1851  std::vector<TrilinosWrappers::types::int_type> indices;
1852  const Epetra_CrsGraph * graph =
1853  (nonlocal_matrix.get() != nullptr &&
1854  matrix->RowMap().MyGID(
1855  static_cast<TrilinosWrappers::types::int_type>(row)) == false) ?
1856  &nonlocal_matrix->Graph() :
1857  &matrix->Graph();
1858 
1859  indices.resize(graph->NumGlobalIndices(
1860  static_cast<TrilinosWrappers::types::int_type>(row)));
1861  int n_indices = 0;
1862  graph->ExtractGlobalRowCopy(
1863  static_cast<TrilinosWrappers::types::int_type>(row),
1864  indices.size(),
1865  n_indices,
1866  indices.data());
1867  AssertDimension(static_cast<unsigned int>(n_indices), indices.size());
1868 
1869  for (TrilinosWrappers::types::int_type i = 0; i < n_indices; ++i)
1870  std::cout << indices[i] << " ";
1871  std::cout << std::endl << std::endl;
1872  Assert(ierr <= 0, ExcAccessToNonPresentElement(row, col_index_ptr[0]));
1873  }
1874 # endif
1875  Assert(ierr >= 0, ExcTrilinosError(ierr));
1876  }
1877 
1878 
1879 
1880  SparseMatrix &
1881  SparseMatrix::operator=(const double d)
1882  {
1884  compress(
1885  ::VectorOperation::unknown); // TODO: why do we do this? Should we
1886  // not check for is_compressed?
1887 
1888  const int ierr = matrix->PutScalar(d);
1889  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1890  if (nonlocal_matrix.get() != nullptr)
1891  nonlocal_matrix->PutScalar(d);
1892 
1893  return *this;
1894  }
1895 
1896 
1897 
1898  void
1899  SparseMatrix::add(const TrilinosScalar factor, const SparseMatrix &rhs)
1900  {
1901  AssertDimension(rhs.m(), m());
1902  AssertDimension(rhs.n(), n());
1903  AssertDimension(rhs.local_range().first, local_range().first);
1904  AssertDimension(rhs.local_range().second, local_range().second);
1905  Assert(matrix->RowMap().SameAs(rhs.matrix->RowMap()),
1906  ExcMessage("Can only add matrices with same distribution of rows"));
1907  Assert(matrix->Filled() && rhs.matrix->Filled(),
1908  ExcMessage("Addition of matrices only allowed if matrices are "
1909  "filled, i.e., compress() has been called"));
1910 
1911  const bool same_col_map = matrix->ColMap().SameAs(rhs.matrix->ColMap());
1912 
1913  for (const auto row : locally_owned_range_indices())
1914  {
1915  const int row_local = matrix->RowMap().LID(
1916  static_cast<TrilinosWrappers::types::int_type>(row));
1917  Assert((row_local >= 0), ExcAccessToNonlocalRow(row));
1918 
1919  // First get a view to the matrix columns of both matrices. Note that
1920  // the data is in local index spaces so we need to be careful not only
1921  // to compare column indices in case they are derived from the same
1922  // map.
1923  int n_entries, rhs_n_entries;
1924  TrilinosScalar *value_ptr, *rhs_value_ptr;
1925  int * index_ptr, *rhs_index_ptr;
1926  int ierr = rhs.matrix->ExtractMyRowView(row_local,
1927  rhs_n_entries,
1928  rhs_value_ptr,
1929  rhs_index_ptr);
1930  (void)ierr;
1931  Assert(ierr == 0, ExcTrilinosError(ierr));
1932 
1933  ierr =
1934  matrix->ExtractMyRowView(row_local, n_entries, value_ptr, index_ptr);
1935  Assert(ierr == 0, ExcTrilinosError(ierr));
1936  bool expensive_checks = (n_entries != rhs_n_entries || !same_col_map);
1937  if (!expensive_checks)
1938  {
1939  // check if the column indices are the same. If yes, can simply
1940  // copy over the data.
1941  expensive_checks = std::memcmp(static_cast<void *>(index_ptr),
1942  static_cast<void *>(rhs_index_ptr),
1943  sizeof(int) * n_entries) != 0;
1944  if (!expensive_checks)
1945  for (int i = 0; i < n_entries; ++i)
1946  value_ptr[i] += rhs_value_ptr[i] * factor;
1947  }
1948  // Now to the expensive case where we need to check all column indices
1949  // against each other (transformed into global index space) and where
1950  // we need to make sure that all entries we are about to add into the
1951  // lhs matrix actually exist
1952  if (expensive_checks)
1953  {
1954  for (int i = 0; i < rhs_n_entries; ++i)
1955  {
1956  if (rhs_value_ptr[i] == 0.)
1957  continue;
1958  const TrilinosWrappers::types::int_type rhs_global_col =
1959  global_column_index(*rhs.matrix, rhs_index_ptr[i]);
1960  int local_col = matrix->ColMap().LID(rhs_global_col);
1961  int *local_index = Utilities::lower_bound(index_ptr,
1962  index_ptr + n_entries,
1963  local_col);
1964  Assert(local_index != index_ptr + n_entries &&
1965  *local_index == local_col,
1966  ExcMessage(
1967  "Adding the entries from the other matrix "
1968  "failed, because the sparsity pattern "
1969  "of that matrix includes more elements than the "
1970  "calling matrix, which is not allowed."));
1971  value_ptr[local_index - index_ptr] += factor * rhs_value_ptr[i];
1972  }
1973  }
1974  }
1975  }
1976 
1977 
1978 
1979  void
1981  {
1982  // This only flips a flag that tells
1983  // Trilinos that any vmult operation
1984  // should be done with the
1985  // transpose. However, the matrix
1986  // structure is not reset.
1987  int ierr;
1988 
1989  if (!matrix->UseTranspose())
1990  {
1991  ierr = matrix->SetUseTranspose(true);
1992  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1993  }
1994  else
1995  {
1996  ierr = matrix->SetUseTranspose(false);
1997  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
1998  }
1999  }
2000 
2001 
2002 
2003  SparseMatrix &
2004  SparseMatrix::operator*=(const TrilinosScalar a)
2005  {
2006  const int ierr = matrix->Scale(a);
2007  Assert(ierr == 0, ExcTrilinosError(ierr));
2008  (void)ierr; // removes -Wunused-variable in optimized mode
2009 
2010  return *this;
2011  }
2012 
2013 
2014 
2015  SparseMatrix &
2016  SparseMatrix::operator/=(const TrilinosScalar a)
2017  {
2018  Assert(a != 0, ExcDivideByZero());
2019 
2020  const TrilinosScalar factor = 1. / a;
2021 
2022  const int ierr = matrix->Scale(factor);
2023  Assert(ierr == 0, ExcTrilinosError(ierr));
2024  (void)ierr; // removes -Wunused-variable in optimized mode
2025 
2026  return *this;
2027  }
2028 
2029 
2030 
2031  TrilinosScalar
2033  {
2034  Assert(matrix->Filled(), ExcMatrixNotCompressed());
2035  return matrix->NormOne();
2036  }
2037 
2038 
2039 
2040  TrilinosScalar
2042  {
2043  Assert(matrix->Filled(), ExcMatrixNotCompressed());
2044  return matrix->NormInf();
2045  }
2046 
2047 
2048 
2049  TrilinosScalar
2051  {
2052  Assert(matrix->Filled(), ExcMatrixNotCompressed());
2053  return matrix->NormFrobenius();
2054  }
2055 
2056 
2057 
2058  namespace internal
2059  {
2060  namespace SparseMatrixImplementation
2061  {
2062  template <typename VectorType>
2063  inline void
2064  check_vector_map_equality(const Epetra_CrsMatrix &,
2065  const VectorType &,
2066  const VectorType &)
2067  {}
2068 
2069  inline void
2070  check_vector_map_equality(const Epetra_CrsMatrix & m,
2072  const TrilinosWrappers::MPI::Vector &out)
2073  {
2074  Assert(in.vector_partitioner().SameAs(m.DomainMap()) == true,
2075  ExcMessage(
2076  "Column map of matrix does not fit with vector map!"));
2077  Assert(out.vector_partitioner().SameAs(m.RangeMap()) == true,
2078  ExcMessage("Row map of matrix does not fit with vector map!"));
2079  (void)m;
2080  (void)in;
2081  (void)out;
2082  }
2083  } // namespace SparseMatrixImplementation
2084  } // namespace internal
2085 
2086 
2087  template <typename VectorType>
2088  void
2089  SparseMatrix::vmult(VectorType &dst, const VectorType &src) const
2090  {
2091  Assert(&src != &dst, ExcSourceEqualsDestination());
2092  Assert(matrix->Filled(), ExcMatrixNotCompressed());
2093  (void)src;
2094  (void)dst;
2095 
2096  internal::SparseMatrixImplementation::check_vector_map_equality(*matrix,
2097  src,
2098  dst);
2099  const size_type dst_local_size = internal::end(dst) - internal::begin(dst);
2100  AssertDimension(dst_local_size,
2101  static_cast<size_type>(matrix->RangeMap().NumMyPoints()));
2102  const size_type src_local_size = internal::end(src) - internal::begin(src);
2103  AssertDimension(src_local_size,
2104  static_cast<size_type>(matrix->DomainMap().NumMyPoints()));
2105 
2106  Epetra_MultiVector tril_dst(
2107  View, matrix->RangeMap(), internal::begin(dst), dst_local_size, 1);
2108  Epetra_MultiVector tril_src(View,
2109  matrix->DomainMap(),
2110  const_cast<TrilinosScalar *>(
2111  internal::begin(src)),
2112  src_local_size,
2113  1);
2114 
2115  const int ierr = matrix->Multiply(false, tril_src, tril_dst);
2116  Assert(ierr == 0, ExcTrilinosError(ierr));
2117  (void)ierr; // removes -Wunused-variable in optimized mode
2118  }
2119 
2120 
2121 
2122  template <typename VectorType>
2123  void
2124  SparseMatrix::Tvmult(VectorType &dst, const VectorType &src) const
2125  {
2126  Assert(&src != &dst, ExcSourceEqualsDestination());
2127  Assert(matrix->Filled(), ExcMatrixNotCompressed());
2128 
2129  internal::SparseMatrixImplementation::check_vector_map_equality(*matrix,
2130  dst,
2131  src);
2132  const size_type dst_local_size = internal::end(dst) - internal::begin(dst);
2133  AssertDimension(dst_local_size,
2134  static_cast<size_type>(matrix->DomainMap().NumMyPoints()));
2135  const size_type src_local_size = internal::end(src) - internal::begin(src);
2136  AssertDimension(src_local_size,
2137  static_cast<size_type>(matrix->RangeMap().NumMyPoints()));
2138 
2139  Epetra_MultiVector tril_dst(
2140  View, matrix->DomainMap(), internal::begin(dst), dst_local_size, 1);
2141  Epetra_MultiVector tril_src(View,
2142  matrix->RangeMap(),
2143  const_cast<double *>(internal::begin(src)),
2144  src_local_size,
2145  1);
2146 
2147  const int ierr = matrix->Multiply(true, tril_src, tril_dst);
2148  Assert(ierr == 0, ExcTrilinosError(ierr));
2149  (void)ierr; // removes -Wunused-variable in optimized mode
2150  }
2151 
2152 
2153 
2154  template <typename VectorType>
2155  void
2156  SparseMatrix::vmult_add(VectorType &dst, const VectorType &src) const
2157  {
2158  Assert(&src != &dst, ExcSourceEqualsDestination());
2159 
2160  // Reinit a temporary vector with fast argument set, which does not
2161  // overwrite the content (to save time).
2162  VectorType tmp_vector;
2163  tmp_vector.reinit(dst, true);
2164  vmult(tmp_vector, src);
2165  dst += tmp_vector;
2166  }
2167 
2168 
2169 
2170  template <typename VectorType>
2171  void
2172  SparseMatrix::Tvmult_add(VectorType &dst, const VectorType &src) const
2173  {
2174  Assert(&src != &dst, ExcSourceEqualsDestination());
2175 
2176  // Reinit a temporary vector with fast argument set, which does not
2177  // overwrite the content (to save time).
2178  VectorType tmp_vector;
2179  tmp_vector.reinit(dst, true);
2180  Tvmult(tmp_vector, src);
2181  dst += tmp_vector;
2182  }
2183 
2184 
2185 
2186  TrilinosScalar
2188  {
2189  Assert(matrix->RowMap().SameAs(matrix->DomainMap()), ExcNotQuadratic());
2190 
2191  MPI::Vector temp_vector;
2192  temp_vector.reinit(v, true);
2193 
2194  vmult(temp_vector, v);
2195  return temp_vector * v;
2196  }
2197 
2198 
2199 
2200  TrilinosScalar
2202  const MPI::Vector &v) const
2203  {
2204  Assert(matrix->RowMap().SameAs(matrix->DomainMap()), ExcNotQuadratic());
2205 
2206  MPI::Vector temp_vector;
2207  temp_vector.reinit(v, true);
2208 
2209  vmult(temp_vector, v);
2210  return u * temp_vector;
2211  }
2212 
2213 
2214 
2215  TrilinosScalar
2217  const MPI::Vector &x,
2218  const MPI::Vector &b) const
2219  {
2220  vmult(dst, x);
2221  dst -= b;
2222  dst *= -1.;
2223 
2224  return dst.l2_norm();
2225  }
2226 
2227 
2228 
2229  namespace internals
2230  {
2232 
2233  void
2234  perform_mmult(const SparseMatrix &inputleft,
2235  const SparseMatrix &inputright,
2236  SparseMatrix & result,
2237  const MPI::Vector & V,
2238  const bool transpose_left)
2239  {
2240 # ifdef DEAL_II_WITH_64BIT_INDICES
2241  Assert(false, ExcNotImplemented())
2242 # endif
2243  const bool use_vector = (V.size() == inputright.m() ? true : false);
2244  if (transpose_left == false)
2245  {
2246  Assert(inputleft.n() == inputright.m(),
2247  ExcDimensionMismatch(inputleft.n(), inputright.m()));
2248  Assert(inputleft.domain_partitioner().SameAs(
2249  inputright.range_partitioner()),
2250  ExcMessage("Parallel partitioning of A and B does not fit."));
2251  }
2252  else
2253  {
2254  Assert(inputleft.m() == inputright.m(),
2255  ExcDimensionMismatch(inputleft.m(), inputright.m()));
2256  Assert(inputleft.range_partitioner().SameAs(
2257  inputright.range_partitioner()),
2258  ExcMessage("Parallel partitioning of A and B does not fit."));
2259  }
2260 
2261  result.clear();
2262 
2263  // create a suitable operator B: in case
2264  // we do not use a vector, all we need to
2265  // do is to set the pointer. Otherwise,
2266  // we insert the data from B, but
2267  // multiply each row with the respective
2268  // vector element.
2269  Teuchos::RCP<Epetra_CrsMatrix> mod_B;
2270  if (use_vector == false)
2271  {
2272  mod_B = Teuchos::rcp(const_cast<Epetra_CrsMatrix *>(
2273  &inputright.trilinos_matrix()),
2274  false);
2275  }
2276  else
2277  {
2278  mod_B = Teuchos::rcp(
2279  new Epetra_CrsMatrix(Copy, inputright.trilinos_sparsity_pattern()),
2280  true);
2281  mod_B->FillComplete(inputright.domain_partitioner(),
2282  inputright.range_partitioner());
2283  Assert(inputright.local_range() == V.local_range(),
2284  ExcMessage("Parallel distribution of matrix B and vector V "
2285  "does not match."));
2286 
2287  const int local_N = inputright.local_size();
2288  for (int i = 0; i < local_N; ++i)
2289  {
2290  int N_entries = -1;
2291  double *new_data, *B_data;
2292  mod_B->ExtractMyRowView(i, N_entries, new_data);
2293  inputright.trilinos_matrix().ExtractMyRowView(i,
2294  N_entries,
2295  B_data);
2296  double value = V.trilinos_vector()[0][i];
2297  for (TrilinosWrappers::types::int_type j = 0; j < N_entries; ++j)
2298  new_data[j] = value * B_data[j];
2299  }
2300  }
2301 
2302  // use ML built-in method for performing
2303  // the matrix-matrix product.
2304  // create ML operators on top of the
2305  // Epetra matrices. if we use a
2306  // transposed matrix, let ML know it
2307  ML_Comm *comm;
2308  ML_Comm_Create(&comm);
2309 # ifdef ML_MPI
2310  const Epetra_MpiComm *epcomm = dynamic_cast<const Epetra_MpiComm *>(
2311  &(inputleft.trilinos_matrix().Comm()));
2312  // Get the MPI communicator, as it may not be MPI_COMM_W0RLD, and update
2313  // the ML comm object
2314  if (epcomm)
2315  ML_Comm_Set_UsrComm(comm, epcomm->Comm());
2316 # endif
2317  ML_Operator *A_ = ML_Operator_Create(comm);
2318  ML_Operator *B_ = ML_Operator_Create(comm);
2319  ML_Operator *C_ = ML_Operator_Create(comm);
2320  SparseMatrix transposed_mat;
2321 
2322  if (transpose_left == false)
2323  ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix *>(
2324  &inputleft.trilinos_matrix()),
2325  A_,
2326  false);
2327  else
2328  {
2329  // create transposed matrix
2330  SparsityPattern sparsity_transposed(inputleft.domain_partitioner(),
2331  inputleft.range_partitioner());
2332  Assert(inputleft.domain_partitioner().LinearMap() == true,
2333  ExcMessage(
2334  "Matrix must be partitioned contiguously between procs."));
2335  for (::types::global_dof_index i = 0;
2336  i < inputleft.local_size();
2337  ++i)
2338  {
2339  int num_entries, *indices;
2340  inputleft.trilinos_sparsity_pattern().ExtractMyRowView(
2341  i, num_entries, indices);
2342  Assert(num_entries >= 0, ExcInternalError());
2343 
2344  const auto & trilinos_matrix = inputleft.trilinos_matrix();
2345  const size_type GID =
2347  for (TrilinosWrappers::types::int_type j = 0; j < num_entries;
2348  ++j)
2349  sparsity_transposed.add(TrilinosWrappers::global_index(
2350  trilinos_matrix.ColMap(), indices[j]),
2351  GID);
2352  }
2353 
2354  sparsity_transposed.compress();
2355  transposed_mat.reinit(sparsity_transposed);
2356  for (::types::global_dof_index i = 0;
2357  i < inputleft.local_size();
2358  ++i)
2359  {
2360  int num_entries, *indices;
2361  double *values;
2362  inputleft.trilinos_matrix().ExtractMyRowView(i,
2363  num_entries,
2364  values,
2365  indices);
2366  Assert(num_entries >= 0, ExcInternalError());
2367 
2368  const auto & trilinos_matrix = inputleft.trilinos_matrix();
2369  const size_type GID =
2371  for (TrilinosWrappers::types::int_type j = 0; j < num_entries;
2372  ++j)
2373  transposed_mat.set(TrilinosWrappers::global_index(
2374  trilinos_matrix.ColMap(), indices[j]),
2375  GID,
2376  values[j]);
2377  }
2378  transposed_mat.compress(VectorOperation::insert);
2379  ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix *>(
2380  &transposed_mat.trilinos_matrix()),
2381  A_,
2382  false);
2383  }
2384  ML_Operator_WrapEpetraCrsMatrix(mod_B.get(), B_, false);
2385 
2386  // We implement the multiplication by
2387  // hand in a similar way as is done in
2388  // ml/src/Operator/ml_rap.c for a triple
2389  // matrix product. This means that the
2390  // code is very similar to the one found
2391  // in ml/src/Operator/ml_rap.c
2392 
2393  // import data if necessary
2394  ML_Operator * Btmp, *Ctmp, *Ctmp2, *tptr;
2395  ML_CommInfoOP * getrow_comm;
2396  int max_per_proc;
2397  TrilinosWrappers::types::int_type N_input_vector = B_->invec_leng;
2398  getrow_comm = B_->getrow->pre_comm;
2399  if (getrow_comm != nullptr)
2400  for (TrilinosWrappers::types::int_type i = 0;
2401  i < getrow_comm->N_neighbors;
2402  i++)
2403  for (TrilinosWrappers::types::int_type j = 0;
2404  j < getrow_comm->neighbors[i].N_send;
2405  j++)
2406  AssertThrow(getrow_comm->neighbors[i].send_list[j] < N_input_vector,
2407  ExcInternalError());
2408 
2409  ML_create_unique_col_id(N_input_vector,
2410  &(B_->getrow->loc_glob_map),
2411  getrow_comm,
2412  &max_per_proc,
2413  B_->comm);
2414  B_->getrow->use_loc_glob_map = ML_YES;
2415  if (A_->getrow->pre_comm != nullptr)
2416  ML_exchange_rows(B_, &Btmp, A_->getrow->pre_comm);
2417  else
2418  Btmp = B_;
2419 
2420  // perform matrix-matrix product
2421  ML_matmat_mult(A_, Btmp, &Ctmp);
2422 
2423  // release temporary structures we needed
2424  // for multiplication
2425  ML_free(B_->getrow->loc_glob_map);
2426  B_->getrow->loc_glob_map = nullptr;
2427  B_->getrow->use_loc_glob_map = ML_NO;
2428  if (A_->getrow->pre_comm != nullptr)
2429  {
2430  tptr = Btmp;
2431  while ((tptr != nullptr) && (tptr->sub_matrix != B_))
2432  tptr = tptr->sub_matrix;
2433  if (tptr != nullptr)
2434  tptr->sub_matrix = nullptr;
2435  ML_RECUR_CSR_MSRdata_Destroy(Btmp);
2436  ML_Operator_Destroy(&Btmp);
2437  }
2438 
2439  // make correct data structures
2440  if (A_->getrow->post_comm != nullptr)
2441  ML_exchange_rows(Ctmp, &Ctmp2, A_->getrow->post_comm);
2442  else
2443  Ctmp2 = Ctmp;
2444 
2445  ML_back_to_csrlocal(Ctmp2, C_, max_per_proc);
2446 
2447  ML_RECUR_CSR_MSRdata_Destroy(Ctmp);
2448  ML_Operator_Destroy(&Ctmp);
2449 
2450  if (A_->getrow->post_comm != nullptr)
2451  {
2452  ML_RECUR_CSR_MSRdata_Destroy(Ctmp2);
2453  ML_Operator_Destroy(&Ctmp2);
2454  }
2455 
2456  // create an Epetra matrix from the ML
2457  // matrix that we got as a result.
2458  Epetra_CrsMatrix *C_mat;
2459  ML_Operator2EpetraCrsMatrix(C_, C_mat);
2460  C_mat->FillComplete(mod_B->DomainMap(),
2461  transpose_left ?
2462  inputleft.trilinos_matrix().DomainMap() :
2463  inputleft.trilinos_matrix().RangeMap());
2464  C_mat->OptimizeStorage();
2465  result.reinit(*C_mat);
2466 
2467  // destroy allocated memory
2468  delete C_mat;
2469  ML_Operator_Destroy(&A_);
2470  ML_Operator_Destroy(&B_);
2471  ML_Operator_Destroy(&C_);
2472  ML_Comm_Destroy(&comm);
2473  }
2474  } // namespace internals
2475 
2476 
2477  void
2479  const SparseMatrix &B,
2480  const MPI::Vector & V) const
2481  {
2482 # ifdef DEAL_II_WITH_64BIT_INDICES
2483  Assert(false, ExcNotImplemented())
2484 # endif
2485  internals::perform_mmult(*this, B, C, V, false);
2486  }
2487 
2488 
2489 
2490  void
2492  const SparseMatrix &B,
2493  const MPI::Vector & V) const
2494  {
2495 # ifdef DEAL_II_WITH_64BIT_INDICES
2496  Assert(false, ExcNotImplemented())
2497 # endif
2498  internals::perform_mmult(*this, B, C, V, true);
2499  }
2500 
2501 
2502 
2503  void
2505  {
2506  Assert(false, ExcNotImplemented());
2507  }
2508 
2509 
2510 
2511  // As of now, no particularly neat
2512  // output is generated in case of
2513  // multiple processors.
2514  void
2515  SparseMatrix::print(std::ostream &out,
2516  const bool print_detailed_trilinos_information) const
2517  {
2518  if (print_detailed_trilinos_information == true)
2519  out << *matrix;
2520  else
2521  {
2522  double *values;
2523  int * indices;
2524  int num_entries;
2525 
2526  for (int i = 0; i < matrix->NumMyRows(); ++i)
2527  {
2528  matrix->ExtractMyRowView(i, num_entries, values, indices);
2529  for (TrilinosWrappers::types::int_type j = 0; j < num_entries; ++j)
2530  out << "(" << TrilinosWrappers::global_row_index(*matrix, i)
2531  << ","
2532  << TrilinosWrappers::global_column_index(*matrix, indices[j])
2533  << ") " << values[j] << std::endl;
2534  }
2535  }
2536 
2537  AssertThrow(out, ExcIO());
2538  }
2539 
2540 
2541 
2544  {
2545  size_type static_memory =
2546  sizeof(*this) + sizeof(*matrix) + sizeof(*matrix->Graph().DataPtr());
2547  return (
2548  (sizeof(TrilinosScalar) + sizeof(TrilinosWrappers::types::int_type)) *
2549  matrix->NumMyNonzeros() +
2550  sizeof(int) * local_size() + static_memory);
2551  }
2552 
2553 
2554 
2555  const Epetra_Map &
2557  {
2558  return matrix->DomainMap();
2559  }
2560 
2561 
2562 
2563  const Epetra_Map &
2565  {
2566  return matrix->RangeMap();
2567  }
2568 
2569 
2570 
2571  const Epetra_Map &
2573  {
2574  return matrix->RowMap();
2575  }
2576 
2577 
2578 
2579  const Epetra_Map &
2581  {
2582  return matrix->ColMap();
2583  }
2584 
2585 
2586 
2587  MPI_Comm
2589  {
2590 # ifdef DEAL_II_WITH_MPI
2591 
2592  const Epetra_MpiComm *mpi_comm =
2593  dynamic_cast<const Epetra_MpiComm *>(&matrix->RangeMap().Comm());
2594  Assert(mpi_comm != nullptr, ExcInternalError());
2595  return mpi_comm->Comm();
2596 # else
2597 
2598  return MPI_COMM_SELF;
2599 
2600 # endif
2601  }
2602 } // namespace TrilinosWrappers
2603 
2604 
2605 namespace TrilinosWrappers
2606 {
2607  namespace internal
2608  {
2609  namespace
2610  {
2611 # ifndef DEAL_II_WITH_MPI
2612  Epetra_Map
2613  make_serial_Epetra_map(const IndexSet &serial_partitioning)
2614  {
2615  // See IndexSet::make_trilinos_map
2616  return Epetra_Map(
2617  TrilinosWrappers::types::int_type(serial_partitioning.size()),
2618  TrilinosWrappers::types::int_type(serial_partitioning.n_elements()),
2619  0,
2620  Epetra_SerialComm());
2621  }
2622 # endif
2623  } // namespace
2624 
2625  namespace LinearOperatorImplementation
2626  {
2627  TrilinosPayload::TrilinosPayload()
2628  : use_transpose(false)
2629  ,
2630 # ifdef DEAL_II_WITH_MPI
2631  communicator(MPI_COMM_SELF)
2632  , domain_map(IndexSet().make_trilinos_map(communicator.Comm()))
2633  , range_map(IndexSet().make_trilinos_map(communicator.Comm()))
2634 # else
2635  domain_map(internal::make_serial_Epetra_map(IndexSet()))
2636  , range_map(internal::make_serial_Epetra_map(IndexSet()))
2637 # endif
2638  {
2639  vmult = [](Range &, const Domain &) {
2640  Assert(false,
2641  ExcMessage("Uninitialized TrilinosPayload::vmult called"
2642  "(Default constructor)"));
2643  };
2644 
2645  Tvmult = [](Domain &, const Range &) {
2646  Assert(false,
2647  ExcMessage("Uninitialized TrilinosPayload::Tvmult called"
2648  "(Default constructor)"));
2649  };
2650 
2651  inv_vmult = [](Domain &, const Range &) {
2652  Assert(false,
2653  ExcMessage("Uninitialized TrilinosPayload::inv_vmult called"
2654  "(Default constructor)"));
2655  };
2656 
2657  inv_Tvmult = [](Range &, const Domain &) {
2658  Assert(false,
2659  ExcMessage("Uninitialized TrilinosPayload::inv_Tvmult called"
2660  "(Default constructor)"));
2661  };
2662  }
2663 
2664 
2665 
2667  const TrilinosWrappers::SparseMatrix &matrix_exemplar,
2668  const TrilinosWrappers::SparseMatrix &matrix)
2669  : use_transpose(matrix_exemplar.trilinos_matrix().UseTranspose())
2670  ,
2671 # ifdef DEAL_II_WITH_MPI
2672  communicator(matrix_exemplar.get_mpi_communicator())
2673  , domain_map(
2674  matrix_exemplar.locally_owned_domain_indices().make_trilinos_map(
2675  communicator.Comm()))
2676  , range_map(
2677  matrix_exemplar.locally_owned_range_indices().make_trilinos_map(
2678  communicator.Comm()))
2679 # else
2680  domain_map(internal::make_serial_Epetra_map(
2681  matrix_exemplar.locally_owned_domain_indices()))
2682  , range_map(internal::make_serial_Epetra_map(
2683  matrix_exemplar.locally_owned_range_indices()))
2684 # endif
2685  {
2686  vmult = [&matrix_exemplar, &matrix](Range & tril_dst,
2687  const Domain &tril_src) {
2688  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
2689  Assert(&tril_src != &tril_dst,
2691  Assert(matrix.trilinos_matrix().Filled(),
2693  internal::check_vector_map_equality(
2694  matrix_exemplar.trilinos_matrix(),
2695  tril_src,
2696  tril_dst,
2697  matrix_exemplar.trilinos_matrix().UseTranspose());
2698  internal::check_vector_map_equality(
2699  matrix.trilinos_matrix(),
2700  tril_src,
2701  tril_dst,
2702  matrix.trilinos_matrix().UseTranspose());
2703 
2704  const int ierr = matrix.trilinos_matrix().Apply(tril_src, tril_dst);
2705  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2706  };
2707 
2708  Tvmult = [&matrix_exemplar, &matrix](Domain & tril_dst,
2709  const Range &tril_src) {
2710  // Duplicated from TrilinosWrappers::SparseMatrix::Tvmult
2711  Assert(&tril_src != &tril_dst,
2713  Assert(matrix.trilinos_matrix().Filled(),
2715  internal::check_vector_map_equality(
2716  matrix_exemplar.trilinos_matrix(),
2717  tril_src,
2718  tril_dst,
2719  !matrix_exemplar.trilinos_matrix().UseTranspose());
2720  internal::check_vector_map_equality(
2721  matrix.trilinos_matrix(),
2722  tril_src,
2723  tril_dst,
2724  !matrix.trilinos_matrix().UseTranspose());
2725 
2726  Epetra_CrsMatrix &tril_mtrx_non_const =
2727  const_cast<Epetra_CrsMatrix &>(matrix.trilinos_matrix());
2728  tril_mtrx_non_const.SetUseTranspose(
2729  !matrix.trilinos_matrix().UseTranspose());
2730  const int ierr = matrix.trilinos_matrix().Apply(tril_src, tril_dst);
2731  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2732  tril_mtrx_non_const.SetUseTranspose(
2733  !matrix.trilinos_matrix().UseTranspose());
2734  };
2735 
2736  inv_vmult = [](Domain &, const Range &) {
2737  Assert(false,
2738  ExcMessage("Uninitialized TrilinosPayload::inv_vmult called"
2739  "(Matrix constructor with matrix exemplar)"));
2740  };
2741 
2742  inv_Tvmult = [](Range &, const Domain &) {
2743  Assert(false,
2744  ExcMessage("Uninitialized TrilinosPayload::inv_Tvmult called"
2745  "(Matrix constructor with matrix exemplar)"));
2746  };
2747  }
2748 
2749 
2750 
2752  const TrilinosWrappers::SparseMatrix & matrix_exemplar,
2753  const TrilinosWrappers::PreconditionBase &preconditioner)
2754  : use_transpose(matrix_exemplar.trilinos_matrix().UseTranspose())
2755  ,
2756 # ifdef DEAL_II_WITH_MPI
2757  communicator(matrix_exemplar.get_mpi_communicator())
2758  , domain_map(
2759  matrix_exemplar.locally_owned_domain_indices().make_trilinos_map(
2760  communicator.Comm()))
2761  , range_map(
2762  matrix_exemplar.locally_owned_range_indices().make_trilinos_map(
2763  communicator.Comm()))
2764 # else
2765  domain_map(internal::make_serial_Epetra_map(
2766  matrix_exemplar.locally_owned_domain_indices()))
2767  , range_map(internal::make_serial_Epetra_map(
2768  matrix_exemplar.locally_owned_range_indices()))
2769 # endif
2770  {
2771  vmult = [&matrix_exemplar, &preconditioner](Range & tril_dst,
2772  const Domain &tril_src) {
2773  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2774  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2775  Assert(&tril_src != &tril_dst,
2777  internal::check_vector_map_equality(
2778  matrix_exemplar.trilinos_matrix(),
2779  tril_src,
2780  tril_dst,
2781  matrix_exemplar.trilinos_matrix().UseTranspose());
2782  internal::check_vector_map_equality(
2783  preconditioner.trilinos_operator(),
2784  tril_src,
2785  tril_dst,
2786  preconditioner.trilinos_operator().UseTranspose());
2787 
2788  const int ierr =
2789  preconditioner.trilinos_operator().ApplyInverse(tril_src, tril_dst);
2790  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2791  };
2792 
2793  Tvmult = [&matrix_exemplar, &preconditioner](Domain & tril_dst,
2794  const Range &tril_src) {
2795  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2796  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2797  Assert(&tril_src != &tril_dst,
2799  internal::check_vector_map_equality(
2800  matrix_exemplar.trilinos_matrix(),
2801  tril_src,
2802  tril_dst,
2803  !matrix_exemplar.trilinos_matrix().UseTranspose());
2804  internal::check_vector_map_equality(
2805  preconditioner.trilinos_operator(),
2806  tril_src,
2807  tril_dst,
2808  !preconditioner.trilinos_operator().UseTranspose());
2809 
2810  preconditioner.trilinos_operator().SetUseTranspose(
2811  !preconditioner.trilinos_operator().UseTranspose());
2812  const int ierr =
2813  preconditioner.trilinos_operator().ApplyInverse(tril_src, tril_dst);
2814  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2815  preconditioner.trilinos_operator().SetUseTranspose(
2816  !preconditioner.trilinos_operator().UseTranspose());
2817  };
2818 
2819  inv_vmult = [&matrix_exemplar, &preconditioner](Domain & tril_dst,
2820  const Range &tril_src) {
2821  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2822  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2823  Assert(&tril_src != &tril_dst,
2825  internal::check_vector_map_equality(
2826  matrix_exemplar.trilinos_matrix(),
2827  tril_src,
2828  tril_dst,
2829  !matrix_exemplar.trilinos_matrix().UseTranspose());
2830  internal::check_vector_map_equality(
2831  preconditioner.trilinos_operator(),
2832  tril_src,
2833  tril_dst,
2834  !preconditioner.trilinos_operator().UseTranspose());
2835 
2836  const int ierr =
2837  preconditioner.trilinos_operator().ApplyInverse(tril_src, tril_dst);
2838  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2839  };
2840 
2841  inv_Tvmult = [&matrix_exemplar,
2842  &preconditioner](Range & tril_dst,
2843  const Domain &tril_src) {
2844  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2845  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2846  Assert(&tril_src != &tril_dst,
2848  internal::check_vector_map_equality(
2849  matrix_exemplar.trilinos_matrix(),
2850  tril_src,
2851  tril_dst,
2852  matrix_exemplar.trilinos_matrix().UseTranspose());
2853  internal::check_vector_map_equality(
2854  preconditioner.trilinos_operator(),
2855  tril_src,
2856  tril_dst,
2857  preconditioner.trilinos_operator().UseTranspose());
2858 
2859  preconditioner.trilinos_operator().SetUseTranspose(
2860  !preconditioner.trilinos_operator().UseTranspose());
2861  const int ierr =
2862  preconditioner.trilinos_operator().ApplyInverse(tril_src, tril_dst);
2863  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2864  preconditioner.trilinos_operator().SetUseTranspose(
2865  !preconditioner.trilinos_operator().UseTranspose());
2866  };
2867  }
2868 
2869 
2870 
2872  const TrilinosWrappers::PreconditionBase &preconditioner_exemplar,
2873  const TrilinosWrappers::PreconditionBase &preconditioner)
2874  : use_transpose(
2875  preconditioner_exemplar.trilinos_operator().UseTranspose())
2876  ,
2877 # ifdef DEAL_II_WITH_MPI
2878  communicator(preconditioner_exemplar.get_mpi_communicator())
2879  , domain_map(preconditioner_exemplar.locally_owned_domain_indices()
2880  .make_trilinos_map(communicator.Comm()))
2881  , range_map(preconditioner_exemplar.locally_owned_range_indices()
2882  .make_trilinos_map(communicator.Comm()))
2883 # else
2884  domain_map(internal::make_serial_Epetra_map(
2885  preconditioner_exemplar.locally_owned_domain_indices()))
2886  , range_map(internal::make_serial_Epetra_map(
2887  preconditioner_exemplar.locally_owned_range_indices()))
2888 # endif
2889  {
2890  vmult = [&preconditioner_exemplar,
2891  &preconditioner](Range &tril_dst, const Domain &tril_src) {
2892  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2893  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2894  Assert(&tril_src != &tril_dst,
2896  internal::check_vector_map_equality(
2897  preconditioner_exemplar.trilinos_operator(),
2898  tril_src,
2899  tril_dst,
2900  preconditioner_exemplar.trilinos_operator().UseTranspose());
2901  internal::check_vector_map_equality(
2902  preconditioner.trilinos_operator(),
2903  tril_src,
2904  tril_dst,
2905  preconditioner.trilinos_operator().UseTranspose());
2906 
2907  const int ierr =
2908  preconditioner.trilinos_operator().Apply(tril_src, tril_dst);
2909  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2910  };
2911 
2912  Tvmult = [&preconditioner_exemplar,
2913  &preconditioner](Domain &tril_dst, const Range &tril_src) {
2914  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2915  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2916  Assert(&tril_src != &tril_dst,
2918  internal::check_vector_map_equality(
2919  preconditioner_exemplar.trilinos_operator(),
2920  tril_src,
2921  tril_dst,
2922  !preconditioner_exemplar.trilinos_operator().UseTranspose());
2923  internal::check_vector_map_equality(
2924  preconditioner.trilinos_operator(),
2925  tril_src,
2926  tril_dst,
2927  !preconditioner.trilinos_operator().UseTranspose());
2928 
2929  preconditioner.trilinos_operator().SetUseTranspose(
2930  !preconditioner.trilinos_operator().UseTranspose());
2931  const int ierr =
2932  preconditioner.trilinos_operator().Apply(tril_src, tril_dst);
2933  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2934  preconditioner.trilinos_operator().SetUseTranspose(
2935  !preconditioner.trilinos_operator().UseTranspose());
2936  };
2937 
2938  inv_vmult = [&preconditioner_exemplar,
2939  &preconditioner](Domain &tril_dst, const Range &tril_src) {
2940  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2941  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2942  Assert(&tril_src != &tril_dst,
2944  internal::check_vector_map_equality(
2945  preconditioner_exemplar.trilinos_operator(),
2946  tril_src,
2947  tril_dst,
2948  !preconditioner_exemplar.trilinos_operator().UseTranspose());
2949  internal::check_vector_map_equality(
2950  preconditioner.trilinos_operator(),
2951  tril_src,
2952  tril_dst,
2953  !preconditioner.trilinos_operator().UseTranspose());
2954 
2955  const int ierr =
2956  preconditioner.trilinos_operator().ApplyInverse(tril_src, tril_dst);
2957  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2958  };
2959 
2960  inv_Tvmult = [&preconditioner_exemplar,
2961  &preconditioner](Range & tril_dst,
2962  const Domain &tril_src) {
2963  // Duplicated from TrilinosWrappers::PreconditionBase::vmult
2964  // as well as from TrilinosWrappers::SparseMatrix::Tvmult
2965  Assert(&tril_src != &tril_dst,
2967  internal::check_vector_map_equality(
2968  preconditioner_exemplar.trilinos_operator(),
2969  tril_src,
2970  tril_dst,
2971  preconditioner_exemplar.trilinos_operator().UseTranspose());
2972  internal::check_vector_map_equality(
2973  preconditioner.trilinos_operator(),
2974  tril_src,
2975  tril_dst,
2976  preconditioner.trilinos_operator().UseTranspose());
2977 
2978  preconditioner.trilinos_operator().SetUseTranspose(
2979  !preconditioner.trilinos_operator().UseTranspose());
2980  const int ierr =
2981  preconditioner.trilinos_operator().ApplyInverse(tril_src, tril_dst);
2982  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
2983  preconditioner.trilinos_operator().SetUseTranspose(
2984  !preconditioner.trilinos_operator().UseTranspose());
2985  };
2986  }
2987 
2988 
2989 
2991  : vmult(payload.vmult)
2992  , Tvmult(payload.Tvmult)
2993  , inv_vmult(payload.inv_vmult)
2994  , inv_Tvmult(payload.inv_Tvmult)
2995  , use_transpose(payload.use_transpose)
2996  , communicator(payload.communicator)
2997  , domain_map(payload.domain_map)
2998  , range_map(payload.range_map)
2999  {}
3000 
3001 
3002 
3003  // Composite copy constructor
3004  // This is required for PackagedOperations
3006  const TrilinosPayload &second_op)
3007  : use_transpose(false)
3008  , // The combination of operators provides the exact
3009  // definition of the operation
3010  communicator(first_op.communicator)
3011  , domain_map(second_op.domain_map)
3012  , range_map(first_op.range_map)
3013  {}
3014 
3015 
3016 
3019  {
3020  TrilinosPayload return_op(*this);
3021 
3022  return_op.vmult = [](Range &tril_dst, const Range &tril_src) {
3023  tril_dst = tril_src;
3024  };
3025 
3026  return_op.Tvmult = [](Range &tril_dst, const Range &tril_src) {
3027  tril_dst = tril_src;
3028  };
3029 
3030  return_op.inv_vmult = [](Range &tril_dst, const Range &tril_src) {
3031  tril_dst = tril_src;
3032  };
3033 
3034  return_op.inv_Tvmult = [](Range &tril_dst, const Range &tril_src) {
3035  tril_dst = tril_src;
3036  };
3037 
3038  return return_op;
3039  }
3040 
3041 
3042 
3045  {
3046  TrilinosPayload return_op(*this);
3047 
3048  return_op.vmult = [](Range &tril_dst, const Domain &) {
3049  const int ierr = tril_dst.PutScalar(0.0);
3050 
3051  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3052  };
3053 
3054  return_op.Tvmult = [](Domain &tril_dst, const Range &) {
3055  const int ierr = tril_dst.PutScalar(0.0);
3056 
3057  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3058  };
3059 
3060  return_op.inv_vmult = [](Domain &tril_dst, const Range &) {
3061  AssertThrow(false,
3062  ExcMessage("Cannot compute inverse of null operator"));
3063 
3064  const int ierr = tril_dst.PutScalar(0.0);
3065 
3066  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3067  };
3068 
3069  return_op.inv_Tvmult = [](Range &tril_dst, const Domain &) {
3070  AssertThrow(false,
3071  ExcMessage("Cannot compute inverse of null operator"));
3072 
3073  const int ierr = tril_dst.PutScalar(0.0);
3074 
3075  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3076  };
3077 
3078  return return_op;
3079  }
3080 
3081 
3082 
3085  {
3086  TrilinosPayload return_op(*this);
3087  return_op.transpose();
3088  return return_op;
3089  }
3090 
3091 
3092 
3093  IndexSet
3095  {
3096  return IndexSet(domain_map);
3097  }
3098 
3099 
3100 
3101  IndexSet
3103  {
3104  return IndexSet(range_map);
3105  }
3106 
3107 
3108 
3109  MPI_Comm
3111  {
3112 # ifdef DEAL_II_WITH_MPI
3113  return communicator.Comm();
3114 # else
3115  return MPI_COMM_SELF;
3116 # endif
3117  }
3118 
3119 
3120 
3121  void
3123  {
3125  }
3126 
3127 
3128 
3129  bool
3131  {
3132  return use_transpose;
3133  }
3134 
3135 
3136 
3137  int
3139  {
3140  if (use_transpose != UseTranspose)
3141  {
3146  }
3147  return 0;
3148  }
3149 
3150 
3151 
3152  int
3154  {
3155  // The transposedness of the operations is taken care of
3156  // when we hit the transpose flag.
3157  vmult(Y, X);
3158  return 0;
3159  }
3160 
3161 
3162 
3163  int
3165  {
3166  // The transposedness of the operations is taken care of
3167  // when we hit the transpose flag.
3168  inv_vmult(Y, X);
3169  return 0;
3170  }
3171 
3172 
3173 
3174  const char *
3176  {
3177  return "TrilinosPayload";
3178  }
3179 
3180 
3181 
3182  const Epetra_Comm &
3184  {
3185  return communicator;
3186  }
3187 
3188 
3189 
3190  const Epetra_Map &
3192  {
3193  return domain_map;
3194  }
3195 
3196 
3197 
3198  const Epetra_Map &
3200  {
3201  return range_map;
3202  }
3203 
3204 
3205 
3206  bool
3208  {
3209  return false;
3210  }
3211 
3212 
3213 
3214  double
3216  {
3217  AssertThrow(false, ExcNotImplemented());
3218  return 0.0;
3219  }
3220 
3221 
3222 
3224  operator+(const TrilinosPayload &first_op,
3225  const TrilinosPayload &second_op)
3226  {
3227  using Domain = typename TrilinosPayload::Domain;
3228  using Range = typename TrilinosPayload::Range;
3229  using Intermediate = typename TrilinosPayload::VectorType;
3230  using GVMVectorType = TrilinosWrappers::MPI::Vector;
3231 
3232  Assert(first_op.locally_owned_domain_indices() ==
3233  second_op.locally_owned_domain_indices(),
3234  ExcMessage(
3235  "Operators are set to work on incompatible IndexSets."));
3236  Assert(first_op.locally_owned_range_indices() ==
3237  second_op.locally_owned_range_indices(),
3238  ExcMessage(
3239  "Operators are set to work on incompatible IndexSets."));
3240 
3241  TrilinosPayload return_op(first_op, second_op);
3242 
3243  // Capture by copy so the payloads are always valid
3244  return_op.vmult = [first_op, second_op](Range & tril_dst,
3245  const Domain &tril_src) {
3246  // Duplicated from LinearOperator::operator*
3247  // TODO: Template the constructor on GrowingVectorMemory vector type?
3248  GrowingVectorMemory<GVMVectorType> vector_memory;
3249  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3250 
3251  // Initialize intermediate vector
3252  const Epetra_Map &first_op_init_map = first_op.OperatorDomainMap();
3253  i->reinit(IndexSet(first_op_init_map),
3254  first_op.get_mpi_communicator(),
3255  /*bool omit_zeroing_entries =*/true);
3256 
3257  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3258  const size_type i_local_size = i->end() - i->begin();
3259  AssertDimension(i_local_size,
3260  static_cast<size_type>(
3261  first_op_init_map.NumMyPoints()));
3262  const Epetra_Map &second_op_init_map = second_op.OperatorDomainMap();
3263  AssertDimension(i_local_size,
3264  static_cast<size_type>(
3265  second_op_init_map.NumMyPoints()));
3266  (void)second_op_init_map;
3267  Intermediate tril_int(View,
3268  first_op_init_map,
3269  const_cast<TrilinosScalar *>(i->begin()),
3270  i_local_size,
3271  1);
3272 
3273  // These operators may themselves be transposed or not, so we let them
3274  // decide what the intended outcome is
3275  second_op.Apply(tril_src, tril_int);
3276  first_op.Apply(tril_src, tril_dst);
3277  const int ierr = tril_dst.Update(1.0, tril_int, 1.0);
3278  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3279  };
3280 
3281  return_op.Tvmult = [first_op, second_op](Domain & tril_dst,
3282  const Range &tril_src) {
3283  // Duplicated from LinearOperator::operator*
3284  // TODO: Template the constructor on GrowingVectorMemory vector type?
3285  GrowingVectorMemory<GVMVectorType> vector_memory;
3286  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3287 
3288  // These operators may themselves be transposed or not, so we let them
3289  // decide what the intended outcome is
3290  // We must first transpose the operators to get the right IndexSets
3291  // for the input, intermediate and result vectors
3292  const_cast<TrilinosPayload &>(first_op).transpose();
3293  const_cast<TrilinosPayload &>(second_op).transpose();
3294 
3295  // Initialize intermediate vector
3296  const Epetra_Map &first_op_init_map = first_op.OperatorRangeMap();
3297  i->reinit(IndexSet(first_op_init_map),
3298  first_op.get_mpi_communicator(),
3299  /*bool omit_zeroing_entries =*/true);
3300 
3301  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3302  const size_type i_local_size = i->end() - i->begin();
3303  AssertDimension(i_local_size,
3304  static_cast<size_type>(
3305  first_op_init_map.NumMyPoints()));
3306  const Epetra_Map &second_op_init_map = second_op.OperatorRangeMap();
3307  AssertDimension(i_local_size,
3308  static_cast<size_type>(
3309  second_op_init_map.NumMyPoints()));
3310  (void)second_op_init_map;
3311  Intermediate tril_int(View,
3312  first_op_init_map,
3313  const_cast<TrilinosScalar *>(i->begin()),
3314  i_local_size,
3315  1);
3316 
3317  // These operators may themselves be transposed or not, so we let them
3318  // decide what the intended outcome is
3319  second_op.Apply(tril_src, tril_int);
3320  first_op.Apply(tril_src, tril_dst);
3321  const int ierr = tril_dst.Update(1.0, tril_int, 1.0);
3322  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3323 
3324  // Reset transpose flag
3325  const_cast<TrilinosPayload &>(first_op).transpose();
3326  const_cast<TrilinosPayload &>(second_op).transpose();
3327  };
3328 
3329  return_op.inv_vmult = [first_op, second_op](Domain & tril_dst,
3330  const Range &tril_src) {
3331  // Duplicated from LinearOperator::operator*
3332  // TODO: Template the constructor on GrowingVectorMemory vector type?
3333  GrowingVectorMemory<GVMVectorType> vector_memory;
3334  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3335 
3336  // Initialize intermediate vector
3337  const Epetra_Map &first_op_init_map = first_op.OperatorRangeMap();
3338  i->reinit(IndexSet(first_op_init_map),
3339  first_op.get_mpi_communicator(),
3340  /*bool omit_zeroing_entries =*/true);
3341 
3342  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3343  const size_type i_local_size = i->end() - i->begin();
3344  AssertDimension(i_local_size,
3345  static_cast<size_type>(
3346  first_op_init_map.NumMyPoints()));
3347  const Epetra_Map &second_op_init_map = second_op.OperatorRangeMap();
3348  AssertDimension(i_local_size,
3349  static_cast<size_type>(
3350  second_op_init_map.NumMyPoints()));
3351  (void)second_op_init_map;
3352  Intermediate tril_int(View,
3353  first_op_init_map,
3354  const_cast<TrilinosScalar *>(i->begin()),
3355  i_local_size,
3356  1);
3357 
3358  // These operators may themselves be transposed or not, so we let them
3359  // decide what the intended outcome is
3360  second_op.ApplyInverse(tril_src, tril_int);
3361  first_op.ApplyInverse(tril_src, tril_dst);
3362  const int ierr = tril_dst.Update(1.0, tril_int, 1.0);
3363  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3364  };
3365 
3366  return_op.inv_Tvmult = [first_op, second_op](Range & tril_dst,
3367  const Domain &tril_src) {
3368  // Duplicated from LinearOperator::operator*
3369  // TODO: Template the constructor on GrowingVectorMemory vector type?
3370  GrowingVectorMemory<GVMVectorType> vector_memory;
3371  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3372 
3373  // These operators may themselves be transposed or not, so we let them
3374  // decide what the intended outcome is
3375  // We must first transpose the operators to get the right IndexSets
3376  // for the input, intermediate and result vectors
3377  const_cast<TrilinosPayload &>(first_op).transpose();
3378  const_cast<TrilinosPayload &>(second_op).transpose();
3379 
3380  // Initialize intermediate vector
3381  const Epetra_Map &first_op_init_map = first_op.OperatorDomainMap();
3382  i->reinit(IndexSet(first_op_init_map),
3383  first_op.get_mpi_communicator(),
3384  /*bool omit_zeroing_entries =*/true);
3385 
3386  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3387  const size_type i_local_size = i->end() - i->begin();
3388  AssertDimension(i_local_size,
3389  static_cast<size_type>(
3390  first_op_init_map.NumMyPoints()));
3391  const Epetra_Map &second_op_init_map = second_op.OperatorDomainMap();
3392  AssertDimension(i_local_size,
3393  static_cast<size_type>(
3394  second_op_init_map.NumMyPoints()));
3395  (void)second_op_init_map;
3396  Intermediate tril_int(View,
3397  first_op_init_map,
3398  const_cast<TrilinosScalar *>(i->begin()),
3399  i_local_size,
3400  1);
3401 
3402  // These operators may themselves be transposed or not, so we let them
3403  // decide what the intended outcome is
3404  second_op.ApplyInverse(tril_src, tril_int);
3405  first_op.ApplyInverse(tril_src, tril_dst);
3406  const int ierr = tril_dst.Update(1.0, tril_int, 1.0);
3407  AssertThrow(ierr == 0, ExcTrilinosError(ierr));
3408 
3409  // Reset transpose flag
3410  const_cast<TrilinosPayload &>(first_op).transpose();
3411  const_cast<TrilinosPayload &>(second_op).transpose();
3412  };
3413 
3414  return return_op;
3415  }
3416 
3417 
3418 
3419  TrilinosPayload operator*(const TrilinosPayload &first_op,
3420  const TrilinosPayload &second_op)
3421  {
3422  using Domain = typename TrilinosPayload::Domain;
3423  using Range = typename TrilinosPayload::Range;
3424  using Intermediate = typename TrilinosPayload::VectorType;
3425  using GVMVectorType = TrilinosWrappers::MPI::Vector;
3426 
3428  second_op.locally_owned_range_indices(),
3429  ExcMessage(
3430  "Operators are set to work on incompatible IndexSets."));
3431 
3432  TrilinosPayload return_op(first_op, second_op);
3433 
3434  // Capture by copy so the payloads are always valid
3435  return_op.vmult = [first_op, second_op](Range & tril_dst,
3436  const Domain &tril_src) {
3437  // Duplicated from LinearOperator::operator*
3438  // TODO: Template the constructor on GrowingVectorMemory vector type?
3439  GrowingVectorMemory<GVMVectorType> vector_memory;
3440  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3441 
3442  // Initialize intermediate vector
3443  const Epetra_Map &first_op_init_map = first_op.OperatorDomainMap();
3444  i->reinit(IndexSet(first_op_init_map),
3445  first_op.get_mpi_communicator(),
3446  /*bool omit_zeroing_entries =*/true);
3447 
3448  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3449  const size_type i_local_size = i->end() - i->begin();
3450  AssertDimension(i_local_size,
3451  static_cast<size_type>(
3452  first_op_init_map.NumMyPoints()));
3453  const Epetra_Map &second_op_init_map = second_op.OperatorRangeMap();
3454  AssertDimension(i_local_size,
3455  static_cast<size_type>(
3456  second_op_init_map.NumMyPoints()));
3457  (void)second_op_init_map;
3458  Intermediate tril_int(View,
3459  first_op_init_map,
3460  const_cast<TrilinosScalar *>(i->begin()),
3461  i_local_size,
3462  1);
3463 
3464  // These operators may themselves be transposed or not, so we let them
3465  // decide what the intended outcome is
3466  second_op.Apply(tril_src, tril_int);
3467  first_op.Apply(tril_int, tril_dst);
3468  };
3469 
3470  return_op.Tvmult = [first_op, second_op](Domain & tril_dst,
3471  const Range &tril_src) {
3472  // Duplicated from LinearOperator::operator*
3473  // TODO: Template the constructor on GrowingVectorMemory vector type?
3474  GrowingVectorMemory<GVMVectorType> vector_memory;
3475  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3476 
3477  // These operators may themselves be transposed or not, so we let them
3478  // decide what the intended outcome is
3479  // We must first transpose the operators to get the right IndexSets
3480  // for the input, intermediate and result vectors
3481  const_cast<TrilinosPayload &>(first_op).transpose();
3482  const_cast<TrilinosPayload &>(second_op).transpose();
3483 
3484  // Initialize intermediate vector
3485  const Epetra_Map &first_op_init_map = first_op.OperatorRangeMap();
3486  i->reinit(IndexSet(first_op_init_map),
3487  first_op.get_mpi_communicator(),
3488  /*bool omit_zeroing_entries =*/true);
3489 
3490  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3491  const size_type i_local_size = i->end() - i->begin();
3492  AssertDimension(i_local_size,
3493  static_cast<size_type>(
3494  first_op_init_map.NumMyPoints()));
3495  const Epetra_Map &second_op_init_map = second_op.OperatorDomainMap();
3496  AssertDimension(i_local_size,
3497  static_cast<size_type>(
3498  second_op_init_map.NumMyPoints()));
3499  (void)second_op_init_map;
3500  Intermediate tril_int(View,
3501  first_op_init_map,
3502  const_cast<TrilinosScalar *>(i->begin()),
3503  i_local_size,
3504  1);
3505 
3506  // Apply the operators in the reverse order to vmult
3507  first_op.Apply(tril_src, tril_int);
3508  second_op.Apply(tril_int, tril_dst);
3509 
3510  // Reset transpose flag
3511  const_cast<TrilinosPayload &>(first_op).transpose();
3512  const_cast<TrilinosPayload &>(second_op).transpose();
3513  };
3514 
3515  return_op.inv_vmult = [first_op, second_op](Domain & tril_dst,
3516  const Range &tril_src) {
3517  // Duplicated from LinearOperator::operator*
3518  // TODO: Template the constructor on GrowingVectorMemory vector type?
3519  GrowingVectorMemory<GVMVectorType> vector_memory;
3520  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3521 
3522  // Initialize intermediate vector
3523  const Epetra_Map &first_op_init_map = first_op.OperatorRangeMap();
3524  i->reinit(IndexSet(first_op_init_map),
3525  first_op.get_mpi_communicator(),
3526  /*bool omit_zeroing_entries =*/true);
3527 
3528  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3529  const size_type i_local_size = i->end() - i->begin();
3530  AssertDimension(i_local_size,
3531  static_cast<size_type>(
3532  first_op_init_map.NumMyPoints()));
3533  const Epetra_Map &second_op_init_map = second_op.OperatorDomainMap();
3534  AssertDimension(i_local_size,
3535  static_cast<size_type>(
3536  second_op_init_map.NumMyPoints()));
3537  (void)second_op_init_map;
3538  Intermediate tril_int(View,
3539  first_op_init_map,
3540  const_cast<TrilinosScalar *>(i->begin()),
3541  i_local_size,
3542  1);
3543 
3544  // Apply the operators in the reverse order to vmult
3545  // and the same order as Tvmult
3546  first_op.ApplyInverse(tril_src, tril_int);
3547  second_op.ApplyInverse(tril_int, tril_dst);
3548  };
3549 
3550  return_op.inv_Tvmult = [first_op, second_op](Range & tril_dst,
3551  const Domain &tril_src) {
3552  // Duplicated from LinearOperator::operator*
3553  // TODO: Template the constructor on GrowingVectorMemory vector type?
3554  GrowingVectorMemory<GVMVectorType> vector_memory;
3555  VectorMemory<GVMVectorType>::Pointer i(vector_memory);
3556 
3557  // These operators may themselves be transposed or not, so we let them
3558  // decide what the intended outcome is
3559  // We must first transpose the operators to get the right IndexSets
3560  // for the input, intermediate and result vectors
3561  const_cast<TrilinosPayload &>(first_op).transpose();
3562  const_cast<TrilinosPayload &>(second_op).transpose();
3563 
3564  // Initialize intermediate vector
3565  const Epetra_Map &first_op_init_map = first_op.OperatorDomainMap();
3566  i->reinit(IndexSet(first_op_init_map),
3567  first_op.get_mpi_communicator(),
3568  /*bool omit_zeroing_entries =*/true);
3569 
3570  // Duplicated from TrilinosWrappers::SparseMatrix::vmult
3571  const size_type i_local_size = i->end() - i->begin();
3572  AssertDimension(i_local_size,
3573  static_cast<size_type>(
3574  first_op_init_map.NumMyPoints()));
3575  const Epetra_Map &second_op_init_map = second_op.OperatorRangeMap();
3576  AssertDimension(i_local_size,
3577  static_cast<size_type>(
3578  second_op_init_map.NumMyPoints()));
3579  (void)second_op_init_map;
3580  Intermediate tril_int(View,
3581  first_op_init_map,
3582  const_cast<TrilinosScalar *>(i->begin()),
3583  i_local_size,
3584  1);
3585 
3586  // These operators may themselves be transposed or not, so we let them
3587  // decide what the intended outcome is
3588  // Apply the operators in the reverse order to Tvmult
3589  // and the same order as vmult
3590  second_op.ApplyInverse(tril_src, tril_int);
3591  first_op.ApplyInverse(tril_int, tril_dst);
3592 
3593  // Reset transpose flag
3594  const_cast<TrilinosPayload &>(first_op).transpose();
3595  const_cast<TrilinosPayload &>(second_op).transpose();
3596  };
3597 
3598  return return_op;
3599  }
3600 
3601  } // namespace LinearOperatorImplementation
3602  } /* namespace internal */
3603 } /* namespace TrilinosWrappers */
3604 
3605 
3606 
3607 // explicit instantiations
3608 # include "trilinos_sparse_matrix.inst"
3609 
3610 
3611 // TODO: put these instantiations into generic file
3612 namespace TrilinosWrappers
3613 {
3614  template void
3615  SparseMatrix::reinit(const ::SparsityPattern &);
3616 
3617  template void
3619 
3620  template void
3621  SparseMatrix::reinit(const Epetra_Map &,
3622  const ::SparsityPattern &,
3623  const bool);
3624  template void
3625  SparseMatrix::reinit(const Epetra_Map &,
3626  const DynamicSparsityPattern &,
3627  const bool);
3628  template void
3629  SparseMatrix::reinit(const Epetra_Map &,
3630  const Epetra_Map &,
3631  const ::SparsityPattern &,
3632  const bool);
3633  template void
3634  SparseMatrix::reinit(const Epetra_Map &,
3635  const Epetra_Map &,
3636  const DynamicSparsityPattern &,
3637  const bool);
3638  template void
3640  const IndexSet &,
3641  const ::SparsityPattern &,
3642  const MPI_Comm &,
3643  const bool);
3644 
3645  template void
3647  const IndexSet &,
3648  const DynamicSparsityPattern &,
3649  const MPI_Comm &,
3650  const bool);
3651 
3652  template void
3653  SparseMatrix::vmult(MPI::Vector &, const MPI::Vector &) const;
3654  template void
3656  const ::Vector<double> &) const;
3657  template void
3660  const ::LinearAlgebra::distributed::Vector<double> &) const;
3661 # ifdef DEAL_II_WITH_MPI
3662  template void
3665  const ::LinearAlgebra::EpetraWrappers::Vector &) const;
3666 # endif
3667  template void
3668  SparseMatrix::Tvmult(MPI::Vector &, const MPI::Vector &) const;
3669  template void
3671  const ::Vector<double> &) const;
3672  template void
3675  const ::LinearAlgebra::distributed::Vector<double> &) const;
3676 # ifdef DEAL_II_WITH_MPI
3677  template void
3680  const ::LinearAlgebra::EpetraWrappers::Vector &) const;
3681 # endif
3682  template void
3684  template void
3686  const ::Vector<double> &) const;
3687  template void
3690  const ::LinearAlgebra::distributed::Vector<double> &) const;
3691 # ifdef DEAL_II_WITH_MPI
3692  template void
3695  const ::LinearAlgebra::EpetraWrappers::Vector &) const;
3696 # endif
3697  template void
3699  template void
3701  const ::Vector<double> &) const;
3702  template void
3705  const ::LinearAlgebra::distributed::Vector<double> &) const;
3706 # ifdef DEAL_II_WITH_MPI
3707  template void
3710  const ::LinearAlgebra::EpetraWrappers::Vector &) const;
3711 # endif
3712 } // namespace TrilinosWrappers
3713 
3714 DEAL_II_NAMESPACE_CLOSE
3715 
3716 #endif // DEAL_II_WITH_TRILINOS
size_type row_length(const size_type row) const
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:939
static::ExceptionBase & ExcTrilinosError(int arg1)
const Epetra_Map & row_partitioner() const
const Epetra_Map & domain_partitioner() const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
void Tmmult(SparseMatrix &C, const SparseMatrix &B, const MPI::Vector &V=MPI::Vector()) const
TrilinosScalar matrix_norm_square(const MPI::Vector &v) const
static::ExceptionBase & ExcSourceEqualsDestination()
const Epetra_CrsMatrix & trilinos_matrix() const
static::ExceptionBase & ExcIO()
void clear_row(const size_type row, const TrilinosScalar new_diag_value=0)
const Epetra_FEVector & trilinos_vector() const
static::ExceptionBase & ExcScalarAssignmentOnlyForZeroValue()
void vmult(VectorType &dst, const VectorType &src) const
std::function< void(VectorType &, const VectorType &)> inv_Tvmult
void reinit(const Vector &v, const bool omit_zeroing_entries=false, const bool allow_different_maps=false)
#define AssertIndexRange(index, range)
Definition: exceptions.h:1407
void mmult(SparseMatrix &C, const SparseMatrix &B, const MPI::Vector &V=MPI::Vector()) const
size_type n_elements() const
Definition: index_set.h:1743
TrilinosWrappers::types::int_type min_my_gid(const Epetra_BlockMap &map)
TrilinosScalar diag_element(const size_type i) const
STL namespace.
std::pair< size_type, size_type > local_range() const
static::ExceptionBase & ExcInvalidIndex(size_type arg1, size_type arg2)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
const Epetra_FECrsGraph & trilinos_sparsity_pattern() const
static::ExceptionBase & ExcAccessToNonPresentElement(size_type arg1, size_type arg2)
size_type size() const
Definition: index_set.h:1611
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
const Epetra_Comm & comm_self()
Definition: utilities.cc:779
static::ExceptionBase & ExcTrilinosError(int arg1)
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
std::unique_ptr< Epetra_CrsGraph > nonlocal_graph
static::ExceptionBase & ExcDivideByZero()
unsigned long long int global_dof_index
Definition: types.h:72
void clear_rows(const std::vector< size_type > &rows, const TrilinosScalar new_diag_value=0)
SparseMatrix & operator*=(const TrilinosScalar factor)
std::unique_ptr< Epetra_FECrsMatrix > matrix
TrilinosScalar matrix_scalar_product(const MPI::Vector &u, const MPI::Vector &v) const
virtual int Apply(const VectorType &X, VectorType &Y) const override
SparseMatrix & operator=(const SparseMatrix &)=delete
static::ExceptionBase & ExcAccessToNonlocalRow(std::size_t arg1)
::types::global_dof_index size_type
static::ExceptionBase & ExcMessage(std::string arg1)
TrilinosScalar el(const size_type i, const size_type j) const
size_type n() const
const IndexSet & row_index_set() const
Definition: types.h:31
void add(const size_type i, const size_type j, const TrilinosScalar value)
const Epetra_Map & domain_partitioner() const
#define Assert(cond, exc)
Definition: exceptions.h:1227
real_type l2_norm() const
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
std::unique_ptr< Epetra_Export > nonlocal_matrix_exporter
TrilinosWrappers::types::int_type n_global_cols(const Epetra_CrsGraph &graph)
TrilinosWrappers::types::int_type global_row_index(const Epetra_CrsMatrix &matrix, const ::types::global_dof_index i)
void Tvmult(VectorType &dst, const VectorType &src) const
std::function< void(VectorType &, const VectorType &)> inv_vmult
unsigned int local_size() const
TrilinosScalar operator()(const size_type i, const size_type j) const
const Epetra_Map & vector_partitioner() const
virtual int ApplyInverse(const VectorType &Y, VectorType &X) const override
size_type m() const
TrilinosWrappers::types::int_type global_column_index(const Epetra_CrsMatrix &matrix, const ::types::global_dof_index i)
Epetra_Map make_trilinos_map(const MPI_Comm &communicator=MPI_COMM_WORLD, const bool overlapping=false) const
Definition: index_set.cc:523
size_type column_number(const size_type row, const size_type index) const
static::ExceptionBase & ExcNotQuadratic()
TrilinosWrappers::types::int_type n_global_elements(const Epetra_BlockMap &map)
void swap(Vector< Number > &u, Vector< Number > &v)
Definition: vector.h:1353
void set_size(const size_type size)
Definition: index_set.h:1599
const Epetra_Map & range_partitioner() const
Epetra_Operator & trilinos_operator() const
Definition: cuda.h:32
size_type n_nonzero_elements() const
void reinit(const SparsityPatternType &sparsity_pattern)
const Epetra_CrsGraph & trilinos_sparsity_pattern() const
void copy_from(const SparseMatrix &source)
void vmult_add(VectorType &dst, const VectorType &src) const
SparseMatrix & operator/=(const TrilinosScalar factor)
unsigned int row_length(const size_type row) const
TrilinosWrappers::types::int_type max_my_gid(const Epetra_BlockMap &map)
const Epetra_Map & col_partitioner() const
static::ExceptionBase & ExcNotImplemented()
bool is_element(const size_type index) const
Definition: index_set.h:1676
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
static::ExceptionBase & ExcMatrixNotCompressed()
IndexSet locally_owned_range_indices() const
std::unique_ptr< Epetra_Map > column_space_map
void compress(::VectorOperation::values operation)
void print(std::ostream &out, const bool write_extended_trilinos_info=false) const
TrilinosScalar residual(MPI::Vector &dst, const MPI::Vector &x, const MPI::Vector &b) const
static::ExceptionBase & ExcAccessToNonLocalElement(size_type arg1, size_type arg2, size_type arg3, size_type arg4)
std::unique_ptr< Epetra_CrsMatrix > nonlocal_matrix
void reinit(const size_type m, const size_type n, const size_type n_entries_per_row=0)
void set(const size_type i, const size_type j, const TrilinosScalar value)
std::pair< size_type, size_type > local_range() const
void Tvmult_add(VectorType &dst, const VectorType &src) const
#define AssertIsFinite(number)
Definition: exceptions.h:1428
const Epetra_MultiVector & trilinos_vector() const
static::ExceptionBase & ExcInternalError()