9 #include "CoordinateElement.h"
11 #include "ElementDofLayout.h"
12 #include <dolfinx/common/types.h>
13 #include <dolfinx/fem/Form.h>
14 #include <dolfinx/fem/Function.h>
15 #include <dolfinx/la/SparsityPattern.h>
16 #include <dolfinx/mesh/cell_types.h>
55 std::vector<std::array<std::shared_ptr<const fem::FunctionSpace>, 2>>>
59 std::vector<std::array<std::shared_ptr<const fem::FunctionSpace>, 2>>>
62 std::vector<std::array<std::shared_ptr<const fem::FunctionSpace>, 2>>(
64 for (std::size_t i = 0; i < a.size(); ++i)
66 for (std::size_t j = 0; j < a[i].size(); ++j)
69 spaces[i][j] = {form->function_spaces()[0], form->function_spaces()[1]};
85 throw std::runtime_error(
86 "Cannot create sparsity pattern. Form is not a bilinear form");
90 std::array<const std::reference_wrapper<const fem::DofMap>, 2> dofmaps{
93 std::shared_ptr mesh = a.
mesh();
97 if (types.find(IntegralType::interior_facet) != types.end()
98 or types.find(IntegralType::exterior_facet) != types.end())
101 const int tdim = mesh->topology().dim();
102 mesh->topology_mutable().create_entities(tdim - 1);
103 mesh->topology_mutable().create_connectivity(tdim - 1, tdim);
114 const std::array<
const std::reference_wrapper<const fem::DofMap>, 2>&
116 const std::set<IntegralType>& integrals);
121 const std::vector<int>& parent_map
132 create_dofmap(MPI_Comm comm,
const ufc_dofmap& dofmap, mesh::Topology& topology,
133 const std::function<std::vector<int>(
134 const graph::AdjacencyList<std::int32_t>&)>& reorder_fn,
135 std::shared_ptr<const dolfinx::fem::FiniteElement> element);
154 template <
typename T>
156 const ufc_form& ufc_form,
157 const std::vector<std::shared_ptr<const fem::FunctionSpace>>& spaces,
161 const std::shared_ptr<const mesh::Mesh>& mesh =
nullptr)
163 if (ufc_form.rank != (
int)spaces.size())
164 throw std::runtime_error(
"Wrong number of argument spaces for Form.");
165 if (ufc_form.num_coefficients != (
int)coefficients.size())
167 throw std::runtime_error(
168 "Mismatch between number of expected and provided Form coefficients.");
170 if (ufc_form.num_constants != (
int)constants.size())
172 throw std::runtime_error(
173 "Mismatch between number of expected and provided Form constants.");
178 for (std::size_t i = 0; i < spaces.size(); ++i)
180 assert(spaces[i]->element());
181 ufc_finite_element* ufc_element = ufc_form.finite_elements[i];
183 if (std::string(ufc_element->signature)
184 != spaces[i]->element()->signature())
186 throw std::runtime_error(
187 "Cannot create form. Wrong type of function space for argument.");
194 using kern = std::function<void(T*,
const T*,
const T*,
const double*,
195 const int*,
const std::uint8_t*)>;
196 std::map<IntegralType, std::pair<std::vector<std::pair<int, kern>>,
200 bool needs_facet_permutations =
false;
203 std::vector<int> cell_integral_ids(ufc_form.integral_ids(cell),
204 ufc_form.integral_ids(cell)
205 + ufc_form.num_integrals(cell));
206 for (
int i = 0; i < ufc_form.num_integrals(cell); ++i)
208 ufc_integral* integral = ufc_form.integrals(cell)[i];
210 integral_data[IntegralType::cell].first.emplace_back(
211 cell_integral_ids[i], integral->tabulate_tensor);
212 if (integral->needs_facet_permutations)
213 needs_facet_permutations =
true;
217 if (
auto it = subdomains.find(IntegralType::cell);
218 it != subdomains.end() and !cell_integral_ids.empty())
220 integral_data[IntegralType::cell].second = it->second;
226 if (ufc_form.num_integrals(exterior_facet) > 0
227 or ufc_form.num_integrals(interior_facet) > 0)
231 auto mesh = spaces[0]->mesh();
232 const int tdim = mesh->topology().dim();
233 spaces[0]->mesh()->topology_mutable().create_entities(tdim - 1);
238 std::vector<int> exterior_facet_integral_ids(
239 ufc_form.integral_ids(exterior_facet),
240 ufc_form.integral_ids(exterior_facet)
241 + ufc_form.num_integrals(exterior_facet));
242 for (
int i = 0; i < ufc_form.num_integrals(exterior_facet); ++i)
244 ufc_integral* integral = ufc_form.integrals(exterior_facet)[i];
246 integral_data[IntegralType::exterior_facet].first.emplace_back(
247 exterior_facet_integral_ids[i], integral->tabulate_tensor);
248 if (integral->needs_facet_permutations)
249 needs_facet_permutations =
true;
253 if (
auto it = subdomains.find(IntegralType::exterior_facet);
254 it != subdomains.end() and !exterior_facet_integral_ids.empty())
256 integral_data[IntegralType::exterior_facet].second = it->second;
260 std::vector<int> interior_facet_integral_ids(
261 ufc_form.integral_ids(interior_facet),
262 ufc_form.integral_ids(interior_facet)
263 + ufc_form.num_integrals(interior_facet));
264 for (
int i = 0; i < ufc_form.num_integrals(interior_facet); ++i)
266 ufc_integral* integral = ufc_form.integrals(interior_facet)[i];
268 integral_data[IntegralType::interior_facet].first.emplace_back(
269 interior_facet_integral_ids[i], integral->tabulate_tensor);
270 if (integral->needs_facet_permutations)
271 needs_facet_permutations =
true;
275 if (
auto it = subdomains.find(IntegralType::interior_facet);
276 it != subdomains.end() and !interior_facet_integral_ids.empty())
278 integral_data[IntegralType::interior_facet].second = it->second;
281 return fem::Form(spaces, integral_data, coefficients, constants,
282 needs_facet_permutations, mesh);
294 template <
typename T>
296 const ufc_form& ufc_form,
297 const std::vector<std::shared_ptr<const fem::FunctionSpace>>& spaces,
303 const std::shared_ptr<const mesh::Mesh>& mesh =
nullptr)
306 std::vector<std::shared_ptr<const fem::Function<T>>> coeff_map;
309 if (
auto it = coefficients.find(name); it != coefficients.end())
310 coeff_map.push_back(it->second);
313 throw std::runtime_error(
"Form coefficient \"" + name
314 +
"\" not provided.");
319 std::vector<std::shared_ptr<const fem::Constant<T>>> const_map;
322 if (
auto it = constants.find(name); it != constants.end())
323 const_map.push_back(it->second);
326 throw std::runtime_error(
"Form constant \"" + name +
"\" not provided.");
330 return create_form(ufc_form, spaces, coeff_map, const_map, subdomains, mesh);
344 template <
typename T>
347 const std::vector<std::shared_ptr<const fem::FunctionSpace>>& spaces,
353 const std::shared_ptr<const mesh::Mesh>& mesh =
nullptr)
355 ufc_form* form = fptr();
356 auto L = std::make_shared<fem::Form<T>>(fem::create_form<T>(
357 *form, spaces, coefficients, constants, subdomains, mesh));
374 ufc_function_space* (*fptr)(
const char*),
const std::string function_name,
375 std::shared_ptr<mesh::Mesh> mesh,
383 template <
typename T,
int _bs = -1>
384 void pack_coefficient(
386 const xtl::span<const std::uint32_t>& cell_info,
const fem::DofMap& dofmap,
387 std::int32_t num_cells, std::int32_t offset,
int space_dim,
388 const std::function<
void(
const xtl::span<T>&,
389 const xtl::span<const std::uint32_t>&,
390 std::int32_t,
int)>& transform)
392 const int bs = dofmap.
bs();
393 assert(_bs < 0 or _bs == bs);
394 for (std::int32_t cell = 0; cell < num_cells; ++cell)
397 auto cell_coeff = c.
row(cell).subspan(offset, space_dim);
398 for (std::size_t i = 0; i < dofs.size(); ++i)
400 if constexpr (_bs < 0)
402 const int pos_c = bs * i;
403 const int pos_v = bs * dofs[i];
404 for (
int k = 0; k < bs; ++k)
405 cell_coeff[pos_c + k] = v[pos_v + k];
409 const int pos_c = _bs * i;
410 const int pos_v = _bs * dofs[i];
411 for (
int k = 0; k < _bs; ++k)
412 cell_coeff[pos_c + k] = v[pos_v + k];
415 transform(cell_coeff, cell_info, cell, 1);
422 template <
typename U>
425 using T =
typename U::scalar_type;
428 const std::vector<std::shared_ptr<const fem::Function<T>>> coefficients
430 const std::vector<int> offsets = u.coefficient_offsets();
431 std::vector<const fem::DofMap*> dofmaps(coefficients.size());
432 std::vector<const fem::FiniteElement*> elements(coefficients.size());
433 std::vector<std::reference_wrapper<const std::vector<T>>> v;
434 v.reserve(coefficients.size());
435 for (std::size_t i = 0; i < coefficients.size(); ++i)
437 elements[i] = coefficients[i]->function_space()->element().get();
438 dofmaps[i] = coefficients[i]->function_space()->dofmap().get();
439 v.push_back(coefficients[i]->x()->array());
443 std::shared_ptr<const mesh::Mesh> mesh = u.mesh();
445 const int tdim = mesh->topology().dim();
446 const std::int32_t num_cells
447 = mesh->topology().index_map(tdim)->size_local()
448 + mesh->topology().index_map(tdim)->num_ghosts();
452 if (!coefficients.empty())
454 bool needs_dof_transformations =
false;
455 for (std::size_t coeff = 0; coeff < dofmaps.size(); ++coeff)
457 if (elements[coeff]->needs_dof_transformations())
459 needs_dof_transformations =
true;
460 mesh->topology_mutable().create_entity_permutations();
465 xtl::span<const std::uint32_t> cell_info;
466 if (needs_dof_transformations)
467 cell_info = xtl::span(mesh->topology().get_cell_permutation_info());
468 for (std::size_t coeff = 0; coeff < dofmaps.size(); ++coeff)
470 const std::function<void(
const xtl::span<T>&,
471 const xtl::span<const std::uint32_t>&,
474 = elements[coeff]->get_dof_transformation_function<T>(
false,
true);
475 if (
int bs = dofmaps[coeff]->bs(); bs == 1)
477 impl::pack_coefficient<T, 1>(
478 c, v[coeff], cell_info, *dofmaps[coeff], num_cells, offsets[coeff],
479 elements[coeff]->space_dimension(), transformation);
483 impl::pack_coefficient<T, 2>(
484 c, v[coeff], cell_info, *dofmaps[coeff], num_cells, offsets[coeff],
485 elements[coeff]->space_dimension(), transformation);
489 impl::pack_coefficient<T, 3>(
490 c, v[coeff], cell_info, *dofmaps[coeff], num_cells, offsets[coeff],
491 elements[coeff]->space_dimension(), transformation);
495 impl::pack_coefficient<T>(
496 c, v[coeff], cell_info, *dofmaps[coeff], num_cells, offsets[coeff],
497 elements[coeff]->space_dimension(), transformation);
507 template <
typename U>
510 using T =
typename U::scalar_type;
511 const std::vector<std::shared_ptr<const fem::Constant<T>>>& constants
515 std::int32_t size = std::accumulate(constants.begin(), constants.end(), 0,
516 [](std::int32_t sum,
const auto& constant)
517 { return sum + constant->value.size(); });
520 std::vector<T> constant_values(size);
521 std::int32_t offset = 0;
522 for (
const auto& constant : constants)
524 const std::vector<T>& value = constant->value;
525 for (std::size_t i = 0; i < value.size(); ++i)
526 constant_values[offset + i] = value[i];
527 offset += value.size();
530 return constant_values;
This class provides a dynamic 2-dimensional row-wise array data structure.
Definition: array2d.h:21
constexpr xtl::span< value_type > row(size_type i)
Access a row in the array.
Definition: array2d.h:114
A constant value which can be attached to a Form. Constants may be scalar (rank 0),...
Definition: Constant.h:19
Degree-of-freedom map.
Definition: DofMap.h:68
xtl::span< const std::int32_t > cell_dofs(int cell) const
Local-to-global mapping of dofs on a cell.
Definition: DofMap.h:113
int bs() const noexcept
Return the block size for the dofmap.
Definition: DofMap.cpp:190
This class represents a function in a finite element function space , given by.
Definition: Function.h:47
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition: AdjacencyList.h:47
This class provides a sparsity pattern data structure that can be used to initialize sparse matrices.
Definition: SparsityPattern.h:33
Topology stores the topology of a mesh, consisting of mesh entities and connectivity (incidence relat...
Definition: Topology.h:56
Miscellaneous classes, functions and types.
Finite element method functionality.
Definition: assemble_matrix_impl.h:23
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:508
Form< T > create_form(const ufc_form &ufc_form, const std::vector< std::shared_ptr< const fem::FunctionSpace >> &spaces, const std::vector< std::shared_ptr< const fem::Function< T >>> &coefficients, const std::vector< std::shared_ptr< const fem::Constant< T >>> &constants, const std::map< IntegralType, const mesh::MeshTags< int > * > &subdomains, const std::shared_ptr< const mesh::Mesh > &mesh=nullptr)
Create a Form from UFC input.
Definition: utils.h:155
ElementDofLayout create_element_dof_layout(const ufc_dofmap &dofmap, const mesh::CellType cell_type, const std::vector< int > &parent_map={})
Create an ElementDofLayout from a ufc_dofmap.
Definition: utils.cpp:77
DofMap create_dofmap(MPI_Comm comm, const ufc_dofmap &dofmap, mesh::Topology &topology, const std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> &reorder_fn, std::shared_ptr< const dolfinx::fem::FiniteElement > element)
Create a dof map on mesh from a ufc_dofmap.
Definition: utils.cpp:145
std::shared_ptr< fem::FunctionSpace > create_functionspace(ufc_function_space *(*fptr)(const char *), const std::string function_name, std::shared_ptr< mesh::Mesh > mesh, const std::function< std::vector< int >(const graph::AdjacencyList< std::int32_t > &)> &reorder_fn=nullptr)
Create a FunctionSpace from UFC data.
Definition: utils.cpp:213
std::vector< std::vector< std::array< std::shared_ptr< const fem::FunctionSpace >, 2 > > > extract_function_spaces(const std::vector< std::vector< const fem::Form< T > * >> &a)
Extract test (0) and trial (1) function spaces pairs for each bilinear form for a rectangular array o...
Definition: utils.h:56
std::vector< std::string > get_coefficient_names(const ufc_form &ufc_form)
Get the name of each coefficient in a UFC form.
Definition: utils.cpp:195
array2d< typename U::scalar_type > pack_coefficients(const U &u)
Pack coefficients of u of generic type U ready for assembly.
Definition: utils.h:423
std::vector< std::string > get_constant_names(const ufc_form &ufc_form)
Get the name of each constant in a UFC form.
Definition: utils.cpp:204
IntegralType
Type of integral.
Definition: Form.h:27
la::SparsityPattern create_sparsity_pattern(const Form< T > &a)
Create a sparsity pattern for a given form. The pattern is not finalised, i.e. the caller is responsi...
Definition: utils.h:81
Mesh data structures and algorithms on meshes.
Definition: DirichletBC.h:20
CellType
Cell type identifier.
Definition: cell_types.h:22