14#ifndef dealii_matrix_free_fe_evaluation_h
15#define dealii_matrix_free_fe_evaluation_h
92 typename VectorizedArrayType>
99 std::conditional_t<n_components_ == 1,
106 n_components_ == dim,
114 n_components_ == dim,
119 static constexpr unsigned int n_lanes = VectorizedArrayType::size();
158 template <
typename VectorType>
161 const VectorType &src,
162 const unsigned int first_index = 0,
163 const std::bitset<n_lanes> &mask = std::bitset<n_lanes>().flip());
196 template <
typename VectorType>
199 const VectorType &src,
200 const unsigned int first_index = 0,
201 const std::bitset<n_lanes> &mask = std::bitset<n_lanes>().flip());
234 template <
typename VectorType>
238 const unsigned int first_index = 0,
239 const std::bitset<n_lanes> &mask = std::bitset<n_lanes>().flip())
const;
279 template <
typename VectorType>
283 const unsigned int first_index = 0,
284 const std::bitset<n_lanes> &mask = std::bitset<n_lanes>().flip())
const;
289 template <
typename VectorType>
293 const unsigned int first_index = 0,
294 const std::bitset<n_lanes> &mask = std::bitset<n_lanes>().flip())
const;
370 typename = std::enable_if_t<n_components == n_components_local>>
373 const unsigned int q_point);
424 template <
int dim_ = dim,
425 typename = std::enable_if_t<dim_ == 1 && n_components == dim_>>
428 const unsigned int q_point);
447 const unsigned int q_point);
523 const unsigned int q_point);
532 template <
int dim_ = dim,
typename = std::enable_if_t<n_components_ == dim_>>
551 template <
int dim_ = dim,
typename = std::enable_if_t<n_components_ == dim_>>
554 const unsigned int q_point);
564 template <
int dim_ = dim,
typename = std::enable_if_t<n_components_ == dim_>>
583 template <
int dim_ = dim,
typename = std::enable_if_t<n_components_ == dim_>>
587 const unsigned int q_point);
597 template <
int dim_ = dim,
598 typename = std::enable_if_t<n_components_ == dim_ && dim_ != 1>>
615 template <
int dim_ = dim,
616 typename = std::enable_if_t<n_components_ == dim_ && dim != 1>>
658 const unsigned int dof_handler_index,
661 const unsigned int fe_degree,
662 const unsigned int n_q_points,
666 const unsigned int face_type);
740 template <
typename VectorType,
typename VectorOperation>
744 const std::array<VectorType *, n_components_> &vectors,
747 n_components_> &vectors_sm,
748 const std::bitset<n_lanes> &mask,
749 const bool apply_constraints =
true)
const;
758 template <
typename VectorType,
typename VectorOperation>
762 const std::array<VectorType *, n_components_> &vectors,
765 n_components_> &vectors_sm,
766 const std::bitset<n_lanes> &mask)
const;
775 template <
typename VectorType,
typename VectorOperation>
779 const std::array<VectorType *, n_components_> &vectors)
const;
1374 typename VectorizedArrayType>
1379 VectorizedArrayType>
1382 std::is_same_v<Number, typename VectorizedArrayType::value_type>,
1383 "Type of Number and of VectorizedArrayType do not match.");
1425 static constexpr unsigned int n_lanes = VectorizedArrayType::size();
1510 const unsigned int dof_handler_index = 0,
1524 const std::pair<unsigned int, unsigned int> &range,
1525 const unsigned int dof_handler_index = 0,
1636 template <
bool level_dof_access>
1658 const unsigned int given_n_q_points_1d);
1701 template <
typename VectorType>
1731 VectorizedArrayType *values_array,
1732 const bool sum_into_values =
false);
1747 template <
typename VectorType>
1750 VectorType &output_vector);
1834 int n_q_points_1d = fe_degree + 1,
1835 int n_components_ = 1,
1836 typename Number = double,
1842 VectorizedArrayType>
1845 std::is_same_v<Number, typename VectorizedArrayType::value_type>,
1846 "Type of Number and of VectorizedArrayType do not match.");
1888 static constexpr unsigned int n_lanes = VectorizedArrayType::size();
1990 const unsigned int dof_handler_index = 0,
2006 const std::pair<unsigned int, unsigned int> &range,
2008 const unsigned int dof_handler_index = 0,
2023 reinit(
const unsigned int face_batch_number);
2033 reinit(
const unsigned int cell_batch_number,
const unsigned int face_number);
2040 const unsigned int given_n_q_points_1d);
2104 template <
typename VectorType>
2120 const bool sum_into_values =
false);
2133 VectorizedArrayType *values_array,
2134 const bool sum_into_values =
false);
2151 const bool sum_into_values =
false);
2159 VectorizedArrayType *values_array,
2160 const bool sum_into_values =
false);
2173 template <
typename VectorType>
2176 VectorType &output_vector);
2181 template <
typename VectorType>
2184 const bool integrate_gradients,
2185 VectorType &output_vector);
2261 namespace MatrixFreeFunctions
2265 template <
int dim,
int degree>
2274 template <
int degree>
2277 static constexpr unsigned int value = degree + 1;
2293 template <
bool is_face,
2296 typename VectorizedArrayType>
2299 extract_initialization_data(
2301 const unsigned int dof_handler_index,
2302 const unsigned int first_selected_component,
2303 const unsigned int quadrature_index,
2304 const unsigned int fe_degree,
2305 const unsigned int n_q_points,
2306 const unsigned int active_fe_index_given,
2307 const unsigned int active_quad_index_given,
2308 const unsigned int face_type)
2311 InitializationData init_data;
2315 &internal::MatrixFreeFunctions::
2316 MappingInfoCellsOrFaces<dim, Number, is_face, VectorizedArrayType>::get(
2324 active_fe_index_given :
2330 active_quad_index_given :
2331 std::min<unsigned int>(
2334 (is_face ? std::max<unsigned int>(1, dim - 1) : 1) -
2363 typename VectorizedArrayType>
2368 VectorizedArrayType>::
2371 const unsigned int dof_handler_index,
2372 const unsigned int first_selected_component,
2373 const unsigned int quadrature_index,
2374 const unsigned int fe_degree,
2375 const unsigned int n_q_points,
2376 const bool is_interior_face,
2377 const unsigned int active_fe_index,
2378 const unsigned int active_quad_index,
2379 const unsigned int face_type)
2381 internal::extract_initialization_data<is_face>(matrix_free,
2383 first_selected_component,
2392 first_selected_component)
2393 , scratch_data_array(matrix_free.acquire_scratch_data())
2394 , matrix_free(&matrix_free)
2396 this->set_data_pointers(scratch_data_array, n_components_);
2398 this->dof_info->start_components.back() == 1 ||
2399 static_cast<int>(n_components_) <=
2401 this->dof_info->start_components
2402 [this->dof_info->component_to_base_index[first_selected_component] +
2404 first_selected_component,
2406 "You tried to construct a vector-valued evaluator with " +
2407 std::to_string(n_components) +
2408 " components. However, "
2409 "the current base element has only " +
2411 this->dof_info->start_components
2412 [this->dof_info->component_to_base_index[first_selected_component] +
2414 first_selected_component) +
2415 " components left when starting from local element index " +
2417 first_selected_component -
2418 this->dof_info->start_components
2419 [this->dof_info->component_to_base_index[first_selected_component]]) +
2420 " (global index " + std::to_string(first_selected_component) +
")"));
2432 typename VectorizedArrayType>
2437 VectorizedArrayType>::
2443 const unsigned int first_selected_component,
2447 other->mapped_geometry->get_quadrature() == quadrature ?
2448 other->mapped_geometry :
2450 MappingDataOnTheFly<dim, VectorizedArrayType>>(
2455 first_selected_component)
2456 , scratch_data_array(new
AlignedVector<VectorizedArrayType>())
2457 , matrix_free(nullptr)
2459 const unsigned int base_element_number =
2463 first_selected_component >=
2465 ExcMessage(
"The underlying element must at least contain as many "
2466 "components as requested by this class"));
2467 (void)base_element_number;
2471 Quadrature<(is_face ? dim - 1 : dim)>(quadrature),
2473 fe.component_to_base_index(first_selected_component).
first);
2475 this->set_data_pointers(scratch_data_array, n_components_);
2484 typename VectorizedArrayType>
2489 VectorizedArrayType>::
2494 VectorizedArrayType> &other)
2496 , scratch_data_array(other.matrix_free == nullptr ?
2498 other.matrix_free->acquire_scratch_data())
2499 , matrix_free(other.matrix_free)
2501 if (other.matrix_free ==
nullptr)
2508 this->mapped_geometry =
2509 std::make_shared<internal::MatrixFreeFunctions::
2510 MappingDataOnTheFly<dim, VectorizedArrayType>>(
2515 if constexpr (is_face ==
false)
2516 this->mapping_data = &this->mapped_geometry->get_data_storage();
2520 "face evaluators is not currently "
2526 this->mapped_geometry->get_data_storage().jacobians[0].begin();
2528 this->mapped_geometry->get_data_storage().JxW_values.begin();
2529 this->jacobian_gradients =
2530 this->mapped_geometry->get_data_storage().jacobian_gradients[0].begin();
2531 this->jacobian_gradients_non_inverse =
2532 this->mapped_geometry->get_data_storage()
2533 .jacobian_gradients_non_inverse[0]
2536 this->mapped_geometry->get_data_storage().quadrature_points.begin();
2539 this->set_data_pointers(scratch_data_array, n_components_);
2548 typename VectorizedArrayType>
2553 VectorizedArrayType> &
2559 VectorizedArrayType> &other)
2562 if (matrix_free ==
nullptr)
2565 delete scratch_data_array;
2574 matrix_free = other.matrix_free;
2576 if (other.matrix_free ==
nullptr)
2584 this->mapped_geometry =
2585 std::make_shared<internal::MatrixFreeFunctions::
2586 MappingDataOnTheFly<dim, VectorizedArrayType>>(
2591 if constexpr (is_face ==
false)
2592 this->mapping_data = &this->mapped_geometry->get_data_storage();
2596 "face evaluators is not currently "
2601 this->mapped_geometry->get_data_storage().jacobians[0].begin();
2603 this->mapped_geometry->get_data_storage().JxW_values.begin();
2604 this->jacobian_gradients =
2605 this->mapped_geometry->get_data_storage().jacobian_gradients[0].begin();
2606 this->jacobian_gradients_non_inverse =
2607 this->mapped_geometry->get_data_storage()
2608 .jacobian_gradients_non_inverse[0]
2611 this->mapped_geometry->get_data_storage().quadrature_points.begin();
2618 this->set_data_pointers(scratch_data_array, n_components_);
2629 typename VectorizedArrayType>
2634 VectorizedArrayType>::~FEEvaluationBase()
2636 if (matrix_free !=
nullptr)
2647 delete scratch_data_array;
2658 typename VectorizedArrayType>
2663 Assert(matrix_free !=
nullptr,
2665 "FEEvaluation was not initialized with a MatrixFree object!"));
2666 return *matrix_free;
2675 template <
typename VectorType,
bool>
2676 struct ConstBlockVectorSelector;
2678 template <
typename VectorType>
2679 struct ConstBlockVectorSelector<
VectorType, true>
2681 using BaseVectorType =
const typename VectorType::BlockType;
2684 template <
typename VectorType>
2685 struct ConstBlockVectorSelector<
VectorType, false>
2687 using BaseVectorType =
typename VectorType::BlockType;
2693 template <
typename VectorType,
bool>
2694 struct BlockVectorSelector;
2696 template <
typename VectorType>
2699 using BaseVectorType =
typename ConstBlockVectorSelector<
2701 std::is_const_v<VectorType>>::BaseVectorType;
2703 static BaseVectorType *
2704 get_vector_component(VectorType &vec,
const unsigned int component)
2707 return &vec.block(component);
2711 template <
typename VectorType>
2712 struct BlockVectorSelector<
VectorType, false>
2716 static BaseVectorType *
2717 get_vector_component(VectorType &vec,
const unsigned int component)
2736 template <
typename VectorType>
2737 struct BlockVectorSelector<
std::vector<VectorType>, false>
2741 static BaseVectorType *
2742 get_vector_component(std::vector<VectorType> &vec,
2743 const unsigned int component)
2750 template <
typename VectorType>
2751 struct BlockVectorSelector<
const std::vector<VectorType>, false>
2755 static const BaseVectorType *
2756 get_vector_component(
const std::vector<VectorType> &vec,
2757 const unsigned int component)
2764 template <
typename VectorType>
2765 struct BlockVectorSelector<
std::vector<VectorType *>, false>
2769 static BaseVectorType *
2770 get_vector_component(std::vector<VectorType *> &vec,
2771 const unsigned int component)
2778 template <
typename VectorType>
2779 struct BlockVectorSelector<
const std::vector<VectorType *>, false>
2783 static const BaseVectorType *
2784 get_vector_component(
const std::vector<VectorType *> &vec,
2785 const unsigned int component)
2792 template <
typename VectorType, std::
size_t N>
2793 struct BlockVectorSelector<
std::array<VectorType *, N>, false>
2797 static BaseVectorType *
2798 get_vector_component(std::array<VectorType *, N> &vec,
2799 const unsigned int component)
2813 typename VectorizedArrayType>
2814template <
typename VectorType,
typename VectorOperation>
2819 const std::array<VectorType *, n_components_> &src,
2822 n_components_> &src_sm,
2823 const std::bitset<n_lanes> &
mask,
2824 const bool apply_constraints)
const
2829 if (this->matrix_free ==
nullptr)
2831 read_write_operation_global(operation, src);
2838 if (this->n_fe_components == 1)
2839 for (
unsigned int comp = 0; comp < n_components; ++comp)
2841 Assert(src[comp] !=
nullptr,
2842 ExcMessage(
"The finite element underlying this FEEvaluation "
2843 "object is scalar, but you requested " +
2844 std::to_string(n_components) +
2845 " components via the template argument in "
2846 "FEEvaluation. In that case, you must pass an "
2847 "std::vector<VectorType> or a BlockVector to " +
2848 "read_dof_values and distribute_local_to_global."));
2860 const bool accesses_exterior_dofs =
2861 this->dof_access_index ==
2863 this->is_interior_face() ==
false;
2873 bool is_contiguous =
true;
2875 if (accesses_exterior_dofs)
2877 const std::array<unsigned int, n_lanes> &cells = this->get_cell_ids();
2878 const unsigned int n_filled_lanes =
2883 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2884 if (
mask[v] ==
true &&
2887 [cells[v] / n_lanes] <
2890 is_contiguous = false;
2894 this->dof_access_index :
2895 internal::MatrixFreeFunctions::DoFInfo::dof_access_cell]
2896 [this->cell] <
internal::MatrixFreeFunctions::DoFInfo::
2899 is_contiguous =
false;
2904 read_write_operation_contiguous(operation, src, src_sm,
mask);
2911 std::array<unsigned int, n_lanes> cells = this->get_cell_ids();
2913 const bool masking_is_active =
mask.count() < n_lanes;
2914 if (masking_is_active)
2915 for (
unsigned int v = 0; v < n_lanes; ++v)
2916 if (
mask[v] ==
false)
2919 std::bool_constant<internal::is_vectorizable<VectorType, Number>::value>
2922 const bool use_vectorized_path =
2923 !(masking_is_active || accesses_exterior_dofs);
2925 const std::size_t dofs_per_component = this->
data->dofs_per_component_on_cell;
2929 [is_face ? this->dof_access_index :
2930 internal::MatrixFreeFunctions::DoFInfo::dof_access_cell]
2931 [this->cell] ==
internal::MatrixFreeFunctions::DoFInfo::
2932 IndexStorageVariants::interleaved &&
2933 use_vectorized_path)
2935 const unsigned int *dof_indices =
2937 dof_info.
row_starts[this->cell * this->n_fe_components * n_lanes]
2941 [this->first_selected_component] *
2944 std::array<typename VectorType::value_type *, n_components> src_ptrs;
2945 if (n_components == 1 || this->n_fe_components == 1)
2946 for (
unsigned int comp = 0; comp < n_components; ++comp)
2948 const_cast<typename VectorType::value_type *
>(src[comp]->
begin());
2951 const_cast<typename VectorType::value_type *
>(src[0]->begin());
2953 if (n_components == 1 || this->n_fe_components == 1)
2954 for (
unsigned int i = 0; i < dofs_per_component;
2955 ++i, dof_indices += n_lanes)
2956 for (
unsigned int comp = 0; comp < n_components; ++comp)
2957 operation.process_dof_gather(
2962 this->values_dofs[comp * dofs_per_component + i],
2965 for (
unsigned int comp = 0; comp < n_components; ++comp)
2966 for (
unsigned int i = 0; i < dofs_per_component;
2967 ++i, dof_indices += n_lanes)
2968 operation.process_dof_gather(
2973 this->values_dofs[comp * dofs_per_component + i],
2978 std::array<VectorizedArrayType *, n_components> values_dofs;
2979 for (
unsigned int c = 0; c < n_components; ++c)
2980 values_dofs[c] =
const_cast<VectorizedArrayType *
>(this->values_dofs) +
2981 c * dofs_per_component;
2985 std::array<const unsigned int *, n_lanes> dof_indices;
2986 dof_indices.fill(
nullptr);
2991 bool has_constraints =
false;
2992 const unsigned int n_components_read =
2993 this->n_fe_components > 1 ? n_components : 1;
2997 for (
unsigned int v = 0; v < n_lanes; ++v)
3003 const std::pair<unsigned int, unsigned int> *my_index_start =
3004 &dof_info.
row_starts[cells[v] * this->n_fe_components +
3005 this->first_selected_component];
3010 if (my_index_start[n_components_read].
second !=
3011 my_index_start[0].
second)
3012 has_constraints =
true;
3015 dof_info.
dof_indices.data() + my_index_start[0].first;
3020 for (
unsigned int v = 0; v < n_lanes; ++v)
3025 const std::pair<unsigned int, unsigned int> *my_index_start =
3026 &dof_info.
row_starts[cells[v] * this->n_fe_components +
3027 this->first_selected_component];
3028 if (my_index_start[n_components_read].
second !=
3029 my_index_start[0].
second)
3030 has_constraints =
true;
3033 my_index_start[0].
first ||
3036 my_index_start[0].
first,
3039 dof_info.
dof_indices.data() + my_index_start[0].first;
3043 for (
unsigned int comp = 0; comp < n_components; ++comp)
3044 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3045 operation.process_empty(values_dofs[comp][i]);
3049 if (!has_constraints && apply_constraints)
3051 if (n_components == 1 || this->n_fe_components == 1)
3053 for (
unsigned int v = 0; v < n_lanes; ++v)
3058 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3060 for (
unsigned int comp = 0; comp < n_components; ++comp)
3061 operation.process_dof(dof_indices[v][i],
3063 values_dofs[comp][i][v]);
3068 for (
unsigned int comp = 0; comp < n_components; ++comp)
3069 for (
unsigned int v = 0; v < n_lanes; ++v)
3074 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3075 if (dof_indices[v][comp * dofs_per_component + i] !=
3077 operation.process_dof(
3078 dof_indices[v][comp * dofs_per_component + i],
3080 values_dofs[comp][i][v]);
3092 for (
unsigned int v = 0; v < n_lanes; ++v)
3098 const unsigned int cell_dof_index =
3099 cell_index * this->n_fe_components + this->first_selected_component;
3100 unsigned int index_indicators =
3102 unsigned int next_index_indicators =
3103 dof_info.
row_starts[cell_dof_index + 1].second;
3107 if (apply_constraints ==
false &&
3115 [this->first_selected_component] +
3117 next_index_indicators = index_indicators;
3120 if (n_components == 1 || this->n_fe_components == 1)
3122 unsigned int ind_local = 0;
3123 for (; index_indicators != next_index_indicators; ++index_indicators)
3125 const std::pair<unsigned short, unsigned short> indicator =
3128 for (
unsigned int j = 0; j < indicator.first; ++j)
3130 for (
unsigned int comp = 0; comp < n_components; ++comp)
3131 operation.process_dof(dof_indices[v][j],
3133 values_dofs[comp][ind_local + j][v]);
3135 ind_local += indicator.first;
3136 dof_indices[v] += indicator.first;
3141 for (
unsigned int comp = 0; comp < n_components; ++comp)
3142 operation.pre_constraints(values_dofs[comp][ind_local][v],
3149 for (; data_val != end_pool; ++data_val, ++dof_indices[v])
3151 for (
unsigned int comp = 0; comp < n_components; ++comp)
3152 operation.process_constraint(*dof_indices[v],
3157 for (
unsigned int comp = 0; comp < n_components; ++comp)
3158 operation.post_constraints(
value[comp],
3159 values_dofs[comp][ind_local][v]);
3165 for (; ind_local < dofs_per_component; ++dof_indices[v], ++ind_local)
3167 for (
unsigned int comp = 0; comp < n_components; ++comp)
3168 operation.process_dof(*dof_indices[v],
3170 values_dofs[comp][ind_local][v]);
3179 for (
unsigned int comp = 0; comp < n_components; ++comp)
3181 unsigned int ind_local = 0;
3184 for (; index_indicators != next_index_indicators;
3187 const std::pair<unsigned short, unsigned short> indicator =
3191 for (
unsigned int j = 0; j < indicator.first; ++j)
3193 operation.process_dof(
3196 values_dofs[comp][ind_local + j][v]);
3197 ind_local += indicator.first;
3198 dof_indices[v] += indicator.first;
3203 operation.pre_constraints(values_dofs[comp][ind_local][v],
3211 for (; data_val != end_pool; ++data_val, ++dof_indices[v])
3213 operation.process_constraint(*dof_indices[v],
3218 operation.post_constraints(
value,
3219 values_dofs[comp][ind_local][v]);
3226 for (; ind_local < dofs_per_component;
3227 ++dof_indices[v], ++ind_local)
3231 operation.process_dof(*dof_indices[v],
3233 values_dofs[comp][ind_local][v]);
3236 if (apply_constraints ==
true && comp + 1 < n_components)
3237 next_index_indicators =
3238 dof_info.
row_starts[cell_dof_index + comp + 2].second;
3250 typename VectorizedArrayType>
3251template <
typename VectorType,
typename VectorOperation>
3256 const std::array<VectorType *, n_components_> &src)
const
3260 const std::size_t dofs_per_component = this->
data->dofs_per_component_on_cell;
3261 unsigned int index = this->first_selected_component * dofs_per_component;
3262 for (
unsigned int comp = 0; comp < n_components; ++comp)
3264 for (
unsigned int i = 0; i < dofs_per_component; ++i, ++
index)
3266 operation.process_empty(
3267 this->values_dofs[comp * dofs_per_component + i]);
3268 operation.process_dof_global(
3269 local_dof_indices[this->
data->lexicographic_numbering[index]],
3271 this->values_dofs[comp * dofs_per_component + i][0]);
3282 typename VectorizedArrayType>
3283template <
typename VectorType,
typename VectorOperation>
3288 const std::array<VectorType *, n_components_> &src,
3291 n_components_> &vectors_sm,
3292 const std::bitset<n_lanes> &
mask)
const
3301 std::bool_constant<internal::is_vectorizable<VectorType, Number>::value>
3304 is_face ? this->dof_access_index :
3306 const unsigned int n_active_lanes =
mask.count();
3309 const std::vector<unsigned int> &dof_indices_cont =
3312 const std::size_t dofs_per_component = this->
data->dofs_per_component_on_cell;
3313 std::array<VectorizedArrayType *, n_components> values_dofs{{
nullptr}};
3314 for (
unsigned int c = 0; c < n_components; ++c)
3315 values_dofs[c] =
const_cast<VectorizedArrayType *
>(this->values_dofs) +
3316 c * dofs_per_component;
3320 const bool accesses_exterior_dofs =
3321 this->dof_access_index ==
3323 this->is_interior_face() ==
false;
3332 const bool separate_vectors =
3333 (n_components == 1 || this->n_fe_components == 1);
3339 interleaved_contiguous &&
3340 n_active_lanes == n_lanes && !accesses_exterior_dofs)
3342 const unsigned int dof_index =
3343 dof_indices_cont[this->cell * n_lanes] +
3346 [this->first_selected_component] *
3348 if (separate_vectors)
3349 for (
unsigned int comp = 0; comp < n_components; ++comp)
3350 operation.process_dofs_vectorized(dofs_per_component,
3356 operation.process_dofs_vectorized(dofs_per_component * n_components,
3364 const std::array<unsigned int, n_lanes> &cells = this->get_cell_or_face_ids();
3368 const unsigned int n_filled_lanes =
3371 const bool use_vectorized_path = n_filled_lanes == n_lanes &&
3372 n_active_lanes == n_lanes &&
3373 !accesses_exterior_dofs;
3375 if (vectors_sm[0] !=
nullptr)
3377 const auto compute_vector_ptrs = [&](
const unsigned int comp) {
3378 std::array<typename VectorType::value_type *, n_lanes> vector_ptrs{
3381 const auto upper_bound =
3382 std::min<unsigned int>(n_filled_lanes, n_lanes);
3383 for (
unsigned int v = 0; v < upper_bound; ++v)
3385 if (
mask[v] ==
false)
3387 vector_ptrs[v] =
nullptr;
3407 vector_ptrs[v] =
const_cast<typename VectorType::value_type *
>(
3408 vectors_sm[comp]->operator[](temp.first).
data() + temp.second +
3410 [this->active_fe_index][this->first_selected_component]);
3412 vector_ptrs[v] =
nullptr;
3414 for (
unsigned int v = n_filled_lanes; v < n_lanes; ++v)
3415 vector_ptrs[v] =
nullptr;
3420 if (use_vectorized_path)
3429 const unsigned int n_blocks = separate_vectors ? n_components : 1;
3430 const unsigned int block_size = separate_vectors ?
3431 dofs_per_component :
3432 dofs_per_component * n_components;
3433 for (
unsigned int comp = 0; comp <
n_blocks; ++comp)
3436 compute_vector_ptrs(separate_vectors ? comp : 0);
3437 operation.process_dofs_vectorized_transpose(block_size,
3446 for (
unsigned int comp = 0; comp < n_components; ++comp)
3448 auto vector_ptrs = compute_vector_ptrs(separate_vectors ? comp : 0);
3450 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3451 operation.process_empty(values_dofs[comp][i]);
3456 const unsigned int comp_offset =
3457 separate_vectors ? 0 : comp * dofs_per_component;
3458 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3459 if (
mask[v] ==
true)
3460 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3461 operation.process_dof(vector_ptrs[v][i + comp_offset],
3462 values_dofs[comp][i][v]);
3467 std::array<unsigned int, n_lanes> dof_indices{
3470 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3474 if (
mask[v] ==
true)
3476 dof_indices_cont[cells[v]] +
3479 [this->first_selected_component] *
3485 if (use_vectorized_path)
3491 if (separate_vectors)
3492 for (
unsigned int comp = 0; comp < n_components; ++comp)
3493 operation.process_dofs_vectorized_transpose(dofs_per_component,
3499 operation.process_dofs_vectorized_transpose(dofs_per_component *
3508 interleaved_contiguous_strided)
3510 std::array<typename VectorType::value_type *, n_components> src_ptrs{
3512 if (separate_vectors)
3513 for (
unsigned int comp = 0; comp < n_components; ++comp)
3514 src_ptrs[comp] =
const_cast<typename VectorType::value_type *
>(
3515 src[comp]->
begin());
3518 const_cast<typename VectorType::value_type *
>(src[0]->begin());
3520 if (separate_vectors)
3521 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3523 for (
unsigned int comp = 0; comp < n_components; ++comp)
3524 operation.process_dof_gather(dof_indices.data(),
3527 src_ptrs[comp] + i * n_lanes,
3528 values_dofs[comp][i],
3532 for (
unsigned int comp = 0; comp < n_components; ++comp)
3533 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3535 operation.process_dof_gather(
3538 (comp * dofs_per_component + i) * n_lanes,
3539 src_ptrs[0] + (comp * dofs_per_component + i) * n_lanes,
3540 values_dofs[comp][i],
3548 IndexStorageVariants::interleaved_contiguous_mixed_strides,
3550 std::array<typename VectorType::value_type *, n_components> src_ptrs{
3552 if (separate_vectors)
3553 for (
unsigned int comp = 0; comp < n_components; ++comp)
3554 src_ptrs[comp] =
const_cast<typename VectorType::value_type *
>(
3555 src[comp]->
begin());
3558 const_cast<typename VectorType::value_type *
>(src[0]->begin());
3560 const unsigned int *offsets =
3562 if (separate_vectors)
3563 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3565 for (
unsigned int comp = 0; comp < n_components; ++comp)
3566 operation.process_dof_gather(dof_indices.data(),
3570 values_dofs[comp][i],
3573 for (
unsigned int v = 0; v < n_lanes; ++v)
3574 dof_indices[v] += offsets[v];
3577 for (
unsigned int comp = 0; comp < n_components; ++comp)
3578 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3580 operation.process_dof_gather(dof_indices.data(),
3584 values_dofs[comp][i],
3587 for (
unsigned int v = 0; v < n_lanes; ++v)
3588 dof_indices[v] += offsets[v];
3593 for (
unsigned int comp = 0; comp < n_components; ++comp)
3595 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3596 operation.process_empty(values_dofs[comp][i]);
3597 if (accesses_exterior_dofs)
3599 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3600 if (
mask[v] ==
true)
3603 [ind][cells[v] / VectorizedArrayType::size()] ==
3607 if (separate_vectors)
3609 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3610 operation.process_dof(dof_indices[v] + i,
3612 values_dofs[comp][i][v]);
3616 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3617 operation.process_dof(dof_indices[v] + i +
3618 comp * dofs_per_component,
3620 values_dofs[comp][i][v]);
3625 const unsigned int offset =
3628 if (separate_vectors)
3630 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3631 operation.process_dof(dof_indices[v] + i * offset,
3633 values_dofs[comp][i][v]);
3637 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3638 operation.process_dof(
3640 (i + comp * dofs_per_component) * offset,
3642 values_dofs[comp][i][v]);
3653 if (separate_vectors)
3655 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3656 if (
mask[v] ==
true)
3657 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3658 operation.process_dof(dof_indices[v] + i,
3660 values_dofs[comp][i][v]);
3664 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3665 if (
mask[v] ==
true)
3666 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3667 operation.process_dof(dof_indices[v] + i +
3668 comp * dofs_per_component,
3670 values_dofs[comp][i][v]);
3675 const unsigned int *offsets =
3677 [ind][VectorizedArrayType::size() * this->cell];
3678 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3680 if (separate_vectors)
3681 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3683 if (
mask[v] ==
true)
3684 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3685 operation.process_dof(dof_indices[v] + i * offsets[v],
3687 values_dofs[comp][i][v]);
3691 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3692 if (
mask[v] ==
true)
3693 for (
unsigned int i = 0; i < dofs_per_component; ++i)
3694 operation.process_dof(
3696 (i + comp * dofs_per_component) * offsets[v],
3698 values_dofs[comp][i][v]);
3710 std::enable_if_t<!IsBlockVector<VectorType>::value,
VectorType> * =
nullptr>
3711 decltype(std::declval<VectorType>().begin())
3712 get_beginning(VectorType &vec)
3720 std::enable_if_t<IsBlockVector<VectorType>::value,
VectorType> * =
nullptr>
3721 typename VectorType::value_type *
3722 get_beginning(VectorType &)
3728 std::enable_if_t<has_shared_vector_data<VectorType>,
VectorType> * =
3730 const std::vector<ArrayView<const typename VectorType::value_type>> *
3731 get_shared_vector_data(VectorType *vec,
3732 const bool is_valid_mode_for_sm,
3733 const unsigned int active_fe_index,
3737 if (is_valid_mode_for_sm &&
3740 active_fe_index == 0)
3741 return &vec->shared_vector_data();
3747 std::enable_if_t<!has_shared_vector_data<VectorType>,
VectorType>
3749 const std::vector<ArrayView<const typename VectorType::value_type>> *
3750 get_shared_vector_data(VectorType *,
3758 template <
int n_components,
typename VectorType>
3760 std::array<
typename internal::BlockVectorSelector<
3765 const std::vector<
ArrayView<
const typename internal::BlockVectorSelector<
3769 get_vector_data(VectorType &src,
3770 const unsigned int first_index,
3771 const bool is_valid_mode_for_sm,
3772 const unsigned int active_fe_index,
3778 std::array<
typename internal::BlockVectorSelector<
3784 ArrayView<
const typename internal::BlockVectorSelector<
3790 for (
unsigned int d = 0;
d < n_components; ++
d)
3791 src_data.first[d] = internal::BlockVectorSelector<
3797 for (
unsigned int d = 0;
d < n_components; ++
d)
3798 src_data.second[d] = get_shared_vector_data(
3799 const_cast<typename internal::BlockVectorSelector<
3800 std::remove_const_t<VectorType>,
3802 *>(src_data.first[d]),
3803 is_valid_mode_for_sm,
3817 typename VectorizedArrayType>
3822 if (this->dof_info ==
nullptr ||
3824 this->dof_info->hanging_node_constraint_masks_comp.empty() ||
3825 this->dof_info->hanging_node_constraint_masks_comp
3826 [this->active_fe_index][this->first_selected_component] ==
false)
3829 std::array<internal::MatrixFreeFunctions::compressed_constraint_kind, n_lanes>
3830 constraint_mask{{internal::MatrixFreeFunctions::
3831 unconstrained_compressed_constraint_kind}};
3833 bool hn_available =
false;
3835 const std::array<unsigned int, n_lanes> &cells = this->get_cell_ids();
3837 for (
unsigned int v = 0; v < n_lanes; ++v)
3849 constraint_mask[v] =
mask;
3855 if (hn_available ==
false)
3860 this->
data->data.front().fe_degree,
3861 this->get_shape_info(),
3873 typename VectorizedArrayType>
3874template <
typename VectorType>
3878 const unsigned int first_index,
3879 const std::bitset<n_lanes> &
mask)
3881 const auto src_data = internal::get_vector_data<n_components_>(
3884 this->dof_info !=
nullptr &&
3885 this->dof_access_index ==
3887 this->active_fe_index,
3891 read_write_operation(reader, src_data.first, src_data.second,
mask,
true);
3893 apply_hanging_node_constraints(
false);
3897 this->dof_values_initialized =
true;
3907 typename VectorizedArrayType>
3908template <
typename VectorType>
3912 const unsigned int first_index,
3913 const std::bitset<n_lanes> &
mask)
3915 const auto src_data = internal::get_vector_data<n_components_>(
3918 this->dof_info !=
nullptr &&
3919 this->dof_access_index ==
3921 this->active_fe_index,
3925 read_write_operation(reader, src_data.first, src_data.second,
mask,
false);
3929 this->dof_values_initialized =
true;
3939 typename VectorizedArrayType>
3940template <
typename VectorType>
3944 const unsigned int first_index,
3945 const std::bitset<n_lanes> &
mask)
const
3949 Assert(this->dof_values_initialized ==
true,
3953 apply_hanging_node_constraints(
true);
3955 const auto dst_data = internal::get_vector_data<n_components_>(
3958 this->dof_info !=
nullptr &&
3959 this->dof_access_index ==
3961 this->active_fe_index,
3966 read_write_operation(distributor, dst_data.first, dst_data.second,
mask);
3975 typename VectorizedArrayType>
3976template <
typename VectorType>
3980 const unsigned int first_index,
3981 const std::bitset<n_lanes> &
mask)
const
3985 Assert(this->dof_values_initialized ==
true,
3989 const auto dst_data = internal::get_vector_data<n_components_>(
3992 this->dof_info !=
nullptr &&
3993 this->dof_access_index ==
3995 this->active_fe_index,
3999 read_write_operation(setter, dst_data.first, dst_data.second,
mask);
4008 typename VectorizedArrayType>
4009template <
typename VectorType>
4013 const unsigned int first_index,
4014 const std::bitset<n_lanes> &
mask)
const
4018 Assert(this->dof_values_initialized ==
true,
4022 const auto dst_data = internal::get_vector_data<n_components_>(
4025 this->dof_access_index ==
4027 this->active_fe_index,
4031 read_write_operation(setter, dst_data.first, dst_data.second,
mask,
false);
4044 typename VectorizedArrayType>
4055 if constexpr (n_components == 1)
4056 return this->values_dofs[dof];
4059 const std::size_t dofs = this->
data->dofs_per_component_on_cell;
4060 Tensor<1, n_components_, VectorizedArrayType> return_value;
4061 for (
unsigned int comp = 0; comp < n_components; ++comp)
4062 return_value[comp] = this->values_dofs[comp * dofs + dof];
4063 return return_value;
4073 typename VectorizedArrayType>
4081 get_value(
const unsigned int q_point)
const
4085 Assert(this->values_quad_initialized ==
true,
4090 if constexpr (n_components == 1)
4091 return this->values_quad[q_point];
4094 if (n_components == dim &&
4095 this->
data->element_type ==
4101 Assert(this->values_quad_initialized ==
true,
4106 Assert(this->J_value !=
nullptr,
4109 const std::size_t nqp = this->n_quadrature_points;
4117 const VectorizedArrayType inv_det =
4118 (dim == 2) ? this->jacobian[0][0][0] * this->jacobian[0][1][1] :
4119 this->jacobian[0][0][0] * this->jacobian[0][1][1] *
4120 this->jacobian[0][2][2];
4123 for (
unsigned int comp = 0; comp < n_components; ++comp)
4124 value_out[comp] = this->values_quad[comp * nqp + q_point] *
4125 jac[comp][comp] * inv_det;
4132 this->jacobian[q_point] :
4141 const VectorizedArrayType inv_det =
4142 (is_face && dim == 2 && this->get_face_no() < 2) ?
4146 for (
unsigned int comp = 0; comp < n_components; ++comp)
4148 value_out[comp] = this->values_quad[q_point] * jac[comp][0];
4149 for (
unsigned int e = 1;
e < dim; ++
e)
4151 this->values_quad[e * nqp + q_point] * jac[comp][e];
4152 value_out[comp] *= inv_det;
4157 else if (n_components == dim &&
4158 this->
data->element_type ==
4164 Assert(this->values_quad_initialized ==
true,
4169 Assert(this->J_value !=
nullptr,
4172 const std::size_t nqp = this->n_quadrature_points;
4184 for (
unsigned int comp = 0; comp < n_components; ++comp)
4185 value_out[comp] = this->values_quad[comp * nqp + q_point] *
4186 inv_transp_jac[comp][comp];
4193 this->jacobian[q_point] :
4197 for (
unsigned int comp = 0; comp < n_components; ++comp)
4200 this->values_quad[q_point] * inv_t_jac[comp][0];
4201 for (
unsigned int e = 1;
e < dim; ++
e)
4203 this->values_quad[e * nqp + q_point] * inv_t_jac[comp][e];
4210 const std::size_t nqp = this->n_quadrature_points;
4212 for (
unsigned int comp = 0; comp < n_components; ++comp)
4213 return_value[comp] = this->values_quad[comp * nqp + q_point];
4214 return return_value;
4225 typename VectorizedArrayType>
4231 VectorizedArrayType>::gradient_type
4237 Assert(this->gradients_quad_initialized ==
true,
4242 Assert(this->jacobian !=
nullptr,
4244 "update_gradients"));
4245 const std::size_t nqp = this->n_quadrature_points;
4247 if constexpr (n_components == dim && dim > 1)
4249 if (this->
data->element_type ==
4255 Assert(this->gradients_quad_initialized ==
true,
4260 Assert(this->jacobian !=
nullptr,
4262 "update_gradients"));
4263 const std::size_t nqp = this->n_quadrature_points;
4264 const std::size_t nqp_d = nqp * dim;
4267 this->gradients_quad + q_point * dim;
4278 const VectorizedArrayType inv_det =
4279 (dim == 2) ? this->jacobian[0][0][0] * this->jacobian[0][1][1] :
4280 this->jacobian[0][0][0] * this->jacobian[0][1][1] *
4281 this->jacobian[0][2][2];
4284 for (
unsigned int d = 0;
d < dim; ++
d)
4285 for (
unsigned int comp = 0; comp < n_components; ++comp)
4286 grad_out[comp][d] = gradients[comp * nqp_d + d] *
4288 (jac[comp][comp] * inv_det);
4300 const VectorizedArrayType inv_det =
4301 (is_face && dim == 2 && this->get_face_no() < 2) ?
4305 VectorizedArrayType tmp[dim][dim];
4307 for (
unsigned int d = 0;
d < dim; ++
d)
4308 for (
unsigned int e = 0;
e < dim; ++
e)
4311 for (
unsigned int f = 1; f < dim; ++f)
4312 tmp[d][e] += inv_t_jac[d][f] * gradients[e * nqp_d + f];
4314 for (
unsigned int comp = 0; comp < n_components; ++comp)
4315 for (
unsigned int d = 0;
d < dim; ++
d)
4317 VectorizedArrayType res = jac[comp][0] * tmp[
d][0];
4318 for (
unsigned int f = 1; f < dim; ++f)
4319 res += jac[comp][f] * tmp[d][f];
4321 grad_out[comp][
d] = res * inv_det;
4332 Assert(this->jacobian_gradients_non_inverse !=
nullptr,
4334 "update_hessians"));
4336 const auto jac_grad =
4337 this->jacobian_gradients_non_inverse[q_point];
4339 this->jacobian[q_point];
4343 const VectorizedArrayType inv_det =
4344 (is_face && dim == 2 && this->get_face_no() < 2) ?
4351 VectorizedArrayType tmp[dim][dim];
4352 for (
unsigned int d = 0;
d < dim; ++
d)
4353 for (
unsigned int e = 0;
e < dim; ++
e)
4356 for (
unsigned int f = 1; f < dim; ++f)
4357 tmp[e][d] += t_jac[f][d] * gradients[f * nqp_d + e];
4362 for (
unsigned int d = 0;
d < dim; ++
d)
4364 for (
unsigned int e = 0;
e < dim; ++
e)
4366 jac_grad[e][d] * this->values_quad[e * nqp + q_point];
4367 for (
unsigned int f = 0, r = dim; f < dim; ++f)
4368 for (
unsigned int k = f + 1; k < dim; ++k, ++r)
4371 jac_grad[r][
d] * this->values_quad[f * nqp + q_point];
4373 jac_grad[r][
d] * this->values_quad[k * nqp + q_point];
4378 for (
unsigned int d = 0;
d < dim; ++
d)
4379 for (
unsigned int e = 0;
e < dim; ++
e)
4381 VectorizedArrayType res = tmp[0][
d] * inv_t_jac[
e][0];
4382 for (
unsigned int f = 1; f < dim; ++f)
4383 res += tmp[f][d] * inv_t_jac[e][f];
4384 grad_out[
d][
e] = res;
4390 VectorizedArrayType tmp3[dim], tmp4[dim];
4391 for (
unsigned int d = 0;
d < dim; ++
d)
4393 tmp3[
d] = inv_t_jac[0][
d] * jac_grad[
d][0];
4394 for (
unsigned int e = 1;
e < dim; ++
e)
4395 tmp3[d] += inv_t_jac[e][d] * jac_grad[d][e];
4397 for (
unsigned int e = 0, k = dim;
e < dim; ++
e)
4398 for (
unsigned int f = e + 1; f < dim; ++k, ++f)
4399 for (
unsigned int d = 0;
d < dim; ++
d)
4401 tmp3[f] += inv_t_jac[
d][
e] * jac_grad[k][
d];
4402 tmp3[
e] += inv_t_jac[
d][f] * jac_grad[k][
d];
4404 for (
unsigned int d = 0;
d < dim; ++
d)
4406 tmp4[
d] = tmp3[0] * inv_t_jac[
d][0];
4407 for (
unsigned int e = 1;
e < dim; ++
e)
4408 tmp4[d] += tmp3[e] * inv_t_jac[d][e];
4411 VectorizedArrayType tmp2[dim];
4412 for (
unsigned int d = 0;
d < dim; ++
d)
4414 tmp2[
d] = t_jac[0][
d] * this->values_quad[q_point];
4415 for (
unsigned e = 1;
e < dim; ++
e)
4417 t_jac[e][d] * this->values_quad[e * nqp + q_point];
4420 for (
unsigned int d = 0;
d < dim; ++
d)
4421 for (
unsigned int e = 0;
e < dim; ++
e)
4423 grad_out[
d][
e] -= tmp4[
e] * tmp2[
d];
4427 grad_out[
d][
e] *= inv_det;
4438 for (
unsigned int comp = 0; comp < n_components; ++comp)
4439 for (
unsigned int d = 0;
d < dim; ++
d)
4441 this->gradients_quad[(comp * nqp + q_point) * dim +
d] *
4442 this->jacobian[0][
d][
d];
4451 for (
unsigned int comp = 0; comp < n_components; ++comp)
4452 for (
unsigned int d = 0;
d < dim; ++
d)
4455 jac[
d][0] * this->gradients_quad[(comp * nqp + q_point) * dim];
4456 for (
unsigned int e = 1;
e < dim; ++
e)
4457 grad_out[comp][d] +=
4459 this->gradients_quad[(comp * nqp + q_point) * dim +
e];
4462 if constexpr (n_components == 1)
4474 typename VectorizedArrayType>
4487 Assert(this->gradients_quad_initialized ==
true,
4491 Assert(this->normal_x_jacobian !=
nullptr,
4493 "update_gradients"));
4495 const std::size_t nqp = this->n_quadrature_points;
4499 for (
unsigned int comp = 0; comp < n_components; ++comp)
4501 this->gradients_quad[(comp * nqp + q_point) * dim + dim - 1] *
4502 (this->normal_x_jacobian[0][dim - 1]);
4505 const std::size_t
index =
4507 for (
unsigned int comp = 0; comp < n_components; ++comp)
4509 grad_out[comp] = this->gradients_quad[(comp * nqp + q_point) * dim] *
4510 this->normal_x_jacobian[
index][0];
4511 for (
unsigned int d = 1;
d < dim; ++
d)
4513 this->gradients_quad[(comp * nqp + q_point) * dim +
d] *
4514 this->normal_x_jacobian[
index][
d];
4517 if constexpr (n_components == 1)
4529 template <
typename VectorizedArrayType>
4532 const VectorizedArrayType *
const hessians,
4534 VectorizedArrayType (&tmp)[1][1])
4536 tmp[0][0] = jac[0][0] *
hessians[0];
4539 template <
typename VectorizedArrayType>
4542 const VectorizedArrayType *
const hessians,
4543 const unsigned int nqp,
4544 VectorizedArrayType (&tmp)[2][2])
4546 for (
unsigned int d = 0;
d < 2; ++
d)
4554 template <
typename VectorizedArrayType>
4557 const VectorizedArrayType *
const hessians,
4558 const unsigned int nqp,
4559 VectorizedArrayType (&tmp)[3][3])
4561 for (
unsigned int d = 0;
d < 3; ++
d)
4582 typename VectorizedArrayType>
4587 VectorizedArrayType>::hessian_type
4593 Assert(this->hessians_quad_initialized ==
true,
4598 Assert(this->jacobian !=
nullptr,
4608 const std::size_t nqp = this->n_quadrature_points;
4609 constexpr unsigned int hdim = (dim * (dim + 1)) / 2;
4614 for (
unsigned int comp = 0; comp < n_components; ++comp)
4616 for (
unsigned int d = 0;
d < dim; ++
d)
4617 hessian_out[comp][d][d] =
4618 this->hessians_quad[(comp * hdim + d) * nqp + q_point] *
4619 (jac[
d][
d] * jac[
d][
d]);
4625 hessian_out[comp][0][1] =
4626 this->hessians_quad[(comp * hdim + 2) * nqp + q_point] *
4627 (jac[0][0] * jac[1][1]);
4630 hessian_out[comp][0][1] =
4631 this->hessians_quad[(comp * hdim + 3) * nqp + q_point] *
4632 (jac[0][0] * jac[1][1]);
4633 hessian_out[comp][0][2] =
4634 this->hessians_quad[(comp * hdim + 4) * nqp + q_point] *
4635 (jac[0][0] * jac[2][2]);
4636 hessian_out[comp][1][2] =
4637 this->hessians_quad[(comp * hdim + 5) * nqp + q_point] *
4638 (jac[1][1] * jac[2][2]);
4643 for (
unsigned int d = 0;
d < dim; ++
d)
4644 for (
unsigned int e = d + 1;
e < dim; ++
e)
4645 hessian_out[comp][e][d] = hessian_out[comp][d][e];
4651 for (
unsigned int comp = 0; comp < n_components; ++comp)
4653 VectorizedArrayType tmp[dim][dim];
4654 internal::hessian_unit_times_jac(
4655 jac, this->hessians_quad + comp * hdim * nqp + q_point, nqp, tmp);
4658 for (
unsigned int d = 0;
d < dim; ++
d)
4659 for (
unsigned int e = d;
e < dim; ++
e)
4661 hessian_out[comp][
d][
e] = jac[
d][0] * tmp[0][
e];
4662 for (
unsigned int f = 1; f < dim; ++f)
4663 hessian_out[comp][d][e] += jac[d][f] * tmp[f][e];
4670 for (
unsigned int d = 0;
d < dim; ++
d)
4671 for (
unsigned int e = d + 1;
e < dim; ++
e)
4672 hessian_out[comp][e][d] = hessian_out[comp][d][e];
4678 const auto &jac_grad = this->jacobian_gradients[q_point];
4679 for (
unsigned int comp = 0; comp < n_components; ++comp)
4681 VectorizedArrayType tmp[dim][dim];
4682 internal::hessian_unit_times_jac(
4683 jac, this->hessians_quad + comp * hdim * nqp + q_point, nqp, tmp);
4686 for (
unsigned int d = 0;
d < dim; ++
d)
4687 for (
unsigned int e = d;
e < dim; ++
e)
4689 hessian_out[comp][
d][
e] = jac[
d][0] * tmp[0][
e];
4690 for (
unsigned int f = 1; f < dim; ++f)
4691 hessian_out[comp][d][e] += jac[d][f] * tmp[f][e];
4695 for (
unsigned int d = 0;
d < dim; ++
d)
4696 for (
unsigned int e = 0;
e < dim; ++
e)
4697 hessian_out[comp][d][d] +=
4699 this->gradients_quad[(comp * nqp + q_point) * dim +
e];
4702 for (
unsigned int d = 0, count = dim;
d < dim; ++
d)
4703 for (
unsigned int e = d + 1;
e < dim; ++
e, ++count)
4704 for (
unsigned int f = 0; f < dim; ++f)
4705 hessian_out[comp][d][e] +=
4706 jac_grad[count][f] *
4707 this->gradients_quad[(comp * nqp + q_point) * dim + f];
4710 for (
unsigned int d = 0;
d < dim; ++
d)
4711 for (
unsigned int e = d + 1;
e < dim; ++
e)
4712 hessian_out[comp][e][d] = hessian_out[comp][d][e];
4715 if constexpr (n_components == 1)
4716 return hessian_out[0];
4727 typename VectorizedArrayType>
4732 VectorizedArrayType>::gradient_type
4739 Assert(this->hessians_quad_initialized ==
true,
4750 const std::size_t nqp = this->n_quadrature_points;
4751 constexpr unsigned int hdim = (dim * (dim + 1)) / 2;
4757 for (
unsigned int comp = 0; comp < n_components; ++comp)
4758 for (
unsigned int d = 0;
d < dim; ++
d)
4759 hessian_out[comp][d] =
4760 this->hessians_quad[(comp * hdim + d) * nqp + q_point] *
4761 (jac[
d][
d] * jac[
d][
d]);
4766 for (
unsigned int comp = 0; comp < n_components; ++comp)
4770 VectorizedArrayType tmp[dim][dim];
4771 internal::hessian_unit_times_jac(
4772 jac, this->hessians_quad + comp * hdim * nqp + q_point, nqp, tmp);
4776 for (
unsigned int d = 0;
d < dim; ++
d)
4778 hessian_out[comp][
d] = jac[
d][0] * tmp[0][
d];
4779 for (
unsigned int f = 1; f < dim; ++f)
4780 hessian_out[comp][d] += jac[d][f] * tmp[f][d];
4787 const auto &jac_grad = this->jacobian_gradients[q_point];
4788 for (
unsigned int comp = 0; comp < n_components; ++comp)
4792 VectorizedArrayType tmp[dim][dim];
4793 internal::hessian_unit_times_jac(
4794 jac, this->hessians_quad + comp * hdim * nqp + q_point, nqp, tmp);
4798 for (
unsigned int d = 0;
d < dim; ++
d)
4800 hessian_out[comp][
d] = jac[
d][0] * tmp[0][
d];
4801 for (
unsigned int f = 1; f < dim; ++f)
4802 hessian_out[comp][d] += jac[d][f] * tmp[f][d];
4805 for (
unsigned int d = 0;
d < dim; ++
d)
4806 for (
unsigned int e = 0;
e < dim; ++
e)
4807 hessian_out[comp][d] +=
4809 this->gradients_quad[(comp * nqp + q_point) * dim +
e];
4813 if constexpr (n_components == 1)
4814 return hessian_out[0];
4825 typename VectorizedArrayType>
4837 Assert(this->hessians_quad_initialized ==
true,
4842 const gradient_type hess_diag = get_hessian_diagonal(q_point);
4843 if constexpr (n_components == 1)
4845 VectorizedArrayType
sum = hess_diag[0];
4846 for (
unsigned int d = 1;
d < dim; ++
d)
4847 sum += hess_diag[d];
4853 for (
unsigned int comp = 0; comp < n_components; ++comp)
4855 laplacian_out[comp] = hess_diag[comp][0];
4856 for (
unsigned int d = 1;
d < dim; ++
d)
4857 laplacian_out[comp] += hess_diag[comp][d];
4859 return laplacian_out;
4869 typename VectorizedArrayType>
4880 Assert(this->hessians_quad_initialized ==
true,
4885 Assert(this->normal_x_jacobian !=
nullptr,
4887 "update_hessians"));
4891 const std::size_t nqp = this->n_quadrature_points;
4892 constexpr unsigned int hdim = (dim * (dim + 1)) / 2;
4896 const auto nxj = this->normal_x_jacobian[0];
4898 for (
unsigned int comp = 0; comp < n_components; ++comp)
4900 for (
unsigned int d = 0;
d < dim; ++
d)
4901 hessian_out[comp] +=
4902 this->hessians_quad[(comp * hdim + d) * nqp + q_point] *
4903 (nxj[
d]) * (nxj[d]);
4910 hessian_out[comp] +=
4911 this->hessians_quad[(comp * hdim + 2) * nqp + q_point] *
4915 hessian_out[comp] +=
4916 2. * this->hessians_quad[(comp * hdim + 3) * nqp + q_point] *
4918 hessian_out[comp] +=
4919 2. * this->hessians_quad[(comp * hdim + 4) * nqp + q_point] *
4921 hessian_out[comp] +=
4922 2. * this->hessians_quad[(comp * hdim + 5) * nqp + q_point] *
4933 const auto normal = this->normal_vector(q_point);
4934 const auto hessian = get_hessian(q_point);
4936 if constexpr (n_components == 1)
4937 hessian_out[0] =
hessian * normal * normal;
4939 for (
unsigned int comp = 0; comp < n_components; ++comp)
4940 hessian_out[comp] =
hessian[comp] * normal * normal;
4942 if constexpr (n_components == 1)
4943 return hessian_out[0];
4954 typename VectorizedArrayType>
4961 this->dof_values_initialized =
true;
4963 const std::size_t dofs = this->
data->dofs_per_component_on_cell;
4965 for (
unsigned int comp = 0; comp < n_components; ++comp)
4966 if constexpr (n_components == 1)
4967 this->values_dofs[comp * dofs + dof] = val_in;
4969 this->values_dofs[comp * dofs + dof] = val_in[comp];
4978 typename VectorizedArrayType>
4988 Assert(this->J_value !=
nullptr,
4993 this->values_quad_submitted =
true;
4996 const std::size_t nqp = this->n_quadrature_points;
4997 VectorizedArrayType *
values = this->values_quad + q_point;
4999 const VectorizedArrayType JxW =
5001 this->J_value[0] * this->quadrature_weights[q_point] :
5002 this->J_value[q_point];
5003 if constexpr (n_components == 1)
5004 values[0] = val_in * JxW;
5007 if (n_components == dim &&
5008 this->
data->element_type ==
5013 Assert(this->J_value !=
nullptr,
5019 this->values_quad_submitted =
true;
5022 VectorizedArrayType *
values = this->values_quad + q_point;
5023 const std::size_t nqp = this->n_quadrature_points;
5029 const VectorizedArrayType weight =
5030 this->quadrature_weights[q_point];
5032 for (
unsigned int comp = 0; comp < n_components; ++comp)
5033 values[comp * nqp] = val_in[comp] * weight * jac[comp][comp];
5040 this->jacobian[q_point] :
5045 const VectorizedArrayType fac =
5047 this->quadrature_weights[q_point] :
5049 this->J_value[q_point] :
5050 this->J_value[0] * this->quadrature_weights[q_point]) *
5051 ((dim == 2 && this->get_face_no() < 2) ?
5060 for (
unsigned int comp = 0; comp < n_components; ++comp)
5062 values[comp * nqp] = val_in[0] * jac[0][comp];
5063 for (
unsigned int e = 1;
e < dim; ++
e)
5064 values[comp * nqp] += val_in[e] * jac[e][comp];
5065 values[comp * nqp] *= fac;
5069 else if (n_components == dim &&
5070 this->
data->element_type ==
5075 Assert(this->J_value !=
nullptr,
5081 this->values_quad_submitted =
true;
5084 VectorizedArrayType *
values = this->values_quad + q_point;
5085 const std::size_t nqp = this->n_quadrature_points;
5092 const VectorizedArrayType det_jac =
5093 (dim == 2) ? this->jacobian[1][0][0] * this->jacobian[1][1][1] :
5094 this->jacobian[1][0][0] * this->jacobian[1][1][1] *
5095 this->jacobian[1][2][2];
5097 const VectorizedArrayType weight =
5098 this->quadrature_weights[q_point];
5101 for (
unsigned int comp = 0; comp < n_components; ++comp)
5102 values[comp * nqp] =
5103 val_in[comp] * weight * inv_t_jac[comp][comp] * det_jac;
5110 this->jacobian[q_point] :
5113 const VectorizedArrayType fac =
5115 this->J_value[q_point] :
5116 this->J_value[0] * this->quadrature_weights[q_point]);
5119 for (
unsigned int comp = 0; comp < n_components; ++comp)
5121 values[comp * nqp] = val_in[0] * inv_t_jac[0][comp];
5122 for (
unsigned int e = 1;
e < dim; ++
e)
5123 values[comp * nqp] += val_in[e] * inv_t_jac[e][comp];
5124 values[comp * nqp] *= fac;
5129 for (
unsigned int comp = 0; comp < n_components; ++comp)
5130 values[comp * nqp] = val_in[comp] * JxW;
5140 typename VectorizedArrayType>
5141template <
int,
typename>
5145 const unsigned int q_point)
5147 static_assert(n_components == 1,
5148 "Do not try to modify the default template parameters used for"
5149 " selectively enabling this function via std::enable_if!");
5150 submit_value(val_in[0], q_point);
5159 typename VectorizedArrayType>
5162 submit_gradient(
const gradient_type grad_in,
const unsigned int q_point)
5169 Assert(this->J_value !=
nullptr,
5171 "update_gradients"));
5172 Assert(this->jacobian !=
nullptr,
5174 "update_gradients"));
5177 this->gradients_quad_submitted =
true;
5180 if constexpr (dim > 1 && n_components == dim)
5182 if (this->
data->element_type ==
5192 Assert(this->J_value !=
nullptr,
5194 "update_gradients"));
5195 Assert(this->jacobian !=
nullptr,
5197 "update_gradients"));
5200 this->gradients_quad_submitted =
true;
5203 VectorizedArrayType *
gradients = this->gradients_quad + q_point * dim;
5204 VectorizedArrayType *
values =
5205 this->values_from_gradients_quad + q_point;
5206 const std::size_t nqp = this->n_quadrature_points;
5207 const std::size_t nqp_d = nqp * dim;
5217 const VectorizedArrayType weight =
5218 this->quadrature_weights[q_point];
5219 for (
unsigned int d = 0;
d < dim; ++
d)
5220 for (
unsigned int comp = 0; comp < n_components; ++comp)
5221 gradients[comp * nqp_d + d] = grad_in[comp][d] *
5223 (jac[comp][comp] * weight);
5235 const VectorizedArrayType fac =
5237 this->quadrature_weights[q_point] :
5238 this->J_value[0] * this->quadrature_weights[q_point] *
5239 ((dim == 2 && this->get_face_no() < 2) ?
5244 VectorizedArrayType tmp[dim][dim];
5245 for (
unsigned int d = 0;
d < dim; ++
d)
5246 for (
unsigned int e = 0;
e < dim; ++
e)
5248 tmp[
d][
e] = inv_t_jac[0][
d] * grad_in[
e][0];
5249 for (
unsigned int f = 1; f < dim; ++f)
5250 tmp[d][e] += inv_t_jac[f][d] * grad_in[e][f];
5252 for (
unsigned int comp = 0; comp < n_components; ++comp)
5253 for (
unsigned int d = 0;
d < dim; ++
d)
5255 VectorizedArrayType res = jac[0][comp] * tmp[
d][0];
5256 for (
unsigned int f = 1; f < dim; ++f)
5257 res += jac[f][comp] * tmp[d][f];
5266 const auto jac_grad =
5267 this->jacobian_gradients_non_inverse[q_point];
5269 this->jacobian[q_point];
5273 const VectorizedArrayType fac =
5274 (!is_face) ? this->quadrature_weights[q_point] :
5275 this->J_value[q_point] *
5276 ((dim == 2 && this->get_face_no() < 2) ?
5285 VectorizedArrayType tmp3[dim], tmp4[dim];
5286 for (
unsigned int d = 0;
d < dim; ++
d)
5288 tmp3[
d] = inv_t_jac[0][
d] * jac_grad[
d][0];
5289 for (
unsigned int e = 1;
e < dim; ++
e)
5290 tmp3[d] += inv_t_jac[e][d] * jac_grad[d][e];
5292 for (
unsigned int e = 0, k = dim;
e < dim; ++
e)
5293 for (
unsigned int f = e + 1; f < dim; ++k, ++f)
5294 for (
unsigned int d = 0;
d < dim; ++
d)
5296 tmp3[f] += inv_t_jac[
d][
e] * jac_grad[k][
d];
5297 tmp3[
e] += inv_t_jac[
d][f] * jac_grad[k][
d];
5299 for (
unsigned int d = 0;
d < dim; ++
d)
5301 tmp4[
d] = tmp3[0] * inv_t_jac[
d][0];
5302 for (
unsigned int e = 1;
e < dim; ++
e)
5303 tmp4[d] += tmp3[e] * inv_t_jac[d][e];
5309 VectorizedArrayType tmp[dim][dim];
5312 for (
unsigned int d = 0;
d < dim; ++
d)
5313 for (
unsigned int e = 0;
e < dim; ++
e)
5315 tmp[
d][
e] = inv_t_jac[0][
d] * grad_in_scaled[
e][0];
5316 for (
unsigned int f = 1; f < dim; ++f)
5317 tmp[d][e] += inv_t_jac[f][d] * grad_in_scaled[e][f];
5320 for (
unsigned int d = 0;
d < dim; ++
d)
5321 for (
unsigned int e = 0;
e < dim; ++
e)
5323 VectorizedArrayType res = t_jac[
d][0] * tmp[
e][0];
5324 for (
unsigned int f = 1; f < dim; ++f)
5325 res += t_jac[d][f] * tmp[e][f];
5332 VectorizedArrayType
value[dim];
5333 for (
unsigned int d = 0;
d < dim; ++
d)
5335 value[
d] = tmp[
d][0] * jac_grad[
d][0];
5336 for (
unsigned int e = 1;
e < dim; ++
e)
5337 value[d] += tmp[d][e] * jac_grad[d][e];
5339 for (
unsigned int e = 0, k = dim;
e < dim; ++
e)
5340 for (
unsigned int f = e + 1; f < dim; ++k, ++f)
5341 for (
unsigned int d = 0;
d < dim; ++
d)
5343 value[
e] += tmp[f][
d] * jac_grad[k][
d];
5344 value[f] += tmp[
e][
d] * jac_grad[k][
d];
5349 for (
unsigned int d = 0;
d < dim; ++
d)
5351 VectorizedArrayType tmp2 = grad_in_scaled[
d][0] * tmp4[0];
5352 for (
unsigned int e = 1;
e < dim; ++
e)
5353 tmp2 += grad_in_scaled[d][e] * tmp4[e];
5354 for (
unsigned int e = 0;
e < dim; ++
e)
5355 value[e] -= t_jac[e][d] * tmp2;
5358 for (
unsigned int d = 0;
d < dim; ++
d)
5359 values[d * nqp] =
value[d];
5365 const std::size_t nqp_d = this->n_quadrature_points * dim;
5366 VectorizedArrayType *
gradients = this->gradients_quad + q_point * dim;
5370 const VectorizedArrayType JxW =
5371 this->J_value[0] * this->quadrature_weights[q_point];
5377 std::array<VectorizedArrayType, dim> jac;
5378 for (
unsigned int d = 0;
d < dim; ++
d)
5379 jac[d] = this->jacobian[0][d][d];
5381 for (
unsigned int d = 0;
d < dim; ++
d)
5383 const VectorizedArrayType factor = this->jacobian[0][
d][
d] * JxW;
5384 if constexpr (n_components == 1)
5385 gradients[d] = grad_in[d] * factor;
5387 for (
unsigned int comp = 0; comp < n_components; ++comp)
5388 gradients[comp * nqp_d + d] = grad_in[comp][d] * factor;
5395 this->jacobian[q_point] :
5397 const VectorizedArrayType JxW =
5399 this->J_value[q_point] :
5400 this->J_value[0] * this->quadrature_weights[q_point];
5401 if constexpr (n_components == 1)
5402 for (
unsigned int d = 0;
d < dim; ++
d)
5404 VectorizedArrayType new_val = jac[0][
d] * grad_in[0];
5405 for (
unsigned int e = 1;
e < dim; ++
e)
5406 new_val += (jac[e][d] * grad_in[e]);
5410 for (
unsigned int comp = 0; comp < n_components; ++comp)
5411 for (
unsigned int d = 0;
d < dim; ++
d)
5413 VectorizedArrayType new_val = jac[0][
d] * grad_in[comp][0];
5414 for (
unsigned int e = 1;
e < dim; ++
e)
5415 new_val += (jac[e][d] * grad_in[comp][e]);
5427 typename VectorizedArrayType>
5428template <
int,
typename>
5432 const unsigned int q_point)
5434 static_assert(n_components == 1 && dim == 1,
5435 "Do not try to modify the default template parameters used for"
5436 " selectively enabling this function via std::enable_if!");
5437 submit_gradient(grad_in[0], q_point);
5446 typename VectorizedArrayType>
5452 Assert(this->normal_x_jacobian !=
nullptr,
5454 "update_gradients"));
5457 this->gradients_quad_submitted =
true;
5460 const std::size_t nqp_d = this->n_quadrature_points * dim;
5461 VectorizedArrayType *
gradients = this->gradients_quad + q_point * dim;
5465 const VectorizedArrayType JxW_jac = this->J_value[0] *
5466 this->quadrature_weights[q_point] *
5467 this->normal_x_jacobian[0][dim - 1];
5468 for (
unsigned int comp = 0; comp < n_components; ++comp)
5470 for (
unsigned int d = 0;
d < dim - 1; ++
d)
5471 gradients[comp * nqp_d + d] = VectorizedArrayType();
5472 if constexpr (n_components == 1)
5473 gradients[dim - 1] = grad_in * JxW_jac;
5475 gradients[comp * nqp_d + dim - 1] = grad_in[comp] * JxW_jac;
5480 const unsigned int index =
5483 this->normal_x_jacobian[
index];
5484 const VectorizedArrayType JxW =
5486 this->J_value[
index] * this->quadrature_weights[q_point] :
5487 this->J_value[
index];
5488 for (
unsigned int comp = 0; comp < n_components; ++comp)
5489 for (
unsigned int d = 0;
d < dim; ++
d)
5490 if constexpr (n_components == 1)
5493 gradients[comp * nqp_d +
d] = (grad_in[comp] * JxW) * jac[d];
5503 typename VectorizedArrayType>
5506 submit_hessian(
const hessian_type hessian_in,
const unsigned int q_point)
5513 Assert(this->J_value !=
nullptr,
5515 "update_hessians"));
5516 Assert(this->jacobian !=
nullptr,
5518 "update_hessians"));
5521 this->hessians_quad_submitted =
true;
5525 const std::size_t nqp = this->n_quadrature_points;
5526 constexpr unsigned int hdim = (dim * (dim + 1)) / 2;
5529 const VectorizedArrayType JxW =
5530 this->J_value[0] * this->quadrature_weights[q_point];
5533 for (
unsigned int d = 0;
d < dim; ++
d)
5535 const auto jac_d = this->jacobian[0][
d][
d];
5536 const VectorizedArrayType factor = jac_d * jac_d * JxW;
5537 for (
unsigned int comp = 0; comp < n_components; ++comp)
5538 if constexpr (n_components == 1)
5539 this->hessians_quad[
d * nqp + q_point] =
5540 hessian_in[
d][
d] * factor;
5542 this->hessians_quad[(comp * hdim +
d) * nqp + q_point] =
5543 hessian_in[comp][d][d] * factor;
5547 for (
unsigned int d = 1, off_dia = dim;
d < dim; ++
d)
5548 for (
unsigned int e = 0;
e <
d; ++
e, ++off_dia)
5550 const auto jac_d = this->jacobian[0][
d][
d];
5551 const auto jac_e = this->jacobian[0][
e][
e];
5552 const VectorizedArrayType factor = jac_d * jac_e * JxW;
5553 for (
unsigned int comp = 0; comp < n_components; ++comp)
5554 if constexpr (n_components == 1)
5555 this->hessians_quad[off_dia * nqp + q_point] =
5556 (hessian_in[
d][
e] + hessian_in[
e][
d]) * factor;
5558 this->hessians_quad[(comp * hdim + off_dia) * nqp + q_point] =
5559 (hessian_in[comp][d][e] + hessian_in[comp][e][d]) * factor;
5566 const VectorizedArrayType JxW =
5567 this->J_value[0] * this->quadrature_weights[q_point];
5568 for (
unsigned int comp = 0; comp < n_components; ++comp)
5571 if constexpr (n_components == 1)
5572 hessian_c = hessian_in;
5574 hessian_c = hessian_in[comp];
5577 VectorizedArrayType tmp[dim][dim];
5578 for (
unsigned int i = 0; i < dim; ++i)
5579 for (
unsigned int j = 0; j < dim; ++j)
5581 tmp[i][j] = hessian_c[i][0] * jac[0][j];
5582 for (
unsigned int k = 1; k < dim; ++k)
5583 tmp[i][j] += hessian_c[i][k] * jac[k][j];
5587 VectorizedArrayType tmp2[dim][dim];
5588 for (
unsigned int i = 0; i < dim; ++i)
5589 for (
unsigned int j = 0; j < dim; ++j)
5591 tmp2[i][j] = jac[0][i] * tmp[0][j];
5592 for (
unsigned int k = 1; k < dim; ++k)
5593 tmp2[i][j] += jac[k][i] * tmp[k][j];
5597 for (
unsigned int d = 0;
d < dim; ++
d)
5598 this->hessians_quad[(comp * hdim + d) * nqp + q_point] =
5602 for (
unsigned int d = 0, off_diag = dim;
d < dim; ++
d)
5603 for (
unsigned int e = d + 1;
e < dim; ++
e, ++off_diag)
5604 this->hessians_quad[(comp * hdim + off_diag) * nqp + q_point] =
5605 (tmp2[
d][
e] + tmp2[
e][
d]) * JxW;
5611 const VectorizedArrayType JxW = this->J_value[q_point];
5612 const auto &jac_grad = this->jacobian_gradients[q_point];
5613 for (
unsigned int comp = 0; comp < n_components; ++comp)
5616 if constexpr (n_components == 1)
5617 hessian_c = hessian_in;
5619 hessian_c = hessian_in[comp];
5622 VectorizedArrayType tmp[dim][dim];
5623 for (
unsigned int i = 0; i < dim; ++i)
5624 for (
unsigned int j = 0; j < dim; ++j)
5626 tmp[i][j] = hessian_c[i][0] * jac[0][j];
5627 for (
unsigned int k = 1; k < dim; ++k)
5628 tmp[i][j] += hessian_c[i][k] * jac[k][j];
5632 VectorizedArrayType tmp2[dim][dim];
5633 for (
unsigned int i = 0; i < dim; ++i)
5634 for (
unsigned int j = 0; j < dim; ++j)
5636 tmp2[i][j] = jac[0][i] * tmp[0][j];
5637 for (
unsigned int k = 1; k < dim; ++k)
5638 tmp2[i][j] += jac[k][i] * tmp[k][j];
5642 for (
unsigned int d = 0;
d < dim; ++
d)
5643 this->hessians_quad[(comp * hdim + d) * nqp + q_point] =
5647 for (
unsigned int d = 0, off_diag = dim;
d < dim; ++
d)
5648 for (
unsigned int e = d + 1;
e < dim; ++
e, ++off_diag)
5649 this->hessians_quad[(comp * hdim + off_diag) * nqp + q_point] =
5650 (tmp2[
d][
e] + tmp2[
e][
d]) * JxW;
5653 for (
unsigned int d = 0;
d < dim; ++
d)
5655 VectorizedArrayType
sum = 0;
5656 for (
unsigned int e = 0;
e < dim; ++
e)
5657 sum += hessian_c[e][e] * jac_grad[e][d];
5658 for (
unsigned int e = 0, count = dim;
e < dim; ++
e)
5659 for (
unsigned int f = e + 1; f < dim; ++f, ++count)
5661 (hessian_c[e][f] + hessian_c[f][e]) * jac_grad[count][
d];
5662 this->gradients_from_hessians_quad[(comp * nqp + q_point) * dim +
5675 typename VectorizedArrayType>
5679 const unsigned int q_point)
5686 Assert(this->J_value !=
nullptr,
5688 "update_hessians"));
5689 Assert(this->jacobian !=
nullptr,
5691 "update_hessians"));
5694 this->hessians_quad_submitted =
true;
5698 const std::size_t nqp = this->n_quadrature_points;
5699 constexpr unsigned int hdim = (dim * (dim + 1)) / 2;
5702 const VectorizedArrayType JxW =
5703 this->J_value[0] * this->quadrature_weights[q_point];
5705 const auto nxj = this->normal_x_jacobian[0];
5708 for (
unsigned int d = 0;
d < dim; ++
d)
5710 const auto nxj_d = nxj[
d];
5711 const VectorizedArrayType factor = nxj_d * nxj_d * JxW;
5712 for (
unsigned int comp = 0; comp < n_components; ++comp)
5713 if constexpr (n_components == 1)
5714 this->hessians_quad[
d * nqp + q_point] =
5715 normal_hessian_in * factor;
5717 this->hessians_quad[(comp * hdim +
d) * nqp + q_point] =
5718 normal_hessian_in[comp] * factor;
5722 for (
unsigned int d = 1, off_dia = dim;
d < dim; ++
d)
5723 for (
unsigned int e = 0;
e <
d; ++
e, ++off_dia)
5725 const auto jac_d = nxj[
d];
5726 const auto jac_e = nxj[
e];
5727 const VectorizedArrayType factor = jac_d * jac_e * JxW;
5728 for (
unsigned int comp = 0; comp < n_components; ++comp)
5729 if constexpr (n_components == 1)
5730 this->hessians_quad[off_dia * nqp + q_point] =
5731 2. * normal_hessian_in * factor;
5733 this->hessians_quad[(comp * hdim + off_dia) * nqp + q_point] =
5734 2. * normal_hessian_in[comp] * factor;
5739 const auto normal = this->normal_vector(q_point);
5740 const auto normal_projector =
outer_product(normal, normal);
5741 if constexpr (n_components == 1)
5742 submit_hessian(normal_hessian_in * normal_projector, q_point);
5746 for (
unsigned int comp = 0; comp < n_components; ++comp)
5747 tmp[comp] = normal_hessian_in[comp] * normal_projector;
5748 submit_hessian(tmp, q_point);
5759 typename VectorizedArrayType>
5771 Assert(this->values_quad_submitted ==
true,
5776 const std::size_t nqp = this->n_quadrature_points;
5777 for (
unsigned int q = 0; q < nqp; ++q)
5778 for (
unsigned int comp = 0; comp < n_components; ++comp)
5779 return_value[comp] += this->values_quad[comp * nqp + q];
5780 if constexpr (n_components == 1)
5781 return return_value[0];
5783 return return_value;
5792 typename VectorizedArrayType>
5793template <
int,
typename>
5798 static_assert(n_components == dim,
5799 "Do not try to modify the default template parameters used for"
5800 " selectively enabling this function via std::enable_if!");
5804 Assert(this->gradients_quad_initialized ==
true,
5808 Assert(this->jacobian !=
nullptr,
5810 "update_gradients"));
5812 VectorizedArrayType divergence;
5813 const std::size_t nqp = this->n_quadrature_points;
5816 this->
data->element_type ==
5819 VectorizedArrayType inv_det =
5822 this->jacobian[0][0][0] *
5823 ((dim == 2) ? this->jacobian[0][1][1] :
5824 this->jacobian[0][1][1] * this->jacobian[0][2][2]) :
5832 if (is_face && dim == 2 && this->get_face_no() < 2)
5836 divergence = this->gradients_quad[q_point * dim];
5837 for (
unsigned int d = 1;
d < dim; ++
d)
5838 divergence += this->gradients_quad[(d * nqp + q_point) * dim +
d];
5839 divergence *= inv_det;
5848 this->gradients_quad[q_point * dim] * this->jacobian[0][0][0];
5849 for (
unsigned int d = 1;
d < dim; ++
d)
5850 divergence += this->gradients_quad[(d * nqp + q_point) * dim +
d] *
5851 this->jacobian[0][
d][
d];
5858 this->jacobian[q_point] :
5860 divergence = jac[0][0] * this->gradients_quad[q_point * dim];
5861 for (
unsigned int e = 1;
e < dim; ++
e)
5862 divergence += jac[0][e] * this->gradients_quad[q_point * dim + e];
5863 for (
unsigned int d = 1;
d < dim; ++
d)
5864 for (
unsigned int e = 0;
e < dim; ++
e)
5866 jac[d][e] * this->gradients_quad[(d * nqp + q_point) * dim +
e];
5878 typename VectorizedArrayType>
5879template <
int,
typename>
5884 static_assert(n_components == dim,
5885 "Do not try to modify the default template parameters used for"
5886 " selectively enabling this function via std::enable_if!");
5889 const auto grad = get_gradient(q_point);
5890 VectorizedArrayType symmetrized[(dim * dim + dim) / 2];
5891 VectorizedArrayType half =
Number(0.5);
5892 for (
unsigned int d = 0;
d < dim; ++
d)
5893 symmetrized[d] = grad[d][d];
5899 symmetrized[2] = grad[0][1] + grad[1][0];
5900 symmetrized[2] *= half;
5903 symmetrized[3] = grad[0][1] + grad[1][0];
5904 symmetrized[3] *= half;
5905 symmetrized[4] = grad[0][2] + grad[2][0];
5906 symmetrized[4] *= half;
5907 symmetrized[5] = grad[1][2] + grad[2][1];
5908 symmetrized[5] *= half;
5922 typename VectorizedArrayType>
5923template <
int,
typename>
5929 VectorizedArrayType>::curl_type
5931 get_curl(
const unsigned int q_point)
const
5933 static_assert(dim > 1 && n_components == dim,
5934 "Do not try to modify the default template parameters used for"
5935 " selectively enabling this function via std::enable_if!");
5937 if (dim > 1 && this->
data->element_type ==
5945 Assert(this->gradients_quad_initialized ==
true,
5949 Assert(this->jacobian !=
nullptr,
5951 "update_gradients"));
5953 const std::size_t nqp = this->n_quadrature_points;
5954 const std::size_t nqp_d = nqp * dim;
5956 this->gradients_quad + q_point * dim;
5957 if constexpr (dim == 2)
5958 curl = gradients[1 * nqp_d + 0] - gradients[0 * nqp_d + 1];
5959 else if constexpr (dim == 3)
5971 VectorizedArrayType inv_det =
5972 this->jacobian[0][0][0] *
5973 ((dim == 2) ? this->jacobian[0][1][1] :
5974 this->jacobian[0][1][1] * this->jacobian[0][2][2]);
5979 if constexpr (dim == 2)
5982 for (
unsigned int d = 0;
d < (dim == 2 ? 1 : dim); ++
d)
5983 curl[d] *= jac[d][d] * inv_det;
5990 this->jacobian[q_point] :
5997 VectorizedArrayType inv_det =
determinant(inv_t_jac);
6001 if (is_face && dim == 2 && this->get_face_no() < 2)
6006 if constexpr (dim == 2)
6011 for (
unsigned int comp = 0; comp < dim; ++comp)
6013 curl_temp[comp] = curl[0] * jac[comp][0];
6014 for (
unsigned int e = 1;
e < dim; ++
e)
6015 curl_temp[comp] += jac[comp][e] * curl[e];
6017 for (
unsigned int comp = 0; comp < dim; ++comp)
6018 curl[comp] = curl_temp[comp] * inv_det;
6027 if constexpr (dim == 2)
6028 curl = grad[1][0] - grad[0][1];
6029 else if constexpr (dim == 3)
6031 curl[0] = grad[2][1] - grad[1][2];
6032 curl[1] = grad[0][2] - grad[2][0];
6033 curl[2] = grad[1][0] - grad[0][1];
6047 typename VectorizedArrayType>
6048template <
int,
typename>
6052 const unsigned int q_point)
6054 static_assert(n_components == dim,
6055 "Do not try to modify the default template parameters used for"
6056 " selectively enabling this function via std::enable_if!");
6063 Assert(this->J_value !=
nullptr,
6065 "update_gradients"));
6066 Assert(this->jacobian !=
nullptr,
6068 "update_gradients"));
6071 this->gradients_quad_submitted =
true;
6074 const std::size_t nqp_d = this->n_quadrature_points * dim;
6075 VectorizedArrayType *
gradients = this->gradients_quad + q_point * dim;
6077 if (this->
data->element_type ==
6084 const VectorizedArrayType fac =
6086 this->quadrature_weights[q_point] * div_in :
6088 this->J_value[q_point] :
6089 this->J_value[0] * this->quadrature_weights[q_point]) *
6092 this->jacobian[this->cell_type >
6096 Number((dim == 2 && this->get_face_no() < 2) ? -1 : 1);
6098 for (
unsigned int d = 0;
d < dim; ++
d)
6100 for (
unsigned int e = 0;
e < dim; ++
e)
6101 gradients[d * nqp_d + e] = (d == e) ? fac : 0.;
6103 this->divergence_is_requested =
true;
6110 const VectorizedArrayType fac =
6111 this->J_value[0] * this->quadrature_weights[q_point] * div_in;
6112 for (
unsigned int d = 0;
d < dim; ++
d)
6114 const VectorizedArrayType jac_dd = this->jacobian[0][
d][
d];
6115 for (
unsigned int e = 0;
e < dim; ++
e)
6116 gradients[d * nqp_d + e] = (d == e) ? fac * jac_dd : 0.;
6123 this->jacobian[q_point] :
6125 const VectorizedArrayType fac =
6127 this->J_value[q_point] :
6128 this->J_value[0] * this->quadrature_weights[q_point]) *
6130 for (
unsigned int d = 0;
d < dim; ++
d)
6132 for (
unsigned int e = 0;
e < dim; ++
e)
6133 gradients[d * nqp_d + e] = jac[d][e] * fac;
6145 typename VectorizedArrayType>
6146template <
int,
typename>
6151 const unsigned int q_point)
6153 static_assert(n_components == dim,
6154 "Do not try to modify the default template parameters used for"
6155 " selectively enabling this function via std::enable_if!");
6158 this->
data->element_type !=
6170 Assert(this->J_value !=
nullptr,
6172 "update_gradients"));
6173 Assert(this->jacobian !=
nullptr,
6175 "update_gradients"));
6178 this->gradients_quad_submitted =
true;
6181 const std::size_t nqp_d = this->n_quadrature_points * dim;
6182 VectorizedArrayType *
gradients = this->gradients_quad + dim * q_point;
6185 const VectorizedArrayType JxW =
6186 this->J_value[0] * this->quadrature_weights[q_point];
6188 for (
unsigned int d = 0;
d < dim; ++
d)
6189 gradients[d * nqp_d + d] =
6191 for (
unsigned int e = 0, counter = dim;
e < dim; ++
e)
6192 for (
unsigned int d = e + 1;
d < dim; ++
d, ++counter)
6194 const VectorizedArrayType
value =
6203 const VectorizedArrayType JxW =
6205 this->J_value[q_point] :
6206 this->J_value[0] * this->quadrature_weights[q_point];
6209 this->jacobian[q_point] :
6211 VectorizedArrayType weighted[dim][dim];
6212 for (
unsigned int i = 0; i < dim; ++i)
6214 for (
unsigned int i = 0, counter = dim; i < dim; ++i)
6215 for (
unsigned int j = i + 1; j < dim; ++j, ++counter)
6217 const VectorizedArrayType
value =
6219 weighted[i][j] =
value;
6220 weighted[j][i] =
value;
6222 for (
unsigned int comp = 0; comp < dim; ++comp)
6223 for (
unsigned int d = 0;
d < dim; ++
d)
6225 VectorizedArrayType new_val = jac[0][
d] * weighted[comp][0];
6226 for (
unsigned int e = 1;
e < dim; ++
e)
6227 new_val += jac[e][d] * weighted[comp][e];
6239 typename VectorizedArrayType>
6240template <
int,
typename>
6248 VectorizedArrayType>::curl_type curl,
6249 const unsigned int q_point)
6251 static_assert(n_components == dim,
6252 "Do not try to modify the default template parameters used for"
6253 " selectively enabling this function via std::enable_if!");
6257 if (this->
data->element_type ==
6260 curl_type curl_temp;
6264 Assert(this->J_value !=
nullptr,
6269 this->gradients_quad_submitted =
true;
6272 const std::size_t nqp_d = this->n_quadrature_points * dim;
6273 VectorizedArrayType *
gradients = this->gradients_quad + q_point * dim;
6279 const VectorizedArrayType weight = this->quadrature_weights[q_point];
6281 if constexpr (dim == 2)
6283 curl_temp = curl * weight;
6285 else if constexpr (dim == 3)
6287 for (
unsigned int comp = 0; comp < dim; ++comp)
6289 curl_temp[comp] = curl[comp] * jac[comp][comp] * weight;
6300 this->jacobian[q_point] :
6305 const VectorizedArrayType fac =
6307 this->quadrature_weights[q_point] :
6309 this->J_value[q_point] :
6310 this->J_value[0] * this->quadrature_weights[q_point]) *
6311 ((dim == 2 && this->get_face_no() < 2) ?
6319 if constexpr (dim == 2)
6321 curl_temp = curl * fac;
6323 else if constexpr (dim == 3)
6326 for (
unsigned int comp = 0; comp < n_components; ++comp)
6328 curl_temp[comp] = curl[0] * jac[0][comp];
6329 for (
unsigned int e = 1;
e < dim; ++
e)
6330 curl_temp[comp] += curl[e] * jac[e][comp];
6331 curl_temp[comp] *= fac;
6340 grad[1][0] = curl_temp[0];
6341 grad[0][1] = -curl_temp[0];
6346 grad[2][1] = curl_temp[0];
6347 grad[1][2] = -curl_temp[0];
6348 grad[0][2] = curl_temp[1];
6349 grad[2][0] = -curl_temp[1];
6350 grad[1][0] = curl_temp[2];
6351 grad[0][1] = -curl_temp[2];
6359 for (
unsigned int d = 0;
d < dim; ++
d)
6361 for (
unsigned int comp = 0; comp < n_components; ++comp)
6362 gradients[comp * nqp_d + d] = grad[comp][d];
6367 if constexpr (dim == 2)
6372 else if constexpr (dim == 3)
6374 grad[2][1] = curl[0];
6375 grad[1][2] = -curl[0];
6376 grad[0][2] = curl[1];
6377 grad[2][0] = -curl[1];
6378 grad[1][0] = curl[2];
6379 grad[0][1] = -curl[2];
6384 submit_gradient(grad, q_point);
6397 typename VectorizedArrayType>
6403 VectorizedArrayType>::
6405 const unsigned int fe_no,
6406 const unsigned int quadrature_index,
6407 const unsigned int first_selected_component,
6408 const unsigned int active_fe_index,
6409 const unsigned int active_quad_index)
6410 : BaseClass(matrix_free,
6412 first_selected_component,
6420 , dofs_per_component(this->
data->dofs_per_component_on_cell)
6421 , dofs_per_cell(this->
data->dofs_per_component_on_cell * n_components_)
6422 , n_q_points(this->
data->n_q_points)
6424 check_template_arguments(fe_no, 0);
6434 typename VectorizedArrayType>
6440 VectorizedArrayType>::
6442 const std::pair<unsigned int, unsigned int> &range,
6443 const unsigned int dof_handler_index,
6444 const unsigned int quadrature_index,
6445 const unsigned int first_selected_component)
6449 first_selected_component,
6450 matrix_free.get_cell_active_fe_index(range, dof_handler_index))
6460 typename VectorizedArrayType>
6466 VectorizedArrayType>::
6471 const unsigned int first_selected_component)
6472 : BaseClass(mapping,
6476 first_selected_component,
6478 , dofs_per_component(this->
data->dofs_per_component_on_cell)
6479 , dofs_per_cell(this->
data->dofs_per_component_on_cell * n_components_)
6480 , n_q_points(this->
data->n_q_points)
6492 typename VectorizedArrayType>
6498 VectorizedArrayType>::
6502 const unsigned int first_selected_component)
6507 first_selected_component,
6509 , dofs_per_component(this->
data->dofs_per_component_on_cell)
6510 , dofs_per_cell(this->
data->dofs_per_component_on_cell * n_components_)
6511 , n_q_points(this->
data->n_q_points)
6523 typename VectorizedArrayType>
6529 VectorizedArrayType>::
6532 const unsigned int first_selected_component)
6533 : BaseClass(other.mapped_geometry->get_fe_values().get_mapping(),
6535 other.mapped_geometry->get_quadrature(),
6537 first_selected_component,
6539 , dofs_per_component(this->
data->dofs_per_component_on_cell)
6540 , dofs_per_cell(this->
data->dofs_per_component_on_cell * n_components_)
6541 , n_q_points(this->
data->n_q_points)
6553 typename VectorizedArrayType>
6562 , dofs_per_component(this->
data->dofs_per_component_on_cell)
6563 , dofs_per_cell(this->
data->dofs_per_component_on_cell * n_components_)
6564 , n_q_points(this->
data->n_q_points)
6576 typename VectorizedArrayType>
6582 VectorizedArrayType> &
6588 VectorizedArrayType>::operator=(
const FEEvaluation &other)
6590 BaseClass::operator=(other);
6602 typename VectorizedArrayType>
6609 VectorizedArrayType>::
6610 check_template_arguments(
const unsigned int dof_handler_index,
6611 const unsigned int first_selected_component)
6613 (void)dof_handler_index;
6614 (void)first_selected_component;
6617 this->
data->dofs_per_component_on_cell > 0,
6619 "There is nothing useful you can do with an FEEvaluation object with "
6620 "FE_Nothing, i.e., without DoFs! If you have passed to "
6621 "MatrixFree::reinit() a collection of finite elements also containing "
6622 "FE_Nothing, please check - before creating FEEvaluation - the category "
6623 "of the current range by calling either "
6624 "MatrixFree::get_cell_range_category(range) or "
6625 "MatrixFree::get_face_range_category(range). The returned category "
6626 "is the index of the active FE, which you can use to exclude "
6633 if ((
static_cast<unsigned int>(fe_degree) !=
6635 static_cast<unsigned int>(fe_degree) !=
6636 this->
data->data.front().fe_degree) ||
6637 n_q_points != this->n_quadrature_points)
6639 std::string message =
6640 "-------------------------------------------------------\n";
6642 "Illegal arguments in constructor/wrong template arguments!\n";
6643 message +=
" Called --> FEEvaluation<dim,";
6647 message +=
",Number>(data";
6665 if (
static_cast<unsigned int>(fe_degree) ==
6666 this->
data->data.front().fe_degree)
6668 proposed_dof_comp = dof_handler_index;
6669 proposed_fe_comp = first_selected_component;
6672 for (
unsigned int no = 0;
6675 for (
unsigned int nf = 0;
6678 if (this->matrix_free
6679 ->get_shape_info(no, 0, nf, this->active_fe_index, 0)
6681 .fe_degree ==
static_cast<unsigned int>(fe_degree))
6683 proposed_dof_comp = no;
6684 proposed_fe_comp = nf;
6688 this->mapping_data->descriptor[this->active_quad_index]
6690 proposed_quad_comp = this->quadrature_index;
6692 for (
unsigned int no = 0;
6698 .descriptor[this->active_quad_index]
6699 .n_q_points == n_q_points)
6701 proposed_quad_comp = no;
6708 if (proposed_dof_comp != first_selected_component)
6709 message +=
"Wrong vector component selection:\n";
6711 message +=
"Wrong quadrature formula selection:\n";
6712 message +=
" Did you mean FEEvaluation<dim,";
6716 message +=
",Number>(data";
6726 std::string correct_pos;
6727 if (proposed_dof_comp != dof_handler_index)
6728 correct_pos =
" ^ ";
6731 if (proposed_quad_comp != this->quadrature_index)
6732 correct_pos +=
" ^ ";
6735 if (proposed_fe_comp != first_selected_component)
6736 correct_pos +=
" ^\n";
6738 correct_pos +=
" \n";
6745 const unsigned int proposed_n_q_points_1d =
static_cast<unsigned int>(
6746 std::pow(1.001 * this->n_quadrature_points, 1. / dim));
6747 message +=
"Wrong template arguments:\n";
6748 message +=
" Did you mean FEEvaluation<dim,";
6753 message +=
",Number>(data";
6763 std::string correct_pos;
6764 if (this->
data->data.front().fe_degree !=
6765 static_cast<unsigned int>(fe_degree))
6769 if (proposed_n_q_points_1d != n_q_points_1d)
6770 correct_pos +=
" ^\n";
6772 correct_pos +=
" \n";
6773 message +=
" " + correct_pos;
6775 Assert(
static_cast<unsigned int>(fe_degree) ==
6776 this->
data->data.front().fe_degree &&
6777 n_q_points == this->n_quadrature_points,
6783 this->mapping_data->descriptor[this->active_quad_index].n_q_points);
6794 typename VectorizedArrayType>
6803 Assert(this->matrix_free !=
nullptr,
6804 ExcMessage(
"FEEvaluation was initialized without a matrix-free object."
6805 " Integer indexing is not possible."));
6813 const unsigned int offsets =
6814 this->mapping_data->data_index_offsets[
cell_index];
6815 this->jacobian = &this->mapping_data->jacobians[0][offsets];
6816 this->J_value = &this->mapping_data->JxW_values[offsets];
6817 if (!this->mapping_data->jacobian_gradients[0].empty())
6819 this->jacobian_gradients =
6820 this->mapping_data->jacobian_gradients[0].data() + offsets;
6821 this->jacobian_gradients_non_inverse =
6822 this->mapping_data->jacobian_gradients_non_inverse[0].data() + offsets;
6828 for (
unsigned int i = 0; i < n_lanes; ++i)
6829 this->cell_ids[i] =
cell_index * n_lanes + i;
6836 this->cell_ids[i] =
cell_index * n_lanes + i;
6837 for (; i < n_lanes; ++i)
6841 if (this->mapping_data->quadrature_points.empty() ==
false)
6843 &this->mapping_data->quadrature_points
6844 [this->mapping_data->quadrature_point_offsets[this->cell]];
6848 this->is_reinitialized =
true;
6849 this->dof_values_initialized =
false;
6850 this->values_quad_initialized =
false;
6851 this->gradients_quad_initialized =
false;
6852 this->hessians_quad_initialized =
false;
6863 typename VectorizedArrayType>
6870 VectorizedArrayType>
::reinit(
const std::array<
unsigned int,
6877 this->cell_ids = cell_ids;
6882 for (
unsigned int v = 0; v < n_lanes; ++v)
6896 if (this->mapped_geometry ==
nullptr)
6897 this->mapped_geometry =
6898 std::make_shared<internal::MatrixFreeFunctions::
6899 MappingDataOnTheFly<dim, VectorizedArrayType>>();
6901 auto &mapping_storage = this->mapped_geometry->get_data_storage();
6903 auto &this_jacobian_data = mapping_storage.jacobians[0];
6904 auto &this_J_value_data = mapping_storage.JxW_values;
6905 auto &this_jacobian_gradients_data = mapping_storage.jacobian_gradients[0];
6906 auto &this_jacobian_gradients_non_inverse_data =
6907 mapping_storage.jacobian_gradients_non_inverse[0];
6908 auto &this_quadrature_points_data = mapping_storage.quadrature_points;
6912 if (this_jacobian_data.size() != 2)
6913 this_jacobian_data.resize_fast(2);
6915 if (this_J_value_data.size() != 1)
6916 this_J_value_data.resize_fast(1);
6918 const auto &update_flags_cells =
6922 this_jacobian_gradients_data.size() != 1)
6924 this_jacobian_gradients_data.resize_fast(1);
6925 this_jacobian_gradients_non_inverse_data.resize_fast(1);
6929 this_quadrature_points_data.size() != 1)
6930 this_quadrature_points_data.resize_fast(1);
6934 if (this_jacobian_data.size() != this->n_quadrature_points)
6935 this_jacobian_data.resize_fast(this->n_quadrature_points);
6937 if (this_J_value_data.size() != this->n_quadrature_points)
6938 this_J_value_data.resize_fast(this->n_quadrature_points);
6940 const auto &update_flags_cells =
6944 this_jacobian_gradients_data.size() != this->n_quadrature_points)
6946 this_jacobian_gradients_data.resize_fast(this->n_quadrature_points);
6947 this_jacobian_gradients_non_inverse_data.resize_fast(
6948 this->n_quadrature_points);
6952 this_quadrature_points_data.size() != this->n_quadrature_points)
6953 this_quadrature_points_data.resize_fast(this->n_quadrature_points);
6957 this->jacobian = this_jacobian_data.data();
6958 this->J_value = this_J_value_data.data();
6959 this->jacobian_gradients = this_jacobian_gradients_data.data();
6960 this->jacobian_gradients_non_inverse =
6961 this_jacobian_gradients_non_inverse_data.data();
6965 for (
unsigned int v = 0; v < n_lanes; ++v)
6972 const unsigned int cell_batch_index =
cell_index / n_lanes;
6973 const unsigned int offsets =
6974 this->mapping_data->data_index_offsets[cell_batch_index];
6975 const unsigned int lane =
cell_index % n_lanes;
6977 if (this->cell_type <=
6981 for (
unsigned int q = 0; q < 2; ++q)
6982 for (
unsigned int i = 0; i < dim; ++i)
6983 for (
unsigned int j = 0; j < dim; ++j)
6984 this_jacobian_data[q][i][j][v] =
6985 this->mapping_data->jacobians[0][offsets + q][i][j][lane];
6987 const unsigned int q = 0;
6989 this_J_value_data[q][v] =
6990 this->mapping_data->JxW_values[offsets + q][lane];
6992 const auto &update_flags_cells =
6997 for (
unsigned int i = 0; i < dim * (dim + 1) / 2; ++i)
6998 for (
unsigned int j = 0; j < dim; ++j)
6999 this_jacobian_gradients_data[q][i][j][v] =
7001 ->jacobian_gradients[0][offsets + q][i][j][lane];
7003 for (
unsigned int i = 0; i < dim * (dim + 1) / 2; ++i)
7004 for (
unsigned int j = 0; j < dim; ++j)
7005 this_jacobian_gradients_non_inverse_data[q][i][j][v] =
7007 ->jacobian_gradients_non_inverse[0][offsets + q][i][j]
7012 for (
unsigned int i = 0; i < dim; ++i)
7013 this_quadrature_points_data[q][i][v] =
7014 this->mapping_data->quadrature_points
7016 ->quadrature_point_offsets[cell_batch_index] +
7022 const auto cell_type =
7026 for (
unsigned int q = 0; q < this->n_quadrature_points; ++q)
7028 const unsigned int q_src =
7034 this_J_value_data[q][v] =
7035 this->mapping_data->JxW_values[offsets + q_src][lane];
7037 for (
unsigned int i = 0; i < dim; ++i)
7038 for (
unsigned int j = 0; j < dim; ++j)
7039 this_jacobian_data[q][i][j][v] =
7041 ->jacobians[0][offsets + q_src][i][j][lane];
7043 const auto &update_flags_cells =
7048 for (
unsigned int i = 0; i < dim * (dim + 1) / 2; ++i)
7049 for (
unsigned int j = 0; j < dim; ++j)
7050 this_jacobian_gradients_data[q][i][j][v] =
7052 ->jacobian_gradients[0][offsets + q_src][i][j][lane];
7054 for (
unsigned int i = 0; i < dim * (dim + 1) / 2; ++i)
7055 for (
unsigned int j = 0; j < dim; ++j)
7056 this_jacobian_gradients_non_inverse_data[q][i][j][v] =
7058 ->jacobian_gradients_non_inverse[0][offsets + q_src]
7071 this->mapping_data->quadrature_points
7073 ->quadrature_point_offsets[cell_batch_index] +
7077 this->mapping_data->jacobians[0][offsets + 1];
7079 for (
unsigned int d = 0;
d < dim; ++
d)
7083 this->descriptor->quadrature.point(q)[
d]);
7085 for (
unsigned int d = 0;
d < dim; ++
d)
7086 for (
unsigned int e = 0;
e < dim; ++
e)
7090 this->descriptor->quadrature.point(q)[
e]);
7092 for (
unsigned int i = 0; i < dim; ++i)
7093 this_quadrature_points_data[q][i][v] = point[i][lane];
7098 for (
unsigned int i = 0; i < dim; ++i)
7099 this_quadrature_points_data[q][i][v] =
7100 this->mapping_data->quadrature_points
7102 ->quadrature_point_offsets[cell_batch_index] +
7112 this->is_reinitialized =
true;
7113 this->dof_values_initialized =
false;
7114 this->values_quad_initialized =
false;
7115 this->gradients_quad_initialized =
false;
7116 this->hessians_quad_initialized =
false;
7127 typename VectorizedArrayType>
7128template <
bool level_dof_access>
7135 VectorizedArrayType>
::
7138 Assert(this->matrix_free ==
nullptr,
7139 ExcMessage(
"Cannot use initialization from cell iterator if "
7140 "initialized from MatrixFree object. Use variant for "
7141 "on the fly computation with arguments as for FEValues "
7144 this->mapped_geometry->reinit(
7146 this->local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
7147 if (level_dof_access)
7148 cell->get_mg_dof_indices(this->local_dof_indices);
7150 cell->get_dof_indices(this->local_dof_indices);
7154 this->is_reinitialized =
true;
7165 typename VectorizedArrayType>
7172 VectorizedArrayType>
::
7175 Assert(this->matrix_free == 0,
7176 ExcMessage(
"Cannot use initialization from cell iterator if "
7177 "initialized from MatrixFree object. Use variant for "
7178 "on the fly computation with arguments as for FEValues "
7181 this->mapped_geometry->reinit(cell);
7185 this->is_reinitialized =
true;
7196 typename VectorizedArrayType>
7203 VectorizedArrayType>::
7208 Assert(this->dof_values_initialized ==
true,
7211 evaluate(this->values_dofs, evaluation_flags);
7221 typename VectorizedArrayType>
7228 VectorizedArrayType>::
7229 evaluate(
const VectorizedArrayType *values_array,
7232 const bool hessians_on_general_cells =
7236 if (hessians_on_general_cells)
7239 if (this->
data->element_type ==
7245 if constexpr (fe_degree > -1)
7248 template run<fe_degree, n_q_points_1d>(n_components,
7249 evaluation_flag_actual,
7257 evaluation_flag_actual,
7258 const_cast<VectorizedArrayType *
>(values_array),
7264 this->values_quad_initialized =
7266 this->gradients_quad_initialized =
7268 this->hessians_quad_initialized =
7279 template <
typename Number,
7280 typename VectorizedArrayType,
7282 typename EvaluatorType,
7283 std::enable_if_t<internal::has_begin<VectorType> &&
7286 VectorizedArrayType *
7287 check_vector_access_inplace(
const EvaluatorType &fe_eval, VectorType &vector)
7293 const unsigned int cell = fe_eval.get_cell_or_face_batch_id();
7294 const auto &dof_info = fe_eval.get_dof_info();
7301 if (std::is_same_v<typename VectorType::value_type, Number> &&
7305 interleaved_contiguous &&
7306 reinterpret_cast<
std::size_t>(
7308 dof_info.dof_indices_contiguous
7309 [
internal::MatrixFreeFunctions::DoFInfo::dof_access_cell]
7310 [cell * VectorizedArrayType::
size()]) %
7311 sizeof(VectorizedArrayType) ==
7314 return reinterpret_cast<VectorizedArrayType *
>(
7318 [cell * VectorizedArrayType::size()] +
7320 [fe_eval.get_active_fe_index()]
7321 [fe_eval.get_first_selected_component()] *
7322 VectorizedArrayType::size());
7331 template <
typename Number,
7332 typename VectorizedArrayType,
7334 typename EvaluatorType,
7335 std::enable_if_t<!internal::has_begin<VectorType> ||
7338 VectorizedArrayType *
7339 check_vector_access_inplace(
const EvaluatorType &, VectorType &)
7352 typename VectorizedArrayType>
7353template <
typename VectorType>
7360 VectorizedArrayType>::
7361 gather_evaluate(
const VectorType &input_vector,
7364 const VectorizedArrayType *src_ptr =
7365 internal::check_vector_access_inplace<Number, const VectorizedArrayType>(
7366 *
this, input_vector);
7367 if (src_ptr !=
nullptr)
7368 evaluate(src_ptr, evaluation_flag);
7371 this->read_dof_values(input_vector);
7372 evaluate(this->begin_dof_values(), evaluation_flag);
7383 typename VectorizedArrayType>
7390 VectorizedArrayType>::
7393 integrate(integration_flag, this->values_dofs);
7397 this->dof_values_initialized =
true;
7408 typename VectorizedArrayType>
7415 VectorizedArrayType>::
7417 VectorizedArrayType *values_array,
7418 const bool sum_into_values_array)
7423 Assert(this->values_quad_submitted ==
true,
7426 Assert(this->gradients_quad_submitted ==
true,
7429 Assert(this->hessians_quad_submitted ==
true,
7432 Assert(this->matrix_free !=
nullptr ||
7433 this->mapped_geometry->is_initialized(),
7439 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, and "
7440 "EvaluationFlags::hessians are supported."));
7446 unsigned int size = n_components * dim * n_q_points;
7449 for (
unsigned int i = 0; i <
size; ++i)
7450 this->gradients_quad[i] += this->gradients_from_hessians_quad[i];
7454 for (
unsigned int i = 0; i <
size; ++i)
7455 this->gradients_quad[i] = this->gradients_from_hessians_quad[i];
7460 if (n_components == dim &&
7461 this->
data->element_type ==
7465 this->divergence_is_requested ==
false)
7467 unsigned int size = n_components * n_q_points;
7470 for (
unsigned int i = 0; i <
size; ++i)
7471 this->values_quad[i] += this->values_from_gradients_quad[i];
7475 for (
unsigned int i = 0; i <
size; ++i)
7476 this->values_quad[i] = this->values_from_gradients_quad[i];
7481 if constexpr (fe_degree > -1)
7484 template run<fe_degree, n_q_points_1d>(n_components,
7485 integration_flag_actual,
7488 sum_into_values_array);
7494 integration_flag_actual,
7497 sum_into_values_array);
7502 this->dof_values_initialized =
true;
7513 typename VectorizedArrayType>
7514template <
typename VectorType>
7521 VectorizedArrayType>::
7523 VectorType &destination)
7525 VectorizedArrayType *dst_ptr =
7526 internal::check_vector_access_inplace<Number, VectorizedArrayType>(
7527 *
this, destination);
7528 if (dst_ptr !=
nullptr)
7529 integrate(integration_flag, dst_ptr,
true);
7532 integrate(integration_flag, this->begin_dof_values());
7533 this->distribute_local_to_global(destination);
7544 typename VectorizedArrayType>
7551 VectorizedArrayType>::dof_indices()
const
7568 typename VectorizedArrayType>
7574 VectorizedArrayType>::
7577 const bool is_interior_face,
7578 const unsigned int dof_handler_index,
7579 const unsigned int quadrature_index,
7580 const unsigned int first_selected_component,
7581 const unsigned int active_fe_index,
7582 const unsigned int active_quad_index,
7583 const unsigned int face_type)
7584 : BaseClass(matrix_free,
7586 first_selected_component,
7594 , dofs_per_component(this->
data->dofs_per_component_on_cell)
7595 , dofs_per_cell(this->
data->dofs_per_component_on_cell * n_components_)
7596 , n_q_points(this->n_quadrature_points)
7606 typename VectorizedArrayType>
7612 VectorizedArrayType>::
7615 const std::pair<unsigned int, unsigned int> &range,
7616 const bool is_interior_face,
7617 const unsigned int dof_handler_index,
7618 const unsigned int quadrature_index,
7619 const unsigned int first_selected_component)
7624 first_selected_component,
7625 matrix_free.get_face_active_fe_index(range,
7628 matrix_free.get_face_info(range.
first).face_type)
7638 typename VectorizedArrayType>
7645 VectorizedArrayType>
::reinit(
const unsigned int face_index)
7647 Assert(this->mapped_geometry ==
nullptr,
7648 ExcMessage(
"FEEvaluation was initialized without a matrix-free object."
7649 " Integer indexing is not possible"));
7650 if (this->mapped_geometry !=
nullptr)
7653 this->cell = face_index;
7654 this->dof_access_index =
7655 this->is_interior_face() ?
7663 this->matrix_free->get_task_info().boundary_partition_data.back())
7664 Assert(this->is_interior_face(),
7666 "Boundary faces do not have a neighbor. When looping over "
7667 "boundary faces use FEFaceEvaluation with the parameter "
7668 "is_interior_face set to true. "));
7670 this->reinit_face(this->matrix_free->
get_face_info(face_index));
7675 this->face_ids[i] = face_index * n_lanes + i;
7676 for (; i < n_lanes; ++i)
7679 this->cell_type = this->matrix_free->
get_mapping_info().face_type[face_index];
7680 const unsigned int offsets =
7681 this->mapping_data->data_index_offsets[face_index];
7682 this->J_value = &this->mapping_data->JxW_values[offsets];
7683 this->normal_vectors = &this->mapping_data->normal_vectors[offsets];
7685 &this->mapping_data->jacobians[!this->is_interior_face()][offsets];
7686 this->normal_x_jacobian =
7688 ->normals_times_jacobians[!this->is_interior_face()][offsets];
7689 this->jacobian_gradients =
7690 this->mapping_data->jacobian_gradients[!this->is_interior_face()].data() +
7692 this->jacobian_gradients_non_inverse =
7694 ->jacobian_gradients_non_inverse[!this->is_interior_face()]
7698 if (this->mapping_data->quadrature_point_offsets.empty() ==
false)
7701 this->mapping_data->quadrature_point_offsets.size());
7703 this->mapping_data->quadrature_points.data() +
7704 this->mapping_data->quadrature_point_offsets[this->cell];
7709 this->is_reinitialized =
true;
7710 this->dof_values_initialized =
false;
7711 this->values_quad_initialized =
false;
7712 this->gradients_quad_initialized =
false;
7713 this->hessians_quad_initialized =
false;
7724 typename VectorizedArrayType>
7732 const unsigned int face_number)
7735 this->quadrature_index <
7738 "You must set MatrixFree::AdditionalData::mapping_update_flags_faces_by_cells to use the present reinit method."));
7742 Assert(this->mapped_geometry ==
nullptr,
7743 ExcMessage(
"FEEvaluation was initialized without a matrix-free object."
7744 " Integer indexing is not possible"));
7745 if (this->mapped_geometry !=
nullptr)
7750 .faces_by_cells_type[
cell_index][face_number];
7753 this->dof_access_index =
7756 if (this->is_interior_face() ==
false)
7761 for (
unsigned int i = 0; i < n_lanes; ++i)
7764 const unsigned int cell_this =
cell_index * n_lanes + i;
7766 unsigned int face_index =
7771 this->face_ids[i] = face_index;
7776 this->face_numbers[i] =
static_cast<std::uint8_t
>(-1);
7777 this->face_orientations[i] =
7785 auto cell_m = faces.cells_interior[face_index % n_lanes];
7786 auto cell_p = faces.cells_exterior[face_index % n_lanes];
7788 const bool face_identifies_as_interior = cell_m != cell_this;
7790 Assert(cell_m == cell_this || cell_p == cell_this,
7794 if (face_identifies_as_interior)
7796 this->cell_ids[i] = cell_m;
7797 this->face_numbers[i] = faces.interior_face_no;
7801 this->cell_ids[i] = cell_p;
7802 this->face_numbers[i] = faces.exterior_face_no;
7805 const bool orientation_interior_face = faces.face_orientation >= 8;
7807 faces.face_orientation % 8;
7808 if (face_identifies_as_interior != orientation_interior_face)
7811 ->reference_cell() ==
7812 ReferenceCells::get_hypercube<dim>(),
7816 .get_inverse_combined_orientation(face_orientation);
7818 this->face_orientations[i] = face_orientation;
7824 this->face_numbers[0] = face_number;
7829 for (
unsigned int i = 0; i < n_lanes; ++i)
7830 this->cell_ids[i] =
cell_index * n_lanes + i;
7838 this->cell_ids[i] =
cell_index * n_lanes + i;
7839 for (; i < n_lanes; ++i)
7842 for (
unsigned int i = 0; i < n_lanes; ++i)
7849 const unsigned int offsets =
7851 .face_data_by_cells[this->quadrature_index]
7856 .face_data_by_cells[this->quadrature_index]
7857 .JxW_values.size());
7859 .face_data_by_cells[this->quadrature_index]
7860 .JxW_values[offsets];
7862 .face_data_by_cells[this->quadrature_index]
7863 .normal_vectors[offsets];
7865 .face_data_by_cells[this->quadrature_index]
7866 .jacobians[!this->is_interior_face()][offsets];
7867 this->normal_x_jacobian =
7869 .face_data_by_cells[this->quadrature_index]
7870 .normals_times_jacobians[!this->is_interior_face()][offsets];
7871 this->jacobian_gradients =
7872 this->mapping_data->jacobian_gradients[!this->is_interior_face()].data() +
7874 this->jacobian_gradients_non_inverse =
7876 ->jacobian_gradients_non_inverse[!this->is_interior_face()]
7881 .face_data_by_cells[this->quadrature_index]
7882 .quadrature_point_offsets.empty() ==
false)
7884 const unsigned int index =
7888 .face_data_by_cells[this->quadrature_index]
7889 .quadrature_point_offsets.size());
7891 .face_data_by_cells[this->quadrature_index]
7892 .quadrature_points.data() +
7894 .face_data_by_cells[this->quadrature_index]
7895 .quadrature_point_offsets[
index];
7900 this->is_reinitialized =
true;
7901 this->dof_values_initialized =
false;
7902 this->values_quad_initialized =
false;
7903 this->gradients_quad_initialized =
false;
7904 this->hessians_quad_initialized =
false;
7915 typename VectorizedArrayType>
7922 VectorizedArrayType>::
7930 evaluate(this->values_dofs, evaluation_flag);
7940 typename VectorizedArrayType>
7947 VectorizedArrayType>::
7948 evaluate(
const VectorizedArrayType *values_array,
7951 Assert((evaluation_flag &
7954 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
7955 "and EvaluationFlags::hessians are supported."));
7957 const bool hessians_on_general_cells =
7961 if (hessians_on_general_cells)
7964 if (this->
data->element_type ==
7970 if constexpr (fe_degree > -1)
7972 template
run<fe_degree, n_q_points_1d>(n_components,
7973 evaluation_flag_actual,
7978 n_components, evaluation_flag_actual, values_array, *
this);
7982 this->values_quad_initialized =
7984 this->gradients_quad_initialized =
7986 this->hessians_quad_initialized =
7998 typename VectorizedArrayType>
8005 VectorizedArrayType>::
8013 project_to_face(this->values_dofs, evaluation_flag);
8023 typename VectorizedArrayType>
8030 VectorizedArrayType>::
8031 project_to_face(
const VectorizedArrayType *values_array,
8034 Assert((evaluation_flag &
8037 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
8038 "and EvaluationFlags::hessians are supported."));
8040 const bool hessians_on_general_cells =
8044 if (hessians_on_general_cells)
8047 if (this->
data->element_type ==
8053 if constexpr (fe_degree > -1)
8056 VectorizedArrayType>::template run<fe_degree>(n_components,
8057 evaluation_flag_actual,
8063 evaluation_flag_actual,
8077 typename VectorizedArrayType>
8084 VectorizedArrayType>::
8087 Assert((evaluation_flag &
8090 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
8091 "and EvaluationFlags::hessians are supported."));
8093 const bool hessians_on_general_cells =
8097 if (hessians_on_general_cells)
8100 if (this->
data->element_type ==
8106 if constexpr (fe_degree > -1)
8109 VectorizedArrayType>::template run<fe_degree>(n_components,
8110 evaluation_flag_actual,
8118 this->values_quad_initialized =
8120 this->gradients_quad_initialized =
8122 this->hessians_quad_initialized =
8134 typename VectorizedArrayType>
8141 VectorizedArrayType>::
8143 const bool sum_into_values)
8145 integrate(integration_flag, this->values_dofs, sum_into_values);
8149 this->dof_values_initialized =
true;
8160 typename VectorizedArrayType>
8167 VectorizedArrayType>::
8169 VectorizedArrayType *values_array,
8170 const bool sum_into_values)
8172 Assert((integration_flag &
8175 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
8176 "and EvaluationFlags::hessians are supported."));
8182 unsigned int size = n_components * dim * n_q_points;
8185 for (
unsigned int i = 0; i <
size; ++i)
8186 this->gradients_quad[i] += this->gradients_from_hessians_quad[i];
8190 for (
unsigned int i = 0; i <
size; ++i)
8191 this->gradients_quad[i] = this->gradients_from_hessians_quad[i];
8196 if (this->
data->element_type ==
8200 this->divergence_is_requested ==
false)
8202 unsigned int size = n_components * n_q_points;
8205 for (
unsigned int i = 0; i <
size; ++i)
8206 this->values_quad[i] += this->values_from_gradients_quad[i];
8210 for (
unsigned int i = 0; i <
size; ++i)
8211 this->values_quad[i] = this->values_from_gradients_quad[i];
8216 if constexpr (fe_degree > -1)
8218 template
run<fe_degree, n_q_points_1d>(n_components,
8219 integration_flag_actual,
8226 integration_flag_actual,
8239 typename VectorizedArrayType>
8246 VectorizedArrayType>::
8249 Assert((integration_flag &
8252 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
8253 "and EvaluationFlags::hessians are supported."));
8259 unsigned int size = n_components * dim * n_q_points;
8262 for (
unsigned int i = 0; i <
size; ++i)
8263 this->gradients_quad[i] += this->gradients_from_hessians_quad[i];
8267 for (
unsigned int i = 0; i <
size; ++i)
8268 this->gradients_quad[i] = this->gradients_from_hessians_quad[i];
8273 if (this->
data->element_type ==
8277 this->divergence_is_requested ==
false)
8279 unsigned int size = n_components * n_q_points;
8282 for (
unsigned int i = 0; i <
size; ++i)
8283 this->values_quad[i] += this->values_from_gradients_quad[i];
8287 for (
unsigned int i = 0; i <
size; ++i)
8288 this->values_quad[i] = this->values_from_gradients_quad[i];
8293 if constexpr (fe_degree > -1)
8296 VectorizedArrayType>::template run<fe_degree>(n_components,
8297 integration_flag_actual,
8313 typename VectorizedArrayType>
8320 VectorizedArrayType>::
8322 const bool sum_into_values)
8324 collect_from_face(integration_flag, this->values_dofs, sum_into_values);
8328 this->dof_values_initialized =
true;
8339 typename VectorizedArrayType>
8346 VectorizedArrayType>::
8348 VectorizedArrayType *values_array,
8349 const bool sum_into_values)
8351 Assert((integration_flag &
8354 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
8355 "and EvaluationFlags::hessians are supported."));
8362 if (this->
data->element_type ==
8366 this->divergence_is_requested ==
false)
8369 if constexpr (fe_degree > -1)
8372 VectorizedArrayType>::template run<fe_degree>(n_components,
8373 integration_flag_actual,
8380 integration_flag_actual,
8393 typename VectorizedArrayType>
8394template <
typename VectorType>
8401 VectorizedArrayType>::
8402 gather_evaluate(
const VectorType &input_vector,
8405 Assert((evaluation_flag &
8408 ExcMessage(
"Only EvaluationFlags::values, EvaluationFlags::gradients, "
8409 "and EvaluationFlags::hessians are supported."));
8411 const auto shared_vector_data = internal::get_shared_vector_data(
8413 this->dof_access_index ==
8415 this->active_fe_index,
8418 if (this->
data->data.front().fe_degree > 0 &&
8419 fast_evaluation_supported(this->
data->data.front().fe_degree,
8420 this->data->data.front().n_q_points_1d) &&
8423 typename VectorType::value_type,
8424 VectorizedArrayType>::
8425 supports(evaluation_flag,
8429 this->dof_info->index_storage_variants[this->dof_access_index]
8432 if constexpr (fe_degree > -1)
8436 typename VectorType::value_type,
8437 VectorizedArrayType>::template
run<fe_degree,
8441 internal::get_beginning<typename VectorType::value_type>(
8450 typename VectorType::value_type,
8451 VectorizedArrayType>::evaluate(n_components,
8453 internal::get_beginning<
8454 typename VectorType::value_type>(
8462 this->read_dof_values(input_vector);
8463 this->evaluate(evaluation_flag);
8469 this->gradients_quad_initialized =
8471 this->hessians_quad_initialized =
8483 typename VectorizedArrayType>
8484template <
typename VectorType>
8492 VectorizedArrayType>::integrate_scatter(
const bool integrate_values,
8493 const bool integrate_gradients,
8494 VectorType &destination)
8501 integrate_scatter(flag, destination);
8511 typename VectorizedArrayType>
8512template <
typename VectorType>
8519 VectorizedArrayType>::
8521 VectorType &destination)
8523 Assert((this->dof_access_index ==
8525 this->is_interior_face() ==
false) ==
false,
8528 const auto shared_vector_data = internal::get_shared_vector_data(
8530 this->dof_access_index ==
8532 this->active_fe_index,
8535 if (this->
data->data.front().fe_degree > 0 &&
8536 fast_evaluation_supported(this->
data->data.front().fe_degree,
8537 this->data->data.front().n_q_points_1d) &&
8540 typename VectorType::value_type,
8541 VectorizedArrayType>::
8542 supports(integration_flag,
8546 this->dof_info->index_storage_variants[this->dof_access_index]
8549 if constexpr (fe_degree > -1)
8553 typename VectorType::value_type,
8554 VectorizedArrayType>::template
run<fe_degree,
8558 internal::get_beginning<typename VectorType::value_type>(
8567 typename VectorType::value_type,
8568 VectorizedArrayType>::integrate(n_components,
8570 internal::get_beginning<
8571 typename VectorType::value_type>(
8579 integrate(integration_flag);
8580 this->distribute_local_to_global(destination);
8591 typename VectorizedArrayType>
8598 VectorizedArrayType>::dof_indices()
const
8611 typename VectorizedArrayType>
8618 VectorizedArrayType>::
8619 fast_evaluation_supported(
const unsigned int given_degree,
8620 const unsigned int given_n_q_points_1d)
8622 return fe_degree == -1 ?
8635 typename VectorizedArrayType>
8642 VectorizedArrayType>::
8643 fast_evaluation_supported(
const unsigned int given_degree,
8644 const unsigned int given_n_q_points_1d)
8646 return fe_degree == -1 ?
8659 typename VectorizedArrayType>
8666 VectorizedArrayType>::at_boundary()
const
8668 Assert(this->dof_access_index !=
8672 if (this->is_interior_face() ==
false)
8677 this->matrix_free->n_boundary_face_batches()))
8690 typename VectorizedArrayType>
8697 VectorizedArrayType>::boundary_id()
const
8699 Assert(this->dof_access_index !=
8716 typename VectorizedArrayType>
8724 VectorizedArrayType>::get_dofs_per_component_projected_to_face()
8726 return this->
data->dofs_per_component_on_face;
8736 typename VectorizedArrayType>
8743 VectorizedArrayType>::get_dofs_projected_to_face()
8745 return this->
data->dofs_per_component_on_face * n_components_;
value_type get_dof_value(const unsigned int dof) const
void read_write_operation_global(const VectorOperation &operation, const std::array< VectorType *, n_components_ > &vectors) const
value_type get_laplacian(const unsigned int q_point) const
AlignedVector< VectorizedArrayType > * scratch_data_array
gradient_type get_gradient(const unsigned int q_point) const
void submit_gradient(const Tensor< 2, 1, VectorizedArrayType > val_in, const unsigned int q_point)
void submit_normal_hessian(const value_type normal_hessian_in, const unsigned int q_point)
internal::CurlType< dim, VectorizedArrayType > curl_type
static constexpr unsigned int dimension
void read_write_operation(const VectorOperation &operation, const std::array< VectorType *, n_components_ > &vectors, const std::array< const std::vector< ArrayView< const typename VectorType::value_type > > *, n_components_ > &vectors_sm, const std::bitset< n_lanes > &mask, const bool apply_constraints=true) const
void submit_gradient(const gradient_type grad_in, const unsigned int q_point)
void submit_value(const value_type val_in, const unsigned int q_point)
void submit_divergence(const VectorizedArrayType div_in, const unsigned int q_point)
void submit_dof_value(const value_type val_in, const unsigned int dof)
std::vector< types::global_dof_index > local_dof_indices
void distribute_local_to_global(VectorType &dst, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip()) const
std::conditional_t< n_components_==1, Tensor< 2, dim, VectorizedArrayType >, std::conditional_t< n_components_==dim, Tensor< 3, dim, VectorizedArrayType >, Tensor< 1, n_components_, Tensor< 2, dim, VectorizedArrayType > > > > hessian_type
std::conditional_t< n_components_==1, Tensor< 1, dim, VectorizedArrayType >, std::conditional_t< n_components_==dim, Tensor< 2, dim, VectorizedArrayType >, Tensor< 1, n_components_, Tensor< 1, dim, VectorizedArrayType > > > > gradient_type
FEEvaluationBase(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const unsigned int dof_handler_index, const unsigned int first_selected_component, const unsigned int quadrature_index, const unsigned int fe_degree, const unsigned int n_q_points, const bool is_interior_face, const unsigned int active_fe_index, const unsigned int active_quad_index, const unsigned int face_type)
void read_dof_values_plain(const VectorType &src, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
curl_type get_curl(const unsigned int q_point) const
VectorizedArrayType get_divergence(const unsigned int q_point) const
hessian_type get_hessian(const unsigned int q_point) const
FEEvaluationBase(const Mapping< dim > &mapping, const FiniteElement< dim > &fe, const Quadrature< 1 > &quadrature, const UpdateFlags update_flags, const unsigned int first_selected_component, const FEEvaluationData< dim, VectorizedArrayType, is_face > *other)
void submit_curl(const curl_type curl_in, const unsigned int q_point)
FEEvaluationBase & operator=(const FEEvaluationBase &other)
SymmetricTensor< 2, dim, VectorizedArrayType > get_symmetric_gradient(const unsigned int q_point) const
static constexpr unsigned int n_components
void submit_symmetric_gradient(const SymmetricTensor< 2, dim, VectorizedArrayType > grad_in, const unsigned int q_point)
gradient_type get_hessian_diagonal(const unsigned int q_point) const
void submit_value(const Tensor< 1, 1, VectorizedArrayType > val_in, const unsigned int q_point)
std::conditional_t< n_components_==1, VectorizedArrayType, Tensor< 1, n_components_, VectorizedArrayType > > value_type
const MatrixFree< dim, Number, VectorizedArrayType > & get_matrix_free() const
void apply_hanging_node_constraints(const bool transpose) const
void set_dof_values_plain(VectorType &dst, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip()) const
void submit_normal_derivative(const value_type grad_in, const unsigned int q_point)
void read_write_operation_contiguous(const VectorOperation &operation, const std::array< VectorType *, n_components_ > &vectors, const std::array< const std::vector< ArrayView< const typename VectorType::value_type > > *, n_components_ > &vectors_sm, const std::bitset< n_lanes > &mask) const
value_type integrate_value() const
FEEvaluationBase(const FEEvaluationBase &other)
void submit_hessian(const hessian_type hessian_in, const unsigned int q_point)
void set_dof_values(VectorType &dst, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip()) const
static constexpr unsigned int n_lanes
const MatrixFree< dim, Number, VectorizedArrayType > * matrix_free
value_type get_normal_derivative(const unsigned int q_point) const
value_type get_value(const unsigned int q_point) const
value_type get_normal_hessian(const unsigned int q_point) const
void read_dof_values(const VectorType &src, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
const MappingInfoStorageType::QuadratureDescriptor * descriptor
const MappingInfoStorageType * mapping_data
const ShapeInfoType * data
std::shared_ptr< internal::MatrixFreeFunctions::MappingDataOnTheFly< dim, Number > > mapped_geometry
const unsigned int active_fe_index
std::array< unsigned int, n_lanes > cell_ids
const unsigned int active_quad_index
const unsigned int quadrature_index
bool is_interior_face() const
FEEvaluationData & operator=(const FEEvaluationData &other)
const unsigned int first_selected_component
const unsigned int dofs_per_component
std_cxx20::ranges::iota_view< unsigned int, unsigned int > dof_indices() const
FEEvaluation(const Mapping< dim > &mapping, const FiniteElement< dim > &fe, const Quadrature< 1 > &quadrature, const UpdateFlags update_flags, const unsigned int first_selected_component=0)
const unsigned int n_q_points
FEEvaluation(const FiniteElement< dim > &fe, const Quadrature< 1 > &quadrature, const UpdateFlags update_flags, const unsigned int first_selected_component=0)
void reinit(const typename Triangulation< dim >::cell_iterator &cell)
static bool fast_evaluation_supported(const unsigned int given_degree, const unsigned int given_n_q_points_1d)
void integrate_scatter(const EvaluationFlags::EvaluationFlags integration_flag, VectorType &output_vector)
void reinit(const unsigned int cell_batch_index)
void reinit(const std::array< unsigned int, n_lanes > &cell_ids)
FEEvaluation(const FiniteElement< dim > &fe, const FEEvaluationData< dim, VectorizedArrayType, false > &other, const unsigned int first_selected_component=0)
void reinit(const TriaIterator< DoFCellAccessor< dim, dim, level_dof_access > > &cell)
void evaluate(const EvaluationFlags::EvaluationFlags evaluation_flag)
FEEvaluation(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const unsigned int dof_handler_index=0, const unsigned int quadrature_index=0, const unsigned int first_selected_component=0, const unsigned int active_fe_index=numbers::invalid_unsigned_int, const unsigned int active_quad_index=numbers::invalid_unsigned_int)
static constexpr unsigned int tensor_dofs_per_cell
void evaluate(const VectorizedArrayType *values_array, const EvaluationFlags::EvaluationFlags evaluation_flag)
typename BaseClass::gradient_type gradient_type
void integrate(const EvaluationFlags::EvaluationFlags integration_flag, VectorizedArrayType *values_array, const bool sum_into_values=false)
FEEvaluation(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const std::pair< unsigned int, unsigned int > &range, const unsigned int dof_handler_index=0, const unsigned int quadrature_index=0, const unsigned int first_selected_component=0)
static constexpr unsigned int dimension
void gather_evaluate(const VectorType &input_vector, const EvaluationFlags::EvaluationFlags evaluation_flag)
const unsigned int dofs_per_cell
static constexpr unsigned int static_dofs_per_cell
typename BaseClass::value_type value_type
FEEvaluation & operator=(const FEEvaluation &other)
void integrate(const EvaluationFlags::EvaluationFlags integration_flag)
static constexpr unsigned int n_components
static constexpr unsigned int static_n_q_points
static constexpr unsigned int n_lanes
FEEvaluation(const FEEvaluation &other)
void check_template_arguments(const unsigned int fe_no, const unsigned int first_selected_component)
static constexpr unsigned int static_dofs_per_component
typename BaseClass::value_type value_type
std_cxx20::ranges::iota_view< unsigned int, unsigned int > dof_indices() const
void integrate(const EvaluationFlags::EvaluationFlags integration_flag, VectorizedArrayType *values_array, const bool sum_into_values=false)
FEFaceEvaluation(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const std::pair< unsigned int, unsigned int > &range, const bool is_interior_face=true, const unsigned int dof_handler_index=0, const unsigned int quadrature_index=0, const unsigned int first_selected_component=0)
void collect_from_face(const EvaluationFlags::EvaluationFlags integration_flag, VectorizedArrayType *values_array, const bool sum_into_values=false)
void integrate_scatter(const EvaluationFlags::EvaluationFlags integration_flag, VectorType &output_vector)
static constexpr unsigned int static_n_q_points_cell
void project_to_face(const EvaluationFlags::EvaluationFlags evaluation_flag)
static constexpr unsigned int tensor_dofs_per_cell
unsigned int get_dofs_per_component_projected_to_face()
void project_to_face(const VectorizedArrayType *values_array, const EvaluationFlags::EvaluationFlags evaluation_flag)
const unsigned int dofs_per_component
void reinit(const unsigned int face_batch_number)
const unsigned int n_q_points
void gather_evaluate(const VectorType &input_vector, const EvaluationFlags::EvaluationFlags evaluation_flag)
void reinit(const unsigned int cell_batch_number, const unsigned int face_number)
static bool fast_evaluation_supported(const unsigned int given_degree, const unsigned int given_n_q_points_1d)
void evaluate(const VectorizedArrayType *values_array, const EvaluationFlags::EvaluationFlags evaluation_flag)
const unsigned int dofs_per_cell
static constexpr unsigned int n_components
FEFaceEvaluation(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const bool is_interior_face=true, const unsigned int dof_handler_index=0, const unsigned int quadrature_index=0, const unsigned int first_selected_component=0, const unsigned int active_fe_index=numbers::invalid_unsigned_int, const unsigned int active_quad_index=numbers::invalid_unsigned_int, const unsigned int face_type=numbers::invalid_unsigned_int)
void evaluate(const EvaluationFlags::EvaluationFlags evaluation_flag)
void collect_from_face(const EvaluationFlags::EvaluationFlags integration_flag, const bool sum_into_values=false)
static constexpr unsigned int static_dofs_per_component
static constexpr unsigned int n_lanes
static constexpr unsigned int static_n_q_points
unsigned int get_dofs_projected_to_face()
static constexpr unsigned int dimension
typename BaseClass::gradient_type gradient_type
types::boundary_id boundary_id() const
void integrate(const EvaluationFlags::EvaluationFlags integration_flag, const bool sum_into_values=false)
void evaluate_in_face(const EvaluationFlags::EvaluationFlags evaluation_flag)
void integrate_scatter(const bool integrate_values, const bool integrate_gradients, VectorType &output_vector)
static constexpr unsigned int static_dofs_per_cell
void integrate_in_face(const EvaluationFlags::EvaluationFlags integration_flag)
std::pair< unsigned int, unsigned int > component_to_base_index(const unsigned int component) const
unsigned int element_multiplicity(const unsigned int index) const
Abstract base class for mapping classes.
const internal::MatrixFreeFunctions::TaskInfo & get_task_info() const
types::boundary_id get_boundary_id(const unsigned int face_batch_index) const
const Table< 3, unsigned int > & get_cell_and_face_to_plain_faces() const
unsigned int n_inner_face_batches() const
unsigned int n_active_entries_per_cell_batch(const unsigned int cell_batch_index) const
const internal::MatrixFreeFunctions::FaceToCellTopology< VectorizedArrayType::size()> & get_face_info(const unsigned int face_batch_index) const
const internal::MatrixFreeFunctions::DoFInfo & get_dof_info(const unsigned int dof_handler_index_component=0) const
AlignedVector< VectorizedArrayType > * acquire_scratch_data() const
const Number * constraint_pool_begin(const unsigned int pool_index) const
void release_scratch_data(const AlignedVector< VectorizedArrayType > *memory) const
DoFHandler< dim >::cell_iterator get_cell_iterator(const unsigned int cell_batch_index, const unsigned int lane_index, const unsigned int dof_handler_index=0) const
const internal::MatrixFreeFunctions::MappingInfo< dim, Number, VectorizedArrayType > & get_mapping_info() const
bool indices_initialized() const
const Number * constraint_pool_end(const unsigned int pool_index) const
unsigned int n_components() const
unsigned int n_active_entries_per_face_batch(const unsigned int face_batch_index) const
const internal::MatrixFreeFunctions::ShapeInfo< Number > & get_shape_info(const unsigned int dof_handler_index_component=0, const unsigned int quad_index=0, const unsigned int fe_base_element=0, const unsigned int hp_active_fe_index=0, const unsigned int hp_active_quad_index=0) const
unsigned int n_base_elements(const unsigned int dof_handler_index) const
constexpr const Number & access_raw_entry(const unsigned int unrolled_index) const
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_OPENMP_SIMD_PRAGMA
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcAccessToUninitializedField()
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMatrixFreeAccessToUninitializedMappingField(std::string arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
@ update_jacobian_grads
Gradient of volume element.
@ update_quadrature_points
Transformed quadrature points.
std::vector< index_type > data
The namespace for the EvaluationFlags enum.
EvaluationFlags
The EvaluationFlags enum.
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
std::enable_if_t< IsBlockVector< VectorType >::value, unsigned int > n_blocks(const VectorType &vector)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
void quadrature_points(const Triangulation< dim, spacedim > &triangulation, const Quadrature< dim > &quadrature, const std::vector< std::vector< BoundingBox< spacedim > > > &global_bounding_boxes, ParticleHandler< dim, spacedim > &particle_handler, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< spacedim >()), const std::vector< std::vector< double > > &properties={})
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
* * * ScaleZFunction< dim, Number, components >::ScaleZFunction * component(component)
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
* * * * * * TimeRateUpdateFlags TimeRateRequest< ValueType, dim, Number > get_update_flags() const
* * * * std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters const
constexpr const ReferenceCell< dim > & get_hypercube()
T sum(const T &t, const MPI_Comm mpi_communicator)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
constexpr T pow(const T base, const int iexp)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
constexpr compressed_constraint_kind unconstrained_compressed_constraint_kind
std::conditional_t< dim==3, Tensor< 1, 3, NumberType >, std::conditional_t< dim==2, NumberType, std::monostate > > CurlType
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
void check_vector_compatibility(const VectorType &vec, const MatrixFree< dim, Number, VectorizedArrayType > &, const internal::MatrixFreeFunctions::DoFInfo &dof_info)
constexpr types::geometric_orientation invalid_geometric_orientation
constexpr unsigned int invalid_unsigned_int
constexpr types::boundary_id internal_face_boundary_id
constexpr types::geometric_orientation default_geometric_orientation
boost::integer_range< IncrementableType > iota_view
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
std::uint8_t geometric_orientation
static bool fast_evaluation_supported(const unsigned int given_degree, const unsigned int n_q_points_1d)
static void evaluate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval)
static void integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, Number *values_dofs, FEEvaluationData< dim, Number, false > &fe_eval, const bool sum_into_values_array)
static void apply(const unsigned int n_components, const unsigned int fe_degree, const MatrixFreeFunctions::ShapeInfo< Number > &shape_info, const bool transpose, const std::array< MatrixFreeFunctions::compressed_constraint_kind, VectorizedArrayType::size()> &c_mask, VectorizedArrayType *values)
static void integrate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, Number *values_dofs, FEEvaluationData< dim, Number, true > &fe_eval, const bool sum_into_values)
static void evaluate(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const Number *values_dofs, FEEvaluationData< dim, Number, true > &fe_eval)
static bool fast_evaluation_supported(const unsigned int given_degree, const unsigned int n_q_points_1d)
static void evaluate_in_face(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, FEEvaluationData< dim, Number, true > &fe_eval)
static void integrate_in_face(const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, FEEvaluationData< dim, Number, true > &fe_eval)
static void collect_from_face(const unsigned int n_components, const EvaluationFlags::EvaluationFlags integration_flag, Number *values_dofs, FEEvaluationData< dim, Number, true > &fe_eval, const bool sum_into_values)
static void project_to_face(const unsigned int n_components, const EvaluationFlags::EvaluationFlags evaluation_flag, const Number *values_dofs, FEEvaluationData< dim, Number, true > &fe_eval)
static constexpr unsigned int value
@ dof_access_face_exterior
@ dof_access_face_interior
std::vector< std::pair< unsigned short, unsigned short > > constraint_indicator
std::vector< std::pair< unsigned int, unsigned int > > row_starts
std::vector< std::vector< unsigned int > > component_dof_indices_offset
unsigned int fe_index_from_degree(const unsigned int first_selected_component, const unsigned int fe_degree) const
std::vector< unsigned int > dof_indices
std::vector< compressed_constraint_kind > hanging_node_constraint_masks
std::array< std::vector< unsigned int >, 3 > dof_indices_interleave_strides
std::array< std::vector< std::pair< unsigned int, unsigned int > >, 3 > dof_indices_contiguous_sm
std::vector< unsigned int > row_starts_plain_indices
std::vector< unsigned int > component_to_base_index
std::array< std::vector< unsigned int >, 3 > dof_indices_contiguous
std::vector< unsigned int > plain_dof_indices
std::array< std::vector< unsigned char >, 3 > n_vectorization_lanes_filled
std::vector< unsigned int > dof_indices_interleaved
std::array< std::vector< IndexStorageVariants >, 3 > index_storage_variants
std::vector< QuadratureDescriptor > descriptor
unsigned int quad_index_from_n_q_points(const unsigned int n_q_points) const
std::vector< unsigned int > face_partition_data
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)