deal.II version GIT relicensing-2287-g6548a49e0a 2024-12-20 18:30:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
portable_fe_evaluation.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2023 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_portable_fe_evaluation_h
16#define dealii_portable_fe_evaluation_h
17
18#include <deal.II/base/config.h>
19
21#include <deal.II/base/tensor.h>
23
27#include <deal.II/matrix_free/portable_matrix_free.templates.h>
29
30#include <Kokkos_Core.hpp>
31
33
37namespace Portable
38{
62 template <int dim,
63 int fe_degree,
64 int n_q_points_1d = fe_degree + 1,
65 int n_components_ = 1,
66 typename Number = double>
68 {
69 public:
73 using value_type = std::conditional_t<(n_components_ == 1),
74 Number,
76
80 using gradient_type = std::conditional_t<
81 n_components_ == 1,
83 std::conditional_t<n_components_ == dim,
86
91
95 static constexpr unsigned int dimension = dim;
96
100 static constexpr unsigned int n_components = n_components_;
101
105 static constexpr unsigned int n_q_points =
106 Utilities::pow(n_q_points_1d, dim);
107
111 static constexpr unsigned int tensor_dofs_per_cell =
112 Utilities::pow(fe_degree + 1, dim);
113
119
129 read_dof_values(const Number *src);
130
138 distribute_local_to_global(Number *dst) const;
139
148 evaluate(const EvaluationFlags::EvaluationFlags evaluate_flag);
149
157 DEAL_II_DEPRECATED_WITH_COMMENT("Use the version taking EvaluationFlags.")
159 void
160 evaluate(const bool evaluate_val, const bool evaluate_grad);
161
169 integrate(const EvaluationFlags::EvaluationFlags integration_flag);
170
178 DEAL_II_DEPRECATED_WITH_COMMENT("Use the version taking EvaluationFlags.")
180 void
181 integrate(const bool integrate_val, const bool integrate_grad);
182
188 get_value(int q_point) const;
189
195 get_dof_value(int q_point) const;
196
202 submit_value(const value_type &val_in, int q_point);
203
209 submit_dof_value(const value_type &val_in, int q_point);
210
216 get_gradient(int q_point) const;
217
223 submit_gradient(const gradient_type &grad_in, int q_point);
224
225 // clang-format off
236 // clang-format on
237 template <typename Functor>
239 apply_for_each_quad_point(const Functor &func);
240
241 private:
243 SharedData<dim, Number> *shared_data;
245 };
246
247
248
249 template <int dim,
250 int fe_degree,
251 int n_q_points_1d,
252 int n_components_,
253 typename Number>
255 FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
256 FEEvaluation(const data_type *data, SharedData<dim, Number> *shdata)
257 : data(data)
258 , shared_data(shdata)
259 , cell_id(shared_data->team_member.league_rank())
260 {}
261
262
263
264 template <int dim,
265 int fe_degree,
266 int n_q_points_1d,
267 int n_components_,
268 typename Number>
271 read_dof_values(const Number *src)
272 {
273 // Populate the scratch memory
274 Kokkos::parallel_for(
275 Kokkos::TeamThreadRange(shared_data->team_member, n_q_points),
276 [&](const int &i) {
277 for (unsigned int c = 0; c < n_components_; ++c)
278 shared_data->values(i, c) =
279 src[data->local_to_global(cell_id, i + tensor_dofs_per_cell * c)];
280 });
281 shared_data->team_member.team_barrier();
282
283 for (unsigned int c = 0; c < n_components_; ++c)
284 {
285 internal::resolve_hanging_nodes<dim, fe_degree, false, Number>(
286 shared_data->team_member,
287 data->constraint_weights,
288 data->constraint_mask(cell_id),
289 Kokkos::subview(shared_data->values, Kokkos::ALL, c));
290 }
291 }
292
293
294
295 template <int dim,
296 int fe_degree,
297 int n_q_points_1d,
298 int n_components_,
299 typename Number>
302 distribute_local_to_global(Number *dst) const
303 {
304 for (unsigned int c = 0; c < n_components_; ++c)
305 {
306 internal::resolve_hanging_nodes<dim, fe_degree, true, Number>(
307 shared_data->team_member,
308 data->constraint_weights,
309 data->constraint_mask(cell_id),
310 Kokkos::subview(shared_data->values, Kokkos::ALL, c));
311 }
312
313 if (data->use_coloring)
314 {
315 Kokkos::parallel_for(
316 Kokkos::TeamThreadRange(shared_data->team_member, n_q_points),
317 [&](const int &i) {
318 for (unsigned int c = 0; c < n_components_; ++c)
319 dst[data->local_to_global(cell_id,
320 i + tensor_dofs_per_cell * c)] +=
321 shared_data->values(i, c);
322 });
323 }
324 else
325 {
326 Kokkos::parallel_for(
327 Kokkos::TeamThreadRange(shared_data->team_member, n_q_points),
328 [&](const int &i) {
329 for (unsigned int c = 0; c < n_components_; ++c)
330 Kokkos::atomic_add(&dst[data->local_to_global(
331 cell_id, i + tensor_dofs_per_cell * c)],
332 shared_data->values(i, c));
333 });
334 }
335 }
336
337
338
339 template <int dim,
340 int fe_degree,
341 int n_q_points_1d,
342 int n_components_,
343 typename Number>
346 const EvaluationFlags::EvaluationFlags evaluate_flag)
347 {
348 // First evaluate the gradients because it requires values that will be
349 // changed if evaluate_val is true
352 dim,
353 fe_degree,
354 n_q_points_1d,
355 Number>
356 evaluator_tensor_product(shared_data->team_member,
357 data->shape_values,
358 data->shape_gradients,
359 data->co_shape_gradients);
360
361 for (unsigned int c = 0; c < n_components_; ++c)
362 {
363 if ((evaluate_flag & EvaluationFlags::values) &&
364 (evaluate_flag & EvaluationFlags::gradients))
365 {
366 evaluator_tensor_product.evaluate_values_and_gradients(
367 Kokkos::subview(shared_data->values, Kokkos::ALL, c),
368 Kokkos::subview(
369 shared_data->gradients, Kokkos::ALL, Kokkos::ALL, c));
370 shared_data->team_member.team_barrier();
371 }
372 else if (evaluate_flag & EvaluationFlags::gradients)
373 {
374 evaluator_tensor_product.evaluate_gradients(
375 Kokkos::subview(shared_data->values, Kokkos::ALL, c),
376 Kokkos::subview(
377 shared_data->gradients, Kokkos::ALL, Kokkos::ALL, c));
378 shared_data->team_member.team_barrier();
379 }
380 else if (evaluate_flag & EvaluationFlags::values)
381 {
382 evaluator_tensor_product.evaluate_values(
383 Kokkos::subview(shared_data->values, Kokkos::ALL, c));
384 shared_data->team_member.team_barrier();
385 }
386 }
387 }
388
389
390
391 template <int dim,
392 int fe_degree,
393 int n_q_points_1d,
394 int n_components_,
395 typename Number>
398 const bool evaluate_val,
399 const bool evaluate_grad)
400 {
401 evaluate(
404 }
405
406
407
408 template <int dim,
409 int fe_degree,
410 int n_q_points_1d,
411 int n_components_,
412 typename Number>
415 const EvaluationFlags::EvaluationFlags integration_flag)
416 {
419 dim,
420 fe_degree,
421 n_q_points_1d,
422 Number>
423 evaluator_tensor_product(shared_data->team_member,
424 data->shape_values,
425 data->shape_gradients,
426 data->co_shape_gradients);
427
428
429 for (unsigned int c = 0; c < n_components_; ++c)
430 {
431 if ((integration_flag & EvaluationFlags::values) &&
432 (integration_flag & EvaluationFlags::gradients))
433 {
434 evaluator_tensor_product.integrate_values_and_gradients(
435 Kokkos::subview(shared_data->values, Kokkos::ALL, c),
436 Kokkos::subview(
437 shared_data->gradients, Kokkos::ALL, Kokkos::ALL, c));
438 }
439 else if (integration_flag & EvaluationFlags::values)
440 {
441 evaluator_tensor_product.integrate_values(
442 Kokkos::subview(shared_data->values, Kokkos::ALL, c));
443 shared_data->team_member.team_barrier();
444 }
445 else if (integration_flag & EvaluationFlags::gradients)
446 {
447 evaluator_tensor_product.template integrate_gradients<false>(
448 Kokkos::subview(shared_data->values, Kokkos::ALL, c),
449 Kokkos::subview(
450 shared_data->gradients, Kokkos::ALL, Kokkos::ALL, c));
451 shared_data->team_member.team_barrier();
452 }
453 }
454 }
455
456
457
458 template <int dim,
459 int fe_degree,
460 int n_q_points_1d,
461 int n_components_,
462 typename Number>
465 const bool integrate_val,
466 const bool integrate_grad)
467 {
468 integrate(
471 }
472
473
474
475 template <int dim,
476 int fe_degree,
477 int n_q_points_1d,
478 int n_components_,
479 typename Number>
481 fe_degree,
482 n_q_points_1d,
483 n_components_,
484 Number>::value_type
486 int q_point) const
487 {
488 if constexpr (n_components_ == 1)
489 {
490 return shared_data->values(q_point, 0);
491 }
492 else
493 {
494 value_type result;
495 for (unsigned int c = 0; c < n_components; ++c)
496 result[c] = shared_data->values(q_point, c);
497 return result;
498 }
499 }
500
501
502
503 template <int dim,
504 int fe_degree,
505 int n_q_points_1d,
506 int n_components_,
507 typename Number>
509 fe_degree,
510 n_q_points_1d,
511 n_components_,
512 Number>::value_type
514 get_dof_value(int q_point) const
515 {
516 if constexpr (n_components_ == 1)
517 {
518 return shared_data->values(q_point, 0);
519 }
520 else
521 {
522 value_type result;
523 for (unsigned int c = 0; c < n_components; ++c)
524 result[c] = shared_data->values(q_point, c);
525 return result;
526 }
527 }
528
529
530
531 template <int dim,
532 int fe_degree,
533 int n_q_points_1d,
534 int n_components_,
535 typename Number>
538 submit_value(const value_type &val_in, int q_point)
539 {
540 if constexpr (n_components_ == 1)
541 {
542 shared_data->values(q_point, 0) = val_in * data->JxW(cell_id, q_point);
543 }
544 else
545 {
546 for (unsigned int c = 0; c < n_components; ++c)
547 shared_data->values(q_point, c) =
548 val_in[c] * data->JxW(cell_id, q_point);
549 }
550 }
551
552
553
554 template <int dim,
555 int fe_degree,
556 int n_q_points_1d,
557 int n_components_,
558 typename Number>
561 submit_dof_value(const value_type &val_in, int q_point)
562 {
563 if constexpr (n_components_ == 1)
564 {
565 shared_data->values(q_point, 0) = val_in;
566 }
567 else
568 {
569 for (unsigned int c = 0; c < n_components; ++c)
570 shared_data->values(q_point, c) = val_in[c];
571 }
572 }
573
574
575
576 template <int dim,
577 int fe_degree,
578 int n_q_points_1d,
579 int n_components_,
580 typename Number>
582 fe_degree,
583 n_q_points_1d,
584 n_components_,
585 Number>::gradient_type
587 get_gradient(int q_point) const
588 {
589 gradient_type grad;
590
591 if constexpr (n_components_ == 1)
592 {
593 for (unsigned int d_1 = 0; d_1 < dim; ++d_1)
594 {
595 Number tmp = 0.;
596 for (unsigned int d_2 = 0; d_2 < dim; ++d_2)
597 tmp += data->inv_jacobian(cell_id, q_point, d_2, d_1) *
598 shared_data->gradients(q_point, d_2, 0);
599 grad[d_1] = tmp;
600 }
601 }
602 else
603 {
604 for (unsigned int c = 0; c < n_components; ++c)
605 for (unsigned int d_1 = 0; d_1 < dim; ++d_1)
606 {
607 Number tmp = 0.;
608 for (unsigned int d_2 = 0; d_2 < dim; ++d_2)
609 tmp += data->inv_jacobian(cell_id, q_point, d_2, d_1) *
610 shared_data->gradients(q_point, d_2, c);
611 grad[c][d_1] = tmp;
612 }
613 }
614
615 return grad;
616 }
617
618
619
620 template <int dim,
621 int fe_degree,
622 int n_q_points_1d,
623 int n_components_,
624 typename Number>
627 submit_gradient(const gradient_type &grad_in, int q_point)
628 {
629 if constexpr (n_components_ == 1)
630 {
631 for (unsigned int d_1 = 0; d_1 < dim; ++d_1)
632 {
633 Number tmp = 0.;
634 for (unsigned int d_2 = 0; d_2 < dim; ++d_2)
635 tmp +=
636 data->inv_jacobian(cell_id, q_point, d_1, d_2) * grad_in[d_2];
637 shared_data->gradients(q_point, d_1, 0) =
638 tmp * data->JxW(cell_id, q_point);
639 }
640 }
641 else
642 {
643 for (unsigned int c = 0; c < n_components; ++c)
644 for (unsigned int d_1 = 0; d_1 < dim; ++d_1)
645 {
646 Number tmp = 0.;
647 for (unsigned int d_2 = 0; d_2 < dim; ++d_2)
648 tmp += data->inv_jacobian(cell_id, q_point, d_1, d_2) *
649 grad_in[c][d_2];
650 shared_data->gradients(q_point, d_1, c) =
651 tmp * data->JxW(cell_id, q_point);
652 }
653 }
654 }
655
656
657
658 template <int dim,
659 int fe_degree,
660 int n_q_points_1d,
661 int n_components_,
662 typename Number>
663 template <typename Functor>
666 apply_for_each_quad_point(const Functor &func)
667 {
668 Kokkos::parallel_for(Kokkos::TeamThreadRange(shared_data->team_member,
669 n_q_points),
670 [&](const int &i) { func(this, i); });
671 shared_data->team_member.team_barrier();
672 }
673
674
675
676#ifndef DOXYGEN
677 template <int dim,
678 int fe_degree,
679 int n_q_points_1d,
680 int n_components_,
681 typename Number>
682 constexpr unsigned int
685#endif
686} // namespace Portable
687
689
690#endif
static constexpr unsigned int n_q_points
SharedData< dim, Number > * shared_data
void integrate(const EvaluationFlags::EvaluationFlags integration_flag)
static constexpr unsigned int dimension
static constexpr unsigned int n_components
value_type get_value(int q_point) const
static constexpr unsigned int tensor_dofs_per_cell
value_type get_dof_value(int q_point) const
std::conditional_t< n_components_==1, Tensor< 1, dim, Number >, std::conditional_t< n_components_==dim, Tensor< 2, dim, Number >, Tensor< 1, n_components_, Tensor< 1, dim, Number > > > > gradient_type
std::conditional_t<(n_components_==1), Number, Tensor< 1, n_components_, Number > > value_type
void evaluate(const EvaluationFlags::EvaluationFlags evaluate_flag)
void distribute_local_to_global(Number *dst) const
gradient_type get_gradient(int q_point) const
typename MatrixFree< dim, Number >::Data data_type
void read_dof_values(const Number *src)
void submit_dof_value(const value_type &val_in, int q_point)
void submit_value(const value_type &val_in, int q_point)
void submit_gradient(const gradient_type &grad_in, int q_point)
void apply_for_each_quad_point(const Functor &func)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_DEPRECATED_WITH_COMMENT(comment)
Definition config.h:206
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
The namespace for the EvaluationFlags enum.
EvaluationFlags
The EvaluationFlags enum.
constexpr T pow(const T base, const int iexp)
Definition utilities.h:966
#define DEAL_II_HOST_DEVICE
Definition numbers.h:30