Reference documentation for deal.II version 8.5.1
packaged_operation.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__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 #ifdef DEAL_II_WITH_CXX11
24 
25 #include <functional>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
29 // Forward declarations:
30 template <typename Number> class Vector;
31 template <typename Range, typename Domain, typename Payload> class LinearOperator;
32 template <typename Range = Vector<double> > class PackagedOperation;
33 
34 
97 template <typename Range> class PackagedOperation
98 {
99 public:
100 
107  {
108  apply = [](Range &)
109  {
110  Assert(false,
111  ExcMessage("Uninitialized PackagedOperation<Range>::apply called"));
112  };
113 
114  apply_add = [](Range &)
115  {
116  Assert(false,
117  ExcMessage("Uninitialized PackagedOperation<Range>::apply_add called"));
118  };
119 
120  reinit_vector = [](Range &, bool)
121  {
122  Assert(false,
123  ExcMessage("Uninitialized PackagedOperation<Range>::reinit_vector "
124  "method called"));
125  };
126  }
127 
131  PackagedOperation (const PackagedOperation<Range> &) = default;
132 
142  PackagedOperation (const Range &u)
143  {
144  *this = u;
145  }
146 
151 
162  {
163  apply = [&u](Range &v)
164  {
165  v = u;
166  };
167 
168  apply_add = [&u](Range &v)
169  {
170  v += u;
171  };
172 
173  reinit_vector = [&u](Range &v, bool omit_zeroing_entries)
174  {
175  v.reinit(u, omit_zeroing_entries);
176  };
177 
178  return *this;
179  }
180 
187  operator Range() const
188  {
189  Range result_vector;
190 
191  reinit_vector(result_vector, /*bool omit_zeroing_entries=*/ true);
192  apply(result_vector);
193 
194  return result_vector;
195  }
196 
201 
206  {
207  *this = *this + second_comp;
208  return *this;
209  }
210 
216  {
217  *this = *this - second_comp;
218  return *this;
219  }
220 
225  PackagedOperation<Range> &operator+=(const Range &offset)
226  {
227  *this = *this + PackagedOperation<Range>(offset);
228  return *this;
229  }
230 
235  PackagedOperation<Range> &operator-=(const Range &offset)
236  {
237  *this = *this - PackagedOperation<Range>(offset);
238  return *this;
239  }
240 
244  PackagedOperation<Range> &operator*=(typename Range::value_type number)
245  {
246  *this = *this * number;
247  return *this;
248  }
250 
255  std::function<void(Range &v)> apply;
256 
261  std::function<void(Range &v)> apply_add;
262 
270  std::function<void(Range &v, bool omit_zeroing_entries)> reinit_vector;
271 };
272 
273 
278 
287 template <typename Range>
290  const PackagedOperation<Range> &second_comp)
291 {
292  PackagedOperation<Range> return_comp;
293 
294  return_comp.reinit_vector = first_comp.reinit_vector;
295 
296  // ensure to have valid PackagedOperation objects by catching first_comp and
297  // second_comp by value
298 
299  return_comp.apply = [first_comp, second_comp](Range &v)
300  {
301  first_comp.apply(v);
302  second_comp.apply_add(v);
303  };
304 
305  return_comp.apply_add = [first_comp, second_comp](Range &v)
306  {
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  {
336  second_comp.apply(v);
337  v *= -1.;
338  first_comp.apply_add(v);
339  };
340 
341  return_comp.apply_add = [first_comp, second_comp](Range &v)
342  {
343  first_comp.apply_add(v);
344  v *= -1.;
345  second_comp.apply_add(v);
346  v *= -1.;
347  };
348 
349  return return_comp;
350 }
351 
360 template <typename Range>
363  typename Range::value_type number)
364 {
365  PackagedOperation<Range> return_comp;
366 
367  return_comp.reinit_vector = comp.reinit_vector;
368 
369  // the trivial case: number is zero
370  if (number == 0.)
371  {
372  return_comp.apply = [](Range &v)
373  {
374  v = 0.;
375  };
376 
377  return_comp.apply_add = [](Range &)
378  {
379  };
380  }
381  else
382  {
383  return_comp.apply = [comp, number](Range &v)
384  {
385  comp.apply(v);
386  v *= number;
387  };
388 
389  return_comp.apply_add = [comp, number](Range &v)
390  {
391  v /= number;
392  comp.apply_add(v);
393  v *= number;
394  };
395  }
396 
397  return return_comp;
398 }
399 
408 template <typename Range>
410 operator*(typename Range::value_type number,
411  const PackagedOperation<Range> &comp)
412 {
413  return comp * number;
414 }
415 
424 template <typename Range>
426  const Range &offset)
427 {
428  return comp + PackagedOperation<Range>(offset);
429 }
430 
439 template <typename Range>
441  const PackagedOperation<Range> &comp)
442 {
443  return PackagedOperation<Range>(offset) + comp;
444 }
445 
454 template <typename Range>
456  const Range &offset)
457 {
458  return comp - PackagedOperation<Range>(offset);
459 }
460 
461 
471 template <typename Range>
473  const PackagedOperation<Range> &comp)
474 {
475  return PackagedOperation<Range>(offset) - comp;
476 }
477 
479 
480 
485 
486 namespace
487 {
488  // Poor man's trait class that determines whether type T is a vector:
489  // FIXME: Implement this as a proper type trait - similar to
490  // isBlockVector
491 
492  template <typename T>
493  class has_vector_interface
494  {
495  template <typename C>
496  static std::false_type test(...);
497 
498  template <typename C>
499  static std::true_type test(decltype(&C::operator+=),
500  decltype(&C::operator-=),
501  decltype(&C::l2_norm));
502 
503  public:
504  // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
505  // otherwise it is std::false_type
506 
507  typedef decltype(test<T>(0, 0, 0)) type;
508  };
509 }
510 
511 
526 template <typename Range,
527  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
528 PackagedOperation<Range> operator+(const Range &u, const Range &v)
529 {
530  PackagedOperation<Range> return_comp;
531 
532  // ensure to have valid PackagedOperation objects by catching op by value
533  // u is caught by reference
534 
535  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries)
536  {
537  x.reinit(u, omit_zeroing_entries);
538  };
539 
540  return_comp.apply = [&u, &v](Range &x)
541  {
542  x = u;
543  x += v;
544  };
545 
546  return_comp.apply_add = [&u, &v](Range &x)
547  {
548  x += u;
549  x += v;
550  };
551 
552  return return_comp;
553 }
554 
555 
571 template <typename Range,
572  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
573 PackagedOperation<Range> operator-(const Range &u, const Range &v)
574 {
575  PackagedOperation<Range> return_comp;
576 
577  // ensure to have valid PackagedOperation objects by catching op by value
578  // u is catched by reference
579 
580  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries)
581  {
582  x.reinit(u, omit_zeroing_entries);
583  };
584 
585  return_comp.apply = [&u, &v](Range &x)
586  {
587  x = u;
588  x -= v;
589  };
590 
591  return_comp.apply_add = [&u, &v](Range &x)
592  {
593  x += u;
594  x -= v;
595  };
596 
597  return return_comp;
598 }
599 
600 
615 template <typename Range,
616  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
618  typename Range::value_type number)
619 {
620  return PackagedOperation<Range>(u) * number;
621 }
622 
623 
638 template <typename Range,
639  typename = typename std::enable_if<has_vector_interface<Range>::type::value>::type>
640 PackagedOperation<Range> operator*(typename Range::value_type number,
641  const Range &u)
642 {
643  return number * PackagedOperation<Range>(u);
644 }
645 
646 
663 template <typename Range, typename Domain, typename Payload>
666  const Domain &u)
667 {
668  PackagedOperation<Range> return_comp;
669 
670  return_comp.reinit_vector = op.reinit_range_vector;
671 
672  // ensure to have valid PackagedOperation objects by catching op by value
673  // u is caught by reference
674 
675  return_comp.apply = [op, &u](Range &v)
676  {
677  op.vmult(v, u);
678  };
679 
680  return_comp.apply_add = [op, &u](Range &v)
681  {
682  op.vmult_add(v, u);
683  };
684 
685  return return_comp;
686 }
687 
688 
705 template <typename Range, typename Domain, typename Payload>
707 operator*(const Range &u,
709 {
710  PackagedOperation<Range> return_comp;
711 
712  return_comp.reinit_vector = op.reinit_domain_vector;
713 
714  // ensure to have valid PackagedOperation objects by catching op by value
715  // u is caught by reference
716 
717  return_comp.apply = [op, &u](Domain &v)
718  {
719  op.Tvmult(v, u);
720  };
721 
722  return_comp.apply_add = [op, &u](Domain &v)
723  {
724  op.Tvmult_add(v, u);
725  };
726 
727  return return_comp;
728 }
729 
730 
739 template <typename Range, typename Domain, typename Payload>
742  const PackagedOperation<Domain> &comp)
743 {
744  PackagedOperation<Range> return_comp;
745 
746  return_comp.reinit_vector = op.reinit_range_vector;
747 
748  // ensure to have valid PackagedOperation objects by catching op by value
749  // u is caught by reference
750 
751  return_comp.apply = [op, comp](Domain &v)
752  {
753  static GrowingVectorMemory<Range> vector_memory;
754 
755  Range *i = vector_memory.alloc();
756  op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/ true);
757 
758  comp.apply(*i);
759  op.vmult(v, *i);
760 
761  vector_memory.free(i);
762  };
763 
764  return_comp.apply_add = [op, comp](Domain &v)
765  {
766  static GrowingVectorMemory<Range> vector_memory;
767 
768  Range *i = vector_memory.alloc();
769  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
770 
771  comp.apply(*i);
772  op.vmult_add(v, *i);
773 
774  vector_memory.free(i);
775  };
776 
777  return return_comp;
778 }
779 
780 
789 template <typename Range, typename Domain, typename Payload>
793 {
794  PackagedOperation<Range> return_comp;
795 
796  return_comp.reinit_vector = op.reinit_domain_vector;
797 
798  // ensure to have valid PackagedOperation objects by catching op by value
799  // u is caught by reference
800 
801  return_comp.apply = [op, comp](Domain &v)
802  {
803  static GrowingVectorMemory<Range> vector_memory;
804 
805  Range *i = vector_memory.alloc();
806  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
807 
808  comp.apply(*i);
809  op.Tvmult(v, *i);
810 
811  vector_memory.free(i);
812  };
813 
814  return_comp.apply_add = [op, comp](Domain &v)
815  {
816  static GrowingVectorMemory<Range> vector_memory;
817 
818  Range *i = vector_memory.alloc();
819  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/ true);
820 
821  comp.apply(*i);
822  op.Tvmult_add(v, *i);
823 
824  vector_memory.free(i);
825  };
826 
827  return return_comp;
828 }
829 
831 
832 DEAL_II_NAMESPACE_CLOSE
833 
834 #endif // DEAL_II_WITH_CXX11
835 #endif
PackagedOperation< Range > & operator+=(const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > operator*(const LinearOperator< Range, Domain, Payload > &op, const PackagedOperation< Domain > &comp)
PackagedOperation< Range > operator*(const LinearOperator< Range, Domain, Payload > &op, const Domain &u)
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)
PackagedOperation< Range > operator*(const Range &u, typename Range::value_type number)
PackagedOperation< Range > operator+(const PackagedOperation< Range > &comp, const Range &offset)
PackagedOperation< Domain > operator*(const PackagedOperation< Range > &comp, const LinearOperator< Range, Domain, Payload > &op)
PackagedOperation< Range > operator-(const Range &offset, const PackagedOperation< Range > &comp)
PackagedOperation< Range > & operator=(const PackagedOperation< Range > &)=default
PackagedOperation< Range > operator-(const Range &u, const Range &v)
static ::ExceptionBase & ExcMessage(std::string arg1)
PackagedOperation< Range > & operator=(const Range &u)
virtual VectorType * alloc()
#define Assert(cond, exc)
Definition: exceptions.h:313
std::function< void(Range &v, const Domain &u)> vmult
virtual void free(const VectorType *const)
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, const PackagedOperation< Range > &comp)
PackagedOperation< Range > & operator+=(const Range &offset)
PackagedOperation< Range > operator-(const PackagedOperation< Range > &comp, const Range &offset)
PackagedOperation< Domain > operator*(const Range &u, const LinearOperator< Range, Domain, Payload > &op)
PackagedOperation< Range > operator*(const PackagedOperation< Range > &comp, typename Range::value_type number)
PackagedOperation< Range > operator*(typename Range::value_type number, const PackagedOperation< Range > &comp)
PackagedOperation< Range > operator*(typename Range::value_type number, const Range &u)
PackagedOperation< Range > operator+(const PackagedOperation< Range > &first_comp, const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > & operator-=(const Range &offset)