MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
interpolate.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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#pragma once
12
13#include "util.hpp"
14
15namespace mfem::future
16{
17
18template <typename field_operator_t>
19MFEM_HOST_DEVICE inline
21 DeviceTensor<2> &field_qp,
22 const DofToQuadMap &dtq,
23 const DeviceTensor<1> &field_e,
24 const field_operator_t &input,
25 const DeviceTensor<1, const real_t> &integration_weights,
26 const std::array<DeviceTensor<1>, 6> &scratch_mem)
27{
28 [[maybe_unused]] auto B = dtq.B;
29 [[maybe_unused]] auto G = dtq.G;
30
32 {
33 auto [q1d, unused, d1d] = B.GetShape();
34 const int vdim = input.vdim;
35 const auto field = Reshape(&field_e[0], d1d, d1d, d1d, vdim);
36 auto fqp = Reshape(&field_qp[0], vdim, q1d, q1d, q1d);
37 auto s0 = Reshape(&scratch_mem[0](0), d1d, d1d, q1d);
38 auto s1 = Reshape(&scratch_mem[1](0), d1d, q1d, q1d);
39
40 for (int vd = 0; vd < vdim; vd++)
41 {
42 MFEM_FOREACH_THREAD(dz, z, d1d)
43 {
44 MFEM_FOREACH_THREAD(dy, y, d1d)
45 {
46 MFEM_FOREACH_THREAD(qx, x, q1d)
47 {
48 real_t acc = 0.0;
49 for (int dx = 0; dx < d1d; dx++)
50 {
51 acc += B(qx, 0, dx) * field(dx, dy, dz, vd);
52 }
53 s0(dz, dy, qx) = acc;
54 }
55 }
56 }
57 MFEM_SYNC_THREAD;
58
59 MFEM_FOREACH_THREAD(dz, z, d1d)
60 {
61 MFEM_FOREACH_THREAD(qx, x, q1d)
62 {
63 MFEM_FOREACH_THREAD(qy, y, q1d)
64 {
65 real_t acc = 0.0;
66 for (int dy = 0; dy < d1d; dy++)
67 {
68 acc += s0(dz, dy, qx) * B(qy, 0, dy);
69 }
70 s1(dz, qy, qx) = acc;
71 }
72 }
73 }
74 MFEM_SYNC_THREAD;
75
76 MFEM_FOREACH_THREAD(qz, z, q1d)
77 {
78 MFEM_FOREACH_THREAD(qy, y, q1d)
79 {
80 MFEM_FOREACH_THREAD(qx, x, q1d)
81 {
82 real_t acc = 0.0;
83 for (int dz = 0; dz < d1d; dz++)
84 {
85 acc += s1(dz, qy, qx) * B(qz, 0, dz);
86 }
87 fqp(vd, qx, qy, qz) = acc;
88 }
89 }
90 }
91 MFEM_SYNC_THREAD;
92 }
93 }
94 else if constexpr (
96 {
97 const auto [q1d, unused, d1d] = B.GetShape();
98 const int vdim = input.vdim;
99 const int dim = input.dim;
100 const auto field = Reshape(&field_e[0], d1d, d1d, d1d, vdim);
101 auto fqp = Reshape(&field_qp[0], vdim, dim, q1d, q1d, q1d);
102
103 auto s0 = Reshape(&scratch_mem[0](0), d1d, d1d, q1d);
104 auto s1 = Reshape(&scratch_mem[1](0), d1d, d1d, q1d);
105 auto s2 = Reshape(&scratch_mem[2](0), d1d, q1d, q1d);
106 auto s3 = Reshape(&scratch_mem[3](0), d1d, q1d, q1d);
107 auto s4 = Reshape(&scratch_mem[4](0), d1d, q1d, q1d);
108
109 for (int vd = 0; vd < vdim; vd++)
110 {
111 MFEM_FOREACH_THREAD(dz, z, d1d)
112 {
113 MFEM_FOREACH_THREAD(dy, y, d1d)
114 {
115 MFEM_FOREACH_THREAD(qx, x, q1d)
116 {
117 real_t uv[2] = {0.0, 0.0};
118 for (int dx = 0; dx < d1d; dx++)
119 {
120 const real_t f = field(dx, dy, dz, vd);
121 uv[0] += f * B(qx, 0, dx);
122 uv[1] += f * G(qx, 0, dx);
123 }
124 s0(dz, dy, qx) = uv[0];
125 s1(dz, dy, qx) = uv[1];
126 }
127 }
128 }
129 MFEM_SYNC_THREAD;
130
131 MFEM_FOREACH_THREAD(dz, z, d1d)
132 {
133 MFEM_FOREACH_THREAD(qy, y, q1d)
134 {
135 MFEM_FOREACH_THREAD(qx, x, q1d)
136 {
137 real_t uvw[3] = {0.0, 0.0, 0.0};
138 for (int dy = 0; dy < d1d; dy++)
139 {
140 const real_t s0i = s0(dz, dy, qx);
141 uvw[0] += s1(dz, dy, qx) * B(qy, 0, dy);
142 uvw[1] += s0i * G(qy, 0, dy);
143 uvw[2] += s0i * B(qy, 0, dy);
144 }
145 s2(dz, qy, qx) = uvw[0];
146 s3(dz, qy, qx) = uvw[1];
147 s4(dz, qy, qx) = uvw[2];
148 }
149 }
150 }
151 MFEM_SYNC_THREAD;
152
153 MFEM_FOREACH_THREAD(qz, z, q1d)
154 {
155 MFEM_FOREACH_THREAD(qy, y, q1d)
156 {
157 MFEM_FOREACH_THREAD(qx, x, q1d)
158 {
159 real_t uvw[3] = {0.0, 0.0, 0.0};
160 for (int dz = 0; dz < d1d; dz++)
161 {
162 uvw[0] += s2(dz, qy, qx) * B(qz, 0, dz);
163 uvw[1] += s3(dz, qy, qx) * B(qz, 0, dz);
164 uvw[2] += s4(dz, qy, qx) * G(qz, 0, dz);
165 }
166 fqp(vd, 0, qx, qy, qz) = uvw[0];
167 fqp(vd, 1, qx, qy, qz) = uvw[1];
168 fqp(vd, 2, qx, qy, qz) = uvw[2];
169 }
170 }
171 }
172 MFEM_SYNC_THREAD;
173 }
174 }
175 // TODO: Create separate function for clarity
176 else if constexpr (
177 std::is_same_v<std::decay_t<field_operator_t>, Weight>)
178 {
179 const int num_qp = integration_weights.GetShape()[0];
180 // TODO: eeek
181 const int q1d = (int)floor(std::pow(num_qp, 1.0/input.dim) + 0.5);
182 auto w = Reshape(&integration_weights[0], q1d, q1d, q1d);
183 auto f = Reshape(&field_qp[0], q1d, q1d, q1d);
184 MFEM_FOREACH_THREAD(qx, x, q1d)
185 {
186 MFEM_FOREACH_THREAD(qy, y, q1d)
187 {
188 MFEM_FOREACH_THREAD(qz, z, q1d)
189 {
190 f(qx, qy, qz) = w(qx, qy, qz);
191 }
192 }
193 }
194 MFEM_SYNC_THREAD;
195 }
196 else if constexpr (is_identity_fop<std::decay_t<field_operator_t>>::value)
197 {
198 const int q1d = B.GetShape()[0];
199 auto field = Reshape(&field_e[0], input.size_on_qp, q1d * q1d * q1d);
200 field_qp = field;
201 }
202 else
203 {
205 "can't map field to quadrature data");
206 }
207}
208
209template <typename field_operator_t>
210MFEM_HOST_DEVICE inline
212 DeviceTensor<2> &field_qp,
213 const DofToQuadMap &dtq,
214 const DeviceTensor<1> &field_e,
215 const field_operator_t &input,
216 const DeviceTensor<1, const real_t> &integration_weights,
217 const std::array<DeviceTensor<1>, 6> &scratch_mem)
218{
219 [[maybe_unused]] auto B = dtq.B;
220 [[maybe_unused]] auto G = dtq.G;
221
223 {
224 auto [q1d, unused, d1d] = B.GetShape();
225 const int vdim = input.vdim;
226 const auto field = Reshape(&field_e[0], d1d, d1d, vdim);
227 auto fqp = Reshape(&field_qp[0], vdim, q1d, q1d);
228 auto s0 = Reshape(&scratch_mem[0](0), d1d, q1d);
229
230 for (int vd = 0; vd < vdim; vd++)
231 {
232 MFEM_FOREACH_THREAD(dy, y, d1d)
233 {
234 MFEM_FOREACH_THREAD(qx, x, q1d)
235 {
236 real_t acc = 0.0;
237 for (int dx = 0; dx < d1d; dx++)
238 {
239 acc += B(qx, 0, dx) * field(dx, dy, vd);
240 }
241 s0(dy, qx) = acc;
242 }
243 }
244 MFEM_SYNC_THREAD;
245
246 MFEM_FOREACH_THREAD(qx, x, q1d)
247 {
248 MFEM_FOREACH_THREAD(qy, y, q1d)
249 {
250 real_t acc = 0.0;
251 for (int dy = 0; dy < d1d; dy++)
252 {
253 acc += s0(dy, qx) * B(qy, 0, dy);
254 }
255 fqp(vd, qx, qy) = acc;
256 }
257 }
258 MFEM_SYNC_THREAD;
259 }
260 }
261 else if constexpr (
263 {
264 const auto [q1d, unused, d1d] = B.GetShape();
265 const int vdim = input.vdim;
266 const int dim = input.dim;
267 const auto field = Reshape(&field_e[0], d1d, d1d, vdim);
268 auto fqp = Reshape(&field_qp[0], vdim, dim, q1d, q1d);
269
270 auto s0 = Reshape(&scratch_mem[0](0), d1d, q1d);
271 auto s1 = Reshape(&scratch_mem[1](0), d1d, q1d);
272
273 for (int vd = 0; vd < vdim; vd++)
274 {
275 MFEM_FOREACH_THREAD(dy, y, d1d)
276 {
277 MFEM_FOREACH_THREAD(qx, x, q1d)
278 {
279 real_t uv[2] = {0.0, 0.0};
280 for (int dx = 0; dx < d1d; dx++)
281 {
282 const real_t f = field(dx, dy, vd);
283 uv[0] += f * B(qx, 0, dx);
284 uv[1] += f * G(qx, 0, dx);
285 }
286 s0(dy, qx) = uv[0];
287 s1(dy, qx) = uv[1];
288 }
289 }
290 MFEM_SYNC_THREAD;
291
292 MFEM_FOREACH_THREAD(qy, y, q1d)
293 {
294 MFEM_FOREACH_THREAD(qx, x, q1d)
295 {
296 real_t uv[2] = {0.0, 0.0};
297 for (int dy = 0; dy < d1d; dy++)
298 {
299 const real_t s0i = s0(dy, qx);
300 uv[0] += s1(dy, qx) * B(qy, 0, dy);
301 uv[1] += s0i * G(qy, 0, dy);
302 }
303 fqp(vd, 0, qx, qy) = uv[0];
304 fqp(vd, 1, qx, qy) = uv[1];
305 }
306 }
307 MFEM_SYNC_THREAD;
308 }
309 }
310 // TODO: Create separate function for clarity
311 else if constexpr (
312 std::is_same_v<std::decay_t<field_operator_t>, Weight>)
313 {
314 const int num_qp = integration_weights.GetShape()[0];
315 // TODO: eeek
316 const int q1d = (int)floor(std::pow(num_qp, 1.0/input.dim) + 0.5);
317 auto w = Reshape(&integration_weights[0], q1d, q1d);
318 auto f = Reshape(&field_qp[0], q1d, q1d);
319 MFEM_FOREACH_THREAD(qx, x, q1d)
320 {
321 MFEM_FOREACH_THREAD(qy, y, q1d)
322 {
323 f(qx, qy) = w(qx, qy);
324 }
325 }
326 MFEM_SYNC_THREAD;
327 }
328 else if constexpr (is_identity_fop<std::decay_t<field_operator_t>>::value)
329 {
330 const int q1d = B.GetShape()[0];
331 auto field = Reshape(&field_e[0], input.size_on_qp, q1d * q1d);
332 field_qp = field;
333 }
334 else
335 {
337 "can't map field to quadrature data");
338 }
339}
340
341
342template <typename field_operator_t>
343MFEM_HOST_DEVICE inline
345 DeviceTensor<2> &field_qp,
346 const DofToQuadMap &dtq,
347 const DeviceTensor<1> &field_e,
348 const field_operator_t &input,
349 const DeviceTensor<1, const real_t> &integration_weights,
350 const std::array<DeviceTensor<1>, 6> &scratch_mem)
351{
352 [[maybe_unused]] auto B = dtq.B;
353 [[maybe_unused]] auto G = dtq.G;
354
356 {
357 auto [q1d, unused, d1d] = B.GetShape();
358 const int vdim = input.vdim;
359 const auto field = Reshape(&field_e[0], d1d, vdim);
360 auto fqp = Reshape(&field_qp[0], vdim, q1d);
361
362 for (int vd = 0; vd < vdim; vd++)
363 {
364 MFEM_FOREACH_THREAD(qx, x, q1d)
365 {
366 real_t acc = 0.0;
367 for (int dx = 0; dx < d1d; dx++)
368 {
369 acc += B(qx, 0, dx) * field(dx, vd);
370 }
371 fqp(vd, qx) = acc;
372 }
373 }
374 MFEM_SYNC_THREAD;
375 }
376 else if constexpr (
378 {
379 const auto [q1d, unused, d1d] = B.GetShape();
380 const int vdim = input.vdim;
381 const int dim = input.dim;
382 const auto field = Reshape(&field_e[0], d1d, vdim);
383 auto fqp = Reshape(&field_qp[0], vdim, dim, q1d);
384
385 for (int vd = 0; vd < vdim; vd++)
386 {
387 MFEM_FOREACH_THREAD(qx, x, q1d)
388 {
389 real_t acc = 0.0;
390 for (int dx = 0; dx < d1d; dx++)
391 {
392 acc += G(qx, 0, dx) * field(dx, vd);
393 }
394 fqp(vd, 0, qx) = acc;
395 }
396 MFEM_SYNC_THREAD;
397 }
398 }
399 // TODO: Create separate function for clarity
400 else if constexpr (
401 std::is_same_v<std::decay_t<field_operator_t>, Weight>)
402 {
403 const int num_qp = integration_weights.GetShape()[0];
404 // TODO: eeek
405 const int q1d = (int)floor(std::pow(num_qp, 1.0/input.dim) + 0.5);
406 auto w = Reshape(&integration_weights[0], q1d);
407 auto f = Reshape(&field_qp[0], q1d);
408 MFEM_FOREACH_THREAD(qx, x, q1d)
409 {
410 f(qx) = w(qx);
411 }
412 MFEM_SYNC_THREAD;
413 }
414 else if constexpr (is_identity_fop<std::decay_t<field_operator_t>>::value)
415 {
416 const int q1d = B.GetShape()[0];
417 auto field = Reshape(&field_e[0], input.size_on_qp, q1d);
418 field_qp = field;
419 }
420 else
421 {
423 "can't map field to quadrature data");
424 }
425}
426
427template <typename field_operator_t>
428MFEM_HOST_DEVICE
430 DeviceTensor<2> field_qp,
431 const DofToQuadMap &dtq,
432 const DeviceTensor<1> &field_e,
433 const field_operator_t &input,
434 const DeviceTensor<1, const real_t> &integration_weights)
435{
436 [[maybe_unused]] auto B = dtq.B;
437 [[maybe_unused]] auto G = dtq.G;
439 {
440 auto [num_qp, dim, num_dof] = B.GetShape();
441 const int vdim = input.vdim;
442 const auto field = Reshape(&field_e(0), num_dof, vdim);
443
444 for (int vd = 0; vd < vdim; vd++)
445 {
446 for (int qp = 0; qp < num_qp; qp++)
447 {
448 real_t acc = 0.0;
449 for (int dof = 0; dof < num_dof; dof++)
450 {
451 acc += B(qp, 0, dof) * field(dof, vd);
452 }
453 field_qp(vd, qp) = acc;
454 }
455 }
456 }
458 {
459 const auto [num_qp, dim, num_dof] = G.GetShape();
460 const int vdim = input.vdim;
461 const auto field = Reshape(&field_e(0), num_dof, vdim);
462
463 auto f = Reshape(&field_qp[0], vdim, dim, num_qp);
464 for (int vd = 0; vd < vdim; vd++)
465 {
466 for (int qp = 0; qp < num_qp; qp++)
467 {
468 for (int d = 0; d < dim; d++)
469 {
470 real_t acc = 0.0;
471 for (int dof = 0; dof < num_dof; dof++)
472 {
473 acc += G(qp, d, dof) * field(dof, vd);
474 }
475 f(vd, d, qp) = acc;
476 }
477 }
478 }
479 }
480 else if constexpr (std::is_same_v<field_operator_t, Weight>)
481 {
482 const int num_qp = integration_weights.GetShape()[0];
483 auto f = Reshape(&field_qp[0], num_qp);
484 for (int qp = 0; qp < num_qp; qp++)
485 {
486 f(qp) = integration_weights(qp);
487 }
488 }
490 {
491 auto [num_qp, unused, num_dof] = B.GetShape();
492 const int size_on_qp = input.size_on_qp;
493 const auto field = Reshape(&field_e[0], size_on_qp * num_qp);
494 auto f = Reshape(&field_qp[0], size_on_qp * num_qp);
495 for (int i = 0; i < size_on_qp * num_qp; i++)
496 {
497 f(i) = field(i);
498 }
499 }
500 else
501 {
503 "can't map field to quadrature data");
504
505 }
506}
507
508template <typename field_operator_ts, size_t num_inputs, size_t num_fields>
509MFEM_HOST_DEVICE inline
511 std::array<DeviceTensor<2>, num_inputs> &fields_qp,
512 const std::array<DeviceTensor<1>, num_fields> &fields_e,
513 const std::array<DofToQuadMap, num_inputs> &dtqmaps,
514 const std::array<size_t, num_inputs> &input_to_field,
515 const field_operator_ts &fops,
516 const DeviceTensor<1, const real_t> &integration_weights,
517 const std::array<DeviceTensor<1>, 6> &scratch_mem,
518 const int &dimension,
519 const bool &use_sum_factorization = false)
520{
521 // When the input_to_field map returns -1, this means the requested input
522 // is the integration weight. Weights don't have a user defined field
523 // attached to them and we create a dummy field which is not accessed
524 // inside the functions it is passed to.
525 const auto dummy_field_weight = DeviceTensor<1>(nullptr, 0);
526 for_constexpr<num_inputs>([&](auto i)
527 {
528 const DeviceTensor<1> &field_e =
529 (input_to_field[i] == SIZE_MAX) ? dummy_field_weight :
530 fields_e[input_to_field[i]];
531
532 if (use_sum_factorization)
533 {
534 if (dimension == 1)
535 {
537 fields_qp[i], dtqmaps[i], field_e, get<i>(fops),
538 integration_weights, scratch_mem);
539 }
540 else if (dimension == 2)
541 {
543 fields_qp[i], dtqmaps[i], field_e, get<i>(fops),
544 integration_weights, scratch_mem);
545 }
546 else if (dimension == 3)
547 {
549 fields_qp[i], dtqmaps[i], field_e, get<i>(fops),
550 integration_weights, scratch_mem);
551 }
552 else
553 {
554#if !(defined(MFEM_USE_CUDA) || defined(MFEM_USE_HIP))
555 MFEM_ABORT("unsupported dimension");
556#endif
557 }
558 }
559 else
560 {
562 fields_qp[i], dtqmaps[i], field_e, get<i>(fops),
563 integration_weights);
564 }
565 });
566}
567
568template <typename field_operator_t>
569MFEM_HOST_DEVICE
571 DeviceTensor<2> &field_qp,
572 const DeviceTensor<1> &field_e,
573 const DofToQuadMap &dtqmap,
574 field_operator_t &fop,
575 const DeviceTensor<1, const real_t> &integration_weights,
576 const std::array<DeviceTensor<1>, 6> &scratch_mem,
577 const bool &condition,
578 const int &dimension,
579 const bool &use_sum_factorization = false)
580{
581 if (condition)
582 {
583 if (use_sum_factorization)
584 {
585 if (dimension == 1)
586 {
588 field_qp, dtqmap, field_e, fop, integration_weights, scratch_mem);
589
590 }
591 else if (dimension == 2)
592 {
594 field_qp, dtqmap, field_e, fop, integration_weights, scratch_mem);
595 }
596 else if (dimension == 3)
597 {
599 field_qp, dtqmap, field_e, fop, integration_weights, scratch_mem);
600 }
601 }
602 else
603 {
605 field_qp, dtqmap, field_e, fop, integration_weights);
606 }
607 }
608}
609
610template <size_t num_fields, size_t num_inputs, typename field_operator_ts>
611MFEM_HOST_DEVICE
613 std::array<DeviceTensor<2>, num_inputs> &fields_qp,
614 const std::array<DeviceTensor<1, const real_t>, num_fields> &fields_e,
615 const std::array<DofToQuadMap, num_inputs> &dtqmaps,
616 field_operator_ts fops,
617 const DeviceTensor<1, const real_t> &integration_weights,
618 const std::array<DeviceTensor<1>, 6> &scratch_mem,
619 const std::array<bool, num_inputs> &conditions,
620 const bool &use_sum_factorization = false)
621{
622 for_constexpr<num_inputs>([&](auto i)
623 {
625 fields_qp[i], fields_e[i], dtqmaps[i], get<i>(fops), integration_weights,
626 scratch_mem, conditions[i], use_sum_factorization);
627 });
628}
629
630template <size_t num_inputs, typename field_operator_ts>
631MFEM_HOST_DEVICE
633 std::array<DeviceTensor<2>, num_inputs> &directions_qp,
634 const DeviceTensor<1> &direction_e,
635 const std::array<DofToQuadMap, num_inputs> &dtqmaps,
636 field_operator_ts fops,
637 const DeviceTensor<1, const real_t> &integration_weights,
638 const std::array<DeviceTensor<1>, 6> &scratch_mem,
639 const std::array<bool, num_inputs> &conditions,
640 const int &dimension,
641 const bool &use_sum_factorization)
642{
643 for_constexpr<num_inputs>([&](auto i)
644 {
645 if (conditions[i])
646 {
647 if (use_sum_factorization)
648 {
649 if (dimension == 1)
650 {
652 directions_qp[i], dtqmaps[i], direction_e, get<i>(fops),
653 integration_weights, scratch_mem);
654 }
655 else if (dimension == 2)
656 {
658 directions_qp[i], dtqmaps[i], direction_e, get<i>(fops),
659 integration_weights, scratch_mem);
660 }
661 else if (dimension == 3)
662 {
664 directions_qp[i], dtqmaps[i], direction_e, get<i>(fops),
665 integration_weights, scratch_mem);
666 }
667 }
668 else
669 {
671 directions_qp[i], dtqmaps[i], direction_e, get<i>(fops),
672 integration_weights);
673 }
674 }
675 });
676}
677
678}
A basic generic Tensor class, appropriate for use on the GPU.
Definition dtensor.hpp:84
MFEM_HOST_DEVICE auto & GetShape() const
Returns the shape of the tensor.
Definition dtensor.hpp:131
Weight FieldOperator.
int dim
Definition ex24.cpp:53
constexpr int dimension
This example only works in 3D. Kernels for 2D are not implemented.
Definition hooke.cpp:45
constexpr bool always_false
Definition util.hpp:575
MFEM_HOST_DEVICE void map_fields_to_quadrature_data(std::array< DeviceTensor< 2 >, num_inputs > &fields_qp, const std::array< DeviceTensor< 1 >, num_fields > &fields_e, const std::array< DofToQuadMap, num_inputs > &dtqmaps, const std::array< size_t, num_inputs > &input_to_field, const field_operator_ts &fops, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem, const int &dimension, const bool &use_sum_factorization=false)
MFEM_HOST_DEVICE void map_field_to_quadrature_data_tensor_product_2d(DeviceTensor< 2 > &field_qp, const DofToQuadMap &dtq, const DeviceTensor< 1 > &field_e, const field_operator_t &input, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem)
MFEM_HOST_DEVICE void map_field_to_quadrature_data_tensor_product_1d(DeviceTensor< 2 > &field_qp, const DofToQuadMap &dtq, const DeviceTensor< 1 > &field_e, const field_operator_t &input, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem)
MFEM_HOST_DEVICE void map_fields_to_quadrature_data_conditional(std::array< DeviceTensor< 2 >, num_inputs > &fields_qp, const std::array< DeviceTensor< 1, const real_t >, num_fields > &fields_e, const std::array< DofToQuadMap, num_inputs > &dtqmaps, field_operator_ts fops, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem, const std::array< bool, num_inputs > &conditions, const bool &use_sum_factorization=false)
MFEM_HOST_DEVICE void map_direction_to_quadrature_data_conditional(std::array< DeviceTensor< 2 >, num_inputs > &directions_qp, const DeviceTensor< 1 > &direction_e, const std::array< DofToQuadMap, num_inputs > &dtqmaps, field_operator_ts fops, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem, const std::array< bool, num_inputs > &conditions, const int &dimension, const bool &use_sum_factorization)
constexpr void for_constexpr(lambda &&f, std::integer_sequence< std::size_t, i ... >)
Definition util.hpp:71
MFEM_HOST_DEVICE void map_field_to_quadrature_data_tensor_product_3d(DeviceTensor< 2 > &field_qp, const DofToQuadMap &dtq, const DeviceTensor< 1 > &field_e, const field_operator_t &input, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem)
MFEM_HOST_DEVICE void map_field_to_quadrature_data_conditional(DeviceTensor< 2 > &field_qp, const DeviceTensor< 1 > &field_e, const DofToQuadMap &dtqmap, field_operator_t &fop, const DeviceTensor< 1, const real_t > &integration_weights, const std::array< DeviceTensor< 1 >, 6 > &scratch_mem, const bool &condition, const int &dimension, const bool &use_sum_factorization=false)
MFEM_HOST_DEVICE void map_field_to_quadrature_data(DeviceTensor< 2 > field_qp, const DofToQuadMap &dtq, const DeviceTensor< 1 > &field_e, const field_operator_t &input, const DeviceTensor< 1, const real_t > &integration_weights)
MFEM_HOST_DEVICE zero & get(zero &x)
let zero be accessed like a tuple
Definition tensor.hpp:281
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition dtensor.hpp:138
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
DofToQuadMap struct.
Definition util.hpp:1518
DeviceTensor< 3, const real_t > G
Gradient of the basis functions evaluated at quadrature points.
Definition util.hpp:1535
DeviceTensor< 3, const real_t > B
Basis functions evaluated at quadrature points.
Definition util.hpp:1530