dolfinx-adjoint 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dolfinx_adjoint-0.2.0/src/dolfinx_adjoint.egg-info → dolfinx_adjoint-0.3.0}/PKG-INFO +32 -16
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/README.md +27 -12
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/pyproject.toml +4 -14
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/__init__.py +2 -1
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/blocks/_vector.py +12 -1
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/blocks/assembly.py +4 -0
- dolfinx_adjoint-0.3.0/src/dolfinx_adjoint/blocks/dirichletbc.py +42 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/blocks/function_assigner.py +7 -5
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/blocks/solvers.py +223 -78
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/petsc_utils.py +2 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/solvers.py +153 -81
- dolfinx_adjoint-0.3.0/src/dolfinx_adjoint/types/__init__.py +4 -0
- dolfinx_adjoint-0.3.0/src/dolfinx_adjoint/types/dirichletbc.py +97 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/types/function.py +11 -11
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/utils.py +1 -4
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0/src/dolfinx_adjoint.egg-info}/PKG-INFO +32 -16
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint.egg-info/SOURCES.txt +5 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint.egg-info/requires.txt +4 -3
- dolfinx_adjoint-0.3.0/tests/test_constant.py +27 -0
- dolfinx_adjoint-0.3.0/tests/test_dirichlet_bc.py +138 -0
- dolfinx_adjoint-0.3.0/tests/test_hessian.py +188 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/tests/test_poisson_mother.py +2 -2
- dolfinx_adjoint-0.2.0/src/dolfinx_adjoint/types/__init__.py +0 -3
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/LICENSE +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/setup.cfg +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/assembly.py +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/blocks/__init__.py +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint.egg-info/dependency_links.txt +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint.egg-info/top_level.txt +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/tests/test_assemble_scalar.py +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/tests/test_assign.py +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/tests/test_linear_solver.py +0 -0
- {dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dolfinx-adjoint
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Automatic differentation compatible with DOLFINx
|
|
5
5
|
Author-email: "Jørgen S. Dokken" <dokken@simula.no>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -9,6 +9,7 @@ License-File: LICENSE
|
|
|
9
9
|
Requires-Dist: fenics-dolfinx>=0.10.0
|
|
10
10
|
Requires-Dist: pyadjoint-ad>=2025.10.0
|
|
11
11
|
Requires-Dist: typing_extensions; python_version < "3.11"
|
|
12
|
+
Requires-Dist: packaging>=24.2
|
|
12
13
|
Provides-Extra: test
|
|
13
14
|
Requires-Dist: pytest; extra == "test"
|
|
14
15
|
Provides-Extra: dev
|
|
@@ -24,9 +25,9 @@ Requires-Dist: pyvista[all]>0.45; extra == "docs"
|
|
|
24
25
|
Requires-Dist: networkx; extra == "docs"
|
|
25
26
|
Requires-Dist: pygraphviz; extra == "docs"
|
|
26
27
|
Provides-Extra: all
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: dolfinx-adjoint[test]; extra == "all"
|
|
29
|
+
Requires-Dist: dolfinx-adjoint[dev]; extra == "all"
|
|
30
|
+
Requires-Dist: dolfinx-adjoint[docs]; extra == "all"
|
|
30
31
|
Dynamic: license-file
|
|
31
32
|
|
|
32
33
|
# DOLFINx-Adjoint
|
|
@@ -49,7 +50,7 @@ Read the [Latest Documentation here](https://scientificcomputing.github.io/dolfi
|
|
|
49
50
|
|
|
50
51
|
### Dependencies
|
|
51
52
|
|
|
52
|
-
DOLFINx-Adjoint requires **DOLFINx** (>=0.
|
|
53
|
+
DOLFINx-Adjoint requires **DOLFINx** (>=0.11.0) and **pyadjoint-ad**.
|
|
53
54
|
|
|
54
55
|
### via pip
|
|
55
56
|
|
|
@@ -59,6 +60,14 @@ The main way to install the package is via pip:
|
|
|
59
60
|
python3 -m pip install dolfinx-adjoint
|
|
60
61
|
```
|
|
61
62
|
|
|
63
|
+
### via conda
|
|
64
|
+
|
|
65
|
+
You can also install dolfinx-adjoint via conda which also comes with **DOLFINx**
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
conda install -c conda-forge dolfinx-adjoint
|
|
69
|
+
```
|
|
70
|
+
|
|
62
71
|
### Development Install
|
|
63
72
|
|
|
64
73
|
To install the latest development version directly from the repository, use:
|
|
@@ -75,15 +84,6 @@ cd dolfinx-adjoint
|
|
|
75
84
|
python3 -m pip install -e ".[all]"
|
|
76
85
|
```
|
|
77
86
|
|
|
78
|
-
### Docker
|
|
79
|
-
|
|
80
|
-
A pre-built Docker image is automatically published by the CI. You can pull the nightly build which comes with DOLFINx and DOLFINx-Adjoint pre-installed:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
docker run -ti ghcr.io/scientificcomputing/dolfinx-adjoint:v0.2.0
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
*(Note: Adjust the tag to the latest release or build).*
|
|
87
87
|
|
|
88
88
|
## Quick Start
|
|
89
89
|
|
|
@@ -94,6 +94,7 @@ Using `dolfinx_adjoint` is designed to be as close to standard `dolfinx` syntax
|
|
|
94
94
|
import dolfinx
|
|
95
95
|
from mpi4py import MPI
|
|
96
96
|
import pyadjoint
|
|
97
|
+
import ufl
|
|
97
98
|
import dolfinx_adjoint
|
|
98
99
|
|
|
99
100
|
# Create mesh and function space
|
|
@@ -103,16 +104,31 @@ V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
|
|
|
103
104
|
# Use dolfinx_adjoint overloaded types
|
|
104
105
|
# This ensures operations are tracked on the pyadjoint tape!
|
|
105
106
|
f = dolfinx_adjoint.Function(V, name="Control")
|
|
107
|
+
f.interpolate(lambda x: x[0] + x[1]) # Initial guess for control
|
|
106
108
|
uh = dolfinx_adjoint.Function(V, name="State")
|
|
107
109
|
|
|
108
|
-
#
|
|
110
|
+
# Define UFL forms for a simple Poisson problem: - \Delta u = f
|
|
111
|
+
u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
|
|
112
|
+
a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
|
|
113
|
+
L = f * v * ufl.dx
|
|
114
|
+
|
|
115
|
+
# Set up Dirichlet boundary condition (u = 0 on boundary)
|
|
116
|
+
mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim)
|
|
117
|
+
exterior_facets = dolfinx.mesh.exterior_facet_indices(mesh.topology)
|
|
118
|
+
exterior_dofs = dolfinx.fem.locate_dofs_topological(V, mesh.topology.dim - 1, exterior_facets)
|
|
119
|
+
bc = dolfinx.fem.dirichletbc(dolfinx.default_scalar_type(0.0), exterior_dofs, V)
|
|
109
120
|
|
|
110
121
|
# Use overloaded solvers
|
|
111
122
|
problem = dolfinx_adjoint.LinearProblem(a, L, u=uh, bcs=[bc])
|
|
112
123
|
problem.solve()
|
|
113
124
|
|
|
125
|
+
# Define a desired temperature profile 'd' and regularization parameter 'alpha'
|
|
126
|
+
x = ufl.SpatialCoordinate(mesh)
|
|
127
|
+
d = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1])
|
|
128
|
+
alpha = dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(1e-6))
|
|
129
|
+
|
|
114
130
|
# Assemble the objective scalar using the overloaded assembly
|
|
115
|
-
J_symbolic = 0.5 * ufl.inner(uh - d, uh - d) * ufl.dx
|
|
131
|
+
J_symbolic = 0.5 * ufl.inner(uh - d, uh - d) * ufl.dx + 0.5 * alpha * ufl.inner(f, f) * ufl.dx
|
|
116
132
|
J = dolfinx_adjoint.assemble_scalar(J_symbolic)
|
|
117
133
|
|
|
118
134
|
# Create a ReducedFunctional for optimization
|
|
@@ -18,7 +18,7 @@ Read the [Latest Documentation here](https://scientificcomputing.github.io/dolfi
|
|
|
18
18
|
|
|
19
19
|
### Dependencies
|
|
20
20
|
|
|
21
|
-
DOLFINx-Adjoint requires **DOLFINx** (>=0.
|
|
21
|
+
DOLFINx-Adjoint requires **DOLFINx** (>=0.11.0) and **pyadjoint-ad**.
|
|
22
22
|
|
|
23
23
|
### via pip
|
|
24
24
|
|
|
@@ -28,6 +28,14 @@ The main way to install the package is via pip:
|
|
|
28
28
|
python3 -m pip install dolfinx-adjoint
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
### via conda
|
|
32
|
+
|
|
33
|
+
You can also install dolfinx-adjoint via conda which also comes with **DOLFINx**
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
conda install -c conda-forge dolfinx-adjoint
|
|
37
|
+
```
|
|
38
|
+
|
|
31
39
|
### Development Install
|
|
32
40
|
|
|
33
41
|
To install the latest development version directly from the repository, use:
|
|
@@ -44,15 +52,6 @@ cd dolfinx-adjoint
|
|
|
44
52
|
python3 -m pip install -e ".[all]"
|
|
45
53
|
```
|
|
46
54
|
|
|
47
|
-
### Docker
|
|
48
|
-
|
|
49
|
-
A pre-built Docker image is automatically published by the CI. You can pull the nightly build which comes with DOLFINx and DOLFINx-Adjoint pre-installed:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
docker run -ti ghcr.io/scientificcomputing/dolfinx-adjoint:v0.2.0
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
*(Note: Adjust the tag to the latest release or build).*
|
|
56
55
|
|
|
57
56
|
## Quick Start
|
|
58
57
|
|
|
@@ -63,6 +62,7 @@ Using `dolfinx_adjoint` is designed to be as close to standard `dolfinx` syntax
|
|
|
63
62
|
import dolfinx
|
|
64
63
|
from mpi4py import MPI
|
|
65
64
|
import pyadjoint
|
|
65
|
+
import ufl
|
|
66
66
|
import dolfinx_adjoint
|
|
67
67
|
|
|
68
68
|
# Create mesh and function space
|
|
@@ -72,16 +72,31 @@ V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
|
|
|
72
72
|
# Use dolfinx_adjoint overloaded types
|
|
73
73
|
# This ensures operations are tracked on the pyadjoint tape!
|
|
74
74
|
f = dolfinx_adjoint.Function(V, name="Control")
|
|
75
|
+
f.interpolate(lambda x: x[0] + x[1]) # Initial guess for control
|
|
75
76
|
uh = dolfinx_adjoint.Function(V, name="State")
|
|
76
77
|
|
|
77
|
-
#
|
|
78
|
+
# Define UFL forms for a simple Poisson problem: - \Delta u = f
|
|
79
|
+
u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
|
|
80
|
+
a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
|
|
81
|
+
L = f * v * ufl.dx
|
|
82
|
+
|
|
83
|
+
# Set up Dirichlet boundary condition (u = 0 on boundary)
|
|
84
|
+
mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim)
|
|
85
|
+
exterior_facets = dolfinx.mesh.exterior_facet_indices(mesh.topology)
|
|
86
|
+
exterior_dofs = dolfinx.fem.locate_dofs_topological(V, mesh.topology.dim - 1, exterior_facets)
|
|
87
|
+
bc = dolfinx.fem.dirichletbc(dolfinx.default_scalar_type(0.0), exterior_dofs, V)
|
|
78
88
|
|
|
79
89
|
# Use overloaded solvers
|
|
80
90
|
problem = dolfinx_adjoint.LinearProblem(a, L, u=uh, bcs=[bc])
|
|
81
91
|
problem.solve()
|
|
82
92
|
|
|
93
|
+
# Define a desired temperature profile 'd' and regularization parameter 'alpha'
|
|
94
|
+
x = ufl.SpatialCoordinate(mesh)
|
|
95
|
+
d = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1])
|
|
96
|
+
alpha = dolfinx.fem.Constant(mesh, dolfinx.default_scalar_type(1e-6))
|
|
97
|
+
|
|
83
98
|
# Assemble the objective scalar using the overloaded assembly
|
|
84
|
-
J_symbolic = 0.5 * ufl.inner(uh - d, uh - d) * ufl.dx
|
|
99
|
+
J_symbolic = 0.5 * ufl.inner(uh - d, uh - d) * ufl.dx + 0.5 * alpha * ufl.inner(f, f) * ufl.dx
|
|
85
100
|
J = dolfinx_adjoint.assemble_scalar(J_symbolic)
|
|
86
101
|
|
|
87
102
|
# Create a ReducedFunctional for optimization
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools>=61.0.0", "wheel"]
|
|
|
3
3
|
|
|
4
4
|
[project]
|
|
5
5
|
name = "dolfinx-adjoint"
|
|
6
|
-
version = "0.
|
|
6
|
+
version = "0.3.0"
|
|
7
7
|
description = "Automatic differentation compatible with DOLFINx"
|
|
8
8
|
authors = [{ name = "Jørgen S. Dokken", email = "dokken@simula.no" }]
|
|
9
9
|
license = "MIT"
|
|
@@ -13,6 +13,7 @@ dependencies = [
|
|
|
13
13
|
"fenics-dolfinx>=0.10.0",
|
|
14
14
|
"pyadjoint-ad>=2025.10.0",
|
|
15
15
|
"typing_extensions; python_version < '3.11'",
|
|
16
|
+
"packaging>=24.2",
|
|
16
17
|
]
|
|
17
18
|
|
|
18
19
|
|
|
@@ -28,7 +29,7 @@ docs = [
|
|
|
28
29
|
"networkx",
|
|
29
30
|
"pygraphviz"
|
|
30
31
|
]
|
|
31
|
-
all = ["
|
|
32
|
+
all = ["dolfinx-adjoint[test]", "dolfinx-adjoint[dev]", "dolfinx-adjoint[docs]"]
|
|
32
33
|
|
|
33
34
|
[tool.pytest.ini_options]
|
|
34
35
|
addopts = ["--import-mode=importlib"]
|
|
@@ -91,21 +92,10 @@ tag = true
|
|
|
91
92
|
sign_tags = false
|
|
92
93
|
tag_name = "v{new_version}"
|
|
93
94
|
tag_message = "Bump version: {current_version} → {new_version}"
|
|
94
|
-
current_version = "0.
|
|
95
|
+
current_version = "0.3.0"
|
|
95
96
|
|
|
96
97
|
|
|
97
98
|
[[tool.bumpversion.files]]
|
|
98
99
|
filename = "pyproject.toml"
|
|
99
100
|
search = 'version = "{current_version}"'
|
|
100
101
|
replace = 'version = "{new_version}"'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
[[tool.bumpversion.files]]
|
|
104
|
-
filename = "README.md"
|
|
105
|
-
search = "ghcr.io/scientificcomputing/dolfinx-adjoint:v{current_version}"
|
|
106
|
-
replace = "ghcr.io/scientificcomputing/dolfinx-adjoint:v{new_version}"
|
|
107
|
-
|
|
108
|
-
[[tool.bumpversion.files]]
|
|
109
|
-
filename = "Dockerfile"
|
|
110
|
-
search = "ghcr.io/scientificcomputing/dolfinx-adjoint:v{current_version}"
|
|
111
|
-
replace = "ghcr.io/scientificcomputing/dolfinx-adjoint:v{new_version}"
|
|
@@ -7,7 +7,7 @@ import pyadjoint as _pyad
|
|
|
7
7
|
|
|
8
8
|
from .assembly import assemble_scalar, error_norm
|
|
9
9
|
from .solvers import LinearProblem, NonlinearProblem
|
|
10
|
-
from .types import Constant, Function
|
|
10
|
+
from .types import Constant, Function, dirichletbc
|
|
11
11
|
from .types.function import assign
|
|
12
12
|
|
|
13
13
|
meta = metadata("dolfinx_adjoint")
|
|
@@ -24,6 +24,7 @@ _pyad.continue_annotation()
|
|
|
24
24
|
__all__ = [
|
|
25
25
|
"Constant",
|
|
26
26
|
"Function",
|
|
27
|
+
"dirichletbc",
|
|
27
28
|
"LinearProblem",
|
|
28
29
|
"NonlinearProblem",
|
|
29
30
|
"assemble_scalar",
|
|
@@ -41,6 +41,15 @@ def _vector(
|
|
|
41
41
|
Returns:
|
|
42
42
|
A distributed vector.
|
|
43
43
|
"""
|
|
44
|
+
vtype: (
|
|
45
|
+
type[dolfinx.cpp.la.Vector_float32]
|
|
46
|
+
| type[dolfinx.cpp.la.Vector_float64]
|
|
47
|
+
| type[dolfinx.cpp.la.Vector_complex64]
|
|
48
|
+
| type[dolfinx.cpp.la.Vector_complex128]
|
|
49
|
+
| type[dolfinx.cpp.la.Vector_int8]
|
|
50
|
+
| type[dolfinx.cpp.la.Vector_int32]
|
|
51
|
+
| type[dolfinx.cpp.la.Vector_int64]
|
|
52
|
+
)
|
|
44
53
|
if np.issubdtype(dtype, np.float32):
|
|
45
54
|
vtype = dolfinx.cpp.la.Vector_float32
|
|
46
55
|
elif np.issubdtype(dtype, np.float64):
|
|
@@ -72,6 +81,8 @@ def _create_vector(L: dolfinx.fem.Form, space: dolfinx.fem.FunctionSpace) -> _Sp
|
|
|
72
81
|
"""
|
|
73
82
|
# Can just take the first dofmap here, since all dof maps have the same
|
|
74
83
|
# index map in mixed-topology meshes
|
|
75
|
-
|
|
84
|
+
|
|
85
|
+
dofmap = L.function_spaces[0].dofmaps[0] # type: ignore
|
|
86
|
+
|
|
76
87
|
assert space._cpp_object == L.function_spaces[0], "Function space mismatch when creating vector."
|
|
77
88
|
return _vector(dofmap.index_map, dofmap.index_map_bs, dtype=L.dtype, function_space=space)
|
|
@@ -129,6 +129,7 @@ class AssembleBlock(Block):
|
|
|
129
129
|
form_compiler_options=self._form_compiler_options,
|
|
130
130
|
entity_maps=self._entity_maps,
|
|
131
131
|
)
|
|
132
|
+
|
|
132
133
|
if space is None:
|
|
133
134
|
# If space is not supplied infer it from the form
|
|
134
135
|
assert len(dform.arguments()) == 1
|
|
@@ -143,6 +144,9 @@ class AssembleBlock(Block):
|
|
|
143
144
|
# assemble_compiled_form(compiled_adjoint, self._cached_vectors[id(space)])
|
|
144
145
|
assemble_compiled_form(compiled_adjoint, vector)
|
|
145
146
|
# return a vector scaled by the scalar `adj_input`
|
|
147
|
+
# Safegaurd against None seeds from PyAdjoint
|
|
148
|
+
if adj_input is None:
|
|
149
|
+
adj_input = 1.0
|
|
146
150
|
vector.array[:] *= vector.x.array.dtype.type(adj_input)
|
|
147
151
|
vector.scatter_forward()
|
|
148
152
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import dolfinx
|
|
2
|
+
import numpy as np
|
|
3
|
+
import numpy.typing as npt
|
|
4
|
+
from pyadjoint.block import Block
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DirichletBCBlock(Block):
|
|
8
|
+
"""A block representing a DirichletBC in the adjoint framework.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
value: The value of the Dirichlet BC.
|
|
12
|
+
dofs: An array of degree-of-freedom indices in `V` where the BC should be applied.
|
|
13
|
+
V: The function space associated with the Dirichlet BC.
|
|
14
|
+
ad_block_tag: An optional tag to identify this block in the adjoint framework.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
value: dolfinx.fem.Function | dolfinx.fem.Constant,
|
|
21
|
+
dofs: npt.NDArray[np.int32],
|
|
22
|
+
V: dolfinx.fem.FunctionSpace | None = None,
|
|
23
|
+
ad_block_tag: str | None = None,
|
|
24
|
+
):
|
|
25
|
+
super().__init__(ad_block_tag=ad_block_tag)
|
|
26
|
+
self._dofs = dofs
|
|
27
|
+
self._V = V
|
|
28
|
+
self.add_dependency(value)
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def dofs(self):
|
|
32
|
+
return self._dofs
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def V(self):
|
|
36
|
+
return self._V
|
|
37
|
+
|
|
38
|
+
def prepare_recompute_component(self, inputs, relevant_outputs):
|
|
39
|
+
return inputs[0] if inputs else None
|
|
40
|
+
|
|
41
|
+
def recompute_component(self, inputs, block_variable, idx, prepared):
|
|
42
|
+
return block_variable.saved_output
|
{dolfinx_adjoint-0.2.0 → dolfinx_adjoint-0.3.0}/src/dolfinx_adjoint/blocks/function_assigner.py
RENAMED
|
@@ -6,8 +6,7 @@ import ufl
|
|
|
6
6
|
from pyadjoint import AdjFloat, Block, OverloadedType
|
|
7
7
|
from ufl.formatting.ufl2unicode import ufl2unicode
|
|
8
8
|
|
|
9
|
-
from
|
|
10
|
-
|
|
9
|
+
from ..utils import function_from_vector
|
|
11
10
|
from ._vector import _vector
|
|
12
11
|
|
|
13
12
|
|
|
@@ -178,15 +177,18 @@ class FunctionAssignBlock(Block):
|
|
|
178
177
|
def recompute_component(self, inputs, block_variable, idx, prepared):
|
|
179
178
|
if self.expr is None:
|
|
180
179
|
prepared = inputs[0]
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
)
|
|
180
|
+
|
|
181
|
+
# We should return the exact object instance to maintain C++ memory bindings
|
|
182
|
+
# (especially for DirichletBCs), updating it in-place.
|
|
183
|
+
output = block_variable.saved_output
|
|
184
|
+
|
|
184
185
|
try:
|
|
185
186
|
if output.function_space == prepared.function_space:
|
|
186
187
|
output.x.array[:] = prepared.x.array[:]
|
|
187
188
|
except AttributeError:
|
|
188
189
|
# Handling float value
|
|
189
190
|
output.x.array[:] = prepared
|
|
191
|
+
|
|
190
192
|
return output
|
|
191
193
|
|
|
192
194
|
def __str__(self):
|