Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
tree_amg.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!
35 use num_types, only : rp
36 use utils, only : neko_error
37 use math, only : rzero, col2
40 use coefs, only : coef_t
41 use mesh, only : mesh_t
42 use space, only : space_t
43 use ax_product, only: ax_t
44 use bc_list, only: bc_list_t
45 use gather_scatter, only : gs_t, gs_op_add
49 use, intrinsic :: iso_c_binding
50 implicit none
51 private
52
54 type, private :: tamg_node_t
55 logical :: isleaf = .true.
56 integer :: gid = -1
57 integer :: lvl = -1
58 integer :: ndofs = 0
59 integer, allocatable :: dofs(:)
60 real(kind=rp) :: xyz(3)
61 real(kind=rp), allocatable :: interp_r(:)
62 real(kind=rp), allocatable :: interp_p(:)
63 contains
64 procedure, pass(this) :: free => node_free
65 end type tamg_node_t
66
68 type, private :: tamg_lvl_t
69 integer :: lvl = -1
70 integer :: nnodes = 0
71 type(tamg_node_t), allocatable :: nodes(:)
72 integer :: fine_lvl_dofs = 0
73 real(kind=rp), allocatable :: wrk_in(:)
74 type(c_ptr) :: wrk_in_d = c_null_ptr
75 real(kind=rp), allocatable :: wrk_out(:)
76 type(c_ptr) :: wrk_out_d = c_null_ptr
77 integer, allocatable :: map_finest2lvl(:)
78 type(c_ptr) :: map_finest2lvl_d = c_null_ptr
79 !--!
80 integer, allocatable :: map_f2c(:)
81 type(c_ptr) :: map_f2c_d = c_null_ptr
82 contains
83 procedure, pass(this) :: free => lvl_free
84 end type tamg_lvl_t
85
87 type, public :: tamg_hierarchy_t
89 integer :: nlvls
91 type(tamg_lvl_t), allocatable :: lvl(:)
92
94 class(ax_t), pointer :: ax
95 type(mesh_t), pointer :: msh
96 type(space_t), pointer :: xh
97 type(coef_t), pointer :: coef
98 type(gs_t), pointer :: gs_h
99 type(bc_list_t), pointer :: blst
100
101 contains
102 procedure, pass(this) :: init => tamg_init
103 procedure, pass(this) :: free => tamg_free
104 procedure, pass(this) :: matvec => tamg_matvec
105 procedure, pass(this) :: matvec_impl => tamg_matvec_impl
106 procedure, pass(this) :: interp_f2c => tamg_restriction_operator
107 procedure, pass(this) :: interp_c2f => tamg_prolongation_operator
108 procedure, pass(this) :: interp_f2c_d => tamg_device_restriction_operator
109 procedure, pass(this) :: interp_c2f_d => tamg_device_prolongation_operator
110 procedure, pass(this) :: device_matvec => tamg_device_matvec_flat_impl
111 end type tamg_hierarchy_t
112
114
115contains
116
125 subroutine tamg_init(this, ax, Xh, coef, msh, gs_h, nlvls, blst)
126 class(tamg_hierarchy_t), target, intent(inout) :: this
127 class(ax_t), target, intent(in) :: ax
128 type(space_t),target, intent(in) :: Xh
129 type(coef_t), target, intent(in) :: coef
130 type(mesh_t), target, intent(in) :: msh
131 type(gs_t), target, intent(in) :: gs_h
132 integer, intent(in) :: nlvls
133 type(bc_list_t), target, intent(in) :: blst
134 integer :: i, n
135
136 this%ax => ax
137 this%msh => msh
138 this%Xh => xh
139 this%coef => coef
140 this%gs_h => gs_h
141 this%blst => blst
142
143 if (nlvls .lt. 2) then
144 call neko_error("Need to request at least two multigrid levels.")
145 end if
146
147 this%nlvls = nlvls
148 allocate( this%lvl(this%nlvls) )
149
150 do i = 1, nlvls
151 allocate( this%lvl(i)%map_finest2lvl( 0:coef%dof%size() ))
152 if (neko_bcknd_device .eq. 1) then
153 call device_map(this%lvl(i)%map_finest2lvl, this%lvl(i)%map_finest2lvl_d, coef%dof%size()+1)
154 end if
155 end do
156
157 end subroutine tamg_init
158
160 subroutine tamg_free(this)
161 class(tamg_hierarchy_t), intent(inout) :: this
162 integer :: i
163 if (allocated(this%lvl)) then
164 ! using size() instead of this%nlvls since
165 ! this%nlvls may be less than the allocated number of levels due to early
166 ! termination of aggregation
167 do i = 1, size(this%lvl)
168 call this%lvl(i)%free()
169 end do
170 deallocate(this%lvl)
171 end if
172 nullify(this%ax)
173 nullify(this%msh)
174 nullify(this%Xh)
175 nullify(this%coef)
176 nullify(this%gs_h)
177 nullify(this%blst)
178 end subroutine tamg_free
179
185 subroutine tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
186 type(tamg_lvl_t), intent(inout) :: tamg_lvl
187 integer, intent(in) :: lvl
188 integer, intent(in) :: nnodes
189 integer, intent(in) :: ndofs
190
191 tamg_lvl%lvl = lvl
192 tamg_lvl%nnodes = nnodes
193 allocate( tamg_lvl%nodes(tamg_lvl%nnodes) )
194 allocate( tamg_lvl%map_f2c(0:ndofs) )
195 if (neko_bcknd_device .eq. 1) then
196 call device_map(tamg_lvl%map_f2c, tamg_lvl%map_f2c_d, ndofs+1)
197 end if
198
199 tamg_lvl%fine_lvl_dofs = ndofs
200 allocate( tamg_lvl%wrk_in( ndofs ) )
201 allocate( tamg_lvl%wrk_out( ndofs ) )
202 if (neko_bcknd_device .eq. 1) then
203 call device_map(tamg_lvl%wrk_in, tamg_lvl%wrk_in_d, ndofs)
204 call device_cfill(tamg_lvl%wrk_in_d, 0.0_rp, ndofs)
205 call device_map(tamg_lvl%wrk_out, tamg_lvl%wrk_out_d, ndofs)
206 call device_cfill(tamg_lvl%wrk_out_d, 0.0_rp, ndofs)
207 ! Order the async fills against host writes; on unified memory
208 ! the device pointers may alias the work arrays
209 call device_sync()
210 end if
211 end subroutine tamg_lvl_init
212
214 subroutine lvl_free(this)
215 class(tamg_lvl_t), intent(inout) :: this
216 integer :: i
217
218 if (allocated(this%nodes)) then
219 do i = 1, this%nnodes
220 call this%nodes(i)%free()
221 end do
222 deallocate(this%nodes)
223 end if
224 if (allocated(this%wrk_in)) then
225 if (neko_bcknd_device .eq. 1 .and. c_associated(this%wrk_in_d)) then
226 call device_unmap(this%wrk_in, this%wrk_in_d)
227 end if
228 deallocate(this%wrk_in)
229 end if
230 if (allocated(this%wrk_out)) then
231 if (neko_bcknd_device .eq. 1 .and. c_associated(this%wrk_out_d)) then
232 call device_unmap(this%wrk_out, this%wrk_out_d)
233 end if
234 deallocate(this%wrk_out)
235 end if
236 if (allocated(this%map_f2c)) then
237 if (neko_bcknd_device .eq. 1 .and. c_associated(this%map_f2c_d)) then
238 call device_unmap(this%map_f2c, this%map_f2c_d)
239 end if
240 deallocate(this%map_f2c)
241 end if
242 if (allocated(this%map_finest2lvl)) then
243 if (neko_bcknd_device .eq. 1 .and. c_associated(this%map_finest2lvl_d)) then
244 call device_unmap(this%map_finest2lvl, this%map_finest2lvl_d)
245 end if
246 deallocate(this%map_finest2lvl)
247 end if
248 this%nnodes = 0
249 this%lvl = -1
250 this%fine_lvl_dofs = 0
251 end subroutine lvl_free
252
257 subroutine tamg_node_init(node, gid, ndofs)
258 type(tamg_node_t), intent(inout) :: node
259 integer, intent(in) :: gid
260 integer, intent(in) :: ndofs
261
262 node%gid = gid
263 node%ndofs = ndofs
264 allocate( node%dofs( node%ndofs) )
265 node%dofs = -1
266 allocate( node%interp_r( node%ndofs) )
267 allocate( node%interp_p( node%ndofs) )
268 node%interp_r = 1.0_rp
269 node%interp_p = 1.0_rp
270 end subroutine tamg_node_init
271
273 subroutine node_free(this)
274 class(tamg_node_t), intent(inout) :: this
275
276 if (allocated(this%dofs)) then
277 deallocate(this%dofs)
278 end if
279 if (allocated(this%interp_r)) then
280 deallocate(this%interp_r)
281 end if
282 if (allocated(this%interp_p)) then
283 deallocate(this%interp_p)
284 end if
285 end subroutine node_free
286
293 recursive subroutine tamg_matvec(this, vec_out, vec_in, lvl_out)
294 class(tamg_hierarchy_t), intent(inout) :: this
295 real(kind=rp), intent(inout) :: vec_out(:)
296 real(kind=rp), intent(inout) :: vec_in(:)
297 integer, intent(in) :: lvl_out
298 integer :: i, n, e
299 !call this%matvec_impl(vec_out, vec_in, this%nlvls, lvl_out)
300 call tamg_matvec_flat_impl(this, vec_out, vec_in, this%nlvls, lvl_out)
301 end subroutine tamg_matvec
302
310 recursive subroutine tamg_matvec_impl(this, vec_out, vec_in, lvl, lvl_out)
311 class(tamg_hierarchy_t), intent(inout) :: this
312 real(kind=rp), intent(inout) :: vec_out(:)
313 real(kind=rp), intent(inout) :: vec_in(:)
314 integer, intent(in) :: lvl
315 integer, intent(in) :: lvl_out
316 integer :: i, n, e
317
318 if (lvl .eq. 0) then
320 n = size(vec_in)
322 call this%gs_h%op(vec_in, n, gs_op_add)
323 call col2( vec_in, this%coef%mult, n)
324
325 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
326 call this%gs_h%op(vec_out, n, gs_op_add)
327 call this%blst%apply(vec_out, n)
328
329 if (lvl_out .ne. 0) then
330 call col2(vec_out, this%coef%mult, n)
331 end if
333 else
334 if (lvl_out .ge. lvl) then
337 associate( wrk_in => this%lvl(lvl)%wrk_in, wrk_out => this%lvl(lvl)%wrk_out)
338 n = this%lvl(lvl)%fine_lvl_dofs
339 call rzero(wrk_in, n)
340 call rzero(vec_out, this%lvl(lvl)%nnodes)
341 do n = 1, this%lvl(lvl)%nnodes
342 associate(node => this%lvl(lvl)%nodes(n))
343 do i = 1, node%ndofs
344 wrk_in( node%dofs(i) ) = wrk_in( node%dofs(i) ) + vec_in( node%gid ) * node%interp_p( i )
345 end do
346 end associate
347 end do
348
349 call this%matvec_impl(wrk_out, wrk_in, lvl-1, lvl_out)
350
352 do n = 1, this%lvl(lvl)%nnodes
353 associate(node => this%lvl(lvl)%nodes(n))
354 do i = 1, node%ndofs
355 vec_out( node%gid ) = vec_out(node%gid ) + wrk_out( node%dofs(i) ) * node%interp_r( i )
356 end do
357 end associate
358 end do
359 end associate
360 else if (lvl_out .lt. lvl) then
362 call this%matvec_impl(vec_out, vec_in, lvl-1, lvl_out)
363 else
364 call neko_error("TAMG: matvec level numbering problem.")
365 end if
366 end if
367 end subroutine tamg_matvec_impl
368
369
371 recursive subroutine tamg_matvec_flat_impl(this, vec_out, vec_in, lvl_blah, lvl_out)
372 class(tamg_hierarchy_t), intent(inout) :: this
373 real(kind=rp), intent(inout) :: vec_out(:)
374 real(kind=rp), intent(inout) :: vec_in(:)
375 integer, intent(in) :: lvl_blah
376 integer, intent(in) :: lvl_out
377 integer :: i, n, cdof, lvl
378
379 lvl = lvl_out
380 n = this%lvl(1)%fine_lvl_dofs
381 if (lvl .eq. 0) then
382 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
383 call this%gs_h%op(vec_out, n, gs_op_add)
384 call this%blst%apply(vec_out, n)
385 else
386 associate( wrk_in => this%lvl(1)%wrk_in, wrk_out => this%lvl(1)%wrk_out)
388 do i = 1, n
389 cdof = this%lvl(lvl)%map_finest2lvl(i)
390 wrk_in(i) = vec_in( cdof )
391 end do
392
394 call this%gs_h%op(wrk_in, n, gs_op_add)
395 call col2( wrk_in, this%coef%mult, n)
396 call this%blst%apply(wrk_in, n)
397
399 call this%ax%compute(wrk_out, wrk_in, this%coef, this%msh, this%Xh)
400 call this%gs_h%op(wrk_out, n, gs_op_add)
401 call this%blst%apply(wrk_out, n)
402
403 call col2(wrk_out, this%coef%mult, n)
404
406 call rzero(vec_out, this%lvl(lvl)%nnodes)
407 !$omp parallel do private(cdof)
408 do i = 1, n
409 cdof = this%lvl(lvl)%map_finest2lvl(i)
410 !$omp atomic
411 vec_out(cdof) = vec_out(cdof) + wrk_out( i )
412 end do
413 !$omp end parallel do
414 end associate
415 end if
416 end subroutine tamg_matvec_flat_impl
417
418
419
424 subroutine tamg_restriction_operator(this, vec_out, vec_in, lvl)
425 class(tamg_hierarchy_t), intent(inout) :: this
426 real(kind=rp), intent(inout) :: vec_out(:)
427 real(kind=rp), intent(inout) :: vec_in(:)
428 integer, intent(in) :: lvl
429 integer :: i, n, node_start, node_end, node_id
430
431 vec_out = 0d0
432 if (lvl-1 .eq. 0) then
433 call col2(vec_in, this%coef%mult, this%lvl(lvl)%fine_lvl_dofs)
434 end if
435 do n = 1, this%lvl(lvl)%nnodes
436 associate(node => this%lvl(lvl)%nodes(n))
437 do i = 1, node%ndofs
438 vec_out( node%gid ) = vec_out( node%gid ) + vec_in( node%dofs(i) ) * node%interp_r( i )
439 end do
440 end associate
441 end do
442 end subroutine tamg_restriction_operator
443
448 subroutine tamg_prolongation_operator(this, vec_out, vec_in, lvl)
449 class(tamg_hierarchy_t), intent(inout) :: this
450 real(kind=rp), intent(inout) :: vec_out(:)
451 real(kind=rp), intent(inout) :: vec_in(:)
452 integer, intent(in) :: lvl
453 integer :: i, n, node_start, node_end, node_id
454
455 vec_out = 0d0
456 do n = 1, this%lvl(lvl)%nnodes
457 associate(node => this%lvl(lvl)%nodes(n))
458 do i = 1, node%ndofs
459 vec_out( node%dofs(i) ) = vec_out( node%dofs(i) ) + vec_in( node%gid ) * node%interp_p( i )
460 end do
461 end associate
462 end do
463 if (lvl-1 .eq. 0) then
464 call this%gs_h%op(vec_out, this%lvl(lvl)%fine_lvl_dofs, gs_op_add)
465 call col2(vec_out, this%coef%mult, this%lvl(lvl)%fine_lvl_dofs)
466 call this%blst%apply(vec_out, this%lvl(lvl)%fine_lvl_dofs)
467 end if
468 end subroutine tamg_prolongation_operator
469
470
471 subroutine tamg_device_matvec_flat_impl(this, vec_out, vec_in, vec_out_d, vec_in_d, lvl_out)
472 class(tamg_hierarchy_t), intent(inout) :: this
473 real(kind=rp), intent(inout) :: vec_out(:)
474 real(kind=rp), intent(inout) :: vec_in(:)
475 type(c_ptr) :: vec_out_d
476 type(c_ptr) :: vec_in_d
477 integer, intent(in) :: lvl_out
478 integer :: i, n, cdof, lvl
479
480 lvl = lvl_out
481 n = this%lvl(1)%fine_lvl_dofs
482 if (lvl .eq. 0) then
483 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
484 call this%gs_h%op(vec_out, n, gs_op_add, glb_cmd_event)
485 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
486 call this%blst%apply(vec_out, n)
487 else
488
489 associate( wrk_in_d => this%lvl(1)%wrk_in_d, wrk_out_d => this%lvl(1)%wrk_out_d)
491 call device_masked_gather_copy_0(wrk_in_d, vec_in_d, this%lvl(lvl)%map_finest2lvl_d, this%lvl(lvl)%nnodes, n)
493 call this%gs_h%op(this%lvl(1)%wrk_in, n, gs_op_add, glb_cmd_event)
494 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
495 call device_col2( wrk_in_d, this%coef%mult_d, n)
496 call this%blst%apply(this%lvl(1)%wrk_in, n)
497
499 call this%ax%compute(this%lvl(1)%wrk_out, this%lvl(1)%wrk_in, this%coef, this%msh, this%Xh)
500 call this%gs_h%op(this%lvl(1)%wrk_out, n, gs_op_add, glb_cmd_event)
501 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
502 call this%blst%apply(this%lvl(1)%wrk_out, n)
503
504 call device_col2( wrk_out_d, this%coef%mult_d, n)
505
507 call device_rzero(vec_out_d, this%lvl(lvl)%nnodes)
508 call device_masked_atomic_reduction_0(vec_out_d, wrk_out_d, this%lvl(lvl)%map_finest2lvl_d, this%lvl(lvl)%nnodes, n)
509 end associate
510
511 end if
512 end subroutine tamg_device_matvec_flat_impl
513
514 subroutine tamg_device_restriction_operator(this, vec_out_d, vec_in_d, lvl)
515 class(tamg_hierarchy_t), intent(inout) :: this
516 type(c_ptr) :: vec_out_d
517 type(c_ptr) :: vec_in_d
518 integer, intent(in) :: lvl
519 integer :: i, n, m
520 n = this%lvl(lvl)%nnodes
521 m = this%lvl(lvl)%fine_lvl_dofs
522 if (lvl-1 .eq. 0) then
523 call device_col2(vec_in_d, this%coef%mult_d, m)
524 end if
525 call device_rzero(vec_out_d, n)
526 call device_masked_atomic_reduction_0(vec_out_d, vec_in_d, this%lvl(lvl)%map_f2c_d, n, m)
528
529 subroutine tamg_device_prolongation_operator(this, vec_out_d, vec_in_d, lvl, vec_out)
530 class(tamg_hierarchy_t), intent(inout) :: this
531 real(kind=rp), intent(inout) :: vec_out(:)
532 type(c_ptr) :: vec_out_d
533 type(c_ptr) :: vec_in_d
534 integer, intent(in) :: lvl
535 integer :: i, n, m
536 n = this%lvl(lvl)%nnodes
537 m = this%lvl(lvl)%fine_lvl_dofs
538 call device_masked_gather_copy_0(vec_out_d, vec_in_d, this%lvl(lvl)%map_f2c_d, n, m)
539 if (lvl-1 .eq. 0) then
540 call this%gs_h%op(vec_out, m, gs_op_add, glb_cmd_event)
541 call device_stream_wait_event(glb_cmd_queue, glb_cmd_event, 0)
542 call device_col2( vec_out_d, this%coef%mult_d, m)
543 call this%blst%apply( vec_out, m)
544 end if
546
547end module tree_amg
Map a Fortran array to a device (allocate and associate)
Definition device.F90:83
Synchronize a device or stream.
Definition device.F90:119
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:89
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
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.
Definition device.F90:34
subroutine, public device_stream_wait_event(stream, event, flags)
Synchronize a device stream with an event.
Definition device.F90:1544
type(c_ptr), bind(C), public glb_cmd_queue
Global command queue.
Definition device.F90:52
type(c_ptr), bind(C), public glb_cmd_event
Event for the global command queue.
Definition device.F90:63
Gather-scatter.
Definition math.f90:60
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1046
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
Defines a function space.
Definition space.f90:34
Implements the base type for TreeAMG hierarchy structure.
Definition tree_amg.f90:34
subroutine tamg_device_matvec_flat_impl(this, vec_out, vec_in, vec_out_d, vec_in_d, lvl_out)
Definition tree_amg.f90:472
subroutine tamg_device_prolongation_operator(this, vec_out_d, vec_in_d, lvl, vec_out)
Definition tree_amg.f90:530
subroutine lvl_free(this)
deallocate tamg level
Definition tree_amg.f90:215
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...
Definition tree_amg.f90:311
subroutine, public tamg_node_init(node, gid, ndofs)
Initialization of a TreeAMG tree node.
Definition tree_amg.f90:258
subroutine tamg_restriction_operator(this, vec_out, vec_in, lvl)
Restriction operator for TreeAMG. vec_out = R * vec_in.
Definition tree_amg.f90:425
subroutine tamg_prolongation_operator(this, vec_out, vec_in, lvl)
Prolongation operator for TreeAMG. vec_out = P * vec_in.
Definition tree_amg.f90:449
subroutine node_free(this)
deallocate tamg tree node
Definition tree_amg.f90:274
subroutine, public tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
Initialization of a TreeAMG level.
Definition tree_amg.f90:186
subroutine tamg_free(this)
deallocate tamg hierarchy
Definition tree_amg.f90:161
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...
Definition tree_amg.f90:294
subroutine tamg_device_restriction_operator(this, vec_out_d, vec_in_d, lvl)
Definition tree_amg.f90:515
subroutine tamg_init(this, ax, xh, coef, msh, gs_h, nlvls, blst)
Initialization of TreeAMG hierarchy.
Definition tree_amg.f90:126
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.
Definition tree_amg.f90:372
Utilities.
Definition utils.f90:35
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 storing TreeAMG level information.
Definition tree_amg.f90:68
Type for storing TreeAMG tree node information.
Definition tree_amg.f90:54