12#include <dune/localfunctions/utility/field.hh>
29 template <
class F,
int dimD,
unsigned int deriv>
32 typedef LFETensor<F,dimD,deriv> This;
33 typedef LFETensor<F,dimD-1,deriv> BaseDim;
34 typedef LFETensor<F,dimD,deriv-1> BaseDeriv;
38 static const unsigned int size = BaseDim::size+BaseDeriv::size;
42 This &operator= (
const FF &f )
44 block() = field_cast< F >( f );
48 This &operator= (
const Block &b )
54 This &operator*= (
const field_type &f )
60 const field_type &operator[] (
const unsigned int i )
const
65 field_type &operator[] (
const unsigned int i )
74 const Block &block()
const
78 void axpy(
const F& a,
const This &y)
80 block().axpy(a,y.block());
83 void assign(
const LFETensor<Fy,dimD,deriv> &y)
91 template <
class F,
unsigned int deriv>
92 struct LFETensor<F,0,deriv>
94 static const int size = 0;
98 struct LFETensor<F,0,0>
100 static const int size = 1;
103 template <
class F,
int dimD>
104 class LFETensor<F,dimD,0>
106 typedef LFETensor<F,dimD,0> This;
109 typedef F field_type;
110 static const int size = 1;
114 This &operator= (
const FF &f )
116 block() = field_cast< F >( f );
120 This &operator= (
const Block &b )
126 This &operator*= (
const field_type &f )
132 const F &operator[] (
const unsigned int i )
const
137 F &operator[] (
const unsigned int i )
142 void axpy(
const F& a,
const This &y)
144 block().axpy(a,y.block());
147 void assign(
const LFETensor<Fy,dimD,0> &y)
156 const Block &block()
const
165 enum DerivativeLayout {value,derivative};
166 template <
class F,
int dimD,
int dimR,
unsigned int deriv,
167 DerivativeLayout layout>
171 template <
class F,
int dimD,
int dimR,
unsigned int deriv>
172 struct Derivatives<F,dimD,dimR,deriv,value>
173 :
public Derivatives<F,dimD,dimR,deriv-1,value>
175 typedef Derivatives<F,dimD,dimR,deriv,value> This;
176 typedef Derivatives<F,dimD,dimR,deriv-1,value> Base;
177 typedef LFETensor<F,dimD,deriv> ThisLFETensor;
180 typedef F field_type;
182 static const DerivativeLayout layout = value;
183 static const unsigned int dimDomain = dimD;
184 static const unsigned int dimRange = dimR;
186 enum { size = Base::size+ThisLFETensor::size*dimR };
189 This &operator=(
const F& f)
199 template <
unsigned int dorder>
202 tensor<dorder>() = t;
205 This &operator=(
const Block &t)
211 This &operator*= (
const field_type &f )
217 void axpy(
const F &a,
const This &y)
219 block().axpy(a,y.block());
224 void assign(
const Derivatives<Fy,dimD,dimR,deriv,value> &y)
230 void assign(
const Derivatives<Fy,dimD,dimR,deriv,derivative> &y)
233 for (
int rr=0; rr<dimR; ++rr)
234 tensor_[rr] = y[rr].
template tensor<deriv>()[0];
237 template <
class Fy,
int dimRy>
238 void assign(
const Derivatives<Fy,dimD,dimRy,deriv,value> &y,
unsigned int r)
240 assign<Fy,dimRy>(y.block(),r);
244 void assign(
unsigned int r,
const Derivatives<Fy,dimD,1,deriv,value> &y)
249 void assign(
unsigned int r,
const Derivatives<Fy,dimD,1,deriv,derivative> &y)
256 return reinterpret_cast<Block&
>(*this);
258 const Block &block()
const
260 return reinterpret_cast<const Block&
>(*this);
263 template <
unsigned int dorder>
267 const std::integral_constant<int,dorder> a = {};
270 template <
unsigned int dorder>
274 return tensor(std::integral_constant<int,dorder>());
276 template <
unsigned int dorder>
280 const std::integral_constant<int,dorder> a = {};
283 template <
unsigned int dorder>
287 const std::integral_constant<int,dorder> a = {};
290 ThisLFETensor &operator[](
int r) {
293 const ThisLFETensor &operator[](
int r)
const {
297 template <
class Fy,
int dimRy>
298 void assign(
const FieldVector<Fy,size*dimRy> &y,
unsigned int r)
300 Base::template assign<Fy,dimRy>(
reinterpret_cast<const FieldVector<Fy,Base::size*dimRy>&
>(y),r);
301 tensor_[0] =
reinterpret_cast<const FieldVector<Fy,ThisLFETensor::size>&
>(y[Base::size*dimRy+r*ThisLFETensor::size]);
304 void assign(
unsigned int r,
const FieldVector<Fy,size/dimR> &y)
306 Base::assign(r,
reinterpret_cast<const FieldVector<Fy,Base::size/dimR
>&>(y));
307 tensor_[r] =
reinterpret_cast<const FieldVector<Fy,ThisLFETensor::size>&
>(y[Base::size/dimR]);
310 template <
class Fy,
unsigned int dy>
311 void assign(
const Derivatives<Fy,dimD,dimR,dy,derivative> &y)
314 for (
int rr=0; rr<dimR; ++rr)
315 tensor_[rr] = y[rr].
template tensor<deriv>()[0];
318 template <
int dorder>
320 tensor(
const std::integral_constant<int,dorder> &dorderVar)
const
322 return Base::tensor(dorderVar);
325 tensor(
const std::integral_constant<int,deriv> &dorderVar)
const
329 template <
int dorder>
331 tensor(
const std::integral_constant<int,dorder> &dorderVar)
333 return Base::tensor(dorderVar);
336 tensor(
const std::integral_constant<int,deriv> &dorderVar)
343 template <
class F,
int dimD,
int dimR>
344 struct Derivatives<F,dimD,dimR,0,value>
346 typedef Derivatives<F,dimD,dimR,0,value> This;
347 typedef LFETensor<F,dimD,0> ThisLFETensor;
350 typedef F field_type;
352 static const DerivativeLayout layout = value;
353 static const unsigned int dimDomain = dimD;
354 static const unsigned int dimRange = dimR;
356 enum { size = ThisLFETensor::size*dimR };
360 This &operator=(
const FF& f)
362 for (
int r=0; r<dimR; ++r)
363 tensor_[r] = field_cast<F>(f);
372 This &operator=(
const Block &t)
378 This &operator*= (
const field_type &f )
384 void axpy(
const F &a,
const This &y)
386 block().axpy(a,y.block());
389 void assign(
const Derivatives<Fy,dimD,dimR,0,value> &y)
394 void assign(
const Derivatives<Fy,dimD,dimR,0,derivative> &y)
396 for (
int rr=0; rr<dimR; ++rr)
397 tensor_[rr] = y[rr].
template tensor<0>()[0];
399 template <
class Fy,
int dimRy>
400 void assign(
const Derivatives<Fy,dimD,dimRy,0,value> &y,
unsigned int r)
402 assign<Fy,dimRy>(y.block(),r);
405 void assign(
unsigned int r,
const Derivatives<Fy,dimD,1,0,value> &y)
407 tensor_[r].assign(y[0]);
410 void assign(
unsigned int r,
const Derivatives<Fy,dimD,1,0,derivative> &y)
412 tensor_[r].assign(y[0][0]);
417 return reinterpret_cast<Block&
>(*this);
419 const Block &block()
const
421 return reinterpret_cast<const Block&
>(*this);
424 ThisLFETensor &operator[](
int r) {
427 const ThisLFETensor &operator[](
int r)
const {
430 template <
int dorder>
439 template <
unsigned int dorder>
443 const std::integral_constant<int,dorder> a = {};
446 template <
unsigned int dorder>
450 const std::integral_constant<int,dorder> a = {};
456 tensor(
const std::integral_constant<int,0> &dorderVar)
const
461 tensor(
const std::integral_constant<int,0> &dorderVar)
465 template <
class Fy,
unsigned int dy>
466 void assign(
const Derivatives<Fy,dimD,dimR,dy,derivative> &y)
468 for (
int rr=0; rr<dimR; ++rr)
469 tensor_[rr] = y[rr].
template tensor<0>()[0];
471 template <
class Fy,
int dimRy>
472 void assign(
const FieldVector<Fy,size*dimRy> &y,
unsigned int r)
474 tensor_[0] =
reinterpret_cast<const FieldVector<Fy,ThisLFETensor::size>&
>(y[r*ThisLFETensor::size]);
477 void assign(
unsigned int r,
const FieldVector<Fy,size/dimR> &y)
485 template <
class F,
int dimD,
int dimR,
unsigned int deriv>
486 struct Derivatives<F,dimD,dimR,deriv,derivative>
488 typedef Derivatives<F,dimD,dimR,deriv,derivative> This;
489 typedef Derivatives<F,dimD,1,deriv,value> ScalarDeriv;
492 typedef F field_type;
494 static const DerivativeLayout layout = value;
495 static const unsigned int dimDomain = dimD;
496 static const unsigned int dimRange = dimR;
498 enum { size = ScalarDeriv::size*dimR };
502 This &operator=(
const FF& f)
504 block() = field_cast<F>(f);
507 This &operator=(
const Block &t)
513 This &operator*= (
const field_type &f )
520 void axpy(
const FF &a,
const This &y)
522 block().axpy(field_cast<F>(a),y.block());
526 void assign(
const Derivatives<Fy,dimD,dimR,deriv,derivative> &y)
532 void assign(
const Derivatives<Fy,dimD,dimR,deriv,value> &y)
534 for (
unsigned int rr=0; rr<dimR; ++rr)
538 template <
class Fy,DerivativeLayout layouty>
539 void assign(
unsigned int r,
const Derivatives<Fy,dimD,1,deriv,layouty> &y)
541 deriv_[r].assign(r,y);
546 return reinterpret_cast<Block&
>(*this);
548 const Block &block()
const
550 return reinterpret_cast<const Block&
>(*this);
553 ScalarDeriv &operator[](
int r) {
556 const ScalarDeriv &operator[](
int r)
const {
566 template <
class Vec1,
class Vec2,
unsigned int deriv>
569 template <
class Field>
570 static void apply(
unsigned int r,
const Field &a,
571 const Vec1 &x, Vec2 &y)
576 template <
class F1,
int dimD,
int dimR,
580 struct LFETensorAxpy<Derivatives<F1,dimD,dimR,d,value>,Vec2,deriv>
582 typedef Derivatives<F1,dimD,dimR,d,value> Vec1;
583 template <
class Field>
584 static void apply(
unsigned int r,
const Field &a,
585 const Vec1 &x, Vec2 &y)
587 const FieldVector<F1,Vec2::size> &xx = x.template block<deriv>();
588 for (
int i=0; i<y.size; ++i)
592 template <
class F1,
int dimD,
int dimR,
596 struct LFETensorAxpy<Derivatives<F1,dimD,dimR,d,derivative>,Vec2,deriv>
598 typedef Derivatives<F1,dimD,dimR,d,derivative> Vec1;
599 template <
class Field>
600 static void apply(
unsigned int r,
const Field &a,
601 const Vec1 &x, Vec2 &y)
603 for (
int rr=0; rr<dimR; ++rr)
604 LFETensorAxpy<Derivatives<F1,dimD,1,d,value>,
605 Vec2,deriv>
::apply(rr,a,x[rr],y);
608 template <
class F1,
int dimD,
612 struct LFETensorAxpy<Derivatives<F1,dimD,1,d,derivative>,Vec2,deriv>
614 typedef Derivatives<F1,dimD,1,d,derivative> Vec1;
615 template <
class Field>
616 static void apply(
unsigned int r,
const Field &a,
617 const Vec1 &x, Vec2 &y)
619 LFETensorAxpy<Derivatives<F1,dimD,1,d,value>,
620 Vec2,deriv>
::apply(r,a,x[0],y);
623 template <
class F1,
int dimD,
627 struct LFETensorAxpy<Derivatives<F1,dimD,1,d,value>,Vec2,deriv>
629 typedef Derivatives<F1,dimD,1,d,value> Vec1;
630 template <
class Field>
631 static void apply(
unsigned int r,
const Field &a,
632 const Vec1 &x, Vec2 &y)
634 typedef LFETensor<F1,dimD,deriv> LFETensorType;
635 const unsigned int rr = r*LFETensorType::size;
636 const FieldVector<F1,LFETensorType::size> &xx = x.template block<deriv>();
637 for (
int i=0; i<FieldVector<F1,LFETensorType::size>::dimension; ++i)
645 template <
class Vec1,
class Vec2>
646 struct DerivativeAssign
648 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
653 template <
int dimD,
int dimR,
unsigned int deriv, DerivativeLayout layout,
655 struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,layout>,
656 Derivatives<F2,dimD,dimR,deriv,layout> >
658 typedef Derivatives<F1,dimD,dimR,deriv,layout> Vec1;
659 typedef Derivatives<F2,dimD,dimR,deriv,layout> Vec2;
660 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
665 template <
int dimD,
int dimR,
unsigned int deriv,
667 struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,value>,
668 Derivatives<F2,dimD,dimR,deriv,derivative> >
670 typedef Derivatives<F1,dimD,dimR,deriv,value> Vec1;
671 typedef Derivatives<F2,dimD,dimR,deriv,derivative> Vec2;
672 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
677 template <
int dimD,
int dimR,
unsigned int deriv,
679 struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,derivative>,
680 Derivatives<F2,dimD,dimR,deriv,value> >
682 typedef Derivatives<F1,dimD,dimR,deriv,derivative> Vec1;
683 typedef Derivatives<F2,dimD,dimR,deriv,value> Vec2;
684 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
689 template <
int dimD,
int dimR,
unsigned int deriv,DerivativeLayout layout,
691 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,layout>,
692 Derivatives<F2,dimD,dimR,deriv,value> >
694 typedef Derivatives<F1,dimD,1,deriv,layout> Vec1;
695 typedef Derivatives<F2,dimD,dimR,deriv,value> Vec2;
696 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
701 template <
int dimD,
int dimR,
unsigned int deriv,DerivativeLayout layout,
703 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,layout>,
704 Derivatives<F2,dimD,dimR,deriv,derivative> >
706 typedef Derivatives<F1,dimD,1,deriv,layout> Vec1;
707 typedef Derivatives<F2,dimD,dimR,deriv,derivative> Vec2;
708 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
713 template <
int dimD,
unsigned int deriv,
715 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,
716 Derivatives<F2,dimD,1,deriv,value> >
718 typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
719 typedef Derivatives<F2,dimD,1,deriv,value> Vec2;
720 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
725 template <
int dimD,
unsigned int deriv,
727 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,
728 Derivatives<F2,dimD,1,deriv,derivative> >
730 typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
731 typedef Derivatives<F2,dimD,1,deriv,derivative> Vec2;
732 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
737 template <
int dimD,
unsigned int deriv,
739 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,
740 Derivatives<F2,dimD,1,deriv,value> >
742 typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
743 typedef Derivatives<F2,dimD,1,deriv,value> Vec2;
744 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
749 template <
int dimD,
unsigned int deriv,
751 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,
752 Derivatives<F2,dimD,1,deriv,derivative> >
754 typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
755 typedef Derivatives<F2,dimD,1,deriv,derivative> Vec2;
756 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
761 template <
int dimD,
unsigned int deriv,DerivativeLayout layout,
763 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,layout>,
766 typedef Derivatives<F1,dimD,1,deriv,layout> Vec1;
768 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
773 template <
int dimD,
int dimR,
774 class F1,
unsigned int deriv,
776 struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,value>,FieldVector<F2,dimR> >
778 typedef Derivatives<F1,dimD,dimR,deriv,value> Vec1;
779 typedef FieldVector<F2,dimR> Vec2;
780 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
785 template <
int dimD,
int dimR,
786 class F1,
unsigned int deriv,
788 struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,derivative>,FieldVector<F2,dimR> >
790 typedef Derivatives<F1,dimD,dimR,deriv,derivative> Vec1;
791 typedef FieldVector<F2,dimR> Vec2;
792 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
794 for (
int rr=0; rr<dimR; ++rr)
795 field_cast(vec1[rr].
template tensor<0>()[0].block(),vec2[rr]);
799 class F1,
unsigned int deriv,
801 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,FieldVector<F2,dimR> >
803 typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
804 typedef FieldVector<F2,dimR> Vec2;
805 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
807 field_cast(vec1.template tensor<0>()[0].block(),vec2[r]);
811 class F1,
unsigned int deriv,
813 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,FieldVector<F2,dimR> >
815 typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
816 typedef FieldVector<F2,dimR> Vec2;
817 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
819 field_cast(vec1[0].
template tensor<0>()[0].block(),vec2[r]);
823 class F1,
unsigned int deriv,
825 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,FieldVector<F2,1> >
827 typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
828 typedef FieldVector<F2,1> Vec2;
829 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
831 field_cast(vec1.template tensor<0>()[0].block(),vec2);
835 class F1,
unsigned int deriv,
837 struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,FieldVector<F2,1> >
839 typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
840 typedef FieldVector<F2,1> Vec2;
841 static void apply(
unsigned int r,
const Vec1 &vec1,Vec2 &vec2)
843 field_cast(vec1[0].
template tensor<0>()[0].block(),vec2);
850 template <
class F,
int dimD,
unsigned int deriv>
851 std::ostream &operator<< ( std::ostream &out,
const LFETensor< F,dimD,deriv > &tensor )
853 return out << tensor.block();
856 template <
class F,
int dimD,
unsigned int deriv>
857 std::ostream &operator<< ( std::ostream &out,
const ScalarDerivatives< F,dimD,deriv > &d )
859 out <<
static_cast<const ScalarDerivatives< F,dimD,deriv-1
> &>(d);
860 out <<
" , " << d.tensor() << std::endl;
863 template <
class F,
int dimD>
864 std::ostream &operator<< ( std::ostream &out,
const ScalarDerivatives< F,dimD,0 > &d )
866 out << d.tensor() << std::endl;
870 template <
class F,
int dimD,
int dimR,
unsigned int deriv>
871 std::ostream &operator<< ( std::ostream &out,
const Derivatives< F,dimD,dimR,deriv,derivative > &d )
875 for (
int r=1; r<dimR; ++r)
877 out <<
" , " << d[r];
879 out <<
" ) " << std::endl;
882 template <
class F,
int dimD,
int dimR,
unsigned int deriv>
883 std::ostream &operator<< ( std::ostream &out,
const Derivatives< F,dimD,dimR,deriv,value > &d )
885 out <<
static_cast<const Derivatives< F,dimD,dimR,deriv-1,value
> &>(d);
888 for (
int r=1; r<dimR; ++r)
890 out <<
" , " << d[r];
892 out <<
" ) " << std::endl;
895 template <
class F,
int dimD,
int dimR>
896 std::ostream &operator<< ( std::ostream &out,
const Derivatives< F,dimD,dimR,0,derivative > &d )
900 for (
int r=1; r<dimR; ++r)
902 out <<
" , " << d[r];
904 out <<
" ) " << std::endl;
907 template <
class F,
int dimD,
int dimR>
908 std::ostream &operator<< ( std::ostream &out,
const Derivatives< F,dimD,dimR,0,value > &d )
912 for (
int r=1; r<dimR; ++r)
914 out <<
" , " << d[r];
916 out <<
" ) " << std::endl;
919 template <
class F,
int dimD,
int dimR,
unsigned int deriv,DerivativeLayout layout>
920 std::ostream &operator<< ( std::ostream &out,
const std::vector<Derivatives< F,dimD,dimR,deriv,layout > > &y )
922 out <<
"Number of basis functions: " << y.size() << std::endl;
923 for (
unsigned int i=0; i<y.size(); ++i)
925 out <<
"Base " << i <<
" : " << std::endl;
Implements a vector constructed from a given type representing a field and a compile-time given size.
decltype(auto) apply(F &&f, ArgTuple &&args)
Apply function with arguments given as tuple.
Definition: apply.hh:58
Dune namespace.
Definition: alignedallocator.hh:10
void field_cast(const F1 &f1, F2 &f2)
a helper class to cast from one field to another
Definition: field.hh:157
void assign(T &dst, const T &src, bool mask)
masked Simd assignment (scalar version)
Definition: simd.hh:421