DUNE PDELab (git)

combinedoperator.hh
1// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=8 sw=2 sts=2:
3#ifndef DUNE_PDELAB_LOCALOPERATOR_COMBINEDOPERATOR_HH
4#define DUNE_PDELAB_LOCALOPERATOR_COMBINEDOPERATOR_HH
5
6#include <cstddef>
7
8#include <tuple>
11
12#include <dune/pdelab/localoperator/callswitch.hh>
13
14namespace Dune {
15 namespace PDELab {
16
20
22
28 template<typename ApplyOp, typename... Args>
30 {
31 protected:
32 using ArgPtrs = std::tuple<std::shared_ptr<std::remove_reference_t<Args>>...>;
33 using ArgRefs = std::tuple<Args&...>;
34
35 ArgPtrs lops;
36
37 template<typename... FArgs>
38 void applyLops(FArgs &... args) const
39 {
40 static_cast<const ApplyOp&>(*this).applyLops(args...);
41 }
42
43 public:
45 //
48 //
49
51
52 CombinedOperator(Args&... args) : lops(stackobject_to_shared_ptr(args)...) {}
53
54 CombinedOperator(Args&&... args) : lops(std::make_shared<Args>(std::move(args))...) {}
55
56 protected:
57 // CombinedOperator(const ArgPtrs & l) : lops(l) {}
58 CombinedOperator(ArgPtrs && l) : lops(std::move(l)) {}
59 public:
60
62 template<std::size_t i>
63 void setSummand(typename std::tuple_element_t<i,ArgRefs> summand)
64 { std::get<i>(lops) = &summand; }
65
67 template<std::size_t i>
68 typename std::tuple_element_t<i,ArgRefs> getSummand()
69 { return *std::get<i>(lops); }
70
72
74 //
77 //
78
79 private:
80 // we only evaluate the one-/two-sided flags, if a skeleton term is to be evaluated
81 template<typename T>
82 using OneSidedSkeleton = std::integral_constant
83 < bool, ( ( T::doAlphaSkeleton || T::doLambdaSkeleton) && ! T::doSkeletonTwoSided)>;
84 template<typename T>
85 using TwoSidedSkeleton = std::integral_constant
86 < bool, ( ( T::doAlphaSkeleton || T::doLambdaSkeleton) && T::doSkeletonTwoSided)>;
87
88 public:
89
92 enum { doSkipEntity =
93 std::disjunction_v<std::integral_constant<bool,Args::doSkipEntity>...> };
94
95
98 enum { doSkipIntersection =
99 std::disjunction_v<std::integral_constant<bool,Args::doSkipIntersection>...> };
100
102
105 enum { doPatternVolume =
106 std::disjunction_v<std::integral_constant<bool,Args::doPatternVolume>...> };
107
111 enum { doPatternVolumePostSkeleton =
112 std::disjunction_v<std::integral_constant<bool,Args::doPatternVolumePostSkeleton>...> };
116 enum { doPatternSkeleton =
117 std::disjunction_v<std::integral_constant<bool,Args::doPatternSkeleton>...> };
121 enum { doPatternBoundary =
122 std::disjunction_v<std::integral_constant<bool,Args::doPatternBoundary>...> };
123
125
128 enum { doAlphaVolume =
129 std::disjunction_v<std::integral_constant<bool,Args::doAlphaVolume>...> };
134 enum { doAlphaVolumePostSkeleton =
135 std::disjunction_v<std::integral_constant<bool,Args::doAlphaVolumePostSkeleton>...> };
138 enum { doAlphaSkeleton =
139 std::disjunction_v<std::integral_constant<bool,Args::doAlphaSkeleton>...> };
142 enum { doAlphaBoundary =
143 std::disjunction_v<std::integral_constant<bool,Args::doAlphaBoundary>...> };
144
146 enum { doLambdaVolume =
147 std::disjunction_v<std::integral_constant<bool,Args::doLambdaVolume>...> };
150 enum { doLambdaVolumePostSkeleton =
151 std::disjunction_v<std::integral_constant<bool,Args::doLambdaVolumePostSkeleton>...> };
153 enum { doLambdaSkeleton =
154 std::disjunction_v<std::integral_constant<bool,Args::doLambdaSkeleton>...> };
156 enum { doLambdaBoundary =
157 std::disjunction_v<std::integral_constant<bool,Args::doLambdaBoundary>...> };
158
160 enum { doSkeletonTwoSided =
161 std::disjunction_v<TwoSidedSkeleton<Args>...> };
162 static_assert(!(std::conjunction_v<OneSidedSkeleton<Args>...> &&
163 std::conjunction_v<TwoSidedSkeleton<Args>...>),
164 "Some summands require a one-sided skelton, others a "
165 "two-sided skeleton. This is not supported.");
166
168 enum { isLinear = std::conjunction_v<std::integral_constant<bool,Args::isLinear>...> };
169
171
173 //
176 //
177
179 template<typename EG>
181 ( const EG& eg) const
182 {
183 // check that all operators return the same
184 bool different_skips = false;
185 Hybrid::forEach(std::make_index_sequence<sizeof...(Args)>{},
186 [&](auto i) {
187 different_skips ^= getSummand<i>().skip_entity(eg);
188 }
189 );
190 if (different_skips)
191 DUNE_THROW(RangeError, "CombinedOperator is not allowed to have "
192 "different skip_entity results");
193 return getSummand<0>().skip_entity(eg);
194 }
195
197 template<typename IG>
199 ( const IG& ig) const
200 {
201 // check that all operators return the same
202 bool different_skips = false;
203 Hybrid::forEach(std::make_index_sequence<sizeof...(Args)>{},
204 [&](auto i) {
205 different_skips ^= getSummand<i>().skip_intersection(ig);
206 }
207 );
208 if (different_skips)
209 DUNE_THROW(RangeError, "CombinedOperator is not allowed to have "
210 "different skip_intersection results");
211 return getSummand<0>().skip_intersection(ig);
212 }
213
215
217 //
220 //
221
223
228 template<typename LFSU, typename LFSV, typename LocalPattern>
230 ( const LFSU& lfsu, const LFSV& lfsv,
231 LocalPattern& pattern) const
232 {
233 applyLops(LocalOperatorApply::patternVolume, lfsu, lfsv, pattern);
234 }
235
238
243 template<typename LFSU, typename LFSV, typename LocalPattern>
245 ( const LFSU& lfsu, const LFSV& lfsv,
246 LocalPattern& pattern) const
247 {
248 applyLops(LocalOperatorApply::patternVolumePostSkeleton, lfsu, lfsv, pattern);
249 }
250
252
257 template<typename LFSU, typename LFSV, typename LocalPattern>
259 ( const LFSU& lfsu_s, const LFSV& lfsv_s,
260 const LFSU& lfsu_n, const LFSV& lfsv_n,
261 LocalPattern& pattern_sn,
262 LocalPattern& pattern_ns) const
263 {
264 applyLops(LocalOperatorApply::patternSkeleton,
265 lfsu_s, lfsv_s, lfsu_n, lfsv_n,
266 pattern_sn, pattern_ns);
267 }
268
270
275 template<typename LFSU, typename LFSV, typename LocalPattern>
277 ( const LFSU& lfsu_s, const LFSV& lfsv_s,
278 LocalPattern& pattern_ss) const
279 {
280 applyLops(LocalOperatorApply::patternBoundary, lfsu_s, lfsv_s, pattern_ss);
281 }
282
284
286 //
289 //
290
292
296 template<typename EG, typename LFSU, typename X, typename LFSV,
297 typename R>
299 ( const EG& eg,
300 const LFSU& lfsu, const X& x, const LFSV& lfsv,
301 R& r) const
302 {
303 applyLops(LocalOperatorApply::alphaVolume, eg, lfsu, x, lfsv, r);
304 }
305
308
312 template<typename EG, typename LFSU, typename X, typename LFSV,
313 typename R>
315 ( const EG& eg,
316 const LFSU& lfsu, const X& x, const LFSV& lfsv,
317 R& r) const
318 {
319 applyLops(LocalOperatorApply::alphaVolumePostSkeleton, eg, lfsu, x, lfsv, r);
320 }
321
323
327 template<typename IG, typename LFSU, typename X, typename LFSV,
328 typename R>
330 ( const IG& ig,
331 const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
332 const LFSU& lfsu_n, const X& x_n, const LFSV& lfsv_n,
333 R& r_s, R& r_n) const
334 {
335 applyLops(LocalOperatorApply::alphaSkeleton, ig,
336 lfsu_s, x_s, lfsv_s,
337 lfsu_n, x_n, lfsv_n,
338 r_s, r_n);
339 }
340
342
346 template<typename IG, typename LFSU, typename X, typename LFSV,
347 typename R>
349 ( const IG& ig,
350 const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
351 R& r_s) const
352 {
353 applyLops(LocalOperatorApply::alphaVolumePostSkeleton, ig, lfsu_s, x_s, lfsv_s, r_s);
354 }
355
357
359 //
362 //
363
365
369 template<typename EG, typename LFSV, typename R>
370 void lambda_volume(const EG& eg, const LFSV& lfsv, R& r) const
371 {
372 applyLops(LocalOperatorApply::lambdaVolume, eg, lfsv, r);
373 }
374
377
381 template<typename EG, typename LFSV, typename R>
383 const LFSV& lfsv,
384 R& r) const
385 {
386 applyLops(LocalOperatorApply::lambdaVolumePostSkeleton, eg, lfsv, r);
387 }
388
390
394 template<typename IG, typename LFSV, typename R>
395 void lambda_skeleton(const IG& ig,
396 const LFSV& lfsv_s, const LFSV& lfsv_n,
397 R& r_s, R& r_n) const
398 {
399 applyLops(LocalOperatorApply::lambdaSkeleton, ig, lfsv_s, lfsv_n, r_s, r_n);
400 }
401
403
407 template<typename IG, typename LFSV, typename R>
408 void lambda_boundary(const IG& ig, const LFSV& lfsv_s, R& r_s) const
409 {
410 applyLops(LocalOperatorApply::lambdaBoundary, ig, lfsv_s, r_s);
411 }
412
414
416 //
419 //
420
422
426 template<typename EG, typename LFSU, typename X, typename LFSV,
427 typename Y>
429 ( const EG& eg,
430 const LFSU& lfsu, const X& x, const LFSV& lfsv,
431 Y& y) const
432 {
433 applyLops(LocalOperatorApply::jacobianApplyVolume, eg, lfsu, x, lfsv, y);
434 }
435
438
442 template<typename EG, typename LFSU, typename X, typename LFSV,
443 typename Y>
445 ( const EG& eg,
446 const LFSU& lfsu, const X& x, const LFSV& lfsv,
447 Y& y) const
448 {
449 applyLops(LocalOperatorApply::jacobianApplyVolumePostSkeleton, eg, lfsu, x, lfsv, y);
450 }
451
453
457 template<typename IG, typename LFSU, typename X, typename LFSV,
458 typename Y>
460 ( const IG& ig,
461 const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
462 const LFSU& lfsu_n, const X& x_n, const LFSV& lfsv_n,
463 Y& y_s, Y& y_n) const
464 {
465 applyLops(LocalOperatorApply::jacobianApplySkeleton, ig,
466 lfsu_s, x_s, lfsv_s,
467 lfsu_n, x_n, lfsv_n,
468 y_s, y_n);
469 }
470
472
476 template<typename IG, typename LFSU, typename X, typename LFSV,
477 typename Y>
479 ( const IG& ig,
480 const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
481 Y& y_s) const
482 {
483 applyLops(LocalOperatorApply::jacobianApplyBoundary, ig, lfsu_s, x_s, lfsv_s, y_s);
484 }
485
487
489 //
492 //
493
495
499 template<typename EG, typename LFSU, typename X, typename LFSV,
500 typename LocalMatrix>
502 ( const EG& eg,
503 const LFSU& lfsu, const X& x, const LFSV& lfsv,
504 LocalMatrix& mat) const
505 {
506 applyLops(LocalOperatorApply::jacobianVolume, eg, lfsu, x, lfsv, mat);
507 }
508
510
514 template<typename EG, typename LFSU, typename X, typename LFSV,
515 typename LocalMatrix>
517 ( const EG& eg,
518 const LFSU& lfsu, const X& x, const LFSV& lfsv,
519 LocalMatrix& mat) const
520 {
521 applyLops(LocalOperatorApply::jacobianVolumePostSkeleton, eg, lfsu, x, lfsv, mat);
522 }
523
525
529 template<typename IG, typename LFSU, typename X, typename LFSV,
530 typename LocalMatrix>
532 ( const IG& ig,
533 const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
534 const LFSU& lfsu_n, const X& x_n, const LFSV& lfsv_n,
535 LocalMatrix& mat_ss, LocalMatrix& mat_sn,
536 LocalMatrix& mat_ns, LocalMatrix& mat_nn) const
537 {
538 applyLops(LocalOperatorApply::jacobianSkeleton, ig,
539 lfsu_s, x_s, lfsv_s,
540 lfsu_n, x_n, lfsv_n,
541 mat_ss, mat_sn, mat_ns, mat_nn);
542 }
543
545
549 template<typename IG, typename LFSU, typename X, typename LFSV,
550 typename LocalMatrix>
552 ( const IG& ig,
553 const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
554 LocalMatrix& mat_ss) const
555 {
556 applyLops(LocalOperatorApply::jacobianBoundary, ig, lfsu_s, x_s, lfsv_s, mat_ss);
557 }
558
560
562 //
565 //
566
568 typedef typename std::tuple_element<0, std::tuple<Args...>>::type::RealType RealType;
569
570 private:
571 // template meta program helpers for the methods related to instationary
572 // stuff
573
574 struct Apply {
575 template<typename LOP>
576 static void setTime(const LOP& lop, RealType t)
577 {
578 lop.setTime(t);
579 }
580
581 template<typename LOP>
582 static void preStep(const LOP& lop,
583 RealType time, RealType dt, int stages)
584 {
585 lop.preStep(time, dt, stages);
586 }
587
588 template<typename LOP>
589 static void postStep(const LOP& lop)
590 {
591 lop.postStep();
592 }
593
594 template<typename LOP>
595 static void preStage(const LOP& lop, RealType time, int r)
596 {
597 lop.preStage(time, r);
598 }
599
600 template<typename LOP>
601 static void postStage(const LOP& lop)
602 {
603 lop.postStage();
604 }
605
606 template<typename LOP>
607 static RealType suggestTimestep(const LOP& lop, RealType & dt)
608 {
609 dt = std::min(dt,lop.suggestTimestep(dt));
610 }
611 };
612
613 public:
616 {
617 applyLops(Apply::setTime, t);
618 }
619
622 {
623 return get<0>(lops)->getTime();
624 }
625
627 void preStep (RealType time, RealType dt, int stages)
628 {
629 applyLops(Apply::preStep, time, dt, stages);
630 }
631
633 void postStep ()
634 {
635 applyLops(Apply::postStep, lops);
636 }
637
639 void preStage (RealType time, int r)
640 {
641 applyLops(Apply::preStage, time, r);
642 }
643
645 int getStage () const
646 {
647 return get<0>(lops)->getStage();
648 }
649
651 void postStage ()
652 {
653 applyLops(Apply::postStage, lops);
654 }
655
657
663 {
664 applyLops(Apply::suggestTimestep, dt);
665 return dt;
666 }
667
669 };
670
671 }
672}
673
674#endif // DUNE_PDELAB_LOCALOPERATOR_COMBINEDOPERATOR_HH
A local operator to take combine different local operators.
Definition: combinedoperator.hh:30
A dense matrix for storing data associated with the degrees of freedom of a pair of LocalFunctionSpac...
Definition: localmatrix.hh:184
Default exception class for range errors.
Definition: exceptions.hh:254
Traits for type conversions and type information.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
constexpr auto min
Function object that returns the smaller of the given values.
Definition: hybridutilities.hh:506
void jacobian_apply_skeleton(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, const LFSU &lfsu_n, const X &x_n, const LFSV &lfsv_n, Y &y_s, Y &y_n) const
apply an internal intersections's jacobians
Definition: combinedoperator.hh:460
bool skip_intersection(const IG &ig) const
whether to assembly methods associated with a given intersection
Definition: combinedoperator.hh:199
void pattern_volume(const LFSU &lfsu, const LFSV &lfsv, LocalPattern &pattern) const
get an element's contribution to the sparsity pattern
Definition: combinedoperator.hh:230
RealType suggestTimestep(RealType dt) const
to be called after stage 1
Definition: combinedoperator.hh:662
RealType getTime() const
get current time
Definition: combinedoperator.hh:621
void jacobian_apply_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, Y &y_s) const
apply a boundary intersections's jacobian
Definition: combinedoperator.hh:479
void lambda_volume(const EG &eg, const LFSV &lfsv, R &r) const
get an element's contribution to lambda
Definition: combinedoperator.hh:370
void pattern_skeleton(const LFSU &lfsu_s, const LFSV &lfsv_s, const LFSU &lfsu_n, const LFSV &lfsv_n, LocalPattern &pattern_sn, LocalPattern &pattern_ns) const
get an internal intersection's contribution to the sparsity pattern
Definition: combinedoperator.hh:259
void jacobian_apply_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, Y &y) const
apply an element's jacobian
Definition: combinedoperator.hh:429
void alpha_volume_post_skeleton(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, R &r) const
get an element's contribution to alpha after the intersections have been handled
Definition: combinedoperator.hh:315
void pattern_boundary(const LFSU &lfsu_s, const LFSV &lfsv_s, LocalPattern &pattern_ss) const
get a boundary intersection's contribution to the sparsity pattern
Definition: combinedoperator.hh:277
void jacobian_skeleton(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, const LFSU &lfsu_n, const X &x_n, const LFSV &lfsv_n, LocalMatrix &mat_ss, LocalMatrix &mat_sn, LocalMatrix &mat_ns, LocalMatrix &mat_nn) const
apply an internal intersections's jacobians
Definition: combinedoperator.hh:532
void postStep()
to be called once at the end of each time step
Definition: combinedoperator.hh:633
void lambda_volume_post_skeleton(const EG &eg, const LFSV &lfsv, R &r) const
get an element's contribution to lambda after the intersections have been handled
Definition: combinedoperator.hh:382
void preStage(RealType time, int r)
to be called once before each stage
Definition: combinedoperator.hh:639
void jacobian_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, LocalMatrix &mat_ss) const
get a boundary intersections's jacobian
Definition: combinedoperator.hh:552
std::tuple_element_t< i, ArgRefs > getSummand()
get the i'th component of the sum
Definition: combinedoperator.hh:68
int getStage() const
get current stage
Definition: combinedoperator.hh:645
void jacobian_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, LocalMatrix &mat) const
get an element's jacobian
Definition: combinedoperator.hh:502
void alpha_skeleton(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, const LFSU &lfsu_n, const X &x_n, const LFSV &lfsv_n, R &r_s, R &r_n) const
get an internal intersections's contribution to alpha
Definition: combinedoperator.hh:330
void postStage()
to be called once at the end of each stage
Definition: combinedoperator.hh:651
void setSummand(typename std::tuple_element_t< i, ArgRefs > summand)
set the i'th component of the sum
Definition: combinedoperator.hh:63
void pattern_volume_post_skeleton(const LFSU &lfsu, const LFSV &lfsv, LocalPattern &pattern) const
get an element's contribution to the sparsity pattern after the intersections have been handled
Definition: combinedoperator.hh:245
std::tuple_element< 0, std::tuple< Args... > >::type::RealType RealType
Export type used for time values.
Definition: combinedoperator.hh:568
void preStep(RealType time, RealType dt, int stages)
to be called once before each time step
Definition: combinedoperator.hh:627
void lambda_skeleton(const IG &ig, const LFSV &lfsv_s, const LFSV &lfsv_n, R &r_s, R &r_n) const
get an internal intersections's contribution to lambda
Definition: combinedoperator.hh:395
void lambda_boundary(const IG &ig, const LFSV &lfsv_s, R &r_s) const
get a boundary intersections's contribution to lambda
Definition: combinedoperator.hh:408
void jacobian_volume_post_skeleton(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, LocalMatrix &mat) const
get an element's jacobian after the intersections have been handled
Definition: combinedoperator.hh:517
void setTime(RealType t)
set time for subsequent evaluation
Definition: combinedoperator.hh:615
bool skip_entity(const EG &eg) const
whether to assembly methods associated with a given entity
Definition: combinedoperator.hh:181
void jacobian_apply_volume_post_skeleton(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, Y &y) const
apply an element's jacobian after the intersections have been handled
Definition: combinedoperator.hh:445
void alpha_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, R &r_s) const
get a boundary intersections's contribution to alpha
Definition: combinedoperator.hh:349
void alpha_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, R &r) const
get an element's contribution to alpha
Definition: combinedoperator.hh:299
Dune namespace.
Definition: alignedallocator.hh:13
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:72
Contains utility classes which can be used with std::tuple.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)