13#include "FunctionSpace.h"
17#include <dolfinx/common/types.h>
55std::vector<std::int32_t>
57 int dim, std::span<const std::int32_t> entities,
87 const mesh::Topology& topology,
88 std::array<std::reference_wrapper<const DofMap>, 2> dofmaps,
int dim,
89 std::span<const std::int32_t> entities,
bool remote =
true);
102template <std::
floating_po
int T,
typename U>
110 for (std::size_t i = 0; i < V.
mesh()->topology()->cell_types().size(); ++i)
115 throw std::runtime_error(
116 "Cannot locate dofs geometrically for mixed space. Use subspaces.");
124 = md::mdspan<const T, md::extents<std::size_t, 3, md::dynamic_extent>>;
127 cmdspan3x_t x(dof_coordinates.data(), 3, dof_coordinates.size() / 3);
128 const std::vector<std::int8_t> marked_dofs = marker_fn(x);
130 std::vector<std::int32_t> dofs;
131 dofs.reserve(std::count(marked_dofs.begin(), marked_dofs.end(),
true));
132 for (std::size_t i = 0; i < marked_dofs.size(); ++i)
154template <std::
floating_po
int T,
typename U>
172 throw std::runtime_error(
"Meshes are not the same.");
173 const int tdim =
mesh->topology()->dim();
178 throw std::runtime_error(
"Function spaces must have the same element.");
184 = md::mdspan<const T, md::extents<std::size_t, 3, md::dynamic_extent>>;
187 cmdspan3x_t x(dof_coordinates.data(), 3, dof_coordinates.size() / 3);
188 const std::vector<std::int8_t> marked_dofs = marker_fn(x);
191 std::shared_ptr<const DofMap> dofmap0 = V0.
dofmap();
193 const int bs0 = dofmap0->bs();
194 std::shared_ptr<const DofMap> dofmap1 = V1.
dofmap();
196 const int bs1 = dofmap1->bs();
198 const int element_bs = dofmap0->element_dof_layout().block_size();
199 assert(element_bs == dofmap1->element_dof_layout().block_size());
202 auto topology =
mesh->topology();
204 std::vector<std::array<std::int32_t, 2>> bc_dofs;
205 for (
int c = 0; c < topology->connectivity(tdim, 0)->num_nodes(); ++c)
208 auto cell_dofs0 = dofmap0->cell_dofs(c);
209 auto cell_dofs1 = dofmap1->cell_dofs(c);
212 for (std::size_t i = 0; i < cell_dofs1.size(); ++i)
214 if (marked_dofs[cell_dofs1[i]])
217 for (
int k = 0; k < element_bs; ++k)
219 const int local_pos = element_bs * i + k;
220 const std::div_t pos0 = std::div(local_pos, bs0);
221 const std::div_t pos1 = std::div(local_pos, bs1);
222 const std::int32_t dof_index0
223 = bs0 * cell_dofs0[pos0.quot] + pos0.rem;
224 const std::int32_t dof_index1
225 = bs1 * cell_dofs1[pos1.quot] + pos1.rem;
226 bc_dofs.push_back({dof_index0, dof_index1});
233 std::ranges::sort(bc_dofs);
234 auto [unique_end, range_end] = std::ranges::unique(bc_dofs);
235 bc_dofs.erase(unique_end, range_end);
238 std::array dofs = {std::vector<std::int32_t>(bc_dofs.size()),
239 std::vector<std::int32_t>(bc_dofs.size())};
240 std::ranges::transform(bc_dofs, dofs[0].begin(),
241 [](
auto dof) {
return dof[0]; });
242 std::ranges::transform(bc_dofs, dofs[1].begin(),
243 [](
auto dof) {
return dof[1]; });
256template <dolfinx::scalar T, std::
floating_po
int U = dolfinx::scalar_value_t<T>>
262 std::size_t num_owned(
const DofMap& dofmap,
263 std::span<const std::int32_t> dofs)
266 std::int32_t map_size = dofmap.
index_map->size_local();
267 std::int32_t owned_size = bs * map_size;
268 auto it = std::ranges::lower_bound(dofs, owned_size);
269 return std::distance(dofs.begin(), it);
273 static std::vector<std::int32_t>
274 unroll_dofs(std::span<const std::int32_t> dofs,
int bs)
276 std::vector<std::int32_t> dofs_unrolled(bs * dofs.size());
277 for (std::size_t i = 0; i < dofs.size(); ++i)
278 for (
int k = 0; k < bs; ++k)
279 dofs_unrolled[bs * i + k] = bs * dofs[i] + k;
280 return dofs_unrolled;
301 template <
typename S,
typename X>
302 requires(std::is_convertible_v<S, T>
303 || std::is_convertible_v<S, std::span<const T>>)
304 && std::is_convertible_v<std::remove_cvref_t<X>,
305 std::vector<std::int32_t>>
326 template <
typename X>
327 requires std::is_convertible_v<std::remove_cvref_t<X>,
328 std::vector<std::int32_t>>
331 : _function_space(V), _g(g), _dofs0(std::forward<X>(dofs))
335 assert(V->elements(0));
336 if (g->shape.size() != V->elements(0)->value_shape().size())
338 throw std::runtime_error(
339 "Rank mismatch between Constant and function space in DirichletBC");
342 if (g->value.size() != (std::size_t)_function_space->dofmaps(0)->bs())
344 throw std::runtime_error(
345 "Creating a DirichletBC using a Constant is not supported when the "
346 "Constant size is not equal to the block size of the constrained "
347 "(sub-)space. Use a fem::Function to create the fem::DirichletBC.");
350 if (!V->elements(0)->interpolation_ident())
352 throw std::runtime_error(
353 "Constant can be used only with point-evaluation elements");
357 if (
const int bs = V->dofmaps(0)->bs(); bs > 1)
358 _dofs0 = unroll_dofs(_dofs0, bs);
360 _owned_indices0 = num_owned(*_function_space->dofmaps(0), _dofs0);
375 template <
typename X>
376 requires std::is_convertible_v<std::remove_cvref_t<X>,
377 std::vector<std::int32_t>>
380 _dofs0(std::forward<X>(dofs))
382 assert(_function_space);
385 if (
const int bs = _function_space->dofmaps(0)->bs(); bs > 1)
386 _dofs0 = unroll_dofs(_dofs0, bs);
388 _owned_indices0 = num_owned(*_function_space->dofmaps(0), _dofs0);
412 template <
typename X>
415 : _function_space(V), _g(g),
416 _dofs0(std::forward<typename std::remove_reference_t<X>::value_type>(
418 _dofs1_g(std::forward<typename std::remove_reference_t<X>::value_type>(
420 _owned_indices0(num_owned(*_function_space->dofmap(), _dofs0))
446 return _function_space;
451 std::variant<std::shared_ptr<const Function<T, U>>,
452 std::shared_ptr<const Constant<T>>>
464 std::pair<std::span<const std::int32_t>, std::int32_t>
dof_indices()
const
466 return {_dofs0, _owned_indices0};
491 void set(std::span<T> x, std::optional<std::span<const T>> x0,
496 auto apply = [&](std::invocable<std::int32_t>
auto set_fn)
499 std::is_same_v<std::invoke_result_t<
decltype(set_fn), std::int32_t>,
502 std::int32_t x_size = x.size();
503 for (std::size_t i = 0; i < _dofs0.size(); ++i)
505 if (_dofs0[i] < x_size)
506 x[_dofs0[i]] = set_fn(i);
512 apply([](std::int32_t) -> T {
return 0; });
516 if (std::holds_alternative<std::shared_ptr<
const Function<T, U>>>(_g))
518 auto g = std::get<std::shared_ptr<const Function<T, U>>>(_g);
520 std::span<const T> values = g->x()->array();
525 auto dofs_g = _dofs1_g.empty() ? std::span(_dofs0) : std::span(_dofs1_g);
529 assert(x.size() <= x0->size());
531 [dofs_g, x0 = *x0, alpha, values,
532 &dofs0 = this->_dofs0](std::int32_t i) -> T
534 assert(dofs_g[i] <
static_cast<std::int32_t
>(values.size()));
535 return alpha * (values[dofs_g[i]] - x0[dofs0[i]]);
541 [dofs_g, values, alpha](std::int32_t i) -> T
543 assert(dofs_g[i] <
static_cast<std::int32_t
>(values.size()));
544 return alpha * values[dofs_g[i]];
548 else if (std::holds_alternative<std::shared_ptr<
const Constant<T>>>(_g))
550 auto g = std::get<std::shared_ptr<const Constant<T>>>(_g);
551 const std::vector<T>&
value = g->value;
552 std::int32_t bs = _function_space->dofmaps(0)->bs();
555 assert(x.size() <= x0->size());
557 [x0 = *x0, alpha, bs, &
value, &dofs0 = _dofs0](std::int32_t i) -> T
560 return alpha * (
value[dof % bs] - x0[dof]);
565 apply([alpha, bs, &
value, &dofs0 = _dofs0](std::int32_t i) -> T
566 {
return alpha *
value[dofs0[i] % bs]; });
587 for (std::int32_t idx : _dofs0)
589 assert(idx < (std::int32_t)markers.size());
596 std::shared_ptr<const FunctionSpace<U>> _function_space;
599 std::variant<std::shared_ptr<const Function<T, U>>,
600 std::shared_ptr<const Constant<T>>>
605 std::vector<std::int32_t> _dofs0, _dofs1_g;
608 std::int32_t _owned_indices0 = -1;
Degree-of-freedom map representations and tools.
Constant (in space) value which can be attached to a Form.
Definition Constant.h:22
DirichletBC(const S &g, X &&dofs, std::shared_ptr< const FunctionSpace< U > > V)
Create a representation of a Dirichlet boundary condition constrained by a scalar- or vector-valued c...
Definition DirichletBC.h:306
DirichletBC(std::shared_ptr< const Function< T, U > > g, X &&dofs)
Create a representation of a Dirichlet boundary condition where the space being constrained is the sa...
Definition DirichletBC.h:378
DirichletBC & operator=(const DirichletBC &bc)=default
void set(std::span< T > x, std::optional< std::span< const T > > x0, T alpha=1) const
Set entries in an array that are constrained by Dirichlet boundary conditions.
Definition DirichletBC.h:491
std::variant< std::shared_ptr< const Function< T, U > >, std::shared_ptr< const Constant< T > > > value() const
Definition DirichletBC.h:453
DirichletBC(const DirichletBC &bc)=default
DirichletBC(DirichletBC &&bc)=default
std::pair< std::span< const std::int32_t >, std::int32_t > dof_indices() const
Definition DirichletBC.h:464
std::shared_ptr< const FunctionSpace< U > > function_space() const
Definition DirichletBC.h:444
~DirichletBC()=default
Destructor.
DirichletBC & operator=(DirichletBC &&bc)=default
Move assignment operator.
void mark_dofs(std::span< std::int8_t > markers) const
Set markers[i] = true if dof i has a boundary condition applied.
Definition DirichletBC.h:585
DirichletBC(std::shared_ptr< const Function< T, U > > g, X &&V_g_dofs, std::shared_ptr< const FunctionSpace< U > > V)
Create a representation of a Dirichlet boundary condition where the space being constrained and the f...
Definition DirichletBC.h:413
DirichletBC(std::shared_ptr< const Constant< T > > g, X &&dofs, std::shared_ptr< const FunctionSpace< U > > V)
Create a representation of a Dirichlet boundary condition constrained by a fem::Constant.
Definition DirichletBC.h:329
Degree-of-freedom map.
Definition DofMap.h:73
std::shared_ptr< const common::IndexMap > index_map
Index map that describes the parallel distribution of the dofmap.
Definition DofMap.h:164
int index_map_bs() const
Block size associated with the index_map.
Definition DofMap.cpp:279
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:34
std::shared_ptr< const FiniteElement< geometry_type > > elements(int cell_type_idx) const
The finite elements.
Definition FunctionSpace.h:380
std::shared_ptr< const DofMap > dofmap() const
The dofmap.
Definition FunctionSpace.h:386
std::shared_ptr< const mesh::Mesh< geometry_type > > mesh() const
The mesh.
Definition FunctionSpace.h:361
std::shared_ptr< const FiniteElement< geometry_type > > element() const
The finite element.
Definition FunctionSpace.h:367
std::vector< geometry_type > tabulate_dof_coordinates(bool transpose) const
Tabulate the physical coordinates of all dofs on this process.
Definition FunctionSpace.h:229
Finite element method functionality.
Definition assemble_expression_impl.h:23
std::vector< std::int32_t > locate_dofs_geometrical(const FunctionSpace< T > &V, U marker_fn)
Find degrees of freedom whose geometric coordinate is true for the provided marking function.
Definition DirichletBC.h:103
std::vector< std::int32_t > locate_dofs_topological(const mesh::Topology &topology, const DofMap &dofmap, int dim, std::span< const std::int32_t > entities, bool remote=true)
Find degrees-of-freedom which belong to the provided mesh entities (topological).
Definition DirichletBC.cpp:199
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32