Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
tree_amg_multigrid.f90
Go to the documentation of this file.
1! Copyright (c) 2024-2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
45 use num_types, only: rp
46 use utils, only : neko_error, neko_warning
47 use math, only : add2, rzero, glsc2, col2, copy, add2s1
50 use comm
51 use mpi_f08, only: mpi_allreduce, mpi_min, mpi_in_place, mpi_integer
52 use coefs, only : coef_t
53 use mesh, only : mesh_t
54 use space, only : space_t
55 use ax_product, only: ax_t
56 use bc_list, only : bc_list_t
57 use gather_scatter, only : gs_t, gs_op_add
63 use logger, only : neko_log, log_size
67 use, intrinsic :: iso_c_binding
68 implicit none
69 private
70
71 type :: tamg_wrk_t
72 integer :: n = -1
73 real(kind=rp), allocatable :: r(:)
74 real(kind=rp), allocatable :: b(:)
75 real(kind=rp), allocatable :: x(:)
76 type(c_ptr) :: r_d = c_null_ptr
77 type(c_ptr) :: b_d = c_null_ptr
78 type(c_ptr) :: x_d = c_null_ptr
79 end type tamg_wrk_t
80
82 type, public :: tamg_solver_t
83 type(tamg_hierarchy_t), allocatable :: amg
84 type(amg_cheby_t), allocatable :: smoo(:)
85 type(tamg_wrk_t), allocatable :: wrk(:)
86 !type(amg_jacobi_t), allocatable :: jsmoo(:)
87 integer :: nlvls
88 integer :: max_iter
89 contains
90 procedure, pass(this) :: init => tamg_mg_init
91 procedure, pass(this) :: solve => tamg_mg_solve
92 procedure, pass(this) :: free => tamg_mg_free
93 procedure, private, pass(this) :: mg_cycle => tamg_mg_cycle
94 procedure, private, pass(this) :: mg_cycle_d => tamg_mg_cycle_d
95 end type tamg_solver_t
96
97contains
98
108 subroutine tamg_mg_init(this, ax, Xh, coef, msh, gs_h, nlvls, blst, &
109 max_iter, cheby_degree)
110 class(tamg_solver_t), intent(inout), target :: this
111 class(ax_t), target, intent(in) :: ax
112 type(space_t), target, intent(in) :: Xh
113 type(coef_t), target, intent(in) :: coef
114 type(mesh_t), target, intent(in) :: msh
115 type(gs_t), target, intent(in) :: gs_h
116 type(bc_list_t), target, intent(in) :: blst
117 integer, intent(in) :: nlvls
118 integer, intent(in) :: max_iter
119 integer, intent(in) :: cheby_degree
120 integer :: lvl, n, mlvl, target_num_aggs
121 integer, allocatable :: agg_nhbr(:,:), nhbr_tmp(:,:)
122 character(len=LOG_SIZE) :: log_buf
123 integer :: glb_min_target_aggs
124 logical :: use_greedy_agg
125
126 call neko_log%section('AMG')
127
128 write(log_buf, '(A28,I2,A8)') 'Creating AMG hierarchy with', &
129 nlvls, 'levels.'
130 call neko_log%message(log_buf)
131
132 allocate( this%amg )
133 call this%amg%init(ax, xh, coef, msh, gs_h, nlvls, blst)
134
135 ! Aggregation
136 use_greedy_agg = .true.
137 ! Create level 1 (neko elements are level 0)
138 call aggregate_finest_level(this%amg, xh%lx, xh%ly, xh%lz, msh%nelv)
139
140 ! Create the remaining levels
141 allocate( agg_nhbr, source = msh%facet_neigh )
142 do mlvl = 2, nlvls-1
143 ! estimate number of aggregates
144 if (use_greedy_agg) then
145 target_num_aggs = this%amg%lvl(mlvl-1)%nnodes / 8
146 else
147 target_num_aggs = this%amg%lvl(mlvl-1)%nnodes / 2
148 end if
149
150 glb_min_target_aggs = target_num_aggs
151 call mpi_allreduce(mpi_in_place, glb_min_target_aggs, 1, &
152 mpi_integer, mpi_min, neko_comm)
153 if (glb_min_target_aggs .lt. 4 ) then
154 call neko_warning( &
155 "TAMG: Too many levels. Not enough DOFs for coarsest grid.")
156 this%amg%nlvls = mlvl
157 exit
158 end if
159
160 if (use_greedy_agg) then
161 call print_preagg_info( mlvl, glb_min_target_aggs, 1)
162 call aggregate_greedy(this%amg, mlvl, target_num_aggs, &
163 agg_nhbr, nhbr_tmp)
164 else
165 call print_preagg_info( mlvl, glb_min_target_aggs, 2)
166 call aggregate_pairs(this%amg, mlvl, target_num_aggs, &
167 agg_nhbr, nhbr_tmp)
168 end if
169
170 agg_nhbr = nhbr_tmp
171 deallocate( nhbr_tmp )
172 end do
173 deallocate( agg_nhbr )
174
175 ! Create the end point
176 call aggregate_end(this%amg, this%amg%nlvls)
177
178 this%max_iter = max_iter
179
180 this%nlvls = this%amg%nlvls
181 if (this%nlvls .gt. this%amg%nlvls) then
182 call neko_error( &
183 "Requested number multigrid levels &
184 & is greater than the initialized AMG levels")
185 end if
186
187 ! Initialize relaxation methods
188 allocate(this%smoo(0:(this%amg%nlvls)))
189 do lvl = 0, this%amg%nlvls-1
190 n = this%amg%lvl(lvl+1)%fine_lvl_dofs
191 call this%smoo(lvl)%init(n, lvl, cheby_degree)
192 end do
193
194 ! Allocate work space on each level
195 allocate(this%wrk(0:(this%amg%nlvls)))
196 do lvl = 0, this%amg%nlvls-1
197 n = this%amg%lvl(lvl+1)%fine_lvl_dofs
198 this%wrk(lvl)%n = n
199 allocate( this%wrk(lvl)%r(n) )
200 allocate( this%wrk(lvl)%b(n) )
201 allocate( this%wrk(lvl)%x(n) )
202 if (neko_bcknd_device .eq. 1) then
203 call device_map( this%wrk(lvl)%r, this%wrk(lvl)%r_d, n)
204 call device_map( this%wrk(lvl)%b, this%wrk(lvl)%b_d, n)
205 call device_map( this%wrk(lvl)%x, this%wrk(lvl)%x_d, n)
206 end if
207 end do
208
209 !allocate(this%jsmoo(0:(this%amg%nlvls)))
210 !do lvl = 0, this%amg%nlvls-1
211 ! n = this%amg%lvl(lvl+1)%fine_lvl_dofs
212 ! call this%jsmoo(lvl)%init(n ,lvl, cheby_degree)
213 !end do
214
215 ! Create index mapping between levels
216 call fill_lvl_map(this%amg)
217
218 call neko_log%end_section()
219
220 end subroutine tamg_mg_init
221
223 subroutine tamg_mg_free(this)
224 class(tamg_solver_t), intent(inout), target :: this
225 integer :: i
226 if (allocated(this%amg)) then
227 call this%amg%free()
228 deallocate(this%amg)
229 end if
230 if (allocated(this%smoo)) then
231 do i = 0, (size(this%smoo)-1)
232 call this%smoo(i)%free()
233 end do
234 deallocate(this%smoo)
235 end if
236 if (allocated(this%wrk)) then
237 do i = 0, (size(this%wrk)-1)
238 if (allocated(this%wrk(i)%r)) then
239 if (neko_bcknd_device .eq. 1 .and. &
240 c_associated(this%wrk(i)%r_d)) then
241 call device_unmap(this%wrk(i)%r, this%wrk(i)%r_d)
242 end if
243 deallocate(this%wrk(i)%r)
244 end if
245 if (allocated(this%wrk(i)%b)) then
246 if (neko_bcknd_device .eq. 1 .and. &
247 c_associated(this%wrk(i)%b_d)) then
248 call device_unmap(this%wrk(i)%b, this%wrk(i)%b_d)
249 end if
250 deallocate(this%wrk(i)%b)
251 end if
252 if (allocated(this%wrk(i)%x)) then
253 if (neko_bcknd_device .eq. 1 .and. &
254 c_associated(this%wrk(i)%x_d)) then
255 call device_unmap(this%wrk(i)%x, this%wrk(i)%x_d)
256 end if
257 deallocate(this%wrk(i)%x)
258 end if
259 end do
260 end if
261 end subroutine tamg_mg_free
262
263
268 subroutine tamg_mg_solve(this, z, r, n)
269 integer, intent(in) :: n
270 class(tamg_solver_t), intent(inout) :: this
271 real(kind=rp), dimension(n), intent(inout) :: z
272 real(kind=rp), dimension(n), intent(inout) :: r
273 type(c_ptr) :: z_d
274 type(c_ptr) :: r_d
275 integer :: iter, max_iter, i
276 logical :: zero_initial_guess
277
278 max_iter = this%max_iter
279
280 if (neko_bcknd_device .eq. 1) then
281 z_d = device_get_ptr(z)
282 r_d = device_get_ptr(r)
283 ! Zero out the initial guess because we do not handle null
284 ! spaces very well...
285 call device_rzero(this%wrk(0)%x_d, n)
286 call device_copy(this%wrk(0)%b_d, r_d, n)
287 zero_initial_guess = .true.
288 ! Call the amg cycle
289 do iter = 1, max_iter
290 call this%mg_cycle_d(zero_initial_guess)
291 zero_initial_guess = .false.
292 end do
293 call device_copy(z_d, this%wrk(0)%x_d, n)
294 else
295 ! Zero out the initial guess becuase we do not handle null spaces
296 ! very well...
297 !OCL NORECURRENCE, NOVREC, NOALIAS
298 !DIR$ CONCURRENT
299 !DIR$ IVDEP
300 !GCC$ ivdep
301 !$omp parallel do
302 do i = 1, n
303 this%wrk(0)%x(i) = 0.0_rp
304 this%wrk(0)%b(i) = r(i)
305 end do
306 !$omp end parallel do
307 zero_initial_guess = .true.
308 ! Call the amg cycle
309 do iter = 1, max_iter
310 call this%mg_cycle(zero_initial_guess)
311 zero_initial_guess = .false.
312 end do
313 call copy(z, this%wrk(0)%x, n)
314 end if
315 end subroutine tamg_mg_solve
316
317
321 subroutine tamg_mg_cycle(this, zero_initial_guess)
322 class(tamg_solver_t), intent(inout), target :: this
323 logical, intent(inout) :: zero_initial_guess
324 character(len=2) :: lvl_name
325 integer :: max_lvl, lvl
326
327 max_lvl = this%nlvls-1
328 ! Loop down hierarchy. Fine to coarse
329 do lvl = 0, max_lvl-1
330 write(lvl_name, '(I0)') lvl
331 call profiler_start_region( "AMG_level_" // trim(lvl_name))
332 associate(x => this%wrk(lvl)%x, b => this%wrk(lvl)%b, &
333 r => this%wrk(lvl)%r, n => this%wrk(lvl)%n)
334 !!----------!!
335 !! SMOOTH !!
336 !!----------!!
337 call this%smoo(lvl)%solve(x, b, n, this%amg, &
338 zero_initial_guess)
339 !!----------!!
340 !! Residual !!
341 !!----------!!
342 call calc_resid(r, x, b, this%amg, lvl, n)
343 !!----------!!
344 !! Restrict !!
345 !!----------!!
346 call this%amg%interp_f2c(this%wrk(lvl+1)%b, r, lvl+1)
347
348 call rzero(this%wrk(lvl+1)%x, this%wrk(lvl+1)%n)
349 zero_initial_guess = .true.
350 end associate
351 call profiler_end_region( "AMG_level_" // trim(lvl_name))
352 end do
353 write(lvl_name, '(I0)') max_lvl
354 call profiler_start_region( "AMG_level_" // trim(lvl_name))
355 !!-------------------!!
356 !! Call Coarse solve !!
357 !!-------------------!!
358 call this%smoo(max_lvl)%solve(this%wrk(max_lvl)%x, &
359 this%wrk(max_lvl)%b, this%amg%lvl(max_lvl)%nnodes, this%amg, &
360 zero_initial_guess)
361 call profiler_end_region( "AMG_level_" // trim(lvl_name))
362
363 zero_initial_guess = .false.
364 ! Loop up hierarchy. Coarse to fine
365 do lvl = max_lvl-1, 0, -1
366 write(lvl_name, '(I0)') lvl
367 call profiler_start_region( "AMG_level_" // trim(lvl_name))
368 associate(x => this%wrk(lvl)%x, b => this%wrk(lvl)%b, &
369 r => this%wrk(lvl)%r, n => this%wrk(lvl)%n)
370 !!----------!!
371 !! Project !!
372 !!----------!!
373 call this%amg%interp_c2f(r, this%wrk(lvl+1)%x, lvl+1)
374 !!----------!!
375 !! Correct !!
376 !!----------!!
377 call add2(x, r, n)
378 !!----------!!
379 !! SMOOTH !!
380 !!----------!!
381 call this%smoo(lvl)%solve(x, b, n, this%amg)
382 end associate
383 call profiler_end_region( "AMG_level_" // trim(lvl_name))
384 end do
385 end subroutine tamg_mg_cycle
386
390 subroutine tamg_mg_cycle_d(this, zero_initial_guess)
391 class(tamg_solver_t), intent(inout), target :: this
392 logical, intent(inout) :: zero_initial_guess
393 character(len=2) :: lvl_name
394 integer :: max_lvl, lvl
395
396 max_lvl = this%nlvls-1
397 ! Loop down hierarchy. Fine to coarse
398 do lvl = 0, max_lvl-1
399 write(lvl_name, '(I0)') lvl
400 call profiler_start_region( "AMG_level_" // trim(lvl_name))
401 associate(x => this%wrk(lvl)%x, x_d => this%wrk(lvl)%x_d, &
402 b => this%wrk(lvl)%b, b_d => this%wrk(lvl)%b_d, &
403 r => this%wrk(lvl)%r, r_d => this%wrk(lvl)%r_d, &
404 n => this%wrk(lvl)%n)
405 !!----------!!
406 !! SMOOTH !!
407 !!----------!!
408 call this%smoo(lvl)%device_solve(x, b, x_d, b_d, n, this%amg, &
409 zero_initial_guess)
410 !!----------!!
411 !! Residual !!
412 !!----------!!
413 call this%amg%device_matvec(r, x, r_d, x_d, lvl)
414 call device_sub3(r_d, b_d, r_d, n)
415 !!----------!!
416 !! Restrict !!
417 !!----------!!
418 call this%amg%interp_f2c_d(this%wrk(lvl+1)%b_d, r_d, lvl+1)
419
420 call device_rzero(this%wrk(lvl+1)%x_d, this%wrk(lvl+1)%n)
421 zero_initial_guess = .true.
422 end associate
423 call profiler_end_region( "AMG_level_" // trim(lvl_name))
424 end do
425 write(lvl_name, '(I0)') max_lvl
426 call profiler_start_region( "AMG_level_" // trim(lvl_name))
427 !!-------------------!!
428 !! Call Coarse solve !!
429 !!-------------------!!
430 call this%smoo(max_lvl)%device_solve( &
431 this%wrk(max_lvl)%x, this%wrk(max_lvl)%b, &
432 this%wrk(max_lvl)%x_d, this%wrk(max_lvl)%b_d, &
433 this%amg%lvl(max_lvl)%nnodes, this%amg, &
434 zero_initial_guess)
435 call profiler_end_region( "AMG_level_" // trim(lvl_name))
436
437 zero_initial_guess = .false.
438 ! Loop up hierarchy. Coarse to fine
439 do lvl = max_lvl-1, 0, -1
440 write(lvl_name, '(I0)') lvl
441 call profiler_start_region( "AMG_level_" // trim(lvl_name))
442 associate(x => this%wrk(lvl)%x, x_d => this%wrk(lvl)%x_d, &
443 b => this%wrk(lvl)%b, b_d => this%wrk(lvl)%b_d, &
444 r => this%wrk(lvl)%r, r_d => this%wrk(lvl)%r_d, &
445 n => this%wrk(lvl)%n)
446 !!----------!!
447 !! Project !!
448 !!----------!!
449 call this%amg%interp_c2f_d(r_d, this%wrk(lvl+1)%x_d, lvl+1, r)
450 !!----------!!
451 !! Correct !!
452 !!----------!!
453 call device_add2(x_d, r_d, n)
454 !!----------!!
455 !! SMOOTH !!
456 !!----------!!
457 call this%smoo(lvl)%device_solve(x, b, x_d, b_d, n, this%amg)
458 end associate
459 call profiler_end_region( "AMG_level_" // trim(lvl_name))
460 end do
461 end subroutine tamg_mg_cycle_d
462
463
471 subroutine calc_resid(r, x, b, amg, lvl, n)
472 integer, intent(in) :: n
473 real(kind=rp), intent(inout) :: r(n)
474 real(kind=rp), intent(inout) :: x(n)
475 real(kind=rp), intent(inout) :: b(n)
476 type(tamg_hierarchy_t), intent(inout) :: amg
477 integer, intent(in) :: lvl
478 integer :: i
479 call amg%matvec(r, x, lvl)
480 call add2s1(r, b, -1.0_rp, n)
481 end subroutine calc_resid
482
483
484 subroutine print_preagg_info(lvl, nagg, agg_type)
485 integer, intent(in) :: lvl, nagg, agg_type
486 character(len=LOG_SIZE) :: log_buf
487 !TODO: calculate min and max agg size
488 if (agg_type .eq. 1) then
489 write(log_buf, '(A8,I2,A31)') '-- level', lvl, &
490 '-- Calling Greedy Aggregation'
491 else if (agg_type .eq. 2) then
492 write(log_buf, '(A8,I2,A33)') '-- level', lvl, &
493 '-- Calling Pairwise Aggregation'
494 else
495 write(log_buf, '(A8,I2,A31)') '-- level', lvl, &
496 '-- UNKNOWN Aggregation'
497 end if
498 call neko_log%message(log_buf)
499 write(log_buf, '(A33,I6)') 'Target Aggregates:', nagg
500 call neko_log%message(log_buf)
501 end subroutine print_preagg_info
502
503 subroutine print_resid_info(r, x, b, r_d, x_d, b_d, amg, lvl, n)
504 integer, intent(in) :: lvl, n
505 real(kind=rp), intent(inout) :: r(n)
506 real(kind=rp), intent(inout) :: x(n)
507 real(kind=rp), intent(inout) :: b(n)
508 type(c_ptr) :: r_d
509 type(c_ptr) :: x_d
510 type(c_ptr) :: b_d
511 type(tamg_hierarchy_t), intent(inout) :: amg
512 real(kind=rp) :: val
513 character(len=LOG_SIZE) :: log_buf
514
515 call amg%device_matvec(r, x, r_d, x_d, lvl)
516 call device_sub3(r_d, b_d, r_d, n)
517 val = device_glsc2(r_d, r_d, n)
518
519 write(log_buf, '(A33,I6,F12.6)') 'tAMG resid:', lvl, val
520 call neko_log%message(log_buf)
521 end subroutine print_resid_info
522
525 subroutine fill_lvl_map(amg)
526 type(tamg_hierarchy_t), intent(inout) :: amg
527 integer :: i, j, k, l, nid, n
528 do j = 1, amg%lvl(1)%nnodes
529 do k = 1, amg%lvl(1)%nodes(j)%ndofs
530 nid = amg%lvl(1)%nodes(j)%dofs(k)
531 amg%lvl(1)%map_finest2lvl(nid) = amg%lvl(1)%nodes(j)%gid
532 end do
533 end do
534 n = size(amg%lvl(1)%map_finest2lvl)
535 do l = 2, amg%nlvls
536 do i = 1, n
537 nid = amg%lvl(l-1)%map_finest2lvl(i)
538 do j = 1, amg%lvl(l)%nnodes
539 do k = 1, amg%lvl(l)%nodes(j)%ndofs
540 if (nid .eq. amg%lvl(l)%nodes(j)%dofs(k)) then
541 amg%lvl(l)%map_finest2lvl(i) = amg%lvl(l)%nodes(j)%gid
542 end if
543 end do
544 end do
545 end do
546 end do
547 if (neko_bcknd_device .eq. 1) then
548 do l = 1, amg%nlvls
549 amg%lvl(l)%map_finest2lvl(0) = n
550 call device_memcpy( amg%lvl(l)%map_finest2lvl, &
551 amg%lvl(l)%map_finest2lvl_d, n, &
552 host_to_device, .true.)
553 call device_memcpy( amg%lvl(l)%map_f2c, &
554 amg%lvl(l)%map_f2c_d, amg%lvl(l)%fine_lvl_dofs+1, &
555 host_to_device, .true.)
556 end do
557 end if
558 end subroutine fill_lvl_map
559end module tree_amg_multigrid
__device__ T solve(const T u, const T y, const T guess, const T nu, const T kappa, const T B)
Return the device pointer for an associated Fortran array.
Definition device.F90:108
Map a Fortran array to a device (allocate and associate)
Definition device.F90:78
Copy data between host and device (or device and device)
Definition device.F90:72
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:84
Defines a Matrix-vector product.
Definition ax.f90:34
Defines a list of bc_t.
Definition bc_list.f90:34
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
subroutine, public device_sub3(a_d, b_d, c_d, n, strm)
Vector subtraction .
subroutine, public device_add2(a_d, b_d, n, strm)
Vector addition .
subroutine, public device_rzero(a_d, n, strm)
Zero a real vector.
subroutine, public device_copy(a_d, b_d, n, strm)
Copy a vector .
subroutine, public device_col2(a_d, b_d, n, strm)
Vector multiplication .
real(kind=rp) function, public device_glsc2(a_d, b_d, n, strm)
Weighted inner product .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
Gather-scatter.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public add2s1(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
Definition math.f90:981
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
Definition math.f90:1266
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:900
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1046
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:291
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:235
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Profiling interface.
Definition profiler.F90:34
subroutine, public profiler_start_region(name, region_id)
Started a named (name) profiler region.
Definition profiler.F90:79
subroutine, public profiler_end_region(name, region_id)
End the most recently started profiler region.
Definition profiler.F90:116
Defines a function space.
Definition space.f90:34
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_pairs(tamg, lvl_id, max_aggs, facet_neigh, agg_nhbr)
Aggregates pairs of dofs based on adjacent dofs.
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.
subroutine tamg_mg_cycle_d(this, zero_initial_guess)
multigrid cycle for the TreeAMG solver object on device
subroutine tamg_mg_free(this)
free tree amg solver object
subroutine fill_lvl_map(amg)
Create index mapping between levels and directly to finest level.
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.
subroutine tamg_mg_cycle(this, zero_initial_guess)
multigrid cycle for the TreeAMG solver object
subroutine print_preagg_info(lvl, nagg, agg_type)
subroutine tamg_mg_init(this, ax, xh, coef, msh, gs_h, nlvls, blst, max_iter, cheby_degree)
Initialization of the TreeAMG multigrid solver.
Implements smoothers for use with TreeAMG matrix vector product.
Implements the base type for TreeAMG hierarchy structure.
Definition tree_amg.f90:34
subroutine, public tamg_node_init(node, gid, ndofs)
Initialization of a TreeAMG tree node.
Definition tree_amg.f90:255
subroutine, public tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
Initialization of a TreeAMG level.
Definition tree_amg.f90:186
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
Base type for a matrix-vector product providing .
Definition ax.f90:43
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
Gather-scatter kernel.
The function space for the SEM solution fields.
Definition space.f90:64
Type for a TreeAMG hierarchy.
Definition tree_amg.f90:87
Type for the TreeAMG solver.
Type for Chebyshev iteration using TreeAMG matvec.