10 #include "FiniteElement.h"
11 #include "FunctionSpace.h"
12 #include "interpolate.h"
13 #include <dolfinx/common/IndexMap.h>
14 #include <dolfinx/la/Vector.h>
15 #include <dolfinx/mesh/Geometry.h>
16 #include <dolfinx/mesh/Mesh.h>
17 #include <dolfinx/mesh/Topology.h>
24 #include <xtensor/xadapt.hpp>
25 #include <xtensor/xtensor.hpp>
26 #include <xtl/xspan.hpp>
52 explicit Function(std::shared_ptr<const FunctionSpace> V)
54 _x(std::make_shared<la::Vector<T>>(V->dofmap()->index_map,
55 V->dofmap()->index_map_bs()))
57 if (!V->component().empty())
59 throw std::runtime_error(
"Cannot create Function from subspace. Consider "
60 "collapsing the function space");
71 Function(std::shared_ptr<const FunctionSpace> V,
73 : _function_space(V), _x(
x)
80 assert(V->dofmap()->index_map->size_global() * V->dofmap()->index_map_bs()
81 <= _x->bs() * _x->map()->size_global());
104 auto sub_space = _function_space->
sub({i});
115 auto [V, map] = _function_space->
collapse();
118 auto x = std::make_shared<la::Vector<T>>(V.dofmap()->index_map,
119 V.dofmap()->index_map_bs());
122 xtl::span<const T> x_old = _x->array();
123 xtl::span<T> x_new =
x->mutable_array();
124 for (std::size_t i = 0; i < map.size(); ++i)
126 assert((
int)i < x_new.size());
127 assert(map[i] < x_old.size());
128 x_new[i] = x_old[map[i]];
131 return Function(std::make_shared<FunctionSpace>(std::move(V)),
x);
138 return _function_space;
142 std::shared_ptr<const la::Vector<T>>
x()
const {
return _x; }
145 std::shared_ptr<la::Vector<T>>
x() {
return _x; }
151 const xtl::span<const std::int32_t>& cells)
160 assert(_function_space);
161 assert(_function_space->mesh());
162 int tdim = _function_space->mesh()->topology().dim();
163 auto cell_map = _function_space->mesh()->topology().index_map(tdim);
165 std::int32_t num_cells = cell_map->size_local() + cell_map->num_ghosts();
166 std::vector<std::int32_t> cells(num_cells, 0);
167 std::iota(cells.begin(), cells.end(), 0);
176 const std::function<xt::xarray<T>(
const xt::xtensor<double, 2>&)>& f,
177 const xtl::span<const std::int32_t>& cells)
179 assert(_function_space);
180 assert(_function_space->element());
181 assert(_function_space->mesh());
183 *_function_space->element(), *_function_space->mesh(), cells);
185 if (
int vs = _function_space->element()->value_size();
186 vs == 1 and fx.dimension() == 1)
189 if (fx.shape(0) !=
x.shape(1))
190 throw std::runtime_error(
"Data returned by callable has wrong length");
195 if (fx.dimension() != 2)
196 throw std::runtime_error(
"Expected 2D array of data");
197 if (fx.shape(0) != vs)
199 throw std::runtime_error(
200 "Data returned by callable has wrong shape(0) size");
202 if (fx.shape(1) !=
x.shape(1))
204 throw std::runtime_error(
205 "Data returned by callable has wrong shape(1) size");
215 const std::function<xt::xarray<T>(
const xt::xtensor<double, 2>&)>& f)
217 assert(_function_space);
218 assert(_function_space->mesh());
219 const int tdim = _function_space->mesh()->topology().dim();
220 auto cell_map = _function_space->mesh()->topology().index_map(tdim);
222 std::int32_t num_cells = cell_map->size_local() + cell_map->num_ghosts();
223 std::vector<std::int32_t> cells(num_cells, 0);
224 std::iota(cells.begin(), cells.end(), 0);
235 const xtl::span<const std::int32_t>& cells)
238 assert(_function_space);
239 assert(_function_space->element());
242 throw std::runtime_error(
"Cannot interpolate Expression with Argument");
244 if (value_size != _function_space->element()->value_size())
246 throw std::runtime_error(
247 "Function value size not equal to Expression value size");
250 if (!xt::allclose(e.
X(),
251 _function_space->element()->interpolation_points()))
253 throw std::runtime_error(
"Function element interpolation points not "
254 "equal to Expression interpolation points");
258 std::size_t num_cells = cells.size();
259 std::size_t num_points = e.
X().shape(0);
260 xt::xtensor<T, 3> f({num_cells, num_points, value_size});
263 auto f_view = xt::reshape_view(f, {num_cells, num_points * value_size});
264 e.
eval(cells, f_view);
271 xt::xarray<T> _f = xt::reshape_view(xt::transpose(f, {2, 0, 1}),
272 {value_size, num_cells * num_points});
282 assert(_function_space);
283 assert(_function_space->mesh());
284 const int tdim = _function_space->mesh()->topology().dim();
285 auto cell_map = _function_space->mesh()->topology().index_map(tdim);
287 std::int32_t num_cells = cell_map->size_local() + cell_map->num_ghosts();
288 std::vector<std::int32_t> cells(num_cells, 0);
289 std::iota(cells.begin(), cells.end(), 0);
303 void eval(
const xt::xtensor<double, 2>&
x,
304 const xtl::span<const std::int32_t>& cells,
305 xt::xtensor<T, 2>& u)
const
313 if (
x.shape(0) != cells.size())
315 throw std::runtime_error(
316 "Number of points and number of cells must be equal.");
318 if (
x.shape(0) != u.shape(0))
320 throw std::runtime_error(
321 "Length of array for Function values must be the "
322 "same as the number of points.");
326 assert(_function_space);
327 std::shared_ptr<const mesh::Mesh> mesh = _function_space->mesh();
329 const std::size_t gdim = mesh->geometry().dim();
330 const std::size_t tdim = mesh->topology().dim();
331 auto map = mesh->topology().index_map(tdim);
335 = mesh->geometry().dofmap();
336 const std::size_t num_dofs_g = mesh->geometry().cmap().dim();
337 xtl::span<const double> x_g = mesh->geometry().x();
343 assert(_function_space->element());
344 std::shared_ptr<const fem::FiniteElement> element
345 = _function_space->element();
347 const int bs_element = element->block_size();
348 const std::size_t reference_value_size
349 = element->reference_value_size() / bs_element;
350 const std::size_t value_size = element->value_size() / bs_element;
351 const std::size_t space_dimension = element->space_dimension() / bs_element;
355 const int num_sub_elements = element->num_sub_elements();
356 if (num_sub_elements > 1 and num_sub_elements != bs_element)
358 throw std::runtime_error(
"Function::eval is not supported for mixed "
359 "elements. Extract subspaces.");
363 std::vector<T> coefficients(space_dimension * bs_element);
366 std::shared_ptr<const fem::DofMap> dofmap = _function_space->dofmap();
368 const int bs_dof = dofmap->bs();
370 xtl::span<const std::uint32_t> cell_info;
371 if (element->needs_dof_transformations())
373 mesh->topology_mutable().create_entity_permutations();
374 cell_info = xtl::span(mesh->topology().get_cell_permutation_info());
377 xt::xtensor<double, 2> coordinate_dofs
378 = xt::zeros<double>({num_dofs_g, gdim});
379 xt::xtensor<double, 2> xp = xt::zeros<double>({std::size_t(1), gdim});
382 std::fill(u.data(), u.data() + u.size(), 0.0);
383 const xtl::span<const T>& _v = _x->array();
387 const xt::xtensor<double, 2> X0(xt::zeros<double>({std::size_t(1), tdim}));
389 const xt::xtensor<double, 2> dphi_i
390 = xt::view(data, xt::range(1, tdim + 1), 0, xt::all(), 0);
391 auto pull_back_affine = [dphi_i](
auto&& X,
const auto& cell_geometry,
392 auto&& J,
auto&& K,
const auto&
x)
mutable
400 xt::xtensor<double, 2> dphi;
401 xt::xtensor<double, 2> X({
x.shape(0), tdim});
402 xt::xtensor<double, 3> J = xt::zeros<double>({
x.shape(0), gdim, tdim});
403 xt::xtensor<double, 3> K = xt::zeros<double>({
x.shape(0), tdim, gdim});
404 xt::xtensor<double, 1> detJ = xt::zeros<double>({
x.shape(0)});
407 xt::xtensor<double, 2> _Xp({1, tdim});
408 for (std::size_t p = 0; p < cells.size(); ++p)
410 const int cell_index = cells[p];
416 auto x_dofs = x_dofmap.
links(cell_index);
417 assert(x_dofs.size() == num_dofs_g);
418 for (std::size_t i = 0; i < num_dofs_g; ++i)
420 const int pos = 3 * x_dofs[i];
421 for (std::size_t j = 0; j < gdim; ++j)
422 coordinate_dofs(i, j) = x_g[pos + j];
425 for (std::size_t j = 0; j < gdim; ++j)
428 auto _J = xt::view(J, p, xt::all(), xt::all());
429 auto _K = xt::view(K, p, xt::all(), xt::all());
433 pull_back_affine(_Xp, coordinate_dofs, _J, _K, xp);
441 dphi = xt::view(phi, xt::range(1, tdim + 1), 0, xt::all(), 0);
448 xt::row(X, p) = xt::row(_Xp, 0);
452 xt::xtensor<double, 4> basis_derivatives_reference_values(
453 {1,
x.shape(0), space_dimension, reference_value_size});
454 xt::xtensor<double, 3> basis_values(
455 {
static_cast<std::size_t
>(1), space_dimension, value_size});
458 element->tabulate(basis_derivatives_reference_values, X, 0);
460 using u_t = xt::xview<decltype(basis_values)&, std::size_t,
461 xt::xall<std::size_t>, xt::xall<std::size_t>>;
463 = xt::xview<decltype(basis_derivatives_reference_values)&, std::size_t,
464 std::size_t, xt::xall<std::size_t>, xt::xall<std::size_t>>;
465 using J_t = xt::xview<decltype(J)&, std::size_t, xt::xall<std::size_t>,
466 xt::xall<std::size_t>>;
467 using K_t = xt::xview<decltype(K)&, std::size_t, xt::xall<std::size_t>,
468 xt::xall<std::size_t>>;
469 auto push_forward_fn = element->map_fn<u_t, U_t, J_t, K_t>();
470 const std::function<void(
const xtl::span<double>&,
471 const xtl::span<const std::uint32_t>&,
473 apply_dof_transformation
474 = element->get_dof_transformation_function<
double>();
475 const std::size_t num_basis_values = space_dimension * reference_value_size;
477 for (std::size_t p = 0; p < cells.size(); ++p)
479 const int cell_index = cells[p];
485 apply_dof_transformation(
486 xtl::span(basis_derivatives_reference_values.data()
487 + p * num_basis_values,
489 cell_info, cell_index, reference_value_size);
491 auto _K = xt::view(K, p, xt::all(), xt::all());
492 auto _J = xt::view(J, p, xt::all(), xt::all());
493 auto _U = xt::view(basis_derivatives_reference_values, (std::size_t)0, p,
494 xt::all(), xt::all());
495 auto _u = xt::view(basis_values, (std::size_t)0, xt::all(), xt::all());
496 push_forward_fn(_u, _U, _J, detJ[p], _K);
499 xtl::span<const std::int32_t> dofs = dofmap->cell_dofs(cell_index);
500 for (std::size_t i = 0; i < dofs.size(); ++i)
501 for (
int k = 0; k < bs_dof; ++k)
502 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
505 auto u_row = xt::row(u, p);
506 for (
int k = 0; k < bs_element; ++k)
508 for (std::size_t i = 0; i < space_dimension; ++i)
510 for (std::size_t j = 0; j < value_size; ++j)
512 u_row[j * bs_element + k]
513 += coefficients[bs_element * i + k] * basis_values(0, i, j);
525 std::shared_ptr<const FunctionSpace> _function_space;
528 std::shared_ptr<la::Vector<T>> _x;
Degree-of-freedeom map representations ans tools.
Definition: CoordinateElement.h:31
static void compute_jacobian(const U &dphi, const V &cell_geometry, W &&J)
Compute Jacobian for a cell with given geometry using the basis functions and first order derivatives...
Definition: CoordinateElement.h:107
static double compute_jacobian_determinant(const U &J)
Compute the determinant of the Jacobian.
Definition: CoordinateElement.h:130
static void pull_back_affine(xt::xtensor< double, 2 > &X, const xt::xtensor< double, 2 > &K, const std::array< double, 3 > &x0, const xt::xtensor< double, 2 > &x)
Compute reference coordinates X for physical coordinates x for an affine map. For the affine case,...
Definition: CoordinateElement.cpp:89
static void compute_jacobian_inverse(const U &J, V &&K)
Compute the inverse of the Jacobian.
Definition: CoordinateElement.h:116
void pull_back_nonaffine(xt::xtensor< double, 2 > &X, const xt::xtensor< double, 2 > &x, const xt::xtensor< double, 2 > &cell_geometry, double tol=1.0e-8, int maxit=10) const
Compute reference coordinates X for physical coordinates x for a non-affine map.
Definition: CoordinateElement.cpp:106
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 FiniteElement::tabulate
Definition: CoordinateElement.cpp:44
static std::array< double, 3 > x0(const xt::xtensor< double, 2 > &cell_geometry)
Compute the physical coordinate of the reference point X=(0 , 0, 0)
Definition: CoordinateElement.cpp:81
bool is_affine() const noexcept
Check is geometry map is affine.
Definition: CoordinateElement.h:212
xt::xtensor< double, 4 > tabulate(int nd, const xt::xtensor< double, 2 > &X) const
Evaluate basis values and derivatives at set of points.
Definition: CoordinateElement.cpp:50
Represents a mathematical expression evaluated at a pre-defined set of points on the reference cell....
Definition: Expression.h:34
void eval(const xtl::span< const std::int32_t > &cells, U &values) const
Evaluate the expression on cells.
Definition: Expression.h:124
std::shared_ptr< const fem::FunctionSpace > argument_function_space() const
Get argument function space.
Definition: Expression.h:81
int value_size() const
Get value size.
Definition: Expression.h:215
const xt::xtensor< double, 2 > & X() const
Get evaluation points on reference cell.
Definition: Expression.h:227
This class represents a function in a finite element function space , given by.
Definition: Function.h:45
void interpolate(const Expression< T > &e, const xtl::span< const std::int32_t > &cells)
Interpolate an Expression (based on UFL)
Definition: Function.h:234
Function(std::shared_ptr< const FunctionSpace > V, std::shared_ptr< la::Vector< T >> x)
Create function on given function space with a given vector.
Definition: Function.h:71
void interpolate(const Expression< T > &e)
Interpolate an Expression (based on UFL) on all cells.
Definition: Function.h:280
void interpolate(const Function< T > &v, const xtl::span< const std::int32_t > &cells)
Interpolate a Function.
Definition: Function.h:150
void interpolate(const Function< T > &v)
Interpolate a Function.
Definition: Function.h:158
std::shared_ptr< la::Vector< T > > x()
Underlying vector.
Definition: Function.h:145
Function collapse() const
Collapse a subfunction (view into a Function) to a stand-alone Function.
Definition: Function.h:112
Function sub(int i) const
Extract subfunction (view into the Function)
Definition: Function.h:102
void eval(const xt::xtensor< double, 2 > &x, const xtl::span< const std::int32_t > &cells, xt::xtensor< T, 2 > &u) const
Evaluate the Function at points.
Definition: Function.h:303
void interpolate(const std::function< xt::xarray< T >(const xt::xtensor< double, 2 > &)> &f)
Interpolate an expression function on the whole domain.
Definition: Function.h:214
std::shared_ptr< const la::Vector< T > > x() const
Underlying vector.
Definition: Function.h:142
std::string name
Name.
Definition: Function.h:521
Function(std::shared_ptr< const FunctionSpace > V)
Create function on given function space.
Definition: Function.h:52
~Function()=default
Destructor.
void interpolate(const std::function< xt::xarray< T >(const xt::xtensor< double, 2 > &)> &f, const xtl::span< const std::int32_t > &cells)
Interpolate an expression function on a list of cells.
Definition: Function.h:175
Function(Function &&v)=default
Move constructor.
std::shared_ptr< const FunctionSpace > function_space() const
Access the function space.
Definition: Function.h:136
Function & operator=(Function &&v)=default
Move assignment.
T value_type
Field type for the Function, e.g. double.
Definition: Function.h:48
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition: AdjacencyList.h:46
xtl::span< T > links(int node)
Get the links (edges) for given node.
Definition: AdjacencyList.h:131
Distributed vector.
Definition: Vector.h:25
Finite element method functionality.
Definition: assemble_matrix_impl.h:24
void interpolate(Function< T > &u, const xt::xarray< T > &f, const xtl::span< const std::int32_t > &cells)
Interpolate an expression f(x) in a finite element space.
Definition: interpolate.h:383
xt::xtensor< double, 2 > interpolation_coords(const fem::FiniteElement &element, const mesh::Mesh &mesh, const xtl::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.cpp:17