12 #ifndef MFEM_TEMPLATE_TENSOR
13 #define MFEM_TEMPLATE_TENSOR
15 #include "../config/tconfig.hpp"
16 #include "../general/tassign.hpp"
37 template <
AssignOp::Type Op,
typename A_layout_t,
typename A_data_t,
39 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
42 MFEM_STATIC_ASSERT(A_layout_t::rank == 1,
"invalid rank");
43 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
45 mfem::Assign<Op>(A_data[A_layout.ind(i1)], value);
51 typename A_layout_t,
typename A_data_t,
52 typename B_layout_t,
typename B_data_t>
53 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
54 const B_layout_t &B_layout,
const B_data_t &B_data)
56 MFEM_STATIC_ASSERT(A_layout_t::rank == 1 && B_layout_t::rank == 1,
58 MFEM_STATIC_ASSERT(A_layout_t::dim_1 == B_layout_t::dim_1,
59 "invalid dimensions");
60 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
62 mfem::Assign<Op>(A_data[A_layout.ind(i1)], B_data[B_layout.ind(i1)]);
71 template <
AssignOp::Type Op,
typename A_layout_t,
typename A_data_t,
73 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
76 MFEM_STATIC_ASSERT(A_layout_t::rank == 2,
"invalid rank");
77 for (
int i2 = 0; i2 < A_layout_t::dim_2; i2++)
79 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
81 mfem::Assign<Op>(A_data[A_layout.ind(i1,i2)], value);
88 typename A_layout_t,
typename A_data_t,
89 typename B_layout_t,
typename B_data_t>
90 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
91 const B_layout_t &B_layout,
const B_data_t &B_data)
93 MFEM_STATIC_ASSERT(A_layout_t::rank == 2 && B_layout_t::rank == 2,
95 MFEM_STATIC_ASSERT(A_layout_t::dim_1 == B_layout_t::dim_1 &&
96 A_layout_t::dim_2 == B_layout_t::dim_2,
97 "invalid dimensions");
98 for (
int i2 = 0; i2 < A_layout_t::dim_2; i2++)
100 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
102 mfem::Assign<Op>(A_data[A_layout.ind(i1,i2)],
103 B_data[B_layout.ind(i1,i2)]);
113 template <
AssignOp::Type Op,
typename A_layout_t,
typename A_data_t,
115 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
118 MFEM_STATIC_ASSERT(A_layout_t::rank == 3,
"invalid rank");
119 for (
int i3 = 0; i3 < A_layout_t::dim_3; i3++)
121 for (
int i2 = 0; i2 < A_layout_t::dim_2; i2++)
123 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
125 mfem::Assign<Op>(A_data[A_layout.ind(i1,i2,i3)], value);
133 typename A_layout_t,
typename A_data_t,
134 typename B_layout_t,
typename B_data_t>
135 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
136 const B_layout_t &B_layout,
const B_data_t &B_data)
138 MFEM_STATIC_ASSERT(A_layout_t::rank == 3 && B_layout_t::rank == 3,
140 MFEM_STATIC_ASSERT(A_layout_t::dim_1 == B_layout_t::dim_1 &&
141 A_layout_t::dim_2 == B_layout_t::dim_2 &&
142 A_layout_t::dim_3 == B_layout_t::dim_3,
143 "invalid dimensions");
144 for (
int i3 = 0; i3 < A_layout_t::dim_3; i3++)
146 for (
int i2 = 0; i2 < A_layout_t::dim_2; i2++)
148 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
150 mfem::Assign<Op>(A_data[A_layout.ind(i1,i2,i3)],
151 B_data[B_layout.ind(i1,i2,i3)]);
162 template <
AssignOp::Type Op,
typename A_layout_t,
typename A_data_t,
164 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
167 MFEM_STATIC_ASSERT(A_layout_t::rank == 4,
"invalid rank");
168 for (
int i4 = 0; i4 < A_layout_t::dim_4; i4++)
170 for (
int i3 = 0; i3 < A_layout_t::dim_3; i3++)
172 for (
int i2 = 0; i2 < A_layout_t::dim_2; i2++)
174 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
176 mfem::Assign<Op>(A_data[A_layout.ind(i1,i2,i3,i4)], value);
185 typename A_layout_t,
typename A_data_t,
186 typename B_layout_t,
typename B_data_t>
187 static void Assign(
const A_layout_t &A_layout, A_data_t &A_data,
188 const B_layout_t &B_layout,
const B_data_t &B_data)
190 MFEM_STATIC_ASSERT(A_layout_t::rank == 4 && B_layout_t::rank == 4,
192 MFEM_STATIC_ASSERT(A_layout_t::dim_1 == B_layout_t::dim_1 &&
193 A_layout_t::dim_2 == B_layout_t::dim_2 &&
194 A_layout_t::dim_3 == B_layout_t::dim_3 &&
195 A_layout_t::dim_4 == B_layout_t::dim_4,
196 "invalid dimensions");
197 for (
int i4 = 0; i4 < A_layout_t::dim_4; i4++)
199 for (
int i3 = 0; i3 < A_layout_t::dim_3; i3++)
201 for (
int i2 = 0; i2 < A_layout_t::dim_2; i2++)
203 for (
int i1 = 0; i1 < A_layout_t::dim_1; i1++)
205 mfem::Assign<Op>(A_data[A_layout.ind(i1,i2,i3,i4)],
206 B_data[B_layout.ind(i1,i2,i3,i4)]);
217 template <
AssignOp::Type Op,
typename A_layout_t,
typename A_data_t,
219 inline void TAssign(
const A_layout_t &A_layout, A_data_t &A_data,
222 internal::TensorOps<A_layout_t::rank>::
223 template Assign<Op>(A_layout, A_data, value);
230 typename A_layout_t,
typename A_data_t,
231 typename B_layout_t,
typename B_data_t>
232 inline void TAssign(
const A_layout_t &A_layout, A_data_t &A_data,
233 const B_layout_t &B_layout,
const B_data_t &B_data)
235 internal::TensorOps<A_layout_t::rank>::
236 template Assign<Op>(A_layout, A_data, B_layout, B_data);
242 template <
int S,
typename data_t =
double,
bool align = false>
257 template <AssignOp::Type Op>
263 template <AssignOp::Type Op,
typename src_data_t>
269 template <AssignOp::Type Op,
typename dest_data_t>
277 Assign<AssignOp::Set>(d);
280 template <
typename src_data_t>
281 void Set(
const src_data_t &src)
283 Assign<AssignOp::Set>(src);
286 template <
typename dest_data_t>
289 AssignTo<AssignOp::Add>(dest);
294 Assign<AssignOp::Mult>(scale);
298 template <
int S,
typename data_t,
bool align>
299 const typename TVector<S,data_t,align>::layout_type
300 TVector<S,data_t,align>::layout = layout_type();
303 template <
int N1,
int N2,
typename data_t =
double,
bool align = false>
334 template <
int N1,
int N2,
typename data_t,
bool align>
335 const typename TMatrix<N1,N2,data_t,align>::layout_type
336 TMatrix<N1,N2,data_t,align>::layout = layout_type();
339 template <
int N1,
int N2,
int N3,
typename data_t =
double,
bool align = false>
348 static inline int ind(
int i1,
int i2,
int i3)
356 template <
int N1,
int N2,
int N3,
typename data_t,
bool align>
357 const typename TTensor3<N1,N2,N3,data_t,align>::layout_type
358 TTensor3<N1,N2,N3,data_t,align>::layout = layout_type();
360 template <
int N1,
int N2,
int N3,
int N4,
typename data_t = double,
370 static inline int ind(
int i1,
int i2,
int i3,
int i4)
379 template <
int N1,
int N2,
int N3,
int N4,
typename data_t,
bool align>
380 const typename TTensor4<N1,N2,N3,N4,data_t,align>::layout_type
381 TTensor4<N1,N2,N3,N4,data_t,align>::layout = layout_type();
388 typename A_layout_t,
typename A_data_t,
389 typename B_layout_t,
typename B_data_t,
390 typename C_layout_t,
typename C_data_t>
391 MFEM_ALWAYS_INLINE
inline
392 void Mult_1_2(
const A_layout_t &A_layout,
const A_data_t &A_data,
393 const B_layout_t &B_layout,
const B_data_t &B_data,
394 const C_layout_t &C_layout, C_data_t &C_data)
396 MFEM_STATIC_ASSERT(A_layout_t::rank == 2 && B_layout_t::rank == 3 &&
397 C_layout_t::rank == 3,
"invalid ranks");
398 const int B3 = B_layout_t::dim_3;
399 const int C3 = C_layout_t::dim_3;
400 MFEM_STATIC_ASSERT(B3 == C3,
"invalid dimentions");
401 for (
int k = 0; k < B3; k++)
403 Mult_AB<Add>(B_layout.ind3(k), B_data,
405 C_layout.ind3(k), C_data);
411 typename A_layout_t,
typename A_data_t,
412 typename B_layout_t,
typename B_data_t,
413 typename C_layout_t,
typename C_data_t>
414 MFEM_ALWAYS_INLINE
inline
415 void Mult_2_1(
const A_layout_t &A_layout,
const A_data_t &A_data,
416 const B_layout_t &B_layout,
const B_data_t &B_data,
417 const C_layout_t &C_layout, C_data_t &C_data)
419 MFEM_STATIC_ASSERT(A_layout_t::rank == 2 && B_layout_t::rank == 3 &&
420 C_layout_t::rank == 3,
"invalid ranks");
421 Mult_AB<Add>(A_layout, A_data,
422 B_layout.merge_23(), B_data,
423 C_layout.merge_23(), C_data);
428 typename A_layout_t,
typename A_data_t,
429 typename B_layout_t,
typename B_data_t,
430 typename C_layout_t,
typename C_data_t>
431 MFEM_ALWAYS_INLINE
inline
433 const B_layout_t &B_layout,
const B_data_t &B_data,
434 const C_layout_t &C_layout, C_data_t &C_data)
436 MFEM_STATIC_ASSERT(A_layout_t::rank == 2 && B_layout_t::rank == 3 &&
437 C_layout_t::rank == 4,
"invalid ranks");
438 const int A1 = A_layout_t::dim_1;
439 const int A2 = A_layout_t::dim_2;
440 const int B1 = B_layout_t::dim_1;
441 const int B2 = B_layout_t::dim_2;
442 const int B3 = B_layout_t::dim_3;
443 const int C1 = C_layout_t::dim_1;
444 const int C2 = C_layout_t::dim_2;
445 const int C3 = C_layout_t::dim_3;
446 const int C4 = C_layout_t::dim_4;
447 MFEM_STATIC_ASSERT(A1 == B2 && A2 == C1 && A2 == C3 && B1 == C2 && B3 == C4,
448 "invalid dimensions");
452 MFEM_FLOPS_ADD(3*A1*A2*A2*B1*B3);
453 if (!
Add) { TAssign<AssignOp::Set>(C_layout, C_data, 0.0); }
454 for (
int j = 0; j < A2; j++)
456 for (
int i = 0; i < A2; i++)
458 for (
int l = 0; l < B3; l++)
460 for (
int k = 0; k < B1; k++)
462 for (
int s = 0; s < A1; s++)
465 C_data[C_layout.ind(i,k,j,l)] +=
466 A_data[A_layout.ind(s,i)] *
467 A_data[A_layout.ind(s,j)] *
468 B_data[B_layout.ind(k,s,l)];
476 if (!
Add) { TAssign<AssignOp::Set>(C_layout, C_data, 0.0); }
477 for (
int s = 0; s < A1; s++)
479 for (
int i = 0; i < A2; i++)
481 for (
int k = 0; k < B1; k++)
483 for (
int j = 0; j < A2; j++)
485 for (
int l = 0; l < B3; l++)
488 C_data[C_layout.ind(i,k,j,l)] +=
489 A_data[A_layout.ind(s,i)] *
490 A_data[A_layout.ind(s,j)] *
491 B_data[B_layout.ind(k,s,l)];
502 typename A_layout_t,
typename A_data_t,
503 typename B_layout_t,
typename B_data_t,
504 typename C_layout_t,
typename C_data_t,
505 typename D_layout_t,
typename D_data_t>
506 MFEM_ALWAYS_INLINE
inline
508 const B_layout_t &B_layout,
const B_data_t &B_data,
509 const C_layout_t &C_layout,
const C_data_t &C_data,
510 const D_layout_t &D_layout, D_data_t &D_data)
512 MFEM_STATIC_ASSERT(A_layout_t::rank == 2 && B_layout_t::rank == 2 &&
513 C_layout_t::rank == 3 && D_layout_t::rank == 4,
515 const int A1 = A_layout_t::dim_1;
516 const int A2 = A_layout_t::dim_2;
517 const int B1 = B_layout_t::dim_1;
518 const int B2 = B_layout_t::dim_2;
519 const int C1 = C_layout_t::dim_1;
520 const int C2 = C_layout_t::dim_2;
521 const int C3 = C_layout_t::dim_3;
522 const int D1 = D_layout_t::dim_1;
523 const int D2 = D_layout_t::dim_2;
524 const int D3 = D_layout_t::dim_3;
525 const int D4 = D_layout_t::dim_4;
526 MFEM_STATIC_ASSERT(A2 == B1 && A2 == C2 && A1 == D1 && B2 == D3 &&
527 C1 == D2 && C3 == D4,
"invalid dimensions");
532 for (
int l = 0; l < C3; l++)
534 for (
int s = 0; s < B1; s++)
536 for (
int k = 0; k < C1; k++)
538 for (
int i = 0; i < A1; i++)
540 H(i,k,s,l) = A_data[A_layout.ind(i,s)]*
541 C_data[C_layout.ind(k,s,l)];
547 Mult_1_2<Add>(B_layout, B_data, H.
layout.merge_12(), H,
548 D_layout.merge_12(), D_data);
550 MFEM_FLOPS_ADD(A1*B1*C1*C3);
551 for (
int l = 0; l < C3; l++)
555 for (
int s = 0; s < B1; s++)
557 for (
int k = 0; k < C1; k++)
559 for (
int i = 0; i < A1; i++)
561 H(i,k,s) = A_data[A_layout.ind(i,s)]*
562 C_data[C_layout.ind(k,s,l)];
567 Mult_AB<Add>(H.
layout.merge_12(), H, B_layout, B_data,
568 D_layout.merge_12().ind3(l), D_data);
572 for (
int l = 0; l < C3; l++)
574 for (
int j = 0; j < B2; j++)
576 for (
int k = 0; k < C1; k++)
578 for (
int s = 0; s < B1; s++)
580 F(s,k,j,l) = B_data[B_layout.ind(s,j)]*
581 C_data[C_layout.ind(k,s,l)];
586 Mult_AB<Add>(A_layout, A_data, F.
layout.merge_34().merge_23(), F,
587 D_layout.merge_34().merge_23(), D_data);
594 typename A_layout_t,
typename A_data_t,
595 typename B_layout_t,
typename B_data_t,
596 typename C_layout_t,
typename C_data_t>
597 MFEM_ALWAYS_INLINE
inline
599 const B_layout_t &b,
const B_data_t &B,
600 const C_layout_t &c, C_data_t &C)
602 const int A1 = A_layout_t::dim_1;
603 const int A2 = A_layout_t::dim_2;
604 const int A3 = A_layout_t::dim_3;
605 const int B1 = B_layout_t::dim_1;
606 const int B2 = B_layout_t::dim_2;
607 const int C1 = C_layout_t::dim_1;
608 const int C2 = C_layout_t::dim_2;
609 const int C3 = C_layout_t::dim_3;
610 const int C4 = C_layout_t::dim_4;
611 MFEM_STATIC_ASSERT(A1 == C1 && A2 == B1 && A2 == C2 && A3 == C3 && B2 == C4,
612 "invalid dimensions");
614 MFEM_FLOPS_ADD(A1*A2*A3*B2);
615 for (
int l = 0; l < B2; l++)
617 for (
int k = 0; k < A3; k++)
619 for (
int j = 0; j < A2; j++)
621 for (
int i = 0; i < A1; i++)
623 mfem::Assign<Op>(C[c.ind(i,j,k,l)],
624 A[a.ind(i,j,k)]*B[b.ind(j,l)]);
633 #endif // MFEM_TEMPLATE_TENSOR
void Assemble(dest_data_t &dest) const
ColumnMajorLayout3D< N1, N2, N3 > layout_type
ColumnMajorLayout4D< N1, N2, N3, N4 > layout_type
static const layout_type layout
void Adjugate(TMatrix< N1, N2, data_t > &adj) const
void Assign(const src_data_t &src)
void AssignTo(dest_data_t &dest)
const data_t & operator()(int i, int j, int k) const
void TAssign(const A_layout_t &A_layout, A_data_t &A_data, scalar_t value)
void Assign(const data_t d)
static const layout_type layout
static int ind(int i1, int i2, int i3)
const data_t & operator()(int i, int j) const
data_t & operator()(int i, int j)
MFEM_ALWAYS_INLINE void TensorAssemble(const A_layout_t &A_layout, const A_data_t &A_data, const B_layout_t &B_layout, const B_data_t &B_data, const C_layout_t &C_layout, C_data_t &C_data)
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
static const layout_type layout
static int ind(int i1, int i2, int i3, int i4)
static int ind(int i1, int i2, int i3, int i4)
data_t & operator[](int i)
const data_t & operator()(int i, int j, int k, int l) const
static int ind(int i1, int i2, int i3)
TVector< N1 *N2, data_t, align > base_class
static int ind(int i1, int i2)
MFEM_ALWAYS_INLINE void Mult_2_1(const A_layout_t &A_layout, const A_data_t &A_data, const B_layout_t &B_layout, const B_data_t &B_data, const C_layout_t &C_layout, C_data_t &C_data)
ColumnMajorLayout2D< N1, N2 > layout_type
MFEM_ALWAYS_INLINE void TensorProduct(const A_layout_t &a, const A_data_t &A, const B_layout_t &b, const B_data_t &B, const C_layout_t &c, C_data_t &C)
static const layout_type layout
lvalue_t & Assign(lvalue_t &a, const rvalue_t &b)
TVector< N1 *N2 *N3 *N4, data_t, align > base_class
static int ind(int i1, int i2)
data_t AdjDet(TMatrix< N2, N1, data_t > &adj) const
MFEM_ALWAYS_INLINE void Mult_1_2(const A_layout_t &A_layout, const A_data_t &A_data, const B_layout_t &B_layout, const B_data_t &B_data, const C_layout_t &C_layout, C_data_t &C_data)
TVector< N1 *N2 *N3, data_t, align > base_class
StridedLayout1D< S, 1 > layout_type
data_t data[aligned_size >0?aligned_size:1]
void Set(const src_data_t &src)
const data_t & operator[](int i) const
static const int aligned_size
void Scale(const data_t scale)
data_t & operator()(int i, int j, int k, int l)
data_t & operator()(int i, int j, int k)