1c $Id: unary.f,v 1.1 2008-04-11 06:01:06 geuzaine Exp $ 2c----------------------------------------------------------------------c 3c S P A R S K I T c 4c----------------------------------------------------------------------c 5c UNARY SUBROUTINES MODULE c 6c----------------------------------------------------------------------c 7c contents: c 8c---------- c 9c submat : extracts a submatrix from a sparse matrix. c 10c filter : filters elements from a matrix according to their magnitude.c 11c filterm: same as above, but for the MSR format c 12c csort : sorts the elements in increasing order of columns c 13c clncsr : clean up the CSR format matrix, remove duplicate entry, etc c 14c transp : in-place transposition routine (see also csrcsc in formats) c 15c copmat : copy of a matrix into another matrix (both stored csr) c 16c msrcop : copies a matrix in MSR format into a matrix in MSR format c 17c getelm : returns a(i,j) for any (i,j) from a CSR-stored matrix. c 18c getdia : extracts a specified diagonal from a matrix. c 19c getl : extracts lower triangular part c 20c getu : extracts upper triangular part c 21c levels : gets the level scheduling structure for lower triangular c 22c matrices. c 23c amask : extracts C = A mask M c 24c rperm : permutes the rows of a matrix (B = P A) c 25c cperm : permutes the columns of a matrix (B = A Q) c 26c dperm : permutes both the rows and columns of a matrix (B = P A Q ) c 27c dperm1 : general extractiob routine (extracts arbitrary rows) c 28c dperm2 : general submatrix permutation/extraction routine c 29c dmperm : symmetric permutation of row and column (B=PAP') in MSR fmt c 30c dvperm : permutes a real vector (in-place) c 31c ivperm : permutes an integer vector (in-place) c 32c retmx : returns the max absolute value in each row of the matrix c 33c diapos : returns the positions of the diagonal elements in A. c 34c extbdg : extracts the main diagonal blocks of a matrix. c 35c getbwd : returns the bandwidth information on a matrix. c 36c blkfnd : finds the block-size of a matrix. c 37c blkchk : checks whether a given integer is the block size of A. c 38c infdia : obtains information on the diagonals of A. c 39c amubdg : gets number of nonzeros in each row of A*B (as well as NNZ) c 40c aplbdg : gets number of nonzeros in each row of A+B (as well as NNZ) c 41c rnrms : computes the norms of the rows of A c 42c cnrms : computes the norms of the columns of A c 43c roscal : scales the rows of a matrix by their norms. c 44c coscal : scales the columns of a matrix by their norms. c 45c addblk : Adds a matrix B into a block of A. c 46c get1up : Collects the first elements of each row of the upper c 47c triangular portion of the matrix. c 48c xtrows : extracts given rows from a matrix in CSR format. c 49c csrkvstr: Finds block row partitioning of matrix in CSR format c 50c csrkvstc: Finds block column partitioning of matrix in CSR format c 51c kvstmerge: Merges block partitionings, for conformal row/col pattern c 52c----------------------------------------------------------------------c 53 subroutine submat (n,job,i1,i2,j1,j2,a,ja,ia,nr,nc,ao,jao,iao) 54 integer n,job,i1,i2,j1,j2,nr,nc,ia(*),ja(*),jao(*),iao(*) 55 real*8 a(*),ao(*) 56c----------------------------------------------------------------------- 57c extracts the submatrix A(i1:i2,j1:j2) and puts the result in 58c matrix ao,iao,jao 59c---- In place: ao,jao,iao may be the same as a,ja,ia. 60c-------------- 61c on input 62c--------- 63c n = row dimension of the matrix 64c i1,i2 = two integers with i2 .ge. i1 indicating the range of rows to be 65c extracted. 66c j1,j2 = two integers with j2 .ge. j1 indicating the range of columns 67c to be extracted. 68c * There is no checking whether the input values for i1, i2, j1, 69c j2 are between 1 and n. 70c a, 71c ja, 72c ia = matrix in compressed sparse row format. 73c 74c job = job indicator: if job .ne. 1 then the real values in a are NOT 75c extracted, only the column indices (i.e. data structure) are. 76c otherwise values as well as column indices are extracted... 77c 78c on output 79c-------------- 80c nr = number of rows of submatrix 81c nc = number of columns of submatrix 82c * if either of nr or nc is nonpositive the code will quit. 83c 84c ao, 85c jao,iao = extracted matrix in general sparse format with jao containing 86c the column indices,and iao being the pointer to the beginning 87c of the row,in arrays a,ja. 88c----------------------------------------------------------------------c 89c Y. Saad, Sep. 21 1989 c 90c----------------------------------------------------------------------c 91 nr = i2-i1+1 92 nc = j2-j1+1 93c 94 if ( nr .le. 0 .or. nc .le. 0) return 95c 96 klen = 0 97c 98c simple procedure. proceeds row-wise... 99c 100 do 100 i = 1,nr 101 ii = i1+i-1 102 k1 = ia(ii) 103 k2 = ia(ii+1)-1 104 iao(i) = klen+1 105c----------------------------------------------------------------------- 106 do 60 k=k1,k2 107 j = ja(k) 108 if (j .ge. j1 .and. j .le. j2) then 109 klen = klen+1 110 if (job .eq. 1) ao(klen) = a(k) 111 jao(klen) = j - j1+1 112 endif 113 60 continue 114 100 continue 115 iao(nr+1) = klen+1 116 return 117c------------end-of submat---------------------------------------------- 118c----------------------------------------------------------------------- 119 end 120c----------------------------------------------------------------------- 121 subroutine filter(n,job,drptol,a,ja,ia,b,jb,ib,len,ierr) 122 real*8 a(*),b(*),drptol 123 integer ja(*),jb(*),ia(*),ib(*),n,job,len,ierr 124c----------------------------------------------------------------------- 125c This module removes any elements whose absolute value 126c is small from an input matrix A and puts the resulting 127c matrix in B. The input parameter job selects a definition 128c of small. 129c----------------------------------------------------------------------- 130c on entry: 131c--------- 132c n = integer. row dimension of matrix 133c job = integer. used to determine strategy chosen by caller to 134c drop elements from matrix A. 135c job = 1 136c Elements whose absolute value is less than the 137c drop tolerance are removed. 138c job = 2 139c Elements whose absolute value is less than the 140c product of the drop tolerance and the Euclidean 141c norm of the row are removed. 142c job = 3 143c Elements whose absolute value is less that the 144c product of the drop tolerance and the largest 145c element in the row are removed. 146c 147c drptol = real. drop tolerance used for dropping strategy. 148c a 149c ja 150c ia = input matrix in compressed sparse format 151c len = integer. the amount of space available in arrays b and jb. 152c 153c on return: 154c---------- 155c b 156c jb 157c ib = resulting matrix in compressed sparse format. 158c 159c ierr = integer. containing error message. 160c ierr .eq. 0 indicates normal return 161c ierr .gt. 0 indicates that there is'nt enough 162c space is a and ja to store the resulting matrix. 163c ierr then contains the row number where filter stopped. 164c note: 165c------ This module is in place. (b,jb,ib can ne the same as 166c a, ja, ia in which case the result will be overwritten). 167c----------------------------------------------------------------------c 168c contributed by David Day, Sep 19, 1989. c 169c----------------------------------------------------------------------c 170c local variables 171 real*8 norm,loctol 172 integer index,row,k,k1,k2 173c 174 index = 1 175 do 10 row= 1,n 176 k1 = ia(row) 177 k2 = ia(row+1) - 1 178 ib(row) = index 179 goto (100,200,300) job 180 100 norm = 1.0d0 181 goto 400 182 200 norm = 0.0d0 183 do 22 k = k1,k2 184 norm = norm + a(k) * a(k) 185 22 continue 186 norm = sqrt(norm) 187 goto 400 188 300 norm = 0.0d0 189 do 23 k = k1,k2 190 if( abs(a(k)) .gt. norm) then 191 norm = abs(a(k)) 192 endif 193 23 continue 194 400 loctol = drptol * norm 195 do 30 k = k1,k2 196 if( abs(a(k)) .gt. loctol)then 197 if (index .gt. len) then 198 ierr = row 199 return 200 endif 201 b(index) = a(k) 202 jb(index) = ja(k) 203 index = index + 1 204 endif 205 30 continue 206 10 continue 207 ib(n+1) = index 208 return 209c--------------------end-of-filter ------------------------------------- 210c----------------------------------------------------------------------- 211 end 212c----------------------------------------------------------------------- 213 subroutine filterm (n,job,drop,a,ja,b,jb,len,ierr) 214 real*8 a(*),b(*),drop 215 integer ja(*),jb(*),n,job,len,ierr 216c----------------------------------------------------------------------- 217c This subroutine removes any elements whose absolute value 218c is small from an input matrix A. Same as filter but 219c uses the MSR format. 220c----------------------------------------------------------------------- 221c on entry: 222c--------- 223c n = integer. row dimension of matrix 224c job = integer. used to determine strategy chosen by caller to 225c drop elements from matrix A. 226c job = 1 227c Elements whose absolute value is less than the 228c drop tolerance are removed. 229c job = 2 230c Elements whose absolute value is less than the 231c product of the drop tolerance and the Euclidean 232c norm of the row are removed. 233c job = 3 234c Elements whose absolute value is less that the 235c product of the drop tolerance and the largest 236c element in the row are removed. 237c 238c drop = real. drop tolerance used for dropping strategy. 239c a 240c ja = input matrix in Modifief Sparse Row format 241c len = integer. the amount of space in arrays b and jb. 242c 243c on return: 244c---------- 245c 246c b, jb = resulting matrix in Modifief Sparse Row format 247c 248c ierr = integer. containing error message. 249c ierr .eq. 0 indicates normal return 250c ierr .gt. 0 indicates that there is'nt enough 251c space is a and ja to store the resulting matrix. 252c ierr then contains the row number where filter stopped. 253c note: 254c------ This module is in place. (b,jb can ne the same as 255c a, ja in which case the result will be overwritten). 256c----------------------------------------------------------------------c 257c contributed by David Day, Sep 19, 1989. c 258c----------------------------------------------------------------------c 259c local variables 260c 261 real*8 norm,loctol 262 integer index,row,k,k1,k2 263c 264 index = n+2 265 do 10 row= 1,n 266 k1 = ja(row) 267 k2 = ja(row+1) - 1 268 jb(row) = index 269 goto (100,200,300) job 270 100 norm = 1.0d0 271 goto 400 272 200 norm = a(row)**2 273 do 22 k = k1,k2 274 norm = norm + a(k) * a(k) 275 22 continue 276 norm = sqrt(norm) 277 goto 400 278 300 norm = abs(a(row)) 279 do 23 k = k1,k2 280 norm = max(abs(a(k)),norm) 281 23 continue 282 400 loctol = drop * norm 283 do 30 k = k1,k2 284 if( abs(a(k)) .gt. loctol)then 285 if (index .gt. len) then 286 ierr = row 287 return 288 endif 289 b(index) = a(k) 290 jb(index) = ja(k) 291 index = index + 1 292 endif 293 30 continue 294 10 continue 295 jb(n+1) = index 296 return 297c--------------------end-of-filterm------------------------------------- 298c----------------------------------------------------------------------- 299 end 300c----------------------------------------------------------------------- 301 subroutine csort (n,a,ja,ia,iwork,values) 302 logical values 303 integer n, ja(*), ia(n+1), iwork(*) 304 real*8 a(*) 305c----------------------------------------------------------------------- 306c This routine sorts the elements of a matrix (stored in Compressed 307c Sparse Row Format) in increasing order of their column indices within 308c each row. It uses a form of bucket sort with a cost of O(nnz) where 309c nnz = number of nonzero elements. 310c requires an integer work array of length 2*nnz. 311c----------------------------------------------------------------------- 312c on entry: 313c--------- 314c n = the row dimension of the matrix 315c a = the matrix A in compressed sparse row format. 316c ja = the array of column indices of the elements in array a. 317c ia = the array of pointers to the rows. 318c iwork = integer work array of length max ( n+1, 2*nnz ) 319c where nnz = 2* (ia(n+1)-ia(1)) ) . 320c values= logical indicating whether or not the real values a(*) must 321c also be permuted. if (.not. values) then the array a is not 322c touched by csort and can be a dummy array. 323c 324c on return: 325c---------- 326c the matrix stored in the structure a, ja, ia is permuted in such a 327c way that the column indices are in increasing order within each row. 328c iwork(1:nnz) contains the permutation used to rearrange the elements. 329c----------------------------------------------------------------------- 330c Y. Saad - Feb. 1, 1991. 331c----------------------------------------------------------------------- 332c local variables 333 integer i, k, j, ifirst, nnz, next 334c 335c count the number of elements in each column 336c 337 do 1 i=1,n+1 338 iwork(i) = 0 339 1 continue 340 do 3 i=1, n 341 do 2 k=ia(i), ia(i+1)-1 342 j = ja(k)+1 343 iwork(j) = iwork(j)+1 344 2 continue 345 3 continue 346c 347c compute pointers from lengths. 348c 349 iwork(1) = 1 350 do 4 i=1,n 351 iwork(i+1) = iwork(i) + iwork(i+1) 352 4 continue 353c 354c get the positions of the nonzero elements in order of columns. 355c 356 ifirst = ia(1) 357 nnz = ia(n+1)-ifirst 358 do 5 i=1,n 359 do 51 k=ia(i),ia(i+1)-1 360 j = ja(k) 361 next = iwork(j) 362 iwork(nnz+next) = k 363 iwork(j) = next+1 364 51 continue 365 5 continue 366c 367c convert to coordinate format 368c 369 do 6 i=1, n 370 do 61 k=ia(i), ia(i+1)-1 371 iwork(k) = i 372 61 continue 373 6 continue 374c 375c loop to find permutation: for each element find the correct 376c position in (sorted) arrays a, ja. Record this in iwork. 377c 378 do 7 k=1, nnz 379 ko = iwork(nnz+k) 380 irow = iwork(ko) 381 next = ia(irow) 382c 383c the current element should go in next position in row. iwork 384c records this position. 385c 386 iwork(ko) = next 387 ia(irow) = next+1 388 7 continue 389c 390c perform an in-place permutation of the arrays. 391c 392 call ivperm (nnz, ja(ifirst), iwork) 393 if (values) call dvperm (nnz, a(ifirst), iwork) 394c 395c reshift the pointers of the original matrix back. 396c 397 do 8 i=n,1,-1 398 ia(i+1) = ia(i) 399 8 continue 400 ia(1) = ifirst 401c 402 return 403c---------------end-of-csort-------------------------------------------- 404c----------------------------------------------------------------------- 405 end 406c----------------------------------------------------------------------- 407 subroutine clncsr(job,value2,nrow,a,ja,ia,indu,iwk) 408c .. Scalar Arguments .. 409 integer job, nrow, value2 410c .. 411c .. Array Arguments .. 412 integer ia(nrow+1),indu(nrow),iwk(nrow+1),ja(*) 413 real*8 a(*) 414c .. 415c 416c This routine performs two tasks to clean up a CSR matrix 417c -- remove duplicate/zero entries, 418c -- perform a partial ordering, new order lower triangular part, 419c main diagonal, upper triangular part. 420c 421c On entry: 422c 423c job = options 424c 0 -- nothing is done 425c 1 -- eliminate duplicate entries, zero entries. 426c 2 -- eliminate duplicate entries and perform partial ordering. 427c 3 -- eliminate duplicate entries, sort the entries in the 428c increasing order of clumn indices. 429c 430c value2 -- 0 the matrix is pattern only (a is not touched) 431c 1 matrix has values too. 432c nrow -- row dimension of the matrix 433c a,ja,ia -- input matrix in CSR format 434c 435c On return: 436c a,ja,ia -- cleaned matrix 437c indu -- pointers to the beginning of the upper triangular 438c portion if job > 1 439c 440c Work space: 441c iwk -- integer work space of size nrow+1 442c 443c .. Local Scalars .. 444 integer i,j,k,ko,ipos,kfirst,klast 445 real*8 tmp 446c .. 447c 448 if (job.le.0) return 449c 450c .. eliminate duplicate entries -- 451c array INDU is used as marker for existing indices, it is also the 452c location of the entry. 453c IWK is used to stored the old IA array. 454c matrix is copied to squeeze out the space taken by the duplicated 455c entries. 456c 457 do 90 i = 1, nrow 458 indu(i) = 0 459 iwk(i) = ia(i) 460 90 continue 461 iwk(nrow+1) = ia(nrow+1) 462 k = 1 463 do 120 i = 1, nrow 464 ia(i) = k 465 ipos = iwk(i) 466 klast = iwk(i+1) 467 100 if (ipos.lt.klast) then 468 j = ja(ipos) 469 if (indu(j).eq.0) then 470c .. new entry .. 471 if (value2.ne.0) then 472 if (a(ipos) .ne. 0.0D0) then 473 indu(j) = k 474 ja(k) = ja(ipos) 475 a(k) = a(ipos) 476 k = k + 1 477 endif 478 else 479 indu(j) = k 480 ja(k) = ja(ipos) 481 k = k + 1 482 endif 483 else if (value2.ne.0) then 484c .. duplicate entry .. 485 a(indu(j)) = a(indu(j)) + a(ipos) 486 endif 487 ipos = ipos + 1 488 go to 100 489 endif 490c .. remove marks before working on the next row .. 491 do 110 ipos = ia(i), k - 1 492 indu(ja(ipos)) = 0 493 110 continue 494 120 continue 495 ia(nrow+1) = k 496 if (job.le.1) return 497c 498c .. partial ordering .. 499c split the matrix into strict upper/lower triangular 500c parts, INDU points to the the beginning of the upper part. 501c 502 do 140 i = 1, nrow 503 klast = ia(i+1) - 1 504 kfirst = ia(i) 505 130 if (klast.gt.kfirst) then 506 if (ja(klast).lt.i .and. ja(kfirst).ge.i) then 507c .. swap klast with kfirst .. 508 j = ja(klast) 509 ja(klast) = ja(kfirst) 510 ja(kfirst) = j 511 if (value2.ne.0) then 512 tmp = a(klast) 513 a(klast) = a(kfirst) 514 a(kfirst) = tmp 515 endif 516 endif 517 if (ja(klast).ge.i) 518 & klast = klast - 1 519 if (ja(kfirst).lt.i) 520 & kfirst = kfirst + 1 521 go to 130 522 endif 523c 524 if (ja(klast).lt.i) then 525 indu(i) = klast + 1 526 else 527 indu(i) = klast 528 endif 529 140 continue 530 if (job.le.2) return 531c 532c .. order the entries according to column indices 533c burble-sort is used 534c 535 do 190 i = 1, nrow 536 do 160 ipos = ia(i), indu(i)-1 537 do 150 j = indu(i)-1, ipos+1, -1 538 k = j - 1 539 if (ja(k).gt.ja(j)) then 540 ko = ja(k) 541 ja(k) = ja(j) 542 ja(j) = ko 543 if (value2.ne.0) then 544 tmp = a(k) 545 a(k) = a(j) 546 a(j) = tmp 547 endif 548 endif 549 150 continue 550 160 continue 551 do 180 ipos = indu(i), ia(i+1)-1 552 do 170 j = ia(i+1)-1, ipos+1, -1 553 k = j - 1 554 if (ja(k).gt.ja(j)) then 555 ko = ja(k) 556 ja(k) = ja(j) 557 ja(j) = ko 558 if (value2.ne.0) then 559 tmp = a(k) 560 a(k) = a(j) 561 a(j) = tmp 562 endif 563 endif 564 170 continue 565 180 continue 566 190 continue 567 return 568c---- end of clncsr ---------------------------------------------------- 569c----------------------------------------------------------------------- 570 end 571c----------------------------------------------------------------------- 572 subroutine copmat (nrow,a,ja,ia,ao,jao,iao,ipos,job) 573 real*8 a(*),ao(*) 574 integer nrow, ia(*),ja(*),jao(*),iao(*), ipos, job 575c---------------------------------------------------------------------- 576c copies the matrix a, ja, ia, into the matrix ao, jao, iao. 577c---------------------------------------------------------------------- 578c on entry: 579c--------- 580c nrow = row dimension of the matrix 581c a, 582c ja, 583c ia = input matrix in compressed sparse row format. 584c ipos = integer. indicates the position in the array ao, jao 585c where the first element should be copied. Thus 586c iao(1) = ipos on return. 587c job = job indicator. if (job .ne. 1) the values are not copies 588c (i.e., pattern only is copied in the form of arrays ja, ia). 589c 590c on return: 591c---------- 592c ao, 593c jao, 594c iao = output matrix containing the same data as a, ja, ia. 595c----------------------------------------------------------------------- 596c Y. Saad, March 1990. 597c----------------------------------------------------------------------- 598c local variables 599 integer kst, i, k 600c 601 kst = ipos -ia(1) 602 do 100 i = 1, nrow+1 603 iao(i) = ia(i) + kst 604 100 continue 605c 606 do 200 k=ia(1), ia(nrow+1)-1 607 jao(kst+k)= ja(k) 608 200 continue 609c 610 if (job .ne. 1) return 611 do 201 k=ia(1), ia(nrow+1)-1 612 ao(kst+k) = a(k) 613 201 continue 614c 615 return 616c--------end-of-copmat ------------------------------------------------- 617c----------------------------------------------------------------------- 618 end 619c----------------------------------------------------------------------- 620 subroutine msrcop (nrow,a,ja,ao,jao,job) 621 real*8 a(*),ao(*) 622 integer nrow, ja(*),jao(*), job 623c---------------------------------------------------------------------- 624c copies the MSR matrix a, ja, into the MSR matrix ao, jao 625c---------------------------------------------------------------------- 626c on entry: 627c--------- 628c nrow = row dimension of the matrix 629c a,ja = input matrix in Modified compressed sparse row format. 630c job = job indicator. Values are not copied if job .ne. 1 631c 632c on return: 633c---------- 634c ao, jao = output matrix containing the same data as a, ja. 635c----------------------------------------------------------------------- 636c Y. Saad, 637c----------------------------------------------------------------------- 638c local variables 639 integer i, k 640c 641 do 100 i = 1, nrow+1 642 jao(i) = ja(i) 643 100 continue 644c 645 do 200 k=ja(1), ja(nrow+1)-1 646 jao(k)= ja(k) 647 200 continue 648c 649 if (job .ne. 1) return 650 do 201 k=ja(1), ja(nrow+1)-1 651 ao(k) = a(k) 652 201 continue 653 do 202 k=1,nrow 654 ao(k) = a(k) 655 202 continue 656c 657 return 658c--------end-of-msrcop ------------------------------------------------- 659c----------------------------------------------------------------------- 660 end 661c----------------------------------------------------------------------- 662 double precision function getelm (i,j,a,ja,ia,iadd,sorted) 663c----------------------------------------------------------------------- 664c purpose: 665c -------- 666c this function returns the element a(i,j) of a matrix a, 667c for any pair (i,j). the matrix is assumed to be stored 668c in compressed sparse row (csr) format. getelm performs a 669c binary search in the case where it is known that the elements 670c are sorted so that the column indices are in increasing order. 671c also returns (in iadd) the address of the element a(i,j) in 672c arrays a and ja when the search is successsful (zero if not). 673c----- 674c first contributed by noel nachtigal (mit). 675c recoded jan. 20, 1991, by y. saad [in particular 676c added handling of the non-sorted case + the iadd output] 677c----------------------------------------------------------------------- 678c parameters: 679c ----------- 680c on entry: 681c---------- 682c i = the row index of the element sought (input). 683c j = the column index of the element sought (input). 684c a = the matrix a in compressed sparse row format (input). 685c ja = the array of column indices (input). 686c ia = the array of pointers to the rows' data (input). 687c sorted = logical indicating whether the matrix is knonw to 688c have its column indices sorted in increasing order 689c (sorted=.true.) or not (sorted=.false.). 690c (input). 691c on return: 692c----------- 693c getelm = value of a(i,j). 694c iadd = address of element a(i,j) in arrays a, ja if found, 695c zero if not found. (output) 696c 697c note: the inputs i and j are not checked for validity. 698c----------------------------------------------------------------------- 699c noel m. nachtigal october 28, 1990 -- youcef saad jan 20, 1991. 700c----------------------------------------------------------------------- 701 integer i, ia(*), iadd, j, ja(*) 702 double precision a(*) 703 logical sorted 704c 705c local variables. 706c 707 integer ibeg, iend, imid, k 708c 709c initialization 710c 711 iadd = 0 712 getelm = 0.0 713 ibeg = ia(i) 714 iend = ia(i+1)-1 715c 716c case where matrix is not necessarily sorted 717c 718 if (.not. sorted) then 719c 720c scan the row - exit as soon as a(i,j) is found 721c 722 do 5 k=ibeg, iend 723 if (ja(k) .eq. j) then 724 iadd = k 725 goto 20 726 endif 727 5 continue 728c 729c end unsorted case. begin sorted case 730c 731 else 732c 733c begin binary search. compute the middle index. 734c 735 10 imid = ( ibeg + iend ) / 2 736c 737c test if found 738c 739 if (ja(imid).eq.j) then 740 iadd = imid 741 goto 20 742 endif 743 if (ibeg .ge. iend) goto 20 744c 745c else update the interval bounds. 746c 747 if (ja(imid).gt.j) then 748 iend = imid -1 749 else 750 ibeg = imid +1 751 endif 752 goto 10 753c 754c end both cases 755c 756 endif 757c 758 20 if (iadd .ne. 0) getelm = a(iadd) 759c 760 return 761c--------end-of-getelm-------------------------------------------------- 762c----------------------------------------------------------------------- 763 end 764c----------------------------------------------------------------------- 765 subroutine getdia (nrow,ncol,job,a,ja,ia,len,diag,idiag,ioff) 766 real*8 diag(*),a(*) 767 integer nrow, ncol, job, len, ioff, ia(*), ja(*), idiag(*) 768c----------------------------------------------------------------------- 769c this subroutine extracts a given diagonal from a matrix stored in csr 770c format. the output matrix may be transformed with the diagonal removed 771c from it if desired (as indicated by job.) 772c----------------------------------------------------------------------- 773c our definition of a diagonal of matrix is a vector of length nrow 774c (always) which contains the elements in rows 1 to nrow of 775c the matrix that are contained in the diagonal offset by ioff 776c with respect to the main diagonal. if the diagonal element 777c falls outside the matrix then it is defined as a zero entry. 778c thus the proper definition of diag(*) with offset ioff is 779c 780c diag(i) = a(i,ioff+i) i=1,2,...,nrow 781c with elements falling outside the matrix being defined as zero. 782c 783c----------------------------------------------------------------------- 784c 785c on entry: 786c---------- 787c 788c nrow = integer. the row dimension of the matrix a. 789c ncol = integer. the column dimension of the matrix a. 790c job = integer. job indicator. if job = 0 then 791c the matrix a, ja, ia, is not altered on return. 792c if job.ne.0 then getdia will remove the entries 793c collected in diag from the original matrix. 794c this is done in place. 795c 796c a,ja, 797c ia = matrix stored in compressed sparse row a,ja,ia,format 798c ioff = integer,containing the offset of the wanted diagonal 799c the diagonal extracted is the one corresponding to the 800c entries a(i,j) with j-i = ioff. 801c thus ioff = 0 means the main diagonal 802c 803c on return: 804c----------- 805c len = number of nonzero elements found in diag. 806c (len .le. min(nrow,ncol-ioff)-max(1,1-ioff) + 1 ) 807c 808c diag = real*8 array of length nrow containing the wanted diagonal. 809c diag contains the diagonal (a(i,j),j-i = ioff ) as defined 810c above. 811c 812c idiag = integer array of length len, containing the poisitions 813c in the original arrays a and ja of the diagonal elements 814c collected in diag. a zero entry in idiag(i) means that 815c there was no entry found in row i belonging to the diagonal. 816c 817c a, ja, 818c ia = if job .ne. 0 the matrix is unchanged. otherwise the nonzero 819c diagonal entries collected in diag are removed from the 820c matrix and therefore the arrays a, ja, ia will change. 821c (the matrix a, ja, ia will contain len fewer elements) 822c 823c----------------------------------------------------------------------c 824c Y. Saad, sep. 21 1989 - modified and retested Feb 17, 1996. c 825c----------------------------------------------------------------------c 826c local variables 827 integer istart, max, iend, i, kold, k, kdiag, ko 828c 829 istart = max(0,-ioff) 830 iend = min(nrow,ncol-ioff) 831 len = 0 832 do 1 i=1,nrow 833 idiag(i) = 0 834 diag(i) = 0.0d0 835 1 continue 836c 837c extract diagonal elements 838c 839 do 6 i=istart+1, iend 840 do 51 k= ia(i),ia(i+1) -1 841 if (ja(k)-i .eq. ioff) then 842 diag(i)= a(k) 843 idiag(i) = k 844 len = len+1 845 goto 6 846 endif 847 51 continue 848 6 continue 849 if (job .eq. 0 .or. len .eq.0) return 850c 851c remove diagonal elements and rewind structure 852c 853 ko = 0 854 do 7 i=1, nrow 855 kold = ko 856 kdiag = idiag(i) 857 do 71 k= ia(i), ia(i+1)-1 858 if (k .ne. kdiag) then 859 ko = ko+1 860 a(ko) = a(k) 861 ja(ko) = ja(k) 862 endif 863 71 continue 864 ia(i) = kold+1 865 7 continue 866c 867c redefine ia(nrow+1) 868c 869 ia(nrow+1) = ko+1 870 return 871c------------end-of-getdia---------------------------------------------- 872c----------------------------------------------------------------------- 873 end 874c----------------------------------------------------------------------- 875 subroutine transp (nrow,ncol,a,ja,ia,iwk,ierr) 876 integer nrow, ncol, ia(*), ja(*), iwk(*), ierr 877 real*8 a(*) 878c------------------------------------------------------------------------ 879c In-place transposition routine. 880c------------------------------------------------------------------------ 881c this subroutine transposes a matrix stored in compressed sparse row 882c format. the transposition is done in place in that the arrays a,ja,ia 883c of the transpose are overwritten onto the original arrays. 884c------------------------------------------------------------------------ 885c on entry: 886c--------- 887c nrow = integer. The row dimension of A. 888c ncol = integer. The column dimension of A. 889c a = real array of size nnz (number of nonzero elements in A). 890c containing the nonzero elements 891c ja = integer array of length nnz containing the column positions 892c of the corresponding elements in a. 893c ia = integer of size n+1, where n = max(nrow,ncol). On entry 894c ia(k) contains the position in a,ja of the beginning of 895c the k-th row. 896c 897c iwk = integer work array of same length as ja. 898c 899c on return: 900c---------- 901c 902c ncol = actual row dimension of the transpose of the input matrix. 903c Note that this may be .le. the input value for ncol, in 904c case some of the last columns of the input matrix are zero 905c columns. In the case where the actual number of rows found 906c in transp(A) exceeds the input value of ncol, transp will 907c return without completing the transposition. see ierr. 908c a, 909c ja, 910c ia = contains the transposed matrix in compressed sparse 911c row format. The row dimension of a, ja, ia is now ncol. 912c 913c ierr = integer. error message. If the number of rows for the 914c transposed matrix exceeds the input value of ncol, 915c then ierr is set to that number and transp quits. 916c Otherwise ierr is set to 0 (normal return). 917c 918c Note: 919c----- 1) If you do not need the transposition to be done in place 920c it is preferrable to use the conversion routine csrcsc 921c (see conversion routines in formats). 922c 2) the entries of the output matrix are not sorted (the column 923c indices in each are not in increasing order) use csrcsc 924c if you want them sorted. 925c----------------------------------------------------------------------c 926c Y. Saad, Sep. 21 1989 c 927c modified Oct. 11, 1989. c 928c----------------------------------------------------------------------c 929c local variables 930 real*8 t, t1 931 ierr = 0 932 nnz = ia(nrow+1)-1 933c 934c determine column dimension 935c 936 jcol = 0 937 do 1 k=1, nnz 938 jcol = max(jcol,ja(k)) 939 1 continue 940 if (jcol .gt. ncol) then 941 ierr = jcol 942 return 943 endif 944c 945c convert to coordinate format. use iwk for row indices. 946c 947 ncol = jcol 948c 949 do 3 i=1,nrow 950 do 2 k=ia(i),ia(i+1)-1 951 iwk(k) = i 952 2 continue 953 3 continue 954c find pointer array for transpose. 955 do 35 i=1,ncol+1 956 ia(i) = 0 957 35 continue 958 do 4 k=1,nnz 959 i = ja(k) 960 ia(i+1) = ia(i+1)+1 961 4 continue 962 ia(1) = 1 963c------------------------------------------------------------------------ 964 do 44 i=1,ncol 965 ia(i+1) = ia(i) + ia(i+1) 966 44 continue 967c 968c loop for a cycle in chasing process. 969c 970 init = 1 971 k = 0 972 5 t = a(init) 973 i = ja(init) 974 j = iwk(init) 975 iwk(init) = -1 976c------------------------------------------------------------------------ 977 6 k = k+1 978c current row number is i. determine where to go. 979 l = ia(i) 980c save the chased element. 981 t1 = a(l) 982 inext = ja(l) 983c then occupy its location. 984 a(l) = t 985 ja(l) = j 986c update pointer information for next element to be put in row i. 987 ia(i) = l+1 988c determine next element to be chased 989 if (iwk(l) .lt. 0) goto 65 990 t = t1 991 i = inext 992 j = iwk(l) 993 iwk(l) = -1 994 if (k .lt. nnz) goto 6 995 goto 70 996 65 init = init+1 997 if (init .gt. nnz) goto 70 998 if (iwk(init) .lt. 0) goto 65 999c restart chasing -- 1000 goto 5 1001 70 continue 1002 do 80 i=ncol,1,-1 1003 ia(i+1) = ia(i) 1004 80 continue 1005 ia(1) = 1 1006c 1007 return 1008c------------------end-of-transp ---------------------------------------- 1009c------------------------------------------------------------------------ 1010 end 1011c------------------------------------------------------------------------ 1012 subroutine getl (n,a,ja,ia,ao,jao,iao) 1013 integer n, ia(*), ja(*), iao(*), jao(*) 1014 real*8 a(*), ao(*) 1015c------------------------------------------------------------------------ 1016c this subroutine extracts the lower triangular part of a matrix 1017c and writes the result ao, jao, iao. The routine is in place in 1018c that ao, jao, iao can be the same as a, ja, ia if desired. 1019c----------- 1020c on input: 1021c 1022c n = dimension of the matrix a. 1023c a, ja, 1024c ia = matrix stored in compressed sparse row format. 1025c On return: 1026c ao, jao, 1027c iao = lower triangular matrix (lower part of a) 1028c stored in a, ja, ia, format 1029c note: the diagonal element is the last element in each row. 1030c i.e. in a(ia(i+1)-1 ) 1031c ao, jao, iao may be the same as a, ja, ia on entry -- in which case 1032c getl will overwrite the result on a, ja, ia. 1033c 1034c------------------------------------------------------------------------ 1035c local variables 1036 real*8 t 1037 integer ko, kold, kdiag, k, i 1038c 1039c inititialize ko (pointer for output matrix) 1040c 1041 ko = 0 1042 do 7 i=1, n 1043 kold = ko 1044 kdiag = 0 1045 do 71 k = ia(i), ia(i+1) -1 1046 if (ja(k) .gt. i) goto 71 1047 ko = ko+1 1048 ao(ko) = a(k) 1049 jao(ko) = ja(k) 1050 if (ja(k) .eq. i) kdiag = ko 1051 71 continue 1052 if (kdiag .eq. 0 .or. kdiag .eq. ko) goto 72 1053c 1054c exchange 1055c 1056 t = ao(kdiag) 1057 ao(kdiag) = ao(ko) 1058 ao(ko) = t 1059c 1060 k = jao(kdiag) 1061 jao(kdiag) = jao(ko) 1062 jao(ko) = k 1063 72 iao(i) = kold+1 1064 7 continue 1065c redefine iao(n+1) 1066 iao(n+1) = ko+1 1067 return 1068c----------end-of-getl ------------------------------------------------- 1069c----------------------------------------------------------------------- 1070 end 1071c----------------------------------------------------------------------- 1072 subroutine getu (n,a,ja,ia,ao,jao,iao) 1073 integer n, ia(*), ja(*), iao(*), jao(*) 1074 real*8 a(*), ao(*) 1075c------------------------------------------------------------------------ 1076c this subroutine extracts the upper triangular part of a matrix 1077c and writes the result ao, jao, iao. The routine is in place in 1078c that ao, jao, iao can be the same as a, ja, ia if desired. 1079c----------- 1080c on input: 1081c 1082c n = dimension of the matrix a. 1083c a, ja, 1084c ia = matrix stored in a, ja, ia, format 1085c On return: 1086c ao, jao, 1087c iao = upper triangular matrix (upper part of a) 1088c stored in compressed sparse row format 1089c note: the diagonal element is the last element in each row. 1090c i.e. in a(ia(i+1)-1 ) 1091c ao, jao, iao may be the same as a, ja, ia on entry -- in which case 1092c getu will overwrite the result on a, ja, ia. 1093c 1094c------------------------------------------------------------------------ 1095c local variables 1096 real*8 t 1097 integer ko, k, i, kdiag, kfirst 1098 ko = 0 1099 do 7 i=1, n 1100 kfirst = ko+1 1101 kdiag = 0 1102 do 71 k = ia(i), ia(i+1) -1 1103 if (ja(k) .lt. i) goto 71 1104 ko = ko+1 1105 ao(ko) = a(k) 1106 jao(ko) = ja(k) 1107 if (ja(k) .eq. i) kdiag = ko 1108 71 continue 1109 if (kdiag .eq. 0 .or. kdiag .eq. kfirst) goto 72 1110c exchange 1111 t = ao(kdiag) 1112 ao(kdiag) = ao(kfirst) 1113 ao(kfirst) = t 1114c 1115 k = jao(kdiag) 1116 jao(kdiag) = jao(kfirst) 1117 jao(kfirst) = k 1118 72 iao(i) = kfirst 1119 7 continue 1120c redefine iao(n+1) 1121 iao(n+1) = ko+1 1122 return 1123c----------end-of-getu ------------------------------------------------- 1124c----------------------------------------------------------------------- 1125 end 1126c----------------------------------------------------------------------- 1127 subroutine levels (n, jal, ial, nlev, lev, ilev, levnum) 1128 integer jal(*),ial(*), levnum(*), ilev(*), lev(*) 1129c----------------------------------------------------------------------- 1130c levels gets the level structure of a lower triangular matrix 1131c for level scheduling in the parallel solution of triangular systems 1132c strict lower matrices (e.g. unit) as well matrices with their main 1133c diagonal are accepted. 1134c----------------------------------------------------------------------- 1135c on entry: 1136c---------- 1137c n = integer. The row dimension of the matrix 1138c jal, ial = 1139c 1140c on return: 1141c----------- 1142c nlev = integer. number of levels found 1143c lev = integer array of length n containing the level 1144c scheduling permutation. 1145c ilev = integer array. pointer to beginning of levels in lev. 1146c the numbers lev(i) to lev(i+1)-1 contain the row numbers 1147c that belong to level number i, in the level scheduling 1148c ordering. The equations of the same level can be solved 1149c in parallel, once those of all the previous levels have 1150c been solved. 1151c work arrays: 1152c------------- 1153c levnum = integer array of length n (containing the level numbers 1154c of each unknown on return) 1155c----------------------------------------------------------------------- 1156 do 10 i = 1, n 1157 levnum(i) = 0 1158 10 continue 1159c 1160c compute level of each node -- 1161c 1162 nlev = 0 1163 do 20 i = 1, n 1164 levi = 0 1165 do 15 j = ial(i), ial(i+1) - 1 1166 levi = max (levi, levnum(jal(j))) 1167 15 continue 1168 levi = levi+1 1169 levnum(i) = levi 1170 nlev = max(nlev,levi) 1171 20 continue 1172c-------------set data structure -------------------------------------- 1173 do 21 j=1, nlev+1 1174 ilev(j) = 0 1175 21 continue 1176c------count number of elements in each level ----------------------- 1177 do 22 j=1, n 1178 i = levnum(j)+1 1179 ilev(i) = ilev(i)+1 1180 22 continue 1181c---- set up pointer for each level ---------------------------------- 1182 ilev(1) = 1 1183 do 23 j=1, nlev 1184 ilev(j+1) = ilev(j)+ilev(j+1) 1185 23 continue 1186 1187c-----determine elements of each level -------------------------------- 1188 do 30 j=1,n 1189 i = levnum(j) 1190 lev(ilev(i)) = j 1191 ilev(i) = ilev(i)+1 1192 30 continue 1193c reset pointers backwards 1194 do 35 j=nlev, 1, -1 1195 ilev(j+1) = ilev(j) 1196 35 continue 1197 ilev(1) = 1 1198 return 1199c----------end-of-levels------------------------------------------------ 1200C----------------------------------------------------------------------- 1201 end 1202c----------------------------------------------------------------------- 1203 subroutine amask (nrow,ncol,a,ja,ia,jmask,imask, 1204 * c,jc,ic,iw,nzmax,ierr) 1205c--------------------------------------------------------------------- 1206 real*8 a(*),c(*) 1207 integer ia(nrow+1),ja(*),jc(*),ic(nrow+1),jmask(*),imask(nrow+1) 1208 logical iw(ncol) 1209c----------------------------------------------------------------------- 1210c This subroutine builds a sparse matrix from an input matrix by 1211c extracting only elements in positions defined by the mask jmask, imask 1212c----------------------------------------------------------------------- 1213c On entry: 1214c--------- 1215c nrow = integer. row dimension of input matrix 1216c ncol = integer. Column dimension of input matrix. 1217c 1218c a, 1219c ja, 1220c ia = matrix in Compressed Sparse Row format 1221c 1222c jmask, 1223c imask = matrix defining mask (pattern only) stored in compressed 1224c sparse row format. 1225c 1226c nzmax = length of arrays c and jc. see ierr. 1227c 1228c On return: 1229c----------- 1230c 1231c a, ja, ia and jmask, imask are unchanged. 1232c 1233c c 1234c jc, 1235c ic = the output matrix in Compressed Sparse Row format. 1236c 1237c ierr = integer. serving as error message.c 1238c ierr = 1 means normal return 1239c ierr .gt. 1 means that amask stopped when processing 1240c row number ierr, because there was not enough space in 1241c c, jc according to the value of nzmax. 1242c 1243c work arrays: 1244c------------- 1245c iw = logical work array of length ncol. 1246c 1247c note: 1248c------ the algorithm is in place: c, jc, ic can be the same as 1249c a, ja, ia in which cas the code will overwrite the matrix c 1250c on a, ja, ia 1251c 1252c----------------------------------------------------------------------- 1253 ierr = 0 1254 len = 0 1255 do 1 j=1, ncol 1256 iw(j) = .false. 1257 1 continue 1258c unpack the mask for row ii in iw 1259 do 100 ii=1, nrow 1260c save pointer in order to be able to do things in place 1261 do 2 k=imask(ii), imask(ii+1)-1 1262 iw(jmask(k)) = .true. 1263 2 continue 1264c add umasked elemnts of row ii 1265 k1 = ia(ii) 1266 k2 = ia(ii+1)-1 1267 ic(ii) = len+1 1268 do 200 k=k1,k2 1269 j = ja(k) 1270 if (iw(j)) then 1271 len = len+1 1272 if (len .gt. nzmax) then 1273 ierr = ii 1274 return 1275 endif 1276 jc(len) = j 1277 c(len) = a(k) 1278 endif 1279 200 continue 1280c 1281 do 3 k=imask(ii), imask(ii+1)-1 1282 iw(jmask(k)) = .false. 1283 3 continue 1284 100 continue 1285 ic(nrow+1)=len+1 1286c 1287 return 1288c-----end-of-amask ----------------------------------------------------- 1289c----------------------------------------------------------------------- 1290 end 1291c----------------------------------------------------------------------- 1292 subroutine rperm (nrow,a,ja,ia,ao,jao,iao,perm,job) 1293 integer nrow,ja(*),ia(nrow+1),jao(*),iao(nrow+1),perm(nrow),job 1294 real*8 a(*),ao(*) 1295c----------------------------------------------------------------------- 1296c this subroutine permutes the rows of a matrix in CSR format. 1297c rperm computes B = P A where P is a permutation matrix. 1298c the permutation P is defined through the array perm: for each j, 1299c perm(j) represents the destination row number of row number j. 1300c Youcef Saad -- recoded Jan 28, 1991. 1301c----------------------------------------------------------------------- 1302c on entry: 1303c---------- 1304c n = dimension of the matrix 1305c a, ja, ia = input matrix in csr format 1306c perm = integer array of length nrow containing the permutation arrays 1307c for the rows: perm(i) is the destination of row i in the 1308c permuted matrix. 1309c ---> a(i,j) in the original matrix becomes a(perm(i),j) 1310c in the output matrix. 1311c 1312c job = integer indicating the work to be done: 1313c job = 1 permute a, ja, ia into ao, jao, iao 1314c (including the copying of real values ao and 1315c the array iao). 1316c job .ne. 1 : ignore real values. 1317c (in which case arrays a and ao are not needed nor 1318c used). 1319c 1320c------------ 1321c on return: 1322c------------ 1323c ao, jao, iao = input matrix in a, ja, ia format 1324c note : 1325c if (job.ne.1) then the arrays a and ao are not used. 1326c----------------------------------------------------------------------c 1327c Y. Saad, May 2, 1990 c 1328c----------------------------------------------------------------------c 1329 logical values 1330 values = (job .eq. 1) 1331c 1332c determine pointers for output matix. 1333c 1334 do 50 j=1,nrow 1335 i = perm(j) 1336 iao(i+1) = ia(j+1) - ia(j) 1337 50 continue 1338c 1339c get pointers from lengths 1340c 1341 iao(1) = 1 1342 do 51 j=1,nrow 1343 iao(j+1)=iao(j+1)+iao(j) 1344 51 continue 1345c 1346c copying 1347c 1348 do 100 ii=1,nrow 1349c 1350c old row = ii -- new row = iperm(ii) -- ko = new pointer 1351c 1352 ko = iao(perm(ii)) 1353 do 60 k=ia(ii), ia(ii+1)-1 1354 jao(ko) = ja(k) 1355 if (values) ao(ko) = a(k) 1356 ko = ko+1 1357 60 continue 1358 100 continue 1359c 1360 return 1361c---------end-of-rperm ------------------------------------------------- 1362c----------------------------------------------------------------------- 1363 end 1364c----------------------------------------------------------------------- 1365 subroutine cperm (nrow,a,ja,ia,ao,jao,iao,perm,job) 1366 integer nrow,ja(*),ia(nrow+1),jao(*),iao(nrow+1),perm(*), job 1367 real*8 a(*), ao(*) 1368c----------------------------------------------------------------------- 1369c this subroutine permutes the columns of a matrix a, ja, ia. 1370c the result is written in the output matrix ao, jao, iao. 1371c cperm computes B = A P, where P is a permutation matrix 1372c that maps column j into column perm(j), i.e., on return 1373c a(i,j) becomes a(i,perm(j)) in new matrix 1374c Y. Saad, May 2, 1990 / modified Jan. 28, 1991. 1375c----------------------------------------------------------------------- 1376c on entry: 1377c---------- 1378c nrow = row dimension of the matrix 1379c 1380c a, ja, ia = input matrix in csr format. 1381c 1382c perm = integer array of length ncol (number of columns of A 1383c containing the permutation array the columns: 1384c a(i,j) in the original matrix becomes a(i,perm(j)) 1385c in the output matrix. 1386c 1387c job = integer indicating the work to be done: 1388c job = 1 permute a, ja, ia into ao, jao, iao 1389c (including the copying of real values ao and 1390c the array iao). 1391c job .ne. 1 : ignore real values ao and ignore iao. 1392c 1393c------------ 1394c on return: 1395c------------ 1396c ao, jao, iao = input matrix in a, ja, ia format (array ao not needed) 1397c 1398c Notes: 1399c------- 1400c 1. if job=1 then ao, iao are not used. 1401c 2. This routine is in place: ja, jao can be the same. 1402c 3. If the matrix is initially sorted (by increasing column number) 1403c then ao,jao,iao may not be on return. 1404c 1405c----------------------------------------------------------------------c 1406c local parameters: 1407 integer k, i, nnz 1408c 1409 nnz = ia(nrow+1)-1 1410 do 100 k=1,nnz 1411 jao(k) = perm(ja(k)) 1412 100 continue 1413c 1414c done with ja array. return if no need to touch values. 1415c 1416 if (job .ne. 1) return 1417c 1418c else get new pointers -- and copy values too. 1419c 1420 do 1 i=1, nrow+1 1421 iao(i) = ia(i) 1422 1 continue 1423c 1424 do 2 k=1, nnz 1425 ao(k) = a(k) 1426 2 continue 1427c 1428 return 1429c---------end-of-cperm-------------------------------------------------- 1430c----------------------------------------------------------------------- 1431 end 1432c----------------------------------------------------------------------- 1433 subroutine dperm (nrow,a,ja,ia,ao,jao,iao,perm,qperm,job) 1434 integer nrow,ja(*),ia(nrow+1),jao(*),iao(nrow+1),perm(nrow), 1435 + qperm(*),job 1436 real*8 a(*),ao(*) 1437c----------------------------------------------------------------------- 1438c This routine permutes the rows and columns of a matrix stored in CSR 1439c format. i.e., it computes P A Q, where P, Q are permutation matrices. 1440c P maps row i into row perm(i) and Q maps column j into column qperm(j): 1441c a(i,j) becomes a(perm(i),qperm(j)) in new matrix 1442c In the particular case where Q is the transpose of P (symmetric 1443c permutation of A) then qperm is not needed. 1444c note that qperm should be of length ncol (number of columns) but this 1445c is not checked. 1446c----------------------------------------------------------------------- 1447c Y. Saad, Sep. 21 1989 / recoded Jan. 28 1991. 1448c----------------------------------------------------------------------- 1449c on entry: 1450c---------- 1451c n = dimension of the matrix 1452c a, ja, 1453c ia = input matrix in a, ja, ia format 1454c perm = integer array of length n containing the permutation arrays 1455c for the rows: perm(i) is the destination of row i in the 1456c permuted matrix -- also the destination of column i in case 1457c permutation is symmetric (job .le. 2) 1458c 1459c qperm = same thing for the columns. This should be provided only 1460c if job=3 or job=4, i.e., only in the case of a nonsymmetric 1461c permutation of rows and columns. Otherwise qperm is a dummy 1462c 1463c job = integer indicating the work to be done: 1464c * job = 1,2 permutation is symmetric Ao :== P * A * transp(P) 1465c job = 1 permute a, ja, ia into ao, jao, iao 1466c job = 2 permute matrix ignoring real values. 1467c * job = 3,4 permutation is non-symmetric Ao :== P * A * Q 1468c job = 3 permute a, ja, ia into ao, jao, iao 1469c job = 4 permute matrix ignoring real values. 1470c 1471c on return: 1472c----------- 1473c ao, jao, iao = input matrix in a, ja, ia format 1474c 1475c in case job .eq. 2 or job .eq. 4, a and ao are never referred to 1476c and can be dummy arguments. 1477c Notes: 1478c------- 1479c 1) algorithm is in place 1480c 2) column indices may not be sorted on return even though they may be 1481c on entry. 1482c----------------------------------------------------------------------c 1483c local variables 1484 integer locjob, mod 1485c 1486c locjob indicates whether or not real values must be copied. 1487c 1488 locjob = mod(job,2) 1489c 1490c permute rows first 1491c 1492 call rperm (nrow,a,ja,ia,ao,jao,iao,perm,locjob) 1493c 1494c then permute columns 1495c 1496 locjob = 0 1497c 1498 if (job .le. 2) then 1499 call cperm (nrow,ao,jao,iao,ao,jao,iao,perm,locjob) 1500 else 1501 call cperm (nrow,ao,jao,iao,ao,jao,iao,qperm,locjob) 1502 endif 1503c 1504 return 1505c-------end-of-dperm---------------------------------------------------- 1506c----------------------------------------------------------------------- 1507 end 1508c----------------------------------------------------------------------- 1509 subroutine dperm1 (i1,i2,a,ja,ia,b,jb,ib,perm,ipos,job) 1510 integer i1,i2,job,ja(*),ia(*),jb(*),ib(*),perm(*) 1511 real*8 a(*),b(*) 1512c----------------------------------------------------------------------- 1513c general submatrix extraction routine. 1514c----------------------------------------------------------------------- 1515c extracts rows perm(i1), perm(i1+1), ..., perm(i2) (in this order) 1516c from a matrix (doing nothing in the column indices.) The resulting 1517c submatrix is constructed in b, jb, ib. A pointer ipos to the 1518c beginning of arrays b,jb,is also allowed (i.e., nonzero elements 1519c are accumulated starting in position ipos of b, jb). 1520c----------------------------------------------------------------------- 1521c Y. Saad,Sep. 21 1989 / recoded Jan. 28 1991 / modified for PSPARSLIB 1522c Sept. 1997.. 1523c----------------------------------------------------------------------- 1524c on entry: 1525c---------- 1526c n = dimension of the matrix 1527c a,ja, 1528c ia = input matrix in CSR format 1529c perm = integer array of length n containing the indices of the rows 1530c to be extracted. 1531c 1532c job = job indicator. if (job .ne.1) values are not copied (i.e., 1533c only pattern is copied). 1534c 1535c on return: 1536c----------- 1537c b,ja, 1538c ib = matrix in csr format. b(ipos:ipos+nnz-1),jb(ipos:ipos+nnz-1) 1539c contain the value and column indices respectively of the nnz 1540c nonzero elements of the permuted matrix. thus ib(1)=ipos. 1541c 1542c Notes: 1543c------- 1544c algorithm is NOT in place 1545c----------------------------------------------------------------------- 1546c local variables 1547c 1548 integer ko,irow,k 1549 logical values 1550c----------------------------------------------------------------------- 1551 values = (job .eq. 1) 1552 ko = ipos 1553 ib(1) = ko 1554 do 900 i=i1,i2 1555 irow = perm(i) 1556 do 800 k=ia(irow),ia(irow+1)-1 1557 if (values) b(ko) = a(k) 1558 jb(ko) = ja(k) 1559 ko=ko+1 1560 800 continue 1561 ib(i-i1+2) = ko 1562 900 continue 1563 return 1564c--------end-of-dperm1-------------------------------------------------- 1565c----------------------------------------------------------------------- 1566 end 1567c----------------------------------------------------------------------- 1568 subroutine dperm2 (i1,i2,a,ja,ia,b,jb,ib,cperm,rperm,istart, 1569 * ipos,job) 1570 integer i1,i2,job,istart,ja(*),ia(*),jb(*),ib(*),cperm(*),rperm(*) 1571 real*8 a(*),b(*) 1572c----------------------------------------------------------------------- 1573c general submatrix permutation/ extraction routine. 1574c----------------------------------------------------------------------- 1575c extracts rows rperm(i1), rperm(i1+1), ..., rperm(i2) and does an 1576c associated column permutation (using array cperm). The resulting 1577c submatrix is constructed in b, jb, ib. For added flexibility, the 1578c extracted elements are put in sequence starting from row 'istart' 1579c of B. In addition a pointer ipos to the beginning of arrays b,jb, 1580c is also allowed (i.e., nonzero elements are accumulated starting in 1581c position ipos of b, jb). In most applications istart and ipos are 1582c equal to one. However, the generality adds substantial flexiblity. 1583c EXPLE: (1) to permute msr to msr (excluding diagonals) 1584c call dperm2 (1,n,a,ja,ja,b,jb,jb,rperm,rperm,1,n+2) 1585c (2) To extract rows 1 to 10: define rperm and cperm to be 1586c identity permutations (rperm(i)=i, i=1,n) and then 1587c call dperm2 (1,10,a,ja,ia,b,jb,ib,rperm,rperm,1,1) 1588c (3) to achieve a symmetric permutation as defined by perm: 1589c call dperm2 (1,10,a,ja,ia,b,jb,ib,perm,perm,1,1) 1590c (4) to get a symmetric permutation of A and append the 1591c resulting data structure to A's data structure (useful!) 1592c call dperm2 (1,10,a,ja,ia,a,ja,ia(n+1),perm,perm,1,ia(n+1)) 1593c----------------------------------------------------------------------- 1594c Y. Saad,Sep. 21 1989 / recoded Jan. 28 1991. 1595c----------------------------------------------------------------------- 1596c on entry: 1597c---------- 1598c n = dimension of the matrix 1599c i1,i2 = extract rows rperm(i1) to rperm(i2) of A, with i1<i2. 1600c 1601c a,ja, 1602c ia = input matrix in CSR format 1603c cperm = integer array of length n containing the permutation arrays 1604c for the columns: cperm(i) is the destination of column j, 1605c i.e., any column index ja(k) is transformed into cperm(ja(k)) 1606c 1607c rperm = permutation array for the rows. rperm(i) = origin (in A) of 1608c row i in B. This is the reverse permutation relative to the 1609c ones used in routines cperm, dperm,.... 1610c rows rperm(i1), rperm(i1)+1, ... rperm(i2) are 1611c extracted from A and stacked into B, starting in row istart 1612c of B. 1613c istart= starting row for B where extracted matrix is to be added. 1614c this is also only a pointer of the be beginning address for 1615c ib , on return. 1616c ipos = beginning position in arrays b and jb where to start copying 1617c elements. Thus, ib(istart) = ipos. 1618c 1619c job = job indicator. if (job .ne.1) values are not copied (i.e., 1620c only pattern is copied). 1621c 1622c on return: 1623c----------- 1624c b,ja, 1625c ib = matrix in csr format. positions 1,2,...,istart-1 of ib 1626c are not touched. b(ipos:ipos+nnz-1),jb(ipos:ipos+nnz-1) 1627c contain the value and column indices respectively of the nnz 1628c nonzero elements of the permuted matrix. thus ib(istart)=ipos. 1629c 1630c Notes: 1631c------- 1632c 1) algorithm is NOT in place 1633c 2) column indices may not be sorted on return even though they 1634c may be on entry. 1635c----------------------------------------------------------------------- 1636c local variables 1637c 1638 integer ko,irow,k 1639 logical values 1640c----------------------------------------------------------------------- 1641 values = (job .eq. 1) 1642 ko = ipos 1643 ib(istart) = ko 1644 do 900 i=i1,i2 1645 irow = rperm(i) 1646 do 800 k=ia(irow),ia(irow+1)-1 1647 if (values) b(ko) = a(k) 1648 jb(ko) = cperm(ja(k)) 1649 ko=ko+1 1650 800 continue 1651 ib(istart+i-i1+1) = ko 1652 900 continue 1653 return 1654c--------end-of-dperm2-------------------------------------------------- 1655c----------------------------------------------------------------------- 1656 end 1657c----------------------------------------------------------------------- 1658 subroutine dmperm (nrow,a,ja,ao,jao,perm,job) 1659 integer nrow,ja(*),jao(*),perm(nrow),job 1660 real*8 a(*),ao(*) 1661c----------------------------------------------------------------------- 1662c This routine performs a symmetric permutation of the rows and 1663c columns of a matrix stored in MSR format. i.e., it computes 1664c B = P A transp(P), where P, is a permutation matrix. 1665c P maps row i into row perm(i) and column j into column perm(j): 1666c a(i,j) becomes a(perm(i),perm(j)) in new matrix 1667c (i.e. ao(perm(i),perm(j)) = a(i,j) ) 1668c calls dperm. 1669c----------------------------------------------------------------------- 1670c Y. Saad, Nov 15, 1991. 1671c----------------------------------------------------------------------- 1672c on entry: 1673c---------- 1674c n = dimension of the matrix 1675c a, ja = input matrix in MSR format. 1676c perm = integer array of length n containing the permutation arrays 1677c for the rows: perm(i) is the destination of row i in the 1678c permuted matrix -- also the destination of column i in case 1679c permutation is symmetric (job .le. 2) 1680c 1681c job = integer indicating the work to be done: 1682c job = 1 permute a, ja, ia into ao, jao, iao 1683c job = 2 permute matrix ignoring real values. 1684c 1685c on return: 1686c----------- 1687c ao, jao = output matrix in MSR. 1688c 1689c in case job .eq. 2 a and ao are never referred to and can be dummy 1690c arguments. 1691c 1692c Notes: 1693c------- 1694c 1) algorithm is NOT in place 1695c 2) column indices may not be sorted on return even though they may be 1696c on entry. 1697c----------------------------------------------------------------------c 1698c local variables 1699c 1700 integer n1, n2 1701 n1 = nrow+1 1702 n2 = n1+1 1703c 1704 call dperm (nrow,a,ja,ja,ao(n2),jao(n2),jao,perm,perm,job) 1705c 1706 jao(1) = n2 1707 do 101 j=1, nrow 1708 ao(perm(j)) = a(j) 1709 jao(j+1) = jao(j+1)+n1 1710 101 continue 1711c 1712c done 1713c 1714 return 1715c----------------------------------------------------------------------- 1716c--------end-of-dmperm-------------------------------------------------- 1717 end 1718c----------------------------------------------------------------------- 1719 subroutine dvperm (n, x, perm) 1720 integer n, perm(n) 1721 real*8 x(n) 1722c----------------------------------------------------------------------- 1723c this subroutine performs an in-place permutation of a real vector x 1724c according to the permutation array perm(*), i.e., on return, 1725c the vector x satisfies, 1726c 1727c x(perm(j)) :== x(j), j=1,2,.., n 1728c 1729c----------------------------------------------------------------------- 1730c on entry: 1731c--------- 1732c n = length of vector x. 1733c perm = integer array of length n containing the permutation array. 1734c x = input vector 1735c 1736c on return: 1737c---------- 1738c x = vector x permuted according to x(perm(*)) := x(*) 1739c 1740c----------------------------------------------------------------------c 1741c Y. Saad, Sep. 21 1989 c 1742c----------------------------------------------------------------------c 1743c local variables 1744 real*8 tmp, tmp1 1745c 1746 init = 1 1747 tmp = x(init) 1748 ii = perm(init) 1749 perm(init)= -perm(init) 1750 k = 0 1751c 1752c loop 1753c 1754 6 k = k+1 1755c 1756c save the chased element -- 1757c 1758 tmp1 = x(ii) 1759 x(ii) = tmp 1760 next = perm(ii) 1761 if (next .lt. 0 ) goto 65 1762c 1763c test for end 1764c 1765 if (k .gt. n) goto 101 1766 tmp = tmp1 1767 perm(ii) = - perm(ii) 1768 ii = next 1769c 1770c end loop 1771c 1772 goto 6 1773c 1774c reinitilaize cycle -- 1775c 1776 65 init = init+1 1777 if (init .gt. n) goto 101 1778 if (perm(init) .lt. 0) goto 65 1779 tmp = x(init) 1780 ii = perm(init) 1781 perm(init)=-perm(init) 1782 goto 6 1783c 1784 101 continue 1785 do 200 j=1, n 1786 perm(j) = -perm(j) 1787 200 continue 1788c 1789 return 1790c-------------------end-of-dvperm--------------------------------------- 1791c----------------------------------------------------------------------- 1792 end 1793c----------------------------------------------------------------------- 1794 subroutine ivperm (n, ix, perm) 1795 integer n, perm(n), ix(n) 1796c----------------------------------------------------------------------- 1797c this subroutine performs an in-place permutation of an integer vector 1798c ix according to the permutation array perm(*), i.e., on return, 1799c the vector x satisfies, 1800c 1801c ix(perm(j)) :== ix(j), j=1,2,.., n 1802c 1803c----------------------------------------------------------------------- 1804c on entry: 1805c--------- 1806c n = length of vector x. 1807c perm = integer array of length n containing the permutation array. 1808c ix = input vector 1809c 1810c on return: 1811c---------- 1812c ix = vector x permuted according to ix(perm(*)) := ix(*) 1813c 1814c----------------------------------------------------------------------c 1815c Y. Saad, Sep. 21 1989 c 1816c----------------------------------------------------------------------c 1817c local variables 1818 integer tmp, tmp1 1819c 1820 init = 1 1821 tmp = ix(init) 1822 ii = perm(init) 1823 perm(init)= -perm(init) 1824 k = 0 1825c 1826c loop 1827c 1828 6 k = k+1 1829c 1830c save the chased element -- 1831c 1832 tmp1 = ix(ii) 1833 ix(ii) = tmp 1834 next = perm(ii) 1835 if (next .lt. 0 ) goto 65 1836c 1837c test for end 1838c 1839 if (k .gt. n) goto 101 1840 tmp = tmp1 1841 perm(ii) = - perm(ii) 1842 ii = next 1843c 1844c end loop 1845c 1846 goto 6 1847c 1848c reinitilaize cycle -- 1849c 1850 65 init = init+1 1851 if (init .gt. n) goto 101 1852 if (perm(init) .lt. 0) goto 65 1853 tmp = ix(init) 1854 ii = perm(init) 1855 perm(init)=-perm(init) 1856 goto 6 1857c 1858 101 continue 1859 do 200 j=1, n 1860 perm(j) = -perm(j) 1861 200 continue 1862c 1863 return 1864c-------------------end-of-ivperm--------------------------------------- 1865c----------------------------------------------------------------------- 1866 end 1867c----------------------------------------------------------------------- 1868 subroutine retmx (n,a,ja,ia,dd) 1869 real*8 a(*),dd(*) 1870 integer n,ia(*),ja(*) 1871c----------------------------------------------------------------------- 1872c returns in dd(*) the max absolute value of elements in row *. 1873c used for scaling purposes. superseded by rnrms . 1874c 1875c on entry: 1876c n = dimension of A 1877c a,ja,ia 1878c = matrix stored in compressed sparse row format 1879c dd = real*8 array of length n. On output,entry dd(i) contains 1880c the element of row i that has the largest absolute value. 1881c Moreover the sign of dd is modified such that it is the 1882c same as that of the diagonal element in row i. 1883c----------------------------------------------------------------------c 1884c Y. Saad, Sep. 21 1989 c 1885c----------------------------------------------------------------------c 1886c local variables 1887 integer k2, i, k1, k 1888 real*8 t, t1, t2 1889c 1890c initialize 1891c 1892 k2 = 1 1893 do 11 i=1,n 1894 k1 = k2 1895 k2 = ia(i+1) - 1 1896 t = 0.0d0 1897 do 101 k=k1,k2 1898 t1 = abs(a(k)) 1899 if (t1 .gt. t) t = t1 1900 if (ja(k) .eq. i) then 1901 if (a(k) .ge. 0.0) then 1902 t2 = a(k) 1903 else 1904 t2 = - a(k) 1905 endif 1906 endif 1907 101 continue 1908 dd(i) = t2*t 1909c we do not invert diag 1910 11 continue 1911 return 1912c---------end of retmx ------------------------------------------------- 1913c----------------------------------------------------------------------- 1914 end 1915c----------------------------------------------------------------------- 1916 subroutine diapos (n,ja,ia,idiag) 1917 integer ia(n+1), ja(*), idiag(n) 1918c----------------------------------------------------------------------- 1919c this subroutine returns the positions of the diagonal elements of a 1920c sparse matrix a, ja, ia, in the array idiag. 1921c----------------------------------------------------------------------- 1922c on entry: 1923c---------- 1924c 1925c n = integer. row dimension of the matrix a. 1926c a,ja, 1927c ia = matrix stored compressed sparse row format. a array skipped. 1928c 1929c on return: 1930c----------- 1931c idiag = integer array of length n. The i-th entry of idiag 1932c points to the diagonal element a(i,i) in the arrays 1933c a, ja. (i.e., a(idiag(i)) = element A(i,i) of matrix A) 1934c if no diagonal element is found the entry is set to 0. 1935c----------------------------------------------------------------------c 1936c Y. Saad, March, 1990 1937c----------------------------------------------------------------------c 1938 do 1 i=1, n 1939 idiag(i) = 0 1940 1 continue 1941c 1942c sweep through data structure. 1943c 1944 do 6 i=1,n 1945 do 51 k= ia(i),ia(i+1) -1 1946 if (ja(k) .eq. i) idiag(i) = k 1947 51 continue 1948 6 continue 1949c----------- -end-of-diapos--------------------------------------------- 1950c----------------------------------------------------------------------- 1951 return 1952 end 1953c----------------------------------------------------------------------- 1954 subroutine dscaldg (n,a,ja,ia,diag,job) 1955 real*8 a(*), diag(*),t 1956 integer ia(*),ja(*) 1957c----------------------------------------------------------------------- 1958c scales rows by diag where diag is either given (job=0) 1959c or to be computed: 1960c job = 1 ,scale row i by by +/- max |a(i,j) | and put inverse of 1961c scaling factor in diag(i),where +/- is the sign of a(i,i). 1962c job = 2 scale by 2-norm of each row.. 1963c if diag(i) = 0,then diag(i) is replaced by one 1964c (no scaling).. 1965c----------------------------------------------------------------------c 1966c Y. Saad, Sep. 21 1989 c 1967c----------------------------------------------------------------------c 1968 goto (12,11,10) job+1 1969 10 do 110 j=1,n 1970 k1= ia(j) 1971 k2 = ia(j+1)-1 1972 t = 0.0d0 1973 do 111 k = k1,k2 1974 111 t = t+a(k)*a(k) 1975 110 diag(j) = sqrt(t) 1976 goto 12 1977 11 continue 1978 call retmx (n,a,ja,ia,diag) 1979c------ 1980 12 do 1 j=1,n 1981 if (diag(j) .ne. 0.0d0) then 1982 diag(j) = 1.0d0/diag(j) 1983 else 1984 diag(j) = 1.0d0 1985 endif 1986 1 continue 1987 do 2 i=1,n 1988 t = diag(i) 1989 do 21 k=ia(i),ia(i+1) -1 1990 a(k) = a(k)*t 1991 21 continue 1992 2 continue 1993 return 1994c--------end of dscaldg ----------------------------------------------- 1995c----------------------------------------------------------------------- 1996 end 1997c----------------------------------------------------------------------- 1998 subroutine extbdg (n,a,ja,ia,bdiag,nblk,ao,jao,iao) 1999 implicit real*8 (a-h,o-z) 2000 real*8 bdiag(*),a(*),ao(*) 2001 integer ia(*),ja(*),jao(*),iao(*) 2002c----------------------------------------------------------------------- 2003c this subroutine extracts the main diagonal blocks of a 2004c matrix stored in compressed sparse row format and puts the result 2005c into the array bdiag and the remainder in ao,jao,iao. 2006c----------------------------------------------------------------------- 2007c on entry: 2008c---------- 2009c n = integer. The row dimension of the matrix a. 2010c a, 2011c ja, 2012c ia = matrix stored in csr format 2013c nblk = dimension of each diagonal block. The diagonal blocks are 2014c stored in compressed format rowwise,i.e.,we store in 2015c succession the i nonzeros of the i-th row after those of 2016c row number i-1.. 2017c 2018c on return: 2019c---------- 2020c bdiag = real*8 array of size (n x nblk) containing the diagonal 2021c blocks of A on return 2022c ao, 2023c jao, 2024C iao = remainder of the matrix stored in csr format. 2025c----------------------------------------------------------------------c 2026c Y. Saad, Sep. 21 1989 c 2027c----------------------------------------------------------------------c 2028 m = 1 + (n-1)/nblk 2029c this version is sequential -- there is a more parallel version 2030c that goes through the structure twice .... 2031 ltr = ((nblk-1)*nblk)/2 2032 l = m * ltr 2033 do 1 i=1,l 2034 bdiag(i) = 0.0d0 2035 1 continue 2036 ko = 0 2037 kb = 1 2038 iao(1) = 1 2039c------------------------- 2040 do 11 jj = 1,m 2041 j1 = (jj-1)*nblk+1 2042 j2 = min0 (n,j1+nblk-1) 2043 do 12 j=j1,j2 2044 do 13 i=ia(j),ia(j+1) -1 2045 k = ja(i) 2046 if (k .lt. j1) then 2047 ko = ko+1 2048 ao(ko) = a(i) 2049 jao(ko) = k 2050 else if (k .lt. j) then 2051c kb = (jj-1)*ltr+((j-j1)*(j-j1-1))/2+k-j1+1 2052c bdiag(kb) = a(i) 2053 bdiag(kb+k-j1) = a(i) 2054 endif 2055 13 continue 2056 kb = kb + j-j1 2057 iao(j+1) = ko+1 2058 12 continue 2059 11 continue 2060 return 2061c---------end-of-extbdg------------------------------------------------- 2062c----------------------------------------------------------------------- 2063 end 2064c----------------------------------------------------------------------- 2065 subroutine getbwd(n,a,ja,ia,ml,mu) 2066c----------------------------------------------------------------------- 2067c gets the bandwidth of lower part and upper part of A. 2068c does not assume that A is sorted. 2069c----------------------------------------------------------------------- 2070c on entry: 2071c---------- 2072c n = integer = the row dimension of the matrix 2073c a, ja, 2074c ia = matrix in compressed sparse row format. 2075c 2076c on return: 2077c----------- 2078c ml = integer. The bandwidth of the strict lower part of A 2079c mu = integer. The bandwidth of the strict upper part of A 2080c 2081c Notes: 2082c ===== ml and mu are allowed to be negative or return. This may be 2083c useful since it will tell us whether a band is confined 2084c in the strict upper/lower triangular part. 2085c indeed the definitions of ml and mu are 2086c 2087c ml = max ( (i-j) s.t. a(i,j) .ne. 0 ) 2088c mu = max ( (j-i) s.t. a(i,j) .ne. 0 ) 2089c----------------------------------------------------------------------c 2090c Y. Saad, Sep. 21 1989 c 2091c----------------------------------------------------------------------c 2092 real*8 a(*) 2093 integer ja(*),ia(n+1),ml,mu,ldist,i,k 2094 ml = - n 2095 mu = - n 2096 do 3 i=1,n 2097 do 31 k=ia(i),ia(i+1)-1 2098 ldist = i-ja(k) 2099 ml = max(ml,ldist) 2100 mu = max(mu,-ldist) 2101 31 continue 2102 3 continue 2103 return 2104c---------------end-of-getbwd ------------------------------------------ 2105c----------------------------------------------------------------------- 2106 end 2107c----------------------------------------------------------------------- 2108 subroutine blkfnd (nrow,ja,ia,nblk) 2109c----------------------------------------------------------------------- 2110c This routine attemptps to determine whether or not the input 2111c matrix has a block structure and finds the blocks size 2112c if it does. A block matrix is one which is 2113c comprised of small square dense blocks. If there are zero 2114c elements within the square blocks and the original data structure 2115c takes these zeros into account then blkchk may fail to find the 2116c correct block size. 2117c----------------------------------------------------------------------- 2118c on entry 2119c--------- 2120c nrow = integer equal to the row dimension of the matrix. 2121c ja = integer array containing the column indices of the entries 2122c nonzero entries of the matrix stored by row. 2123c ia = integer array of length nrow + 1 containing the pointers 2124c beginning of each row in array ja. 2125c 2126c nblk = integer containing the assumed value of nblk if job = 0 2127c 2128c on return 2129c---------- 2130c nblk = integer containing the value found for nblk when job = 1. 2131c if imsg .ne. 0 this value is meaningless however. 2132c 2133c----------------------------------------------------------------------c 2134c Y. Saad, Sep. 21 1989 c 2135c----------------------------------------------------------------------c 2136 integer ia(nrow+1),ja(*) 2137c----------------------------------------------------------------------- 2138c first part of code will find candidate block sizes. 2139c criterion used here is a simple one: scan rows and determine groups 2140c of rows that have the same length and such that the first column 2141c number and the last column number are identical. 2142c----------------------------------------------------------------------- 2143 minlen = ia(2)-ia(1) 2144 irow = 1 2145 do 1 i=2,nrow 2146 len = ia(i+1)-ia(i) 2147 if (len .lt. minlen) then 2148 minlen = len 2149 irow = i 2150 endif 2151 1 continue 2152c 2153c ---- candidates are all dividers of minlen 2154c 2155 nblk = 1 2156 if (minlen .le. 1) return 2157c 2158 do 99 iblk = minlen, 1, -1 2159 if (mod(minlen,iblk) .ne. 0) goto 99 2160 len = ia(2) - ia(1) 2161 len0 = len 2162 jfirst = ja(1) 2163 jlast = ja(ia(2)-1) 2164 do 10 jrow = irow+1,irow+nblk-1 2165 i1 = ia(jrow) 2166 i2 = ia(jrow+1)-1 2167 len = i2+1-i1 2168 jf = ja(i1) 2169 jl = ja(i2) 2170 if (len .ne. len0 .or. jf .ne. jfirst .or. 2171 * jl .ne. jlast) goto 99 2172 10 continue 2173c 2174c check for this candidate ---- 2175c 2176 call blkchk (nrow,ja,ia,iblk,imsg) 2177 if (imsg .eq. 0) then 2178c 2179c block size found 2180c 2181 nblk = iblk 2182 return 2183 endif 2184 99 continue 2185c--------end-of-blkfnd ------------------------------------------------- 2186c----------------------------------------------------------------------- 2187 end 2188c----------------------------------------------------------------------- 2189 subroutine blkchk (nrow,ja,ia,nblk,imsg) 2190c----------------------------------------------------------------------- 2191c This routine checks whether the input matrix is a block 2192c matrix with block size of nblk. A block matrix is one which is 2193c comprised of small square dense blocks. If there are zero 2194c elements within the square blocks and the data structure 2195c takes them into account then blkchk may fail to find the 2196c correct block size. 2197c----------------------------------------------------------------------- 2198c on entry 2199c--------- 2200c nrow = integer equal to the row dimension of the matrix. 2201c ja = integer array containing the column indices of the entries 2202c nonzero entries of the matrix stored by row. 2203c ia = integer array of length nrow + 1 containing the pointers 2204c beginning of each row in array ja. 2205c 2206c nblk = integer containing the value of nblk to be checked. 2207c 2208c on return 2209c---------- 2210c 2211c imsg = integer containing a message with the following meaning. 2212c imsg = 0 means that the output value of nblk is a correct 2213c block size. nblk .lt. 0 means nblk not correct 2214c block size. 2215c imsg = -1 : nblk does not divide nrow 2216c imsg = -2 : a starting element in a row is at wrong position 2217c (j .ne. mult*nblk +1 ) 2218c imsg = -3 : nblk does divide a row length - 2219c imsg = -4 : an element is isolated outside a block or 2220c two rows in same group have different lengths 2221c----------------------------------------------------------------------c 2222c Y. Saad, Sep. 21 1989 c 2223c----------------------------------------------------------------------c 2224 integer ia(nrow+1),ja(*) 2225c---------------------------------------------------------------------- 2226c first part of code will find candidate block sizes. 2227c this is not guaranteed to work . so a check is done at the end 2228c the criterion used here is a simple one: 2229c scan rows and determine groups of rows that have the same length 2230c and such that the first column number and the last column number 2231c are identical. 2232c---------------------------------------------------------------------- 2233 imsg = 0 2234 if (nblk .le. 1) return 2235 nr = nrow/nblk 2236 if (nr*nblk .ne. nrow) goto 101 2237c-- main loop --------------------------------------------------------- 2238 irow = 1 2239 do 20 ii=1, nr 2240c i1= starting position for group of nblk rows in original matrix 2241 i1 = ia(irow) 2242 j2 = i1 2243c lena = length of each row in that group in the original matrix 2244 lena = ia(irow+1)-i1 2245c len = length of each block-row in that group in the output matrix 2246 len = lena/nblk 2247 if (len* nblk .ne. lena) goto 103 2248c 2249c for each row 2250c 2251 do 6 i = 1, nblk 2252 irow = irow + 1 2253 if (ia(irow)-ia(irow-1) .ne. lena ) goto 104 2254c 2255c for each block 2256c 2257 do 7 k=0, len-1 2258 jstart = ja(i1+nblk*k)-1 2259 if ( (jstart/nblk)*nblk .ne. jstart) goto 102 2260c 2261c for each column 2262c 2263 do 5 j=1, nblk 2264 if (jstart+j .ne. ja(j2) ) goto 104 2265 j2 = j2+1 2266 5 continue 2267 7 continue 2268 6 continue 2269 20 continue 2270c went through all loops successfully: 2271 return 2272 101 imsg = -1 2273 return 2274 102 imsg = -2 2275 return 2276 103 imsg = -3 2277 return 2278 104 imsg = -4 2279c----------------end of chkblk ----------------------------------------- 2280c----------------------------------------------------------------------- 2281 return 2282 end 2283c----------------------------------------------------------------------- 2284 subroutine infdia (n,ja,ia,ind,idiag) 2285 integer ia(*), ind(*), ja(*) 2286c----------------------------------------------------------------------- 2287c obtains information on the diagonals of A. 2288c----------------------------------------------------------------------- 2289c this subroutine finds the lengths of each of the 2*n-1 diagonals of A 2290c it also outputs the number of nonzero diagonals found. 2291c----------------------------------------------------------------------- 2292c on entry: 2293c---------- 2294c n = dimension of the matrix a. 2295c 2296c a, ..... not needed here. 2297c ja, 2298c ia = matrix stored in csr format 2299c 2300c on return: 2301c----------- 2302c 2303c idiag = integer. number of nonzero diagonals found. 2304c 2305c ind = integer array of length at least 2*n-1. The k-th entry in 2306c ind contains the number of nonzero elements in the diagonal 2307c number k, the numbering beeing from the lowermost diagonal 2308c (bottom-left). In other words ind(k) = length of diagonal 2309c whose offset wrt the main diagonal is = - n + k. 2310c----------------------------------------------------------------------c 2311c Y. Saad, Sep. 21 1989 c 2312c----------------------------------------------------------------------c 2313 n2= n+n-1 2314 do 1 i=1,n2 2315 ind(i) = 0 2316 1 continue 2317 do 3 i=1, n 2318 do 2 k=ia(i),ia(i+1)-1 2319 j = ja(k) 2320 ind(n+j-i) = ind(n+j-i) +1 2321 2 continue 2322 3 continue 2323c count the nonzero ones. 2324 idiag = 0 2325 do 41 k=1, n2 2326 if (ind(k) .ne. 0) idiag = idiag+1 2327 41 continue 2328 return 2329c done 2330c------end-of-infdia --------------------------------------------------- 2331c----------------------------------------------------------------------- 2332 end 2333c----------------------------------------------------------------------- 2334 subroutine amubdg (nrow,ncol,ncolb,ja,ia,jb,ib,ndegr,nnz,iw) 2335 integer ja(*),jb(*),ia(nrow+1),ib(ncol+1),ndegr(nrow),iw(ncolb) 2336c----------------------------------------------------------------------- 2337c gets the number of nonzero elements in each row of A*B and the total 2338c number of nonzero elements in A*B. 2339c----------------------------------------------------------------------- 2340c on entry: 2341c -------- 2342c 2343c nrow = integer. row dimension of matrix A 2344c ncol = integer. column dimension of matrix A = row dimension of 2345c matrix B. 2346c ncolb = integer. the colum dimension of the matrix B. 2347c 2348c ja, ia= row structure of input matrix A: ja = column indices of 2349c the nonzero elements of A stored by rows. 2350c ia = pointer to beginning of each row in ja. 2351c 2352c jb, ib= row structure of input matrix B: jb = column indices of 2353c the nonzero elements of A stored by rows. 2354c ib = pointer to beginning of each row in jb. 2355c 2356c on return: 2357c --------- 2358c ndegr = integer array of length nrow containing the degrees (i.e., 2359c the number of nonzeros in each row of the matrix A * B 2360c 2361c nnz = total number of nonzero elements found in A * B 2362c 2363c work arrays: 2364c------------- 2365c iw = integer work array of length ncolb. 2366c----------------------------------------------------------------------- 2367 do 1 k=1, ncolb 2368 iw(k) = 0 2369 1 continue 2370 2371 do 2 k=1, nrow 2372 ndegr(k) = 0 2373 2 continue 2374c 2375c method used: Transp(A) * A = sum [over i=1, nrow] a(i)^T a(i) 2376c where a(i) = i-th row of A. We must be careful not to add the 2377c elements already accounted for. 2378c 2379c 2380 do 7 ii=1,nrow 2381c 2382c for each row of A 2383c 2384 ldg = 0 2385c 2386c end-of-linked list 2387c 2388 last = -1 2389 do 6 j = ia(ii),ia(ii+1)-1 2390c 2391c row number to be added: 2392c 2393 jr = ja(j) 2394 do 5 k=ib(jr),ib(jr+1)-1 2395 jc = jb(k) 2396 if (iw(jc) .eq. 0) then 2397c 2398c add one element to the linked list 2399c 2400 ldg = ldg + 1 2401 iw(jc) = last 2402 last = jc 2403 endif 2404 5 continue 2405 6 continue 2406 ndegr(ii) = ldg 2407c 2408c reset iw to zero 2409c 2410 do 61 k=1,ldg 2411 j = iw(last) 2412 iw(last) = 0 2413 last = j 2414 61 continue 2415c----------------------------------------------------------------------- 2416 7 continue 2417c 2418 nnz = 0 2419 do 8 ii=1, nrow 2420 nnz = nnz+ndegr(ii) 2421 8 continue 2422c 2423 return 2424c---------------end-of-amubdg ------------------------------------------ 2425c----------------------------------------------------------------------- 2426 end 2427c----------------------------------------------------------------------- 2428 subroutine aplbdg (nrow,ncol,ja,ia,jb,ib,ndegr,nnz,iw) 2429 integer ja(*),jb(*),ia(nrow+1),ib(nrow+1),iw(ncol),ndegr(nrow) 2430c----------------------------------------------------------------------- 2431c gets the number of nonzero elements in each row of A+B and the total 2432c number of nonzero elements in A+B. 2433c----------------------------------------------------------------------- 2434c on entry: 2435c --------- 2436c nrow = integer. The row dimension of A and B 2437c ncol = integer. The column dimension of A and B. 2438c 2439c a, 2440c ja, 2441c ia = Matrix A in compressed sparse row format. 2442c 2443c b, 2444c jb, 2445c ib = Matrix B in compressed sparse row format. 2446c 2447c on return: 2448c---------- 2449c ndegr = integer array of length nrow containing the degrees (i.e., 2450c the number of nonzeros in each row of the matrix A + B. 2451c 2452c nnz = total number of nonzero elements found in A * B 2453c 2454c work arrays: 2455c------------ 2456c iw = integer work array of length equal to ncol. 2457c 2458c----------------------------------------------------------------------- 2459 do 1 k=1, ncol 2460 iw(k) = 0 2461 1 continue 2462c 2463 do 2 k=1, nrow 2464 ndegr(k) = 0 2465 2 continue 2466c 2467 do 7 ii=1,nrow 2468 ldg = 0 2469c 2470c end-of-linked list 2471c 2472 last = -1 2473c 2474c row of A 2475c 2476 do 5 j = ia(ii),ia(ii+1)-1 2477 jr = ja(j) 2478c 2479c add element to the linked list 2480c 2481 ldg = ldg + 1 2482 iw(jr) = last 2483 last = jr 2484 5 continue 2485c 2486c row of B 2487c 2488 do 6 j=ib(ii),ib(ii+1)-1 2489 jc = jb(j) 2490 if (iw(jc) .eq. 0) then 2491c 2492c add one element to the linked list 2493c 2494 ldg = ldg + 1 2495 iw(jc) = last 2496 last = jc 2497 endif 2498 6 continue 2499c done with row ii. 2500 ndegr(ii) = ldg 2501c 2502c reset iw to zero 2503c 2504 do 61 k=1,ldg 2505 j = iw(last) 2506 iw(last) = 0 2507 last = j 2508 61 continue 2509c----------------------------------------------------------------------- 2510 7 continue 2511c 2512 nnz = 0 2513 do 8 ii=1, nrow 2514 nnz = nnz+ndegr(ii) 2515 8 continue 2516 return 2517c----------------end-of-aplbdg ----------------------------------------- 2518c----------------------------------------------------------------------- 2519 end 2520c----------------------------------------------------------------------- 2521 subroutine rnrms (nrow, nrm, a, ja, ia, diag) 2522 real*8 a(*), diag(nrow), scal 2523 integer ja(*), ia(nrow+1) 2524c----------------------------------------------------------------------- 2525c gets the norms of each row of A. (choice of three norms) 2526c----------------------------------------------------------------------- 2527c on entry: 2528c --------- 2529c nrow = integer. The row dimension of A 2530c 2531c nrm = integer. norm indicator. nrm = 1, means 1-norm, nrm =2 2532c means the 2-nrm, nrm = 0 means max norm 2533c 2534c a, 2535c ja, 2536c ia = Matrix A in compressed sparse row format. 2537c 2538c on return: 2539c---------- 2540c 2541c diag = real vector of length nrow containing the norms 2542c 2543c----------------------------------------------------------------- 2544 do 1 ii=1,nrow 2545c 2546c compute the norm if each element. 2547c 2548 scal = 0.0d0 2549 k1 = ia(ii) 2550 k2 = ia(ii+1)-1 2551 if (nrm .eq. 0) then 2552 do 2 k=k1, k2 2553 scal = max(scal,abs(a(k) ) ) 2554 2 continue 2555 elseif (nrm .eq. 1) then 2556 do 3 k=k1, k2 2557 scal = scal + abs(a(k) ) 2558 3 continue 2559 else 2560 do 4 k=k1, k2 2561 scal = scal+a(k)**2 2562 4 continue 2563 endif 2564 if (nrm .eq. 2) scal = sqrt(scal) 2565 diag(ii) = scal 2566 1 continue 2567 return 2568c----------------------------------------------------------------------- 2569c-------------end-of-rnrms---------------------------------------------- 2570 end 2571c----------------------------------------------------------------------- 2572 subroutine cnrms (nrow, nrm, a, ja, ia, diag) 2573 real*8 a(*), diag(nrow) 2574 integer ja(*), ia(nrow+1) 2575c----------------------------------------------------------------------- 2576c gets the norms of each column of A. (choice of three norms) 2577c----------------------------------------------------------------------- 2578c on entry: 2579c --------- 2580c nrow = integer. The row dimension of A 2581c 2582c nrm = integer. norm indicator. nrm = 1, means 1-norm, nrm =2 2583c means the 2-nrm, nrm = 0 means max norm 2584c 2585c a, 2586c ja, 2587c ia = Matrix A in compressed sparse row format. 2588c 2589c on return: 2590c---------- 2591c 2592c diag = real vector of length nrow containing the norms 2593c 2594c----------------------------------------------------------------- 2595 do 10 k=1, nrow 2596 diag(k) = 0.0d0 2597 10 continue 2598 do 1 ii=1,nrow 2599 k1 = ia(ii) 2600 k2 = ia(ii+1)-1 2601 do 2 k=k1, k2 2602 j = ja(k) 2603c update the norm of each column 2604 if (nrm .eq. 0) then 2605 diag(j) = max(diag(j),abs(a(k) ) ) 2606 elseif (nrm .eq. 1) then 2607 diag(j) = diag(j) + abs(a(k) ) 2608 else 2609 diag(j) = diag(j)+a(k)**2 2610 endif 2611 2 continue 2612 1 continue 2613 if (nrm .ne. 2) return 2614 do 3 k=1, nrow 2615 diag(k) = sqrt(diag(k)) 2616 3 continue 2617 return 2618c----------------------------------------------------------------------- 2619c------------end-of-cnrms----------------------------------------------- 2620 end 2621c----------------------------------------------------------------------- 2622 subroutine roscal(nrow,job,nrm,a,ja,ia,diag,b,jb,ib,ierr) 2623 real*8 a(*), b(*), diag(nrow) 2624 integer nrow,job,nrm,ja(*),jb(*),ia(nrow+1),ib(nrow+1),ierr 2625c----------------------------------------------------------------------- 2626c scales the rows of A such that their norms are one on return 2627c 3 choices of norms: 1-norm, 2-norm, max-norm. 2628c----------------------------------------------------------------------- 2629c on entry: 2630c --------- 2631c nrow = integer. The row dimension of A 2632c 2633c job = integer. job indicator. Job=0 means get array b only 2634c job = 1 means get b, and the integer arrays ib, jb. 2635c 2636c nrm = integer. norm indicator. nrm = 1, means 1-norm, nrm =2 2637c means the 2-nrm, nrm = 0 means max norm 2638c 2639c a, 2640c ja, 2641c ia = Matrix A in compressed sparse row format. 2642c 2643c on return: 2644c---------- 2645c 2646c diag = diagonal matrix stored as a vector containing the matrix 2647c by which the rows have been scaled, i.e., on return 2648c we have B = Diag*A. 2649c 2650c b, 2651c jb, 2652c ib = resulting matrix B in compressed sparse row sparse format. 2653c 2654c ierr = error message. ierr=0 : Normal return 2655c ierr=i > 0 : Row number i is a zero row. 2656c Notes: 2657c------- 2658c 1) The column dimension of A is not needed. 2659c 2) algorithm in place (B can take the place of A). 2660c----------------------------------------------------------------- 2661 call rnrms (nrow,nrm,a,ja,ia,diag) 2662 ierr = 0 2663 do 1 j=1, nrow 2664 if (diag(j) .eq. 0.0d0) then 2665 ierr = j 2666 return 2667 else 2668 diag(j) = 1.0d0/diag(j) 2669 endif 2670 1 continue 2671 call diamua(nrow,job,a,ja,ia,diag,b,jb,ib) 2672 return 2673c-------end-of-roscal--------------------------------------------------- 2674c----------------------------------------------------------------------- 2675 end 2676c----------------------------------------------------------------------- 2677 subroutine coscal(nrow,job,nrm,a,ja,ia,diag,b,jb,ib,ierr) 2678c----------------------------------------------------------------------- 2679 real*8 a(*),b(*),diag(nrow) 2680 integer nrow,job,ja(*),jb(*),ia(nrow+1),ib(nrow+1),ierr 2681c----------------------------------------------------------------------- 2682c scales the columns of A such that their norms are one on return 2683c result matrix written on b, or overwritten on A. 2684c 3 choices of norms: 1-norm, 2-norm, max-norm. in place. 2685c----------------------------------------------------------------------- 2686c on entry: 2687c --------- 2688c nrow = integer. The row dimension of A 2689c 2690c job = integer. job indicator. Job=0 means get array b only 2691c job = 1 means get b, and the integer arrays ib, jb. 2692c 2693c nrm = integer. norm indicator. nrm = 1, means 1-norm, nrm =2 2694c means the 2-nrm, nrm = 0 means max norm 2695c 2696c a, 2697c ja, 2698c ia = Matrix A in compressed sparse row format. 2699c 2700c on return: 2701c---------- 2702c 2703c diag = diagonal matrix stored as a vector containing the matrix 2704c by which the columns have been scaled, i.e., on return 2705c we have B = A * Diag 2706c 2707c b, 2708c jb, 2709c ib = resulting matrix B in compressed sparse row sparse format. 2710c 2711c ierr = error message. ierr=0 : Normal return 2712c ierr=i > 0 : Column number i is a zero row. 2713c Notes: 2714c------- 2715c 1) The column dimension of A is not needed. 2716c 2) algorithm in place (B can take the place of A). 2717c----------------------------------------------------------------- 2718 call cnrms (nrow,nrm,a,ja,ia,diag) 2719 ierr = 0 2720 do 1 j=1, nrow 2721 if (diag(j) .eq. 0.0) then 2722 ierr = j 2723 return 2724 else 2725 diag(j) = 1.0d0/diag(j) 2726 endif 2727 1 continue 2728 call amudia (nrow,job,a,ja,ia,diag,b,jb,ib) 2729 return 2730c--------end-of-coscal-------------------------------------------------- 2731c----------------------------------------------------------------------- 2732 end 2733c----------------------------------------------------------------------- 2734 subroutine addblk(nrowa, ncola, a, ja, ia, ipos, jpos, job, 2735 & nrowb, ncolb, b, jb, ib, nrowc, ncolc, c, jc, ic, nzmx, ierr) 2736c implicit none 2737 integer nrowa, nrowb, nrowc, ncola, ncolb, ncolc, ipos, jpos 2738 integer nzmx, ierr, job 2739 integer ja(1:*), ia(1:*), jb(1:*), ib(1:*), jc(1:*), ic(1:*) 2740 real*8 a(1:*), b(1:*), c(1:*) 2741c----------------------------------------------------------------------- 2742c This subroutine adds a matrix B into a submatrix of A whose 2743c (1,1) element is located in the starting position (ipos, jpos). 2744c The resulting matrix is allowed to be larger than A (and B), 2745c and the resulting dimensions nrowc, ncolc will be redefined 2746c accordingly upon return. 2747c The input matrices are assumed to be sorted, i.e. in each row 2748c the column indices appear in ascending order in the CSR format. 2749c----------------------------------------------------------------------- 2750c on entry: 2751c --------- 2752c nrowa = number of rows in A. 2753c bcola = number of columns in A. 2754c a,ja,ia = Matrix A in compressed sparse row format with entries sorted 2755c nrowb = number of rows in B. 2756c ncolb = number of columns in B. 2757c b,jb,ib = Matrix B in compressed sparse row format with entries sorted 2758c 2759c nzmax = integer. The length of the arrays c and jc. addblk will 2760c stop if the number of nonzero elements in the matrix C 2761c exceeds nzmax. See ierr. 2762c 2763c on return: 2764c---------- 2765c nrowc = number of rows in C. 2766c ncolc = number of columns in C. 2767c c,jc,ic = resulting matrix C in compressed sparse row sparse format 2768c with entries sorted ascendly in each row. 2769c 2770c ierr = integer. serving as error message. 2771c ierr = 0 means normal return, 2772c ierr .gt. 0 means that addblk stopped while computing the 2773c i-th row of C with i=ierr, because the number 2774c of elements in C exceeds nzmax. 2775c 2776c Notes: 2777c------- 2778c this will not work if any of the two input matrices is not sorted 2779c----------------------------------------------------------------------- 2780 logical values 2781 integer i,j1,j2,ka,kb,kc,kamax,kbmax 2782 values = (job .ne. 0) 2783 ierr = 0 2784 nrowc = max(nrowa, nrowb+ipos-1) 2785 ncolc = max(ncola, ncolb+jpos-1) 2786 kc = 1 2787 kbmax = 0 2788 ic(1) = kc 2789c 2790 do 10 i=1, nrowc 2791 if (i.le.nrowa) then 2792 ka = ia(i) 2793 kamax = ia(i+1)-1 2794 else 2795 ka = ia(nrowa+1) 2796 end if 2797 if ((i.ge.ipos).and.((i-ipos).le.nrowb)) then 2798 kb = ib(i-ipos+1) 2799 kbmax = ib(i-ipos+2)-1 2800 else 2801 kb = ib(nrowb+1) 2802 end if 2803c 2804c a do-while type loop -- goes through all the elements in a row. 2805c 2806 20 continue 2807 if (ka .le. kamax) then 2808 j1 = ja(ka) 2809 else 2810 j1 = ncolc+1 2811 endif 2812 if (kb .le. kbmax) then 2813 j2 = jb(kb) + jpos - 1 2814 else 2815 j2 = ncolc+1 2816 endif 2817c 2818c if there are more elements to be added. 2819c 2820 if ((ka .le. kamax .or. kb .le. kbmax) .and. 2821 & (j1 .le. ncolc .or. j2 .le. ncolc)) then 2822c 2823c three cases 2824c 2825 if (j1 .eq. j2) then 2826 if (values) c(kc) = a(ka)+b(kb) 2827 jc(kc) = j1 2828 ka = ka+1 2829 kb = kb+1 2830 kc = kc+1 2831 else if (j1 .lt. j2) then 2832 jc(kc) = j1 2833 if (values) c(kc) = a(ka) 2834 ka = ka+1 2835 kc = kc+1 2836 else if (j1 .gt. j2) then 2837 jc(kc) = j2 2838 if (values) c(kc) = b(kb) 2839 kb = kb+1 2840 kc = kc+1 2841 endif 2842 if (kc .gt. nzmx) goto 999 2843 goto 20 2844 end if 2845 ic(i+1) = kc 2846 10 continue 2847 return 2848 999 ierr = i 2849 return 2850c---------end-of-addblk------------------------------------------------- 2851 end 2852c----------------------------------------------------------------------- 2853 subroutine get1up (n,ja,ia,ju) 2854 integer n, ja(*),ia(*),ju(*) 2855c---------------------------------------------------------------------- 2856c obtains the first element of each row of the upper triangular part 2857c of a matrix. Assumes that the matrix is already sorted. 2858c----------------------------------------------------------------------- 2859c parameters 2860c input 2861c ----- 2862c ja = integer array containing the column indices of aij 2863c ia = pointer array. ia(j) contains the position of the 2864c beginning of row j in ja 2865c 2866c output 2867c ------ 2868c ju = integer array of length n. ju(i) is the address in ja 2869c of the first element of the uper triangular part of 2870c of A (including rthe diagonal. Thus if row i does have 2871c a nonzero diagonal element then ju(i) will point to it. 2872c This is a more general version of diapos. 2873c----------------------------------------------------------------------- 2874c local vAriables 2875 integer i, k 2876c 2877 do 5 i=1, n 2878 ju(i) = 0 2879 k = ia(i) 2880c 2881 1 continue 2882 if (ja(k) .ge. i) then 2883 ju(i) = k 2884 goto 5 2885 elseif (k .lt. ia(i+1) -1) then 2886 k=k+1 2887c 2888c go try next element in row 2889c 2890 goto 1 2891 endif 2892 5 continue 2893 return 2894c-----end-of-get1up----------------------------------------------------- 2895 end 2896 2897c---------------------------------------------------------------------- 2898 subroutine xtrows (i1,i2,a,ja,ia,ao,jao,iao,iperm,job) 2899 integer i1,i2,ja(*),ia(*),jao(*),iao(*),iperm(*),job 2900 real*8 a(*),ao(*) 2901c----------------------------------------------------------------------- 2902c this subroutine extracts given rows from a matrix in CSR format. 2903c Specifically, rows number iperm(i1), iperm(i1+1), ...., iperm(i2) 2904c are extracted and put in the output matrix ao, jao, iao, in CSR 2905c format. NOT in place. 2906c Youcef Saad -- coded Feb 15, 1992. 2907c----------------------------------------------------------------------- 2908c on entry: 2909c---------- 2910c i1,i2 = two integers indicating the rows to be extracted. 2911c xtrows will extract rows iperm(i1), iperm(i1+1),..,iperm(i2), 2912c from original matrix and stack them in output matrix 2913c ao, jao, iao in csr format 2914c 2915c a, ja, ia = input matrix in csr format 2916c 2917c iperm = integer array of length nrow containing the reverse permutation 2918c array for the rows. row number iperm(j) in permuted matrix PA 2919c used to be row number j in unpermuted matrix. 2920c ---> a(i,j) in the permuted matrix was a(iperm(i),j) 2921c in the inout matrix. 2922c 2923c job = integer indicating the work to be done: 2924c job .ne. 1 : get structure only of output matrix,, 2925c i.e., ignore real values. (in which case arrays a 2926c and ao are not used nor accessed). 2927c job = 1 get complete data structure of output matrix. 2928c (i.e., including arrays ao and iao). 2929c------------ 2930c on return: 2931c------------ 2932c ao, jao, iao = input matrix in a, ja, ia format 2933c note : 2934c if (job.ne.1) then the arrays a and ao are not used. 2935c----------------------------------------------------------------------c 2936c Y. Saad, revised May 2, 1990 c 2937c----------------------------------------------------------------------c 2938 logical values 2939 values = (job .eq. 1) 2940c 2941c copying 2942c 2943 ko = 1 2944 iao(1) = ko 2945 do 100 j=i1,i2 2946c 2947c ii=iperm(j) is the index of old row to be copied. 2948c 2949 ii = iperm(j) 2950 do 60 k=ia(ii), ia(ii+1)-1 2951 jao(ko) = ja(k) 2952 if (values) ao(ko) = a(k) 2953 ko = ko+1 2954 60 continue 2955 iao(j-i1+2) = ko 2956 100 continue 2957c 2958 return 2959c---------end-of-xtrows------------------------------------------------- 2960c----------------------------------------------------------------------- 2961 end 2962c----------------------------------------------------------------------- 2963 subroutine csrkvstr(n, ia, ja, nr, kvstr) 2964c----------------------------------------------------------------------- 2965 integer n, ia(n+1), ja(*), nr, kvstr(*) 2966c----------------------------------------------------------------------- 2967c Finds block row partitioning of matrix in CSR format. 2968c----------------------------------------------------------------------- 2969c On entry: 2970c-------------- 2971c n = number of matrix scalar rows 2972c ia,ja = input matrix sparsity structure in CSR format 2973c 2974c On return: 2975c--------------- 2976c nr = number of block rows 2977c kvstr = first row number for each block row 2978c 2979c Notes: 2980c----------- 2981c Assumes that the matrix is sorted by columns. 2982c This routine does not need any workspace. 2983c 2984c----------------------------------------------------------------------- 2985c local variables 2986 integer i, j, jdiff 2987c----------------------------------------------------------------------- 2988 nr = 1 2989 kvstr(1) = 1 2990c--------------------------------- 2991 do i = 2, n 2992 jdiff = ia(i+1)-ia(i) 2993 if (jdiff .eq. ia(i)-ia(i-1)) then 2994 do j = ia(i), ia(i+1)-1 2995 if (ja(j) .ne. ja(j-jdiff)) then 2996 nr = nr + 1 2997 kvstr(nr) = i 2998 goto 299 2999 endif 3000 enddo 3001 299 continue 3002 else 3003 300 nr = nr + 1 3004 kvstr(nr) = i 3005 endif 3006 enddo 3007 kvstr(nr+1) = n+1 3008c--------------------------------- 3009 return 3010 end 3011c----------------------------------------------------------------------- 3012c------------------------end-of-csrkvstr-------------------------------- 3013 subroutine csrkvstc(n, ia, ja, nc, kvstc, iwk) 3014c----------------------------------------------------------------------- 3015 integer n, ia(n+1), ja(*), nc, kvstc(*), iwk(*) 3016c----------------------------------------------------------------------- 3017c Finds block column partitioning of matrix in CSR format. 3018c----------------------------------------------------------------------- 3019c On entry: 3020c-------------- 3021c n = number of matrix scalar rows 3022c ia,ja = input matrix sparsity structure in CSR format 3023c 3024c On return: 3025c--------------- 3026c nc = number of block columns 3027c kvstc = first column number for each block column 3028c 3029c Work space: 3030c---------------- 3031c iwk(*) of size equal to the number of scalar columns plus one. 3032c Assumed initialized to 0, and left initialized on return. 3033c 3034c Notes: 3035c----------- 3036c Assumes that the matrix is sorted by columns. 3037c 3038c----------------------------------------------------------------------- 3039c local variables 3040 integer i, j, k, ncol 3041c 3042c----------------------------------------------------------------------- 3043 3044c-----use ncol to find maximum scalar column number 3045 ncol = 0 3046 3047c-----mark the beginning position of the blocks in iwk 3048 do i = 1, n 3049 if (ia(i) .lt. ia(i+1)) then 3050 j = ja(ia(i)) 3051 iwk(j) = 1 3052 do k = ia(i)+1, ia(i+1)-1 3053 j = ja(k) 3054 if (ja(k-1).ne.j-1) then 3055 iwk(j) = 1 3056 iwk(ja(k-1)+1) = 1 3057 endif 3058 enddo 3059 iwk(j+1) = 1 3060 ncol = max0(ncol, j) 3061 endif 3062 enddo 3063c--------------------------------- 3064 nc = 1 3065 kvstc(1) = 1 3066 do i = 2, ncol+1 3067 if (iwk(i).ne.0) then 3068 nc = nc + 1 3069 kvstc(nc) = i 3070 iwk(i) = 0 3071 endif 3072 enddo 3073 nc = nc - 1 3074c--------------------------------- 3075 return 3076 end 3077c----------------------------------------------------------------------- 3078c------------------------end-of-csrkvstc-------------------------------- 3079c----------------------------------------------------------------------- 3080 subroutine kvstmerge(nr, kvstr, nc, kvstc, n, kvst) 3081c----------------------------------------------------------------------- 3082 integer nr, kvstr(nr+1), nc, kvstc(nc+1), n, kvst(*) 3083c----------------------------------------------------------------------- 3084c Merges block partitionings, for conformal row/col pattern. 3085c----------------------------------------------------------------------- 3086c On entry: 3087c-------------- 3088c nr,nc = matrix block row and block column dimension 3089c kvstr = first row number for each block row 3090c kvstc = first column number for each block column 3091c 3092c On return: 3093c--------------- 3094c n = conformal row/col matrix block dimension 3095c kvst = conformal row/col block partitioning 3096c 3097c Notes: 3098c----------- 3099c If matrix is not square, this routine returns without warning. 3100c 3101c----------------------------------------------------------------------- 3102c-----local variables 3103 integer i,j 3104c--------------------------------- 3105 3106 if (kvstr(nr+1) .ne. kvstc(nc+1)) return 3107 3108 i = 1 3109 j = 1 3110 n = 1 3111 200 if (i .gt. nr+1) then 3112 kvst(n) = kvstc(j) 3113 j = j + 1 3114 elseif (j .gt. nc+1) then 3115 kvst(n) = kvstr(i) 3116 i = i + 1 3117 elseif (kvstc(j) .eq. kvstr(i)) then 3118 kvst(n) = kvstc(j) 3119 j = j + 1 3120 i = i + 1 3121 elseif (kvstc(j) .lt. kvstr(i)) then 3122 kvst(n) = kvstc(j) 3123 j = j + 1 3124 else 3125 kvst(n) = kvstr(i) 3126 i = i + 1 3127 endif 3128 n = n + 1 3129 if (i.le.nr+1 .or. j.le.nc+1) goto 200 3130 n = n - 2 3131c--------------------------------- 3132 return 3133c------------------------end-of-kvstmerge------------------------------- 3134 end 3135