256 assert(_function_space);
257 assert(_function_space->element());
260 throw std::runtime_error(
"Cannot interpolate Expression with Argument");
262 if (value_size != _function_space->element()->value_size())
264 throw std::runtime_error(
265 "Function value size not equal to Expression value size");
270 auto [X0, shape0] = e.
X();
271 auto [X1, shape1] = _function_space->element()->interpolation_points();
272 if (shape0 != shape1)
274 throw std::runtime_error(
275 "Function element interpolation points has different shape to "
276 "Expression interpolation points");
278 for (std::size_t i = 0; i < X0.size(); ++i)
280 if (std::abs(X0[i] - X1[i]) > 1.0e-10)
282 throw std::runtime_error(
"Function element interpolation points not "
283 "equal to Expression interpolation points");
288 namespace stdex = std::experimental;
291 std::size_t num_cells = cells.size();
292 std::size_t num_points = e.
X().second[0];
293 std::vector<T> fdata(num_cells * num_points * value_size);
294 stdex::mdspan<const T, stdex::dextents<std::size_t, 3>> f(
295 fdata.data(), num_cells, num_points, value_size);
298 e.
eval(cells, fdata, {num_cells, num_points * value_size});
306 std::vector<T> fdata1(num_cells * num_points * value_size);
307 stdex::mdspan<T, stdex::dextents<std::size_t, 3>> f1(
308 fdata1.data(), value_size, num_cells, num_points);
309 for (std::size_t i = 0; i < f.extent(0); ++i)
310 for (std::size_t j = 0; j < f.extent(1); ++j)
311 for (std::size_t k = 0; k < f.extent(2); ++k)
312 f1(k, i, j) = f(i, j, k);
316 {value_size, num_cells * num_points}, cells);
346 void eval(std::span<const double>
x, std::array<std::size_t, 2> xshape,
347 std::span<const std::int32_t> cells, std::span<T> u,
348 std::array<std::size_t, 2> ushape)
const
353 assert(
x.size() == xshape[0] * xshape[1]);
354 assert(u.size() == ushape[0] * ushape[1]);
359 if (xshape[0] != cells.size())
361 throw std::runtime_error(
362 "Number of points and number of cells must be equal.");
364 if (xshape[0] != ushape[0])
366 throw std::runtime_error(
367 "Length of array for Function values must be the "
368 "same as the number of points.");
372 assert(_function_space);
373 std::shared_ptr<const mesh::Mesh> mesh = _function_space->mesh();
375 const std::size_t gdim = mesh->geometry().dim();
376 const std::size_t tdim = mesh->topology().dim();
377 auto map = mesh->topology().index_map(tdim);
381 = mesh->geometry().dofmap();
382 const std::size_t num_dofs_g = mesh->geometry().cmap().dim();
383 std::span<const double> x_g = mesh->geometry().x();
389 std::shared_ptr<const FiniteElement> element = _function_space->element();
391 const int bs_element = element->block_size();
392 const std::size_t reference_value_size
393 = element->reference_value_size() / bs_element;
394 const std::size_t value_size = element->value_size() / bs_element;
395 const std::size_t space_dimension = element->space_dimension() / bs_element;
399 const int num_sub_elements = element->num_sub_elements();
400 if (num_sub_elements > 1 and num_sub_elements != bs_element)
402 throw std::runtime_error(
"Function::eval is not supported for mixed "
403 "elements. Extract subspaces.");
407 std::vector<T> coefficients(space_dimension * bs_element);
410 std::shared_ptr<const DofMap> dofmap = _function_space->dofmap();
412 const int bs_dof = dofmap->bs();
414 std::span<const std::uint32_t> cell_info;
415 if (element->needs_dof_transformations())
417 mesh->topology_mutable().create_entity_permutations();
418 cell_info = std::span(mesh->topology().get_cell_permutation_info());
421 namespace stdex = std::experimental;
423 = stdex::mdspan<const double, stdex::dextents<std::size_t, 4>>;
424 using mdspan2_t = stdex::mdspan<double, stdex::dextents<std::size_t, 2>>;
425 using mdspan3_t = stdex::mdspan<double, stdex::dextents<std::size_t, 3>>;
427 std::vector<double> coord_dofs_b(num_dofs_g * gdim);
428 mdspan2_t coord_dofs(coord_dofs_b.data(), num_dofs_g, gdim);
429 std::vector<double> xp_b(1 * gdim);
430 mdspan2_t xp(xp_b.data(), 1, gdim);
433 std::fill(u.data(), u.data() + u.size(), 0.0);
434 std::span<const T> _v = _x->array();
438 std::array<std::size_t, 4> phi0_shape = cmap.
tabulate_shape(1, 1);
439 std::vector<double> phi0_b(std::reduce(phi0_shape.begin(), phi0_shape.end(),
440 1, std::multiplies{}));
441 cmdspan4_t phi0(phi0_b.data(), phi0_shape);
442 cmap.
tabulate(1, std::vector<double>(tdim), {1, tdim}, phi0_b);
443 auto dphi0 = stdex::submdspan(phi0, std::pair(1, tdim + 1), 0,
444 stdex::full_extent, 0);
449 std::vector<double> phi_b(
450 std::reduce(phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
451 cmdspan4_t phi(phi_b.data(), phi_shape);
452 auto dphi = stdex::submdspan(phi, std::pair(1, tdim + 1), 0,
453 stdex::full_extent, 0);
456 std::vector<double> Xb(xshape[0] * tdim);
457 mdspan2_t X(Xb.data(), xshape[0], tdim);
460 std::vector<double> J_b(xshape[0] * gdim * tdim);
461 mdspan3_t J(J_b.data(), xshape[0], gdim, tdim);
462 std::vector<double> K_b(xshape[0] * tdim * gdim);
463 mdspan3_t K(K_b.data(), xshape[0], tdim, gdim);
464 std::vector<double> detJ(xshape[0]);
465 std::vector<double> det_scratch(2 * gdim * tdim);
468 for (std::size_t p = 0; p < cells.size(); ++p)
470 const int cell_index = cells[p];
477 auto x_dofs = x_dofmap.
links(cell_index);
478 assert(x_dofs.size() == num_dofs_g);
479 for (std::size_t i = 0; i < num_dofs_g; ++i)
481 const int pos = 3 * x_dofs[i];
482 for (std::size_t j = 0; j < gdim; ++j)
483 coord_dofs(i, j) = x_g[pos + j];
486 for (std::size_t j = 0; j < gdim; ++j)
487 xp(0, j) =
x[p * xshape[1] + j];
489 auto _J = stdex::submdspan(J, p, stdex::full_extent, stdex::full_extent);
490 auto _K = stdex::submdspan(K, p, stdex::full_extent, stdex::full_extent);
492 std::array<double, 3> Xpb = {0, 0, 0};
493 stdex::mdspan<double,
494 stdex::extents<std::size_t, 1, stdex::dynamic_extent>>
495 Xp(Xpb.data(), 1, tdim);
502 std::array<double, 3> x0 = {0, 0, 0};
503 for (std::size_t i = 0; i < coord_dofs.extent(1); ++i)
504 x0[i] += coord_dofs(0, i);
514 cmap.
tabulate(1, std::span(Xpb.data(), tdim), {1, tdim}, phi_b);
521 for (std::size_t j = 0; j < X.extent(1); ++j)
526 std::vector<double> basis_derivatives_reference_values_b(
527 1 * xshape[0] * space_dimension * reference_value_size);
528 cmdspan4_t basis_derivatives_reference_values(
529 basis_derivatives_reference_values_b.data(), 1, xshape[0],
530 space_dimension, reference_value_size);
531 std::vector<double> basis_values_b(space_dimension * value_size);
532 mdspan2_t basis_values(basis_values_b.data(), space_dimension, value_size);
535 element->tabulate(basis_derivatives_reference_values_b, Xb,
536 {X.extent(0), X.extent(1)}, 0);
538 using xu_t = stdex::mdspan<double, stdex::dextents<std::size_t, 2>>;
539 using xU_t = stdex::mdspan<const double, stdex::dextents<std::size_t, 2>>;
540 using xJ_t = stdex::mdspan<const double, stdex::dextents<std::size_t, 2>>;
541 using xK_t = stdex::mdspan<const double, stdex::dextents<std::size_t, 2>>;
543 = element->basix_element().map_fn<xu_t, xU_t, xJ_t, xK_t>();
545 auto apply_dof_transformation
546 = element->get_dof_transformation_function<
double>();
547 const std::size_t num_basis_values = space_dimension * reference_value_size;
549 for (std::size_t p = 0; p < cells.size(); ++p)
551 const int cell_index = cells[p];
559 apply_dof_transformation(
560 std::span(basis_derivatives_reference_values_b.data()
561 + p * num_basis_values,
563 cell_info, cell_index, reference_value_size);
566 auto _U = stdex::submdspan(basis_derivatives_reference_values, 0, p,
567 stdex::full_extent, stdex::full_extent);
569 = stdex::submdspan(J, p, stdex::full_extent, stdex::full_extent);
571 = stdex::submdspan(K, p, stdex::full_extent, stdex::full_extent);
572 push_forward_fn(basis_values, _U, _J, detJ[p], _K);
576 std::span<const std::int32_t> dofs = dofmap->cell_dofs(cell_index);
577 for (std::size_t i = 0; i < dofs.size(); ++i)
578 for (
int k = 0; k < bs_dof; ++k)
579 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
582 for (
int k = 0; k < bs_element; ++k)
584 for (std::size_t i = 0; i < space_dimension; ++i)
586 for (std::size_t j = 0; j < value_size; ++j)
588 u[p * ushape[1] + (j * bs_element + k)]
589 += coefficients[bs_element * i + k] * basis_values(i, j);