Reference documentation for deal.II version 8.5.1
linear_operator.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2014 - 2017 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 #ifdef DEAL_II_WITH_CXX11
24 
25 #include <array>
26 #include <functional>
27 #include <type_traits>
28 
29 DEAL_II_NAMESPACE_OPEN
30 
31 // Forward declarations:
32 
33 namespace internal
34 {
35  namespace LinearOperator
36  {
37  class EmptyPayload;
38  }
39 }
40 
41 template <typename Number> class Vector;
42 
43 template <typename Range = Vector<double>,
44  typename Domain = Range,
45  typename Payload = internal::LinearOperator::EmptyPayload>
47 
48 template <typename Range = Vector<double>,
49  typename Domain = Range,
50  typename Payload = internal::LinearOperator::EmptyPayload,
51  typename OperatorExemplar,
52  typename Matrix>
54  const Matrix &);
55 
56 template <typename Range = Vector<double>,
57  typename Domain = Range,
58  typename Payload = internal::LinearOperator::EmptyPayload,
59  typename Matrix>
61 
62 template <typename Range = Vector<double>,
63  typename Domain = Range,
64  typename Payload = internal::LinearOperator::EmptyPayload>
67 
68 
155 template <typename Range, typename Domain, typename Payload>
156 class LinearOperator
157  : public Payload
158 {
159 public:
160 
169  LinearOperator(const Payload &payload = Payload())
170  :
171  Payload (payload),
172  is_null_operator(false)
173  {
174 
175  vmult = [](Range &, const Domain &)
176  {
177  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
178  "Domain>::vmult called"));
179  };
180 
181  vmult_add = [](Range &, const Domain &)
182  {
183  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
184  "Domain>::vmult_add called"));
185  };
186 
187  Tvmult = [](Domain &, const Range &)
188  {
189  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
190  "Domain>::Tvmult called"));
191  };
192 
193  Tvmult_add = [](Domain &, const Range &)
194  {
195  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
196  "Domain>::Tvmult_add called"));
197  };
198 
199  reinit_range_vector = [](Range &, bool)
200  {
201  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
202  "Domain>::reinit_range_vector method called"));
203  };
204 
205  reinit_domain_vector = [](Domain &, bool)
206  {
207  Assert(false, ExcMessage("Uninitialized LinearOperator<Range, "
208  "Domain>::reinit_domain_vector method called"));
209  };
210  }
211 
216 
222  template<typename Op,
223  typename = typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
224  LinearOperator (const Op &op)
225  {
226  *this = linear_operator<Range, Domain, Payload, Op>(op);
227  }
228 
234 
239  template <typename Op,
240  typename = typename std::enable_if<!std::is_base_of<LinearOperator<Range, Domain, Payload>, Op>::value>::type>
242  {
243  *this = linear_operator<Range, Domain, Payload, Op>(op);
244  return *this;
245  }
246 
251  std::function<void(Range &v, const Domain &u)> vmult;
252 
257  std::function<void(Range &v, const Domain &u)> vmult_add;
258 
263  std::function<void(Domain &v, const Range &u)> Tvmult;
264 
269  std::function<void(Domain &v, const Range &u)> Tvmult_add;
270 
278  std::function<void(Range &v, bool omit_zeroing_entries)> reinit_range_vector;
279 
287  std::function<void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector;
288 
293 
300  {
301  *this = *this + second_op;
302  return *this;
303  }
304 
311  {
312  *this = *this - second_op;
313  return *this;
314  }
315 
322  {
323  *this = *this * second_op;
324  return *this;
325  }
326 
332  operator*=(typename Domain::value_type number)
333  {
334  *this = *this * number;
335  return *this;
336  }
337 
344 
346 };
347 
348 
353 
363 template <typename Range, typename Domain, typename Payload>
367 {
368  if (first_op.is_null_operator)
369  {
370  return second_op;
371  }
372  else if (second_op.is_null_operator)
373  {
374  return first_op;
375  }
376  else
377  {
379  static_cast<const Payload &>(first_op) + static_cast<const Payload &>(second_op)
380  );
381 
382  return_op.reinit_range_vector = first_op.reinit_range_vector;
383  return_op.reinit_domain_vector = first_op.reinit_domain_vector;
384 
385  // ensure to have valid computation objects by catching first_op and
386  // second_op by value
387 
388  return_op.vmult = [first_op, second_op](Range &v, const Domain &u)
389  {
390  first_op.vmult(v, u);
391  second_op.vmult_add(v, u);
392  };
393 
394  return_op.vmult_add = [first_op, second_op](Range &v, const Domain &u)
395  {
396  first_op.vmult_add(v, u);
397  second_op.vmult_add(v, u);
398  };
399 
400  return_op.Tvmult = [first_op, second_op](Domain &v, const Range &u)
401  {
402  second_op.Tvmult(v, u);
403  first_op.Tvmult_add(v, u);
404  };
405 
406  return_op.Tvmult_add = [first_op, second_op](Domain &v, const Range &u)
407  {
408  second_op.Tvmult_add(v, u);
409  first_op.Tvmult_add(v, u);
410  };
411 
412  return return_op;
413  }
414 }
415 
416 
426 template <typename Range, typename Domain, typename Payload>
430 {
431  if (first_op.is_null_operator)
432  {
433  return -1. * second_op;
434  }
435  else if (second_op.is_null_operator)
436  {
437  return first_op;
438  }
439  else
440  {
441  // implement with addition and scalar multiplication
442  return first_op + (-1. * second_op);
443  }
444 }
445 
446 
464 template <typename Range, typename Domain, typename Payload>
466 operator*(typename Range::value_type number,
468 {
469  static_assert(
470  std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
471  "Range and Domain must have implicitly convertible 'value_type's");
472 
473  if (op.is_null_operator)
474  {
475  return op;
476  }
477  else if (number == 0.)
478  {
479  return null_operator(op);
480  }
481  else
482  {
484 
485  // ensure to have valid computation objects by catching number and op by
486  // value
487 
488  return_op.vmult = [number, op](Range &v, const Domain &u)
489  {
490  op.vmult(v,u);
491  v *= number;
492  };
493 
494  return_op.vmult_add = [number, op](Range &v, const Domain &u)
495  {
496  v /= number;
497  op.vmult_add(v,u);
498  v *= number;
499  };
500 
501  return_op.Tvmult = [number, op](Domain &v, const Range &u)
502  {
503  op.Tvmult(v,u);
504  v *= number;
505  };
506 
507  return_op.Tvmult_add = [number, op](Domain &v, const Range &u)
508  {
509  v /= number;
510  op.Tvmult_add(v,u);
511  v *= number;
512  };
513 
514  return return_op;
515  }
516 }
517 
518 
534 template <typename Range, typename Domain, typename Payload>
537  typename Domain::value_type number)
538 {
539  static_assert(
540  std::is_convertible<typename Range::value_type, typename Domain::value_type>::value,
541  "Range and Domain must have implicitly convertible 'value_type's");
542 
543  return number * op;
544 }
545 
547 
548 
553 
563 template <typename Range, typename Intermediate, typename Domain, typename Payload>
567 {
568  if (first_op.is_null_operator || second_op.is_null_operator)
569  {
571  return_op.reinit_domain_vector = second_op.reinit_domain_vector;
572  return_op.reinit_range_vector = first_op.reinit_range_vector;
573  return null_operator(return_op);
574  }
575  else
576  {
578  static_cast<const Payload &>(first_op) * static_cast<const Payload &>(second_op)
579  );
580 
581  return_op.reinit_domain_vector = second_op.reinit_domain_vector;
582  return_op.reinit_range_vector = first_op.reinit_range_vector;
583 
584  // ensure to have valid computation objects by catching first_op and
585  // second_op by value
586 
587  return_op.vmult = [first_op, second_op](Range &v, const Domain &u)
588  {
589  static GrowingVectorMemory<Intermediate> vector_memory;
590 
591  Intermediate *i = vector_memory.alloc();
592  second_op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
593  second_op.vmult(*i, u);
594  first_op.vmult(v, *i);
595  vector_memory.free(i);
596  };
597 
598  return_op.vmult_add = [first_op, second_op](Range &v, const Domain &u)
599  {
600  static GrowingVectorMemory<Intermediate> vector_memory;
601 
602  Intermediate *i = vector_memory.alloc();
603  second_op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
604  second_op.vmult(*i, u);
605  first_op.vmult_add(v, *i);
606  vector_memory.free(i);
607  };
608 
609  return_op.Tvmult = [first_op, second_op](Domain &v, const Range &u)
610  {
611  static GrowingVectorMemory<Intermediate> vector_memory;
612 
613  Intermediate *i = vector_memory.alloc();
614  first_op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/ true);
615  first_op.Tvmult(*i, u);
616  second_op.Tvmult(v, *i);
617  vector_memory.free(i);
618  };
619 
620  return_op.Tvmult_add = [first_op, second_op](Domain &v, const Range &u)
621  {
622  static GrowingVectorMemory<Intermediate> vector_memory;
623 
624  Intermediate *i = vector_memory.alloc();
625  first_op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/ true);
626  first_op.Tvmult(*i, u);
627  second_op.Tvmult_add(v, *i);
628  vector_memory.free(i);
629  };
630 
631  return return_op;
632  }
633 }
634 
644 template <typename Range, typename Domain, typename Payload>
647 {
649  op.transpose_payload()
650  );
651 
653  return_op.reinit_domain_vector = op.reinit_range_vector;
654 
655  return_op.vmult = op.Tvmult;
656  return_op.vmult_add = op.Tvmult_add;
657  return_op.Tvmult = op.vmult;
658  return_op.Tvmult_add = op.vmult_add;
659 
660  return return_op;
661 }
662 
663 
684 template <typename Payload,
685  typename Solver, typename Preconditioner,
686  typename Range = typename Solver::vector_type, typename Domain = Range>
689  Solver &solver,
690  const Preconditioner &preconditioner)
691 {
693  op.inverse_payload(solver, preconditioner)
694  );
695 
697  return_op.reinit_domain_vector = op.reinit_range_vector;
698 
699  return_op.vmult = [op, &solver, &preconditioner](Range &v, const Domain &u)
700  {
701  op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/ false);
702  solver.solve(op, v, u, preconditioner);
703  };
704 
705  return_op.vmult_add =
706  [op, &solver, &preconditioner](Range &v, const Domain &u)
707  {
708  static GrowingVectorMemory<Range> vector_memory;
709 
710  Range *v2 = vector_memory.alloc();
711  op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/ false);
712  solver.solve(op, *v2, u, preconditioner);
713  v += *v2;
714  vector_memory.free(v2);
715  };
716 
717  return_op.Tvmult = [op, &solver, &preconditioner](Range &v, const Domain &u)
718  {
719  op.reinit_range_vector(v, /*bool omit_zeroing_entries =*/ false);
720  solver.solve(transpose_operator(op), v, u, preconditioner);
721  };
722 
723  return_op.Tvmult_add =
724  [op, &solver, &preconditioner](Range &v, const Domain &u)
725  {
726  static GrowingVectorMemory<Range> vector_memory;
727 
728  Range *v2 = vector_memory.alloc();
729  op.reinit_range_vector(*v2, /*bool omit_zeroing_entries =*/ false);
730  solver.solve(transpose_operator(op), *v2, u, preconditioner);
731  v += *v2;
732  vector_memory.free(v2);
733  };
734 
735  return return_op;
736 }
737 
739 
740 
745 
757 template <typename Range,
758  typename Payload = internal::LinearOperator::EmptyPayload>
760 identity_operator(const std::function<void(Range &, bool)> &reinit_vector)
761 {
762  LinearOperator<Range, Range, Payload> return_op ((Payload()));
763 
764  return_op.reinit_range_vector = reinit_vector;
765  return_op.reinit_domain_vector = reinit_vector;
766 
767  return_op.vmult = [](Range &v, const Range &u)
768  {
769  v = u;
770  };
771 
772  return_op.vmult_add = [](Range &v, const Range &u)
773  {
774  v += u;
775  };
776 
777  return_op.Tvmult = [](Range &v, const Range &u)
778  {
779  v = u;
780  };
781 
782  return_op.Tvmult_add = [](Range &v, const Range &u)
783  {
784  v += u;
785  };
786 
787  return return_op;
788 }
789 
790 
803 template <typename Range, typename Domain, typename Payload>
806 {
808  = identity_operator<Range,Payload>(op.reinit_range_vector);
810  op.identity_payload()
811  );
812 
813  return_op.reinit_range_vector = id_op.reinit_range_vector;
814  return_op.reinit_domain_vector = id_op.reinit_domain_vector;
815  return_op.vmult = id_op.vmult;
816  return_op.vmult_add = id_op.vmult_add;
817  return_op.Tvmult = id_op.Tvmult;
818  return_op.Tvmult_add = id_op.Tvmult_add;
819 
820  return return_op;
821 }
822 
823 
833 template <typename Range, typename Domain, typename Payload>
836 {
838  op.null_payload()
839  );
840 
841  return_op.is_null_operator = true;
842 
843  return_op.reinit_range_vector = op.reinit_range_vector;
844  return_op.reinit_domain_vector = op.reinit_domain_vector;
845 
846  return_op.vmult = [](Range &v, const Domain &)
847  {
848  v = 0.;
849  };
850 
851  return_op.vmult_add = [](Range &, const Domain &)
852  {};
853 
854  return_op.Tvmult = [](Domain &v, const Range &)
855  {
856  v = 0.;
857  };
858 
859  return_op.Tvmult_add = [](Domain &, const Range &)
860  {};
861 
862  return return_op;
863 }
864 
865 
866 namespace internal
867 {
868  namespace LinearOperator
869  {
881  template<typename Vector>
882  class ReinitHelper
883  {
884  public:
896  template <typename Matrix>
897  static
898  void reinit_range_vector (const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
899  {
900  v.reinit(matrix.m(), omit_zeroing_entries);
901  }
902 
914  template <typename Matrix>
915  static
916  void reinit_domain_vector (const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
917  {
918  v.reinit(matrix.n(), omit_zeroing_entries);
919  }
920  };
921 
922 
936  {
937  public:
938 
946  template <typename... Args>
947  EmptyPayload (const Args &...)
948  { }
949 
950 
956  {
957  return *this;
958  }
959 
960 
965  null_payload () const
966  {
967  return *this;
968  }
969 
970 
976  {
977  return *this;
978  }
979 
980 
984  template <typename Solver, typename Preconditioner>
986  inverse_payload (Solver &, const Preconditioner &) const
987  {
988  return *this;
989  }
990  };
991 
996  inline
997  EmptyPayload operator+(const EmptyPayload &,
998  const EmptyPayload &)
999  {
1000  return EmptyPayload();
1001  }
1002 
1007  inline
1008  EmptyPayload operator*(const EmptyPayload &,
1009  const EmptyPayload &)
1010  {
1011  return EmptyPayload();
1012  }
1013 
1014  } /* namespace LinearOperator */
1015 } /* namespace internal */
1016 
1017 
1018 namespace
1019 {
1020  // A trait class that determines whether type T provides public
1021  // (templated or non-templated) vmult_add member functions
1022  template <typename Range, typename Domain, typename T>
1023  class has_vmult_add_and_Tvmult_add
1024  {
1025  template <typename C>
1026  static std::false_type test(...);
1027 
1028  template <typename C>
1029  static auto test(Range *r, Domain *d)
1030  -> decltype(std::declval<C>().vmult_add(*r,*d),
1031  std::declval<C>().Tvmult_add(*d,*r),
1032  std::true_type());
1033 
1034  public:
1035  // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
1036  // otherwise it is std::false_type
1037 
1038  typedef decltype(test<T>(nullptr, nullptr)) type;
1039  };
1040 
1041 
1042  // A helper function to apply a given vmult, or Tvmult to a vector with
1043  // intermediate storage
1044  template <typename Function, typename Range, typename Domain>
1045  void apply_with_intermediate_storage(Function function, Range &v,
1046  const Domain &u, bool add)
1047  {
1048  static GrowingVectorMemory<Range> vector_memory;
1049 
1050  Range *i = vector_memory.alloc();
1051  i->reinit(v, /*bool omit_zeroing_entries =*/true);
1052 
1053  function(*i, u);
1054 
1055  if (add)
1056  v += *i;
1057  else
1058  v = *i;
1059 
1060  vector_memory.free(i);
1061  }
1062 
1063 
1064  // A helper class to add a reduced matrix interface to a LinearOperator
1065  // (typically provided by Preconditioner classes)
1066  template <typename Range, typename Domain, typename Payload>
1067  class MatrixInterfaceWithoutVmultAdd
1068  {
1069  public:
1070  template <typename Matrix>
1071  void operator()(LinearOperator<Range, Domain, Payload> &op, const Matrix &matrix)
1072  {
1073  op.vmult = [&matrix](Range &v, const Domain &u)
1074  {
1075  if (PointerComparison::equal(&v, &u))
1076  {
1077  // If v and u are the same memory location use intermediate storage
1078  apply_with_intermediate_storage([&matrix](Range &b, const Domain &a)
1079  {
1080  matrix.vmult(b, a);
1081  },
1082  v, u, /*bool add =*/ false);
1083  }
1084  else
1085  {
1086  matrix.vmult(v,u);
1087  }
1088  };
1089 
1090  op.vmult_add = [&matrix](Range &v, const Domain &u)
1091  {
1092  // use intermediate storage to implement vmult_add with vmult
1093  apply_with_intermediate_storage([&matrix](Range &b, const Domain &a)
1094  {
1095  matrix.vmult(b, a);
1096  },
1097  v, u, /*bool add =*/ true);
1098  };
1099 
1100  op.Tvmult = [&matrix](Domain &v, const Range &u)
1101  {
1102  if (PointerComparison::equal(&v, &u))
1103  {
1104  // If v and u are the same memory location use intermediate storage
1105  apply_with_intermediate_storage([&matrix](Domain &b, const Range &a)
1106  {
1107  matrix.Tvmult(b, a);
1108  },
1109  v, u, /*bool add =*/ false);
1110  }
1111  else
1112  {
1113  matrix.Tvmult(v,u);
1114  }
1115 
1116  };
1117 
1118  op.Tvmult_add = [&matrix](Domain &v, const Range &u)
1119  {
1120  // use intermediate storage to implement Tvmult_add with Tvmult
1121  apply_with_intermediate_storage([&matrix](Domain &b, const Range &a)
1122  {
1123  matrix.Tvmult(b, a);
1124  },
1125  v, u, /*bool add =*/ true);
1126  };
1127  }
1128  };
1129 
1130 
1131  // A helper class to add the full matrix interface to a LinearOperator
1132  template <typename Range, typename Domain, typename Payload>
1133  class MatrixInterfaceWithVmultAdd
1134  {
1135  public:
1136  template <typename Matrix>
1137  void operator()(LinearOperator<Range, Domain, Payload> &op, const Matrix &matrix)
1138  {
1139  // As above ...
1140 
1141  MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>().operator()(op, matrix);
1142 
1143  // ... but add native vmult_add and Tvmult_add variants:
1144 
1145  op.vmult_add = [&matrix](Range &v, const Domain &u)
1146  {
1147  if (PointerComparison::equal(&v, &u))
1148  {
1149  apply_with_intermediate_storage([&matrix](Range &b, const Domain &a)
1150  {
1151  matrix.vmult(b, a);
1152  },
1153  v, u, /*bool add =*/ false);
1154  }
1155  else
1156  {
1157  matrix.vmult_add(v,u);
1158  }
1159  };
1160 
1161  op.Tvmult_add = [&matrix](Domain &v, const Range &u)
1162  {
1163  if (PointerComparison::equal(&v, &u))
1164  {
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  else
1172  {
1173  matrix.Tvmult_add(v,u);
1174  }
1175  };
1176  }
1177  };
1178 
1179 } /* namespace */
1180 
1181 
1239 template <typename Range, typename Domain,
1240  typename Payload, typename Matrix>
1242 linear_operator(const Matrix &matrix)
1243 {
1244  // implement with the more generic variant below...
1245  return linear_operator<Range, Domain, Payload, Matrix, Matrix>(matrix, matrix);
1246 }
1247 
1248 
1264 template <typename Range,
1265  typename Domain,
1266  typename Payload,
1267  typename OperatorExemplar,
1268  typename Matrix>
1270 linear_operator(const OperatorExemplar &operator_exemplar, const Matrix &matrix)
1271 {
1272  // Initialise the payload based on the input exemplar matrix
1273  LinearOperator<Range, Domain, Payload> return_op (Payload(operator_exemplar,matrix));
1274 
1275  // Always store a reference to matrix and operator_exemplar in the lambda
1276  // functions. This ensures that a modification of the matrix after the
1277  // creation of a LinearOperator wrapper is respected - further a matrix
1278  // or an operator_exemplar cannot usually be copied...
1279 
1280  return_op.reinit_range_vector = [&operator_exemplar](Range &v, bool omit_zeroing_entries)
1281  {
1282  internal::LinearOperator::ReinitHelper<Range>::reinit_range_vector(operator_exemplar, v, omit_zeroing_entries);
1283  };
1284 
1285  return_op.reinit_domain_vector = [&operator_exemplar](Domain &v, bool omit_zeroing_entries)
1286  {
1287  internal::LinearOperator::ReinitHelper<Domain>::reinit_domain_vector(operator_exemplar, v, omit_zeroing_entries);
1288  };
1289 
1290  typename std::conditional<
1291  has_vmult_add_and_Tvmult_add<Range, Domain, Matrix>::type::value,
1292  MatrixInterfaceWithVmultAdd<Range, Domain, Payload>,
1293  MatrixInterfaceWithoutVmultAdd<Range, Domain, Payload>>::type().
1294  operator()(return_op, matrix);
1295 
1296  return return_op;
1297 }
1298 
1299 
1301 
1302 
1303 DEAL_II_NAMESPACE_CLOSE
1304 
1305 #endif // DEAL_II_WITH_CXX11
1306 #endif
EmptyPayload inverse_payload(Solver &, const Preconditioner &) const
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)
static void reinit_domain_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)
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual VectorType * alloc()
#define Assert(cond, exc)
Definition: exceptions.h:313
static bool equal(const T *p1, const T *p2)
std::function< void(Range &v, const Domain &u)> vmult
virtual void free(const VectorType *const)
LinearOperator< Range, Domain, Payload > operator*(const LinearOperator< Range, Intermediate, Payload > &first_op, const LinearOperator< Intermediate, Domain, Payload > &second_op)
LinearOperator< Range, Domain, Payload > & operator=(const Op &op)
LinearOperator< Range, Domain, Payload > & operator-=(const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator< Range, Domain, Payload > operator*(const LinearOperator< Range, Domain, Payload > &op, typename Domain::value_type number)
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)
static void reinit_range_vector(const Matrix &matrix, Vector &v, bool omit_zeroing_entries)
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
LinearOperator< Range, Domain, Payload > operator-(const LinearOperator< Range, Domain, Payload > &first_op, const LinearOperator< Range, Domain, Payload > &second_op)
Definition: solver.h:325
VectorType vector_type
Definition: solver.h:331
std::function< void(Range &v, const Domain &u)> vmult_add
LinearOperator< Range, Domain, Payload > identity_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &operator_exemplar, const Matrix &matrix)
LinearOperator< Range, Domain, Payload > & operator+=(const LinearOperator< Range, Domain, Payload > &second_op)
LinearOperator(const Payload &payload=Payload())
LinearOperator< Range, Domain, Payload > linear_operator(const Matrix &matrix)
LinearOperator(const Op &op)