Reference documentation for deal.II version 9.0.0
linear_operator.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2014 - 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_linear_operator_h
17 #define dealii_linear_operator_h
18 
19 #include <deal.II/base/config.h>
20 #include <deal.II/base/exceptions.h>
21 #include <deal.II/lac/vector_memory.h>
22 
23 #include <array>
24 #include <functional>
25 #include <type_traits>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
29 // Forward declarations:
30 
31 namespace internal
32 {
33  namespace LinearOperatorImplementation
34  {
35  class EmptyPayload;
36  }
37 }
38 
39 template <typename Number> class Vector;
40 
41 template <typename Range = Vector<double>,
42  typename Domain = Range,
43  typename Payload = internal::LinearOperatorImplementation::EmptyPayload>
45 
46 template <typename Range = Vector<double>,
47  typename Domain = Range,
48  typename Payload = internal::LinearOperatorImplementation::EmptyPayload,
49  typename OperatorExemplar,
50  typename Matrix>
52  const Matrix &);
53 
54 template <typename Range = Vector<double>,
55  typename Domain = Range,
56  typename Payload = internal::LinearOperatorImplementation::EmptyPayload,
57  typename Matrix>
59 
60 template <typename Range = Vector<double>,
61  typename Domain = Range,
62  typename Payload = internal::LinearOperatorImplementation::EmptyPayload>
65 
66 
149 template <typename Range, typename Domain, typename Payload>
150 class LinearOperator
151  : public Payload
152 {
153 public:
154 
163  LinearOperator(const Payload &payload = Payload())
164  :
165  Payload (payload),
166  is_null_operator(false)
167  {
168 
169  vmult = [](Range &, const Domain &)
170  {
171  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
172  "Domain>::vmult called"));
173  };
174 
175  vmult_add = [](Range &, const Domain &)
176  {
177  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
178  "Domain>::vmult_add called"));
179  };
180 
181  Tvmult = [](Domain &, const Range &)
182  {
183  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
184  "Domain>::Tvmult called"));
185  };
186 
187  Tvmult_add = [](Domain &, const Range &)
188  {
189  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
190  "Domain>::Tvmult_add called"));
191  };
192 
193  reinit_range_vector = [](Range &, bool)
194  {
195  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
196  "Domain>::reinit_range_vector method called"));
197  };
198 
199  reinit_domain_vector = [](Domain &, bool)
200  {
201  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
202  "Domain>::reinit_domain_vector method called"));
203  };
204  }
205 
210 
216  template <typename Op,
217  typename = typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
218  LinearOperator (const Op &op)
219  {
220  *this = linear_operator<Range, Domain, Payload, Op>(op);
221  }
222 
228 
233  template <typename Op,
234  typename = typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
236  {
237  *this = linear_operator<Range, Domain, Payload, Op>(op);
238  return *this;
239  }
240 
245  std::function<void(Range &v, const Domain &u)> vmult;
246 
251  std::function<void(Range &v, const Domain &u)> vmult_add;
252 
257  std::function<void(Domain &v, const Range &u)> Tvmult;
258 
263  std::function<void(Domain &v, const Range &u)> Tvmult_add;
264 
272  std::function<void(Range &v, bool omit_zeroing_entries)> reinit_range_vector;
273 
281  std::function<void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector;
282 
287 
294  {
295  *this = *this + second_op;
296  return *this;
297  }
298 
305  {
306  *this = *this - second_op;
307  return *this;
308  }
309 
316  {
317  *this = *this * second_op;
318  return *this;
319  }
320 
326  operator*=(typename Domain::value_type number)
327  {
328  *this = *this * number;
329  return *this;
330  }
331 
338 
340 };
341 
342 
347 
357 template <typename Range, typename Domain, typename Payload>
361 {
362  if (first_op.is_null_operator)
363  {
364  return second_op;
365  }
366  else if (second_op.is_null_operator)
367  {
368  return first_op;
369  }
370  else
371  {
373  static_cast<const Payload &>(first_op) + static_cast<const Payload &>(second_op)
374  );
375 
376  return_op.reinit_range_vector = first_op.reinit_range_vector;
377  return_op.reinit_domain_vector = first_op.reinit_domain_vector;
378 
379  // ensure to have valid computation objects by catching first_op and
380  // second_op by value
381 
382  return_op.vmult = [first_op, second_op](Range &v, const Domain &u)
383  {
384  first_op.vmult(v, u);
385  second_op.vmult_add(v, u);
386  };
387 
388  return_op.vmult_add = [first_op, second_op](Range &v, const Domain &u)
389  {
390  first_op.vmult_add(v, u);
391  second_op.vmult_add(v, u);
392  };
393 
394  return_op.Tvmult = [first_op, second_op](Domain &v, const Range &u)
395  {
396  second_op.Tvmult(v, u);
397  first_op.Tvmult_add(v, u);
398  };
399 
400  return_op.Tvmult_add = [first_op, second_op](Domain &v, const Range &u)
401  {
402  second_op.Tvmult_add(v, u);
403  first_op.Tvmult_add(v, u);
404  };
405 
406  return return_op;
407  }
408 }
409 
410 
420 template <typename Range, typename Domain, typename Payload>
424 {
425  if (first_op.is_null_operator)
426  {
427  return -1. * second_op;
428  }
429  else if (second_op.is_null_operator)
430  {
431  return first_op;
432  }
433  else
434  {
435  // implement with addition and scalar multiplication
436  return first_op + (-1. * second_op);
437  }
438 }
439 
440 
458 template <typename Range, typename Domain, typename Payload>
460 operator*(typename Range::value_type number,
462 {
463  static_assert(
464  std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
465  "Range and Domain must have implicitly convertible 'value_type's");
466 
467  if (op.is_null_operator)
468  {
469  return op;
470  }
471  else if (number == 0.)
472  {
473  return null_operator(op);
474  }
475  else
476  {
478 
479  // ensure to have valid computation objects by catching number and op by
480  // value
481 
482  return_op.vmult = [number, op](Range &v, const Domain &u)
483  {
484  op.vmult(v,u);
485  v *= number;
486  };
487 
488  return_op.vmult_add = [number, op](Range &v, const Domain &u)
489  {
490  v /= number;
491  op.vmult_add(v,u);
492  v *= number;
493  };
494 
495  return_op.Tvmult = [number, op](Domain &v, const Range &u)
496  {
497  op.Tvmult(v,u);
498  v *= number;
499  };
500 
501  return_op.Tvmult_add = [number, op](Domain &v, const Range &u)
502  {
503  v /= number;
504  op.Tvmult_add(v,u);
505  v *= number;
506  };
507 
508  return return_op;
509  }
510 }
511 
512 
528 template <typename Range, typename Domain, typename Payload>
531  typename Domain::value_type number)
532 {
533  static_assert(
534  std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
535  "Range and Domain must have implicitly convertible 'value_type's");
536 
537  return number * op;
538 }
539 
541 
542 
547 
557 template <typename Range, typename Intermediate, typename Domain, typename Payload>
561 {
562  if (first_op.is_null_operator || second_op.is_null_operator)
563  {
565  return_op.reinit_domain_vector = second_op.reinit_domain_vector;
566  return_op.reinit_range_vector = first_op.reinit_range_vector;
567  return null_operator(return_op);
568  }
569  else
570  {
572  static_cast<const Payload &>(first_op) * static_cast<const Payload &>(second_op)
573  );
574 
575  return_op.reinit_domain_vector = second_op.reinit_domain_vector;
576  return_op.reinit_range_vector = first_op.reinit_range_vector;
577 
578  // ensure to have valid computation objects by catching first_op and
579  // second_op by value
580 
581  return_op.vmult = [first_op, second_op](Range &v, const Domain &u)
582  {
583  GrowingVectorMemory<Intermediate> vector_memory;
584 
585  typename VectorMemory<Intermediate>::Pointer i (vector_memory);
586  second_op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
587  second_op.vmult(*i, u);
588  first_op.vmult(v, *i);
589  };
590 
591  return_op.vmult_add = [first_op, second_op](Range &v, const Domain &u)
592  {
593  GrowingVectorMemory<Intermediate> vector_memory;
594 
595  typename VectorMemory<Intermediate>::Pointer i (vector_memory);
596  second_op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
597  second_op.vmult(*i, u);
598  first_op.vmult_add(v, *i);
599  };
600 
601  return_op.Tvmult = [first_op, second_op](Domain &v, const Range &u)
602  {
603  GrowingVectorMemory<Intermediate> vector_memory;
604 
605  typename VectorMemory<Intermediate>::Pointer i (vector_memory);
606  first_op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/ true);
607  first_op.Tvmult(*i, u);
608  second_op.Tvmult(v, *i);
609  };
610 
611  return_op.Tvmult_add = [first_op, second_op](Domain &v, const Range &u)
612  {
613  GrowingVectorMemory<Intermediate> vector_memory;
614 
615  typename VectorMemory<Intermediate>::Pointer i (vector_memory);
616  first_op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/ true);
617  first_op.Tvmult(*i, u);
618  second_op.Tvmult_add(v, *i);
619  };
620 
621  return return_op;
622  }
623 }
624 
634 template <typename Range, typename Domain, typename Payload>
637 {
639  op.transpose_payload()
640  );
641 
643  return_op.reinit_domain_vector = op.reinit_range_vector;
644 
645  return_op.vmult = op.Tvmult;
646  return_op.vmult_add = op.Tvmult_add;
647  return_op.Tvmult = op.vmult;
648  return_op.Tvmult_add = op.vmult_add;
649 
650  return return_op;
651 }
652 
653 
674 template <typename Payload,
675  typename Solver, typename Preconditioner,
676  typename Range = typename Solver::vector_type, typename Domain = Range>
679  Solver &solver,
680  const Preconditioner &preconditioner)
681 {
683  op.inverse_payload(solver, preconditioner)
684  );
685 
687  return_op.reinit_domain_vector = op.reinit_range_vector;
688 
689  return_op.vmult = [op, &solver, &preconditioner](Range &v, const Domain &u)
690  {
691  op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/ false);
692  solver.solve(op, v, u, preconditioner);
693  };
694 
695  return_op.vmult_add =
696  [op, &solver, &preconditioner](Range &v, const Domain &u)
697  {
698  GrowingVectorMemory<Range> vector_memory;
699 
700  typename VectorMemory<Range>::Pointer v2 (vector_memory);
701  op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/ false);
702  solver.solve(op, *v2, u, preconditioner);
703  v += *v2;
704  };
705 
706  return_op.Tvmult = [op, &solver, &preconditioner](Range &v, const Domain &u)
707  {
708  op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/ false);
709  solver.solve(transpose_operator(op), v, u, preconditioner);
710  };
711 
712  return_op.Tvmult_add =
713  [op, &solver, &preconditioner](Range &v, const Domain &u)
714  {
715  GrowingVectorMemory<Range> vector_memory;
716 
717  typename VectorMemory<Range>::Pointer v2 (vector_memory);
718  op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/ false);
719  solver.solve(transpose_operator(op), *v2, u, preconditioner);
720  v += *v2;
721  };
722 
723  return return_op;
724 }
725 
727 
728 
733 
745 template <typename Range,
748 identity_operator(const std::function<void(Range &, bool)> &reinit_vector)
749 {
750  LinearOperator<Range, Range, Payload> return_op ((Payload()));
751 
752  return_op.reinit_range_vector = reinit_vector;
753  return_op.reinit_domain_vector = reinit_vector;
754 
755  return_op.vmult = [](Range &v, const Range &u)
756  {
757  v = u;
758  };
759 
760  return_op.vmult_add = [](Range &v, const Range &u)
761  {
762  v += u;
763  };
764 
765  return_op.Tvmult = [](Range &v, const Range &u)
766  {
767  v = u;
768  };
769 
770  return_op.Tvmult_add = [](Range &v, const Range &u)
771  {
772  v += u;
773  };
774 
775  return return_op;
776 }
777 
778 
791 template <typename Range, typename Domain, typename Payload>
794 {
795  auto return_op = identity_operator<Range, Payload>(op.reinit_range_vector);
796  static_cast<Payload &>(return_op) = op.identity_payload();
797 
798  return return_op;
799 }
800 
801 
811 template <typename Range, typename Domain, typename Payload>
814 {
816  op.null_payload()
817  );
818 
819  return_op.is_null_operator = true;
820 
821  return_op.reinit_range_vector = op.reinit_range_vector;
822  return_op.reinit_domain_vector = op.reinit_domain_vector;
823 
824  return_op.vmult = [](Range &v, const Domain &)
825  {
826  v = 0.;
827  };
828 
829  return_op.vmult_add = [](Range &, const Domain &)
830  {};
831 
832  return_op.Tvmult = [](Domain &v, const Range &)
833  {
834  v = 0.;
835  };
836 
837  return_op.Tvmult_add = [](Domain &, const Range &)
838  {};
839 
840  return return_op;
841 }
842 
843 
856 template <typename Range,
859 mean_value_filter(const std::function<void(Range &, bool)> &reinit_vector)
860 {
861  LinearOperator<Range, Range, Payload> return_op ((Payload()));
862 
863  return_op.reinit_range_vector = reinit_vector;
864  return_op.reinit_domain_vector = reinit_vector;
865 
866  return_op.vmult = [](Range &v, const Range &u)
867  {
868  const auto mean = u.mean_value();
869 
870  v = u;
871  v.add(-mean);
872  };
873 
874  return_op.vmult_add = [](Range &v, const Range &u)
875  {
876  const auto mean = u.mean_value();
877 
878  v += u;
879  v.add(-mean);
880  };
881 
882  return_op.Tvmult = return_op.vmult_add;
883  return_op.Tvmult_add = return_op.vmult_add;
884 
885  return return_op;
886 }
887 
888 
901 template <typename Range, typename Domain, typename Payload>
904 {
905  auto return_op = mean_value_filter<Range, Payload>(op.reinit_range_vector);
906  static_cast<Payload &>(return_op) = op.identity_payload();
907 
908  return return_op;
909 }
910 
911 
912 namespace internal
913 {
914  namespace LinearOperatorImplementation
915  {
927  template <typename Vector>
928  class ReinitHelper
929  {
930  public:
942  template <typename Matrix>
943  static
944  void reinit_range_vector (const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
945  {
946  v.reinit(matrix.m(), omit_zeroing_entries);
947  }
948 
960  template <typename Matrix>
961  static
962  void reinit_domain_vector (const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
963  {
964  v.reinit(matrix.n(), omit_zeroing_entries);
965  }
966  };
967 
968 
982  {
983  public:
984 
992  template <typename... Args>
993  EmptyPayload (const Args &...)
994  { }
995 
996 
1000  EmptyPayload
1002  {
1003  return *this;
1004  }
1005 
1006 
1010  EmptyPayload
1011  null_payload () const
1012  {
1013  return *this;
1014  }
1015 
1016 
1020  EmptyPayload
1022  {
1023  return *this;
1024  }
1025 
1026 
1030  template <typename Solver, typename Preconditioner>
1031  EmptyPayload
1032  inverse_payload (Solver &, const Preconditioner &) const
1033  {
1034  return *this;
1035  }
1036  };
1037 
1042  inline
1043  EmptyPayload operator+(const EmptyPayload &,
1044  const EmptyPayload &)
1045  {
1046  return EmptyPayload();
1047  }
1048 
1053  inline
1054  EmptyPayload operator*(const EmptyPayload &,
1055  const EmptyPayload &)
1056  {
1057  return EmptyPayload();
1058  }
1059 
1060  } /* namespace LinearOperator */
1061 } /* namespace internal */
1062 
1063 
1064 namespace
1065 {
1066  // A trait class that determines whether type T provides public
1067  // (templated or non-templated) vmult_add member functions
1068  template <typename Range, typename Domain, typename T>
1069  class has_vmult_add_and_Tvmult_add
1070  {
1071  template <typename C>
1072  static std::false_type test(...);
1073 
1074  template <typename C>
1075  static auto test(Range *r, Domain *d)
1076  -> decltype(std::declval<C>().vmult_add(*r,*d),
1077  std::declval<C>().Tvmult_add(*d,*r),
1078  std::true_type());
1079 
1080  public:
1081  // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
1082  // otherwise it is std::false_type
1083 
1084  typedef decltype(test<T>(nullptr, nullptr)) type;
1085  };
1086 
1087 
1088  // A helper function to apply a given vmult, or Tvmult to a vector with
1089  // intermediate storage
1090  template <typename Function, typename Range, typename Domain>
1091  void apply_with_intermediate_storage(Function function, Range &v,
1092  const Domain &u, bool add)
1093  {
1094  GrowingVectorMemory<Range> vector_memory;
1095 
1096  typename VectorMemory<Range>::Pointer i (vector_memory);
1097  i->reinit(v, /*bool omit_zeroing_entries =*/true);
1098 
1099  function(*i, u);
1100 
1101  if (add)
1102  v += *i;
1103  else
1104  v = *i;
1105  }
1106 
1107 
1108  // A helper class to add a reduced matrix interface to a LinearOperator
1109  // (typically provided by Preconditioner classes)
1110  template <typename Range, typename Domain, typename Payload>
1111  class MatrixInterfaceWithoutVmultAdd
1112  {
1113  public:
1114  template <typename Matrix>
1115  void operator()(LinearOperator<Range, Domain, Payload> &op, const Matrix &matrix)
1116  {
1117  op.vmult = [&matrix](Range &v, const Domain &u)
1118  {
1119  if (PointerComparison::equal(&v, &u))
1120  {
1121  // If v and u are the same memory location use intermediate storage
1122  apply_with_intermediate_storage([&matrix](Range &b, const Domain &a)
1123  {
1124  matrix.vmult(b, a);
1125  },
1126  v, u, /*bool add =*/ false);
1127  }
1128  else
1129  {
1130  matrix.vmult(v,u);
1131  }
1132  };
1133 
1134  op.vmult_add = [&matrix](Range &v, const Domain &u)
1135  {
1136  // use intermediate storage to implement vmult_add with vmult
1137  apply_with_intermediate_storage([&matrix](Range &b, const Domain &a)
1138  {
1139  matrix.vmult(b, a);
1140  },
1141  v, u, /*bool add =*/ true);
1142  };
1143 
1144  op.Tvmult = [&matrix](Domain &v, const Range &u)
1145  {
1146  if (PointerComparison::equal(&v, &u))
1147  {
1148  // If v and u are the same memory location use intermediate storage
1149  apply_with_intermediate_storage([&matrix](Domain &b, const Range &a)
1150  {
1151  matrix.Tvmult(b, a);
1152  },
1153  v, u, /*bool add =*/ false);
1154  }
1155  else
1156  {
1157  matrix.Tvmult(v,u);
1158  }
1159 
1160  };
1161 
1162  op.Tvmult_add = [&matrix](Domain &v, const Range &u)
1163  {
1164  // use intermediate storage to implement Tvmult_add with Tvmult
1165  apply_with_intermediate_storage([&matrix](Domain &b, const Range &a)
1166  {
1167  matrix.Tvmult(b, a);
1168  },
1169  v, u, /*bool add =*/ true);
1170  };
1171  }
1172  };
1173 
1174 
1175  // A helper class to add the full matrix interface to a LinearOperator
1176  template <typename Range, typename Domain, typename Payload>
1177  class MatrixInterfaceWithVmultAdd
1178  {
1179  public:
1180  template <typename Matrix>
1181  void operator()(LinearOperator<Range, Domain, Payload> &op, const Matrix &matrix)
1182  {
1183  // As above ...
1184 
1185  MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>().operator()(op, matrix);
1186 
1187  // ... but add native vmult_add and Tvmult_add variants:
1188 
1189  op.vmult_add = [&matrix](Range &v, const Domain &u)
1190  {
1191  if (PointerComparison::equal(&v, &u))
1192  {
1193  apply_with_intermediate_storage([&matrix](Range &b, const Domain &a)
1194  {
1195  matrix.vmult(b, a);
1196  },
1197  v, u, /*bool add =*/ false);
1198  }
1199  else
1200  {
1201  matrix.vmult_add(v,u);
1202  }
1203  };
1204 
1205  op.Tvmult_add = [&matrix](Domain &v, const Range &u)
1206  {
1207  if (PointerComparison::equal(&v, &u))
1208  {
1209  apply_with_intermediate_storage([&matrix](Domain &b, const Range &a)
1210  {
1211  matrix.Tvmult(b, a);
1212  },
1213  v, u, /*bool add =*/ true);
1214  }
1215  else
1216  {
1217  matrix.Tvmult_add(v,u);
1218  }
1219  };
1220  }
1221  };
1222 
1223 } /* namespace */
1224 
1225 
1283 template <typename Range, typename Domain,
1284  typename Payload, typename Matrix>
1286 linear_operator(const Matrix &matrix)
1287 {
1288  // implement with the more generic variant below...
1289  return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix, matrix);
1290 }
1291 
1292 
1308 template <typename Range,
1309  typename Domain,
1310  typename Payload,
1311  typename OperatorExemplar,
1312  typename Matrix>
1314 linear_operator(const OperatorExemplar &operator_exemplar, const Matrix &matrix)
1315 {
1316  // Initialize the payload based on the input exemplar matrix
1317  LinearOperator<Range, Domain, Payload> return_op (Payload(operator_exemplar,matrix));
1318 
1319  // Always store a reference to matrix and operator_exemplar in the lambda
1320  // functions. This ensures that a modification of the matrix after the
1321  // creation of a LinearOperator wrapper is respected - further a matrix
1322  // or an operator_exemplar cannot usually be copied...
1323 
1324  return_op.reinit_range_vector = [&operator_exemplar](Range &v, bool omit_zeroing_entries)
1325  {
1327  };
1328 
1329  return_op.reinit_domain_vector = [&operator_exemplar](Domain &v, bool omit_zeroing_entries)
1330  {
1332  };
1333 
1334  typename std::conditional<
1335  has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1336  MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1337  MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type().
1338  operator()(return_op, matrix);
1339 
1340  return return_op;
1341 }
1342 
1343 
1344 
1362 template <typename Range,
1363  typename Domain,
1364  typename Payload,
1365  typename Matrix>
1368  const Matrix &matrix)
1369 {
1370  // Initialize the payload based on the LinearOperator exemplar
1371  auto return_op = operator_exemplar;
1372 
1373  typename std::conditional<
1374  has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1375  MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1376  MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type().
1377  operator()(return_op, matrix);
1378 
1379  return return_op;
1380 }
1381 
1382 
1384 
1385 
1386 DEAL_II_NAMESPACE_CLOSE
1387 
1388 #endif
Contents is actually a matrix.
LinearOperator< Range, Range, Payload > mean_value_filter(const std::function< void(Range &, bool)> &reinit_vector)
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Domain &v, const Range &u)> Tvmult_add
std::function< void(Domain &v, const Range &u)> Tvmult
LinearOperator< Range, Domain, Payload > operator*=(typename Domain::value_type number)
LinearOperator< Range, Domain, Payload > operator+(const LinearOperator< Range, Domain, Payload > &first_op, const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator< Range, Domain, Payload > & operator*=(const LinearOperator< Domain, Domain, Payload > &second_op)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
LinearOperator< Range, Domain, Payload > & operator=(const LinearOperator< Range, Domain, Payload > &)=default
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Domain, Payload > null_operator(const LinearOperator< Range, Domain, Payload > &op)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
static void reinit_domain_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
std::function< void(Range &v, const Domain &u)> vmult
LinearOperator< Range, Domain, Payload > & operator=(const Op &op)
LinearOperator< Range, Domain, Payload > & operator-=(const LinearOperator< Range, Domain, Payload > &second_op)
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
LinearOperator< Range, Domain, Payload > operator*(typename Range::value_type number, const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
Definition: solver.h:322
VectorType vector_type
Definition: solver.h:328
std::function< void(Range &v, const Domain &u)> vmult_add
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
LinearOperator< Range, Domain, Payload > & operator+=(const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator(const Payload &payload=Payload())
Point< dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const OtherNumber) const
static bool equal(const T *p1, const T *p2)
LinearOperator< Range, Domain, Payload > linear_operator(const Matrix &matrix)
LinearOperator(const Op &op)