9 #include "FunctionSpace.h"
10 #include "interpolate.h"
11 #include <dolfinx/common/IndexMap.h>
12 #include <dolfinx/common/UniqueIdGenerator.h>
13 #include <dolfinx/common/array2d.h>
14 #include <dolfinx/fem/DofMap.h>
15 #include <dolfinx/fem/FiniteElement.h>
16 #include <dolfinx/la/PETScVector.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>
29 #include <xtensor/xadapt.hpp>
30 #include <xtensor/xtensor.hpp>
31 #include <xtl/xspan.hpp>
51 explicit Function(std::shared_ptr<const FunctionSpace> V)
52 : _id(common::UniqueIdGenerator::
id()), _function_space(V),
53 _x(std::make_shared<la::Vector<T>>(V->dofmap()->index_map,
54 V->dofmap()->index_map_bs()))
56 if (!V->component().empty())
58 throw std::runtime_error(
"Cannot create Function from subspace. Consider "
59 "collapsing the function space");
69 Function(std::shared_ptr<const FunctionSpace> V,
71 : _id(common::UniqueIdGenerator::
id()), _function_space(V), _x(
x)
78 assert(V->dofmap()->index_map->size_global() * V->dofmap()->index_map_bs()
79 <= _x->bs() * _x->map()->size_global());
87 :
name(std::move(v.
name)), _id(std::move(v._id)),
88 _function_space(std::move(v._function_space)), _x(std::move(v._x)),
89 _petsc_vector(std::exchange(v._petsc_vector, nullptr))
97 VecDestroy(&_petsc_vector);
103 name = std::move(v.name);
104 _id = std::move(v._id);
105 _function_space = std::move(v._function_space);
106 _x = std::move(v._x);
107 std::swap(_petsc_vector, v._petsc_vector);
120 auto sub_space = _function_space->
sub({i});
131 const auto [function_space_new, collapsed_map]
135 assert(function_space_new);
136 auto vector_new = std::make_shared<la::Vector<T>>(
137 function_space_new->dofmap()->index_map,
138 function_space_new->dofmap()->index_map_bs());
141 const std::vector<T>& x_old = _x->array();
142 std::vector<T>& x_new = vector_new->mutable_array();
143 for (std::size_t i = 0; i < collapsed_map.size(); ++i)
145 assert((
int)i < x_new.size());
146 assert(collapsed_map[i] < x_old.size());
147 x_new[i] = x_old[collapsed_map[i]];
150 return Function(function_space_new, vector_new);
157 return _function_space;
166 assert(_function_space->dofmap());
167 assert(_function_space->dofmap()->index_map);
168 if (_x->bs() * _x->map()->size_global()
169 != _function_space->dofmap()->index_map->size_global()
170 * _function_space->dofmap()->index_map_bs())
172 throw std::runtime_error(
173 "Cannot access a non-const vector from a subfunction");
177 if constexpr (std::is_same<T, PetscScalar>::value)
182 *_function_space->dofmap()->index_map,
183 _function_space->dofmap()->index_map_bs(), _x->mutable_array());
185 return _petsc_vector;
189 throw std::runtime_error(
190 "Cannot return PETSc vector wrapper. Type mismatch");
195 std::shared_ptr<const la::Vector<T>>
x()
const {
return _x; }
198 std::shared_ptr<la::Vector<T>>
x() {
return _x; }
207 const std::function<xt::xarray<T>(
const xt::xtensor<double, 2>&)>& f)
209 assert(_function_space);
210 assert(_function_space->element());
211 assert(_function_space->mesh());
212 const int tdim = _function_space->mesh()->topology().dim();
213 auto cell_map = _function_space->mesh()->topology().index_map(tdim);
215 const int num_cells = cell_map->size_local() + cell_map->num_ghosts();
216 std::vector<std::int32_t> cells(num_cells, 0);
217 std::iota(cells.begin(), cells.end(), 0);
221 *_function_space->element(), *_function_space->mesh(), cells);
235 void eval(
const xt::xtensor<double, 2>&
x,
236 const xtl::span<const std::int32_t>& cells,
237 xt::xtensor<T, 2>& u)
const
242 if (
x.shape(0) != cells.size())
244 throw std::runtime_error(
245 "Number of points and number of cells must be equal.");
247 if (
x.shape(0) != u.shape(0))
249 throw std::runtime_error(
250 "Length of array for Function values must be the "
251 "same as the number of points.");
255 assert(_function_space);
256 std::shared_ptr<const mesh::Mesh> mesh = _function_space->mesh();
258 const std::size_t gdim = mesh->geometry().dim();
259 const std::size_t tdim = mesh->topology().dim();
260 auto map = mesh->topology().index_map(tdim);
264 = mesh->geometry().dofmap();
266 const std::size_t num_dofs_g = x_dofmap.
num_links(0);
267 const xt::xtensor<double, 2>& x_g = mesh->geometry().x();
273 assert(_function_space->element());
274 std::shared_ptr<const fem::FiniteElement> element
275 = _function_space->element();
277 const int bs_element = element->block_size();
278 const std::size_t reference_value_size
279 = element->reference_value_size() / bs_element;
280 const std::size_t value_size = element->value_size() / bs_element;
281 const std::size_t space_dimension = element->space_dimension() / bs_element;
285 const int num_sub_elements = element->num_sub_elements();
286 if (num_sub_elements > 1 and num_sub_elements != bs_element)
288 throw std::runtime_error(
"Function::eval is not supported for mixed "
289 "elements. Extract subspaces.");
293 xt::xtensor<double, 2> X({1, tdim});
294 xt::xtensor<double, 3> J
295 = xt::zeros<double>({
static_cast<std::size_t
>(1), gdim, tdim});
296 xt::xtensor<double, 3> K
297 = xt::zeros<double>({
static_cast<std::size_t
>(1), tdim, gdim});
298 xt::xtensor<double, 1> detJ = xt::zeros<double>({1});
301 xt::xtensor<double, 4> basis_derivatives_reference_values(
302 {1, 1, space_dimension, reference_value_size});
303 auto basis_reference_values = xt::view(basis_derivatives_reference_values,
304 0, xt::all(), xt::all(), xt::all());
305 xt::xtensor<double, 3> basis_values(
306 {
static_cast<std::size_t
>(1), space_dimension, value_size});
309 std::vector<T> coefficients(space_dimension * bs_element);
312 std::shared_ptr<const fem::DofMap> dofmap = _function_space->dofmap();
314 const int bs_dof = dofmap->bs();
316 xtl::span<const std::uint32_t> cell_info;
317 if (element->needs_dof_transformations())
319 mesh->topology_mutable().create_entity_permutations();
320 cell_info = xtl::span(mesh->topology().get_cell_permutation_info());
323 xt::xtensor<double, 2> coordinate_dofs
324 = xt::zeros<double>({num_dofs_g, gdim});
325 xt::xtensor<double, 2> xp
326 = xt::zeros<double>({
static_cast<std::size_t
>(1), gdim});
329 std::fill(u.data(), u.data() + u.size(), 0.0);
330 const std::vector<T>& _v = _x->mutable_array();
332 const std::function<void(
const xtl::span<double>&,
333 const xtl::span<const std::uint32_t>&,
335 apply_dof_transformation
336 = element->get_dof_transformation_function<
double>();
338 for (std::size_t p = 0; p < cells.size(); ++p)
340 const int cell_index = cells[p];
347 auto x_dofs = x_dofmap.
links(cell_index);
348 for (std::size_t i = 0; i < num_dofs_g; ++i)
349 for (std::size_t j = 0; j < gdim; ++j)
350 coordinate_dofs(i, j) = x_g(x_dofs[i], j);
352 for (std::size_t j = 0; j < gdim; ++j)
356 cmap.
pull_back(X, J, detJ, K, xp, coordinate_dofs);
359 element->tabulate(basis_derivatives_reference_values, X, 0);
362 apply_dof_transformation(xtl::span(basis_reference_values.data(),
363 basis_reference_values.size()),
364 cell_info, cell_index, reference_value_size);
367 element->transform_reference_basis(basis_values, basis_reference_values,
371 xtl::span<const std::int32_t> dofs = dofmap->cell_dofs(cell_index);
372 for (std::size_t i = 0; i < dofs.size(); ++i)
373 for (
int k = 0; k < bs_dof; ++k)
374 coefficients[bs_dof * i + k] = _v[bs_dof * dofs[i] + k];
377 auto u_row = xt::row(u, p);
378 for (
int k = 0; k < bs_element; ++k)
380 for (std::size_t i = 0; i < space_dimension; ++i)
382 for (std::size_t j = 0; j < value_size; ++j)
384 u_row[j * bs_element + k]
385 += coefficients[bs_element * i + k] * basis_values(0, i, j);
396 assert(_function_space);
397 std::shared_ptr<const mesh::Mesh> mesh = _function_space->mesh();
399 const int tdim = mesh->topology().dim();
402 const std::size_t value_size_loc = _function_space->element()->value_size();
405 xt::xtensor<T, 2> point_values(
406 {mesh->geometry().
x().shape(0), value_size_loc});
410 = mesh->geometry().dofmap();
413 const int num_dofs_g = x_dofmap.
num_links(0);
414 const xt::xtensor<double, 2>& x_g = mesh->geometry().x();
418 auto map = mesh->topology().index_map(tdim);
420 const std::int32_t num_cells = map->size_local() + map->num_ghosts();
422 std::vector<std::int32_t> cells(x_g.shape(0));
423 for (std::int32_t c = 0; c < num_cells; ++c)
426 xtl::span<const std::int32_t> dofs = x_dofmap.links(c);
427 for (
int i = 0; i < num_dofs_g; ++i)
431 eval(x_g, cells, point_values);
440 std::size_t
id()
const {
return _id; }
447 std::shared_ptr<const FunctionSpace> _function_space;
450 std::shared_ptr<la::Vector<T>> _x;
453 mutable Vec _petsc_vector =
nullptr;
This class manages coordinate mappings for isoparametric cells.
Definition: CoordinateElement.h:29
void pull_back(xt::xtensor< double, 2 > &X, xt::xtensor< double, 3 > &J, xt::xtensor< double, 1 > &detJ, xt::xtensor< double, 3 > &K, const xt::xtensor< double, 2 > &x, const xt::xtensor< double, 2 > &cell_geometry) const
Compute reference coordinates X, and J, detJ and K for physical coordinates x.
Definition: CoordinateElement.cpp:208
This class represents a function in a finite element function space , given by.
Definition: Function.h:47
Vec vector() const
Return vector of expansion coefficients as a PETSc Vec. Throws an exception if a PETSc Vec cannot be ...
Definition: Function.h:163
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:235
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:69
void interpolate(const Function< T > &v)
Interpolate a Function (on possibly non-matching meshes)
Definition: Function.h:202
Function & operator=(Function &&v) noexcept
Move assignment.
Definition: Function.h:101
Function(Function &&v)
Move constructor.
Definition: Function.h:86
std::shared_ptr< la::Vector< T > > x()
Underlying vector.
Definition: Function.h:198
xt::xtensor< T, 2 > compute_point_values() const
Compute values at all mesh 'nodes'.
Definition: Function.h:394
std::shared_ptr< const FunctionSpace > function_space() const
Return shared pointer to function space.
Definition: Function.h:155
virtual ~Function()
Destructor.
Definition: Function.h:94
std::size_t id() const
ID.
Definition: Function.h:440
std::string name
Name.
Definition: Function.h:437
std::shared_ptr< const la::Vector< T > > x() const
Underlying vector.
Definition: Function.h:195
Function collapse() const
Collapse a subfunction (view into the Function) to a stand-alone Function.
Definition: Function.h:128
Function(std::shared_ptr< const FunctionSpace > V)
Create function on given function space.
Definition: Function.h:51
void interpolate(const std::function< xt::xarray< T >(const xt::xtensor< double, 2 > &)> &f)
Interpolate an expression.
Definition: Function.h:206
Function sub(int i) const
Extract subfunction (view into the Function)
Definition: Function.h:118
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition: AdjacencyList.h:47
xtl::span< T > links(int node)
Get the links (edges) for given node.
Definition: AdjacencyList.h:130
int num_links(int node) const
Number of connections for given node.
Definition: AdjacencyList.h:120
Distributed vector.
Definition: Vector.h:25
Finite element method functionality.
Definition: assemble_matrix_impl.h:23
void interpolate(Function< T > &u, const Function< T > &v)
Interpolate a finite element Function (on possibly non-matching meshes) in another finite element spa...
Definition: interpolate.h:146
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:18
Vec create_ghosted_vector(const common::IndexMap &map, int bs, xtl::span< PetscScalar > x)
Create a PETSc Vec that wraps the data in an array.
Definition: PETScVector.cpp:64