64 use,
intrinsic :: iso_c_binding
69 real(kind=
rp),
allocatable :: r(:)
70 real(kind=
rp),
allocatable :: rc(:)
71 real(kind=
rp),
allocatable :: tmp(:)
72 type(c_ptr) :: r_d = c_null_ptr
73 type(c_ptr) :: rc_d = c_null_ptr
74 type(c_ptr) :: tmp_d = c_null_ptr
102 subroutine tamg_mg_init(this, ax, Xh, coef, msh, gs_h, nlvls_in, blst, max_iter)
104 class(
ax_t),
target,
intent(in) :: ax
105 type(
space_t),
target,
intent(in) :: Xh
106 type(
coef_t),
target,
intent(in) :: coef
107 type(
mesh_t),
target,
intent(in) :: msh
108 type(
gs_t),
target,
intent(in) :: gs_h
109 type(
bc_list_t),
target,
intent(in) :: blst
110 integer,
intent(in) :: nlvls_in
111 integer,
intent(in) :: max_iter
112 integer :: nlvls, lvl, n, cheby_degree, env_len, mlvl, target_num_aggs
113 integer,
allocatable :: agg_nhbr(:,:), asdf(:,:)
114 character(len=255) :: env_cheby_degree, env_mlvl
115 character(len=LOG_SIZE) :: log_buf
119 call get_environment_variable(
"NEKO_TAMG_MAX_LVL", &
121 if (env_len .eq. 0)
then
125 read(env_mlvl(1:env_len), *) mlvl
129 write(log_buf,
'(A28,I2,A8)')
'Creating AMG hierarchy with', nlvls,
'levels.'
133 call this%amg%init(ax, xh, coef, msh, gs_h, nlvls, blst)
139 allocate( agg_nhbr, source=msh%facet_neigh )
141 target_num_aggs = this%amg%lvl(mlvl-1)%nnodes / 8
143 if ( target_num_aggs .lt. 4 )
then
144 call neko_error(
"TAMG: Too many levels. Not enough DOFs for coarsest grid.")
150 deallocate( agg_nhbr )
155 this%max_iter = max_iter
157 this%nlvls = this%amg%nlvls
158 if (this%nlvls .gt. this%amg%nlvls)
then
159 call neko_error(
"Requested number multigrid levels is greater than the initialized AMG levels")
162 call get_environment_variable(
"NEKO_TAMG_CHEBY_DEGREE", &
163 env_cheby_degree, env_len)
164 if (env_len .eq. 0)
then
167 read(env_cheby_degree(1:env_len), *) cheby_degree
170 allocate(this%smoo(0:(nlvls)))
172 n = this%amg%lvl(lvl+1)%fine_lvl_dofs
173 call this%smoo(lvl)%init(n ,lvl, cheby_degree)
177 allocate(this%wrk(nlvls))
179 n = this%amg%lvl(lvl)%fine_lvl_dofs
180 allocate( this%wrk(lvl)%r(n) )
181 allocate( this%wrk(lvl)%rc(n) )
182 allocate( this%wrk(lvl)%tmp(n) )
184 call device_map( this%wrk(lvl)%r, this%wrk(lvl)%r_d, n)
185 call device_map( this%wrk(lvl)%rc, this%wrk(lvl)%rc_d, n)
186 call device_map( this%wrk(lvl)%tmp, this%wrk(lvl)%tmp_d, n)
102 subroutine tamg_mg_init(this, ax, Xh, coef, msh, gs_h, nlvls_in, blst, max_iter)
…
208 integer,
intent(in) :: n
210 real(kind=
rp),
dimension(n),
intent(inout) :: z
211 real(kind=
rp),
dimension(n),
intent(inout) :: r
212 integer :: iter, max_iter
214 max_iter = this%max_iter
220 do iter = 1, max_iter
230 integer,
intent(in) :: n
232 real(kind=
rp),
dimension(n),
intent(inout) :: z
233 real(kind=
rp),
dimension(n),
intent(inout) :: r
236 integer :: iter, max_iter
238 max_iter = this%max_iter
244 do iter = 1, max_iter
257 integer,
intent(in) :: n
258 real(kind=
rp),
intent(inout) :: x(n)
259 real(kind=
rp),
intent(inout) :: b(n)
262 integer,
intent(in) :: lvl
263 real(kind=
rp) :: r(n)
264 real(kind=
rp) :: rc(n)
265 real(kind=
rp) :: tmp(n)
266 integer :: iter, num_iter
274 max_lvl = mgstuff%nlvls-1
281 call mgstuff%smoo(lvl)%solve(x,b, n, amg)
283 if (lvl .eq. max_lvl)
then
298 call amg%interp_f2c(rc, r, lvl+1)
304 call tamg_mg_cycle(tmp, rc, amg%lvl(lvl+1)%nnodes, lvl+1, amg, mgstuff)
309 call amg%interp_c2f(r, tmp, lvl+1)
322 call mgstuff%smoo(lvl)%solve(x,b, n, amg)
340 integer,
intent(in) :: n
341 real(kind=
rp),
intent(inout) :: x(n)
342 real(kind=
rp),
intent(inout) :: b(n)
347 integer,
intent(in) :: lvl
348 integer :: iter, num_iter
351 max_lvl = mgstuff%nlvls-1
355 call mgstuff%smoo(lvl)%device_solve(x, b, x_d, b_d, n, amg)
356 if (lvl .eq. max_lvl)
then
359 associate( r => mgstuff%wrk(lvl+1)%r, r_d => mgstuff%wrk(lvl+1)%r_d, &
360 rc => mgstuff%wrk(lvl+1)%rc, rc_d => mgstuff%wrk(lvl+1)%rc_d, &
361 tmp => mgstuff%wrk(lvl+1)%tmp, tmp_d => mgstuff%wrk(lvl+1)%tmp_d )
365 call amg%device_matvec(r, x, r_d, x_d, lvl)
374 call amg%interp_f2c_d(rc_d, r_d, lvl+1)
379 call tamg_mg_cycle_d(tmp, rc, tmp_d, rc_d, amg%lvl(lvl+1)%nnodes, lvl+1, amg, mgstuff)
383 call amg%interp_c2f_d(r_d, tmp_d, lvl+1)
385 call amg%gs_h%op(r, n, gs_op_add)
395 call mgstuff%smoo(lvl)%device_solve(x, b, x_d, b_d, n, amg)
408 integer,
intent(in) :: n
409 real(kind=rp),
intent(inout) :: r(n)
410 real(kind=rp),
intent(inout) :: x(n)
411 real(kind=rp),
intent(inout) :: b(n)
412 type(tamg_hierarchy_t),
intent(inout) :: amg
413 integer,
intent(in) :: lvl
416 call amg%matvec(r, x, lvl)
428 integer,
intent(in) :: n
429 real(kind=rp),
intent(inout) :: u(n)
430 type(tamg_hierarchy_t),
intent(inout) :: amg
431 integer,
intent(in) :: lvl
433 call amg%gs_h%op(u, n, gs_op_add)
435 u(i) = u(i) * amg%coef%mult(i,1,1,1)
440 integer,
intent(in) :: lvl,nagg
441 character(len=LOG_SIZE) :: log_buf
443 write(log_buf,
'(A8,I2,A31)')
'-- level',lvl,
'-- Calling Greedy Aggregation'
444 call neko_log%message(log_buf)
445 write(log_buf,
'(A33,I6)')
'Target Aggregates:',nagg
446 call neko_log%message(log_buf)
450 integer,
intent(in) :: lvl, n
451 real(kind=rp),
intent(inout) :: r(n)
452 real(kind=rp),
intent(inout) :: x(n)
453 real(kind=rp),
intent(inout) :: b(n)
457 type(tamg_hierarchy_t),
intent(inout) :: amg
459 character(len=LOG_SIZE) :: log_buf
461 call amg%device_matvec(r, x, r_d, x_d, lvl)
462 call device_sub3(r_d, b_d, r_d, n)
463 val = device_glsc2(r_d, r_d, n)
465 write(log_buf,
'(A33,I6,F12.6)')
'tAMG resid:', lvl, val
466 call neko_log%message(log_buf)
470 type(tamg_hierarchy_t),
intent(inout) :: amg
471 integer :: i, j, k, l, nid, n
472 do j = 1, amg%lvl(1)%nnodes
473 do k = 1, amg%lvl(1)%nodes(j)%ndofs
474 nid = amg%lvl(1)%nodes(j)%dofs(k)
475 amg%lvl(1)%map_finest2lvl(nid) = amg%lvl(1)%nodes(j)%gid
478 n =
size(amg%lvl(1)%map_finest2lvl)
481 nid = amg%lvl(l-1)%map_finest2lvl(i)
482 do j = 1, amg%lvl(l)%nnodes
483 do k = 1, amg%lvl(l)%nodes(j)%ndofs
484 if (nid .eq. amg%lvl(l)%nodes(j)%dofs(k))
then
485 amg%lvl(l)%map_finest2lvl(i) = amg%lvl(l)%nodes(j)%gid
491 if (neko_bcknd_device .eq. 1)
then
493 amg%lvl(l)%map_finest2lvl(0) = n
494 call device_memcpy( amg%lvl(l)%map_finest2lvl, amg%lvl(l)%map_finest2lvl_d, n, host_to_device, .true.)
495 call device_memcpy( amg%lvl(l)%map_f2c, amg%lvl(l)%map_f2c_d, amg%lvl(l)%fine_lvl_dofs+1, host_to_device, .true.)
Map a Fortran array to a device (allocate and associate)
Copy data between host and device (or device and device)
Defines a Matrix-vector product.
subroutine, public device_add2(a_d, b_d, n)
Vector addition .
subroutine, public device_col2(a_d, b_d, n)
Vector multiplication .
subroutine, public device_rzero(a_d, n)
Zero a real vector.
real(kind=rp) function, public device_glsc2(a_d, b_d, n)
Weighted inner product .
subroutine, public device_sub3(a_d, b_d, c_d, n)
Vector subtraction .
Device abstraction, common interface for various accelerators.
integer, parameter, public host_to_device
subroutine, public device_free(x_d)
Deallocate memory on the device.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
subroutine, public add2(a, b, n)
Vector addition .
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Defines a function space.
Implements an aggregation for TreeAMG hierarchy structure.
subroutine aggregate_end(tamg, lvl_id)
Aggregate all dofs to a single point to form a tree-like structure.
subroutine aggregate_greedy(tamg, lvl_id, max_aggs, facet_neigh, agg_nhbr)
Aggregates dofs based on adjacent dofs.
subroutine aggregate_finest_level(tamg, lx, ly, lz, ne)
Aggregaiton on finest level Aggregates all dofs in an element into a single aggregate.
Implements multigrid using the TreeAMG hierarchy structure. USE:
subroutine calc_resid(r, x, b, amg, lvl, n)
Wrapper function to calculate residyal.
recursive subroutine tamg_mg_cycle(x, b, n, lvl, amg, mgstuff)
Recrsive multigrid cycle for the TreeAMG solver object.
subroutine tamg_mg_solve_device(this, z, r, z_d, r_d, n)
Solver function for the TreeAMG solver object.
subroutine tamg_mg_init(this, ax, xh, coef, msh, gs_h, nlvls_in, blst, max_iter)
Initialization of the TreeAMG multigrid solver.
subroutine print_preagg_info(lvl, nagg)
subroutine average_duplicates(u, amg, lvl, n)
Wrapper function to gather scatter and average the duplicates.
subroutine fill_lvl_map(amg)
subroutine print_resid_info(r, x, b, r_d, x_d, b_d, amg, lvl, n)
subroutine tamg_mg_solve(this, z, r, n)
Solver function for the TreeAMG solver object.
recursive subroutine tamg_mg_cycle_d(x, b, x_d, b_d, n, lvl, amg, mgstuff)
Recrsive multigrid cycle for the TreeAMG solver object on device.
Implements smoothers for use with TreeAMG matrix vector product.
Implements the base type for TreeAMG hierarchy structure.
subroutine, public tamg_node_init(node, gid, ndofs)
Initialization of a TreeAMG tree node.
subroutine, public tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
Initialization of a TreeAMG level.
Base type for a matrix-vector product providing .
A list of allocatable `bc_t`. Follows the standard interface of lists.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
The function space for the SEM solution fields.
Type for a TreeAMG hierarchy.
Type for the TreeAMG solver.
Type for Chebyshev iteration using TreeAMG matvec.