310 assert(c->function_space());
311 assert(c->function_space()->mesh());
312 if (
auto mesh = c->function_space()->mesh().get(); !mesh0)
314 else if (
mesh != mesh0)
316 throw std::invalid_argument(
317 "Expression coefficient Functions have different meshes.");
322 assert(_function_space);
323 assert(_function_space->mesh());
325 mesh0 = _function_space->mesh().get();
327 if (cells0.size() != cells1.size())
328 throw std::invalid_argument(
"Cell lists have different lengths.");
331 assert(_function_space->element());
334 throw std::invalid_argument(
335 "Cannot interpolate Expression with Argument.");
337 if (value_size != (std::size_t)_function_space->element()->value_size())
339 throw std::invalid_argument(
340 "Function value size not equal to Expression value size.");
345 auto [X0, shape0] = e0.
X();
346 auto [X1, shape1] = _function_space->element()->interpolation_points();
347 if (shape0 != shape1)
349 throw std::invalid_argument(
350 "Function element interpolation points has different shape to "
351 "Expression interpolation points");
354 for (std::size_t i = 0; i < X0.size(); ++i)
356 if (std::abs(X0[i] - X1[i]) > 1.0e-10)
358 throw std::invalid_argument(
359 "Function element interpolation points not "
360 "equal to Expression interpolation points");
366 std::size_t num_cells = cells0.size();
367 std::size_t num_points = e0.
X().second[0];
368 std::vector<value_type> fdata(num_cells * num_points * value_size);
369 md::mdspan<const value_type, md::dextents<std::size_t, 3>> f(
370 fdata.data(), num_cells, num_points, value_size);
373 std::vector<std::int32_t> _cells0(cells0.begin(), cells0.end());
375 md::mdspan(_cells0.data(), _cells0.size()));
382 std::vector<value_type> fdata1(num_cells * num_points * value_size);
383 md::mdspan<value_type, md::dextents<std::size_t, 3>> f1(
384 fdata1.data(), value_size, num_cells, num_points);
385 for (std::size_t i = 0; i < f.extent(0); ++i)
386 for (std::size_t j = 0; j < f.extent(1); ++j)
387 for (std::size_t k = 0; k < f.extent(2); ++k)
388 f1(k, i, j) = f(i, j, k);
392 std::span<const value_type>(fdata1.data(), fdata1.size()),
393 {value_size, num_cells * num_points}, cells1);
462 void eval(std::span<const geometry_type>
x, std::array<std::size_t, 2> xshape,
464 std::array<std::size_t, 2> ushape,
double tol,
int maxit)
const
469 assert(
x.size() == xshape[0] * xshape[1]);
470 assert(u.size() == ushape[0] * ushape[1]);
475 if (xshape[0] != cells.size())
477 throw std::invalid_argument(
478 "Number of points and number of cells must be equal.");
481 if (xshape[0] != ushape[0])
483 throw std::invalid_argument(
484 "Length of array for Function values must be the "
485 "same as the number of points.");
489 assert(_function_space);
490 auto mesh = _function_space->mesh();
492 const std::size_t gdim =
mesh->geometry().dim();
493 const std::size_t tdim =
mesh->topology()->dim();
494 auto map =
mesh->topology()->index_map(tdim);
498 =
mesh->geometry().cmaps().front();
501 auto x_dofmap =
mesh->geometry().dofmaps().front();
502 const std::size_t num_dofs_g = cmap.
dim();
503 auto x_g =
mesh->geometry().x();
506 auto element = _function_space->element();
508 const int bs_element = element->block_size();
509 const std::size_t reference_value_size = element->reference_value_size();
510 const std::size_t value_size
511 = _function_space->element()->reference_value_size();
512 const std::size_t space_dimension = element->space_dimension() / bs_element;
516 const int num_sub_elements = element->num_sub_elements();
517 if (num_sub_elements > 1 and num_sub_elements != bs_element)
519 throw std::invalid_argument(
"Function::eval is not supported for mixed "
520 "elements. Extract subspaces.");
524 std::vector<value_type> coefficients(space_dimension * bs_element);
527 std::shared_ptr<const DofMap> dofmap = _function_space->dofmap();
529 const int bs_dof = dofmap->bs();
531 std::span<const std::uint32_t> cell_info;
532 if (element->needs_dof_transformations())
534 mesh->topology_mutable()->create_entity_permutations();
535 cell_info = std::span(
mesh->topology()->get_cell_permutation_info());
538 std::vector<geometry_type> coord_dofs_b(num_dofs_g * gdim);
539 impl::mdspan_t<geometry_type, 2> coord_dofs(coord_dofs_b.data(), num_dofs_g,
541 std::vector<geometry_type> xp_b(1 * gdim);
542 impl::mdspan_t<geometry_type, 2> xp(xp_b.data(), 1, gdim);
545 std::ranges::fill(u, 0);
546 std::span<const value_type> _v = _x->array();
550 std::array<std::size_t, 4> phi0_shape = cmap.
tabulate_shape(1, 1);
551 std::vector<geometry_type> phi0_b(std::reduce(
552 phi0_shape.begin(), phi0_shape.end(), 1, std::multiplies{}));
553 impl::mdspan_t<const geometry_type, 4> phi0(phi0_b.data(), phi0_shape);
554 cmap.
tabulate(1, std::vector<geometry_type>(tdim), {1, tdim}, phi0_b);
556 = md::submdspan(phi0, std::pair(1, tdim + 1), 0, md::full_extent, 0);
561 std::vector<geometry_type> phi_b(
562 std::reduce(phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
563 impl::mdspan_t<const geometry_type, 4> phi(phi_b.data(), phi_shape);
565 = md::submdspan(phi, std::pair(1, tdim + 1), 0, md::full_extent, 0);
568 std::vector<geometry_type> Xb(xshape[0] * tdim);
569 impl::mdspan_t<geometry_type, 2> X(Xb.data(), xshape[0], tdim);
572 std::vector<geometry_type> J_b(xshape[0] * gdim * tdim);
573 impl::mdspan_t<geometry_type, 3> J(J_b.data(), xshape[0], gdim, tdim);
574 std::vector<geometry_type> K_b(xshape[0] * tdim * gdim);
575 impl::mdspan_t<geometry_type, 3> K(K_b.data(), xshape[0], tdim, gdim);
576 std::vector<geometry_type> detJ(xshape[0]);
577 std::vector<geometry_type> det_scratch(2 * gdim * tdim);
580 std::vector<geometry_type> pull_back_scratch(
584 for (
auto cell_it = cells.begin(); cell_it != cells.end(); ++cell_it)
591 auto x_dofs = md::submdspan(x_dofmap, *cell_it, md::full_extent);
592 assert(x_dofs.size() == num_dofs_g);
593 for (std::size_t i = 0; i < num_dofs_g; ++i)
595 const int pos = 3 * x_dofs[i];
596 for (std::size_t j = 0; j < gdim; ++j)
597 coord_dofs(i, j) = x_g[pos + j];
600 std::size_t p = std::ranges::distance(cells.begin(), cell_it);
601 for (std::size_t j = 0; j < gdim; ++j)
602 xp(0, j) =
x[p * xshape[1] + j];
604 auto _J = md::submdspan(J, p, md::full_extent, md::full_extent);
605 auto _K = md::submdspan(K, p, md::full_extent, md::full_extent);
607 std::array<geometry_type, 3> Xpb{0, 0, 0};
608 md::mdspan<geometry_type, md::extents<std::size_t, 1, md::dynamic_extent>>
609 Xp(Xpb.data(), 1, tdim);
617 std::array<geometry_type, 3> x0{0, 0, 0};
618 for (std::size_t i = 0; i < coord_dofs.extent(1); ++i)
619 x0[i] += coord_dofs(0, i);
630 cmap.
tabulate(1, std::span(Xpb.data(), tdim), {1, tdim}, phi_b);
639 for (std::size_t j = 0; j < X.extent(1); ++j)
644 std::vector<geometry_type> basis_derivatives_reference_values_b(
645 1 * xshape[0] * space_dimension * reference_value_size);
646 impl::mdspan_t<const geometry_type, 4> basis_derivatives_reference_values(
647 basis_derivatives_reference_values_b.data(), 1, xshape[0],
648 space_dimension, reference_value_size);
649 std::vector<geometry_type> basis_values_b(space_dimension * value_size);
650 impl::mdspan_t<geometry_type, 2> basis_values(basis_values_b.data(),
651 space_dimension, value_size);
654 element->tabulate(basis_derivatives_reference_values_b, Xb,
655 {X.extent(0), X.extent(1)}, 0);
657 using xu_t = impl::mdspan_t<geometry_type, 2>;
658 using xU_t = impl::mdspan_t<const geometry_type, 2>;
659 using xJ_t = impl::mdspan_t<const geometry_type, 2>;
660 using xK_t = impl::mdspan_t<const geometry_type, 2>;
662 = element->basix_element().template map_fn<xu_t, xU_t, xJ_t, xK_t>();
665 auto apply_dof_transformation
666 = element->template dof_transformation_fn<geometry_type>(
672 if (element->symmetric())
674 while (matrix_size * matrix_size < (
int)ushape[1])
678 const std::size_t num_basis_values = space_dimension * reference_value_size;
679 for (
auto cell_it = cells.begin(); cell_it != cells.end(); ++cell_it)
686 std::size_t p = std::ranges::distance(cells.begin(), cell_it);
687 if (apply_dof_transformation)
689 apply_dof_transformation(
690 std::span(basis_derivatives_reference_values_b.data()
691 + p * num_basis_values,
693 cell_info, *cell_it, reference_value_size);
697 auto _U = md::submdspan(basis_derivatives_reference_values, 0, p,
698 md::full_extent, md::full_extent);
699 auto _J = md::submdspan(J, p, md::full_extent, md::full_extent);
700 auto _K = md::submdspan(K, p, md::full_extent, md::full_extent);
701 push_forward_fn(basis_values, _U, _J, detJ[p], _K);
705 std::span<const std::int32_t> dofs = dofmap->cell_dofs(*cell_it);
706 for (std::size_t i = 0; i < dofs.size(); ++i)
707 for (
int k = 0; k < bs_dof; ++k)
708 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
710 if (element->symmetric())
715 for (
int k = 0; k < bs_element; ++k)
717 if (k - rowstart > row)
722 for (std::size_t i = 0; i < space_dimension; ++i)
724 for (std::size_t j = 0; j < value_size; ++j)
727 + (j * bs_element + row * matrix_size + k - rowstart)]
728 += coefficients[bs_element * i + k] * basis_values(i, j);
729 if (k - rowstart != row)
732 + (j * bs_element + row + matrix_size * (k - rowstart))]
733 += coefficients[bs_element * i + k] * basis_values(i, j);
742 for (
int k = 0; k < bs_element; ++k)
744 for (std::size_t i = 0; i < space_dimension; ++i)
746 for (std::size_t j = 0; j < value_size; ++j)
748 u[p * ushape[1] + (j * bs_element + k)]
749 += coefficients[bs_element * i + k] * basis_values(i, j);