Neko 0.9.99
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, 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
36 use utils
37 use math
38 use coefs, only : coef_t
39 use mesh, only : mesh_t
40 use space, only : space_t
41 use ax_product, only: ax_t
42 use bc_list, only: bc_list_t
43 use gather_scatter, only : gs_t, gs_op_add
44 implicit none
45 private
46
48 type, private :: tamg_node_t
49 logical :: isleaf = .true.
50 integer :: gid = -1
51 integer :: lvl = -1
52 integer :: ndofs = 0
53 integer, allocatable :: dofs(:)
54 real(kind=rp) :: xyz(3)
55 real(kind=rp), allocatable :: interp_r(:)
56 real(kind=rp), allocatable :: interp_p(:)
57 end type tamg_node_t
58
60 type, private :: tamg_lvl_t
61 integer :: lvl = -1
62 integer :: nnodes = 0
63 type(tamg_node_t), allocatable :: nodes(:)
64 integer :: fine_lvl_dofs = 0
65 real(kind=rp), allocatable :: wrk_in(:)
66 real(kind=rp), allocatable :: wrk_out(:)
67 integer, allocatable :: map_f2c_dof(:)
68 integer, allocatable :: map_c2f_dof(:)
69 !--!
70 integer, allocatable :: nodes_ptr(:)
71 integer, allocatable :: nodes_gid(:)
72 integer, allocatable :: nodes_dofs(:)
73 integer, allocatable :: nodes_gids(:)
74 ! could make another array of the same size of nodes_dofs
75 ! that stores the parent node gid information
76 ! (similar to nodes_gid that stores the gid of each node)
77 ! then some loops can be simplified to a single loop
78 ! of len(nodes_dofs) instead of going through each node
79 ! and looping through nodes_ptr(i) to nodes_ptr(i+1)-1
80 end type tamg_lvl_t
81
83 type, public :: tamg_hierarchy_t
85 integer :: nlvls
87 type(tamg_lvl_t), allocatable :: lvl(:)
88
90 class(ax_t), pointer :: ax
91 type(mesh_t), pointer :: msh
92 type(space_t), pointer :: xh
93 type(coef_t), pointer :: coef
94 type(gs_t), pointer :: gs_h
95 type(bc_list_t), pointer :: blst
96
97 contains
98 procedure, pass(this) :: init => tamg_init
99 procedure, pass(this) :: matvec => tamg_matvec
100 procedure, pass(this) :: matvec_impl => tamg_matvec_impl
101 procedure, pass(this) :: interp_f2c => tamg_restriction_operator
102 procedure, pass(this) :: interp_c2f => tamg_prolongation_operator
103 end type tamg_hierarchy_t
104
106
107contains
108
117 subroutine tamg_init(this, ax, Xh, coef, msh, gs_h, nlvls, blst)
118 class(tamg_hierarchy_t), target, intent(inout) :: this
119 class(ax_t), target, intent(in) :: ax
120 type(space_t),target, intent(in) :: Xh
121 type(coef_t), target, intent(in) :: coef
122 type(mesh_t), target, intent(in) :: msh
123 type(gs_t), target, intent(in) :: gs_h
124 integer, intent(in) :: nlvls
125 type(bc_list_t), target, intent(in) :: blst
126 integer :: i, n
127
128 this%ax => ax
129 this%msh => msh
130 this%Xh => xh
131 this%coef => coef
132 this%gs_h => gs_h
133 this%blst => blst
134
135 if (nlvls .lt. 2) then
136 call neko_error("Need to request at least two multigrid levels.")
137 end if
138
139 this%nlvls = nlvls
140 allocate( this%lvl(this%nlvls) )
141
142 do i = 1, nlvls
143 allocate( this%lvl(i)%map_f2c_dof( coef%dof%size() ))
144 allocate( this%lvl(i)%map_c2f_dof( coef%dof%size() ))
145 end do
146
147 end subroutine tamg_init
148
154 subroutine tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
155 type(tamg_lvl_t), intent(inout) :: tamg_lvl
156 integer, intent(in) :: lvl
157 integer, intent(in) :: nnodes
158 integer, intent(in) :: ndofs
159
160 tamg_lvl%lvl = lvl
161 tamg_lvl%nnodes = nnodes
162 allocate( tamg_lvl%nodes(tamg_lvl%nnodes) )
163 allocate( tamg_lvl%nodes_ptr(tamg_lvl%nnodes+1) )
164 allocate( tamg_lvl%nodes_gid(tamg_lvl%nnodes) )
165 allocate( tamg_lvl%nodes_dofs(ndofs) )
166 allocate( tamg_lvl%nodes_gids(ndofs) )
167
168 tamg_lvl%fine_lvl_dofs = ndofs
169 allocate( tamg_lvl%wrk_in( ndofs ) )
170 allocate( tamg_lvl%wrk_out( ndofs ) )
171 end subroutine tamg_lvl_init
172
177 subroutine tamg_node_init(node, gid, ndofs)
178 type(tamg_node_t), intent(inout) :: node
179 integer, intent(in) :: gid
180 integer, intent(in) :: ndofs
181
182 node%gid = gid
183 node%ndofs = ndofs
184 allocate( node%dofs( node%ndofs) )
185 node%dofs = -1
186 allocate( node%interp_r( node%ndofs) )
187 allocate( node%interp_p( node%ndofs) )
188 node%interp_r = 1.0
189 node%interp_p = 1.0
190 end subroutine tamg_node_init
191
198 recursive subroutine tamg_matvec(this, vec_out, vec_in, lvl_out)
199 class(tamg_hierarchy_t), intent(inout) :: this
200 real(kind=rp), intent(inout) :: vec_out(:)
201 real(kind=rp), intent(inout) :: vec_in(:)
202 integer, intent(in) :: lvl_out
203 integer :: i, n, e
204 call this%matvec_impl(vec_out, vec_in, this%nlvls, lvl_out)
205 !call tamg_matvec_flat_impl(this, vec_out, vec_in, this%nlvls, lvl_out)
206 end subroutine tamg_matvec
207
215 recursive subroutine tamg_matvec_impl(this, vec_out, vec_in, lvl, lvl_out)
216 class(tamg_hierarchy_t), intent(inout) :: this
217 real(kind=rp), intent(inout) :: vec_out(:)
218 real(kind=rp), intent(inout) :: vec_in(:)
219 integer, intent(in) :: lvl
220 integer, intent(in) :: lvl_out
221 integer :: i, n, e
222
223 vec_out = 0d0
224
225 if (lvl .eq. 0) then
227 n = size(vec_in)
229 call this%gs_h%op(vec_in, n, gs_op_add)
230 call col2( vec_in, this%coef%mult(1,1,1,1), n)
232 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
234 call this%gs_h%op(vec_out, n, gs_op_add)
235 call this%blst%apply(vec_out, n)
237 else
238 if (lvl_out .ge. lvl) then
241 associate( wrk_in => this%lvl(lvl)%wrk_in, wrk_out => this%lvl(lvl)%wrk_out)
242 wrk_in = 0d0
243 wrk_out = 0d0
244 do n = 1, this%lvl(lvl)%nnodes
245 associate(node => this%lvl(lvl)%nodes(n))
246 do i = 1, node%ndofs
247 wrk_in( node%dofs(i) ) = wrk_in( node%dofs(i) ) + vec_in( node%gid ) * node%interp_p( i )
248 end do
249 end associate
250 end do
251
252 call this%matvec_impl(wrk_out, wrk_in, lvl-1, lvl_out)
253
255 do n = 1, this%lvl(lvl)%nnodes
256 associate(node => this%lvl(lvl)%nodes(n))
257 do i = 1, node%ndofs
258 vec_out( node%gid ) = vec_out(node%gid ) + wrk_out( node%dofs(i) ) * node%interp_r( i )
259 end do
260 end associate
261 end do
262 end associate
263 else if (lvl_out .lt. lvl) then
265 call this%matvec_impl(vec_out, vec_in, lvl-1, lvl_out)
266 else
267 call neko_error("TAMG: matvec level numbering problem.")
268 end if
269 end if
270 end subroutine tamg_matvec_impl
271
272
274 recursive subroutine tamg_matvec_flat_impl(this, vec_out, vec_in, lvl_blah, lvl_out)
275 class(tamg_hierarchy_t), intent(inout) :: this
276 real(kind=rp), intent(inout) :: vec_out(:)
277 real(kind=rp), intent(inout) :: vec_in(:)
278 integer, intent(in) :: lvl_blah
279 integer, intent(in) :: lvl_out
280 integer :: i, n, cdof, lvl
281
282 lvl = lvl_out
283 if (lvl .eq. 0) then
285 n = size(vec_in)
287 call this%gs_h%op(vec_in, n, gs_op_add)
288 call col2( vec_in, this%coef%mult(1,1,1,1), n)
290 call this%ax%compute(vec_out, vec_in, this%coef, this%msh, this%Xh)
292 call this%gs_h%op(vec_out, n, gs_op_add)
293 call this%blst%apply(vec_out, n)
295 else
296
297 associate( wrk_in => this%lvl(1)%wrk_in, wrk_out => this%lvl(1)%wrk_out)
298 n = size(wrk_in)
299 wrk_out = 0d0
300 vec_out = 0d0
301
303 do i = 1, n
304 cdof = this%lvl(lvl)%map_f2c_dof(i)
305 wrk_in(i) = vec_in( cdof )
306 end do
307
309 call this%gs_h%op(wrk_in, n, gs_op_add)
310 call col2( wrk_in, this%coef%mult(1,1,1,1), n)
312 call this%ax%compute(wrk_out, wrk_in, this%coef, this%msh, this%Xh)
314 call this%gs_h%op(wrk_out, n, gs_op_add)
315 call this%blst%apply(wrk_out, n)
317
319 do i = 1, n
320 cdof = this%lvl(lvl)%map_f2c_dof(i)
321 vec_out(cdof) = vec_out(cdof) + wrk_out( i )
322 end do
323 end associate
324
325 end if
326 end subroutine tamg_matvec_flat_impl
327
328
333 subroutine tamg_restriction_operator(this, vec_out, vec_in, lvl)
334 class(tamg_hierarchy_t), intent(inout) :: this
335 real(kind=rp), intent(inout) :: vec_out(:)
336 real(kind=rp), intent(inout) :: vec_in(:)
337 integer, intent(in) :: lvl
338 integer :: i, n, node_start, node_end, node_id
339
340 vec_out = 0d0
341 do n = 1, this%lvl(lvl)%nnodes
342 associate(node => this%lvl(lvl)%nodes(n))
343 do i = 1, node%ndofs
344 vec_out( node%gid ) = vec_out( node%gid ) + vec_in( node%dofs(i) ) * node%interp_r( i )
345 end do
346 end associate
347 end do
348 !do n = 1, this%lvl(lvl)%nnodes
349 ! node_start = this%lvl(lvl)%nodes_ptr(n)
350 ! node_end = this%lvl(lvl)%nodes_ptr(n+1)-1
351 ! node_id = this%lvl(lvl)%nodes_gid(n)
352 ! do i = node_start, node_end
353 ! vec_out( node_id ) = vec_out( node_id ) + &
354 ! vec_in( this%lvl(lvl)%nodes_dofs(i) )
355 ! end do
356 !end do
357 end subroutine tamg_restriction_operator
358
363 subroutine tamg_prolongation_operator(this, vec_out, vec_in, lvl)
364 class(tamg_hierarchy_t), intent(inout) :: this
365 real(kind=rp), intent(inout) :: vec_out(:)
366 real(kind=rp), intent(inout) :: vec_in(:)
367 integer, intent(in) :: lvl
368 integer :: i, n, node_start, node_end, node_id
369
370 vec_out = 0d0
371 do n = 1, this%lvl(lvl)%nnodes
372 associate(node => this%lvl(lvl)%nodes(n))
373 do i = 1, node%ndofs
374 vec_out( node%dofs(i) ) = vec_out( node%dofs(i) ) + vec_in( node%gid ) * node%interp_p( i )
375 end do
376 end associate
377 end do
378 !do n = 1, this%lvl(lvl)%nnodes
379 ! node_start = this%lvl(lvl)%nodes_ptr(n)
380 ! node_end = this%lvl(lvl)%nodes_ptr(n+1)-1
381 ! node_id = this%lvl(lvl)%nodes_gid(n)
382 ! do i = node_start, node_end
383 ! vec_out( this%lvl(lvl)%nodes_dofs(i) ) = vec_out( this%lvl(lvl)%nodes_dofs(i) ) + &
384 ! vec_in(node_id)
385 ! end do
386 !end do
387 end subroutine tamg_prolongation_operator
388
389end module tree_amg
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
Gather-scatter.
Definition math.f90:60
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:728
Defines a mesh.
Definition mesh.f90:34
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
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:216
subroutine, public tamg_node_init(node, gid, ndofs)
Initialization of a TreeAMG tree node.
Definition tree_amg.f90:178
subroutine tamg_restriction_operator(this, vec_out, vec_in, lvl)
Restriction operator for TreeAMG. vec_out = R * vec_in.
Definition tree_amg.f90:334
subroutine tamg_prolongation_operator(this, vec_out, vec_in, lvl)
Prolongation operator for TreeAMG. vec_out = P * vec_in.
Definition tree_amg.f90:364
subroutine, public tamg_lvl_init(tamg_lvl, lvl, nnodes, ndofs)
Initialization of a TreeAMG level.
Definition tree_amg.f90:155
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:199
subroutine tamg_init(this, ax, xh, coef, msh, gs_h, nlvls, blst)
Initialization of TreeAMG hierarchy.
Definition tree_amg.f90:118
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:275
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:46
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:55
The function space for the SEM solution fields.
Definition space.f90:62
Type for a TreeAMG hierarchy.
Definition tree_amg.f90:83
Type for storing TreeAMG level information.
Definition tree_amg.f90:60
Type for storing TreeAMG tree node information.
Definition tree_amg.f90:48