10#include "FunctionSpace.h"
11#include "assemble_expression_impl.h"
12#include "assemble_matrix_impl.h"
13#include "assemble_scalar_impl.h"
14#include "assemble_vector_impl.h"
19#include <basix/mdspan.hpp>
21#include <dolfinx/common/types.h>
22#include <dolfinx/mesh/EntityMap.h>
35template <dolfinx::scalar T, std::
floating_po
int U>
37template <dolfinx::scalar T, std::
floating_po
int U>
39template <dolfinx::scalar T, std::
floating_po
int U>
41template <std::
floating_po
int T>
65template <dolfinx::scalar T, std::
floating_po
int U>
68 md::mdspan<
const T, md::dextents<std::size_t, 2>> coeffs,
78 throw std::invalid_argument(
79 "Expression was created on a different mesh. Cannot tabulate.");
81 auto [X, Xshape] = e.
X();
82 impl::tabulate_expression(values, e.
kernel(), Xshape, e.
value_size(), coeffs,
83 constants,
mesh, entities, element);
102template <dolfinx::scalar T, std::
floating_po
int U>
109 throw std::invalid_argument(
110 "Expression was created on a different mesh. Cannot tabulate.");
114 std::pair<std::reference_wrapper<const FiniteElement<U>>, std::size_t>>
115 element = std::nullopt;
118 std::size_t num_argument_dofs
119 = V->dofmap()->element_dof_layout().num_dofs() * V->dofmap()->bs();
120 assert(V->element());
121 element = {std::cref(*V->element()), num_argument_dofs};
125 const std::vector<std::shared_ptr<const Function<T, U>>>& coefficients
127 std::vector<T> coeffs(entities.extent(0) * coffsets.back());
128 int cstride = coffsets.back();
130 std::vector<std::reference_wrapper<const Function<T, U>>> c;
131 std::ranges::transform(coefficients, std::back_inserter(c),
139 values, e, md::mdspan(coeffs.data(), entities.extent(0), cstride),
140 std::span<const T>(constants),
mesh, entities, element);
146template <dolfinx::scalar T>
147std::map<std::pair<IntegralType, int>, std::pair<std::span<const T>,
int>>
149 std::pair<std::vector<T>,
int>>& coeffs)
151 using Key =
typename std::remove_reference_t<
decltype(coeffs)>::key_type;
152 std::map<Key, std::pair<std::span<const T>,
int>> c;
153 std::ranges::transform(
154 coeffs, std::inserter(c, c.end()),
155 [](
auto& e) ->
typename decltype(c)::value_type
156 { return {e.first, {e.second.first, e.second.second}}; });
173template <dolfinx::scalar T, std::
floating_po
int U>
175 const Form<T, U>& M, std::span<const T> constants,
176 const std::map<std::pair<IntegralType, int>,
177 std::pair<std::span<const T>,
int>>& coefficients)
180 = md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>>;
182 std::shared_ptr<const mesh::Mesh<U>>
mesh = M.
mesh();
184 std::span x =
mesh->geometry().x();
187 const int num_cell_types =
mesh->topology()->cell_types().size();
189 for (
int cell_type_idx = 0; cell_type_idx < num_cell_types; ++cell_type_idx)
192 md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>> x_dofmap
193 =
mesh->geometry().dofmaps().at(cell_type_idx);
194 val += impl::assemble_scalar(M, x_dofmap,
195 mdspanx3_t(x.data(), x.size() / 3, 3),
196 constants, coefficients, cell_type_idx);
208template <dolfinx::scalar T, std::
floating_po
int U>
231template <
typename V, std::floating_point U,
233 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
235 V&& b,
const Form<T, U>& L, std::span<const T> constants,
236 const std::map<std::pair<IntegralType, int>,
237 std::pair<std::span<const T>,
int>>& coefficients)
239 impl::assemble_vector(b, L, constants, coefficients);
248template <
typename V, std::floating_point U,
250 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
338 std::floating_point U
339 = scalar_value_t<typename std::remove_cvref_t<V>::value_type>,
341 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
344 const std::vector<std::optional<std::reference_wrapper<
const Form<T, U>>>>&
346 const std::vector<std::span<const T>>& constants,
347 const std::vector<std::map<std::pair<IntegralType, int>,
348 std::pair<std::span<const T>,
int>>>& coeffs,
351 const std::vector<std::span<const T>>& x0, T alpha)
354 if (std::ranges::all_of(a, [](
auto ai) {
return !ai; }))
359 if (!x0.empty() and x0.size() != a.size())
361 throw std::invalid_argument(
362 "Mismatch in size between x0 and bilinear form in assembler.");
365 if (a.size() != bcs1.size())
367 throw std::invalid_argument(
368 "Mismatch in size between a and bcs in assembler.");
373 std::vector<std::int8_t> bc_markers1;
374 std::vector<T> bc_values1;
375 for (std::size_t j = 0; j < a.size(); ++j)
377 if (a[j] and !bcs1[j].empty())
379 assert(a[j]->get().function_spaces().at(0));
380 auto V1 = a[j]->get().function_spaces()[1];
383 const int bs0 = a[j]->get().function_spaces()[0]->dofmaps().front()->bs();
384 const int bs1 = V1->dofmaps().front()->bs();
386 std::span<const T> _x0;
390 std::shared_ptr<const DofMap> dofmap = V1->dofmaps().front();
391 auto map1 = dofmap->index_map;
392 const int map_bs1 = dofmap->index_map_bs();
394 const int crange = map_bs1 * (map1->size_local() + map1->num_ghosts());
395 bc_markers1.assign(crange,
false);
396 bc_values1.assign(crange, 0);
397 for (
auto& bc : bcs1[j])
399 bc.get().mark_dofs(bc_markers1);
400 bc.get().set(bc_values1, std::nullopt, 1);
403 if (bs0 == 1 and bs1 == 1)
405 impl::lift_bc(b, a[j]->get(), std::integral_constant<int, 1>{},
406 std::integral_constant<int, 1>{}, constants[j], coeffs[j],
407 std::span<const T>(bc_values1), bc_markers1, _x0, alpha);
409 else if (bs0 == 3 and bs1 == 3)
411 impl::lift_bc(b, a[j]->get(), std::integral_constant<int, 3>{},
412 std::integral_constant<int, 3>{}, constants[j], coeffs[j],
413 std::span<const T>(bc_values1), bc_markers1, _x0, alpha);
417 impl::lift_bc(b, a[j]->get(), bs0, bs1, constants[j], coeffs[j],
418 std::span<const T>(bc_values1), bc_markers1, _x0, alpha);
453 std::floating_point U
454 = scalar_value_t<typename std::remove_cvref_t<V>::value_type>,
456 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
459 const std::vector<std::optional<std::reference_wrapper<
const Form<T, U>>>>&
463 const std::vector<std::span<const T>>& x0, T alpha)
466 std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>,
int>>>
468 std::vector<std::vector<T>> constants;
469 for (
const auto& _a : a)
475 coeffs.push_back(coefficients);
480 coeffs.emplace_back();
481 constants.emplace_back();
485 std::vector<std::span<const T>> _constants(constants.begin(),
487 std::vector<std::map<std::pair<IntegralType, int>,
488 std::pair<std::span<const T>,
int>>>
490 std::ranges::transform(coeffs, std::back_inserter(_coeffs),
514template <dolfinx::scalar T, std::
floating_po
int U>
517 std::span<const T> constants,
518 const std::map<std::pair<IntegralType, int>,
519 std::pair<std::span<const T>,
int>>& coefficients,
520 std::span<const std::int8_t> dof_marker0,
521 std::span<const std::int8_t> dof_marker1)
526 = md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>>;
528 std::shared_ptr<const mesh::Mesh<U>>
mesh = a.
mesh();
530 std::span x =
mesh->geometry().x();
531 impl::assemble_matrix<false>(mat_add, a,
532 mdspanx3_t(x.data(), x.size() / 3, 3), constants,
533 coefficients, dof_marker0, dof_marker1);
543template <dolfinx::scalar T, std::
floating_po
int U>
545 auto mat_add,
const Form<T, U>& a, std::span<const T> constants,
546 const std::map<std::pair<IntegralType, int>,
547 std::pair<std::span<const T>,
int>>& coefficients,
555 auto bs0 = a.
function_spaces().at(0)->dofmaps().front()->index_map_bs();
556 auto bs1 = a.
function_spaces().at(1)->dofmaps().front()->index_map_bs();
559 std::vector<std::int8_t> dof_marker0, dof_marker1;
561 std::int32_t dim0 = bs0 * (map0->size_local() + map0->num_ghosts());
563 std::int32_t dim1 = bs1 * (map1->size_local() + map1->num_ghosts());
564 for (std::size_t k = 0; k < bcs.size(); ++k)
566 assert(bcs[k].get().function_space());
567 if (a.
function_spaces().at(0)->contains(*bcs[k].get().function_space()))
569 dof_marker0.resize(dim0,
false);
570 bcs[k].get().mark_dofs(dof_marker0);
573 if (a.
function_spaces().at(1)->contains(*bcs[k].get().function_space()))
575 dof_marker1.resize(dim1,
false);
576 bcs[k].get().mark_dofs(dof_marker1);
590template <dolfinx::scalar T, std::
floating_po
int U>
616template <dolfinx::scalar T, std::
floating_po
int U>
618 std::span<const std::int8_t> dof_marker0,
619 std::span<const std::int8_t> dof_marker1)
628 impl::assemble_matrix<false>(mat_add, a, std::span(constants),
630 dof_marker0, dof_marker1);
645template <dolfinx::scalar T>
649 for (std::size_t i = 0; i < rows.size(); ++i)
651 std::span diag_span(&diagonal, 1);
652 set_fn(rows.subspan(i, 1), rows.subspan(i, 1), diag_span);
672template <dolfinx::scalar T, std::
floating_po
int U>
678 spdlog::debug(
"Set diagonal");
681 if (V.
contains(*bc.get().function_space()))
683 const auto [dofs, range] = bc.get().dof_indices();
Timer for measuring and logging elapsed time durations.
Definition Timer.h:40
Definition DirichletBC.h:259
An Expression represents a mathematical expression evaluated at a pre-defined points on a reference c...
Definition Expression.h:43
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > X() const
Evaluation point coordinates on the reference cell.
Definition Expression.h:165
const std::vector< std::shared_ptr< const Function< scalar_type, geometry_type > > > & coefficients() const
Expression coefficients.
Definition Expression.h:114
std::shared_ptr< const FunctionSpace< geometry_type > > argument_space() const
Argument function space.
Definition Expression.h:105
std::uint64_t coordinate_element_hash() const
Hash for coordinate element used to create the expression.
Definition Expression.h:178
const std::function< void(scalar_type *, const scalar_type *, const scalar_type *, const geometry_type *, const int *, const uint8_t *, void *)> & kernel() const
Function for tabulating the Expression.
Definition Expression.h:149
std::vector< int > coefficient_offsets() const
Offset for each coefficient expansion array on a cell.
Definition Expression.h:133
int value_size() const
Value size of the Expression result.
Definition Expression.h:155
const std::vector< std::reference_wrapper< const dolfinx::mesh::EntityMap > > & entity_maps() const
Maps between entities of different meshes.
Definition Expression.h:172
Model of a finite element.
Definition FiniteElement.h:62
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:35
bool contains(const FunctionSpace &V) const
Check whether V is subspace of this, or this itself.
Definition FunctionSpace.h:154
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
Concept for mdspan of rank 1 or 2.
Definition traits.h:52
Matrix accumulate/set concept for functions that can be used in assemblers to accumulate or set value...
Definition utils.h:28
Functions supporting finite element method operations.
Finite element method functionality.
Definition assemble_expression_impl.h:24
void assemble_matrix(la::MatSet< T > auto mat_add, const Form< T, U > &a, std::span< const T > constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > &coefficients, std::span< const std::int8_t > dof_marker0, std::span< const std::int8_t > dof_marker1)
Assemble bilinear form into a matrix. Matrix must already be initialised. Does not zero or finalise t...
Definition assembler.h:515
T assemble_scalar(const Form< T, U > &M, std::span< const T > constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > &coefficients)
Assemble functional into scalar.
Definition assembler.h:174
void set_diagonal(auto set_fn, std::span< const std::int32_t > rows, T diagonal=1.0)
Sets a value to the diagonal of a matrix for specified rows.
Definition assembler.h:646
void tabulate_expression(std::span< T > values, const fem::Expression< T, U > &e, md::mdspan< const T, md::dextents< std::size_t, 2 > > coeffs, std::span< const T > constants, const mesh::Mesh< U > &mesh, fem::MDSpan2 auto entities, std::optional< std::pair< std::reference_wrapper< const FiniteElement< U > >, std::size_t > > element)
Evaluate an Expression on cells or facets.
Definition assembler.h:66
std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > make_coefficients_span(const std::map< std::pair< IntegralType, int >, std::pair< std::vector< T >, int > > &coeffs)
Create a map of std::spans from a map of std::vectors.
Definition assembler.h:148
void pack_coefficients(const Form< T, U > &form, std::map< std::pair< IntegralType, int >, std::pair< std::vector< T >, int > > &coeffs)
Pack coefficients of a Form.
Definition pack.h:259
std::pair< std::vector< T >, int > allocate_coefficient_storage(const Form< T, U > &form, IntegralType integral_type, int idx)
Allocate storage for coefficients of a pair (integral_type, idx) from a Form.
Definition pack.h:181
void apply_lifting(V &&b, const std::vector< std::optional< std::reference_wrapper< const Form< T, U > > > > &a, const std::vector< std::span< const T > > &constants, const std::vector< std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > > &coeffs, const std::vector< std::vector< std::reference_wrapper< const DirichletBC< T, U > > > > &bcs1, const std::vector< std::span< const T > > &x0, T alpha)
Modify the right-hand side vector to account for constraints (Dirichlet boundary condition constraint...
Definition assembler.h:342
void assemble_vector(V &&b, const Form< T, U > &L, std::span< const T > constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > &coefficients)
Assemble linear form into a vector.
Definition assembler.h:234
std::vector< T > pack_constants(const std::vector< std::reference_wrapper< const fem::Constant< T > > > &c)
Pack constants of an Expression or Form into a single array ready for assembly.
Definition pack.h:573
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
Functions supporting the packing of coefficient data.