Coverage for python / src / dolfinx_mpc / assemble_vector.py: 100%
57 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-23 11:05 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-23 11:05 +0000
1# Copyright (C) 2020 Jørgen S. Dokken
2#
3# This file is part of DOLFINX_MPC
4#
5# SPDX-License-Identifier: MIT
6from __future__ import annotations
8import contextlib
9from typing import Iterable, Optional, Sequence, Union
11from petsc4py import PETSc as _PETSc
13import dolfinx.cpp as _cpp
14import dolfinx.fem as _fem
15import numpy
16from dolfinx import default_scalar_type
17from dolfinx.common import Timer
18from dolfinx.la.petsc import create_vector
20import dolfinx_mpc.cpp
22from .multipointconstraint import MultiPointConstraint, _float_classes
25def apply_lifting(
26 b: _PETSc.Vec,
27 form: Union[Iterable[Sequence[_fem.Form]], Iterable[_fem.Form]], # type: ignore
28 bcs: Union[Sequence[_fem.DirichletBC], Sequence[Sequence[_fem.DirichletBC]]],
29 constraint: Union[MultiPointConstraint, Sequence[MultiPointConstraint]],
30 x0: Optional[Sequence[_PETSc.Vec]] = None,
31 scale: _float_classes = default_scalar_type(1.0), # type: ignore
32): # type: ignore
33 """
34 Apply lifting to vector b, i.e.
35 :math:`b = b - scale \\cdot K^T (A_j (g_j - x0_j))`
37 Args:
38 b: PETSc vector to assemble into
39 form: The linear form
40 bcs: List of Dirichlet boundary conditions
41 constraint: The multi point constraint
42 x0: List of vectors
43 scale: Scaling for lifting
44 """
45 t = Timer("~MPC: Apply lifting (C++)")
46 if isinstance(scale, numpy.generic): # nanobind conversion of numpy dtypes to general Python types
47 scale = scale.item() # type: ignore
49 if b.getType() == "nest":
50 try:
51 bcs = _fem.bcs_by_block(_fem.extract_function_spaces(form, 1), bcs) # type: ignore
52 except AttributeError:
53 pass
54 x0 = [] if x0 is None else x0.getNestSubVecs() # type: ignore
55 assert isinstance(form, Sequence) and isinstance(constraint, Sequence)
56 for b_sub, a_sub, mpc_i in zip(b.getNestSubVecs(), form, constraint):
57 _a = [None if form is None else form._cpp_object for form in a_sub] # type:ignore
58 _bcs = [[bc._cpp_object for bc in bcs0] for bcs0 in bcs] # type: ignore
59 dolfinx_mpc.cpp.mpc.apply_lifting(b_sub.array_w, _a, _bcs, x0, scale, mpc_i._cpp_object)
60 else:
61 with contextlib.ExitStack() as stack:
62 if x0 is None:
63 x0 = []
64 else:
65 x0 = [stack.enter_context(x.localForm()) for x in x0]
66 x0_r = [x.array_r for x in x0]
67 b_local = stack.enter_context(b.localForm())
68 _forms = [f._cpp_object for f in form] # type: ignore
69 _bcs = [[bc._cpp_object for bc in bcs0] for bcs0 in bcs] # type: ignore
70 assert isinstance(constraint, MultiPointConstraint)
71 dolfinx_mpc.cpp.mpc.apply_lifting(b_local.array_w, _forms, _bcs, x0_r, scale, constraint._cpp_object)
72 t.stop()
75def assemble_vector(
76 form: _fem.Form,
77 constraint: MultiPointConstraint,
78 b: Optional[_PETSc.Vec] = None, # type: ignore
79) -> _PETSc.Vec: # type: ignore
80 """
81 Assemble a linear form into vector `b` with corresponding multi point constraint
83 Args:
84 form: The linear form
85 constraint: The multi point constraint
86 b: PETSc vector to assemble
88 Returns:
89 The vector with the assembled linear form (`b` if supplied)
90 """
92 if b is None:
93 b = create_vector([(constraint.function_space.dofmap.index_map, constraint.function_space.dofmap.index_map_bs)])
94 t = Timer("~MPC: Assemble vector (C++)")
95 with b.localForm() as b_local:
96 b_local.set(0.0)
97 dolfinx_mpc.cpp.mpc.assemble_vector(b_local.array_w, form._cpp_object, constraint._cpp_object)
98 t.stop()
99 return b
102def create_vector_nest(L: Sequence[_fem.Form], constraints: Sequence[MultiPointConstraint]) -> _PETSc.Vec: # type: ignore
103 """
104 Create a PETSc vector of type "nest" appropriate for the provided multi
105 point constraints
107 Args:
108 L: A sequence of linear forms
109 constraints: An ordered list of multi point constraints
111 Returns:
112 PETSc.Vec: A PETSc vector of type "nest" #type: ignore
113 """
114 assert len(constraints) == len(L)
116 maps = [
117 (constraint.function_space.dofmap.index_map, constraint.function_space.dofmap.index_map_bs)
118 for constraint in constraints
119 ]
120 return _cpp.fem.petsc.create_vector_nest(maps)
123def assemble_vector_nest(
124 b: _PETSc.Vec, # type: ignore
125 L: Sequence[_fem.Form],
126 constraints: Sequence[MultiPointConstraint],
127):
128 """
129 Assemble a linear form into a PETSc vector of type "nest"
131 Args:
132 b: A PETSc vector of type "nest"
133 L: A sequence of linear forms
134 constraints: An ordered list of multi point constraints
135 """
136 assert len(constraints) == len(L)
137 assert b.getType() == "nest"
139 b_sub_vecs = b.getNestSubVecs()
140 for i, L_row in enumerate(L):
141 assemble_vector(L_row, constraints[i], b=b_sub_vecs[i])