10#include "FunctionSpace.h"
13#include <basix/mdspan.hpp>
17#include <dolfinx/common/types.h>
18#include <dolfinx/mesh/EntityMap.h>
19#include <dolfinx/mesh/Mesh.h>
34template <dolfinx::scalar T>
36template <dolfinx::scalar T, std::
floating_po
int U>
52template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_t<T>>
60 template <
typename K,
typename V,
typename W>
61 requires std::is_convertible_v<
62 std::remove_cvref_t<K>,
63 std::function<void(T*,
const T*,
const T*,
const U*,
64 const int*,
const uint8_t*,
void*)>>
65 and std::is_convertible_v<std::remove_cvref_t<V>,
66 std::vector<std::int32_t>>
67 and std::is_convertible_v<std::remove_cvref_t<W>,
76 std::function<void(T*,
const T*,
const T*,
const U*,
const int*,
77 const uint8_t*,
void*)>
116template <dolfinx::scalar T, std::
floating_po
int U = dolfinx::scalar_value_t<T>>
151 template <
typename X>
152 requires std::is_convertible_v<
153 std::remove_cvref_t<X>,
154 std::map<std::tuple<IntegralType, int, int>,
165 const std::vector<std::reference_wrapper<const mesh::EntityMap>>&
167 : _function_spaces(V), _integrals(std::forward<X>(integrals)),
172 throw std::runtime_error(
"Form Mesh is null.");
178 const int tdim = topology.
dim();
184 auto it = std::ranges::find_if(
188 return ((em.
topology() == mesh0->topology()
194 if (it == entity_maps.end())
196 throw std::runtime_error(
197 "Incompatible mesh. argument entity_maps must be provided.");
205 auto compute_facet_domains
206 = [](
const auto& int_ents_mesh,
int codim,
const auto& c_to_f,
207 const auto& emap,
bool inverse)
214 std::vector<std::int32_t> entities;
215 entities.reserve(int_ents_mesh.size() / 2);
221 for (std::size_t i = 0; i < int_ents_mesh.size(); i += 2)
222 entities.push_back(int_ents_mesh[i]);
229 for (std::size_t i = 0; i < int_ents_mesh.size(); i += 2)
232 c_to_f->links(int_ents_mesh[i])[int_ents_mesh[i + 1]]);
236 throw std::runtime_error(
"Codimension > 1 not supported.");
240 std::vector<std::int32_t> cells_mesh0
241 = emap.sub_topology_to_topology(entities,
inverse);
247 std::vector<std::int32_t> e = int_ents_mesh;
248 for (std::size_t i = 0; i < cells_mesh0.size(); ++i)
249 e[2 * i] = cells_mesh0[i];
254 _edata.reserve(_function_spaces.size());
255 for (
auto& space : _function_spaces)
258 std::map<std::tuple<IntegralType, int, int>,
259 std::variant<std::vector<std::int32_t>,
260 std::span<const std::int32_t>>>
263 if (
auto mesh0 = space->mesh(); mesh0 == _mesh)
265 for (
auto& [key, integral] : _integrals)
266 vdata.insert({key, std::span(integral.entities)});
277 for (
auto& [key, itg] : _integrals)
279 auto [type, idx, kernel_idx] = key;
280 std::vector<std::int32_t> e;
287 int codim = tdim - mesh0->topology()->dim();
291 e = compute_facet_domains(itg.entities, codim, c_to_f, emap,
295 throw std::runtime_error(
"Integral type not supported.");
297 vdata.insert({key, std::move(e)});
301 _edata.push_back(std::move(vdata));
304 for (
auto& [key, integral] : _integrals)
306 auto [type, idx, kernel_idx] = key;
307 for (
int c : integral.coeffs)
309 if (
auto mesh0 =
coefficients.at(c)->function_space()->mesh();
312 _cdata.insert({{type, idx, c}, std::span(integral.entities)});
320 std::vector<std::int32_t> e;
327 int codim = tdim - mesh0->topology()->dim();
330 e = compute_facet_domains(integral.entities, codim, c_to_f, emap,
334 throw std::runtime_error(
"Integral type not supported.");
335 _cdata.insert({{type, idx, c}, std::move(e)});
363 int rank()
const {
return _function_spaces.size(); }
367 std::shared_ptr<const mesh::Mesh<geometry_type>>
mesh()
const
374 const std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>&
377 return _function_spaces;
392 auto it = _integrals.find({type, idx, kernel_idx});
393 if (it == _integrals.end())
394 throw std::runtime_error(
"Requested integral kernel not found.");
395 return it->second.kernel;
402 std::set<IntegralType> types;
403 for (
auto& [key, integral] : _integrals)
404 types.insert(std::get<0>(key));
423 auto it = std::ranges::find_if(_integrals,
426 auto [t, idx_, kernel_idx] = x.first;
427 return t == type and idx_ == idx;
429 if (it == _integrals.end())
430 throw std::runtime_error(
"Could not find active coefficient list.");
431 return it->second.coeffs;
452 return std::ranges::count_if(_integrals,
453 [type, kernel_idx](
auto& x)
455 auto [t, id, k_idx] = x.first;
456 return t == type and k_idx == kernel_idx;
495 int kernel_idx)
const
497 auto it = _integrals.find({type, idx, kernel_idx});
498 if (it == _integrals.end())
499 throw std::runtime_error(
"Requested domain not found.");
500 return it->second.entities;
539 int kernel_idx)
const
541 auto it = _edata.at(
rank).find({type, idx, kernel_idx});
542 if (it == _edata.at(
rank).end())
543 throw std::runtime_error(
"Requested domain for argument not found.");
545 return std::visit([](
const auto& v) -> std::span<const std::int32_t>
546 {
return v; }, it->second);
566 auto it = _cdata.find({type, idx, c});
567 if (it == _cdata.end())
568 throw std::runtime_error(
"No domain for requested integral.");
569 return std::visit([](
const auto& v) -> std::span<const std::int32_t>
570 {
return v; }, it->second);
576 std::shared_ptr<const Function<scalar_type, geometry_type>>>&
579 return _coefficients;
595 std::vector<int> n{0};
596 n.reserve(_coefficients.size() + 1);
597 for (
auto& c : _coefficients)
600 throw std::runtime_error(
"Not all form coefficients have been set.");
601 n.push_back(n.back() + c->function_space()->element()->space_dimension());
608 const std::vector<std::shared_ptr<const Constant<scalar_type>>>&
616 std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>
620 std::map<std::tuple<IntegralType, int, int>,
625 std::shared_ptr<const mesh::Mesh<geometry_type>> _mesh;
628 std::vector<std::shared_ptr<const Function<scalar_type, geometry_type>>>
632 std::vector<std::shared_ptr<const Constant<scalar_type>>> _constants;
635 bool _needs_facet_permutations;
647 std::vector<std::map<
648 std::tuple<IntegralType, int, int>,
649 std::variant<std::vector<std::int32_t>, std::span<const std::int32_t>>>>
665 std::tuple<IntegralType, int, int>,
666 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:34
A bidirectional map relating entities in one topology to another.
Definition EntityMap.h:22
std::vector< std::int32_t > sub_topology_to_topology(CellRange auto &&entities, bool inverse) const
Map entities between the sub-topology and the parent topology.
Definition EntityMap.h:104
std::shared_ptr< const Topology > sub_topology() const
Get the sub-topology.
Definition EntityMap.cpp:23
std::shared_ptr< const Topology > topology() const
Get the (parent) topology.
Definition EntityMap.cpp:18
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:49
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:929
int dim() const noexcept
Topological dimension of the mesh.
Definition Topology.cpp:867
Finite element method functionality.
Definition assemble_expression_impl.h:23
@ inverse
Inverse.
Definition FiniteElement.h:29
IntegralType
Type of integral.
Definition Form.h:41
@ vertex
Vertex.
Definition Form.h:45
@ interior_facet
Interior facet.
Definition Form.h:44
@ ridge
Ridge.
Definition Form.h:46
@ cell
Cell.
Definition Form.h:42
@ exterior_facet
Exterior facet.
Definition Form.h:43
Represents integral data, containing the kernel, and a list of entities to integrate over and the ind...
Definition Form.h:54
std::function< void(T *, const T *, const T *, const U *, const int *, const uint8_t *, void *)> kernel
The integration kernel.
Definition Form.h:78
integral_data(K &&kernel, V &&entities, W &&coeffs)
Create a structure to hold integral data.
Definition Form.h:69
std::vector< int > coeffs
Indices of coefficients (from the form) that are in this integral.
Definition Form.h:86
std::vector< std::int32_t > entities
The entities to integrate over for this integral. These are the entities in 'full' mesh.
Definition Form.h:82