deal.II version GIT relicensing-2289-g1e5549a87a 2024-12-21 21:30:00+00:00
\(\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\}}\)
Loading...
Searching...
No Matches
packaged_operation.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2015 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_packaged_operation_h
16#define dealii_packaged_operation_h
17
18#include <deal.II/base/config.h>
19
21
23
24#include <functional>
25
27
28// Forward declarations:
29#ifndef DOXYGEN
30template <typename Number>
31class Vector;
32template <typename Range, typename Domain, typename Payload>
33class LinearOperator;
34template <typename Range = Vector<double>>
36#endif
37
38
103template <typename Range>
105{
106public:
113 {
114 apply = [](Range &) {
115 Assert(false,
117 "Uninitialized PackagedOperation<Range>::apply called"));
118 };
119
120 apply_add = [](Range &) {
121 Assert(false,
123 "Uninitialized PackagedOperation<Range>::apply_add called"));
124 };
125
126 reinit_vector = [](Range &, bool) {
127 Assert(false,
128 ExcMessage("Uninitialized PackagedOperation<Range>::reinit_vector "
129 "method called"));
130 };
131 }
132
137
147 PackagedOperation(const Range &u)
148 {
149 *this = u;
150 }
151
157
168 operator=(const Range &u)
169 {
170 apply = [&u](Range &v) { v = u; };
171
172 apply_add = [&u](Range &v) { v += u; };
173
174 reinit_vector = [&u](Range &v, bool omit_zeroing_entries) {
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
207 {
208 *this = *this + second_comp;
209 return *this;
210 }
211
218 {
219 *this = *this - second_comp;
220 return *this;
221 }
222
228 operator+=(const Range &offset)
229 {
230 *this = *this + PackagedOperation<Range>(offset);
231 return *this;
232 }
233
239 operator-=(const Range &offset)
240 {
241 *this = *this - PackagedOperation<Range>(offset);
242 return *this;
243 }
244
249 operator*=(typename Range::value_type number)
250 {
251 *this = *this * number;
252 return *this;
253 }
260 std::function<void(Range &v)> apply;
261
266 std::function<void(Range &v)> apply_add;
267
275 std::function<void(Range &v, bool omit_zeroing_entries)> reinit_vector;
276};
277
278
292template <typename Range>
295 const PackagedOperation<Range> &second_comp)
296{
297 PackagedOperation<Range> return_comp;
298
299 return_comp.reinit_vector = first_comp.reinit_vector;
300
301 // ensure to have valid PackagedOperation objects by catching first_comp and
302 // second_comp by value
303
304 return_comp.apply = [first_comp, second_comp](Range &v) {
305 first_comp.apply(v);
306 second_comp.apply_add(v);
307 };
308
309 return_comp.apply_add = [first_comp, second_comp](Range &v) {
310 first_comp.apply_add(v);
311 second_comp.apply_add(v);
312 };
313
314 return return_comp;
315}
316
325template <typename Range>
328 const PackagedOperation<Range> &second_comp)
329{
330 PackagedOperation<Range> return_comp;
331
332 return_comp.reinit_vector = first_comp.reinit_vector;
333
334 // ensure to have valid PackagedOperation objects by catching first_comp and
335 // second_comp by value
336
337 return_comp.apply = [first_comp, second_comp](Range &v) {
338 second_comp.apply(v);
339 v *= -1.;
340 first_comp.apply_add(v);
341 };
342
343 return_comp.apply_add = [first_comp, second_comp](Range &v) {
344 first_comp.apply_add(v);
345 v *= -1.;
346 second_comp.apply_add(v);
347 v *= -1.;
348 };
349
350 return return_comp;
351}
352
361template <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
402template <typename Range>
404operator*(typename Range::value_type number,
405 const PackagedOperation<Range> &comp)
406{
407 return comp * number;
408}
409
418template <typename Range>
420operator+(const PackagedOperation<Range> &comp, const Range &offset)
421{
422 return comp + PackagedOperation<Range>(offset);
423}
424
433template <typename Range>
435operator+(const Range &offset, const PackagedOperation<Range> &comp)
436{
437 return PackagedOperation<Range>(offset) + comp;
438}
439
448template <typename Range>
450operator-(const PackagedOperation<Range> &comp, const Range &offset)
451{
452 return comp - PackagedOperation<Range>(offset);
453}
454
455
465template <typename Range>
467operator-(const Range &offset, const PackagedOperation<Range> &comp)
468{
469 return PackagedOperation<Range>(offset) - comp;
470}
471
480namespace internal
481{
482 namespace PackagedOperationImplementation
483 {
484 // Poor man's trait class that determines whether type T is a vector:
485 // FIXME: Implement this as a proper type trait - similar to
486 // isBlockVector
487
488 template <typename T>
490 {
491 template <typename C>
492 static std::false_type
493 test(...);
494
495 template <typename C>
496 static std::true_type
497 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 using type = decltype(test<T>(nullptr, nullptr, nullptr));
506 }; // namespace
507 } // namespace PackagedOperationImplementation
508} // namespace internal
509
510
525template <
526 typename Range,
527 typename = std::enable_if_t<internal::PackagedOperationImplementation::
528 has_vector_interface<Range>::type::value>>
530operator+(const Range &u, const Range &v)
531{
532 PackagedOperation<Range> return_comp;
533
534 // ensure to have valid PackagedOperation objects by catching op by value
535 // u is caught by reference
536
537 return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
538 x.reinit(u, omit_zeroing_entries);
539 };
540
541 return_comp.apply = [&u, &v](Range &x) {
542 x = u;
543 x += v;
544 };
545
546 return_comp.apply_add = [&u, &v](Range &x) {
547 x += u;
548 x += v;
549 };
550
551 return return_comp;
552}
553
554
570template <
571 typename Range,
572 typename = std::enable_if_t<internal::PackagedOperationImplementation::
573 has_vector_interface<Range>::type::value>>
575operator-(const Range &u, const Range &v)
576{
577 PackagedOperation<Range> return_comp;
578
579 // ensure to have valid PackagedOperation objects by catching op by value
580 // u is caught by reference
581
582 return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
583 x.reinit(u, omit_zeroing_entries);
584 };
585
586 return_comp.apply = [&u, &v](Range &x) {
587 x = u;
588 x -= v;
589 };
590
591 return_comp.apply_add = [&u, &v](Range &x) {
592 x += u;
593 x -= v;
594 };
595
596 return return_comp;
597}
598
599
614template <
615 typename Range,
616 typename = std::enable_if_t<internal::PackagedOperationImplementation::
617 has_vector_interface<Range>::type::value>>
619operator*(const Range &u, typename Range::value_type number)
620{
621 return PackagedOperation<Range>(u) * number;
622}
623
624
639template <
640 typename Range,
641 typename = std::enable_if_t<internal::PackagedOperationImplementation::
642 has_vector_interface<Range>::type::value>>
644operator*(typename Range::value_type number, const Range &u)
645{
646 return number * PackagedOperation<Range>(u);
647}
648
649
666template <typename Range, typename Domain, typename Payload>
669{
670 PackagedOperation<Range> return_comp;
671
672 return_comp.reinit_vector = op.reinit_range_vector;
673
674 // ensure to have valid PackagedOperation objects by catching op by value
675 // u is caught by reference
676
677 return_comp.apply = [op, &u](Range &v) { op.vmult(v, u); };
678
679 return_comp.apply_add = [op, &u](Range &v) { op.vmult_add(v, u); };
680
681 return return_comp;
682}
683
684
701template <typename Range, typename Domain, typename Payload>
704{
705 PackagedOperation<Range> return_comp;
706
707 return_comp.reinit_vector = op.reinit_domain_vector;
708
709 // ensure to have valid PackagedOperation objects by catching op by value
710 // u is caught by reference
711
712 return_comp.apply = [op, &u](Domain &v) { op.Tvmult(v, u); };
713
714 return_comp.apply_add = [op, &u](Domain &v) { op.Tvmult_add(v, u); };
715
716 return return_comp;
717}
718
719
728template <typename Range, typename Domain, typename Payload>
731 const PackagedOperation<Domain> &comp)
732{
733 PackagedOperation<Range> return_comp;
734
735 return_comp.reinit_vector = op.reinit_range_vector;
736
737 // ensure to have valid PackagedOperation objects by catching op by value
738 // u is caught by reference
739
740 return_comp.apply = [op, comp](Domain &v) {
741 GrowingVectorMemory<Range> vector_memory;
742
743 typename VectorMemory<Range>::Pointer i(vector_memory);
744 op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/true);
745
746 comp.apply(*i);
747 op.vmult(v, *i);
748 };
749
750 return_comp.apply_add = [op, comp](Domain &v) {
751 GrowingVectorMemory<Range> vector_memory;
752
753 typename VectorMemory<Range>::Pointer i(vector_memory);
754 op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
755
756 comp.apply(*i);
757 op.vmult_add(v, *i);
758 };
759
760 return return_comp;
761}
762
763
772template <typename Range, typename Domain, typename Payload>
776{
777 PackagedOperation<Range> return_comp;
778
779 return_comp.reinit_vector = op.reinit_domain_vector;
780
781 // ensure to have valid PackagedOperation objects by catching op by value
782 // u is caught by reference
783
784 return_comp.apply = [op, comp](Domain &v) {
785 GrowingVectorMemory<Range> vector_memory;
786
787 typename VectorMemory<Range>::Pointer i(vector_memory);
788 op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
789
790 comp.apply(*i);
791 op.Tvmult(v, *i);
792 };
793
794 return_comp.apply_add = [op, comp](Domain &v) {
795 GrowingVectorMemory<Range> vector_memory;
796
797 typename VectorMemory<Range>::Pointer i(vector_memory);
798 op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
799
800 comp.apply(*i);
801 op.Tvmult_add(v, *i);
802 };
803
804 return return_comp;
805}
806
810
811#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
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_vector
PackagedOperation< Range > & operator*=(typename Range::value_type number)
PackagedOperation< Range > & operator=(const Range &u)
PackagedOperation(const Range &u)
std::function< void(Range &v)> apply
PackagedOperation< Range > & operator=(const PackagedOperation< Range > &)=default
PackagedOperation< Range > & operator+=(const PackagedOperation< Range > &second_comp)
std::function< void(Range &v)> apply_add
PackagedOperation< Range > & operator-=(const Range &offset)
PackagedOperation(const PackagedOperation< Range > &)=default
PackagedOperation< Range > & operator+=(const Range &offset)
PackagedOperation< Range > & operator-=(const PackagedOperation< Range > &second_comp)
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:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
#define Assert(cond, exc)
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)