DOLFINx 0.10.0.0
DOLFINx C++ interface
Loading...
Searching...
No Matches
Function.h
1// Copyright (C) 2003-2024 Anders Logg, Garth N. Wells and Massimiliano Leoni
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "DofMap.h"
10#include "FiniteElement.h"
11#include "FunctionSpace.h"
12#include "interpolate.h"
13#include <algorithm>
14#include <concepts>
15#include <dolfinx/common/IndexMap.h>
16#include <dolfinx/common/types.h>
17#include <dolfinx/la/Vector.h>
18#include <dolfinx/mesh/Geometry.h>
19#include <dolfinx/mesh/Mesh.h>
20#include <dolfinx/mesh/Topology.h>
21#include <functional>
22#include <memory>
23#include <numeric>
24#include <span>
25#include <string>
26#include <utility>
27#include <vector>
28
29namespace dolfinx::fem
30{
31template <dolfinx::scalar T, std::floating_point U>
33
43template <dolfinx::scalar T,
44 std::floating_point U = dolfinx::scalar_value_type_t<T>>
45class Function
46{
47public:
50 using value_type = T;
52 using geometry_type = U;
53
56 explicit Function(std::shared_ptr<const FunctionSpace<geometry_type>> V)
57 : _function_space(V),
58 _x(std::make_shared<la::Vector<value_type>>(
59 V->dofmap()->index_map, V->dofmap()->index_map_bs()))
60 {
61 if (!V->component().empty())
62 {
63 throw std::runtime_error("Cannot create Function from subspace. Consider "
64 "collapsing the function space");
65 }
66 }
67
76 Function(std::shared_ptr<const FunctionSpace<geometry_type>> V,
77 std::shared_ptr<la::Vector<value_type>> x)
78 : _function_space(V), _x(x)
79 {
80 // NOTE: We do not check for a subspace since this constructor is
81 // used for creating subfunctions
82
83 // Assertion uses '<=' to deal with sub-functions
84 assert(V->dofmap());
85 assert(V->dofmap()->index_map->size_global() * V->dofmap()->index_map_bs()
86 <= _x->bs() * _x->index_map()->size_global());
87 }
88
89 // Copy constructor
90 Function(const Function& v) = delete;
91
93 Function(Function&& v) = default;
94
96 ~Function() = default;
97
99 Function& operator=(Function&& v) = default;
100
101 // Assignment
102 Function& operator=(const Function& v) = delete;
103
107 Function sub(int i) const
108 {
109 auto sub_space = std::make_shared<FunctionSpace<geometry_type>>(
110 _function_space->sub({i}));
111 assert(sub_space);
112 return Function(sub_space, _x);
113 }
114
119 {
120 // Create new collapsed FunctionSpace
121 auto [V, map] = _function_space->collapse();
122
123 // Create new vector
124 auto x = std::make_shared<la::Vector<value_type>>(
125 V.dofmap()->index_map, V.dofmap()->index_map_bs());
126
127 // Copy values into new vector
128 std::span<const value_type> x_old = _x->array();
129 std::span<value_type> x_new = x->mutable_array();
130 for (std::size_t i = 0; i < map.size(); ++i)
131 {
132 assert((int)i < x_new.size());
133 assert(map[i] < x_old.size());
134 x_new[i] = x_old[map[i]];
135 }
136
137 return Function(
138 std::make_shared<FunctionSpace<geometry_type>>(std::move(V)), x);
139 }
140
143 std::shared_ptr<const FunctionSpace<geometry_type>> function_space() const
144 {
145 return _function_space;
146 }
147
149 std::shared_ptr<const la::Vector<value_type>> x() const { return _x; }
150
152 std::shared_ptr<la::Vector<value_type>> x() { return _x; }
153
156 void
157 interpolate(const std::function<
158 std::pair<std::vector<value_type>, std::vector<std::size_t>>(
159 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
160 const geometry_type,
161 MDSPAN_IMPL_STANDARD_NAMESPACE::extents<
162 std::size_t, 3,
163 MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>>)>& f)
164 {
165 assert(_function_space);
166 assert(_function_space->mesh());
167 int tdim = _function_space->mesh()->topology()->dim();
168 auto cmap = _function_space->mesh()->topology()->index_map(tdim);
169 assert(cmap);
170 std::vector<std::int32_t> cells(cmap->size_local() + cmap->num_ghosts(), 0);
171 std::iota(cells.begin(), cells.end(), 0);
172 interpolate(f, cells);
173 }
174
179 const std::function<
180 std::pair<std::vector<value_type>, std::vector<std::size_t>>(
181 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
182 const geometry_type,
183 MDSPAN_IMPL_STANDARD_NAMESPACE::extents<
184 std::size_t, 3,
185 MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>>)>& f,
186 std::span<const std::int32_t> cells)
187 {
188 assert(_function_space);
189 assert(_function_space->element());
190 assert(_function_space->mesh());
191 const std::vector<geometry_type> x
193 *_function_space->element(), _function_space->mesh()->geometry(),
194 cells);
195 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
196 const geometry_type,
197 MDSPAN_IMPL_STANDARD_NAMESPACE::extents<
198 std::size_t, 3, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>>
199 _x(x.data(), 3, x.size() / 3);
200
201 const auto [fx, fshape] = f(_x);
202 assert(fshape.size() <= 2);
203 if (int vs = _function_space->element()->value_size();
204 vs == 1 and fshape.size() == 1)
205 {
206 // Check for scalar-valued functions
207 if (fshape.front() != x.size() / 3)
208 throw std::runtime_error("Data returned by callable has wrong length");
209 }
210 else
211 {
212 // Check for vector/tensor value
213 if (fshape.size() != 2)
214 throw std::runtime_error("Expected 2D array of data");
215
216 if (fshape[0] != vs)
217 {
218 throw std::runtime_error(
219 "Data returned by callable has wrong shape(0) size");
220 }
221
222 if (fshape[1] != x.size() / 3)
223 {
224 throw std::runtime_error(
225 "Data returned by callable has wrong shape(1) size");
226 }
227 }
228
229 std::array<std::size_t, 2> _fshape;
230 if (fshape.size() == 1)
231 _fshape = {1, fshape[0]};
232 else
233 _fshape = {fshape[0], fshape[1]};
234
235 fem::interpolate(*this, std::span<const value_type>(fx.data(), fx.size()),
236 _fshape, cells);
237 }
238
245 {
246 assert(_function_space);
247 assert(_function_space->mesh());
248 int tdim = _function_space->mesh()->topology()->dim();
249 auto cmap = _function_space->mesh()->topology()->index_map(tdim);
250 assert(cmap);
251 std::vector<std::int32_t> cells(cmap->size_local() + cmap->num_ghosts(), 0);
252 std::iota(cells.begin(), cells.end(), 0);
253 interpolate(u, cells, cells);
254 }
255
273 std::span<const std::int32_t> cells0,
274 std::span<const std::int32_t> cells1 = {})
275 {
276 if (cells1.empty())
277 cells1 = cells0;
278 fem::interpolate(*this, cells1, u0, cells0);
279 }
280
287 {
288 assert(_function_space);
289 assert(_function_space->mesh());
290 int tdim = _function_space->mesh()->topology()->dim();
291 auto cmap = _function_space->mesh()->topology()->index_map(tdim);
292 assert(cmap);
293 std::vector<std::int32_t> cells(cmap->size_local() + cmap->num_ghosts(), 0);
294 std::iota(cells.begin(), cells.end(), 0);
295 interpolate(e, cells);
296 }
297
315 std::span<const std::int32_t> cells0,
316 std::span<const std::int32_t> cells1 = {})
317 {
318 // Extract mesh
319 const mesh::Mesh<geometry_type>* mesh0 = nullptr;
320 for (auto& c : e0.coefficients())
321 {
322 assert(c);
323 assert(c->function_space());
324 assert(c->function_space()->mesh());
325 if (const mesh::Mesh<geometry_type>* mesh
326 = c->function_space()->mesh().get();
327 !mesh0)
328 {
329 mesh0 = mesh;
330 }
331 else if (mesh != mesh0)
332 {
333 throw std::runtime_error(
334 "Expression coefficient Functions have different meshes.");
335 }
336 }
337
338 // If Expression has no Function coefficients take mesh from `this`.
339 assert(_function_space);
340 assert(_function_space->mesh());
341 if (!mesh0)
342 mesh0 = _function_space->mesh().get();
343
344 // If cells1 is empty and Function and Expression meshes are the
345 // same, make cells1 the same as cells0. Otherwise check that
346 // lengths of cells0 and cells1 are the same.
347 if (cells1.empty() and mesh0 == _function_space->mesh().get())
348 cells1 = cells0;
349 else if (cells0.size() != cells1.size())
350 throw std::runtime_error("Cells lists have different lengths.");
351
352 // Check that Function and Expression spaces are compatible
353 assert(_function_space->element());
354 std::size_t value_size = e0.value_size();
356 throw std::runtime_error("Cannot interpolate Expression with Argument.");
357 if (value_size != _function_space->element()->value_size())
358 {
359 throw std::runtime_error(
360 "Function value size not equal to Expression value size.");
361 }
362
363 // Compatibility check
364 {
365 auto [X0, shape0] = e0.X();
366 auto [X1, shape1] = _function_space->element()->interpolation_points();
367 if (shape0 != shape1)
368 {
369 throw std::runtime_error(
370 "Function element interpolation points has different shape to "
371 "Expression interpolation points");
372 }
373
374 for (std::size_t i = 0; i < X0.size(); ++i)
375 {
376 if (std::abs(X0[i] - X1[i]) > 1.0e-10)
377 {
378 throw std::runtime_error("Function element interpolation points not "
379 "equal to Expression interpolation points");
380 }
381 }
382 }
383
384 // Array to hold evaluated Expression
385 std::size_t num_cells = cells0.size();
386 std::size_t num_points = e0.X().second[0];
387 std::vector<value_type> fdata(num_cells * num_points * value_size);
388 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
389 const value_type,
390 MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
391 f(fdata.data(), num_cells, num_points, value_size);
392
393 // Evaluate Expression at points
394 e0.eval(*mesh0, cells0, fdata, {num_cells, num_points * value_size});
395
396 // Reshape evaluated data to fit interpolate.
397 // Expression returns matrix of shape (num_cells, num_points *
398 // value_size), i.e. xyzxyz ordering of dof values per cell per
399 // point. The interpolation uses xxyyzz input, ordered for all
400 // points of each cell, i.e. (value_size, num_cells*num_points).
401 std::vector<value_type> fdata1(num_cells * num_points * value_size);
402 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
403 value_type, MDSPAN_IMPL_STANDARD_NAMESPACE::dextents<std::size_t, 3>>
404 f1(fdata1.data(), value_size, num_cells, num_points);
405 for (std::size_t i = 0; i < f.extent(0); ++i)
406 for (std::size_t j = 0; j < f.extent(1); ++j)
407 for (std::size_t k = 0; k < f.extent(2); ++k)
408 f1(k, i, j) = f(i, j, k);
409
410 // Interpolate values into appropriate space
411 fem::interpolate(*this,
412 std::span<const value_type>(fdata1.data(), fdata1.size()),
413 {value_size, num_cells * num_points}, cells1);
414 }
415
425 std::span<const std::int32_t> cells,
426 const geometry::PointOwnershipData<U>& interpolation_data)
427 {
428 fem::interpolate(*this, v, cells, interpolation_data);
429 }
430
443 void eval(std::span<const geometry_type> x, std::array<std::size_t, 2> xshape,
444 std::span<const std::int32_t> cells, std::span<value_type> u,
445 std::array<std::size_t, 2> ushape) const
446 {
447 if (cells.empty())
448 return;
449
450 assert(x.size() == xshape[0] * xshape[1]);
451 assert(u.size() == ushape[0] * ushape[1]);
452
453 // TODO: This could be easily made more efficient by exploiting
454 // points being ordered by the cell to which they belong.
455
456 if (xshape[0] != cells.size())
457 {
458 throw std::runtime_error(
459 "Number of points and number of cells must be equal.");
460 }
461
462 if (xshape[0] != ushape[0])
463 {
464 throw std::runtime_error(
465 "Length of array for Function values must be the "
466 "same as the number of points.");
467 }
468
469 // Get mesh
470 assert(_function_space);
471 auto mesh = _function_space->mesh();
472 assert(mesh);
473 const std::size_t gdim = mesh->geometry().dim();
474 const std::size_t tdim = mesh->topology()->dim();
475 auto map = mesh->topology()->index_map(tdim);
476
477 // Get coordinate map
478 const CoordinateElement<geometry_type>& cmap = mesh->geometry().cmap();
479
480 // Get geometry data
481 auto x_dofmap = mesh->geometry().dofmap();
482 const std::size_t num_dofs_g = cmap.dim();
483 auto x_g = mesh->geometry().x();
484
485 // Get element
486 auto element = _function_space->element();
487 assert(element);
488 const int bs_element = element->block_size();
489 const std::size_t reference_value_size = element->reference_value_size();
490 const std::size_t value_size
491 = _function_space->element()->reference_value_size();
492 const std::size_t space_dimension = element->space_dimension() / bs_element;
493
494 // If the space has sub elements, concatenate the evaluations on the
495 // sub elements
496 const int num_sub_elements = element->num_sub_elements();
497 if (num_sub_elements > 1 and num_sub_elements != bs_element)
498 {
499 throw std::runtime_error("Function::eval is not supported for mixed "
500 "elements. Extract subspaces.");
501 }
502
503 // Create work vector for expansion coefficients
504 std::vector<value_type> coefficients(space_dimension * bs_element);
505
506 // Get dofmap
507 std::shared_ptr<const DofMap> dofmap = _function_space->dofmap();
508 assert(dofmap);
509 const int bs_dof = dofmap->bs();
510
511 std::span<const std::uint32_t> cell_info;
512 if (element->needs_dof_transformations())
513 {
514 mesh->topology_mutable()->create_entity_permutations();
515 cell_info = std::span(mesh->topology()->get_cell_permutation_info());
516 }
517
518 std::vector<geometry_type> coord_dofs_b(num_dofs_g * gdim);
519 impl::mdspan_t<geometry_type, 2> coord_dofs(coord_dofs_b.data(), num_dofs_g,
520 gdim);
521 std::vector<geometry_type> xp_b(1 * gdim);
522 impl::mdspan_t<geometry_type, 2> xp(xp_b.data(), 1, gdim);
523
524 // Loop over points
525 std::ranges::fill(u, 0.0);
526 std::span<const value_type> _v = _x->array();
527
528 // Evaluate geometry basis at point (0, 0, 0) on the reference cell.
529 // Used in affine case.
530 std::array<std::size_t, 4> phi0_shape = cmap.tabulate_shape(1, 1);
531 std::vector<geometry_type> phi0_b(std::reduce(
532 phi0_shape.begin(), phi0_shape.end(), 1, std::multiplies{}));
533 impl::mdspan_t<const geometry_type, 4> phi0(phi0_b.data(), phi0_shape);
534 cmap.tabulate(1, std::vector<geometry_type>(tdim), {1, tdim}, phi0_b);
535 auto dphi0 = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
536 phi0, std::pair(1, tdim + 1), 0,
537 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
538
539 // Data structure for evaluating geometry basis at specific points.
540 // Used in non-affine case.
541 std::array<std::size_t, 4> phi_shape = cmap.tabulate_shape(1, 1);
542 std::vector<geometry_type> phi_b(
543 std::reduce(phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
544 impl::mdspan_t<const geometry_type, 4> phi(phi_b.data(), phi_shape);
545 auto dphi = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
546 phi, std::pair(1, tdim + 1), 0,
547 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent, 0);
548
549 // Reference coordinates for each point
550 std::vector<geometry_type> Xb(xshape[0] * tdim);
551 impl::mdspan_t<geometry_type, 2> X(Xb.data(), xshape[0], tdim);
552
553 // Geometry data at each point
554 std::vector<geometry_type> J_b(xshape[0] * gdim * tdim);
555 impl::mdspan_t<geometry_type, 3> J(J_b.data(), xshape[0], gdim, tdim);
556 std::vector<geometry_type> K_b(xshape[0] * tdim * gdim);
557 impl::mdspan_t<geometry_type, 3> K(K_b.data(), xshape[0], tdim, gdim);
558 std::vector<geometry_type> detJ(xshape[0]);
559 std::vector<geometry_type> det_scratch(2 * gdim * tdim);
560
561 // Prepare geometry data in each cell
562 for (std::size_t p = 0; p < cells.size(); ++p)
563 {
564 const int cell_index = cells[p];
565
566 // Skip negative cell indices
567 if (cell_index < 0)
568 continue;
569
570 // Get cell geometry (coordinate dofs)
571 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
572 x_dofmap, cell_index, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
573 assert(x_dofs.size() == num_dofs_g);
574 for (std::size_t i = 0; i < num_dofs_g; ++i)
575 {
576 const int pos = 3 * x_dofs[i];
577 for (std::size_t j = 0; j < gdim; ++j)
578 coord_dofs(i, j) = x_g[pos + j];
579 }
580
581 for (std::size_t j = 0; j < gdim; ++j)
582 xp(0, j) = x[p * xshape[1] + j];
583
584 auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
585 J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
586 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
587 auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
588 K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
589 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
590
591 std::array<geometry_type, 3> Xpb = {0, 0, 0};
592 MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan<
594 MDSPAN_IMPL_STANDARD_NAMESPACE::extents<
595 std::size_t, 1, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>>
596 Xp(Xpb.data(), 1, tdim);
597
598 // Compute reference coordinates X, and J, detJ and K
599 if (cmap.is_affine())
600 {
602 _J);
604 std::array<geometry_type, 3> x0 = {0, 0, 0};
605 for (std::size_t i = 0; i < coord_dofs.extent(1); ++i)
606 x0[i] += coord_dofs(0, i);
608 detJ[p]
610 _J, det_scratch);
611 }
612 else
613 {
614 // Pull-back physical point xp to reference coordinate Xp
615 cmap.pull_back_nonaffine(Xp, xp, coord_dofs);
616 cmap.tabulate(1, std::span(Xpb.data(), tdim), {1, tdim}, phi_b);
618 _J);
620 detJ[p]
622 _J, det_scratch);
623 }
624
625 for (std::size_t j = 0; j < X.extent(1); ++j)
626 X(p, j) = Xpb[j];
627 }
628
629 // Prepare basis function data structures
630 std::vector<geometry_type> basis_derivatives_reference_values_b(
631 1 * xshape[0] * space_dimension * reference_value_size);
632 impl::mdspan_t<const geometry_type, 4> basis_derivatives_reference_values(
633 basis_derivatives_reference_values_b.data(), 1, xshape[0],
634 space_dimension, reference_value_size);
635 std::vector<geometry_type> basis_values_b(space_dimension * value_size);
636 impl::mdspan_t<geometry_type, 2> basis_values(basis_values_b.data(),
637 space_dimension, value_size);
638
639 // Compute basis on reference element
640 element->tabulate(basis_derivatives_reference_values_b, Xb,
641 {X.extent(0), X.extent(1)}, 0);
642
643 using xu_t = impl::mdspan_t<geometry_type, 2>;
644 using xU_t = impl::mdspan_t<const geometry_type, 2>;
645 using xJ_t = impl::mdspan_t<const geometry_type, 2>;
646 using xK_t = impl::mdspan_t<const geometry_type, 2>;
647 auto push_forward_fn
648 = element->basix_element().template map_fn<xu_t, xU_t, xJ_t, xK_t>();
649
650 // Transformation function for basis function values
651 auto apply_dof_transformation
652 = element->template dof_transformation_fn<geometry_type>(
654
655 // Size of tensor for symmetric elements, unused in non-symmetric case, but
656 // placed outside the loop for pre-computation.
657 int matrix_size;
658 if (element->symmetric())
659 {
660 matrix_size = 0;
661 while (matrix_size * matrix_size < ushape[1])
662 ++matrix_size;
663 }
664
665 const std::size_t num_basis_values = space_dimension * reference_value_size;
666 for (std::size_t p = 0; p < cells.size(); ++p)
667 {
668 const int cell_index = cells[p];
669 if (cell_index < 0) // Skip negative cell indices
670 continue;
671
672 // Permute the reference basis function values to account for the
673 // cell's orientation
674 apply_dof_transformation(
675 std::span(basis_derivatives_reference_values_b.data()
676 + p * num_basis_values,
677 num_basis_values),
678 cell_info, cell_index, reference_value_size);
679
680 {
681 auto _U = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
682 basis_derivatives_reference_values, 0, p,
683 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
684 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
685 auto _J = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
686 J, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
687 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
688 auto _K = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan(
689 K, p, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent,
690 MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
691 push_forward_fn(basis_values, _U, _J, detJ[p], _K);
692 }
693
694 // Get degrees of freedom for current cell
695 std::span<const std::int32_t> dofs = dofmap->cell_dofs(cell_index);
696 for (std::size_t i = 0; i < dofs.size(); ++i)
697 for (int k = 0; k < bs_dof; ++k)
698 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
699
700 if (element->symmetric())
701 {
702 int row = 0;
703 int rowstart = 0;
704 // Compute expansion
705 for (int k = 0; k < bs_element; ++k)
706 {
707 if (k - rowstart > row)
708 {
709 row++;
710 rowstart = k;
711 }
712 for (std::size_t i = 0; i < space_dimension; ++i)
713 {
714 for (std::size_t j = 0; j < value_size; ++j)
715 {
716 u[p * ushape[1]
717 + (j * bs_element + row * matrix_size + k - rowstart)]
718 += coefficients[bs_element * i + k] * basis_values(i, j);
719 if (k - rowstart != row)
720 {
721 u[p * ushape[1]
722 + (j * bs_element + row + matrix_size * (k - rowstart))]
723 += coefficients[bs_element * i + k] * basis_values(i, j);
724 }
725 }
726 }
727 }
728 }
729 else
730 {
731 // Compute expansion
732 for (int k = 0; k < bs_element; ++k)
733 {
734 for (std::size_t i = 0; i < space_dimension; ++i)
735 {
736 for (std::size_t j = 0; j < value_size; ++j)
737 {
738 u[p * ushape[1] + (j * bs_element + k)]
739 += coefficients[bs_element * i + k] * basis_values(i, j);
740 }
741 }
742 }
743 }
744 }
745 }
746
748 std::string name = "u";
749
750private:
751 // Function space
752 std::shared_ptr<const FunctionSpace<geometry_type>> _function_space;
753
754 // Vector of expansion coefficients (local)
755 std::shared_ptr<la::Vector<value_type>> _x;
756};
757
758} // namespace dolfinx::fem
Degree-of-freedom map representations and tools.
Definition XDMFFile.h:29
static void compute_jacobian(const U &dphi, const V &cell_geometry, W &&J)
Definition CoordinateElement.h:126
static void pull_back_affine(U &&X, const V &K, const std::array< T, 3 > &x0, const W &x)
Compute reference coordinates X for physical coordinates x for an affine map. For the affine case,...
Definition CoordinateElement.h:209
void tabulate(int nd, std::span< const T > X, std::array< std::size_t, 2 > shape, std::span< T > basis) const
Evaluate basis values and derivatives at set of points.
Definition CoordinateElement.cpp:55
static void compute_jacobian_inverse(const U &J, V &&K)
Compute the inverse of the Jacobian.
Definition CoordinateElement.h:135
std::array< std::size_t, 4 > tabulate_shape(std::size_t nd, std::size_t num_points) const
Shape of array to fill when calling tabulate.
Definition CoordinateElement.cpp:48
int dim() const
The dimension of the coordinate element space.
Definition CoordinateElement.cpp:206
void pull_back_nonaffine(mdspan2_t< T > X, mdspan2_t< const T > x, mdspan2_t< const T > cell_geometry, double tol=1.0e-6, int maxit=15) const
Compute reference coordinates X for physical coordinates x for a non-affine map.
Definition CoordinateElement.cpp:83
bool is_affine() const noexcept
Definition CoordinateElement.h:261
static double compute_jacobian_determinant(const U &J, std::span< typename U::value_type > w)
Compute the determinant of the Jacobian.
Definition CoordinateElement.h:152
Represents a mathematical expression evaluated at a pre-defined set of points on the reference cell.
Definition Function.h:32
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > X() const
Evaluation points on the reference cell.
Definition Expression.h:276
const std::vector< std::shared_ptr< const Function< scalar_type, geometry_type > > > & coefficients() const
Get coefficients.
Definition Expression.h:114
void eval(const mesh::Mesh< geometry_type > &mesh, std::span< const std::int32_t > entities, std::span< scalar_type > values, std::array< std::size_t, 2 > vshape) const
Evaluate Expression on cells or facets.
Definition Expression.h:156
int value_size() const
Get value size.
Definition Expression.h:264
std::shared_ptr< const FunctionSpace< geometry_type > > argument_function_space() const
Get argument function space.
Definition Expression.h:105
This class represents a finite element function space defined by a mesh, a finite element,...
Definition vtk_utils.h:32
Definition XDMFFile.h:31
U geometry_type
Geometry type of the Mesh that the Function is defined on.
Definition Function.h:52
void interpolate(const Function< value_type, geometry_type > &u)
Interpolate a Function over all cells.
Definition Function.h:244
std::shared_ptr< const FunctionSpace< geometry_type > > function_space() const
Access the function space.
Definition Function.h:143
void interpolate(const std::function< std::pair< std::vector< value_type >, std::vector< std::size_t > >(MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< const geometry_type, MDSPAN_IMPL_STANDARD_NAMESPACE::extents< std::size_t, 3, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent > >)> &f)
Interpolate an expression f(x) on the whole domain.
Definition Function.h:157
void interpolate(const Function< value_type, geometry_type > &v, std::span< const std::int32_t > cells, const geometry::PointOwnershipData< U > &interpolation_data)
Interpolate a Function defined on a different mesh.
Definition Function.h:424
void interpolate(const Expression< value_type, geometry_type > &e0, std::span< const std::int32_t > cells0, std::span< const std::int32_t > cells1={})
Interpolate an Expression over a subset of cells.
Definition Function.h:314
Function(std::shared_ptr< const FunctionSpace< geometry_type > > V)
Create function on given function space.
Definition Function.h:56
void interpolate(const Function< value_type, geometry_type > &u0, std::span< const std::int32_t > cells0, std::span< const std::int32_t > cells1={})
Interpolate a Function over a subset of cells.
Definition Function.h:272
Function collapse() const
Collapse a subfunction (view into a Function) to a stand-alone Function.
Definition Function.h:118
Function sub(int i) const
Extract a sub-function (a view into the Function).
Definition Function.h:107
std::string name
Name.
Definition Function.h:748
std::shared_ptr< la::Vector< value_type > > x()
Underlying vector.
Definition Function.h:152
void interpolate(const Expression< value_type, geometry_type > &e)
Interpolate an Expression on all cells.
Definition Function.h:286
~Function()=default
Destructor.
void interpolate(const std::function< std::pair< std::vector< value_type >, std::vector< std::size_t > >(MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan< const geometry_type, MDSPAN_IMPL_STANDARD_NAMESPACE::extents< std::size_t, 3, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent > >)> &f, std::span< const std::int32_t > cells)
Interpolate an expression f(x) over a set of cells.
Definition Function.h:178
void eval(std::span< const geometry_type > x, std::array< std::size_t, 2 > xshape, std::span< const std::int32_t > cells, std::span< value_type > u, std::array< std::size_t, 2 > ushape) const
Evaluate the Function at points.
Definition Function.h:443
Function(Function &&v)=default
Move constructor.
std::shared_ptr< const la::Vector< value_type > > x() const
Underlying vector (const version).
Definition Function.h:149
Function & operator=(Function &&v)=default
Move assignment.
Function(std::shared_ptr< const FunctionSpace< geometry_type > > V, std::shared_ptr< la::Vector< value_type > > x)
Create function on given function space with a given vector.
Definition Function.h:76
T value_type
Definition Function.h:50
Definition Vector.h:32
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
Definition types.h:20
Finite element method functionality.
Definition assemble_matrix_impl.h:26
void interpolate(Function< T, U > &u, std::span< const T > f, std::array< std::size_t, 2 > fshape, std::span< const std::int32_t > cells)
Interpolate an evaluated expression f(x) in a finite element space.
Definition interpolate.h:704
std::vector< T > interpolation_coords(const fem::FiniteElement< T > &element, const mesh::Geometry< T > &geometry, std::span< const std::int32_t > cells)
Compute the evaluation points in the physical space at which an expression should be computed to inte...
Definition interpolate.h:51
Information on the ownership of points distributed across processes.
Definition utils.h:30