2306 const unsigned int n_components,
2308 typename Processor::Number2_ *global_vector_ptr,
2310 const EvaluationData &fe_eval,
2311 typename Processor::VectorizedArrayType_ *temp1)
2313 constexpr int dim = Processor::dim_;
2314 constexpr int fe_degree = Processor::fe_degree_;
2315 using VectorizedArrayType =
typename Processor::VectorizedArrayType_;
2316 constexpr int n_lanes = VectorizedArrayType::size();
2318 using Number =
typename Processor::Number_;
2319 using Number2_ =
typename Processor::Number2_;
2321 const auto &shape_data = fe_eval.get_shape_info().data.front();
2322 constexpr bool integrate = Processor::do_integrate;
2323 const unsigned int face_no = fe_eval.get_face_no();
2324 const auto &dof_info = fe_eval.get_dof_info();
2325 const unsigned int cell = fe_eval.get_cell_or_face_batch_id();
2327 fe_eval.get_dof_access_index();
2329 dof_info.index_storage_variants[dof_access_index].size());
2330 constexpr unsigned int dofs_per_face =
2332 const unsigned int subface_index = fe_eval.get_subface_index();
2334 const unsigned int n_filled_lanes =
2335 dof_info.n_vectorization_lanes_filled[dof_access_index][cell];
2337 bool all_faces_are_same = n_filled_lanes == n_lanes;
2338 if (n_face_orientations == n_lanes)
2339 for (
unsigned int v = 1; v < n_lanes; ++v)
2340 if (fe_eval.get_face_no(v) != fe_eval.get_face_no(0) ||
2341 fe_eval.get_face_orientation(v) != fe_eval.get_face_orientation(0))
2343 all_faces_are_same =
false;
2348 std::array<const unsigned int *, n_face_orientations> orientation = {};
2350 if (dim == 3 && n_face_orientations == n_lanes && !all_faces_are_same &&
2351 fe_eval.is_interior_face() == 0)
2352 for (
unsigned int v = 0; v < n_lanes; ++v)
2360 if (shape_data.nodal_at_cell_boundaries &&
2361 fe_eval.get_face_orientation(v) != 0)
2366 check_face_orientations ==
false)
2380 orientation[v] = &fe_eval.get_shape_info().face_orientations_dofs(
2381 fe_eval.get_face_orientation(v), 0);
2384 else if (dim == 3 && fe_eval.get_face_orientation() != 0)
2388 check_face_orientations ==
false)
2402 for (
unsigned int v = 0; v < n_face_orientations; ++v)
2403 orientation[v] = &fe_eval.get_shape_info().face_orientations_dofs(
2404 fe_eval.get_face_orientation(), 0);
2410 VectorizedArrayType grad_weight =
2412 .shape_data_on_face[0][fe_degree + (integrate ? (2 - face_no % 2) :
2413 (1 + face_no % 2))];
2416 std::array<const unsigned int *, n_face_orientations> index_array_hermite =
2420 if (n_face_orientations == 1)
2421 index_array_hermite[0] =
2422 &fe_eval.get_shape_info().face_to_cell_index_hermite(face_no, 0);
2425 for (
unsigned int v = 0; v < n_lanes; ++v)
2430 const auto face_no = fe_eval.get_face_no(v);
2434 .shape_data_on_face[0][fe_degree + (integrate ?
2435 (2 - (face_no % 2)) :
2436 (1 + (face_no % 2)))];
2438 index_array_hermite[v] =
2439 &fe_eval.get_shape_info().face_to_cell_index_hermite(face_no,
2446 std::array<const unsigned int *, n_face_orientations> index_array_nodal =
2448 if (shape_data.nodal_at_cell_boundaries ==
true)
2450 if (n_face_orientations == 1)
2451 index_array_nodal[0] =
2452 &fe_eval.get_shape_info().face_to_cell_index_nodal(face_no, 0);
2455 for (
unsigned int v = 0; v < n_lanes; ++v)
2460 const auto face_no = fe_eval.get_face_no(v);
2462 index_array_nodal[v] =
2463 &fe_eval.get_shape_info().face_to_cell_index_nodal(face_no,
2470 const auto reorientate = [&](
const unsigned int v,
const unsigned int i) {
2471 return (!check_face_orientations || orientation[v] ==
nullptr) ?
2478 fe_eval.get_cell_ids()[0] :
2480 const unsigned int *dof_indices =
2481 &dof_info.dof_indices_contiguous[dof_access_index][
cell_index];
2483 for (
unsigned int comp = 0; comp < n_components; ++comp)
2485 const std::size_t index_offset =
2486 dof_info.component_dof_indices_offset
2487 [fe_eval.get_active_fe_index()]
2488 [fe_eval.get_first_selected_component()] +
2492 if (n_face_orientations == 1 &&
2493 dof_info.index_storage_variants[dof_access_index][cell] ==
2495 interleaved_contiguous)
2498 dof_info.n_vectorization_lanes_filled[dof_access_index][cell],
2500 Number2_ *vector_ptr =
2501 global_vector_ptr + dof_indices[0] + index_offset * n_lanes;
2505 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2509 const unsigned int ind1 = index_array_hermite[0][2 * i];
2510 const unsigned int ind2 = index_array_hermite[0][2 * i + 1];
2511 const unsigned int i_ = reorientate(0, i);
2512 proc.hermite_grad_vectorized(temp1[i_],
2513 temp1[i_ + dofs_per_face],
2514 vector_ptr + ind1 * n_lanes,
2515 vector_ptr + ind2 * n_lanes,
2521 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2525 const unsigned int i_ = reorientate(0, i);
2526 const unsigned int ind = index_array_nodal[0][i];
2527 proc.value_vectorized(temp1[i_],
2528 vector_ptr + ind * n_lanes);
2534 else if (n_face_orientations == 1 &&
2535 dof_info.index_storage_variants[dof_access_index][cell] ==
2537 interleaved_contiguous_strided)
2540 dof_info.n_vectorization_lanes_filled[dof_access_index][cell],
2542 Number2_ *vector_ptr = global_vector_ptr + index_offset * n_lanes;
2545 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2549 const unsigned int i_ = reorientate(0, i);
2550 const unsigned int ind1 =
2551 index_array_hermite[0][2 * i] * n_lanes;
2552 const unsigned int ind2 =
2553 index_array_hermite[0][2 * i + 1] * n_lanes;
2554 proc.hermite_grad_vectorized_indexed(
2556 temp1[i_ + dofs_per_face],
2566 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2570 const unsigned int i_ = reorientate(0, i);
2571 const unsigned int ind = index_array_nodal[0][i] * n_lanes;
2572 proc.value_vectorized_indexed(temp1[i_],
2580 else if (n_face_orientations == 1 &&
2581 dof_info.index_storage_variants[dof_access_index][cell] ==
2583 interleaved_contiguous_mixed_strides)
2585 const unsigned int *strides =
2586 &dof_info.dof_indices_interleave_strides[dof_access_index]
2588 unsigned int indices[n_lanes];
2589 for (
unsigned int v = 0; v < n_lanes; ++v)
2590 indices[v] = dof_indices[v] + index_offset * strides[v];
2591 const unsigned int n_filled_lanes =
2592 dof_info.n_vectorization_lanes_filled[dof_access_index][cell];
2596 if (n_filled_lanes == n_lanes)
2597 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2601 const unsigned int i_ = reorientate(0, i);
2602 unsigned int ind1[n_lanes];
2604 for (
unsigned int v = 0; v < n_lanes; ++v)
2605 ind1[v] = indices[v] +
2606 index_array_hermite[0][2 * i] * strides[v];
2607 unsigned int ind2[n_lanes];
2609 for (
unsigned int v = 0; v < n_lanes; ++v)
2613 index_array_hermite[0][2 * i + 1] * strides[v];
2614 proc.hermite_grad_vectorized_indexed(
2616 temp1[i_ + dofs_per_face],
2625 if (integrate ==
false)
2626 for (
unsigned int i = 0; i < 2 * dofs_per_face; ++i)
2627 temp1[i] = VectorizedArrayType();
2629 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2630 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2632 const unsigned int i_ =
2633 reorientate(n_face_orientations == 1 ? 0 : v, i);
2636 temp1[i_ + dofs_per_face][v],
2640 [n_face_orientations == 1 ? 0 : v][2 * i] *
2644 index_array_hermite[n_face_orientations == 1 ?
2648 grad_weight[n_face_orientations == 1 ? 0 : v]);
2654 if (n_filled_lanes == n_lanes)
2655 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2658 unsigned int ind[n_lanes];
2660 for (
unsigned int v = 0; v < n_lanes; ++v)
2662 indices[v] + index_array_nodal[0][i] * strides[v];
2663 const unsigned int i_ = reorientate(0, i);
2664 proc.value_vectorized_indexed(temp1[i_],
2670 if (integrate ==
false)
2671 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2672 temp1[i] = VectorizedArrayType();
2674 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2675 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2677 temp1[reorientate(n_face_orientations == 1 ? 0 : v,
2681 index_array_nodal[n_face_orientations == 1 ? 0 : v]
2689 else if (n_face_orientations > 1 ||
2690 dof_info.index_storage_variants[dof_access_index][cell] ==
2694 Number2_ *vector_ptr = global_vector_ptr + index_offset;
2696 const bool vectorization_possible =
2697 all_faces_are_same && (sm_ptr ==
nullptr);
2699 std::array<Number2_ *, n_lanes> vector_ptrs;
2700 std::array<unsigned int, n_lanes> reordered_indices;
2702 if (vectorization_possible ==
false)
2705 if (n_face_orientations == 1)
2707 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2708 if (sm_ptr ==
nullptr)
2710 vector_ptrs[v] = vector_ptr + dof_indices[v];
2716 .dof_indices_contiguous_sm[dof_access_index]
2717 [cell * n_lanes + v];
2718 vector_ptrs[v] =
const_cast<Number2_ *
>(
2719 sm_ptr->operator[](temp.first).data() +
2720 temp.second + index_offset);
2723 else if (n_face_orientations == n_lanes)
2725 const auto &cells = fe_eval.get_cell_ids();
2726 for (
unsigned int v = 0; v < n_lanes; ++v)
2729 if (sm_ptr ==
nullptr)
2734 .dof_indices_contiguous[dof_access_index]
2741 .dof_indices_contiguous_sm[dof_access_index]
2743 vector_ptrs[v] =
const_cast<Number2_ *
>(
2744 sm_ptr->operator[](temp.first).data() +
2745 temp.second + index_offset);
2754 else if (n_face_orientations == n_lanes)
2756 for (
unsigned int v = 0; v < n_lanes; ++v)
2757 reordered_indices[v] =
2758 dof_info.dof_indices_contiguous[dof_access_index]
2759 [fe_eval.get_cell_ids()[v]];
2760 dof_indices = reordered_indices.data();
2765 if (vectorization_possible)
2766 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2768 const unsigned int ind1 = index_array_hermite[0][2 * i];
2769 const unsigned int ind2 =
2770 index_array_hermite[0][2 * i + 1];
2771 const unsigned int i_ = reorientate(0, i);
2773 proc.hermite_grad_vectorized_indexed(
2775 temp1[i_ + dofs_per_face],
2782 else if (n_face_orientations == 1)
2783 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2785 const unsigned int ind1 = index_array_hermite[0][2 * i];
2786 const unsigned int ind2 =
2787 index_array_hermite[0][2 * i + 1];
2788 const unsigned int i_ = reorientate(0, i);
2790 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2791 proc.hermite_grad(temp1[i_][v],
2792 temp1[i_ + dofs_per_face][v],
2793 vector_ptrs[v][ind1],
2794 vector_ptrs[v][ind2],
2797 if (integrate ==
false)
2798 for (
unsigned int v = n_filled_lanes; v < n_lanes; ++v)
2801 temp1[i + dofs_per_face][v] = 0.0;
2806 if (integrate ==
false && n_filled_lanes < n_lanes)
2807 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2808 temp1[i] = temp1[i + dofs_per_face] = Number();
2810 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2811 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2813 temp1[reorientate(v, i)][v],
2814 temp1[reorientate(v, i) + dofs_per_face][v],
2815 vector_ptrs[v][index_array_hermite[v][2 * i]],
2816 vector_ptrs[v][index_array_hermite[v][2 * i + 1]],
2822 if (vectorization_possible)
2823 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2825 const unsigned int ind = index_array_nodal[0][i];
2826 const unsigned int i_ = reorientate(0, i);
2828 proc.value_vectorized_indexed(temp1[i_],
2834 if constexpr (n_face_orientations == 1)
2835 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2837 const unsigned int ind = index_array_nodal[0][i];
2838 const unsigned int i_ = reorientate(0, i);
2840 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2841 proc.value(temp1[i_][v], vector_ptrs[v][ind]);
2843 if constexpr (integrate ==
false)
2844 for (
unsigned int v = n_filled_lanes; v < n_lanes;
2850 if (integrate ==
false && n_filled_lanes < n_lanes)
2851 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2852 temp1[i] = Number();
2854 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2855 for (
unsigned int i = 0; i < dofs_per_face; ++i)
2856 proc.value(temp1[reorientate(v, i)][v],
2857 vector_ptrs[v][index_array_nodal[v][i]]);
2868 temp1 += 3 * dofs_per_face;