49 integer :: phase1_naggs
50 integer :: phase1_ndof_aggregated
51 integer :: phase2_naggs
52 integer :: phase2_ndof_aggregated
66 integer,
intent(in) :: lx, ly, lz, ne
67 integer :: i, j, k, l, nl, nt
68 integer :: lid, gid_ptr
78 tamg%lvl(lvl_id)%nodes_ptr(l) = gid_ptr
79 tamg%lvl(lvl_id)%nodes_gid(l) = l
87 tamg%lvl(lvl_id)%nodes(l)%dofs(lid) =
linear_index(i,j,k,l,lx,ly,lz)
89 tamg%lvl(lvl_id)%nodes_dofs(gid_ptr) =
linear_index(i,j,k,l,lx,ly,lz)
90 tamg%lvl(lvl_id)%nodes_gids(gid_ptr) = l
96 tamg%lvl(lvl_id)%nodes_ptr(ne+1) = gid_ptr
112 facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
113 integer,
intent(inout):: naggs
114 integer,
intent(in) :: max_aggs, n_elements
115 integer,
intent(in) :: facet_neigh(:,:)
116 integer,
intent(in) :: offset_el, n_facet
117 integer,
intent(inout) :: is_aggregated(:)
118 integer,
allocatable,
intent(inout) :: aggregate_size(:)
119 integer,
allocatable :: as_tmp(:)
120 real(kind=
dp) :: random_value
121 integer :: i, side, nhbr
122 logical :: no_nhbr_agg
128 if (is_aggregated(i) .eq. -1)
then
132 nhbr = facet_neigh(side, i) - offset_el
133 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
134 if (is_aggregated(nhbr) .ne. -1)
then
135 no_nhbr_agg = .false.
141 if (no_nhbr_agg)
then
143 is_aggregated(i) = naggs
144 if(
size(aggregate_size).lt.naggs)
then
145 allocate(as_tmp(naggs + 20))
146 as_tmp(1:
size(aggregate_size)) = aggregate_size
147 call move_alloc(as_tmp, aggregate_size)
149 aggregate_size(naggs) = 1
151 nhbr = facet_neigh(side, i) - offset_el
152 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
153 if (is_aggregated(nhbr) .eq. -1)
then
154 is_aggregated(nhbr) = naggs
155 aggregate_size(naggs) = aggregate_size(naggs) + 1
175 facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
176 integer,
intent(inout):: naggs
177 integer,
intent(in) :: max_aggs, n_elements
178 integer,
intent(in) :: facet_neigh(:,:)
179 integer,
intent(in) :: offset_el, n_facet
180 integer,
intent(inout) :: is_aggregated(:)
181 integer,
intent(inout) :: aggregate_size(:)
182 integer :: i, side, nhbr
183 integer :: tnt_agg, tst_agg, tnt_size, tst_size
187 if (is_aggregated(i) .eq. -1)
then
194 nhbr = facet_neigh(side, i) - offset_el
195 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
196 if (is_aggregated(nhbr) .ne. -1)
then
197 tst_agg = is_aggregated(nhbr)
198 tst_size = aggregate_size(tst_agg)
199 if (tst_size .lt. tnt_size)
then
207 if (tnt_agg .ne. -1)
then
209 is_aggregated(i) = tnt_agg
210 aggregate_size(tnt_agg) = aggregate_size(tnt_agg) + 1
214 if (naggs .gt.
size(aggregate_size)) then
215 call neko_error(
"Creating too many aggregates... something might be wrong... try increasing max_aggs")
217 is_aggregated(i) = naggs
218 aggregate_size(naggs) = 1
221 nhbr = facet_neigh(side, i) - offset_el
222 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
223 if (is_aggregated(nhbr) .eq. -1)
then
224 aggregate_size(naggs) = aggregate_size(naggs) + 1
225 is_aggregated(nhbr) = naggs
245 facet_neigh, offset_el, n_facet, is_aggregated, aggregate_size)
246 integer,
intent(inout) :: agg_nhbr(:,:)
247 integer,
intent(inout) :: n_agg_nhbr
248 integer,
intent(in) :: n_elements
249 integer,
intent(in) :: facet_neigh(:,:)
250 integer,
intent(in) :: offset_el, n_facet
251 integer,
intent(inout) :: is_aggregated(:)
252 integer,
intent(inout) :: aggregate_size(:)
253 integer :: i, j, side, nhbr, tst_agg, tnt_agg
259 tnt_agg = is_aggregated(i)
261 nhbr = facet_neigh(side,i) - offset_el
262 if ((nhbr .gt. 0).and.(nhbr .le. n_elements)) then
263 tst_agg = is_aggregated(nhbr)
264 if (tst_agg .le. 0)
call neko_error(
"Unaggregated element detected. We do not want to handle that here...")
265 if (tst_agg .ne. tnt_agg)
then
268 if ((agg_nhbr(j,tnt_agg) .eq. tst_agg))
then
270 else if ((agg_nhbr(j,tnt_agg).eq.-1).and.(.not.agg_added))
then
271 agg_nhbr(j,tnt_agg) = tst_agg
273 n_agg_nhbr =
max(n_agg_nhbr, j)
276 if (.not.agg_added)
call neko_error(
"Aggregates have too many neighbors... probably. Or some other error.")
290 type(tamg_hierarchy_t),
intent(inout) :: tamg
291 integer,
intent(in) :: lvl_id
292 integer,
intent(in) :: max_aggs
293 integer,
intent(in) :: facet_neigh(:,:)
294 integer,
intent(inout),
allocatable :: agg_nhbr(:,:)
295 integer,
allocatable :: is_aggregated(:)
296 integer,
allocatable :: aggregate_size(:)
297 integer :: n_elements, naggs, n_facet, offset_el
298 integer :: i, j, l, ntot, n_agg_facet, gid_ptr
300 if (lvl_id .lt. 2)
then
301 call neko_error(
"For now, can only use greedy agg after elms have been aggregated to points (level 1)")
302 else if (lvl_id .eq. 2)
then
304 offset_el = tamg%msh%offset_el
311 n_elements = tamg%lvl(lvl_id-1)%nnodes
312 allocate( is_aggregated( n_elements ) )
313 allocate( aggregate_size( max_aggs ) )
319 aggregate_size = huge(i)
323 facet_neigh, offset_el, n_facet, &
324 is_aggregated, aggregate_size)
330 facet_neigh, offset_el, n_facet, &
331 is_aggregated, aggregate_size)
336 allocate( agg_nhbr(50, max_aggs*2) )
339 facet_neigh, offset_el, n_facet, &
340 is_aggregated, aggregate_size)
346 ntot = ntot + aggregate_size(l)
349 call tamg_lvl_init( tamg%lvl(lvl_id), lvl_id, naggs, ntot)
353 tamg%lvl(lvl_id)%nodes_ptr(l) = gid_ptr
354 tamg%lvl(lvl_id)%nodes_gid(l) = l
355 call tamg_node_init( tamg%lvl(lvl_id)%nodes(l), l, aggregate_size(l))
358 if (is_aggregated(i) .eq. l)
then
360 tamg%lvl(lvl_id)%nodes(l)%dofs(j) = i
362 tamg%lvl(lvl_id)%nodes_dofs(gid_ptr) = i
363 tamg%lvl(lvl_id)%nodes_gids(gid_ptr) = l
364 gid_ptr = gid_ptr + 1
367 if (j .ne. tamg%lvl(lvl_id)%nodes(l)%ndofs)
then
368 call neko_error(
"Aggregation problem. Not enough dofs in node.")
370 ntot = ntot + aggregate_size(l)
372 tamg%lvl(lvl_id)%nodes_ptr(naggs+1) = gid_ptr
376 deallocate( is_aggregated )
377 deallocate( aggregate_size )
384 type(tamg_hierarchy_t),
intent(inout) :: tamg
385 integer,
intent(in) :: lvl_id
388 nt = tamg%lvl(lvl_id-1)%nnodes
390 call tamg_lvl_init( tamg%lvl(lvl_id), lvl_id, 1, nt)
393 call tamg_node_init( tamg%lvl(lvl_id)%nodes(1), 1, nt)
395 do i = 1, tamg%lvl(lvl_id-1)%nnodes
396 tamg%lvl(lvl_id)%nodes(1)%dofs(i) = tamg%lvl(lvl_id-1)%nodes(i)%gid
398 tamg%lvl(lvl_id)%nodes_dofs(i) = tamg%lvl(lvl_id-1)%nodes(i)%gid
399 tamg%lvl(lvl_id)%nodes_gids(i) = 1
402 tamg%lvl(lvl_id)%nodes_ptr(1) = 1
403 tamg%lvl(lvl_id)%nodes_ptr(2) = 2
404 tamg%lvl(lvl_id)%nodes_gid(1) = 1
408 integer,
intent(in) :: lvl,ndof,nagg
409 integer :: na_max, na_min, na_avg, na_sum
410 character(len=LOG_SIZE) :: log_buf
412 write(log_buf,
'(A8,I2,A37)')
'-- level',lvl,
'-- Aggregation: Element-as-Aggregate'
414 call neko_log%message(log_buf)
416 call mpi_allreduce(nagg, na_max, 1, mpi_integer, mpi_max, neko_comm)
417 call mpi_allreduce(nagg, na_min, 1, mpi_integer, mpi_min, neko_comm)
418 call mpi_allreduce(nagg, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
419 na_avg = na_sum / pe_size
420 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1)')
'Number of Aggregates: (',na_min,
',',na_avg,
',',na_max,
')'
421 call neko_log%message(log_buf)
426 integer,
intent(in) :: lvl,ndof,nagg
427 integer,
intent(in) :: is_aggregated(:)
428 integer :: num_aggregated, i, na_max, na_min, na_avg, na_sum
429 real(kind=rp) :: agg_frac
430 integer(kind=i8) :: glb_dof, glb_aggd, loc_dof, loc_aggd
431 character(len=LOG_SIZE) :: log_buf
434 if (is_aggregated(i) .gt. -1)
then
435 num_aggregated = num_aggregated + 1
440 write(log_buf,
'(A27)')
'Aggregation: phase1'
441 call neko_log%message(log_buf)
443 loc_aggd = int(num_aggregated, i8)
444 loc_dof = int(ndof, i8)
445 call mpi_allreduce(loc_dof, glb_dof, 1, mpi_integer8, mpi_sum, neko_comm)
446 call mpi_allreduce(loc_aggd, glb_aggd, 1, mpi_integer8, mpi_sum, neko_comm)
447 agg_frac =
real(glb_aggd,rp) /
real(glb_dof,rp)
449 call mpi_allreduce(nagg, na_max, 1, mpi_integer, mpi_max, neko_comm)
450 call mpi_allreduce(nagg, na_min, 1, mpi_integer, mpi_min, neko_comm)
451 call mpi_allreduce(nagg, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
452 na_avg = na_sum / pe_size
453 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1)')
'Number of Aggregates: (',na_min,
',',na_avg,
',',na_max,
')'
454 call neko_log%message(log_buf)
456 call mpi_allreduce(num_aggregated, na_max, 1, mpi_integer, mpi_max, neko_comm)
457 call mpi_allreduce(num_aggregated, na_min, 1, mpi_integer, mpi_min, neko_comm)
458 call mpi_allreduce(num_aggregated, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
459 na_avg = na_sum / pe_size
460 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1,F6.2)')
'Aggregated: (',na_min,
',',na_avg,
',',na_max,
')',(agg_frac*100)
461 call neko_log%message(log_buf)
465 integer,
intent(in) :: lvl,ndof,nagg
466 integer,
intent(in) :: is_aggregated(:)
467 integer :: num_aggregated, i, na_max, na_min, na_avg, na_sum
468 real(kind=rp) :: agg_frac
469 integer(kind=i8) :: glb_dof, glb_aggd, loc_dof, loc_aggd
470 character(len=LOG_SIZE) :: log_buf
473 if (is_aggregated(i) .gt. -1)
then
474 num_aggregated = num_aggregated + 1
478 write(log_buf,
'(A27)')
'Aggregation: phase2'
479 call neko_log%message(log_buf)
481 loc_aggd = int(num_aggregated, i8)
482 loc_dof = int(ndof, i8)
483 call mpi_allreduce(loc_dof, glb_dof, 1, mpi_integer8, mpi_sum, neko_comm)
484 call mpi_allreduce(loc_aggd, glb_aggd, 1, mpi_integer8, mpi_sum, neko_comm)
485 agg_frac =
real(glb_aggd,rp) /
real(glb_dof,rp)
487 call mpi_allreduce(nagg, na_max, 1, mpi_integer, mpi_max, neko_comm)
488 call mpi_allreduce(nagg, na_min, 1, mpi_integer, mpi_min, neko_comm)
489 call mpi_allreduce(nagg, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
490 na_avg = na_sum / pe_size
491 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1)')
'Number of Aggregates: (',na_min,
',',na_avg,
',',na_max,
')'
492 call neko_log%message(log_buf)
494 call mpi_allreduce(num_aggregated, na_max, 1, mpi_integer, mpi_max, neko_comm)
495 call mpi_allreduce(num_aggregated, na_min, 1, mpi_integer, mpi_min, neko_comm)
496 call mpi_allreduce(num_aggregated, na_sum, 1, mpi_integer, mpi_sum, neko_comm)
497 na_avg = na_sum / pe_size
498 write(log_buf,
'(A35,I6,A1,I6,A1,I6,A1,F6.2)')
'Aggregated: (',na_min,
',',na_avg,
',',na_max,
')',(agg_frac*100)
499 call neko_log%message(log_buf)
503 integer,
intent(in) :: lvl,ndof,nagg
504 character(len=LOG_SIZE) :: log_buf
507 write(log_buf,
'(A26,I6)')
'Aggregation: Done.', nagg
508 call neko_log%message(log_buf)
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
integer, parameter, public dp
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.