Reference documentation for deal.II version 9.1.0-pre
packaged_operation.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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_packaged_operation_h
17 #define dealii_packaged_operation_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/exceptions.h>
22 
23 #include <deal.II/lac/vector_memory.h>
24 
25 #include <functional>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
29 // Forward declarations:
30 template <typename Number>
31 class Vector;
32 template <typename Range, typename Domain, typename Payload>
33 class LinearOperator;
34 template <typename Range = Vector<double>>
36 
37 
100 template <typename Range>
101 class PackagedOperation
102 {
103 public:
110  {
111  apply = [](Range &) {
112  Assert(false,
113  ExcMessage(
114  "Uninitialized PackagedOperation<Range>::apply called"));
115  };
116 
117  apply_add = [](Range &) {
118  Assert(false,
119  ExcMessage(
120  "Uninitialized PackagedOperation<Range>::apply_add called"));
121  };
122 
123  reinit_vector = [](Range &, bool) {
124  Assert(false,
125  ExcMessage("Uninitialized PackagedOperation<Range>::reinit_vector "
126  "method called"));
127  };
128  }
129 
133  PackagedOperation(const PackagedOperation<Range> &) = default;
134 
144  PackagedOperation(const Range &u)
145  {
146  *this = u;
147  }
148 
153  operator=(const PackagedOperation<Range> &) = default;
154 
165  operator=(const Range &u)
166  {
167  apply = [&u](Range &v) { v = u; };
168 
169  apply_add = [&u](Range &v) { v += u; };
170 
171  reinit_vector = [&u](Range &v, bool omit_zeroing_entries) {
172  v.reinit(u, omit_zeroing_entries);
173  };
174 
175  return *this;
176  }
177 
184  operator Range() const
185  {
186  Range result_vector;
187 
188  reinit_vector(result_vector, /*bool omit_zeroing_entries=*/true);
189  apply(result_vector);
190 
191  return result_vector;
192  }
193 
198 
204  {
205  *this = *this + second_comp;
206  return *this;
207  }
208 
215  {
216  *this = *this - second_comp;
217  return *this;
218  }
219 
225  operator+=(const Range &offset)
226  {
227  *this = *this + PackagedOperation<Range>(offset);
228  return *this;
229  }
230 
236  operator-=(const Range &offset)
237  {
238  *this = *this - PackagedOperation<Range>(offset);
239  return *this;
240  }
241 
246  operator*=(typename Range::value_type number)
247  {
248  *this = *this * number;
249  return *this;
250  }
252 
257  std::function<void(Range &v)> apply;
258 
263  std::function<void(Range &v)> apply_add;
264 
272  std::function<void(Range &v, bool omit_zeroing_entries)> reinit_vector;
273 };
274 
275 
280 
289 template <typename Range>
292  const PackagedOperation<Range> &second_comp)
293 {
294  PackagedOperation<Range> return_comp;
295 
296  return_comp.reinit_vector = first_comp.reinit_vector;
297 
298  // ensure to have valid PackagedOperation objects by catching first_comp and
299  // second_comp by value
300 
301  return_comp.apply = [first_comp, second_comp](Range &v) {
302  first_comp.apply(v);
303  second_comp.apply_add(v);
304  };
305 
306  return_comp.apply_add = [first_comp, second_comp](Range &v) {
307  first_comp.apply_add(v);
308  second_comp.apply_add(v);
309  };
310 
311  return return_comp;
312 }
313 
322 template <typename Range>
325  const PackagedOperation<Range> &second_comp)
326 {
327  PackagedOperation<Range> return_comp;
328 
329  return_comp.reinit_vector = first_comp.reinit_vector;
330 
331  // ensure to have valid PackagedOperation objects by catching first_comp and
332  // second_comp by value
333 
334  return_comp.apply = [first_comp, second_comp](Range &v) {
335  second_comp.apply(v);
336  v *= -1.;
337  first_comp.apply_add(v);
338  };
339 
340  return_comp.apply_add = [first_comp, second_comp](Range &v) {
341  first_comp.apply_add(v);
342  v *= -1.;
343  second_comp.apply_add(v);
344  v *= -1.;
345  };
346 
347  return return_comp;
348 }
349 
358 template <typename Range>
360  typename Range::value_type number)
361 {
362  PackagedOperation<Range> return_comp;
363 
364  return_comp.reinit_vector = comp.reinit_vector;
365 
366  // the trivial case: number is zero
367  if (number == 0.)
368  {
369  return_comp.apply = [](Range &v) { v = 0.; };
370 
371  return_comp.apply_add = [](Range &) {};
372  }
373  else
374  {
375  return_comp.apply = [comp, number](Range &v) {
376  comp.apply(v);
377  v *= number;
378  };
379 
380  return_comp.apply_add = [comp, number](Range &v) {
381  v /= number;
382  comp.apply_add(v);
383  v *= number;
384  };
385  }
386 
387  return return_comp;
388 }
389 
398 template <typename Range>
399 PackagedOperation<Range> operator*(typename Range::value_type number,
400  const PackagedOperation<Range> &comp)
401 {
402  return comp * number;
403 }
404 
413 template <typename Range>
415 operator+(const PackagedOperation<Range> &comp, const Range &offset)
416 {
417  return comp + PackagedOperation<Range>(offset);
418 }
419 
428 template <typename Range>
430 operator+(const Range &offset, const PackagedOperation<Range> &comp)
431 {
432  return PackagedOperation<Range>(offset) + comp;
433 }
434 
443 template <typename Range>
445 operator-(const PackagedOperation<Range> &comp, const Range &offset)
446 {
447  return comp - PackagedOperation<Range>(offset);
448 }
449 
450 
460 template <typename Range>
462 operator-(const Range &offset, const PackagedOperation<Range> &comp)
463 {
464  return PackagedOperation<Range>(offset) - comp;
465 }
466 
468 
469 
474 
475 namespace internal
476 {
477  namespace PackagedOperationImplementation
478  {
479  // Poor man's trait class that determines whether type T is a vector:
480  // FIXME: Implement this as a proper type trait - similar to
481  // isBlockVector
482 
483  template <typename T>
484  class has_vector_interface
485  {
486  template <typename C>
487  static std::false_type
488  test(...);
489 
490  template <typename C>
491  static std::true_type
492  test(decltype(&C::operator+=),
493  decltype(&C::operator-=),
494  decltype(&C::l2_norm));
495 
496  public:
497  // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
498  // otherwise it is std::false_type
499 
500  using type = decltype(test<T>(nullptr, nullptr, nullptr));
501  }; // namespace
502  } // namespace PackagedOperationImplementation
503 } // namespace internal
504 
505 
520 template <typename Range,
521  typename = typename std::enable_if<
522  internal::PackagedOperationImplementation::has_vector_interface<
523  Range>::type::value>::type>
525 operator+(const Range &u, const Range &v)
526 {
527  PackagedOperation<Range> return_comp;
528 
529  // ensure to have valid PackagedOperation objects by catching op by value
530  // u is caught by reference
531 
532  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
533  x.reinit(u, omit_zeroing_entries);
534  };
535 
536  return_comp.apply = [&u, &v](Range &x) {
537  x = u;
538  x += v;
539  };
540 
541  return_comp.apply_add = [&u, &v](Range &x) {
542  x += u;
543  x += v;
544  };
545 
546  return return_comp;
547 }
548 
549 
565 template <typename Range,
566  typename = typename std::enable_if<
567  internal::PackagedOperationImplementation::has_vector_interface<
568  Range>::type::value>::type>
570 operator-(const Range &u, const Range &v)
571 {
572  PackagedOperation<Range> return_comp;
573 
574  // ensure to have valid PackagedOperation objects by catching op by value
575  // u is caught by reference
576 
577  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
578  x.reinit(u, omit_zeroing_entries);
579  };
580 
581  return_comp.apply = [&u, &v](Range &x) {
582  x = u;
583  x -= v;
584  };
585 
586  return_comp.apply_add = [&u, &v](Range &x) {
587  x += u;
588  x -= v;
589  };
590 
591  return return_comp;
592 }
593 
594 
609 template <typename Range,
610  typename = typename std::enable_if<
611  internal::PackagedOperationImplementation::has_vector_interface<
612  Range>::type::value>::type>
614  typename Range::value_type number)
615 {
616  return PackagedOperation<Range>(u) * number;
617 }
618 
619 
634 template <typename Range,
635  typename = typename std::enable_if<
636  internal::PackagedOperationImplementation::has_vector_interface<
637  Range>::type::value>::type>
638 PackagedOperation<Range> operator*(typename Range::value_type number,
639  const Range & u)
640 {
641  return number * PackagedOperation<Range>(u);
642 }
643 
644 
661 template <typename Range, typename Domain, typename Payload>
664 {
665  PackagedOperation<Range> return_comp;
666 
667  return_comp.reinit_vector = op.reinit_range_vector;
668 
669  // ensure to have valid PackagedOperation objects by catching op by value
670  // u is caught by reference
671 
672  return_comp.apply = [op, &u](Range &v) { op.vmult(v, u); };
673 
674  return_comp.apply_add = [op, &u](Range &v) { op.vmult_add(v, u); };
675 
676  return return_comp;
677 }
678 
679 
696 template <typename Range, typename Domain, typename Payload>
699 {
700  PackagedOperation<Range> return_comp;
701 
702  return_comp.reinit_vector = op.reinit_domain_vector;
703 
704  // ensure to have valid PackagedOperation objects by catching op by value
705  // u is caught by reference
706 
707  return_comp.apply = [op, &u](Domain &v) { op.Tvmult(v, u); };
708 
709  return_comp.apply_add = [op, &u](Domain &v) { op.Tvmult_add(v, u); };
710 
711  return return_comp;
712 }
713 
714 
723 template <typename Range, typename Domain, typename Payload>
726  const PackagedOperation<Domain> & comp)
727 {
728  PackagedOperation<Range> return_comp;
729 
730  return_comp.reinit_vector = op.reinit_range_vector;
731 
732  // ensure to have valid PackagedOperation objects by catching op by value
733  // u is caught by reference
734 
735  return_comp.apply = [op, comp](Domain &v) {
736  GrowingVectorMemory<Range> vector_memory;
737 
738  typename VectorMemory<Range>::Pointer i(vector_memory);
739  op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/true);
740 
741  comp.apply(*i);
742  op.vmult(v, *i);
743  };
744 
745  return_comp.apply_add = [op, comp](Domain &v) {
746  GrowingVectorMemory<Range> vector_memory;
747 
748  typename VectorMemory<Range>::Pointer i(vector_memory);
749  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
750 
751  comp.apply(*i);
752  op.vmult_add(v, *i);
753  };
754 
755  return return_comp;
756 }
757 
758 
767 template <typename Range, typename Domain, typename Payload>
771 {
772  PackagedOperation<Range> return_comp;
773 
774  return_comp.reinit_vector = op.reinit_domain_vector;
775 
776  // ensure to have valid PackagedOperation objects by catching op by value
777  // u is caught by reference
778 
779  return_comp.apply = [op, comp](Domain &v) {
780  GrowingVectorMemory<Range> vector_memory;
781 
782  typename VectorMemory<Range>::Pointer i(vector_memory);
783  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
784 
785  comp.apply(*i);
786  op.Tvmult(v, *i);
787  };
788 
789  return_comp.apply_add = [op, comp](Domain &v) {
790  GrowingVectorMemory<Range> vector_memory;
791 
792  typename VectorMemory<Range>::Pointer i(vector_memory);
793  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
794 
795  comp.apply(*i);
796  op.Tvmult_add(v, *i);
797  };
798 
799  return return_comp;
800 }
801 
803 
804 DEAL_II_NAMESPACE_CLOSE
805 
806 #endif
PackagedOperation< Range > & operator+=(const PackagedOperation< Range > &second_comp)
PackagedOperation(const Range &u)
std::function< void(Range &v)> apply
std::function< void(Range &v, bool omit_zeroing_entries)> 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
PackagedOperation< Range > & operator-=(const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > & operator=(const PackagedOperation< Range > &)=default
static::ExceptionBase & ExcMessage(std::string arg1)
PackagedOperation< Range > & operator=(const Range &u)
#define Assert(cond, exc)
Definition: exceptions.h:1227
std::function< void(Range &v, const Domain &u)> vmult
PackagedOperation< Range > operator-(const PackagedOperation< Range > &first_comp, const PackagedOperation< Range > &second_comp)
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
PackagedOperation< Range > & operator*=(typename Range::value_type number)
std::function< void(Range &v)> apply_add
std::function< void(Range &v, const Domain &u)> vmult_add
PackagedOperation< Range > & operator+=(const Range &offset)
PackagedOperation< Range > operator*(const PackagedOperation< Range > &comp, typename Range::value_type number)
PackagedOperation< Range > operator+(const PackagedOperation< Range > &first_comp, const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > & operator-=(const Range &offset)