10#include "FunctionSpace.h"
13#include <basix/mdspan.hpp>
16#include <dolfinx/common/types.h>
17#include <dolfinx/mesh/EntityMap.h>
18#include <dolfinx/mesh/Mesh.h>
19#include <dolfinx/mesh/Topology.h>
20#include <dolfinx/mesh/cell_types.h>
36template <dolfinx::scalar T>
38template <dolfinx::scalar T, std::
floating_po
int U>
72 throw std::invalid_argument(
"Unknown integral type.");
90inline md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>>
97 const int tdim = topology.
dim();
103 return md::mdspan(p.data(), p.size() / num_entities_per_cell,
104 num_entities_per_cell);
111template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_t<T>>
119 template <
typename K,
typename V,
typename W>
120 requires std::is_convertible_v<
121 std::remove_cvref_t<K>,
122 std::function<void(T*,
const T*,
const T*,
const U*,
123 const int*,
const uint8_t*,
void*)>>
124 and std::is_convertible_v<std::remove_cvref_t<V>,
125 std::vector<std::int32_t>>
126 and std::is_convertible_v<std::remove_cvref_t<W>,
135 std::function<void(T*,
const T*,
const T*,
const U*,
const int*,
136 const uint8_t*,
void*)>
175template <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>,
224 const std::vector<std::reference_wrapper<const mesh::EntityMap>>&
226 : _function_spaces(V), _integrals(std::forward<X>(integrals)),
232 throw std::invalid_argument(
"Form Mesh is null.");
238 const int tdim = topology.
dim();
247 &topology](
IntegralType type, std::span<const std::int32_t> entities,
254 topology0, topology, md::mdspan(entities.data(), entities.size()),
260 throw std::invalid_argument(
261 "Vertex integrals are not supported for a form with an argument "
262 "or coefficient on another mesh. Supported types are cell, "
263 "exterior facet, interior facet and ridge.");
266 const int dim0 = topology0.dim();
268 if (tdim > dim0 and edim != dim0)
270 throw std::invalid_argument(std::format(
271 "Cannot map integration entities of dimension {} to cells of a "
272 "mesh of dimension {}. An argument or coefficient on another mesh "
273 "must live on the entities being integrated over.",
282 md::mdspan<
const std::int32_t,
283 md::extents<std::size_t, md::dynamic_extent, 2>>(
284 entities.data(), entities.size() / 2, 2),
291 std::vector<std::int32_t> e(entities.begin(), entities.end());
292 for (std::size_t i = 0; i < cells.size(); ++i)
297 _edata.reserve(_function_spaces.size());
298 for (
auto& space : _function_spaces)
301 std::map<std::tuple<IntegralType, int, int>,
302 std::variant<std::vector<std::int32_t>,
303 std::span<const std::int32_t>>>
306 if (
auto mesh0 = space->mesh(); mesh0 == _mesh)
308 for (
auto& [key, integral] : _integrals)
309 vdata.insert({key, std::span(integral.entities)});
317 for (
auto& [key, itg] : _integrals)
319 auto [type, idx, kernel_idx] = key;
321 {key, map_entities(type, itg.entities, topology0, emap)});
325 _edata.push_back(std::move(vdata));
328 for (
auto& [key, integral] : _integrals)
330 auto [type, idx, kernel_idx] = key;
331 for (
int c : integral.coeffs)
333 if (
auto mesh0 =
coefficients.at(c)->function_space()->mesh();
336 _cdata.insert({{type, idx, c}, std::span(integral.entities)});
346 map_entities(type, integral.entities, topology0, emap)});
367 Form(
Form&& form)
noexcept =
default;
377 Form& operator=(
const Form& form) =
delete;
391 int rank()
const {
return _function_spaces.size(); }
395 std::shared_ptr<const mesh::Mesh<geometry_type>>
mesh()
const
402 const std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>&
405 return _function_spaces;
420 auto it = _integrals.find({type, idx, kernel_idx});
421 if (it == _integrals.end())
422 throw std::out_of_range(
"Requested integral kernel not found.");
423 return it->second.kernel;
430 std::set<IntegralType> types;
431 for (
auto& [key, integral] : _integrals)
432 types.insert(std::get<0>(key));
451 auto it = std::ranges::find_if(_integrals,
454 auto [t, idx_, kernel_idx] = x.first;
455 return t == type and idx_ == idx;
457 if (it == _integrals.end())
458 throw std::out_of_range(
"Could not find active coefficient list.");
459 return it->second.coeffs;
480 return std::ranges::count_if(_integrals,
481 [type, kernel_idx](
auto& x)
483 auto [t, id, k_idx] = x.first;
484 return t == type and k_idx == kernel_idx;
523 int kernel_idx)
const
525 auto it = _integrals.find({type, idx, kernel_idx});
526 if (it == _integrals.end())
527 throw std::out_of_range(
"Requested domain not found.");
528 return it->second.entities;
567 int kernel_idx)
const
569 auto it = _edata.at(
rank).find({type, idx, kernel_idx});
570 if (it == _edata.at(
rank).end())
571 throw std::out_of_range(
"Requested domain for argument not found.");
573 return std::visit([](
const auto& v) -> std::span<const std::int32_t>
574 {
return v; }, it->second);
594 auto it = _cdata.find({type, idx, c});
595 if (it == _cdata.end())
596 throw std::out_of_range(
"No domain for requested integral.");
597 return std::visit([](
const auto& v) -> std::span<const std::int32_t>
598 {
return v; }, it->second);
604 std::shared_ptr<const Function<scalar_type, geometry_type>>>&
607 return _coefficients;
623 std::vector<int> n{0};
624 n.reserve(_coefficients.size() + 1);
625 for (
auto& c : _coefficients)
628 throw std::runtime_error(
"Not all form coefficients have been set.");
629 n.push_back(n.back() + c->function_space()->element()->space_dimension());
636 const std::vector<std::shared_ptr<const Constant<scalar_type>>>&
644 std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>
648 std::map<std::tuple<IntegralType, int, int>,
653 std::shared_ptr<const mesh::Mesh<geometry_type>> _mesh;
656 std::vector<std::shared_ptr<const Function<scalar_type, geometry_type>>>
660 std::vector<std::shared_ptr<const Constant<scalar_type>>> _constants;
663 bool _needs_facet_permutations;
675 std::vector<std::map<
676 std::tuple<IntegralType, int, int>,
677 std::variant<std::vector<std::int32_t>, std::span<const std::int32_t>>>>
693 std::tuple<IntegralType, int, int>,
694 std::variant<std::vector<std::int32_t>, std::span<const std::int32_t>>>
Constant (in space) value which can be attached to a Form.
Definition Constant.h:22
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:36
A bidirectional map relating entities in one topology to another.
Definition EntityMap.h:36
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:25
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition Topology.h:49
void create_entity_permutations(int dim, int num_threads=1)
Compute entity permutations and reflections.
Definition Topology.cpp:1183
int dim() const noexcept
Topological dimension of the mesh.
Definition Topology.cpp:897
const std::vector< std::uint8_t > & get_entity_permutations(int dim) const
Get the numbers that encode the permutation to apply to each cell-local entity of a given dimension.
Definition Topology.cpp:1058
Finite element method functionality.
Definition assemble_expression_impl.h:28
IntegralType
Type of integral.
Definition Form.h:43
@ vertex
Vertex.
Definition Form.h:47
@ interior_facet
Interior facet.
Definition Form.h:46
@ ridge
Ridge.
Definition Form.h:48
@ cell
Cell.
Definition Form.h:44
@ exterior_facet
Exterior facet.
Definition Form.h:45
constexpr int integral_entity_dim(IntegralType type, int tdim)
Topological dimension of the mesh entities an integral of the given type is over.
Definition Form.h:57
const EntityMap & find_entity_map(std::span< const std::reference_wrapper< const EntityMap > > entity_maps, const Topology &topology0, const Topology &topology1)
Find the entity map relating two topologies.
Definition EntityMap.cpp:31
CellType
Cell type identifier.
Definition cell_types.h:24
std::vector< std::int32_t > extract_cells_from_entities(const Topology &topology_c, const Topology &topology, E entities, std::optional< std::reference_wrapper< const EntityMap > > entity_map)
Map integration entities of a topology to the cells of a related topology.
Definition EntityMap.h:231
int cell_num_entities(CellType type, int dim)
Number of entities of dimension.
Definition cell_types.cpp:97
Represents integral data, containing the kernel, and a list of entities to integrate over and the ind...
Definition Form.h:113
std::function< void(T *, const T *, const T *, const U *, const int *, const uint8_t *, void *)> kernel
The integration kernel.
Definition Form.h:137
integral_data(K &&kernel, V &&entities, W &&coeffs)
Create a structure to hold integral data.
Definition Form.h:128
std::vector< int > coeffs
Indices of coefficients (from the form) that are in this integral.
Definition Form.h:145
std::vector< std::int32_t > entities
The entities to integrate over for this integral. These are the entities in 'full' mesh.
Definition Form.h:141