Reference documentation for deal.II version 9.3.2
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
packaged_operation.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2014 - 2020 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 
22 
24 
25 #include <functional>
26 
28 
29 // Forward declarations:
30 #ifndef DOXYGEN
31 template <typename Number>
32 class Vector;
33 template <typename Range, typename Domain, typename Payload>
34 class LinearOperator;
35 template <typename Range = Vector<double>>
36 class PackagedOperation;
37 #endif
38 
39 
104 template <typename Range>
106 {
107 public:
114  {
115  apply = [](Range &) {
116  Assert(false,
117  ExcMessage(
118  "Uninitialized PackagedOperation<Range>::apply called"));
119  };
120 
121  apply_add = [](Range &) {
122  Assert(false,
123  ExcMessage(
124  "Uninitialized PackagedOperation<Range>::apply_add called"));
125  };
126 
127  reinit_vector = [](Range &, bool) {
128  Assert(false,
129  ExcMessage("Uninitialized PackagedOperation<Range>::reinit_vector "
130  "method called"));
131  };
132  }
133 
138 
148  PackagedOperation(const Range &u)
149  {
150  *this = u;
151  }
152 
158 
169  operator=(const Range &u)
170  {
171  apply = [&u](Range &v) { v = u; };
172 
173  apply_add = [&u](Range &v) { v += u; };
174 
175  reinit_vector = [&u](Range &v, bool omit_zeroing_entries) {
176  v.reinit(u, omit_zeroing_entries);
177  };
178 
179  return *this;
180  }
181 
188  operator Range() const
189  {
190  Range result_vector;
191 
192  reinit_vector(result_vector, /*bool omit_zeroing_entries=*/true);
193  apply(result_vector);
194 
195  return result_vector;
196  }
197 
202 
208  {
209  *this = *this + second_comp;
210  return *this;
211  }
212 
219  {
220  *this = *this - second_comp;
221  return *this;
222  }
223 
229  operator+=(const Range &offset)
230  {
231  *this = *this + PackagedOperation<Range>(offset);
232  return *this;
233  }
234 
240  operator-=(const Range &offset)
241  {
242  *this = *this - PackagedOperation<Range>(offset);
243  return *this;
244  }
245 
250  operator*=(typename Range::value_type number)
251  {
252  *this = *this * number;
253  return *this;
254  }
256 
261  std::function<void(Range &v)> apply;
262 
267  std::function<void(Range &v)> apply_add;
268 
276  std::function<void(Range &v, bool omit_zeroing_entries)> reinit_vector;
277 };
278 
279 
284 
293 template <typename Range>
296  const PackagedOperation<Range> &second_comp)
297 {
298  PackagedOperation<Range> return_comp;
299 
300  return_comp.reinit_vector = first_comp.reinit_vector;
301 
302  // ensure to have valid PackagedOperation objects by catching first_comp and
303  // second_comp by value
304 
305  return_comp.apply = [first_comp, second_comp](Range &v) {
306  first_comp.apply(v);
307  second_comp.apply_add(v);
308  };
309 
310  return_comp.apply_add = [first_comp, second_comp](Range &v) {
311  first_comp.apply_add(v);
312  second_comp.apply_add(v);
313  };
314 
315  return return_comp;
316 }
317 
326 template <typename Range>
329  const PackagedOperation<Range> &second_comp)
330 {
331  PackagedOperation<Range> return_comp;
332 
333  return_comp.reinit_vector = first_comp.reinit_vector;
334 
335  // ensure to have valid PackagedOperation objects by catching first_comp and
336  // second_comp by value
337 
338  return_comp.apply = [first_comp, second_comp](Range &v) {
339  second_comp.apply(v);
340  v *= -1.;
341  first_comp.apply_add(v);
342  };
343 
344  return_comp.apply_add = [first_comp, second_comp](Range &v) {
345  first_comp.apply_add(v);
346  v *= -1.;
347  second_comp.apply_add(v);
348  v *= -1.;
349  };
350 
351  return return_comp;
352 }
353 
362 template <typename Range>
364  typename Range::value_type number)
365 {
366  PackagedOperation<Range> return_comp;
367 
368  return_comp.reinit_vector = comp.reinit_vector;
369 
370  // the trivial case: number is zero
371  if (number == 0.)
372  {
373  return_comp.apply = [](Range &v) { v = 0.; };
374 
375  return_comp.apply_add = [](Range &) {};
376  }
377  else
378  {
379  return_comp.apply = [comp, number](Range &v) {
380  comp.apply(v);
381  v *= number;
382  };
383 
384  return_comp.apply_add = [comp, number](Range &v) {
385  v /= number;
386  comp.apply_add(v);
387  v *= number;
388  };
389  }
390 
391  return return_comp;
392 }
393 
402 template <typename Range>
403 PackagedOperation<Range> operator*(typename Range::value_type number,
404  const PackagedOperation<Range> &comp)
405 {
406  return comp * number;
407 }
408 
417 template <typename Range>
419 operator+(const PackagedOperation<Range> &comp, const Range &offset)
420 {
421  return comp + PackagedOperation<Range>(offset);
422 }
423 
432 template <typename Range>
434 operator+(const Range &offset, const PackagedOperation<Range> &comp)
435 {
436  return PackagedOperation<Range>(offset) + comp;
437 }
438 
447 template <typename Range>
449 operator-(const PackagedOperation<Range> &comp, const Range &offset)
450 {
451  return comp - PackagedOperation<Range>(offset);
452 }
453 
454 
464 template <typename Range>
466 operator-(const Range &offset, const PackagedOperation<Range> &comp)
467 {
468  return PackagedOperation<Range>(offset) - comp;
469 }
470 
472 
473 
478 
479 namespace internal
480 {
481  namespace PackagedOperationImplementation
482  {
483  // Poor man's trait class that determines whether type T is a vector:
484  // FIXME: Implement this as a proper type trait - similar to
485  // isBlockVector
486 
487  template <typename T>
489  {
490  template <typename C>
491  static std::false_type
492  test(...);
493 
494  template <typename C>
495  static std::true_type
496  test(decltype(&C::operator+=),
497  decltype(&C::operator-=),
498  decltype(&C::l2_norm));
499 
500  public:
501  // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
502  // otherwise it is std::false_type
503 
504  using type = decltype(test<T>(nullptr, nullptr, nullptr));
505  }; // namespace
506  } // namespace PackagedOperationImplementation
507 } // namespace internal
508 
509 
524 template <typename Range,
525  typename = typename std::enable_if<
527  Range>::type::value>::type>
529 operator+(const Range &u, const Range &v)
530 {
531  PackagedOperation<Range> return_comp;
532 
533  // ensure to have valid PackagedOperation objects by catching op by value
534  // u is caught by reference
535 
536  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
537  x.reinit(u, omit_zeroing_entries);
538  };
539 
540  return_comp.apply = [&u, &v](Range &x) {
541  x = u;
542  x += v;
543  };
544 
545  return_comp.apply_add = [&u, &v](Range &x) {
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<
572  Range>::type::value>::type>
574 operator-(const Range &u, const Range &v)
575 {
576  PackagedOperation<Range> return_comp;
577 
578  // ensure to have valid PackagedOperation objects by catching op by value
579  // u is caught by reference
580 
581  return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
582  x.reinit(u, omit_zeroing_entries);
583  };
584 
585  return_comp.apply = [&u, &v](Range &x) {
586  x = u;
587  x -= v;
588  };
589 
590  return_comp.apply_add = [&u, &v](Range &x) {
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<
616  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<
641  Range>::type::value>::type>
642 PackagedOperation<Range> operator*(typename Range::value_type number,
643  const Range & u)
644 {
645  return number * PackagedOperation<Range>(u);
646 }
647 
648 
665 template <typename Range, typename Domain, typename Payload>
668 {
669  PackagedOperation<Range> return_comp;
670 
671  return_comp.reinit_vector = op.reinit_range_vector;
672 
673  // ensure to have valid PackagedOperation objects by catching op by value
674  // u is caught by reference
675 
676  return_comp.apply = [op, &u](Range &v) { op.vmult(v, u); };
677 
678  return_comp.apply_add = [op, &u](Range &v) { op.vmult_add(v, u); };
679 
680  return return_comp;
681 }
682 
683 
700 template <typename Range, typename Domain, typename Payload>
703 {
704  PackagedOperation<Range> return_comp;
705 
706  return_comp.reinit_vector = op.reinit_domain_vector;
707 
708  // ensure to have valid PackagedOperation objects by catching op by value
709  // u is caught by reference
710 
711  return_comp.apply = [op, &u](Domain &v) { op.Tvmult(v, u); };
712 
713  return_comp.apply_add = [op, &u](Domain &v) { op.Tvmult_add(v, u); };
714 
715  return return_comp;
716 }
717 
718 
727 template <typename Range, typename Domain, typename Payload>
730  const PackagedOperation<Domain> & comp)
731 {
732  PackagedOperation<Range> return_comp;
733 
734  return_comp.reinit_vector = op.reinit_range_vector;
735 
736  // ensure to have valid PackagedOperation objects by catching op by value
737  // u is caught by reference
738 
739  return_comp.apply = [op, comp](Domain &v) {
740  GrowingVectorMemory<Range> vector_memory;
741 
742  typename VectorMemory<Range>::Pointer i(vector_memory);
743  op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/true);
744 
745  comp.apply(*i);
746  op.vmult(v, *i);
747  };
748 
749  return_comp.apply_add = [op, comp](Domain &v) {
750  GrowingVectorMemory<Range> vector_memory;
751 
752  typename VectorMemory<Range>::Pointer i(vector_memory);
753  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
754 
755  comp.apply(*i);
756  op.vmult_add(v, *i);
757  };
758 
759  return return_comp;
760 }
761 
762 
771 template <typename Range, typename Domain, typename Payload>
775 {
776  PackagedOperation<Range> return_comp;
777 
778  return_comp.reinit_vector = op.reinit_domain_vector;
779 
780  // ensure to have valid PackagedOperation objects by catching op by value
781  // u is caught by reference
782 
783  return_comp.apply = [op, comp](Domain &v) {
784  GrowingVectorMemory<Range> vector_memory;
785 
786  typename VectorMemory<Range>::Pointer i(vector_memory);
787  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
788 
789  comp.apply(*i);
790  op.Tvmult(v, *i);
791  };
792 
793  return_comp.apply_add = [op, comp](Domain &v) {
794  GrowingVectorMemory<Range> vector_memory;
795 
796  typename VectorMemory<Range>::Pointer i(vector_memory);
797  op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
798 
799  comp.apply(*i);
800  op.Tvmult_add(v, *i);
801  };
802 
803  return return_comp;
804 }
805 
807 
809 
810 #endif
std::function< void(Range &v, const Domain &u)> vmult_add
std::function< void(Domain &v, const Range &u)> Tvmult
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
std::function< void(Range &v, const Domain &u)> vmult
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Domain &v, const Range &u)> Tvmult_add
PackagedOperation< Range > & operator+=(const Range &offset)
PackagedOperation< Range > & operator=(const Range &u)
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_vector
PackagedOperation(const Range &u)
std::function< void(Range &v)> apply
PackagedOperation< Range > & operator-=(const Range &offset)
std::function< void(Range &v)> apply_add
PackagedOperation(const PackagedOperation< Range > &)=default
PackagedOperation< Range > & operator-=(const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > & operator=(const PackagedOperation< Range > &)=default
PackagedOperation< Range > & operator+=(const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > & operator*=(typename Range::value_type number)
Definition: vector.h:110
static std::true_type test(decltype(&C::operator+=), decltype(&C::operator-=), decltype(&C::l2_norm))
decltype(test< T >(nullptr, nullptr, nullptr)) type
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:396
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:397
#define Assert(cond, exc)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcMessage(std::string arg1)
PackagedOperation< Range > operator*(const LinearOperator< Range, Domain, Payload > &op, const PackagedOperation< Domain > &comp)
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 &u, const Range &v)
PackagedOperation< Range > operator*(const LinearOperator< Range, Domain, Payload > &op, const Domain &u)
PackagedOperation< Domain > operator*(const Range &u, const LinearOperator< Range, Domain, Payload > &op)
PackagedOperation< Range > operator+(const Range &offset, const PackagedOperation< Range > &comp)
PackagedOperation< Range > operator*(typename Range::value_type number, const Range &u)
PackagedOperation< Range > operator-(const Range &offset, const PackagedOperation< Range > &comp)
PackagedOperation< Range > operator-(const PackagedOperation< Range > &first_comp, const PackagedOperation< Range > &second_comp)
PackagedOperation< Range > operator+(const PackagedOperation< Range > &comp, const Range &offset)
PackagedOperation< Range > operator+(const Range &u, const Range &v)
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*(const Range &u, typename Range::value_type number)
PackagedOperation< Range > operator+(const PackagedOperation< Range > &first_comp, const PackagedOperation< Range > &second_comp)
std::vector< value_type > l2_norm(const typename ::Triangulation< dim, spacedim >::cell_iterator &parent, const value_type parent_value)