9#include "FunctionSpace.h"
12#include <basix/mdspan.hpp>
15#include <dolfinx/common/IndexMap.h>
16#include <dolfinx/common/types.h>
17#include <dolfinx/mesh/Mesh.h>
29template <dolfinx::scalar T>
31template <dolfinx::scalar T, std::
floating_po
int U>
52std::vector<std::int32_t> compute_domain(
53 auto entities, std::span<const std::int32_t> entity_map,
54 std::optional<int> codim = std::nullopt,
60 static_assert(entities.rank() == 1 or entities.rank() == 2);
61 std::vector<std::int32_t> mapped_entities;
62 mapped_entities.reserve(entities.size());
63 if constexpr (entities.rank() == 1)
65 std::span ents(entities.data_handle(), entities.size());
66 std::ranges::transform(ents, std::back_inserter(mapped_entities),
67 [&entity_map](
auto e) {
return entity_map[e]; });
69 else if (entities.rank() == 2)
71 assert(codim.value() >= 0);
72 if (codim.value() == 0)
74 for (std::size_t i = 0; i < entities.extent(0); ++i)
77 mapped_entities.insert(mapped_entities.end(),
78 {entity_map[entities(i, 0)], entities(i, 1)});
81 else if (codim.value() == 1)
86 for (std::size_t i = 0; i < entities.extent(0); ++i)
90 = c_to_f->get().links(entities(i, 0))[entities(i, 1)];
91 mapped_entities.insert(mapped_entities.end(),
92 {entity_map[facet], entities(i, 1)});
96 throw std::runtime_error(
"Codimension > 1 not supported.");
99 throw std::runtime_error(
"Integral type not supported.");
101 return mapped_entities;
108template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_t<T>>
116 template <
typename K,
typename V,
typename W>
117 requires std::is_convertible_v<
118 std::remove_cvref_t<K>,
119 std::function<void(T*,
const T*,
const T*,
const U*,
120 const int*,
const uint8_t*,
void*)>>
121 and std::is_convertible_v<std::remove_cvref_t<V>,
122 std::vector<std::int32_t>>
123 and std::is_convertible_v<std::remove_cvref_t<W>,
132 std::function<void(T*,
const T*,
const T*,
const U*,
const int*,
133 const uint8_t*,
void*)>
173template <dolfinx::scalar T, std::
floating_po
int U = dolfinx::scalar_value_t<T>>
210 template <
typename X>
211 requires std::is_convertible_v<
212 std::remove_cvref_t<X>,
213 std::map<std::tuple<IntegralType, int, int>,
225 std::span<const std::int32_t>>& entity_maps)
226 : _function_spaces(V), _integrals(std::forward<X>(integrals)),
231 throw std::runtime_error(
"Form Mesh is null.");
238 for (
auto& space : _function_spaces)
240 if (
auto mesh0 = space->mesh();
241 mesh0 != _mesh and !entity_maps.contains(mesh0))
243 throw std::runtime_error(
244 "Incompatible mesh. argument entity_maps must be provided.");
249 if (
auto mesh0 = c->function_space()->mesh();
250 mesh0 != _mesh and !entity_maps.contains(mesh0))
252 throw std::runtime_error(
253 "Incompatible mesh. coefficient entity_maps must be provided.");
258 for (
auto& space : _function_spaces)
261 std::map<std::tuple<IntegralType, int, int>,
262 std::variant<std::vector<std::int32_t>,
263 std::span<const std::int32_t>>>
266 if (
auto mesh0 = space->mesh(); mesh0 == _mesh)
268 for (
auto& [key, integral] : _integrals)
269 vdata.insert({key, std::span(integral.entities)});
273 auto it = entity_maps.find(mesh0);
274 assert(it != entity_maps.end());
275 std::span<const std::int32_t> entity_map = it->second;
276 for (
auto& [key, itg] : _integrals)
278 auto [type, id, kernel_idx] = key;
279 std::vector<std::int32_t> e;
282 e = impl::compute_domain(
283 md::mdspan(itg.entities.data(), itg.entities.size()),
290 int tdim = topology.
dim();
292 int codim = tdim - mesh0->topology()->dim();
295 e = impl::compute_domain(
296 md::mdspan<
const std::int32_t,
297 md::extents<std::size_t, md::dynamic_extent, 2>>(
298 itg.entities.data(), itg.entities.size() / 2, 2),
299 entity_map, codim, *c_to_f);
302 throw std::runtime_error(
"Integral type not supported.");
303 vdata.insert({key, std::move(e)});
307 _edata.push_back(vdata);
310 for (
auto& [key, integral] : _integrals)
312 auto [type, id, kernel_idx] = key;
313 for (
int c : integral.coeffs)
315 if (
auto mesh0 =
coefficients.at(c)->function_space()->mesh();
318 _cdata.insert({{type, id, c}, std::span(integral.entities)});
322 auto it = entity_maps.find(mesh0);
323 assert(it != entity_maps.end());
324 std::span<const std::int32_t> entity_map = it->second;
325 std::vector<std::int32_t> e;
328 e = impl::compute_domain(
329 md::mdspan(integral.entities.data(), integral.entities.size()),
336 int tdim = topology.
dim();
338 int codim = tdim - mesh0->topology()->dim();
341 e = impl::compute_domain(
342 md::mdspan<
const std::int32_t,
343 md::extents<std::size_t, md::dynamic_extent, 2>>(
344 integral.entities.data(), integral.entities.size() / 2, 2),
345 entity_map, codim, *c_to_f);
348 throw std::runtime_error(
"Integral type not supported.");
349 _cdata.insert({{type, id, c}, std::move(e)});
369 int rank()
const {
return _function_spaces.size(); }
373 std::shared_ptr<const mesh::Mesh<geometry_type>>
mesh()
const
380 const std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>&
383 return _function_spaces;
396 auto it = _integrals.find({type, id, kernel_idx});
397 if (it == _integrals.end())
398 throw std::runtime_error(
"Requested integral kernel not found.");
399 return it->second.kernel;
406 std::set<IntegralType> set;
407 std::ranges::for_each(_integrals, [&set](
auto& x)
408 { set.insert(std::get<0>(x.first)); });
424 auto it = std::ranges::find_if(_integrals,
427 auto [t, id_, kernel_idx] = x.first;
428 return t == type and id_ == id;
430 if (it == _integrals.end())
431 throw std::runtime_error(
"Could not find active coefficient list.");
432 return it->second.coeffs;
446 std::vector<int> ids;
447 for (
auto& [key, integral] : _integrals)
449 auto [t, id, kernel_idx] = key;
456 std::sort(ids.begin(), ids.end());
457 auto it = std::unique(ids.begin(), ids.end());
458 ids.erase(it, ids.end());
487 int kernel_idx)
const
489 auto it = _integrals.find({type, id, kernel_idx});
490 if (it == _integrals.end())
491 throw std::runtime_error(
"Requested domain not found.");
492 return it->second.entities;
527 int kernel_idx)
const
529 auto it = _edata.at(
rank).find({type, id, kernel_idx});
530 if (it == _edata.at(
rank).end())
531 throw std::runtime_error(
"Requested domain for argument not found.");
534 return std::get<std::span<const std::int32_t>>(it->second);
536 catch (std::bad_variant_access& e)
538 return std::get<std::vector<std::int32_t>>(it->second);
559 auto it = _cdata.find({type, id, c});
560 if (it == _cdata.end())
561 throw std::runtime_error(
"No domain for requested integral.");
564 return std::get<std::span<const std::int32_t>>(it->second);
566 catch (std::bad_variant_access& e)
568 return std::get<std::vector<std::int32_t>>(it->second);
574 std::shared_ptr<const Function<scalar_type, geometry_type>>>&
577 return _coefficients;
591 std::vector<int> n = {0};
592 for (
auto& c : _coefficients)
595 throw std::runtime_error(
"Not all form coefficients have been set.");
596 n.push_back(n.back() + c->function_space()->element()->space_dimension());
602 const std::vector<std::shared_ptr<const Constant<scalar_type>>>&
610 std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>
614 std::map<std::tuple<IntegralType, int, int>,
619 std::shared_ptr<const mesh::Mesh<geometry_type>> _mesh;
622 std::vector<std::shared_ptr<const Function<scalar_type, geometry_type>>>
626 std::vector<std::shared_ptr<const Constant<scalar_type>>> _constants;
629 bool _needs_facet_permutations;
641 std::vector<std::map<
642 std::tuple<IntegralType, int, int>,
643 std::variant<std::vector<std::int32_t>, std::span<const std::int32_t>>>>
657 std::tuple<IntegralType, int, int>,
658 std::variant<std::vector<std::int32_t>, std::span<const std::int32_t>>>
Constant value which can be attached to a Form.
Definition Constant.h:23
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:34
Definition AdjacencyList.h:27
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition Topology.h:46
std::shared_ptr< const graph::AdjacencyList< std::int32_t > > connectivity(std::array< int, 2 > d0, std::array< int, 2 > d1) const
Get the connectivity from entities of topological dimension d0 to dimension d1.
Definition Topology.cpp:832
int dim() const noexcept
Topological dimension of the mesh.
Definition Topology.cpp:785
Finite element method functionality.
Definition assemble_expression_impl.h:23
IntegralType
Type of integral.
Definition Form.h:36
@ vertex
Vertex.
Definition Form.h:40
@ interior_facet
Interior facet.
Definition Form.h:39
@ cell
Cell.
Definition Form.h:37
@ exterior_facet
Exterior facet.
Definition Form.h:38
Represents integral data, containing the kernel, and a list of entities to integrate over and the ind...
Definition Form.h:110
std::function< void(T *, const T *, const T *, const U *, const int *, const uint8_t *, void *)> kernel
The integration kernel.
Definition Form.h:134
integral_data(K &&kernel, V &&entities, W &&coeffs)
Create a structure to hold integral data.
Definition Form.h:125
std::vector< int > coeffs
Indices of coefficients (from the form) that are in this integral.
Definition Form.h:142
std::vector< std::int32_t > entities
The entities to integrate over for this integral. These are the entities in 'full' mesh.
Definition Form.h:138