55                                 std::reference_wrapper<const DofMap>>
 
   58                                 std::reference_wrapper<const DofMap>>
 
   62  auto& e0 = V0.first.get();
 
   63  const DofMap& dofmap0 = V0.second.get();
 
   64  auto& e1 = V1.first.get();
 
   65  const DofMap& dofmap1 = V1.second.get();
 
   67  using cmdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
   68      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
   69  using mdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
   70      U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
   71  using cmdspan4_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
   72      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 4>>;
 
   75  if (e0.map_type() != basix::maps::type::identity)
 
   76    throw std::runtime_error(
"Wrong finite element space for V0.");
 
   77  if (e0.block_size() != 1)
 
   78    throw std::runtime_error(
"Block size is greater than 1 for V0.");
 
   79  if (e0.reference_value_size() != 1)
 
   80    throw std::runtime_error(
"Wrong value size for V0.");
 
   82  if (e1.map_type() != basix::maps::type::covariantPiola)
 
   83    throw std::runtime_error(
"Wrong finite element space for V1.");
 
   84  if (e1.block_size() != 1)
 
   85    throw std::runtime_error(
"Block size is greater than 1 for V1.");
 
   88  const auto [X, Xshape] = e1.interpolation_points();
 
   92  const int ndofs0 = e0.space_dimension();
 
   93  const int tdim = topology.
dim();
 
   94  std::vector<U> phi0_b((tdim + 1) * Xshape[0] * ndofs0 * 1);
 
   95  cmdspan4_t phi0(phi0_b.data(), tdim + 1, Xshape[0], ndofs0, 1);
 
   96  e0.tabulate(phi0_b, X, Xshape, 1);
 
  100  cmdspan2_t dphi_reshaped(
 
  101      phi0_b.data() + phi0.extent(3) * phi0.extent(2) * phi0.extent(1),
 
  102      tdim * phi0.extent(1), phi0.extent(2));
 
  105  auto apply_inverse_dof_transform = e1.template dof_transformation_fn<T>(
 
  110  const std::vector<std::uint32_t>& cell_info
 
  116  std::vector<T> Ab(e1.space_dimension() * ndofs0);
 
  118    MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  119        T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>
 
  120        A(Ab.data(), e1.space_dimension(), ndofs0);
 
  121    const auto [Pi, shape] = e1.interpolation_operator();
 
  122    cmdspan2_t _Pi(Pi.data(), shape);
 
  123    math::dot(_Pi, dphi_reshaped, A);
 
  127  auto cell_map = topology.
index_map(tdim);
 
  129  std::int32_t num_cells = cell_map->size_local();
 
  130  std::vector<T> Ae(Ab.size());
 
  131  for (std::int32_t c = 0; c < num_cells; ++c)
 
  133    std::ranges::copy(Ab, Ae.begin());
 
  134    apply_inverse_dof_transform(Ae, cell_info, c, ndofs0);
 
 
  159  auto mesh = V0.
mesh();
 
  163  const int tdim = mesh->topology()->dim();
 
  164  const int gdim = mesh->geometry().dim();
 
  167  std::shared_ptr<const FiniteElement<U>> e0 = V0.
element();
 
  169  std::shared_ptr<const FiniteElement<U>> e1 = V1.
element();
 
  172  std::span<const std::uint32_t> cell_info;
 
  173  if (e1->needs_dof_transformations() or e0->needs_dof_transformations())
 
  175    mesh->topology_mutable()->create_entity_permutations();
 
  176    cell_info = std::span(mesh->topology()->get_cell_permutation_info());
 
  180  auto dofmap0 = V0.
dofmap();
 
  182  auto dofmap1 = V1.
dofmap();
 
  186  const int bs0 = e0->block_size();
 
  187  const int bs1 = e1->block_size();
 
  188  auto apply_dof_transformation0
 
  190  auto apply_inverse_dof_transform1 = e1->template dof_transformation_fn<T>(
 
  194  const std::size_t space_dim0 = e0->space_dimension();
 
  195  const std::size_t space_dim1 = e1->space_dimension();
 
  196  const std::size_t dim0 = space_dim0 / bs0;
 
  197  const std::size_t value_size_ref0 = e0->reference_value_size() / bs0;
 
  198  const std::size_t value_size0 = V0.
value_size() / bs0;
 
  199  const std::size_t value_size1 = V1.
value_size() / bs1;
 
  203  auto x_dofmap = mesh->geometry().dofmap();
 
  204  const std::size_t num_dofs_g = cmap.
dim();
 
  205  std::span<const U> x_g = mesh->geometry().x();
 
  207  using mdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  208      U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
  209  using cmdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  210      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
  211  using cmdspan3_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  212      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>;
 
  213  using cmdspan4_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  214      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 4>>;
 
  215  using mdspan3_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  216      U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>;
 
  219  const auto [X, Xshape] = e1->interpolation_points();
 
  220  std::array<std::size_t, 4> phi_shape = cmap.
tabulate_shape(1, Xshape[0]);
 
  221  std::vector<U> phi_b(
 
  222      std::reduce(phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
 
  223  cmdspan4_t phi(phi_b.data(), phi_shape);
 
  227  std::vector<U> basis_derivatives_reference0_b(Xshape[0] * dim0
 
  229  cmdspan4_t basis_derivatives_reference0(basis_derivatives_reference0_b.data(),
 
  230                                          1, Xshape[0], dim0, value_size_ref0);
 
  231  e0->tabulate(basis_derivatives_reference0_b, X, Xshape, 0);
 
  234  std::ranges::transform(
 
  235      basis_derivatives_reference0_b, basis_derivatives_reference0_b.begin(),
 
  236      [atol = 1e-14](
auto x) { return std::abs(x) < atol ? 0.0 : x; });
 
  239  std::vector<U> basis_reference0_b(Xshape[0] * dim0 * value_size_ref0);
 
  240  mdspan3_t basis_reference0(basis_reference0_b.data(), Xshape[0], dim0,
 
  242  std::vector<U> J_b(Xshape[0] * gdim * tdim);
 
  243  mdspan3_t J(J_b.data(), Xshape[0], gdim, tdim);
 
  244  std::vector<U> K_b(Xshape[0] * tdim * gdim);
 
  245  mdspan3_t K(K_b.data(), Xshape[0], tdim, gdim);
 
  246  std::vector<U> detJ(Xshape[0]);
 
  247  std::vector<U> det_scratch(2 * tdim * gdim);
 
  252  const auto [_Pi_1, pi_shape] = e1->interpolation_operator();
 
  253  cmdspan2_t Pi_1(_Pi_1.data(), pi_shape);
 
  255  bool interpolation_ident = e1->interpolation_ident();
 
  257  using u_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  258      U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
  259  using U_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  260      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
  261  using J_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  262      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
  263  using K_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  264      const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
 
  265  auto push_forward_fn0
 
  266      = e0->basix_element().template map_fn<u_t, U_t, J_t, K_t>();
 
  270  std::vector<U> basis_values_b(Xshape[0] * bs0 * dim0 * V1.
value_size());
 
  271  mdspan3_t basis_values(basis_values_b.data(), Xshape[0], bs0 * dim0,
 
  273  std::vector<U> mapped_values_b(Xshape[0] * bs0 * dim0 * V1.
value_size());
 
  274  mdspan3_t mapped_values(mapped_values_b.data(), Xshape[0], bs0 * dim0,
 
  278      = e1->basix_element().template map_fn<u_t, U_t, K_t, J_t>();
 
  280  std::vector<U> coord_dofs_b(num_dofs_g * gdim);
 
  281  mdspan2_t coord_dofs(coord_dofs_b.data(), num_dofs_g, gdim);
 
  282  std::vector<U> basis0_b(Xshape[0] * dim0 * value_size0);
 
  283  mdspan3_t basis0(basis0_b.data(), Xshape[0], dim0, value_size0);
 
  286  std::vector<T> Ab(space_dim0 * space_dim1);
 
  287  std::vector<T> local1(space_dim1);
 
  290  auto cell_map = mesh->topology()->index_map(tdim);
 
  292  std::int32_t num_cells = cell_map->size_local();
 
  293  for (std::int32_t c = 0; c < num_cells; ++c)
 
  296    auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  297        x_dofmap, c, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  298    for (std::size_t i = 0; i < x_dofs.size(); ++i)
 
  300      for (std::size_t j = 0; j < gdim; ++j)
 
  301        coord_dofs(i, j) = x_g[3 * x_dofs[i] + j];
 
  305    std::ranges::fill(J_b, 0);
 
  306    for (std::size_t p = 0; p < Xshape[0]; ++p)
 
  308      auto dphi = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  309          phi, std::pair(1, tdim + 1), p,
 
  310          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
 
  311      auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  312          J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  313          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  315      auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  316          K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  317          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  324    for (std::size_t k0 = 0; k0 < basis_reference0.extent(0); ++k0)
 
  325      for (std::size_t k1 = 0; k1 < basis_reference0.extent(1); ++k1)
 
  326        for (std::size_t k2 = 0; k2 < basis_reference0.extent(2); ++k2)
 
  327          basis_reference0(k0, k1, k2)
 
  328              = basis_derivatives_reference0(0, k0, k1, k2);
 
  329    for (std::size_t p = 0; p < Xshape[0]; ++p)
 
  331      apply_dof_transformation0(
 
  332          std::span(basis_reference0.data_handle() + p * dim0 * value_size_ref0,
 
  333                    dim0 * value_size_ref0),
 
  334          cell_info, c, value_size_ref0);
 
  337    for (std::size_t p = 0; p < basis0.extent(0); ++p)
 
  339      auto _u = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  340          basis0, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  341          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  342      auto _U = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  343          basis_reference0, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  344          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  345      auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  346          K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  347          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  348      auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  349          J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  350          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  351      push_forward_fn0(_u, _U, _J, detJ[p], _K);
 
  355    for (std::size_t p = 0; p < Xshape[0]; ++p)
 
  356      for (std::size_t i = 0; i < dim0; ++i)
 
  357        for (std::size_t j = 0; j < value_size0; ++j)
 
  358          for (
int k = 0; k < bs0; ++k)
 
  359            basis_values(p, i * bs0 + k, j * bs0 + k) = basis0(p, i, j);
 
  362    for (std::size_t p = 0; p < basis_values.extent(0); ++p)
 
  364      auto _u = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  365          basis_values, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  366          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  367      auto _U = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  368          mapped_values, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  369          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  370      auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  371          K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  372          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  373      auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  374          J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
 
  375          MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  376      pull_back_fn1(_U, _u, _K, 1.0 / detJ[p], _J);
 
  381    if (interpolation_ident)
 
  383      MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
 
  384          T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
 
  385          A(Ab.data(), Xshape[0], V1.
value_size(), space_dim0);
 
  386      for (std::size_t i = 0; i < mapped_values.extent(0); ++i)
 
  387        for (std::size_t j = 0; j < mapped_values.extent(1); ++j)
 
  388          for (std::size_t k = 0; k < mapped_values.extent(2); ++k)
 
  389            A(i, k, j) = mapped_values(i, j, k);
 
  393      for (std::size_t i = 0; i < mapped_values.extent(1); ++i)
 
  395        auto values = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
 
  396            mapped_values, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, i,
 
  397            MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
 
  398        impl::interpolation_apply(Pi_1, values, std::span(local1), bs1);
 
  399        for (std::size_t j = 0; j < local1.size(); j++)
 
  400          Ab[space_dim0 * j + i] = local1[j];
 
  404    apply_inverse_dof_transform1(Ab, cell_info, c, space_dim0);
 
  405    mat_set(dofmap1->cell_dofs(c), dofmap0->cell_dofs(c), Ab);