MFEM  v4.1.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
tevaluator.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_TEMPLATE_EVALUATOR
13 #define MFEM_TEMPLATE_EVALUATOR
14 
15 #include "../config/tconfig.hpp"
16 #include "../linalg/ttensor.hpp"
17 #include "../general/error.hpp"
18 #include "fespace.hpp"
19 
20 namespace mfem
21 {
22 
23 // Templated classes for transitioning between degrees of freedom and quadrature
24 // points values.
25 
26 // Shape evaluators -- values of basis functions on the reference element
27 
28 template <class FE, class IR, bool TP, typename real_t>
30 
31 // ShapeEvaluator without tensor-product structure
32 template <class FE, class IR, typename real_t>
33 class ShapeEvaluator_base<FE, IR, false, real_t>
34 {
35 public:
36  static const int DOF = FE::dofs;
37  static const int NIP = IR::qpts;
38  static const int DIM = FE::dim;
39 
40 protected:
45 
46 public:
47  ShapeEvaluator_base(const FE &fe)
48  {
49  fe.CalcShapes(IR::GetIntRule(), B.data, G.data);
50  TAssign<AssignOp::Set>(Bt.layout, Bt, B.layout.transpose_12(), B);
51  TAssign<AssignOp::Set>(Gt.layout.merge_23(), Gt,
52  G.layout.merge_12().transpose_12(), G);
53  }
54 
55  // default copy constructor
56 
57  // Multi-component shape evaluation from DOFs to quadrature points.
58  // dof_layout is (DOF x NumComp) and qpt_layout is (NIP x NumComp).
59  template <typename dof_layout_t, typename dof_data_t,
60  typename qpt_layout_t, typename qpt_data_t>
61  MFEM_ALWAYS_INLINE
62  void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data,
63  const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
64  {
65  MFEM_STATIC_ASSERT(dof_layout_t::rank == 2 &&
66  dof_layout_t::dim_1 == DOF,
67  "invalid dof_layout_t.");
68  MFEM_STATIC_ASSERT(qpt_layout_t::rank == 2 &&
69  qpt_layout_t::dim_1 == NIP,
70  "invalid qpt_layout_t.");
71  MFEM_STATIC_ASSERT(dof_layout_t::dim_2 == qpt_layout_t::dim_2,
72  "incompatible dof- and qpt- layouts.");
73 
74  Mult_AB<false>(B.layout, B,
75  dof_layout, dof_data,
76  qpt_layout, qpt_data);
77  }
78 
79  // Multi-component shape evaluation transpose from quadrature points to DOFs.
80  // qpt_layout is (NIP x NumComp) and dof_layout is (DOF x NumComp).
81  template <bool Add,
82  typename qpt_layout_t, typename qpt_data_t,
83  typename dof_layout_t, typename dof_data_t>
84  MFEM_ALWAYS_INLINE
85  void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
86  const dof_layout_t &dof_layout, dof_data_t &dof_data) const
87  {
88  MFEM_STATIC_ASSERT(dof_layout_t::rank == 2 &&
89  dof_layout_t::dim_1 == DOF,
90  "invalid dof_layout_t.");
91  MFEM_STATIC_ASSERT(qpt_layout_t::rank == 2 &&
92  qpt_layout_t::dim_1 == NIP,
93  "invalid qpt_layout_t.");
94  MFEM_STATIC_ASSERT(dof_layout_t::dim_2 == qpt_layout_t::dim_2,
95  "incompatible dof- and qpt- layouts.");
96 
97  Mult_AB<Add>(Bt.layout, Bt,
98  qpt_layout, qpt_data,
99  dof_layout, dof_data);
100  }
101 
102  // Multi-component gradient evaluation from DOFs to quadrature points.
103  // dof_layout is (DOF x NumComp) and grad_layout is (NIP x DIM x NumComp).
104  template <typename dof_layout_t, typename dof_data_t,
105  typename grad_layout_t, typename grad_data_t>
106  MFEM_ALWAYS_INLINE
107  void CalcGrad(const dof_layout_t &dof_layout,
108  const dof_data_t &dof_data,
109  const grad_layout_t &grad_layout,
110  grad_data_t &grad_data) const
111  {
112  MFEM_STATIC_ASSERT(dof_layout_t::rank == 2 &&
113  dof_layout_t::dim_1 == DOF,
114  "invalid dof_layout_t.");
115  MFEM_STATIC_ASSERT(grad_layout_t::rank == 3 &&
116  grad_layout_t::dim_1 == NIP &&
117  grad_layout_t::dim_2 == DIM,
118  "invalid grad_layout_t.");
119  MFEM_STATIC_ASSERT(dof_layout_t::dim_2 == grad_layout_t::dim_3,
120  "incompatible dof- and grad- layouts.");
121 
122  Mult_AB<false>(G.layout.merge_12(), G,
123  dof_layout, dof_data,
124  grad_layout.merge_12(), grad_data);
125  }
126 
127  // Multi-component gradient evaluation transpose from quadrature points to
128  // DOFs. grad_layout is (NIP x DIM x NumComp), dof_layout is (DOF x NumComp).
129  template <bool Add,
130  typename grad_layout_t, typename grad_data_t,
131  typename dof_layout_t, typename dof_data_t>
132  MFEM_ALWAYS_INLINE
133  void CalcGradT(const grad_layout_t &grad_layout,
134  const grad_data_t &grad_data,
135  const dof_layout_t &dof_layout,
136  dof_data_t &dof_data) const
137  {
138  MFEM_STATIC_ASSERT(dof_layout_t::rank == 2 &&
139  dof_layout_t::dim_1 == DOF,
140  "invalid dof_layout_t.");
141  MFEM_STATIC_ASSERT(grad_layout_t::rank == 3 &&
142  grad_layout_t::dim_1 == NIP &&
143  grad_layout_t::dim_2 == DIM,
144  "invalid grad_layout_t.");
145  MFEM_STATIC_ASSERT(dof_layout_t::dim_2 == grad_layout_t::dim_3,
146  "incompatible dof- and grad- layouts.");
147 
148  Mult_AB<Add>(Gt.layout.merge_23(), Gt,
149  grad_layout.merge_12(), grad_data,
150  dof_layout, dof_data);
151  }
152 
153  // Multi-component assemble.
154  // qpt_layout is (NIP x NumComp), M_layout is (DOF x DOF x NumComp)
155  template <typename qpt_layout_t, typename qpt_data_t,
156  typename M_layout_t, typename M_data_t>
157  MFEM_ALWAYS_INLINE
158  void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
159  const M_layout_t &M_layout, M_data_t &M_data) const
160  {
161  // M_{i,j,k} = \sum_{s} B_{s,i} B_{s,j} qpt_data_{s,k}
162  // Using TensorAssemble: <1,NIP,NC> --> <DOF,1,DOF,NC>
163 #if 0
164  TensorAssemble<false>(
165  B.layout, B,
166  qpt_layout.template split_1<1,NIP>(), qpt_data,
167  M_layout.template split_1<DOF,1>(), M_data);
168 #else
169  TensorAssemble<false>(
170  Bt.layout, Bt, B.layout, B,
171  qpt_layout.template split_1<1,NIP>(), qpt_data,
172  M_layout.template split_1<DOF,1>(), M_data);
173 #endif
174  }
175 
176  // Multi-component assemble of grad-grad element matrices.
177  // qpt_layout is (NIP x DIM x DIM x NumComp), and
178  // D_layout is (DOF x DOF x NumComp).
179  template <typename qpt_layout_t, typename qpt_data_t,
180  typename D_layout_t, typename D_data_t>
181  MFEM_ALWAYS_INLINE
182  void AssembleGradGrad(const qpt_layout_t &qpt_layout,
183  const qpt_data_t &qpt_data,
184  const D_layout_t &D_layout,
185  D_data_t &D_data) const
186  {
187  const int NC = qpt_layout_t::dim_4;
189  for (int k = 0; k < NC; k++)
190  {
191  // Next loop performs a batch of matrix-matrix products of size
192  // (DIM x DIM) x (DIM x DOF) --> (DIM x DOF)
193  for (int j = 0; j < NIP; j++)
194  {
195  Mult_AB<false>(qpt_layout.ind14(j,k), qpt_data,
196  G.layout.ind1(j), G,
197  F.layout.ind14(j,k), F);
198  }
199  }
200  // (DOF x (NIP x DIM)) x ((NIP x DIM) x DOF x NC) --> (DOF x DOF x NC)
201  Mult_2_1<false>(Gt.layout.merge_23(), Gt,
202  F.layout.merge_12(), F,
203  D_layout, D_data);
204  }
205 };
206 
207 template <int Dim, int DOF, int NIP, typename real_t>
209 
210 // ShapeEvaluator with 1D tensor-product structure
211 template <int DOF, int NIP, typename real_t>
212 class TProductShapeEvaluator<1, DOF, NIP, real_t>
213 {
214 protected:
215  static const int TDOF = DOF; // total dofs
216 
219 
220 public:
222 
223  // Multi-component shape evaluation from DOFs to quadrature points.
224  // dof_layout is (DOF x NumComp) and qpt_layout is (NIP x NumComp).
225  template <typename dof_layout_t, typename dof_data_t,
226  typename qpt_layout_t, typename qpt_data_t>
227  MFEM_ALWAYS_INLINE
228  void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data,
229  const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
230  {
231  Mult_AB<false>(B_1d.layout, B_1d,
232  dof_layout, dof_data,
233  qpt_layout, qpt_data);
234  }
235 
236  // Multi-component shape evaluation transpose from quadrature points to DOFs.
237  // qpt_layout is (NIP x NumComp) and dof_layout is (DOF x NumComp).
238  template <bool Add,
239  typename qpt_layout_t, typename qpt_data_t,
240  typename dof_layout_t, typename dof_data_t>
241  MFEM_ALWAYS_INLINE
242  void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
243  const dof_layout_t &dof_layout, dof_data_t &dof_data) const
244  {
245  Mult_AB<Add>(Bt_1d.layout, Bt_1d,
246  qpt_layout, qpt_data,
247  dof_layout, dof_data);
248  }
249 
250  // Multi-component gradient evaluation from DOFs to quadrature points.
251  // dof_layout is (DOF x NumComp) and grad_layout is (NIP x DIM x NumComp).
252  template <typename dof_layout_t, typename dof_data_t,
253  typename grad_layout_t, typename grad_data_t>
254  MFEM_ALWAYS_INLINE
255  void CalcGrad(const dof_layout_t &dof_layout,
256  const dof_data_t &dof_data,
257  const grad_layout_t &grad_layout,
258  grad_data_t &grad_data) const
259  {
260  // grad_data(nip,dim,comp) = sum(dof) G(nip,dim,dof) * dof_data(dof,comp)
261  Mult_AB<false>(G_1d.layout, G_1d,
262  dof_layout, dof_data,
263  grad_layout.merge_12(), grad_data);
264  }
265 
266  // Multi-component gradient evaluation transpose from quadrature points to
267  // DOFs. grad_layout is (NIP x DIM x NumComp), dof_layout is (DOF x NumComp).
268  template <bool Add,
269  typename grad_layout_t, typename grad_data_t,
270  typename dof_layout_t, typename dof_data_t>
271  MFEM_ALWAYS_INLINE
272  void CalcGradT(const grad_layout_t &grad_layout,
273  const grad_data_t &grad_data,
274  const dof_layout_t &dof_layout,
275  dof_data_t &dof_data) const
276  {
277  // dof_data(dof,comp) +=
278  // sum(nip,dim) G(nip,dim,dof) * grad_data(nip,dim,comp)
279  Mult_AB<Add>(Gt_1d.layout, Gt_1d,
280  grad_layout.merge_12(), grad_data,
281  dof_layout, dof_data);
282  }
283 
284  // Multi-component assemble.
285  // qpt_layout is (NIP x NumComp), M_layout is (DOF x DOF x NumComp)
286  template <typename qpt_layout_t, typename qpt_data_t,
287  typename M_layout_t, typename M_data_t>
288  MFEM_ALWAYS_INLINE
289  void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
290  const M_layout_t &M_layout, M_data_t &M_data) const
291  {
292  // M_{i,j,k} = \sum_{s} B_1d_{s,i} B_{s,j} qpt_data_{s,k}
293  // Using TensorAssemble: <1,NIP,NC> --> <DOF,1,DOF,NC>
294 #if 0
295  TensorAssemble<false>(
296  B_1d.layout, B_1d,
297  qpt_layout.template split_1<1,NIP>(), qpt_data,
298  M_layout.template split_1<DOF,1>(), M_data);
299 #else
300  TensorAssemble<false>(
301  Bt_1d.layout, Bt_1d, B_1d.layout, B_1d,
302  qpt_layout.template split_1<1,NIP>(), qpt_data,
303  M_layout.template split_1<DOF,1>(), M_data);
304 #endif
305  }
306 
307  // Multi-component assemble of grad-grad element matrices.
308  // qpt_layout is (NIP x DIM x DIM x NumComp), and
309  // D_layout is (DOF x DOF x NumComp).
310  template <typename qpt_layout_t, typename qpt_data_t,
311  typename D_layout_t, typename D_data_t>
312  MFEM_ALWAYS_INLINE
313  void AssembleGradGrad(const qpt_layout_t &qpt_layout,
314  const qpt_data_t &qpt_data,
315  const D_layout_t &D_layout,
316  D_data_t &D_data) const
317  {
318  // D_{i,j,k} = \sum_{s} G_1d_{s,i} G_{s,j} qpt_data_{s,k}
319  // Using TensorAssemble: <1,NIP,NC> --> <DOF,1,DOF,NC>
320 #if 0
321  TensorAssemble<false>(
322  G_1d.layout, G_1d,
323  qpt_layout.merge_12().merge_23().template split_1<1,NIP>(), qpt_data,
324  D_layout.template split_1<DOF,1>(), D_data);
325 #else
326  TensorAssemble<false>(
327  Gt_1d.layout, Gt_1d, G_1d.layout, G_1d,
328  qpt_layout.merge_12().merge_23().template split_1<1,NIP>(), qpt_data,
329  D_layout.template split_1<DOF,1>(), D_data);
330 #endif
331  }
332 };
333 
334 // ShapeEvaluator with 2D tensor-product structure
335 template <int DOF, int NIP, typename real_t>
336 class TProductShapeEvaluator<2, DOF, NIP, real_t>
337 {
338 protected:
341 
342 public:
343  static const int TDOF = DOF*DOF; // total dofs
344  static const int TNIP = NIP*NIP; // total qpts
345 
347 
348  template <bool Dx, bool Dy,
349  typename dof_layout_t, typename dof_data_t,
350  typename qpt_layout_t, typename qpt_data_t>
351  MFEM_ALWAYS_INLINE
352  void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data,
353  const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
354  {
355  const int NC = dof_layout_t::dim_2;
356  // DOF x DOF x NC --> NIP x DOF x NC --> NIP x NIP x NC
358 
359  // (1) A_{i,j,k} = \sum_s B_1d_{i,s} dof_data_{s,j,k}
360  Mult_2_1<false>(B_1d.layout, Dx ? G_1d : B_1d,
361  dof_layout. template split_1<DOF,DOF>(), dof_data,
362  A.layout, A);
363  // (2) qpt_data_{i,j,k} = \sum_s B_1d_{j,s} A_{i,s,k}
364  Mult_1_2<false>(Bt_1d.layout, Dy ? Gt_1d : Bt_1d,
365  A.layout, A,
366  qpt_layout.template split_1<NIP,NIP>(), qpt_data);
367  }
368 
369  // Multi-component shape evaluation from DOFs to quadrature points.
370  // dof_layout is (TDOF x NumComp) and qpt_layout is (TNIP x NumComp).
371  template <typename dof_layout_t, typename dof_data_t,
372  typename qpt_layout_t, typename qpt_data_t>
373  MFEM_ALWAYS_INLINE
374  void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data,
375  const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
376  {
377  Calc<false,false>(dof_layout, dof_data, qpt_layout, qpt_data);
378  }
379 
380  template <bool Dx, bool Dy, bool Add,
381  typename qpt_layout_t, typename qpt_data_t,
382  typename dof_layout_t, typename dof_data_t>
383  MFEM_ALWAYS_INLINE
384  void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
385  const dof_layout_t &dof_layout, dof_data_t &dof_data) const
386  {
387  const int NC = dof_layout_t::dim_2;
388  // NIP x NIP X NC --> NIP x DOF x NC --> DOF x DOF x NC
390 
391  // (1) A_{i,j,k} = \sum_s B_1d_{s,j} qpt_data_{i,s,k}
392  Mult_1_2<false>(B_1d.layout, Dy ? G_1d : B_1d,
393  qpt_layout.template split_1<NIP,NIP>(), qpt_data,
394  A.layout, A);
395  // (2) dof_data_{i,j,k} = \sum_s B_1d_{s,i} A_{s,j,k}
396  Mult_2_1<Add>(Bt_1d.layout, Dx ? Gt_1d : Bt_1d,
397  A.layout, A,
398  dof_layout.template split_1<DOF,DOF>(), dof_data);
399  }
400 
401  // Multi-component shape evaluation transpose from quadrature points to DOFs.
402  // qpt_layout is (TNIP x NumComp) and dof_layout is (TDOF x NumComp).
403  template <bool Add,
404  typename qpt_layout_t, typename qpt_data_t,
405  typename dof_layout_t, typename dof_data_t>
406  MFEM_ALWAYS_INLINE
407  void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
408  const dof_layout_t &dof_layout, dof_data_t &dof_data) const
409  {
410  CalcT<false,false,Add>(qpt_layout, qpt_data, dof_layout, dof_data);
411  }
412 
413  // Multi-component gradient evaluation from DOFs to quadrature points.
414  // dof_layout is (TDOF x NumComp) and grad_layout is (TNIP x DIM x NumComp).
415  template <typename dof_layout_t, typename dof_data_t,
416  typename grad_layout_t, typename grad_data_t>
417  MFEM_ALWAYS_INLINE
418  void CalcGrad(const dof_layout_t &dof_layout,
419  const dof_data_t &dof_data,
420  const grad_layout_t &grad_layout,
421  grad_data_t &grad_data) const
422  {
423  Calc<true,false>(dof_layout, dof_data,
424  grad_layout.ind2(0), grad_data);
425  Calc<false,true>(dof_layout, dof_data,
426  grad_layout.ind2(1), grad_data);
427  }
428 
429  // Multi-component gradient evaluation transpose from quadrature points to
430  // DOFs. grad_layout is (TNIP x DIM x NumComp), dof_layout is
431  // (TDOF x NumComp).
432  template <bool Add,
433  typename grad_layout_t, typename grad_data_t,
434  typename dof_layout_t, typename dof_data_t>
435  MFEM_ALWAYS_INLINE
436  void CalcGradT(const grad_layout_t &grad_layout,
437  const grad_data_t &grad_data,
438  const dof_layout_t &dof_layout,
439  dof_data_t &dof_data) const
440  {
441  CalcT<true,false, Add>(grad_layout.ind2(0), grad_data,
442  dof_layout, dof_data);
443  CalcT<false,true,true>(grad_layout.ind2(1), grad_data,
444  dof_layout, dof_data);
445  }
446 
447  // Multi-component assemble.
448  // qpt_layout is (TNIP x NumComp), M_layout is (TDOF x TDOF x NumComp)
449  template <typename qpt_layout_t, typename qpt_data_t,
450  typename M_layout_t, typename M_data_t>
451  MFEM_ALWAYS_INLINE
452  void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
453  const M_layout_t &M_layout, M_data_t &M_data) const
454  {
455  const int NC = qpt_layout_t::dim_2;
456 
457  // Using TensorAssemble: <I,NIP,J> --> <DOF,I,DOF,J>
458 
459 #if 0
461  // qpt_data<NIP1,NIP2,NC> --> A<DOF2,NIP1,DOF2,NC>
462  TensorAssemble<false>(
463  B_1d.layout, B_1d,
464  qpt_layout.template split_1<NIP,NIP>(), qpt_data,
465  A.layout, A);
466  // A<DOF2,NIP1,DOF2*NC> --> M<DOF1,DOF2,DOF1,DOF2*NC>
467  TensorAssemble<false>(
468  B_1d.layout, B_1d,
470  M_layout.merge_23().template split_12<DOF,DOF,DOF,DOF*NC>(), M_data);
471 #elif 1
473  // qpt_data<NIP1,NIP2,NC> --> A<DOF2,NIP1,DOF2,NC>
474  TensorAssemble<false>(
475  Bt_1d.layout, Bt_1d, B_1d.layout, B_1d,
476  qpt_layout.template split_1<NIP,NIP>(), qpt_data,
477  A.layout, A);
478  // A<DOF2,NIP1,DOF2*NC> --> M<DOF1,DOF2,DOF1,DOF2*NC>
479  TensorAssemble<false>(
480  Bt_1d.layout, Bt_1d, B_1d.layout, B_1d,
481  A.layout.merge_34(), A,
482  M_layout.merge_23().template split_12<DOF,DOF,DOF,DOF*NC>(), M_data);
483 #else
487  for (int k = 0; k < NC; k++)
488  {
489  // <1,NIP1,NIP2> --> <1,NIP1,NIP2,DOF1>
490  TensorProduct<AssignOp::Set>(
491  qpt_layout.ind2(k).template split_1<NIP,NIP>().
492  template split_1<1,NIP>(), qpt_data,
493  B_1d.layout, B_1d, F3.layout.template split_1<1,NIP>(), F3);
494  // <NIP1,NIP2,DOF1> --> <NIP1,NIP2,DOF1,DOF2>
495  TensorProduct<AssignOp::Set>(
496  F3.layout, F3, B_1d.layout, B_1d, F4.layout, F4);
497  // <NIP1,NIP2,DOF1,DOF2> --> <NIP1,DOF2,DOF1,DOF2>
498  Mult_1_2<false>(B_1d.layout, B_1d,
499  F4.layout.merge_34(), F4,
500  H3.layout, H3);
501  // <NIP1,DOF2,DOF1,DOF2> --> <DOF1,DOF2,DOF1,DOF2>
502  Mult_2_1<false>(Bt_1d.layout, Bt_1d,
503  H3.layout, H3,
504  M_layout.ind3(k).template split_1<DOF,DOF>(),
505  M_data);
506  }
507 #endif
508  }
509 
510  template <int D1, int D2, bool Add,
511  typename qpt_layout_t, typename qpt_data_t,
512  typename D_layout_t, typename D_data_t>
513  MFEM_ALWAYS_INLINE
514  void Assemble(const qpt_layout_t &qpt_layout,
515  const qpt_data_t &qpt_data,
516  const D_layout_t &D_layout,
517  D_data_t &D_data) const
518  {
519  const int NC = qpt_layout_t::dim_2;
521 
522  // Using TensorAssemble: <I,NIP,J> --> <DOF,I,DOF,J>
523 
524  // qpt_data<NIP1,NIP2,NC> --> A<DOF2,NIP1,DOF2,NC>
525  TensorAssemble<false>(
526  Bt_1d.layout, D1 == 0 ? Bt_1d : Gt_1d,
527  B_1d.layout, D2 == 0 ? B_1d : G_1d,
528  qpt_layout.template split_1<NIP,NIP>(), qpt_data,
529  A.layout, A);
530  // A<DOF2,NIP1,DOF2*NC> --> M<DOF1,DOF2,DOF1,DOF2*NC>
531  TensorAssemble<Add>(
532  Bt_1d.layout, D1 == 1 ? Bt_1d : Gt_1d,
533  B_1d.layout, D2 == 1 ? B_1d : G_1d,
535  D_layout.merge_23().template split_12<DOF,DOF,DOF,DOF*NC>(), D_data);
536  }
537 
538  // Multi-component assemble of grad-grad element matrices.
539  // qpt_layout is (TNIP x DIM x DIM x NumComp), and
540  // D_layout is (TDOF x TDOF x NumComp).
541  template <typename qpt_layout_t, typename qpt_data_t,
542  typename D_layout_t, typename D_data_t>
543  MFEM_ALWAYS_INLINE
544  void AssembleGradGrad(const qpt_layout_t &qpt_layout,
545  const qpt_data_t &qpt_data,
546  const D_layout_t &D_layout,
547  D_data_t &D_data) const
548  {
549 #if 1
550  Assemble<0,0,false>(qpt_layout.ind23(0,0), qpt_data, D_layout, D_data);
551  Assemble<1,0,true >(qpt_layout.ind23(1,0), qpt_data, D_layout, D_data);
552  Assemble<0,1,true >(qpt_layout.ind23(0,1), qpt_data, D_layout, D_data);
553  Assemble<1,1,true >(qpt_layout.ind23(1,1), qpt_data, D_layout, D_data);
554 #else
555  const int NC = qpt_layout_t::dim_4;
559 
560  for (int k = 0; k < NC; k++)
561  {
562  for (int d1 = 0; d1 < 2; d1++)
563  {
564  const AssignOp::Type Set = AssignOp::Set;
566  // <1,NIP1,NIP2> --> <1,NIP1,NIP2,DOF1>
567  TensorProduct<Set>(qpt_layout.ind23(d1,0).ind2(k).
568  template split_1<NIP,NIP>().
569  template split_1<1,NIP>(), qpt_data,
570  G_1d.layout, G_1d,
571  F3.layout.template split_1<1,NIP>(), F3);
572  // <NIP1,NIP2,DOF1> --> <NIP1,NIP2,DOF1,DOF2>
573  TensorProduct<Set>(F3.layout, F3,
574  B_1d.layout, B_1d,
575  F4.layout, F4);
576  // <1,NIP1,NIP2> --> <1,NIP1,NIP2,DOF1>
577  TensorProduct<Set>(qpt_layout.ind23(d1,1).ind2(k).
578  template split_1<NIP,NIP>().
579  template split_1<1,NIP>(), qpt_data,
580  B_1d.layout, B_1d,
581  F3.layout.template split_1<1,NIP>(), F3);
582  // <NIP1,NIP2,DOF1> --> <NIP1,NIP2,DOF1,DOF2>
583  TensorProduct<Add>(F3.layout, F3,
584  G_1d.layout, G_1d,
585  F4.layout, F4);
586 
587  Mult_1_2<false>(B_1d.layout, d1 == 0 ? B_1d : G_1d,
588  F4.layout.merge_34(), F4,
589  H3.layout, H3);
590  if (d1 == 0)
591  {
592  Mult_2_1<false>(Bt_1d.layout, Gt_1d,
593  H3.layout, H3,
594  D_layout.ind3(k).template split_1<DOF,DOF>(),
595  D_data);
596  }
597  else
598  {
599  Mult_2_1<true>(Bt_1d.layout, Bt_1d,
600  H3.layout, H3,
601  D_layout.ind3(k).template split_1<DOF,DOF>(),
602  D_data);
603  }
604  }
605  }
606 #endif
607  }
608 };
609 
610 // ShapeEvaluator with 3D tensor-product structure
611 template <int DOF, int NIP, typename real_t>
613 {
614 protected:
617 
618 public:
619  static const int TDOF = DOF*DOF*DOF; // total dofs
620  static const int TNIP = NIP*NIP*NIP; // total qpts
621 
623 
624  template <bool Dx, bool Dy, bool Dz,
625  typename dof_layout_t, typename dof_data_t,
626  typename qpt_layout_t, typename qpt_data_t>
627  MFEM_ALWAYS_INLINE
628  void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data,
629  const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
630  {
631  const int NC = dof_layout_t::dim_2;
634 
635  // QDD_{i,jj,k} = \sum_s B_1d_{i,s} dof_data_{s,jj,k}
636  Mult_2_1<false>(B_1d.layout, Dx ? G_1d : B_1d,
637  dof_layout.template split_1<DOF,DOF*DOF>(), dof_data,
639  // QQD_{i,j,kk} = \sum_s B_1d_{j,s} QDD_{i,s,kk}
640  Mult_1_2<false>(Bt_1d.layout, Dy ? Gt_1d : Bt_1d,
643  // qpt_data_{ii,j,k} = \sum_s B_1d_{j,s} QQD_{ii,s,k}
644  Mult_1_2<false>(Bt_1d.layout, Dz ? Gt_1d : Bt_1d,
646  qpt_layout.template split_1<NIP*NIP,NIP>(), qpt_data);
647  }
648 
649  // Multi-component shape evaluation from DOFs to quadrature points.
650  // dof_layout is (TDOF x NumComp) and qpt_layout is (TNIP x NumComp).
651  template <typename dof_layout_t, typename dof_data_t,
652  typename qpt_layout_t, typename qpt_data_t>
653  MFEM_ALWAYS_INLINE
654  void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data,
655  const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
656  {
657  Calc<false,false,false>(dof_layout, dof_data, qpt_layout, qpt_data);
658  }
659 
660  template <bool Dx, bool Dy, bool Dz, bool Add,
661  typename qpt_layout_t, typename qpt_data_t,
662  typename dof_layout_t, typename dof_data_t>
663  MFEM_ALWAYS_INLINE
664  void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
665  const dof_layout_t &dof_layout, dof_data_t &dof_data) const
666  {
667  const int NC = dof_layout_t::dim_2;
670 
671  // QQD_{ii,j,k} = \sum_s B_1d_{s,j} qpt_data_{ii,s,k}
672  Mult_1_2<false>(B_1d.layout, Dz ? G_1d : B_1d,
673  qpt_layout.template split_1<NIP*NIP,NIP>(), qpt_data,
675  // QDD_{i,j,kk} = \sum_s B_1d_{s,j} QQD_{i,s,kk}
676  Mult_1_2<false>(B_1d.layout, Dy ? G_1d : B_1d,
679  // dof_data_{i,jj,k} = \sum_s B_1d_{s,i} QDD_{s,jj,k}
680  Mult_2_1<Add>(Bt_1d.layout, Dx ? Gt_1d : Bt_1d,
682  dof_layout.template split_1<DOF,DOF*DOF>(), dof_data);
683  }
684 
685  // Multi-component shape evaluation transpose from quadrature points to DOFs.
686  // qpt_layout is (TNIP x NumComp) and dof_layout is (TDOF x NumComp).
687  template <bool Add,
688  typename qpt_layout_t, typename qpt_data_t,
689  typename dof_layout_t, typename dof_data_t>
690  MFEM_ALWAYS_INLINE
691  void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
692  const dof_layout_t &dof_layout, dof_data_t &dof_data) const
693  {
694  CalcT<false,false,false,Add>(qpt_layout, qpt_data, dof_layout, dof_data);
695  }
696 
697  // Multi-component gradient evaluation from DOFs to quadrature points.
698  // dof_layout is (TDOF x NumComp) and grad_layout is (TNIP x DIM x NumComp).
699  template <typename dof_layout_t, typename dof_data_t,
700  typename grad_layout_t, typename grad_data_t>
701  MFEM_ALWAYS_INLINE
702  void CalcGrad(const dof_layout_t &dof_layout,
703  const dof_data_t &dof_data,
704  const grad_layout_t &grad_layout,
705  grad_data_t &grad_data) const
706  {
707  Calc<true,false,false>(dof_layout, dof_data,
708  grad_layout.ind2(0), grad_data);
709  Calc<false,true,false>(dof_layout, dof_data,
710  grad_layout.ind2(1), grad_data);
711  Calc<false,false,true>(dof_layout, dof_data,
712  grad_layout.ind2(2), grad_data);
713  // optimization: the x-transition (dof->nip) is done twice -- once for the
714  // y-derivatives and second time for the z-derivatives.
715  }
716 
717  // Multi-component gradient evaluation transpose from quadrature points to
718  // DOFs. grad_layout is (TNIP x DIM x NumComp), dof_layout is
719  // (TDOF x NumComp).
720  template <bool Add,
721  typename grad_layout_t, typename grad_data_t,
722  typename dof_layout_t, typename dof_data_t>
723  MFEM_ALWAYS_INLINE
724  void CalcGradT(const grad_layout_t &grad_layout,
725  const grad_data_t &grad_data,
726  const dof_layout_t &dof_layout,
727  dof_data_t &dof_data) const
728  {
729  CalcT<true,false,false, Add>(grad_layout.ind2(0), grad_data,
730  dof_layout, dof_data);
731  CalcT<false,true,false,true>(grad_layout.ind2(1), grad_data,
732  dof_layout, dof_data);
733  CalcT<false,false,true,true>(grad_layout.ind2(2), grad_data,
734  dof_layout, dof_data);
735  }
736 
737  // Multi-component assemble.
738  // qpt_layout is (TNIP x NumComp), M_layout is (TDOF x TDOF x NumComp)
739  template <typename qpt_layout_t, typename qpt_data_t,
740  typename M_layout_t, typename M_data_t>
741  MFEM_ALWAYS_INLINE
742  void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data,
743  const M_layout_t &M_layout, M_data_t &M_data) const
744  {
745  const int NC = qpt_layout_t::dim_2;
748 
749  // Using TensorAssemble: <I,NIP,J> --> <DOF,I,DOF,J>
750 
751 #if 0
752  // qpt_data<NIP1*NIP2,NIP3,NC> --> A1<DOF3,NIP1*NIP2,DOF3,NC>
753  TensorAssemble<false>(
754  B_1d.layout, B_1d,
755  qpt_layout.template split_1<NIP*NIP,NIP>(), qpt_data,
756  A1.layout, A1);
757  // A1<DOF3*NIP1,NIP2,DOF3*NC> --> A2<DOF2,DOF3*NIP1,DOF2,DOF3*NC>
758  TensorAssemble<false>(
759  B_1d.layout, B_1d,
761  A2.layout, A2);
762  // A2<DOF2*DOF3,NIP1,DOF2*DOF3*NC> --> M<DOF1,DOF2*DOF3,DOF1,DOF2*DOF3*NC>
763  TensorAssemble<false>(
764  B_1d.layout, B_1d,
766  M_layout.merge_23().template split_12<DOF,DOF*DOF,DOF,DOF*DOF*NC>(),
767  M_data);
768 #else
769  // qpt_data<NIP1*NIP2,NIP3,NC> --> A1<DOF3,NIP1*NIP2,DOF3,NC>
770  TensorAssemble<false>(
771  Bt_1d.layout, Bt_1d, B_1d.layout, B_1d,
772  qpt_layout.template split_1<NIP*NIP,NIP>(), qpt_data,
773  A1.layout, A1);
774  // A1<DOF3*NIP1,NIP2,DOF3*NC> --> A2<DOF2,DOF3*NIP1,DOF2,DOF3*NC>
775  TensorAssemble<false>(
776  Bt_1d.layout, Bt_1d, B_1d.layout, B_1d,
777  TTensor3<DOF*NIP,NIP,DOF*NC>::layout, A1,
778  A2.layout, A2);
779  // A2<DOF2*DOF3,NIP1,DOF2*DOF3*NC> --> M<DOF1,DOF2*DOF3,DOF1,DOF2*DOF3*NC>
780  TensorAssemble<false>(
781  Bt_1d.layout, Bt_1d, B_1d.layout, B_1d,
782  TTensor3<DOF*DOF,NIP,DOF*DOF*NC>::layout, A2,
783  M_layout.merge_23().template split_12<DOF,DOF*DOF,DOF,DOF*DOF*NC>(),
784  M_data);
785 #endif
786  }
787 
788  template <int D1, int D2, bool Add,
789  typename qpt_layout_t, typename qpt_data_t,
790  typename D_layout_t, typename D_data_t>
791  MFEM_ALWAYS_INLINE
792  void Assemble(const qpt_layout_t &qpt_layout,
793  const qpt_data_t &qpt_data,
794  const D_layout_t &D_layout,
795  D_data_t &D_data) const
796  {
797  const int NC = qpt_layout_t::dim_2;
800 
801  // Using TensorAssemble: <I,NIP,J> --> <DOF,I,DOF,J>
802 
803  // qpt_data<NIP1*NIP2,NIP3,NC> --> A1<DOF3,NIP1*NIP2,DOF3,NC>
804  TensorAssemble<false>(
805  Bt_1d.layout, D1 != 2 ? Bt_1d : Gt_1d,
806  B_1d.layout, D2 != 2 ? B_1d : G_1d,
807  qpt_layout.template split_1<NIP*NIP,NIP>(), qpt_data,
808  A1.layout, A1);
809  // A1<DOF3*NIP1,NIP2,DOF3*NC> --> A2<DOF2,DOF3*NIP1,DOF2,DOF3*NC>
810  TensorAssemble<false>(
811  Bt_1d.layout, D1 != 1 ? Bt_1d : Gt_1d,
812  B_1d.layout, D2 != 1 ? B_1d : G_1d,
814  A2.layout, A2);
815  // A2<DOF2*DOF3,NIP1,DOF2*DOF3*NC> --> M<DOF1,DOF2*DOF3,DOF1,DOF2*DOF3*NC>
816  TensorAssemble<Add>(
817  Bt_1d.layout, D1 != 0 ? Bt_1d : Gt_1d,
818  B_1d.layout, D2 != 0 ? B_1d : G_1d,
820  D_layout.merge_23().template split_12<DOF,DOF*DOF,DOF,DOF*DOF*NC>(),
821  D_data);
822  }
823 
824 #if 0
825  template <typename qpt_layout_t, typename qpt_data_t,
826  typename D_layout_t, typename D_data_t>
827  MFEM_ALWAYS_INLINE
828  void Assemble(int D1, int D2,
829  const qpt_layout_t &qpt_layout,
830  const qpt_data_t &qpt_data,
831  const D_layout_t &D_layout,
832  D_data_t &D_data) const
833  {
834  const int NC = qpt_layout_t::dim_2;
837 
838  // Using TensorAssemble: <I,NIP,J> --> <DOF,I,DOF,J>
839 
840  // qpt_data<NIP1*NIP2,NIP3,NC> --> A1<DOF3,NIP1*NIP2,DOF3,NC>
841  TensorAssemble<false>(
842  Bt_1d.layout, D1 != 2 ? Bt_1d : Gt_1d,
843  B_1d.layout, D2 != 2 ? B_1d : G_1d,
844  qpt_layout.template split_1<NIP*NIP,NIP>(), qpt_data,
845  A1.layout, A1);
846  // A1<DOF3*NIP1,NIP2,DOF3*NC> --> A2<DOF2,DOF3*NIP1,DOF2,DOF3*NC>
847  TensorAssemble<false>(
848  Bt_1d.layout, D1 != 1 ? Bt_1d : Gt_1d,
849  B_1d.layout, D2 != 1 ? B_1d : G_1d,
851  A2.layout, A2);
852  // A2<DOF2*DOF3,NIP1,DOF2*DOF3*NC> --> M<DOF1,DOF2*DOF3,DOF1,DOF2*DOF3*NC>
853  TensorAssemble<true>(
854  Bt_1d.layout, D1 != 0 ? Bt_1d : Gt_1d,
855  B_1d.layout, D2 != 0 ? B_1d : G_1d,
857  D_layout.merge_23().template split_12<DOF,DOF*DOF,DOF,DOF*DOF*NC>(),
858  D_data);
859  }
860 #endif
861 
862  // Multi-component assemble of grad-grad element matrices.
863  // qpt_layout is (TNIP x DIM x DIM x NumComp), and
864  // D_layout is (TDOF x TDOF x NumComp).
865  template <typename qpt_layout_t, typename qpt_data_t,
866  typename D_layout_t, typename D_data_t>
867  MFEM_ALWAYS_INLINE
868  void AssembleGradGrad(const qpt_layout_t &qpt_layout,
869  const qpt_data_t &qpt_data,
870  const D_layout_t &D_layout,
871  D_data_t &D_data) const
872  {
873 #if 1
874  // NOTE: This function compiles into a large chunk of machine code
875  Assemble<0,0,false>(qpt_layout.ind23(0,0), qpt_data, D_layout, D_data);
876  Assemble<1,0,true >(qpt_layout.ind23(1,0), qpt_data, D_layout, D_data);
877  Assemble<2,0,true >(qpt_layout.ind23(2,0), qpt_data, D_layout, D_data);
878  Assemble<0,1,true >(qpt_layout.ind23(0,1), qpt_data, D_layout, D_data);
879  Assemble<1,1,true >(qpt_layout.ind23(1,1), qpt_data, D_layout, D_data);
880  Assemble<2,1,true >(qpt_layout.ind23(2,1), qpt_data, D_layout, D_data);
881  Assemble<0,2,true >(qpt_layout.ind23(0,2), qpt_data, D_layout, D_data);
882  Assemble<1,2,true >(qpt_layout.ind23(1,2), qpt_data, D_layout, D_data);
883  Assemble<2,2,true >(qpt_layout.ind23(2,2), qpt_data, D_layout, D_data);
884 #else
885  TAssign<AssignOp::Set>(D_layout, D_data, 0.0);
886  for (int d2 = 0; d2 < 3; d2++)
887  {
888  for (int d1 = 0; d1 < 3; d1++)
889  {
890  Assemble(d1, d2, qpt_layout.ind23(d1,d2), qpt_data,
891  D_layout, D_data);
892  }
893  }
894 #endif
895  }
896 };
897 
898 // ShapeEvaluator with tensor-product structure in any dimension
899 template <class FE, class IR, typename real_t>
900 class ShapeEvaluator_base<FE, IR, true, real_t>
901  : public TProductShapeEvaluator<FE::dim, FE::dofs_1d, IR::qpts_1d, real_t>
902 {
903 protected:
904  typedef TProductShapeEvaluator<FE::dim,FE::dofs_1d,
905  IR::qpts_1d,real_t> base_class;
906  using base_class::B_1d;
907  using base_class::Bt_1d;
908  using base_class::G_1d;
909  using base_class::Gt_1d;
910 
911 public:
912  ShapeEvaluator_base(const FE &fe)
913  {
914  fe.Calc1DShapes(IR::Get1DIntRule(), B_1d.data, G_1d.data);
915  TAssign<AssignOp::Set>(Bt_1d.layout, Bt_1d,
916  B_1d.layout.transpose_12(), B_1d);
917  TAssign<AssignOp::Set>(Gt_1d.layout, Gt_1d,
918  G_1d.layout.transpose_12(), G_1d);
919  }
920 
921  // default copy constructor
922 };
923 
924 // General ShapeEvaluator for any scalar FE type (L2 or H1)
925 template <class FE, class IR, typename real_t>
927  : public ShapeEvaluator_base<FE,IR,FE::tensor_prod && IR::tensor_prod,real_t>
928 {
929 public:
930  typedef real_t real_type;
931  static const int dim = FE::dim;
932  static const int qpts = IR::qpts;
933  static const bool tensor_prod = FE::tensor_prod && IR::tensor_prod;
934  typedef FE FE_type;
935  typedef IR IR_type;
937 
938  using base_class::Calc;
939  using base_class::CalcT;
940  using base_class::CalcGrad;
941  using base_class::CalcGradT;
942 
943  ShapeEvaluator(const FE &fe) : base_class(fe) { }
944 
945  // default copy constructor
946 };
947 
948 
949 // Field evaluators -- values of a given global FE grid function
950 
951 template <typename FESpace_t, typename VecLayout_t, typename IR,
952  typename complex_t, typename real_t>
954 {
955 protected:
956  typedef typename FESpace_t::FE_type FE_type;
958 
959  FESpace_t fespace;
961  VecLayout_t vec_layout;
962 
963  // With this constructor, fespace is a shallow copy.
964  inline MFEM_ALWAYS_INLINE
965  FieldEvaluator_base(const FESpace_t &tfes, const ShapeEval_type &shape_eval,
966  const VecLayout_t &vec_layout)
967  : fespace(tfes),
968  shapeEval(shape_eval),
969  vec_layout(vec_layout)
970  { }
971 
972  // This constructor creates new fespace, not a shallow copy.
973  inline MFEM_ALWAYS_INLINE
975  : fespace(fe, fes), shapeEval(fe), vec_layout(fes)
976  { }
977 };
978 
979 // complex_t - dof/qpt data type, real_t - ShapeEvaluator (FE basis) data type
980 template <typename FESpace_t, typename VecLayout_t, typename IR,
981  typename complex_t = double, typename real_t = double>
983  : public FieldEvaluator_base<FESpace_t,VecLayout_t,IR,complex_t,real_t>
984 {
985 public:
986  typedef complex_t complex_type;
987  typedef FESpace_t FESpace_type;
988  typedef typename FESpace_t::FE_type FE_type;
990  typedef VecLayout_t VecLayout_type;
991 
992  // this type
994 
995  static const int dofs = FE_type::dofs;
996  static const int dim = FE_type::dim;
997  static const int qpts = IR::qpts;
998  static const int vdim = VecLayout_t::vec_dim;
999 
1000 protected:
1001 
1004 
1005  using base_class::fespace;
1006  using base_class::shapeEval;
1007  using base_class::vec_layout;
1008  const complex_t *data_in;
1009  complex_t *data_out;
1010 
1011 public:
1012  // With this constructor, fespace is a shallow copy of tfes.
1013  inline MFEM_ALWAYS_INLINE
1014  FieldEvaluator(const FESpace_t &tfes, const ShapeEval_type &shape_eval,
1015  const VecLayout_type &vec_layout,
1016  const complex_t *global_data_in, complex_t *global_data_out)
1017  : base_class(tfes, shape_eval, vec_layout),
1018  data_in(global_data_in),
1019  data_out(global_data_out)
1020  { }
1021 
1022  // With this constructor, fespace is a shallow copy of f.fespace.
1023  inline MFEM_ALWAYS_INLINE
1025  const complex_t *global_data_in, complex_t *global_data_out)
1027  data_in(global_data_in),
1028  data_out(global_data_out)
1029  { }
1030 
1031  // This constructor creates a new fespace, not a shallow copy.
1032  inline MFEM_ALWAYS_INLINE
1034  const complex_t *global_data_in, complex_t *global_data_out)
1035  : base_class(FE_type(*fes.FEColl()), fes),
1036  data_in(global_data_in),
1037  data_out(global_data_out)
1038  { }
1039 
1040  // Default copy constructor
1041 
1042  inline MFEM_ALWAYS_INLINE FESpace_type &FESpace() { return fespace; }
1043  inline MFEM_ALWAYS_INLINE ShapeEval_type &ShapeEval() { return shapeEval; }
1044  inline MFEM_ALWAYS_INLINE VecLayout_type &VecLayout() { return vec_layout; }
1045 
1046  inline MFEM_ALWAYS_INLINE
1047  void SetElement(int el)
1048  {
1049  fespace.SetElement(el);
1050  }
1051 
1052  // val_layout_t is (qpts x vdim x NE)
1053  template <typename val_layout_t, typename val_data_t>
1054  inline MFEM_ALWAYS_INLINE
1055  void GetValues(int el, const val_layout_t &l, val_data_t &vals)
1056  {
1057  const int ne = val_layout_t::dim_3;
1059  SetElement(el);
1060  fespace.VectorExtract(vec_layout, data_in, val_dofs.layout, val_dofs);
1061  shapeEval.Calc(val_dofs.layout.merge_23(), val_dofs, l.merge_23(), vals);
1062  }
1063 
1064  // grad_layout_t is (qpts x dim x vdim x NE)
1065  template <typename grad_layout_t, typename grad_data_t>
1066  inline MFEM_ALWAYS_INLINE
1067  void GetGradients(int el, const grad_layout_t &l, grad_data_t &grad)
1068  {
1069  const int ne = grad_layout_t::dim_4;
1071  SetElement(el);
1072  fespace.VectorExtract(vec_layout, data_in, val_dofs.layout, val_dofs);
1073  shapeEval.CalcGrad(val_dofs.layout.merge_23(), val_dofs,
1074  l.merge_34(), grad);
1075  }
1076 
1077  // TODO: add method GetValuesAndGradients()
1078 
1079  template <typename DataType>
1080  inline MFEM_ALWAYS_INLINE
1081  void Eval(DataType &F)
1082  {
1083  // T.SetElement() must be called outside
1085  }
1086 
1087  template <typename DataType>
1088  inline MFEM_ALWAYS_INLINE
1089  void Eval(int el, DataType &F)
1090  {
1091  SetElement(el);
1092  Eval(F);
1093  }
1094 
1095  template <bool Add, typename DataType>
1096  inline MFEM_ALWAYS_INLINE
1097  void Assemble(DataType &F)
1098  {
1099  // T.SetElement() must be called outside
1101  template Assemble<Add>(vec_layout, *this, F);
1102  }
1103 
1104  template <bool Add, typename DataType>
1105  inline MFEM_ALWAYS_INLINE
1106  void Assemble(int el, DataType &F)
1107  {
1108  SetElement(el);
1109  Assemble<Add>(F);
1110  }
1111 
1112 #ifdef MFEM_TEMPLATE_ENABLE_SERIALIZE
1113  template <typename DataType>
1114  inline MFEM_ALWAYS_INLINE
1115  void EvalSerialized(const complex_t *loc_dofs, DataType &F)
1116  {
1118  }
1119 
1120  template <bool Add, typename DataType>
1121  inline MFEM_ALWAYS_INLINE
1122  void AssembleSerialized(const DataType &F, complex_t *loc_dofs)
1123  {
1125  template AssembleSerialized<Add>(*this, F, loc_dofs);
1126  }
1127 #endif
1128 
1129  // Enumeration for the data type used by the Eval() and Assemble() methods.
1130  // The types can obtained by summing constants from this enumeration and used
1131  // as a template parameter in struct Data.
1133  {
1134  None = 0,
1135  Values = 1,
1137  };
1138 
1139  // Auxiliary templated struct AData, used by the Eval() and Assemble()
1140  // methods. The template parameter IOData is "bitwise or" of constants from
1141  // the enum InOutData. The parameter NE is the number of elements to be
1142  // processed in the Eval() and Assemble() methods.
1143  template<int IOData, int NE> struct AData;
1144 
1145  template <int NE> struct AData<0,NE> // 0 = None
1146  {
1147  // Do we need this?
1148  };
1149 
1150  template <int NE> struct AData<1,NE> // 1 = Values
1151  {
1152 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1155 #else
1157 #endif
1159  };
1160 
1161  template <int NE> struct AData<2,NE> // 2 = Gradients
1162  {
1163 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1166 #else
1168 #endif
1170  };
1171 
1172  template <int NE> struct AData<3,NE> // 3 = Values+Gradients
1173  {
1174 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1177 #else
1179 #endif
1182  };
1183 
1184  // This struct is similar to struct AData, adding separate static data
1185  // members for the input (InData) and output (OutData) data types.
1186  template <int IData, int OData, int NE>
1187  struct BData : public AData<IData|OData,NE>
1188  {
1190  static const int ne = NE;
1191  static const int InData = IData;
1192  static const int OutData = OData;
1193  };
1194 
1195  // This struct implements the input (Eval, EvalSerialized) and output
1196  // (Assemble, AssembleSerialized) operations for the given Ops.
1197  // Ops is "bitwise or" of constants from the enum InOutData.
1198  template <int Ops, bool dummy> struct Action;
1199 
1200  template <bool dummy> struct Action<0,dummy> // 0 = None
1201  {
1202  // Do we need this?
1203  };
1204 
1205  template <bool dummy> struct Action<1,dummy> // 1 = Values
1206  {
1207  template <typename vec_layout_t, typename AData_t>
1208  static inline MFEM_ALWAYS_INLINE
1209  void Eval(const vec_layout_t &l, T_type &T, AData_t &D)
1210  {
1211 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1212  typename AData_t::val_dofs_t &val_dofs = D.val_dofs;
1213 #else
1214  typename AData_t::val_dofs_t val_dofs;
1215 #endif
1216  T.fespace.VectorExtract(l, T.data_in, val_dofs.layout, val_dofs);
1217  T.shapeEval.Calc(val_dofs.layout.merge_23(), val_dofs,
1218  D.val_qpts.layout.merge_23(), D.val_qpts);
1219  }
1220 
1221  template <bool Add, typename vec_layout_t, typename AData_t>
1222  static inline MFEM_ALWAYS_INLINE
1223  void Assemble(const vec_layout_t &l, T_type &T, AData_t &D)
1224  {
1226 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1227  typename AData_t::val_dofs_t &val_dofs = D.val_dofs;
1228 #else
1229  typename AData_t::val_dofs_t val_dofs;
1230 #endif
1231  T.shapeEval.template CalcT<false>(
1232  D.val_qpts.layout.merge_23(), D.val_qpts,
1233  val_dofs.layout.merge_23(), val_dofs);
1234  T.fespace.template VectorAssemble<Op>(
1235  val_dofs.layout, val_dofs, l, T.data_out);
1236  }
1237 
1238 #ifdef MFEM_TEMPLATE_ENABLE_SERIALIZE
1239  template <typename AData_t>
1240  static inline MFEM_ALWAYS_INLINE
1241  void EvalSerialized(T_type &T, const complex_t *loc_dofs, AData_t &D)
1242  {
1243  T.shapeEval.Calc(AData_t::val_dofs_t::layout.merge_23(), loc_dofs,
1244  D.val_qpts.layout.merge_23(), D.val_qpts);
1245  }
1246 
1247  template <bool Add, typename AData_t>
1248  static inline MFEM_ALWAYS_INLINE
1249  void AssembleSerialized(T_type &T, const AData_t &D, complex_t *loc_dofs)
1250  {
1251  T.shapeEval.template CalcT<Add>(
1252  D.val_qpts.layout.merge_23(), D.val_qpts,
1253  AData_t::val_dofs_t::layout.merge_23(), loc_dofs);
1254  }
1255 #endif
1256  };
1257 
1258  template <bool dummy> struct Action<2,dummy> // 2 = Gradients
1259  {
1260  template <typename vec_layout_t, typename AData_t>
1261  static inline MFEM_ALWAYS_INLINE
1262  void Eval(const vec_layout_t &l, T_type &T, AData_t &D)
1263  {
1264 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1265  typename AData_t::val_dofs_t &val_dofs = D.val_dofs;
1266 #else
1267  typename AData_t::val_dofs_t val_dofs;
1268 #endif
1269  T.fespace.VectorExtract(l, T.data_in, val_dofs.layout, val_dofs);
1270  T.shapeEval.CalcGrad(val_dofs.layout.merge_23(), val_dofs,
1271  D.grad_qpts.layout.merge_34(), D.grad_qpts);
1272  }
1273 
1274  template <bool Add, typename vec_layout_t, typename AData_t>
1275  static inline MFEM_ALWAYS_INLINE
1276  void Assemble(const vec_layout_t &l, T_type &T, AData_t &D)
1277  {
1279 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1280  typename AData_t::val_dofs_t &val_dofs = D.val_dofs;
1281 #else
1282  typename AData_t::val_dofs_t val_dofs;
1283 #endif
1284  T.shapeEval.template CalcGradT<false>(
1285  D.grad_qpts.layout.merge_34(), D.grad_qpts,
1286  val_dofs.layout.merge_23(), val_dofs);
1287  T.fespace.template VectorAssemble<Op>(
1288  val_dofs.layout, val_dofs, l, T.data_out);
1289  }
1290 
1291 #ifdef MFEM_TEMPLATE_ENABLE_SERIALIZE
1292  template <typename AData_t>
1293  static inline MFEM_ALWAYS_INLINE
1294  void EvalSerialized(T_type &T, const complex_t *loc_dofs, AData_t &D)
1295  {
1296  T.shapeEval.CalcGrad(AData_t::val_dofs_t::layout.merge_23(), loc_dofs,
1297  D.grad_qpts.layout.merge_34(), D.grad_qpts);
1298  }
1299 
1300  template <bool Add, typename AData_t>
1301  static inline MFEM_ALWAYS_INLINE
1302  void AssembleSerialized(T_type &T, const AData_t &D, complex_t *loc_dofs)
1303  {
1304  T.shapeEval.template CalcGradT<Add>(
1305  D.grad_qpts.layout.merge_34(), D.grad_qpts,
1306  AData_t::val_dofs_t::layout.merge_23(), loc_dofs);
1307  }
1308 #endif
1309  };
1310 
1311  template <bool dummy> struct Action<3,dummy> // 3 = Values+Gradients
1312  {
1313  template <typename vec_layout_t, typename AData_t>
1314  static inline MFEM_ALWAYS_INLINE
1315  void Eval(const vec_layout_t &l, T_type &T, AData_t &D)
1316  {
1317 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1318  typename AData_t::val_dofs_t &val_dofs = D.val_dofs;
1319 #else
1320  typename AData_t::val_dofs_t val_dofs;
1321 #endif
1322  T.fespace.VectorExtract(l, T.data_in, val_dofs.layout, val_dofs);
1323  T.shapeEval.Calc(val_dofs.layout.merge_23(), val_dofs,
1324  D.val_qpts.layout.merge_23(), D.val_qpts);
1325  T.shapeEval.CalcGrad(val_dofs.layout.merge_23(), val_dofs,
1326  D.grad_qpts.layout.merge_34(), D.grad_qpts);
1327  }
1328 
1329  template <bool Add, typename vec_layout_t, typename AData_t>
1330  static inline MFEM_ALWAYS_INLINE
1331  void Assemble(const vec_layout_t &l, T_type &T, AData_t &D)
1332  {
1334 #ifdef MFEM_TEMPLATE_FIELD_EVAL_DATA_HAS_DOFS
1335  typename AData_t::val_dofs_t &val_dofs = D.val_dofs;
1336 #else
1337  typename AData_t::val_dofs_t val_dofs;
1338 #endif
1339  T.shapeEval.template CalcT<false>(
1340  D.val_qpts.layout.merge_23(), D.val_qpts,
1341  val_dofs.layout.merge_23(), val_dofs);
1342  T.shapeEval.template CalcGradT<true>(
1343  D.grad_qpts.layout.merge_34(), D.grad_qpts,
1344  val_dofs.layout.merge_23(), val_dofs);
1345  T.fespace.template VectorAssemble<Op>(
1346  val_dofs.layout, val_dofs, l, T.data_out);
1347  }
1348 
1349 #ifdef MFEM_TEMPLATE_ENABLE_SERIALIZE
1350  template <typename AData_t>
1351  static inline MFEM_ALWAYS_INLINE
1352  void EvalSerialized(T_type &T, const complex_t *loc_dofs, AData_t &D)
1353  {
1354  T.shapeEval.Calc(AData_t::val_dofs_t::layout.merge_23(), loc_dofs,
1355  D.val_qpts.layout.merge_23(), D.val_qpts);
1356  T.shapeEval.CalcGrad(AData_t::val_dofs_t::layout.merge_23(), loc_dofs,
1357  D.grad_qpts.layout.merge_34(), D.grad_qpts);
1358  }
1359 
1360  template <bool Add, typename AData_t>
1361  static inline MFEM_ALWAYS_INLINE
1362  void AssembleSerialized(T_type &T, const AData_t &D, complex_t *loc_dofs)
1363  {
1364  T.shapeEval.template CalcT<Add>(
1365  D.val_qpts.layout.merge_23(), D.val_qpts,
1366  AData_t::val_dofs_t::layout.merge_23(), loc_dofs);
1367  T.shapeEval.template CalcGradT<true>(
1368  D.grad_qpts.layout.merge_34(), D.grad_qpts,
1369  AData_t::val_dofs_t::layout.merge_23(), loc_dofs);
1370  }
1371 #endif
1372  };
1373 
1374  // This struct implements element matrix computation for some combinations
1375  // of input (InOps) and output (OutOps) operations.
1376  template <int InOps, int OutOps, int NE> struct TElementMatrix;
1377 
1378  template <int NE> struct TElementMatrix<1,1,NE> // 1,1 = Values,Values
1379  {
1380  // qpt_layout_t is (nip), M_layout_t is (dof x dof)
1381  // NE = 1 is assumed
1382  template <typename qpt_layout_t, typename qpt_data_t,
1383  typename M_layout_t, typename M_data_t>
1384  static inline MFEM_ALWAYS_INLINE
1385  void Compute(const qpt_layout_t &a, const qpt_data_t &A,
1386  const M_layout_t &m, M_data_t &M, ShapeEval_type &ev)
1387  {
1388  ev.Assemble(a.template split_1<qpts,1>(), A,
1389  m.template split_2<dofs,1>(), M);
1390  }
1391  };
1392 
1393  template <int NE> struct TElementMatrix<2,2,NE> // 2,2 = Gradients,Gradients
1394  {
1395  // qpt_layout_t is (nip x dim x dim), M_layout_t is (dof x dof)
1396  // NE = 1 is assumed
1397  template <typename qpt_layout_t, typename qpt_data_t,
1398  typename M_layout_t, typename M_data_t>
1399  static inline MFEM_ALWAYS_INLINE
1400  void Compute(const qpt_layout_t &a, const qpt_data_t &A,
1401  const M_layout_t &m, M_data_t &M, ShapeEval_type &ev)
1402  {
1403  ev.AssembleGradGrad(a.template split_3<dim,1>(), A,
1404  m.template split_2<dofs,1>(), M);
1405  }
1406  };
1407 
1408  template <typename kernel_t, int NE> struct Spec
1409  {
1410  static const int InData =
1411  Values*kernel_t::in_values + Gradients*kernel_t::in_gradients;
1412  static const int OutData =
1413  Values*kernel_t::out_values + Gradients*kernel_t::out_gradients;
1414 
1417  };
1418 };
1419 
1420 } // namespace mfem
1421 
1422 #endif // MFEM_TEMPLATE_EVALUATOR
TMatrix< NIP, DOF, real_t, true > G_1d
Definition: tevaluator.hpp:217
static MFEM_ALWAYS_INLINE void Compute(const qpt_layout_t &a, const qpt_data_t &A, const M_layout_t &m, M_data_t &M, ShapeEval_type &ev)
static const bool tensor_prod
Definition: tevaluator.hpp:933
MFEM_ALWAYS_INLINE VecLayout_type & VecLayout()
static MFEM_ALWAYS_INLINE void Compute(const qpt_layout_t &a, const qpt_data_t &A, const M_layout_t &m, M_data_t &M, ShapeEval_type &ev)
ShapeEvaluator< FE_type, IR, real_t > ShapeEval_type
Definition: tevaluator.hpp:957
TMatrix< DOF, NIP, real_t, true > Bt
Definition: tevaluator.hpp:42
VecLayout_t VecLayout_type
Definition: tevaluator.hpp:990
MFEM_ALWAYS_INLINE void CalcGradT(const grad_layout_t &grad_layout, const grad_data_t &grad_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:133
static MFEM_ALWAYS_INLINE void Eval(const vec_layout_t &l, T_type &T, AData_t &D)
MFEM_ALWAYS_INLINE void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:664
TMatrix< DOF, NIP, real_t, true > Gt_1d
Definition: tevaluator.hpp:340
MFEM_ALWAYS_INLINE void CalcGradT(const grad_layout_t &grad_layout, const grad_data_t &grad_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:272
static MFEM_ALWAYS_INLINE void EvalSerialized(T_type &T, const complex_t *loc_dofs, AData_t &D)
MFEM_ALWAYS_INLINE void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const M_layout_t &M_layout, M_data_t &M_data) const
Definition: tevaluator.hpp:452
TTensor3< dofs, vdim, NE, complex_t > val_dofs_t
TProductShapeEvaluator< FE::dim, FE::dofs_1d, IR::qpts_1d, real_t > base_class
Definition: tevaluator.hpp:905
TTensor4< qpts, dim, vdim, NE, complex_t > grad_qpts
static const layout_type layout
Definition: ttensor.hpp:316
MFEM_ALWAYS_INLINE void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
Definition: tevaluator.hpp:654
MFEM_ALWAYS_INLINE void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:792
MFEM_ALWAYS_INLINE void Eval(DataType &F)
TMatrix< DOF, NIP, real_t, true > Gt_1d
Definition: tevaluator.hpp:218
MFEM_ALWAYS_INLINE void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
Definition: tevaluator.hpp:628
static const int qpts
Definition: tevaluator.hpp:997
MFEM_ALWAYS_INLINE void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:384
MFEM_ALWAYS_INLINE void CalcGradT(const grad_layout_t &grad_layout, const grad_data_t &grad_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:724
MFEM_ALWAYS_INLINE void Assemble(DataType &F)
MFEM_ALWAYS_INLINE FieldEvaluator_base(const FE_type &fe, const FiniteElementSpace &fes)
Definition: tevaluator.hpp:974
MFEM_ALWAYS_INLINE FieldEvaluator(const FiniteElementSpace &fes, const complex_t *global_data_in, complex_t *global_data_out)
TElementMatrix< InData, OutData, NE > ElementMatrix
static const layout_type layout
Definition: ttensor.hpp:352
MFEM_ALWAYS_INLINE void AssembleGradGrad(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:868
static MFEM_ALWAYS_INLINE void EvalSerialized(T_type &T, const complex_t *loc_dofs, AData_t &D)
TTensor3< qpts, vdim, NE, complex_t > val_qpts
ShapeEval_type shapeEval
Definition: tevaluator.hpp:960
TTensor3< DOF, NIP, DIM, real_t > Gt
Definition: tevaluator.hpp:44
TTensor3< dofs, vdim, NE, complex_t, true > val_dofs_t
MFEM_ALWAYS_INLINE FieldEvaluator(const FieldEvaluator &f, const complex_t *global_data_in, complex_t *global_data_out)
FESpace_t::FE_type FE_type
Definition: tevaluator.hpp:956
static MFEM_ALWAYS_INLINE void Assemble(const vec_layout_t &l, T_type &T, AData_t &D)
MFEM_ALWAYS_INLINE void CalcGradT(const grad_layout_t &grad_layout, const grad_data_t &grad_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:436
MFEM_ALWAYS_INLINE void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
Definition: tevaluator.hpp:228
MFEM_ALWAYS_INLINE void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:514
ShapeEvaluator(const FE &fe)
Definition: tevaluator.hpp:943
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
Definition: densemat.cpp:1926
MFEM_ALWAYS_INLINE void AssembleSerialized(const DataType &F, complex_t *loc_dofs)
static const layout_type layout
Definition: ttensor.hpp:374
MFEM_ALWAYS_INLINE void AssembleGradGrad(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:182
MFEM_ALWAYS_INLINE FieldEvaluator(const FESpace_t &tfes, const ShapeEval_type &shape_eval, const VecLayout_type &vec_layout, const complex_t *global_data_in, complex_t *global_data_out)
static MFEM_ALWAYS_INLINE void AssembleSerialized(T_type &T, const AData_t &D, complex_t *loc_dofs)
TTensor3< qpts, vdim, NE, complex_t, true > val_qpts
MFEM_ALWAYS_INLINE void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const M_layout_t &M_layout, M_data_t &M_data) const
Definition: tevaluator.hpp:289
MFEM_ALWAYS_INLINE FESpace_type & FESpace()
MFEM_ALWAYS_INLINE void EvalSerialized(const complex_t *loc_dofs, DataType &F)
TMatrix< DOF, NIP, real_t, true > Gt_1d
Definition: tevaluator.hpp:616
ShapeEvaluator_base< FE, IR, tensor_prod, real_t > base_class
Definition: tevaluator.hpp:936
static MFEM_ALWAYS_INLINE void Eval(const vec_layout_t &l, T_type &T, AData_t &D)
MFEM_ALWAYS_INLINE void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
Definition: tevaluator.hpp:62
TTensor3< NIP, DIM, DOF, real_t, true > G
Definition: tevaluator.hpp:43
MFEM_ALWAYS_INLINE void CalcGrad(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const grad_layout_t &grad_layout, grad_data_t &grad_data) const
Definition: tevaluator.hpp:702
MFEM_ALWAYS_INLINE ShapeEval_type & ShapeEval()
TTensor3< dofs, vdim, NE, complex_t, true > val_dofs_t
static MFEM_ALWAYS_INLINE void Assemble(const vec_layout_t &l, T_type &T, AData_t &D)
MFEM_ALWAYS_INLINE void Eval(int el, DataType &F)
static const int OutData
MFEM_ALWAYS_INLINE void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:85
static const int dim
Definition: tevaluator.hpp:996
MFEM_ALWAYS_INLINE void AssembleGradGrad(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:544
MFEM_ALWAYS_INLINE void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
Definition: tevaluator.hpp:352
MFEM_ALWAYS_INLINE void CalcGrad(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const grad_layout_t &grad_layout, grad_data_t &grad_data) const
Definition: tevaluator.hpp:418
static const int dofs
Definition: tevaluator.hpp:995
MFEM_ALWAYS_INLINE void CalcGrad(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const grad_layout_t &grad_layout, grad_data_t &grad_data) const
Definition: tevaluator.hpp:255
ShapeEvaluator< FE_type, IR, real_t > ShapeEval_type
Definition: tevaluator.hpp:989
BData< InData, OutData, NE > DataType
static MFEM_ALWAYS_INLINE void AssembleSerialized(T_type &T, const AData_t &D, complex_t *loc_dofs)
TTensor3< dofs, vdim, NE, complex_t > val_dofs_t
static const int dim
Definition: tevaluator.hpp:931
MFEM_ALWAYS_INLINE void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const M_layout_t &M_layout, M_data_t &M_data) const
Definition: tevaluator.hpp:158
MFEM_ALWAYS_INLINE void AssembleGradGrad(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:313
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:87
MFEM_ALWAYS_INLINE void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:407
const complex_t * data_in
MFEM_ALWAYS_INLINE void GetValues(int el, const val_layout_t &l, val_data_t &vals)
static MFEM_ALWAYS_INLINE void Assemble(const vec_layout_t &l, T_type &T, AData_t &D)
double a
Definition: lissajous.cpp:41
MFEM_ALWAYS_INLINE void Assemble(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const M_layout_t &M_layout, M_data_t &M_data) const
Definition: tevaluator.hpp:742
MFEM_ALWAYS_INLINE void SetElement(int el)
TTensor4< qpts, dim, vdim, NE, complex_t > grad_qpts
TMatrix< NIP, DOF, real_t, true > G_1d
Definition: tevaluator.hpp:339
MFEM_ALWAYS_INLINE void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:691
int dim
Definition: ex24.cpp:43
FieldEvaluator_base< FESpace_t, VecLayout_t, IR, complex_t, real_t > base_class
MFEM_ALWAYS_INLINE void GetGradients(int el, const grad_layout_t &l, grad_data_t &grad)
FieldEvaluator< FESpace_t, VecLayout_t, IR, complex_t, real_t > T_type
Definition: tevaluator.hpp:993
TMatrix< NIP, DOF, real_t, true > B
Definition: tevaluator.hpp:41
static const int qpts
Definition: tevaluator.hpp:932
TTensor3< dofs, vdim, NE, complex_t > val_dofs_t
static MFEM_ALWAYS_INLINE void AssembleSerialized(T_type &T, const AData_t &D, complex_t *loc_dofs)
static MFEM_ALWAYS_INLINE void EvalSerialized(T_type &T, const complex_t *loc_dofs, AData_t &D)
FESpace_t::FE_type FE_type
Definition: tevaluator.hpp:988
MFEM_ALWAYS_INLINE void CalcT(const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tevaluator.hpp:242
TTensor3< dofs, vdim, NE, complex_t, true > val_dofs_t
static MFEM_ALWAYS_INLINE void Eval(const vec_layout_t &l, T_type &T, AData_t &D)
MFEM_ALWAYS_INLINE void Assemble(int D1, int D2, const qpt_layout_t &qpt_layout, const qpt_data_t &qpt_data, const D_layout_t &D_layout, D_data_t &D_data) const
Definition: tevaluator.hpp:828
MFEM_ALWAYS_INLINE void Assemble(int el, DataType &F)
MFEM_ALWAYS_INLINE FieldEvaluator_base(const FESpace_t &tfes, const ShapeEval_type &shape_eval, const VecLayout_t &vec_layout)
Definition: tevaluator.hpp:965
TMatrix< NIP, DOF, real_t, true > G_1d
Definition: tevaluator.hpp:615
static const int vdim
Definition: tevaluator.hpp:998
MFEM_ALWAYS_INLINE void CalcGrad(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const grad_layout_t &grad_layout, grad_data_t &grad_data) const
Definition: tevaluator.hpp:107
MFEM_ALWAYS_INLINE void Calc(const dof_layout_t &dof_layout, const dof_data_t &dof_data, const qpt_layout_t &qpt_layout, qpt_data_t &qpt_data) const
Definition: tevaluator.hpp:374