39 use mpi_f08,
only : mpi_allreduce, mpi_integer, mpi_integer8, &
40 mpi_min, mpi_max, mpi_sum
51 integer :: phase1_naggs
52 integer :: phase1_ndof_aggregated
53 integer :: phase2_naggs
54 integer :: phase2_ndof_aggregated
68 integer,
intent(in) :: lx, ly, lz, ne
69 integer :: i, j, k, l, nl, nt
70 integer :: lid, gid_ptr
80 tamg%lvl(lvl_id)%nodes_ptr(l) = gid_ptr
81 tamg%lvl(lvl_id)%nodes_gid(l) = l
89 tamg%lvl(lvl_id)%nodes(l)%dofs(lid) =
linear_index(i, j, k, l, &
92 tamg%lvl(lvl_id)%nodes_dofs(gid_ptr) =
linear_index(i,j,k,l,lx,ly,lz)
94 tamg%lvl(lvl_id)%map_f2c(
linear_index(i,j,k,l,lx,ly,lz)) = l
100 tamg%lvl(lvl_id)%nodes_ptr(ne+1) = gid_ptr
116 facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
117 integer,
intent(inout):: naggs
118 integer,
intent(in) :: max_aggs, n_elements
119 integer,
intent(in) :: facet_neigh(:,:)
120 integer,
intent(in) :: offset_el, n_facet
121 integer,
intent(inout) :: is_aggregated(:)
122 integer,
allocatable,
intent(inout) :: aggregate_size(:)
123 integer,
allocatable :: as_tmp(:)
124 real(kind=
dp) :: random_value
125 integer :: i, side, nhbr
126 logical :: no_nhbr_agg
132 if (is_aggregated(i) .eq. -1)
then
136 nhbr = facet_neigh(side, i) - offset_el
137 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
138 if (is_aggregated(nhbr) .ne. -1)
then
139 no_nhbr_agg = .false.
145 if (no_nhbr_agg)
then
147 is_aggregated(i) = naggs
148 if(
size(aggregate_size).lt.naggs)
then
149 allocate(as_tmp(naggs + 20))
150 as_tmp(1:
size(aggregate_size)) = aggregate_size
151 call move_alloc(as_tmp, aggregate_size)
153 aggregate_size(naggs) = 1
155 nhbr = facet_neigh(side, i) - offset_el
156 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
157 if (is_aggregated(nhbr) .eq. -1)
then
158 is_aggregated(nhbr) = naggs
159 aggregate_size(naggs) = aggregate_size(naggs) + 1
179 facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
180 integer,
intent(inout):: naggs
181 integer,
intent(in) :: max_aggs, n_elements
182 integer,
intent(in) :: facet_neigh(:,:)
183 integer,
intent(in) :: offset_el, n_facet
184 integer,
intent(inout) :: is_aggregated(:)
185 integer,
intent(inout) :: aggregate_size(:)
186 integer :: i, side, nhbr
187 integer :: tnt_agg, tst_agg, tnt_size, tst_size
191 if (is_aggregated(i) .eq. -1)
then
198 nhbr = facet_neigh(side, i) - offset_el
199 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
200 if (is_aggregated(nhbr) .ne. -1)
then
201 tst_agg = is_aggregated(nhbr)
202 tst_size = aggregate_size(tst_agg)
203 if (tst_size .lt. tnt_size)
then
211 if (tnt_agg .ne. -1)
then
213 is_aggregated(i) = tnt_agg
214 aggregate_size(tnt_agg) = aggregate_size(tnt_agg) + 1
218 if (naggs .gt.
size(aggregate_size)) then
219 call neko_error(
"Creating too many aggregates... something might be wrong... try increasing max_aggs")
221 is_aggregated(i) = naggs
222 aggregate_size(naggs) = 1
225 nhbr = facet_neigh(side, i) - offset_el
226 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
227 if (is_aggregated(nhbr) .eq. -1)
then
228 aggregate_size(naggs) = aggregate_size(naggs) + 1
229 is_aggregated(nhbr) = naggs
249 facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
250 integer,
intent(inout) :: agg_nhbr(:,:)
251 integer,
intent(inout) :: n_agg_nhbr
252 integer,
intent(in) :: n_elements
253 integer,
intent(in) :: facet_neigh(:,:)
254 integer,
intent(in) :: offset_el, n_facet
255 integer,
intent(inout) :: is_aggregated(:)
256 integer,
intent(inout) :: aggregate_size(:)
257 integer :: i, j, side, nhbr, tst_agg, tnt_agg
263 tnt_agg = is_aggregated(i)
265 nhbr = facet_neigh(side,i) - offset_el
266 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
267 tst_agg = is_aggregated(nhbr)
268 if (tst_agg .le. 0)
call neko_error(
"Unaggregated element detected. We do not want to handle that here...")
269 if (tst_agg .ne. tnt_agg)
then
272 if ((agg_nhbr(j,tnt_agg) .eq. tst_agg))
then
274 else if ((agg_nhbr(j,tnt_agg).eq.-1).and.(.not.agg_added))
then
275 agg_nhbr(j,tnt_agg) = tst_agg
277 n_agg_nhbr =
max(n_agg_nhbr, j)
280 if (.not.agg_added)
call neko_error(
"Aggregates have too many neighbors... probably. Or some other error.")
294 type(tamg_hierarchy_t),
intent(inout) :: tamg
295 integer,
intent(in) :: lvl_id
296 integer,
intent(in) :: max_aggs
297 integer,
intent(in) :: facet_neigh(:,:)
298 integer,
intent(inout),
allocatable :: agg_nhbr(:,:)
299 integer,
allocatable :: is_aggregated(:)
300 integer,
allocatable :: aggregate_size(:)
301 integer :: n_elements, naggs, n_facet, offset_el
302 integer :: i, j, l, ntot, n_agg_facet, gid_ptr
304 if (lvl_id .lt. 2)
then
305 call neko_error(
"For now, can only use greedy agg after elms have been aggregated to points (level 1)")
306 else if (lvl_id .eq. 2)
then
308 offset_el = tamg%msh%offset_el
315 n_elements = tamg%lvl(lvl_id-1)%nnodes
316 allocate( is_aggregated( n_elements ) )
317 allocate( aggregate_size( max_aggs ) )
323 aggregate_size = huge(i)
327 facet_neigh, offset_el, n_facet, &
328 is_aggregated, aggregate_size)
334 facet_neigh, offset_el, n_facet, &
335 is_aggregated, aggregate_size)
340 allocate( agg_nhbr(50, max_aggs*2) )
343 facet_neigh, offset_el, n_facet, &
344 is_aggregated, aggregate_size)
350 ntot = ntot + aggregate_size(l)
353 call tamg_lvl_init( tamg%lvl(lvl_id), lvl_id, naggs, ntot)
357 tamg%lvl(lvl_id)%nodes_ptr(l) = gid_ptr
358 tamg%lvl(lvl_id)%nodes_gid(l) = l
359 call tamg_node_init( tamg%lvl(lvl_id)%nodes(l), l, aggregate_size(l))
362 if (is_aggregated(i) .eq. l)
then
364 tamg%lvl(lvl_id)%nodes(l)%dofs(j) = i
366 tamg%lvl(lvl_id)%nodes_dofs(gid_ptr) = i
368 tamg%lvl(lvl_id)%map_f2c(i) = l
369 gid_ptr = gid_ptr + 1
372 if (j .ne. tamg%lvl(lvl_id)%nodes(l)%ndofs)
then
373 call neko_error(
"Aggregation problem. Not enough dofs in node.")
375 ntot = ntot + aggregate_size(l)
377 tamg%lvl(lvl_id)%nodes_ptr(naggs+1) = gid_ptr
381 deallocate( is_aggregated )
382 deallocate( aggregate_size )
389 type(tamg_hierarchy_t),
intent(inout) :: tamg
390 integer,
intent(in) :: lvl_id
393 nt = tamg%lvl(lvl_id-1)%nnodes
395 call tamg_lvl_init( tamg%lvl(lvl_id), lvl_id, 1, nt)
398 call tamg_node_init( tamg%lvl(lvl_id)%nodes(1), 1, nt)
400 do i = 1, tamg%lvl(lvl_id-1)%nnodes
401 tamg%lvl(lvl_id)%nodes(1)%dofs(i) = tamg%lvl(lvl_id-1)%nodes(i)%gid
403 tamg%lvl(lvl_id)%nodes_dofs(i) = tamg%lvl(lvl_id-1)%nodes(i)%gid
404 tamg%lvl(lvl_id)%map_f2c(i) = 1
407 tamg%lvl(lvl_id)%nodes_ptr(1) = 1
408 tamg%lvl(lvl_id)%nodes_ptr(2) = 2
409 tamg%lvl(lvl_id)%nodes_gid(1) = 1
413 integer,
intent(in) :: lvl,ndof,nagg
414 integer :: na_max, na_min, na_avg, na_sum
415 character(len=LOG_SIZE) :: log_buf
417 write(log_buf,
'(A8,I2,A37)')
'-- level',lvl,
'-- Aggregation: Element-as-Aggregate'
419 call neko_log%message(log_buf)
421 call mpi_allreduce(nagg, na_max, 1, mpi_integer, mpi_max, neko_comm)
422 call mpi_allreduce(nagg, na_min, 1, mpi_integer, mpi_min, neko_comm)
423 call mpi_allreduce(nagg, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
424 na_avg = na_sum / pe_size
425 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1)')
'Number of Aggregates: (',na_min,
',',na_avg,
',',na_max,
')'
426 call neko_log%message(log_buf)
431 integer,
intent(in) :: lvl,ndof,nagg
432 integer,
intent(in) :: is_aggregated(:)
433 integer :: num_aggregated, i, na_max, na_min, na_avg, na_sum
434 real(kind=rp) :: agg_frac
435 integer(kind=i8) :: glb_dof, glb_aggd, loc_dof, loc_aggd
436 character(len=LOG_SIZE) :: log_buf
439 if (is_aggregated(i) .gt. -1)
then
440 num_aggregated = num_aggregated + 1
445 write(log_buf,
'(A27)')
'Aggregation: phase1'
446 call neko_log%message(log_buf)
448 loc_aggd = int(num_aggregated, i8)
449 loc_dof = int(ndof, i8)
450 call mpi_allreduce(loc_dof, glb_dof, 1, mpi_integer8, mpi_sum, neko_comm)
451 call mpi_allreduce(loc_aggd, glb_aggd, 1, mpi_integer8, mpi_sum, neko_comm)
452 agg_frac =
real(glb_aggd,rp) /
real(glb_dof,rp)
454 call mpi_allreduce(nagg, na_max, 1, mpi_integer, mpi_max, neko_comm)
455 call mpi_allreduce(nagg, na_min, 1, mpi_integer, mpi_min, neko_comm)
456 call mpi_allreduce(nagg, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
457 na_avg = na_sum / pe_size
458 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1)')
'Number of Aggregates: (',na_min,
',',na_avg,
',',na_max,
')'
459 call neko_log%message(log_buf)
461 call mpi_allreduce(num_aggregated, na_max, 1, mpi_integer, mpi_max, neko_comm)
462 call mpi_allreduce(num_aggregated, na_min, 1, mpi_integer, mpi_min, neko_comm)
463 call mpi_allreduce(num_aggregated, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
464 na_avg = na_sum / pe_size
465 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1,F6.2)')
'Aggregated: (',na_min,
',',na_avg,
',',na_max,
')',(agg_frac*100)
466 call neko_log%message(log_buf)
470 integer,
intent(in) :: lvl,ndof,nagg
471 integer,
intent(in) :: is_aggregated(:)
472 integer :: num_aggregated, i, na_max, na_min, na_avg, na_sum
473 real(kind=rp) :: agg_frac
474 integer(kind=i8) :: glb_dof, glb_aggd, loc_dof, loc_aggd
475 character(len=LOG_SIZE) :: log_buf
478 if (is_aggregated(i) .gt. -1)
then
479 num_aggregated = num_aggregated + 1
483 write(log_buf,
'(A27)')
'Aggregation: phase2'
484 call neko_log%message(log_buf)
486 loc_aggd = int(num_aggregated, i8)
487 loc_dof = int(ndof, i8)
488 call mpi_allreduce(loc_dof, glb_dof, 1, mpi_integer8, mpi_sum, neko_comm)
489 call mpi_allreduce(loc_aggd, glb_aggd, 1, mpi_integer8, mpi_sum, neko_comm)
490 agg_frac =
real(glb_aggd,rp) /
real(glb_dof,rp)
492 call mpi_allreduce(nagg, na_max, 1, mpi_integer, mpi_max, neko_comm)
493 call mpi_allreduce(nagg, na_min, 1, mpi_integer, mpi_min, neko_comm)
494 call mpi_allreduce(nagg, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
495 na_avg = na_sum / pe_size
496 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1)')
'Number of Aggregates: (',na_min,
',',na_avg,
',',na_max,
')'
497 call neko_log%message(log_buf)
499 call mpi_allreduce(num_aggregated, na_max, 1, mpi_integer, mpi_max, neko_comm)
500 call mpi_allreduce(num_aggregated, na_min, 1, mpi_integer, mpi_min, neko_comm)
501 call mpi_allreduce(num_aggregated, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
502 na_avg = na_sum / pe_size
503 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1,F6.2)')
'Aggregated: (',na_min,
',',na_avg,
',',na_max,
')',(agg_frac*100)
504 call neko_log%message(log_buf)
508 integer,
intent(in) :: lvl,ndof,nagg
509 character(len=LOG_SIZE) :: log_buf
512 write(log_buf,
'(A26,I6)')
'Aggregation: Done.', nagg
513 call neko_log%message(log_buf)
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
integer, public pe_size
MPI size of communicator.
type(mpi_comm), public neko_comm
MPI communicator.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
integer, parameter, public i8
integer, parameter, public dp
integer, parameter, public rp
Global precision used in computations.
Implements an aggregation for TreeAMG hierarchy structure.
subroutine agg_greedy_first_pass(naggs, max_aggs, n_elements, facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
First pass of a greedy aggregation Loop through all dofs and aggregate on dof that has all unaggregat...
subroutine aggregate_end(tamg, lvl_id)
Aggregate all dofs to a single point to form a tree-like structure.
subroutine aggregation_monitor_phase2(lvl, ndof, nagg, is_aggregated)
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.
subroutine aggregation_monitor_final(lvl, ndof, nagg)
subroutine agg_greedy_second_pass(naggs, max_aggs, n_elements, facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
Second pass of a greedy aggregation Loop through all unaggregated dofs and add them to a neighboring ...
subroutine aggregation_monitor_finest(lvl, ndof, nagg)
subroutine agg_fill_nhbr_info(agg_nhbr, n_agg_nhbr, n_elements, facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
Create information on which aggregates are "adjacent" to eachother.
subroutine aggregation_monitor_phase1(lvl, ndof, nagg, is_aggregated)
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.
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Type for a TreeAMG hierarchy.