9#include "FunctionSpace.h"
10#include "assemble_matrix_impl.h"
11#include "assemble_scalar_impl.h"
12#include "assemble_vector_impl.h"
17#include <basix/mdspan.hpp>
20#include <dolfinx/common/IndexMap.h>
21#include <dolfinx/common/log.h>
22#include <dolfinx/common/sort.h>
23#include <dolfinx/common/types.h>
24#include <dolfinx/la/utils.h>
25#include <dolfinx/mesh/EntityMap.h>
42template <dolfinx::scalar T, std::
floating_po
int U>
44template <dolfinx::scalar T, std::
floating_po
int U>
46template <std::
floating_po
int T>
52template <dolfinx::scalar T>
53std::map<std::pair<IntegralType, int>, std::pair<std::span<const T>,
int>>
55 std::pair<std::vector<T>,
int>>& coeffs)
57 using Key =
typename std::remove_reference_t<
decltype(coeffs)>::key_type;
58 std::map<Key, std::pair<std::span<const T>,
int>> c;
59 std::ranges::transform(
60 coeffs, std::inserter(c, c.end()),
61 [](
auto& e) ->
typename decltype(c)::value_type
62 { return {e.first, {e.second.first, e.second.second}}; });
79template <dolfinx::scalar T, std::
floating_po
int U>
81 const Form<T, U>& M, std::span<const T> constants,
82 const std::map<std::pair<IntegralType, int>,
83 std::pair<std::span<const T>,
int>>& coefficients)
86 = md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>>;
88 std::shared_ptr<const mesh::Mesh<U>>
mesh = M.
mesh();
90 std::span x =
mesh->geometry().x();
93 const int num_cell_types =
mesh->topology()->cell_types().size();
95 for (
int cell_type_idx = 0; cell_type_idx < num_cell_types; ++cell_type_idx)
98 md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>> x_dofmap
99 =
mesh->geometry().dofmaps().at(cell_type_idx);
100 val += impl::assemble_scalar(M, x_dofmap,
101 mdspanx3_t(x.data(), x.size() / 3, 3),
102 constants, coefficients, cell_type_idx);
114template <dolfinx::scalar T, std::
floating_po
int U>
137template <
typename V, std::floating_point U,
139 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
141 V&& b,
const Form<T, U>& L, std::span<const T> constants,
142 const std::map<std::pair<IntegralType, int>,
143 std::pair<std::span<const T>,
int>>& coefficients)
145 impl::assemble_vector(b, L, constants, coefficients);
154template <
typename V, std::floating_point U,
156 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
173template <dolfinx::scalar T, std::
floating_po
int U>
178 std::vector<std::int8_t> markers;
181 assert(bc.get().function_space());
182 if (V.
contains(*bc.get().function_space()))
186 std::shared_ptr<const DofMap> dofmap = V.
dofmaps().front();
187 std::shared_ptr<const common::IndexMap> map = dofmap->index_map;
189 markers.resize(dofmap->index_map_bs()
190 * (map->size_local() + map->num_ghosts()),
193 bc.get().mark_dofs(markers);
214template <dolfinx::scalar T, std::
floating_po
int U>
218 std::array<std::vector<std::int8_t>, 2>& storage)
221 std::span<const std::int8_t> marker0(storage[0]);
223 return {marker0, marker0};
226 return {marker0, std::span<const std::int8_t>(storage[1])};
233template <dolfinx::scalar T, std::
floating_po
int U>
234std::pair<std::vector<std::vector<std::int8_t>>, std::vector<std::vector<T>>>
236 const std::vector<std::optional<std::reference_wrapper<
const Form<T, U>>>>&
241 if (a.size() != bcs1.size())
243 throw std::invalid_argument(
244 "Mismatch in size between a and bcs in assembler.");
247 std::vector<std::vector<std::int8_t>> markers(a.size());
248 std::vector<std::vector<T>> values(a.size());
249 for (std::size_t j = 0; j < a.size(); ++j)
251 if (a[j] and !bcs1[j].empty())
253 std::shared_ptr<const DofMap> dofmap
254 = a[j]->get().function_spaces().at(1)->dofmaps().front();
255 std::shared_ptr<const common::IndexMap> map1 = dofmap->index_map;
257 const std::int32_t crange
258 = dofmap->index_map_bs() * (map1->size_local() + map1->num_ghosts());
259 markers[j].assign(crange, 0);
260 values[j].assign(crange, 0);
261 for (
auto& bc : bcs1[j])
263 bc.get().mark_dofs(markers[j]);
264 bc.get().set(values[j], std::nullopt, 1);
269 return {std::move(markers), std::move(values)};
307 std::floating_point U
308 = scalar_value_t<typename std::remove_cvref_t<V>::value_type>,
310 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
313 const std::vector<std::optional<std::reference_wrapper<
const Form<T, U>>>>&
315 const std::vector<std::span<const T>>& constants,
316 const std::vector<std::map<std::pair<IntegralType, int>,
317 std::pair<std::span<const T>,
int>>>& coeffs,
318 const std::vector<std::span<const std::int8_t>>& bc_markers1,
319 const std::vector<std::span<const T>>& bc_values1,
320 const std::vector<std::span<const T>>& x0, T alpha)
323 if (std::ranges::all_of(a, [](
auto ai) {
return !ai; }))
328 if (!x0.empty() and x0.size() != a.size())
330 throw std::invalid_argument(
331 "Mismatch in size between x0 and bilinear form in assembler.");
334 if (bc_markers1.size() != a.size() or bc_values1.size() != a.size())
336 throw std::invalid_argument(
337 "Mismatch in size between a and bc markers/values in assembler.");
340 for (std::size_t j = 0; j < a.size(); ++j)
342 if (!a[j] or bc_markers1[j].empty())
345 assert(a[j]->get().function_spaces().at(0));
346 auto V1 = a[j]->get().function_spaces()[1];
349 std::shared_ptr<const DofMap> dofmap = V1->dofmaps().front();
350 auto map1 = dofmap->index_map;
352 const std::size_t crange
353 = dofmap->index_map_bs() * (map1->size_local() + map1->num_ghosts());
354 if (bc_markers1[j].size() != crange or bc_values1[j].size() != crange)
356 throw std::invalid_argument(std::format(
357 "bc markers/values for block {} have length {}/{}, expected {}.", j,
358 bc_markers1[j].size(), bc_values1[j].size(), crange));
361 const int bs0 = a[j]->get().function_spaces()[0]->dofmaps().front()->bs();
362 const int bs1 = dofmap->bs();
364 std::span<const T> _x0;
368 impl::dispatch_bs(bs0, bs1,
369 [&b, &a, j, &constants, &coeffs, &bc_values1,
370 &bc_markers1, &_x0, alpha](
auto bs0,
auto bs1)
372 impl::lift_bc(b, a[j]->get(), bs0, bs1, constants[j],
373 coeffs[j], bc_values1[j], bc_markers1[j],
462 std::floating_point U
463 = scalar_value_t<typename std::remove_cvref_t<V>::value_type>,
465 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
468 const std::vector<std::optional<std::reference_wrapper<
const Form<T, U>>>>&
470 const std::vector<std::span<const T>>& constants,
471 const std::vector<std::map<std::pair<IntegralType, int>,
472 std::pair<std::span<const T>,
int>>>& coeffs,
475 const std::vector<std::span<const T>>& x0, T alpha)
477 auto [bc_markers1, bc_values1] = impl::bc_lifting_data(a, bcs1);
479 b, a, constants, coeffs,
480 std::vector<std::span<const std::int8_t>>(bc_markers1.begin(),
482 std::vector<std::span<const T>>(bc_values1.begin(), bc_values1.end()), x0,
520 std::floating_point U
521 = scalar_value_t<typename std::remove_cvref_t<V>::value_type>,
523 requires std::is_same_v<typename std::remove_cvref_t<V>::value_type, T>
526 const std::vector<std::optional<std::reference_wrapper<
const Form<T, U>>>>&
530 const std::vector<std::span<const T>>& x0, T alpha)
533 std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>,
int>>>
535 std::vector<std::vector<T>> constants;
536 for (
const auto& _a : a)
542 coeffs.push_back(coefficients);
547 coeffs.emplace_back();
548 constants.emplace_back();
552 std::vector<std::span<const T>> _constants(constants.begin(),
554 std::vector<std::map<std::pair<IntegralType, int>,
555 std::pair<std::span<const T>,
int>>>
557 std::ranges::transform(coeffs, std::back_inserter(_coeffs),
560 auto [bc_markers1, bc_values1] = impl::bc_lifting_data(a, bcs1);
562 b, a, _constants, _coeffs,
563 std::vector<std::span<const std::int8_t>>(bc_markers1.begin(),
565 std::vector<std::span<const T>>(bc_values1.begin(), bc_values1.end()), x0,
587template <dolfinx::scalar T, std::
floating_po
int U>
590 std::span<const T> constants,
591 const std::map<std::pair<IntegralType, int>,
592 std::pair<std::span<const T>,
int>>& coefficients,
593 std::span<const std::int8_t> dof_marker0,
594 std::span<const std::int8_t> dof_marker1)
599 = md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>>;
601 std::shared_ptr<const mesh::Mesh<U>>
mesh = a.
mesh();
603 std::span x =
mesh->geometry().x();
604 impl::assemble_matrix<false>(mat_add, a,
605 mdspanx3_t(x.data(), x.size() / 3, 3), constants,
606 coefficients, dof_marker0, dof_marker1);
619template <dolfinx::scalar T, std::
floating_po
int U>
629 std::array<std::vector<std::int8_t>, 2> markers;
630 auto [dof_marker0, dof_marker1] = impl::bc_dof_markers_pair(a, bcs, markers);
649template <dolfinx::scalar T, std::
floating_po
int U>
651 std::span<const std::int8_t> dof_marker0,
652 std::span<const std::int8_t> dof_marker1)
698template <dolfinx::scalar T, std::
floating_po
int U>
704 logger().debug(
"Set diagonal");
706 std::vector<std::int32_t> rows;
709 if (V.
contains(*bc.get().function_space()))
711 const auto [dofs, range] = bc.get().dof_indices();
712 std::span<const std::int32_t> owned = dofs.first(range);
713 rows.insert(rows.end(), owned.begin(), owned.end());
721 if (!std::ranges::is_sorted(rows))
725 rows.erase(std::ranges::unique(rows).begin(), rows.end());
std::pair< std::vector< std::vector< std::int8_t > >, std::vector< std::vector< T > > > bc_lifting_data(const std::vector< std::optional< std::reference_wrapper< const Form< T, U > > > > &a, const std::vector< std::vector< std::reference_wrapper< const DirichletBC< T, U > > > > &bcs1)
Constrained dof markers and boundary condition values on the trial space of each form in a,...
Definition assembler.h:235
std::array< std::span< const std::int8_t >, 2 > bc_dof_markers_pair(const Form< T, U > &a, const std::vector< std::reference_wrapper< const DirichletBC< T, U > > > &bcs, std::array< std::vector< std::int8_t >, 2 > &storage)
Mark the dofs of the test and trial spaces of a that the boundary conditions in bcs constrain.
Definition assembler.h:215
std::vector< std::int8_t > bc_dof_markers(const FunctionSpace< U > &V, const std::vector< std::reference_wrapper< const DirichletBC< T, U > > > &bcs)
Mark the dofs of V (owned and ghost, unrolled) constrained by the boundary conditions in bcs that are...
Definition assembler.h:174
Timer for measuring and logging elapsed time durations.
Definition Timer.h:41
Definition DirichletBC.h:261
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:36
bool contains(const FunctionSpace &V) const
Check whether V is subspace of this, or this itself.
Definition FunctionSpace.h:166
const std::vector< std::shared_ptr< const DofMap > > & dofmaps() const
The dofmaps.
Definition FunctionSpace.h:420
Matrix accumulate/set concept for functions that can be used in assemblers to accumulate or set value...
Definition utils.h:33
Finite element method functionality.
Definition assemble_expression_impl.h:28
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:588
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:80
void set_diagonal(auto set_fn, const FunctionSpace< U > &V, const std::vector< std::reference_wrapper< const DirichletBC< T, U > > > &bcs, T diagonal=T(1))
Set a value on the diagonal of the locally owned rows that a Dirichlet boundary condition constrains.
Definition assembler.h:699
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:54
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:267
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:189
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:140
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::span< const std::int8_t > > &bc_markers1, const std::vector< std::span< const T > > &bc_values1, 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:311
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:459
void set_diagonal(MatSet< T > auto &&set_fn, const common::LocalIndexRange auto &rows, T diagonal=T(1))
Set a value on the diagonal of a matrix for specified rows.
Definition utils.h:51
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
constexpr void radix_sort(R &&range, P proj={})
Sort a range with radix sorting algorithm. The bucket size is determined by the number of bits to sor...
Definition sort.h:81
auto logger() -> spdlog::logger &
Dolfinx's logger.
Definition log.cpp:24
Functions supporting the packing of coefficient data.