9#include "FunctionSpace.h"
15#include <dolfinx/common/IndexMap.h>
16#include <dolfinx/common/types.h>
17#include <dolfinx/mesh/Mesh.h>
28template <dolfinx::scalar T>
30template <dolfinx::scalar T, std::
floating_po
int U>
44template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
53 template <
typename K,
typename V,
typename W>
54 requires std::is_convertible_v<
55 std::remove_cvref_t<K>,
56 std::function<void(T*,
const T*,
const T*,
const U*,
57 const int*,
const uint8_t*)>>
58 and std::is_convertible_v<std::remove_cvref_t<V>,
59 std::vector<std::int32_t>>
60 and std::is_convertible_v<std::remove_cvref_t<W>,
78 template <
typename K,
typename W>
79 requires std::is_convertible_v<
80 std::remove_cvref_t<K>,
81 std::function<void(T*,
const T*,
const T*,
const U*,
82 const int*,
const uint8_t*)>>
83 and std::is_convertible_v<std::remove_cvref_t<W>,
97 std::function<void(T*,
const T*,
const T*,
const U*,
const int*,
137 std::floating_point U = dolfinx::scalar_value_type_t<T>>
175 template <
typename X>
176 requires std::is_convertible_v<
177 std::remove_cvref_t<X>,
190 std::span<const std::int32_t>>& entity_maps,
196 if (!_mesh and !V.empty())
197 _mesh = V[0]->mesh();
198 for (
auto& space : V)
200 if (_mesh != space->mesh()
201 and entity_maps.find(space->mesh()) == entity_maps.end())
203 throw std::runtime_error(
204 "Incompatible mesh. entity_maps must be provided.");
208 throw std::runtime_error(
"No mesh could be associated with the Form.");
211 for (
auto&& [domain_type, data] : integrals)
213 if (!std::ranges::is_sorted(data,
214 [](
auto& a,
auto& b) {
return a.id < b.id; }))
216 throw std::runtime_error(
"Integral IDs not sorted");
219 std::vector<integral_data<scalar_type, geometry_type>>& itg
220 = _integrals[
static_cast<std::size_t
>(domain_type)];
221 for (
auto&& [
id, kern, e, c] : data)
222 itg.emplace_back(
id, kern, std::move(e), std::move(c));
226 for (
auto [msh, map] : entity_maps)
227 _entity_maps.insert({msh, std::vector(map.begin(), map.end())});
244 int rank()
const {
return _function_spaces.size(); }
248 std::shared_ptr<const mesh::Mesh<geometry_type>>
mesh()
const
255 const std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>&
258 return _function_spaces;
270 const auto& integrals = _integrals[
static_cast<std::size_t
>(type)];
271 auto it = std::ranges::lower_bound(integrals, i, std::less<>{},
272 [](
const auto& a) {
return a.id; });
273 if (it != integrals.end() and it->id == i)
276 throw std::runtime_error(
"No kernel for requested domain index.");
283 std::set<IntegralType> set;
284 for (std::size_t i = 0; i < _integrals.size(); ++i)
286 if (!_integrals[i].empty())
298 return _integrals[
static_cast<std::size_t
>(type)].size();
313 assert(i < _integrals[
static_cast<std::size_t
>(type)].size());
314 return _integrals[
static_cast<std::size_t
>(type)][i].coeffs;
326 std::vector<int> ids;
327 const auto& integrals = _integrals[
static_cast<std::size_t
>(type)];
328 std::ranges::transform(integrals, std::back_inserter(ids),
329 [](
auto& integral) {
return integral.id; });
352 const auto& integrals = _integrals[
static_cast<std::size_t
>(type)];
353 auto it = std::ranges::lower_bound(integrals, i, std::less<>{},
354 [](
const auto& a) {
return a.id; });
355 if (it != integrals.end() and it->id == i)
358 throw std::runtime_error(
"No mesh entities for requested domain index.");
373 std::shared_ptr<const mesh::Mesh<geometry_type>> msh_ptr(
376 std::span<const std::int32_t> entities =
domain(type, i);
377 if (msh_ptr == _mesh)
378 return std::vector(entities.begin(), entities.end());
381 std::span<const std::int32_t> entity_map = _entity_maps.at(msh_ptr);
382 std::vector<std::int32_t> mapped_entities;
383 mapped_entities.reserve(entities.size());
388 std::ranges::transform(entities, std::back_inserter(mapped_entities),
389 [&entity_map](
auto e) {
return entity_map[e]; });
395 const int tdim = _mesh->topology()->dim();
396 const int codim = tdim -
mesh.topology()->dim();
400 for (std::size_t i = 0; i < entities.size(); i += 2)
403 mapped_entities.insert(mapped_entities.end(),
404 {entity_map[entities[i]], entities[i + 1]});
412 auto c_to_f = _mesh->topology()->connectivity(tdim, tdim - 1);
414 for (std::size_t i = 0; i < entities.size(); i += 2)
417 const std::int32_t facet
418 = c_to_f->links(entities[i])[entities[i + 1]];
420 mapped_entities.insert(mapped_entities.end(),
421 {entity_map[facet], entities[i + 1]});
425 throw std::runtime_error(
"Codimension > 1 not supported.");
432 const int tdim = _mesh->topology()->dim();
433 const int codim = tdim -
mesh.topology()->dim();
437 for (std::size_t i = 0; i < entities.size(); i += 2)
440 mapped_entities.insert(mapped_entities.end(),
441 {entity_map[entities[i]], entities[i + 1]});
449 auto c_to_f = _mesh->topology()->connectivity(tdim, tdim - 1);
451 for (std::size_t i = 0; i < entities.size(); i += 2)
454 const std::int32_t facet
455 = c_to_f->links(entities[i])[entities[i + 1]];
457 mapped_entities.insert(mapped_entities.end(),
458 {entity_map[facet], entities[i + 1]});
464 throw std::runtime_error(
"Integral type not supported.");
467 return mapped_entities;
473 std::shared_ptr<const Function<scalar_type, geometry_type>>>&
476 return _coefficients;
490 std::vector<int> n = {0};
491 for (
auto& c : _coefficients)
494 throw std::runtime_error(
"Not all form coefficients have been set.");
495 n.push_back(n.back() + c->function_space()->element()->space_dimension());
501 const std::vector<std::shared_ptr<const Constant<scalar_type>>>&
509 std::vector<std::shared_ptr<const FunctionSpace<geometry_type>>>
514 std::array<std::vector<integral_data<scalar_type, geometry_type>>, 4>
518 std::vector<std::shared_ptr<const Function<scalar_type, geometry_type>>>
522 std::vector<std::shared_ptr<const Constant<scalar_type>>> _constants;
525 std::shared_ptr<const mesh::Mesh<geometry_type>> _mesh;
528 bool _needs_facet_permutations;
531 std::map<std::shared_ptr<const mesh::Mesh<geometry_type>>,
532 std::vector<std::int32_t>>
Constant value which can be attached to a Form.
Definition Form.h:29
This class represents a finite element function space defined by a mesh, a finite element,...
Definition vtk_utils.h:32
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:35
@ 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:46
int id
Integral ID.
Definition Form.h:94
integral_data(int id, K &&kernel, V &&entities, W &&coeffs)
Create a structure to hold integral data.
Definition Form.h:62
std::function< void(T *, const T *, const T *, const U *, const int *, const uint8_t *)> kernel
The integration kernel.
Definition Form.h:99
std::vector< int > coeffs
Indices of coefficients (from the form) that are in this integral.
Definition Form.h:106
std::vector< std::int32_t > entities
The entities to integrate over.
Definition Form.h:102
integral_data(int id, K &&kernel, std::span< const std::int32_t > entities, W &&coeffs)
Create a structure to hold integral data.
Definition Form.h:85