dune-pdelab  2.7-git
combinedoperator.hh
Go to the documentation of this file.
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>
9 #include <dune/common/tupleutility.hh>
10 #include <dune/common/typetraits.hh>
11 
13 
14 namespace 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 
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 
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>...> };
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>...> };
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>
382  void lambda_volume_post_skeleton(const EG& eg,
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  {
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:
615  void setTime (RealType t)
616  {
617  applyLops(Apply::setTime, t);
618  }
619 
621  RealType getTime () const
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
const IG & ig
Definition: constraints.hh:149
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
static void postStep(const LOP &lop)
Definition: combinedoperator.hh:589
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
static void preStage(const LOP &lop, RealType time, int r)
Definition: combinedoperator.hh:595
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 applyLops(FArgs &... args) const
Definition: combinedoperator.hh:38
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
static void setTime(const LOP &lop, RealType t)
Definition: combinedoperator.hh:576
ArgPtrs lops
Definition: combinedoperator.hh:35
std::tuple< Args &... > ArgRefs
Definition: combinedoperator.hh:33
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
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
static void postStage(const LOP &lop)
Definition: combinedoperator.hh:601
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
CombinedOperator(ArgPtrs &&l)
Definition: combinedoperator.hh:58
CombinedOperator(Args &&... args)
Definition: combinedoperator.hh:54
void preStep(RealType time, RealType dt, int stages)
to be called once before each time step
Definition: combinedoperator.hh:627
static void preStep(const LOP &lop, RealType time, RealType dt, int stages)
Definition: combinedoperator.hh:582
std::tuple_element_t< i, ArgRefs > getSummand()
get the i'th component of the sum
Definition: combinedoperator.hh:68
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
std::tuple< std::shared_ptr< std::remove_reference_t< Args > >... > ArgPtrs
Definition: combinedoperator.hh:32
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
static RealType suggestTimestep(const LOP &lop, RealType &dt)
Definition: combinedoperator.hh:607
CombinedOperator(Args &... args)
Definition: combinedoperator.hh:52
CombinedOperator()
Definition: combinedoperator.hh:50
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
@ doLambdaVolumePostSkeleton
Definition: combinedoperator.hh:150
@ doLambdaSkeleton
Definition: combinedoperator.hh:153
@ doSkeletonTwoSided
Definition: combinedoperator.hh:160
@ isLinear
Definition: combinedoperator.hh:168
@ doPatternSkeleton
Definition: combinedoperator.hh:116
@ doAlphaSkeleton
Definition: combinedoperator.hh:138
@ doLambdaVolume
Definition: combinedoperator.hh:146
@ doAlphaBoundary
Definition: combinedoperator.hh:142
@ doPatternBoundary
Definition: combinedoperator.hh:121
@ doPatternVolumePostSkeleton
Definition: combinedoperator.hh:111
@ doPatternVolume
Definition: combinedoperator.hh:105
@ doSkipEntity
Definition: combinedoperator.hh:92
@ doLambdaBoundary
Definition: combinedoperator.hh:156
@ doSkipIntersection
Definition: combinedoperator.hh:98
@ doAlphaVolume
Definition: combinedoperator.hh:128
@ doAlphaVolumePostSkeleton
Definition: combinedoperator.hh:134
For backward compatibility – Do not use this!
Definition: adaptivity.hh:28
std::enable_if_t< LOP::isLinear > jacobianApplySkeleton(const LOP &lop, const IG &ig, const LFSU &lfsu_s, const X &z_s, const LFSV &lfsv_s, const LFSU &lfsu_n, const X &z_n, const LFSV &lfsv_n, Y &y_s, Y &y_n)
Definition: jacobianapplyhelper.hh:64
std::enable_if_t< LOP::isLinear > jacobianApplyVolume(const LOP &lop, const EG &eg, const LFSU &lfsu, const X &z, const LFSV &lfsv, Y &y)
Definition: jacobianapplyhelper.hh:23
std::enable_if_t< LOP::isLinear > jacobianApplyBoundary(const LOP &lop, const IG &ig, const LFSU &lfsu_s, const X &z_s, const LFSV &lfsv_s, Y &y_s)
Definition: jacobianapplyhelper.hh:109
A dense matrix for storing data associated with the degrees of freedom of a pair of LocalFunctionSpac...
Definition: localmatrix.hh:184
A local operator to take combine different local operators.
Definition: combinedoperator.hh:30