deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+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: Apache-2.0 WITH LLVM-exception OR 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// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_packaged_operation_h
14#define dealii_packaged_operation_h
15
16#include <deal.II/base/config.h>
17
19
21
22#include <functional>
23
25
26// Forward declarations:
27#ifndef DOXYGEN
28template <typename Number>
29class Vector;
30template <typename Range, typename Domain, typename Payload>
31class LinearOperator;
32template <typename Range = Vector<double>>
34#endif
35
36
101template <typename Range>
103{
104public:
111 {
112 apply = [](Range &) {
113 Assert(false,
115 "Uninitialized PackagedOperation<Range>::apply called"));
116 };
117
118 apply_add = [](Range &) {
119 Assert(false,
121 "Uninitialized PackagedOperation<Range>::apply_add called"));
122 };
123
124 reinit_vector = [](Range &, bool) {
125 Assert(false,
126 ExcMessage("Uninitialized PackagedOperation<Range>::reinit_vector "
127 "method called"));
128 };
129 }
130
135
145 PackagedOperation(const Range &u)
146 {
147 *this = u;
148 }
149
155
166 operator=(const Range &u)
167 {
168 apply = [&u](Range &v) { v = u; };
169
170 apply_add = [&u](Range &v) { v += u; };
171
172 reinit_vector = [&u](Range &v, bool omit_zeroing_entries) {
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
205 {
206 *this = *this + second_comp;
207 return *this;
208 }
209
216 {
217 *this = *this - second_comp;
218 return *this;
219 }
220
226 operator+=(const Range &offset)
227 {
228 *this = *this + PackagedOperation<Range>(offset);
229 return *this;
230 }
231
237 operator-=(const Range &offset)
238 {
239 *this = *this - PackagedOperation<Range>(offset);
240 return *this;
241 }
242
247 operator*=(typename Range::value_type number)
248 {
249 *this = *this * number;
250 return *this;
251 }
258 std::function<void(Range &v)> apply;
259
264 std::function<void(Range &v)> apply_add;
265
273 std::function<void(Range &v, bool omit_zeroing_entries)> reinit_vector;
274};
275
276
290template <typename Range>
293 const PackagedOperation<Range> &second_comp)
294{
295 PackagedOperation<Range> return_comp;
296
297 return_comp.reinit_vector = first_comp.reinit_vector;
298
299 // ensure to have valid PackagedOperation objects by catching first_comp and
300 // second_comp by value
301
302 return_comp.apply = [first_comp, second_comp](Range &v) {
303 first_comp.apply(v);
304 second_comp.apply_add(v);
305 };
306
307 return_comp.apply_add = [first_comp, second_comp](Range &v) {
308 first_comp.apply_add(v);
309 second_comp.apply_add(v);
310 };
311
312 return return_comp;
313}
314
323template <typename Range>
326 const PackagedOperation<Range> &second_comp)
327{
328 PackagedOperation<Range> return_comp;
329
330 return_comp.reinit_vector = first_comp.reinit_vector;
331
332 // ensure to have valid PackagedOperation objects by catching first_comp and
333 // second_comp by value
334
335 return_comp.apply = [first_comp, second_comp](Range &v) {
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 first_comp.apply_add(v);
343 v *= -1.;
344 second_comp.apply_add(v);
345 v *= -1.;
346 };
347
348 return return_comp;
349}
350
359template <typename Range>
362 typename Range::value_type number)
363{
364 PackagedOperation<Range> return_comp;
365
366 return_comp.reinit_vector = comp.reinit_vector;
367
368 // the trivial case: number is zero
369 if (number == 0.)
370 {
371 return_comp.apply = [](Range &v) { v = 0.; };
372
373 return_comp.apply_add = [](Range &) {};
374 }
375 else
376 {
377 return_comp.apply = [comp, number](Range &v) {
378 comp.apply(v);
379 v *= number;
380 };
381
382 return_comp.apply_add = [comp, number](Range &v) {
383 v /= number;
384 comp.apply_add(v);
385 v *= number;
386 };
387 }
388
389 return return_comp;
390}
391
400template <typename Range>
402operator*(typename Range::value_type number,
403 const PackagedOperation<Range> &comp)
404{
405 return comp * number;
406}
407
416template <typename Range>
418operator+(const PackagedOperation<Range> &comp, const Range &offset)
419{
420 return comp + PackagedOperation<Range>(offset);
421}
422
431template <typename Range>
433operator+(const Range &offset, const PackagedOperation<Range> &comp)
434{
435 return PackagedOperation<Range>(offset) + comp;
436}
437
446template <typename Range>
448operator-(const PackagedOperation<Range> &comp, const Range &offset)
449{
450 return comp - PackagedOperation<Range>(offset);
451}
452
453
463template <typename Range>
465operator-(const Range &offset, const PackagedOperation<Range> &comp)
466{
467 return PackagedOperation<Range>(offset) - comp;
468}
469
478namespace internal
479{
480 namespace PackagedOperationImplementation
481 {
482 // Poor man's trait class that determines whether type T is a vector:
483 // FIXME: Implement this as a proper type trait - similar to
484 // isBlockVector
485
486 template <typename T>
488 {
489 template <typename C>
490 static std::false_type
491 test(...);
492
493 template <typename C>
494 static std::true_type
495 test(decltype(&C::operator+=),
496 decltype(&C::operator-=),
497 decltype(&C::l2_norm));
498
499 public:
500 // type is std::true_type if Matrix provides vmult_add and Tvmult_add,
501 // otherwise it is std::false_type
502
503 using type = decltype(test<T>(nullptr, nullptr, nullptr));
504 }; // namespace
505 } // namespace PackagedOperationImplementation
506} // namespace internal
507
508
523template <
524 typename Range,
525 typename = std::enable_if_t<internal::PackagedOperationImplementation::
526 has_vector_interface<Range>::type::value>>
528operator+(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 x.reinit(u, omit_zeroing_entries);
537 };
538
539 return_comp.apply = [&u, &v](Range &x) {
540 x = u;
541 x += v;
542 };
543
544 return_comp.apply_add = [&u, &v](Range &x) {
545 x += u;
546 x += v;
547 };
548
549 return return_comp;
550}
551
552
568template <
569 typename Range,
570 typename = std::enable_if_t<internal::PackagedOperationImplementation::
571 has_vector_interface<Range>::type::value>>
573operator-(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 caught by reference
579
580 return_comp.reinit_vector = [&u](Range &x, bool omit_zeroing_entries) {
581 x.reinit(u, omit_zeroing_entries);
582 };
583
584 return_comp.apply = [&u, &v](Range &x) {
585 x = u;
586 x -= v;
587 };
588
589 return_comp.apply_add = [&u, &v](Range &x) {
590 x += u;
591 x -= v;
592 };
593
594 return return_comp;
595}
596
597
612template <
613 typename Range,
614 typename = std::enable_if_t<internal::PackagedOperationImplementation::
615 has_vector_interface<Range>::type::value>>
617operator*(const Range &u, typename Range::value_type number)
618{
619 return PackagedOperation<Range>(u) * number;
620}
621
622
637template <
638 typename Range,
639 typename = std::enable_if_t<internal::PackagedOperationImplementation::
640 has_vector_interface<Range>::type::value>>
642operator*(typename Range::value_type number, const Range &u)
643{
644 return number * PackagedOperation<Range>(u);
645}
646
647
664template <typename Range, typename Domain, typename Payload>
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) { op.vmult(v, u); };
676
677 return_comp.apply_add = [op, &u](Range &v) { op.vmult_add(v, u); };
678
679 return return_comp;
680}
681
682
699template <typename Range, typename Domain, typename Payload>
702{
703 PackagedOperation<Range> return_comp;
704
705 return_comp.reinit_vector = op.reinit_domain_vector;
706
707 // ensure to have valid PackagedOperation objects by catching op by value
708 // u is caught by reference
709
710 return_comp.apply = [op, &u](Domain &v) { op.Tvmult(v, u); };
711
712 return_comp.apply_add = [op, &u](Domain &v) { op.Tvmult_add(v, u); };
713
714 return return_comp;
715}
716
717
726template <typename Range, typename Domain, typename Payload>
729 const PackagedOperation<Domain> &comp)
730{
731 PackagedOperation<Range> return_comp;
732
733 return_comp.reinit_vector = op.reinit_range_vector;
734
735 // ensure to have valid PackagedOperation objects by catching op by value
736 // u is caught by reference
737
738 return_comp.apply = [op, comp](Domain &v) {
739 GrowingVectorMemory<Range> vector_memory;
740
741 typename VectorMemory<Range>::Pointer i(vector_memory);
742 op.reinit_domain_vector(*i, /*bool omit_zeroing_entries =*/true);
743
744 comp.apply(*i);
745 op.vmult(v, *i);
746 };
747
748 return_comp.apply_add = [op, comp](Domain &v) {
749 GrowingVectorMemory<Range> vector_memory;
750
751 typename VectorMemory<Range>::Pointer i(vector_memory);
752 op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
753
754 comp.apply(*i);
755 op.vmult_add(v, *i);
756 };
757
758 return return_comp;
759}
760
761
770template <typename Range, typename Domain, typename Payload>
774{
775 PackagedOperation<Range> return_comp;
776
777 return_comp.reinit_vector = op.reinit_domain_vector;
778
779 // ensure to have valid PackagedOperation objects by catching op by value
780 // u is caught by reference
781
782 return_comp.apply = [op, comp](Domain &v) {
783 GrowingVectorMemory<Range> vector_memory;
784
785 typename VectorMemory<Range>::Pointer i(vector_memory);
786 op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
787
788 comp.apply(*i);
789 op.Tvmult(v, *i);
790 };
791
792 return_comp.apply_add = [op, comp](Domain &v) {
793 GrowingVectorMemory<Range> vector_memory;
794
795 typename VectorMemory<Range>::Pointer i(vector_memory);
796 op.reinit_range_vector(*i, /*bool omit_zeroing_entries =*/true);
797
798 comp.apply(*i);
799 op.Tvmult_add(v, *i);
800 };
801
802 return return_comp;
803}
804
808
809#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:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#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)