1
1
2
- function Fields. gradient (f:: Function ,uh:: DistributedCellField )
2
+ const DistributedADTypes = Union{DistributedCellField,DistributedMultiFieldCellField}
3
+
4
+ # Distributed counterpart of: src/FESpaces/FEAutodiff.jl
5
+
6
+ function Fields. gradient (f:: Function ,uh:: DistributedADTypes )
3
7
fuh = f (uh)
4
8
FESpaces. _gradient (f,uh,fuh)
5
9
end
@@ -9,15 +13,15 @@ function FESpaces._gradient(f,uh,fuh::DistributedDomainContribution)
9
13
local_domains = tuple_of_arrays (map (Tuple∘ get_domains,local_views (fuh)))
10
14
for local_trians in local_domains
11
15
g = FESpaces. _change_argument (gradient,f,local_trians,uh)
12
- cell_u = map (get_cell_dof_values,local_views (uh))
16
+ cell_u = map (FESpaces . get_cell_dof_values,local_views (uh))
13
17
cell_id = map (FESpaces. _compute_cell_ids,local_views (uh),local_trians)
14
18
cell_grad = distributed_autodiff_array_gradient (g,cell_u,cell_id)
15
19
map (add_contribution!,local_terms,local_trians,cell_grad)
16
20
end
17
21
DistributedDomainContribution (local_terms)
18
22
end
19
23
20
- function Fields. jacobian (f:: Function ,uh:: DistributedCellField )
24
+ function Fields. jacobian (f:: Function ,uh:: DistributedADTypes )
21
25
fuh = f (uh)
22
26
FESpaces. _jacobian (f,uh,fuh)
23
27
end
@@ -27,79 +31,222 @@ function FESpaces._jacobian(f,uh,fuh::DistributedDomainContribution)
27
31
local_domains = tuple_of_arrays (map (Tuple∘ get_domains,local_views (fuh)))
28
32
for local_trians in local_domains
29
33
g = FESpaces. _change_argument (jacobian,f,local_trians,uh)
30
- cell_u = map (get_cell_dof_values,local_views (uh))
34
+ cell_u = map (FESpaces . get_cell_dof_values,local_views (uh))
31
35
cell_id = map (FESpaces. _compute_cell_ids,local_views (uh),local_trians)
32
36
cell_grad = distributed_autodiff_array_jacobian (g,cell_u,cell_id)
33
37
map (add_contribution!,local_terms,local_trians,cell_grad)
34
38
end
35
39
DistributedDomainContribution (local_terms)
36
40
end
37
41
38
- function FESpaces. _change_argument (op,f,trian,uh:: DistributedCellField )
39
- spaces = map (get_fe_space,local_views (uh))
40
- function g (cell_u)
41
- cf = DistributedCellField (
42
- map (CellField,spaces,cell_u),
43
- get_triangulation (uh),
42
+ function Fields. hessian (f:: Function ,uh:: DistributedADTypes )
43
+ fuh = f (uh)
44
+ FESpaces. _hessian (f,uh,fuh)
45
+ end
46
+
47
+ function FESpaces. _hessian (f,uh,fuh:: DistributedDomainContribution )
48
+ local_terms = map (r -> DomainContribution (), get_parts (fuh))
49
+ local_domains = tuple_of_arrays (map (Tuple∘ get_domains,local_views (fuh)))
50
+ for local_trians in local_domains
51
+ g = FESpaces. _change_argument (hessian,f,local_trians,uh)
52
+ cell_u = map (FESpaces. get_cell_dof_values,local_views (uh))
53
+ cell_id = map (FESpaces. _compute_cell_ids,local_views (uh),local_trians)
54
+ cell_grad = distributed_autodiff_array_hessian (g,cell_u,cell_id)
55
+ map (add_contribution!,local_terms,local_trians,cell_grad)
56
+ end
57
+ DistributedDomainContribution (local_terms)
58
+ end
59
+
60
+ function FESpaces. _change_argument (op,f,local_trians,uh:: DistributedADTypes )
61
+ function dist_cf (uh:: DistributedCellField ,cfs)
62
+ DistributedCellField (cfs,get_triangulation (uh))
63
+ end
64
+ function dist_cf (uh:: DistributedMultiFieldCellField ,cfs)
65
+ sf_cfs = map (DistributedCellField,
66
+ [tuple_of_arrays (map (cf -> Tuple (cf. single_fields),cfs))... ],
67
+ map (get_triangulation,uh)
44
68
)
45
- cell_grad = f (cf)
46
- map (get_contribution,local_views (cell_grad),trian)
69
+ DistributedMultiFieldCellField (sf_cfs,cfs)
70
+ end
71
+
72
+ uhs = local_views (uh)
73
+ spaces = map (get_fe_space,uhs)
74
+ function g (cell_u)
75
+ cfs = map (CellField,spaces,cell_u)
76
+ cf = dist_cf (uh,cfs)
77
+ cg = f (cf)
78
+ map (get_contribution,local_views (cg),local_trians)
47
79
end
48
80
g
49
81
end
50
82
83
+ # Distributed counterpart of: src/Arrays/Autodiff.jl
51
84
# autodiff_array_xxx
52
85
53
86
function distributed_autodiff_array_gradient (a,i_to_x)
54
- dummy_forwarddiff_tag = ()-> ()
55
- i_to_xdual = map (i_to_x) do i_to_x
56
- lazy_map (DualizeMap (ForwardDiff. gradient,dummy_forwarddiff_tag),i_to_x)
87
+ dummy_tag = ()-> ()
88
+ i_to_cfg = map (i_to_x) do i_to_x
89
+ lazy_map (ConfigMap (ForwardDiff. gradient,dummy_tag),i_to_x)
90
+ end
91
+ i_to_xdual = map (i_to_cfg,i_to_x) do i_to_cfg, i_to_x
92
+ lazy_map (DualizeMap (),i_to_cfg,i_to_x)
57
93
end
58
94
i_to_ydual = a (i_to_xdual)
59
- i_to_result = map (i_to_ydual,i_to_x) do i_to_ydual,i_to_x
60
- i_to_cfg = lazy_map (ConfigMap (ForwardDiff. gradient,dummy_forwarddiff_tag),i_to_x)
61
- lazy_map (AutoDiffMap (ForwardDiff. gradient),i_to_ydual,i_to_x,i_to_cfg)
95
+ i_to_result = map (i_to_cfg,i_to_ydual) do i_to_cfg,i_to_ydual
96
+ lazy_map (AutoDiffMap (),i_to_cfg,i_to_ydual)
62
97
end
63
98
return i_to_result
64
99
end
65
100
66
101
function distributed_autodiff_array_jacobian (a,i_to_x)
67
- dummy_forwarddiff_tag = ()-> ()
68
- i_to_xdual = map (i_to_x) do i_to_x
69
- lazy_map (DualizeMap (ForwardDiff. jacobian,dummy_forwarddiff_tag),i_to_x)
102
+ dummy_tag = ()-> ()
103
+ i_to_cfg = map (i_to_x) do i_to_x
104
+ lazy_map (ConfigMap (ForwardDiff. jacobian,dummy_tag),i_to_x)
105
+ end
106
+ i_to_xdual = map (i_to_cfg,i_to_x) do i_to_cfg, i_to_x
107
+ lazy_map (DualizeMap (),i_to_cfg,i_to_x)
70
108
end
71
109
i_to_ydual = a (i_to_xdual)
72
- i_to_result = map (i_to_ydual,i_to_x) do i_to_ydual,i_to_x
73
- i_to_cfg = lazy_map (ConfigMap (ForwardDiff. jacobian,dummy_forwarddiff_tag),i_to_x)
74
- lazy_map (AutoDiffMap (ForwardDiff. jacobian),i_to_ydual,i_to_x,i_to_cfg)
110
+ i_to_result = map (i_to_cfg,i_to_ydual) do i_to_cfg,i_to_ydual
111
+ lazy_map (AutoDiffMap (),i_to_cfg,i_to_ydual)
75
112
end
76
- i_to_result
113
+ return i_to_result
114
+ end
115
+
116
+ function distributed_autodiff_array_hessian (a,i_to_x)
117
+ agrad = i_to_y -> distributed_autodiff_array_gradient (a,i_to_y)
118
+ distributed_autodiff_array_jacobian (agrad,i_to_x)
77
119
end
78
120
79
121
function distributed_autodiff_array_gradient (a,i_to_x,j_to_i)
80
- dummy_forwarddiff_tag = ()-> ()
81
- i_to_xdual = map (i_to_x) do i_to_x
82
- lazy_map (DualizeMap (ForwardDiff. gradient,dummy_forwarddiff_tag),i_to_x)
122
+ dummy_tag = ()-> ()
123
+ i_to_cfg = map (i_to_x) do i_to_x
124
+ lazy_map (ConfigMap (ForwardDiff. gradient,dummy_tag),i_to_x)
125
+ end
126
+ i_to_xdual = map (i_to_cfg,i_to_x) do i_to_cfg, i_to_x
127
+ lazy_map (DualizeMap (),i_to_cfg,i_to_x)
83
128
end
84
129
j_to_ydual = a (i_to_xdual)
85
- j_to_result = map (i_to_x,j_to_i,j_to_ydual) do i_to_x,j_to_i,j_to_ydual
86
- j_to_x = lazy_map (Reindex (i_to_x),j_to_i)
87
- j_to_cfg = lazy_map (ConfigMap (ForwardDiff. gradient,dummy_forwarddiff_tag),j_to_x)
88
- lazy_map (AutoDiffMap (ForwardDiff. gradient),j_to_ydual,j_to_x,j_to_cfg)
130
+ j_to_result = map (i_to_cfg,j_to_i,j_to_ydual) do i_to_cfg,j_to_i,j_to_ydual
131
+ j_to_cfg = Arrays. autodiff_array_reindex (i_to_cfg,j_to_i)
132
+ lazy_map (AutoDiffMap (),j_to_cfg,j_to_ydual)
89
133
end
90
134
return j_to_result
91
135
end
92
136
93
137
function distributed_autodiff_array_jacobian (a,i_to_x,j_to_i)
94
- dummy_forwarddiff_tag = ()-> ()
95
- i_to_xdual = map (i_to_x) do i_to_x
96
- lazy_map (DualizeMap (ForwardDiff. jacobian,dummy_forwarddiff_tag),i_to_x)
138
+ dummy_tag = ()-> ()
139
+ i_to_cfg = map (i_to_x) do i_to_x
140
+ lazy_map (ConfigMap (ForwardDiff. jacobian,dummy_tag),i_to_x)
141
+ end
142
+ i_to_xdual = map (i_to_cfg,i_to_x) do i_to_cfg, i_to_x
143
+ lazy_map (DualizeMap (),i_to_cfg,i_to_x)
97
144
end
98
145
j_to_ydual = a (i_to_xdual)
99
- j_to_result = map (i_to_x,j_to_i,j_to_ydual) do i_to_x,j_to_i,j_to_ydual
100
- j_to_x = lazy_map (Reindex (i_to_x),j_to_i)
101
- j_to_cfg = lazy_map (ConfigMap (ForwardDiff. jacobian,dummy_forwarddiff_tag),j_to_x)
102
- lazy_map (AutoDiffMap (ForwardDiff. jacobian),j_to_ydual,j_to_x,j_to_cfg)
146
+ j_to_result = map (i_to_cfg,j_to_i,j_to_ydual) do i_to_cfg,j_to_i,j_to_ydual
147
+ j_to_cfg = Arrays. autodiff_array_reindex (i_to_cfg,j_to_i)
148
+ lazy_map (AutoDiffMap (),j_to_cfg,j_to_ydual)
103
149
end
104
- j_to_result
150
+ return j_to_result
151
+ end
152
+
153
+ function distributed_autodiff_array_hessian (a,i_to_x,i_to_j)
154
+ agrad = i_to_y -> distributed_autodiff_array_gradient (a,i_to_y,i_to_j)
155
+ distributed_autodiff_array_jacobian (agrad,i_to_x,i_to_j)
156
+ end
157
+
158
+ # Skeleton AD
159
+
160
+ function FESpaces. _change_argument (op,f,local_trians:: AbstractArray{<:SkeletonTriangulation} ,uh:: DistributedADTypes )
161
+ function dist_cf (uh:: DistributedCellField ,cfs)
162
+ DistributedCellField (cfs, get_triangulation (uh))
163
+ end
164
+ function dist_cf (uh:: DistributedMultiFieldCellField ,cfs)
165
+ sf_cfs = map (DistributedCellField,
166
+ [tuple_of_arrays (map (cf -> Tuple (cf. single_fields),cfs))... ],
167
+ map (get_triangulation,uh)
168
+ )
169
+ DistributedMultiFieldCellField (sf_cfs,cfs)
170
+ end
171
+
172
+ uhs = local_views (uh)
173
+ spaces = map (get_fe_space,uhs)
174
+ function g (cell_u)
175
+ uhs_dual = map (CellField,spaces,cell_u)
176
+ cf_plus = dist_cf (uh,map (SkeletonCellFieldPair,uhs_dual,uhs))
177
+ cf_minus = dist_cf (uh,map (SkeletonCellFieldPair,uhs,uhs_dual))
178
+ cg_plus = f (cf_plus)
179
+ cg_minus = f (cf_minus)
180
+ plus = map (get_contribution,local_views (cg_plus),local_trians)
181
+ minus = map (get_contribution,local_views (cg_minus),local_trians)
182
+ plus, minus
183
+ end
184
+ g
185
+ end
186
+
187
+ function distributed_autodiff_array_gradient (a, i_to_x, j_to_i:: AbstractArray{<:SkeletonPair} )
188
+ dummy_tag = ()-> ()
189
+ i_to_cfg = map (i_to_x) do i_to_x
190
+ lazy_map (ConfigMap (ForwardDiff. gradient,dummy_tag),i_to_x)
191
+ end
192
+ i_to_xdual = map (i_to_cfg,i_to_x) do i_to_cfg, i_to_x
193
+ lazy_map (DualizeMap (),i_to_cfg,i_to_x)
194
+ end
195
+
196
+ # dual output of both sides at once
197
+ j_to_ydual_plus, j_to_ydual_minus = a (i_to_xdual)
198
+
199
+ j_to_result = map (i_to_cfg,j_to_i,j_to_ydual_plus,j_to_ydual_minus) do i_to_cfg,j_to_i,j_to_ydual_plus,j_to_ydual_minus
200
+ # Work for plus side
201
+ j_to_cfg_plus = Arrays. autodiff_array_reindex (i_to_cfg,j_to_i. plus)
202
+ j_to_result_plus = lazy_map (AutoDiffMap (),j_to_cfg_plus,j_to_ydual_plus)
203
+
204
+ # Work for minus side
205
+ j_to_cfg_minus = Arrays. autodiff_array_reindex (i_to_cfg,j_to_i. minus)
206
+ j_to_result_minus = lazy_map (AutoDiffMap (),j_to_cfg_minus,j_to_ydual_minus)
207
+
208
+ # Assemble on SkeletonTriangulation expects an array of interior of facets
209
+ # where each entry is a 2-block BlockVector with the first block being the
210
+ # contribution of the plus side and the second, the one of the minus side
211
+ is_single_field = eltype (eltype (j_to_result_plus)) <: Number
212
+ k = is_single_field ? BlockMap (2 ,[1 ,2 ]) : Fields. BlockBroadcasting (BlockMap (2 ,[1 ,2 ]))
213
+ lazy_map (k,j_to_result_plus,j_to_result_minus)
214
+ end
215
+
216
+ return j_to_result
217
+ end
218
+
219
+ function distributed_autodiff_array_jacobian (a, i_to_x, j_to_i:: AbstractArray{<:SkeletonPair} )
220
+ dummy_tag = ()-> ()
221
+ i_to_cfg = map (i_to_x) do i_to_x
222
+ lazy_map (ConfigMap (ForwardDiff. jacobian,dummy_tag),i_to_x)
223
+ end
224
+ i_to_xdual = map (i_to_cfg,i_to_x) do i_to_cfg, i_to_x
225
+ lazy_map (DualizeMap (),i_to_cfg,i_to_x)
226
+ end
227
+
228
+ # dual output of both sides at once
229
+ j_to_ydual_plus, j_to_ydual_minus = a (i_to_xdual)
230
+
231
+ j_to_result = map (i_to_cfg,j_to_i,j_to_ydual_plus,j_to_ydual_minus) do i_to_cfg,j_to_i,j_to_ydual_plus,j_to_ydual_minus
232
+ # Work for plus side
233
+ j_to_cfg_plus = Arrays. autodiff_array_reindex (i_to_cfg,j_to_i. plus)
234
+ j_to_result_plus = lazy_map (AutoDiffMap (),j_to_cfg_plus,j_to_ydual_plus)
235
+
236
+ # Work for minus side
237
+ j_to_cfg_minus = Arrays. autodiff_array_reindex (i_to_cfg,j_to_i. minus)
238
+ j_to_result_minus = lazy_map (AutoDiffMap (),j_to_cfg_minus,j_to_ydual_minus)
239
+
240
+ # Merge the columns into a 2x2 block matrix
241
+ # I = [[(CartesianIndex(i,),CartesianIndex(i,j)) for i in 1:2] for j in 1:2]
242
+ I = [
243
+ [(CartesianIndex (1 ,), CartesianIndex (1 , 1 )), (CartesianIndex (2 ,), CartesianIndex (2 , 1 ))], # Plus -> First column
244
+ [(CartesianIndex (1 ,), CartesianIndex (1 , 2 )), (CartesianIndex (2 ,), CartesianIndex (2 , 2 ))] # Minus -> Second column
245
+ ]
246
+ is_single_field = eltype (eltype (j_to_result_plus)) <: AbstractArray
247
+ k = is_single_field ? Fields. MergeBlockMap ((2 ,2 ),I) : Fields. BlockBroadcasting (Fields. MergeBlockMap ((2 ,2 ),I))
248
+ lazy_map (k,j_to_result_plus,j_to_result_minus)
249
+ end
250
+
251
+ return j_to_result
105
252
end
0 commit comments