Reference documentation for deal.II version 9.0.0
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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_packaged_operation_h
17 #define dealii_packaged_operation_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 <functional>
24 
25 DEAL_II_NAMESPACE_OPEN
26 
27 // Forward declarations:
28 template <typename Number> class Vector;
29 template <typename Range, typename Domain, typename Payload> class LinearOperator;
30 template <typename Range = Vector<double> > class PackagedOperation;
31 
32 
95 template <typename Range> class PackagedOperation
96 {
97 public:
98 
105  {
106  apply = [](Range &)
107  {
108  Assert(false,
109  ExcMessage("Uninitialized PackagedOperation<Range>::apply called"));
110  };
111 
112  apply_add = [](Range &)
113  {
114  Assert(false,
115  ExcMessage("Uninitialized PackagedOperation<Range>::apply_add called"));
116  };
117 
118  reinit_vector = [](Range &, bool)
119  {
120  Assert(false,
121  ExcMessage("Uninitialized PackagedOperation<Range>::reinit_vector "
122  "method called"));
123  };
124  }
125 
129  PackagedOperation (const PackagedOperation<Range> &) = default;
130 
140  PackagedOperation (const Range &u)
141  {
142  *this = u;
143  }
144 
149 
160  {
161  apply = [&u](Range &v)
162  {
163  v = u;
164  };
165 
166  apply_add = [&u](Range &v)
167  {
168  v += u;
169  };
170 
171  reinit_vector = [&u](Range &v, bool omit_zeroing_entries)
172  {
173  v.reinit(u, omit_zeroing_entries);
174  };
175 
176  return *this;
177  }
178 
185  operator Range() const
186  {
187  Range result_vector;
188 
189  reinit_vector(result_vector, /*bool omit_zeroing_entries=*/ true);
190  apply(result_vector);
191 
192  return result_vector;
193  }
194 
199 
204  {
205  *this = *this + second_comp;
206  return *this;
207  }
208 
214  {
215  *this = *this - second_comp;
216  return *this;
217  }
218 
223  PackagedOperation<Range> &operator+=(const Range &offset)
224  {
225  *this = *this + PackagedOperation<Range>(offset);
226  return *this;
227  }
228 
233  PackagedOperation<Range> &operator-=(const Range &offset)
234  {
235  *this = *this - PackagedOperation<Range>(offset);
236  return *this;
237  }
238 
242  PackagedOperation<Range> &operator*=(typename Range::value_type number)
243  {
244  *this = *this * number;
245  return *this;
246  }
248 
253  std::function<void(Range &v)> apply;
254 
259  std::function<void(Range &v)> apply_add;
260 
268  std::function<void(Range &v, bool omit_zeroing_entries)> reinit_vector;
269 };
270 
271 
276 
285 template <typename Range>
288  const PackagedOperation<Range> &second_comp)
289 {
290  PackagedOperation<Range> return_comp;
291 
292  return_comp.reinit_vector = first_comp.reinit_vector;
293 
294  // ensure to have valid PackagedOperation objects by catching first_comp and
295  // second_comp by value
296 
297  return_comp.apply = [first_comp, second_comp](Range &v)
298  {
299  first_comp.apply(v);
300  second_comp.apply_add(v);
301  };
302 
303  return_comp.apply_add = [first_comp, second_comp](Range &v)
304  {
305  first_comp.apply_add(v);
306  second_comp.apply_add(v);
307  };
308 
309  return return_comp;
310 }
311 
320 template <typename Range>
323  const PackagedOperation<Range> &second_comp)
324 {
325  PackagedOperation<Range> return_comp;
326 
327  return_comp.reinit_vector = first_comp.reinit_vector;
328 
329  // ensure to have valid PackagedOperation objects by catching first_comp and
330  // second_comp by value
331 
332  return_comp.apply = [first_comp, second_comp](Range &v)
333  {
334  second_comp.apply(v);
335  v *= -1.;
336  first_comp.apply_add(v);
337  };
338 
339  return_comp.apply_add = [first_comp, second_comp](Range &v)
340  {
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>
361  typename Range::value_type number)
362 {
363  PackagedOperation<Range> return_comp;
364 
365  return_comp.reinit_vector = comp.reinit_vector;
366 
367  // the trivial case: number is zero
368  if (number == 0.)
369  {
370  return_comp.apply = [](Range &v)
371  {
372  v = 0.;
373  };
374 
375  return_comp.apply_add = [](Range &)
376  {
377  };
378  }
379  else
380  {
381  return_comp.apply = [comp, number](Range &v)
382  {
383  comp.apply(v);
384  v *= number;
385  };
386 
387  return_comp.apply_add = [comp, number](Range &v)
388  {
389  v /= number;
390  comp.apply_add(v);
391  v *= number;
392  };
393  }
394 
395  return return_comp;
396 }
397 
406 template <typename Range>
408 operator*(typename Range::value_type number,
409  const PackagedOperation<Range> &comp)
410 {
411  return comp * number;
412 }
413 
422 template <typename Range>
424  const Range &offset)
425 {
426  return comp + PackagedOperation<Range>(offset);
427 }
428 
437 template <typename Range>
439  const PackagedOperation<Range> &comp)
440 {
441  return PackagedOperation<Range>(offset) + comp;
442 }
443 
452 template <typename Range>
454  const Range &offset)
455 {
456  return comp - PackagedOperation<Range>(offset);
457 }
458 
459 
469 template <typename Range>
471  const PackagedOperation<Range> &comp)
472 {
473  return PackagedOperation<Range>(offset) - comp;
474 }
475 
477 
478 
483 
484 namespace
485 {
486  // Poor man's trait class that determines whether type T is a vector:
487  // FIXME: Implement this as a proper type trait - similar to
488  // isBlockVector
489 
490  template <typename T>
491  class has_vector_interface
492  {
493  template <typename C>
494  static std::false_type test(...);
495 
496  template <typename C>
497  static std::true_type test(decltype(&C::operator+=),
498  decltype(&C::operator-=),
499  decltype(&C::l2_norm));
500 
501  public:
502  // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
503  // otherwise it is std::false_type
504 
505  typedef decltype(test<T>(nullptr, nullptr, nullptr)) type;
506  };
507 }
508 
509 
524 template <typename Range,
525  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
526 PackagedOperation<Range> operator+(const Range &u, const Range &v)
527 {
528  PackagedOperation<Range> return_comp;
529 
530  // ensure to have valid PackagedOperation objects by catching op by value
531  // u is caught by reference
532 
533  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries)
534  {
535  x.reinit(u, omit_zeroing_entries);
536  };
537 
538  return_comp.apply = [&u, &v](Range &x)
539  {
540  x = u;
541  x += v;
542  };
543 
544  return_comp.apply_add = [&u, &v](Range &x)
545  {
546  x += u;
547  x += v;
548  };
549 
550  return return_comp;
551 }
552 
553 
569 template <typename Range,
570  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
571 PackagedOperation<Range> operator-(const Range &u, const Range &v)
572 {
573  PackagedOperation<Range> return_comp;
574 
575  // ensure to have valid PackagedOperation objects by catching op by value
576  // u is caught by reference
577 
578  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries)
579  {
580  x.reinit(u, omit_zeroing_entries);
581  };
582 
583  return_comp.apply = [&u, &v](Range &x)
584  {
585  x = u;
586  x -= v;
587  };
588 
589  return_comp.apply_add = [&u, &v](Range &x)
590  {
591  x += u;
592  x -= v;
593  };
594 
595  return return_comp;
596 }
597 
598 
613 template <typename Range,
614  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
616  typename Range::value_type number)
617 {
618  return PackagedOperation<Range>(u) * number;
619 }
620 
621 
636 template <typename Range,
637  typename = typename std::enable_if<has_vector_interface<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  const Domain &u)
665 {
666  PackagedOperation<Range> return_comp;
667 
668  return_comp.reinit_vector = op.reinit_range_vector;
669 
670  // ensure to have valid PackagedOperation objects by catching op by value
671  // u is caught by reference
672 
673  return_comp.apply = [op, &u](Range &v)
674  {
675  op.vmult(v, u);
676  };
677 
678  return_comp.apply_add = [op, &u](Range &v)
679  {
680  op.vmult_add(v, u);
681  };
682 
683  return return_comp;
684 }
685 
686 
703 template <typename Range, typename Domain, typename Payload>
705 operator*(const Range &u,
707 {
708  PackagedOperation<Range> return_comp;
709 
710  return_comp.reinit_vector = op.reinit_domain_vector;
711 
712  // ensure to have valid PackagedOperation objects by catching op by value
713  // u is caught by reference
714 
715  return_comp.apply = [op, &u](Domain &v)
716  {
717  op.Tvmult(v, u);
718  };
719 
720  return_comp.apply_add = [op, &u](Domain &v)
721  {
722  op.Tvmult_add(v, u);
723  };
724 
725  return return_comp;
726 }
727 
728 
737 template <typename Range, typename Domain, typename Payload>
740  const PackagedOperation<Domain> &comp)
741 {
742  PackagedOperation<Range> return_comp;
743 
744  return_comp.reinit_vector = op.reinit_range_vector;
745 
746  // ensure to have valid PackagedOperation objects by catching op by value
747  // u is caught by reference
748 
749  return_comp.apply = [op, comp](Domain &v)
750  {
751  GrowingVectorMemory<Range> vector_memory;
752 
753  typename VectorMemory<Range>::Pointer i (vector_memory);
754  op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/ true);
755 
756  comp.apply(*i);
757  op.vmult(v, *i);
758  };
759 
760  return_comp.apply_add = [op, comp](Domain &v)
761  {
762  GrowingVectorMemory<Range> vector_memory;
763 
764  typename VectorMemory<Range>::Pointer i (vector_memory);
765  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
766 
767  comp.apply(*i);
768  op.vmult_add(v, *i);
769  };
770 
771  return return_comp;
772 }
773 
774 
783 template <typename Range, typename Domain, typename Payload>
787 {
788  PackagedOperation<Range> return_comp;
789 
790  return_comp.reinit_vector = op.reinit_domain_vector;
791 
792  // ensure to have valid PackagedOperation objects by catching op by value
793  // u is caught by reference
794 
795  return_comp.apply = [op, comp](Domain &v)
796  {
797  GrowingVectorMemory<Range> vector_memory;
798 
799  typename VectorMemory<Range>::Pointer i (vector_memory);
800  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
801 
802  comp.apply(*i);
803  op.Tvmult(v, *i);
804  };
805 
806  return_comp.apply_add = [op, comp](Domain &v)
807  {
808  GrowingVectorMemory<Range> vector_memory;
809 
810  typename VectorMemory<Range>::Pointer i (vector_memory);
811  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
812 
813  comp.apply(*i);
814  op.Tvmult_add(v, *i);
815  };
816 
817  return return_comp;
818 }
819 
821 
822 DEAL_II_NAMESPACE_CLOSE
823 
824 #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
STL namespace.
PackagedOperation< Range > & operator-=(const PackagedOperation< Range > &second_comp)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
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:1142
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)
Point< dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const OtherNumber) const
PackagedOperation< Range > & operator-=(const Range &offset)