|
1 |
| -# Copyright (C) 2018-2022 Garth N. Wells and Jørgen S. Dokken |
| 1 | +# Copyright (C) 2018-2025 Garth N. Wells and Jørgen S. Dokken |
2 | 2 | #
|
3 | 3 | # This file is part of DOLFINx (https://www.fenicsproject.org)
|
4 | 4 | #
|
|
16 | 16 | import contextlib
|
17 | 17 | import functools
|
18 | 18 | import typing
|
| 19 | +from collections.abc import Sequence |
19 | 20 |
|
20 | 21 | from petsc4py import PETSc
|
21 | 22 |
|
|
27 | 28 | import numpy as np
|
28 | 29 |
|
29 | 30 | import dolfinx.cpp as _cpp
|
| 31 | +import dolfinx.la.petsc |
30 | 32 | import ufl
|
31 |
| -from dolfinx import la |
32 | 33 | from dolfinx.cpp.fem import pack_coefficients as _pack_coefficients
|
33 | 34 | from dolfinx.cpp.fem import pack_constants as _pack_constants
|
34 | 35 | from dolfinx.cpp.fem.petsc import discrete_curl as _discrete_curl
|
|
42 | 43 | from dolfinx.fem.forms import form as _create_form
|
43 | 44 | from dolfinx.fem.function import Function as _Function
|
44 | 45 | from dolfinx.fem.function import FunctionSpace as _FunctionSpace
|
45 |
| -from dolfinx.la import create_petsc_vector |
46 | 46 |
|
47 | 47 | __all__ = [
|
48 | 48 | "LinearProblem",
|
|
55 | 55 | "assemble_vector",
|
56 | 56 | "assemble_vector_block",
|
57 | 57 | "assemble_vector_nest",
|
| 58 | + "assign", |
58 | 59 | "create_matrix",
|
59 | 60 | "create_matrix_block",
|
60 | 61 | "create_matrix_nest",
|
@@ -118,7 +119,7 @@ def create_vector(L: Form) -> PETSc.Vec:
|
118 | 119 | A PETSc vector with a layout that is compatible with ``L``.
|
119 | 120 | """
|
120 | 121 | dofmap = L.function_spaces[0].dofmaps(0)
|
121 |
| - return create_petsc_vector(dofmap.index_map, dofmap.index_map_bs) |
| 122 | + return dolfinx.la.petsc.create_vector(dofmap.index_map, dofmap.index_map_bs) |
122 | 123 |
|
123 | 124 |
|
124 | 125 | def create_vector_block(L: list[Form]) -> PETSc.Vec:
|
@@ -261,7 +262,7 @@ def assemble_vector(L: typing.Any, constants=None, coeffs=None) -> PETSc.Vec:
|
261 | 262 | Returns:
|
262 | 263 | An assembled vector.
|
263 | 264 | """
|
264 |
| - b = create_petsc_vector( |
| 265 | + b = dolfinx.la.petsc.create_vector( |
265 | 266 | L.function_spaces[0].dofmaps(0).index_map, L.function_spaces[0].dofmaps(0).index_map_bs
|
266 | 267 | )
|
267 | 268 | with b.localForm() as b_local:
|
@@ -881,7 +882,7 @@ def __init__(
|
881 | 882 | else:
|
882 | 883 | self.u = u
|
883 | 884 |
|
884 |
| - self._x = la.create_petsc_vector_wrap(self.u.x) |
| 885 | + self._x = dolfinx.la.petsc.create_vector_wrap(self.u.x) |
885 | 886 | self.bcs = bcs
|
886 | 887 |
|
887 | 888 | self._solver = PETSc.KSP().create(self.u.function_space.mesh.comm)
|
@@ -939,12 +940,12 @@ def solve(self) -> _Function:
|
939 | 940 |
|
940 | 941 | @property
|
941 | 942 | def L(self) -> Form:
|
942 |
| - """The compiled linear form""" |
| 943 | + """The compiled linear form.""" |
943 | 944 | return self._L
|
944 | 945 |
|
945 | 946 | @property
|
946 | 947 | def a(self) -> Form:
|
947 |
| - """The compiled bilinear form""" |
| 948 | + """The compiled bilinear form.""" |
948 | 949 | return self._a
|
949 | 950 |
|
950 | 951 | @property
|
@@ -1015,12 +1016,12 @@ def __init__(
|
1015 | 1016 |
|
1016 | 1017 | @property
|
1017 | 1018 | def L(self) -> Form:
|
1018 |
| - """Compiled linear form (the residual form)""" |
| 1019 | + """The compiled linear form (the residual form).""" |
1019 | 1020 | return self._L
|
1020 | 1021 |
|
1021 | 1022 | @property
|
1022 | 1023 | def a(self) -> Form:
|
1023 |
| - """Compiled bilinear form (the Jacobian form)""" |
| 1024 | + """The compiled bilinear form (the Jacobian form).""" |
1024 | 1025 | return self._a
|
1025 | 1026 |
|
1026 | 1027 | def form(self, x: PETSc.Vec) -> None:
|
@@ -1118,3 +1119,61 @@ def interpolation_matrix(space0: _FunctionSpace, space1: _FunctionSpace) -> PETS
|
1118 | 1119 | Interpolation matrix.
|
1119 | 1120 | """
|
1120 | 1121 | return _interpolation_matrix(space0._cpp_object, space1._cpp_object)
|
| 1122 | + |
| 1123 | + |
| 1124 | +@functools.singledispatch |
| 1125 | +def assign(u: typing.Union[_Function, Sequence[_Function]], x: PETSc.Vec): |
| 1126 | + """Assign :class:`Function` degrees-of-freedom to a vector. |
| 1127 | +
|
| 1128 | + Assigns degree-of-freedom values in values of ``u``, which is possibly a |
| 1129 | + Sequence of ``Functions``s, to ``x``. When ``u`` is a Sequence of |
| 1130 | + ``Function``s, degrees-of-freedom for the ``Function``s in ``u`` are |
| 1131 | + 'stacked' and assigned to ``x``. See :func:`assign` for documentation on |
| 1132 | + how stacked assignment is handled. |
| 1133 | +
|
| 1134 | + Args: |
| 1135 | + u: ``Function`` (s) to assign degree-of-freedom value from. |
| 1136 | + x: Vector to assign degree-of-freedom values in ``u`` to. |
| 1137 | + """ |
| 1138 | + if x.getType() == PETSc.Vec.Type().NEST: |
| 1139 | + dolfinx.la.petsc.assign([v.x.array for v in u], x) |
| 1140 | + else: |
| 1141 | + if isinstance(u, Sequence): |
| 1142 | + data0, data1 = [], [] |
| 1143 | + for v in u: |
| 1144 | + bs = v.function_space.dofmap.bs |
| 1145 | + n = v.function_space.dofmap.index_map.size_local |
| 1146 | + data0.append(v.x.array[: bs * n]) |
| 1147 | + data1.append(v.x.array[bs * n :]) |
| 1148 | + dolfinx.la.petsc.assign(data0 + data1, x) |
| 1149 | + else: |
| 1150 | + dolfinx.la.petsc.assign(u.x.array, x) |
| 1151 | + |
| 1152 | + |
| 1153 | +@assign.register(PETSc.Vec) |
| 1154 | +def _(x: PETSc.Vec, u: typing.Union[_Function, Sequence[_Function]]): |
| 1155 | + """Assign vector entries to :class:`Function` degrees-of-freedom. |
| 1156 | +
|
| 1157 | + Assigns values in ``x`` to the degrees-of-freedom of ``u``, which is |
| 1158 | + possibly a Sequence of ``Function``s. When ``u`` is a Sequence of |
| 1159 | + ``Function``s, values in ``x`` are assigned block-wise to the |
| 1160 | + ``Function``s. See :func:`assign` for documentation on how blocked |
| 1161 | + assignment is handled. |
| 1162 | +
|
| 1163 | + Args: |
| 1164 | + x: Vector with values to assign values from. |
| 1165 | + u: ``Function`` (s) to assign degree-of-freedom values to. |
| 1166 | + """ |
| 1167 | + if x.getType() == PETSc.Vec.Type().NEST: |
| 1168 | + dolfinx.la.petsc.assign(x, [v.x.array for v in u]) |
| 1169 | + else: |
| 1170 | + if isinstance(u, Sequence): |
| 1171 | + data0, data1 = [], [] |
| 1172 | + for v in u: |
| 1173 | + bs = v.function_space.dofmap.bs |
| 1174 | + n = v.function_space.dofmap.index_map.size_local |
| 1175 | + data0.append(v.x.array[: bs * n]) |
| 1176 | + data1.append(v.x.array[bs * n :]) |
| 1177 | + dolfinx.la.petsc.assign(x, data0 + data1) |
| 1178 | + else: |
| 1179 | + dolfinx.la.petsc.assign(x, u.x.array) |
0 commit comments