10#include "CoordinateElement.h"
12#include "ElementDofLayout.h"
13#include "Expression.h"
16#include "FunctionSpace.h"
17#include "sparsitybuild.h"
20#include <dolfinx/common/types.h>
21#include <dolfinx/la/SparsityPattern.h>
22#include <dolfinx/mesh/Topology.h>
23#include <dolfinx/mesh/cell_types.h>
40template <std::
floating_po
int T>
60template <
int num_cells>
61std::array<std::int32_t, 2 * num_cells>
66 assert(cells.size() == num_cells);
67 std::array<std::int32_t, 2 * num_cells> cell_local_facet_pairs;
68 for (
int c = 0; c < num_cells; ++c)
71 std::int32_t
cell = cells[c];
73 auto facet_it = std::find(cell_facets.begin(), cell_facets.end(), f);
74 assert(facet_it != cell_facets.end());
75 int local_f = std::distance(cell_facets.begin(), facet_it);
76 cell_local_facet_pairs[2 * c] =
cell;
77 cell_local_facet_pairs[2 * c + 1] = local_f;
80 return cell_local_facet_pairs;
110std::vector<std::pair<int, std::vector<std::int32_t>>>
113 std::span<const std::int32_t> entities,
int dim,
114 std::span<const int> values);
123template <dolfinx::scalar T, std::
floating_po
int U>
124std::vector<std::vector<std::array<std::shared_ptr<const FunctionSpace<U>>, 2>>>
128 std::vector<std::array<std::shared_ptr<const FunctionSpace<U>>, 2>>>
133 for (std::size_t i = 0; i < a.size(); ++i)
135 for (std::size_t j = 0; j < a[i].size(); ++j)
138 spaces[i][j] = {form->function_spaces()[0], form->function_spaces()[1]};
149template <dolfinx::scalar T, std::
floating_po
int U>
154 throw std::runtime_error(
155 "Cannot create sparsity pattern. Form is not a bilinear.");
159 std::array<std::reference_wrapper<const DofMap>, 2> dofmaps{
160 *a.function_spaces().at(0)->dofmap(),
161 *a.function_spaces().at(1)->dofmap()};
162 std::shared_ptr mesh = a.mesh();
165 std::shared_ptr mesh0 = a.function_spaces().at(0)->mesh();
167 std::shared_ptr mesh1 = a.function_spaces().at(1)->mesh();
170 const std::set<IntegralType> types = a.integral_types();
175 int tdim = mesh->topology()->dim();
176 mesh->topology_mutable()->create_entities(tdim - 1);
177 mesh->topology_mutable()->create_connectivity(tdim - 1, tdim);
183 const std::array index_maps{dofmaps[0].get().index_map,
184 dofmaps[1].get().index_map};
186 = {dofmaps[0].get().index_map_bs(), dofmaps[1].get().index_map_bs()};
188 auto extract_cells = [](std::span<const std::int32_t> facets)
190 assert(facets.size() % 2 == 0);
191 std::vector<std::int32_t> cells;
192 cells.reserve(facets.size() / 2);
193 for (std::size_t i = 0; i < facets.size(); i += 2)
194 cells.push_back(facets[i]);
200 for (
auto type : types)
202 std::vector<int> ids = a.integral_ids(type);
209 pattern, {a.domain(type,
id, *mesh0), a.domain(type,
id, *mesh1)},
210 {{dofmaps[0], dofmaps[1]}});
218 {extract_cells(a.domain(type,
id, *mesh0)),
219 extract_cells(a.domain(type,
id, *mesh1))},
220 {{dofmaps[0], dofmaps[1]}});
227 {extract_cells(a.domain(type,
id, *mesh0)),
228 extract_cells(a.domain(type,
id, *mesh1))},
229 {{dofmaps[0], dofmaps[1]}});
233 throw std::runtime_error(
"Unsupported integral type");
245 const std::vector<int>& parent_map
257 MPI_Comm comm,
const ElementDofLayout& layout, mesh::Topology& topology,
258 std::function<
void(std::span<std::int32_t>, std::uint32_t)> permute_inv,
259 std::function<std::vector<int>(
const graph::AdjacencyList<std::int32_t>&)>
273 MPI_Comm comm,
const std::vector<ElementDofLayout>& layouts,
274 mesh::Topology& topology,
275 std::function<
void(std::span<std::int32_t>, std::uint32_t)> permute_inv,
276 std::function<std::vector<int>(
const graph::AdjacencyList<std::int32_t>&)>
306template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
308 const ufcx_form& ufcx_form,
310 const std::vector<std::shared_ptr<
const Function<T, U>>>& coefficients,
311 const std::vector<std::shared_ptr<
const Constant<T>>>& constants,
314 std::vector<std::pair<std::int32_t, std::span<const std::int32_t>>>>&
317 std::span<const std::int32_t>>& entity_maps,
320 if (ufcx_form.rank != (
int)spaces.size())
321 throw std::runtime_error(
"Wrong number of argument spaces for Form.");
322 if (ufcx_form.num_coefficients != (
int)coefficients.size())
324 throw std::runtime_error(
325 "Mismatch between number of expected and provided Form coefficients.");
327 if (ufcx_form.num_constants != (
int)constants.size())
329 throw std::runtime_error(
330 "Mismatch between number of expected and provided Form constants.");
335 for (std::size_t i = 0; i < spaces.size(); ++i)
337 assert(spaces[i]->element());
338 ufcx_finite_element* ufcx_element = ufcx_form.finite_elements[i];
339 assert(ufcx_element);
340 if (std::string(ufcx_element->signature)
341 != spaces[i]->element()->signature())
343 throw std::runtime_error(
344 "Cannot create form. Wrong type of function space for argument.");
350 if (!mesh and !spaces.empty())
351 mesh = spaces[0]->mesh();
352 for (
auto& V : spaces)
354 if (mesh != V->mesh() and entity_maps.find(V->mesh()) == entity_maps.end())
355 throw std::runtime_error(
356 "Incompatible mesh. entity_maps must be provided.");
359 throw std::runtime_error(
"No mesh could be associated with the Form.");
361 auto topology = mesh->topology();
363 const int tdim = topology->dim();
365 const int* integral_offsets = ufcx_form.form_integral_offsets;
366 std::vector<int> num_integrals_type(3);
367 for (
int i = 0; i < 3; ++i)
368 num_integrals_type[i] = integral_offsets[i + 1] - integral_offsets[i];
374 mesh->topology_mutable()->create_entities(tdim - 1);
375 mesh->topology_mutable()->create_connectivity(tdim - 1, tdim);
376 mesh->topology_mutable()->create_connectivity(tdim, tdim - 1);
381 using kern_t = std::function<void(T*,
const T*,
const T*,
const U*,
382 const int*,
const std::uint8_t*)>;
383 std::map<IntegralType, std::vector<integral_data<T, U>>> integrals;
386 bool needs_facet_permutations =
false;
387 std::vector<std::int32_t> default_cells;
389 std::span<const int> ids(ufcx_form.form_integral_ids
390 + integral_offsets[
cell],
391 num_integrals_type[
cell]);
394 for (
int i = 0; i < num_integrals_type[
cell]; ++i)
396 const int id = ids[i];
397 ufcx_integral* integral
398 = ufcx_form.form_integrals[integral_offsets[
cell] + i];
402 if constexpr (std::is_same_v<T, float>)
403 k = integral->tabulate_tensor_float32;
404 else if constexpr (std::is_same_v<T, std::complex<float>>)
406 k =
reinterpret_cast<void (*)(
407 T*,
const T*,
const T*,
408 const typename scalar_value_type<T>::value_type*,
const int*,
409 const unsigned char*)
>(integral->tabulate_tensor_complex64);
411 else if constexpr (std::is_same_v<T, double>)
412 k = integral->tabulate_tensor_float64;
413 else if constexpr (std::is_same_v<T, std::complex<double>>)
415 k =
reinterpret_cast<void (*)(
416 T*,
const T*,
const T*,
417 const typename scalar_value_type<T>::value_type*,
const int*,
418 const unsigned char*)
>(integral->tabulate_tensor_complex128);
422 throw std::runtime_error(
423 "UFCx kernel function is NULL. Check requested types.");
430 assert(topology->index_map(tdim));
431 default_cells.resize(topology->index_map(tdim)->size_local(), 0);
432 std::iota(default_cells.begin(), default_cells.end(), 0);
433 itg.first->second.emplace_back(
id, k, default_cells);
435 else if (sd != subdomains.end())
438 auto it = std::lower_bound(sd->second.begin(), sd->second.end(),
id,
439 [](
auto& pair,
auto val)
440 { return pair.first < val; });
441 if (it != sd->second.end() and it->first ==
id)
442 itg.first->second.emplace_back(
id, k, it->second);
445 if (integral->needs_facet_permutations)
446 needs_facet_permutations =
true;
451 std::vector<std::int32_t> default_facets_ext;
453 std::span<const int> ids(ufcx_form.form_integral_ids
460 const int id = ids[i];
461 ufcx_integral* integral
466 if constexpr (std::is_same_v<T, float>)
467 k = integral->tabulate_tensor_float32;
468 else if constexpr (std::is_same_v<T, std::complex<float>>)
470 k =
reinterpret_cast<void (*)(
471 T*,
const T*,
const T*,
472 const typename scalar_value_type<T>::value_type*,
const int*,
473 const unsigned char*)
>(integral->tabulate_tensor_complex64);
475 else if constexpr (std::is_same_v<T, double>)
476 k = integral->tabulate_tensor_float64;
477 else if constexpr (std::is_same_v<T, std::complex<double>>)
479 k =
reinterpret_cast<void (*)(
480 T*,
const T*,
const T*,
481 const typename scalar_value_type<T>::value_type*,
const int*,
482 const unsigned char*)
>(integral->tabulate_tensor_complex128);
488 auto f_to_c = topology->connectivity(tdim - 1, tdim);
490 auto c_to_f = topology->connectivity(tdim, tdim - 1);
495 default_facets_ext.reserve(2 * bfacets.size());
496 for (std::int32_t f : bfacets)
500 = impl::get_cell_facet_pairs<1>(f, f_to_c->links(f), *c_to_f);
501 default_facets_ext.insert(default_facets_ext.end(), pair.begin(),
504 itg.first->second.emplace_back(
id, k, default_facets_ext);
506 else if (sd != subdomains.end())
509 auto it = std::lower_bound(sd->second.begin(), sd->second.end(),
id,
510 [](
auto& pair,
auto val)
511 { return pair.first < val; });
512 if (it != sd->second.end() and it->first ==
id)
513 itg.first->second.emplace_back(
id, k, it->second);
516 if (integral->needs_facet_permutations)
517 needs_facet_permutations =
true;
522 std::vector<std::int32_t> default_facets_int;
524 std::span<const int> ids(ufcx_form.form_integral_ids
531 const int id = ids[i];
532 ufcx_integral* integral
537 if constexpr (std::is_same_v<T, float>)
538 k = integral->tabulate_tensor_float32;
539 else if constexpr (std::is_same_v<T, std::complex<float>>)
541 k =
reinterpret_cast<void (*)(
542 T*,
const T*,
const T*,
543 const typename scalar_value_type<T>::value_type*,
const int*,
544 const unsigned char*)
>(integral->tabulate_tensor_complex64);
546 else if constexpr (std::is_same_v<T, double>)
547 k = integral->tabulate_tensor_float64;
548 else if constexpr (std::is_same_v<T, std::complex<double>>)
550 k =
reinterpret_cast<void (*)(
551 T*,
const T*,
const T*,
552 const typename scalar_value_type<T>::value_type*,
const int*,
553 const unsigned char*)
>(integral->tabulate_tensor_complex128);
558 auto f_to_c = topology->connectivity(tdim - 1, tdim);
560 auto c_to_f = topology->connectivity(tdim, tdim - 1);
565 assert(topology->index_map(tdim - 1));
566 std::int32_t num_facets = topology->index_map(tdim - 1)->size_local();
567 default_facets_int.reserve(4 * num_facets);
568 for (std::int32_t f = 0; f < num_facets; ++f)
570 if (f_to_c->num_links(f) == 2)
573 = impl::get_cell_facet_pairs<2>(f, f_to_c->links(f), *c_to_f);
574 default_facets_int.insert(default_facets_int.end(), pairs.begin(),
578 itg.first->second.emplace_back(
id, k, default_facets_int);
580 else if (sd != subdomains.end())
582 auto it = std::lower_bound(sd->second.begin(), sd->second.end(),
id,
583 [](
auto& pair,
auto val)
584 { return pair.first < val; });
585 if (it != sd->second.end() and it->first ==
id)
586 itg.first->second.emplace_back(
id, k, it->second);
589 if (integral->needs_facet_permutations)
590 needs_facet_permutations =
true;
595 std::vector<std::pair<std::int32_t, std::vector<std::int32_t>>>>
597 for (
auto& [itg, data] : subdomains)
599 std::vector<std::pair<std::int32_t, std::vector<std::int32_t>>> x;
600 for (
auto& [
id, idx] : data)
601 x.emplace_back(
id, std::vector(idx.data(), idx.data() + idx.size()));
602 sd.insert({itg, std::move(x)});
605 return Form<T, U>(spaces, integrals, coefficients, constants,
606 needs_facet_permutations, entity_maps, mesh);
620template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
622 const ufcx_form& ufcx_form,
624 const std::map<std::string, std::shared_ptr<
const Function<T, U>>>&
626 const std::map<std::string, std::shared_ptr<
const Constant<T>>>& constants,
629 std::vector<std::pair<std::int32_t, std::span<const std::int32_t>>>>&
634 std::vector<std::shared_ptr<const Function<T, U>>> coeff_map;
637 if (
auto it = coefficients.find(name); it != coefficients.end())
638 coeff_map.push_back(it->second);
641 throw std::runtime_error(
"Form coefficient \"" + name
642 +
"\" not provided.");
647 std::vector<std::shared_ptr<const Constant<T>>> const_map;
650 if (
auto it = constants.find(name); it != constants.end())
651 const_map.push_back(it->second);
653 throw std::runtime_error(
"Form constant \"" + name +
"\" not provided.");
657 subdomains, {}, mesh);
675template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
677 ufcx_form* (*fptr)(),
679 const std::map<std::string, std::shared_ptr<
const Function<T, U>>>&
681 const std::map<std::string, std::shared_ptr<
const Constant<T>>>& constants,
684 std::vector<std::pair<std::int32_t, std::span<const std::int32_t>>>>&
688 ufcx_form* form = fptr();
689 Form<T, U> L = create_form<T, U>(*form, spaces, coefficients, constants,
706template <std::
floating_po
int T>
709 const std::vector<std::size_t>& value_shape = {},
714 if (!e.value_shape().empty() and !value_shape.empty())
716 throw std::runtime_error(
717 "Cannot specify value shape for non-scalar base element.");
720 std::size_t bs = value_shape.empty()
722 : std::accumulate(value_shape.begin(), value_shape.end(),
723 1, std::multiplies{});
726 auto _e = std::make_shared<const FiniteElement<T>>(e, bs);
729 const std::vector<std::size_t> _value_shape
730 = (value_shape.empty() and !e.value_shape().empty())
732 mesh->geometry().dim())
736 const int num_sub_elements = _e->num_sub_elements();
737 std::vector<ElementDofLayout> sub_doflayout;
738 sub_doflayout.reserve(num_sub_elements);
739 for (
int i = 0; i < num_sub_elements; ++i)
741 auto sub_element = _e->extract_sub_element({i});
742 std::vector<int> parent_map_sub(sub_element->space_dimension());
743 for (std::size_t j = 0; j < parent_map_sub.size(); ++j)
744 parent_map_sub[j] = i + _e->block_size() * j;
745 sub_doflayout.emplace_back(1, e.entity_dofs(), e.entity_closure_dofs(),
746 parent_map_sub, std::vector<ElementDofLayout>());
750 ElementDofLayout layout(_e->block_size(), e.entity_dofs(),
751 e.entity_closure_dofs(), {}, sub_doflayout);
752 std::function<void(std::span<std::int32_t>, std::uint32_t)> permute_inv
754 if (_e->needs_dof_permutations())
755 permute_inv = _e->dof_permutation_fn(
true,
true);
757 assert(mesh->topology());
759 mesh->comm(), layout, *mesh->topology(), permute_inv, reorder_fn));
773template <std::
floating_po
int T>
775 ufcx_function_space* (*fptr)(
const char*),
const std::string& function_name,
781 ufcx_function_space* space = fptr(function_name.c_str());
784 throw std::runtime_error(
785 "Could not create UFC function space with function name "
789 ufcx_finite_element* ufcx_element = space->finite_element;
790 assert(ufcx_element);
791 std::vector<std::size_t> value_shape(space->value_shape,
792 space->value_shape + space->value_rank);
794 const auto& geometry = mesh->geometry();
795 auto& cmap = geometry.cmap();
796 if (space->geometry_degree != cmap.degree()
797 or
static_cast<basix::cell::type
>(space->geometry_basix_cell)
799 or
static_cast<basix::element::lagrange_variant
>(
800 space->geometry_basix_variant)
803 throw std::runtime_error(
"UFL mesh and CoordinateElement do not match.");
806 auto element = std::make_shared<FiniteElement<T>>(*ufcx_element);
808 ufcx_dofmap* ufcx_map = space->dofmap;
810 const auto topology = mesh->topology();
815 std::function<void(std::span<std::int32_t>, std::uint32_t)> permute_inv;
816 if (element->needs_dof_permutations())
817 permute_inv = element->dof_permutation_fn(
true,
true);
820 std::make_shared<DofMap>(
create_dofmap(mesh->comm(), layout, *topology,
821 permute_inv, reorder_fn)),
829template <dolfinx::scalar T, std::
floating_po
int U>
830std::span<const std::uint32_t>
831get_cell_orientation_info(
const Function<T, U>& coefficient)
833 std::span<const std::uint32_t> cell_info;
834 auto element = coefficient.function_space()->element();
835 if (element->needs_dof_transformations())
837 auto mesh = coefficient.function_space()->mesh();
838 mesh->topology_mutable()->create_entity_permutations();
839 cell_info = std::span(mesh->topology()->get_cell_permutation_info());
846template <dolfinx::scalar T,
int _bs>
847void pack(std::span<T> coeffs, std::int32_t
cell,
int bs, std::span<const T> v,
848 std::span<const std::uint32_t> cell_info,
const DofMap& dofmap,
852 for (std::size_t i = 0; i < dofs.size(); ++i)
854 if constexpr (_bs < 0)
856 const int pos_c = bs * i;
857 const int pos_v = bs * dofs[i];
858 for (
int k = 0; k < bs; ++k)
859 coeffs[pos_c + k] = v[pos_v + k];
863 const int pos_c = _bs * i;
864 const int pos_v = _bs * dofs[i];
865 for (
int k = 0; k < _bs; ++k)
866 coeffs[pos_c + k] = v[pos_v + k];
870 transform(coeffs, cell_info,
cell, 1);
876concept FetchCells =
requires(F&& f, std::span<const std::int32_t> v) {
877 requires std::invocable<F, std::span<const std::int32_t>>;
878 { f(v) } -> std::convertible_to<std::int32_t>;
894template <dolfinx::scalar T, std::
floating_po
int U>
897 std::span<const std::uint32_t> cell_info,
898 std::span<const std::int32_t> entities,
899 std::size_t estride,
FetchCells auto&& fetch_cells,
903 std::span<const T> v = u.x()->array();
904 const DofMap& dofmap = *u.function_space()->dofmap();
905 auto element = u.function_space()->element();
907 int space_dim = element->space_dimension();
913 const int bs = dofmap.
bs();
917 for (std::size_t e = 0; e < entities.size(); e += estride)
919 auto entity = entities.subspan(e, estride);
920 std::int32_t
cell = fetch_cells(entity);
921 auto cell_coeff = c.subspan((e / estride) * cstride + offset, space_dim);
922 pack<T, 1>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
926 for (std::size_t e = 0; e < entities.size(); e += estride)
928 auto entity = entities.subspan(e, estride);
929 std::int32_t
cell = fetch_cells(entity);
930 auto cell_coeff = c.subspan((e / estride) * cstride + offset, space_dim);
931 pack<T, 2>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
935 for (std::size_t e = 0; e < entities.size(); e += estride)
937 auto entity = entities.subspan(e, estride);
938 std::int32_t
cell = fetch_cells(entity);
939 auto cell_coeff = c.subspan(e / estride * cstride + offset, space_dim);
940 pack<T, 3>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
944 for (std::size_t e = 0; e < entities.size(); e += estride)
946 auto entity = entities.subspan(e, estride);
947 std::int32_t
cell = fetch_cells(entity);
948 auto cell_coeff = c.subspan((e / estride) * cstride + offset, space_dim);
949 pack<T, -1>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
963template <dolfinx::scalar T, std::
floating_po
int U>
964std::pair<std::vector<T>,
int>
969 const std::vector<std::shared_ptr<const Function<T, U>>>& coefficients
973 std::size_t num_entities = 0;
975 if (!coefficients.empty())
977 cstride = offsets.back();
978 num_entities = form.
domain(integral_type,
id).size();
986 return {std::vector<T>(num_entities * cstride), cstride};
993template <dolfinx::scalar T, std::
floating_po
int U>
994std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>,
int>>
997 std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>,
int>> coeffs;
1002 coeffs.emplace_hint(
1003 coeffs.end(), std::pair(integral_type,
id),
1018template <dolfinx::scalar T, std::
floating_po
int U>
1020 int id, std::span<T> c,
int cstride)
1023 const std::vector<std::shared_ptr<const Function<T, U>>>& coefficients
1027 if (!coefficients.empty())
1029 switch (integral_type)
1034 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
1036 auto mesh = coefficients[coeff]->function_space()->mesh();
1038 std::vector<std::int32_t> cells
1040 std::span<const std::uint32_t> cell_info
1041 = impl::get_cell_orientation_info(*coefficients[coeff]);
1042 impl::pack_coefficient_entity(
1043 c, cstride, *coefficients[coeff], cell_info, cells, 1,
1044 [](
auto entity) {
return entity.front(); }, offsets[coeff]);
1051 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
1053 auto mesh = coefficients[coeff]->function_space()->mesh();
1054 std::vector<std::int32_t> facets
1056 std::span<const std::uint32_t> cell_info
1057 = impl::get_cell_orientation_info(*coefficients[coeff]);
1058 impl::pack_coefficient_entity(
1059 c, cstride, *coefficients[coeff], cell_info, facets, 2,
1060 [](
auto entity) {
return entity.front(); }, offsets[coeff]);
1067 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
1069 auto mesh = coefficients[coeff]->function_space()->mesh();
1070 std::vector<std::int32_t> facets
1072 std::span<const std::uint32_t> cell_info
1073 = impl::get_cell_orientation_info(*coefficients[coeff]);
1076 impl::pack_coefficient_entity(
1077 c, 2 * cstride, *coefficients[coeff], cell_info, facets, 4,
1078 [](
auto entity) {
return entity[0]; }, 2 * offsets[coeff]);
1080 impl::pack_coefficient_entity(
1081 c, 2 * cstride, *coefficients[coeff], cell_info, facets, 4,
1082 [](
auto entity) {
return entity[2]; },
1083 offsets[coeff] + offsets[coeff + 1]);
1088 throw std::runtime_error(
1089 "Could not pack coefficient. Integral type not supported.");
1095template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
1097 const ufcx_expression& e,
1098 const std::vector<std::shared_ptr<
const Function<T, U>>>& coefficients,
1099 const std::vector<std::shared_ptr<
const Constant<T>>>& constants,
1102 if (e.rank > 0 and !argument_function_space)
1104 throw std::runtime_error(
"Expression has Argument but no Argument "
1105 "function space was provided.");
1108 std::vector<U> X(e.points, e.points + e.num_points * e.entity_dimension);
1109 std::array<std::size_t, 2> Xshape
1110 = {
static_cast<std::size_t
>(e.num_points),
1111 static_cast<std::size_t
>(e.entity_dimension)};
1112 std::vector<int> value_shape(e.value_shape, e.value_shape + e.num_components);
1113 std::function<void(T*,
const T*,
const T*,
1114 const typename scalar_value_type<T>::value_type*,
1115 const int*,
const std::uint8_t*)>
1116 tabulate_tensor =
nullptr;
1117 if constexpr (std::is_same_v<T, float>)
1118 tabulate_tensor = e.tabulate_tensor_float32;
1119 else if constexpr (std::is_same_v<T, std::complex<float>>)
1121 tabulate_tensor =
reinterpret_cast<void (*)(
1122 T*,
const T*,
const T*,
1123 const typename scalar_value_type<T>::value_type*,
const int*,
1124 const unsigned char*)
>(e.tabulate_tensor_complex64);
1126 else if constexpr (std::is_same_v<T, double>)
1127 tabulate_tensor = e.tabulate_tensor_float64;
1128 else if constexpr (std::is_same_v<T, std::complex<double>>)
1130 tabulate_tensor =
reinterpret_cast<void (*)(
1131 T*,
const T*,
const T*,
1132 const typename scalar_value_type<T>::value_type*,
const int*,
1133 const unsigned char*)
>(e.tabulate_tensor_complex128);
1136 throw std::runtime_error(
"Type not supported.");
1138 assert(tabulate_tensor);
1139 return Expression(coefficients, constants, std::span<const U>(X), Xshape,
1140 tabulate_tensor, value_shape, argument_function_space);
1145template <dolfinx::scalar T, std::
floating_po
int U = scalar_value_type_t<T>>
1147 const ufcx_expression& e,
1148 const std::map<std::string, std::shared_ptr<
const Function<T, U>>>&
1150 const std::map<std::string, std::shared_ptr<
const Constant<T>>>& constants,
1154 std::vector<std::shared_ptr<const Function<T, U>>> coeff_map;
1155 std::vector<std::string> coefficient_names;
1156 for (
int i = 0; i < e.num_coefficients; ++i)
1157 coefficient_names.push_back(e.coefficient_names[i]);
1159 for (
const std::string& name : coefficient_names)
1161 if (
auto it = coefficients.find(name); it != coefficients.end())
1162 coeff_map.push_back(it->second);
1165 throw std::runtime_error(
"Expression coefficient \"" + name
1166 +
"\" not provided.");
1171 std::vector<std::shared_ptr<const Constant<T>>> const_map;
1172 std::vector<std::string> constant_names;
1173 for (
int i = 0; i < e.num_constants; ++i)
1174 constant_names.push_back(e.constant_names[i]);
1176 for (
const std::string& name : constant_names)
1178 if (
auto it = constants.find(name); it != constants.end())
1179 const_map.push_back(it->second);
1182 throw std::runtime_error(
"Expression constant \"" + name
1183 +
"\" not provided.");
1200template <dolfinx::scalar T, std::
floating_po
int U>
1202 std::map<std::pair<IntegralType, int>,
1203 std::pair<std::vector<T>,
int>>& coeffs)
1205 for (
auto& [key, val] : coeffs)
1206 pack_coefficients<T>(form, key.first, key.second, val.first, val.second);
1217template <dolfinx::scalar T, std::
floating_po
int U>
1218std::pair<std::vector<T>,
int>
1220 std::span<const std::int32_t> entities, std::size_t estride)
1223 const std::vector<std::shared_ptr<const Function<T, U>>>& coeffs
1225 const std::vector<int> offsets = e.coefficient_offsets();
1228 const int cstride = offsets.back();
1229 std::vector<T> c(entities.size() / estride * offsets.back());
1230 if (!coeffs.empty())
1233 for (std::size_t coeff = 0; coeff < coeffs.size(); ++coeff)
1235 std::span<const std::uint32_t> cell_info
1236 = impl::get_cell_orientation_info(*coeffs[coeff]);
1238 impl::pack_coefficient_entity(
1239 std::span(c), cstride, *coeffs[coeff], cell_info, entities, estride,
1240 [](
auto entity) {
return entity[0]; }, offsets[coeff]);
1243 return {std::move(c), cstride};
1248template <
typename U>
1251 using T =
typename U::scalar_type;
1252 const std::vector<std::shared_ptr<const Constant<T>>>& constants
1256 std::int32_t size = std::accumulate(constants.cbegin(), constants.cend(), 0,
1257 [](std::int32_t sum,
auto& constant)
1258 { return sum + constant->value.size(); });
1261 std::vector<T> constant_values(size);
1262 std::int32_t offset = 0;
1263 for (
auto& constant : constants)
1265 const std::vector<T>& value = constant->value;
1266 std::copy(value.begin(), value.end(),
1267 std::next(constant_values.begin(), offset));
1268 offset += value.size();
1271 return constant_values;
Degree-of-freedom map representations and tools.
Definition CoordinateElement.h:26
double stop()
Definition Timer.cpp:45
Constant value which can be attached to a Form.
Definition Constant.h:23
Degree-of-freedom map.
Definition DofMap.h:76
std::span< const std::int32_t > cell_dofs(std::int32_t c) const
Local-to-global mapping of dofs on a cell.
Definition DofMap.h:130
int bs() const noexcept
Return the block size for the dofmap.
Definition DofMap.cpp:173
Definition ElementDofLayout.h:30
Represents a mathematical expression evaluated at a pre-defined set of points on the reference cell.
Definition Expression.h:41
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:34
Definition AdjacencyList.h:28
std::span< T > links(std::size_t node)
Definition AdjacencyList.h:112
Definition SparsityPattern.h:26
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:44
Concepts for function that returns cell index.
Definition utils.h:876
void pack(std::span< T > coeffs, std::int32_t cell, int bs, std::span< const T > v, std::span< const std::uint32_t > cell_info, const DofMap &dofmap, auto transform)
Pack a single coefficient for a single cell.
Definition utils.h:847
std::array< std::int32_t, 2 *num_cells > get_cell_facet_pairs(std::int32_t f, std::span< const std::int32_t > cells, const graph::AdjacencyList< std::int32_t > &c_to_f)
Definition utils.h:62
void pack_coefficient_entity(std::span< T > c, int cstride, const Function< T, U > &u, std::span< const std::uint32_t > cell_info, std::span< const std::int32_t > entities, std::size_t estride, FetchCells auto &&fetch_cells, std::int32_t offset)
Pack a single coefficient for a set of active entities.
Definition utils.h:895
Functions supporting mesh operations.
Miscellaneous classes, functions and types.
Definition dolfinx_common.h:8
void interior_facets(la::SparsityPattern &pattern, std::array< std::span< const std::int32_t >, 2 > cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over interior facets and insert entries into sparsity pattern.
Definition sparsitybuild.cpp:27
void cells(la::SparsityPattern &pattern, std::array< std::span< const std::int32_t >, 2 > cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition sparsitybuild.cpp:15
Finite element method functionality.
Definition assemble_matrix_impl.h:26
std::vector< std::string > get_constant_names(const ufcx_form &ufcx_form)
Get the name of each constant in a UFC form.
Definition utils.cpp:191
std::pair< std::vector< T >, int > allocate_coefficient_storage(const Form< T, U > &form, IntegralType integral_type, int id)
Allocate storage for coefficients of a pair (integral_type, id) from a Form.
Definition utils.h:965
Form< T, U > create_form_factory(const ufcx_form &ufcx_form, const std::vector< std::shared_ptr< const FunctionSpace< U > > > &spaces, const std::vector< std::shared_ptr< const Function< T, U > > > &coefficients, const std::vector< std::shared_ptr< const Constant< T > > > &constants, const std::map< IntegralType, std::vector< std::pair< std::int32_t, std::span< const std::int32_t > > > > &subdomains, const std::map< std::shared_ptr< const mesh::Mesh< U > >, std::span< const std::int32_t > > &entity_maps, std::shared_ptr< const mesh::Mesh< U > > mesh=nullptr)
Create a Form from UFCx input with coefficients and constants passed in the required order.
Definition utils.h:307
std::vector< std::pair< int, std::vector< std::int32_t > > > compute_integration_domains(IntegralType integral_type, const mesh::Topology &topology, std::span< const std::int32_t > entities, int dim, std::span< const int > values)
Given an integral type and mesh tag data, compute the entities that should be integrated over.
Definition utils.cpp:199
std::vector< DofMap > create_dofmaps(MPI_Comm comm, const std::vector< ElementDofLayout > &layouts, mesh::Topology &topology, std::function< void(std::span< std::int32_t >, std::uint32_t)> permute_inv, std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> reorder_fn)
Create a set of dofmaps on a given topology.
Definition utils.cpp:135
DofMap create_dofmap(MPI_Comm comm, const ElementDofLayout &layout, mesh::Topology &topology, std::function< void(std::span< std::int32_t >, std::uint32_t)> permute_inv, std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> reorder_fn)
Create a dof map on mesh.
Definition utils.cpp:98
std::vector< std::string > get_coefficient_names(const ufcx_form &ufcx_form)
Definition utils.cpp:184
FunctionSpace(U mesh, V element, W dofmap, X value_shape) -> FunctionSpace< typename std::remove_cvref< typename U::element_type >::type::geometry_type::value_type >
Type deduction.
std::vector< std::vector< std::array< std::shared_ptr< const FunctionSpace< U > >, 2 > > > extract_function_spaces(const std::vector< std::vector< const Form< T, U > * > > &a)
Extract test (0) and trial (1) function spaces pairs for each bilinear form for a rectangular array o...
Definition utils.h:125
std::vector< typename U::scalar_type > pack_constants(const U &u)
Pack constants of u into a single array ready for assembly.
Definition utils.h:1249
Expression< T, U > create_expression(const ufcx_expression &e, const std::vector< std::shared_ptr< const Function< T, U > > > &coefficients, const std::vector< std::shared_ptr< const Constant< T > > > &constants, std::shared_ptr< const FunctionSpace< U > > argument_function_space=nullptr)
Create Expression from UFC.
Definition utils.h:1096
IntegralType
Type of integral.
Definition Form.h:34
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
Form< T, U > create_form(const ufcx_form &ufcx_form, const std::vector< std::shared_ptr< const FunctionSpace< U > > > &spaces, const std::map< std::string, std::shared_ptr< const Function< T, U > > > &coefficients, const std::map< std::string, std::shared_ptr< const Constant< T > > > &constants, const std::map< IntegralType, std::vector< std::pair< std::int32_t, std::span< const std::int32_t > > > > &subdomains, std::shared_ptr< const mesh::Mesh< U > > mesh=nullptr)
Create a Form from UFC input with coefficients and constants resolved by name.
Definition utils.h:621
FunctionSpace< T > create_functionspace(std::shared_ptr< mesh::Mesh< T > > mesh, const basix::FiniteElement< T > &e, const std::vector< std::size_t > &value_shape={}, std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> reorder_fn=nullptr)
Create a function space from a Basix element.
Definition utils.h:707
la::SparsityPattern create_sparsity_pattern(const Form< T, U > &a)
Create a sparsity pattern for a given form.
Definition utils.h:150
std::vector< std::size_t > compute_value_shape(std::shared_ptr< const dolfinx::fem::FiniteElement< T > > element, std::size_t tdim, std::size_t gdim)
Compute the physical value shape of an element for a mesh.
Definition FunctionSpace.h:439
ElementDofLayout create_element_dof_layout(const ufcx_dofmap &dofmap, const mesh::CellType cell_type, const std::vector< int > &parent_map={})
Create an ElementDofLayout from a ufcx_dofmap.
Definition utils.cpp:32
void pack_coefficients(const Form< T, U > &form, IntegralType integral_type, int id, std::span< T > c, int cstride)
Pack coefficients of a Form for a given integral type and domain id.
Definition utils.h:1019
basix::cell::type cell_type_to_basix_type(CellType celltype)
Convert a cell type to a Basix cell type.
Definition cell_types.cpp:212
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:58
CellType
Cell type identifier.
Definition cell_types.h:22