9#include "FunctionSpace.h"
14#include <dolfinx/common/IndexMap.h>
15#include <dolfinx/common/types.h>
16#include <dolfinx/mesh/Mesh.h>
27template <dolfinx::scalar T>
29template <dolfinx::scalar T, std::
floating_po
int U>
43template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
51 template <
typename K,
typename V>
52 requires std::is_convertible_v<
53 std::remove_cvref_t<K>,
54 std::function<void(T*,
const T*,
const T*,
const U*,
55 const int*,
const uint8_t*)>>
56 and std::is_convertible_v<std::remove_cvref_t<V>,
57 std::vector<std::int32_t>>
69 requires std::is_convertible_v<
70 std::remove_cvref_t<K>,
71 std::function<void(T*,
const T*,
const T*,
const U*,
72 const int*,
const uint8_t*)>>
82 std::function<void(T*,
const T*,
const T*,
const U*,
const int*,
118 std::floating_point U = dolfinx::scalar_value_type_t<T>>
153 template <
typename X>
154 requires std::is_convertible_v<
155 std::remove_cvref_t<X>,
156 std::map<IntegralType, std::vector<integral_data<T, U>>>>
165 std::span<const std::int32_t>>& entity_maps,
171 if (!_mesh and !V.empty())
172 _mesh = V[0]->mesh();
173 for (
auto& space : V)
175 if (_mesh != space->mesh()
176 and entity_maps.find(space->mesh()) == entity_maps.end())
178 throw std::runtime_error(
179 "Incompatible mesh. entity_maps must be provided.");
183 throw std::runtime_error(
"No mesh could be associated with the Form.");
186 for (
auto&& [domain_type, data] : integrals)
188 if (!std::is_sorted(data.begin(), data.end(),
189 [](
auto& a,
auto& b) { return a.id < b.id; }))
191 throw std::runtime_error(
"Integral IDs not sorted");
194 std::vector<integral_data<T, U>>& itg
195 = _integrals[
static_cast<std::size_t
>(domain_type)];
196 for (
auto&& [
id, kern, e] : data)
197 itg.emplace_back(
id, kern, std::move(e));
201 for (
auto [msh, map] : entity_maps)
202 _entity_maps.insert({msh, std::vector(map.begin(), map.end())});
219 int rank()
const {
return _function_spaces.size(); }
223 std::shared_ptr<const mesh::Mesh<U>>
mesh()
const {
return _mesh; }
227 const std::vector<std::shared_ptr<const FunctionSpace<U>>>&
230 return _function_spaces;
238 std::function<void(T*,
const T*,
const T*,
const U*,
const int*,
242 const auto& integrals = _integrals[
static_cast<std::size_t
>(type)];
243 auto it = std::lower_bound(integrals.begin(), integrals.end(), i,
244 [](
auto& itg_data,
int i)
245 { return itg_data.id < i; });
246 if (it != integrals.end() and it->id == i)
249 throw std::runtime_error(
"No kernel for requested domain index.");
256 std::set<IntegralType> set;
257 for (std::size_t i = 0; i < _integrals.size(); ++i)
259 if (!_integrals[i].empty())
271 return _integrals[
static_cast<std::size_t
>(type)].size();
283 std::vector<int> ids;
284 const auto& integrals = _integrals[
static_cast<std::size_t
>(type)];
285 std::transform(integrals.begin(), integrals.end(), std::back_inserter(ids),
286 [](
auto& integral) { return integral.id; });
309 const auto& integrals = _integrals[
static_cast<std::size_t
>(type)];
310 auto it = std::lower_bound(integrals.begin(), integrals.end(), i,
311 [](
auto& itg_data,
int i)
312 { return itg_data.id < i; });
313 if (it != integrals.end() and it->id == i)
316 throw std::runtime_error(
"No mesh entities for requested domain index.");
331 std::shared_ptr<const mesh::Mesh<U>> msh_ptr(&mesh,
334 std::span<const std::int32_t> entities = domain(type, i);
335 if (msh_ptr == _mesh)
336 return std::vector(entities.begin(), entities.end());
339 std::span<const std::int32_t> entity_map = _entity_maps.at(msh_ptr);
340 std::vector<std::int32_t> mapped_entities;
341 mapped_entities.reserve(entities.size());
346 std::transform(entities.begin(), entities.end(),
347 std::back_inserter(mapped_entities),
348 [&entity_map](
auto e) { return entity_map[e]; });
356 for (std::size_t i = 0; i < entities.size(); i += 2)
359 mapped_entities.insert(mapped_entities.end(),
360 {entity_map[entities[i]], entities[i + 1]});
365 throw std::runtime_error(
"Integral type not supported.");
368 return mapped_entities;
373 const std::vector<std::shared_ptr<const Function<T, U>>>&
coefficients()
const
375 return _coefficients;
389 std::vector<int> n = {0};
390 for (
auto& c : _coefficients)
393 throw std::runtime_error(
"Not all form coefficients have been set.");
394 n.push_back(n.back() + c->function_space()->element()->space_dimension());
400 const std::vector<std::shared_ptr<const Constant<T>>>&
constants()
const
407 std::vector<std::shared_ptr<const FunctionSpace<U>>> _function_spaces;
411 std::array<std::vector<integral_data<T, U>>, 4> _integrals;
414 std::vector<std::shared_ptr<const Function<T, U>>> _coefficients;
417 std::vector<std::shared_ptr<const Constant<T>>> _constants;
420 std::shared_ptr<const mesh::Mesh<U>> _mesh;
423 bool _needs_facet_permutations;
426 std::map<std::shared_ptr<const mesh::Mesh<U>>, std::vector<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
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
Finite element method functionality.
Definition assemble_matrix_impl.h:26
IntegralType
Type of integral.
Definition Form.h:34
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
Represents integral data, containing the integral ID, the kernel, and a list of entities to integrate...
Definition Form.h:45
integral_data(int id, K &&kernel, std::span< const std::int32_t > e)
Create a structure to hold integral data.
Definition Form.h:73
std::function< void(T *, const T *, const T *, const U *, const int *, const uint8_t *) kernel)
The integration kernel.
Definition Form.h:84
int id
Integral ID.
Definition Form.h:79
integral_data(int id, K &&kernel, V &&entities)
Create a structure to hold integral data.
Definition Form.h:58
std::vector< std::int32_t > entities
The entities to integrate over.
Definition Form.h:87