9#include "FunctionSpace.h"
12#include <dolfinx/common/IndexMap.h>
13#include <dolfinx/mesh/Mesh.h>
14#include <dolfinx/mesh/MeshTags.h>
65 template <
typename X,
typename =
void>
66 struct scalar_value_type
71 struct scalar_value_type<X, std::void_t<typename X::value_type>>
73 typedef typename X::value_type value_type;
75 using scalar_value_type_t =
typename scalar_value_type<T>::value_type;
98 std::vector<std::pair<
99 int, std::function<
void(T*,
const T*,
const T*,
100 const scalar_value_type_t*,
101 const int*,
const std::uint8_t*)>>>,
106 std::shared_ptr<const mesh::Mesh>
mesh =
nullptr)
116 if (_mesh != V->mesh())
117 throw std::runtime_error(
"Incompatible mesh");
120 throw std::runtime_error(
"No mesh could be associated with the Form.");
123 for (
auto& integral_type : integrals)
130 for (
auto& integral : integral_type.second.first)
131 _cell_integrals.insert({integral.first, {integral.second, {}}});
134 for (
auto& integral : integral_type.second.first)
136 _exterior_facet_integrals.insert(
137 {integral.first, {integral.second, {}}});
141 for (
auto& integral : integral_type.second.first)
143 _interior_facet_integrals.insert(
144 {integral.first, {integral.second, {}}});
149 if (integral_type.second.second)
151 assert(_mesh == integral_type.second.second->mesh());
152 set_domains(type, *integral_type.second.second);
158 set_default_domains(*_mesh);
173 int rank()
const {
return _function_spaces.size(); }
177 std::shared_ptr<const mesh::Mesh>
mesh()
const {
return _mesh; }
181 const std::vector<std::shared_ptr<const FunctionSpace>>&
184 return _function_spaces;
192 const std::function<void(T*,
const T*,
const T*,
const scalar_value_type_t*,
193 const int*,
const std::uint8_t*)>&
199 return get_kernel_from_integrals(_cell_integrals, i);
201 return get_kernel_from_integrals(_exterior_facet_integrals, i);
203 return get_kernel_from_integrals(_interior_facet_integrals, i);
205 throw std::runtime_error(
206 "Cannot access kernel. Integral type not supported.");
214 std::set<IntegralType> set;
215 if (!_cell_integrals.empty())
217 if (!_exterior_facet_integrals.empty())
219 if (!_interior_facet_integrals.empty())
233 return _cell_integrals.size();
235 return _exterior_facet_integrals.size();
237 return _interior_facet_integrals.size();
239 throw std::runtime_error(
"Integral type not supported.");
251 std::vector<int> ids;
255 std::transform(_cell_integrals.cbegin(), _cell_integrals.cend(),
256 std::back_inserter(ids),
257 [](
auto& integral) { return integral.first; });
260 std::transform(_exterior_facet_integrals.cbegin(),
261 _exterior_facet_integrals.cend(), std::back_inserter(ids),
262 [](
auto& integral) { return integral.first; });
265 std::transform(_interior_facet_integrals.cbegin(),
266 _interior_facet_integrals.cend(), std::back_inserter(ids),
267 [](
auto& integral) { return integral.first; });
270 throw std::runtime_error(
271 "Cannot return IDs. Integral type not supported.");
283 auto it = _cell_integrals.find(i);
284 if (it == _cell_integrals.end())
285 throw std::runtime_error(
"No mesh entities for requested domain index.");
286 return it->second.second;
296 auto it = _exterior_facet_integrals.find(i);
297 if (it == _exterior_facet_integrals.end())
298 throw std::runtime_error(
"No mesh entities for requested domain index.");
299 return it->second.second;
311 auto it = _interior_facet_integrals.find(i);
312 if (it == _interior_facet_integrals.end())
313 throw std::runtime_error(
"No mesh entities for requested domain index.");
314 return it->second.second;
318 const std::vector<std::shared_ptr<const Function<T>>>&
coefficients()
const
320 return _coefficients;
333 std::vector<int> n = {0};
334 for (
const auto& c : _coefficients)
337 throw std::runtime_error(
"Not all form coefficients have been set.");
338 n.push_back(n.back() + c->function_space()->element()->space_dimension());
344 const std::vector<std::shared_ptr<const Constant<T>>>&
constants()
const
354 = std::function<void(T*,
const T*,
const T*,
const scalar_value_type_t*,
355 const int*,
const std::uint8_t*)>;
362 template <
typename U>
363 const std::function<void(T*,
const T*,
const T*,
const scalar_value_type_t*,
364 const int*,
const std::uint8_t*)>&
365 get_kernel_from_integrals(
const U& integrals,
int i)
const
367 auto it = integrals.find(i);
368 if (it == integrals.end())
369 throw std::runtime_error(
"No kernel for requested domain index.");
370 return it->second.first;
379 template <
int num_cells>
380 static std::array<std::array<std::int32_t, 2>, num_cells>
381 get_cell_local_facet_pairs(std::int32_t f,
382 std::span<const std::int32_t> cells,
386 assert(cells.size() == num_cells);
387 std::array<std::array<std::int32_t, 2>, num_cells> cell_local_facet_pairs;
388 for (
int c = 0; c < num_cells; ++c)
391 std::int32_t
cell = cells[c];
393 auto facet_it = std::find(cell_facets.begin(), cell_facets.end(), f);
394 assert(facet_it != cell_facets.end());
395 int local_f = std::distance(cell_facets.begin(), facet_it);
396 cell_local_facet_pairs[c] = {
cell, local_f};
399 return cell_local_facet_pairs;
403 void set_cell_domains(
404 std::map<
int, std::pair<kern, std::vector<std::int32_t>>>& integrals,
405 std::span<const std::int32_t> tagged_cells, std::span<const int> tags)
408 for (std::size_t i = 0; i < tagged_cells.size(); ++i)
410 if (
auto it = integrals.find(tags[i]); it != integrals.end())
412 std::vector<std::int32_t>& integration_entities = it->second.second;
413 integration_entities.push_back(tagged_cells[i]);
424 void set_exterior_facet_domains(
425 const mesh::Topology& topology,
426 std::map<
int, std::pair<kern, std::vector<std::int32_t>>>& integrals,
427 std::span<const std::int32_t> tagged_facets, std::span<const int> tags)
429 const std::vector<std::int32_t> boundary_facets
433 std::vector<std::int32_t> tagged_ext_facets;
434 std::set_intersection(tagged_facets.begin(), tagged_facets.end(),
435 boundary_facets.begin(), boundary_facets.end(),
436 std::back_inserter(tagged_ext_facets));
438 const int tdim = topology.dim();
439 auto f_to_c = topology.connectivity(tdim - 1, tdim);
441 auto c_to_f = topology.connectivity(tdim, tdim - 1);
446 for (std::int32_t f : tagged_ext_facets)
453 = std::lower_bound(tagged_facets.begin(), tagged_facets.end(), f);
454 assert(index_it != tagged_facets.end() and *index_it == f);
455 const int index = std::distance(tagged_facets.begin(), index_it);
456 if (
auto it = integrals.find(tags[index]); it != integrals.end())
460 std::array<std::int32_t, 2> facet
461 = get_cell_local_facet_pairs<1>(f, f_to_c->links(f), *c_to_f)
463 std::vector<std::int32_t>& integration_entities = it->second.second;
464 integration_entities.insert(integration_entities.end(), facet.cbegin(),
471 static void set_interior_facet_domains(
472 const mesh::Topology& topology,
473 std::map<
int, std::pair<kern, std::vector<std::int32_t>>>& integrals,
474 std::span<const std::int32_t> tagged_facets, std::span<const int> tags)
476 int tdim = topology.dim();
477 auto f_to_c = topology.connectivity(tdim - 1, tdim);
479 auto c_to_f = topology.connectivity(tdim, tdim - 1);
481 for (std::size_t i = 0; i < tagged_facets.size(); ++i)
483 const std::int32_t f = tagged_facets[i];
484 if (f_to_c->num_links(f) == 2)
486 if (
auto it = integrals.find(tags[i]); it != integrals.end())
490 auto [facet_0, facet_1]
491 = get_cell_local_facet_pairs<2>(f, f_to_c->links(f), *c_to_f);
492 std::vector<std::int32_t>& integration_entities = it->second.second;
493 integration_entities.insert(integration_entities.end(),
494 facet_0.cbegin(), facet_0.cend());
495 integration_entities.insert(integration_entities.end(),
496 facet_1.cbegin(), facet_1.cend());
508 void set_domains(
IntegralType type,
const mesh::MeshTags<int>& marker)
510 std::shared_ptr<const mesh::Mesh>
mesh = marker.mesh();
511 const mesh::Topology& topology =
mesh->topology();
512 const int tdim = topology.dim();
514 if (dim != marker.dim())
516 throw std::runtime_error(
"Invalid MeshTags dimension: "
517 + std::to_string(marker.dim()));
521 assert(topology.index_map(dim));
523 = std::lower_bound(marker.indices().begin(), marker.indices().end(),
524 topology.index_map(dim)->size_local());
526 std::span<const std::int32_t> owned_tagged_entities(
527 marker.indices().data(),
528 std::distance(marker.indices().begin(), entity_end));
532 set_cell_domains(_cell_integrals, owned_tagged_entities, marker.values());
535 mesh->topology_mutable().create_connectivity(dim, tdim);
536 mesh->topology_mutable().create_connectivity(tdim, dim);
540 set_exterior_facet_domains(topology, _exterior_facet_integrals,
541 owned_tagged_entities, marker.values());
544 set_interior_facet_domains(topology, _interior_facet_integrals,
545 owned_tagged_entities, marker.values());
548 throw std::runtime_error(
549 "Cannot set domains. Integral type not supported.");
559 void set_default_domains(
const mesh::Mesh&
mesh)
561 const mesh::Topology& topology =
mesh.topology();
562 const int tdim = topology.dim();
566 for (
auto& [domain_id, kernel_cells] : _cell_integrals)
570 std::vector<std::int32_t>&
cells = kernel_cells.second;
571 const int num_cells = topology.index_map(tdim)->size_local();
572 cells.resize(num_cells);
580 if (!_exterior_facet_integrals.empty())
582 mesh.topology_mutable().create_connectivity(tdim - 1, tdim);
583 mesh.topology_mutable().create_connectivity(tdim, tdim - 1);
586 const std::vector<std::int32_t> boundary_facets
587 = _exterior_facet_integrals.empty()
588 ? std::vector<std::int32_t>()
590 for (
auto& [domain_id, kernel_facets] : _exterior_facet_integrals)
594 std::vector<std::int32_t>& facets = kernel_facets.second;
597 auto f_to_c = topology.connectivity(tdim - 1, tdim);
599 auto c_to_f = topology.connectivity(tdim, tdim - 1);
601 for (std::int32_t f : boundary_facets)
604 std::array<std::int32_t, 2> pair
605 = get_cell_local_facet_pairs<1>(f, f_to_c->links(f), *c_to_f)[0];
606 facets.insert(facets.end(), pair.cbegin(), pair.cend());
613 for (
auto& [domain_id, kernel_facets] : _interior_facet_integrals)
617 std::vector<std::int32_t>& facets = kernel_facets.second;
620 mesh.topology_mutable().create_connectivity(tdim - 1, tdim);
621 auto f_to_c = topology.connectivity(tdim - 1, tdim);
623 mesh.topology_mutable().create_connectivity(tdim, tdim - 1);
624 auto c_to_f =
mesh.topology().connectivity(tdim, tdim - 1);
628 assert(topology.index_map(tdim - 1));
629 const int num_facets = topology.index_map(tdim - 1)->size_local();
630 facets.reserve(num_facets);
631 for (
int f = 0; f < num_facets; ++f)
633 if (f_to_c->num_links(f) == 2)
635 const std::array<std::array<std::int32_t, 2>, 2> pairs
636 = get_cell_local_facet_pairs<2>(f, f_to_c->links(f), *c_to_f);
637 facets.insert(facets.end(), pairs[0].cbegin(), pairs[0].cend());
638 facets.insert(facets.end(), pairs[1].cbegin(), pairs[1].cend());
646 std::vector<std::shared_ptr<const FunctionSpace>> _function_spaces;
649 std::vector<std::shared_ptr<const Function<T>>> _coefficients;
652 std::vector<std::shared_ptr<const Constant<T>>> _constants;
655 std::shared_ptr<const mesh::Mesh> _mesh;
658 std::map<int, std::pair<kern, std::vector<std::int32_t>>> _cell_integrals;
661 std::map<int, std::pair<kern, std::vector<std::int32_t>>>
662 _exterior_facet_integrals;
665 std::map<int, std::pair<kern, std::vector<std::int32_t>>>
666 _interior_facet_integrals;
669 bool _needs_facet_permutations;
Constant value which can be attached to a Form. Constants may be scalar (rank 0), vector (rank 1),...
Definition: Constant.h:20
This class represents a function in a finite element function space , given by.
Definition: Function.h:43
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition: AdjacencyList.h:27
std::span< T > links(int node)
Get the links (edges) for given node.
Definition: AdjacencyList.h:109
void cells(la::SparsityPattern &pattern, const mesh::Topology &topology, const std::array< const std::reference_wrapper< const DofMap >, 2 > &dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition: sparsitybuild.cpp:18
Finite element method functionality.
Definition: assemble_matrix_impl.h:25
IntegralType
Type of integral.
Definition: Form.h:32
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
std::vector< std::int32_t > exterior_facet_indices(const Topology &topology)
Compute the indices of all exterior facets that are owned by the caller.
Definition: utils.cpp:580