13#ifndef dealii_portable_fe_evaluation_h
14#define dealii_portable_fe_evaluation_h
26#include <deal.II/matrix_free/portable_matrix_free.templates.h>
29#include <Kokkos_Core.hpp>
63 int n_q_points_1d = fe_degree + 1,
64 int n_components_ = 1,
73 using value_type = std::conditional_t<(n_components_ == 1),
83 std::conditional_t<n_components_ == dim,
348 : dof_handler_index(dof_handler_index)
350 , precomputed_data(&
data->precomputed_data[dof_handler_index])
351 , shared_data(&
data->shared_data[dof_handler_index])
352 , cell_id(
data->team_member.league_rank())
353 , cell_type(precomputed_data->cell_type(cell_id))
354 , mapping_data_offset(precomputed_data->data_index_offsets(cell_id))
356 (cell_type != ::
internal::MatrixFreeFunctions::general &&
357 precomputed_data->JxW.
size() > 0) ?
358 precomputed_data->JxW(mapping_data_offset) :
366 "Portable::FEEvaluation initialized with wrong number of components. Should be " +
368 " but the template argument 4 is set to " +
419 Kokkos::parallel_for(Kokkos::TeamThreadRange(
data->team_member,
420 tensor_dofs_per_component),
422 for (unsigned int c = 0; c < n_components_; ++c)
423 shared_data->values(i, c) =
424 src[precomputed_data->local_to_global(
425 i + tensor_dofs_per_component * c, cell_id)];
427 data->team_member.team_barrier();
429 for (
unsigned int c = 0; c < n_components_; ++c)
431 if (precomputed_data->constraint_mask(cell_id * n_components + c) !=
434 internal::resolve_hanging_nodes<dim, fe_degree, false, Number>(
436 precomputed_data->constraint_weights,
437 precomputed_data->constraint_mask(cell_id * n_components + c),
438 Kokkos::subview(shared_data->values, Kokkos::ALL, c));
453 for (
unsigned int c = 0; c < n_components_; ++c)
455 if (precomputed_data->constraint_mask(cell_id * n_components + c) !=
458 internal::resolve_hanging_nodes<dim, fe_degree, true, Number>(
460 precomputed_data->constraint_weights,
461 precomputed_data->constraint_mask(cell_id * n_components + c),
462 Kokkos::subview(shared_data->values, Kokkos::ALL, c));
465 if (precomputed_data->use_coloring)
467 Kokkos::parallel_for(
468 Kokkos::TeamThreadRange(
data->team_member, tensor_dofs_per_component),
470 for (unsigned int c = 0; c < n_components_; ++c)
471 dst[precomputed_data->local_to_global(
472 i + tensor_dofs_per_component * c, cell_id)] +=
473 shared_data->values(i, c);
478 Kokkos::parallel_for(
479 Kokkos::TeamThreadRange(
data->team_member, tensor_dofs_per_component),
481 for (unsigned int c = 0; c < n_components_; ++c)
482 Kokkos::atomic_add(&dst[precomputed_data->local_to_global(
483 i + (tensor_dofs_per_component)*c, cell_id)],
484 shared_data->values(i, c));
502 if (fe_degree >= 0 && fe_degree + 1 == n_q_points_1d &&
503 precomputed_data->element_type ==
504 ElementType::tensor_symmetric_collocation)
507 dof_handler_index, n_components, evaluation_flag,
data);
511 else if (fe_degree >= 0 &&
513 precomputed_data->element_type <= ElementType::tensor_symmetric)
519 Number>::evaluate(dof_handler_index,
524 else if (fe_degree >= 0 && precomputed_data->element_type <=
525 ElementType::tensor_symmetric_no_collocation)
528 evaluate(dof_handler_index, n_components, evaluation_flag,
data);
532 Kokkos::abort(
"The element type is not yet supported by the portable "
533 "matrix-free module.");
550 if (fe_degree >= 0 && fe_degree + 1 == n_q_points_1d &&
551 precomputed_data->element_type ==
552 ElementType::tensor_symmetric_collocation)
555 integrate(dof_handler_index, n_components, integration_flag,
data);
559 else if (fe_degree >= 0 &&
561 precomputed_data->element_type <= ElementType::tensor_symmetric)
567 Number>::integrate(dof_handler_index,
572 else if (fe_degree >= 0 && precomputed_data->element_type <=
573 ElementType::tensor_symmetric_no_collocation)
576 integrate(dof_handler_index, n_components, integration_flag,
data);
580 Kokkos::abort(
"The element type is not yet supported by the portable "
581 "matrix-free module.");
598 const int q_point)
const
601 if constexpr (n_components_ == 1)
603 return shared_data->values(q_point, 0);
608 for (
unsigned int c = 0; c < n_components; ++c)
609 result[c] = shared_data->values(q_point, c);
630 if constexpr (n_components_ == 1)
632 return shared_data->values(dof_index, 0);
637 for (
unsigned int c = 0; c < n_components; ++c)
638 result[c] = shared_data->values(dof_index, c);
655 Assert(precomputed_data->JxW.size() > 0,
656 ExcMessage(
"submit_value() requires precomputed JxW"));
657 const Number JxW = JxW_value(q_point);
658 if constexpr (n_components_ == 1)
660 shared_data->values(q_point, 0) = value * JxW;
664 for (
unsigned int c = 0; c < n_components; ++c)
665 shared_data->values(q_point, c) = value[c] * JxW;
681 if constexpr (n_components_ == 1)
683 shared_data->values(dof_index, 0) = value;
687 for (
unsigned int c = 0; c < n_components; ++c)
688 shared_data->values(dof_index, c) = value[c];
703 Number>::gradient_type
708 Assert(precomputed_data->inv_jacobian.size() > 0,
709 ExcMessage(
"get_gradient() requires precomputed inv_jacobian"));
712 const unsigned int inv_jac_idx = inv_jacobian_index(q_point);
715 if constexpr (n_components_ == 1)
717 for (
unsigned int d = 0; d < dim; ++d)
718 grad[d] = precomputed_data->inv_jacobian(inv_jac_idx, d, d) *
719 shared_data->gradients(q_point, d, 0);
723 for (
unsigned int c = 0; c < n_components; ++c)
724 for (
unsigned int d = 0; d < dim; ++d)
725 grad[c][d] = precomputed_data->inv_jacobian(inv_jac_idx, d, d) *
726 shared_data->gradients(q_point, d, c);
729 else if constexpr (n_components_ == 1)
731 for (
unsigned int d_1 = 0; d_1 < dim; ++d_1)
734 for (
unsigned int d_2 = 0; d_2 < dim; ++d_2)
735 tmp += precomputed_data->inv_jacobian(inv_jac_idx, d_2, d_1) *
736 shared_data->gradients(q_point, d_2, 0);
742 for (
unsigned int c = 0; c < n_components; ++c)
743 for (
unsigned int d_1 = 0; d_1 < dim; ++d_1)
746 for (
unsigned int d_2 = 0; d_2 < dim; ++d_2)
747 tmp += precomputed_data->inv_jacobian(inv_jac_idx, d_2, d_1) *
748 shared_data->gradients(q_point, d_2, c);
768 Assert(precomputed_data->inv_jacobian.size() > 0,
769 ExcMessage(
"submit_gradient() requires precomputed inv_jacobian"));
770 Assert(precomputed_data->JxW.size() > 0,
771 ExcMessage(
"submit_gradient() requires precomputed JxW"));
773 const unsigned int inv_jac_idx = inv_jacobian_index(q_point);
774 const Number JxW = JxW_value(q_point);
777 if constexpr (n_components_ == 1)
779 for (
unsigned int d = 0; d < dim; ++d)
780 shared_data->gradients(q_point, d, 0) =
781 precomputed_data->inv_jacobian(inv_jac_idx, d, d) *
786 for (
unsigned int c = 0; c < n_components; ++c)
787 for (
unsigned int d = 0; d < dim; ++d)
788 shared_data->gradients(q_point, d, c) =
789 precomputed_data->inv_jacobian(inv_jac_idx, d, d) *
790 gradient[c][d] * JxW;
793 else if constexpr (n_components_ == 1)
795 for (
unsigned int d_1 = 0; d_1 < dim; ++d_1)
798 for (
unsigned int d_2 = 0; d_2 < dim; ++d_2)
799 tmp += precomputed_data->inv_jacobian(inv_jac_idx, d_1, d_2) *
801 shared_data->gradients(q_point, d_1, 0) = tmp * JxW;
806 for (
unsigned int c = 0; c < n_components; ++c)
807 for (
unsigned int d_1 = 0; d_1 < dim; ++d_1)
810 for (
unsigned int d_2 = 0; d_2 < dim; ++d_2)
811 tmp += precomputed_data->inv_jacobian(inv_jac_idx, d_1, d_2) *
813 shared_data->gradients(q_point, d_1, c) = tmp * JxW;
830 Assert(n_components_ == dim,
831 ExcMessage(
"Function get_symmetric_gradient() only works when the "
832 "number of components and the number of dimensions are "
850 Assert(n_components_ == dim,
851 ExcMessage(
"Function get_divergence() only works when the "
852 "number of components and the number of dimensions are "
854 Assert(precomputed_data->inv_jacobian.size() > 0,
855 ExcMessage(
"get_divergence() requires precomputed inv_jacobian"));
857 const unsigned int inv_jac_idx = inv_jacobian_index(q_point);
858 Number divergence = 0.;
859 for (
unsigned int c = 0; c < dim; ++c)
860 for (
unsigned int d = 0; d < dim; ++d)
861 divergence += precomputed_data->inv_jacobian(inv_jac_idx, d, c) *
862 shared_data->gradients(q_point, d, c);
878 Assert(n_components_ == dim,
879 ExcMessage(
"Function submit_divergence() only works when the "
880 "number of components and the number of dimensions are "
882 Assert(precomputed_data->inv_jacobian.size() > 0,
883 ExcMessage(
"submit_divergence() requires precomputed inv_jacobian"));
884 Assert(precomputed_data->JxW.size() > 0,
885 ExcMessage(
"submit_divergence() requires precomputed JxW"));
887 const unsigned int inv_jac_idx = inv_jacobian_index(q_point);
888 const Number JxW = JxW_value(q_point);
889 for (
unsigned int c = 0; c < dim; ++c)
890 for (
unsigned int d_1 = 0; d_1 < dim; ++d_1)
891 shared_data->gradients(q_point, d_1, c) =
892 precomputed_data->inv_jacobian(inv_jac_idx, d_1, c) * div_in * JxW;
908 Assert(n_components_ == dim,
909 ExcMessage(
"Function submit_symmetric_gradient() only works when "
910 "the number of components and the number of dimensions "
912 Assert(precomputed_data->inv_jacobian.size() > 0,
914 "submit_symmetric_gradient() requires precomputed inv_jacobian"));
915 Assert(precomputed_data->JxW.size() > 0,
916 ExcMessage(
"submit_symmetric_gradient() requires precomputed JxW"));
918 const unsigned int inv_jac_idx = inv_jacobian_index(q_point);
919 const Number JxW = JxW_value(q_point);
920 for (
unsigned int c = 0; c < dim; ++c)
921 for (
unsigned int d_1 = 0; d_1 < dim; ++d_1)
924 for (
unsigned int d_2 = 0; d_2 < dim; ++d_2)
925 tmp += precomputed_data->inv_jacobian(inv_jac_idx, d_1, d_2) *
927 shared_data->gradients(q_point, d_1, c) = tmp * JxW;
939 constexpr unsigned int
friend class FEEvaluation
unsigned int n_components() const
unsigned int mapping_data_offset
int get_current_cell_index()
static constexpr unsigned int n_q_points
SharedData< dim, Number > * shared_data
void integrate(const EvaluationFlags::EvaluationFlags integration_flag)
static constexpr unsigned int dimension
const data_type * get_matrix_free_data()
const MatrixFree< dim, Number >::Data * data
static constexpr unsigned int n_components
void submit_gradient(const gradient_type &gradient, const int q_point)
void submit_divergence(const Number &div_in, const int q_point)
void evaluate(const EvaluationFlags::EvaluationFlags evaluate_flag)
void read_dof_values(const DeviceVector< Number > &src)
Number get_divergence(const int q_point) const
void distribute_local_to_global(DeviceVector< Number > &dst) const
static constexpr unsigned int tensor_dofs_per_cell
void submit_value(const value_type &val_in, const int q_point)
const MatrixFree< dim, Number >::PrecomputedData * precomputed_data
unsigned int inv_jacobian_index(const int q_point) const
const unsigned int dof_handler_index
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
SymmetricTensor< 2, dim, Number > get_symmetric_gradient(const int q_point) const
::internal::MatrixFreeFunctions::GeometryType cell_type
std::conditional_t<(n_components_==1), Number, Tensor< 1, n_components_, Number > > value_type
void submit_dof_value(const value_type &value, const int dof_index)
value_type get_value(const int q_point) const
void submit_symmetric_gradient(const SymmetricTensor< 2, dim, Number > &sym_grad, const int q_point)
static constexpr unsigned int tensor_dofs_per_component
typename MatrixFree< dim, Number >::Data data_type
gradient_type get_gradient(const int q_point) const
Number JxW_value(const int q_point) const
value_type get_dof_value(const int dof_index) const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_HOST_DEVICE
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
EvaluationFlags
The EvaluationFlags enum.
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
constexpr bool use_collocation_evaluation(const unsigned int fe_degree, const unsigned int n_q_points_1d)
Kokkos::View< Number *, MemorySpace::Default::kokkos_space > DeviceVector
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
constexpr T pow(const T base, const int iexp)
static void integrate(const unsigned int dof_handler_index, const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, const typename MatrixFree< dim, Number >::Data *data)
static void evaluate(const unsigned int dof_handler_index, const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const typename MatrixFree< dim, Number >::Data *data)
static void evaluate(const unsigned int dof_handler_index, const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const typename MatrixFree< dim, Number >::Data *data)
static void integrate(const unsigned int dof_handler_index, const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, const typename MatrixFree< dim, Number >::Data *data)
constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)