Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/v0.3.0/v0.9.0/cpp
DOLFINx  0.3.0
DOLFINx C++ interface
assembler.h
1 // Copyright (C) 2018-2020 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 <memory>
13 #include <vector>
14 #include <xtl/xspan.hpp>
15 
16 namespace dolfinx::fem
17 {
18 template <typename T>
19 class DirichletBC;
20 template <typename T>
21 class Form;
22 class FunctionSpace;
23 
24 // -- Scalar ----------------------------------------------------------------
25 
35 template <typename T>
36 T assemble_scalar(const Form<T>& M, const xtl::span<const T>& constants,
37  const array2d<T>& coeffs)
38 {
39  return impl::assemble_scalar(M, constants, coeffs);
40 }
41 
47 template <typename T>
49 {
50  const std::vector<T> constants = pack_constants(M);
51  const array2d<T> coeffs = pack_coefficients(M);
52  return assemble_scalar(M, tcb::make_span(constants), coeffs);
53 }
54 
55 // -- Vectors ----------------------------------------------------------------
56 
65 template <typename T>
66 void assemble_vector(xtl::span<T> b, const Form<T>& L,
67  const xtl::span<const T>& constants,
68  const array2d<T>& coeffs)
69 {
70  impl::assemble_vector(b, L, constants, coeffs);
71 }
72 
77 template <typename T>
78 void assemble_vector(xtl::span<T> b, const Form<T>& L)
79 {
80  const std::vector<T> constants = pack_constants(L);
81  const array2d<T> coeffs = pack_coefficients(L);
82  assemble_vector(b, L, tcb::make_span(constants), coeffs);
83 }
84 
85 // FIXME: clarify how x0 is used
86 // FIXME: if bcs entries are set
87 
88 // FIXME: need to pass an array of Vec for x0?
89 // FIXME: clarify zeroing of vector
90 
103 template <typename T>
105  xtl::span<T> b, const std::vector<std::shared_ptr<const Form<T>>>& a,
106  const std::vector<xtl::span<const T>>& constants,
107  const std::vector<const array2d<T>*>& coeffs,
108  const std::vector<std::vector<std::shared_ptr<const DirichletBC<T>>>>& bcs1,
109  const std::vector<xtl::span<const T>>& x0, double scale)
110 {
111  impl::apply_lifting(b, a, constants, coeffs, bcs1, x0, scale);
112 }
113 
126 template <typename T>
128  xtl::span<T> b, const std::vector<std::shared_ptr<const Form<T>>>& a,
129  const std::vector<std::vector<std::shared_ptr<const DirichletBC<T>>>>& bcs1,
130  const std::vector<xtl::span<const T>>& x0, double scale)
131 {
132  std::vector<std::unique_ptr<array2d<T>>> coeffs;
133  std::vector<std::vector<T>> constants;
134  for (auto _a : a)
135  {
136  if (_a)
137  {
138  coeffs.push_back(std::make_unique<array2d<T>>(pack_coefficients(*_a)));
139  constants.push_back(pack_constants(*_a));
140  }
141  else
142  {
143  coeffs.push_back(nullptr);
144  constants.push_back({});
145  }
146  }
147 
148  std::vector<const array2d<T>*> _coeffs;
149  std::for_each(coeffs.begin(), coeffs.end(),
150  [&_coeffs](const auto& c) { _coeffs.push_back(c.get()); });
151  std::vector<xtl::span<const T>> _constants(constants.begin(),
152  constants.end());
153  apply_lifting(b, a, _constants, _coeffs, bcs1, x0, scale);
154 }
155 
156 // -- Matrices ---------------------------------------------------------------
157 
165 template <typename T>
167  const std::function<int(std::int32_t, const std::int32_t*, std::int32_t,
168  const std::int32_t*, const T*)>& mat_add,
169  const Form<T>& a, const xtl::span<const T>& constants,
170  const array2d<T>& coeffs,
171  const std::vector<std::shared_ptr<const DirichletBC<T>>>& bcs)
172 {
173  // Index maps for dof ranges
174  auto map0 = a.function_spaces().at(0)->dofmap()->index_map;
175  auto map1 = a.function_spaces().at(1)->dofmap()->index_map;
176  auto bs0 = a.function_spaces().at(0)->dofmap()->index_map_bs();
177  auto bs1 = a.function_spaces().at(1)->dofmap()->index_map_bs();
178 
179  // Build dof markers
180  std::vector<bool> dof_marker0, dof_marker1;
181  assert(map0);
182  std::int32_t dim0 = bs0 * (map0->size_local() + map0->num_ghosts());
183  assert(map1);
184  std::int32_t dim1 = bs1 * (map1->size_local() + map1->num_ghosts());
185  for (std::size_t k = 0; k < bcs.size(); ++k)
186  {
187  assert(bcs[k]);
188  assert(bcs[k]->function_space());
189  if (a.function_spaces().at(0)->contains(*bcs[k]->function_space()))
190  {
191  dof_marker0.resize(dim0, false);
192  bcs[k]->mark_dofs(dof_marker0);
193  }
194 
195  if (a.function_spaces().at(1)->contains(*bcs[k]->function_space()))
196  {
197  dof_marker1.resize(dim1, false);
198  bcs[k]->mark_dofs(dof_marker1);
199  }
200  }
201 
202  // Assemble
203  impl::assemble_matrix(mat_add, a, constants, coeffs, dof_marker0,
204  dof_marker1);
205 }
206 
212 template <typename T>
214  const std::function<int(std::int32_t, const std::int32_t*, std::int32_t,
215  const std::int32_t*, const T*)>& mat_add,
216  const Form<T>& a,
217  const std::vector<std::shared_ptr<const DirichletBC<T>>>& bcs)
218 {
219  // Prepare constants and coefficients
220  const std::vector<T> constants = pack_constants(a);
221  const array2d<T> coeffs = pack_coefficients(a);
222 
223  // Assemble
224  assemble_matrix(mat_add, a, tcb::make_span(constants), coeffs, bcs);
225 }
226 
239 template <typename T>
241  const std::function<int(std::int32_t, const std::int32_t*, std::int32_t,
242  const std::int32_t*, const T*)>& mat_add,
243  const Form<T>& a, const xtl::span<const T>& constants,
244  const array2d<T>& coeffs, const std::vector<bool>& dof_marker0,
245  const std::vector<bool>& dof_marker1)
246 
247 {
248  impl::assemble_matrix(mat_add, a, constants, coeffs, dof_marker0,
249  dof_marker1);
250 }
251 
262 template <typename T>
264  const std::function<int(std::int32_t, const std::int32_t*, std::int32_t,
265  const std::int32_t*, const T*)>& mat_add,
266  const Form<T>& a, const std::vector<bool>& dof_marker0,
267  const std::vector<bool>& dof_marker1)
268 
269 {
270  // Prepare constants and coefficients
271  const std::vector<T> constants = pack_constants(a);
272  const array2d<T> coeffs = pack_coefficients(a);
273 
274  // Assemble
275  assemble_matrix(mat_add, a, tcb::make_span(constants), coeffs, dof_marker0,
276  dof_marker1);
277 }
278 
289 template <typename T>
291  const std::function<int(std::int32_t, const std::int32_t*, std::int32_t,
292  const std::int32_t*, const T*)>& set_fn,
293  const xtl::span<const std::int32_t>& rows, T diagonal = 1.0)
294 {
295  for (std::size_t i = 0; i < rows.size(); ++i)
296  {
297  const std::int32_t row = rows[i];
298  set_fn(1, &row, 1, &row, &diagonal);
299  }
300 }
301 
317 template <typename T>
319  const std::function<int(std::int32_t, const std::int32_t*, std::int32_t,
320  const std::int32_t*, const T*)>& set_fn,
321  const fem::FunctionSpace& V,
322  const std::vector<std::shared_ptr<const DirichletBC<T>>>& bcs,
323  T diagonal = 1.0)
324 {
325  for (const auto& bc : bcs)
326  {
327  assert(bc);
328  if (V.contains(*bc->function_space()))
329  {
330  const auto [dofs, range] = bc->dof_indices();
331  set_diagonal<T>(set_fn, dofs.first(range), diagonal);
332  }
333  }
334 }
335 
336 // -- Setting bcs ------------------------------------------------------------
337 
338 // FIXME: Move these function elsewhere?
339 
340 // FIXME: clarify x0
341 // FIXME: clarify what happens with ghosts
342 
346 template <typename T>
347 void set_bc(xtl::span<T> b,
348  const std::vector<std::shared_ptr<const DirichletBC<T>>>& bcs,
349  const xtl::span<const T>& x0, double scale = 1.0)
350 {
351  if (b.size() > x0.size())
352  throw std::runtime_error("Size mismatch between b and x0 vectors.");
353  for (const auto& bc : bcs)
354  {
355  assert(bc);
356  bc->set(b, x0, scale);
357  }
358 }
359 
363 template <typename T>
364 void set_bc(xtl::span<T> b,
365  const std::vector<std::shared_ptr<const DirichletBC<T>>>& bcs,
366  double scale = 1.0)
367 {
368  for (const auto& bc : bcs)
369  {
370  assert(bc);
371  bc->set(b, scale);
372  }
373 }
374 
375 // FIXME: Handle null block
376 // FIXME: Pass function spaces rather than forms
377 
385 template <typename T>
386 std::vector<std::vector<std::shared_ptr<const fem::DirichletBC<T>>>>
387 bcs_rows(const std::vector<const Form<T>*>& L,
388  const std::vector<std::shared_ptr<const fem::DirichletBC<T>>>& bcs)
389 {
390  // Pack DirichletBC pointers for rows
391  std::vector<std::vector<std::shared_ptr<const fem::DirichletBC<T>>>> bcs0(
392  L.size());
393  for (std::size_t i = 0; i < L.size(); ++i)
394  for (const std::shared_ptr<const DirichletBC<T>>& bc : bcs)
395  if (L[i]->function_spaces()[0]->contains(*bc->function_space()))
396  bcs0[i].push_back(bc);
397  return bcs0;
398 }
399 
400 // FIXME: Handle null block
401 // FIXME: Pass function spaces rather than forms
402 
410 template <typename T>
411 std::vector<
412  std::vector<std::vector<std::shared_ptr<const fem::DirichletBC<T>>>>>
413 bcs_cols(const std::vector<std::vector<std::shared_ptr<const Form<T>>>>& a,
414  const std::vector<std::shared_ptr<const DirichletBC<T>>>& bcs)
415 {
416  // Pack DirichletBC pointers for columns
417  std::vector<
418  std::vector<std::vector<std::shared_ptr<const fem::DirichletBC<T>>>>>
419  bcs1(a.size());
420  for (std::size_t i = 0; i < a.size(); ++i)
421  {
422  for (std::size_t j = 0; j < a[i].size(); ++j)
423  {
424  bcs1[i].resize(a[j].size());
425  for (const std::shared_ptr<const DirichletBC<T>>& bc : bcs)
426  {
427  // FIXME: handle case where a[i][j] is null
428  if (a[i][j])
429  {
430  if (a[i][j]->function_spaces()[1]->contains(*bc->function_space()))
431  bcs1[i][j].push_back(bc);
432  }
433  }
434  }
435  }
436 
437  return bcs1;
438 }
439 
440 } // namespace dolfinx::fem
This class provides a dynamic 2-dimensional row-wise array data structure.
Definition: array2d.h:21
Interface for setting (strong) Dirichlet boundary conditions.
Definition: DirichletBC.h:128
Class for variational forms.
Definition: Form.h:60
const std::vector< std::shared_ptr< const fem::FunctionSpace > > & function_spaces() const
Return function spaces for all arguments.
Definition: Form.h:149
This class represents a finite element function space defined by a mesh, a finite element,...
Definition: FunctionSpace.h:31
bool contains(const FunctionSpace &V) const
Check whether V is subspace of this, or this itself.
Definition: FunctionSpace.cpp:230
Finite element method functionality.
Definition: assemble_matrix_impl.h:23
void set_diagonal(const std::function< int(std::int32_t, const std::int32_t *, std::int32_t, const std::int32_t *, const T *)> &set_fn, const xtl::span< const std::int32_t > &rows, T diagonal=1.0)
Sets a value to the diagonal of a matrix for specified rows. It is typically called after assembly....
Definition: assembler.h:290
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
std::vector< std::vector< std::shared_ptr< const fem::DirichletBC< T > > > > bcs_rows(const std::vector< const Form< T > * > &L, const std::vector< std::shared_ptr< const fem::DirichletBC< T >>> &bcs)
Arrange boundary conditions by block.
Definition: assembler.h:387
std::vector< std::vector< std::vector< std::shared_ptr< const fem::DirichletBC< T > > > > > bcs_cols(const std::vector< std::vector< std::shared_ptr< const Form< T >>>> &a, const std::vector< std::shared_ptr< const DirichletBC< T >>> &bcs)
Arrange boundary conditions by block.
Definition: assembler.h:413
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
void assemble_vector(xtl::span< T > b, const Form< T > &L, const xtl::span< const T > &constants, const array2d< T > &coeffs)
Assemble linear form into a vector, The caller supplies the form constants and coefficients for this ...
Definition: assembler.h:66
T assemble_scalar(const Form< T > &M, const xtl::span< const T > &constants, const array2d< T > &coeffs)
Assemble functional into scalar. The caller supplies the form constants and coefficients for this ver...
Definition: assembler.h:36
void set_bc(xtl::span< T > b, const std::vector< std::shared_ptr< const DirichletBC< T >>> &bcs, const xtl::span< const T > &x0, double scale=1.0)
Set bc values in owned (local) part of the vector, multiplied by 'scale'. The vectors b and x0 must h...
Definition: assembler.h:347
void apply_lifting(xtl::span< T > b, const std::vector< std::shared_ptr< const Form< T >>> &a, const std::vector< xtl::span< const T >> &constants, const std::vector< const array2d< T > * > &coeffs, const std::vector< std::vector< std::shared_ptr< const DirichletBC< T >>>> &bcs1, const std::vector< xtl::span< const T >> &x0, double scale)
Modify b such that:
Definition: assembler.h:104
void assemble_matrix(const std::function< int(std::int32_t, const std::int32_t *, std::int32_t, const std::int32_t *, const T *)> &mat_add, const Form< T > &a, const xtl::span< const T > &constants, const array2d< T > &coeffs, const std::vector< std::shared_ptr< const DirichletBC< T >>> &bcs)
Assemble bilinear form into a matrix.
Definition: assembler.h:166