50 use,
intrinsic :: iso_c_binding
57 logical :: isleaf = .true.
61 integer,
allocatable :: dofs(:)
62 real(kind=
rp) :: xyz(3)
63 real(kind=
rp),
allocatable :: interp_r(:)
64 real(kind=
rp),
allocatable :: interp_p(:)
74 integer :: fine_lvl_dofs = 0
75 real(kind=
rp),
allocatable :: wrk_in(:)
76 type(c_ptr) :: wrk_in_d = c_null_ptr
77 real(kind=
rp),
allocatable :: wrk_out(:)
78 type(c_ptr) :: wrk_out_d = c_null_ptr
79 integer,
allocatable :: map_finest2lvl(:)
80 type(c_ptr) :: map_finest2lvl_d = c_null_ptr
82 integer,
allocatable :: map_f2c(:)
83 type(c_ptr) :: map_f2c_d = c_null_ptr
88 integer,
allocatable :: agg_ptr(:)
89 integer,
allocatable :: agg_dof(:)
95 real(kind=
rp),
allocatable :: agg_part(:,:)
139 subroutine tamg_init(this, ax, Xh, coef, msh, gs_h, nlvls, bc_projector)
141 class(
ax_t),
target,
intent(in) :: ax
142 type(
space_t),
target,
intent(in) :: Xh
143 type(
coef_t),
target,
intent(in) :: coef
144 type(
mesh_t),
target,
intent(in) :: msh
145 type(
gs_t),
target,
intent(in) :: gs_h
146 integer,
intent(in) :: nlvls
155 this%bc_projector => bc_projector
157 if (nlvls .lt. 2)
then
158 call neko_error(
"Need to request at least two multigrid levels.")
162 allocate( this%lvl(this%nlvls) )
165 allocate( this%lvl(i)%map_finest2lvl( 0:coef%dof%size() ))
168 this%lvl(i)%map_finest2lvl_d, coef%dof%size() + 1)
178 if (
allocated(this%lvl))
then
182 do i = 1,
size(this%lvl)
183 call this%lvl(i)%free()
192 nullify(this%bc_projector)
202 integer,
intent(in) :: lvl
203 integer,
intent(in) :: nnodes
204 integer,
intent(in) :: ndofs
207 tamg_lvl%nnodes = nnodes
208 allocate( tamg_lvl%nodes(tamg_lvl%nnodes) )
209 allocate( tamg_lvl%map_f2c(0:ndofs) )
211 call device_map(tamg_lvl%map_f2c, tamg_lvl%map_f2c_d, ndofs+1)
214 tamg_lvl%fine_lvl_dofs = ndofs
215 allocate( tamg_lvl%wrk_in( ndofs ) )
216 allocate( tamg_lvl%wrk_out( ndofs ) )
218 call device_map(tamg_lvl%wrk_in, tamg_lvl%wrk_in_d, ndofs)
220 call device_map(tamg_lvl%wrk_out, tamg_lvl%wrk_out_d, ndofs)
233 if (
allocated(this%nodes))
then
234 do i = 1, this%nnodes
235 call this%nodes(i)%free()
237 deallocate(this%nodes)
239 if (
allocated(this%wrk_in))
then
243 deallocate(this%wrk_in)
245 if (
allocated(this%wrk_out))
then
249 deallocate(this%wrk_out)
251 if (
allocated(this%map_f2c))
then
255 deallocate(this%map_f2c)
257 if (
allocated(this%map_finest2lvl))
then
259 call device_unmap(this%map_finest2lvl, this%map_finest2lvl_d)
261 deallocate(this%map_finest2lvl)
263 if (
allocated(this%agg_ptr))
then
264 deallocate(this%agg_ptr)
266 if (
allocated(this%agg_dof))
then
267 deallocate(this%agg_dof)
269 if (
allocated(this%agg_part))
then
270 deallocate(this%agg_part)
274 this%fine_lvl_dofs = 0
283 integer,
intent(in) :: gid
284 integer,
intent(in) :: ndofs
288 allocate( node%dofs( node%ndofs) )
290 allocate( node%interp_r( node%ndofs) )
291 allocate( node%interp_p( node%ndofs) )
292 node%interp_r = 1.0_rp
293 node%interp_p = 1.0_rp
300 if (
allocated(this%dofs))
then
301 deallocate(this%dofs)
303 if (
allocated(this%interp_r))
then
304 deallocate(this%interp_r)
306 if (
allocated(this%interp_p))
then
307 deallocate(this%interp_p)
319 real(kind=
rp),
intent(inout) :: vec_out(:)
320 real(kind=
rp),
intent(inout) :: vec_in(:)
321 integer,
intent(in) :: lvl_out
336 real(kind=
rp),
intent(inout) :: vec_out(:)
337 real(kind=
rp),
intent(inout) :: vec_in(:)
338 integer,
intent(in) :: lvl
339 integer,
intent(in) :: lvl_out
346 call this%gs_h%op(vec_in, n, gs_op_add)
347 call col2( vec_in, this%coef%mult, n)
349 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
350 call this%gs_h%op(vec_out, n, gs_op_add)
351 call this%bc_projector%apply(vec_out, n)
353 if (lvl_out .ne. 0)
then
354 call col2(vec_out, this%coef%mult, n)
358 if (lvl_out .ge. lvl)
then
361 associate(wrk_in => this%lvl(lvl)%wrk_in, &
362 wrk_out => this%lvl(lvl)%wrk_out)
363 n = this%lvl(lvl)%fine_lvl_dofs
364 call rzero(wrk_in, n)
365 call rzero(vec_out, this%lvl(lvl)%nnodes)
366 do n = 1, this%lvl(lvl)%nnodes
367 associate(node => this%lvl(lvl)%nodes(n))
369 wrk_in(node%dofs(i)) = wrk_in(node%dofs(i)) + &
370 vec_in(node%gid) * node%interp_p(i)
375 call this%matvec_impl(wrk_out, wrk_in, lvl-1, lvl_out)
378 do n = 1, this%lvl(lvl)%nnodes
379 associate(node => this%lvl(lvl)%nodes(n))
381 vec_out(node%gid) = vec_out(node%gid) + &
382 wrk_out(node%dofs(i)) * node%interp_r(i)
387 else if (lvl_out .lt. lvl)
then
389 call this%matvec_impl(vec_out, vec_in, lvl-1, lvl_out)
391 call neko_error(
"TAMG: matvec level numbering problem.")
402 real(kind=rp),
intent(inout) :: vec_out(:)
403 real(kind=rp),
intent(inout) :: vec_in(:)
404 integer,
intent(in) :: lvl_blah
405 integer,
intent(in) :: lvl_out
406 integer :: i, n, lvl, c, k, nagg, tid, nthrds
407 real(kind=rp) :: val, acc
408 logical :: use_partials
411 n = this%lvl(1)%fine_lvl_dofs
413 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
414 call this%gs_h%op(vec_out, n, gs_op_add)
415 call this%bc_projector%apply(vec_out, n)
421 nagg = this%lvl(lvl)%nnodes
422 use_partials =
allocated(this%lvl(lvl)%agg_part)
424 if (use_partials) nthrds =
size(this%lvl(lvl)%agg_part, 2)
430 associate( wrk_in => this%lvl(1)%wrk_in, &
431 wrk_out => this%lvl(1)%wrk_out, &
432 aptr => this%lvl(lvl)%agg_ptr, adof => this%lvl(lvl)%agg_dof, &
433 map => this%lvl(lvl)%map_finest2lvl)
441 do k = aptr(c), aptr(c + 1) - 1
442 wrk_in(adof(k)) = val
448 call this%gs_h%op(wrk_in, n, gs_op_add)
449 call col2( wrk_in, this%coef%mult, n)
450 call this%bc_projector%apply(wrk_in, n)
453 call this%ax%compute(wrk_out, wrk_in, this%coef, this%msh, this%Xh)
454 call this%gs_h%op(wrk_out, n, gs_op_add)
455 call this%bc_projector%apply(wrk_out, n)
457 call col2(wrk_out, this%coef%mult, n)
466 if (.not. use_partials)
then
470 do k = aptr(c), aptr(c + 1) - 1
471 acc = acc + wrk_out(adof(k))
486 this%lvl(lvl)%agg_part = 0.0_rp
494 this%lvl(lvl)%agg_part(c, tid) = &
495 this%lvl(lvl)%agg_part(c, tid) + wrk_out(i)
503 acc = acc + this%lvl(lvl)%agg_part(c, k)
520 real(kind=rp),
intent(inout) :: vec_out(:)
521 real(kind=rp),
intent(inout) :: vec_in(:)
522 integer,
intent(in) :: lvl
523 integer :: i, n, nagg, node_start, node_end, node_id
527 if (lvl-1 .eq. 0)
then
528 call col2(vec_in, this%coef%mult, this%lvl(lvl)%fine_lvl_dofs)
530 nagg = this%lvl(lvl)%nnodes
539 do i = 1, this%lvl(lvl)%nodes(n)%ndofs
540 acc = acc + vec_in( this%lvl(lvl)%nodes(n)%dofs(i) ) &
541 * this%lvl(lvl)%nodes(n)%interp_r( i )
543 vec_out( this%lvl(lvl)%nodes(n)%gid ) = acc
555 real(kind=rp),
intent(inout) :: vec_out(:)
556 real(kind=rp),
intent(inout) :: vec_in(:)
557 integer,
intent(in) :: lvl
558 integer :: i, n, nagg, node_start, node_end, node_id
562 nagg = this%lvl(lvl)%nnodes
570 val = vec_in( this%lvl(lvl)%nodes(n)%gid )
571 do i = 1, this%lvl(lvl)%nodes(n)%ndofs
572 vec_out( this%lvl(lvl)%nodes(n)%dofs(i) ) = &
573 vec_out( this%lvl(lvl)%nodes(n)%dofs(i) ) &
574 + val * this%lvl(lvl)%nodes(n)%interp_p( i )
578 if (lvl-1 .eq. 0)
then
579 call this%gs_h%op(vec_out, this%lvl(lvl)%fine_lvl_dofs, gs_op_add)
580 call col2(vec_out, this%coef%mult, this%lvl(lvl)%fine_lvl_dofs)
581 call this%bc_projector%apply(vec_out, this%lvl(lvl)%fine_lvl_dofs)
589 real(kind=rp),
intent(inout) :: vec_out(:)
590 real(kind=rp),
intent(inout) :: vec_in(:)
591 type(c_ptr) :: vec_out_d
592 type(c_ptr) :: vec_in_d
593 integer,
intent(in) :: lvl_out
594 integer :: i, n, cdof, lvl
597 n = this%lvl(1)%fine_lvl_dofs
599 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
600 call this%gs_h%op(vec_out, n, gs_op_add, glb_cmd_event)
601 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
602 call this%bc_projector%apply(vec_out, n)
605 associate(wrk_in_d => this%lvl(1)%wrk_in_d, &
606 wrk_out_d => this%lvl(1)%wrk_out_d)
608 call device_masked_gather_copy_0(wrk_in_d, vec_in_d, &
609 this%lvl(lvl)%map_finest2lvl_d, this%lvl(lvl)%nnodes, n)
611 call this%gs_h%op(this%lvl(1)%wrk_in, n, gs_op_add, glb_cmd_event)
612 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
613 call device_col2( wrk_in_d, this%coef%mult_d, n)
614 call this%bc_projector%apply(this%lvl(1)%wrk_in, n)
617 call this%ax%compute(this%lvl(1)%wrk_out, this%lvl(1)%wrk_in, &
618 this%coef, this%msh, this%Xh)
619 call this%gs_h%op(this%lvl(1)%wrk_out, n, gs_op_add, glb_cmd_event)
620 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
621 call this%bc_projector%apply(this%lvl(1)%wrk_out, n)
623 call device_col2( wrk_out_d, this%coef%mult_d, n)
626 call device_rzero(vec_out_d, this%lvl(lvl)%nnodes)
627 call device_masked_atomic_reduction_0(vec_out_d, wrk_out_d, &
628 this%lvl(lvl)%map_finest2lvl_d, this%lvl(lvl)%nnodes, n)
636 type(c_ptr) :: vec_out_d
637 type(c_ptr) :: vec_in_d
638 integer,
intent(in) :: lvl
640 n = this%lvl(lvl)%nnodes
641 m = this%lvl(lvl)%fine_lvl_dofs
642 if (lvl-1 .eq. 0)
then
643 call device_col2(vec_in_d, this%coef%mult_d, m)
645 call device_rzero(vec_out_d, n)
646 call device_masked_atomic_reduction_0(vec_out_d, vec_in_d, &
647 this%lvl(lvl)%map_f2c_d, n, m)
653 real(kind=rp),
intent(inout) :: vec_out(:)
654 type(c_ptr) :: vec_out_d
655 type(c_ptr) :: vec_in_d
656 integer,
intent(in) :: lvl
658 n = this%lvl(lvl)%nnodes
659 m = this%lvl(lvl)%fine_lvl_dofs
660 call device_masked_gather_copy_0(vec_out_d, vec_in_d, &
661 this%lvl(lvl)%map_f2c_d, n, m)
662 if (lvl-1 .eq. 0)
then
663 call this%gs_h%op(vec_out, m, gs_op_add, glb_cmd_event)
664 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
665 call device_col2( vec_out_d, this%coef%mult_d, m)
666 call this%bc_projector%apply(vec_out, m)
Map a Fortran array to a device (allocate and associate)
Synchronize a device or stream.
Unmap a Fortran array from a device (deassociate and free)
Defines a Matrix-vector product.
subroutine, public device_masked_atomic_reduction_0(a_d, b_d, mask_d, n, n_mask, strm)
subroutine, public device_rzero(a_d, n, strm)
Zero a real vector.
subroutine, public device_col2(a_d, b_d, n, strm)
Vector multiplication .
subroutine, public device_masked_gather_copy_0(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked vector .
subroutine, public device_cfill(a_d, c, n, strm)
Set all elements to a constant c .
Device abstraction, common interface for various accelerators.
subroutine, public device_stream_wait_event(stream, event, flags)
Synchronize a device stream with an event.
type(c_ptr), bind(C), public glb_cmd_queue
Global command queue.
type(c_ptr), bind(C), public glb_cmd_event
Event for the global command queue.
subroutine, public col2(a, b, n)
Vector multiplication .
subroutine, public rzero(a, n)
Zero a real vector.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Implements scalar_projector_t.
Defines a function space.
Implements the base type for TreeAMG hierarchy structure.
subroutine tamg_init(this, ax, xh, coef, msh, gs_h, nlvls, bc_projector)
Initialization of TreeAMG hierarchy.
subroutine tamg_device_matvec_flat_impl(this, vec_out, vec_in, vec_out_d, vec_in_d, lvl_out)
subroutine tamg_device_prolongation_operator(this, vec_out_d, vec_in_d, lvl, vec_out)
subroutine lvl_free(this)
deallocate tamg level
recursive subroutine tamg_matvec_impl(this, vec_out, vec_in, lvl, lvl_out)
Matrix vector product using the TreeAMG hierarchy structure b=Ax done as vec_out = A * vec_in This is...
subroutine, public tamg_node_init(node, gid, ndofs)
Initialization of a TreeAMG tree node.
subroutine tamg_restriction_operator(this, vec_out, vec_in, lvl)
Restriction operator for TreeAMG. vec_out = R * vec_in.
subroutine tamg_prolongation_operator(this, vec_out, vec_in, lvl)
Prolongation operator for TreeAMG. vec_out = P * vec_in.
subroutine node_free(this)
deallocate tamg tree node
subroutine, public tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
Initialization of a TreeAMG level.
subroutine tamg_free(this)
deallocate tamg hierarchy
recursive subroutine tamg_matvec(this, vec_out, vec_in, lvl_out)
Wrapper for matrix vector product using the TreeAMG hierarchy structure b=Ax done as vec_out = A * ve...
subroutine tamg_device_restriction_operator(this, vec_out_d, vec_in_d, lvl)
recursive subroutine tamg_matvec_flat_impl(this, vec_out, vec_in, lvl_blah, lvl_out)
Ignore this. For piecewise constant, can create index map directly to finest level.
Base type for a matrix-vector product providing .
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Projector for scalar boundary conditions.
The function space for the SEM solution fields.
Type for a TreeAMG hierarchy.
Type for storing TreeAMG level information.
Type for storing TreeAMG tree node information.