diff --git a/psb_zgenaggrmap.f90 b/psb_zgenaggrmap.f90 new file mode 100644 index 00000000..f89b00ca --- /dev/null +++ b/psb_zgenaggrmap.f90 @@ -0,0 +1,292 @@ +!!$ +!!$ +!!$ MD2P4 +!!$ Multilevel Domain Decomposition Parallel Preconditioner Package for PSBLAS +!!$ for +!!$ Parallel Sparse BLAS v2.0 +!!$ (C) Copyright 2006 Salvatore Filippone University of Rome Tor Vergata +!!$ Alfredo Buttari University of Rome Tor Vergata +!!$ Daniela di Serafino Second University of Naples +!!$ Pasqua D'Ambra ICAR-CNR +!!$ +!!$ Redistribution and use in source and binary forms, with or without +!!$ modification, are permitted provided that the following conditions +!!$ are met: +!!$ 1. Redistributions of source code must retain the above copyright +!!$ notice, this list of conditions and the following disclaimer. +!!$ 2. Redistributions in binary form must reproduce the above copyright +!!$ notice, this list of conditions, and the following disclaimer in the +!!$ documentation and/or other materials provided with the distribution. +!!$ 3. The name of the MD2P4 group or the names of its contributors may +!!$ not be used to endorse or promote products derived from this +!!$ software without specific written permission. +!!$ +!!$ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +!!$ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +!!$ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +!!$ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MD2P4 GROUP OR ITS CONTRIBUTORS +!!$ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +!!$ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +!!$ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +!!$ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +!!$ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +!!$ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +!!$ POSSIBILITY OF SUCH DAMAGE. +!!$ +!!$ +subroutine psb_zgenaggrmap(aggr_type,a,desc_a,nlaggr,ilaggr,info) + use psb_base_mod + use psb_prec_type + implicit none + integer, intent(in) :: aggr_type + type(psb_zspmat_type), intent(in) :: a + type(psb_desc_type), intent(in) :: desc_a + integer, allocatable :: ilaggr(:),nlaggr(:) + integer, intent(out) :: info + ! Locals + integer, allocatable :: ils(:), neigh(:) + integer :: icnt,nlp,k,n,ia,isz,nr, naggr,i,j,m + + logical :: recovery + logical, parameter :: debug=.false. + integer ::ictxt,np,me,err_act + integer :: nrow, ncol, n_ne + integer, parameter :: one=1, two=2 + character(len=20) :: name, ch_err + + if(psb_get_errstatus().ne.0) return + info=0 + name = 'psb_bldaggrmat' + call psb_erractionsave(err_act) + ! + ! Note. At the time being we are ignoring aggr_type + ! so that we only have local decoupled aggregation. This might + ! change in the future. + ! + ictxt=psb_cd_get_context(desc_a) + call psb_info(ictxt,me,np) + nrow = psb_cd_get_local_rows(desc_a) + ncol = psb_cd_get_local_cols(desc_a) + + nr = a%m + allocate(ilaggr(nr),neigh(nr),stat=info) + if(info.ne.0) then + info=4000 + call psb_errpush(info,name,a_err=ch_err) + goto 9999 + end if + + do i=1, nr + ilaggr(i) = -(nr+1) + end do + ! Note: -(nr+1) Untouched as yet + ! -i 1<=i<=nr Adjacent to aggregate i + ! i 1<=i<=nr Belonging to aggregate i + + ! + ! Phase one: group nodes together. + ! Very simple minded strategy. + ! + naggr = 0 + nlp = 0 + do + icnt = 0 + do i=1, nr + if (ilaggr(i) == -(nr+1)) then + ! + ! 1. Untouched nodes are marked >0 together + ! with their neighbours + ! + icnt = icnt + 1 + naggr = naggr + 1 + ilaggr(i) = naggr + + call psb_neigh(a,i,neigh,n_ne,info,lev=one) + if (info/=0) then + info=4010 + ch_err='psb_neigh' + call psb_errpush(info,name,a_err=ch_err) + goto 9999 + end if + do k=1, n_ne + j = neigh(k) + if ((1<=j).and.(j<=nr)) then + ilaggr(j) = naggr +!!$ if (ilaggr(j) < 0) ilaggr(j) = naggr +!!$ if (ilaggr(j) == -(nr+1)) ilaggr(j) = naggr + endif + enddo + ! + ! 2. Untouched neighbours of these nodes are marked <0. + ! + call psb_neigh(a,i,neigh,n_ne,info,lev=two) + if (info/=0) then + info=4010 + ch_err='psb_neigh' + call psb_errpush(info,name,a_err=ch_err) + goto 9999 + end if + + do n = 1, n_ne + m = neigh(n) + if ((1<=m).and.(m<=nr)) then + if (ilaggr(m) == -(nr+1)) ilaggr(m) = -naggr + endif + enddo + endif + enddo + nlp = nlp + 1 + if (icnt == 0) exit + enddo + if (debug) then + write(0,*) 'Check 1:',count(ilaggr == -(nr+1)),(a%ia1(i),i=a%ia2(1),a%ia2(2)-1) + end if + + ! + ! Phase two: sweep over leftovers. + ! + allocate(ils(naggr+10),stat=info) + if(info.ne.0) then + info=4000 + call psb_errpush(info,name) + goto 9999 + end if + + do i=1, size(ils) + ils(i) = 0 + end do + do i=1, nr + n = ilaggr(i) + if (n>0) then + if (n>naggr) then + write(0,*) 'loc_Aggregate: n > naggr 1 ? ',n,naggr + else + ils(n) = ils(n) + 1 + end if + + end if + end do + if (debug) then + write(0,*) 'Phase 1: number of aggregates ',naggr + write(0,*) 'Phase 1: nodes aggregated ',sum(ils) + end if + + recovery=.false. + do i=1, nr + if (ilaggr(i) < 0) then + ! + ! Now some silly rule to break ties: + ! Group with smallest adjacent aggregate. + ! + isz = nr+1 + ia = -1 + + call psb_neigh(a,i,neigh,n_ne,info,lev=one) + if (info/=0) then + info=4010 + ch_err='psb_neigh' + call psb_errpush(info,name,a_err=ch_err) + goto 9999 + end if + + do j=1, n_ne + k = neigh(j) + if ((1<=k).and.(k<=nr)) then + n = ilaggr(k) + if (n>0) then + if (n>naggr) then + write(0,*) 'loc_Aggregate: n > naggr 2? ',n,naggr + end if + + if (ils(n) < isz) then + ia = n + isz = ils(n) + endif + endif + endif + enddo + if (ia == -1) then + if (ilaggr(i) > -(nr+1)) then + ilaggr(i) = abs(ilaggr(i)) + if (ilaggr(I)>naggr) then + write(0,*) 'loc_Aggregate: n > naggr 3? ',ilaggr(i),naggr + end if + ils(ilaggr(i)) = ils(ilaggr(i)) + 1 + ! + ! This might happen if the pattern is non symmetric. + ! Need a better handling. + ! + recovery = .true. + else + write(0,*) 'Unrecoverable error !!',ilaggr(i), nr + endif + else + ilaggr(i) = ia + if (ia>naggr) then + write(0,*) 'loc_Aggregate: n > naggr 4? ',ia,naggr + end if + + ils(ia) = ils(ia) + 1 + endif + end if + enddo + if (recovery) then + write(0,*) 'Had to recover from strange situation in loc_aggregate.' + write(0,*) 'Perhaps an unsymmetric pattern?' + endif + if (debug) then + write(0,*) 'Phase 2: number of aggregates ',naggr + write(0,*) 'Phase 2: nodes aggregated ',sum(ils) + do i=1, naggr + write(*,*) 'Size of aggregate ',i,' :',count(ilaggr==i), ils(i) + enddo + write(*,*) maxval(ils(1:naggr)) + write(*,*) 'Leftovers ',count(ilaggr<0), ' in ',nlp,' loops' + end if + +!!$ write(0,*) 'desc_a loc_aggr 4 : ', desc_a%matrix_data(m_) + if (count(ilaggr<0) >0) then + write(0,*) 'Fatal error: some leftovers!!!' + endif + + deallocate(ils,neigh,stat=info) + if (info/=0) then + info=4000 + call psb_errpush(info,name) + goto 9999 + end if + + if (nrow /= size(ilaggr)) then + write(0,*) 'SOmething wrong ilaggr ',nrow,size(ilaggr) + endif + call psb_realloc(ncol,ilaggr,info) + if (info/=0) then + info=4010 + ch_err='psb_realloc' + call psb_errpush(info,name,a_err=ch_err) + goto 9999 + end if + + allocate(nlaggr(np),stat=info) + if (info/=0) then + info=4000 + call psb_errpush(info,name) + goto 9999 + end if + + nlaggr(:) = 0 + nlaggr(me+1) = naggr + call psb_sum(ictxt,nlaggr(1:np)) + + call psb_erractionrestore(err_act) + return + +9999 continue + call psb_erractionrestore(err_act) + if (err_act.eq.act_abort) then + call psb_error() + return + end if + return + +end subroutine psb_zgenaggrmap