!=============================================================================== ! SVN $Id: mapsort_mod.F90 35698 2012-03-22 23:59:57Z kauff $ ! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/tools/mapping/trunk_tags/mapping_121113b/gen_mapping_files/runoff_to_ocn/src/mapsort_mod.F90 $ !=============================================================================== MODULE mapsort_mod use shr_sys_mod use shr_timer_mod use kind_mod use map_mod implicit none private ! default private public :: mapsort_checkSort ! checks if map matrix is properly sorted public :: mapsort_sort ! sort the map interface mapsort_sort; module procedure mapsort_byrow; end interface integer(IN),parameter :: debug = 1 !=============================================================================== CONTAINS !=============================================================================== SUBROUTINE mapsort_checkSort(map,rowOK,colOK) implicit none !--- arguments --- type(sMatrix), intent(inout) :: map logical,optional,intent(out) :: rowOK,colOK !--- local --- integer(IN) :: n logical :: sorted !--- formats --- character(*),parameter :: subName = "(mapsort_checkSort) " character(*),parameter :: F00 = "('(mapsort_checkSort) ',8a)" !------------------------------------------------------------------------------- ! PURPOSE: ! o checks whether elements of an sMatrix are properly sorted !------------------------------------------------------------------------------- !--- are rows monotonically increasing? --- sorted = .true. do n=1,map%n_s-1 if (map%row(n) > map%row(n+1) ) sorted = .false. enddo if ( sorted ) write(6,F00) "VERIFIED: rows are monotonically increasing" if (.not. sorted ) write(6,F00) "WARNING : rows are not monotonically increasing" if (present(rowOK)) rowOK = sorted !--- for a given row, are cols monotonically increasing? --- sorted = .true. do n=1,map%n_s-1 if ((map%row(n) == map%row(n+1)) .and. (map%col(n) > map%col(n+1))) sorted = .false. enddo if ( sorted ) write(6,F00) "VERIFIED: cols are monotonically increasing" if (.not. sorted ) write(6,F00) "WARNING : cols are not monotonically increasing" if (present(colOK)) colOK = sorted END SUBROUTINE mapsort_checkSort !=============================================================================== !=============================================================================== SUBROUTINE mapsort_byrow(map) implicit none !--- arguments --- type(sMatrix), intent(inout) :: map !--- local --- integer(IN) :: i,j ! index into 2d matrix S(i,j) integer(IN) :: n ! index into 1d vector S(n) integer(IN) :: k ! index into tempS(i,k) = S(i,j) where j = tempCol(n,k) integer(IN) :: na,nb ! size of uncompressed matrix nb*na integer(IN) :: ns ! size of compressed matrix real (R8),allocatable :: tempS (:,:) ! matrix elements in temp non-standard format integer(IN),allocatable :: tempCol(:,:) ! matrix columns in temp non-standard format integer(IN),allocatable :: nCols ( :) ! number of active cols in each row of tempS(i,k) integer(IN) :: kMax ! size of k dim allocated/available in tempS(i,k) integer(IN) :: count ! counts occurances of things for debugging logical :: noSwap ! flags col swapping when col sorting integer(IN) :: nMin ,nMax ! integer(IN) :: nMin2,nMax2 ! integer(IN) :: nMin0 ! integer(IN),parameter :: nMod=100000 ! for debug info integer(IN) :: iTmp ! temp var for col sorting real (R8) :: rTmp ! temp var for col sorting logical :: done ! col sorting is complete integer(IN) :: nNew ! new S(n) index wrt combining duplicate i/j character( 8) :: dstr ! wall clock date character(10) :: tstr ! wall clock time #ifdef _OPENMP integer(IN) :: omp_get_max_threads ! $OMP function call #endif !--- formats --- character(*),parameter :: subName = '(mapsort_byrow) ' character(*),parameter :: F00 = "('(mapsort_byrow) ',8a)" character(*),parameter :: F01 = "('(mapsort_byrow) ',a,4i11)" character(*),parameter :: F12 = "('(mapsort_byrow) date & time:',1x,a4,2('-',a2),2x,a2,2(':',a2))" !------------------------------------------------------------------------------- ! PURPOSE: ! sort all elements of S so that row(n) <= row(n+1) ! and if row(n) == row(n+1), then col(n) <= col(n+1) !------------------------------------------------------------------------------- ns = map%n_s na = map%n_a nb = map%n_b write(6,F01) "na, nb, ns = ",map%n_a,map%n_b,map%n_s write(6,F01) "min/max row = ",minval(map%row),maxval(map%row) write(6,F01) "min/max col = ",minval(map%col),maxval(map%col) !---------------------------------------------------------------------------- write(6,F00) "fill a temp matrix (non-standard format) with row-sorted data" !---------------------------------------------------------------------------- call date_and_time(dstr,tstr) write(6,F12) dstr(1:4),dstr(5:6),dstr(7:8) ,tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) !--- determine how big temp matrix must be, allocate temp matrix --- allocate(nCols(nb)) nCols = 0 kMax = 0 do n=1,ns i = map%row(n) nCols(i) = nCols(i)+1 kMax = max(kMax,nCols(i)) end do write(6,F01) "max number of cols per row = ",kMax allocate(tempS (nb,kMax)) allocate(tempCol(nb,kMax)) !--- fill the temp matrix arrays with data --- nCols = 0 do n=1,ns if (debug > 0 .and. mod(n,nMod) == 0) then write(6,F01) "... working, max elements, current element = ",ns,n call shr_sys_flush(6) endif i = map%row(n) ! s(n) belongs in row i k = nCols(i)+1 ! s(n) is k-th non-zero element in row i if (nCols(i) > kMax) then write(6,F01) "ERROR: temp S,col arrays not large enough, kMax = ",kMax call shr_sys_abort() endif nCols (i) = k ! number of elements in row i tempCol(i,k) = map%col(n) ! associated col tempS (i,k) = map%s (n) ! matrix element end do !---------------------------------------------------------------------------- write(6,F00) "fill a input/output matrix with row-sorted data" !---------------------------------------------------------------------------- call date_and_time(dstr,tstr) write(6,F12) dstr(1:4),dstr(5:6),dstr(7:8) ,tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) n = 0 do i=1,nb do k=1,nCols(i) n = n+1 map%row(n) = i map%col(n) = tempCol(i,k) map%s (n) = tempS (i,k) end do end do deallocate(nCols,tempS,tempCol) call mapsort_checkSort(map) ! confirm rows are sorted !---------------------------------------------------------------------------- write(6,F00) "sort columns within each row (assumes rows are sorted)" !---------------------------------------------------------------------------- call date_and_time(dstr,tstr) write(6,F12) dstr(1:4),dstr(5:6),dstr(7:8) ,tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) call map_Sn1(map) ! determine where rows begin & end in s(n) #ifdef _OPENMP n = omp_get_max_threads() write(6,F01) 'FYI: this routine is threaded, omp_get_max_threads() = ',n #else write(6,F00) 'FYI: this routine is not threaded' #endif !$OMP PARALLEL DO PRIVATE(i,done,n,nMin,nMax,nMin0,nMin2,nMax2,iTmp,rTmp,noSwap,dstr,tstr) do i=1,nb if (debug > 0 .and. mod(i,nMod) == 0) then write(6,F01) "... working on row ",i call date_and_time(dstr,tstr) write(6,F12) dstr(1:4),dstr(5:6),dstr(7:8) ,tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) endif nMin0 = map%sn2(i) + 1 ! 1st element in row i nMin = nMin0 ! 1st potentially out-of-order element in row i nMax = map%sn2(i) + map%sn1(i) ! last potentially out-of-order element in row i done = .false. do while ( .not. done ) noSwap = .true. do n=nMin,nMax-1 ! all elements should be in the same row ! if (map%row(n) == map%row(n+1) .and. map%col(n) > map%col(n+1)) then if (map%col(n) > map%col(n+1)) then !--- swap adjacent out-of-order columns (within same row) --- iTmp = map%col(n+1) map%col(n+1) = map%col(n) map%col(n) = iTmp rTmp = map%s(n+1) map%s(n+1) = map%s(n) map%s(n) = rTmp !--- note subset of out-of-order elements --- if (noSwap) then ! 1st swap nMin2 = max(n-1,nMin0) noSwap = .false. end if nMax2=n ! last swap endif enddo if (noSwap) then done = .true. else ! narrow the search nMin=nMin2 ! 1st potentially out-of-order element nMax=nMax2 ! last potentially out-of-order element endif enddo end do call mapsort_checkSort(map) ! confirm cols are sorted !---------------------------------------------------------------------------- write(6,F00) "combine elements with same row/col (assumes matrix is sorted)" !---------------------------------------------------------------------------- call date_and_time(dstr,tstr) write(6,F12) dstr(1:4),dstr(5:6),dstr(7:8) ,tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) write(6,F01) "... orig size of S = ",map%n_s i = 0 j = 0 nNew = 0 count = 0 do n=1,map%n_s if (map%row(n) == i .and. map%col(n) == j) then !--- same i,j as previous element => combine them --- count = count + 1 map%s(nNew) = map%s(nNew) + map%s(n) else !--- different i,j from previous element => don't combine --- nNew = nNew + 1 map%row(nNew) = map%row(n) map%col(nNew) = map%col(n) map%s (nNew) = map%s (n) i = map%row(n) j = map%col(n) endif enddo map%n_s = nNew write(6,F01) "... new size of S = ",map%n_s write(6,F01) "... number of duplicate row/col = ",count call map_Sn1(map) ! determine where rows begin & end in s(n) write(6,F00) "Done." call date_and_time(dstr,tstr) write(6,F12) dstr(1:4),dstr(5:6),dstr(7:8) ,tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) END SUBROUTINE mapsort_byrow !=============================================================================== !=============================================================================== SUBROUTINE mapsort_sortMatRC(map) implicit none !--- arguments --- type(sMatrix), intent(inout) :: map !--- local --- integer(IN) :: i,m,n logical :: rowOK,colOK integer(IN) :: t01 = 0 ! system-clock-timer number #ifdef _OPENMP integer(IN) :: omp_get_max_threads ! $OMP function call #endif character(8) :: dstr ! F90 wall clock date string yyyymmdd character(10) :: tstr ! F90 wall clock time string hhmmss.sss !--- formats --- character(*),parameter :: subName = "(mapsort_sortMatRC) " character(*),parameter :: F00 = "('(mapsort_sortMatRC) ',8a)" character(*),parameter :: F01 = "('(mapsort_sortMatRC) ',a,4i11)" character(*),parameter :: F10 = "('(mapsort_sortMatRC) ',a,i7, & & ' date & time:',1x, & & a4,2('-',a2),2x,a2,2(':',a2))" !------------------------------------------------------------------------------- ! PURPOSE: ! o sorts the elements of an sMatrix to achieve uniformly increasing columns ! within each given row ! o assumes the elements of an sMatrix already have uniformly increasing rows !------------------------------------------------------------------------------- write(6,F01) "sort matrix, size = ",map%n_s if (t01 == 0) call shr_timer_get(t01,subName//"sort matrix") !---------------------------------------------------------------------------- !check for correct row/column sorting !---------------------------------------------------------------------------- call mapsort_checkSort(map) !---------------------------------------------------------------------------- ! sort entire matrix !---------------------------------------------------------------------------- write(6,F00) "sort entire matrix" call shr_timer_zero (t01) call shr_timer_start(t01) call date_and_time(dstr,tstr) ! F90 intrinsic routine write(6,F10) 'i=',0,dstr(1:4),dstr(5:6),dstr(7:8),tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) n = 1 m = map%n_s call mapsort_qsortRC(map%s(n:m),map%row(n:m),map%col(n:m)) call shr_timer_stop(t01) call shr_timer_print(t01) !---------------------------------------------------------------------------- ! verify matrix has been properly sorted !---------------------------------------------------------------------------- call mapsort_checkSort(map,rowOK=rowOK,colOK=colOK) if (.not. rowOK ) write(6,F00) "ERROR: rows are NOT monotonically increasing" if (.not. colOK ) write(6,F00) "ERROR: cols are NOT monotonically increasing" if (.not. colOK .or. .not. rowOK) stop END SUBROUTINE mapsort_sortMatRC !=============================================================================== !=============================================================================== recursive SUBROUTINE mapsort_qsortRC(S,row,col) implicit none !--- arguments --- real (R8) :: S(:) integer(IN) :: row(:),col(:) !--- local --- integer(IN) :: ns ! size of data array to sort integer(IN) :: m ! marker that divides data array into two !--- formats --- character(*),parameter :: F00 = "('(mapsort_qsortRC) ',8a)" character(*),parameter :: F01 = "('(mapsort_qsortRC) ',a,5i6)" !------------------------------------------------------------------------------- ! PURPOSE: ! sort all elements of S so that col(n) is strickly increasing ! assumes that row(n) is a constant (ie. row(n) = row(m) for every n,m) !------------------------------------------------------------------------------- ns = size(S) if ( ns > 1) then call mapsort_partitianRC(S,row,col,m) call mapsort_qsortRC (S(1:m-1),row(1:m-1),col(1:m-1)) call mapsort_qsortRC (S(m:ns ),row(m:ns ),col(m:ns )) end if END SUBROUTINE mapsort_qsortRC !=============================================================================== !=============================================================================== SUBROUTINE mapsort_partitianRC(S,row,col,marker) implicit none !--- arguments --- real (R8) :: S(:) ! must rearrange along with col values integer(IN) :: row(:) ! unused: assumed constant integer(IN) :: col(:) ! sort wrt column value integer(IN) :: marker ! partitian wrt this index !--- local --- integer(IN) :: i,j ! generic index integer(IN) :: ns ! size of S(:),row(:),col(:) integer(IN) :: pivotR ! partitian wrt this row value... integer(IN) :: pivotC ! ... and wrt this col value real (R8) :: rTemp ! temp var for swapping integer(IN) :: iTemp ! temp var for swapping !--- formats --- character(*),parameter :: F00 = "('(mapsort_partitianRC) ',8a)" character(*),parameter :: F01 = "('(mapsort_partitianRC) ',a,2i11)" !------------------------------------------------------------------------------- ! PURPOSE: ! o DOES NOT assume rows are sorted, assumes a completely unsorted matrix ! o rearrange elements in S & col and compute marker such that ! if n = marker and i <= n <= j we have col(i) <= col(n) <= col(j) !------------------------------------------------------------------------------- ns = size(S) if (ns < 2) then write(6,F01) "ERROR: ns < 2, ns = ",ns stop end if pivotC = col(ns/2) ! note: fortran truncation pivotR = row(ns/2) ! note: fortran truncation ! pivotC = col(1) ! pivotR = row(1) i = 0 j = ns+1 do !--- move j downward --- j = j-1 do if (row(j) < pivotR) exit if (row(j) == pivotR .and. col(j) <= pivotC) exit j = j-1 end do !--- move i upward --- i = i+1 do if (row(j) > pivotR) exit if (row(j) == pivotR .and. col(j) >= pivotC ) exit i = i+1 end do !--- if (i 1) then call mapsort_partitianC(S,row,col,m) call mapsort_QsortC (S(1:m-1),row(1:m-1),col(1:m-1)) call mapsort_QsortC (S(m:ns ),row(m:ns ),col(m:ns )) end if END SUBROUTINE mapsort_QsortC !=============================================================================== !=============================================================================== SUBROUTINE mapsort_partitianC(S,row,col,marker) implicit none !--- arguments --- real (R8) :: S(:) ! must rearrange along with col values integer(IN) :: row(:) ! unused: assumed constant integer(IN) :: col(:) ! sort wrt column value integer(IN) :: marker ! partitian wrt this index !--- local --- integer(IN) :: i,j ! generic index integer(IN) :: ns ! size of S(:),row(:),col(:) integer(IN) :: pivot ! partitian wrt this value real (R8) :: rTemp ! temp var for swapping integer(IN) :: iTemp ! temp var for swapping !--- formats --- character(*),parameter :: F00 = "('(mapsort_partitianC) ',8a)" character(*),parameter :: F01 = "('(mapsort_partitianC) ',a,2i11)" !------------------------------------------------------------------------------- ! PURPOSE: ! o assumes rows are already sorted ! o rearrange elements in S & col and compute marker such that ! if n = marker and i <= n <= j we have col(i) <= col(n) <= col(j) !------------------------------------------------------------------------------- ns = size(S) if (ns < 2) then write(6,F01) "ERROR: ns < 2, ns = ",ns stop end if if (minval(row) /= maxval(row)) then write(6,F01) "ERROR: all elements not in same row" write(6,F01) "ERROR: row min/max = ",minval(row),maxval(row) stop end if ! pivot = col(ns/2) ! note: fortran truncation pivot = col(1) i = 0 j = ns+1 do !--- move j downward --- j = j-1 do if (col(j) <= pivot) exit j = j-1 end do !--- move i upward --- i = i+1 do if (col(i) >= pivot) exit i = i+1 end do !--- if (irow links found ',n1 print *,'(mapsort_sortH): now n_s = ',n0 END SUBROUTINE mapsort_sortH !=============================================================================== SUBROUTINE mapsort_sortY(map) implicit none !--- arguments --- type(sMatrix), intent(inout) :: map !--- local --- integer i,j,n,thisrow,thiscol,n0,n1,ncnt,nskip,nrow integer imin,imax,cnt,itmp,imin2,imax2 integer, allocatable :: rowtmp(:),coltmp(:),stmp(:) logical rowok,colok double precision rtmp !------------------------------------------------------------------------------- ! PURPOSE: ! o subroutinized version of /fs/cgd/home0/hecht/csm/runoff/sort_map.F ! o sorts the links in sMatrix "map" to achieve a uniformly increasing ! map%row array. ! o sorts the links in sMatrix "map" to achieve uniformly increasing ! map%col for a given map%row value. ! o assures that the array of links contains unique row-col pairs. !------------------------------------------------------------------------------- allocate(stmp(map%n_s)) allocate(rowtmp(map%n_s)) allocate(coltmp(map%n_s)) stmp = map%s rowtmp = map%row coltmp = map%col ! check for correct row/column sorting (copied from map_check) rowok = .true. colok = .true. ! is row monotonically increasing? do n=2,map%n_s if (map%row(n-1) > map%row(n) ) rowok = .false. enddo ! is col monotonically increasing for a given row? do i=1,map%n_s-1 if (map%col(i).gt.map%col(i+1).and.map%row(i+1).eq.map%row(i)) then colok = .false. endif enddo ! if (.not. rowok .and. .not. colok) then ! imin=1 ! imax=map%n_s ! cnt=map%n_s ! print *,'(mapsort_sortY): slow-sorting rows...' ! do while (cnt.gt.0) ! cnt=0 ! do n=imin,imax-1 ! if (map%row(n).gt.map%row(n+1)) then ! itmp=map%row(n+1) ! map%row(n+1)=map%row(n) ! map%row(n)=itmp ! itmp=map%col(n+1) ! map%col(n+1)=map%col(n) ! map%col(n)=itmp ! rtmp=map%s(n+1) ! map%s(n+1)=map%s(n) ! map%s(n)=rtmp ! cnt=cnt+1 ! if (cnt.eq.1) imin2=n-1 ! imax2=n ! endif ! enddo ! imin=max(imin2,1) ! imax=imax2 ! enddo ! endif ! if (.not. rowok .and. colok) then ! cnt=1 ! print *,'(mapsort_sortY): fast-sorting rows...' ! do j=1,map%n_b ! n0 = 0 ! n1 = 0 ! do n=cnt,map%n_s ! if (map%row(n).eq.j .and. n0.eq.0) n0=n ! if (map%row(n).ne.j .and. n0.ne.0 .and. n1.eq.0) n1=n-1 ! enddo ! if (n0.ne.0) then ! if (n1.eq.0) n1=n0 ! nrow = n1-n0+1 ! nskip = n0-cnt ! map%row(cnt:cnt+nrow-1)=rowtmp(n0:n1) ! map%col(cnt:cnt+nrow-1)=coltmp(n0:n1) ! map%s(cnt:cnt+nrow-1)=stmp(n0:n1) ! if (nskip.gt.0) then ! map%row(cnt+nrow:cnt+nrow+nskip-1) = rowtmp(cnt:n0-1) ! map%col(cnt+nrow:cnt+nrow+nskip-1) = coltmp(cnt:n0-1) ! map%s(cnt+nrow:cnt+nrow+nskip-1) = stmp(cnt:n0-1) ! endif ! cnt = cnt+nrow ! if (n1.lt.map%n_s) then ! if (cnt+nskip .ne. n1+1) write(6,*) 'ERROR cnt+nskip .ne. n1+1' ! map%row(n1+1:map%n_s) = rowtmp(n1+1:map%n_s) ! map%col(n1+1:map%n_s) = coltmp(n1+1:map%n_s) ! map%s(n1+1:map%n_s) = stmp(n1+1:map%n_s) ! endif ! rowtmp = map%row ! coltmp = map%col ! stmp = map%s ! endif ! enddo ! endif if (.not. rowok) then call mapsort_byrow(map) endif if (.not. colok) then imin=1 imax=map%n_s cnt=map%n_s print *,'(mapsort_sortY): sorting columns...' do while (cnt.gt.0) cnt=0 do n=imin,imax-1 if (map%col(n).gt.map%col(n+1).and.map%row(n).eq.map%row(n+1)) then itmp=map%col(n+1) map%col(n+1)=map%col(n) map%col(n)=itmp rtmp=map%s(n+1) map%s(n+1)=map%s(n) map%s(n)=rtmp cnt=cnt+1 if (cnt.eq.1) imin2=n-1 imax2=n endif enddo imin=max(imin2,1) imax=imax2 enddo endif print *,'(mapsort_sortY): done sorting for both row AND col' thisrow = 0 thiscol = 0 n0 = 0 n1 = 0 do n=1,map%n_s if (map%row(n).eq.thisrow.and.map%col(n).eq.thiscol) then n1 = n1 + 1 map%s(n0) = map%s(n0)+map%s(n) else n0 = n0 + 1 thisrow = map%row(n) thiscol = map%col(n) map%row(n0) = map%row(n) map%col(n0) = map%col(n) map%s(n0) = map%s(n) endif enddo map%n_s = n0 print *,'(mapsort_sortY): # of repeat col->row links found ',n1 print *,'(mapsort_sortY): now n_s = ',n0 END SUBROUTINE mapsort_sortY !=============================================================================== !=============================================================================== SUBROUTINE mapsort_bubble(map) implicit none !--- arguments --- type(sMatrix), intent(inout) :: map !--- local --- integer(IN) :: k,m,n ! logical :: rowOK,colOK ! integer(IN) :: t01 = 0 ! system-clock-timer number real (R8) :: rTemp ! temp var for swapping integer(IN) :: iTemp ! temp var for swapping real (R8),pointer :: S (:) ! integer(IN),pointer :: row(:) ! integer(IN),pointer :: col(:) ! character(8) :: dstr ! F90 wall clock date string yyyymmdd character(10) :: tstr ! F90 wall clock time string hhmmss.sss !--- formats --- character(*),parameter :: subName = "(mapsort_bubble) " character(*),parameter :: F00 = "('(mapsort_bubble) ',8a)" character(*),parameter :: F01 = "('(mapsort_bubble) ',a,4i11)" character(*),parameter :: F10 = "('(mapsort_bubble) ',a,i7, & & ' date & time:',1x, & & a4,2('-',a2),2x,a2,2(':',a2))" !------------------------------------------------------------------------------- ! PURPOSE: !------------------------------------------------------------------------------- write(6,F01) "sort entire matrix, size = ",map%n_s if (t01 == 0) call shr_timer_get(t01,subName//"sort matrix") !---------------------------------------------------------------------------- !check for correct row/column sorting !---------------------------------------------------------------------------- call mapsort_checkSort(map) !---------------------------------------------------------------------------- ! sort entire matrix !---------------------------------------------------------------------------- call shr_timer_zero (t01) call shr_timer_start(t01) S => map%S row => map%row col => map%col do n = 1, map%n_s - 1 !--- progress report ---------------------------------- if (mod(n-1,10000)==0) then call date_and_time(dstr,tstr) ! F90 intrinsic routine write(6,F10) 'n=',n,dstr(1:4),dstr(5:6),dstr(7:8),tstr(1:2),tstr(3:4),tstr(5:6) call shr_sys_flush(6) end if !--- find desired element --------------------------- k = n do m = n+1, map%n_s if (row(m) < row(k)) then k = m else if (row(m) == row(k) .and. col(m) < col(k)) then k = m end if end do !--- put desired element into place ----------------- if ( n /= k ) then !--- swap matrix elements --- rTemp = S (n) S (n) = S (k) S (k) = rTemp !--- swap column index --- iTemp = col(n) col(n) = col(k) col(k) = iTemp !--- swap row index --- iTemp = row(n) row(n) = row(k) row(k) = iTemp end if end do call shr_timer_stop (t01) call shr_timer_print(t01) !---------------------------------------------------------------------------- ! verify matrix has been properly sorted !---------------------------------------------------------------------------- call mapsort_checkSort(map,rowOK=rowOK,colOK=colOK) if (.not. rowOK ) write(6,F00) "ERROR: rows are NOT monotonically increasing" if (.not. colOK ) write(6,F00) "ERROR: cols are NOT monotonically increasing" if (.not. colOK .or. .not. rowOK) stop END SUBROUTINE mapsort_bubble !=============================================================================== !=============================================================================== END MODULE mapsort_mod