2458 const unsigned int n_components,
2460 typename Processor::Number2_ *global_vector_ptr,
2462 const EvaluationData &fe_eval,
2463 typename Processor::VectorizedArrayType_ *temp1)
2465 constexpr int dim = Processor::dim_;
2466 constexpr int fe_degree = Processor::fe_degree_;
2467 using VectorizedArrayType =
typename Processor::VectorizedArrayType_;
2468 constexpr int n_lanes = VectorizedArrayType::size();
2470 using Number =
typename Processor::Number_;
2471 using Number2_ =
typename Processor::Number2_;
2473 const auto &shape_data = fe_eval.get_shape_info().data.front();
2474 constexpr bool integrate = Processor::do_integrate;
2475 const unsigned int face_no = fe_eval.get_face_no();
2476 const auto &dof_info = fe_eval.get_dof_info();
2477 const unsigned int cell = fe_eval.get_cell_or_face_batch_id();
2479 fe_eval.get_dof_access_index();
2481 dof_info.index_storage_variants[dof_access_index].size());
2482 constexpr unsigned int dofs_per_face =
2484 const unsigned int subface_index = fe_eval.get_subface_index();
2486 const unsigned int n_filled_lanes =
2487 dof_info.n_vectorization_lanes_filled[dof_access_index][cell];
2489 bool all_faces_are_same = n_filled_lanes == n_lanes;
2490 if (n_face_orientations == n_lanes)
2491 for (
unsigned int v = 1; v < n_lanes; ++v)
2492 if (fe_eval.get_face_no(v) != fe_eval.get_face_no(0) ||
2493 fe_eval.get_face_orientation(v) != fe_eval.get_face_orientation(0))
2495 all_faces_are_same =
false;
2500 std::array<const unsigned int *, n_face_orientations> orientation = {};
2502 if (dim == 3 && n_face_orientations == n_lanes && !all_faces_are_same &&
2503 fe_eval.is_interior_face() == 0)
2504 for (
unsigned int v = 0; v < n_lanes; ++v)
2512 if (shape_data.nodal_at_cell_boundaries &&
2513 fe_eval.get_face_orientation(v) != 0)
2518 check_face_orientations ==
false)
2532 orientation[v] = &fe_eval.get_shape_info().face_orientations_dofs(
2533 fe_eval.get_face_orientation(v), 0);
2536 else if (dim == 3 && fe_eval.get_face_orientation() != 0)
2540 check_face_orientations ==
false)
2554 for (
unsigned int v = 0; v < n_face_orientations; ++v)
2555 orientation[v] = &fe_eval.get_shape_info().face_orientations_dofs(
2556 fe_eval.get_face_orientation(), 0);
2562 VectorizedArrayType grad_weight =
2564 .shape_data_on_face[0][fe_degree + (integrate ? (2 - face_no % 2) :
2565 (1 + face_no % 2))];
2568 std::array<const unsigned int *, n_face_orientations> index_array_hermite =
2572 if (n_face_orientations == 1)
2573 index_array_hermite[0] =
2574 &fe_eval.get_shape_info().face_to_cell_index_hermite(face_no, 0);
2577 for (
unsigned int v = 0; v < n_lanes; ++v)
2582 const auto face_no = fe_eval.get_face_no(v);
2586 .shape_data_on_face[0][fe_degree + (integrate ?
2587 (2 - (face_no % 2)) :
2588 (1 + (face_no % 2)))];
2590 index_array_hermite[v] =
2591 &fe_eval.get_shape_info().face_to_cell_index_hermite(face_no,
2598 std::array<const unsigned int *, n_face_orientations> index_array_nodal =
2600 if (shape_data.nodal_at_cell_boundaries ==
true)
2602 if (n_face_orientations == 1)
2603 index_array_nodal[0] =
2604 &fe_eval.get_shape_info().face_to_cell_index_nodal(face_no, 0);
2607 for (
unsigned int v = 0; v < n_lanes; ++v)
2612 const auto face_no = fe_eval.get_face_no(v);
2614 index_array_nodal[v] =
2615 &fe_eval.get_shape_info().face_to_cell_index_nodal(face_no,
2622 const auto reorientate = [&](
const unsigned int v,
const unsigned int i) {
2623 return (!check_face_orientations || orientation[v] ==
nullptr) ?
2630 fe_eval.get_cell_ids()[0] :
2632 const unsigned int *dof_indices =
2633 &dof_info.dof_indices_contiguous[dof_access_index][
cell_index];
2635 for (
unsigned int comp = 0; comp < n_components; ++comp)
2637 const std::size_t index_offset =
2638 dof_info.component_dof_indices_offset
2639 [fe_eval.get_active_fe_index()]
2640 [fe_eval.get_first_selected_component()] +
2644 if (n_face_orientations == 1 &&
2645 dof_info.index_storage_variants[dof_access_index][cell] ==
2647 interleaved_contiguous)
2650 dof_info.n_vectorization_lanes_filled[dof_access_index][cell],
2652 Number2_ *vector_ptr =
2653 global_vector_ptr + dof_indices[0] + index_offset * n_lanes;
2657 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2661 const unsigned int ind1 = index_array_hermite[0][2 * i];
2662 const unsigned int ind2 = index_array_hermite[0][2 * i + 1];
2663 const unsigned int i_ = reorientate(0, i);
2664 proc.hermite_grad_vectorized(temp1[i_],
2665 temp1[i_ + dofs_per_face],
2666 vector_ptr + ind1 * n_lanes,
2667 vector_ptr + ind2 * n_lanes,
2673 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2677 const unsigned int i_ = reorientate(0, i);
2678 const unsigned int ind = index_array_nodal[0][i];
2679 proc.value_vectorized(temp1[i_],
2680 vector_ptr + ind * n_lanes);
2686 else if (n_face_orientations == 1 &&
2687 dof_info.index_storage_variants[dof_access_index][cell] ==
2689 interleaved_contiguous_strided)
2692 dof_info.n_vectorization_lanes_filled[dof_access_index][cell],
2694 Number2_ *vector_ptr = global_vector_ptr + index_offset * n_lanes;
2697 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2701 const unsigned int i_ = reorientate(0, i);
2702 const unsigned int ind1 =
2703 index_array_hermite[0][2 * i] * n_lanes;
2704 const unsigned int ind2 =
2705 index_array_hermite[0][2 * i + 1] * n_lanes;
2706 proc.hermite_grad_vectorized_indexed(
2708 temp1[i_ + dofs_per_face],
2718 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2722 const unsigned int i_ = reorientate(0, i);
2723 const unsigned int ind = index_array_nodal[0][i] * n_lanes;
2724 proc.value_vectorized_indexed(temp1[i_],
2732 else if (n_face_orientations == 1 &&
2733 dof_info.index_storage_variants[dof_access_index][cell] ==
2735 interleaved_contiguous_mixed_strides)
2737 const unsigned int *strides =
2738 &dof_info.dof_indices_interleave_strides[dof_access_index]
2740 unsigned int indices[n_lanes];
2741 for (
unsigned int v = 0; v < n_lanes; ++v)
2742 indices[v] = dof_indices[v] + index_offset * strides[v];
2743 const unsigned int n_filled_lanes =
2744 dof_info.n_vectorization_lanes_filled[dof_access_index][cell];
2748 if (n_filled_lanes == n_lanes)
2749 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2753 const unsigned int i_ = reorientate(0, i);
2754 unsigned int ind1[n_lanes];
2756 for (
unsigned int v = 0; v < n_lanes; ++v)
2757 ind1[v] = indices[v] +
2758 index_array_hermite[0][2 * i] * strides[v];
2759 unsigned int ind2[n_lanes];
2761 for (
unsigned int v = 0; v < n_lanes; ++v)
2765 index_array_hermite[0][2 * i + 1] * strides[v];
2766 proc.hermite_grad_vectorized_indexed(
2768 temp1[i_ + dofs_per_face],
2777 if (integrate ==
false)
2778 for (
unsigned int i = 0; i < 2 * dofs_per_face; ++i)
2779 temp1[i] = VectorizedArrayType();
2781 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2782 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2784 const unsigned int i_ =
2785 reorientate(n_face_orientations == 1 ? 0 : v, i);
2788 temp1[i_ + dofs_per_face][v],
2792 [n_face_orientations == 1 ? 0 : v][2 * i] *
2796 index_array_hermite[n_face_orientations == 1 ?
2800 grad_weight[n_face_orientations == 1 ? 0 : v]);
2806 if (n_filled_lanes == n_lanes)
2807 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2810 unsigned int ind[n_lanes];
2812 for (
unsigned int v = 0; v < n_lanes; ++v)
2814 indices[v] + index_array_nodal[0][i] * strides[v];
2815 const unsigned int i_ = reorientate(0, i);
2816 proc.value_vectorized_indexed(temp1[i_],
2822 if (integrate ==
false)
2823 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2824 temp1[i] = VectorizedArrayType();
2826 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2827 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2829 temp1[reorientate(n_face_orientations == 1 ? 0 : v,
2833 index_array_nodal[n_face_orientations == 1 ? 0 : v]
2841 else if (n_face_orientations > 1 ||
2842 dof_info.index_storage_variants[dof_access_index][cell] ==
2846 Number2_ *vector_ptr = global_vector_ptr + index_offset;
2848 const bool vectorization_possible =
2849 all_faces_are_same && (sm_ptr ==
nullptr);
2851 std::array<Number2_ *, n_lanes> vector_ptrs{{
nullptr}};
2852 std::array<unsigned int, n_lanes> reordered_indices{
2855 if (vectorization_possible ==
false)
2857 if (n_face_orientations == 1)
2859 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2860 if (sm_ptr ==
nullptr)
2862 vector_ptrs[v] = vector_ptr + dof_indices[v];
2868 .dof_indices_contiguous_sm[dof_access_index]
2869 [cell * n_lanes + v];
2870 vector_ptrs[v] =
const_cast<Number2_ *
>(
2871 sm_ptr->operator[](temp.first).
data() +
2872 temp.second + index_offset);
2875 else if (n_face_orientations == n_lanes)
2877 const auto &cells = fe_eval.get_cell_ids();
2878 for (
unsigned int v = 0; v < n_lanes; ++v)
2881 if (sm_ptr ==
nullptr)
2886 .dof_indices_contiguous[dof_access_index]
2893 .dof_indices_contiguous_sm[dof_access_index]
2895 vector_ptrs[v] =
const_cast<Number2_ *
>(
2896 sm_ptr->operator[](temp.first).
data() +
2897 temp.second + index_offset);
2906 else if (n_face_orientations == n_lanes)
2908 for (
unsigned int v = 0; v < n_lanes; ++v)
2909 reordered_indices[v] =
2910 dof_info.dof_indices_contiguous[dof_access_index]
2911 [fe_eval.get_cell_ids()[v]];
2912 dof_indices = reordered_indices.data();
2917 if (vectorization_possible)
2918 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2920 const unsigned int ind1 = index_array_hermite[0][2 * i];
2921 const unsigned int ind2 =
2922 index_array_hermite[0][2 * i + 1];
2923 const unsigned int i_ = reorientate(0, i);
2925 proc.hermite_grad_vectorized_indexed(
2927 temp1[i_ + dofs_per_face],
2934 else if (n_face_orientations == 1)
2935 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2937 const unsigned int ind1 = index_array_hermite[0][2 * i];
2938 const unsigned int ind2 =
2939 index_array_hermite[0][2 * i + 1];
2940 const unsigned int i_ = reorientate(0, i);
2942 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2943 proc.hermite_grad(temp1[i_][v],
2944 temp1[i_ + dofs_per_face][v],
2945 vector_ptrs[v][ind1],
2946 vector_ptrs[v][ind2],
2949 if (integrate ==
false)
2950 for (
unsigned int v = n_filled_lanes; v < n_lanes; ++v)
2953 temp1[i + dofs_per_face][v] = 0.0;
2958 if (integrate ==
false && n_filled_lanes < n_lanes)
2959 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2960 temp1[i] = temp1[i + dofs_per_face] = Number();
2962 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2963 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2965 temp1[reorientate(v, i)][v],
2966 temp1[reorientate(v, i) + dofs_per_face][v],
2967 vector_ptrs[v][index_array_hermite[v][2 * i]],
2968 vector_ptrs[v][index_array_hermite[v][2 * i + 1]],
2974 if (vectorization_possible)
2975 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2977 const unsigned int ind = index_array_nodal[0][i];
2978 const unsigned int i_ = reorientate(0, i);
2980 proc.value_vectorized_indexed(temp1[i_],
2986 if constexpr (n_face_orientations == 1)
2987 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2989 const unsigned int ind = index_array_nodal[0][i];
2990 const unsigned int i_ = reorientate(0, i);
2992 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2993 proc.value(temp1[i_][v], vector_ptrs[v][ind]);
2995 if constexpr (integrate ==
false)
2996 for (
unsigned int v = n_filled_lanes; v < n_lanes;
3002 if (integrate ==
false && n_filled_lanes < n_lanes)
3003 for (
unsigned int i = 0; i < dofs_per_face; ++i)
3004 temp1[i] = Number();
3006 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
3007 for (
unsigned int i = 0; i < dofs_per_face; ++i)
3008 proc.value(temp1[reorientate(v, i)][v],
3009 vector_ptrs[v][index_array_nodal[v][i]]);
3020 temp1 += 3 * dofs_per_face;