Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/d4/dec/assembler_8h_source.html
DOLFINx 0.7.3
DOLFINx C++ interface
Loading...
Searching...
No Matches
assembler.h
1// Copyright (C) 2018-2022 Garth N. Wells
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "assemble_matrix_impl.h"
10#include "assemble_scalar_impl.h"
11#include "assemble_vector_impl.h"
12#include "utils.h"
13#include <concepts>
14#include <cstdint>
15#include <dolfinx/common/types.h>
16#include <memory>
17#include <span>
18#include <vector>
19
20namespace dolfinx::fem
21{
22template <dolfinx::scalar T, std::floating_point U>
23class DirichletBC;
24template <dolfinx::scalar T, std::floating_point U>
25class Form;
26template <std::floating_point T>
27class FunctionSpace;
28
29// -- Helper functions -----------------------------------------------------
30
32template <dolfinx::scalar T>
33std::map<std::pair<IntegralType, int>, std::pair<std::span<const T>, int>>
34make_coefficients_span(const std::map<std::pair<IntegralType, int>,
35 std::pair<std::vector<T>, int>>& coeffs)
36{
37 using Key = typename std::remove_reference_t<decltype(coeffs)>::key_type;
38 std::map<Key, std::pair<std::span<const T>, int>> c;
39 std::transform(coeffs.cbegin(), coeffs.cend(), std::inserter(c, c.end()),
40 [](auto& e) -> typename decltype(c)::value_type {
41 return {e.first, {e.second.first, e.second.second}};
42 });
43 return c;
44}
45
46// -- Scalar ----------------------------------------------------------------
47
59template <dolfinx::scalar T, std::floating_point U>
60T assemble_scalar(
61 const Form<T, U>& M, std::span<const T> constants,
62 const std::map<std::pair<IntegralType, int>,
63 std::pair<std::span<const T>, int>>& coefficients)
64{
65 std::shared_ptr<const mesh::Mesh<U>> mesh = M.mesh();
66 assert(mesh);
67 if constexpr (std::is_same_v<U, scalar_value_type_t<T>>)
68 {
69 return impl::assemble_scalar(M, mesh->geometry().dofmap(),
70 mesh->geometry().x(), constants, coefficients);
71 }
72 else
73 {
74 auto x = mesh->geometry().x();
75 std::vector<scalar_value_type_t<T>> _x(x.begin(), x.end());
76 return impl::assemble_scalar(M, mesh->geometry().dofmap(), _x, constants,
77 coefficients);
78 }
79}
80
86template <dolfinx::scalar T, std::floating_point U>
87T assemble_scalar(const Form<T, U>& M)
88{
89 const std::vector<T> constants = pack_constants(M);
90 auto coefficients = allocate_coefficient_storage(M);
91 pack_coefficients(M, coefficients);
92 return assemble_scalar(M, std::span(constants),
93 make_coefficients_span(coefficients));
94}
95
96// -- Vectors ----------------------------------------------------------------
97
108template <dolfinx::scalar T, std::floating_point U>
109void assemble_vector(
110 std::span<T> b, const Form<T, U>& L, std::span<const T> constants,
111 const std::map<std::pair<IntegralType, int>,
112 std::pair<std::span<const T>, int>>& coefficients)
113{
114 impl::assemble_vector(b, L, constants, coefficients);
115}
116
121template <dolfinx::scalar T, std::floating_point U>
122void assemble_vector(std::span<T> b, const Form<T, U>& L)
123{
124 auto coefficients = allocate_coefficient_storage(L);
125 pack_coefficients(L, coefficients);
126 const std::vector<T> constants = pack_constants(L);
127 assemble_vector(b, L, std::span(constants),
128 make_coefficients_span(coefficients));
129}
130
131// FIXME: clarify how x0 is used
132// FIXME: if bcs entries are set
133
134// FIXME: need to pass an array of Vec for x0?
135// FIXME: clarify zeroing of vector
136
149template <dolfinx::scalar T, std::floating_point U>
150void apply_lifting(
151 std::span<T> b, const std::vector<std::shared_ptr<const Form<T, U>>>& a,
152 const std::vector<std::span<const T>>& constants,
153 const std::vector<std::map<std::pair<IntegralType, int>,
154 std::pair<std::span<const T>, int>>>& coeffs,
155 const std::vector<std::vector<std::shared_ptr<const DirichletBC<T, U>>>>&
156 bcs1,
157 const std::vector<std::span<const T>>& x0, T scale)
158{
159 std::shared_ptr<const mesh::Mesh<U>> mesh;
160 for (auto& a_i : a)
161 {
162 if (a_i and !mesh)
163 mesh = a_i->mesh();
164 if (a_i and mesh and a_i->mesh() != mesh)
165 throw std::runtime_error("Mismatch between meshes.");
166 }
167
168 if (!mesh)
169 throw std::runtime_error("Unable to extract a mesh.");
170
171 if constexpr (std::is_same_v<U, scalar_value_type_t<T>>)
172 {
173 impl::apply_lifting<T>(b, a, mesh->geometry().dofmap(),
174 mesh->geometry().x(), constants, coeffs, bcs1, x0,
175 scale);
176 }
177 else
178 {
179 auto x = mesh->geometry().x();
180 std::vector<scalar_value_type_t<T>> _x(x.begin(), x.end());
181 impl::apply_lifting<T>(b, a, mesh->geometry().dofmap(), _x, constants,
182 coeffs, bcs1, x0, scale);
183 }
184}
185
198template <dolfinx::scalar T, std::floating_point U>
199void apply_lifting(
200 std::span<T> b, const std::vector<std::shared_ptr<const Form<T, U>>>& a,
201 const std::vector<std::vector<std::shared_ptr<const DirichletBC<T, U>>>>&
202 bcs1,
203 const std::vector<std::span<const T>>& x0, T scale)
204{
205 std::vector<
206 std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>, int>>>
207 coeffs;
208 std::vector<std::vector<T>> constants;
209 for (auto _a : a)
210 {
211 if (_a)
212 {
213 auto coefficients = allocate_coefficient_storage(*_a);
214 pack_coefficients(*_a, coefficients);
215 coeffs.push_back(coefficients);
216 constants.push_back(pack_constants(*_a));
217 }
218 else
219 {
220 coeffs.emplace_back();
221 constants.emplace_back();
222 }
223 }
224
225 std::vector<std::span<const T>> _constants(constants.begin(),
226 constants.end());
227 std::vector<std::map<std::pair<IntegralType, int>,
228 std::pair<std::span<const T>, int>>>
229 _coeffs;
230 std::transform(coeffs.cbegin(), coeffs.cend(), std::back_inserter(_coeffs),
231 [](auto& c) { return make_coefficients_span(c); });
232
233 apply_lifting(b, a, _constants, _coeffs, bcs1, x0, scale);
234}
235
236// -- Matrices ---------------------------------------------------------------
237
250template <dolfinx::scalar T, std::floating_point U>
251void assemble_matrix(
252 la::MatSet<T> auto mat_add, const Form<T, U>& a,
253 std::span<const T> constants,
254 const std::map<std::pair<IntegralType, int>,
255 std::pair<std::span<const T>, int>>& coefficients,
256 std::span<const std::int8_t> dof_marker0,
257 std::span<const std::int8_t> dof_marker1)
258
259{
260 std::shared_ptr<const mesh::Mesh<U>> mesh = a.mesh();
261 assert(mesh);
262 if constexpr (std::is_same_v<U, scalar_value_type_t<T>>)
263 {
264 impl::assemble_matrix(mat_add, a, mesh->geometry().dofmap(),
265 mesh->geometry().x(), constants, coefficients,
266 dof_marker0, dof_marker1);
267 }
268 else
269 {
270 auto x = mesh->geometry().x();
271 std::vector<scalar_value_type_t<T>> _x(x.begin(), x.end());
272 impl::assemble_matrix(mat_add, a, mesh->geometry().dofmap(), _x, constants,
273 coefficients, dof_marker0, dof_marker1);
274 }
275}
276
284template <dolfinx::scalar T, std::floating_point U>
285void assemble_matrix(
286 auto mat_add, const Form<T, U>& a, std::span<const T> constants,
287 const std::map<std::pair<IntegralType, int>,
288 std::pair<std::span<const T>, int>>& coefficients,
289 const std::vector<std::shared_ptr<const DirichletBC<T, U>>>& bcs)
290{
291 // Index maps for dof ranges
292 auto map0 = a.function_spaces().at(0)->dofmap()->index_map;
293 auto map1 = a.function_spaces().at(1)->dofmap()->index_map;
294 auto bs0 = a.function_spaces().at(0)->dofmap()->index_map_bs();
295 auto bs1 = a.function_spaces().at(1)->dofmap()->index_map_bs();
296
297 // Build dof markers
298 std::vector<std::int8_t> dof_marker0, dof_marker1;
299 assert(map0);
300 std::int32_t dim0 = bs0 * (map0->size_local() + map0->num_ghosts());
301 assert(map1);
302 std::int32_t dim1 = bs1 * (map1->size_local() + map1->num_ghosts());
303 for (std::size_t k = 0; k < bcs.size(); ++k)
304 {
305 assert(bcs[k]);
306 assert(bcs[k]->function_space());
307 if (a.function_spaces().at(0)->contains(*bcs[k]->function_space()))
308 {
309 dof_marker0.resize(dim0, false);
310 bcs[k]->mark_dofs(dof_marker0);
311 }
312
313 if (a.function_spaces().at(1)->contains(*bcs[k]->function_space()))
314 {
315 dof_marker1.resize(dim1, false);
316 bcs[k]->mark_dofs(dof_marker1);
317 }
318 }
319
320 // Assemble
321 assemble_matrix(mat_add, a, constants, coefficients, dof_marker0,
322 dof_marker1);
323}
324
330template <dolfinx::scalar T, std::floating_point U>
331void assemble_matrix(
332 auto mat_add, const Form<T, U>& a,
333 const std::vector<std::shared_ptr<const DirichletBC<T, U>>>& bcs)
334{
335 // Prepare constants and coefficients
336 const std::vector<T> constants = pack_constants(a);
337 auto coefficients = allocate_coefficient_storage(a);
338 pack_coefficients(a, coefficients);
339
340 // Assemble
341 assemble_matrix(mat_add, a, std::span(constants),
342 make_coefficients_span(coefficients), bcs);
343}
344
355template <dolfinx::scalar T, std::floating_point U>
356void assemble_matrix(auto mat_add, const Form<T, U>& a,
357 std::span<const std::int8_t> dof_marker0,
358 std::span<const std::int8_t> dof_marker1)
359
360{
361 // Prepare constants and coefficients
362 const std::vector<T> constants = pack_constants(a);
363 auto coefficients = allocate_coefficient_storage(a);
364 pack_coefficients(a, coefficients);
365
366 // Assemble
367 assemble_matrix(mat_add, a, std::span(constants),
368 make_coefficients_span(coefficients), dof_marker0,
369 dof_marker1);
370}
371
383template <dolfinx::scalar T>
384void set_diagonal(auto set_fn, std::span<const std::int32_t> rows,
385 T diagonal = 1.0)
386{
387 for (std::size_t i = 0; i < rows.size(); ++i)
388 {
389 std::span diag_span(&diagonal, 1);
390 set_fn(rows.subspan(i, 1), rows.subspan(i, 1), diag_span);
391 }
392}
393
410template <dolfinx::scalar T, std::floating_point U>
412 auto set_fn, const FunctionSpace<U>& V,
413 const std::vector<std::shared_ptr<const DirichletBC<T, U>>>& bcs,
414 T diagonal = 1.0)
415{
416 for (auto& bc : bcs)
417 {
418 assert(bc);
419 if (V.contains(*bc->function_space()))
420 {
421 const auto [dofs, range] = bc->dof_indices();
422 set_diagonal(set_fn, dofs.first(range), diagonal);
423 }
424 }
425}
426
427// -- Setting bcs ------------------------------------------------------------
428
429// FIXME: Move these function elsewhere?
430
431// FIXME: clarify x0
432// FIXME: clarify what happens with ghosts
433
437template <dolfinx::scalar T, std::floating_point U>
438void set_bc(std::span<T> b,
439 const std::vector<std::shared_ptr<const DirichletBC<T, U>>>& bcs,
440 std::span<const T> x0, T scale = 1)
441{
442 if (b.size() > x0.size())
443 throw std::runtime_error("Size mismatch between b and x0 vectors.");
444 for (auto& bc : bcs)
445 {
446 assert(bc);
447 bc->set(b, x0, scale);
448 }
449}
450
454template <dolfinx::scalar T, std::floating_point U>
455void set_bc(std::span<T> b,
456 const std::vector<std::shared_ptr<const DirichletBC<T, U>>>& bcs,
457 T scale = 1)
458{
459 for (auto& bc : bcs)
460 {
461 assert(bc);
462 bc->set(b, scale);
463 }
464}
465
466} // namespace dolfinx::fem
Object for setting (strong) Dirichlet boundary conditions.
Definition DirichletBC.h:251
A representation of finite element variational forms.
Definition Form.h:66
const std::vector< std::shared_ptr< const FunctionSpace< U > > > & function_spaces() const
Return function spaces for all arguments.
Definition Form.h:143
std::shared_ptr< const mesh::Mesh< U > > mesh() const
Extract common mesh for the form.
Definition Form.h:138
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:107
Matrix accumulate/set concept for functions that can be used in assemblers to accumulate or set value...
Definition utils.h:28
Finite element method functionality.
Definition assemble_matrix_impl.h:25
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:920
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:384
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:34
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:1196
void set_bc(std::span< T > b, const std::vector< std::shared_ptr< const DirichletBC< T, U > > > &bcs, std::span< const T > x0, T scale=1)
Set bc values in owned (local) part of the vector, multiplied by 'scale'. The vectors b and x0 must h...
Definition assembler.h:438
FunctionSpace(U mesh, V element, W dofmap) -> FunctionSpace< typename std::remove_cvref< typename U::element_type >::type::geometry_type::value_type >
Type deduction.
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:974