10#include "CoordinateElement.h"
12#include "ElementDofLayout.h"
13#include "Expression.h"
16#include "sparsitybuild.h"
19#include <dolfinx/la/SparsityPattern.h>
20#include <dolfinx/mesh/cell_types.h>
59template <
typename T,
typename =
void>
60struct scalar_value_type
67struct scalar_value_type<T, std::void_t<typename T::value_type>>
69 typedef typename T::value_type value_type;
73using scalar_value_type_t =
typename scalar_value_type<T>::value_type;
81template <
class U,
class T>
82concept FEkernel = std::is_invocable_v<U, T*,
const T*,
const T*,
83 const impl::scalar_value_type_t<T>*,
84 const int*,
const std::uint8_t*>;
94std::vector<std::vector<std::array<std::shared_ptr<const FunctionSpace>, 2>>>
97 std::vector<std::vector<std::array<std::shared_ptr<const FunctionSpace>, 2>>>
99 std::vector<std::array<std::shared_ptr<const FunctionSpace>, 2>>(
101 for (std::size_t i = 0; i < a.size(); ++i)
103 for (std::size_t j = 0; j < a[i].size(); ++j)
105 if (
const Form<T>* form = a[i][j]; form)
106 spaces[i][j] = {form->function_spaces()[0], form->function_spaces()[1]};
117 const std::array<std::reference_wrapper<const DofMap>, 2>& dofmaps,
118 const std::set<IntegralType>& integrals);
130 throw std::runtime_error(
131 "Cannot create sparsity pattern. Form is not a bilinear form");
135 std::array<std::reference_wrapper<const DofMap>, 2> dofmaps{
138 std::shared_ptr mesh = a.
mesh();
146 const int tdim = mesh->topology().dim();
147 mesh->topology_mutable().create_entities(tdim - 1);
148 mesh->topology_mutable().create_connectivity(tdim - 1, tdim);
154 const std::array index_maps{dofmaps[0].get().index_map,
155 dofmaps[1].get().index_map};
157 = {dofmaps[0].get().index_map_bs(), dofmaps[1].get().index_map_bs()};
161 for (
auto type : types)
169 const std::vector<std::int32_t>& cells = a.
cell_domains(
id);
178 {{dofmaps[0], dofmaps[1]}});
186 {{dofmaps[0], dofmaps[1]}});
190 throw std::runtime_error(
"Unsupported integral type");
202 const std::vector<int>& parent_map
215 mesh::Topology& topology,
216 const std::function<std::vector<int>(
217 const graph::AdjacencyList<std::int32_t>&)>& reorder_fn,
218 const FiniteElement& element);
239 const ufcx_form& ufcx_form,
240 const std::vector<std::shared_ptr<const FunctionSpace>>& spaces,
241 const std::vector<std::shared_ptr<
const Function<T>>>& coefficients,
242 const std::vector<std::shared_ptr<
const Constant<T>>>& constants,
244 std::shared_ptr<const mesh::Mesh> mesh =
nullptr)
246 if (ufcx_form.rank != (
int)spaces.size())
247 throw std::runtime_error(
"Wrong number of argument spaces for Form.");
248 if (ufcx_form.num_coefficients != (
int)coefficients.size())
250 throw std::runtime_error(
251 "Mismatch between number of expected and provided Form coefficients.");
253 if (ufcx_form.num_constants != (
int)constants.size())
255 throw std::runtime_error(
256 "Mismatch between number of expected and provided Form constants.");
261 for (std::size_t i = 0; i < spaces.size(); ++i)
263 assert(spaces[i]->element());
264 ufcx_finite_element* ufcx_element = ufcx_form.finite_elements[i];
265 assert(ufcx_element);
266 if (std::string(ufcx_element->signature)
267 != spaces[i]->element()->signature())
269 throw std::runtime_error(
270 "Cannot create form. Wrong type of function space for argument.");
277 using kern = std::function<void(
278 T*,
const T*,
const T*,
279 const typename impl::scalar_value_type<T>::value_type*,
const int*,
280 const std::uint8_t*)>;
281 std::map<IntegralType, std::pair<std::vector<std::pair<int, kern>>,
285 bool needs_facet_permutations =
false;
288 std::vector<int> cell_integral_ids(ufcx_form.integral_ids(
cell),
289 ufcx_form.integral_ids(
cell)
290 + ufcx_form.num_integrals(
cell));
291 for (
int i = 0; i < ufcx_form.num_integrals(
cell); ++i)
293 ufcx_integral* integral = ufcx_form.integrals(
cell)[i];
297 if constexpr (std::is_same_v<T, float>)
298 k = integral->tabulate_tensor_float32;
299 else if constexpr (std::is_same_v<T, std::complex<float>>)
301 k =
reinterpret_cast<void (*)(
302 T*,
const T*,
const T*,
303 const typename impl::scalar_value_type<T>::value_type*,
const int*,
304 const unsigned char*)
>(integral->tabulate_tensor_complex64);
306 else if constexpr (std::is_same_v<T, double>)
307 k = integral->tabulate_tensor_float64;
308 else if constexpr (std::is_same_v<T, std::complex<double>>)
310 k =
reinterpret_cast<void (*)(
311 T*,
const T*,
const T*,
312 const typename impl::scalar_value_type<T>::value_type*,
const int*,
313 const unsigned char*)
>(integral->tabulate_tensor_complex128);
319 if (integral->needs_facet_permutations)
320 needs_facet_permutations =
true;
325 it != subdomains.end() and !cell_integral_ids.empty())
338 auto mesh = spaces[0]->mesh();
339 const int tdim = mesh->topology().dim();
340 spaces[0]->mesh()->topology_mutable().create_entities(tdim - 1);
345 std::vector<int> exterior_facet_integral_ids(
355 if constexpr (std::is_same_v<T, float>)
356 k = integral->tabulate_tensor_float32;
357 else if constexpr (std::is_same_v<T, std::complex<float>>)
359 k =
reinterpret_cast<void (*)(
360 T*,
const T*,
const T*,
361 const typename impl::scalar_value_type<T>::value_type*,
const int*,
362 const unsigned char*)
>(integral->tabulate_tensor_complex64);
364 else if constexpr (std::is_same_v<T, double>)
365 k = integral->tabulate_tensor_float64;
366 else if constexpr (std::is_same_v<T, std::complex<double>>)
368 k =
reinterpret_cast<void (*)(
369 T*,
const T*,
const T*,
370 const typename impl::scalar_value_type<T>::value_type*,
const int*,
371 const unsigned char*)
>(integral->tabulate_tensor_complex128);
376 exterior_facet_integral_ids[i], k);
377 if (integral->needs_facet_permutations)
378 needs_facet_permutations =
true;
383 it != subdomains.end() and !exterior_facet_integral_ids.empty())
389 std::vector<int> interior_facet_integral_ids(
399 if constexpr (std::is_same_v<T, float>)
400 k = integral->tabulate_tensor_float32;
401 else if constexpr (std::is_same_v<T, std::complex<float>>)
403 k =
reinterpret_cast<void (*)(
404 T*,
const T*,
const T*,
405 const typename impl::scalar_value_type<T>::value_type*,
const int*,
406 const unsigned char*)
>(integral->tabulate_tensor_complex64);
408 else if constexpr (std::is_same_v<T, double>)
409 k = integral->tabulate_tensor_float64;
410 else if constexpr (std::is_same_v<T, std::complex<double>>)
412 k =
reinterpret_cast<void (*)(
413 T*,
const T*,
const T*,
414 const typename impl::scalar_value_type<T>::value_type*,
const int*,
415 const unsigned char*)
>(integral->tabulate_tensor_complex128);
420 interior_facet_integral_ids[i], k);
421 if (integral->needs_facet_permutations)
422 needs_facet_permutations =
true;
427 it != subdomains.end() and !interior_facet_integral_ids.empty())
432 return Form<T>(spaces, integral_data, coefficients, constants,
433 needs_facet_permutations, mesh);
447 const ufcx_form& ufcx_form,
448 const std::vector<std::shared_ptr<const FunctionSpace>>& spaces,
449 const std::map<std::string, std::shared_ptr<
const Function<T>>>&
451 const std::map<std::string, std::shared_ptr<
const Constant<T>>>& constants,
453 std::shared_ptr<const mesh::Mesh> mesh =
nullptr)
456 std::vector<std::shared_ptr<const Function<T>>> coeff_map;
459 if (
auto it = coefficients.find(name); it != coefficients.end())
460 coeff_map.push_back(it->second);
463 throw std::runtime_error(
"Form coefficient \"" + name
464 +
"\" not provided.");
469 std::vector<std::shared_ptr<const Constant<T>>> const_map;
472 if (
auto it = constants.find(name); it != constants.end())
473 const_map.push_back(it->second);
475 throw std::runtime_error(
"Form constant \"" + name +
"\" not provided.");
478 return create_form(ufcx_form, spaces, coeff_map, const_map, subdomains, mesh);
494 ufcx_form* (*fptr)(),
495 const std::vector<std::shared_ptr<const FunctionSpace>>& spaces,
496 const std::map<std::string, std::shared_ptr<
const Function<T>>>&
498 const std::map<std::string, std::shared_ptr<
const Constant<T>>>& constants,
500 std::shared_ptr<const mesh::Mesh> mesh =
nullptr)
502 ufcx_form* form = fptr();
503 Form<T> L = create_form<T>(*form, spaces, coefficients, constants, subdomains,
518 std::shared_ptr<mesh::Mesh> mesh,
const basix::FiniteElement& e,
int bs,
536 ufcx_function_space* (*fptr)(
const char*),
const std::string& function_name,
537 std::shared_ptr<mesh::Mesh> mesh,
547std::span<const std::uint32_t> get_cell_orientation_info(
548 const std::vector<std::shared_ptr<
const Function<T>>>& coefficients)
550 bool needs_dof_transformations =
false;
551 for (
auto coeff : coefficients)
553 std::shared_ptr<const FiniteElement> element
554 = coeff->function_space()->element();
555 if (element->needs_dof_transformations())
557 needs_dof_transformations =
true;
562 std::span<const std::uint32_t> cell_info;
563 if (needs_dof_transformations)
565 auto mesh = coefficients.front()->function_space()->mesh();
566 mesh->topology_mutable().create_entity_permutations();
567 cell_info = std::span(mesh->topology().get_cell_permutation_info());
574template <
typename T,
int _bs>
575void pack(std::span<T> coeffs, std::int32_t
cell,
int bs, std::span<const T> v,
576 std::span<const std::uint32_t> cell_info,
const DofMap& dofmap,
580 for (std::size_t i = 0; i < dofs.size(); ++i)
582 if constexpr (_bs < 0)
584 const int pos_c = bs * i;
585 const int pos_v = bs * dofs[i];
586 for (
int k = 0; k < bs; ++k)
587 coeffs[pos_c + k] = v[pos_v + k];
591 const int pos_c = _bs * i;
592 const int pos_v = _bs * dofs[i];
593 for (
int k = 0; k < _bs; ++k)
594 coeffs[pos_c + k] = v[pos_v + k];
598 transform(coeffs, cell_info,
cell, 1);
604concept FetchCells =
requires(F&& f, std::span<const std::int32_t> v) {
605 std::invocable<F, std::span<const std::int32_t>>;
608 } -> std::convertible_to<std::int32_t>;
626 std::span<const std::uint32_t> cell_info,
627 std::span<const std::int32_t> entities,
628 std::size_t estride,
FetchCells auto&& fetch_cells,
632 std::span<const T> v = u.
x()->array();
634 std::shared_ptr<const FiniteElement> element = u.
function_space()->element();
636 int space_dim = element->space_dimension();
637 const auto transformation
638 = element->get_dof_transformation_function<T>(
false,
true);
640 const int bs = dofmap.
bs();
644 for (std::size_t e = 0; e < entities.size(); e += estride)
646 auto entity = entities.subspan(e, estride);
647 std::int32_t
cell = fetch_cells(entity);
648 auto cell_coeff = c.subspan((e / estride) * cstride + offset, space_dim);
649 pack<T, 1>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
653 for (std::size_t e = 0; e < entities.size(); e += estride)
655 auto entity = entities.subspan(e, estride);
656 std::int32_t
cell = fetch_cells(entity);
657 auto cell_coeff = c.subspan((e / estride) * cstride + offset, space_dim);
658 pack<T, 2>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
662 for (std::size_t e = 0; e < entities.size(); e += estride)
664 auto entity = entities.subspan(e, estride);
665 std::int32_t
cell = fetch_cells(entity);
666 auto cell_coeff = c.subspan(e / estride * cstride + offset, space_dim);
667 pack<T, 3>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
671 for (std::size_t e = 0; e < entities.size(); e += estride)
673 auto entity = entities.subspan(e, estride);
674 std::int32_t
cell = fetch_cells(entity);
675 auto cell_coeff = c.subspan((e / estride) * cstride + offset, space_dim);
676 pack<T, -1>(cell_coeff,
cell, bs, v, cell_info, dofmap, transformation);
691std::pair<std::vector<T>,
int>
696 const std::vector<std::shared_ptr<const Function<T>>>& coefficients
700 std::size_t num_entities = 0;
702 if (!coefficients.empty())
704 cstride = offsets.back();
705 switch (integral_type)
717 throw std::runtime_error(
718 "Could not allocate coefficient data. Integral type not supported.");
722 return {std::vector<T>(num_entities * cstride), cstride};
730std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>,
int>>
733 std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>,
int>> coeffs;
739 coeffs.end(), std::pair(integral_type,
id),
756 std::span<T> c,
int cstride)
759 const std::vector<std::shared_ptr<const Function<T>>>& coefficients
763 if (!coefficients.empty())
765 std::span<const std::uint32_t> cell_info
766 = impl::get_cell_orientation_info(coefficients);
768 switch (integral_type)
772 auto fetch_cell = [](
auto& entity) {
return entity.front(); };
773 const std::vector<std::int32_t>& cells = form.
cell_domains(
id);
776 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
778 impl::pack_coefficient_entity(c, cstride, *coefficients[coeff],
779 cell_info, cells, 1, fetch_cell,
789 auto fetch_cell = [](
auto& entity) {
return entity.front(); };
792 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
794 impl::pack_coefficient_entity(c, cstride, *coefficients[coeff],
795 cell_info, facets, 2, fetch_cell,
805 auto fetch_cell0 = [](
auto& entity) {
return entity[0]; };
806 auto fetch_cell1 = [](
auto& entity) {
return entity[2]; };
809 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
812 impl::pack_coefficient_entity(c, 2 * cstride, *coefficients[coeff],
813 cell_info, facets, 4, fetch_cell0,
816 impl::pack_coefficient_entity(c, 2 * cstride, *coefficients[coeff],
817 cell_info, facets, 4, fetch_cell1,
818 offsets[coeff] + offsets[coeff + 1]);
823 throw std::runtime_error(
824 "Could not pack coefficient. Integral type not supported.");
832 const ufcx_expression& expression,
833 const std::vector<std::shared_ptr<
const Function<T>>>& coefficients,
834 const std::vector<std::shared_ptr<
const Constant<T>>>& constants,
835 std::shared_ptr<const mesh::Mesh> mesh =
nullptr,
836 std::shared_ptr<const FunctionSpace> argument_function_space =
nullptr)
838 if (expression.rank > 0 and !argument_function_space)
840 throw std::runtime_error(
841 "Expression has Argument but no Argument function space was provided.");
844 const std::size_t size
845 = expression.num_points * expression.topological_dimension;
846 std::span<const double> X(expression.points, size);
847 std::array<std::size_t, 2> Xshape
848 = {
static_cast<std::size_t
>(expression.num_points),
849 static_cast<std::size_t
>(expression.topological_dimension)};
851 std::vector<int> value_shape;
852 for (
int i = 0; i < expression.num_components; ++i)
853 value_shape.push_back(expression.value_shape[i]);
855 std::function<void(T*,
const T*,
const T*,
856 const typename impl::scalar_value_type<T>::value_type*,
857 const int*,
const std::uint8_t*)>
858 tabulate_tensor =
nullptr;
859 if constexpr (std::is_same_v<T, float>)
860 tabulate_tensor = expression.tabulate_tensor_float32;
861 else if constexpr (std::is_same_v<T, std::complex<float>>)
863 tabulate_tensor =
reinterpret_cast<void (*)(
864 T*,
const T*,
const T*,
865 const typename impl::scalar_value_type<T>::value_type*,
const int*,
866 const unsigned char*)
>(expression.tabulate_tensor_complex64);
868 else if constexpr (std::is_same_v<T, double>)
869 tabulate_tensor = expression.tabulate_tensor_float64;
870 else if constexpr (std::is_same_v<T, std::complex<double>>)
872 tabulate_tensor =
reinterpret_cast<void (*)(
873 T*,
const T*,
const T*,
874 const typename impl::scalar_value_type<T>::value_type*,
const int*,
875 const unsigned char*)
>(expression.tabulate_tensor_complex128);
878 throw std::runtime_error(
"Type not supported.");
880 assert(tabulate_tensor);
881 return Expression(coefficients, constants, X, Xshape, tabulate_tensor,
882 value_shape, mesh, argument_function_space);
889 const ufcx_expression& expression,
890 const std::map<std::string, std::shared_ptr<
const Function<T>>>&
892 const std::map<std::string, std::shared_ptr<
const Constant<T>>>& constants,
893 std::shared_ptr<const mesh::Mesh> mesh =
nullptr,
894 std::shared_ptr<const FunctionSpace> argument_function_space =
nullptr)
897 std::vector<std::shared_ptr<const Function<T>>> coeff_map;
898 std::vector<std::string> coefficient_names;
899 for (
int i = 0; i < expression.num_coefficients; ++i)
900 coefficient_names.push_back(expression.coefficient_names[i]);
902 for (
const std::string& name : coefficient_names)
904 if (
auto it = coefficients.find(name); it != coefficients.end())
905 coeff_map.push_back(it->second);
908 throw std::runtime_error(
"Expression coefficient \"" + name
909 +
"\" not provided.");
914 std::vector<std::shared_ptr<const Constant<T>>> const_map;
915 std::vector<std::string> constant_names;
916 for (
int i = 0; i < expression.num_constants; ++i)
917 constant_names.push_back(expression.constant_names[i]);
919 for (
const std::string& name : constant_names)
921 if (
auto it = constants.find(name); it != constants.end())
922 const_map.push_back(it->second);
925 throw std::runtime_error(
"Expression constant \"" + name
926 +
"\" not provided.");
931 argument_function_space);
941 std::map<std::pair<IntegralType, int>,
942 std::pair<std::vector<T>,
int>>& coeffs)
944 for (
auto& [key, val] : coeffs)
945 pack_coefficients<T>(form, key.first, key.second, val.first, val.second);
955std::pair<std::vector<T>,
int>
959 const std::vector<std::shared_ptr<const Function<T>>>& coefficients
964 const int cstride = offsets.back();
965 std::vector<T> c(cells.size() * offsets.back());
966 if (!coefficients.empty())
968 std::span<const std::uint32_t> cell_info
969 = impl::get_cell_orientation_info(coefficients);
972 for (std::size_t coeff = 0; coeff < coefficients.size(); ++coeff)
974 impl::pack_coefficient_entity(
975 std::span(c), cstride, *coefficients[coeff], cell_info, cells, 1,
976 [](
auto entity) {
return entity[0]; }, offsets[coeff]);
979 return {std::move(c), cstride};
987 using T =
typename U::scalar_type;
988 const std::vector<std::shared_ptr<const Constant<T>>>& constants
992 std::int32_t size = std::accumulate(constants.cbegin(), constants.cend(), 0,
993 [](std::int32_t sum,
auto& constant)
994 { return sum + constant->value.size(); });
997 std::vector<T> constant_values(size);
998 std::int32_t offset = 0;
999 for (
auto& constant : constants)
1001 const std::vector<T>& value = constant->value;
1002 std::copy(value.begin(), value.end(),
1003 std::next(constant_values.begin(), offset));
1004 offset += value.size();
1007 return constant_values;
Degree-of-freedom map representations and tools.
A timer can be used for timing tasks. The basic usage is.
Definition: Timer.h:31
double stop()
Stop timer, return wall time elapsed and store timing data into logger.
Definition: Timer.cpp:45
Constant value which can be attached to a Form. Constants may be scalar (rank 0), vector (rank 1),...
Definition: Constant.h:20
Degree-of-freedom map.
Definition: DofMap.h:72
std::span< const std::int32_t > cell_dofs(int cell) const
Local-to-global mapping of dofs on a cell.
Definition: DofMap.h:121
int bs() const noexcept
Return the block size for the dofmap.
Definition: DofMap.cpp:183
Represents a mathematical expression evaluated at a pre-defined set of points on the reference cell....
Definition: Expression.h:34
std::vector< int > coefficient_offsets() const
Offset for each coefficient expansion array on a cell. Used to pack data for multiple coefficients in...
Definition: Expression.h:121
const std::vector< std::shared_ptr< const Function< T > > > & coefficients() const
Get coefficients.
Definition: Expression.h:104
This class represents a function in a finite element function space , given by.
Definition: Function.h:43
std::shared_ptr< const FunctionSpace > function_space() const
Access the function space.
Definition: Function.h:134
std::shared_ptr< const la::Vector< T > > x() const
Underlying vector.
Definition: Function.h:140
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition: AdjacencyList.h:27
This class provides a sparsity pattern data structure that can be used to initialize sparse matrices....
Definition: SparsityPattern.h:34
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition: Topology.h:43
Finite element cell kernel concept.
Definition: utils.h:82
Concepts for function that returns cell index.
Definition: utils.h:604
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:575
void pack_coefficient_entity(std::span< T > c, int cstride, const Function< T > &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:625
Miscellaneous classes, functions and types.
void interior_facets(la::SparsityPattern &pattern, const mesh::Topology &topology, const std::array< const std::reference_wrapper< const DofMap >, 2 > &dofmaps)
Iterate over interior facets and insert entries into sparsity pattern.
Definition: sparsitybuild.cpp:43
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
void exterior_facets(la::SparsityPattern &pattern, const mesh::Topology &topology, const std::array< const std::reference_wrapper< const DofMap >, 2 > &dofmaps)
Iterate over exterior facets and insert entries into sparsity pattern.
Definition: sparsitybuild.cpp:112
Finite element method functionality.
Definition: assemble_matrix_impl.h:25
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:186
Form< T > create_form(const ufcx_form &ufcx_form, const std::vector< std::shared_ptr< const FunctionSpace > > &spaces, const std::vector< std::shared_ptr< const Function< T > > > &coefficients, const std::vector< std::shared_ptr< const Constant< T > > > &constants, const std::map< IntegralType, const mesh::MeshTags< int > * > &subdomains, std::shared_ptr< const mesh::Mesh > mesh=nullptr)
Create a Form from UFC input.
Definition: utils.h:238
std::vector< std::string > get_coefficient_names(const ufcx_form &ufcx_form)
Get the name of each coefficient in a UFC form.
Definition: utils.cpp:177
Expression< T > create_expression(const ufcx_expression &expression, const std::vector< std::shared_ptr< const Function< T > > > &coefficients, const std::vector< std::shared_ptr< const Constant< T > > > &constants, std::shared_ptr< const mesh::Mesh > mesh=nullptr, std::shared_ptr< const FunctionSpace > argument_function_space=nullptr)
Create Expression from UFC.
Definition: utils.h:831
std::vector< std::vector< std::array< std::shared_ptr< const FunctionSpace >, 2 > > > extract_function_spaces(const std::vector< std::vector< const Form< T > * > > &a)
Extract test (0) and trial (1) function spaces pairs for each bilinear form for a rectangular array o...
Definition: utils.h:95
void pack_coefficients(const Form< T > &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:755
std::vector< typename U::scalar_type > pack_constants(const U &u)
Pack constants of u of generic type U ready for assembly.
Definition: utils.h:985
FunctionSpace create_functionspace(std::shared_ptr< mesh::Mesh > mesh, const basix::FiniteElement &e, int bs, const std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> &reorder_fn=nullptr)
Create a FunctionSpace from a Basix element.
Definition: utils.cpp:195
IntegralType
Type of integral.
Definition: Form.h:32
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
la::SparsityPattern create_sparsity_pattern(const mesh::Topology &topology, const std::array< std::reference_wrapper< const DofMap >, 2 > &dofmaps, const std::set< IntegralType > &integrals)
Create a sparsity pattern for a given form.
Definition: utils.cpp:30
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:73
DofMap create_dofmap(MPI_Comm comm, const ElementDofLayout &layout, mesh::Topology &topology, const std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> &reorder_fn, const FiniteElement &element)
Create a dof map on mesh.
Definition: utils.cpp:140
std::pair< std::vector< T >, int > allocate_coefficient_storage(const Form< T > &form, IntegralType integral_type, int id)
Allocate storage for coefficients of a pair (integral_type, id) from a fem::Form form.
Definition: utils.h:692
Mesh data structures and algorithms on meshes.
Definition: DofMap.h:31
CellType
Cell type identifier.
Definition: cell_types.h:22