Coverage for python/src/dolfinx_mpc/rbe.py: 89%
18 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-07 09:58 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-07 09:58 +0000
1# Copyright (C) 2026 Jørgen S. Dokken
2#
3# This file is part of DOLFINX_MPC
4#
5# SPDX-License-Identifier: MIT
6"""Constraints tying dofs to spiders (RBE2, RBE3): points of a spider mesh, see :mod:`dolfinx_mpc.spider`."""
8from __future__ import annotations
10import dolfinx.fem as _fem
11import numpy as np
12import numpy.typing as npt
14from .container import _cpp_function, _mpc_data_classes, _scalar_type
16__all__ = ["create_rbe2", "create_rbe3"]
19def create_rbe2(
20 V: _fem.FunctionSpace,
21 dofs: npt.NDArray[np.int32],
22 spiders: npt.NDArray[np.int64],
23 W: _fem.FunctionSpace,
24 dtype: npt.DTypeLike | None = None,
25 x: npt.NDArray[np.floating] | None = None,
26) -> _mpc_data_classes:
27 r"""The constraint tying every component of the blocked `dofs` to the rigid-body motion of a spider.
29 Foot `i`, at `x`, follows spider `spiders[i]` at :math:`x_c`:
30 :math:`u_j = t_j + (\theta \times (x - x_c))_j`. The translation :math:`t` is the first
31 `gdim` components of the spider's block of dofs in `W`, the rotation :math:`\theta` the rest
32 (components 3, 4, 5 in 3D, component 2 in 2D), and :math:`x_c` the coordinate of that block.
33 Every rotation term is kept, also where its coefficient is zero, so that the masters do not
34 depend on the configuration. Wraps `dolfinx_mpc::create_rbe2`.
36 Args:
37 V: The space of the feet, with one component per dimension
38 dofs: The feet, blocked dofs of `V` local to the process, ghosts included
39 spiders: The spider of each foot, its input index (see :func:`create_spider_mesh`)
40 W: The space on the spider mesh
41 dtype: The scalar type of the coefficients. Defaults to the default scalar type of
42 DOLFINx, real or complex, at the precision of the meshes.
43 x: The coordinates of all dofs of `V` local to the process, from
44 `V.tabulate_dof_coordinates()`, if already at hand
46 Returns:
47 The slaves, masters (global dofs of `W`), coefficients, owners and offsets.
49 Note:
50 Collective.
51 """
52 real_type = V.mesh.geometry.x.dtype
53 if W.mesh.geometry.x.dtype != real_type:
54 raise ValueError("The mesh of the feet and the spider mesh must have the same coordinate type")
55 create = _cpp_function("create_rbe2", _scalar_type(real_type, dtype))
56 return create(
57 V._cpp_object,
58 np.ascontiguousarray(dofs, dtype=np.int32),
59 np.ascontiguousarray(spiders, dtype=np.int64),
60 W._cpp_object,
61 None if x is None else np.ascontiguousarray(x, dtype=real_type),
62 )
65def create_rbe3(
66 W: _fem.FunctionSpace,
67 V: list[_fem.FunctionSpace],
68 dofs: list[npt.NDArray[np.int32]],
69 spiders: list[npt.NDArray[np.int64]],
70 weights: list[npt.NDArray[np.floating]],
71 dtype: npt.DTypeLike | None = None,
72) -> tuple[_mpc_data_classes, npt.NDArray[np.int32]]:
73 r"""The constraint tying the dofs of spiders to the motion of their feet (RBE3).
75 Each spider moves with the rigid motion that best fits its feet,
76 :math:`\min_{t, \theta} \sum_i w_i |u_i - t - \theta \times (x_i - x_c)|^2`. Without rotations,
77 :math:`t` is the weighted mean of the feet. Wraps `dolfinx_mpc::create_rbe3`.
79 Args:
80 W: The space on the spider mesh, holding the slaves
81 V: The spaces of the feet, with one component per dimension
82 dofs: The feet in each space, blocked dofs local to the process
83 spiders: The spider of each foot, its input index (see :func:`create_spider_mesh`)
84 weights: The weight of each foot, non-negative
85 dtype: The scalar type of the coefficients. Defaults to the default scalar type of
86 DOLFINx, real or complex, at the precision of the meshes.
88 Returns:
89 The slaves, masters, coefficients, owners and offsets, and the position in `V` of the
90 space of each master.
92 Note:
93 Collective.
94 """
95 real_type = W.mesh.geometry.x.dtype
96 if any(V_s.mesh.geometry.x.dtype != real_type for V_s in V):
97 raise ValueError("The meshes of the feet and the spider mesh must have the same coordinate type")
98 create = _cpp_function("create_rbe3", _scalar_type(real_type, dtype))
99 return create(
100 W._cpp_object,
101 [V_s._cpp_object for V_s in V],
102 [np.ascontiguousarray(d, dtype=np.int32) for d in dofs],
103 [np.ascontiguousarray(k, dtype=np.int64) for k in spiders],
104 [np.ascontiguousarray(w, dtype=real_type) for w in weights],
105 )