@@ -256,6 +256,135 @@ function assemble!(
256256 return nothing
257257end
258258
259+ # wrapper
260+ function assemble! (
261+ assembler:: SparseMatrixAssembler ,
262+ func:: F ,
263+ U:: T ,
264+ sym:: Symbol
265+ ) where {F, T}
266+ assemble! (assembler, func, U, Val {sym} ())
267+ end
268+
269+ KA. @kernel function _assemble_residual_kernel! (asm, func, U, X, conns, ref_fe, block_id)
270+ E = KA. @index (Global)
271+
272+ # some helpers
273+ NDim = size (X, 1 )
274+ ND, NN = num_dofs_per_node (asm. dof), num_nodes (asm. dof)
275+ NNPE = ReferenceFiniteElements. num_vertices (ref_fe)
276+ # NDim = ReferenceFiniteElements.num_dimensions(ref_fe)
277+ NxNDof = NNPE * ND
278+ # IDs = reshape(1:length(asm.dof), ND, size(U, 2))
279+
280+ # extract element level stuff
281+ u_el = @views SMatrix {ND, NNPE, Float64, NxNDof} (U[:, conns[:, E]])
282+ x_el = @views SMatrix {NDim, NNPE, Float64, NDim * NNPE} (X[:, conns[:, E]])
283+ # dof_conns = reshape(IDs[:, conns], ND * length(conns))
284+
285+ # assemble element level residual
286+ R_el = zeros (SVector{NxNDof, Float64})
287+ for q in 1 : num_quadrature_points (ref_fe)
288+ interps = MappedInterpolants (ref_fe. cell_interps. vals[q], x_el)
289+
290+ # dynamic method invocation isn't working here.
291+ # R_q = func(interps, u_el)
292+ # R_el = R_el + R_q
293+
294+ X_q, N, ∇N_X, JxW = interps. X_q, interps. N, interps.∇N_X, interps. JxW
295+ ∇u_q = u_el * ∇N_X
296+ f = 2. * π^ 2 * sin (2 π * X_q[1 ]) * sin (4 π * X_q[2 ])
297+ R_q = ∇u_q * ∇N_X' - N' * f
298+ R_el = R_el + JxW * R_q[:]
299+ end
300+
301+ # now assemble
302+ # TODO won't work for problems with more than one dof...
303+ # need to create dof_conns
304+ for i in axes (conns, 1 )
305+ Atomix. @atomic asm. residual_storage. vals[conns[i]] += R_el[i]
306+ end
307+ end
308+
309+ KA. @kernel function _assemble_stiffness_kernel! (asm, func, U, X, conns, ref_fe, block_id)
310+ E = KA. @index (Global)
311+
312+ # some helpers
313+ NDim = size (X, 1 )
314+ ND, NN = num_dofs_per_node (asm. dof), num_nodes (asm. dof)
315+ NNPE = ReferenceFiniteElements. num_vertices (ref_fe)
316+ # NDim = ReferenceFiniteElements.num_dimensions(ref_fe)
317+ NxNDof = NNPE * ND
318+
319+ # extract element level stuff
320+ u_el = @views SMatrix {ND, NNPE, Float64, NxNDof} (U[:, conns[:, E]])
321+ x_el = @views SMatrix {NDim, NNPE, Float64, NDim * NNPE} (X[:, conns[:, E]])
322+
323+ # assemble element level residual
324+ K_el = zeros (SMatrix{NxNDof, NxNDof, Float64, NxNDof * NxNDof})
325+ for q in 1 : num_quadrature_points (ref_fe)
326+ interps = MappedInterpolants (ref_fe. cell_interps. vals[q], x_el)
327+
328+ # dynamic method invocation isn't working here.
329+ # R_q = func(interps, u_el)
330+ # R_el = R_el + R_q
331+
332+ X_q, N, ∇N_X, JxW = interps. X_q, interps. N, interps.∇N_X, interps. JxW
333+ K_q = ∇N_X * ∇N_X'
334+ K_el = K_el + JxW * K_q
335+ end
336+
337+ # now assemble
338+ # TODO won't work for problems with more than one dof...
339+ # need to create dof_conns
340+ # start_id = (block_id - 1) * asm.pattern.block_sizes[block_id] +
341+ # (el_id - 1) * asm.pattern.block_offsets[block_id] + 1
342+ # end_id = start_id + asm.pattern.block_offsets[block_id] - 1
343+ # ids = start_id:end_id
344+ # for id in ids
345+ # Atomix.@atomic asm.stiffness_storage[id] += K_el[:]
346+ # end
347+ end
348+
349+ # newer method try to dispatch based on field type
350+ function assemble! (
351+ assembler:: SparseMatrixAssembler ,
352+ residual_func:: F ,
353+ U:: T ,
354+ :: Val{:residual}
355+ ) where {F <: Function , T <: H1Field }
356+ # TODO hack for now, only grabbing first var fspace
357+ # fspace = getproperty(assembler.dof.H1_vars, :H1_var_1)
358+ fspace = assembler. dof. H1_vars[1 ]. fspace
359+ for (block_id, conns) in enumerate (values (fspace. elem_conns))
360+ ref_fe = values (fspace. ref_fes)[block_id]
361+ # backend = KA.get_backend(assembler)
362+ # TODO eventually dispatch on CPU vs. GPU
363+ kernel! = _assemble_residual_kernel! (KA. get_backend (assembler))
364+ kernel! (assembler, residual_func, U, fspace. coords, conns, ref_fe, block_id, ndrange = size (conns, 2 ))
365+ end
366+ end
367+
368+ function assemble! (
369+ assembler:: SparseMatrixAssembler ,
370+ tangent_func:: F ,
371+ U:: T ,
372+ :: Val{:stiffness}
373+ ) where {F <: Function , T <: H1Field }
374+ # TODO hack for now, only grabbing first var fspace
375+ # fspace = getproperty(assembler.dof.H1_vars, :H1_var_1)
376+ fspace = assembler. dof. H1_vars[1 ]. fspace
377+ for (block_id, conns) in enumerate (values (fspace. elem_conns))
378+ ref_fe = values (fspace. ref_fes)[block_id]
379+ # backend = KA.get_backend(assembler)
380+ # TODO eventually dispatch on CPU vs. GPU
381+
382+ # TODO going to need to query the start/end ids for the block assembler
383+ kernel! = _assemble_stiffness_kernel! (KA. get_backend (assembler))
384+ kernel! (assembler, tangent_func, U, fspace. coords, conns, ref_fe, block_id, ndrange = size (conns, 2 ))
385+ end
386+ end
387+
259388# TODO hardcoded for H1
260389function assemble! (
261390 R,
@@ -265,6 +394,7 @@ function assemble!(
265394) where {F <: Function , T <: AbstractArray }
266395
267396 R .= zero (eltype (R))
397+ # fill(R.vals, zero(eltype(R)))
268398
269399 vars = assembler. dof. H1_vars
270400
@@ -274,42 +404,9 @@ function assemble!(
274404
275405 fspace = vars[1 ]. fspace
276406
277- # NDim = size(fspace.coords, 1)
278- # ND, NN = num_dofs_per_node(assembler.dof), num_nodes(assembler.dof)
279- # ids = reshape(1:length(assembler.dof), ND, NN)
280-
281407 for (block_id, conns) in enumerate (values (fspace. elem_conns))
282408 ref_fe = values (fspace. ref_fes)[block_id]
283-
284409 assemble! (R, assembler, residual_func, U, fspace. coords, conns, ref_fe)
285- # NNPE = ReferenceFiniteElements.num_vertices(ref_fe)
286- # NxNDof = NNPE * ND
287- # dof_conns = @views reshape(ids[:, conns], ND * size(conns, 1), size(conns, 2))
288-
289- # for e in 1:size(conns, 2)
290- # AK.foraxes(conns, 2) do e
291- # u_el = @views SMatrix{ND, NNPE, Float64, NxNDof}(U[dof_conns[:, e]])
292- # x_el = @views SMatrix{NDim, NNPE, Float64, NDim * NNPE}(fspace.coords[:, conns[:, e]])
293- # # K_el = zeros(SMatrix{NxNDof, NxNDof, Float64, NxNDof * NxNDof})
294- # # R_el = zeros(SMatrix{ND, NNPE, Float64, NxNDof})
295- # R_el = zeros(SVector{NxNDof, Float64})
296-
297- # for q in 1:num_quadrature_points(ref_fe)
298- # N = ReferenceFiniteElements.shape_function_value(ref_fe, q)
299- # ∇N_ξ = ReferenceFiniteElements.shape_function_gradient(ref_fe, q)
300- # ∇N_X = map_shape_function_gradients(x_el, ∇N_ξ)
301- # JxW = volume(x_el, ∇N_ξ) * quadrature_weight(ref_fe, q)
302- # x_q = x_el * N
303- # interps = Interpolants(x_q, N, ∇N_X, JxW)
304-
305- # R_q = residual_func(interps, u_el)
306- # R_el = R_el + JxW * R_q
307- # end
308-
309- # # assemble!(assembler, R_el, e, block_id)
310- # # Note this method is in old stuff TODO
311- # @views assemble!(R, R_el, dof_conns[:, e])
312- # end
313410 end
314411end
315412
@@ -396,6 +493,7 @@ function assemble!(
396493 end
397494end
398495
496+ create_bcs (asm:: SparseMatrixAssembler , type) = create_bcs (asm. dof, type)
399497create_field (asm:: SparseMatrixAssembler , type) = create_field (asm. dof, type)
400498create_unknowns (asm:: SparseMatrixAssembler ) = create_unknowns (asm. dof)
401499
0 commit comments