295 std::span<const std::int32_t> cells,
297 std::span<const std::int32_t> cell_map
298 = std::span<const std::int32_t>())
301 assert(_function_space);
302 assert(_function_space->element());
303 std::size_t value_size = e.value_size();
304 if (e.argument_function_space())
305 throw std::runtime_error(
"Cannot interpolate Expression with Argument");
307 if (value_size != _function_space->value_size())
309 throw std::runtime_error(
310 "Function value size not equal to Expression value size");
315 auto [X0, shape0] = e.X();
316 auto [X1, shape1] = _function_space->element()->interpolation_points();
317 if (shape0 != shape1)
319 throw std::runtime_error(
320 "Function element interpolation points has different shape to "
321 "Expression interpolation points");
324 for (std::size_t i = 0; i < X0.size(); ++i)
326 if (std::abs(X0[i] - X1[i]) > 1.0e-10)
328 throw std::runtime_error(
"Function element interpolation points not "
329 "equal to Expression interpolation points");
335 std::size_t num_cells = cells.size();
336 std::size_t num_points = e.X().second[0];
337 std::vector<value_type> fdata(num_cells * num_points * value_size);
338 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
340 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
341 f(fdata.data(), num_cells, num_points, value_size);
344 assert(_function_space->mesh());
346 std::vector<std::int32_t> cells_expr;
347 cells_expr.reserve(num_cells);
349 if (
auto mesh_v = _function_space->mesh();
350 expr_mesh.
topology() == mesh_v->topology())
352 cells_expr.insert(cells_expr.end(), cells.begin(), cells.end());
355 else if (!cell_map.empty())
357 std::transform(cells.begin(), cells.end(), std::back_inserter(cells_expr),
358 [&cell_map](std::int32_t c) { return cell_map[c]; });
361 std::runtime_error(
"Meshes are different and no cell map is provided");
363 e.eval(expr_mesh, cells_expr, fdata, {num_cells, num_points * value_size});
370 std::vector<value_type> fdata1(num_cells * num_points * value_size);
371 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
372 value_type, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
373 f1(fdata1.data(), value_size, num_cells, num_points);
374 for (std::size_t i = 0; i < f.extent(0); ++i)
375 for (std::size_t j = 0; j < f.extent(1); ++j)
376 for (std::size_t k = 0; k < f.extent(2); ++k)
377 f1(k, i, j) = f(i, j, k);
381 std::span<const value_type>(fdata1.data(), fdata1.size()),
382 {value_size, num_cells * num_points}, cells);
422 void eval(std::span<const geometry_type>
x, std::array<std::size_t, 2> xshape,
423 std::span<const std::int32_t> cells, std::span<value_type> u,
424 std::array<std::size_t, 2> ushape)
const
429 assert(
x.size() == xshape[0] * xshape[1]);
430 assert(u.size() == ushape[0] * ushape[1]);
435 if (xshape[0] != cells.size())
437 throw std::runtime_error(
438 "Number of points and number of cells must be equal.");
441 if (xshape[0] != ushape[0])
443 throw std::runtime_error(
444 "Length of array for Function values must be the "
445 "same as the number of points.");
449 assert(_function_space);
450 auto mesh = _function_space->mesh();
452 const std::size_t gdim = mesh->geometry().dim();
453 const std::size_t tdim = mesh->topology()->dim();
454 auto map = mesh->topology()->index_map(tdim);
460 auto x_dofmap = mesh->geometry().dofmap();
461 const std::size_t num_dofs_g = cmap.
dim();
462 auto x_g = mesh->geometry().x();
465 auto element = _function_space->element();
467 const int bs_element = element->block_size();
468 const std::size_t reference_value_size
469 = element->reference_value_size() / bs_element;
470 const std::size_t value_size = _function_space->value_size() / bs_element;
471 const std::size_t space_dimension = element->space_dimension() / bs_element;
475 const int num_sub_elements = element->num_sub_elements();
476 if (num_sub_elements > 1 and num_sub_elements != bs_element)
478 throw std::runtime_error(
"Function::eval is not supported for mixed "
479 "elements. Extract subspaces.");
483 std::vector<value_type> coefficients(space_dimension * bs_element);
486 std::shared_ptr<const DofMap> dofmap = _function_space->dofmap();
488 const int bs_dof = dofmap->bs();
490 std::span<const std::uint32_t> cell_info;
491 if (element->needs_dof_transformations())
493 mesh->topology_mutable()->create_entity_permutations();
494 cell_info = std::span(mesh->topology()->get_cell_permutation_info());
497 std::vector<geometry_type> coord_dofs_b(num_dofs_g * gdim);
498 impl::mdspan_t<geometry_type, 2> coord_dofs(coord_dofs_b.data(), num_dofs_g,
500 std::vector<geometry_type> xp_b(1 * gdim);
501 impl::mdspan_t<geometry_type, 2> xp(xp_b.data(), 1, gdim);
504 std::fill(u.data(), u.data() + u.size(), 0.0);
505 std::span<const value_type> _v = _x->array();
509 std::array<std::size_t, 4> phi0_shape = cmap.
tabulate_shape(1, 1);
510 std::vector<geometry_type> phi0_b(std::reduce(
511 phi0_shape.begin(), phi0_shape.end(), 1, std::multiplies{}));
512 impl::mdspan_t<const geometry_type, 4> phi0(phi0_b.data(), phi0_shape);
513 cmap.
tabulate(1, std::vector<geometry_type>(tdim), {1, tdim}, phi0_b);
514 auto dphi0 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
515 phi0, std::pair(1, tdim + 1), 0,
516 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
521 std::vector<geometry_type> phi_b(
522 std::reduce(phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
523 impl::mdspan_t<const geometry_type, 4> phi(phi_b.data(), phi_shape);
524 auto dphi = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
525 phi, std::pair(1, tdim + 1), 0,
526 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
529 std::vector<geometry_type> Xb(xshape[0] * tdim);
530 impl::mdspan_t<geometry_type, 2> X(Xb.data(), xshape[0], tdim);
533 std::vector<geometry_type> J_b(xshape[0] * gdim * tdim);
534 impl::mdspan_t<geometry_type, 3> J(J_b.data(), xshape[0], gdim, tdim);
535 std::vector<geometry_type> K_b(xshape[0] * tdim * gdim);
536 impl::mdspan_t<geometry_type, 3> K(K_b.data(), xshape[0], tdim, gdim);
537 std::vector<geometry_type> detJ(xshape[0]);
538 std::vector<geometry_type> det_scratch(2 * gdim * tdim);
541 for (std::size_t p = 0; p < cells.size(); ++p)
543 const int cell_index = cells[p];
550 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
551 x_dofmap, cell_index, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
552 assert(x_dofs.size() == num_dofs_g);
553 for (std::size_t i = 0; i < num_dofs_g; ++i)
555 const int pos = 3 * x_dofs[i];
556 for (std::size_t j = 0; j < gdim; ++j)
557 coord_dofs(i, j) = x_g[pos + j];
560 for (std::size_t j = 0; j < gdim; ++j)
561 xp(0, j) =
x[p * xshape[1] + j];
563 auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
564 J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
565 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
566 auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
567 K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
568 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
570 std::array<geometry_type, 3> Xpb = {0, 0, 0};
571 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
573 MDSPAN_IMPL_STANDARD_NAMESPACE::extents<
574 std::size_t, 1, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>>
575 Xp(Xpb.data(), 1, tdim);
583 std::array<geometry_type, 3> x0 = {0, 0, 0};
584 for (std::size_t i = 0; i < coord_dofs.extent(1); ++i)
585 x0[i] += coord_dofs(0, i);
596 cmap.
tabulate(1, std::span(Xpb.data(), tdim), {1, tdim}, phi_b);
605 for (std::size_t j = 0; j < X.extent(1); ++j)
610 std::vector<geometry_type> basis_derivatives_reference_values_b(
611 1 * xshape[0] * space_dimension * reference_value_size);
612 impl::mdspan_t<const geometry_type, 4> basis_derivatives_reference_values(
613 basis_derivatives_reference_values_b.data(), 1, xshape[0],
614 space_dimension, reference_value_size);
615 std::vector<geometry_type> basis_values_b(space_dimension * value_size);
616 impl::mdspan_t<geometry_type, 2> basis_values(basis_values_b.data(),
617 space_dimension, value_size);
620 element->tabulate(basis_derivatives_reference_values_b, Xb,
621 {X.extent(0), X.extent(1)}, 0);
623 using xu_t = impl::mdspan_t<geometry_type, 2>;
624 using xU_t = impl::mdspan_t<const geometry_type, 2>;
625 using xJ_t = impl::mdspan_t<const geometry_type, 2>;
626 using xK_t = impl::mdspan_t<const geometry_type, 2>;
628 = element->basix_element().template map_fn<xu_t, xU_t, xJ_t, xK_t>();
631 auto apply_dof_transformation
632 = element->template dof_transformation_fn<geometry_type>(
638 if (element->symmetric())
641 while (matrix_size * matrix_size < ushape[1])
644 const std::size_t num_basis_values = space_dimension * reference_value_size;
645 for (std::size_t p = 0; p < cells.size(); ++p)
647 const int cell_index = cells[p];
653 apply_dof_transformation(
654 std::span(basis_derivatives_reference_values_b.data()
655 + p * num_basis_values,
657 cell_info, cell_index, reference_value_size);
660 auto _U = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
661 basis_derivatives_reference_values, 0, p,
662 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
663 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
664 auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
665 J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
666 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
667 auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
668 K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
669 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
670 push_forward_fn(basis_values, _U, _J, detJ[p], _K);
674 std::span<const std::int32_t> dofs = dofmap->cell_dofs(cell_index);
675 for (std::size_t i = 0; i < dofs.size(); ++i)
676 for (
int k = 0; k < bs_dof; ++k)
677 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
679 if (element->symmetric())
684 for (
int k = 0; k < bs_element; ++k)
686 if (k - rowstart > row)
691 for (std::size_t i = 0; i < space_dimension; ++i)
693 for (std::size_t j = 0; j < value_size; ++j)
696 + (j * bs_element + row * matrix_size + k - rowstart)]
697 += coefficients[bs_element * i + k] * basis_values(i, j);
698 if (k - rowstart != row)
701 + (j * bs_element + row + matrix_size * (k - rowstart))]
702 += coefficients[bs_element * i + k] * basis_values(i, j);
711 for (
int k = 0; k < bs_element; ++k)
713 for (std::size_t i = 0; i < space_dimension; ++i)
715 for (std::size_t j = 0; j < value_size; ++j)
717 u[p * ushape[1] + (j * bs_element + k)]
718 += coefficients[bs_element * i + k] * basis_values(i, j);