280 std::span<const std::int32_t> cells)
283 assert(_function_space);
284 assert(_function_space->element());
287 throw std::runtime_error(
"Cannot interpolate Expression with Argument");
289 if (value_size != _function_space->element()->value_size())
291 throw std::runtime_error(
292 "Function value size not equal to Expression value size");
297 auto [X0, shape0] = e.
X();
298 auto [X1, shape1] = _function_space->element()->interpolation_points();
299 if (shape0 != shape1)
301 throw std::runtime_error(
302 "Function element interpolation points has different shape to "
303 "Expression interpolation points");
306 for (std::size_t i = 0; i < X0.size(); ++i)
308 if (std::abs(X0[i] - X1[i]) > 1.0e-10)
310 throw std::runtime_error(
"Function element interpolation points not "
311 "equal to Expression interpolation points");
317 std::size_t num_cells = cells.size();
318 std::size_t num_points = e.
X().second[0];
319 std::vector<T> fdata(num_cells * num_points * value_size);
320 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
321 const T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
322 f(fdata.data(), num_cells, num_points, value_size);
325 assert(_function_space->mesh());
326 e.
eval(*_function_space->mesh(), cells, fdata,
327 {num_cells, num_points * value_size});
334 std::vector<T> fdata1(num_cells * num_points * value_size);
335 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
336 T, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
337 f1(fdata1.data(), value_size, num_cells, num_points);
338 for (std::size_t i = 0; i < f.extent(0); ++i)
339 for (std::size_t j = 0; j < f.extent(1); ++j)
340 for (std::size_t k = 0; k < f.extent(2); ++k)
341 f1(k, i, j) = f(i, j, k);
345 {value_size, num_cells * num_points}, cells);
375 void eval(std::span<const U>
x, std::array<std::size_t, 2> xshape,
376 std::span<const std::int32_t> cells, std::span<T> u,
377 std::array<std::size_t, 2> ushape)
const
382 assert(
x.size() == xshape[0] * xshape[1]);
383 assert(u.size() == ushape[0] * ushape[1]);
388 if (xshape[0] != cells.size())
390 throw std::runtime_error(
391 "Number of points and number of cells must be equal.");
394 if (xshape[0] != ushape[0])
396 throw std::runtime_error(
397 "Length of array for Function values must be the "
398 "same as the number of points.");
402 assert(_function_space);
403 auto mesh = _function_space->mesh();
405 const std::size_t gdim = mesh->geometry().dim();
406 const std::size_t tdim = mesh->topology()->dim();
407 auto map = mesh->topology()->index_map(tdim);
410 if (mesh->geometry().cmaps().size() > 1)
412 throw std::runtime_error(
413 "Function with multiple geometry maps not implemented.");
418 auto x_dofmap = mesh->geometry().dofmap();
419 const std::size_t num_dofs_g = cmap.
dim();
420 std::span<const U> x_g = mesh->geometry().x();
423 auto element = _function_space->element();
425 const int bs_element = element->block_size();
426 const std::size_t reference_value_size
427 = element->reference_value_size() / bs_element;
428 const std::size_t value_size = element->value_size() / bs_element;
429 const std::size_t space_dimension = element->space_dimension() / bs_element;
433 const int num_sub_elements = element->num_sub_elements();
434 if (num_sub_elements > 1 and num_sub_elements != bs_element)
436 throw std::runtime_error(
"Function::eval is not supported for mixed "
437 "elements. Extract subspaces.");
441 std::vector<T> coefficients(space_dimension * bs_element);
444 std::shared_ptr<const DofMap> dofmap = _function_space->dofmap();
446 const int bs_dof = dofmap->bs();
448 std::span<const std::uint32_t> cell_info;
449 if (element->needs_dof_transformations())
451 mesh->topology_mutable()->create_entity_permutations();
452 cell_info = std::span(mesh->topology()->get_cell_permutation_info());
455 using cmdspan4_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
456 const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 4>>;
457 using mdspan2_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
458 U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
459 using mdspan3_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
460 U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>;
462 std::vector<U> coord_dofs_b(num_dofs_g * gdim);
463 mdspan2_t coord_dofs(coord_dofs_b.data(), num_dofs_g, gdim);
464 std::vector<U> xp_b(1 * gdim);
465 mdspan2_t xp(xp_b.data(), 1, gdim);
468 std::fill(u.data(), u.data() + u.size(), 0.0);
469 std::span<const T> _v = _x->array();
473 std::array<std::size_t, 4> phi0_shape = cmap.
tabulate_shape(1, 1);
474 std::vector<U> phi0_b(std::reduce(phi0_shape.begin(), phi0_shape.end(), 1,
476 cmdspan4_t phi0(phi0_b.data(), phi0_shape);
477 cmap.
tabulate(1, std::vector<U>(tdim), {1, tdim}, phi0_b);
479 = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
480 submdspan(phi0, std::pair(1, tdim + 1), 0,
481 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
486 std::vector<U> phi_b(
487 std::reduce(phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
488 cmdspan4_t phi(phi_b.data(), phi_shape);
489 auto dphi = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
490 submdspan(phi, std::pair(1, tdim + 1), 0,
491 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
494 std::vector<U> Xb(xshape[0] * tdim);
495 mdspan2_t X(Xb.data(), xshape[0], tdim);
498 std::vector<U> J_b(xshape[0] * gdim * tdim);
499 mdspan3_t J(J_b.data(), xshape[0], gdim, tdim);
500 std::vector<U> K_b(xshape[0] * tdim * gdim);
501 mdspan3_t K(K_b.data(), xshape[0], tdim, gdim);
502 std::vector<U> detJ(xshape[0]);
503 std::vector<U> det_scratch(2 * gdim * tdim);
506 for (std::size_t p = 0; p < cells.size(); ++p)
508 const int cell_index = cells[p];
516 = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
517 submdspan(x_dofmap, cell_index,
518 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
519 assert(x_dofs.size() == num_dofs_g);
520 for (std::size_t i = 0; i < num_dofs_g; ++i)
522 const int pos = 3 * x_dofs[i];
523 for (std::size_t j = 0; j < gdim; ++j)
524 coord_dofs(i, j) = x_g[pos + j];
527 for (std::size_t j = 0; j < gdim; ++j)
528 xp(0, j) =
x[p * xshape[1] + j];
530 auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
531 submdspan(J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
532 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
533 auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
534 submdspan(K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
535 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
537 std::array<U, 3> Xpb = {0, 0, 0};
538 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
540 MDSPAN_IMPL_STANDARD_NAMESPACE::extents<
541 std::size_t, 1, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>>
542 Xp(Xpb.data(), 1, tdim);
549 std::array<U, 3> x0 = {0, 0, 0};
550 for (std::size_t i = 0; i < coord_dofs.extent(1); ++i)
551 x0[i] += coord_dofs(0, i);
561 cmap.
tabulate(1, std::span(Xpb.data(), tdim), {1, tdim}, phi_b);
568 for (std::size_t j = 0; j < X.extent(1); ++j)
573 std::vector<U> basis_derivatives_reference_values_b(
574 1 * xshape[0] * space_dimension * reference_value_size);
575 cmdspan4_t basis_derivatives_reference_values(
576 basis_derivatives_reference_values_b.data(), 1, xshape[0],
577 space_dimension, reference_value_size);
578 std::vector<U> basis_values_b(space_dimension * value_size);
579 mdspan2_t basis_values(basis_values_b.data(), space_dimension, value_size);
582 element->tabulate(basis_derivatives_reference_values_b, Xb,
583 {X.extent(0), X.extent(1)}, 0);
585 using xu_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
586 U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
587 using xU_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
588 const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
589 using xJ_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
590 const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
591 using xK_t = MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
592 const U, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 2>>;
594 = element->basix_element().template map_fn<xu_t, xU_t, xJ_t, xK_t>();
596 auto apply_dof_transformation
597 = element->template get_dof_transformation_function<U>();
598 const std::size_t num_basis_values = space_dimension * reference_value_size;
600 for (std::size_t p = 0; p < cells.size(); ++p)
602 const int cell_index = cells[p];
610 apply_dof_transformation(
611 std::span(basis_derivatives_reference_values_b.data()
612 + p * num_basis_values,
614 cell_info, cell_index, reference_value_size);
618 = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
619 submdspan(basis_derivatives_reference_values, 0, p,
620 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
621 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
623 = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
624 submdspan(J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
625 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
627 = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
628 submdspan(K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
629 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
630 push_forward_fn(basis_values, _U, _J, detJ[p], _K);
634 std::span<const std::int32_t> dofs = dofmap->cell_dofs(cell_index);
635 for (std::size_t i = 0; i < dofs.size(); ++i)
636 for (
int k = 0; k < bs_dof; ++k)
637 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
640 using X =
typename dolfinx::scalar_value_type_t<T>;
641 for (
int k = 0; k < bs_element; ++k)
643 for (std::size_t i = 0; i < space_dimension; ++i)
645 for (std::size_t j = 0; j < value_size; ++j)
647 u[p * ushape[1] + (j * bs_element + k)]
648 += coefficients[bs_element * i + k]
649 *
static_cast<X
>(basis_values(i, j));